Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / experiment / test / test_mmu_dcache.py
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
8
9 if True:
10 from nmigen.back.pysim import Simulator, Delay, Settle
11 else:
12 from nmigen.sim.cxxsim import Simulator, Delay, Settle
13 from nmutil.util import wrap
14
15 from soc.experiment.mem_types import (LoadStore1ToMMUType,
16 MMUToLoadStore1Type,
17 MMUToDCacheType,
18 DCacheToMMUType,
19 MMUToICacheType)
20
21 from soc.experiment.mmu import MMU
22 from soc.experiment.dcache import DCache
23 from soc.experiment.icache import ICache
24 from openpower.test.wb_get import wb_get
25 from openpower.test import wb_get as wbget
26
27 import random
28
29 wbget.stop = False
30
31 def b(x):
32 return int.from_bytes(x.to_bytes(8, byteorder='little'),
33 byteorder='big', signed=False)
34
35
36 default_mem = { 0x10000: # PARTITION_TABLE_2
37 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
38 b(0x800000000100000b),
39
40 0x30000: # RADIX_ROOT_PTE
41 # V = 1 L = 0 NLB = 0x400 NLS = 9
42 b(0x8000000000040009),
43
44 0x40000: # RADIX_SECOND_LEVEL
45 # V = 1 L = 1 SW = 0 RPN = 0
46 # R = 1 C = 1 ATT = 0 EAA 0x7
47 b(0xc000000000000187),
48
49 0x1000000: # PROCESS_TABLE_3
50 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
51 b(0x40000000000300ad),
52 }
53
54
55 def icache_sim(dut, mem):
56 i_out = dut.i_in
57 i_in = dut.i_out
58 m_out = dut.m_in
59
60 wbget.stop = False
61
62 for k,v in mem.items():
63 yield i_in.valid.eq(0)
64 yield i_out.priv_mode.eq(1)
65 yield i_out.req.eq(0)
66 yield i_out.nia.eq(0)
67 yield i_out.stop_mark.eq(0)
68 yield m_out.tlbld.eq(0)
69 yield m_out.tlbie.eq(0)
70 yield m_out.addr.eq(0)
71 yield m_out.pte.eq(0)
72 yield
73 yield
74 yield
75 yield
76 yield i_out.req.eq(1)
77 yield i_out.nia.eq(C(k, 64))
78 while True:
79 yield
80 valid = yield i_in.valid
81 if valid:
82 break
83 nia = yield i_out.nia
84 insn = yield i_in.insn
85 yield
86 assert insn == v, \
87 "insn @%x=%x expected %x" % (nia, insn, v)
88 yield i_out.req.eq(0)
89 yield
90
91 wbget.stop = True
92
93 def test_icache_il():
94 dut = ICache()
95 vl = rtlil.convert(dut, ports=[])
96 with open("test_icache.il", "w") as f:
97 f.write(vl)
98
99
100 def test_icache():
101 # create a random set of addresses and "instructions" at those addresses
102 mem = {}
103 # fail 'AssertionError: insn @1d8=0 expected 61928a6100000000'
104 #random.seed(41)
105 # fail infinite loop 'cache read adr: 24 data: 0'
106 random.seed(43)
107 for i in range(3):
108 mem[random.randint(0, 1<<10)] = b(random.randint(0,1<<32))
109
110 # set up module for simulation
111 m = Module()
112 icache = ICache()
113 m.submodules.icache = icache
114
115 # nmigen Simulation
116 sim = Simulator(m)
117 sim.add_clock(1e-6)
118
119 # read from "memory" process and corresponding wishbone "read" process
120 sim.add_sync_process(wrap(icache_sim(icache, mem)))
121 sim.add_sync_process(wrap(wb_get(icache.bus, mem, "ICACHE")))
122 with sim.write_vcd('test_icache.vcd'):
123 sim.run()
124
125
126 def mmu_lookup(mmu, addr):
127
128 yield mmu.l_in.load.eq(1)
129 yield mmu.l_in.priv.eq(1)
130 yield mmu.l_in.addr.eq(addr)
131 yield mmu.l_in.valid.eq(1)
132
133 print ("mmu lookup %x stopped" % addr, wbget.stop)
134 while not wbget.stop: # wait for dc_valid / err
135 print ("stopped", wbget.stop)
136 l_done = yield (mmu.l_out.done)
137 l_err = yield (mmu.l_out.err)
138 l_badtree = yield (mmu.l_out.badtree)
139 l_permerr = yield (mmu.l_out.perm_error)
140 l_rc_err = yield (mmu.l_out.rc_error)
141 l_segerr = yield (mmu.l_out.segerr)
142 l_invalid = yield (mmu.l_out.invalid)
143 if (l_done or l_err or l_badtree or
144 l_permerr or l_rc_err or l_segerr or l_invalid):
145 break
146 yield
147 phys_addr = yield mmu.d_out.addr
148 pte = yield mmu.d_out.pte
149 print ("translated done %d err %d badtree %d addr %x pte %x" % \
150 (l_done, l_err, l_badtree, phys_addr, pte))
151 yield
152 yield mmu.l_in.valid.eq(0)
153
154 return phys_addr
155
156
157 def mmu_sim(mmu):
158 wbget.stop = False
159 yield mmu.rin.prtbl.eq(0x1000000) # set process table
160 yield
161
162 phys_addr = yield from mmu_lookup(mmu, 0x10000)
163 assert phys_addr == 0x40000
164
165 phys_addr = yield from mmu_lookup(mmu, 0x10000)
166 assert phys_addr == 0x40000
167 yield
168
169 wbget.stop = True
170
171
172 def test_mmu():
173 mmu = MMU()
174 dcache = DCache()
175 m = Module()
176 m.submodules.mmu = mmu
177 m.submodules.dcache = dcache
178
179 # link mmu and dcache together
180 m.d.comb += dcache.m_in.eq(mmu.d_out)
181 m.d.comb += mmu.d_in.eq(dcache.m_out)
182
183 # nmigen Simulation
184 sim = Simulator(m)
185 sim.add_clock(1e-6)
186
187 sim.add_sync_process(wrap(mmu_sim(mmu)))
188 sim.add_sync_process(wrap(wb_get(dcache.bus,
189 default_mem, "DCACHE")))
190 with sim.write_vcd('test_mmu.vcd'):
191 sim.run()
192
193
194 if __name__ == '__main__':
195 test_mmu()
196 #test_icache_il()
197 #test_icache()