make gates use cdata for critical logic

This commit is contained in:
Redo 2022-11-04 13:10:10 -06:00
parent 07b3decc45
commit cdbf3ed089
10 changed files with 232 additions and 62 deletions

View File

@ -3,47 +3,122 @@ local ffi = FFI or require("ffi")
Simulation = Simulation or {} Simulation = Simulation or {}
ffi.cdef[[ 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) function Simulation.compile(sim)
sim.compilation = {
gates = {},
wires = {},
cgates = {},
cwires = {},
}
local comp = sim.compilation
-- assemble a list of all nets -- assemble a list of all nets
local all_nets = {}
local all_nets_t = {} local all_nets_t = {}
for k, wire in pairs(sim.wires) do for k, wire in pairs(sim.wires) do
local net = Wire.getgroup(wire) local net = Wire.getgroup(wire)
all_nets_t[net] = net all_nets_t[net] = net
end end
local num_nets = 0 local all_nets = {}
for net_id, net in pairs(all_nets_t) do 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 end
-- assemble a list of all gates -- assemble a list of all gates
local all_gates = {} local all_gates = {}
for k, gate in pairs(sim.gates) do 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 end
-- construct each gate into an array for netidx, net in ipairs(comp.nets) do
local cnet = comp.cnets[net] or error("no cnet")
-- construct array of all nets cnet.in_queue = net.in_queue
local c_nets = ffi.new("struct Net["..(#all_nets).."]") cnet.num_out_ports_on = net.state_num
for net_idx, net in ipairs(all_nets) do cnet.state = net.state
local c_net = ffi.new("struct Net", #net.gates_update) cnet.update_tick = net.update_tick
for i = 1, net.num_gates_update do
for gate_idx, gate in ipairs(net.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 end
c_nets[net_idx] = c_net
end end
end end
function Simulation.decompile(sim) 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 end
function Simulation.tick_compiled(sim) function Simulation.tick_compiled(sim, count)
end end

2
sim/compiled_sim.bat Normal file
View File

@ -0,0 +1,2 @@
gcc compiled_sim.c -shared -o compiled_sim.dll -Wall -Werror
pause

View File

@ -1,7 +1,75 @@
void sim_init(int num_gates, int num_nets); void sim_init(int num_gates, int num_nets);
void sim_add_gate(); void sim_add_gate(int gateid, int logic_func_id, char* logic_func_name, int num_out_ports, char* data);
void sim_add_net(); void sim_add_net(int netid, int num_gates_update);
void sim_tick(); void sim_connect_out_port(int gateid, int index, int netid);
void sim_get_net_state(int objref); void sim_connect_in_port(int gateid, int index, int netid);
void sim_get_port_state(int objref, int index); 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 <stdlib.h>
#include <assert.h>
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; i<num_ports_out; i++) { // alloc bool for each output state
*((*data)++) = *(indata++);
}
}
void sim_compile_net_function(char** prog, char* in_queue, int* gates, u64** indata, int num_gates_update) {
}
void sim_compile_net(char** prog, char** data, int** idat, u64* indata) {
int num_gates_update = *(indata++);
int num_ports_on = *(indata++);
int in_queue = *(indata++);
sim_compile_net_function(prog, *data, *idat, &indata, num_gates_update);
*((*data)++) = in_queue;
*((*idat)++) = num_ports_on;
}

BIN
sim/compiled_sim.dll Normal file

Binary file not shown.

View File

@ -1,39 +1,48 @@
local ffi = FFI local ffi = FFI or require("ffi")
Gate = {} Gate = {}
ffi.cdef [[
struct OutPort {
struct Net* net;
int state;
};
struct Gate {
int in_queue;
struct OutPort ports[0];
};
]]
function Gate.new(objref, definition) function Gate.new(objref, definition)
local o = { local gate = {
-- Logic Critical -- Logic Critical
in_queue = 0, c = nil,
logic = definition.logic, logic = definition.logic,
ports = {}, ports = {},
port_nets = {}, port_nets = {},
port_states = {},
objref = objref, objref = objref,
definition = definition, definition = definition,
} }
return o local cdata = ffi.new("char["..(ffi.sizeof("struct Gate") + ffi.sizeof("struct OutPort")*(#gate.ports+1)).."]")
gate.c = ffi.cast("struct Gate*", cdata)
gate.c.in_queue = 0
Gate.update_c_ports(gate)
return gate
end end
-- Logic Critical -- Logic Critical
function Gate.getportstate(gate, index) function Gate.getportstate(gate, index)
--return gate[index*2].state return gate.c.ports[index].state
return gate.port_nets[index].state
end end
-- Logic Critical -- Logic Critical
function Gate.setportstate(gate, index, state) function Gate.setportstate(gate, index, state)
--if state ~= gate[index*2+1] then if state ~= gate.c.ports[index].state then
if state ~= gate.port_states[index] then
--local group = gate[index*2]
local group = gate.port_nets[index] local group = gate.port_nets[index]
--group.state_num = group.state_num - gate[index*2+1] + state group.state_num = group.state_num - gate.c.ports[index].state + state
group.state_num = group.state_num - gate.port_states[index] + state gate.c.ports[index].state = state
--gate[index*2+1] = state
gate.port_states[index] = state
if ((group.state_num>0) ~= (group.state==1)) and (group.in_queue==0) then if ((group.state_num>0) ~= (group.state==1)) and (group.in_queue==0) then
Simulation.queuegroup(GSim, group) Simulation.queuegroup(GSim, group)
@ -41,6 +50,11 @@ function Gate.setportstate(gate, index, state)
end end
end end
-- Logic Critical
function Gate.logic(gate)
gate.logic(gate)
end
function Gate.preinit(gate) function Gate.preinit(gate)
end end
@ -83,10 +97,6 @@ function Gate.init(gate)
Gate.getdefinition(gate).init(gate) Gate.getdefinition(gate).init(gate)
end end
function Gate.logic(gate)
gate.logic(gate)
end
function Gate.input(gate, argv) function Gate.input(gate, argv)
Gate.getdefinition(gate).input(gate, argv) Gate.getdefinition(gate).input(gate, argv)
end end

View File

@ -5,7 +5,7 @@ GateDefinition = {
input = function(gate, argv) end 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) name = collapseescape(name)
init = collapseescape(init) init = collapseescape(init)
@ -13,17 +13,24 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa
input = collapseescape(input) input = collapseescape(input)
global = collapseescape(global) global = collapseescape(global)
description = collapseescape(description) description = collapseescape(description)
code = collapseescape(code)
local o = { local compiled_size, compiled_code = Simulation.compile_code(nil, code)
local def = {
objref = objref, objref = objref,
name = name, name = name,
description = description, 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)) local initfunc = loadstring(tostring(init))
if initfunc~=nil then if initfunc~=nil then
o.init = initfunc() or function()end def.init = initfunc() or function()end
else else
print("Error loading init func for ".. (name or "")) print("Error loading init func for ".. (name or ""))
print(init) print(init)
@ -31,7 +38,7 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa
local logicfunc = loadstring(tostring(logic)) local logicfunc = loadstring(tostring(logic))
if logicfunc ~= nil then if logicfunc ~= nil then
o.logic = logicfunc() or function()end def.logic = logicfunc() or function()end
else else
print("Error loading logic function for " .. (name or "")) print("Error loading logic function for " .. (name or ""))
print(logic) print(logic)
@ -39,7 +46,7 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa
local inputfunc = loadstring(tostring(input)) local inputfunc = loadstring(tostring(input))
if inputfunc ~= nil then if inputfunc ~= nil then
o.input = inputfunc() or function()end def.input = inputfunc() or function()end
else else
print("Error loading input function for " .. (name or "")) print("Error loading input function for " .. (name or ""))
print(input) print(input)
@ -53,7 +60,16 @@ function GateDefinition.new(objref, name, description, init, logic, input, globa
print(global) print(global)
end 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 end
function GateDefinition.constructgate(def, objref, position, rotation) 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) 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.ports[port.idx] = port
--gate[port.idx*2] = nil
--gate[port.idx*2+1] = 0
gate.port_nets[port.idx] = nil gate.port_nets[port.idx] = nil
gate.port_states[port.idx] = 0 gate.c.ports[port.idx].state = 0
end end
return gate return gate

View File

@ -185,7 +185,7 @@ function Group.setstate(group, state)
local len = group.num_gates_update local len = group.num_gates_update
for i = 1, len do for i = 1, len do
local gate = group.gates_update[i] 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) Simulation.queuegate(sim, gate)
end end
end end

View File

@ -76,10 +76,11 @@ function network_update()
local logic = data[i+5] local logic = data[i+5]
local input = data[i+6] local input = data[i+6]
local global = data[i+7] local global = data[i+7]
local numports = tonumber(data[i+8]) local code = data[i+8]
local numports = tonumber(data[i+9])
local ports = {} local ports = {}
for a = i+9, numports*5+i+8, 5 do for a = i+10, numports*5+i+9, 5 do
local portd = { local portd = {
type = tonumber(data[a]), type = tonumber(data[a]),
position = vectotable(data[a+1]), position = vectotable(data[a+1]),
@ -92,10 +93,10 @@ function network_update()
if not portd.direction then print(line) end if not portd.direction then print(line) end
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) Simulation.addgatedefinition(sim, definition)
i = i + 8 + numports*5 i = i + 9 + numports*5
elseif data[i] == "SL" then elseif data[i] == "SL" then
local wire = Simulation.getwirebyref(sim, tonumber(data[i+1])) local wire = Simulation.getwirebyref(sim, tonumber(data[i+1]))
if wire ~= nil then if wire ~= nil then

View File

@ -62,5 +62,5 @@ function Port.gettype(port)
end end
function Port.getstate(port) function Port.getstate(port)
return Port.getgate(port).port_states[port.idx] return Port.getgate(port).c.ports[port.idx].state
end end

View File

@ -244,11 +244,11 @@ end
function Simulation.queuegate(sim, gate) function Simulation.queuegate(sim, gate)
sim.gatequeue[sim.num_gatequeue+1] = gate sim.gatequeue[sim.num_gatequeue+1] = gate
sim.num_gatequeue = sim.num_gatequeue + 1 sim.num_gatequeue = sim.num_gatequeue + 1
gate.in_queue = 1 gate.c.in_queue = 1
end end
function Simulation.queuegate_safe(sim, gate) function Simulation.queuegate_safe(sim, gate)
if gate.in_queue==0 then if gate.c.in_queue==0 then
Simulation.queuegate(sim, gate) Simulation.queuegate(sim, gate)
end end
end end
@ -296,10 +296,10 @@ function Simulation.dequeuegroup(sim, group)
end end
function Simulation.dequeuegate(sim, gate) function Simulation.dequeuegate(sim, gate)
if gate.in_queue~=0 then if gate.c.in_queue~=0 then
array_remove(sim.gatequeue, gate, true) array_remove(sim.gatequeue, gate, true)
sim.num_gatequeue = sim.num_gatequeue - 1 sim.num_gatequeue = sim.num_gatequeue - 1
gate.in_queue = 0 gate.c.in_queue = 0
end end
if sim.inputqueue~=nil then sim.inputqueue[gate] = nil end if sim.inputqueue~=nil then sim.inputqueue[gate] = nil end
if sim.initqueue ~=nil then sim.initqueue [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 if sim.tickqueue[sim.current_tick] ~= nil then
for i, gate in pairs(sim.tickqueue[sim.current_tick]) do 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) Simulation.queuegate(sim, gate)
end end
end end
@ -340,7 +340,7 @@ function Simulation.ticklogic(sim)
for i = 1, sim.num_gatequeue do for i = 1, sim.num_gatequeue do
local gate = sim.gatequeue[i] local gate = sim.gatequeue[i]
gate.logic(gate) gate.logic(gate)
gate.in_queue = 0 gate.c.in_queue = 0
sim.gatequeue[i] = nil sim.gatequeue[i] = nil
end end
--sim.gatequeue = {} --sim.gatequeue = {}