bugfix new ReservationStations2
[nmutil.git] / src / nmutil / concurrentunit.py
index 433ec10b4a50fed67c9deb3f3553f338e314cd7d..b0faea7d35d4845c5555179d2fba6247ffa6f7bf 100644 (file)
 """
 
 from math import log
 """
 
 from math import log
-from nmigen import Module, Elaboratable, Signal
+from nmigen import Module, Elaboratable, Signal, Cat
 from nmigen.asserts import Assert
 from nmigen.asserts import Assert
+from nmigen.lib.coding import PriorityEncoder
 from nmigen.cli import main, verilog
 
 from nmutil.singlepipe import PassThroughStage
 from nmutil.multipipe import CombMuxOutPipe
 from nmutil.multipipe import PriorityCombMuxInPipe
 from nmigen.cli import main, verilog
 
 from nmutil.singlepipe import PassThroughStage
 from nmutil.multipipe import CombMuxOutPipe
 from nmutil.multipipe import PriorityCombMuxInPipe
-from nmutil.multipipe import InputPriorityArbiter
 from nmutil.iocontrol import NextControl, PrevControl
 from nmutil.iocontrol import NextControl, PrevControl
+from nmutil import nmoperator
 
 
 def num_bits(n):
 
 
 def num_bits(n):
@@ -193,16 +194,15 @@ class ReservationStations2(Elaboratable):
         self.n = []
         self.alu = alu
         # create prev and next ready/valid and add replica of ALU data specs
         self.n = []
         self.alu = alu
         # create prev and next ready/valid and add replica of ALU data specs
-        for i in range(p_len):
+        for i in range(num_rows):
             suffix = "_%d" % i
             suffix = "_%d" % i
-            p = PrevControl(maskwid=i_wid, name=suffix)
-            n = NextControl(maskwid=i_wid, name=suffix)
+            p = PrevControl(name=suffix)
+            n = NextControl(name=suffix)
             p.i_data, n.o_data = self.alu.new_specs("rs_%d" % i)
             self.p.append(p)
             self.n.append(n)
 
         self.pipe = self # for Arbiter to select the incoming prevcontrols
             p.i_data, n.o_data = self.alu.new_specs("rs_%d" % i)
             self.p.append(p)
             self.n.append(n)
 
         self.pipe = self # for Arbiter to select the incoming prevcontrols
-        self.p_mux = InputPriorityArbiter(self, num_rows)
 
         # set up pseudo-alus that look like a standard pipeline
         self.pseudoalus = []
 
         # set up pseudo-alus that look like a standard pipeline
         self.pseudoalus = []
@@ -223,6 +223,9 @@ class ReservationStations2(Elaboratable):
         pe = PriorityEncoder(self.num_rows) # input priority picker
         m.submodules.alu = self.alu
         m.submodules.selector = pe
         pe = PriorityEncoder(self.num_rows) # input priority picker
         m.submodules.alu = self.alu
         m.submodules.selector = pe
+        for i, (p, n) in enumerate(zip(self.p, self.n)):
+            m.submodules["rs_p_%d" % i] = p
+            m.submodules["rs_n_%d" % i] = n
 
         # Priority picker for one RS
         self.active = Signal()
 
         # Priority picker for one RS
         self.active = Signal()
@@ -235,7 +238,7 @@ class ReservationStations2(Elaboratable):
 
         # pick first non-reserved ReservationStation with data not already
         # sent into the ALU
 
         # pick first non-reserved ReservationStation with data not already
         # sent into the ALU
-        m.d.comb += pe.i.eq(~rsvd & ~sent)
+        m.d.comb += pe.i.eq(rsvd & ~sent)
         m.d.comb += self.active.eq(~pe.n)   # encoder active (one input valid)
         m.d.comb += self.m_id.eq(pe.o)       # output one active input
 
         m.d.comb += self.active.eq(~pe.n)   # encoder active (one input valid)
         m.d.comb += self.m_id.eq(pe.o)       # output one active input
 
@@ -256,48 +259,45 @@ class ReservationStations2(Elaboratable):
         # input side
         #####
 
         # input side
         #####
 
-        # check if ALU is ready
-        n_i_ready = Signal(reset_less=True, name="n_i_rdy_data")
-        m.d.comb += alu_p_i_valid.eq(self.alu.p.i_valid_test)
-
         # first, establish input: select one input to pass data to (p_mux)
         for i in range(self.num_rows):
         # first, establish input: select one input to pass data to (p_mux)
         for i in range(self.num_rows):
-            i_buf = _spec(self.alu.stage.ispec, "i_buf%d" % i) # input buffer
-            o_buf = _spec(self.alu.stage.ospec, "o_buf%d" % i) # output buffer
+            i_buf, o_buf = self.alu.new_specs("buf%d" % i) # buffers
             with m.FSM():
                 # indicate ready to accept data, and accept it if incoming
                 with m.State("ACCEPTING%d" % i):
                     m.d.comb += self.p[i].o_ready.eq(1) # ready indicator
             with m.FSM():
                 # indicate ready to accept data, and accept it if incoming
                 with m.State("ACCEPTING%d" % i):
                     m.d.comb += self.p[i].o_ready.eq(1) # ready indicator
+                    m.d.sync += self.n[i].o_valid.eq(0) # invalidate output
                     with m.If(self.p[i].i_valid):  # valid data incoming
                         m.d.sync += rsvd[i].eq(1)  # now reserved
                         m.d.sync += nmoperator.eq(i_buf, self.p[i].i_data)
                     with m.If(self.p[i].i_valid):  # valid data incoming
                         m.d.sync += rsvd[i].eq(1)  # now reserved
                         m.d.sync += nmoperator.eq(i_buf, self.p[i].i_data)
-                        m.next = "ACCEPTED%d" % i) # move to "accepted"
+                        m.next = "ACCEPTED%d" % i # move to "accepted"
                 # now try to deliver to the ALU, but only if we are "picked"
                 with m.State("ACCEPTED%d" % i):
                 # now try to deliver to the ALU, but only if we are "picked"
                 with m.State("ACCEPTED%d" % i):
-                    with m.If(mid == i): # priority picker selected us
+                    with m.If(mid == i): # picker selected us
                         with m.If(self.alu.p.o_ready):  # ALU can accept
                             m.d.comb += self.alu.p.i_valid.eq(1) # transfer
                             m.d.comb += nmoperator.eq(self.alu.p.i_data, i_buf)
                             m.d.sync += sent[i].eq(1) # now reserved
                         with m.If(self.alu.p.o_ready):  # ALU can accept
                             m.d.comb += self.alu.p.i_valid.eq(1) # transfer
                             m.d.comb += nmoperator.eq(self.alu.p.i_data, i_buf)
                             m.d.sync += sent[i].eq(1) # now reserved
-                            m.next = "WAITOUT%d" % i) # move to "wait output"
+                            m.next = "WAITOUT%d" % i # move to "wait output"
                 # waiting for output to appear on the ALU, take a copy
                 with m.State("WAITOUT%d" % i):
                     with m.If(o_muxid == i): # when ALU output matches our RS
                 # waiting for output to appear on the ALU, take a copy
                 with m.State("WAITOUT%d" % i):
                     with m.If(o_muxid == i): # when ALU output matches our RS
-                        with m.If(self.n.alu.o_valid):  # ALU can accept
+                        with m.If(self.alu.n.o_valid):  # ALU can accept
                             m.d.sync += nmoperator.eq(o_buf, self.alu.n.o_data)
                             m.d.sync += wait[i].eq(1) # now waiting
                             m.d.sync += nmoperator.eq(o_buf, self.alu.n.o_data)
                             m.d.sync += wait[i].eq(1) # now waiting
-                            m.next = "SENDON%d" % i) # move to "send data on"
+                            m.next = "SENDON%d" % i # move to "send data on"
                 # waiting for "valid" indicator on RS output: deliver it
                 with m.State("SENDON%d" % i):
                     with m.If(self.n[i].i_ready): # user is ready to receive
                 # waiting for "valid" indicator on RS output: deliver it
                 with m.State("SENDON%d" % i):
                     with m.If(self.n[i].i_ready): # user is ready to receive
-                        m.d.comb += self.n[i].o_valid.eq(1) # indicate valid
+                        # XXX this should be combinatorial not sync
+                        #m.d.sync += self.n[i].o_valid.eq(1) # indicate valid
+                        #m.d.sync += nmoperator.eq(self.n[i].o_data, o_buf)
+                        m.d.sync += self.n[i].o_valid.eq(1) # indicate valid
+                        m.d.sync += nmoperator.eq(self.n[i].o_data, o_buf)
                         m.d.sync += wait[i].eq(0) # clear waiting
                         m.d.sync += sent[i].eq(0) # and sending
                         m.d.sync += rsvd[i].eq(0) # and reserved
                         m.d.sync += wait[i].eq(0) # clear waiting
                         m.d.sync += sent[i].eq(0) # and sending
                         m.d.sync += rsvd[i].eq(0) # and reserved
-                        m.next = "ACCEPTING%d" % i) # and back to "accepting"
+                        m.next = "ACCEPTING%d" % i # and back to "accepting"
 
         return m
 
 
         return m
 
-    def ports(self):
-        return self._ports
-