experiment switching over fwd and rsel in dependency cell
[soc.git] / src / scoreboard / dependence_cell.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
4 from nmutil.latch import SRLatch
5
6
7 class DepCell(Elaboratable):
8 """ implements 11.4.7 mitch alsup dependence cell, p27
9 adjusted to be clock-sync'd on rising edge only.
10 mitch design (as does 6600) requires alternating rising/falling clock
11 """
12 def __init__(self):
13 # inputs
14 self.reg_i = Signal(reset_less=True) # reg bit in (top)
15 self.issue_i = Signal(reset_less=True) # Issue in (top)
16 self.go_i = Signal(reset_less=True) # Go read/write in (left)
17
18 # for Register File Select Lines (vertical)
19 self.rsel_o = Signal(reset_less=True) # reg sel (bottom)
20 # for Function Unit "forward progress" (horizontal)
21 self.fwd_o = Signal(reset_less=True) # FU forard progress (right)
22
23 def elaborate(self, platform):
24 m = Module()
25 m.submodules.l = l = SRLatch(sync=False) # async latch
26
27 # reset on go HI, set on dest and issue
28 m.d.comb += dest_l.s.eq(self.issue_i & self.reg_i)
29 m.d.comb += dest_l.r.eq(self.go_i)
30
31 # FU "Forward Progress" (read out horizontally)
32 m.d.sync += self.fwdl_o.eq(l.q & self.reg_i)
33
34 # Register File Select (read out vertically)
35 m.d.comb += self.rselo.eq(l.q & self.go_i)
36
37 return m
38
39 def __iter__(self):
40 yield self.regt_i
41 yield self.issue_i
42 yield self.go_i
43 yield self.rsel_o
44 yield self.fwd_o
45
46 def ports(self):
47 return list(self)
48
49
50 class DependenceCell(Elaboratable):
51 """ implements 11.4.7 mitch alsup dependence cell, p27
52 """
53 def __init__(self):
54 # inputs
55 self.dest_i = Signal(reset_less=True) # Dest in (top)
56 self.src1_i = Signal(reset_less=True) # oper1 in (top)
57 self.src2_i = Signal(reset_less=True) # oper2 in (top)
58 self.issue_i = Signal(reset_less=True) # Issue in (top)
59
60 self.go_wr_i = Signal(reset_less=True) # Go Write in (left)
61 self.go_rd_i = Signal(reset_less=True) # Go Read in (left)
62
63 # for Register File Select Lines (vertical)
64 self.dest_rsel_o = Signal(reset_less=True) # dest reg sel (bottom)
65 self.src1_rsel_o = Signal(reset_less=True) # src1 reg sel (bottom)
66 self.src2_rsel_o = Signal(reset_less=True) # src2 reg sel (bottom)
67
68 # for Function Unit "forward progress" (horizontal)
69 self.dest_fwd_o = Signal(reset_less=True) # dest FU fw (right)
70 self.src1_fwd_o = Signal(reset_less=True) # src1 FU fw (right)
71 self.src2_fwd_o = Signal(reset_less=True) # src2 FU fw (right)
72
73 def elaborate(self, platform):
74 m = Module()
75 m.submodules.dest_l = dest_l = SRLatch(sync=False) # clock-sync'd
76 m.submodules.src1_l = src1_l = SRLatch(sync=False) # clock-sync'd
77 m.submodules.src2_l = src2_l = SRLatch(sync=False) # clock-sync'd
78
79 # destination latch: reset on go_wr HI, set on dest and issue
80 m.d.comb += dest_l.s.eq(self.issue_i & self.dest_i)
81 m.d.comb += dest_l.r.eq(self.go_wr_i)
82
83 # src1 latch: reset on go_rd HI, set on src1_i and issue
84 m.d.comb += src1_l.s.eq(self.issue_i & self.src1_i)
85 m.d.comb += src1_l.r.eq(self.go_rd_i)
86
87 # src2 latch: reset on go_rd HI, set on op2_i and issue
88 m.d.comb += src2_l.s.eq(self.issue_i & self.src2_i)
89 m.d.comb += src2_l.r.eq(self.go_rd_i)
90
91 # FU "Forward Progress" (read out horizontally)
92 m.d.comb += self.dest_fwd_o.eq(dest_l.q & self.dest_i)
93 m.d.comb += self.src1_fwd_o.eq(src1_l.q & self.src1_i)
94 m.d.comb += self.src2_fwd_o.eq(src2_l.q & self.src2_i)
95
96 # Register File Select (read out vertically)
97 m.d.sync += self.dest_rsel_o.eq(dest_l.q & ~self.go_wr_i)
98 m.d.sync += self.src1_rsel_o.eq(src1_l.q & ~self.go_rd_i)
99 m.d.sync += self.src2_rsel_o.eq(src2_l.q & ~self.go_rd_i)
100
101 return m
102
103 def __iter__(self):
104 yield self.dest_i
105 yield self.src1_i
106 yield self.src2_i
107 yield self.issue_i
108 yield self.go_wr_i
109 yield self.go_rd_i
110 yield self.dest_rsel_o
111 yield self.src1_rsel_o
112 yield self.src2_rsel_o
113 yield self.dest_fwd_o
114 yield self.src1_fwd_o
115 yield self.src2_fwd_o
116
117 def ports(self):
118 return list(self)
119
120
121 class DependencyRow(Elaboratable):
122 def __init__(self, n_reg_col):
123 self.n_reg_col = n_reg_col
124
125 # ----
126 # fields all match DependencyCell precisely
127
128 self.dest_i = Signal(n_reg_col, reset_less=True)
129 self.src1_i = Signal(n_reg_col, reset_less=True)
130 self.src2_i = Signal(n_reg_col, reset_less=True)
131
132 self.issue_i = Signal(reset_less=True)
133 self.go_wr_i = Signal(reset_less=True)
134 self.go_rd_i = Signal(reset_less=True)
135
136 self.dest_rsel_o = Signal(n_reg_col, reset_less=True)
137 self.src1_rsel_o = Signal(n_reg_col, reset_less=True)
138 self.src2_rsel_o = Signal(n_reg_col, reset_less=True)
139
140 self.dest_fwd_o = Signal(n_reg_col, reset_less=True)
141 self.src1_fwd_o = Signal(n_reg_col, reset_less=True)
142 self.src2_fwd_o = Signal(n_reg_col, reset_less=True)
143
144 def elaborate(self, platform):
145 m = Module()
146 rcell = Array(DependenceCell() for f in range(self.n_reg_col))
147 for rn in range(self.n_reg_col):
148 setattr(m.submodules, "dm_r%d" % rn, rcell[rn])
149
150 # ---
151 # connect Dep dest/src to module dest/src
152 # ---
153 dest_i = []
154 src1_i = []
155 src2_i = []
156 for rn in range(self.n_reg_col):
157 dc = rcell[rn]
158 # accumulate cell inputs dest/src1/src2
159 dest_i.append(dc.dest_i)
160 src1_i.append(dc.src1_i)
161 src2_i.append(dc.src2_i)
162 # wire up inputs from module to row cell inputs (Cat is gooood)
163 m.d.comb += [Cat(*dest_i).eq(self.dest_i),
164 Cat(*src1_i).eq(self.src1_i),
165 Cat(*src2_i).eq(self.src2_i),
166 ]
167
168 # ---
169 # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr
170 # ---
171 for rn in range(self.n_reg_col):
172 dc = rcell[rn]
173 m.d.comb += [dc.go_rd_i.eq(self.go_rd_i),
174 dc.go_wr_i.eq(self.go_wr_i),
175 dc.issue_i.eq(self.issue_i),
176 ]
177
178 # ---
179 # connect Function Unit vector
180 # ---
181 dest_fwd_o = []
182 src1_fwd_o = []
183 src2_fwd_o = []
184 for rn in range(self.n_reg_col):
185 dc = rcell[rn]
186 # accumulate cell fwd outputs for dest/src1/src2
187 dest_fwd_o.append(dc.dest_fwd_o)
188 src1_fwd_o.append(dc.src1_fwd_o)
189 src2_fwd_o.append(dc.src2_fwd_o)
190 # connect cell fwd outputs to FU Vector Out [Cat is gooood]
191 m.d.comb += [self.dest_fwd_o.eq(Cat(*dest_fwd_o)),
192 self.src1_fwd_o.eq(Cat(*src1_fwd_o)),
193 self.src2_fwd_o.eq(Cat(*src2_fwd_o))
194 ]
195
196 # ---
197 # connect Reg Selection vector
198 # ---
199 dest_rsel_o = []
200 src1_rsel_o = []
201 src2_rsel_o = []
202 for rn in range(self.n_reg_col):
203 dc = rcell[rn]
204 # accumulate cell reg-select outputs dest/src1/src2
205 dest_rsel_o.append(dc.dest_rsel_o)
206 src1_rsel_o.append(dc.src1_rsel_o)
207 src2_rsel_o.append(dc.src2_rsel_o)
208 # connect cell reg-select outputs to Reg Vector Out
209 m.d.comb += self.dest_rsel_o.eq(Cat(*dest_rsel_o))
210 m.d.comb += self.src1_rsel_o.eq(Cat(*src1_rsel_o))
211 m.d.comb += self.src2_rsel_o.eq(Cat(*src2_rsel_o))
212
213 return m
214
215 def __iter__(self):
216 yield self.dest_i
217 yield self.src1_i
218 yield self.src2_i
219 yield self.issue_i
220 yield self.go_wr_i
221 yield self.go_rd_i
222 yield self.dest_rsel_o
223 yield self.src1_rsel_o
224 yield self.src2_rsel_o
225 yield self.dest_fwd_o
226 yield self.src1_fwd_o
227 yield self.src2_fwd_o
228
229 def ports(self):
230 return list(self)
231
232
233 def dcell_sim(dut):
234 yield dut.dest_i.eq(1)
235 yield dut.issue_i.eq(1)
236 yield
237 yield dut.issue_i.eq(0)
238 yield
239 yield dut.src1_i.eq(1)
240 yield dut.issue_i.eq(1)
241 yield
242 yield
243 yield
244 yield dut.issue_i.eq(0)
245 yield
246 yield dut.go_rd_i.eq(1)
247 yield
248 yield dut.go_rd_i.eq(0)
249 yield
250 yield dut.go_wr_i.eq(1)
251 yield
252 yield dut.go_wr_i.eq(0)
253 yield
254
255 def test_dcell():
256 dut = DependencyRow(4)
257 vl = rtlil.convert(dut, ports=dut.ports())
258 with open("test_drow.il", "w") as f:
259 f.write(vl)
260
261 dut = DependenceCell()
262 vl = rtlil.convert(dut, ports=dut.ports())
263 with open("test_dcell.il", "w") as f:
264 f.write(vl)
265
266 run_simulation(dut, dcell_sim(dut), vcd_name='test_dcell.vcd')
267
268 if __name__ == '__main__':
269 test_dcell()