print("RADIX memread", addr, sz, val)
return SelectableInt(val, sz*8)
- def ld(self, address, width=8, swap=True, check_in_mem=False):
+ def ld(self, address, width=8, swap=True, check_in_mem=False,
+ instr_fetch=False):
print("RADIX: ld from addr 0x%x width %d" % (address, width))
- mode = 'LOAD' # XXX TODO: executable load (icache)
+ priv = 1 # XXX TODO: read MSR PR bit here priv = not ctrl.msr(MSR_PR);
+ if instr_fetch:
+ mode = 'EXECUTE'
+ else:
+ mode = 'LOAD'
addr = SelectableInt(address, 64)
(shift, mbits, pgbase) = self._decode_prte(addr)
#shift = SelectableInt(0, 32)
- pte = self._walk_tree(addr, pgbase, mode, mbits, shift)
+ pte = self._walk_tree(addr, pgbase, mode, mbits, shift, priv)
# use pte to caclculate phys address
return self.mem.ld(address, width, swap, check_in_mem)
def st(self, address, v, width=8, swap=True):
print("RADIX: st to addr 0x%x width %d data %x" % (address, width, v))
+ priv = 1 # XXX TODO: read MSR PR bit here priv = not ctrl.msr(MSR_PR);
mode = 'STORE'
addr = SelectableInt(address, 64)
(shift, mbits, pgbase) = self._decode_prte(addr)
- pte = self._walk_tree(addr, pgbase, mode, mbits, shift)
+ pte = self._walk_tree(addr, pgbase, mode, mbits, shift, priv)
# use pte to caclculate phys address (addr)
return self.mem.st(addr.value, v, width, swap)
## DSISR_NOPTE
## Prepare for next iteration
- def _walk_tree(self, addr, pgbase, mode, mbits, shift):
+ def _walk_tree(self, addr, pgbase, mode, mbits, shift, priv=1):
"""walk tree
// vaddr 64 Bit
check_in_mem = False
entry_width = 8
value = self.mem.ld(prtable_addr.value, entry_width, swap, check_in_mem)
+ data = SelectableInt(value, 64) # convert to SelectableInt
print("value",value)
test_input = [
print("nextlevel----------------------------")
l = test_input[index]
index += 1
- valid,leaf = self._next_level(l)
- if not leaf:
- mbits = l[59:64]
- print("mbits=")
- print(mbits)
- if mbits < 5 or mbits > 16:
- print("badtree")
+ valid, leaf = self._next_level(l)
+ print(" valid, leaf", valid, leaf)
+ if leaf:
+ ok = self._check_perms(data, priv, mode)
+ # TODO: check permissions
+ else:
+ data = l # TODO put actual data here
+ newlookup = self._new_lookup(data, mbits, shift)
+ if newlookup == 'badtree':
return None
- """
- mbits := unsigned('0' & data(4 downto 0));
- if mbits < 5 or mbits > 16 or mbits > r.shift then
- v.state := RADIX_FINISH;
- v.badtree := '1'; -- throw error
- else
- v.shift := v.shift - mbits;
- v.mask_size := mbits(4 downto 0);
- v.pgbase := data(55 downto 8) & x"00"; NLB?
- v.state := RADIX_LOOKUP; --> next level
- end if;
- """
- print(valid)
- print(leaf)
- if not valid: return None
- if leaf: return None
+ shift, mask, pgbase = newlookup
+ print (" next level", shift, mask, pgbase)
+ if not valid:
+ return None # TODO: return error
+ if leaf:
+ return None # TODO return something
+
+ def _new_lookup(self, data, mbits, shift):
+ """
+ mbits := unsigned('0' & data(4 downto 0));
+ if mbits < 5 or mbits > 16 or mbits > r.shift then
+ v.state := RADIX_FINISH;
+ v.badtree := '1'; -- throw error
+ else
+ v.shift := v.shift - mbits;
+ v.mask_size := mbits(4 downto 0);
+ v.pgbase := data(55 downto 8) & x"00"; NLB?
+ v.state := RADIX_LOOKUP; --> next level
+ end if;
+ """
+ mbits = data[59:64]
+ print("mbits=", mbits)
+ if mbits < 5 or mbits > 16:
+ print("badtree")
+ return "badtree"
+ shift = shift - mbits
+ mask_size = mbits[1:5] # get 4 LSBs
+ pgbase = selectconcat(data[8:56], SelectableInt(0, 8)) # shift up 8
+ return shift, mask_size, pgbase
def _decode_prte(self, data):
"""PRTE0 Layout
new_shift = shift + (31 - 12) - mbits
return new_shift
- def _check_perms(self, data, priv, iside, store):
+ def _check_perms(self, data, priv, mode):
"""check page permissions
// Leaf PDE |
// |------------------------------| |----------------|
v.rc_error := perm_ok;
end if;
"""
+ # decode mode into something that matches microwatt equivalent code
+ instr_fetch, store = 0, 0
+ if mode == 'STORE':
+ store = 1
+ if mode == 'EXECUTE':
+ inst_fetch = 1
+
# check permissions and RC bits
perm_ok = 0
if priv == 1 or data[60] == 0:
- if iside == 0:
+ if instr_fetch == 0:
perm_ok = data[62] | (data[61] & (store == 0))
# no IAMR, so no KUEP support for now
# deny execute permission if cache inhibited
rc_ok = data[55] & (data[56] | (store == 0))
if perm_ok == 1 and rc_ok == 1:
return True
+
return "perm_err" if perm_ok == 0 else "rc_err"
def _get_prtable_addr(self, shift, prtbl, addr, pid):