Add PteEntry parser to centralize Page Table Entry parsing
authorDaniel Benusovich <flyingmonkeys1996@gmail.com>
Wed, 20 Mar 2019 04:55:46 +0000 (21:55 -0700)
committerDaniel Benusovich <flyingmonkeys1996@gmail.com>
Wed, 20 Mar 2019 04:55:46 +0000 (21:55 -0700)
TLB/src/PteEntry.py [new file with mode: 0644]
TLB/test/test_pte_entry.py [new file with mode: 0644]

diff --git a/TLB/src/PteEntry.py b/TLB/src/PteEntry.py
new file mode 100644 (file)
index 0000000..249251e
--- /dev/null
@@ -0,0 +1,36 @@
+from nmigen import Module, Signal
+from nmigen.cli import main
+
+class PteEntry():
+    def __init__(self, asid_size, pte_size):
+        # Internal
+        self.asid_start = pte_size
+        self.asid_end = pte_size + asid_size
+
+        # Input
+        self.i = Signal(asid_size + pte_size)
+
+        # Output
+        self.d = Signal(1) # Dirty bit (From pte)
+        self.a = Signal(1) # Accessed bit (From pte)
+        self.g = Signal(1) # Global Access (From pte)
+        self.u = Signal(1) # User Mode (From pte)
+        self.xwr = Signal(3) # Execute Read Write (From pte)
+        self.v = Signal(1) # Valid (From pte)
+        self.asid = Signal(asid_size) # Associated Address Space IDentifier
+        self.pte = Signal(pte_size) # Full Page Table Entry
+
+    def elaborate(self, platform=None):
+        m = Module()
+        # Pull out all control bites from PTE
+        m.d.comb += [
+            self.d.eq(self.i[7]),
+            self.a.eq(self.i[6]),
+            self.g.eq(self.i[5]),
+            self.u.eq(self.i[4]),
+            self.xwr.eq(self.i[1:4]),
+            self.v.eq(self.i[0])
+        ]
+        m.d.comb += self.asid.eq(self.i[self.asid_start:self.asid_end])
+        m.d.comb += self.pte.eq(self.i[0:self.asid_start])
+        return m
\ No newline at end of file
diff --git a/TLB/test/test_pte_entry.py b/TLB/test/test_pte_entry.py
new file mode 100644 (file)
index 0000000..3b1c139
--- /dev/null
@@ -0,0 +1,101 @@
+import sys
+sys.path.append("../src")
+sys.path.append("../../TestUtil")
+
+from nmigen.compat.sim import run_simulation
+
+from PteEntry import PteEntry
+
+from test_helper import assert_op
+
+def set_entry(dut, i):
+    yield dut.i.eq(i)
+    yield
+
+def check_dirty(dut, d, op):
+    out_d = yield dut.d
+    assert_op("Dirty", out_d, d, op)
+
+def check_accessed(dut, a, op):
+    out_a = yield dut.a
+    assert_op("Accessed", out_a, a, op)
+
+def check_global(dut, o, op):
+    out = yield dut.g
+    assert_op("Global", out, o, op)
+
+def check_user(dut, o, op):
+    out = yield dut.u
+    assert_op("User Mode", out, o, op)
+
+def check_xwr(dut, o, op):
+    out = yield dut.xwr
+    assert_op("XWR", out, o, op)
+
+def check_asid(dut, o, op):
+    out = yield dut.asid
+    assert_op("ASID", out, o, op)
+
+def check_pte(dut, o, op):
+    out = yield dut.pte
+    assert_op("ASID", out, o, op)
+
+def check_valid(dut, v, op):
+    out_v = yield dut.v
+    assert_op("Valid", out_v, v, op)
+
+def check_all(dut, d, a, g, u, xwr, v, asid, pte):
+    yield from check_dirty(dut, d, 0)
+    yield from check_accessed(dut, a, 0)
+    yield from check_global(dut, g, 0)
+    yield from check_user(dut, u, 0)
+    yield from check_xwr(dut, xwr, 0)
+    yield from check_valid(dut, v, 0)
+
+def testbench(dut):
+    # 80 bits represented. Ignore the MSB as it will be truncated
+    # ASID is bits first 4 hex values (bits 64 - 78)
+
+    i = 0x7FFF0000000000000031
+    dirty = 0
+    access = 0
+    glob = 1
+    user = 1
+    xwr = 0
+    valid = 1
+    asid = 0x7FFF
+    pte = 0x0000000000000031
+    yield from set_entry(dut, i)
+    yield from check_all(dut, dirty, access, glob, user, xwr, valid, asid, pte)
+
+    i = 0x0FFF00000000000000FF
+    dirty = 1
+    access = 1
+    glob = 1
+    user = 1
+    xwr = 7
+    valid = 1
+    asid = 0x0FFF
+    pte = 0x00000000000000FF
+    yield from set_entry(dut, i)
+    yield from check_all(dut, dirty, access, glob, user, xwr, valid, asid, pte)
+
+    i = 0x0721000000001100001F
+    dirty = 0
+    access = 0
+    glob = 0
+    user = 1
+    xwr = 7
+    valid = 1
+    asid = 0x0721
+    pte = 0x00000000110000FF
+    yield from set_entry(dut, i)
+    yield from check_all(dut, dirty, access, glob, user, xwr, valid, asid, pte)
+
+    yield
+
+
+if __name__ == "__main__":
+    dut = PteEntry(15, 64);
+    run_simulation(dut, testbench(dut), vcd_name="Waveforms/test_pte_entry.vcd")
+    print("PteEntry Unit Test Success")
\ No newline at end of file