1 """MMU PortInterface Test
3 quite basic, calls pi_ld to get data via PortInterface. this test
4 shouldn't really exist, it's superceded by test_ldst_pi.py
7 from nmigen
import (C
, Module
, Signal
, Elaboratable
, Mux
, Cat
, Repl
, Signal
)
8 from nmigen
.cli
import main
9 from nmigen
.cli
import rtlil
10 from nmutil
.iocontrol
import RecordObject
11 from nmutil
.byterev
import byte_reverse
12 from nmutil
.mask
import Mask
, masked
13 from nmutil
.util
import Display
16 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
18 from nmigen
.sim
.cxxsim
import Simulator
, Delay
, Settle
19 from nmutil
.util
import wrap
21 from soc
.config
.test
.test_pi2ls
import pi_ld
, pi_st
, pi_ldst
23 from soc
.experiment
.mem_types
import (LoadStore1ToMMUType
,
29 from soc
.experiment
.mmu
import MMU
30 from soc
.experiment
.dcache
import DCache
34 from soc
.experiment
.l0_cache
import L0CacheBuffer2
35 from nmigen
import Module
, Signal
, Mux
, Elaboratable
, Cat
, Const
36 from nmigen
.cli
import rtlil
38 from soc
.config
.test
.test_pi2ls
import pi_ld
, pi_st
, pi_ldst
40 from soc
.experiment
.pimem
import PortInterfaceBase
42 from nmigen
.compat
.sim
import run_simulation
, Settle
44 # guess: those four need to be connected
45 #class DCacheToLoadStore1Type(RecordObject): dcache.d_out
46 #class LoadStore1ToDCacheType(RecordObject): dcache.d_in
47 #class LoadStore1ToMMUType(RecordObject): mmu.l_in
48 #class MMUToLoadStore1Type(RecordObject): mmu.l_out
49 # will take at least one week (10.10.2020)
50 # many unconnected signals
53 class TestMicrowattMemoryPortInterface(PortInterfaceBase
):
54 """TestMicrowattMemoryPortInterface
56 This is a Test Class for MMU and DCache conforming to PortInterface
59 def __init__(self
, mmu
, dcache
, regwid
=64, addrwid
=4):
60 super().__init
__(regwid
, addrwid
)
64 def set_wr_addr(self
, m
, addr
, mask
, misalign
, msr_pr
):
65 m
.d
.comb
+= self
.dcache
.d_in
.addr
.eq(addr
)
66 m
.d
.comb
+= self
.mmu
.l_in
.addr
.eq(addr
)
67 m
.d
.comb
+= self
.mmu
.l_in
.load
.eq(0)
68 m
.d
.comb
+= self
.mmu
.l_in
.priv
.eq(1) # TODO put msr_pr here
69 m
.d
.comb
+= self
.mmu
.l_in
.valid
.eq(1)
71 def set_rd_addr(self
, m
, addr
, mask
, misalign
, msr_pr
):
72 m
.d
.comb
+= self
.dcache
.d_in
.addr
.eq(addr
)
73 m
.d
.comb
+= self
.mmu
.l_in
.addr
.eq(addr
)
74 m
.d
.comb
+= self
.mmu
.l_in
.load
.eq(1)
75 m
.d
.comb
+= self
.mmu
.l_in
.priv
.eq(1) # TODO put msr_pr here
76 m
.d
.comb
+= self
.mmu
.l_in
.valid
.eq(1)
78 def set_wr_data(self
, m
, data
, wen
):
79 m
.d
.comb
+= self
.dcache
.d_in
.data
.eq(data
) # write st to mem
80 m
.d
.comb
+= self
.dcache
.d_in
.load
.eq(~wen
) # enable writes
84 # LoadStore1ToDCacheType
93 def get_rd_data(self
, m
):
94 # get data from dcache
95 ld_ok
= self
.mmu
.l_out
.done
96 data
= self
.dcache
.d_out
.data
100 # DCacheToLoadStore1Type NC
107 def elaborate(self
, platform
):
108 m
= super().elaborate(platform
)
110 m
.submodules
.mmu
= self
.mmu
111 m
.submodules
.dcache
= self
.dcache
113 # link mmu and dcache together
114 m
.d
.comb
+= self
.dcache
.m_in
.eq(self
.mmu
.d_out
)
115 m
.d
.comb
+= self
.mmu
.d_in
.eq(self
.dcache
.m_out
)
120 yield from super().ports()
127 """simulator process for getting memory load requests
133 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
134 byteorder
='big', signed
=False)
136 mem
= {0x10000: # PARTITION_TABLE_2
137 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
138 b(0x800000000100000b),
140 0x30000: # RADIX_ROOT_PTE
141 # V = 1 L = 0 NLB = 0x400 NLS = 9
142 b(0x8000000000040009),
144 0x40000: # RADIX_SECOND_LEVEL
145 # V = 1 L = 1 SW = 0 RPN = 0
146 # R = 1 C = 1 ATT = 0 EAA 0x7
147 b(0xc000000000000187),
149 0x1000000: # PROCESS_TABLE_3
150 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
151 b(0x40000000000300ad),
155 while True: # wait for dc_valid
158 cyc
= yield (dc
.wb_out
.cyc
)
159 stb
= yield (dc
.wb_out
.stb
)
163 addr
= (yield dc
.wb_out
.adr
) << 3
165 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr
))
167 data
= mem
.get(addr
, 0)
168 yield dc
.wb_in
.dat
.eq(data
)
169 print (" DCACHE get %x data %x" % (addr
, data
))
170 yield dc
.wb_in
.ack
.eq(1)
172 yield dc
.wb_in
.ack
.eq(0)
175 def mmu_lookup(dut
, addr
):
180 yield from pi_ld(dut
.pi
, addr
, 1)
183 # original test code kept for reference
184 while not stop: # wait for dc_valid / err
185 print("waiting for mmu")
186 l_done = yield (mmu.l_out.done)
187 l_err = yield (mmu.l_out.err)
188 l_badtree = yield (mmu.l_out.badtree)
189 l_permerr = yield (mmu.l_out.perm_error)
190 l_rc_err = yield (mmu.l_out.rc_error)
191 l_segerr = yield (mmu.l_out.segerr)
192 l_invalid = yield (mmu.l_out.invalid)
193 if (l_done or l_err or l_badtree or
194 l_permerr or l_rc_err or l_segerr or l_invalid):
198 phys_addr
= yield mmu
.d_out
.addr
199 pte
= yield mmu
.d_out
.pte
200 l_done
= yield (mmu
.l_out
.done
)
201 l_err
= yield (mmu
.l_out
.err
)
202 l_badtree
= yield (mmu
.l_out
.badtree
)
203 print ("translated done %d err %d badtree %d addr %x pte %x" % \
204 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
206 yield mmu
.l_in
.valid
.eq(0)
213 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
220 # TODO mmu_lookup using port interface
222 phys_addr
= yield from mmu_lookup(dut
, 0x10000)
223 assert phys_addr
== 0x40000
225 phys_addr
= yield from mmu_lookup(dut
, 0x10000)
226 assert phys_addr
== 0x40000
234 dut
= TestMicrowattMemoryPortInterface(mmu
, dcache
)
237 m
.submodules
.dut
= dut
243 sim
.add_sync_process(wrap(mmu_sim(dut
)))
244 sim
.add_sync_process(wrap(wb_get(dcache
)))
245 with sim
.write_vcd('test_mmu_pi.vcd'):
249 if __name__
== '__main__':