reduce ANDing chain (using NOR) in group picker
[soc.git] / src / scoreboard / group_picker.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 PriorityPicker(Elaboratable):
7 """ implements a priority-picker. input: N bits, output: N bits
8 """
9 def __init__(self, wid):
10 self.wid = wid
11 # inputs
12 self.i = Signal(wid, reset_less=True)
13 self.o = Signal(wid, reset_less=True)
14
15 def elaborate(self, platform):
16 m = Module()
17
18 res = []
19 ni = Signal(self.wid, reset_less = True)
20 m.d.comb += ni.eq(~self.i)
21 for i in range(0, self.wid):
22 t = Signal(reset_less = True)
23 res.append(t)
24 if i == 0:
25 m.d.comb += t.eq(self.i[i])
26 else:
27 m.d.comb += t.eq(~Cat(ni[i], *self.i[:i]).bool())
28
29 # we like Cat(*xxx). turn lists into concatenated bits
30 m.d.comb += self.o.eq(Cat(*res))
31
32 return m
33
34 def __iter__(self):
35 yield self.i
36 yield self.o
37
38 def ports(self):
39 return list(self)
40
41
42 class GroupPicker(Elaboratable):
43 """ implements 10.5 mitch alsup group picker, p27
44 """
45 def __init__(self, wid):
46 self.gp_wid = wid
47 # inputs
48 self.readable_i = Signal(wid, reset_less=True) # readable in (top)
49 self.writable_i = Signal(wid, reset_less=True) # writable in (top)
50 self.req_rel_i = Signal(wid, reset_less=True) # release request in (top)
51
52 # outputs
53 self.go_rd_o = Signal(wid, reset_less=True) # go read (bottom)
54 self.go_wr_o = Signal(wid, reset_less=True) # go write (bottom)
55
56 def elaborate(self, platform):
57 m = Module()
58
59 m.submodules.rpick = rpick = PriorityPicker(self.gp_wid)
60 m.submodules.wpick = wpick = PriorityPicker(self.gp_wid)
61
62 # combine release (output ready signal) with writeable
63 m.d.comb += wpick.i.eq(self.writable_i & self.req_rel_i)
64 m.d.comb += self.go_wr_o.eq(wpick.o)
65
66 m.d.comb += rpick.i.eq(self.readable_i)
67 m.d.comb += self.go_rd_o.eq(rpick.o)
68
69 return m
70
71 def __iter__(self):
72 yield self.readable_i
73 yield self.writable_i
74 yield self.req_rel_i
75 yield self.go_rd_o
76 yield self.go_wr_o
77
78 def ports(self):
79 return list(self)
80
81
82 def grp_pick_sim(dut):
83 yield dut.dest_i.eq(1)
84 yield dut.issue_i.eq(1)
85 yield
86 yield dut.issue_i.eq(0)
87 yield
88 yield dut.src1_i.eq(1)
89 yield dut.issue_i.eq(1)
90 yield
91 yield
92 yield
93 yield dut.issue_i.eq(0)
94 yield
95 yield dut.go_rd_i.eq(1)
96 yield
97 yield dut.go_rd_i.eq(0)
98 yield
99 yield dut.go_wr_i.eq(1)
100 yield
101 yield dut.go_wr_i.eq(0)
102 yield
103
104 def test_grp_pick():
105 dut = GroupPicker(4)
106 vl = rtlil.convert(dut, ports=dut.ports())
107 with open("test_grp_pick.il", "w") as f:
108 f.write(vl)
109
110 run_simulation(dut, grp_pick_sim(dut), vcd_name='test_grp_pick.vcd')
111
112 if __name__ == '__main__':
113 test_grp_pick()