Building an Order RISC-V CPU from scratch
This technical deep dive chronicles the journey of building Specula, an Out-of-Order RISC-V CPU, from its Bluespec SystemVerilog inception to booting xv6. The author meticulously details the complex microarchitectural design choices, from register renaming to branch prediction, that define modern processors. It's a testament to the Hacker News ethos of learning by doing, showcasing intense hardware design challenges and ingenious FPGA optimization strategies.
The Lowdown
The story details the ambitious personal project, Specula, to design and implement a 32-bit, single-issue, Out-of-Order (OoO) and speculative RISC-V processor from scratch. Driven by a desire for a deeper understanding of CPU architecture beyond basic university courses, the author embarked on creating a sophisticated processor capable of booting an educational operating system, all while navigating the complexities of hardware description languages and FPGA synthesis.
- Motivation and Initial Design: The project began out of boredom and a fascination with how modern "Out-of-Order" CPUs function, contrasting with simpler in-order designs. Specula evolved into a 32-bit, single-issue OoO processor leveraging register renaming and a reorder buffer, written in Bluespec SystemVerilog.
- Architectural Foundations: The author provides a crash course on OoO principles, explaining how it enables independent instructions to execute when ready, using mechanisms like register renaming to eliminate false dependencies, reservation stations for scheduling, and a reorder buffer for in-order retirement.
- Frontend and Backend: The frontend handles instruction fetching, Sv32 address translation, compressed instruction expansion, and employs a gshare branch predictor for efficient control flow. The backend manages register renaming, dispatches instructions to an 8-entry Reservation Station or Memory Queue, and tracks their progress via a 32-entry Reorder Buffer (ROB).
- Execution and Retirement: Instructions execute in the ALU, multiplier, or iterative divider. Memory operations utilize a Memory Queue with store forwarding. The ROB is crucial for ensuring instructions retire in program order and for handling misprediction recovery by flushing incorrect paths.
- Operating System Integration: A significant milestone involved extending Specula to support privileged modes, CSRs, trap handling, Sv32 virtual memory, and peripherals like UART, PLIC, and a VirtIO block device. This enabled the successful booting of
xv6-rv32in simulation. - FPGA Synthesis and Optimization: The project then moved to physical hardware, targeting an Artix-7 FPGA (Basys3). Initial synthesis results showed significant resource (LUT) and timing challenges, leading to extensive microarchitectural optimizations.
- Key Optimizations: Notable improvements included replacing a combinational divider with an iterative one, optimizing Memory Queue selection logic, restructuring Store Queue forwarding, reducing the ROB size, and pipelining memory stages. Frontend and dispatch logic were also refined.
- Final Results: After numerous experiments and iterations, Specula achieved 19,675 LUTs (94.59% of target capacity) and a Worst Negative Slack of -0.115 ns against a 100 MHz clock constraint in post-synthesis, demonstrating remarkable resource efficiency.
The project underscores the immense challenges and rewards of deep-seated computer architecture work. It serves as a comprehensive case study in tackling complex hardware design, from theoretical implementation to practical FPGA optimization, culminating in a functional Out-of-Order RISC-V core that successfully boots an operating system.