70f4b9ba0e1b36e20194408dbd39d135cb3d3363
1 """ Mitch Alsup 6600-style LD/ST scoreboard Dependency Cell
5 * http://bugs.libre-riscv.org/show_bug.cgi?id=81
9 from nmigen
.compat
.sim
import run_simulation
10 from nmigen
.cli
import verilog
, rtlil
11 from nmigen
import Module
, Signal
, Repl
, Elaboratable
12 from nmutil
.latch
import SRLatch
15 class LDSTDepCell(Elaboratable
):
16 """ implements 11.4.12 mitch alsup load/store dependence cell, p45
18 def __init__(self
, n_ls
=1):
21 self
.load_h_i
= Signal(reset_less
=True) # load in (left)
22 self
.stor_h_i
= Signal(reset_less
=True) # store in (left)
23 self
.load_v_i
= Signal(n_ls
, reset_less
=True) # load in (top)
24 self
.stor_v_i
= Signal(n_ls
, reset_less
=True) # store in (top)
25 self
.issue_i
= Signal(reset_less
=True) # Issue in (left)
26 self
.go_die_i
= Signal(reset_less
=True) # Issue in (left)
28 # load / store hit - basically connect these to go_wr from LD/STCompUnit
29 # LD.go_wr -> load_hit_i, ST.go_wr -> stwd_hit_i.
30 self
.load_hit_i
= Signal(n_ls
, reset_less
=True) # ld hit in (right)
31 self
.stwd_hit_i
= Signal(n_ls
, reset_less
=True) # st w/ hit in (right)
33 # outputs (latched rd/wr pend)
34 self
.ld_hold_st_o
= Signal(reset_less
=True) # ld holds st out (l)
35 self
.st_hold_ld_o
= Signal(reset_less
=True) # st holds ld out (l)
37 def elaborate(self
, platform
):
39 m
.submodules
.war_l
= war_l
= SRLatch(sync
=False, llen
=self
.n_ls
) # WaR
40 m
.submodules
.raw_l
= raw_l
= SRLatch(sync
=False, llen
=self
.n_ls
) # RaW
42 # temporaries (repeat-extend)
43 issue
= Repl(self
.issue_i
, self
.n_ls
)
44 die
= Repl(self
.go_die_i
, self
.n_ls
)
46 # issue & store & load - used for WAR Setting. LD is left, ST is top
47 i_s
= Signal(reset_less
=True)
48 i_s_l
= Signal(self
.n_ls
, reset_less
=True)
49 m
.d
.comb
+= i_s
.eq(issue
& self
.stor_h_i
) # horizontal single-signal
50 m
.d
.comb
+= i_s_l
.eq(Repl(i_s
, self
.n_ls
) & self
.load_v_i
) # multi, vert
52 # issue & load & store - used for RAW Setting. ST is left, LD is top
53 i_l
= Signal(reset_less
=True)
54 i_l_s
= Signal(self
.n_ls
, reset_less
=True)
55 m
.d
.comb
+= i_l
.eq(issue
& self
.load_h_i
) # horizontal single-signal
56 m
.d
.comb
+= i_l_s
.eq(Repl(i_l
, self
.n_ls
) & self
.stor_v_i
) # multi, vert
58 # write after read latch: loads block stores
59 m
.d
.comb
+= war_l
.s
.eq(i_s_l
)
60 m
.d
.comb
+= war_l
.r
.eq(die | ~self
.load_v_i
) # reset on LD
62 # read after write latch: stores block loads
63 m
.d
.comb
+= raw_l
.s
.eq(i_s_l
)
64 m
.d
.comb
+= raw_l
.r
.eq(die | ~self
.stor_v_i
) # reset on ST
66 # Hold results (read out horizontally, accumulate in OR fashion)
67 m
.d
.comb
+= self
.ld_hold_st_o
.eq((war_l
.qn
& self
.load_hit_i
).bool())
68 m
.d
.comb
+= self
.st_hold_ld_o
.eq((raw_l
.qn
& self
.stwd_hit_i
).bool())
80 yield self
.ld_hold_st_o
81 yield self
.st_hold_ld_o
88 yield dut
.dest_i
.eq(1)
89 yield dut
.issue_i
.eq(1)
91 yield dut
.issue_i
.eq(0)
93 yield dut
.src1_i
.eq(1)
94 yield dut
.issue_i
.eq(1)
96 yield dut
.issue_i
.eq(0)
98 yield dut
.go_rd_i
.eq(1)
100 yield dut
.go_rd_i
.eq(0)
102 yield dut
.go_wr_i
.eq(1)
104 yield dut
.go_wr_i
.eq(0)
109 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
110 with
open("test_ldst_dcell.il", "w") as f
:
113 run_simulation(dut
, dcell_sim(dut
), vcd_name
='test_ldst_dcell.vcd')
115 if __name__
== '__main__':