diff --git a/sim/compile.lua b/sim/compile.lua index db4930e..b69d83a 100644 --- a/sim/compile.lua +++ b/sim/compile.lua @@ -3,47 +3,122 @@ local ffi = FFI or require("ffi") Simulation = Simulation or {} ffi.cdef[[ - + struct Net { + int in_queue; + int num_out_ports_on; + int state; + int update_tick; + struct Gate* gates_update[0]; + }; + struct OutPort { + struct Net* net; + int state; + }; + struct Gate { + int in_queue; + struct OutPort out_ports[0]; + }; ]] +function Simulation.compile_code(sim, text) + -- todo: compile some kind of DSL into machine code + + return code, size +end + +local net_program_code = Simulation.compile_code( [[ + +]] ) + function Simulation.compile(sim) + sim.compilation = { + gates = {}, + wires = {}, + cgates = {}, + cwires = {}, + } + local comp = sim.compilation + -- assemble a list of all nets - local all_nets = {} local all_nets_t = {} for k, wire in pairs(sim.wires) do local net = Wire.getgroup(wire) all_nets_t[net] = net end - local num_nets = 0 + local all_nets = {} for net_id, net in pairs(all_nets_t) do - table.insert(all_nets, net) + table.insert(comp.nets, net) + local cdata = ffi.new("char["..(ffi.sizeof("struct Net") + ffi.sizeof("struct Gate*")*net.num_gates_update).."]") + local cnet = ffi.cast(cdata, "struct Net") + comp.cnets[net] = cnet end -- assemble a list of all gates local all_gates = {} for k, gate in pairs(sim.gates) do - table.insert(all_gates, gate) + table.insert(comp.gates, gate) + local cdata = ffi.new("char["..(ffi.sizeof("struct Gate") + ffi.sizeof("struct OutPort")*gate.num_ports_out).."]") + local cgate = ffi.cast(cdata, "struct Gate") + comp.cgates[gate] = cgate end - -- construct each gate into an array - - -- construct array of all nets - local c_nets = ffi.new("struct Net["..(#all_nets).."]") - for net_idx, net in ipairs(all_nets) do - local c_net = ffi.new("struct Net", #net.gates_update) - - for gate_idx, gate in ipairs(net.gates_update) do - + for netidx, net in ipairs(comp.nets) do + local cnet = comp.cnets[net] or error("no cnet") + cnet.in_queue = net.in_queue + cnet.num_out_ports_on = net.state_num + cnet.state = net.state + cnet.update_tick = net.update_tick + for i = 1, net.num_gates_update do + local gate = net.gates_update[i] + local cgate = comp.cgates[gate] or error("no cgate") + cnet.gates_update[i-1] = cgate + end + end + + for gateidx, gate in ipairs(comp.gates) do + local cgate = comp.cgates[gate] or error("no cgate") + cgate.in_queue = gate.in_queue + local j = 0 + for i, port in ipairs(gate.ports) do + if port.type == PortTypes.output then + local net = port.group + if net then + local cnet = comp.cnets[net] or error("no cnet") + cgate.out_ports[j].net = cnet + else + cgate.out_ports[j].net = 0 + end + cgate.out_ports[j].state = gate.port_states[i] or error("no gate port_state") + j = j + 1 + end end - - c_nets[net_idx] = c_net end end function Simulation.decompile(sim) + local comp = sim.compilation + for netidx, net in ipairs(comp.nets) do + local cnet = comp.cnets[net] or error("no cnet") + net.in_queue = cnet.in_queue + net.state_num = cnet.num_out_ports_on + net.state = cnet.state + net.update_tick = cnet.update_tick + end + + for gateidx, gate in ipairs(comp.gates) do + local cgate = comp.cgates[gate] or error("no cgate") + gate.in_queue = cgate.in_queue + local j = 0 + for i, port in ipairs(gate.ports) do + if port.type == PortTypes.output then + gate.port_states[i] = cgate.out_ports[j].state + j = j + 1 + end + end + end end -function Simulation.tick_compiled(sim) +function Simulation.tick_compiled(sim, count) end diff --git a/sim/compiled_sim.bat b/sim/compiled_sim.bat new file mode 100644 index 0000000..576c50a --- /dev/null +++ b/sim/compiled_sim.bat @@ -0,0 +1,2 @@ +gcc compiled_sim.c -shared -o compiled_sim.dll -Wall -Werror +pause diff --git a/sim/compiled_sim.c b/sim/compiled_sim.c index 442f766..da809c4 100644 --- a/sim/compiled_sim.c +++ b/sim/compiled_sim.c @@ -1,7 +1,75 @@ void sim_init(int num_gates, int num_nets); -void sim_add_gate(); -void sim_add_net(); -void sim_tick(); -void sim_get_net_state(int objref); -void sim_get_port_state(int objref, int index); +void sim_add_gate(int gateid, int logic_func_id, char* logic_func_name, int num_out_ports, char* data); +void sim_add_net(int netid, int num_gates_update); +void sim_connect_out_port(int gateid, int index, int netid); +void sim_connect_in_port(int gateid, int index, int netid); +void sim_tick(int count); +void sim_get_net_state(int netid); +void sim_get_port_state(int gateid, int index); +void sim_set_net_state(int netid); +void sim_set_port_state(int gateid, int index); +void sim_delete_net(int netid); +void sim_delete_gate(int gateid); + +//////// + +void sim_create(unsigned int datalen, char* text); + +#include +#include + +typedef unsigned int uint; +typedef unsigned long long u64; + +void sim_copy_logic_function( + char** prog, + char* in_queue, + char* out_port_states, + int logic_func, + char** port_in_net_states, + char** port_out_net_inqueue, + char** port_out_net_update_func, + int num_ports_in, + int num_ports_out +) { + // todo: indata = inport net state pointers, outport net in queue pointers, outport net update function pointers +} + +void sim_compile_gate(char** prog, char** data, int** idat, u64* indata) { + int num_ports_in = *(indata++); + int num_ports_out = *(indata++); + int in_queue = *(indata++); + int logic_func = *(indata++); + + char* port_in_net_states[256]; + sim_copy_logic_function( // copy logic function into program + prog, + *data, + (*data)+1, + logic_func, + &indata, + num_ports_in, + num_ports_out + ); + + *(*data++) = in_queue; // alloc bool for in queue + for(int i=0; i0) ~= (group.state==1)) and (group.in_queue==0) then Simulation.queuegroup(GSim, group) @@ -41,6 +50,11 @@ function Gate.setportstate(gate, index, state) end end +-- Logic Critical +function Gate.logic(gate) + gate.logic(gate) +end + function Gate.preinit(gate) end @@ -83,10 +97,6 @@ function Gate.init(gate) Gate.getdefinition(gate).init(gate) end -function Gate.logic(gate) - gate.logic(gate) -end - function Gate.input(gate, argv) Gate.getdefinition(gate).input(gate, argv) end diff --git a/sim/gatedef.lua b/sim/gatedef.lua index f14cb7b..c8a9bde 100644 --- a/sim/gatedef.lua +++ b/sim/gatedef.lua @@ -5,7 +5,7 @@ GateDefinition = { input = function(gate, argv) end } -function GateDefinition.new(objref, name, description, init, logic, input, global, ports) +function GateDefinition.new(objref, name, description, init, logic, input, code, global, ports, code) name = collapseescape(name) init = collapseescape(init) @@ -13,17 +13,24 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa input = collapseescape(input) global = collapseescape(global) description = collapseescape(description) + code = collapseescape(code) - local o = { + local compiled_size, compiled_code = Simulation.compile_code(nil, code) + + local def = { objref = objref, name = name, description = description, - ports = ports or {} + ports = ports or {}, + num_in_ports = 0, + num_out_ports = 0, + compiled_program_code = compiled_code, + compiled_program_size = compiled_size, } local initfunc = loadstring(tostring(init)) if initfunc~=nil then - o.init = initfunc() or function()end + def.init = initfunc() or function()end else print("Error loading init func for ".. (name or "")) print(init) @@ -31,7 +38,7 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa local logicfunc = loadstring(tostring(logic)) if logicfunc ~= nil then - o.logic = logicfunc() or function()end + def.logic = logicfunc() or function()end else print("Error loading logic function for " .. (name or "")) print(logic) @@ -39,7 +46,7 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa local inputfunc = loadstring(tostring(input)) if inputfunc ~= nil then - o.input = inputfunc() or function()end + def.input = inputfunc() or function()end else print("Error loading input function for " .. (name or "")) print(input) @@ -53,7 +60,16 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa print(global) end - return o + for i = 1, #def.ports do + local portd = def.ports[i] + if portd.type==PortTypes.output then + def.num_out_ports = def.num_out_ports + 1 + elseif portd.type==PortTypes.input then + def.num_in_ports = def.num_in_ports + 1 + else error("invalid port type: "..name.." port "..i..) end + end + + return def end function GateDefinition.constructgate(def, objref, position, rotation) @@ -85,10 +101,8 @@ function GateDefinition.constructgate(def, objref, position, rotation) local port = Port.new(type, dir, {position[1]+pos[1], position[2]+pos[2], position[3]+pos[3]}, portd.causeupdate, i, gate) gate.ports[port.idx] = port - --gate[port.idx*2] = nil - --gate[port.idx*2+1] = 0 gate.port_nets[port.idx] = nil - gate.port_states[port.idx] = 0 + gate.c.ports[port.idx].state = 0 end return gate diff --git a/sim/group.lua b/sim/group.lua index 675c626..629d2d6 100644 --- a/sim/group.lua +++ b/sim/group.lua @@ -185,7 +185,7 @@ function Group.setstate(group, state) local len = group.num_gates_update for i = 1, len do local gate = group.gates_update[i] - if gate and gate.in_queue==0 then + if gate and gate.c.in_queue==0 then Simulation.queuegate(sim, gate) end end diff --git a/sim/network.lua b/sim/network.lua index f40194f..d99f819 100644 --- a/sim/network.lua +++ b/sim/network.lua @@ -76,10 +76,11 @@ function network_update() local logic = data[i+5] local input = data[i+6] local global = data[i+7] - local numports = tonumber(data[i+8]) + local code = data[i+8] + local numports = tonumber(data[i+9]) local ports = {} - for a = i+9, numports*5+i+8, 5 do + for a = i+10, numports*5+i+9, 5 do local portd = { type = tonumber(data[a]), position = vectotable(data[a+1]), @@ -92,10 +93,10 @@ function network_update() if not portd.direction then print(line) end end - local definition = GateDefinition.new(objref, name, desc, init, logic, input, global, ports) + local definition = GateDefinition.new(objref, name, desc, init, logic, input, global, ports, code) Simulation.addgatedefinition(sim, definition) - i = i + 8 + numports*5 + i = i + 9 + numports*5 elseif data[i] == "SL" then local wire = Simulation.getwirebyref(sim, tonumber(data[i+1])) if wire ~= nil then diff --git a/sim/port.lua b/sim/port.lua index 305c80a..5a92e25 100644 --- a/sim/port.lua +++ b/sim/port.lua @@ -62,5 +62,5 @@ function Port.gettype(port) end function Port.getstate(port) - return Port.getgate(port).port_states[port.idx] + return Port.getgate(port).c.ports[port.idx].state end diff --git a/sim/simulation.lua b/sim/simulation.lua index 010a8f6..f4ab6f8 100644 --- a/sim/simulation.lua +++ b/sim/simulation.lua @@ -244,11 +244,11 @@ end function Simulation.queuegate(sim, gate) sim.gatequeue[sim.num_gatequeue+1] = gate sim.num_gatequeue = sim.num_gatequeue + 1 - gate.in_queue = 1 + gate.c.in_queue = 1 end function Simulation.queuegate_safe(sim, gate) - if gate.in_queue==0 then + if gate.c.in_queue==0 then Simulation.queuegate(sim, gate) end end @@ -296,10 +296,10 @@ function Simulation.dequeuegroup(sim, group) end function Simulation.dequeuegate(sim, gate) - if gate.in_queue~=0 then + if gate.c.in_queue~=0 then array_remove(sim.gatequeue, gate, true) sim.num_gatequeue = sim.num_gatequeue - 1 - gate.in_queue = 0 + gate.c.in_queue = 0 end if sim.inputqueue~=nil then sim.inputqueue[gate] = nil end if sim.initqueue ~=nil then sim.initqueue [gate] = nil end @@ -330,7 +330,7 @@ function Simulation.ticklogic(sim) if sim.tickqueue[sim.current_tick] ~= nil then for i, gate in pairs(sim.tickqueue[sim.current_tick]) do - if gate.in_queue==0 then + if gate.c.in_queue==0 then Simulation.queuegate(sim, gate) end end @@ -340,7 +340,7 @@ function Simulation.ticklogic(sim) for i = 1, sim.num_gatequeue do local gate = sim.gatequeue[i] gate.logic(gate) - gate.in_queue = 0 + gate.c.in_queue = 0 sim.gatequeue[i] = nil end --sim.gatequeue = {}