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
.experiment
.mem_types
import (LoadStore1ToMMUType
,
21 from soc
.experiment
.mmu
import MMU
22 from soc
.experiment
.dcache
import DCache
23 from soc
.experiment
.icache
import ICache
35 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
36 byteorder
='big', signed
=False)
39 default_mem
= { 0x10000: # PARTITION_TABLE_2
40 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
41 b(0x800000000100000b),
43 0x30000: # RADIX_ROOT_PTE
44 # V = 1 L = 0 NLB = 0x400 NLS = 9
45 b(0x8000000000040009),
47 0x40000: # RADIX_SECOND_LEVEL
48 # V = 1 L = 1 SW = 0 RPN = 0
49 # R = 1 C = 1 ATT = 0 EAA 0x7
50 b(0xc000000000000187),
52 0x1000000: # PROCESS_TABLE_3
53 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
54 b(0x40000000000300ad),
58 def wb_get(c
, mem
, name
):
59 """simulator process for getting memory load requests
62 logfile
= open("/tmp/wb_get.log","w")
65 logfile
.write(msg
+"\n")
70 while True: # wait for dc_valid
74 cyc
= yield (c
.wb_out
.cyc
)
75 stb
= yield (c
.wb_out
.stb
)
79 addr
= (yield c
.wb_out
.adr
) << 3
81 log("%s LOOKUP FAIL %x" % (name
, addr
))
87 yield c
.wb_in
.dat
.eq(data
)
88 log("%s get %x data %x" % (name
, addr
, data
))
89 yield c
.wb_in
.ack
.eq(1)
91 yield c
.wb_in
.ack
.eq(0)
95 def icache_sim(dut
, mem
):
100 for k
,v
in mem
.items():
101 yield i_in
.valid
.eq(0)
102 yield i_out
.priv_mode
.eq(1)
103 yield i_out
.req
.eq(0)
104 yield i_out
.nia
.eq(0)
105 yield i_out
.stop_mark
.eq(0)
106 yield m_out
.tlbld
.eq(0)
107 yield m_out
.tlbie
.eq(0)
108 yield m_out
.addr
.eq(0)
109 yield m_out
.pte
.eq(0)
114 yield i_out
.req
.eq(1)
115 yield i_out
.nia
.eq(C(k
, 64))
118 valid
= yield i_in
.valid
121 nia
= yield i_out
.nia
122 insn
= yield i_in
.insn
125 "insn @%x=%x expected %x" % (nia
, insn
, v
)
126 yield i_out
.req
.eq(0)
130 def test_icache_il():
132 vl
= rtlil
.convert(dut
, ports
=[])
133 with
open("test_icache.il", "w") as f
:
138 # create a random set of addresses and "instructions" at those addresses
140 # fail 'AssertionError: insn @1d8=0 expected 61928a6100000000'
142 # fail infinite loop 'cache read adr: 24 data: 0'
145 mem
[random
.randint(0, 1<<10)] = b(random
.randint(0,1<<32))
147 # set up module for simulation
150 m
.submodules
.icache
= icache
156 # read from "memory" process and corresponding wishbone "read" process
157 sim
.add_sync_process(wrap(icache_sim(icache
, mem
)))
158 sim
.add_sync_process(wrap(wb_get(icache
, mem
, "ICACHE")))
159 with sim
.write_vcd('test_icache.vcd'):
163 def mmu_lookup(mmu
, addr
):
166 yield mmu
.l_in
.load
.eq(1)
167 yield mmu
.l_in
.priv
.eq(1)
168 yield mmu
.l_in
.addr
.eq(addr
)
169 yield mmu
.l_in
.valid
.eq(1)
170 while not stop
: # wait for dc_valid / err
171 l_done
= yield (mmu
.l_out
.done
)
172 l_err
= yield (mmu
.l_out
.err
)
173 l_badtree
= yield (mmu
.l_out
.badtree
)
174 l_permerr
= yield (mmu
.l_out
.perm_error
)
175 l_rc_err
= yield (mmu
.l_out
.rc_error
)
176 l_segerr
= yield (mmu
.l_out
.segerr
)
177 l_invalid
= yield (mmu
.l_out
.invalid
)
178 if (l_done
or l_err
or l_badtree
or
179 l_permerr
or l_rc_err
or l_segerr
or l_invalid
):
182 phys_addr
= yield mmu
.d_out
.addr
183 pte
= yield mmu
.d_out
.pte
184 print ("translated done %d err %d badtree %d addr %x pte %x" % \
185 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
187 yield mmu
.l_in
.valid
.eq(0)
194 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
197 phys_addr
= yield from mmu_lookup(mmu
, 0x10000)
198 assert phys_addr
== 0x40000
200 phys_addr
= yield from mmu_lookup(mmu
, 0x10000)
201 assert phys_addr
== 0x40000
210 m
.submodules
.mmu
= mmu
211 m
.submodules
.dcache
= dcache
213 # link mmu and dcache together
214 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
)
215 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
)
221 sim
.add_sync_process(wrap(mmu_sim(mmu
)))
222 sim
.add_sync_process(wrap(wb_get(dcache
, default_mem
, "DCACHE")))
223 with sim
.write_vcd('test_mmu.vcd'):
227 if __name__
== '__main__':