a2f142b72e5dcd0093bfcd12f157b5024403907f
[soc.git] / src / scoreboard / 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, Elaboratable
4 from nmutil.latch import SRLatch
5
6 class DepCell(Elaboratable):
7 """ FU Dependency Cell
8 """
9 def __init__(self):
10 # inputs
11 self.pend_i = Signal(reset_less=True) # pending bit in (left)
12 self.issue_i = Signal(reset_less=True) # Issue in (top)
13 self.go_i = Signal(reset_less=True) # Go read/write in (left)
14
15 # wait
16 self.wait_o = Signal(reset_less=True) # wait out (right)
17
18 def elaborate(self, platform):
19 m = Module()
20 m.submodules.l = l = SRLatch(sync=False) # async latch
21
22 # record current version of q in a sync'd register
23 cq = Signal() # resets to 0
24 m.d.sync += cq.eq(l.q)
25
26 # reset on go HI, set on dest and issue
27 m.d.comb += l.s.eq(self.issue_i & self.pend_i)
28 m.d.comb += l.r.eq(self.go_i)
29
30 # wait out
31 m.d.comb += self.wait_o.eq((cq | l.q) & ~self.issue_i)
32
33 return m
34
35 def __iter__(self):
36 yield self.pend_i
37 yield self.issue_i
38 yield self.go_i
39 yield self.wait_o
40
41 def ports(self):
42 return list(self)
43
44
45 class FUDependenceCell(Elaboratable):
46 """ implements 11.4.7 mitch alsup dependence cell, p27
47 """
48 def __init__(self):
49 # inputs
50 self.rd_pend_i = Signal(reset_less=True) # read pending in (left)
51 self.wr_pend_i = Signal(reset_less=True) # write pending in (left)
52 self.issue_i = Signal(reset_less=True) # Issue in (top)
53
54 self.go_wr_i = Signal(reset_less=True) # Go Write in (left)
55 self.go_rd_i = Signal(reset_less=True) # Go Read in (left)
56
57 # outputs (latched rd/wr wait)
58 self.rd_wait_o = Signal(reset_less=True) # read waiting out (right)
59 self.wr_wait_o = Signal(reset_less=True) # write waiting out (right)
60
61 def elaborate(self, platform):
62 m = Module()
63 m.submodules.rd_c = rd_c = DepCell()
64 m.submodules.wr_c = wr_c = DepCell()
65
66 # connect issue
67 for c in [rd_c, wr_c]:
68 m.d.comb += c.issue_i.eq(self.issue_i)
69
70 # connect go_rd / go_wr
71 m.d.comb += wr_c.go_i.eq(self.go_wr_i)
72 m.d.comb += rd_c.go_i.eq(self.go_rd_i)
73
74 # connect pend_i
75 m.d.comb += wr_c.go_i.eq(self.wr_pend_i)
76 m.d.comb += rd_c.go_i.eq(self.rd_pend_i)
77
78 # connect output
79 m.d.comb += self.wr_wait_o.eq(wr_c.wait_o)
80 m.d.comb += self.rd_wait_o.eq(rd_c.wait_o)
81
82 return m
83
84 def __iter__(self):
85 yield self.rd_pend_i
86 yield self.wr_pend_i
87 yield self.issue_i
88 yield self.go_wr_i
89 yield self.go_rd_i
90 yield self.rd_wait_o
91 yield self.wr_wait_o
92
93 def ports(self):
94 return list(self)
95
96
97 def dcell_sim(dut):
98 yield dut.dest_i.eq(1)
99 yield dut.issue_i.eq(1)
100 yield
101 yield dut.issue_i.eq(0)
102 yield
103 yield dut.src1_i.eq(1)
104 yield dut.issue_i.eq(1)
105 yield
106 yield dut.issue_i.eq(0)
107 yield
108 yield dut.go_rd_i.eq(1)
109 yield
110 yield dut.go_rd_i.eq(0)
111 yield
112 yield dut.go_wr_i.eq(1)
113 yield
114 yield dut.go_wr_i.eq(0)
115 yield
116
117 def test_dcell():
118 dut = FUDependenceCell()
119 vl = rtlil.convert(dut, ports=dut.ports())
120 with open("test_fu_dcell.il", "w") as f:
121 f.write(vl)
122
123 run_simulation(dut, dcell_sim(dut), vcd_name='test_fu_dcell.vcd')
124
125 if __name__ == '__main__':
126 test_dcell()