1 from nmigen
.compat
.sim
import run_simulation
2 from nmigen
.cli
import verilog
, rtlil
3 from nmigen
import Module
, Signal
, Cat
, Array
, Const
, Elaboratable
4 from nmigen
.lib
.coding
import Decoder
6 from nmutil
.latch
import SRLatch
, latchregister
8 from scoreboard
.shadow_fn
import ShadowFn
11 class Shadow(Elaboratable
):
12 """ implements shadowing 11.5.1, p55
14 shadowing can be used for branches as well as exceptions (interrupts),
15 load/store hold (exceptions again), and vector-element predication
16 (once the predicate is known, which it may not be at instruction issue)
19 * :shadow_wid: number of shadow/fail/good/go_die sets
22 * when shadow_wid = 0, recover and shadown are Consts (i.e. do nothing)
24 def __init__(self
, shadow_wid
=0):
25 self
.shadow_wid
= shadow_wid
28 self
.issue_i
= Signal(reset_less
=True)
29 self
.shadow_i
= Signal(shadow_wid
, reset_less
=True)
30 self
.s_fail_i
= Signal(shadow_wid
, reset_less
=True)
31 self
.s_good_i
= Signal(shadow_wid
, reset_less
=True)
32 self
.go_die_o
= Signal(reset_less
=True)
33 self
.shadown_o
= Signal(reset_less
=True)
35 self
.shadown_o
= Const(1)
36 self
.go_die_o
= Const(0)
38 def elaborate(self
, platform
):
41 for i
in range(self
.shadow_wid
):
43 setattr(m
.submodules
, "shadow%d" % i
, sh
)
46 # shadow / recover (optional: shadow_wid > 0)
54 # get list of latch signals. really must be a better way to do this
57 shi_l
.append(l
.shadow_i
)
58 fail_l
.append(l
.s_fail_i
)
59 good_l
.append(l
.s_good_i
)
60 sho_l
.append(l
.shadow_o
)
61 rec_l
.append(l
.recover_o
)
62 m
.d
.comb
+= Cat(*i_l
).eq(self
.issue_i
)
63 m
.d
.comb
+= Cat(*fail_l
).eq(self
.s_fail_i
)
64 m
.d
.comb
+= Cat(*good_l
).eq(self
.s_good_i
)
65 m
.d
.comb
+= Cat(*shi_l
).eq(self
.shadow_i
)
66 m
.d
.comb
+= self
.shadown_o
.eq(~
(Cat(*sho_l
).bool()))
67 m
.d
.comb
+= self
.go_die_o
.eq(Cat(*rec_l
).bool())
84 class ShadowMatrix(Elaboratable
):
85 """ Matrix of Shadow Functions. One per FU.
88 * :n_fus: register file width
89 * :shadow_wid: number of shadow/fail/good/go_die sets
93 * Shadow enable/fail/good are all connected to all Shadow Functions
96 * Output is an array of "shadow active" (schroedinger wires: neither
97 alive nor dead) and an array of "go die" signals, one per FU.
99 * the shadown must be connected to the Computation Unit's
100 write release request, preventing it (ANDing) from firing
101 (and thus preventing Writable. this by the way being the
102 whole point of having the Shadow Matrix...)
104 * go_die_o must be connected to *both* the Computation Unit's
105 src-operand and result-operand latch resets, causing both
108 * go_die_o also needs to be wired into the Dependency and Function
109 Unit Matrices by way of over-enabling (ORing) into Go_Read and
110 Go_Write, resetting every cell that is required to "die"
112 def __init__(self
, n_fus
, shadow_wid
=0):
114 self
.shadow_wid
= shadow_wid
117 self
.issue_i
= Signal(n_fus
, reset_less
=True)
118 self
.shadow_i
= Array(Signal(shadow_wid
, name
="sh_i", reset_less
=True) \
119 for f
in range(n_fus
))
120 self
.s_fail_i
= Signal(shadow_wid
, reset_less
=True)
121 self
.s_good_i
= Signal(shadow_wid
, reset_less
=True)
124 self
.go_die_o
= Signal(n_fus
, reset_less
=True)
125 self
.shadown_o
= Signal(n_fus
, reset_less
=True)
127 def elaborate(self
, platform
):
130 for i
in range(self
.n_fus
):
131 sh
= Shadow(self
.shadow_wid
)
132 setattr(m
.submodules
, "sh%d" % i
, sh
)
134 # connect shadow/fail/good to all shadows
135 m
.d
.comb
+= sh
.s_fail_i
.eq(self
.s_fail_i
)
136 m
.d
.comb
+= sh
.s_good_i
.eq(self
.s_good_i
)
137 # this one is the matrix (shadow enables)
138 m
.d
.comb
+= sh
.shadow_i
.eq(self
.shadow_i
[i
])
140 # connect all shadow outputs and issue input
145 issue_l
.append(l
.issue_i
)
146 sho_l
.append(l
.shadown_o
)
147 rec_l
.append(l
.go_die_o
)
148 m
.d
.comb
+= Cat(*issue_l
).eq(self
.issue_i
)
149 m
.d
.comb
+= self
.shadown_o
.eq(Cat(*sho_l
))
150 m
.d
.comb
+= self
.go_die_o
.eq(Cat(*rec_l
))
156 yield from self
.shadow_i
167 yield dut
.dest_i
.eq(1)
168 yield dut
.issue_i
.eq(1)
170 yield dut
.issue_i
.eq(0)
172 yield dut
.src1_i
.eq(1)
173 yield dut
.issue_i
.eq(1)
177 yield dut
.issue_i
.eq(0)
179 yield dut
.go_rd_i
.eq(1)
181 yield dut
.go_rd_i
.eq(0)
183 yield dut
.go_wr_i
.eq(1)
185 yield dut
.go_wr_i
.eq(0)
189 dut
= ShadowMatrix(4, 2)
190 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
191 with
open("test_shadow.il", "w") as f
:
194 run_simulation(dut
, shadow_sim(dut
), vcd_name
='test_shadow.vcd')
196 if __name__
== '__main__':