From: Luke Kenneth Casson Leighton Date: Mon, 3 Jun 2019 08:13:14 +0000 (+0100) Subject: connect up LD/ST matrix properly X-Git-Tag: div_pipeline~1894 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7adf51897efdb091cce67a7db7ab2a20ebd34e35;p=soc.git connect up LD/ST matrix properly --- diff --git a/src/scoreboard/ldst_dep_cell.py b/src/scoreboard/ldst_dep_cell.py index 5f8ff890..70f4b9ba 100644 --- a/src/scoreboard/ldst_dep_cell.py +++ b/src/scoreboard/ldst_dep_cell.py @@ -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 diff --git a/src/scoreboard/ldst_matrix.py b/src/scoreboard/ldst_matrix.py index dc9d7362..1597f364 100644 --- a/src/scoreboard/ldst_matrix.py +++ b/src/scoreboard/ldst_matrix.py @@ -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