# RISC-V Bare-Metal I/O Starter Project

Supplementary material for  
**Computer Architecture: Design and Analysis** (2026 edition)  
Krerk Piromsopa, Ph.D. · Department of Computer Engineering · Chulalongkorn University

---

## Overview

This starter project provides the minimum scaffolding needed for the **I/O activity** in Appendix D of the textbook.  
You will implement a UART driver in two flavors — **polling** and **interrupt-driven** — and compare CPU utilization between them.

| File | Description |
|---|---|
| `startup.S` | Reset vector, BSS zero-fill, trap entry point |
| `link.ld` | Linker script (DRAM at `0x80000000`) |
| `platform.h` | UART, PLIC, CLINT register addresses and CSR helpers |
| `uart.h` | Driver interface (function declarations) |
| `uart.c` | **← Fill in the TODOs** |
| `main.c` | **← Entry point + trap handler; fill in the TODOs** |
| `Makefile` | `make` / `make run` / `make dump` |

---

## Prerequisites

### 1 — RISC-V toolchain

| OS | Install command |
|---|---|
| Debian / Ubuntu | `sudo apt install gcc-riscv64-linux-gnu` then symlink as 32-bit, **or** build `riscv32-unknown-elf-gcc` from source |
| macOS | `brew install riscv-gnu-toolchain` |
| Windows | Use WSL2 (Ubuntu) and follow the Debian instructions above |

> **Tip:** If you only have the 64-bit bare-metal toolchain (`riscv64-unknown-elf-gcc`), edit the `Makefile` and set `CROSS = riscv64-unknown-elf`. The flags `-march=rv32ima -mabi=ilp32` force it to produce 32-bit output.

### 2 — QEMU

```
# Debian / Ubuntu
sudo apt install qemu-system-misc

# macOS
brew install qemu
```

Verify: `qemu-system-riscv32 --version`

---

## Build and Run

```bash
# Build
make

# Run in QEMU (opens a serial terminal in your shell)
make run
# Press Ctrl-A then X to quit QEMU
```

Expected output after Exercise 1 is complete:

```
=== Polling echo ready (press keys, Ctrl-A X to exit QEMU) ===
Hello!   ← characters you type appear echoed back
```

---

## QEMU Machine: `virt`

The Makefile targets `qemu-system-riscv32 -machine virt`.

| Resource | Address |
|---|---|
| DRAM | `0x8000_0000` (128 MB default) |
| UART0 (NS16550A) | `0x1000_0000` |
| PLIC | `0x0C00_0000` |
| CLINT | `0x0200_0000` |
| UART0 PLIC source | 10 |

---

## Exercise Guide

### Exercise 1 — Polling driver

1. Open `uart.c`.  
2. Implement `uart_init()`: configure baud rate (38400), 8N1, enable FIFOs.  
3. Implement `uart_putc()`: spin on `UART_LSR_THRE`, then write to `UART_THR`.  
4. Implement `uart_getc()`: spin on `UART_LSR_DR`, then read `UART_RBR`.  
5. In `main.c`, confirm `polling_echo()` is called from `main()`.  
6. `make run` — type characters; each should echo back.

Answer the questions in the textbook (CPU utilization, throughput, Fibonacci conflict).

### Exercise 2 — Interrupt-driven driver

1. Implement `uart_init_irq()` in `uart.c`: enable RX interrupt in IER, configure PLIC, enable `MIE_MEIE` in `mie` and `MSTATUS_MIE` in `mstatus`.  
2. Implement `uart_rx_isr()`: claim PLIC, read `RBR`, enqueue into the ring buffer, complete PLIC.  
3. Implement `uart_getc_irq()`: dequeue from the ring buffer.  
4. In `main.c`, switch to `irq_echo()` and fill in the dequeue-and-echo line.  
5. `make run` — type characters while Fibonacci runs in the background.

Answer the questions in the textbook (cycles per character, Fibonacci slowdown, missing complete-interrupt bug).

### Exercise 3 — Analysis

Fill in the table in the textbook comparing the two drivers across CPU cycles, utilization, and latency metrics.

### Exercise 4 (optional) — DMA

If you have access to a platform with a DMA controller, extend the TX path to use DMA bulk transfers and compare CPU cycles per character.

---

## Disassembly / Debugging

```bash
# View disassembly with interleaved C source
make dump | less

# Debug in QEMU GDB stub
# Terminal 1:
qemu-system-riscv32 -machine virt -bios none -kernel app.elf -nographic -S -gdb tcp::1234

# Terminal 2:
riscv32-unknown-elf-gdb app.elf
(gdb) target remote :1234
(gdb) break main
(gdb) continue
```

---

## Licence

This project is provided for educational use.  
© 2016–2026 Krerk Piromsopa, Ph.D.  No warranty is given.
