PasRISCV is a RV64GCV/RVA23 RISC-V emulator, which is implemented in Object Pascal
Pascal
8
812 commits
updated Sep 30, 2026
[!IMPORTANT] The primary repository has moved to git.rosseaux.net/BeRo1985/pasriscv. This GitHub repository is kept up-to-date via push mirroring.
A RISC-V RV64GCV/RVA23 emulator written in Object Pascal. It simulates processor cores, memory, I/O, and much more.
{$define PasRISCVSmcntrpmf}){$define PasRISCVSmcdeleg}){$define PasRISCVSmepmp}){$define PasRISCVSmdbltrp}){$define PasRISCVSsdbltrp}; requires Smdbltrp)-netdev user/slirp) that proxies ARP, DHCP, ICMP, UDP, and TCP (including IPv6) from the guest to the host network. No TAP device or special privileges are needed.VirtIONetBackend=TUN and VirtIONetTAPInterface (default: tap0).arm,sp805 / arm,primecell, at $10030000, IRQ $0e; two-phase expiry: first timeout fires IRQ, second triggers machine reset if RESEN set; register-write protected by lock key 0x1ACCE551)The decision to support only 64-bit RISC-V (RV64GCV) is primarily driven by the need for a modern architecture that can efficiently handle current and future workloads. 64-bit architectures provide several advantages over their 32-bit counterparts, including:
Larger Address Space: 64-bit systems can address significantly more memory than 32-bit systems, allowing for more extensive and complex applications.
Improved Performance: 64-bit processors can handle more data per clock cycle, leading to better performance for compute-intensive tasks.
Future-Proofing: As software and workloads evolve, the demand for 64-bit processing power will only increase. Supporting 64-bit from the outset ensures that the emulator can accommodate future developments.
Compatibility with Modern Software: Most modern operating systems and applications are designed with 64-bit architectures in mind, making it essential for the emulator to support this architecture for compatibility reasons.
And support for 32-bit RISC-V is virtually nonexistent outside of source-based distros (Gentoo, Buildroot, Yocto, etc.), microcontrollers, strange embedded systems and some hobbyist projects. Most mainstream Linux distributions, other operating systems and software projects have moved to 64-bit as the standard, making it more practical to focus only on 64-bit support. 32-bit support would require additional development and maintenance effort, which may not be justified given the limited use cases and demand for 32-bit RISC-V. So, it is 64-bit only, and it will remain that way. The same applies to 128-bit RISC-V, which is not supported at all, since there is no real-world implementation or use case for it at this time.
The decision to support only Little-Endian mode in the PasRISCV emulator is based on several practical considerations:
Prevalence of Little-Endian: Little-Endian is the most commonly used endianness in modern computing systems, including x86 and modern ARM architectures. By focusing on Little-Endian, the emulator aligns with the majority of existing software and hardware, ensuring better compatibility and ease of use. And most all RISC-V systems in the wild are also Little-Endian. And the RISC-V specification itself defaults to Little-Endian, with Big-Endian support being not specified and rarely implemented officially.
Simplicity and Maintainability: Supporting multiple endianness modes (Little-Endian, Big-Endian, and Mixed-Endian) would significantly increase the complexity of the emulator's design and implementation. This added complexity could lead to more bugs, increased development time, and greater maintenance challenges. By limiting the scope to Little-Endian, the development process becomes more straightforward and manageable.
Target Audience: The primary users of the PasRISCV emulator are likely to be developers and enthusiasts who are already familiar with Little-Endian systems. By catering to this audience, the emulator can provide a more focused and optimized experience.
Performance Considerations: Emulating multiple endianness modes could introduce performance overhead due to the need for additional checks and conversions during memory access operations. By standardizing on Little-Endian, the emulator can optimize performance for the most common use cases.
Low Byte-Swapping Costs: Modern compilers and processors are highly optimized for handling byte-swapping operations when necessary. This means that even if a user needs to work with Big-Endian data, the performance impact of converting between endianness is minimal in most scenarios. PasRISCV supports the Zbb extension, which includes bit manipulation instructions that can facilitate efficient byte-swapping just in a single instruction when needed, for example for network protocols (network byte order) or older file formats that used still Big-Endian.
Big-Endian Is Dead: There are very few use cases for Big-Endian systems today, and they are mostly limited to legacy systems or specific niche applications. The demand for Big-Endian support is minimal, making it less justifiable to invest resources in its implementation. Big-Endian lives on mostly in some network protocols (network byte order) and some older file formats, but even there, its use is declining as more systems adopt Little-Endian.
Mixed-Endian Complexity: Mixed-Endian systems, which use different endianness for different data types or structures, are even more complex to implement and maintain. The rarity of Mixed-Endian systems in practical applications further diminishes the need for support in the emulator.
Overall, the decision to support only Little-Endian mode in the PasRISCV emulator is a strategic choice that balances compatibility, simplicity, performance, and user needs. While Big-Endian and Mixed-Endian modes have their use cases, the benefits of focusing on Little-Endian outweigh the potential advantages of supporting multiple endianness modes in this context.
See pasriscvemu PasVulkan project for an emulator frontend that uses this library.
Some features are controlled by compile-time {$define} directives at the top of src/PasRISCV.pas. These flags exist because even when a feature is logically inactive at runtime, having the conditional checks compiled in can still impose a measurable performance overhead in hot paths (e.g. every instruction's cycle counter update in the JIT or interpreter).
| Define | Default | Description |
|---|---|---|
PasRISCVSmcntrpmf | enabled | Smcntrpmf — Counter Privilege-Mode Filtering. When enabled, the cycle counter can be inhibited per-privilege-mode via mcyclecfg/minstretcfg CSRs. The JIT uses a branchless mask (CycleIncrementMask) to avoid branches in hot paths, but the extra load+AND+memory-add sequence has a small cost even when counting is not inhibited. Disable by commenting out {$define PasRISCVSmcntrpmf} if Smcntrpmf guest support is not required. |
PasRISCVSmdbltrp | disabled | Smdbltrp — Machine-Mode Double Trap. When enabled, trapping to M-mode while mstatus.MDT=1 triggers a double-trap: the hart is redirected to the RNMI handler (if mnstatus.NMIE=1) or halted. mstatus.MDT is set on every M-mode trap entry and cleared by MRET. Although the checks are only reached on the (rare) trap path, the MDT bit participates in the mstatus WARL mask even when inactive, which subtly changes CSR write behaviour. Enable by uncommenting {$define PasRISCVSmdbltrp}. |
PasRISCVSsdbltrp | disabled | Ssdbltrp — Supervisor-Mode Double Trap. Requires PasRISCVSmdbltrp. When enabled, two independent double-trap mechanisms are active: (1) HS-mode: if menvcfg.DTE=1 and mstatus.SDT=1, a trap to HS-mode escalates to M-mode as a synchronous cause-16 exception (mcause=16, mtval2=original scause). (2) VS-mode: if henvcfg.DTE=1 and vsstatus.SDT=1, a trap to VS-mode escalates to HS-mode as a synchronous cause-16 exception (scause=16, htval=original vscause). Both SDT bits are set on every respective trap entry (when the corresponding DTE=1) and cleared by the matching SRET. Writing SDT=1 to mstatus/vsstatus forces the corresponding SIE=0. Enable by uncommenting {$define PasRISCVSsdbltrp}. |
PasRISCVSmcdeleg | disabled | Smcdeleg+Ssccfg — Counter Delegation. When enabled, adds mcounterdeleg (0x309, MRW) and scounterinhibit (0x120, SRW). M-mode can delegate counters 0–31 to S-mode by setting bits in mcounterdeleg. S-mode (HS-mode only; VS-mode raises VirtualInstruction) can then inhibit delegated counters via scounterinhibit, with writes masked to bits that are set in mcounterdeleg (WARL). Since HPM counters 3–31 do not track real events in the emulator, the inhibition has no visible counting effect, but the CSRs are correctly accessible and Linux/OpenSBI counter-delegation setup will not trap. Enable by uncommenting {$define PasRISCVSmcdeleg}. |
PasRISCVSmepmp | enabled | Smepmp — Enhanced Physical Memory Protection. When enabled, the three Smepmp bits in mseccfg (RLB bit 2, MMWP bit 1, MML bit 0) are writable and fully enforced. PMP entries (pmpcfg0–pmpcfg3, pmpaddr0–pmpaddr15) are checked on every TLB miss for all privilege modes. MMWP=1 enables whitelist semantics for M-mode. MML=1 activates the Smepmp permission table that redefines how R/W/X/L bits are interpreted for M-mode vs. S/U-mode access. Any write to a PMP or mseccfg CSR flushes the TLB. Disable by commenting out {$define PasRISCVSmepmp} if PMP enforcement is not required (e.g. for maximum interpreter throughput in a trusted environment). |
What it does in real hardware:
srmcfg CSRsrmcfg on every context switch to assign the incoming task's QoS class and monitoring slot.What this means for the emulator:
srmcfg CSR ($181) is fully implemented as a read/write register with correct WPRI masking (only bits 11:0 and 27:16 are writable), ensuring that guest software (including the Linux CBQRI / Ssqosid kernel driver) can discover and use the extension without taking illegal-instruction traps and without observing any data corruption on reads.What they do in real hardware:
These extensions (ratified August 2024) add hardware-enforced detection of nested trap conditions that would otherwise silently corrupt machine state.
mstatus.MDT (bit 42). Hardware sets MDT=1 on every M-mode trap entry. If a second trap to M-mode occurs while MDT is already 1, the hart detects a machine double trap: if mnstatus.NMIE=1 it is redirected to the RNMI handler to allow controlled recovery; otherwise the hart enters a non-recoverable error state. MRET clears MDT. On reset, MDT is initialised to 1 (the hart starts as though it just took a trap) so that any early boot fault is caught.mstatus.SDT (bit 24), vsstatus.SDT (bit 24), menvcfg.DTE (bit 24), and henvcfg.DTE (bit 24). Two independent double-trap mechanisms apply:
menvcfg.DTE=1, hardware sets mstatus.SDT=1 on every HS-mode trap entry. If a second trap to HS-mode occurs while SDT is already 1, the fault escalates to M-mode as a synchronous exception with mcause=16, mtval2 holding the original would-be scause. SRET and MRET clear mstatus.SDT.henvcfg.DTE=1, hardware sets vsstatus.SDT=1 on every VS-mode trap entry. If a second trap to VS-mode occurs while vsstatus.SDT is already 1, the fault escalates to HS-mode as a synchronous exception with scause=16, htval holding the original would-be vscause. VS-mode SRET clears vsstatus.SDT. In both cases, writing SDT=1 to the respective status CSR also forces the corresponding SIE bit to 0.What this means for the emulator:
mstatus.MDT, mstatus.SDT, vsstatus.SDT, menvcfg.DTE, and henvcfg.DTE are readable and writable WARL fieldsmstatus/vsstatus WARL mask even when logically inactive, so they are guarded behind compile-time {$define} flags (PasRISCVSmdbltrp / PasRISCVSsdbltrp) to allow complete exclusion when not needed.What they do in real hardware:
Smcdeleg (Machine Counter Delegation) and its companion Ssccfg (Supervisor Counter Configuration) allow M-mode to hand performance counter management to S-mode:
mcounterdeleg (0x309, MRW): a 32-bit bitmask where bit N=1 means counter N is delegated to S-mode. Delegated counters are independently controlled by S-mode; non-delegated counters remain exclusively in M-mode's domain.scounterinhibit (0x120, SRW): once a counter is delegated, S-mode can prevent it from counting while in S or U privilege mode by setting the corresponding bit. Only bits corresponding to delegated counters (set in mcounterdeleg) are writable; all other bits read as zero (WARL). VS-mode raises a VirtualInstruction exception when accessing this CSR (it has no VS-mode shadow).Together they allow Linux's perf subsystem to manage performance counters from S-mode without M-mode (OpenSBI) involvement on every counter event.
What this means for the emulator:
mcounterdeleg and scounterinhibit are fully implemented as read/write WARL CSRs with correct privilege enforcement.{$define PasRISCVSmcdeleg} (disabled by default).What it does in real hardware:
Smepmp (ratified 2021) extends the baseline PMP with three new mseccfg control bits that tighten M-mode memory isolation:
OpenSBI >= v1.3 uses Smepmp to enforce M-mode memory isolation by clearing RLB and optionally setting MMWP, hardening the security boundary between the firmware and the OS.
What this means for the emulator (when {$define PasRISCVSmepmp} is enabled):
mseccfg CSR ($747) is fully writable with correct WARL masking including RLB, MMWP, and MML bits.{$define Zicfilp} is active.mseccfg flushes the entire TLB to ensure cached translations are re-validated.{$define PasRISCVSmepmp} (enabled by default).See the docs directory for more information.
This project is released under zlib license.
131 followers · starred May 2026
Pascal
95.9%
Assembly
2.7%
PasRISCV is a RV64GCV/RVA23 RISC-V emulator, which is implemented in Object Pascal
Pascal
8
812 commits
updated Sep 30, 2026
[!IMPORTANT] The primary repository has moved to git.rosseaux.net/BeRo1985/pasriscv. This GitHub repository is kept up-to-date via push mirroring.
A RISC-V RV64GCV/RVA23 emulator written in Object Pascal. It simulates processor cores, memory, I/O, and much more.
{$define PasRISCVSmcntrpmf}){$define PasRISCVSmcdeleg}){$define PasRISCVSmepmp}){$define PasRISCVSmdbltrp}){$define PasRISCVSsdbltrp}; requires Smdbltrp)-netdev user/slirp) that proxies ARP, DHCP, ICMP, UDP, and TCP (including IPv6) from the guest to the host network. No TAP device or special privileges are needed.VirtIONetBackend=TUN and VirtIONetTAPInterface (default: tap0).arm,sp805 / arm,primecell, at $10030000, IRQ $0e; two-phase expiry: first timeout fires IRQ, second triggers machine reset if RESEN set; register-write protected by lock key 0x1ACCE551)The decision to support only 64-bit RISC-V (RV64GCV) is primarily driven by the need for a modern architecture that can efficiently handle current and future workloads. 64-bit architectures provide several advantages over their 32-bit counterparts, including:
Larger Address Space: 64-bit systems can address significantly more memory than 32-bit systems, allowing for more extensive and complex applications.
Improved Performance: 64-bit processors can handle more data per clock cycle, leading to better performance for compute-intensive tasks.
Future-Proofing: As software and workloads evolve, the demand for 64-bit processing power will only increase. Supporting 64-bit from the outset ensures that the emulator can accommodate future developments.
Compatibility with Modern Software: Most modern operating systems and applications are designed with 64-bit architectures in mind, making it essential for the emulator to support this architecture for compatibility reasons.
And support for 32-bit RISC-V is virtually nonexistent outside of source-based distros (Gentoo, Buildroot, Yocto, etc.), microcontrollers, strange embedded systems and some hobbyist projects. Most mainstream Linux distributions, other operating systems and software projects have moved to 64-bit as the standard, making it more practical to focus only on 64-bit support. 32-bit support would require additional development and maintenance effort, which may not be justified given the limited use cases and demand for 32-bit RISC-V. So, it is 64-bit only, and it will remain that way. The same applies to 128-bit RISC-V, which is not supported at all, since there is no real-world implementation or use case for it at this time.
The decision to support only Little-Endian mode in the PasRISCV emulator is based on several practical considerations:
Prevalence of Little-Endian: Little-Endian is the most commonly used endianness in modern computing systems, including x86 and modern ARM architectures. By focusing on Little-Endian, the emulator aligns with the majority of existing software and hardware, ensuring better compatibility and ease of use. And most all RISC-V systems in the wild are also Little-Endian. And the RISC-V specification itself defaults to Little-Endian, with Big-Endian support being not specified and rarely implemented officially.
Simplicity and Maintainability: Supporting multiple endianness modes (Little-Endian, Big-Endian, and Mixed-Endian) would significantly increase the complexity of the emulator's design and implementation. This added complexity could lead to more bugs, increased development time, and greater maintenance challenges. By limiting the scope to Little-Endian, the development process becomes more straightforward and manageable.
Target Audience: The primary users of the PasRISCV emulator are likely to be developers and enthusiasts who are already familiar with Little-Endian systems. By catering to this audience, the emulator can provide a more focused and optimized experience.
Performance Considerations: Emulating multiple endianness modes could introduce performance overhead due to the need for additional checks and conversions during memory access operations. By standardizing on Little-Endian, the emulator can optimize performance for the most common use cases.
Low Byte-Swapping Costs: Modern compilers and processors are highly optimized for handling byte-swapping operations when necessary. This means that even if a user needs to work with Big-Endian data, the performance impact of converting between endianness is minimal in most scenarios. PasRISCV supports the Zbb extension, which includes bit manipulation instructions that can facilitate efficient byte-swapping just in a single instruction when needed, for example for network protocols (network byte order) or older file formats that used still Big-Endian.
Big-Endian Is Dead: There are very few use cases for Big-Endian systems today, and they are mostly limited to legacy systems or specific niche applications. The demand for Big-Endian support is minimal, making it less justifiable to invest resources in its implementation. Big-Endian lives on mostly in some network protocols (network byte order) and some older file formats, but even there, its use is declining as more systems adopt Little-Endian.
Mixed-Endian Complexity: Mixed-Endian systems, which use different endianness for different data types or structures, are even more complex to implement and maintain. The rarity of Mixed-Endian systems in practical applications further diminishes the need for support in the emulator.
Overall, the decision to support only Little-Endian mode in the PasRISCV emulator is a strategic choice that balances compatibility, simplicity, performance, and user needs. While Big-Endian and Mixed-Endian modes have their use cases, the benefits of focusing on Little-Endian outweigh the potential advantages of supporting multiple endianness modes in this context.
See pasriscvemu PasVulkan project for an emulator frontend that uses this library.
Some features are controlled by compile-time {$define} directives at the top of src/PasRISCV.pas. These flags exist because even when a feature is logically inactive at runtime, having the conditional checks compiled in can still impose a measurable performance overhead in hot paths (e.g. every instruction's cycle counter update in the JIT or interpreter).
| Define | Default | Description |
|---|---|---|
PasRISCVSmcntrpmf | enabled | Smcntrpmf — Counter Privilege-Mode Filtering. When enabled, the cycle counter can be inhibited per-privilege-mode via mcyclecfg/minstretcfg CSRs. The JIT uses a branchless mask (CycleIncrementMask) to avoid branches in hot paths, but the extra load+AND+memory-add sequence has a small cost even when counting is not inhibited. Disable by commenting out {$define PasRISCVSmcntrpmf} if Smcntrpmf guest support is not required. |
PasRISCVSmdbltrp | disabled | Smdbltrp — Machine-Mode Double Trap. When enabled, trapping to M-mode while mstatus.MDT=1 triggers a double-trap: the hart is redirected to the RNMI handler (if mnstatus.NMIE=1) or halted. mstatus.MDT is set on every M-mode trap entry and cleared by MRET. Although the checks are only reached on the (rare) trap path, the MDT bit participates in the mstatus WARL mask even when inactive, which subtly changes CSR write behaviour. Enable by uncommenting {$define PasRISCVSmdbltrp}. |
PasRISCVSsdbltrp | disabled | Ssdbltrp — Supervisor-Mode Double Trap. Requires PasRISCVSmdbltrp. When enabled, two independent double-trap mechanisms are active: (1) HS-mode: if menvcfg.DTE=1 and mstatus.SDT=1, a trap to HS-mode escalates to M-mode as a synchronous cause-16 exception (mcause=16, mtval2=original scause). (2) VS-mode: if henvcfg.DTE=1 and vsstatus.SDT=1, a trap to VS-mode escalates to HS-mode as a synchronous cause-16 exception (scause=16, htval=original vscause). Both SDT bits are set on every respective trap entry (when the corresponding DTE=1) and cleared by the matching SRET. Writing SDT=1 to mstatus/vsstatus forces the corresponding SIE=0. Enable by uncommenting {$define PasRISCVSsdbltrp}. |
PasRISCVSmcdeleg | disabled | Smcdeleg+Ssccfg — Counter Delegation. When enabled, adds mcounterdeleg (0x309, MRW) and scounterinhibit (0x120, SRW). M-mode can delegate counters 0–31 to S-mode by setting bits in mcounterdeleg. S-mode (HS-mode only; VS-mode raises VirtualInstruction) can then inhibit delegated counters via scounterinhibit, with writes masked to bits that are set in mcounterdeleg (WARL). Since HPM counters 3–31 do not track real events in the emulator, the inhibition has no visible counting effect, but the CSRs are correctly accessible and Linux/OpenSBI counter-delegation setup will not trap. Enable by uncommenting {$define PasRISCVSmcdeleg}. |
PasRISCVSmepmp | enabled | Smepmp — Enhanced Physical Memory Protection. When enabled, the three Smepmp bits in mseccfg (RLB bit 2, MMWP bit 1, MML bit 0) are writable and fully enforced. PMP entries (pmpcfg0–pmpcfg3, pmpaddr0–pmpaddr15) are checked on every TLB miss for all privilege modes. MMWP=1 enables whitelist semantics for M-mode. MML=1 activates the Smepmp permission table that redefines how R/W/X/L bits are interpreted for M-mode vs. S/U-mode access. Any write to a PMP or mseccfg CSR flushes the TLB. Disable by commenting out {$define PasRISCVSmepmp} if PMP enforcement is not required (e.g. for maximum interpreter throughput in a trusted environment). |
What it does in real hardware:
srmcfg CSRsrmcfg on every context switch to assign the incoming task's QoS class and monitoring slot.What this means for the emulator:
srmcfg CSR ($181) is fully implemented as a read/write register with correct WPRI masking (only bits 11:0 and 27:16 are writable), ensuring that guest software (including the Linux CBQRI / Ssqosid kernel driver) can discover and use the extension without taking illegal-instruction traps and without observing any data corruption on reads.What they do in real hardware:
These extensions (ratified August 2024) add hardware-enforced detection of nested trap conditions that would otherwise silently corrupt machine state.
mstatus.MDT (bit 42). Hardware sets MDT=1 on every M-mode trap entry. If a second trap to M-mode occurs while MDT is already 1, the hart detects a machine double trap: if mnstatus.NMIE=1 it is redirected to the RNMI handler to allow controlled recovery; otherwise the hart enters a non-recoverable error state. MRET clears MDT. On reset, MDT is initialised to 1 (the hart starts as though it just took a trap) so that any early boot fault is caught.mstatus.SDT (bit 24), vsstatus.SDT (bit 24), menvcfg.DTE (bit 24), and henvcfg.DTE (bit 24). Two independent double-trap mechanisms apply:
menvcfg.DTE=1, hardware sets mstatus.SDT=1 on every HS-mode trap entry. If a second trap to HS-mode occurs while SDT is already 1, the fault escalates to M-mode as a synchronous exception with mcause=16, mtval2 holding the original would-be scause. SRET and MRET clear mstatus.SDT.henvcfg.DTE=1, hardware sets vsstatus.SDT=1 on every VS-mode trap entry. If a second trap to VS-mode occurs while vsstatus.SDT is already 1, the fault escalates to HS-mode as a synchronous exception with scause=16, htval holding the original would-be vscause. VS-mode SRET clears vsstatus.SDT. In both cases, writing SDT=1 to the respective status CSR also forces the corresponding SIE bit to 0.What this means for the emulator:
mstatus.MDT, mstatus.SDT, vsstatus.SDT, menvcfg.DTE, and henvcfg.DTE are readable and writable WARL fieldsmstatus/vsstatus WARL mask even when logically inactive, so they are guarded behind compile-time {$define} flags (PasRISCVSmdbltrp / PasRISCVSsdbltrp) to allow complete exclusion when not needed.What they do in real hardware:
Smcdeleg (Machine Counter Delegation) and its companion Ssccfg (Supervisor Counter Configuration) allow M-mode to hand performance counter management to S-mode:
mcounterdeleg (0x309, MRW): a 32-bit bitmask where bit N=1 means counter N is delegated to S-mode. Delegated counters are independently controlled by S-mode; non-delegated counters remain exclusively in M-mode's domain.scounterinhibit (0x120, SRW): once a counter is delegated, S-mode can prevent it from counting while in S or U privilege mode by setting the corresponding bit. Only bits corresponding to delegated counters (set in mcounterdeleg) are writable; all other bits read as zero (WARL). VS-mode raises a VirtualInstruction exception when accessing this CSR (it has no VS-mode shadow).Together they allow Linux's perf subsystem to manage performance counters from S-mode without M-mode (OpenSBI) involvement on every counter event.
What this means for the emulator:
mcounterdeleg and scounterinhibit are fully implemented as read/write WARL CSRs with correct privilege enforcement.{$define PasRISCVSmcdeleg} (disabled by default).What it does in real hardware:
Smepmp (ratified 2021) extends the baseline PMP with three new mseccfg control bits that tighten M-mode memory isolation:
OpenSBI >= v1.3 uses Smepmp to enforce M-mode memory isolation by clearing RLB and optionally setting MMWP, hardening the security boundary between the firmware and the OS.
What this means for the emulator (when {$define PasRISCVSmepmp} is enabled):
mseccfg CSR ($747) is fully writable with correct WARL masking including RLB, MMWP, and MML bits.{$define Zicfilp} is active.mseccfg flushes the entire TLB to ensure cached translations are re-validated.{$define PasRISCVSmepmp} (enabled by default).See the docs directory for more information.
This project is released under zlib license.
131 followers · starred May 2026
Pascal
95.9%
Assembly
2.7%