diff --git a/sim/gate.lua b/sim/gate.lua index 5a0d0eb..7b6b28b 100644 --- a/sim/gate.lua +++ b/sim/gate.lua @@ -27,7 +27,7 @@ function Gate.addport(self, port) end function Gate.getportstate(self, index) - return self.ports[index].state + return Port.getinputstate(self.ports[index]) end function Gate.setportstate(self, index, state) diff --git a/sim/group.lua b/sim/group.lua index 43246ca..f278485 100644 --- a/sim/group.lua +++ b/sim/group.lua @@ -22,6 +22,7 @@ function Group.new(self, sim) wires = {}, out_ports = {}, in_ports = {}, + in_ports_update = {}, state_num = 0, @@ -92,32 +93,65 @@ function Group.removewire(self, wire) self.nwires = 0 self.nout_ports = 0 self.nin_ports = 0 + + Simulation.dequeuegroup(Group.getsim(self), 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(Group.getsim(self), 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 - Port.setinputstate(port, self.state) + if port.causeupdate then + self.in_ports_update[port] = port + end + + Simulation.queuegate(Port.getsim(port), 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(Group.getsim(self), 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(Port.getsim(port), Port.getgate(port)) end - - Simulation.queuegroup(Group.getsim(self), self) end function Group.mergewith(self, group) @@ -137,13 +171,15 @@ function Group.mergeinto(self, group) 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 = {} @@ -151,6 +187,8 @@ function Group.mergeinto(self, group) self.nwires = 0 self.nout_ports = 0 self.nin_ports = 0 + + Simulation.dequeuegroup(Group.getsim(self), self) end function Group.setstate(self, state) @@ -158,8 +196,8 @@ function Group.setstate(self, state) self.state = state self.updatetick = Group.getsim(self).currenttick - for k, port in pairs(self.in_ports) do - Port.setinputstate(port, state) + for k, port in pairs(self.in_ports_update) do + Simulation.queuegate(Port.getsim(port), Port.getgate(port)) end Simulation.queuegroupfx(Group.getsim(self), self) @@ -171,13 +209,5 @@ function Group.getsim(group) 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) + Group.setstate(group, group.state_num>0) end diff --git a/sim/main.lua b/sim/main.lua index 0df544e..ac02d0b 100644 --- a/sim/main.lua +++ b/sim/main.lua @@ -260,8 +260,9 @@ while 1 do local wire = Simulation.getwirebyref(sim, objref) if wire then local group = Wire.getgroup(wire) - local numwires = 0; for k, wire2 in pairs(group.wires ) do numwires = numwires +1 end - local numportsi = 0; for k, port in pairs(group.in_ports ) do numportsi = numportsi+1 end + local numwires = 0; for k, wire2 in pairs(group.wires ) do numwires = numwires +1 end + local numportsi = 0; for k, port in pairs(group.in_ports ) do numportsi = numportsi+1 end + local numportsu = 0; for k, port in pairs(group.in_ports_update) do numportsu = numportsu+1 end local numportso = 0; local numportson=0; for k, port in pairs(group.out_ports) do numportso = numportso+1 @@ -272,7 +273,8 @@ while 1 do "Wires: "..numwires.."\n".. "In Ports: " ..numportsi.."\n".. "Out Ports: "..numportso.."\n".. - "Out Ports On: "..numportson + "In Ports Update: "..numportsu.."\n".. + "Out Ports On: "..(group.state_num) ; end diff --git a/sim/port.lua b/sim/port.lua index a2767aa..277bc45 100644 --- a/sim/port.lua +++ b/sim/port.lua @@ -45,19 +45,15 @@ function Port.new(self, type, direction, position, causeupdate, sim) return o end -function Port.setstate(port, state) +function Port.setstate(port, state) -- output state if state ~= port.state then port.state = state - Simulation.queuegroup(Port.getsim(port), port.group) - end -end - -function Port.setinputstate(port, state) - if state ~= port.state then - port.state = state - if port.causeupdate then - Simulation.queuegate(Port.getsim(port), port.gate) + if state then + Port.getgroup(port).state_num = Port.getgroup(port).state_num + 1 + else + Port.getgroup(port).state_num = Port.getgroup(port).state_num - 1 end + Simulation.queuegroup(Port.getsim(port), Port.getgroup(port)) end end @@ -80,6 +76,10 @@ function Port.isfalling(port) return port.group.state == false and (port.updatetick == Port.getsim(port).currenttick) end +function Port.getgate(port) + return port.gate +end + function Port.setgate(port, gate) port.gate = gate end @@ -100,6 +100,10 @@ function Port.getstate(port) return port.state end +function Port.getinputstate(port) + return Port.getgroup(port).state +end + function Port.getsim(port) return port.sim end diff --git a/sim/simulation.lua b/sim/simulation.lua index 0cd9487..39ae01a 100644 --- a/sim/simulation.lua +++ b/sim/simulation.lua @@ -122,28 +122,28 @@ function Simulation.removewire(self, objref) self.wires[objref] = nil local bounds = Wire.getbounds(wire) - + for x = bounds[1]+1, bounds[4]-1, 2 do for z = bounds[3]+1, bounds[6]-1, 2 do self[x][bounds[2]][z][wire] = nil self[x][bounds[5]][z][wire] = nil end end - + for y = bounds[2]+1, bounds[5]-1, 2 do for z = bounds[3]+1, bounds[6]-1, 2 do self[bounds[1]][y][z][wire] = nil self[bounds[4]][y][z][wire] = nil end end - + for x = bounds[1]+1, bounds[4]-1, 2 do for y = bounds[2]+1, bounds[5]-1, 2 do self[x][y][bounds[3]][wire] = nil self[x][y][bounds[6]][wire] = nil end end - + self.nwires = self.nwires - 1 Group.removewire(Wire.getgroup(wire), wire) end @@ -156,7 +156,7 @@ function Simulation.removegate(self, objref) local pos = Port.getconnectionposition(port) self[pos[1]][pos[2]][pos[3]][port] = nil Group.removeport(Port.getgroup(port), port) - + if Port.gettype(port) == PortTypes.input then self.ninports = self.ninports - 1 elseif Port.gettype(port) == PortTypes.output then @@ -164,7 +164,8 @@ function Simulation.removegate(self, objref) end end end - + + Simulation.dequeuegate(self, gate) self.gates[objref] = nil self.ngates = self.ngates - 1 end @@ -240,7 +241,7 @@ function Simulation.queuegatelater(self, gate, delay) if self.tickqueue[tick] == nil then self.tickqueue[tick] = {} end - table.insert(self.tickqueue[tick], gate) + self.tickqueue[tick][gate] = gate end function Simulation.queuegateinput(self, gate, argv) @@ -256,6 +257,20 @@ function Simulation.queuegroup(self, group) self.groupqueue[group] = group end +function Simulation.dequeuegroup(self, group) + self.groupqueue[group] = nil + self.groupfxqueue[group] = nil +end + +function Simulation.dequeuegate(self, gate) + self.gatequeue[gate] = nil + self.initqueue[gate] = nil + self.inputqueue[gate] = nil + for tick, tickq in pairs(self.tickqueue) do + tickq[gate] = nil + end +end + function Simulation.queuegroupfx(self, group) self.groupfxqueue[group] = group end @@ -283,7 +298,7 @@ function Simulation.tick(self) self.inputqueue = {} if self.tickqueue[self.currenttick] ~= nil then - for i, gate in ipairs(self.tickqueue[self.currenttick]) do + for i, gate in pairs(self.tickqueue[self.currenttick]) do Simulation.queuegate(self, gate) end self.tickqueue[self.currenttick] = nil