convert SPRs and others to Data.data/ok
[soc.git] / src / scoreboard / shadow_fn.py
index 7abc8261d0d14f0482be7c2181cbb073d864b65a..69a56a5ceec13014e07a3d0e74715e9506a097e5 100644 (file)
@@ -1,49 +1,75 @@
 from nmigen.compat.sim import run_simulation
 from nmigen.cli import verilog, rtlil
-from nmigen import Module, Signal, Cat, Elaboratable
+from nmigen import Module, Signal, Cat, Repl, Const, Elaboratable
 from nmutil.latch import SRLatch
 
 
 class ShadowFn(Elaboratable):
     """ implements shadowing 11.5.1, p55, just the individual shadow function
-    """
-    def __init__(self):
 
-        # inputs
-        self.issue_i = Signal(reset_less=True)
-        self.shadow_i  = Signal(reset_less=True)
-        self.reset_i  = Signal(reset_less=True)
-        self.s_fail_i  = Signal(reset_less=True)
-        self.s_good_i  = Signal(reset_less=True)
+        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
+        * :shadow_wid:  number of shadow/fail/good/go_die sets
 
-        # outputs
-        self.shadow_o = Signal(reset_less=True)
-        self.recover_o = Signal(reset_less=True)
+        notes:
+        * when shadow_wid = 0, recover and shadown are Consts (i.e. do nothing)
+    """
+    def __init__(self, slen, syncreset=False):
+
+        self.slen = slen
+        self.syncreset = syncreset
+
+        if self.slen:
+            # inputs
+            self.issue_i = Signal(reset_less=True)
+            self.shadow_i  = Signal(slen, reset_less=True)
+            self.reset_i  = Signal(reset_less=True)
+            self.s_fail_i  = Signal(slen, reset_less=True)
+            self.s_good_i  = Signal(slen, reset_less=True)
+
+            # outputs
+            self.shadown_o = Signal(reset_less=True)
+            self.go_die_o = Signal(reset_less=True)
+        else:
+            # outputs when no shadowing needed
+            self.shadown_o = Const(1)
+            self.go_die_o = Const(0)
 
     def elaborate(self, platform):
         m = Module()
-        m.submodules.sl = sl = SRLatch(sync=False)
-
-        #reset_r = Signal()
-        #m.d.sync += reset_r.eq(self.s_good_i | self.s_fail_i)
-
-        m.d.comb += sl.s.eq(self.shadow_i & self.issue_i & \
-                            ~self.s_good_i & ~self.reset_i)
-        m.d.comb += sl.r.eq(self.reset_i | self.s_good_i | \
-                            (self.issue_i & ~self.shadow_i))
-        m.d.comb += self.recover_o.eq(sl.qlq & self.s_fail_i)
-        m.d.comb += self.shadow_o.eq(sl.qlq)
+        if self.slen == 0:
+            return
+
+        m.submodules.sl = sl = SRLatch(sync=False, llen=self.slen)
+
+        r_ext = Repl(self.reset_i, self.slen)
+        reset_r = Signal(self.slen)
+        if self.syncreset:
+            m.d.comb += reset_r.eq(self.s_good_i | self.s_fail_i | r_ext)
+        else:
+            m.d.comb += reset_r.eq(self.s_good_i | self.s_fail_i | r_ext)
+
+        i_ext = Repl(self.issue_i, self.slen)
+        m.d.comb += sl.s.eq(self.shadow_i & i_ext & \
+                            ~self.s_good_i & ~reset_r)
+        m.d.comb += sl.r.eq(r_ext | reset_r | self.s_good_i | \
+                            (i_ext & ~self.shadow_i))
+        m.d.comb += self.go_die_o.eq((sl.qlq & self.s_fail_i).bool())
+        m.d.comb += self.shadown_o.eq(~sl.qlq.bool())
 
         return m
 
     def __iter__(self):
         yield self.issue_i
-        yield self.s_reset_i
+        yield self.reset_i
         yield self.shadow_i
         yield self.s_fail_i
         yield self.s_good_i
-        yield self.shadow_o
-        yield self.recover_o
+        yield self.shadown_o
+        yield self.go_die_o
 
     def ports(self):
         return list(self)
@@ -73,7 +99,7 @@ def shadow_fn_unit_sim(dut):
 
 
 def test_shadow_fn_unit():
-    dut = ShadowFn()
+    dut = ShadowFn(4)
     vl = rtlil.convert(dut, ports=dut.ports())
     with open("test_shadow_fn_unit.il", "w") as f:
         f.write(vl)