connect up LD/ST matrix properly
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 3 Jun 2019 08:13:14 +0000 (09:13 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 3 Jun 2019 08:13:14 +0000 (09:13 +0100)
src/scoreboard/ldst_dep_cell.py
src/scoreboard/ldst_matrix.py

index 5f8ff890937b53609a6b3788be546d9c18cb6c73..70f4b9ba0e1b36e20194408dbd39d135cb3d3363 100644 (file)
@@ -1,13 +1,5 @@
 """ Mitch Alsup 6600-style LD/ST scoreboard Dependency Cell
 
-Relevant comments (p45-46):
-
-* If there are no WAR dependencies on a Load instruction with a computed
-  address it can assert Bank_Addressable and Translate_Addressable.
-
-* If there are no RAW dependencies on a Store instruction with both a
-  write permission and store data present it can assert Bank_Addressable
-
 Relevant bugreports:
 
 * http://bugs.libre-riscv.org/show_bug.cgi?id=81
@@ -26,10 +18,12 @@ class LDSTDepCell(Elaboratable):
     def __init__(self, n_ls=1):
         self.n_ls = n_ls
         # inputs
-        self.load_i = Signal(n_ls, reset_less=True)     # load pend in (top)
-        self.stor_i = Signal(n_ls, reset_less=True)     # store pend in (top)
-        self.issue_i = Signal(reset_less=True)    # Issue in (top)
-        self.go_die_i = Signal(reset_less=True)    # Issue in (top)
+        self.load_h_i = Signal(reset_less=True)     # load in (left)
+        self.stor_h_i = Signal(reset_less=True)     # store in (left)
+        self.load_v_i = Signal(n_ls, reset_less=True)     # load in (top)
+        self.stor_v_i = Signal(n_ls, reset_less=True)     # store in (top)
+        self.issue_i = Signal(reset_less=True)    # Issue in (left)
+        self.go_die_i = Signal(reset_less=True)    # Issue in (left)
 
         # load / store hit - basically connect these to go_wr from LD/STCompUnit
         # LD.go_wr -> load_hit_i, ST.go_wr -> stwd_hit_i.
@@ -49,17 +43,25 @@ class LDSTDepCell(Elaboratable):
         issue = Repl(self.issue_i, self.n_ls)
         die = Repl(self.go_die_i, self.n_ls)
 
-        # issue & store & load - used for both WAR and RAW Setting
+        # issue & store & load - used for WAR Setting.  LD is left, ST is top
+        i_s = Signal(reset_less=True)
         i_s_l = Signal(self.n_ls, reset_less=True)
-        m.d.comb += i_s_l.eq(issue & self.stor_i & self.load_i)
+        m.d.comb += i_s.eq(issue & self.stor_h_i) # horizontal single-signal
+        m.d.comb += i_s_l.eq(Repl(i_s, self.n_ls) & self.load_v_i) # multi, vert
+
+        # issue & load & store - used for RAW Setting.  ST is left, LD is top
+        i_l = Signal(reset_less=True)
+        i_l_s = Signal(self.n_ls, reset_less=True)
+        m.d.comb += i_l.eq(issue & self.load_h_i) # horizontal single-signal
+        m.d.comb += i_l_s.eq(Repl(i_l, self.n_ls) & self.stor_v_i) # multi, vert
 
         # write after read latch: loads block stores
         m.d.comb += war_l.s.eq(i_s_l)
-        m.d.comb += war_l.r.eq(die | self.load_i) # reset on LD
+        m.d.comb += war_l.r.eq(die | ~self.load_v_i) # reset on LD
 
         # read after write latch: stores block loads
         m.d.comb += raw_l.s.eq(i_s_l)
-        m.d.comb += raw_l.r.eq(die | self.stor_i) # reset on ST
+        m.d.comb += raw_l.r.eq(die | ~self.stor_v_i) # reset on ST
 
         # Hold results (read out horizontally, accumulate in OR fashion)
         m.d.comb += self.ld_hold_st_o.eq((war_l.qn & self.load_hit_i).bool())
@@ -68,8 +70,10 @@ class LDSTDepCell(Elaboratable):
         return m
 
     def __iter__(self):
-        yield self.load_i
-        yield self.stor_i
+        yield self.load_h_i
+        yield self.load_v_i
+        yield self.stor_h_i
+        yield self.stor_h_i
         yield self.issue_i
         yield self.load_hit_i
         yield self.stwd_hit_i
index dc9d736238a3883301194fbd339b5ba5cb226edc..1597f36497e5fffebfe55a37755d75951c670c85 100644 (file)
@@ -12,8 +12,22 @@ Relevant comments (p45-46):
   write permission and store data present it can assert Bank_Addressable
 
 Relevant bugreports:
+
 * http://bugs.libre-riscv.org/show_bug.cgi?id=81
 
+Notes:
+
+* Load Hit (or Store Hit with Data) are asserted by the LD/ST Computation
+  Unit when it has data and address ready
+
+* Asserting the ld_hit_i (or stwd_hit_i) *requires* that the output be
+  captured or at least taken into consideration for the next LD/STs
+  *right then*.  Failure to observe the xx_hold_xx_o *will* result in
+  data corruption, as they are *only* asserted if xx_hit_i is asserted
+
+* The hold signals still have to go through "maybe address clashes"
+  detection, they cannot just be used as-is to stop a LD/ST.
+
 """
 
 from nmigen.compat.sim import run_simulation
@@ -41,21 +55,21 @@ class LDSTDepMatrix(Elaboratable):
         self.stwd_hit_i = Signal(n_ldst, reset_less=True) # store w/data hit in
 
         # outputs
-        self.ld_hold_st_o = Signal(reset_less=True) # load holds st out
-        self.st_hold_ld_o = Signal(reset_less=True) # st holds load out
+        self.ld_hold_st_o = Signal(n_ldst, reset_less=True) # load holds st out
+        self.st_hold_ld_o = Signal(n_ldst, reset_less=True) # st holds load out
 
     def elaborate(self, platform):
         m = Module()
 
         # ---
-        # matrix of dependency cells
+        # matrix of dependency cells.  actually, LDSTDepCell is a row, now
         # ---
-        dm = Array(LDSTDepCell() for f in range(self.n_ldst))
+        dm = Array(LDSTDepCell(self.n_ldst) for f in range(self.n_ldst))
         for fu in range(self.n_ldst):
             setattr(m.submodules, "dm_fu%d" % (fu), dm[fu])
 
         # ---
-        # connect Function Unit vector
+        # connect Function Unit vector, all horizontal
         # ---
         lhs_l = []
         shl_l = []
@@ -66,26 +80,39 @@ class LDSTDepMatrix(Elaboratable):
         sh_l = []
         for fu in range(self.n_ldst):
             dc = dm[fu]
-            # accumulate load-hold-store / store-hold-load bits
+            # accumulate load-hold-store / store-hold-load bits (horizontal)
             lhs_l.append(dc.ld_hold_st_o)
             shl_l.append(dc.st_hold_ld_o)
             # accumulate inputs (for Cat'ing later) - TODO: must be a better way
-            load_l.append(dc.load_i)
-            stor_l.append(dc.stor_i)
+            load_l.append(dc.load_h_i)
+            stor_l.append(dc.stor_h_i)
             issue_l.append(dc.issue_i)
-            lh_l.append(dc.load_hit_i)
-            sh_l.append(dc.stwd_hit_i)
+
+            # load-hit and store-with-data-hit go in vertically (top)
+            m.d.comb += [dc.load_hit_i.eq(self.load_hit_i),
+                         dc.stwd_hit_i.eq(self.stwd_hit_i)
+                        ]
 
         # connect cell inputs using Cat(*list_of_stuff)
         m.d.comb += [Cat(*load_l).eq(self.load_i),
                      Cat(*stor_l).eq(self.stor_i),
                      Cat(*issue_l).eq(self.issue_i),
-                     Cat(*lh_l).eq(self.load_hit_i),
-                     Cat(*sh_l).eq(self.stwd_hit_i),
                     ]
-        # set the load-hold-store / store-hold-load OR-accumulated outputs
-        m.d.comb += self.ld_hold_st_o.eq(Cat(*lhs_l).bool())
-        m.d.comb += self.st_hold_ld_o.eq(Cat(*shl_l).bool())
+        # connect the load-hold-store / store-hold-load OR-accumulated outputs
+        m.d.comb += self.ld_hold_st_o.eq(Cat(*lhs_l))
+        m.d.comb += self.st_hold_ld_o.eq(Cat(*shl_l))
+
+        # the load/store input also needs to be connected to "top" (vertically)
+        for fu in range(self.n_ldst):
+            load_v_l = []
+            stor_v_l = []
+            for fux in range(self.n_ldst):
+                dc = dm[fux]
+                load_v_l.append(dc.load_v_i[fu])
+                stor_v_l.append(dc.stor_v_i[fu])
+            m.d.comb += [Cat(*load_v_l).eq(self.load_i),
+                         Cat(*stor_v_l).eq(self.stor_i),
+                        ]
 
         return m