start putting LDSTSplitter together
[soc.git] / src / soc / scoreboard / shadow_fn.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Signal, Cat, Repl, Const, Elaboratable
4 from nmutil.latch import SRLatch
5
6
7 class ShadowFn(Elaboratable):
8 """ implements shadowing 11.5.1, p55, just the individual shadow function
9
10 shadowing can be used for branches as well as exceptions (interrupts),
11 load/store hold (exceptions again), and vector-element predication
12 (once the predicate is known, which it may not be at instruction issue)
13
14 Inputs
15 * :shadow_wid: number of shadow/fail/good/go_die sets
16
17 notes:
18 * when shadow_wid = 0, recover and shadown are Consts (i.e. do nothing)
19 """
20 def __init__(self, slen, syncreset=False):
21
22 self.slen = slen
23 self.syncreset = syncreset
24
25 if self.slen:
26 # inputs
27 self.issue_i = Signal(reset_less=True)
28 self.shadow_i = Signal(slen, reset_less=True)
29 self.reset_i = Signal(reset_less=True)
30 self.s_fail_i = Signal(slen, reset_less=True)
31 self.s_good_i = Signal(slen, reset_less=True)
32
33 # outputs
34 self.shadown_o = Signal(reset_less=True)
35 self.go_die_o = Signal(reset_less=True)
36 else:
37 # outputs when no shadowing needed
38 self.shadown_o = Const(1)
39 self.go_die_o = Const(0)
40
41 def elaborate(self, platform):
42 m = Module()
43 if self.slen == 0:
44 return
45
46 m.submodules.sl = sl = SRLatch(sync=False, llen=self.slen)
47
48 r_ext = Repl(self.reset_i, self.slen)
49 reset_r = Signal(self.slen)
50 if self.syncreset:
51 m.d.comb += reset_r.eq(self.s_good_i | self.s_fail_i | r_ext)
52 else:
53 m.d.comb += reset_r.eq(self.s_good_i | self.s_fail_i | r_ext)
54
55 i_ext = Repl(self.issue_i, self.slen)
56 m.d.comb += sl.s.eq(self.shadow_i & i_ext & \
57 ~self.s_good_i & ~reset_r)
58 m.d.comb += sl.r.eq(r_ext | reset_r | self.s_good_i | \
59 (i_ext & ~self.shadow_i))
60 m.d.comb += self.go_die_o.eq((sl.qlq & self.s_fail_i).bool())
61 m.d.comb += self.shadown_o.eq(~sl.qlq.bool())
62
63 return m
64
65 def __iter__(self):
66 yield self.issue_i
67 yield self.reset_i
68 yield self.shadow_i
69 yield self.s_fail_i
70 yield self.s_good_i
71 yield self.shadown_o
72 yield self.go_die_o
73
74 def ports(self):
75 return list(self)
76
77
78 def shadow_fn_unit_sim(dut):
79 yield dut.dest_i.eq(1)
80 yield dut.issue_i.eq(1)
81 yield
82 yield dut.issue_i.eq(0)
83 yield
84 yield dut.src1_i.eq(1)
85 yield dut.issue_i.eq(1)
86 yield
87 yield
88 yield
89 yield dut.issue_i.eq(0)
90 yield
91 yield dut.go_rd_i.eq(1)
92 yield
93 yield dut.go_rd_i.eq(0)
94 yield
95 yield dut.go_wr_i.eq(1)
96 yield
97 yield dut.go_wr_i.eq(0)
98 yield
99
100
101 def test_shadow_fn_unit():
102 dut = ShadowFn(4)
103 vl = rtlil.convert(dut, ports=dut.ports())
104 with open("test_shadow_fn_unit.il", "w") as f:
105 f.write(vl)
106
107 run_simulation(dut, shadow_fn_unit_sim(dut),
108 vcd_name='test_shadow_fn_unit.vcd')
109
110 if __name__ == '__main__':
111 test_shadow_fn_unit()