+++ /dev/null
-from nmigen import Memory, Module, Signal
-from nmigen.cli import main
-from math import log
-
-# The purpose of this module is to search a memory block given an
-# associativity.
-# This module will attempt to find a matching entry when given an address
-# and perform permission validation if successful.
-#
-# Arguments:
-# data_size: (bit count) The size of the data words being processed
-# assoc: (int) The associativity of the memory to be parsed
-# mem: (nmigen.Memory) The memory to be parsed
-#
-# Return:
-# 1. An entry was found -> Return PTE, set hit HIGH, set valid HIGH
-# 2. An entry was NOT found -> set hit LOW, set valid HIGH
-# 3. A permission fault occurs -> set hit LOW, set valid LOW
-class CacheWalker():
- def __init__(self, data_size, assoc, mem):
- # Parameter parsing
- self.assoc = assoc # Assciativity of the cache
-
- self.read_port = mem.read_port
- self.write_port = mem.write_port
-
- if (mem_size % assoc != 0):
- print("Cache Walker: Memory cannot be distributed between sets")
-
- self.set_count = mem.depth / assoc # Number of sets in memory
- self.set_bit_count = log(set_count, 2) # Bit count for sets
- # Ensure set_bit_count is fully represented
- if(set_count % 2 != 0):
- set_bit_count += 1
-
- self.assoc_bits = Signal(set_bit_count) # Bits for associativity
-
- # Inputs
- self.vma = Signal(36) # Virtual Memory Address (VMA)
-
- # Output
- self.hit = Signal(1) # Denotes if the VMA had a mapped PTE
- self.pte = Signal(64) # PTE that was mapped to by the VMA
- self.valid = Signal(1) # Denotes if the permissions are correct
\ No newline at end of file
+++ /dev/null
-from nmigen import Signal
-from nmigen.cli import main
-
-# The purpose of this Module is to check the Permissions of a given PTE
-# against the requested access permissions.
-# This module will either validate (by setting the valid bit HIGH) the request
-# or find a permission fault and invalidate (by setting the valid bit LOW)
-# the request
-#
-# Arguments:
-# data_size: (bit count) The size of the data words being processed
-#
-# Return:
-# 1. Data is valid -> valid is HIGH
-# 2. Data is not valid -> valid is LOW
-class PermissionValidator():
- def __init__(self, data_size):
- # Input
- self.data = Signal(data_size);
- self.xwr = Signal(3) # Execute, Write, Read
- self.super = Signal(1) # Supervisor Mode
- self.super_access = Signal(1) # Supervisor Access
- self.asid = Signal(15) # Address Space IDentifier (ASID)
-
- # Output
- self.valid = Signal(1) # Denotes if the permissions are correct
-
- def elaborate(self, platform):
- m = Module()
- m.d.comb += [
- # Check if ASID matches OR entry is global
- If(data[64:78] == self.asid or data[5] == 1,
- # Check Execute, Write, Read (XWR) Permissions
- If(data[3] == self.xwr[2] and data[2] == self.xwr[1] \
- and data[1] == self.xwr[0],
- # Check if supervisor
- If(self.super == 1,
- # Check if entry is in user mode
- # Check if supervisor has access
- If(data[4] == 0,
- self.valid.eq(1)
- ).Elif(self.super_access == 1,
- self.valid.eq(1)
- ).Else(
- self.valid.eq(0)
- )
- ).Else(
- # Check if entry is in user mode
- If(data[4] == 1,
- self.valid.eq(1)
- ).Else(
- self.valid.eq(0)
- )
- )
- ).Else(
- self.valid.eq(0)
- )
- ).Else(
- self.valid.eq(0)
- )
- ]
+++ /dev/null
-from nmigen import Memory, Module, Signal
-from nmigen.cli import main
-
-from PermissionValidator import PermissionValidator
-
-# The expected form of the data is
-# Item (Bits)
-# Tag (N - 79) / ASID (78 - 64) / PTE (63 - 0)
-
-class TLB():
- def __init__(self):
- # Inputs
- self.super = Signal(1) # Supervisor Mode
- self.super_access = Signal(1) # Supervisor Access
- self.command = Signal(2) # 00=None, 01=Search, 10=Write PTE, 11=Reset
- self.xwr = Signal(3) # Execute, Write, Read
- self.mode = Signal(4) # 4 bits for access to Sv48 on Rv64
- self.asid = Signal(15) # Address Space IDentifier (ASID)
- self.vma = Signal(36) # Virtual Memory Address (VMA)
- self.pte_in = Signal(64) # To be saved Page Table Entry (PTE)
-
- # Outputs
- self.hit = Signal(1) # Denotes if the VMA had a mapped PTE
- self.valid = Signal(1) # Denotes if the permissions are correct
- self.pteOut = Signal(64) # PTE that was mapped to by the VMA
-
- # Cam simulations
- mem_l1 = Memory(113, 32) # L1 TLB cache
- read_port_l1 = mem_l1.read_port
- write_port_l1 = mem_l1.write_port
-
- mem_l2 = Memory(113, 128) # L2 TLB cache
- read_port_l2 = mem_l2.read_port
- write_port_l2 = mem_l2.write_port
-
- def elaborate(self, platform):
- m = Module()
- m.d.submodules.perm_valid = perm_valid = PermissionValidator(113)
- m.d.sync += [
- Case(self.command, {
- # Search for PTE
- 1: [
- # Check first entry in set
- # TODO make module?
- read_port_l1.addr.eq(vma[0,2]),
- If(read_port_l1.data[0] == 1,
- perm_valid.data.eq(read_port_l1.data),
- perm_valid.xwr.eq(self.xwr),
- perm_valid.super.eq(self.super),
- perm_valid.super_access.eq(self.super_access),
- perm_valid.asid.eq(self.asid),
- self.valid,eq(perm_valid.valid)
- ),
- If(self.valid == 0,
- read_port_l1.addr.eq(vma[0,2] + 1),
- If(read_port_l1.data[0] == 1,
- perm_valid.data.eq(read_port_l1.data),
- perm_valid.xwr.eq(self.xwr),
- perm_valid.super.eq(self.super),
- perm_valid.super_access.eq(self.super_access),
- perm_valid.asid.eq(self.asid),
- self.valid,eq(perm_valid.valid)
- )
- )
- ]
- })
- ]
- return m
-
-thing = TLB()
-print("Gottem")
-
--- /dev/null
+from nmigen import Memory, Module, Signal
+from nmigen.cli import main
+from math import log
+
+# The purpose of this module is to search a memory block given an
+# associativity.
+# This module will attempt to find a matching entry when given an address
+# and perform permission validation if successful.
+#
+# Arguments:
+# data_size: (bit count) The size of the data words being processed
+# assoc: (int) The associativity of the memory to be parsed
+# mem: (nmigen.Memory) The memory to be parsed
+#
+# Return:
+# 1. An entry was found -> Return PTE, set hit HIGH, set valid HIGH
+# 2. An entry was NOT found -> set hit LOW, set valid HIGH
+# 3. A permission fault occurs -> set hit LOW, set valid LOW
+class CacheWalker():
+ def __init__(self, data_size, assoc, mem):
+ # Parameter parsing
+ self.assoc = assoc # Assciativity of the cache
+
+ self.read_port = mem.read_port
+ self.write_port = mem.write_port
+
+ if (mem_size % assoc != 0):
+ print("Cache Walker: Memory cannot be distributed between sets")
+
+ self.set_count = mem.depth / assoc # Number of sets in memory
+ self.set_bit_count = log(set_count, 2) # Bit count for sets
+ # Ensure set_bit_count is fully represented
+ if(set_count % 2 != 0):
+ set_bit_count += 1
+
+ self.assoc_bits = Signal(set_bit_count) # Bits for associativity
+
+ # Inputs
+ self.vma = Signal(36) # Virtual Memory Address (VMA)
+
+ # Output
+ self.hit = Signal(1) # Denotes if the VMA had a mapped PTE
+ self.pte = Signal(64) # PTE that was mapped to by the VMA
+ self.valid = Signal(1) # Denotes if the permissions are correct
\ No newline at end of file
--- /dev/null
+from nmigen import Signal
+from nmigen.cli import main
+
+# The purpose of this Module is to check the Permissions of a given PTE
+# against the requested access permissions.
+# This module will either validate (by setting the valid bit HIGH) the request
+# or find a permission fault and invalidate (by setting the valid bit LOW)
+# the request
+#
+# Arguments:
+# data_size: (bit count) The size of the data words being processed
+#
+# Return:
+# 1. Data is valid -> valid is HIGH
+# 2. Data is not valid -> valid is LOW
+class PermissionValidator():
+ def __init__(self, data_size):
+ # Input
+ self.data = Signal(data_size);
+ self.xwr = Signal(3) # Execute, Write, Read
+ self.super = Signal(1) # Supervisor Mode
+ self.super_access = Signal(1) # Supervisor Access
+ self.asid = Signal(15) # Address Space IDentifier (ASID)
+
+ # Output
+ self.valid = Signal(1) # Denotes if the permissions are correct
+
+ def elaborate(self, platform):
+ m = Module()
+ m.d.comb += [
+ # Check if ASID matches OR entry is global
+ If(data[64:78] == self.asid or data[5] == 1,
+ # Check Execute, Write, Read (XWR) Permissions
+ If(data[3] == self.xwr[2] and data[2] == self.xwr[1] \
+ and data[1] == self.xwr[0],
+ # Check if supervisor
+ If(self.super == 1,
+ # Check if entry is in user mode
+ # Check if supervisor has access
+ If(data[4] == 0,
+ self.valid.eq(1)
+ ).Elif(self.super_access == 1,
+ self.valid.eq(1)
+ ).Else(
+ self.valid.eq(0)
+ )
+ ).Else(
+ # Check if entry is in user mode
+ If(data[4] == 1,
+ self.valid.eq(1)
+ ).Else(
+ self.valid.eq(0)
+ )
+ )
+ ).Else(
+ self.valid.eq(0)
+ )
+ ).Else(
+ self.valid.eq(0)
+ )
+ ]
--- /dev/null
+from nmigen import Memory, Module, Signal
+from nmigen.cli import main
+
+from PermissionValidator import PermissionValidator
+
+# The expected form of the data is
+# Item (Bits)
+# Tag (N - 79) / ASID (78 - 64) / PTE (63 - 0)
+
+class TLB():
+ def __init__(self):
+ # Inputs
+ self.super = Signal(1) # Supervisor Mode
+ self.super_access = Signal(1) # Supervisor Access
+ self.command = Signal(2) # 00=None, 01=Search, 10=Write PTE, 11=Reset
+ self.xwr = Signal(3) # Execute, Write, Read
+ self.mode = Signal(4) # 4 bits for access to Sv48 on Rv64
+ self.asid = Signal(15) # Address Space IDentifier (ASID)
+ self.vma = Signal(36) # Virtual Memory Address (VMA)
+ self.pte_in = Signal(64) # To be saved Page Table Entry (PTE)
+
+ # Outputs
+ self.hit = Signal(1) # Denotes if the VMA had a mapped PTE
+ self.valid = Signal(1) # Denotes if the permissions are correct
+ self.pteOut = Signal(64) # PTE that was mapped to by the VMA
+
+ # Cam simulations
+ mem_l1 = Memory(113, 32) # L1 TLB cache
+ read_port_l1 = mem_l1.read_port
+ write_port_l1 = mem_l1.write_port
+
+ mem_l2 = Memory(113, 128) # L2 TLB cache
+ read_port_l2 = mem_l2.read_port
+ write_port_l2 = mem_l2.write_port
+
+ def elaborate(self, platform):
+ m = Module()
+ m.d.submodules.perm_valid = perm_valid = PermissionValidator(113)
+ m.d.sync += [
+ Case(self.command, {
+ # Search for PTE
+ 1: [
+ # Check first entry in set
+ # TODO make module?
+ read_port_l1.addr.eq(vma[0,2]),
+ If(read_port_l1.data[0] == 1,
+ perm_valid.data.eq(read_port_l1.data),
+ perm_valid.xwr.eq(self.xwr),
+ perm_valid.super.eq(self.super),
+ perm_valid.super_access.eq(self.super_access),
+ perm_valid.asid.eq(self.asid),
+ self.valid,eq(perm_valid.valid)
+ ),
+ If(self.valid == 0,
+ read_port_l1.addr.eq(vma[0,2] + 1),
+ If(read_port_l1.data[0] == 1,
+ perm_valid.data.eq(read_port_l1.data),
+ perm_valid.xwr.eq(self.xwr),
+ perm_valid.super.eq(self.super),
+ perm_valid.super_access.eq(self.super_access),
+ perm_valid.asid.eq(self.asid),
+ self.valid,eq(perm_valid.valid)
+ )
+ )
+ ]
+ })
+ ]
+ return m
+
+thing = TLB()
+print("Gottem")
+