Group = {} FFI.cdef[[ struct Port; struct Net { bool state; bool fxstate; bool in_queue; int updatetick; int internal_ref; int state_num; int num_in_ports_update; struct Port* in_ports_update[1]; }; ]] function Group.new() local o = { state = false, fxstate = false, updatetick = 0, wires = {}, out_ports = {}, in_ports = {}, in_ports_update = {}, state_num = 0, in_queue = false, nwires = 0, nout_ports = 0, nin_ports = 0, } return o 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(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.dequeuegroup(GSim, group) end function Group.addport(group, port) if port.group~=nil then error("port already has group") end port.group = 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 if Port.getstate(port) then group.state_num = group.state_num + 1 end Simulation.queuegroup(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 if port.causeupdate then table.insert(group.in_ports_update, port) end Simulation.queuegate(GSim, Port.getgate(port)) end end function Group.removeport(group, port) if port.group~=group then error("port does not have group") end port.group = 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 if Port.getstate(port) then group.state_num = group.state_num - 1 end Simulation.queuegroup(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 if port.causeupdate then array_remove(group.in_ports_update, port) end Simulation.queuegate(GSim, Port.getgate(port)) end 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.dequeuegroup(GSim, group) end function Group.setstate(group, state) if state ~= group.state then local sim = GSim group.state = state group.updatetick = sim.currenttick for k, port in ipairs(group.in_ports_update) do Simulation.queuegate(sim, Port.getgate(port)) end Simulation.queuegroupfx(sim, group) end end function Group.update(group) Group.setstate(group, group.state_num>0) end