ba8c70a9f9c770a8e63d480467ad21cc633f5bce
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
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
12 * SET mode: issue_i HI, go_i LO, reg_i HI - register is captured
13 - FWD is DISABLED (~issue_i)
15 * QRY mode: issue_i LO, go_i LO, haz_i HI - FWD is ASSERTED
17 * GO mode : issue_i LO, go_i HI - RSEL is ASSERTED
18 haz_i HI - FWD still can be ASSERTED
20 FWD assertion (hazard protection) therefore still occurs in both
21 Query and Go Modes, for this cycle, due to the cq register
23 GO mode works for one cycle, again due to the cq register capturing
24 the latch output. Without the cq register, the SR Latch (which is
25 asynchronous) would be reset at the exact moment that GO was requested,
26 and the RSEL would be garbage.
30 self
.reg_i
= Signal(reset_less
=True) # reg bit in (top)
31 self
.issue_i
= Signal(reset_less
=True) # Issue in (top)
32 self
.hazard_i
= Signal(reset_less
=True) # to check hazard
33 self
.go_i
= Signal(reset_less
=True) # Go read/write in (left)
35 # for Register File Select Lines (vertical)
36 self
.rsel_o
= Signal(reset_less
=True) # reg sel (bottom)
37 # for Function Unit "forward progress" (horizontal)
38 self
.fwd_o
= Signal(reset_less
=True) # FU forard progress (right)
40 def elaborate(self
, platform
):
42 m
.submodules
.l
= l
= SRLatch(sync
=False) # async latch
44 # record current version of q in a sync'd register
45 cq
= Signal() # resets to 0
46 m
.d
.sync
+= cq
.eq(l
.q
)
48 # reset on go HI, set on dest and issue
49 m
.d
.comb
+= l
.s
.eq(self
.issue_i
& self
.reg_i
)
50 m
.d
.comb
+= l
.r
.eq(self
.go_i
)
52 # Function Unit "Forward Progress".
53 m
.d
.comb
+= self
.fwd_o
.eq((cq | l
.q
) & self
.hazard_i
& ~self
.issue_i
)
55 # Register Select. Activated on go read/write and *current* latch set
56 m
.d
.comb
+= self
.rsel_o
.eq((cq | l
.q
) & self
.go_i
)
72 class DependenceCell(Elaboratable
):
73 """ implements 11.4.7 mitch alsup dependence cell, p27
77 self
.dest_i
= Signal(reset_less
=True) # Dest in (top)
78 self
.src1_i
= Signal(reset_less
=True) # oper1 in (top)
79 self
.src2_i
= Signal(reset_less
=True) # oper2 in (top)
80 self
.issue_i
= Signal(reset_less
=True) # Issue in (top)
82 self
.go_wr_i
= Signal(reset_less
=True) # Go Write in (left)
83 self
.go_rd_i
= Signal(reset_less
=True) # Go Read in (left)
85 # for Register File Select Lines (vertical)
86 self
.dest_rsel_o
= Signal(reset_less
=True) # dest reg sel (bottom)
87 self
.src1_rsel_o
= Signal(reset_less
=True) # src1 reg sel (bottom)
88 self
.src2_rsel_o
= Signal(reset_less
=True) # src2 reg sel (bottom)
90 # for Function Unit "forward progress" (horizontal)
91 self
.dest_fwd_o
= Signal(reset_less
=True) # dest FU fw (right)
92 self
.src1_fwd_o
= Signal(reset_less
=True) # src1 FU fw (right)
93 self
.src2_fwd_o
= Signal(reset_less
=True) # src2 FU fw (right)
95 def elaborate(self
, platform
):
97 m
.submodules
.dest_c
= dest_c
= DepCell()
98 m
.submodules
.src1_c
= src1_c
= DepCell()
99 m
.submodules
.src2_c
= src2_c
= DepCell()
102 for c
in [dest_c
, src1_c
, src2_c
]:
103 m
.d
.comb
+= c
.issue_i
.eq(self
.issue_i
)
105 # connect go_rd / go_wr (dest->wr, src->rd)
106 m
.d
.comb
+= dest_c
.go_i
.eq(self
.go_wr_i
)
107 m
.d
.comb
+= src1_c
.go_i
.eq(self
.go_rd_i
)
108 m
.d
.comb
+= src2_c
.go_i
.eq(self
.go_rd_i
)
110 # connect input reg bit (unary)
111 for c
, reg
in [(dest_c
, self
.dest_i
),
112 (src1_c
, self
.src1_i
),
113 (src2_c
, self
.src2_i
)]:
114 m
.d
.comb
+= c
.reg_i
.eq(reg
)
116 # connect up hazard checks: read-after-write and write-after-read
117 srcactive
= Signal(reset_less
=True)
118 m
.d
.comb
+= srcactive
.eq(self
.src1_i | self
.src2_i
)
119 m
.d
.comb
+= dest_c
.hazard_i
.eq(srcactive
) # read-after-write
120 m
.d
.comb
+= src1_c
.hazard_i
.eq(self
.dest_i
) # write-after-read
121 m
.d
.comb
+= src2_c
.hazard_i
.eq(self
.dest_i
) # write-after-read
123 # connect fwd / reg-sel outputs
124 for c
, fwd
, rsel
in [(dest_c
, self
.dest_fwd_o
, self
.dest_rsel_o
),
125 (src1_c
, self
.src1_fwd_o
, self
.src1_rsel_o
),
126 (src2_c
, self
.src2_fwd_o
, self
.src2_rsel_o
)]:
127 m
.d
.comb
+= fwd
.eq(c
.fwd_o
)
128 m
.d
.comb
+= rsel
.eq(c
.rsel_o
)
139 yield self
.dest_rsel_o
140 yield self
.src1_rsel_o
141 yield self
.src2_rsel_o
142 yield self
.dest_fwd_o
143 yield self
.src1_fwd_o
144 yield self
.src2_fwd_o
150 class DependencyRow(Elaboratable
):
151 def __init__(self
, n_reg_col
):
152 self
.n_reg_col
= n_reg_col
155 # fields all match DependencyCell precisely
157 self
.dest_i
= Signal(n_reg_col
, reset_less
=True)
158 self
.src1_i
= Signal(n_reg_col
, reset_less
=True)
159 self
.src2_i
= Signal(n_reg_col
, reset_less
=True)
161 self
.issue_i
= Signal(reset_less
=True)
162 self
.go_wr_i
= Signal(reset_less
=True)
163 self
.go_rd_i
= Signal(reset_less
=True)
165 self
.dest_rsel_o
= Signal(n_reg_col
, reset_less
=True)
166 self
.src1_rsel_o
= Signal(n_reg_col
, reset_less
=True)
167 self
.src2_rsel_o
= Signal(n_reg_col
, reset_less
=True)
169 self
.dest_fwd_o
= Signal(n_reg_col
, reset_less
=True)
170 self
.src1_fwd_o
= Signal(n_reg_col
, reset_less
=True)
171 self
.src2_fwd_o
= Signal(n_reg_col
, reset_less
=True)
173 def elaborate(self
, platform
):
175 rcell
= Array(DependenceCell() for f
in range(self
.n_reg_col
))
176 for rn
in range(self
.n_reg_col
):
177 setattr(m
.submodules
, "dm_r%d" % rn
, rcell
[rn
])
180 # connect Dep dest/src to module dest/src
185 for rn
in range(self
.n_reg_col
):
187 # accumulate cell inputs dest/src1/src2
188 dest_i
.append(dc
.dest_i
)
189 src1_i
.append(dc
.src1_i
)
190 src2_i
.append(dc
.src2_i
)
191 # wire up inputs from module to row cell inputs (Cat is gooood)
192 m
.d
.comb
+= [Cat(*dest_i
).eq(self
.dest_i
),
193 Cat(*src1_i
).eq(self
.src1_i
),
194 Cat(*src2_i
).eq(self
.src2_i
),
198 # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr
200 for rn
in range(self
.n_reg_col
):
202 m
.d
.comb
+= [dc
.go_rd_i
.eq(self
.go_rd_i
),
203 dc
.go_wr_i
.eq(self
.go_wr_i
),
204 dc
.issue_i
.eq(self
.issue_i
),
208 # connect Function Unit vector
213 for rn
in range(self
.n_reg_col
):
215 # accumulate cell fwd outputs for dest/src1/src2
216 dest_fwd_o
.append(dc
.dest_fwd_o
)
217 src1_fwd_o
.append(dc
.src1_fwd_o
)
218 src2_fwd_o
.append(dc
.src2_fwd_o
)
219 # connect cell fwd outputs to FU Vector Out [Cat is gooood]
220 m
.d
.comb
+= [self
.dest_fwd_o
.eq(Cat(*dest_fwd_o
)),
221 self
.src1_fwd_o
.eq(Cat(*src1_fwd_o
)),
222 self
.src2_fwd_o
.eq(Cat(*src2_fwd_o
))
226 # connect Reg Selection vector
231 for rn
in range(self
.n_reg_col
):
233 # accumulate cell reg-select outputs dest/src1/src2
234 dest_rsel_o
.append(dc
.dest_rsel_o
)
235 src1_rsel_o
.append(dc
.src1_rsel_o
)
236 src2_rsel_o
.append(dc
.src2_rsel_o
)
237 # connect cell reg-select outputs to Reg Vector Out
238 m
.d
.comb
+= self
.dest_rsel_o
.eq(Cat(*dest_rsel_o
))
239 m
.d
.comb
+= self
.src1_rsel_o
.eq(Cat(*src1_rsel_o
))
240 m
.d
.comb
+= self
.src2_rsel_o
.eq(Cat(*src2_rsel_o
))
251 yield self
.dest_rsel_o
252 yield self
.src1_rsel_o
253 yield self
.src2_rsel_o
254 yield self
.dest_fwd_o
255 yield self
.src1_fwd_o
256 yield self
.src2_fwd_o
263 yield dut
.dest_i
.eq(1)
264 yield dut
.issue_i
.eq(1)
266 yield dut
.issue_i
.eq(0)
268 yield dut
.src1_i
.eq(1)
269 yield dut
.issue_i
.eq(1)
273 yield dut
.issue_i
.eq(0)
275 yield dut
.go_rd_i
.eq(1)
277 yield dut
.go_rd_i
.eq(0)
279 yield dut
.go_wr_i
.eq(1)
281 yield dut
.go_wr_i
.eq(0)
285 dut
= DependencyRow(4)
286 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
287 with
open("test_drow.il", "w") as f
:
290 dut
= DependenceCell()
291 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
292 with
open("test_dcell.il", "w") as f
:
295 run_simulation(dut
, dcell_sim(dut
), vcd_name
='test_dcell.vcd')
297 if __name__
== '__main__':