initial support for exceptions

This commit is contained in:
Yehowshua Immanuel 2025-03-02 23:12:02 -05:00
parent 5552ad3d4a
commit 88ec010f98
9 changed files with 116 additions and 42 deletions

View file

@ -12,7 +12,7 @@ import Data.Maybe (listToMaybe)
import Data.List (isPrefixOf)
import Text.Show.Pretty (ppShow)
import Simulation (simulation, Args(..), Simulation(..))
import Simulation (simulation, Args(..), Simulation(..), RISCVCPU(..), Machine(..))
main :: IO ()
main = do
@ -23,7 +23,7 @@ main = do
case simResult of
Success states -> do
-- mapM_ (putStrLn . ppShow) states -- Uncomment to print each state, if needed.
putStrLn $ "Last state: " ++ show (last states)
putStrLn $ "GPR last state: " ++ (show $ gpr $ cpu $ last states)
putStrLn $ "Executed for " ++ show (length states) ++ " cycles"
putStrLn "Simulation complete"
Failure err -> do

View file

@ -16,7 +16,6 @@ import BusTypes(
BusError(..),
TransactionSize(..),
ReadRequest(..),
BusResponse(..),
BusVal(..),
)
import Types(Addr,

View file

@ -3,7 +3,6 @@ module BusTypes(
BusError(..),
TransactionSize(..),
ReadRequest(..),
BusResponse(..),
BusVal(..),
) where
@ -28,11 +27,6 @@ data TransactionSize
data ReadRequest = Request Addr TransactionSize
deriving (Generic, Show, Eq, NFDataX)
data BusResponse a
= Result a
| Error BusError
deriving (Generic, Show, Eq, NFDataX)
data BusVal
= BusByte Byte
| BusHalfWord HalfWord

View file

@ -24,6 +24,7 @@ data RISCVCPU = RISCVCPU
{ pc :: Pc,
gpr :: GPR,
fpr :: FPR,
csr :: CSR,
privilegeLevel :: PrivilegeLevel
}
deriving (Generic, Show, Eq, NFDataX)
@ -34,4 +35,5 @@ riscvCPUInit =
0
gprInit
fprInit
csrInit
MachineMode

34
hs/Exceptions.hs Normal file
View file

@ -0,0 +1,34 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NumericUnderscores #-}
module Exceptions() where
import Clash.Prelude
data Exception =
SupervisorSoftwareInterrupt
| MachineSoftwareInterrupt
| SupervisorTimerInterrupt
| MachineTimerInterrupt
| SupervisorExternalInterrupt
| MachineExternalInterrupt
| CounterOverflowInterrupt
| InstructionAddressMisaligned
| InstructionAccessFault
| IllegalInstruction
| Breakpoint
| LoadAddressMisaligned
| LoadAccessFault
| StoreAMOAddressMisaligned
| StoreAMOAccessFault
| EnvironmentCallFromUMode
| EnvironmentCallFromSMode
| EnvironmentCallFromMMode
| InstructionPageFault
| LoadPageFault
| Reserved
| StoreAMOPageFault
| DoubleTrap
| SoftwareCheck
| HardwareError
deriving (Generic, Show, Eq, NFDataX)

View file

@ -14,6 +14,11 @@ import Clash.Prelude
import Types(Mem, Addr, Insn)
import Util(endianSwapWord)
import Bus(ReadResponse, WriteResponse, read)
import Bus(Peripherals(..))
import BusTypes(ReadRequest(..), TransactionSize(..))
import GHC.IO (IO)
import GHC.Base (Applicative(pure))
data FetchResult = Instruction Insn
| Misaligned Addr
@ -30,3 +35,7 @@ fetchInstruction mem addr =
case isWordAligned of
True -> Instruction insn
False -> Misaligned addr
fetchInstruction1 :: Peripherals -> Addr -> IO ReadResponse
fetchInstruction1 peripherals addr =
read (BusTypes.Request addr BusTypes.SizeFullWord) peripherals

View file

@ -1,6 +1,17 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NumericUnderscores #-}
-- | This module defines the register files used in a RISC-V core, including:
-- General Purpose Registers (GPR), Floating Point Registers (FPR), and Control & Status Registers (CSR).
--
-- In RISC-V, besides the GPR, FPR, and CSR, we may also encounter
-- the following which are not modeled in this codebase:
-- * VRF (Vector Registers File) for vector processing.
-- * Debug Registers (DBR) for hardware debugging.
-- * Shadow Registers for fast context switching (optional).
-- * MPU Registers for memory protection.
-- * Counter/Timer Registers for time/cycle counting.
-- * Hypervisor Registers (HPR) for guest virtualization.
module RegFiles(
GPR,
FPR,
@ -12,18 +23,9 @@ module RegFiles(
import Clash.Prelude
-- In RISC-V, besides the GPR, FPR, and CSR, we may also encounter
-- the following which are not modeled in this codebase.
-- * VRF(Vector Registers File) for vector processing.
-- * Debug Registers (DBR) for hardware debugging.
-- * Shadow Registers for fast context switching (optional).
-- * MPU Registers for memory protection.
-- * Counter/Timer Registers for time/cycle counting.
-- * Hypervisor Registers (HPR) for guest virtualization.
type GPR = Vec 32 (Unsigned 64)
type FPR = Vec 32 (Unsigned 64)
type CSR = Vec 4096 (Unsigned 64)
type GPR = Vec 32 (Unsigned 64) -- General Purpose Registers
type FPR = Vec 32 (Unsigned 64) -- Floating Point Registers
type CSR = Vec 4096 (Unsigned 64) -- Control and Status Registers
gprInit :: GPR
gprInit = repeat 0
@ -31,26 +33,54 @@ gprInit = repeat 0
fprInit :: FPR
fprInit = repeat 0
-- TODO: CSR can't actually be all 0 during initialization.
-- We need to revisit the following and properly initialize
-- various registers later.
-- | The 'CSRName' data type enumerates a subset of RISC-V CSRs (Control and Status Registers)
-- that are modeled in this codebase. Each variant represents a particular CSR.
data CSRName =
STVEC -- ^ Supervisor Trap-Vector Base Address: Base address for supervisor mode exception handlers.
| SEPC -- ^ Supervisor Exception Program Counter: Holds the return address for supervisor mode exceptions.
| MSTATUS -- ^ Machine Status Register: Contains global machine status flags and control bits.
| MISA -- ^ Machine ISA Register: Indicates the supported ISA extensions and width.
| MTVEC -- ^ Machine Trap-Vector Base Address: Base address for machine mode exception handlers.
| MEPC -- ^ Machine Exception Program Counter: Holds the return address for machine mode exceptions.
| MVENDORID -- ^ Machine Vendor ID: Identifies the vendor of the processor.
| MARCHID -- ^ Machine Architecture ID: Identifies the architecture of the processor.
| MIMPID -- ^ Machine Implementation ID: Identifies the implementation of the processor.
deriving (Generic, Show, Eq, NFDataX)
-- | Map each 'CSRName' variant to its corresponding CSR address.
csrNameToAddr :: CSRName -> Integer
csrNameToAddr STVEC = 0x105 -- Address for Supervisor Trap-Vector
csrNameToAddr SEPC = 0x141 -- Address for Supervisor Exception PC
csrNameToAddr MSTATUS = 0x300
csrNameToAddr MISA = 0x301
csrNameToAddr MTVEC = 0x305
csrNameToAddr MEPC = 0x341 -- Address for Machine Exception PC
csrNameToAddr MVENDORID = 0xF11
csrNameToAddr MARCHID = 0xF12
csrNameToAddr MIMPID = 0xF13
-- | Initial CSR values.
-- Note: The CSR registers are not all zero during proper initialization; these values
-- are placeholders to be revisited for proper initialization later.
csrInit :: CSR
csrInit =
replace (0x301 :: Integer) misa_init
$ replace (0x300 :: Integer) mstatus_init
$ replace (0x305 :: Integer) mtvec_init
$ replace (0xF11 :: Integer) mvendorid_init
$ replace (0xF12 :: Integer) marchid_init
$ replace (0xF13 :: Integer) mimpid_init
$ replace (0x701 :: Integer) mtime_init
$ replace (0x321 :: Integer) mtimecmp_init
replace (csrNameToAddr STVEC) stvec_init
$ replace (csrNameToAddr SEPC) sepc_init
$ replace (csrNameToAddr MSTATUS) mstatus_init
$ replace (csrNameToAddr MISA) misa_init
$ replace (csrNameToAddr MTVEC) mtvec_init
$ replace (csrNameToAddr MEPC) mepc_init
$ replace (csrNameToAddr MVENDORID) mvendorid_init
$ replace (csrNameToAddr MARCHID) marchid_init
$ replace (csrNameToAddr MIMPID) mimpid_init
$ repeat 0
where
misa_init = 0x8000000000001104 -- `RV64IMAFD`
mstatus_init = 0x0000000000001800 -- Default `mstatus`
mtvec_init = 0x0000000000001000 -- Trap vector base
mvendorid_init = 0x00000000
marchid_init = 0x00000000
mimpid_init = 0x00000000
mtime_init = 0x0000000000000000
mtimecmp_init = 0xFFFFFFFFFFFFFFFF
stvec_init = 0x0000000000002000 -- Supervisor mode trap vector base address.
sepc_init = 0x0000000000000000 -- Supervisor Exception PC initial value.
mstatus_init = 0x0000000000001800 -- Default machine status.
misa_init = 0x8000000000001104 -- RV64IMAFD: Machine ISA with standard extensions.
mtvec_init = 0x0000000000001000 -- Machine mode trap vector base address.
mepc_init = 0x0000000000000000 -- Machine Exception PC initial value.
mvendorid_init = 0x00000000 -- Vendor-specific ID.
marchid_init = 0x00000000 -- Architecture-specific ID.
mimpid_init = 0x00000000 -- Implementation-specific ID.

View file

@ -3,7 +3,13 @@
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstraintKinds #-}
module Simulation(Args(..), simulation, Simulation(..)) where
module Simulation(
Args(..),
simulation,
RISCVCPU(..),
Machine(..),
Simulation(..)
) where
import qualified Prelude as P
import Peripherals.Setup(setupPeripherals, InitializedPeripherals(..))
@ -12,7 +18,6 @@ import Clash.Prelude
import Bus(Peripherals(..))
import Cpu(
RISCVCPU(..),
RISCVCPU (RISCVCPU),
riscvCPUInit)
import Fetch(fetchInstruction, FetchResult (Instruction, Misaligned))
import Isa.Decode(decode)

View file

@ -100,6 +100,7 @@ library
Cpu,
RegFiles,
Fetch,
Exceptions,
Util
c-sources: c/uart_sim_device.c
include-dirs: c