1bb75b039ba793e905a96ae3f8b9c00bda3b1826
1 """ Mitch Alsup 6600-style LD/ST Memory Scoreboard Matrix (sparse vector)
3 6600 LD/ST Dependency Table Matrix inputs / outputs
4 ---------------------------------------------------
6 Relevant comments (p45-46):
8 * If there are no WAR dependencies on a Load instruction with a computed
9 address it can assert Bank_Addressable and Translate_Addressable.
11 * If there are no RAW dependencies on a Store instruction with both a
12 write permission and store data present it can assert Bank_Addressable
16 * http://bugs.libre-riscv.org/show_bug.cgi?id=81
20 * Load Hit (or Store Hit with Data) are asserted by the LD/ST Computation
21 Unit when it has data and address ready
23 * Asserting the ld_hit_i (or stwd_hit_i) *requires* that the output be
24 captured or at least taken into consideration for the next LD/STs
25 *right then*. Failure to observe the xx_hold_xx_o *will* result in
26 data corruption, as they are *only* asserted if xx_hit_i is asserted
28 * The hold signals still have to go through "maybe address clashes"
29 detection, they cannot just be used as-is to stop a LD/ST.
33 from nmigen
.compat
.sim
import run_simulation
34 from nmigen
.cli
import verilog
, rtlil
35 from nmigen
import Module
, Signal
, Elaboratable
, Array
, Cat
, Const
37 from ldst_dep_cell
import LDSTDepCell
40 class LDSTDepMatrix(Elaboratable
):
41 """ implements 11.4.12 mitch alsup LD/ST Dependency Matrix, p46
42 actually a sparse matrix along the diagonal.
44 load-hold-store and store-hold-load accumulate in a priority-picking
45 fashion, ORing together. the OR gate from the dependency cell is
48 def __init__(self
, n_ldst
):
49 self
.n_ldst
= n_ldst
# X and Y (FUs)
50 self
.ld_pend_i
= Signal(n_ldst
, reset_less
=True) # load pending in
51 self
.st_pend_i
= Signal(n_ldst
, reset_less
=True) # store pending in
52 self
.issue_i
= Signal(n_ldst
, reset_less
=True) # Issue in
53 self
.go_die_i
= Signal(n_ldst
, reset_less
=True) # Die/Reset in
55 self
.load_hit_i
= Signal(n_ldst
, reset_less
=True) # load hit in
56 self
.stwd_hit_i
= Signal(n_ldst
, reset_less
=True) # store w/data hit in
59 self
.ld_hold_st_o
= Signal(n_ldst
, reset_less
=True) # load holds st out
60 self
.st_hold_ld_o
= Signal(n_ldst
, reset_less
=True) # st holds load out
62 def elaborate(self
, platform
):
66 # matrix of dependency cells. actually, LDSTDepCell is a row, now
68 dm
= Array(LDSTDepCell(self
.n_ldst
) for f
in range(self
.n_ldst
))
69 for fu
in range(self
.n_ldst
):
70 setattr(m
.submodules
, "dm_fu%d" % (fu
), dm
[fu
])
73 # connect Function Unit vector, all horizontal
81 for fu
in range(self
.n_ldst
):
83 # accumulate load-hold-store / store-hold-load bits (horizontal)
84 lhs_l
.append(dc
.ld_hold_st_o
)
85 shl_l
.append(dc
.st_hold_ld_o
)
86 # accumulate inputs (for Cat'ing later) - TODO: must be a better way
87 issue_l
.append(dc
.issue_i
)
88 go_die_l
.append(dc
.go_die_i
)
90 # load-hit and store-with-data-hit go in vertically (top)
91 m
.d
.comb
+= [dc
.load_hit_i
.eq(self
.load_hit_i
),
92 dc
.stwd_hit_i
.eq(self
.stwd_hit_i
),
93 dc
.load_v_i
.eq(self
.ld_pend_i
),
94 dc
.stor_v_i
.eq(self
.st_pend_i
),
97 # connect cell inputs using Cat(*list_of_stuff)
98 m
.d
.comb
+= [Cat(*issue_l
).eq(self
.issue_i
),
99 Cat(*go_die_l
).eq(self
.go_die_i
),
101 # connect the load-hold-store / store-hold-load OR-accumulated outputs
102 m
.d
.comb
+= self
.ld_hold_st_o
.eq(Cat(*lhs_l
))
103 m
.d
.comb
+= self
.st_hold_ld_o
.eq(Cat(*shl_l
))
105 # the load/store input also needs to be connected to "top" (vertically)
106 for fu
in range(self
.n_ldst
):
109 for fux
in range(self
.n_ldst
):
111 load_h_l
.append(dc
.load_h_i
)
112 stor_h_l
.append(dc
.stor_h_i
)
113 m
.d
.comb
+= [Cat(*load_h_l
).eq(self
.ld_pend_i
),
114 Cat(*stor_h_l
).eq(self
.st_pend_i
),
124 yield self
.load_hit_i
125 yield self
.stwd_hit_i
126 yield self
.ld_hold_st_o
127 yield self
.st_hold_ld_o
132 def d_matrix_sim(dut
):
135 yield dut
.dest_i
.eq(1)
136 yield dut
.issue_i
.eq(1)
138 yield dut
.issue_i
.eq(0)
140 yield dut
.src1_i
.eq(1)
141 yield dut
.issue_i
.eq(1)
143 yield dut
.issue_i
.eq(0)
145 yield dut
.go_rd_i
.eq(1)
147 yield dut
.go_rd_i
.eq(0)
149 yield dut
.go_wr_i
.eq(1)
151 yield dut
.go_wr_i
.eq(0)
155 dut
= LDSTDepMatrix(n_ldst
=4)
156 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
157 with
open("test_ld_st_matrix.il", "w") as f
:
160 run_simulation(dut
, d_matrix_sim(dut
), vcd_name
='test_ld_st_matrix.vcd')
162 if __name__
== '__main__':