diff --git a/c/uart_sim_device.c b/c/uart_sim_device.c index 391c384..98af3ac 100644 --- a/c/uart_sim_device.c +++ b/c/uart_sim_device.c @@ -8,6 +8,8 @@ static volatile bool ctrl_c_received = false; static char last_char = '\0'; +int is_char_available(); + void sigint_handler(int sig_num) { ctrl_c_received = true; } diff --git a/hello.asm b/hello.asm deleted file mode 100644 index 64dc0bc..0000000 --- a/hello.asm +++ /dev/null @@ -1,22 +0,0 @@ - -./rv_tests/hello_world/hello.bin: file format binary - - -Disassembly of section .data: - -0000000000000000 <.data>: - 0: 00000597 auipc a1,0x0 - 4: 02458593 add a1,a1,36 # 0x24 - 8: 0005c503 lbu a0,0(a1) - c: 00050a63 beqz a0,0x20 - 10: 100002b7 lui t0,0x10000 - 14: 00a28023 sb a0,0(t0) # 0x10000000 - 18: 00158593 add a1,a1,1 - 1c: fedff06f j 0x8 - 20: 0000006f j 0x20 - 24: 6548 ld a0,136(a0) - 26: 6c6c ld a1,216(s0) - 28: 77202c6f jal s8,0x279a - 2c: 646c726f jal tp,0xc7672 - 30: 0a21 add s4,s4,8 - ... diff --git a/hs/Bus.hs b/hs/Bus.hs index f1b2167..c6edbc6 100644 --- a/hs/Bus.hs +++ b/hs/Bus.hs @@ -4,6 +4,7 @@ module Bus() where import Clash.Prelude import Peripherals.Ram(Ram, RamLine, read, RamAddr) +import Peripherals.Uart(UartAddr, read) import Machine(Peripherals(..)) import BusTypes( BusError(..), @@ -35,10 +36,19 @@ alignCheck addr SizeQuadWord = addr `mod` 16 == 0 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) + | (addr >= ramStart) && (addr <= ramEnd) = + return $ + ReadResponse $ + Result $ Peripherals.Ram.read size ramAddr (ram peripherals) + | (addr >= uartStart) && (addr <= uartEnd) = + ReadResponse . Result <$> + Peripherals.Uart.read size uartAddr | otherwise = return $ ReadResponse $ Error UnMapped where ramAddrNoOffset = addr - ramStart ramAddr :: RamAddr ramAddr = resize ramAddrNoOffset + + uartAddrNoOffset = addr - uartStart + uartAddr :: UartAddr + uartAddr = resize uartAddrNoOffset diff --git a/hs/Peripherals/Uart.hs b/hs/Peripherals/Uart.hs index 1a7ba45..98ced6a 100644 --- a/hs/Peripherals/Uart.hs +++ b/hs/Peripherals/Uart.hs @@ -1,8 +1,8 @@ -module Peripherals.Uart (read) where +module Peripherals.Uart (read, write, UartAddr) where import Clash.Prelude hiding (read) import Types (Byte) -import Data.Char (ord) +import Data.Char (ord, chr) import Peripherals.UartCFFI ( initTerminal, @@ -20,6 +20,7 @@ import BusTypes ( ReadResponse(..), WriteResponse(..) ) +import GHC.Generics (URec(UAddr), Generic (from)) -- based on a 16550 UART which has an address space of 8 bytes type UartAddr = Unsigned 3 @@ -28,6 +29,9 @@ type UartAddr = Unsigned 3 rbrAddr :: UartAddr rbrAddr = 0x0 +thrAddr :: UartAddr +thrAddr = 0x0 + -- Line Status Register address lsrAddr :: UartAddr lsrAddr = 0x5 @@ -50,8 +54,11 @@ buildRBR = do -- Reads the Line Status Register (LSR) to check character availability buildLSR :: IO Byte buildLSR = do - char_available <- isCharAvailable - return $ fromIntegral char_available + (char_available :: Byte) <- fromIntegral <$> isCharAvailable + -- highly unlikely that we overflow stdout buffer, so we set + -- transmit to always ready + let (transmit_ready :: Byte) = 0b0010_0000 + return (char_available .|. transmit_ready) -- Updated 'read' function to handle RBR and LSR reads read :: TransactionSize -> UartAddr -> IO BusVal @@ -59,3 +66,18 @@ read size addr | addr == rbrAddr = busValFromByte size <$> buildRBR | addr == lsrAddr = busValFromByte size <$> buildLSR | otherwise = return $ busValFromByte size 0x00 + +extractLowestByte :: BusVal -> Byte +extractLowestByte (BusByte b) = b +extractLowestByte (BusHalfWord hw) = resize hw +extractLowestByte (BusFullWord fw) = resize fw +extractLowestByte (BusDoubleWord dw) = resize dw +extractLowestByte (BusQuadWord qw) = resize qw + +byteToChar :: Byte -> Char +byteToChar = chr . fromIntegral + +write :: BusVal -> UartAddr -> IO () +write val addr + | addr == thrAddr = writeCharToTerminal $ byteToChar $ extractLowestByte val + | otherwise = return () diff --git a/rv_tests/hello.asm b/rv_tests/hello.asm deleted file mode 100644 index e69de29..0000000 diff --git a/rv_tests/hello_world/Makefile b/rv_tests/hello_world/Makefile index 07b15c3..87d8a1c 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 -device sifive_uart + $(QEMU) -machine virt -nographic -bios none -kernel $(BIN) -device loader,file=$(BIN),addr=0x80000000 # Clean up generated files clean: