local ffi = FFI Group = {} function Group.new() local o = { -- Logic Critical state = 0, state_num = 0, in_queue = 0, gates_update = {}, num_gates_update = 0, fxstate = 0, update_tick = 0, wires = {}, out_ports = {}, in_ports = {}, 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_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.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 = group.state_num + 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 = group.state_num - 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.dequeuegroup(GSim, group) end -- Logic Critical function Group.setstate(group, state) if state ~= group.state then local sim = GSim group.state = state group.update_tick = sim.current_tick local len = group.num_gates_update for i = 1, len do local gate = group.gates_update[i] if gate.in_queue==0 then Simulation.queuegate(sim, gate) end end Simulation.queuegroupfx(sim, group) end end -- Logic Critical function Group.update(group) Group.setstate(group, group.state_num>0 and 1 or 0) end function Group.rebuild_ports(group) group.gates_update = {} group.num_gates_update = 0 for k, port in pairs(group.in_ports) do if port.causeupdate then array_add(group.gates_update, Port.getgate(port)) group.num_gates_update = group.num_gates_update + 1 end end end