diff --git a/hs/Bus.hs b/hs/Bus.hs index d7d4701..a2f749c 100644 --- a/hs/Bus.hs +++ b/hs/Bus.hs @@ -3,7 +3,7 @@ module Bus() where import Clash.Prelude -import Peripherals.Ram(Ram, RamLine) +import Peripherals.Ram(Ram, RamLine, read, RamAddr) import Machine(Peripherals(..)) import BusTypes( BusError(..), @@ -16,24 +16,33 @@ import BusTypes( ) import Types(Addr, Byte, HalfWord, FullWord, DoubleWord, QuadWord) +import Peripherals.Ram(read, bytesInRam) +import Distribution.Types.UnitId (DefUnitId(unDefUnitId)) alignCheck :: Addr -> TransactionSize -> Bool alignCheck addr SizeByte = True alignCheck addr SizeHalfWord = addr `mod` 2 == 0 -alignCheck addr SizeWord = addr `mod` 4 == 0 +alignCheck addr SizeFullWord = addr `mod` 4 == 0 alignCheck addr SizeDoubleWord = addr `mod` 8 == 0 alignCheck addr SizeQuadWord = addr `mod` 16 == 0 --- ram shoudl start at 0x80000000 +-- address space follows QEMU behavior for now +(ramStart, ramEnd) = (0x80000000 :: Addr, ramStart + (bytesInRam - 1)) +(uartStart, uartEnd) = (0x10000000 :: Addr, uartStart + 7) --- concatWords :: [Ram -> Addr -> RamLine] -> Ram -> Addr -> RamLine --- concatWords readers ram baseAddr = foldl (\acc f -> (acc `shiftL` 32) .|. f ram baseAddr) 0 readers +read :: Request -> Peripherals -> IO ReadResponse +read (Request addr size) peripherals + | not (alignCheck addr size) = return $ ReadResponse $ Error UnAligned + | (addr > ramStart) && (addr < ramEnd) = + return $ ReadResponse $ Result $ Peripherals.Ram.read size ramAddr (ram peripherals) + | otherwise = return $ ReadResponse $ Error UnMapped + where + ramAddrNoOffset = addr - ramStart + ramAddr :: RamAddr + ramAddr = resize ramAddrNoOffset --- read :: Request -> Peripherals -> ReadResponse --- read (Request addr size) peripherals --- | not (alignCheck addr size) = ReadError UnAligned + -- | (addr > ramStart) && (addr < ramEnd) = return $ ReadResponse $ Peripherals.Ram.read addr size (ram peripherals) -- | addr >= numBytesInRam = ReadError UnMapped --- | otherwise = -- case size of -- SizeByte -> BusByte $ fromIntegral $ extractByte (ramRead 0) -- SizeHalfWord -> BusHalfWord $ fromIntegral $ (ramRead 0 `shiftL` 8) .|. ramRead 1 diff --git a/hs/BusTypes.hs b/hs/BusTypes.hs index ec17998..628371e 100644 --- a/hs/BusTypes.hs +++ b/hs/BusTypes.hs @@ -11,8 +11,6 @@ module BusTypes( import Clash.Prelude -import Peripherals.Ram(Ram, RamLine) -import Machine(Peripherals(..)) import Types(Addr, Byte, HalfWord, FullWord, DoubleWord, QuadWord) @@ -24,7 +22,7 @@ data BusError data TransactionSize = SizeByte | SizeHalfWord - | SizeWord + | SizeFullWord | SizeDoubleWord | SizeQuadWord deriving (Generic, Show, Eq, NFDataX) @@ -40,7 +38,7 @@ data BusResponse a data BusVal = BusByte Byte | BusHalfWord HalfWord - | BusWord FullWord + | BusFullWord FullWord | BusDoubleWord DoubleWord | BusQuadWord QuadWord deriving (Generic, Show, Eq, NFDataX) diff --git a/hs/Peripherals/Ram.hs b/hs/Peripherals/Ram.hs index 81a5ccc..50acc50 100644 --- a/hs/Peripherals/Ram.hs +++ b/hs/Peripherals/Ram.hs @@ -5,12 +5,14 @@ module Peripherals.Ram( initRamFromFile, + RamAddr, Ram, RamLine, - -- Peripherals.Ram.read, + bytesInRam, + read, write) where -import Clash.Prelude +import Clash.Prelude hiding (read) import qualified Prelude as P import qualified Data.ByteString.Lazy as BL import Data.Binary.Get @@ -18,6 +20,15 @@ import Data.Int (Int32) import qualified Clash.Sized.Vector as Vec import Types(Addr, Byte, HalfWord, FullWord, DoubleWord, QuadWord) +import BusTypes( + BusError(..), + TransactionSize(..), + Request(..), + BusResponse(..), + BusVal(..), + ReadResponse(..), + WriteResponse(..) + ) -- vector depth has to be known statically at compile time #ifndef _RAM_DEPTH @@ -28,46 +39,54 @@ import Types(Addr, type Ram = Vec _RAM_DEPTH (Unsigned 32) type RamAddr = Unsigned (CLog 2 _RAM_DEPTH) type RamLine = Unsigned 32 -bytesInRam = 1024 * 4 +bytesInRam :: Addr +bytesInRam = _RAM_DEPTH * 4 -readByte0 :: Ram -> RamAddr -> Byte -readByte0 ram addr = unpack $ slice d31 d24 word - where word = ram !! addr - -readByte1 :: Ram -> RamAddr -> Byte -readByte1 ram addr = unpack $ slice d23 d16 word - where word = ram !! addr - -readByte2 :: Ram -> RamAddr -> Byte -readByte2 ram addr = unpack $ slice d15 d8 word - where word = ram !! addr - -readByte3 :: Ram -> RamAddr -> Byte -readByte3 ram addr = unpack $ slice d7 d0 word - where word = ram !! addr - -readHalfWord0 :: Ram -> RamAddr -> HalfWord -readHalfWord0 ram addr = unpack $ slice d31 d16 word - where word = ram !! addr - -readHalfWord1 :: Ram -> RamAddr -> HalfWord -readHalfWord1 ram addr = unpack $ slice d15 d0 word - where word = ram !! addr - -readFullWord :: Ram -> RamAddr -> FullWord -readFullWord ram addr = ram !! addr - -readDoubleWord :: Ram -> RamAddr -> DoubleWord -readDoubleWord ram addr = bitCoerce $ bitCoerce word0 ++# bitCoerce word1 +read :: TransactionSize -> RamAddr -> Ram -> BusVal +read SizeByte addr ram = BusByte $ unpack byte where - word0 = readFullWord ram addr - word1 = readFullWord ram (addr + 1) + word = ram !! addr + byteOffset :: BitVector 2 + byteOffset = slice d1 d0 addr + byte = case byteOffset of + 0b00 -> slice d31 d24 word + 0b01 -> slice d23 d16 word + 0b10 -> slice d15 d8 word + 0b11 -> slice d7 d0 word -readQuadWord :: Ram -> RamAddr -> QuadWord -readQuadWord ram addr = bitCoerce $ bitCoerce dword0 ++# bitCoerce dword1 +read SizeHalfWord addr ram = BusHalfWord $ unpack halfWord where - dword0 = readDoubleWord ram addr - dword1 = readDoubleWord ram (addr + 2) + word = ram !! addr + halfWordOffset :: Unsigned 1 + halfWordOffset = unpack $ slice d0 d0 addr + halfWord = case halfWordOffset of + 0b0 -> slice d31 d16 word + 0b1 -> slice d15 d0 word + +read SizeFullWord addr ram = BusFullWord fullWord + where + fullWord = ram !! addr + +read SizeDoubleWord addr ram = BusDoubleWord doubleWord + where + doubleWord = bitCoerce $ bitCoerce word0 ++# bitCoerce word1 + word0 = readFullWordHelper ram addr + word1 = readFullWordHelper ram (addr + 1) + +read SizeQuadWord addr ram = BusQuadWord quadWord + where + quadWord = bitCoerce $ bitCoerce dword0 ++# bitCoerce dword1 + dword0 = readDoubleWordHelper ram addr + dword1 = readDoubleWordHelper ram (addr + 2) + +readFullWordHelper :: Ram -> RamAddr -> FullWord +readFullWordHelper ram addr = ram !! addr + +readDoubleWordHelper :: Ram -> RamAddr -> DoubleWord +readDoubleWordHelper ram addr = bitCoerce $ bitCoerce word0 ++# bitCoerce word1 + where + word0 = readFullWordHelper ram addr + word1 = readFullWordHelper ram (addr + 1) write :: Ram -> RamAddr -> RamLine -> Ram write ram addr value = replace addr value ram diff --git a/rv_tests/hello_world/Makefile b/rv_tests/hello_world/Makefile index 87d8a1c..07b15c3 100644 --- a/rv_tests/hello_world/Makefile +++ b/rv_tests/hello_world/Makefile @@ -34,7 +34,7 @@ $(BIN): $(ELF) # Run in QEMU run: $(BIN) echo "Press CTRL+A then X to exit QEMU" - $(QEMU) -machine virt -nographic -bios none -kernel $(BIN) -device loader,file=$(BIN),addr=0x80000000 + $(QEMU) -machine virt -nographic -bios none -kernel $(BIN) -device loader,file=$(BIN),addr=0x80000000 -device sifive_uart # Clean up generated files clean: