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