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