X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Fexperiment%2Ftest%2Ftest_ldst_pi.py;h=f444a06fa6a8854184d061b8054b7180c89a795c;hb=b79586f9c44294c5f831ee62a41a582ed0be987f;hp=ee90c585b0496235271d56d22c4e6488f9ba6c54;hpb=a9eb2efe76ae1a29db26cbe5f8a3876d458215b5;p=soc.git diff --git a/src/soc/experiment/test/test_ldst_pi.py b/src/soc/experiment/test/test_ldst_pi.py index ee90c585..f444a06f 100644 --- a/src/soc/experiment/test/test_ldst_pi.py +++ b/src/soc/experiment/test/test_ldst_pi.py @@ -9,6 +9,9 @@ from nmigen.cli import main from nmigen.cli import rtlil from nmutil.mask import Mask, masked from nmutil.util import Display +from random import randint, seed +from openpower.test.wb_get import wb_get +from openpower.test import wb_get as wbget if True: from nmigen.back.pysim import Simulator, Delay, Settle @@ -26,67 +29,27 @@ from soc.experiment.mmu import MMU from nmigen.compat.sim import run_simulation -stop = False +wbget.stop = False -def wb_get(wb): - """simulator process for getting memory load requests - """ - - global stop +def b(x): # byte-reverse function + return int.from_bytes(x.to_bytes(8, byteorder='little'), + byteorder='big', signed=False) - def b(x): - return int.from_bytes(x.to_bytes(8, byteorder='little'), - byteorder='big', signed=False) - - 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(0xc000000000000187), - - 0x1000000: # PROCESS_TABLE_3 - # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13 - b(0x40000000000300ad), - } - - while not stop: - while True: # wait for dc_valid - if stop: - return - cyc = yield (wb.cyc) - stb = yield (wb.stb) - if cyc and stb: - break - yield - addr = (yield wb.adr) << 3 - if addr not in mem: - print (" WB LOOKUP NO entry @ %x, returning zero" % (addr)) - - data = mem.get(addr, 0) - yield wb.dat_r.eq(data) - print (" DCACHE get %x data %x" % (addr, data)) - yield wb.ack.eq(1) - yield - yield wb.ack.eq(0) +#def dumpmem(mem,fn): +# f = open(fn,"w") +# for cell in mem: +# f.write(str(hex(cell))+"="+str(hex(mem[cell]))+"\n") def mmu_lookup(dut, addr): mmu = dut.submodules.mmu - global stop - print("pi_ld") - yield from pi_ld(dut.submodules.ldst.pi, addr, 1, msr_pr=1) - print("pi_ld done") + print("pi_ld", hex(addr)) + data, _, _ = yield from pi_ld(dut.submodules.ldst.pi, addr, 4, msr_pr=1) + print("pi_ld done, data", hex(data)) """ # original test code kept for reference - while not stop: # wait for dc_valid / err + while not wbget.stop: # wait for dc_valid / err print("waiting for mmu") l_done = yield (mmu.l_out.done) l_err = yield (mmu.l_out.err) @@ -110,31 +73,49 @@ def mmu_lookup(dut, addr): yield yield mmu.l_in.valid.eq(0) - return phys_addr + return data def ldst_sim(dut): mmu = dut.submodules.mmu - global stop yield mmu.rin.prtbl.eq(0x1000000) # set process table yield - addr = 0x10000 - data = 0 - print("pi_st") + # expecting this data to return + # 0x1000: 0xdeadbeef01234567, + # 0x1008: 0xfeedf00ff001a5a5 + + addr = 0x1000 + print("pi_ld") # TODO mmu_lookup using port interface - # set inputs - phys_addr = yield from mmu_lookup(dut, 0x10000) - assert phys_addr == 0x40000 + # set inputs + data = yield from mmu_lookup(dut, addr) + assert data == 0x1234567 - phys_addr = yield from mmu_lookup(dut, 0x10000) - assert phys_addr == 0x40000 + data = yield from mmu_lookup(dut, addr+8) + assert data == 0xf001a5a5 + #assert phys_addr == addr # happens to be the same (for this example) - stop = True + data = yield from mmu_lookup(dut, addr+4) + assert data == 0xdeadbeef + data = yield from mmu_lookup(dut, addr+8) + assert data == 0xf001a5a5 -def test_mmu(): + yield from pi_st(dut.submodules.ldst.pi, addr+4, 0x10015a5a, 4, msr_pr=1) + + data = yield from mmu_lookup(dut, addr+4) + assert data == 0x10015a5a + + yield + yield + + wbget.stop = True + +def setup_mmu(): + + wbget.stop = False pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb', imem_ifacetype='', @@ -152,7 +133,6 @@ def test_mmu(): l_in, l_out = mmu.l_in, mmu.l_out d_in, d_out = dcache.d_in, dcache.d_out - wb_out, wb_in = dcache.wb_out, dcache.wb_in # link mmu and dcache together m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType @@ -162,16 +142,423 @@ def test_mmu(): comb += l_in.eq(ldst.m_out) comb += ldst.m_in.eq(l_out) + return m, cmpi + + +def test_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(m))) - sim.add_sync_process(wrap(wb_get(cmpi.wb_bus()))) + sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem))) with sim.write_vcd('test_ldst_pi.vcd'): sim.run() +def ldst_sim_misalign(dut): + mmu = dut.submodules.mmu + wbget.stop = False + + yield mmu.rin.prtbl.eq(0x1000000) # set process table + yield + + data, _, _ = yield from pi_ld(dut.submodules.ldst.pi, 0x1007, 8, msr_pr=1) + print ("misalign ld data", data) + + yield + wbget.stop = True + + +def test_misalign_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_misalign(m))) + sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem))) + with sim.write_vcd('test_ldst_pi_misalign.vcd'): + sim.run() + + +def ldst_sim_radixmiss(dut): + mmu = dut.submodules.mmu + wbget.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", data) + + yield + wbget.stop = True + +def ldst_sim_dcache_regression(dut): + mmu = dut.submodules.mmu + wbget.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", data) + assert(data == 0xdeadbeef01234567) + + yield + wbget.stop = True + +def ldst_sim_dcache_random(dut): + mmu = dut.submodules.mmu + pi = dut.submodules.ldst.pi + wbget.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 + wbget.stop = True + +def ldst_sim_dcache_first(dut): # this test is likely to fail + mmu = dut.submodules.mmu + pi = dut.submodules.ldst.pi + wbget.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 + wbget.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 + wbget.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 + wbget.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