import unittest
from soc.config.test.test_loadstore import TestMemPspec
from soc.config.loadstore import ConfigMemoryPortInterface
+from openpower.exceptions import LDSTExceptionTuple
def wait_busy(port, no=False, debug=None):
cnt = 0
while True:
addr_ok = yield port.addr_ok_o
- print("addrok", addr_ok,cnt,debug)
- if addr_ok:
+ exc_happened = yield port.exc_o.happened
+ print("addrok", addr_ok,cnt,debug,exc_happened)
+ if addr_ok or exc_happened:
break
yield
cnt += 1
yield port1.is_dcbz_i.eq(is_dcbz) # reset dcbz too
yield port1.is_st_i.eq(1) # indicate ST
yield port1.data_len.eq(datalen) # ST length (1/2/4/8)
- yield port1.msr_pr.eq(msr_pr) # MSR PR bit (1==>virt, 0==>real)
+ yield port1.priv_mode.eq(~msr_pr) # MSR PR bit (1==>virt, 0==>real)
yield port1.addr.data.eq(addr) # set address
yield port1.addr.ok.eq(1) # set ok
yield Settle()
+
+ # must check exception even before waiting for address.
+ # XXX TODO: wait_addr should check for exception
+ exc_info = yield from get_exception_info(port1.exc_o)
+ exc_happened = exc_info.happened
+ if exc_happened:
+ print("print fast ST exception happened")
+ yield # MUST wait for one clock cycle before de-asserting these
+ yield port1.is_st_i.eq(0) # end
+ yield port1.addr.ok.eq(0) # set !ok
+ yield port1.is_dcbz_i.eq(0) # reset dcbz too
+ return "fast", exc_info
+
yield from wait_addr(port1) # wait until addr ok
- yield from wait_addr(port1) # wait until addr ok
+
+ exc_info = yield from get_exception_info(port1.exc_o)
+ exc_happened = exc_info.happened
+ if exc_happened:
+ print("print fast ST exception happened")
+ yield # MUST wait for one clock cycle before de-asserting these
+ yield port1.is_st_i.eq(0) # end
+ yield port1.addr.ok.eq(0) # set !ok
+ yield port1.is_dcbz_i.eq(0) # reset dcbz too
+ return "fast", exc_info
+
# yield # not needed, just for checking
# yield # not needed, just for checking
yield port1.st.ok.eq(1)
yield
yield port1.st.ok.eq(0)
- exc_happened = yield port1.exc_o.happened
+ exc_info = yield from get_exception_info(port1.exc_o)
+ exc_happened = exc_info.happened
if exc_happened:
- print("print fast exception happened")
+ print("print fast ST exception happened")
+ yield # MUST wait for one clock cycle before de-asserting these
yield port1.is_st_i.eq(0) # end
yield port1.addr.ok.eq(0) # set !ok
yield port1.is_dcbz_i.eq(0) # reset dcbz too
- return "fast"
+ return "fast", exc_info
+
yield from wait_busy(port1,debug="pi_st_E") # wait while busy
+ exc_info = yield from get_exception_info(port1.exc_o)
+ exc_happened = exc_info.happened
+ if exc_happened:
+ yield # needed if mmu/dache is used
+ yield port1.is_st_i.eq(0) # end
+ yield port1.addr.ok.eq(0) # set !ok
+ yield port1.is_dcbz_i.eq(0) # reset dcbz too
+ yield # needed if mmu/dache is used
+ return "slow", exc_info
# can go straight to reset.
yield port1.is_st_i.eq(0) # end
yield port1.addr.ok.eq(0) # set !ok
yield port1.is_dcbz_i.eq(0) # reset dcbz too
-
- return None
+ yield # needed if mmu/dache is used
+
+ return None, None
+
+def get_exception_info(exc_o):
+ attrs = []
+ for fname in LDSTExceptionTuple._fields:
+ attr = getattr(exc_o, fname)
+ val = yield attr
+ attrs.append(val)
+ return LDSTExceptionTuple(*attrs)
# copy of pi_st removed
# set up a LD on the port. address first:
yield port1.is_ld_i.eq(1) # indicate LD
yield port1.data_len.eq(datalen) # LD length (1/2/4/8)
- yield port1.msr_pr.eq(msr_pr) # MSR PR bit (1==>virt, 0==>real)
+ yield port1.priv_mode.eq(~msr_pr) # MSR PR bit (1==>virt, 0==>real)
yield port1.addr.data.eq(addr) # set address
yield port1.addr.ok.eq(1) # set ok
yield Settle()
yield from wait_addr(port1) # wait until addr ok
- exc_happened = yield port1.exc_o.happened
+ exc_info = yield from get_exception_info(port1.exc_o)
+ exc_happened = exc_info.happened
if exc_happened:
- print("print fast exception happened")
+ print("print fast LD exception happened")
+ yield # MUST wait for one clock cycle before de-asserting these
yield port1.is_ld_i.eq(0) # end
yield port1.addr.ok.eq(0) # set !ok
- return 0, "fast"
+ return None, "fast", exc_info
yield
yield from wait_ldok(port1) # wait until ld ok
data = yield port1.ld.data
+ exc_info = yield from get_exception_info(port1.exc_o)
exc_happened = yield port1.exc_o.happened
+ exc_happened = exc_info.happened
# cleanup
yield port1.is_ld_i.eq(0) # end
yield port1.addr.ok.eq(0) # set !ok
if exc_happened:
- return 0, "slow"
+ return None, "slow", exc_info
+
+ yield from wait_busy(port1, debug="pi_ld_E") # wait while busy
- yield from wait_busy(port1,debug="pi_ld_E") # wait while busy
+ exc_info = yield from get_exception_info(port1.exc_o)
+ exc_happened = exc_info.happened
+ if exc_happened:
+ return None, "slow", exc_info
- return data, None
+ return data, None, None
def pi_ldst(arg, dut, msr_pr=0):