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(self) 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, } setmetatable(o, self) self.__index = self return o end function Group.getsize(self) return self.nwires + self.nout_ports + self.nin_ports end function Group.addwire(self, wire) if Wire.getgroup(wire) ~= self then if Wire.getgroup(wire) ~= nil then Group.mergewith(self, Wire.getgroup(wire)) else self.wires[wire] = wire self.nwires = self.nwires + 1 Wire.setgroup(wire, self) Wire.update(wire) Simulation.queuegroup(GSim, self) end end end function Group.removewire(self, wire) Wire.setgroup(wire, nil) self.wires[wire] = nil local sim = GSim for k, wire in pairs(self.wires) do Wire.setgroup(wire, nil) end for k, port in pairs(self.out_ports) do Port.setgroup(port, nil) end for k, port in pairs(self.in_ports) do Port.setgroup(port, nil) end for k, wire in pairs(self.wires) do Simulation.connectwire(sim, wire) end for k, port in pairs(self.out_ports) do Simulation.connectport(sim, port) end for k, port in pairs(self.in_ports) do Simulation.connectport(sim, port) end self.wires = {} self.out_ports = {} self.in_ports = {} self.nwires = 0 self.nout_ports = 0 self.nin_ports = 0 Simulation.dequeuegroup(GSim, self) end function Group.addport(self, port) if port.group~=nil then error("port already has group") end port.group = self if port.type == PortTypes.output then if self.out_ports[port] then error("port already in group") end self.out_ports[port] = port self.nout_ports = self.nout_ports + 1 if Port.getstate(port) then self.state_num = self.state_num + 1 end Simulation.queuegroup(GSim, self) elseif port.type == PortTypes.input then if self.in_ports[port] then error("port already in group") end self.in_ports[port] = port self.nin_ports = self.nin_ports + 1 if port.causeupdate then self.in_ports_update[port] = port end Simulation.queuegate(GSim, Port.getgate(port)) end end function Group.removeport(self, port) if port.group~=self then error("port does not have group") end port.group = nil if port.type == PortTypes.output then if not self.out_ports[port] then error("port not in group") end self.out_ports[port] = nil self.nout_ports = self.nout_ports - 1 if Port.getstate(port) then self.state_num = self.state_num - 1 end Simulation.queuegroup(GSim, self) elseif port.type == PortTypes.input then if not self.in_ports[port] then error("port not in group") end self.in_ports[port] = nil self.nin_ports = self.nin_ports - 1 if port.causeupdate then self.in_ports_update[port] = nil end Simulation.queuegate(GSim, Port.getgate(port)) end end function Group.mergewith(self, group) if Group.getsize(self) >= Group.getsize(group) then Group.mergeinto(group, self) return self else Group.mergeinto(self, group) return group end end function Group.mergeinto(self, group) for k, wire in pairs(self.wires) do Wire.setgroup(wire, nil) Group.addwire(group, wire) end for k, port in pairs(self.out_ports) do Port.setgroup(port, nil) Group.addport(group, port) end for k, port in pairs(self.in_ports) do Port.setgroup(port, nil) Group.addport(group, port) end self.wires = {} self.out_ports = {} self.in_ports = {} self.nwires = 0 self.nout_ports = 0 self.nin_ports = 0 Simulation.dequeuegroup(GSim, self) end function Group.setstate(self, state) if state ~= self.state then local sim = GSim self.state = state self.updatetick = sim.currenttick for k, port in pairs(self.in_ports_update) do Simulation.queuegate(sim, Port.getgate(port)) end Simulation.queuegroupfx(sim, self) end end function Group.update(group) Group.setstate(group, group.state_num>0) end