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
31 from openpower
.test
.wb_get
import wb_get
32 from openpower
.test
import wb_get
as wbget
36 from soc
.experiment
.l0_cache
import L0CacheBuffer2
37 from nmigen
import Module
, Signal
, Mux
, Elaboratable
, Cat
, Const
38 from nmigen
.cli
import rtlil
40 from soc
.config
.test
.test_pi2ls
import pi_ld
, pi_st
, pi_ldst
42 from soc
.experiment
.pimem
import PortInterfaceBase
44 from nmigen
.compat
.sim
import run_simulation
, Settle
46 # guess: those four need to be connected
47 #class DCacheToLoadStore1Type(RecordObject): dcache.d_out
48 #class LoadStore1ToDCacheType(RecordObject): dcache.d_in
49 #class LoadStore1ToMMUType(RecordObject): mmu.l_in
50 #class MMUToLoadStore1Type(RecordObject): mmu.l_out
51 # will take at least one week (10.10.2020)
52 # many unconnected signals
55 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
56 byteorder
='big', signed
=False)
58 mem
= {0x10000: # PARTITION_TABLE_2
59 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
60 b(0x800000000100000b),
62 0x30000: # RADIX_ROOT_PTE
63 # V = 1 L = 0 NLB = 0x400 NLS = 9
64 b(0x8000000000040009),
66 0x40000: # RADIX_SECOND_LEVEL
67 # V = 1 L = 1 SW = 0 RPN = 0
68 # R = 1 C = 1 ATT = 0 EAA 0x7
69 b(0xc000000000000187),
71 0x1000000: # PROCESS_TABLE_3
72 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
73 b(0x40000000000300ad),
77 class TestMicrowattMemoryPortInterface(PortInterfaceBase
):
78 """TestMicrowattMemoryPortInterface
80 This is a Test Class for MMU and DCache conforming to PortInterface
83 def __init__(self
, mmu
, dcache
, regwid
=64, addrwid
=4):
84 super().__init
__(regwid
, addrwid
)
88 def set_wr_addr(self
, m
, addr
, mask
, misalign
, msr_pr
, is_dcbz
):
89 m
.d
.comb
+= self
.dcache
.d_in
.addr
.eq(addr
)
90 m
.d
.comb
+= self
.mmu
.l_in
.addr
.eq(addr
)
91 m
.d
.comb
+= self
.mmu
.l_in
.load
.eq(0)
92 m
.d
.comb
+= self
.mmu
.l_in
.priv
.eq(1) # TODO put msr_pr here
93 m
.d
.comb
+= self
.mmu
.l_in
.valid
.eq(1)
95 def set_rd_addr(self
, m
, addr
, mask
, misalign
, msr_pr
):
96 m
.d
.comb
+= self
.dcache
.d_in
.addr
.eq(addr
)
97 m
.d
.comb
+= self
.mmu
.l_in
.addr
.eq(addr
)
98 m
.d
.comb
+= self
.mmu
.l_in
.load
.eq(1)
99 m
.d
.comb
+= self
.mmu
.l_in
.priv
.eq(1) # TODO put msr_pr here
100 m
.d
.comb
+= self
.mmu
.l_in
.valid
.eq(1)
102 def set_wr_data(self
, m
, data
, wen
):
103 m
.d
.comb
+= self
.dcache
.d_in
.data
.eq(data
) # write st to mem
104 m
.d
.comb
+= self
.dcache
.d_in
.load
.eq(~wen
) # enable writes
108 # LoadStore1ToDCacheType
117 def get_rd_data(self
, m
):
118 # get data from dcache
119 ld_ok
= self
.mmu
.l_out
.done
120 data
= self
.dcache
.d_out
.data
124 # DCacheToLoadStore1Type NC
131 def elaborate(self
, platform
):
132 m
= super().elaborate(platform
)
134 m
.submodules
.mmu
= self
.mmu
135 m
.submodules
.dcache
= self
.dcache
137 # link mmu and dcache together
138 m
.d
.comb
+= self
.dcache
.m_in
.eq(self
.mmu
.d_out
)
139 m
.d
.comb
+= self
.mmu
.d_in
.eq(self
.dcache
.m_out
)
144 yield from super().ports()
150 def mmu_lookup(dut
, addr
):
154 yield from pi_ld(dut
.pi
, addr
, 1)
157 # original test code kept for reference
158 while not stop: # wait for dc_valid / err
159 print("waiting for mmu")
160 l_done = yield (mmu.l_out.done)
161 l_err = yield (mmu.l_out.err)
162 l_badtree = yield (mmu.l_out.badtree)
163 l_permerr = yield (mmu.l_out.perm_error)
164 l_rc_err = yield (mmu.l_out.rc_error)
165 l_segerr = yield (mmu.l_out.segerr)
166 l_invalid = yield (mmu.l_out.invalid)
167 if (l_done or l_err or l_badtree or
168 l_permerr or l_rc_err or l_segerr or l_invalid):
172 phys_addr
= yield mmu
.d_out
.addr
173 pte
= yield mmu
.d_out
.pte
174 l_done
= yield (mmu
.l_out
.done
)
175 l_err
= yield (mmu
.l_out
.err
)
176 l_badtree
= yield (mmu
.l_out
.badtree
)
177 print ("translated done %d err %d badtree %d addr %x pte %x" % \
178 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
180 yield mmu
.l_in
.valid
.eq(0)
186 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
193 # TODO mmu_lookup using port interface
195 phys_addr
= yield from mmu_lookup(dut
, 0x10000)
196 assert phys_addr
== 0x40000
198 phys_addr
= yield from mmu_lookup(dut
, 0x10000)
199 assert phys_addr
== 0x40000
207 dut
= TestMicrowattMemoryPortInterface(mmu
, dcache
)
210 m
.submodules
.dut
= dut
216 sim
.add_sync_process(wrap(mmu_sim(dut
)))
217 sim
.add_sync_process(wrap(wb_get(dcache
.bus
, mem
)))
218 with sim
.write_vcd('test_mmu_pi.vcd'):
222 if __name__
== '__main__':