Commit 67ed0710 authored by Adam P. Goucher's avatar Adam P. Goucher

Migrate lifelike and generations rules

parent 9540f87d
......@@ -8,6 +8,20 @@ namespace apg {
return -1;
}
int uli_get_family(int rule) {
switch (rule) {
case 0 : return 0;
}
return 0;
}
uint64_t uli_valid_mantissa(int rule) {
switch (rule) {
case 0 : return 511;
}
return 3;
}
int iterate_var_leaf(int rule, int n, uint64_t * inleaves, uint64_t * outleaf) {
switch(rule) {
case 0 :
......@@ -17,17 +31,9 @@ namespace apg {
}
int iterate_var_32_28(int rule, uint32_t* d, uint32_t * diffs) {
uint32_t e[32];
int bis = apg::best_instruction_set();
switch(rule) {
case 0 :
if (bis >= 10) {
return b3s23::iterate_avx2_32_28(d, e, 0, 0, diffs, false);
} else if (bis >= 9) {
return b3s23::iterate_avx_32_28(d, e, 0, 0, diffs, false);
} else {
return b3s23::iterate_sse2_32_28(d, e, 0, 0, diffs, false);
}
return b3s23::iterate_var_32_28(d, diffs);
}
return -1;
}
......@@ -41,17 +47,9 @@ namespace apg {
}
int iterate_var_32_28(int rule, uint32_t* d, uint32_t* h, uint32_t * diffs) {
uint32_t e[32];
int bis = apg::best_instruction_set();
switch(rule) {
case 0 :
if (bis >= 10) {
return b3s23::iterate_avx2_32_28(d, e, h, 0, diffs, false);
} else if (bis >= 9) {
return b3s23::iterate_avx_32_28(d, e, h, 0, diffs, false);
} else {
return b3s23::iterate_sse2_32_28(d, e, h, 0, diffs, false);
}
return b3s23::iterate_var_32_28(d, h, diffs);
}
return -1;
}
......@@ -65,35 +63,11 @@ namespace apg {
}
int iterate_var_32_28(int rule, uint32_t* d, uint32_t* h, uint32_t* j, uint32_t * diffs) {
uint32_t e[32];
int bis = apg::best_instruction_set();
switch(rule) {
case 0 :
if (bis >= 10) {
return b3s23::iterate_avx2_32_28(d, e, h, j, diffs, false);
} else if (bis >= 9) {
return b3s23::iterate_avx_32_28(d, e, h, j, diffs, false);
} else {
return b3s23::iterate_sse2_32_28(d, e, h, j, diffs, false);
}
return b3s23::iterate_var_32_28(d, h, j, diffs);
}
return -1;
}
int uli_get_family(int rule) {
switch (rule) {
case 0 :
return 0;
}
return 0;
}
uint64_t uli_valid_mantissa(int rule) {
switch (rule) {
case 0 :
return 511;
}
return 3;
}
}
......@@ -24,3 +24,7 @@ def rule_property(rulestring, attribute):
if callable(attr):
attr = attr(rulestring)
return attr
def create_rule(rulestring):
rule_property(rulestring, 'create_rule')
This diff is collapsed.
from _iwriter import iwriter
family = 2
mantissa = 3
def bitplanes(rulestring):
bplanes = int(rulestring[1:rulestring.index('b')])
bplanes = 2 if (bplanes == 3) else len(bin(bplanes - 3))
return bplanes
def create_rule(rulestring):
logstring = rulestring[rulestring.index('b'):]
for iset in [['sse2'], ['sse2', 'avx'], ['sse2', 'avx', 'avx2']]:
with open('ll_%s_%s.asm' % (iset[-1], logstring), 'w') as f:
ix = genewriter(f, iset)
ix.genlogic(logstring)
with open('iterators_%s.h' % rulestring, 'w') as f:
f.write('#pragma once\n')
f.write('#include <stdint.h>\n')
f.write('#include "../lifeconsts.h"\n')
f.write('#include "../lifeperm.h"\n')
f.write('#include "../eors.h"\n')
f.write('namespace %s {\n\n' % rulestring.replace('-', '_'))
for iset in [['sse2'], ['sse2', 'avx'], ['sse2', 'avx', 'avx2']]:
iw = genewriter(f, iset)
iw.write_function(rulestring, 20, 16)
iw.write_iterator()
gwrite_leaf_iterator(f, int(rulestring[1:rulestring.index('b')]))
f.write('}\n')
class genewriter(iwriter):
def write_function(self, rulestring, rowcount, dwidth):
name = 'iterate_%s_%d_%d' % (self.besti, rowcount, dwidth)
params = 'uint32_t * __restrict__ d, uint32_t * __restrict__ e, uint32_t * __restrict__ h, uint32_t * __restrict__ j'
self.f.write(' void %s(%s) {\n' % (name, params))
logstring = rulestring[rulestring.index('b'):]
self.assemble(logstring, 0, rowcount, dwidth)
self.f.write(' for (int i = 1; i < %d; i++) {\n' % (rowcount - 1))
self.f.write(' e[i-1] &= (~h[i]);\n')
self.f.write(' j[i] = d[i] & (~e[i-1]);\n')
self.f.write(' d[i] = e[i-1];\n')
self.f.write(' }\n')
self.f.write(' return;\n')
self.f.write(' }\n\n')
def write_iterator(self):
name = 'iterate_var_%s' % self.besti
self.f.write(' void %s(uint32_t * __restrict__ d, uint32_t * __restrict__ h) {\n' % name)
self.f.write(' uint32_t e[32];\n')
self.f.write(' uint32_t j[32];\n')
self.f.write(' iterate_%s_20_16(d+6, e+6, h+6, j+6);\n' % self.besti)
self.f.write(' for (int i = 8; i < 24; i++) { h[i] = j[i]; }\n')
self.f.write(' return;\n')
self.f.write(' }\n\n')
def gwrite_leaf_iterator(f, nstates):
name = 'iterate_var_leaf'
params = 'uint64_t * inleaves, uint64_t * hleaves, uint64_t * outleaf'
f.write(' bool %s(%s) {\n' % (name, params))
f.write(' uint64_t outleaf2[4];')
f.write(' int bis = apg::best_instruction_set();\n')
f.write(' uint32_t d[32];\n')
f.write(' uint32_t h[32];\n')
f.write(' if (bis >= 10) {\n')
gwli_bsi(f, 'avx2', 'avx2')
f.write(' } else if (bis >= 9) {\n')
gwli_bsi(f, 'avx', 'avx')
f.write(' } else if (bis >= 7) {\n')
gwli_bsi(f, 'sse2', 'sse4')
f.write(' } else {\n')
gwli_bsi(f, 'sse2', 'ssse3')
f.write(' }\n')
br = '' if (nstates == 3) else (bin(nstates - 3)[2:])[::-1]
# We run 256 parallel binary counters in outleaf:
f.write(' for (int i = 0; i < 4; i++) {\n')
f.write(' uint64_t carry = outleaf[4+i];\n')
for i, c in enumerate(br):
f.write(' outleaf[%d+i] ^= carry;\n' % (4 * i + 8))
f.write(' carry &= outleaf[%d+i];\n' % (4 * i + 8))
if (c == '1'):
f.write(' outleaf[%d+i] |= outleaf2[i];\n' % (4 * i + 8))
# else:
# f.write(' outleaf[%d+i] &= outleaf2[i];\n' % (4 * i + 8))
f.write(' outleaf[4+i] ^= carry;\n')
for i, c in enumerate(br):
f.write(' outleaf[%d+i] ^= carry;\n' % (4 * i + 8))
f.write(' outleaf[4+i] |= outleaf2[i];\n')
f.write(' }\n')
f.write(' return false;\n')
f.write(' }\n\n')
from _iwriter import iwriter
family = 0
bitplanes = 1
......@@ -9,3 +11,144 @@ def mantissa(rulestring):
else:
return {0, 1, 2, 3, 4, 5, 6, 7, 8}
def create_rule(rulestring):
logstring = rulestring[rulestring.index('b'):]
for iset in [['sse2'], ['sse2', 'avx'], ['sse2', 'avx', 'avx2']]:
with open('ll_%s_%s.asm' % (iset[-1], logstring), 'w') as f:
ix = lifewriter(f, iset)
ix.genlogic(logstring)
with open('iterators_%s.h' % rulestring, 'w') as f:
f.write('#pragma once\n')
f.write('#include <stdint.h>\n')
f.write('#include "../lifeconsts.h"\n')
f.write('#include "../lifeperm.h"\n')
f.write('#include "../eors.h"\n')
f.write('namespace %s {\n\n' % rulestring.replace('-', '_'))
for iset in [['sse2'], ['sse2', 'avx'], ['sse2', 'avx', 'avx2']]:
iw = lifewriter(f, iset)
iw.write_function(rulestring, 32, 28)
iw.write_function(rulestring, 28, 24)
iw.write_function(rulestring, 24, 20)
iw.write_function(rulestring, 20, 16)
iw.write_function(rulestring, 16, 12)
iw.write_function(rulestring, 12, 8)
iw.write_iterator()
f.write('\n#include "../leaf_iterators.h"\n')
f.write('}\n')
class lifewriter(iwriter):
def write_function(self, rulestring, rowcount, dwidth):
name = 'iterate_%s_%d_%d' % (self.besti, rowcount, dwidth)
params = 'uint32_t * __restrict__ diffs, bool onegen'
for i in 'jhed':
params = 'uint32_t * __restrict__ ' + i + ', ' + params
self.f.write(' bool %s(%s) {\n' % (name, params))
self.f.write(' if (h) {\n')
self.f.write(' for (int i = 0; i < %d; i++) {\n' % (rowcount))
self.f.write(' h[i] |= d[i];\n')
self.f.write(' }\n')
self.f.write(' }\n')
self.f.write(' if (j) {\n')
self.f.write(' for (int i = 0; i < %d; i++) {\n' % (rowcount))
self.f.write(' j[i] &= d[i];\n')
self.f.write(' }\n')
self.f.write(' }\n')
self.assemble(rulestring, 0, rowcount, dwidth)
self.f.write(' if (h) {\n')
self.f.write(' for (int i = 1; i < %d; i++) {\n' % (rowcount - 1))
if (rulestring[:2] == 'b0'):
# We want the history state to match the envelope of the Gollyfied
# version of the B0 rule:
self.f.write(' h[i] |= (~e[i-1]);\n')
else:
self.f.write(' h[i] |= e[i-1];\n')
self.f.write(' }\n')
self.f.write(' }\n')
self.f.write(' if (j) {\n')
self.f.write(' for (int i = 1; i < %d; i++) {\n' % (rowcount - 1))
self.f.write(' j[i] &= e[i-1];\n')
self.f.write(' }\n')
self.f.write(' }\n')
self.f.write(' if (onegen) {\n')
self.f.write(' for (int i = 2; i < %d; i++) {\n' % (rowcount - 2))
self.f.write(' d[i] = e[i-1];\n')
self.f.write(' }\n')
self.f.write(' return false;\n')
self.f.write(' }\n')
self.assemble(rulestring, 1, rowcount, dwidth)
self.f.write(' if (h) {\n')
self.f.write(' for (int i = 2; i < %d; i++) {\n' % (rowcount - 2))
self.f.write(' h[i] |= d[i];\n')
self.f.write(' }\n')
self.f.write(' }\n')
self.f.write(' if (j) {\n')
self.f.write(' for (int i = 2; i < %d; i++) {\n' % (rowcount - 2))
self.f.write(' j[i] &= d[i];\n')
self.f.write(' }\n')
self.f.write(' }\n')
if 'avx2' in self.iset:
self.f.write(' uint32_t bigdiff = e[8] | e[9] | e[10] | e[11] | e[12] | e[13] | e[14] | e[15];\n')
self.f.write(' if (diffs != 0) {\n')
self.f.write(' diffs[0] = bigdiff;\n')
self.f.write(' diffs[1] = e[0] | e[1];\n')
self.f.write(' diffs[2] = e[18] | e[19];\n')
self.f.write(' }\n')
else:
self.f.write(' uint32_t bigdiff = e[4] | e[5] | e[6] | e[7];\n')
self.f.write(' if (diffs != 0) {\n')
self.f.write(' diffs[0] = bigdiff;\n')
self.f.write(' diffs[1] = e[0] | e[1];\n')
self.f.write(' diffs[2] = e[10] | e[11];\n')
self.f.write(' }\n')
self.f.write(' return (bigdiff == 0);\n')
self.f.write(' }\n\n')
def write_iterator(self):
name = 'iterate_var_%s' % self.besti
self.f.write(' int %s(int n, uint32_t * __restrict__ d, uint32_t * __restrict__ h, uint32_t * __restrict__ j) {\n' % name)
self.f.write(' uint32_t e[32];\n')
self.f.write(' if (n >= 7) { if (iterate_%s_32_28(d, e, h, j, 0, (n == 7))) {return 8;} }\n' % self.besti)
self.f.write(' if (n >= 5) { if (iterate_%s_28_24(d+2, e+2, h+2, j+2, 0, (n == 5))) {return 6;} }\n' % self.besti)
self.f.write(' if (n >= 3) { if (iterate_%s_24_20(d+4, e+4, h+4, j+4, 0, (n == 3))) {return 4;} }\n' % self.besti)
self.f.write(' if (n >= 1) { if (iterate_%s_20_16(d+6, e+6, h+6, j+6, 0, (n == 1))) {return 2;} }\n' % self.besti)
self.f.write(' return 0;\n')
self.f.write(' }\n\n')
self.f.write(' int %s(int n, uint32_t * __restrict__ d, uint32_t * __restrict__ h) {\n' % name)
self.f.write(' uint32_t e[32];\n')
self.f.write(' if (n >= 7) { if (iterate_%s_32_28(d, e, h, 0, 0, (n == 7))) {return 8;} }\n' % self.besti)
self.f.write(' if (n >= 5) { if (iterate_%s_28_24(d+2, e+2, h+2, 0, 0, (n == 5))) {return 6;} }\n' % self.besti)
self.f.write(' if (n >= 3) { if (iterate_%s_24_20(d+4, e+4, h+4, 0, 0, (n == 3))) {return 4;} }\n' % self.besti)
self.f.write(' if (n >= 1) { if (iterate_%s_20_16(d+6, e+6, h+6, 0, 0, (n == 1))) {return 2;} }\n' % self.besti)
self.f.write(' return 0;\n')
self.f.write(' }\n\n')
self.f.write(' int %s(int n, uint32_t * __restrict__ d) {\n' % name)
self.f.write(' uint32_t e[32];\n')
self.f.write(' if (n >= 7) { if (iterate_%s_32_28(d, e, 0, 0, 0, (n == 7))) {return 8;} }\n' % self.besti)
self.f.write(' if (n >= 5) { if (iterate_%s_28_24(d+2, e+2, 0, 0, 0, (n == 5))) {return 6;} }\n' % self.besti)
self.f.write(' if (n >= 3) { if (iterate_%s_24_20(d+4, e+4, 0, 0, 0, (n == 3))) {return 4;} }\n' % self.besti)
self.f.write(' if (n >= 1) { if (iterate_%s_20_16(d+6, e+6, 0, 0, 0, (n == 1))) {return 2;} }\n' % self.besti)
self.f.write(' return 0;\n')
self.f.write(' }\n\n')
......@@ -144,6 +144,11 @@ def main(logic_directory='avxlife/lifelogic'):
f.write('}\n')
# Create the source code for the rules:
for r in rules:
genera.create_rule(r)
if __name__ == '__main__':
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment