diff --git a/submissions/Abhinavagarwa/README.md b/submissions/Abhinavagarwa/README.md
new file mode 100644
index 0000000..6394236
--- /dev/null
+++ b/submissions/Abhinavagarwa/README.md
@@ -0,0 +1,68 @@
+
RISC-V PMP Checker - Abhinavagarwa
+
+Author: Abhinavagarwa
+
+Overview:
+
+This script is designed to verify access permissions for physical addresses in RISC-V processors based on Physical Memory Protection (PMP) rules. It follows the guidelines outlined in Chapter 3.7 of the RISC-V Privileged Architecture specification. The program accepts a PMP configuration file, a physical address, a privilege mode, and an access type as input arguments and determines whether the access is permitted or results in a fault.
+
+
+Execution Instructions:
+
+This script does not require compilation and can be run directly using Python.
+
+To execute the program, use the following command:
+
+```bash
+python pmp_checker.py
+```
+
+Where:
+
+- ``: Path to the PMP configuration file. The file consists of 128 lines:
+ - The first 64 lines represent the hexadecimal values of pmpNcfg registers (N = 0 to 63).
+ - The last 64 lines represent the hexadecimal values of pmpaddrN registers (N = 0 to 63).
+- ``: The target address for verification, provided in hexadecimal format (e.g., 0xdeadbeef).
+- ``: The privilege level of the access attempt. Acceptable values: `M` (Machine), `S` (Supervisor), or `U` (User).
+- ``: The type of memory access: `R` (Read), `W` (Write), or `X` (Execute).
+
+Example Usage:
+```bash
+python pmp_checker.py pmp_configuration.txt 0x80000000 M R
+```
+
+---
+
+Dependencies:
+
+This script is implemented using standard Python libraries and does not require any additional dependencies.
+
+---
+
+Implementation Details:
+
+1. Reading Configuration: The script loads the PMP settings from the configuration file, storing `pmpNcfg` and `pmpaddrN` values in separate lists.
+2. Parsing Inputs: It processes command-line arguments, converting the physical address to an integer and validating privilege modes and access types.
+3. PMP Region Matching: The script iterates through PMP entries to determine if the given address falls within a defined PMP region. It evaluates:
+ - `TOR (Top of Range)`: Defines a memory region between a previous address and the current PMP address.
+ - `NA4 (Naturally Aligned 4-byte)`: Protects a fixed 4-byte region.
+ - `NAPOT (Naturally Aligned Power of Two)`: Covers larger aligned memory blocks.
+4. Access Permission Check: If the address falls within a matching PMP region, the script checks the access permissions based on `R/W/X` bits in `pmpNcfg`.
+5. Output Decision: If the access is allowed, the script prints `Access allowed`; otherwise, it prints `Access fault`.
+
+Testing Scenarios:
+
+The script has been tested under multiple conditions, including:
+
+- Access requests inside and outside PMP regions.
+- Various combinations of `R`, `W`, and `X` permissions.
+- Addresses located at PMP region boundaries.
+- Handling of `NAPOT` regions with different configurations.
+- Error handling for invalid inputs (e.g., incorrect file paths, malformed addresses, and unsupported modes).
+
+This ensures robust functionality across different access conditions.
+
+Conclusion:
+
+The RISC-V PMP Checker provides a straightforward method to validate memory access permissions on RISC-V processors. It efficiently interprets PMP configurations and verifies access control based on defined security rules. This tool is particularly useful for developers working on RISC-V-based embedded systems, operating systems, and security-sensitive applications.
+
diff --git a/submissions/Abhinavagarwa/pmp_checker.py b/submissions/Abhinavagarwa/pmp_checker.py
new file mode 100644
index 0000000..e0d46e5
--- /dev/null
+++ b/submissions/Abhinavagarwa/pmp_checker.py
@@ -0,0 +1,94 @@
+import sys
+
+def main():
+ # Parse command-line arguments
+ if len(sys.argv) != 5:
+ print("Usage: python3 pmp_check.py pmp_configuration.txt 0xaddress M/S/U R/W/X")
+ sys.exit(1)
+
+ config_file = sys.argv[1]
+ address_str = sys.argv[2]
+ mode = sys.argv[3].upper()
+ operation = sys.argv[4].upper()
+
+ # Validate physical address
+ if not address_str.startswith("0x"):
+ print("Invalid address format. Must start with '0x'.")
+ sys.exit(1)
+ try:
+ address = int(address_str, 16)
+ except ValueError:
+ print("Invalid address format.")
+ sys.exit(1)
+
+ # Validate privilege mode and operation
+ if mode not in ['M', 'S', 'U']:
+ print("Invalid privilege mode. Must be one of 'M', 'S', or 'U'.")
+ sys.exit(1)
+ if operation not in ['R', 'W', 'X']:
+ print("Invalid operation. Must be one of 'R', 'W', or 'X'.")
+ sys.exit(1)
+
+ # Map privilege modes to levels
+ priv_level = {'M': 3, 'S': 1, 'U': 0}[mode]
+
+ try:
+ with open(config_file, 'r') as f:
+ lines = f.read().splitlines()
+ if len(lines) != 128:
+ print("Configuration file must have exactly 128 lines.")
+ sys.exit(1)
+ pmpcfg = [int(line, 16) for line in lines[:64]]
+ pmpaddr = [int(line, 16) for line in lines[64:]]
+ except Exception as e:
+ print(f"Error reading configuration file: {e}")
+ sys.exit(1)
+
+ # Define PMP region class
+ class PMPRegion:
+ def __init__(self, cfg, addr):
+ self.cfg = cfg
+ self.addr = addr
+ self.a = (cfg >> 3) & 0x3 # Address matching mode
+ self.r = (cfg >> 0) & 0x1 # Read permission
+ self.w = (cfg >> 1) & 0x1 # Write permission
+ self.x = (cfg >> 2) & 0x1 # Execute permission
+
+ def matches(self, addr, prev_addr):
+ if self.a == 0: # OFF (disabled region)
+ return False
+ elif self.a == 1: # TOR (Top of Range)
+ return prev_addr <= addr < self.addr
+ elif self.a == 2: # NA4 (Naturally Aligned 4-byte region)
+ return addr >= self.addr and addr < self.addr + 4
+ elif self.a == 3: # NAPOT (Naturally Aligned Power-of-Two region)
+ size = 1 << ((self.addr & 0xFFFFFFFC) + 2) # Calculate size from address bits
+ return (addr & ~(size - 1)) == (self.addr & ~(size - 1))
+ return False
+
+ def permits(self, op):
+ if op == 'R':
+ return self.r
+ if op == 'W':
+ return self.w
+ if op == 'X':
+ return self.x
+ return False
+
+ # Iterate through PMP entries to check access permissions
+ previous_addr = 0
+ for i in range(64):
+ region = PMPRegion(pmpcfg[i], pmpaddr[i])
+ if region.matches(address, previous_addr):
+ if region.permits(operation):
+ print("Access allowed")
+ return
+ else:
+ print("Access fault")
+ return
+ previous_addr = pmpaddr[i]
+
+ print("Access fault")
+
+if __name__ == "__main__":
+ main()
diff --git a/submissions/Abhinavagarwa/pmp_configuration.txt b/submissions/Abhinavagarwa/pmp_configuration.txt
new file mode 100644
index 0000000..fbba5f9
--- /dev/null
+++ b/submissions/Abhinavagarwa/pmp_configuration.txt
@@ -0,0 +1,128 @@
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x0
+0x1F
+0x0F
+0x80000000
+0x90000000
+0xA0000000
+0xB0000000
+0xC0000000
+0xD0000000
+0xE0000000
+0xF0000000
+0x100000000
+0x110000000
+0x120000000
+0x130000000
+0x140000000
+0x150000000
+0x160000000
+0x170000000
+0x180000000
+0x190000000
+0x1A0000000
+0x1B0000000
+0x1C0000000
+0x1D0000000
+0x1E0000000
+0x1F0000000
+0x200000000
+0x210000000
+0x220000000
+0x230000000
+0x240000000
+0x250000000
+0x260000000
+0x270000000
+0x280000000
+0x290000000
+0x2A0000000
+0x2B0000000
+0x2C0000000
+0x2D0000000
+0x2E0000000
+0x2F0000000
+0x300000000
+0x310000000
+0x320000000
+0x330000000
+0x340000000
+0x350000000
+0x360000000
+0x370000000
+0x380000000
+0x390000000
+0x3A0000000
+0x3B0000000
+0x3C0000000
+0x3D0000000
+0x3E0000000
+0x3F0000000
+0x400000000
+0x4A0000000
+0x4B0000000
+0x4C0000000
+0x4D0000000
+0x4E0000000
+0x4F0000000
+0x500000000
\ No newline at end of file