from nmigen.cli import rtlil
from nmutil.mask import Mask, masked
from nmutil.util import Display
+from random import randint, seed
if True:
from nmigen.back.pysim import Simulator, Delay, Settle
return int.from_bytes(x.to_bytes(8, byteorder='little'),
byteorder='big', signed=False)
+#def dumpmem(mem,fn):
+# f = open(fn,"w")
+# for cell in mem:
+# f.write(str(hex(cell))+"="+str(hex(mem[cell]))+"\n")
+
def wb_get(wb, mem):
"""simulator process for getting memory load requests
"""
global stop
+ assert(stop==False)
while not stop:
while True: # wait for dc_valid
def setup_mmu():
+ global stop
+ stop = False
+
pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
imem_ifacetype='',
addr_wid=48,
with sim.write_vcd('test_ldst_pi.vcd'):
sim.run()
+
def ldst_sim_misalign(dut):
mmu = dut.submodules.mmu
global stop
sim.run()
+def ldst_sim_radixmiss(dut):
+ mmu = dut.submodules.mmu
+ global stop
+ stop = False
+
+ yield mmu.rin.prtbl.eq(1<<40) # set process table
+ yield
+
+ data = yield from pi_ld(dut.submodules.ldst.pi, 0x10000000, 8, msr_pr=1)
+ print ("radixmiss ld data", hex(data))
+
+ yield
+ stop = True
+
+def ldst_sim_dcache_regression(dut):
+ mmu = dut.submodules.mmu
+ global stop
+ stop = False
+
+ yield mmu.rin.prtbl.eq(0x1000000) # set process table
+ yield
+
+ addr = 0x10000
+ data = yield from pi_ld(dut.submodules.ldst.pi, addr, 8, msr_pr=1)
+ print ("=== dcache_regression ld data", hex(data))
+ assert(data == 0xdeadbeef01234567)
+
+ yield
+ stop = True
+
+def ldst_sim_dcache_random(dut):
+ mmu = dut.submodules.mmu
+ pi = dut.submodules.ldst.pi
+ global stop
+ stop = False
+
+ yield mmu.rin.prtbl.eq(0x1000000) # set process table
+ yield
+
+ memsize = 64
+
+ for i in range(16):
+ addr = randint(0, memsize-1)
+ data = randint(0, (1<<64)-1)
+ addr *= 8
+ addr += 0x10000
+
+ yield from pi_st(pi, addr, data, 8, msr_pr=1)
+ yield
+
+ ld_data = yield from pi_ld(pi, addr, 8, msr_pr=1)
+
+ eq = (data==ld_data)
+ print ("dcache_random values", hex(addr), hex(data), hex(ld_data), eq)
+ assert(data==ld_data) ## investigate why this fails -- really seldom
+
+ yield
+ stop = True
+
+def ldst_sim_dcache_first(dut): # this test is likely to fail
+ mmu = dut.submodules.mmu
+ pi = dut.submodules.ldst.pi
+ global stop
+ stop = False
+
+ yield mmu.rin.prtbl.eq(0x1000000) # set process table
+ yield
+
+ # failed ramdom data
+ addr = 65888
+ data = 0x8c5a3e460d71f0b4
+
+ # known to fail without bugfix in src/soc/fu/ldst/loadstore.py
+ yield from pi_st(pi, addr, data, 8, msr_pr=1)
+ yield
+
+ ld_data = yield from pi_ld(pi, addr, 8, msr_pr=1)
+
+ print ("addr",addr)
+ print ("dcache_first ld data", hex(data), hex(ld_data))
+
+ assert(data==ld_data)
+
+ yield
+ stop = True
+
+def test_radixmiss_mmu():
+
+ m, cmpi = setup_mmu()
+
+ # virtual "memory" to use for this test
+
+ mem = {0x10000: # PARTITION_TABLE_2
+ # PATB_GR=1 PRTB=0x1000 PRTS=0xb
+ b(0x800000000100000b),
+
+ 0x30000: # RADIX_ROOT_PTE
+ # V = 1 L = 0 NLB = 0x400 NLS = 9
+ b(0x8000000000040009),
+
+ 0x40000: # RADIX_SECOND_LEVEL
+ # V = 1 L = 1 SW = 0 RPN = 0
+ # R = 1 C = 1 ATT = 0 EAA 0x7
+ b(0xc000000000000183),
+
+ 0x1000000: # PROCESS_TABLE_3
+ # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
+ b(0x40000000000300ad),
+
+ # data to return
+ 0x1000: 0xdeadbeef01234567,
+ 0x1008: 0xfeedf00ff001a5a5
+ }
+
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(ldst_sim_radixmiss(m)))
+ sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_ldst_pi_radix_miss.vcd'):
+ sim.run()
+
+def test_dcache_regression():
+
+ m, cmpi = setup_mmu()
+
+ # dcache_load at addr 0
+ mem = {
+ 0x10000: # PARTITION_TABLE_2
+ # PATB_GR=1 PRTB=0x1000 PRTS=0xb
+ b(0x800000000100000b),
+
+ 0x30000: # RADIX_ROOT_PTE
+ # V = 1 L = 0 NLB = 0x400 NLS = 9
+ b(0x8000000000040009),
+
+ 0x40000: # RADIX_SECOND_LEVEL
+ # V = 1 L = 1 SW = 0 RPN = 0
+ # R = 1 C = 1 ATT = 0 EAA 0x7
+ b(0xc000000000000183),
+
+ 0x1000000: # PROCESS_TABLE_3
+ # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
+ b(0x40000000000300ad),
+
+ # data to return
+ 0x10000: 0xdeadbeef01234567,
+ 0x10008: 0xfeedf00ff001a5a5
+ }
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(ldst_sim_dcache_regression(m)))
+ sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_ldst_pi_radix_miss.vcd'):
+ sim.run()
+
+def test_dcache_random():
+
+ m, cmpi = setup_mmu()
+
+ # dcache_load at addr 0
+ mem = {
+ 0x10000: # PARTITION_TABLE_2
+ # PATB_GR=1 PRTB=0x1000 PRTS=0xb
+ b(0x800000000100000b),
+
+ 0x30000: # RADIX_ROOT_PTE
+ # V = 1 L = 0 NLB = 0x400 NLS = 9
+ b(0x8000000000040009),
+
+ 0x40000: # RADIX_SECOND_LEVEL
+ # V = 1 L = 1 SW = 0 RPN = 0
+ # R = 1 C = 1 ATT = 0 EAA 0x7
+ b(0xc000000000000183),
+
+ 0x1000000: # PROCESS_TABLE_3
+ # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
+ b(0x40000000000300ad),
+ }
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(ldst_sim_dcache_random(m)))
+ sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_ldst_pi_random.vcd'):
+ sim.run()
+
+def ldst_sim_dcache_random2(dut, mem):
+ mmu = dut.submodules.mmu
+ pi = dut.submodules.ldst.pi
+ global stop
+ stop = False
+
+ yield mmu.rin.prtbl.eq(0x1000000) # set process table
+ yield
+
+ memsize = 64
+
+ refs = [
+ ## random values from a failed test
+ #[0x100e0,0xf553b658ba7e1f51,0,0], ## 1
+ #[0x10150,0x12c95a730df1cee7,0,0], ## 2
+ #[0x10080,0x5a921ae06674cd81,0,0], ## 3
+ #[0x100f8,0x4fea5eab80090fa5,0,0], ## 4
+ #[0x10080,0xd481432d17a340be,0,0], ## 5
+ #[0x10060,0x8553fcf29526fb32,0,0], ## 6
+ [0x101d0,0x327c967c8be30ded,0,0], ## 7
+ [0x101e0,0x8f15d8d05d25b151,1,0] ## 8
+ #uncommenting line 7 will cause the original test not to fail
+
+ ]
+
+ c = 0
+ for i in refs:
+ addr = i[0]
+ data = i[1]
+ c1 = i[2]
+ c2 = i[3]
+
+ print("== write: wb_get")
+
+ for i in range(0,c1):
+ print("before_pi_st")
+ yield
+
+ yield from pi_st(pi, addr, data, 8, msr_pr=1)
+ yield
+
+ for i in range(0,c2):
+ print("before_pi_ld")
+ yield
+
+ print("== read: wb_get")
+ ld_data = yield from pi_ld(pi, addr, 8, msr_pr=1)
+
+ #dumpmem(mem,"/tmp/dumpmem"+str(c)+".txt")
+ #c += 1
+
+ eq = (data==ld_data)
+ print ("dcache_random values", hex(addr), hex(data), hex(ld_data), eq)
+ assert(data==ld_data) ## investigate why this fails -- really seldom
+
+ yield
+ stop = True
+
+def test_dcache_random2():
+
+ m, cmpi = setup_mmu()
+
+ # dcache_load at addr 0
+ mem = {
+ 0x10000: # PARTITION_TABLE_2
+ # PATB_GR=1 PRTB=0x1000 PRTS=0xb
+ b(0x800000000100000b),
+
+ 0x30000: # RADIX_ROOT_PTE
+ # V = 1 L = 0 NLB = 0x400 NLS = 9
+ b(0x8000000000040009),
+
+ 0x40000: # RADIX_SECOND_LEVEL
+ # V = 1 L = 1 SW = 0 RPN = 0
+ # R = 1 C = 1 ATT = 0 EAA 0x7
+ b(0xc000000000000183),
+
+ 0x1000000: # PROCESS_TABLE_3
+ # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
+ b(0x40000000000300ad),
+
+ ###0x101e0:0x8f15d8d05d25b152 ## flush cache -- then check again
+ }
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(ldst_sim_dcache_random2(m, mem)))
+ sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_ldst_pi_random2.vcd'):
+ sim.run()
+
+def test_dcache_first():
+
+ m, cmpi = setup_mmu()
+
+ # dcache_load at addr 0
+ mem = {
+ 0x10000: # PARTITION_TABLE_2
+ # PATB_GR=1 PRTB=0x1000 PRTS=0xb
+ b(0x800000000100000b),
+
+ 0x30000: # RADIX_ROOT_PTE
+ # V = 1 L = 0 NLB = 0x400 NLS = 9
+ b(0x8000000000040009),
+
+ 0x40000: # RADIX_SECOND_LEVEL
+ # V = 1 L = 1 SW = 0 RPN = 0
+ # R = 1 C = 1 ATT = 0 EAA 0x7
+ b(0xc000000000000183),
+
+ 0x1000000: # PROCESS_TABLE_3
+ # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
+ b(0x40000000000300ad),
+ }
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(ldst_sim_dcache_first(m)))
+ sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_ldst_pi_first.vcd'):
+ sim.run()
+
if __name__ == '__main__':
test_mmu()
test_misalign_mmu()
+ test_radixmiss_mmu()
+ ### tests taken from src/soc/experiment/test/test_dcache.py
+ test_dcache_regression()
+ test_dcache_first()
+ test_dcache_random() #sometimes fails
+ test_dcache_random2() #reproduce error