9b121d45ba3b2ba926d0bdf6a587c539cc9f6036
[soc.git] / src / soc / experiment / test / test_loadstore1.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.mask import Mask, masked
5 from nmutil.util import Display
6 from random import randint, seed
7 from nmigen.sim import Simulator, Delay, Settle
8 from nmutil.util import wrap
9
10 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst, wait_busy
11 #from soc.config.test.test_pi2ls import pi_st_debug
12 from soc.config.test.test_loadstore import TestMemPspec
13 from soc.config.loadstore import ConfigMemoryPortInterface
14
15 from soc.fu.ldst.loadstore import LoadStore1
16 from soc.experiment.mmu import MMU
17 from soc.experiment.test import pagetables
18
19 from nmigen.compat.sim import run_simulation
20
21 stop = False
22
23 def wb_get(wb, mem):
24 """simulator process for getting memory load requests
25 """
26
27 global stop
28 assert(stop==False)
29
30 while not stop:
31 while True: # wait for dc_valid
32 if stop:
33 return
34 cyc = yield (wb.cyc)
35 stb = yield (wb.stb)
36 if cyc and stb:
37 break
38 yield
39 addr = (yield wb.adr) << 3
40 if addr not in mem:
41 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr))
42
43 # read or write?
44 we = (yield wb.we)
45 if we:
46 store = (yield wb.dat_w)
47 sel = (yield wb.sel)
48 data = mem.get(addr, 0)
49 # note we assume 8-bit sel, here
50 res = 0
51 for i in range(8):
52 mask = 0xff << (i*8)
53 if sel & (1<<i):
54 res |= store & mask
55 else:
56 res |= data & mask
57 mem[addr] = res
58 print (" DCACHE set %x mask %x data %x" % (addr, sel, res))
59 else:
60 data = mem.get(addr, 0)
61 yield wb.dat_r.eq(data)
62 print (" DCACHE get %x data %x" % (addr, data))
63
64 yield wb.ack.eq(1)
65 yield
66 yield wb.ack.eq(0)
67 yield
68
69 def setup_mmu():
70
71 global stop
72 stop = False
73
74 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
75 imem_ifacetype='',
76 addr_wid=48,
77 #disable_cache=True, # hmmm...
78 mask_wid=8,
79 reg_wid=64)
80
81 m = Module()
82 comb = m.d.comb
83 cmpi = ConfigMemoryPortInterface(pspec)
84 m.submodules.ldst = ldst = cmpi.pi
85 m.submodules.mmu = mmu = MMU()
86 dcache = ldst.dcache
87
88 l_in, l_out = mmu.l_in, mmu.l_out
89 d_in, d_out = dcache.d_in, dcache.d_out
90 wb_out, wb_in = dcache.wb_out, dcache.wb_in
91
92 # link mmu and dcache together
93 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
94 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
95
96 # link ldst and MMU together
97 comb += l_in.eq(ldst.m_out)
98 comb += ldst.m_in.eq(l_out)
99
100 return m, cmpi
101
102 test_exceptions = True
103
104 def _test_loadstore1_invalid(dut, mem):
105 mmu = dut.submodules.mmu
106 pi = dut.submodules.ldst.pi
107 global stop
108 stop = False
109
110 print("=== test invalid ===")
111
112 addr = 0
113 ld_data, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
114 print("ld_data",ld_data,exc)
115 assert(exc=="slow")
116 invalid = yield pi.exc_o.invalid
117 assert(invalid==1)
118
119 print("=== test invalid done ===")
120
121 stop = True
122
123
124 def _test_loadstore1(dut, mem):
125 mmu = dut.submodules.mmu
126 pi = dut.submodules.ldst.pi
127 global stop
128 stop = False
129
130 yield mmu.rin.prtbl.eq(0x1000000) # set process table
131 yield
132
133 addr = 0x100e0
134 data = 0xf553b658ba7e1f51
135
136 yield from pi_st(pi, addr, data, 8, msr_pr=1)
137 yield
138
139 ld_data, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
140 assert ld_data == 0xf553b658ba7e1f51
141 assert exc is None
142 ld_data, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
143 assert ld_data == 0xf553b658ba7e1f51
144 assert exc is None
145
146 print("do_dcbz ===============")
147 yield from pi_st(pi, addr, data, 8, msr_pr=1, is_dcbz=1)
148 print("done_dcbz ===============")
149 yield
150
151 ld_data, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
152 print("ld_data after dcbz")
153 print(ld_data)
154 assert ld_data == 0
155 assert exc is None
156
157 if test_exceptions:
158 print("=== alignment error (ld) ===")
159 addr = 0xFF100e0FF
160 ld_data, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
161 alignment = yield pi.exc_o.alignment
162 happened = yield pi.exc_o.happened
163 dar = yield pi.dar_o
164 assert(happened==1)
165 assert(alignment==1)
166 assert(dar==addr)
167 assert(exc=="fast")
168 yield from wait_busy(pi, debug="pi_ld_E_alignment_error")
169 # wait is only needed in case of in exception here
170 print("=== alignment error test passed (ld) ===")
171
172 print("=== alignment error (st) ===")
173 addr = 0xFF100e0FF
174 exc = yield from pi_st(pi, addr,0, 8, msr_pr=1)
175 alignment = yield pi.exc_o.alignment
176 happened = yield pi.exc_o.happened
177 dar = yield pi.dar_o
178 assert(happened==1)
179 assert(alignment==1)
180 assert(dar==addr)
181 assert(exc=="fast")
182 yield from wait_busy(pi, debug="pi_st_E_alignment_error")
183 # wait is only needed in case of in exception here
184 print("=== alignment error test passed (st) ===")
185 yield # IMPORTANT: wait one clock cycle after failed st
186
187 print("=== no error ===")
188 addr = 0x100e0
189 ld_data, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
190 print("ld_data",ld_data,exc)
191 print("=== no error done ===")
192
193 stop = True
194
195 def test_loadstore1():
196
197 m, cmpi = setup_mmu()
198
199 mem = pagetables.test1
200
201 # nmigen Simulation
202 sim = Simulator(m)
203 sim.add_clock(1e-6)
204
205 sim.add_sync_process(wrap(_test_loadstore1(m, mem)))
206 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
207 with sim.write_vcd('test_loadstore1.vcd'):
208 sim.run()
209
210 def test_loadstore1_invalid():
211
212 m, cmpi = setup_mmu()
213
214 mem = {}
215
216 # nmigen Simulation
217 sim = Simulator(m)
218 sim.add_clock(1e-6)
219
220 sim.add_sync_process(wrap(_test_loadstore1_invalid(m, mem)))
221 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
222 with sim.write_vcd('test_loadstore1_invalid.vcd'):
223 sim.run()
224
225 if __name__ == '__main__':
226 test_loadstore1()
227 test_loadstore1_invalid()