radix: reading first page table entry
[soc.git] / src / soc / scoremulti / fu_dep_cell.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Signal, Const, Elaboratable, Array
4 from nmutil.latch import SRLatch
5
6 from functools import reduce
7 from operator import or_
8
9
10 class FUDependenceCell(Elaboratable):
11 """ implements 11.4.7 mitch alsup dependence cell, p27
12 """
13 def __init__(self, dummy, n_fu, n_src, n_dest):
14 self.n_fu = n_fu
15 self.n_src = n_src
16 self.n_dest = n_dest
17 self.dummy = Const(~(1<<dummy), n_fu)
18 # inputs
19 self.rd_pend_i = Signal(n_fu, reset_less=True) # read pend in (left)
20 self.wr_pend_i = Signal(n_fu, reset_less=True) # write pend in (left)
21 self.issue_i = Signal(n_fu, reset_less=True) # Issue in (top)
22
23 # set up go_wr and go_wr array
24 rd = []
25 for i in range(n_src):
26 j = i + 1 # name numbering to match src1/src2
27 rd.append(Signal(n_fu, name="gord%d_i" % j, reset_less=True))
28 wr = []
29 for i in range(n_src):
30 j = i + 1 # name numbering to match src1/src2
31 wr.append(Signal(n_fu, name="gowr%d_i" % j, reset_less=True))
32
33 self.go_wr_i = Array(wr) # Go Write in (left)
34 self.go_rd_i = Array(rd) # Go Read in (left)
35
36 self.go_die_i = Signal(n_fu, reset_less=True) # Go Die in (left)
37
38 # outputs (latched rd/wr wait)
39 self.rd_wait_o = Signal(n_fu, reset_less=True) # read wait out (right)
40 self.wr_wait_o = Signal(n_fu, reset_less=True) # write wait out (right)
41
42 def elaborate(self, platform):
43 m = Module()
44
45 # set up rd/wr latches
46 rd_c = []
47 for i in range(self.n_src):
48 rd_l = SRLatch(sync=False, name="rd%d_c" % i, llen=self.n_fu)
49 setattr(m.submodules, "src%d_c" % (i+1), rd_l)
50 rd_c.append(rd_l)
51 wr_c = []
52 for i in range(self.n_dest):
53 wr_l = SRLatch(sync=False, name="wr%d_c" % i, llen=self.n_fu)
54 setattr(m.submodules, "dst%d_c" % (i+1), wr_l)
55 wr_c.append(wr_l)
56
57 # reset on go HI, set on dest and issue
58
59 # connect go_wr / pend
60 for i in range(self.n_dest):
61 m.d.comb += wr_c[i].r.eq(self.go_wr_i[i] | self.go_die_i)
62 m.d.comb += wr_c[i].s.eq(self.issue_i & self.wr_pend_i & self.dummy)
63
64 # connect go_rd / pend_i
65 for i in range(self.n_src):
66 m.d.comb += rd_c[i].r.eq(self.go_rd_i[i] | self.go_die_i)
67 m.d.comb += rd_c[i].s.eq(self.issue_i & self.rd_pend_i & self.dummy)
68
69 # connect output with OR-reduce (DO NOT USE bool()!)
70 # read-wait (and write-wait) only go off when all GORD (and GOWR) fire
71 rd_q = []
72 for i in range(self.n_src):
73 rd_q.append(rd_c[i].qlq)
74 m.d.comb += self.rd_wait_o.eq(reduce(or_, rd_q) & ~self.issue_i)
75 wr_q = []
76 for i in range(self.n_dest):
77 wr_q.append(wr_c[i].qlq)
78 m.d.comb += self.wr_wait_o.eq(reduce(or_, wr_q) & ~self.issue_i)
79
80 return m
81
82 def __iter__(self):
83 yield self.rd_pend_i
84 yield self.wr_pend_i
85 yield self.issue_i
86 yield from self.go_wr_i
87 yield from self.go_rd_i
88 yield self.go_die_i
89 yield self.rd_wait_o
90 yield self.wr_wait_o
91
92 def ports(self):
93 return list(self)
94
95
96 def dcell_sim(dut):
97 yield dut.dest_i.eq(1)
98 yield dut.issue_i.eq(1)
99 yield
100 yield dut.issue_i.eq(0)
101 yield
102 yield dut.src1_i.eq(1)
103 yield dut.issue_i.eq(1)
104 yield
105 yield dut.issue_i.eq(0)
106 yield
107 yield dut.go_rd_i.eq(1)
108 yield
109 yield dut.go_rd_i.eq(0)
110 yield
111 yield dut.go_wr_i.eq(1)
112 yield
113 yield dut.go_wr_i.eq(0)
114 yield
115
116 def test_dcell():
117 dut = FUDependenceCell(dummy=4, n_fu=4, n_src=2, n_dest=2)
118 vl = rtlil.convert(dut, ports=dut.ports())
119 with open("test_fu_dcell.il", "w") as f:
120 f.write(vl)
121
122 run_simulation(dut, dcell_sim(dut), vcd_name='test_fu_dcell.vcd')
123
124 if __name__ == '__main__':
125 test_dcell()