c529372a9c7c66cd5dee33c643999329d2f35fee
[soc.git] / src / soc / experiment / test / test_ldst_pi.py
1 """MMU PortInterface Test
2
3 quite basic, goes directly to the MMU to assert signals (does not
4 yet use PortInterface)
5 """
6
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.mask import Mask, masked
11 from nmutil.util import Display
12
13 if True:
14 from nmigen.back.pysim import Simulator, Delay, Settle
15 else:
16 from nmigen.sim.cxxsim import Simulator, Delay, Settle
17 from nmutil.util import wrap
18
19 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst
20 from soc.config.test.test_loadstore import TestMemPspec
21 from soc.config.loadstore import ConfigMemoryPortInterface
22
23 from soc.fu.ldst.loadstore import LoadStore1
24 from soc.experiment.mmu import MMU
25
26 from nmigen.compat.sim import run_simulation
27
28
29 stop = False
30
31 def wb_get(wb):
32 """simulator process for getting memory load requests
33 """
34
35 global stop
36
37 def b(x):
38 return int.from_bytes(x.to_bytes(8, byteorder='little'),
39 byteorder='big', signed=False)
40
41 mem = {0x10000: # PARTITION_TABLE_2
42 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
43 b(0x800000000100000b),
44
45 0x30000: # RADIX_ROOT_PTE
46 # V = 1 L = 0 NLB = 0x400 NLS = 9
47 b(0x8000000000040009),
48
49 0x40000: # RADIX_SECOND_LEVEL
50 # V = 1 L = 1 SW = 0 RPN = 0
51 # R = 1 C = 1 ATT = 0 EAA 0x7
52 b(0xc000000000000187),
53
54 0x1000000: # PROCESS_TABLE_3
55 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
56 b(0x40000000000300ad),
57
58 # data to return
59 0x1000: 0xdeadbeef01234567,
60 0x1008: 0xfeedf00ff001a5a5
61 }
62
63 while not stop:
64 while True: # wait for dc_valid
65 if stop:
66 return
67 cyc = yield (wb.cyc)
68 stb = yield (wb.stb)
69 if cyc and stb:
70 break
71 yield
72 addr = (yield wb.adr) << 3
73 if addr not in mem:
74 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr))
75
76 data = mem.get(addr, 0)
77 yield wb.dat_r.eq(data)
78 print (" DCACHE get %x data %x" % (addr, data))
79 yield wb.ack.eq(1)
80 yield
81 yield wb.ack.eq(0)
82
83
84 def mmu_lookup(dut, addr):
85 mmu = dut.submodules.mmu
86 global stop
87
88 print("pi_ld")
89 data = yield from pi_ld(dut.submodules.ldst.pi, addr, 4, msr_pr=1)
90 print("pi_ld done, data", hex(data))
91 """
92 # original test code kept for reference
93 while not stop: # wait for dc_valid / err
94 print("waiting for mmu")
95 l_done = yield (mmu.l_out.done)
96 l_err = yield (mmu.l_out.err)
97 l_badtree = yield (mmu.l_out.badtree)
98 l_permerr = yield (mmu.l_out.perm_error)
99 l_rc_err = yield (mmu.l_out.rc_error)
100 l_segerr = yield (mmu.l_out.segerr)
101 l_invalid = yield (mmu.l_out.invalid)
102 if (l_done or l_err or l_badtree or
103 l_permerr or l_rc_err or l_segerr or l_invalid):
104 break
105 yield
106 """
107 phys_addr = yield mmu.d_out.addr
108 pte = yield mmu.d_out.pte
109 l_done = yield (mmu.l_out.done)
110 l_err = yield (mmu.l_out.err)
111 l_badtree = yield (mmu.l_out.badtree)
112 print ("translated done %d err %d badtree %d addr %x pte %x" % \
113 (l_done, l_err, l_badtree, phys_addr, pte))
114 yield
115 yield mmu.l_in.valid.eq(0)
116
117 return data
118
119
120 def ldst_sim(dut):
121 mmu = dut.submodules.mmu
122 global stop
123 yield mmu.rin.prtbl.eq(0x1000000) # set process table
124 yield
125
126 addr = 0x1000
127 print("pi_ld")
128
129 # TODO mmu_lookup using port interface
130 # set inputs
131 phys_addr = yield from mmu_lookup(dut, addr)
132 #assert phys_addr == addr # happens to be the same (for this example)
133
134 phys_addr = yield from mmu_lookup(dut, addr)
135 #assert phys_addr == addr # happens to be the same (for this example)
136
137 phys_addr = yield from mmu_lookup(dut, addr+4)
138
139 phys_addr = yield from mmu_lookup(dut, addr+8)
140
141 stop = True
142
143
144 def test_mmu():
145
146 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
147 imem_ifacetype='',
148 addr_wid=48,
149 #disable_cache=True, # hmmm...
150 mask_wid=8,
151 reg_wid=64)
152
153 m = Module()
154 comb = m.d.comb
155 cmpi = ConfigMemoryPortInterface(pspec)
156 m.submodules.ldst = ldst = cmpi.pi
157 m.submodules.mmu = mmu = MMU()
158 dcache = ldst.dcache
159
160 l_in, l_out = mmu.l_in, mmu.l_out
161 d_in, d_out = dcache.d_in, dcache.d_out
162 wb_out, wb_in = dcache.wb_out, dcache.wb_in
163
164 # link mmu and dcache together
165 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
166 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
167
168 # link ldst and MMU together
169 comb += l_in.eq(ldst.m_out)
170 comb += ldst.m_in.eq(l_out)
171
172
173 # nmigen Simulation
174 sim = Simulator(m)
175 sim.add_clock(1e-6)
176
177 sim.add_sync_process(wrap(ldst_sim(m)))
178 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus())))
179 with sim.write_vcd('test_ldst_pi.vcd'):
180 sim.run()
181
182
183 if __name__ == '__main__':
184 test_mmu()