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
26 from nmigen
.compat
.sim
import run_simulation
27 from nmigen
.cli
import verilog
, rtlil
28 from nmigen
import Module
, Signal
, Elaboratable
, Cat
, Repl
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
36 class FURegDepMatrix(Elaboratable
):
37 """ implements 11.4.7 mitch alsup FU-to-Reg Dependency Matrix, p26
39 def __init__(self
, n_fu_row
, n_reg_col
, n_src
, cancel
=None):
41 self
.n_fu_row
= nf
= n_fu_row
# Y (FUs) ^v
42 self
.n_reg_col
= n_reg
= n_reg_col
# X (Regs) <>
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))
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))
56 self
.dest_i
= Signal(n_reg_col
, reset_less
=True) # Dest in (top)
57 self
.src_i
= tuple(src
) # oper in (top)
59 # cancellation array (from Address Matching), ties in with go_die_i
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)
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)
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)
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
82 def elaborate(self
, platform
):
84 return self
._elaborate
(m
, platform
)
86 def _elaborate(self
, m
, platform
):
89 # matrix of dependency cells
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
])
98 # array of Function Unit Pending vectors
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
])
106 # array of Register Reservation vectors
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
])
114 # connect Function Unit vector
118 for fu
in range(self
.n_fu_row
):
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
)),
128 # accumulate FU Vector outputs
129 wr_pend
.append(fup
.reg_wr_pend_o
)
130 rd_pend
.append(fup
.reg_rd_pend_o
)
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
))
137 for i
in range(self
.n_src
):
139 for fu
in range(self
.n_fu_row
):
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
))
154 # connect Reg Selection vector
157 for rn
in range(self
.n_reg_col
):
160 for fu
in range(self
.n_fu_row
):
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
)),
167 # accumulate Reg-Sel Vector outputs
168 dest_rsel
.append(rsv
.dest_rsel_o
)
170 # ... and output them from this module (horizontal, width=REGs)
171 m
.d
.comb
+= self
.dest_rsel_o
.eq(Cat(*dest_rsel
))
174 for i
in range(self
.n_src
):
176 for rn
in range(self
.n_reg_col
):
179 for fu
in range(self
.n_fu_row
):
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
])
188 # ... and output them from this module (horizontal, width=REGs)
189 m
.d
.comb
+= self
.src_rsel_o
[i
].eq(Cat(*src_rsel
))
192 # connect Dependency Matrix dest/src1/src2/issue to module d/s/s/i
194 for fu
in range(self
.n_fu_row
):
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
),
202 for i
in range(self
.n_src
):
203 for fu
in range(self
.n_fu_row
):
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
])
208 # accumulate rsel bits into read/write pending vectors.
211 for fu
in range(self
.n_fu_row
):
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
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
)
224 # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr
229 for fu
in range(self
.n_fu_row
):
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
),
242 # connect Dep go_die_i
245 for fu
in range(self
.n_fu_row
):
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
)
252 for fu
in range(self
.n_fu_row
):
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
)
262 yield from self
.src_i
267 yield self
.dest_rsel_o
268 yield from self
.src_rsel_o
273 yield self
.v_wr_rsel_o
274 yield self
.v_rd_rsel_o
275 yield from self
.rd_src_pend_o
280 def d_matrix_sim(dut
):
283 yield dut
.dest_i
.eq(1)
284 yield dut
.issue_i
.eq(1)
286 yield dut
.issue_i
.eq(0)
288 yield dut
.src1_i
.eq(1)
289 yield dut
.issue_i
.eq(1)
291 yield dut
.issue_i
.eq(0)
293 yield dut
.go_rd_i
.eq(1)
295 yield dut
.go_rd_i
.eq(0)
297 yield dut
.go_wr_i
.eq(1)
299 yield dut
.go_wr_i
.eq(0)
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
:
308 run_simulation(dut
, d_matrix_sim(dut
), vcd_name
='test_fu_reg_matrix.vcd')
310 if __name__
== '__main__':