have to bring in a reset signal into the shadow units to get them to go to
[soc.git] / src / scoreboard / fn_unit.py
index b2ef9468a243fa89adc9e3736d00ff16324e19ec..63beb70b3aa021cf818878391e7a056c668d9f4a 100644 (file)
@@ -1,10 +1,11 @@
 from nmigen.compat.sim import run_simulation
 from nmigen.cli import verilog, rtlil
 from nmigen import Module, Signal, Cat, Array, Const, Elaboratable
-from nmutil.latch import SRLatch
 from nmigen.lib.coding import Decoder
 
-from shadow_fn import ShadowFn
+from nmutil.latch import SRLatch, latchregister
+
+from scoreboard.shadow import Shadow
 
 
 class FnUnit(Elaboratable):
@@ -50,8 +51,8 @@ class FnUnit(Elaboratable):
         self.src2_i = Signal(max=wid, reset_less=True) # oper2 R# in (top)
         self.issue_i = Signal(reset_less=True)    # Issue in (top)
 
-        self.go_write_i = Signal(reset_less=True) # Go Write in (left)
-        self.go_read_i = Signal(reset_less=True)  # Go Read in (left)
+        self.go_wr_i = Signal(reset_less=True) # Go Write in (left)
+        self.go_rd_i = Signal(reset_less=True)  # Go Read in (left)
         self.req_rel_i = Signal(reset_less=True)  # request release (left)
 
         self.g_xx_pend_i = Array(Signal(wid, reset_less=True, name="g_pend_i") \
@@ -70,6 +71,8 @@ class FnUnit(Elaboratable):
                                for i in range(n_dests)) # writable out (right)
         self.busy_o = Signal(reset_less=True) # busy out (left)
 
+        self.src1_pend_o = Signal(wid, reset_less=True) # src1 pending
+        self.src2_pend_o = Signal(wid, reset_less=True) # src1 pending
         self.rd_pend_o = Signal(wid, reset_less=True) # rd pending (right)
         self.xx_pend_o = Array(Signal(wid, reset_less=True, name="pend_o") \
                                for i in range(n_dests))# wr pending (right)
@@ -81,39 +84,16 @@ class FnUnit(Elaboratable):
         m.submodules.dest_d = dest_d = Decoder(self.reg_width)
         m.submodules.src1_d = src1_d = Decoder(self.reg_width)
         m.submodules.src2_d = src2_d = Decoder(self.reg_width)
-        s_latches = []
-        for i in range(self.shadow_wid):
-            sh = ShadowFn()
-            setattr(m.submodules, "shadow%d" % i, sh)
-            s_latches.append(sh)
 
         # shadow / recover (optional: shadow_wid > 0)
+        m.submodules.shadow = shadow = Shadow(self.shadow_wid)
         if self.shadow_wid:
-            recover = self.go_die_o
-            shadown = Signal(reset_less=True)
-            i_l = []
-            fail_l = []
-            good_l = []
-            shi_l = []
-            sho_l = []
-            rec_l = []
-            # get list of latch signals. really must be a better way to do this
-            for l in s_latches:
-                i_l.append(l.issue_i)
-                shi_l.append(l.shadow_i)
-                fail_l.append(l.s_fail_i)
-                good_l.append(l.s_good_i)
-                sho_l.append(l.shadow_o)
-                rec_l.append(l.recover_o)
-            m.d.comb += Cat(*i_l).eq(self.issue_i)
-            m.d.comb += Cat(*fail_l).eq(self.s_fail_i)
-            m.d.comb += Cat(*good_l).eq(self.s_good_i)
-            m.d.comb += Cat(*shi_l).eq(self.shadow_i)
-            m.d.comb += shadown.eq(~(Cat(*sho_l).bool()))
-            m.d.comb += recover.eq(Cat(*rec_l).bool())
-        else:
-            shadown = Const(1)
-            recover = Const(0)
+            m.d.comb += shadow.issue_i.eq(self.issue_i)
+            m.d.comb += shadow.s_fail_i.eq(self.s_fail_i)
+            m.d.comb += shadow.s_good_i.eq(self.s_good_i)
+            m.d.comb += shadow.shadow_i.eq(self.shadow_i)
+        shadown = shadow.shadown_o
+        recover = shadow.go_die_o
 
         # selector
         xx_pend_o = self.xx_pend_o[self.rfile_sel_i]
@@ -123,32 +103,46 @@ class FnUnit(Elaboratable):
         for i in range(self.n_dests):
             m.d.comb += self.xx_pend_o[i].eq(0)  # initialise all array
             m.d.comb += self.writable_o[i].eq(0) # to zero
+        m.d.comb += self.readable_o.eq(0) # to zero
 
-        # go_write latch: reset on go_write HI, set on issue
+        # go_wr latch: reset on go_wr HI, set on issue
         m.d.comb += wr_l.s.eq(self.issue_i)
-        m.d.comb += wr_l.r.eq(self.go_write_i | recover)
+        m.d.comb += wr_l.r.eq(self.go_wr_i | recover)
 
-        # src1 latch: reset on go_read HI, set on issue
+        # src1 latch: reset on go_rd HI, set on issue
         m.d.comb += rd_l.s.eq(self.issue_i)
-        m.d.comb += rd_l.r.eq(self.go_read_i | recover)
-
-        # dest decoder: write-pending out
-        m.d.comb += dest_d.i.eq(self.dest_i)
+        m.d.comb += rd_l.r.eq(self.go_rd_i | recover)
+
+        # latch/registers for dest / src1 / src2
+        dest_r = Signal(max=self.reg_width, reset_less=True)
+        src1_r = Signal(max=self.reg_width, reset_less=True)
+        src2_r = Signal(max=self.reg_width, reset_less=True)
+        # XXX latch based on *issue* rather than !latch (as in book)
+        latchregister(m, self.dest_i, dest_r, self.issue_i) #wr_l.qn)
+        latchregister(m, self.src1_i, src1_r, self.issue_i) #wr_l.qn)
+        latchregister(m, self.src2_i, src2_r, self.issue_i) #wr_l.qn)
+
+        # dest decoder (use dest reg as input): write-pending out
+        m.d.comb += dest_d.i.eq(dest_r)
         m.d.comb += dest_d.n.eq(wr_l.qn) # decode is inverted
         m.d.comb += self.busy_o.eq(wr_l.q) # busy if set
         m.d.comb += xx_pend_o.eq(dest_d.o)
 
-        # src1/src2 decoder: read-pending out
-        m.d.comb += src1_d.i.eq(self.src1_i)
+        # src1/src2 decoder (use src1/2 regs as input): read-pending out
+        m.d.comb += src1_d.i.eq(src1_r)
         m.d.comb += src1_d.n.eq(rd_l.qn) # decode is inverted
-        m.d.comb += src2_d.i.eq(self.src2_i)
+        m.d.comb += src2_d.i.eq(src2_r)
         m.d.comb += src2_d.n.eq(rd_l.qn) # decode is inverted
+        m.d.comb += self.src1_pend_o.eq(src1_d.o)
+        m.d.comb += self.src2_pend_o.eq(src2_d.o)
         m.d.comb += self.rd_pend_o.eq(src1_d.o | src2_d.o)
 
         # readable output signal
         g_rd = Signal(self.reg_width, reset_less=True)
-        m.d.comb += g_rd.eq(self.g_wr_pend_i & self.rd_pend_o)
-        m.d.comb += self.readable_o.eq(g_rd.bool())
+        ro = Signal(reset_less=True)
+        m.d.comb += g_rd.eq(~self.g_wr_pend_i & self.rd_pend_o)
+        m.d.comb += ro.eq(~g_rd.bool())
+        m.d.comb += self.readable_o.eq(ro)
 
         # writable output signal
         g_wr_v = Signal(self.reg_width, reset_less=True)
@@ -156,7 +150,7 @@ class FnUnit(Elaboratable):
         wo = Signal(reset_less=True)
         m.d.comb += g_wr_v.eq(g_pend_i & xx_pend_o)
         m.d.comb += g_wr.eq(~g_wr_v.bool())
-        m.d.comb += wo.eq(g_wr & rd_l.q & self.req_rel_i & shadown)
+        m.d.comb += wo.eq(g_wr & rd_l.qn & self.req_rel_i & shadown)
         m.d.comb += writable_o.eq(wo)
 
         return m
@@ -166,8 +160,8 @@ class FnUnit(Elaboratable):
         yield self.src1_i
         yield self.src2_i
         yield self.issue_i
-        yield self.go_write_i
-        yield self.go_read_i
+        yield self.go_wr_i
+        yield self.go_rd_i
         yield self.req_rel_i
         yield from self.g_xx_pend_i
         yield self.g_wr_pend_i
@@ -296,13 +290,13 @@ def int_fn_unit_sim(dut):
     yield
     yield dut.issue_i.eq(0)
     yield
-    yield dut.go_read_i.eq(1)
+    yield dut.go_rd_i.eq(1)
     yield
-    yield dut.go_read_i.eq(0)
+    yield dut.go_rd_i.eq(0)
     yield
-    yield dut.go_write_i.eq(1)
+    yield dut.go_wr_i.eq(1)
     yield
-    yield dut.go_write_i.eq(0)
+    yield dut.go_wr_i.eq(0)
     yield
 
 def test_int_fn_unit():