ee998e913772fc7fe0c3b5aa9856e18d58906833
[ieee754fpu.git] / src / scoreboard / ldst_dep_cell.py
1 """ Mitch Alsup 6600-style LD/ST scoreboard Dependency Cell
2
3 Relevant bugreports:
4 * http://bugs.libre-riscv.org/show_bug.cgi?id=81
5
6 """
7
8 from nmigen.compat.sim import run_simulation
9 from nmigen.cli import verilog, rtlil
10 from nmigen import Module, Signal, Elaboratable
11 from nmutil.latch import SRLatch
12
13
14 class LDSTDepCell(Elaboratable):
15 """ implements 11.4.12 mitch alsup load/store dependence cell, p45
16
17 note: the load-hold-store / store-hold-load both come through from
18 the previous cell and accumulate using ORing to create priority
19 picking (in the sparse-matrix, which is where the cells are wired up)
20 """
21 def __init__(self):
22 # inputs
23 self.load_i = Signal(reset_less=True) # load pending in (top)
24 self.stor_i = Signal(reset_less=True) # store pending in (top)
25 self.issue_i = Signal(reset_less=True) # Issue in (top)
26
27 self.load_hit_i = Signal(reset_less=True) # load hit in (right)
28 self.stwd_hit_i = Signal(reset_less=True) # store w/ data hit in (right)
29 self.ld_hold_st_i = Signal(reset_less=True) # load holds st in (right)
30 self.st_hold_ld_i = Signal(reset_less=True) # st holds load in (right)
31
32 # outputs (latched rd/wr pend)
33 self.ld_hold_st_o = Signal(reset_less=True) # load holds st out (left)
34 self.st_hold_ld_o = Signal(reset_less=True) # st holds load out (left)
35
36 def elaborate(self, platform):
37 m = Module()
38 m.submodules.war_l = war_l = SRLatch() # Write After Read Latch
39 m.submodules.raw_l = raw_l = SRLatch() # Read After Write Latch
40
41 # issue & store & load - used for both WAR and RAW Setting
42 i_s_l = Signal(reset_less=True)
43 m.d.comb += i_s_l.eq(self.issue_i & self.stor_i & self.load_i)
44
45 # write after read latch: loads block stores
46 m.d.comb += war_l.s.eq(i_s_l)
47 m.d.comb += war_l.r.eq(self.load_i) # reset on LD
48
49 # read after write latch: stores block loads
50 m.d.comb += raw_l.s.eq(i_s_l)
51 m.d.comb += raw_l.r.eq(self.stor_i) # reset on ST
52
53 # Hold results (read out horizontally, accumulate in OR fashion)
54 lhs = war_l.qn & self.load_hit_i
55 shl = raw_l.qn & self.stwd_hit_i
56 m.d.comb += self.ld_hold_st_o.eq(self.ld_hold_st_i | lhs)
57 m.d.comb += self.st_hold_ld_o.eq(self.st_hold_ld_i | shl)
58
59 return m
60
61 def __iter__(self):
62 yield self.load_i
63 yield self.stor_i
64 yield self.issue_i
65 yield self.load_hit_i
66 yield self.stwd_hit_i
67 yield self.ld_hold_st_i
68 yield self.st_hold_ld_i
69 yield self.ld_hold_st_o
70 yield self.st_hold_ld_o
71
72 def ports(self):
73 return list(self)
74
75
76 def dcell_sim(dut):
77 yield dut.dest_i.eq(1)
78 yield dut.issue_i.eq(1)
79 yield
80 yield dut.issue_i.eq(0)
81 yield
82 yield dut.src1_i.eq(1)
83 yield dut.issue_i.eq(1)
84 yield
85 yield dut.issue_i.eq(0)
86 yield
87 yield dut.go_read_i.eq(1)
88 yield
89 yield dut.go_read_i.eq(0)
90 yield
91 yield dut.go_write_i.eq(1)
92 yield
93 yield dut.go_write_i.eq(0)
94 yield
95
96 def test_dcell():
97 dut = LDSTDepCell()
98 vl = rtlil.convert(dut, ports=dut.ports())
99 with open("test_ldst_dcell.il", "w") as f:
100 f.write(vl)
101
102 run_simulation(dut, dcell_sim(dut), vcd_name='test_ldst_dcell.vcd')
103
104 if __name__ == '__main__':
105 test_dcell()