local c_code = [[ // Auto-generated by gencfuncs.lua enum GateFuncs { GateFunc_None, %s }; %s GateFunc sim_logic_functions[] = { 0, %s }; ]] local lua_code = [[ -- Auto-generated by gencfuncs.lua cFuncsByName = { %s } cDataSizeByName = { %s } ]] local function writeFile(fn, data) local f = io.open(fn, "wb") or error("Could not open file for writing: "..fn) f:write(data) f:close() end local function exportGates(gates) local gateNameList = {} local gateFuncList = {} local gateSizeList = {} local gateAliasList = {} local numGates = 0 for k, gate in pairs(gates) do table.insert(gateNameList, gate.name or error("gate "..k.." has no name")) table.insert(gateFuncList, gate.func or error("gate "..gate.name.." has no c function")) table.insert(gateSizeList, gate.size or 0) numGates = numGates + 1; gate.idx = numGates; for _, name in ipairs(gate.names) do table.insert(gateAliasList, { name = name, idx = gate.idx } ) end end local function map(t, f) local u = {}; for i, v in ipairs(t) do table.insert(u, f(v, i)) end; return u; end writeFile("compiled_sim_gates.c", string.format(c_code, table.concat(map(gateNameList, function(v, i) return string.format("\tGateFunc_%s,", v) end), "\n"), table.concat(map(gateNameList, function(v, i) local func = gateFuncList[i] local nl = func:find("\n") and "\n" or "" local nt = func:find("\n") and "\t" or "" local ns = func:find("\n") and "" or " " return string.format("GATEFUNC(%s) {"..nl..nt..ns.."%s"..nl..ns.."}", v, gateFuncList[i]:gsub("\n", "\n\t"):gsub("\n+$", ""):gsub("^\n+", "")) end), "\n"), table.concat(map(gateNameList, function(v, i) return string.format("\tGATEFUNCID(%s),", v) end), "\n") )) writeFile("compiled_sim_gates.lua", string.format(lua_code, table.concat(map(gateAliasList, function(v, i) return string.format("\t[\"%s\"] = %i,", v.name:lower(), v.idx) end), "\n"), table.concat(map(gateAliasList, function(v, i) if gateSizeList[v.idx]>0 then return string.format("\t[\"%s\"] = %i,", v.name:lower(), gateSizeList[v.idx]) else return nil end end), "\n") )) end local function log2(n) return math.max(math.ceil(math.log(n)/math.log(2)-0.00000001), 1) end local function sizestrFromAddrwS(w) return ({"2 ", "4 ", "8 ", "16 ", "32 ", "64 ", "128 ", "256 ", "512 ", "1 K", "2 K", "4 K", "8 K", "16 K", "32 K", "64 K"})[w] end local function sizestrFromAddrw(w) sizeFromAddrWS(w):gsub(" ", "") end local function bwFromN(n) return ({"B", "W", nil, "DW"})[n/8] or error("invalid size "..n) end local function sizecast(n) return n>=32 and "(unsigned long long)" or "" end local function sizetype(n) return n>=32 and "unsigned long long" or "unsigned int" end local function sizeword(n) return n>=32 and "64" or "" end local function sizeint(n) return n>=32 and "ull" or "" end local function sizemax(n) return math.pow(2, n)-1 end local function createEnabler(n) return { name = "Enabler"..n, names = {"Enabler " ..n.." Bit", "Enabler " ..n.." Bit Up", "Enabler " ..n.." Bit Down"}, func = "if(getport("..(n*2+1)..")) { copyword("..n..", 1, "..(n+1).."); } else { clearword("..n..", "..(n+1).."); }" } end local function createBuffer (n) return { name = "Buffer" ..n, names = {"Buffer " ..n.." Bit", "Buffer " ..n.." Bit Up", "Buffer " ..n.." Bit Down"}, func = "if(getport("..(n*2+1)..")) { copyword("..n..", 1, "..(n+1).."); } else { clearword("..n..", "..(n+1).."); }" } end local function createDFF (n) return { name = "DFF" ..n, names = {"D FlipFlop " ..n.." Bit", "D FlipFlop " ..n.." Bit Up", "D FlipFlop " ..n.." Bit Down"}, func = "if(getport("..(n*2+1)..")) { copyword("..n..", 1, "..(n+1).."); }" } end local function createMux(n) return { name = "Mux"..n, names = {"Mux "..n.." Bit", "Mux "..n.." Bit Vertical"}, func = "if(getport("..(n+math.pow(2,n)+1)..")) { setport("..(n+math.pow(2,n)+2)..", getport(getword("..n..", 1)+"..(n+1)..")); } else { setport("..(n+math.pow(2,n)+2)..", 0); }" } end local function createDemux(n) return { name = "Demux"..n, names = {"Demux "..n.." Bit", "Demux "..n.." Bit Vertical"}, size = 1, func = "int pa = getdata(0); if(getport("..(n+math.pow(2,n)+1)..")) { int a = getword("..n..", 1) + "..(n+1).."; if(pa != a) { if(pa) { setport(pa, 0); } setport(a, 1); setdata(0, a); } } else { if(pa) { setport(pa, 0); setdata(0, 0); } }" } end local function createRom(x, y, z) local w = log2(x*y); return { name = "Rom"..w.."x"..z, names = {"ROM "..x.."x"..y..(z>1 and ("x"..z) or "")}, size = x*y*z, func="if(getport("..(w+z+1)..")) { int a = getword("..w..", 1); for(int i=0; i<"..z.."; i++) { setport("..(w+1).."+i, getdata(a + i*"..(x*y)..")); } } else { clearword("..z..", "..(w+1).."); }" } end local function createAdder(n) return { name = "Adder"..n, names = {"Adder "..n.." Bit"}, func = sizetype(n).." v = ".. sizecast(n).."getword("..n..", 1) + ".. sizecast(n).."(getword("..n..", "..(n+1)..")^(getport("..(n*3+3)..")*"..sizemax(n)..")) + ".. sizecast(n).."getport("..(n*3+1).."); ".. "setword("..n..", "..(n*2+1)..", v); ".. "setport("..(n*3+2)..", (v>>"..n..sizeint(n)..") & 1);" } end local function createIncrementer(n) return { name = "Incrementer"..n, names = {"Incrementer "..n.." Bit"}, func = sizetype(n).." a = ".. sizecast(n).."(getword("..n..", 1)^(getport("..(n*2+4)..")*"..sizemax(n)..")) + ".. sizecast(n).."getport("..(n*2+1)..") + ".. sizecast(n).."(getport("..(n*2+2)..")*"..sizemax(n).."); ".. "setword("..n..", "..(n+1)..", a); ".. "setport("..(n*2+3)..", (a>>"..n..sizeint(n)..") & 1);" } end local function createShifterLeft (n) return { name = "ShifterLeft" ..n, names = {"Shifter Left " ..n.." Bit"}, func = "int dist = getword("..log2(n)..", "..(n*3+1).."); ".. "setword"..sizeword(n).."("..(n*2)..", "..(n+1)..", ".. " (("..sizecast(n).."getword("..n..", 1))<>("..n .."-dist)) : 0"..sizeint(n).."));" } end local function createShifterRight(n) return { name = "ShifterRight"..n, names = {"Shifter Right "..n.." Bit"}, func = "int dist = getword("..log2(n)..", "..(n*3+1).."); ".. "setword"..sizeword(n).."("..(n*2)..", "..(n+1)..", ".. "(("..sizecast(n).."getword("..n..", 1))<<("..n.."-dist)) | ".. "("..(n>=16 and "dist!=0 && " or "").."getport("..(n*3+log2(n)+1)..") ? ".. "("..sizemax(n)..sizeint(n).."<<("..(n*2).."-dist)) : ".. "0"..sizeint(n).. ")".. ");" } end local function createMultiplier(n) return { name = "Multiplier"..n, names = {"Multiplier "..n.." Bit"}, func = "setword"..sizeword(n).."("..(n*2)..", "..(n*2+1)..", "..sizecast(n).."getword("..n..", 1) * "..sizecast(n).."getword("..n..", "..(n+1).."));" } end local function createDivider(n) return { name = "Divider"..n, names = {"Divider "..n.." Bit"}, func = "unsigned int a = getword("..n..", 1); unsigned int b = getword("..n..", "..(n+1).."); setword("..n..", "..(n*2+1)..", b!=0 ? a/b : 0); setword("..n..", "..(n*3+1)..", b!=0 ? a%b : 0);" } end local function createBinary(name, f, inv, n) local ilist = {}; for i = 1, n do table.insert(ilist, "getport("..i..")") end; return { name = name..n, names = {name:upper().." "..n.." Bit"}, func = "setport("..(n+1)..", "..inv.."("..table.concat(ilist, " "..f.." ").."));" } end local function createRam(n, w) return { name = "Ram"..n.."x"..w, names = {"RAM "..sizestrFromAddrwS(w)..bwFromN(n)}, size = math.pow(2, w), func = "if(getport("..(n*2+w+1)..")) { setword("..n..", "..(n+1)..", getdata(getword("..w..", "..(n*2+1).."))); } else { clearword("..n..", "..(n+1).."); } if(getport("..(n*2+w+2)..")) { setdata(getword("..w..", "..(n*2+1).."), getword("..n..", 1)); }" } end -- in*n out*n addr*w readclk writeclk local binaries = { {"And" , "&&", "" }, {"Or" , "||", "" }, {"Xor" , "^" , "" }, {"Nand", "&&", "!"}, {"Nor" , "||", "!"}, {"Xnor", "^" , "!"}, } local romsizes = { -- copied from brick gen -- 1 bit data 4 bit data 8 bit data 16 bit data 32 bit data 48 bit data 64 bit data { 4, 4 }, { 4, 4, 4}, { 8, 2, 8}, -- 4 bit addr { 8, 8 }, { 8, 8, 4}, { 8, 8, 8}, {16, 4, 16}, {32, 2, 32}, {64, 1, 48}, {64, 1, 64}, -- 6 bit addr {16, 16 }, {16, 16, 4}, {16, 16, 8}, {16, 16, 16}, {32, 8, 32}, {64, 4, 48}, {64, 4, 64}, -- 8 bit addr {32, 16 }, {32, 16, 4}, {32, 16, 8}, {32, 16, 16}, {32, 16, 32}, {64, 8, 48}, {64, 8, 64}, -- 9 bit addr {32, 32, 8}, {32, 32, 16}, {32, 32, 32}, {64, 16, 48}, {64, 16, 64}, -- 10 bit addr {64, 32, 8}, {64, 32, 16}, {64, 32, 32}, {64, 32, 48}, {64, 32, 64}, -- 11 bit addr {64, 64, 8}, {64, 64, 16}, {64, 64, 32}, {64, 64, 48}, {64, 64, 64}, -- 12 bit addr } local ramsizes = { {8, 8}, {8, 12}, } local gates = { { name = "Diode", names = {"Diode", "Diode Up", "Diode Down"}, func = "setport(2, getport(1));" }, { name = "Not" , names = {"Not" , "Not Up" , "Not Down" }, func = "setport(2, !getport(1));" }, createEnabler(1), createEnabler(2), createEnabler(3), createEnabler(4), createEnabler(5), createEnabler(6), createEnabler(7), createEnabler(8), createEnabler(9), createEnabler(10), createEnabler(11), createEnabler(12), createEnabler(13), createEnabler(14), createEnabler(15), createEnabler(16), createEnabler(24), createEnabler(32), createEnabler(48), createEnabler(64), createBuffer (1), createBuffer (2), createBuffer (3), createBuffer (4), createBuffer (5), createBuffer (6), createBuffer (7), createBuffer (8), createBuffer (9), createBuffer (10), createBuffer (11), createBuffer (12), createBuffer (13), createBuffer (14), createBuffer (15), createBuffer (16), createBuffer (24), createBuffer (32), createBuffer (48), createBuffer (64), createDFF (1), createDFF (2), createDFF (3), createDFF (4), createDFF (5), createDFF (6), createDFF (7), createDFF (8), createDFF (9), createDFF (10), createDFF (11), createDFF (12), createDFF (13), createDFF (14), createDFF (15), createDFF (16), createDFF (24), createDFF (32), createDFF (48), createDFF (64), createMux (1), createMux (2), createMux (3), createMux (4), createMux (5), createMux (6), createMux (7), createMux (8), createDemux(1), createDemux(2), createDemux(3), createDemux(4), createDemux(5), createDemux(6), createDemux(7), createDemux(8), createAdder (2), createAdder (4), createAdder (8), createAdder (16), createAdder (32), createIncrementer (2), createIncrementer (4), createIncrementer (8), createIncrementer (16), createIncrementer (32), createMultiplier (2), createMultiplier (4), createMultiplier (8), createMultiplier (16), createMultiplier (32), createDivider (2), createDivider (4), createDivider (8), createDivider (16), createDivider (32), createShifterLeft (2), createShifterLeft (4), createShifterLeft (8), createShifterLeft (16), createShifterLeft (32), createShifterRight(2), createShifterRight(4), createShifterRight(8), createShifterRight(16), createShifterRight(32), } for _, v in ipairs(binaries) do for i = 2, 8 do table.insert(gates, createBinary(v[1], v[2], v[3], i)) end end for i, size in ipairs(romsizes) do table.insert(gates, createRom(size[1], size[2], size[3] or 1)) end for i, size in ipairs(ramsizes) do table.insert(gates, createRam(size[1], size[2])) end exportGates(gates)