Computer Architecture MOC

A map of the concepts behind a small RISC-V system on a chip and the microkernel that runs on it. This MOC organizes everything below the operating-system boundary: the instruction set architecture (ISA) that the CPU speaks, the microarchitecture that executes it (pipeline, hazards, forwarding, branch prediction), the memory protection and virtual memory that isolate processes, the privilege model and trap machinery that turns hardware events into software handlers, the SoC fabric and peripherals (bus, timer, interrupt controller, UART) that surround the core, and the kernel-level primitives (microkernel, scheduling, IPC) that sit just above the metal. Each section has a paragraph of framing and a list of atomic leaf notes. Read this MOC top-to-bottom for the layered picture; then dive into a leaf for depth.

This MOC is the technical companion to the definitely-not-esp32 project: a year-long, from-scratch RV32IMC SoC and Rust microkernel, developed in Verilator simulation first and then ported to a Tang Nano 20K FPGA, benchmarked honestly against a real ESP32-C3. The leaf notes here are concept references; the project’s own repo holds the spec, the RTL, the kernel code, and the blog series.


How the Pieces Fit Together

flowchart TB
  subgraph SW["Software"]
    USER["User processes (U-mode)"]
    KERN["Microkernel (M-mode)"]
    USER -- "ecall" --> KERN
  end
  subgraph CPU["CPU core"]
    ISA["RV32IMC + Zicsr"]
    PIPE["5-stage pipeline<br/>IF · ID · EX · MEM · WB"]
    HAZ["Hazard unit:<br/>forwarding, stalls, flush"]
    BP["2-bit branch predictor"]
    CSR["CSRs (mtvec, mepc, ...)"]
    TRAP["Trap handler entry"]
    PMP["PMP / MMU"]
    ISA --> PIPE
    PIPE <--> HAZ
    PIPE <--> BP
    PIPE <--> CSR
    CSR --> TRAP
    TRAP --> PMP
  end
  KERN -.->|"runs on"| CPU
  subgraph SOC["SoC fabric"]
    BUS{"Bus (Wishbone)"}
    ROM["Boot ROM"]
    RAM["Main RAM"]
    UART["UART"]
    CLINT["CLINT<br/>timer + sw IRQ"]
    PLIC["PLIC<br/>external IRQ"]
    BUS <--> ROM
    BUS <--> RAM
    BUS <--> UART
    BUS <--> CLINT
    BUS <--> PLIC
  end
  CPU <--> BUS
  CLINT -. "timer / sw IRQ" .-> TRAP
  PLIC -. "external IRQ" .-> TRAP
  UART -. "RX IRQ" .-> PLIC

The layered architecture covered by this MOC. What it shows: a single CPU core executes a fixed ISA through a 5-stage pipeline with hazard handling and branch prediction; CSRs and a trap handler turn hardware events into software dispatch; the core sits on a small bus that fans out to memory, a UART, and two interrupt controllers (CLINT for timer and software IRQs, PLIC for external IRQs); a microkernel in M-mode multiplexes user processes in U-mode, talking to the hardware through traps. The insight to take: every other section of this MOC is a zoom into one of these blocks.


1. Instruction Set Architecture

The contract between hardware and software. The ISA is the part the compiler and assembler target; the microarchitecture is how a specific CPU implements it. RISC-V is the modular open ISA used here. The base integer set (I) is fixed; M (multiply / divide), C (compressed), Zicsr (CSR access), and the privilege levels are optional extensions that get bolted on.

2. Building a Core: Datapath, Control, and the First Processor

Before a pipeline there has to be something to pipeline. These are the blocks a from-scratch RV32 core is actually made of, and the single-cycle machine that assembles them — correct, slow, and the golden reference model every later microarchitecture is differentially tested against.

2. Pipeline Mechanics

How a single ISA instruction actually flows through the CPU. The textbook 5-stage pipeline (Instruction Fetch, Decode, Execute, Memory, Writeback) is the lingua franca of computer architecture teaching. Pipelining buys parallelism, but introduces data and control hazards that have to be resolved with forwarding, stalls, and flushes. The effective performance metric is cycles per instruction (CPI), which the pipeline drives down and the hazards push back up.

3. Branch Prediction and Simulation Tooling

Branches are control hazards: the CPU does not know the next instruction’s address until the branch resolves. A predictor guesses, the pipeline speculates, and a misprediction flushes the in-flight work. A 2-bit saturating counter is the smallest predictor that does meaningfully better than always-taken. The tooling section pairs this with the simulator (Verilator) and FPGA target (Tang Nano 20K) used to verify the design, plus the abstraction level (register-transfer level, or RTL) at which the RTL is written.

4. Memory Protection and Virtual Memory

Two different mechanisms for keeping processes from stomping on each other. Physical Memory Protection (PMP) is a small bank of hardware comparators against physical addresses, cheap and sufficient for a microkernel. A Memory Management Unit (MMU) walks page tables to translate virtual addresses to physical ones, giving every process its own address space. Sv32 is the 32-bit RISC-V virtual memory scheme; the TLB caches translations; the PTE is the leaf entry in the page table. The project ships PMP in v1.0; MMU is a stretch.

5. Privilege, Traps, and System Calls

How the hardware switches privilege levels and hands control to software on events (interrupts, exceptions, syscalls). Control and Status Registers (CSRs) hold the trap vector, the saved PC, the cause, and the interrupt enable bits. The trap handler is the kernel entry point. The ecall instruction is the explicit “I want a syscall” trap. Trap delegation lets M-mode hand certain traps directly to S-mode without a round trip; the Supervisor Binary Interface (SBI) is the standard ABI between the M-mode firmware and an S-mode kernel.

6. SoC Fabric and Peripherals

The hardware around the core. A SoC is “system on a chip”: CPU plus memories plus peripherals on one die, glued by a bus. Wishbone is the open bus standard used here. CLINT is the standard RISC-V Core Local Interruptor (machine timer plus software interrupt). PLIC is the Platform-Level Interrupt Controller that prioritizes and routes external IRQs. UART is the venerable serial port that doubles as the kernel’s console.

7. Kernel-Level Primitives

The smallest set of OS concepts the microkernel needs. A microkernel keeps only the unavoidable parts (traps, scheduling, IPC, address-space protection) in privileged mode and pushes everything else into user processes. Round-robin scheduling is the simplest fair scheduler. Synchronous IPC (rendezvous) is the simplest message-passing primitive: sender blocks until receiver is ready, no buffering. Both are the v1.0 defaults; priority scheduling and async channels are stretches.

8. Reference Hardware

The reference point the project benchmarks against, and the FPGA target the design ports to.


This MOC is part of definitely-not-esp32: a from-scratch RV32IMC SoC plus Rust microkernel, simulated in Verilator and ported to a Tang Nano 20K FPGA, benchmarked against an ESP32-C3. The project repo (spec, roadmap, RTL, kernel) lives outside this vault.

Open Threads

Round 2 leaves: complete

All five round-2 leaves are now written and verified:

Stretch and future leaves

Uncertainty triage — resolved 2026-08-08

A four-agent pass closed 16 of 17 open [!warning] Uncertain callouts across these leaves. Each resolution now sits inline in its note as a [!success] Resolved 2026-08-08 callout with primary citations. This list is rebuilt from a disk scan, not maintained by hand — re-scan before trusting it.

Resolved — the claim was true, now cited:

  • RISC-V Instruction Set Architecture: RV32E/RV64E are Ratified at v2.0. The stale “v1.9 Draft” datum survives only inside the archived 20191213 preface, which the manual reproduces verbatim. Version bumped 1.95→2.0 in commit fefbe61, 2023-01-25.
  • RISC-V Privilege Modes: N extension removed in privileged release 20211203 (Priv ISA 1.12). src/n.tex deleted 2021-07-06, commit b6cade07, Andrew Waterman.
  • Memory Management Unit · Page Table Entry: no profile mandates Svadu. RVA20/22/23S64 all mandate Svade; RVA23S64 adds Svadu as an optional expansion option. The Svade/Svadu names were minted by the profiles WG (renamed from Ssptead, 2023-04-02) and only absorbed into the privileged manual at release 20241017.
  • Supervisor Binary Interface: SBI v3.0 ratified 2025-07-16. OpenSBI has reported SBI 3.0 since v1.7 (2025-06-30).
  • Verilator: 5.048 released 2026-04-26 (from the Changes file and the annotated tag).
  • RV32IMC: Rust riscv32imc-unknown-none-elf is Tier 2 (Rust 1.97.1).
  • Physical Memory Protection: ARM PMSAv7/v8 bit layouts now read from the actual Architecture Reference Manuals.
  • Microkernel: Liedtke’s minimality principle now quoted verbatim from the 1995 SOSP paper (§2, p. 2).

Resolved — the claim was WRONG or unsourced, and the note was corrected:

  • Classic Five-Stage Pipeline · ESP32-C3: the SiFive E2 lineage claim is unsourced. Zero occurrences of “SiFive” in TRM v1.4 or Datasheet v2.4; the core hardwires Espressif’s own mvendorid=0x612 / marchid=0x80000001 (SiFive’s registered ID is 0x489). The rumour traces to a reader’s forum post of 2020-11-21 whose sole argument (“it has an FPU, so it must be the E24”) is false — misa hardwires F=D=0 — and was corrected in-thread by SiFive’s Jim Wilson.
  • Branch Prediction: the ESP32-C3 has no branch predictor. No “predict”/“BTB”/“speculat” in the TRM; mpcer exposes a jump-hazard counter and no mispredict counter; ESP-IDF defines SOC_BRANCH_PREDICTOR_SUPPORTED for the P4/C5 but not the C3.
  • Branch Prediction: the Intel TAGE claim is vendor-UNDISCLOSED. Zero standalone “TAGE” hits in Intel’s Optimization Reference Manual 248966-050US. The claim rests on third-party reverse engineering (Half&Half, IEEE S&P 2023; Pathfinder, ASPLOS 2024) and is now attributed as such, bounded to Raptor Lake (2022) — the newest core with published reconstruction.
  • RISC-V Privilege Modes: the note’s medeleg/mideleg “read-as-zero” claim was wrong — Priv v1.10 §3.1.12 says they should not exist in M+U-without-N systems; read-as-zero was the pre-1.10 convention.
  • System on a Chip: the M4 Max transistor count is unpublished. Apple states 28 billion for the base M4 and zero times for the Pro/Max. The circulating ~95 billion is an unsourced extrapolation.
  • Field-Programmable Gate Array: the Tang Nano 20K has no citable list price; recorded as a dated range (USD 25–40, 2026-08-08) with an evidence table.

Still open (1):

  • RISC-V Privilege Modes: whether any N-extension revival proposal is currently active. Deliberately left open — absence of a task-group proposal is a negative the spec repo cannot prove. To resolve: RVI task-group roster + tech-announce archive.

Corrections worth carrying to other notes

  • Espressif contradicts itself in print: Datasheet v2.4 §4.1.1.1 says “32 vectored interrupts at seven priority levels”; TRM v1.4 §1.5 says 31 (IDs 1–31) at 15 levels.
  • The C3’s PMP is not fully compliant (TRM §1.8.1): no static priority, so overlapping entries fail open; max NAPOT region 1 GB.
  • PMSAv8-M forbids overlapping MPU regions (a MemManage fault, rule RLLLP) — so the three designs are three distinct points: RISC-V lowest-index-wins, PMSAv7 highest-index-wins, PMSAv8-M no-overlap.
  • Do not cite OpenSBI’s README for spec support — it still claims “fully supports SBI specification v0.2”, contradicting its own version macro.
  • RV128I no longer exists in the manual; removed as unratified content in the 20240411 release.