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
8 """Mitch Alsup 6600 Dependency Matrices: Function Units to Registers (FU-REGs)
10 6600 Dependency Table Matrix inputs / outputs
11 ---------------------------------------------
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
24 Sub-module allocation:
26 <----------- DependenceRow dr_fu0 -------> FU_RW_Pend fu_fu_0
27 <----------- DependenceRow dr_fu1 -------> FU_RW_Pend fu_fu_1
28 <----------- DependenceRow dr_fu2 -------> FU_RW_Pend fu_fu_2
29 | | | | | | | | | | | |
30 v v v v v v v v v v v v
31 Reg_Rsv Reg_Rsv Reg_Rsv Reg_Rsv
32 rr_r0 rr_r1 rr_r2 rr_r3
34 <---------- GlobalPending rd_v --------->
35 <---------- GlobalPending wr_v --------->
38 from nmigen
.compat
.sim
import run_simulation
39 from nmigen
.cli
import verilog
, rtlil
40 from nmigen
import Module
, Signal
, Elaboratable
, Cat
, Repl
42 from soc
.scoreboard
.dependence_cell
import DependencyRow
43 from soc
.scoreboard
.fu_wr_pending
import FU_RW_Pend
44 from soc
.scoreboard
.reg_select
import Reg_Rsv
45 from soc
.scoreboard
.global_pending
import GlobalPending
48 class FURegDepMatrix(Elaboratable
):
49 """ implements 11.4.7 mitch alsup FU-to-Reg Dependency Matrix, p26
51 def __init__(self
, n_fu_row
, n_reg_col
, n_src
, n_dst
, cancel
=None):
54 self
.n_fu_row
= nf
= n_fu_row
# Y (FUs) ^v
55 self
.n_reg_col
= n_reg
= n_reg_col
# X (Regs) <>
61 for i
in range(n_src
):
62 j
= i
+ 1 # name numbering to match src1/src2
63 src
.append(Signal(n_reg
, name
="src%d" % j
, reset_less
=True))
64 rsel
.append(Signal(n_reg
, name
="src%d_rsel_o" % j
, reset_less
=True))
65 pend
.append(Signal(nf
, name
="rd_src%d_pend_o" % j
, reset_less
=True))
69 for i
in range(n_dst
):
70 j
= i
+ 1 # name numbering to match dst1/dst2
71 dst
.append(Signal(n_reg
, name
="dst%d" % j
, reset_less
=True))
72 dsel
.append(Signal(n_reg
, name
="dst%d_rsel_o" % j
, reset_less
=True))
73 dpnd
.append(Signal(nf
, name
="wr_dst%d_pend_o" % j
, reset_less
=True))
75 self
.dst_i
= tuple(dst
) # Dest in (top)
76 self
.src_i
= tuple(src
) # oper in (top)
77 self
.dest_i
= self
.dst_i
[0] # old API
79 # cancellation array (from Address Matching), ties in with go_die_i
82 # Register "Global" vectors for determining RaW and WaR hazards
83 self
.wr_pend_i
= Signal(n_reg_col
, reset_less
=True) # wr pending (top)
84 self
.rd_pend_i
= Signal(n_reg_col
, reset_less
=True) # rd pending (top)
85 self
.v_wr_rsel_o
= Signal(n_reg_col
, reset_less
=True) # wr pending (bot)
86 self
.v_rd_rsel_o
= Signal(n_reg_col
, reset_less
=True) # rd pending (bot)
88 self
.issue_i
= Signal(n_fu_row
, reset_less
=True) # Issue in (top)
89 self
.go_wr_i
= Signal(n_fu_row
, reset_less
=True) # Go Write in (left)
90 self
.go_rd_i
= Signal(n_fu_row
, reset_less
=True) # Go Read in (left)
91 self
.go_die_i
= Signal(n_fu_row
, reset_less
=True) # Go Die in (left)
93 # for Register File Select Lines (horizontal), per-reg
94 self
.dst_rsel_o
= tuple(dsel
) # dest reg (bot)
95 self
.src_rsel_o
= tuple(rsel
) # src reg (bot)
96 self
.dest_rsel_o
= self
.dst_rsel_o
[0] # old API
98 # for Function Unit "forward progress" (vertical), per-FU
99 self
.wr_pend_o
= Signal(n_fu_row
, reset_less
=True) # wr pending (right)
100 self
.rd_pend_o
= Signal(n_fu_row
, reset_less
=True) # rd pending (right)
101 self
.rd_src_pend_o
= tuple(pend
) # src pending
102 self
.wr_dst_pend_o
= tuple(dpnd
) # dest pending
104 def elaborate(self
, platform
):
106 return self
._elaborate
(m
, platform
)
108 def _elaborate(self
, m
, platform
):
111 # matrix of dependency cells. horizontal object, allocated vertically
113 cancel_mode
= self
.cancel
is not None
114 dm
= tuple(DependencyRow(self
.n_reg_col
, self
.n_src
, self
.n_dst
,
115 cancel_mode
=cancel_mode
) \
116 for r
in range(self
.n_fu_row
))
117 for fu
, dc
in enumerate(dm
):
118 m
.submodules
["dr_fu%d" % fu
] = dc
121 # array of Function Unit Pending vecs. allocated vertically (per FU)
123 fupend
= tuple(FU_RW_Pend(self
.n_reg_col
, self
.n_src
, self
.n_dst
) \
124 for f
in range(self
.n_fu_row
))
125 for fu
, fup
in enumerate(fupend
):
126 m
.submodules
["fu_fu%d" % (fu
)] = fup
129 # array of Register Reservation vecs. allocated horizontally (per reg)
131 regrsv
= tuple(Reg_Rsv(self
.n_fu_row
, self
.n_src
, self
.n_dst
) \
132 for r
in range(self
.n_reg_col
))
133 for rn
in range(self
.n_reg_col
):
134 m
.submodules
["rr_r%d" % (rn
)] = regrsv
[rn
]
137 # connect Function Unit vector
142 # accumulate FU Vector outputs
143 wr_pend
.append(fup
.reg_wr_pend_o
)
144 rd_pend
.append(fup
.reg_rd_pend_o
)
146 # ... and output them from this module (vertical, width=FUs)
147 m
.d
.comb
+= self
.wr_pend_o
.eq(Cat(*wr_pend
))
148 m
.d
.comb
+= self
.rd_pend_o
.eq(Cat(*rd_pend
))
150 # connect dst fwd vectors
151 for i
in range(self
.n_dst
):
153 for dc
, fup
in zip(dm
, fupend
):
155 for rn
in range(self
.n_reg_col
):
156 # accumulate cell fwd outputs for dest
157 dst_fwd_o
.append(dc
.dst_fwd_o
[i
][rn
])
158 # connect cell fwd outputs to FU Vector in [Cat is gooood]
159 m
.d
.comb
+= fup
.dst_fwd_i
[i
].eq(Cat(*dst_fwd_o
))
160 # accumulate FU Vector outputs
161 wr_dst_pend
.append(fup
.reg_wr_dst_pend_o
[i
])
162 # ... and output them from this module (vertical, width=FUs)
163 m
.d
.comb
+= self
.wr_dst_pend_o
[i
].eq(Cat(*wr_dst_pend
))
166 for i
in range(self
.n_src
):
168 for dc
, fup
in zip(dm
, fupend
):
170 for rn
in range(self
.n_reg_col
):
171 # accumulate cell fwd outputs for dest/src1/src2
172 src_fwd_o
.append(dc
.src_fwd_o
[i
][rn
])
173 # connect cell fwd outputs to FU Vector in [Cat is gooood]
174 m
.d
.comb
+= fup
.src_fwd_i
[i
].eq(Cat(*src_fwd_o
))
175 # accumulate FU Vector outputs
176 rd_src_pend
.append(fup
.reg_rd_src_pend_o
[i
])
177 # ... and output them from this module (vertical, width=FUs)
178 m
.d
.comb
+= self
.rd_src_pend_o
[i
].eq(Cat(*rd_src_pend
))
181 # connect Reg Selection vector
183 for i
in range(self
.n_dst
):
185 for rn
, rsv
in enumerate(regrsv
):
187 # accumulate cell reg-select outputs dest1/2/...
189 dst_rsel_o
.append(dc
.dst_rsel_o
[i
][rn
])
190 # connect cell reg-select outputs to Reg Vector In
191 m
.d
.comb
+= rsv
.dst_rsel_i
[i
].eq(Cat(*dst_rsel_o
)),
192 # accumulate Reg-Sel Vector outputs
193 dest_rsel
.append(rsv
.dst_rsel_o
[i
])
194 # ... and output them from this module (horizontal, width=REGs)
195 m
.d
.comb
+= self
.dst_rsel_o
[i
].eq(Cat(*dest_rsel
))
198 for i
in range(self
.n_src
):
200 for rn
, rsv
in enumerate(regrsv
):
202 # accumulate cell reg-select outputs src1/src2
204 src_rsel_o
.append(dc
.src_rsel_o
[i
][rn
])
205 # connect cell reg-select outputs to Reg Vector In
206 m
.d
.comb
+= rsv
.src_rsel_i
[i
].eq(Cat(*src_rsel_o
)),
207 # accumulate Reg-Sel Vector outputs
208 src_rsel
.append(rsv
.src_rsel_o
[i
])
209 # ... and output them from this module (horizontal, width=REGs)
210 m
.d
.comb
+= self
.src_rsel_o
[i
].eq(Cat(*src_rsel
))
213 # connect Dependency Matrix dest/src1/src2/issue to module d/s/s/i
216 # wire up inputs from module to row cell inputs (Cat is gooood)
217 m
.d
.comb
+= [dc
.rd_pend_i
.eq(self
.rd_pend_i
),
218 dc
.wr_pend_i
.eq(self
.wr_pend_i
),
220 # for dest: wire up output from module to row cell outputs
221 for i
in range(self
.n_dst
):
222 m
.d
.comb
+= dc
.dst_i
[i
].eq(self
.dst_i
[i
])
223 # for src: wire up inputs from module to row cell inputs
224 for i
in range(self
.n_src
):
225 m
.d
.comb
+= dc
.src_i
[i
].eq(self
.src_i
[i
])
227 # accumulate rsel bits into read/write pending vectors.
231 rd_pend_v
.append(dc
.v_rd_rsel_o
)
232 wr_pend_v
.append(dc
.v_wr_rsel_o
)
233 rd_v
= GlobalPending(self
.n_reg_col
, rd_pend_v
)
234 wr_v
= GlobalPending(self
.n_reg_col
, wr_pend_v
)
235 m
.submodules
.rd_v
= rd_v
236 m
.submodules
.wr_v
= wr_v
238 m
.d
.comb
+= self
.v_rd_rsel_o
.eq(rd_v
.g_pend_o
)
239 m
.d
.comb
+= self
.v_wr_rsel_o
.eq(wr_v
.g_pend_o
)
242 # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr
248 # accumulate cell fwd outputs for dest/src1/src2
249 go_rd_i
.append(dc
.go_rd_i
)
250 go_wr_i
.append(dc
.go_wr_i
)
251 issue_i
.append(dc
.issue_i
)
252 # wire up inputs from module to row cell inputs (Cat is gooood)
253 m
.d
.comb
+= [Cat(*go_rd_i
).eq(self
.go_rd_i
),
254 Cat(*go_wr_i
).eq(self
.go_wr_i
),
255 Cat(*issue_i
).eq(self
.issue_i
),
259 # connect Dep go_die_i
262 for fu
, dc
in enumerate(dm
):
263 go_die
= Repl(self
.go_die_i
[fu
], self
.n_fu_row
)
264 go_die
= go_die | self
.cancel
[fu
]
265 m
.d
.comb
+= dc
.go_die_i
.eq(go_die
)
269 # accumulate cell fwd outputs for dest/src1/src2
270 go_die_i
.append(dc
.go_die_i
)
271 # wire up inputs from module to row cell inputs (Cat is gooood)
272 m
.d
.comb
+= Cat(*go_die_i
).eq(self
.go_die_i
)
276 if self
.cancel
is not None:
279 yield from self
.src_i
284 yield from self
.dst_rsel_o
285 yield from self
.src_rsel_o
290 yield self
.v_wr_rsel_o
291 yield self
.v_rd_rsel_o
292 yield from self
.rd_src_pend_o
293 yield from self
.wr_dst_pend_o
298 def d_matrix_sim(dut
):
301 yield dut
.dest_i
.eq(1)
302 yield dut
.issue_i
.eq(1)
304 yield dut
.issue_i
.eq(0)
306 yield dut
.src_i
[0].eq(1)
307 yield dut
.issue_i
.eq(1)
309 yield dut
.issue_i
.eq(0)
311 yield dut
.go_rd_i
.eq(1)
313 yield dut
.go_rd_i
.eq(0)
315 yield dut
.go_wr_i
.eq(1)
317 yield dut
.go_wr_i
.eq(0)
322 dut
= FURegDepMatrix(n_fu_row
=3, n_reg_col
=4, n_src
=2, n_dst
=2,
324 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
325 with
open("test_fu_reg_matrix.il", "w") as f
:
328 run_simulation(dut
, d_matrix_sim(dut
), vcd_name
='test_fu_reg_matrix.vcd')
330 if __name__
== '__main__':