packages feed

libriscv-0.1.0.0: test/ArchStateTest.hs

module ArchStateTest where

import Data.Array.IO (IOUArray)
import qualified Data.ByteString.Lazy as BSL
import Data.Word
import LibRISCV (RegIdx (..))
import LibRISCV.Effects.Operations.Default.Machine.Memory
import LibRISCV.Effects.Operations.Default.Machine.Register
import Test.Tasty
import Test.Tasty.HUnit

mkReg :: IO (RegisterFile IOUArray Word32)
mkReg = mkRegFile 0

registerTests :: TestTree
registerTests =
    testGroup
        "RegisterFile Tests"
        [ testCase "Read and write general-puropose register" $ do
            r <- mkReg
            writeRegister r A1 23
            regVal <- readRegister r A1
            assertEqual "" 23 regVal
        , testCase "Write zero register" $ do
            r <- mkReg
            writeRegister r Zero 42
            regVal <- readRegister r Zero
            assertEqual "" 0 regVal
        , testCase "Read and write program counter" $ do
            r <- mkReg
            initVal <- readPC r
            assertEqual "PC is zero initially" 0 initVal

            writePC r 1337
            regVal <- readPC r
            assertEqual "PC can be written" 1337 regVal

            writePC r 0
            regVal <- readPC r
            assertEqual "Zero can be written to PC" 0 regVal
        ]

memoryTests :: TestTree
memoryTests =
    testGroup
        "Memory Tests"
        [ testCase "Create memory and extract its size" $ do
            m <- mkMemory 0x0 512 :: IO (Memory IOUArray Word8)
            memSize m >>= assertEqual "" 512
        , testCase "Store and load byte" $ do
            m <- mkMemory 0x0 512 :: IO (Memory IOUArray Word8)
            storeByte m 0x4 0xab
            loadByte m 0x04 >>= assertEqual "" 0xab
        , testCase "Read uninitialized memory" $ do
            m <- mkMemory 0x0 256 :: IO (Memory IOUArray Word8)

            -- We don't really care what this evaluates to. This returns
            -- undefined values which is fine as long as the memory doesn't
            -- error on an uninitialized memory accesses.
            (loadWord m 128 :: IO Word32) >> pure ()
        , testCase "StoreWord in between" $ do
            m <- mkMemory 0x0 12 :: IO (Memory IOUArray Word8)
            storeWord m 0 (0xffffffff :: Word32)
            storeWord m 4 (0xffffffff :: Word32)
            storeWord m 8 (0xffffffff :: Word32)
            storeWord m 0x2 (0x12345678 :: Word32)
            (loadWord m 0 :: IO Word32) >>= assertEqual "1st word" 0x5678ffff
            (loadWord m 4 :: IO Word32) >>= assertEqual "2nd word" 0xffff1234
            (loadWord m 8 :: IO Word32) >>= assertEqual "3rd word" 0xffffffff
        , testCase "Store and load word" $ do
            m <- mkMemory 0x0 256 :: IO (Memory IOUArray Word8)
            storeWord m 8 (0xdeadbeef :: Word32)
            (loadWord m 8 :: IO Word32) >>= assertEqual "Load entire word" 0xdeadbeef
            loadByte m 8 >>= assertEqual "Load 1st byte" 0xef
            loadByte m 9 >>= assertEqual "Load 2nd byte" 0xbe
            loadByte m 11 >>= assertEqual "Load 4th byte" 0xde
        , testCase "Write ByteString in little endian byteorder" $ do
            m <- mkMemory 0x0 32 :: IO (Memory IOUArray Word8)
            let bs = BSL.pack [0xde, 0xad, 0xbe, 0xef]

            storeByteString fromIntegral m 0x0 bs
            (loadWord m 0x0 :: IO Word32) >>= assertEqual "" 0xefbeadde
        , testCase "Write ByteString with multiple bytes" $ do
            m <- mkMemory 0x0 8 :: IO (Memory IOUArray Word8)
            let bs = BSL.pack [0xde, 0xad, 0xbe, 0xef, 0x12, 0x23, 0x34, 0xff]

            storeByteString fromIntegral m 0x0 bs
            (loadWord m 0x0 :: IO Word32) >>= assertEqual "" 0xefbeadde
            (loadWord m 0x4 :: IO Word32) >>= assertEqual "" 0xff342312
        ]