from nmigen.compat.sim import run_simulation
from random import random
-from openpower.test.wb_get import wb_get
+from openpower.test.wb_get import wb_get_classic
from openpower.test import wb_get as wbget
from openpower.exceptions import LDSTExceptionTuple
+from soc.config.test.test_fetch import read_from_addr
+from openpower.decoder.power_enums import MSRSpec
+
def setup_mmu():
icache = dut.submodules.ldst.icache
wbget.stop = False
-
print("=== test loadstore instruction (real) ===")
i_in = icache.i_in
i_m_in = icache.m_in
yield from debug(dut, "real mem instruction")
- # set address to zero, update mem[0] to 01234
+ # set address to 0x8, update mem[0x8] to 01234 | 0x5678<<32
+ # (have to do 64-bit writes into the dictionary-memory-emulated-thing)
addr = 8
+ addr2 = 12
+ expected_insn2 = 0x5678
expected_insn = 0x1234
- mem[addr] = expected_insn
+ mem[addr] = expected_insn | expected_insn2<<32
yield i_in.priv_mode.eq(1)
- yield i_in.req.eq(0) # NO, must use FetchUnitInterface
- yield i_in.nia.eq(addr) # NO, must use FetchUnitInterface
- yield i_in.stop_mark.eq(0) # NO, must use FetchUnitInterface
- yield i_m_in.tlbld.eq(0)
- yield i_m_in.tlbie.eq(0)
- yield i_m_in.addr.eq(0)
- yield i_m_in.pte.eq(0)
- yield
- yield
- yield
+ insn = yield from read_from_addr(icache, addr, stall=False)
- # miss, stalls for a bit -- this one is different here
- ##nia, insn, valid, failed = yield from icache_read(dut,addr,0,0)
- ##assert(valid==0)
- ##assert(failed==1)
+ nia = yield i_out.nia # NO, must use FetchUnitInterface
+ print ("fetched %x from addr %x" % (insn, nia))
+ assert insn == expected_insn
- yield i_in.req.eq(1) # NO, must use FetchUnitInterface
- yield i_in.nia.eq(addr) # NO, must use FetchUnitInterface
- yield
- valid = yield i_out.valid # NO, must use FetchUnitInterface
- while not valid: # NO, must use FetchUnitInterface
- yield # NO, must use FetchUnitInterface
- valid = yield i_out.valid # NO, must use FetchUnitInterface
- yield i_in.req.eq(0) # NO, must use FetchUnitInterface
+ print("=== test loadstore instruction (2nd, real) ===")
+ yield from debug(dut, "real mem 2nd (addr 0xc)")
+
+ insn2 = yield from read_from_addr(icache, addr2, stall=False)
nia = yield i_out.nia # NO, must use FetchUnitInterface
- insn = yield i_out.insn # NO, must use FetchUnitInterface
+ print ("fetched %x from addr2 %x" % (insn2, nia))
+ assert insn2 == expected_insn2
+
+ print("=== test loadstore instruction (done) ===")
+
+ yield from debug(dut, "test done")
yield
yield
print ("fetched %x from addr %x" % (insn, nia))
assert insn == expected_insn
- print("=== test loadstore instruction (done) ===")
+ wbget.stop = True
- yield from debug(dut, "test done")
+
+def write_mem2(mem, addr, i1, i2):
+ mem[addr] = i1 | i2<<32
+
+
+#TODO: use fetch interface here
+def lookup_virt(dut,addr):
+ icache = dut.submodules.ldst.icache
+ i_in = icache.i_in
+ i_out = icache.i_out
+ yield i_in.priv_mode.eq(0)
+ yield i_in.virt_mode.eq(1)
+ yield i_in.req.eq(0)
+ yield i_in.stop_mark.eq(0)
+
+ yield icache.a_i_valid.eq(1)
+ yield icache.a_pc_i.eq(addr)
+ yield
+ valid = yield i_out.valid
+ failed = yield i_out.fetch_failed
+ while not valid and not failed:
+ yield
+ valid = yield i_out.valid
+ failed = yield i_out.fetch_failed
+ yield icache.a_i_valid.eq(0)
+
+ return valid,failed
+
+
+def mmu_lookup(dut,addr):
+ ldst = dut.submodules.ldst
+ pi = ldst.pi
+ yield from debug(dut, "instr fault "+hex(addr))
+ yield ldst.priv_mode.eq(0)
+ yield ldst.instr_fault.eq(1)
+ yield ldst.maddr.eq(addr)
+ yield
+ yield ldst.instr_fault.eq(0)
+ while True:
+ done = yield (ldst.done)
+ exc_info = yield from get_exception_info(pi.exc_o)
+ if done or exc_info.happened:
+ break
+ yield
+ yield
+ assert exc_info.happened == 0 # assert just before doing the fault set zero
+ yield ldst.instr_fault.eq(0)
+ yield from debug(dut, "instr fault done "+hex(addr))
+ yield
yield
yield
- print ("failed?", "yes" if failed else "no")
- assert failed == 0
- print ("fetched %x from addr %x" % (insn, nia))
- assert insn == expected_insn
+def _test_loadstore1_ifetch_multi(dut, mem):
+ mmu = dut.submodules.mmu
+ ldst = dut.submodules.ldst
+ pi = ldst.pi
+ icache = dut.submodules.ldst.icache
+ assert wbget.stop == False
+
+ print ("set process table")
+ yield from debug(dut, "set prtble")
+ yield mmu.rin.prtbl.eq(0x1000000) # set process table
+ yield
+
+ i_in = icache.i_in
+ i_out = icache.i_out
+ i_m_in = icache.m_in
+
+ # fetch instructions from multiple addresses
+ # should cope with some addresses being invalid
+ real_addrs = [0,4,8,0,8,4,0,0,12]
+ write_mem2(mem,0,0xF0,0xF4)
+ write_mem2(mem,8,0xF8,0xFC)
+
+ yield i_in.priv_mode.eq(1)
+ for addr in real_addrs:
+ yield from debug(dut, "real_addr "+hex(addr))
+ insn = yield from read_from_addr(icache, addr, stall=False)
+ nia = yield i_out.nia # NO, must use FetchUnitInterface
+ print ("TEST_MULTI: fetched %x from addr %x == %x" % (insn, nia,addr))
+ assert insn==0xF0+addr
+
+ # now with virtual memory enabled
+ yield i_in.virt_mode.eq(1)
+
+ virt_addrs = [0x10200,0x10204,0x10208,0x10200,
+ 0x102008,0x10204,0x10200,0x10200,0x10200C]
+
+ write_mem2(mem,0x10200,0xF8,0xFC)
+
+ for addr in virt_addrs:
+ yield from debug(dut, "virt_addr "+hex(addr))
+
+ valid, failed = yield from lookup_virt(dut,addr)
+ yield
+ print("TEST_MULTI: failed=",failed) # this is reported wrong
+ if failed==1: # test one first
+ yield from mmu_lookup(dut,addr)
+ valid, failed = yield from lookup_virt(dut,addr)
+ assert(valid==1)
wbget.stop = True
yield ldst.priv_mode.eq(0)
yield ldst.instr_fault.eq(1)
yield ldst.maddr.eq(virt_addr)
- #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr_pr=1)
+ # still broken -- investigate
+ # msr = MSRSpec(pr=?, dr=?, sf=0)
+ # ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr=msr)
yield
yield ldst.instr_fault.eq(0)
while True:
print("=== test invalid ===")
addr = 0
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ msr = MSRSpec(pr=1, dr=0, sf=0) # set problem-state
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
print("ld_data", ld_data, exctype, exc)
assert (exctype == "slow")
invalid = exc.invalid
wbget.stop = True
+def _test_loadstore1_microwatt_mmu_bin_test2(dut, mem):
+ mmu = dut.submodules.mmu
+ pi = dut.submodules.ldst.pi
+ ldst = dut.submodules.ldst # to get at DAR (NOT part of PortInterface)
+ wbget.stop = False
+
+ yield mmu.rin.prtbl.eq(0x12000) # set process table
+ yield mmu.rin.pid.eq(0x1) # set PID=1
+ yield
+
+ addr = 0x124108
+ msr = MSRSpec(pr=1, dr=1, sf=1)
+
+ print("=== alignment error (ld) ===")
+
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
+ print("ld_data after mmu.bin test2")
+ print(ld_data)
+ assert ld_data == 0x0000000badc0ffee
+ assert exctype is None
+
+ wbget.stop = True
+
+
+def _test_loadstore1_microwatt_mmu_bin_test5(dut, mem):
+ mmu = dut.submodules.mmu
+ pi = dut.submodules.ldst.pi
+ ldst = dut.submodules.ldst # to get at DAR (NOT part of PortInterface)
+ wbget.stop = False
+
+ yield mmu.rin.prtbl.eq(0x12000) # set process table
+ yield mmu.rin.pid.eq(0x1) # set PID=1
+ yield
+
+ addr = 0x39fffd
+ msr = MSRSpec(pr=1, dr=1, sf=1)
+
+ print("=== page-fault alignment error (ld) ===")
+
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
+ print("ld_data after mmu.bin test5")
+ print(ld_data)
+ print (exctype, exc)
+
+ wbget.stop = True
+
+
+def test_pi_ld_misalign(pi, addr, data_len, msr):
+ for i in range(0,data_len):
+ ld_data, exctype, exc = yield from pi_ld(pi, addr+i, data_len, msr=msr)
+ yield
+ assert exc is None # use "is None" not "== None"
+ print("MISALIGN: test_pi_ld_misalign returned",hex(ld_data))
+
+
+def test_pi_st_ld_misalign(pi, addr, data_len, msr):
+ data = 0x0102030405060708
+ for i in range(0, data_len):
+ exctype, exc = yield from pi_st(pi, addr+i, data, data_len, msr=msr)
+ print (exctype, exc)
+ assert exc is None # use "is None" not "== None"
+ ld_data, exctype, exc = yield from pi_ld(pi, addr+i, data_len, msr=msr)
+ yield
+ assert exc is None # use "is None" not "== None"
+ print("MISALIGN: test_pi_ld_misalign returned",hex(ld_data))
+ assert ld_data == data
+
+
+def _test_loadstore1_misalign(dut, mem):
+ mmu = dut.submodules.mmu
+ pi = dut.submodules.ldst.pi
+ ldst = dut.submodules.ldst # to get at DAR (NOT part of PortInterface)
+ wbget.stop = False
+
+ yield mmu.rin.prtbl.eq(0x12000) # set process table
+ yield mmu.rin.pid.eq(0x1) # set PID=1
+ #yield
+
+ addr = 1
+ msr = MSRSpec(pr=0, dr=0, sf=1)
+
+ yield from test_pi_ld_misalign(pi,0,8,msr)
+
+ yield from test_pi_st_ld_misalign(pi,0,8,msr)
+
+ wbget.stop = True
+
+
def _test_loadstore1(dut, mem):
mmu = dut.submodules.mmu
pi = dut.submodules.ldst.pi
addr = 0x100e0
data = 0xf553b658ba7e1f51
+ msr = MSRSpec(pr=0, dr=0, sf=0)
if test_dcbz:
- yield from pi_st(pi, addr, data, 8, msr_pr=1)
+ yield from pi_st(pi, addr, data, 8, msr=msr)
yield
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
assert ld_data == 0xf553b658ba7e1f51
assert exctype is None
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
assert ld_data == 0xf553b658ba7e1f51
assert exctype is None
print("do_dcbz ===============")
- yield from pi_st(pi, addr, data, 8, msr_pr=1, is_dcbz=1)
+ yield from pi_st(pi, addr, data, 8, msr=msr, is_dcbz=1)
print("done_dcbz ===============")
yield
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
print("ld_data after dcbz")
print(ld_data)
assert ld_data == 0
if test_exceptions:
print("=== alignment error (ld) ===")
addr = 0xFF100e0FF
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
if exc:
alignment = exc.alignment
happened = exc.happened
print("=== alignment error (st) ===")
addr = 0xFF100e0FF
- exctype, exc = yield from pi_st(pi, addr,0, 8, msr_pr=1)
+ exctype, exc = yield from pi_st(pi, addr,0, 8, msr=msr)
if exc:
alignment = exc.alignment
happened = exc.happened
if True:
print("=== no alignment error (ld) ===")
addr = 0x100e0
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
print("ld_data", ld_data, exctype, exc)
if exc:
alignment = exc.alignment
for addr in addrs:
print("== RANDOM addr ==",hex(addr))
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
print("ld_data[RANDOM]",ld_data,exc,addr)
assert (exctype == None)
for addr in addrs:
print("== RANDOM addr ==",hex(addr))
- exc = yield from pi_st(pi, addr,0xFF*addr, 8, msr_pr=1)
+ exc = yield from pi_st(pi, addr,0xFF*addr, 8, msr=msr)
assert (exctype == None)
# readback written data and compare
for addr in addrs:
print("== RANDOM addr ==",hex(addr))
- ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
+ ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr=msr)
print("ld_data[RANDOM_READBACK]",ld_data,exc,addr)
assert (exctype == None)
assert (ld_data == 0xFF*addr)
yield ldst.priv_mode.eq(0)
yield ldst.instr_fault.eq(1)
yield ldst.maddr.eq(virt_addr)
- #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr_pr=1)
+ #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr=msr)
yield
yield ldst.instr_fault.eq(0)
while True:
mem = pagetables.test1
- # nmigen Simulation
- sim = Simulator(m)
- sim.add_clock(1e-6)
-
+ # set this up before passing to Simulator (which calls elaborate)
icache = m.submodules.ldst.icache
icache.use_fetch_interface() # this is the function which converts
# to FetchUnitInterface. *including*
# rewiring the Wishbone Bus to ibus
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
sim.add_sync_process(wrap(_test_loadstore1_ifetch_iface(m, mem)))
- # add two wb_get processes onto the *same* memory dictionary.
+ # add two wb_get_classic processes onto the *same* memory dictionary.
# this shouuuld work.... cross-fingers...
- sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
- sim.add_sync_process(wrap(wb_get(icache.ibus, mem))) # ibus not bus
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
+ sim.add_sync_process(wrap(wb_get_classic(icache.ibus, mem))) # ibus not bus
with sim.write_vcd('test_loadstore1_ifetch_iface.vcd',
traces=[m.debug_status]): # include extra debug
sim.run()
icache = m.submodules.ldst.icache
sim.add_sync_process(wrap(_test_loadstore1_ifetch(m, mem)))
- # add two wb_get processes onto the *same* memory dictionary.
+ # add two wb_get_classic processes onto the *same* memory dictionary.
# this shouuuld work.... cross-fingers...
- sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
- sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
+ sim.add_sync_process(wrap(wb_get_classic(icache.bus, mem)))
with sim.write_vcd('test_loadstore1_ifetch.vcd',
traces=[m.debug_status]): # include extra debug
sim.run()
sim.add_clock(1e-6)
sim.add_sync_process(wrap(_test_loadstore1(m, mem)))
- sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
with sim.write_vcd('test_loadstore1.vcd'):
sim.run()
+def test_loadstore1_microwatt_mmu_bin_test2():
+
+ m, cmpi = setup_mmu()
+
+ mem = pagetables.microwatt_test2
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(_test_loadstore1_microwatt_mmu_bin_test2(m, mem)))
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_microwatt_mmu_test2.vcd'):
+ sim.run()
+
+
+def test_loadstore1_microwatt_mmu_bin_test5():
+
+ m, cmpi = setup_mmu()
+
+ mem = pagetables.microwatt_test5
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(_test_loadstore1_microwatt_mmu_bin_test5(m, mem)))
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_microwatt_mmu_test5.vcd'):
+ sim.run()
+
+
+def test_loadstore1_misalign():
+
+ m, cmpi = setup_mmu()
+
+ mem = pagetables.microwatt_test2
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ ###########1122334455667788
+ mem[0] = 0x0102030405060708
+ mem[8] = 0xffffffffffffffff
+
+ sim.add_sync_process(wrap(_test_loadstore1_misalign(m, mem)))
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
+ with sim.write_vcd('test_loadstore1_misalign.vcd'):
+ sim.run()
+ print ("mem", mem)
+
+
def test_loadstore1_invalid():
m, cmpi = setup_mmu()
sim.add_clock(1e-6)
sim.add_sync_process(wrap(_test_loadstore1_invalid(m, mem)))
- sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
with sim.write_vcd('test_loadstore1_invalid.vcd'):
sim.run()
+
def test_loadstore1_ifetch_invalid():
m, cmpi = setup_mmu()
icache = m.submodules.ldst.icache
sim.add_sync_process(wrap(_test_loadstore1_ifetch_invalid(m, mem)))
- # add two wb_get processes onto the *same* memory dictionary.
+ # add two wb_get_classic processes onto the *same* memory dictionary.
# this shouuuld work.... cross-fingers...
- sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
- sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
+ sim.add_sync_process(wrap(wb_get_classic(icache.bus, mem)))
with sim.write_vcd('test_loadstore1_ifetch_invalid.vcd',
traces=[m.debug_status]): # include extra debug
sim.run()
+def test_loadstore1_ifetch_multi():
+ m, cmpi = setup_mmu()
+ wbget.stop = False
+
+ # this is a specially-arranged page table which has the permissions
+ # barred for execute on the leaf node (EAA=0x2 instead of EAA=0x3)
+ mem = pagetables.test1
-if __name__ == '__main__':
- test_loadstore1()
- test_loadstore1_invalid()
- test_loadstore1_ifetch()
- test_loadstore1_fetch_unit_iface()
- test_loadstore1_ifetch_invalid()
+ # set this up before passing to Simulator (which calls elaborate)
+ icache = m.submodules.ldst.icache
+ icache.use_fetch_interface() # this is the function which converts
+ # to FetchUnitInterface. *including*
+ # rewiring the Wishbone Bus to ibus
+
+ # nmigen Simulation
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ sim.add_sync_process(wrap(_test_loadstore1_ifetch_multi(m, mem)))
+ # add two wb_get_classic processes onto the *same* memory dictionary.
+ # this shouuuld work.... cross-fingers...
+ sim.add_sync_process(wrap(wb_get_classic(cmpi.wb_bus(), mem)))
+ sim.add_sync_process(wrap(wb_get_classic(icache.ibus, mem))) # ibus not bus
+ with sim.write_vcd('test_loadstore1_ifetch_multi.vcd',
+ traces=[m.debug_status]): # include extra debug
+ sim.run()
+if __name__ == '__main__':
+ #test_loadstore1()
+ #test_loadstore1_microwatt_mmu_bin_test2()
+ #test_loadstore1_microwatt_mmu_bin_test5()
+ #test_loadstore1_invalid()
+ #test_loadstore1_ifetch() #FIXME
+ #test_loadstore1_ifetch_invalid()
+ #test_loadstore1_ifetch_unit_iface() # guess: should be working
+ #test_loadstore1_ifetch_multi()
+ test_loadstore1_misalign()