Group = {} FFI.cdef[[ struct Port; struct Net { bool state; bool fxstate; int updatetick; int internal_ref; int state_num; int num_in_ports_update; struct Port* in_ports_update[1]; }; ]] function Group.new(self, sim) local o = { state = false, fxstate = false, updatetick = 0, wires = {}, out_ports = {}, in_ports = {}, state_num = 0, nwires = 0, nout_ports = 0, nin_ports = 0, sim = sim, } 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(Group.getsim(self), self) end end end function Group.removewire(self, wire) Wire.setgroup(wire, nil) self.wires[wire] = nil local sim = Group.getsim(self) 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 end function Group.addport(self, port) port.group = self if port.type == PortTypes.output then self.out_ports[port] = port self.nout_ports = self.nout_ports + 1 Simulation.queuegroup(Group.getsim(self), self) elseif port.type == PortTypes.input then self.in_ports[port] = port self.nin_ports = self.nin_ports + 1 Port.setinputstate(port, self.state) end end function Group.removeport(self, port) if port.type == PortTypes.output then self.out_ports[port] = nil self.nout_ports = self.nout_ports - 1 elseif port.type == PortTypes.input then self.in_ports[port] = nil self.nin_ports = self.nin_ports - 1 end Simulation.queuegroup(Group.getsim(self), self) 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 Group.addport(group, port) end for k, port in pairs(self.in_ports) do Group.addport(group, port) end self.wires = {} self.out_ports = {} self.in_ports = {} self.nwires = 0 self.nout_ports = 0 self.nin_ports = 0 end function Group.setstate(self, state) if state ~= self.state then self.state = state self.updatetick = Group.getsim(self).currenttick for k, port in pairs(self.in_ports) do Port.setinputstate(port, state) end Simulation.queuegroupfx(Group.getsim(self), self) end end function Group.getsim(group) return group.sim end function Group.update(group) local newstate = false for j, port in pairs(group.out_ports) do newstate = newstate or Port.getstate(port) if newstate then break end end Group.setstate(group, newstate) end