update license and attribution in fu_reg_matrix.py
[soc.git] / src / soc / scoreboard / fu_reg_matrix.py
1 # (DO NOT REMOVE THESE NOTICES)
2 # SPDX-License-Identifier: LGPLv3+
3 # Copyright (C) 2019, 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 # Part of the Libre-SOC Project.
5 # Sponsored by NLnet EU Grant No: 825310 and 825322
6 # Sponsored by NGI POINTER EU Grant No: 871528
7
8 """Mitch Alsup 6600 Dependency Matrices: Function Units to Registers (FU-REGs)
9
10 6600 Dependency Table Matrix inputs / outputs
11 ---------------------------------------------
12
13 d s1 s2 i d s1 s2 i d s1 s2 i d s1 s2 i
14 | | | | | | | | | | | | | | | |
15 v v v v v v v v v v v v v v v v
16 go_rd/go_wr -> dm-r0-fu0 dm-r1-fu0 dm-r2-fu0 dm-r3-fu0 -> wr/rd-pend
17 go_rd/go_wr -> dm-r0-fu1 dm-r1-fu1 dm-r2-fu1 dm-r3-fu1 -> wr/rd-pend
18 go_rd/go_wr -> dm-r0-fu2 dm-r1-fu2 dm-r2-fu2 dm-r3-fu2 -> wr/rd-pend
19 | | | | | | | | | | | |
20 v v v v v v v v v v v v
21 d s1 s2 d s1 s2 d s1 s2 d s1 s2
22 reg sel reg sel reg sel reg sel
23
24 """
25
26 from nmigen.compat.sim import run_simulation
27 from nmigen.cli import verilog, rtlil
28 from nmigen import Module, Signal, Elaboratable, Cat, Repl
29
30 from soc.scoreboard.dependence_cell import DependencyRow
31 from soc.scoreboard.fu_wr_pending import FU_RW_Pend
32 from soc.scoreboard.reg_select import Reg_Rsv
33 from soc.scoreboard.global_pending import GlobalPending
34
35
36 class FURegDepMatrix(Elaboratable):
37 """ implements 11.4.7 mitch alsup FU-to-Reg Dependency Matrix, p26
38 """
39 def __init__(self, n_fu_row, n_reg_col, n_src, cancel=None):
40 self.n_src = n_src
41 self.n_fu_row = nf = n_fu_row # Y (FUs) ^v
42 self.n_reg_col = n_reg = n_reg_col # X (Regs) <>
43
44 # arrays
45 src = []
46 rsel = []
47 for i in range(n_src):
48 j = i + 1 # name numbering to match src1/src2
49 src.append(Signal(n_reg, name="src%d" % j, reset_less=True))
50 rsel.append(Signal(n_reg, name="src%d_rsel_o" % j, reset_less=True))
51 pend = []
52 for i in range(nf):
53 j = i + 1 # name numbering to match src1/src2
54 pend.append(Signal(nf, name="rd_src%d_pend_o" % j, reset_less=True))
55
56 self.dest_i = Signal(n_reg_col, reset_less=True) # Dest in (top)
57 self.src_i = tuple(src) # oper in (top)
58
59 # cancellation array (from Address Matching), ties in with go_die_i
60 self.cancel = cancel
61
62 # Register "Global" vectors for determining RaW and WaR hazards
63 self.wr_pend_i = Signal(n_reg_col, reset_less=True) # wr pending (top)
64 self.rd_pend_i = Signal(n_reg_col, reset_less=True) # rd pending (top)
65 self.v_wr_rsel_o = Signal(n_reg_col, reset_less=True) # wr pending (bot)
66 self.v_rd_rsel_o = Signal(n_reg_col, reset_less=True) # rd pending (bot)
67
68 self.issue_i = Signal(n_fu_row, reset_less=True) # Issue in (top)
69 self.go_wr_i = Signal(n_fu_row, reset_less=True) # Go Write in (left)
70 self.go_rd_i = Signal(n_fu_row, reset_less=True) # Go Read in (left)
71 self.go_die_i = Signal(n_fu_row, reset_less=True) # Go Die in (left)
72
73 # for Register File Select Lines (horizontal), per-reg
74 self.dest_rsel_o = Signal(n_reg_col, reset_less=True) # dest reg (bot)
75 self.src_rsel_o = tuple(rsel) # src reg (bot)
76
77 # for Function Unit "forward progress" (vertical), per-FU
78 self.wr_pend_o = Signal(n_fu_row, reset_less=True) # wr pending (right)
79 self.rd_pend_o = Signal(n_fu_row, reset_less=True) # rd pending (right)
80 self.rd_src_pend_o = tuple(pend) # src1 pending
81
82 def elaborate(self, platform):
83 m = Module()
84 return self._elaborate(m, platform)
85
86 def _elaborate(self, m, platform):
87
88 # ---
89 # matrix of dependency cells
90 # ---
91 cancel_mode = self.cancel is not None
92 dm = tuple(DependencyRow(self.n_reg_col, self.n_src, cancel_mode) \
93 for r in range(self.n_fu_row))
94 for fu in range(self.n_fu_row):
95 setattr(m.submodules, "dr_fu%d" % fu, dm[fu])
96
97 # ---
98 # array of Function Unit Pending vectors
99 # ---
100 fupend = tuple(FU_RW_Pend(self.n_reg_col, self.n_src) \
101 for f in range(self.n_fu_row))
102 for fu in range(self.n_fu_row):
103 setattr(m.submodules, "fu_fu%d" % (fu), fupend[fu])
104
105 # ---
106 # array of Register Reservation vectors
107 # ---
108 regrsv = tuple(Reg_Rsv(self.n_fu_row, self.n_src) \
109 for r in range(self.n_reg_col))
110 for rn in range(self.n_reg_col):
111 setattr(m.submodules, "rr_r%d" % (rn), regrsv[rn])
112
113 # ---
114 # connect Function Unit vector
115 # ---
116 wr_pend = []
117 rd_pend = []
118 for fu in range(self.n_fu_row):
119 dc = dm[fu]
120 fup = fupend[fu]
121 dest_fwd_o = []
122 for rn in range(self.n_reg_col):
123 # accumulate cell fwd outputs for dest/src1/src2
124 dest_fwd_o.append(dc.dest_fwd_o[rn])
125 # connect cell fwd outputs to FU Vector in [Cat is gooood]
126 m.d.comb += [fup.dest_fwd_i.eq(Cat(*dest_fwd_o)),
127 ]
128 # accumulate FU Vector outputs
129 wr_pend.append(fup.reg_wr_pend_o)
130 rd_pend.append(fup.reg_rd_pend_o)
131
132 # ... and output them from this module (vertical, width=FUs)
133 m.d.comb += self.wr_pend_o.eq(Cat(*wr_pend))
134 m.d.comb += self.rd_pend_o.eq(Cat(*rd_pend))
135
136 # same for src
137 for i in range(self.n_src):
138 rd_src_pend = []
139 for fu in range(self.n_fu_row):
140 dc = dm[fu]
141 fup = fupend[fu]
142 src_fwd_o = []
143 for rn in range(self.n_reg_col):
144 # accumulate cell fwd outputs for dest/src1/src2
145 src_fwd_o.append(dc.src_fwd_o[i][rn])
146 # connect cell fwd outputs to FU Vector in [Cat is gooood]
147 m.d.comb += fup.src_fwd_i[i].eq(Cat(*src_fwd_o))
148 # accumulate FU Vector outputs
149 rd_src_pend.append(fup.reg_rd_src_pend_o[i])
150 # ... and output them from this module (vertical, width=FUs)
151 m.d.comb += self.rd_src_pend_o[i].eq(Cat(*rd_src_pend))
152
153 # ---
154 # connect Reg Selection vector
155 # ---
156 dest_rsel = []
157 for rn in range(self.n_reg_col):
158 rsv = regrsv[rn]
159 dest_rsel_o = []
160 for fu in range(self.n_fu_row):
161 dc = dm[fu]
162 # accumulate cell reg-select outputs dest/src1/src2
163 dest_rsel_o.append(dc.dest_rsel_o[rn])
164 # connect cell reg-select outputs to Reg Vector In
165 m.d.comb += rsv.dest_rsel_i.eq(Cat(*dest_rsel_o)),
166
167 # accumulate Reg-Sel Vector outputs
168 dest_rsel.append(rsv.dest_rsel_o)
169
170 # ... and output them from this module (horizontal, width=REGs)
171 m.d.comb += self.dest_rsel_o.eq(Cat(*dest_rsel))
172
173 # same for src
174 for i in range(self.n_src):
175 src_rsel = []
176 for rn in range(self.n_reg_col):
177 rsv = regrsv[rn]
178 src_rsel_o = []
179 for fu in range(self.n_fu_row):
180 dc = dm[fu]
181 # accumulate cell reg-select outputs dest/src1/src2
182 src_rsel_o.append(dc.src_rsel_o[i][rn])
183 # connect cell reg-select outputs to Reg Vector In
184 m.d.comb += rsv.src_rsel_i[i].eq(Cat(*src_rsel_o)),
185 # accumulate Reg-Sel Vector outputs
186 src_rsel.append(rsv.src_rsel_o[i])
187
188 # ... and output them from this module (horizontal, width=REGs)
189 m.d.comb += self.src_rsel_o[i].eq(Cat(*src_rsel))
190
191 # ---
192 # connect Dependency Matrix dest/src1/src2/issue to module d/s/s/i
193 # ---
194 for fu in range(self.n_fu_row):
195 dc = dm[fu]
196 # wire up inputs from module to row cell inputs (Cat is gooood)
197 m.d.comb += [dc.dest_i.eq(self.dest_i),
198 dc.rd_pend_i.eq(self.rd_pend_i),
199 dc.wr_pend_i.eq(self.wr_pend_i),
200 ]
201 # same for src
202 for i in range(self.n_src):
203 for fu in range(self.n_fu_row):
204 dc = dm[fu]
205 # wire up inputs from module to row cell inputs (Cat is gooood)
206 m.d.comb += dc.src_i[i].eq(self.src_i[i])
207
208 # accumulate rsel bits into read/write pending vectors.
209 rd_pend_v = []
210 wr_pend_v = []
211 for fu in range(self.n_fu_row):
212 dc = dm[fu]
213 rd_pend_v.append(dc.v_rd_rsel_o)
214 wr_pend_v.append(dc.v_wr_rsel_o)
215 rd_v = GlobalPending(self.n_reg_col, rd_pend_v)
216 wr_v = GlobalPending(self.n_reg_col, wr_pend_v)
217 m.submodules.rd_v = rd_v
218 m.submodules.wr_v = wr_v
219
220 m.d.comb += self.v_rd_rsel_o.eq(rd_v.g_pend_o)
221 m.d.comb += self.v_wr_rsel_o.eq(wr_v.g_pend_o)
222
223 # ---
224 # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr
225 # ---
226 go_rd_i = []
227 go_wr_i = []
228 issue_i = []
229 for fu in range(self.n_fu_row):
230 dc = dm[fu]
231 # accumulate cell fwd outputs for dest/src1/src2
232 go_rd_i.append(dc.go_rd_i)
233 go_wr_i.append(dc.go_wr_i)
234 issue_i.append(dc.issue_i)
235 # wire up inputs from module to row cell inputs (Cat is gooood)
236 m.d.comb += [Cat(*go_rd_i).eq(self.go_rd_i),
237 Cat(*go_wr_i).eq(self.go_wr_i),
238 Cat(*issue_i).eq(self.issue_i),
239 ]
240
241 # ---
242 # connect Dep go_die_i
243 # ---
244 if cancel_mode:
245 for fu in range(self.n_fu_row):
246 dc = dm[fu]
247 go_die = Repl(self.go_die_i[fu], self.n_fu_row)
248 go_die = go_die | self.cancel[fu]
249 m.d.comb += dc.go_die_i.eq(go_die)
250 else:
251 go_die_i = []
252 for fu in range(self.n_fu_row):
253 dc = dm[fu]
254 # accumulate cell fwd outputs for dest/src1/src2
255 go_die_i.append(dc.go_die_i)
256 # wire up inputs from module to row cell inputs (Cat is gooood)
257 m.d.comb += Cat(*go_die_i).eq(self.go_die_i)
258 return m
259
260 def __iter__(self):
261 yield self.dest_i
262 yield from self.src_i
263 yield self.issue_i
264 yield self.go_wr_i
265 yield self.go_rd_i
266 yield self.go_die_i
267 yield self.dest_rsel_o
268 yield from self.src_rsel_o
269 yield self.wr_pend_o
270 yield self.rd_pend_o
271 yield self.wr_pend_i
272 yield self.rd_pend_i
273 yield self.v_wr_rsel_o
274 yield self.v_rd_rsel_o
275 yield from self.rd_src_pend_o
276
277 def ports(self):
278 return list(self)
279
280 def d_matrix_sim(dut):
281 """ XXX TODO
282 """
283 yield dut.dest_i.eq(1)
284 yield dut.issue_i.eq(1)
285 yield
286 yield dut.issue_i.eq(0)
287 yield
288 yield dut.src1_i.eq(1)
289 yield dut.issue_i.eq(1)
290 yield
291 yield dut.issue_i.eq(0)
292 yield
293 yield dut.go_rd_i.eq(1)
294 yield
295 yield dut.go_rd_i.eq(0)
296 yield
297 yield dut.go_wr_i.eq(1)
298 yield
299 yield dut.go_wr_i.eq(0)
300 yield
301
302 def test_d_matrix():
303 dut = FURegDepMatrix(n_fu_row=3, n_reg_col=4, n_src=2)
304 vl = rtlil.convert(dut, ports=dut.ports())
305 with open("test_fu_reg_matrix.il", "w") as f:
306 f.write(vl)
307
308 run_simulation(dut, d_matrix_sim(dut), vcd_name='test_fu_reg_matrix.vcd')
309
310 if __name__ == '__main__':
311 test_d_matrix()