split out shadow into separate module
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 23 May 2019 06:51:13 +0000 (07:51 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 23 May 2019 06:51:13 +0000 (07:51 +0100)
src/experiment/score6600.py
src/scoreboard/fn_unit.py
src/scoreboard/shadow.py [new file with mode: 0644]

index 38d61c34b93b3fd2a50301025235ce82fea940e3..a2a70e02d46c8a404b51486dbee8590bd42790d3 100644 (file)
@@ -382,17 +382,18 @@ def scoreboard_sim(dut, alusim):
 
     yield dut.int_store_i.eq(0)
 
-    for i in range(500):
+    for i in range(1000):
 
         # set random values in the registers
         for i in range(1, dut.n_regs):
-            yield dut.intregs.regs[i].reg.eq(31+i*3)
-            alusim.setval(i, 31+i*3)
+            val = randint(0, (1<<alusim.rwidth)-1) # 31+i*3
+            yield dut.intregs.regs[i].reg.eq(val)
+            alusim.setval(i, val)
 
         # create some instructions (some random, some regression tests)
         instrs = []
         if True:
-            for i in range(20):
+            for i in range(10):
                 src1 = randint(1, dut.n_regs-1)
                 src2 = randint(1, dut.n_regs-1)
                 while True:
index a0d317151294efa2f901a7a6afa2fc64ac0701bd..63beb70b3aa021cf818878391e7a056c668d9f4a 100644 (file)
@@ -5,7 +5,7 @@ from nmigen.lib.coding import Decoder
 
 from nmutil.latch import SRLatch, latchregister
 
-from .shadow_fn import ShadowFn
+from scoreboard.shadow import Shadow
 
 
 class FnUnit(Elaboratable):
@@ -84,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]
@@ -126,7 +103,7 @@ 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[i].eq(0) # to zero
+        m.d.comb += self.readable_o.eq(0) # to zero
 
         # go_wr latch: reset on go_wr HI, set on issue
         m.d.comb += wr_l.s.eq(self.issue_i)
diff --git a/src/scoreboard/shadow.py b/src/scoreboard/shadow.py
new file mode 100644 (file)
index 0000000..adb12f4
--- /dev/null
@@ -0,0 +1,128 @@
+from nmigen.compat.sim import run_simulation
+from nmigen.cli import verilog, rtlil
+from nmigen import Module, Signal, Cat, Array, Const, Elaboratable
+from nmigen.lib.coding import Decoder
+
+from nmutil.latch import SRLatch, latchregister
+
+from scoreboard.shadow_fn import ShadowFn
+
+
+class Shadow(Elaboratable):
+    """ implements shadowing 11.5.1, p55
+
+        shadowing can be used for branches as well as exceptions (interrupts),
+        load/store hold (exceptions again), and vector-element predication
+        (once the predicate is known, which it may not be at instruction issue)
+
+        Inputs
+
+        * :wid:         register file width
+        * :shadow_wid:  number of shadow/fail/good/go_die sets
+        * :n_dests:     number of destination regfile(s) (index: rfile_sel_i)
+        * :wr_pend:     if true, writable observes the g_wr_pend_i vector
+                        otherwise observes g_rd_pend_i
+
+        notes:
+
+        * dest_i / src1_i / src2_i are in *binary*, whereas...
+        * ...g_rd_pend_i / g_wr_pend_i and rd_pend_o / wr_pend_o are UNARY
+        * req_rel_i (request release) is the direct equivalent of pipeline
+                    "output valid" (valid_o)
+        * recover is a local python variable (actually go_die_o)
+        * when shadow_wid = 0, recover and shadown are Consts (i.e. do nothing)
+        * wr_pend is set False for the majority of uses: however for
+          use in a STORE Function Unit it is set to True
+    """
+    def __init__(self, shadow_wid=0):
+        self.shadow_wid = shadow_wid
+
+        if shadow_wid:
+            self.issue_i = Signal(reset_less=True)
+            self.shadow_i = Signal(shadow_wid, reset_less=True)
+            self.s_fail_i = Signal(shadow_wid, reset_less=True)
+            self.s_good_i = Signal(shadow_wid, reset_less=True)
+            self.go_die_o = Signal(reset_less=True)
+            self.shadown_o = Signal(reset_less=True)
+        else:
+            self.shadown_o = Const(1)
+            self.go_die_o = Const(0)
+
+    def elaborate(self, platform):
+        m = Module()
+        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)
+        if self.shadow_wid:
+            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 += self.shadown_o.eq(~(Cat(*sho_l).bool()))
+            m.d.comb += self.go_die_o.eq(Cat(*rec_l).bool())
+
+        return m
+
+    def __iter__(self):
+        if self.shadow_wid:
+            yield self.issue_i
+            yield self.shadow_i
+            yield self.s_fail_i
+            yield self.s_good_i
+        yield self.go_die_o
+        yield self.shadown_o
+
+    def ports(self):
+        return list(self)
+
+
+def shadow_sim(dut):
+    yield dut.dest_i.eq(1)
+    yield dut.issue_i.eq(1)
+    yield
+    yield dut.issue_i.eq(0)
+    yield
+    yield dut.src1_i.eq(1)
+    yield dut.issue_i.eq(1)
+    yield
+    yield
+    yield
+    yield dut.issue_i.eq(0)
+    yield
+    yield dut.go_rd_i.eq(1)
+    yield
+    yield dut.go_rd_i.eq(0)
+    yield
+    yield dut.go_wr_i.eq(1)
+    yield
+    yield dut.go_wr_i.eq(0)
+    yield
+
+def test_shadow():
+    dut = Shadow(2)
+    vl = rtlil.convert(dut, ports=dut.ports())
+    with open("test_shadow.il", "w") as f:
+        f.write(vl)
+
+    run_simulation(dut, shadow_sim(dut), vcd_name='test_shadow.vcd')
+
+if __name__ == '__main__':
+    test_shadow()