from nmigen import Module, Signal, Cat, Array, Const, Elaboratable, Repl
from nmigen.lib.coding import Decoder
-from nmutil.latch import SRLatch, latchregister
-
from scoreboard.shadow_fn import ShadowFn
self.shadow_wid = shadow_wid
if shadow_wid:
+ # inputs
self.issue_i = Signal(reset_less=True)
self.shadow_i = Signal(shadow_wid, reset_less=True)
self.s_fail_i = Signal(shadow_wid, reset_less=True)
self.s_good_i = Signal(shadow_wid, reset_less=True)
+ # outputs
self.go_die_o = Signal(reset_less=True)
self.shadown_o = Signal(reset_less=True)
else:
+ # outputs when no shadowing needed
self.shadown_o = Const(1)
self.go_die_o = Const(0)
good_l.append(l.s_good_i)
sho_l.append(l.shadow_o)
rec_l.append(l.recover_o)
- m.d.comb += Cat(*i_l).eq(self.issue_i)
+ m.d.comb += Cat(*i_l).eq(Repl(self.issue_i, self.shadow_wid))
m.d.comb += Cat(*fail_l).eq(self.s_fail_i)
m.d.comb += Cat(*good_l).eq(self.s_good_i)
m.d.comb += Cat(*shi_l).eq(self.shadow_i)
return list(self)
+class BranchSpeculationRecord(Elaboratable):
+ """ A record of which function units will be cancelled and which
+ allowed to proceed, on a branch.
+
+ Whilst the input is a pair that says whether the instruction is
+ under the "success" branch shadow (good_i) or the "fail" shadow
+ (fail_i path), when the branch result is known, the "good" path
+ must be cancelled if "fail" occurred, and the "fail" path cancelled
+ if "good" occurred.
+
+ therefore, use "good|~fail" and "fail|~good" respectively as
+ output.
+ """
+
+ def __init__(self, n_fus):
+ self.n_fus = n_fus
+
+ # inputs
+ self.issue_i = Signal(n_fus, reset_less=True)
+ self.good_i = Signal(n_fus, reset_less=True)
+ self.fail_i = Signal(n_fus, reset_less=True)
+ self.branch_i = Signal(reset_less=True)
+
+ # outputs
+ self.good_o = Signal(n_fus, reset_less=True)
+ self.fail_o = Signal(n_fus, reset_less=True)
+
+ def elaborate(self, platform):
+ m = Module()
+
+ good_r = Signal(self.n_fus)
+ fail_r = Signal(self.n_fus)
+
+ # sigh, there's a way to do this without if statements, as pure
+ # ANDing and ORing...
+ for i in range(self.n_fus):
+ with m.If(self.branch_i):
+ with m.If(good_r[i] | fail_r[i]):
+ m.d.comb += self.good_o[i].eq(good_r[i] | ~fail_r[i])
+ m.d.comb += self.fail_o[i].eq(fail_r[i] | ~good_r[i])
+ m.d.sync += good_r[i].eq(0) # might be set if issue set as well
+ m.d.sync += fail_r[i].eq(0) # might be set if issue set as well
+ with m.If(self.issue_i[i]):
+ m.d.sync += good_r[i].eq(self.good_i[i])
+ m.d.sync += fail_r[i].eq(self.fail_i[i])
+
+ return m
+
+ def __iter__(self):
+ yield self.issue_i
+ yield self.good_i
+ yield self.fail_i
+ yield self.branch_i
+ yield self.good_o
+ yield self.fail_o
+
+ def ports(self):
+ return list(self)
+
+
+
class WaWGrid(Elaboratable):
""" An NxM grid-selector which raises a 2D bit selected by N and M
"""
with open("test_shadow.il", "w") as f:
f.write(vl)
+ dut = BranchSpeculationRecord(4)
+ vl = rtlil.convert(dut, ports=dut.ports())
+ with open("test_branchspecrecord.il", "w") as f:
+ f.write(vl)
+
run_simulation(dut, shadow_sim(dut), vcd_name='test_shadow.vcd')
if __name__ == '__main__':