add LD/ST Matrix (actually sparse matrix, aka straight 1D array)
[ieee754fpu.git] / src / scoreboard / ldst_matrix.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Signal, Elaboratable, Array, Cat, Const
4
5 from ldst_dep_cell import LDSTDepCell
6
7 """
8
9 6600 LD/ST Dependency Table Matrix inputs / outputs
10 ---------------------------------------------------
11
12 """
13
14 class LDSTDepMatrix(Elaboratable):
15 """ implements 11.4.12 mitch alsup LD/ST Dependency Matrix, p46
16 actually a sparse matrix along the diagonal.
17
18 load-hold-store and store-hold-load accumulate in a priority-picking
19 fashion, ORing together. the OR gate from the dependency cell is
20 here.
21 """
22 def __init__(self, n_ldst):
23 self.n_ldst = n_ldst # X and Y (FUs)
24 self.load_i = Signal(n_ldst, reset_less=True) # load pending in
25 self.stor_i = Signal(n_ldst, reset_less=True) # store pending in
26 self.issue_i = Signal(n_ldst, reset_less=True) # Issue in
27
28 self.load_hit_i = Signal(n_ldst, reset_less=True) # load hit in
29 self.stwd_hit_i = Signal(n_ldst, reset_less=True) # store w/data hit in
30
31 # outputs
32 self.ld_hold_st_o = Signal(n_ldst, reset_less=True) # load holds st out
33 self.st_hold_ld_o = Signal(n_ldst, reset_less=True) # st holds load out
34
35 def elaborate(self, platform):
36 m = Module()
37
38 # ---
39 # matrix of dependency cells
40 # ---
41 dm = Array(LDSTDepCell() for f in range(self.n_ldst))
42 for fu in range(self.n_ldst):
43 setattr(m.submodules, "dm_fu%d" % (fu), dm[fu])
44
45 # ---
46 # connect Function Unit vector
47 # ---
48 lhs = Const(0) # start at const 0
49 shl = Const(0) # (does no harm)
50 lhs_l = []
51 shl_l = []
52 load_l = []
53 stor_l = []
54 issue_l = []
55 lh_l = []
56 sh_l = []
57 for fu in range(self.n_ldst):
58 dc = dm[fu]
59 # OR the load-hold-store / store-hold-load cell outputs in...
60 _lhs = lhs
61 _shl = shl
62 lhs = Signal(reset_less=True)
63 shl = Signal(reset_less=True)
64 m.d.comb += [lhs.eq(_lhs | dc.ld_hold_st_o),
65 shl.eq(_shl | dc.st_hold_ld_o)
66 ]
67 # accumulate load-hold-store / store-hold-load bits
68 lhs_l.append(lhs)
69 shl_l.append(shl)
70 # accumulate inputs (for Cat'ing later) - TODO: must be a better way
71 load_l.append(dc.load_i)
72 stor_l.append(dc.stor_i)
73 issue_l.append(dc.issue_i)
74 lh_l.append(dc.load_hit_i)
75 sh_l.append(dc.stwd_hit_i)
76
77 # connect cell inputs using Cat(*list_of_stuff)
78 m.d.comb += [Cat(*load_l).eq(self.load_i),
79 Cat(*stor_l).eq(self.stor_i),
80 Cat(*issue_l).eq(self.issue_i),
81 Cat(*lh_l).eq(self.load_hit_i),
82 Cat(*sh_l).eq(self.stwd_hit_i),
83 ]
84 # set the load-hold-store / store-hold-load OR-accumulated outputs
85 m.d.comb += self.ld_hold_st_o.eq(Cat(*lhs_l))
86 m.d.comb += self.st_hold_ld_o.eq(Cat(*shl_l))
87
88 return m
89
90 def __iter__(self):
91 yield self.load_i
92 yield self.stor_i
93 yield self.issue_i
94 yield self.load_hit_i
95 yield self.stwd_hit_i
96 yield self.ld_hold_st_o
97 yield self.st_hold_ld_o
98
99 def ports(self):
100 return list(self)
101
102 def d_matrix_sim(dut):
103 """ XXX TODO
104 """
105 yield dut.dest_i.eq(1)
106 yield dut.issue_i.eq(1)
107 yield
108 yield dut.issue_i.eq(0)
109 yield
110 yield dut.src1_i.eq(1)
111 yield dut.issue_i.eq(1)
112 yield
113 yield dut.issue_i.eq(0)
114 yield
115 yield dut.go_read_i.eq(1)
116 yield
117 yield dut.go_read_i.eq(0)
118 yield
119 yield dut.go_write_i.eq(1)
120 yield
121 yield dut.go_write_i.eq(0)
122 yield
123
124 def test_d_matrix():
125 dut = LDSTDepMatrix(n_ldst=4)
126 vl = rtlil.convert(dut, ports=dut.ports())
127 with open("test_ld_st_matrix.il", "w") as f:
128 f.write(vl)
129
130 run_simulation(dut, d_matrix_sim(dut), vcd_name='test_ld_st_matrix.vcd')
131
132 if __name__ == '__main__':
133 test_d_matrix()