{-# LANGUAGE GADTs #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE ConstraintKinds #-} module Simulation( Args(..), simulation, RISCVCPU(..), Machine(..), Simulation(..) ) where import Peripherals.Setup(setupPeripherals, InitializedPeripherals(..)) import Peripherals.Teardown(teardownPeripherals) import Clash.Prelude import Bus(Peripherals(..)) import Cpu( RISCVCPU(..), riscvCPUInit) import Fetch(fetchInstruction, debugInsn) import Decode(decode) import qualified Prelude as P data Args = Args { firmware :: FilePath } deriving (Show) data Simulation = Success [Machine] | Failure String deriving (Show) data Machine = Machine { cpu :: RISCVCPU, peripherals :: Peripherals } deriving (Generic, Show, Eq, NFDataX) simulationLoop :: Int -> Machine -> IO [Machine] simulationLoop 0 machine = return [machine] simulationLoop n machine = do let machinePeripherals = peripherals machine currPc = pc $ cpu machine fetchResult <- fetchInstruction machinePeripherals currPc let decodeResult = decode fetchResult putStrLn $ show decodeResult P.++ debugInsn fetchResult let pc' = currPc + 4 cpu' = (cpu machine) { pc = pc' } machine' = machine { cpu = cpu' } rest <- simulationLoop (n - 1) machine' return (machine : rest) simulation :: Args -> IO Simulation simulation args = do initializedPeripherals <- setupPeripherals (firmware args) case initializedPeripherals of InitializationError e -> return $ Failure e InitializedPeripherals ramDevice -> do let initState = Machine { cpu = riscvCPUInit, peripherals = Bus.Peripherals ramDevice } sim <- simulationLoop 15 initState teardownPeripherals return $ Success sim