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
= Array(Signal(shadow_wid
, name
="f_i", reset_less
=True) \
121 for f
in range(n_fus
))
122 self
.s_good_i
= Array(Signal(shadow_wid
, name
="g_i", reset_less
=True) \
123 for f
in range(n_fus
))
126 self
.go_die_o
= Signal(n_fus
, reset_less
=True)
127 self
.shadown_o
= Signal(n_fus
, reset_less
=True)
129 def elaborate(self
, platform
):
132 for i
in range(self
.n_fus
):
133 sh
= Shadow(self
.shadow_wid
)
134 setattr(m
.submodules
, "sh%d" % i
, sh
)
136 # connect shadow/fail/good to all shadows
137 m
.d
.comb
+= sh
.s_fail_i
.eq(self
.s_fail_i
[i
])
138 m
.d
.comb
+= sh
.s_good_i
.eq(self
.s_good_i
[i
])
139 m
.d
.comb
+= sh
.shadow_i
.eq(self
.shadow_i
[i
])
141 # connect all shadow outputs and issue input
146 issue_l
.append(l
.issue_i
)
147 sho_l
.append(l
.shadown_o
)
148 rec_l
.append(l
.go_die_o
)
149 m
.d
.comb
+= Cat(*issue_l
).eq(self
.issue_i
)
150 m
.d
.comb
+= self
.shadown_o
.eq(Cat(*sho_l
))
151 m
.d
.comb
+= self
.go_die_o
.eq(Cat(*rec_l
))
157 yield from self
.shadow_i
158 yield from self
.s_fail_i
159 yield from self
.s_good_i
168 yield dut
.dest_i
.eq(1)
169 yield dut
.issue_i
.eq(1)
171 yield dut
.issue_i
.eq(0)
173 yield dut
.src1_i
.eq(1)
174 yield dut
.issue_i
.eq(1)
178 yield dut
.issue_i
.eq(0)
180 yield dut
.go_rd_i
.eq(1)
182 yield dut
.go_rd_i
.eq(0)
184 yield dut
.go_wr_i
.eq(1)
186 yield dut
.go_wr_i
.eq(0)
190 dut
= ShadowMatrix(4, 2)
191 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
192 with
open("test_shadow.il", "w") as f
:
195 run_simulation(dut
, shadow_sim(dut
), vcd_name
='test_shadow.vcd')
197 if __name__
== '__main__':