1 from soc
.minerva
.units
.loadstore
import LoadStoreUnitInterface
2 from nmigen
import Signal
, Module
, Elaboratable
, Mux
3 from nmigen
.utils
import log2_int
4 from soc
.experiment
.testmem
import TestMemory
# TODO: replace with TMLSUI
5 from nmigen
.cli
import rtlil
8 class TestMemLoadStoreUnit(LoadStoreUnitInterface
, Elaboratable
):
10 def elaborate(self
, platform
):
12 regwid
, addrwid
, mask_wid
= self
.data_wid
, self
.addr_wid
, self
.mask_wid
13 adr_lsb
= self
.adr_lsbs
15 # limit TestMemory to 2^6 entries of regwid size
16 m
.submodules
.mem
= mem
= TestMemory(regwid
, 6, granularity
=8)
18 do_load
= Signal() # set when load while valid and not stalled
19 do_store
= Signal() # set when store while valid and not stalled
22 do_load
.eq(self
.x_ld_i
& (self
.x_valid_i
& ~self
.x_stall_i
)),
23 do_store
.eq(self
.x_st_i
& (self
.x_valid_i
& ~self
.x_stall_i
)),
25 # bit of a messy FSM that progresses from idle to in progress
27 op_actioned
= Signal(reset
=0)
28 op_in_progress
= Signal(reset
=0)
29 with m
.If(~op_actioned
& (do_load | do_store
)): # idle
30 m
.d
.sync
+= op_actioned
.eq(1)
31 m
.d
.sync
+= op_in_progress
.eq(1)
32 with m
.Elif(op_in_progress
): # in progress
33 m
.d
.sync
+= op_actioned
.eq(0)
34 with m
.If(~
(do_load | do_store
)): # done
35 m
.d
.sync
+= op_in_progress
.eq(0)
37 m
.d
.comb
+= self
.x_busy_o
.eq(op_actioned
& self
.x_valid_i
)
41 mem
.rdport
.addr
.eq(self
.x_addr_i
[adr_lsb
:]),
42 self
.m_ld_data_o
.eq(mem
.rdport
.data
),
44 # store - only activates once
45 mem
.wrport
.addr
.eq(self
.x_addr_i
[adr_lsb
:]),
46 mem
.wrport
.en
.eq(Mux(do_store
& ~op_actioned
,
48 mem
.wrport
.data
.eq(self
.x_st_data_i
)
54 if __name__
== '__main__':
55 dut
= TestMemLoadStoreUnit(regwid
=32, addrwid
=4)
56 vl
= rtlil
.convert(dut
, ports
=[]) # TODOdut.ports())
57 with
open("test_lsmem.il", "w") as f
: