1 from nmigen
import (C
, Module
, Signal
, Elaboratable
, Mux
, Cat
, Repl
, Signal
)
2 from nmigen
.cli
import main
3 from nmigen
.cli
import rtlil
4 from nmutil
.iocontrol
import RecordObject
5 from nmutil
.byterev
import byte_reverse
6 from nmutil
.mask
import Mask
, masked
7 from nmutil
.util
import Display
10 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
12 from nmigen
.sim
.cxxsim
import Simulator
, Delay
, Settle
13 from nmutil
.util
import wrap
15 from soc
.config
.test
.test_pi2ls
import pi_ld
, pi_st
, pi_ldst
17 from soc
.experiment
.mem_types
import (LoadStore1ToMMUType
,
23 from soc
.experiment
.mmu
import MMU
24 from soc
.experiment
.dcache
import DCache
28 from soc
.experiment
.l0_cache
import L0CacheBuffer2
29 from nmigen
import Module
, Signal
, Mux
, Elaboratable
, Cat
, Const
30 from nmigen
.cli
import rtlil
32 from soc
.config
.test
.test_pi2ls
import pi_ld
, pi_st
, pi_ldst
34 from soc
.experiment
.pimem
import PortInterfaceBase
36 from nmigen
.compat
.sim
import run_simulation
, Settle
38 # guess: those four need to be connected
39 #class DCacheToLoadStore1Type(RecordObject): dcache.d_out
40 #class LoadStore1ToDCacheType(RecordObject): dcache.d_in
41 #class LoadStore1ToMMUType(RecordObject): mmu.l_in
42 #class MMUToLoadStore1Type(RecordObject): mmu.l_out
43 # will take at least one week (10.10.2020)
44 # many unconnected signals
47 class TestMicrowattMemoryPortInterface(PortInterfaceBase
):
48 """TestMicrowattMemoryPortInterface
50 This is a Test Class for MMU and DCache conforming to PortInterface
53 def __init__(self
, mmu
, dcache
, regwid
=64, addrwid
=4):
54 super().__init
__(regwid
, addrwid
)
58 def set_wr_addr(self
, m
, addr
, mask
, misalign
, msr_pr
):
59 m
.d
.comb
+= self
.dcache
.d_in
.addr
.eq(addr
)
60 m
.d
.comb
+= self
.mmu
.l_in
.addr
.eq(addr
)
61 m
.d
.comb
+= self
.mmu
.l_in
.load
.eq(0)
62 m
.d
.comb
+= self
.mmu
.l_in
.priv
.eq(1) # TODO put msr_pr here
63 m
.d
.comb
+= self
.mmu
.l_in
.valid
.eq(1)
65 def set_rd_addr(self
, m
, addr
, mask
, misalign
, msr_pr
):
66 m
.d
.comb
+= self
.dcache
.d_in
.addr
.eq(addr
)
67 m
.d
.comb
+= self
.mmu
.l_in
.addr
.eq(addr
)
68 m
.d
.comb
+= self
.mmu
.l_in
.load
.eq(1)
69 m
.d
.comb
+= self
.mmu
.l_in
.priv
.eq(1) # TODO put msr_pr here
70 m
.d
.comb
+= self
.mmu
.l_in
.valid
.eq(1)
72 def set_wr_data(self
, m
, data
, wen
):
73 m
.d
.comb
+= self
.dcache
.d_in
.data
.eq(data
) # write st to mem
74 m
.d
.comb
+= self
.dcache
.d_in
.load
.eq(~wen
) # enable writes
78 # LoadStore1ToDCacheType
87 def get_rd_data(self
, m
):
88 # get data from dcache
89 ld_ok
= self
.mmu
.l_out
.done
90 data
= self
.dcache
.d_out
.data
94 # DCacheToLoadStore1Type NC
101 def elaborate(self
, platform
):
102 m
= super().elaborate(platform
)
104 m
.submodules
.mmu
= self
.mmu
105 m
.submodules
.dcache
= self
.dcache
107 # link mmu and dcache together
108 m
.d
.comb
+= self
.dcache
.m_in
.eq(self
.mmu
.d_out
)
109 m
.d
.comb
+= self
.mmu
.d_in
.eq(self
.dcache
.m_out
)
114 yield from super().ports()
121 """simulator process for getting memory load requests
127 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
128 byteorder
='big', signed
=False)
130 mem
= {0x10000: # PARTITION_TABLE_2
131 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
132 b(0x800000000100000b),
134 0x30000: # RADIX_ROOT_PTE
135 # V = 1 L = 0 NLB = 0x400 NLS = 9
136 b(0x8000000000040009),
138 0x40000: # RADIX_SECOND_LEVEL
139 # V = 1 L = 1 SW = 0 RPN = 0
140 # R = 1 C = 1 ATT = 0 EAA 0x7
141 b(0xc000000000000187),
143 0x1000000: # PROCESS_TABLE_3
144 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
145 b(0x40000000000300ad),
149 while True: # wait for dc_valid
152 cyc
= yield (dc
.wb_out
.cyc
)
153 stb
= yield (dc
.wb_out
.stb
)
157 addr
= (yield dc
.wb_out
.adr
) << 3
159 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr
))
162 yield dc
.wb_in
.dat
.eq(data
)
163 print (" DCACHE get %x data %x" % (addr
, data
))
164 yield dc
.wb_in
.ack
.eq(1)
166 yield dc
.wb_in
.ack
.eq(0)
169 def mmu_lookup(dut
, addr
):
174 yield from pi_ld(dut
.pi
, addr
, 1)
177 # original test code kept for reference
178 while not stop: # wait for dc_valid / err
179 print("waiting for mmu")
180 l_done = yield (mmu.l_out.done)
181 l_err = yield (mmu.l_out.err)
182 l_badtree = yield (mmu.l_out.badtree)
183 l_permerr = yield (mmu.l_out.perm_error)
184 l_rc_err = yield (mmu.l_out.rc_error)
185 l_segerr = yield (mmu.l_out.segerr)
186 l_invalid = yield (mmu.l_out.invalid)
187 if (l_done or l_err or l_badtree or
188 l_permerr or l_rc_err or l_segerr or l_invalid):
192 phys_addr
= yield mmu
.d_out
.addr
193 pte
= yield mmu
.d_out
.pte
194 l_done
= yield (mmu
.l_out
.done
)
195 l_err
= yield (mmu
.l_out
.err
)
196 l_badtree
= yield (mmu
.l_out
.badtree
)
197 print ("translated done %d err %d badtree %d addr %x pte %x" % \
198 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
200 yield mmu
.l_in
.valid
.eq(0)
207 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
214 # TODO mmu_lookup using port interface
216 phys_addr
= yield from mmu_lookup(dut
, 0x10000)
217 assert phys_addr
== 0x40000
219 phys_addr
= yield from mmu_lookup(dut
, 0x10000)
220 assert phys_addr
== 0x40000
228 dut
= TestMicrowattMemoryPortInterface(mmu
, dcache
)
231 m
.submodules
.dut
= dut
237 sim
.add_sync_process(wrap(mmu_sim(dut
)))
238 sim
.add_sync_process(wrap(wb_get(dcache
)))
239 with sim
.write_vcd('test_mmu_pi.vcd'):
243 if __name__
== '__main__':