start putting LDSTSplitter together
[soc.git] / src / soc / scoreboard / global_pending.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Signal, Cat, Elaboratable
4
5
6 class GlobalPending(Elaboratable):
7 """ implements Global Pending Vector, basically ORs all incoming Function
8 Unit vectors together. Can be used for creating Read or Write Global
9 Pending. Can be used for INT or FP Global Pending.
10
11 Inputs:
12 * :dep: register file depth
13 * :fu_vecs: a python list of function unit "pending" vectors, each
14 vector being a Signal of width equal to the reg file.
15
16 Notes:
17
18 * the regfile may be Int or FP, this code doesn't care which.
19 obviously do not try to put in a mixture of regfiles into fu_vecs.
20 * this code also doesn't care if it's used for Read Pending or Write
21 pending, it can be used for both: again, obviously, do not try to
22 put in a mixture of read *and* write pending vectors in.
23 * if some Function Units happen not to be uniform (don't operate
24 on a particular register (extremely unusual), they must set a Const
25 zero bit in the vector.
26 """
27 def __init__(self, dep, fu_vecs, sync=False):
28 self.reg_dep = dep
29 # inputs
30 self.fu_vecs = fu_vecs
31 self.sync = sync
32 for v in fu_vecs:
33 assert len(v) == dep, "FU Vector must be same width as regfile"
34
35 self.g_pend_o = Signal(dep, reset_less=True) # global pending vector
36
37 def elaborate(self, platform):
38 m = Module()
39
40 pend_l = []
41 for i in range(self.reg_dep): # per-register
42 vec_bit_l = []
43 for v in self.fu_vecs:
44 vec_bit_l.append(v[i]) # fu bit for same register
45 pend_l.append(Cat(*vec_bit_l).bool()) # OR all bits for same reg
46 if self.sync:
47 m.d.sync += self.g_pend_o.eq(Cat(*pend_l)) # merge all OR'd bits
48 else:
49 m.d.comb += self.g_pend_o.eq(Cat(*pend_l)) # merge all OR'd bits
50
51 return m
52
53 def __iter__(self):
54 yield from self.fu_vecs
55 yield self.g_pend_o
56
57 def ports(self):
58 return list(self)
59
60
61 def g_vec_sim(dut):
62 yield dut.dest_i.eq(1)
63 yield dut.issue_i.eq(1)
64 yield
65 yield dut.issue_i.eq(0)
66 yield
67 yield dut.src1_i.eq(1)
68 yield dut.issue_i.eq(1)
69 yield
70 yield
71 yield
72 yield dut.issue_i.eq(0)
73 yield
74 yield dut.go_rd_i.eq(1)
75 yield
76 yield dut.go_rd_i.eq(0)
77 yield
78 yield dut.go_wr_i.eq(1)
79 yield
80 yield dut.go_wr_i.eq(0)
81 yield
82
83 def test_g_vec():
84 vecs = []
85 for i in range(3):
86 vecs.append(Signal(32, name="fu%d" % i))
87 dut = GlobalPending(32, vecs)
88 vl = rtlil.convert(dut, ports=dut.ports())
89 with open("test_global_pending.il", "w") as f:
90 f.write(vl)
91
92 run_simulation(dut, g_vec_sim(dut), vcd_name='test_global_pending.vcd')
93
94 if __name__ == '__main__':
95 test_g_vec()