5f8ff890937b53609a6b3788be546d9c18cb6c73
1 """ Mitch Alsup 6600-style LD/ST scoreboard Dependency Cell
3 Relevant comments (p45-46):
5 * If there are no WAR dependencies on a Load instruction with a computed
6 address it can assert Bank_Addressable and Translate_Addressable.
8 * If there are no RAW dependencies on a Store instruction with both a
9 write permission and store data present it can assert Bank_Addressable
13 * http://bugs.libre-riscv.org/show_bug.cgi?id=81
17 from nmigen
.compat
.sim
import run_simulation
18 from nmigen
.cli
import verilog
, rtlil
19 from nmigen
import Module
, Signal
, Repl
, Elaboratable
20 from nmutil
.latch
import SRLatch
23 class LDSTDepCell(Elaboratable
):
24 """ implements 11.4.12 mitch alsup load/store dependence cell, p45
26 def __init__(self
, n_ls
=1):
29 self
.load_i
= Signal(n_ls
, reset_less
=True) # load pend in (top)
30 self
.stor_i
= Signal(n_ls
, reset_less
=True) # store pend in (top)
31 self
.issue_i
= Signal(reset_less
=True) # Issue in (top)
32 self
.go_die_i
= Signal(reset_less
=True) # Issue in (top)
34 # load / store hit - basically connect these to go_wr from LD/STCompUnit
35 # LD.go_wr -> load_hit_i, ST.go_wr -> stwd_hit_i.
36 self
.load_hit_i
= Signal(n_ls
, reset_less
=True) # ld hit in (right)
37 self
.stwd_hit_i
= Signal(n_ls
, reset_less
=True) # st w/ hit in (right)
39 # outputs (latched rd/wr pend)
40 self
.ld_hold_st_o
= Signal(reset_less
=True) # ld holds st out (l)
41 self
.st_hold_ld_o
= Signal(reset_less
=True) # st holds ld out (l)
43 def elaborate(self
, platform
):
45 m
.submodules
.war_l
= war_l
= SRLatch(sync
=False, llen
=self
.n_ls
) # WaR
46 m
.submodules
.raw_l
= raw_l
= SRLatch(sync
=False, llen
=self
.n_ls
) # RaW
48 # temporaries (repeat-extend)
49 issue
= Repl(self
.issue_i
, self
.n_ls
)
50 die
= Repl(self
.go_die_i
, self
.n_ls
)
52 # issue & store & load - used for both WAR and RAW Setting
53 i_s_l
= Signal(self
.n_ls
, reset_less
=True)
54 m
.d
.comb
+= i_s_l
.eq(issue
& self
.stor_i
& self
.load_i
)
56 # write after read latch: loads block stores
57 m
.d
.comb
+= war_l
.s
.eq(i_s_l
)
58 m
.d
.comb
+= war_l
.r
.eq(die | self
.load_i
) # reset on LD
60 # read after write latch: stores block loads
61 m
.d
.comb
+= raw_l
.s
.eq(i_s_l
)
62 m
.d
.comb
+= raw_l
.r
.eq(die | self
.stor_i
) # reset on ST
64 # Hold results (read out horizontally, accumulate in OR fashion)
65 m
.d
.comb
+= self
.ld_hold_st_o
.eq((war_l
.qn
& self
.load_hit_i
).bool())
66 m
.d
.comb
+= self
.st_hold_ld_o
.eq((raw_l
.qn
& self
.stwd_hit_i
).bool())
76 yield self
.ld_hold_st_o
77 yield self
.st_hold_ld_o
84 yield dut
.dest_i
.eq(1)
85 yield dut
.issue_i
.eq(1)
87 yield dut
.issue_i
.eq(0)
89 yield dut
.src1_i
.eq(1)
90 yield dut
.issue_i
.eq(1)
92 yield dut
.issue_i
.eq(0)
94 yield dut
.go_rd_i
.eq(1)
96 yield dut
.go_rd_i
.eq(0)
98 yield dut
.go_wr_i
.eq(1)
100 yield dut
.go_wr_i
.eq(0)
105 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
106 with
open("test_ldst_dcell.il", "w") as f
:
109 run_simulation(dut
, dcell_sim(dut
), vcd_name
='test_ldst_dcell.vcd')
111 if __name__
== '__main__':