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 {}
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
c_nets[net_idx] = c_net
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
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
function Simulation.tick_compiled(sim)
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, count)
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_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 <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 = {}
ffi.cdef [[
struct OutPort {
struct Net* net;
int state;
};
struct Gate {
int in_queue;
struct OutPort ports[0];
};
]]
function Gate.new(objref, definition)
local o = {
local gate = {
-- Logic Critical
in_queue = 0,
c = nil,
logic = definition.logic,
ports = {},
port_nets = {},
port_states = {},
objref = objref,
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
-- Logic Critical
function Gate.getportstate(gate, index)
--return gate[index*2].state
return gate.port_nets[index].state
return gate.c.ports[index].state
end
-- Logic Critical
function Gate.setportstate(gate, index, state)
--if state ~= gate[index*2+1] then
if state ~= gate.port_states[index] then
--local group = gate[index*2]
if state ~= gate.c.ports[index].state then
local group = gate.port_nets[index]
--group.state_num = group.state_num - gate[index*2+1] + state
group.state_num = group.state_num - gate.port_states[index] + state
--gate[index*2+1] = state
gate.port_states[index] = state
group.state_num = group.state_num - gate.c.ports[index].state + state
gate.c.ports[index].state = state
if ((group.state_num>0) ~= (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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 = {}