local ffi = FFI or require("ffi") Group = {} ffi.cdef [[ struct Gate; struct Net { int* state; int* state_num; int* in_queue; int* update_tick; int* num_gates_update; struct Gate** gates_update_c; int id; }; ]] local last_net_id = 1 function Group.new() local net = { -- Logic Critical state = ffi.new("int[1]"), state_num = ffi.new("int[1]"), in_queue = ffi.new("int[1]"), update_tick = ffi.new("int[1]"), gates_update = {}, num_gates_update = ffi.new("int[1]"), gates_update_c = nil, fxstate = 0, wires = {}, out_ports = {}, in_ports = {}, nwires = 0, nout_ports = 0, nin_ports = 0, id = last_net_id, } last_net_id = last_net_id + 1 net.state[0] = 0 net.state_num[0] = 0 net.in_queue[0] = 0 net.update_tick[0] = 0 net.gates_update_c = ffi.cast("struct Gate**", 0) net.c = ffi.new("struct Net") net.c.state = net.state net.c.state_num = net.state_num net.c.in_queue = net.in_queue net.c.update_tick = net.update_tick net.c.num_gates_update = net.num_gates_update net.c.gates_update_c = net.gates_update_c net.c.id = net.id return net end function Group.getsize(group) return group.nwires + group.nout_ports + group.nin_ports end function Group.addwire(group, wire) if Wire.getgroup(wire) ~= group then if Wire.getgroup(wire) ~= nil then Group.mergewith(group, Wire.getgroup(wire)) else group.wires[wire] = wire group.nwires = group.nwires + 1 Wire.setgroup(wire, group) Wire.update(wire) Simulation.queuegroup_safe(GSim, group) end end end function Group.removewire(group, wire) Wire.setgroup(wire, nil) group.wires[wire] = nil local sim = GSim for k, wire in pairs(group.wires) do Wire.setgroup(wire, nil) end for k, port in pairs(group.out_ports) do Port.setgroup(port, nil) end for k, port in pairs(group.in_ports) do Port.setgroup(port, nil) end for k, wire in pairs(group.wires) do Simulation.connectwire(sim, wire) end for k, port in pairs(group.out_ports) do Simulation.connectport(sim, port) end for k, port in pairs(group.in_ports) do Simulation.connectport(sim, port) end group.wires = {} group.out_ports = {} group.in_ports = {} group.nwires = 0 group.nout_ports = 0 group.nin_ports = 0 Simulation.remove_net(GSim, group) Simulation.dequeuegroup(GSim, group) end function Group.addport(group, port) if port.group~=nil then error("port already has group") end Port.setgroup(port, group) if port.type == PortTypes.output then if group.out_ports[port] then error("port already in group") end group.out_ports[port] = port group.nout_ports = group.nout_ports + 1 group.state_num[0] = group.state_num[0] + Port.getstate(port) Simulation.queuegroup_safe(GSim, group) elseif port.type == PortTypes.input then if group.in_ports[port] then error("port already in group") end group.in_ports[port] = port group.nin_ports = group.nin_ports + 1 Simulation.queuegate_safe(GSim, Port.getgate(port)) end Group.rebuild_ports(group) end function Group.removeport(group, port) if port.group~=group then error("port does not have group") end Port.setgroup(port, nil) if port.type == PortTypes.output then if not group.out_ports[port] then error("port not in group") end group.out_ports[port] = nil group.nout_ports = group.nout_ports - 1 group.state_num[0] = group.state_num[0] - Port.getstate(port) Simulation.queuegroup_safe(GSim, group) elseif port.type == PortTypes.input then if not group.in_ports[port] then error("port not in group") end group.in_ports[port] = nil group.nin_ports = group.nin_ports - 1 Simulation.queuegate_safe(GSim, Port.getgate(port)) end Group.rebuild_ports(group) end function Group.mergewith(group, group2) if Group.getsize(group) >= Group.getsize(group2) then Group.mergeinto(group2, group) return group else Group.mergeinto(group, group2) return group2 end end function Group.mergeinto(group, group2) for k, wire in pairs(group.wires) do Wire.setgroup(wire, nil) Group.addwire(group2, wire) end for k, port in pairs(group.out_ports) do Port.setgroup(port, nil) Group.addport(group2, port) end for k, port in pairs(group.in_ports) do Port.setgroup(port, nil) Group.addport(group2, port) end group.wires = {} group.out_ports = {} group.in_ports = {} group.nwires = 0 group.nout_ports = 0 group.nin_ports = 0 Simulation.remove_net(GSim, group) Simulation.dequeuegroup(GSim, group) end -- Logic Critical -- Now implemented in C --function Group.update_c(cnet, tick) -- local state = cnet.state_num[0]>0 and 1 or 0 -- if state ~= cnet.state[0] then -- cnet.state[0] = state -- cnet.update_tick[0] = tick -- -- local len = cnet.num_gates_update[0]-1 -- for i = 0, len do -- local cgate = cnet.gates_update_c[i] -- if cgate.in_queue[0]==0 then -- Simulation.queuegate_c(GSim, cgate) -- end -- end -- -- --Simulation.queuegroupfx(GSim, net) -- end --end function Group.rebuild_ports(net) net.gates_update = {} net.num_gates_update[0] = 0 local gates_seen = {} for k, port in pairs(net.in_ports) do if port.causeupdate then local gate = Port.getgate(port) if not gates_seen[gate] then gates_seen[gate] = true net.gates_update[net.num_gates_update[0]+1] = gate net.num_gates_update[0] = net.num_gates_update[0] + 1 end end end net.gates_update_c = ffi.new("struct Gate*["..(net.num_gates_update[0]+1).."]") for i = 0, net.num_gates_update[0]-1 do net.gates_update_c[i] = net.gates_update[i+1].c end net.c.gates_update_c = net.gates_update_c end