debug radix mmu ISACaller
[soc.git] / src / soc / decoder / isa / radixmmu.py
index 31520694adcf0d0b4d50f59d17a485fb63809fa6..0f092612d265ba5fe58b538123f924a66cc12cb5 100644 (file)
@@ -18,6 +18,7 @@ from copy import copy
 from soc.decoder.selectable_int import (FieldSelectableInt, SelectableInt,
                                         selectconcat)
 from soc.decoder.helpers import exts, gtu, ltu, undefined
+from soc.decoder.isa.mem import Mem
 
 import math
 import sys
@@ -168,6 +169,7 @@ class RADIX:
     def __init__(self, mem, caller):
         self.mem = mem
         self.caller = caller
+        #TODO move to lookup
         self.dsisr = self.caller.spr["DSISR"]
         self.dar   = self.caller.spr["DAR"]
         self.pidr  = self.caller.spr["PIDR"]
@@ -179,11 +181,10 @@ class RADIX:
         self.pgtbl3 = 0
         self.pt3_valid = False
 
-    def __call__(self,*args, **kwargs):
-        print("TODO: implement RADIX.__call__()")
-        print(args)
-        print(kwargs)
-        return None
+    def __call__(self, addr, sz):
+        val = self.ld(addr.value, sz, swap=False)
+        print("RADIX memread", addr, sz, val)
+        return SelectableInt(val, sz*8)
 
     def ld(self, address, width=8, swap=True, check_in_mem=False):
         print("RADIX: ld from addr 0x%x width %d" % (address, width))
@@ -281,6 +282,15 @@ class RADIX:
         //           Authority
         //
         """
+        # get sprs
+        print("_walk_tree")
+        pidr  = self.caller.spr["PIDR"]
+        prtbl = self.caller.spr["PRTBL"]
+        print(pidr)
+        print(prtbl)
+
+        # TODO read root entry from process table first
+
         # walk tree starts on prtbl
         while True:
             ret = self._next_level()
@@ -337,10 +347,30 @@ class RADIX:
         new_shift = shift + (31 - 12) - mbits
         return new_shift
 
-    def _check_perms(self):
+    def _check_perms(self, data, priv, iside, store):
         """check page permissions
+        // Leaf PDE                                           |
+        // |------------------------------|           |----------------|
+        // |V|L|sw|//|RPN|sw|R|C|/|ATT|EAA|           | usefulBits     |
+        // |------------------------------|           |----------------|
+        // [0] = V = Valid Bit                                 |
+        // [1] = L = Leaf Bit = 1 if leaf                      |
+        //                      PDE                            |
+        // [2] = Sw = Sw bit 0.                                |
+        // [7:51] = RPN = Real Page Number,                    V
+        //          real_page = RPN << 12 ------------->  Logical OR
+        // [52:54] = Sw Bits 1:3                               |
+        // [55] = R = Reference                                |
+        // [56] = C = Change                                   V
+        // [58:59] = Att =                                Physical Address
+        //           0b00 = Normal Memory
+        //           0b01 = SAO
+        //           0b10 = Non Idenmpotent
+        //           0b11 = Tolerant I/O
+        // [60:63] = Encoded Access
+        //           Authority
+        //
                     -- test leaf bit
-                    if data(62) = '1' then
                         -- check permissions and RC bits
                         perm_ok := '0';
                         if r.priv = '1' or data(3) = '0' then
@@ -362,6 +392,18 @@ class RADIX:
                             v.rc_error := perm_ok;
                         end if;
         """
+        # check permissions and RC bits
+        perm_ok = 0
+        if priv == 1 or data[60] == 0:
+            if iside == 0:
+                perm_ok = data[62] | (data[61] & (store == 0))
+            # no IAMR, so no KUEP support for now
+            # deny execute permission if cache inhibited
+            perm_ok = data[63] & ~data[58]
+        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):
         """
@@ -428,12 +470,22 @@ class RADIX:
 
 # very quick test of maskgen function (TODO, move to util later)
 if __name__ == '__main__':
+    # set up dummy minimal ISACaller
+    spr = {'DSISR': SelectableInt(0, 64),
+           'DAR': SelectableInt(0, 64),
+           'PIDR': SelectableInt(0, 64),
+           'PRTBL': SelectableInt(0, 64)
+    }
+    class ISACaller: pass
+    caller = ISACaller()
+    caller.spr = spr
+
     shift = SelectableInt(5, 6)
     mask = genmask(shift, 43)
     print ("    mask", bin(mask.value))
 
     mem = Mem(row_bytes=8)
-    mem = RADIX(mem, None)
+    mem = RADIX(mem, caller)
     # -----------------------------------------------
     # |/|RTS1|/|     RPDB          | RTS2 |  RPDS   |
     # -----------------------------------------------