# Assignment 3: Construct a RISC-V CPU with Chisel contributed by <[Wei-Chen Lai](https://github.com/Winstonllllai)> [**`code`**](https://github.com/Winstonllllai/ca2025-HW3) :::spoiler **Table of Content** [TOC] ::: ## Set up Environment ### Install Dependent Packages To run this project on MacOS 26 ``` $ brew install verilator ``` ### Install sbt ``` bash # Uninstall everything brew uninstall sbt brew uninstall jenv # Install sdkman curl -s "https://get.sdkman.io" | bash source "$HOME/.sdkman/bin/sdkman-init.sh" # Install Eclipse Temurin JDK 11 sdk install java 11.0.29-tem sdk install sbt ``` ### Install GTKwave & Surfer [GTKwave](https://gtkwave.sourceforge.net/) & [Surfer](https://surfer-project.org/) are tools to view the waveform of signals - Install Icarus Verilog ``` brew install icarus-verilog ``` - GTKwave ``` brew install desktop-file-utils shared-mime-info\ gobject-introspection gtk-mac-integration \ meson ninja pkg-config gtk+3 gtk4 git clone "https://github.com/gtkwave/gtkwave.git" cd gtkwave meson setup build && cd build && meson install ``` - Surfer ``` $ brew install verilator surfer ``` ## Learn Chisel! [Chisel](https://www.chisel-lang.org/) stands for Constructing Hardware in a [Scala](https://www.scala-lang.org/) Embedded Language. It is an open-source hardware construction language developed by UC Berkeley. Its most famous application is in the design of RISC-V processors (such as Rocket Chip and BOOM). Essence: It is not a brand-new standalone language; rather, it is a "Domain-Specific Language" (DSL) embedded within the Scala programming language. Core Concept: "Hardware Generator". The Chisel code is actually a Scala program. When this program is executed, it generates the corresponding circuit logic (which is ultimately converted into Verilog). ### Pros & Cons #### Pros - High Parameterization: Ideal for creating flexible, modular designs (like CPUs). - Concise Code: Drastically reduces boilerplate using Object-Oriented features. - Type Safety: Catches wiring and width errors before generating Verilog. - Ecosystem: Strong support from the open-source RISC-V community. #### Cons - Steep Learning Curve: Requires mastering Scala and functional programming. - Tricky Debugging: Difficult to map simulation errors back to the original Chisel code. - Complex Setup: Requires software-centric tools (JDK, SBT) unfamiliar to many hardware engineers. ### How to Get Start We Learn Chisel from [Chisel Bootcamp](https://github.com/freechipsproject/chisel-bootcamp) [Learn Chisel Online](https://mybinder.org/v2/gh/sysprog21/chisel-bootcamp/HEAD) #### To run Chsel Bootcamp on MacOS locally run instruction bellow ``` pip3 install --upgrade pip pip3 install jupyter --ignore-installed pip3 install jupyterlab ``` ``` curl -L -o coursier https://git.io/coursier-cli && chmod +x coursier SCALA_VERSION=2.12.10 ALMOND_VERSION=0.9.1 ./coursier bootstrap -r jitpack \ -i user -I user:sh.almond:scala-kernel-api_$SCALA_VERSION:$ALMOND_VERSION \ sh.almond:scala-kernel_$SCALA_VERSION:$ALMOND_VERSION \ --sources --default=true \ -o almond ./almond --install ``` Install Bootcamp ``` git clone https://github.com/freechipsproject/chisel-bootcamp.git cd chisel-bootcamp mkdir -p ~/.jupyter/custom cp source/custom.js ~/.jupyter/custom/custom.js ``` ``` jupyter notebook ``` ### 1. Basic Data Types Chisel types define hardware wires, distinct from Scala types. * **Unsigned Integer:** `UInt(8.W)` (8-bit width) * **Signed Integer:** `SInt(10.W)` (10-bit width) * **Boolean:** `Bool()` (1-bit) * **Literals:** * `10.U` (Width inferred) * `"hff".U(8.W)` (Hex explicit width) * `true.B`, `false.B` ### 2. Modules & IO All hardware must extend `Module`. Ports are defined in `IO`. ```scala class MyModule extends Module { val io = IO(new Bundle { val a = Input(UInt(8.W)) val b = Input(UInt(8.W)) val out = Output(UInt(8.W)) }) // Logic io.out := io.a + io.b } ``` ### 3. Connections & Operators Connect signals from **right to left**. * **Assignment:** `:=` * **Arithmetic:** `+`, `-`, `*`, `/`, `%` * **Bitwise:** `&`, `|`, `^`, `~` * **Shift:** `<<` (Left), `>>` (Right) * **Comparison:** `===` (Equal), `=/=` (Not Equal), `>`, `<` * **Bit Extraction:** `val x = sig(3, 0)` * **Concatenation:** `val cat = Cat(high, low)` ### 4. Registers (Sequential Logic) Clock and Reset are implicit. * **Reg with Reset (Best Practice):** `val reg = RegInit(0.U(8.W))` * **Simple Reg:** `val reg = Reg(UInt(8.W))` * **RegNext (Delay):** `val delayed = RegNext(io.in)` ### 5. Control Flow **Note:** Use `when` for hardware, not Scala's `if`. * **Conditional:** ```scala when(io.a > 10.U) { reg := 1.U } .elsewhen(io.a === 0.U) { reg := 2.U } .otherwise { reg := 0.U } ``` * **Multiplexer:** `Mux(cond, trueVal, falseVal)` * **Switch/Is:** ```scala import chisel3.util._ switch(state) { is(sIdle) { /* logic */ } } ``` ## Minimal CPU The CPU supports exactly these RISC-V instructions: * `AUIPC` (Add Upper Immediate to PC) - for PC-relative addressing * `ADDI` (Add Immediate) - for arithmetic and register initialization * `LW` (Load Word) - word-aligned memory reads only * `SW` (Store Word) - word-aligned memory writes only * `JALR` (Jump and Link Register) - for function calls and returns ### Test result ``` [info] JITTest: [info] Minimal CPU - JIT Test [info] - should correctly execute jit.asmbin and set a0 to 42 [info] Run completed in 35 seconds, 469 milliseconds. [info] Total number of tests run: 1 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. ``` ## RISC-V Single Cycle CPU ![image](https://hackmd.io/_uploads/HygnIY28yZx.png) Adopts a single-cycle execution model where each instruction completes in one clock cycle (CPI = 1). Since there is no pipelining design, there are no data or control hazards. Instruction Set: Fully supports the RV32I base integer instruction set. Memory: Uses Harvard Architecture, separating instruction and data memory to avoid access conflicts. ### Supported Instructions * Arithmetic and Logic Instructions: ```add```, ```sub```, ```slt```, etc. * Memory Access Instructions: ```lb```, ```lw```, ```sb```, etc. * Branch Instructions: ```beq```, ```jar```, etc. ### Exercises * **InstructionDecode.scala:** * `Exercise 1`: Implement immediate extension and bit reordering for S, B, and J types. * `Exercise 2`: Generate control signals for write-back sources and ALU operand selection. * **ALUControl.scala:** * `Exercise 3`: Decode Opcode, Funct3, and Funct7 to generate correct ALU operation codes. * **Execute.scala:** * `Exercise 4`: Implement comparison logic for all six branch instructions (e.g., BEQ, BNE). * `Exercise 5`: Calculate jump target addresses for Branch, JAL, and JALR instructions. * **MemoryAccess.scala:** * `Exercise 6`: Handle sign-extension and zero-extension for Load instructions. * `Exercise 7`: Generate byte strobes and align data for Store instructions. * **WriteBack.scala:** * `Exercise 8`: Implement the multiplexer to select the register write-back source (ALU/Memory/PC+4). * **InstructionFetch.scala:** * `Exercise 9`: Implement PC update logic to handle sequential execution and jumps. ## Testcases * **Unit Tests** * `InstructionFetchTest`: Verifies the Program Counter (PC) update logic, including sequential execution (PC+4) and handling of Jump instructions. * `InstructionDecoderTest`: Checks if the decoder correctly parses various RV32I instruction formats (R, I, S, B, U, J types) and generates accurate control signals (e.g., ALU source selection, register write enable). * `ExecuteTest`: Validates ALU operations (arithmetic, logic, shift, comparison) and the decision logic for Branch instructions. * `RegisterFileTest`: Tests register read/write behavior, ensuring register x0 is always zero and supporting write-through. * **Integration Tests** (CPUTest.scala) * `FibonacciTest`: Executes a recursive Fibonacci program (fibonacci.asmbin) to verify function calls and stack operations. * `QuicksortTest`: Runs a quicksort program (quicksort.asmbin) to sort 10 numbers, verifying complex control flow and data processing. * `ByteAccessTest`: Runs a byte access program (sb.asmbin) to verify lb/sb instructions for memory access, alignment, and sign extension correctness. ### Test Result ``` [info] InstructionDecoderTest: [info] InstructionDecoder [info] - should decode RV32I instructions and generate correct control signals [info] ByteAccessTest: [info] Single Cycle CPU - Integration Tests [info] - should correctly handle byte-level store/load operations (SB/LB) [info] InstructionFetchTest: [info] InstructionFetch [info] - should correctly update PC and handle jumps [info] ExecuteTest: [info] Execute [info] - should execute ALU operations and branch logic correctly [info] FibonacciTest: [info] Single Cycle CPU - Integration Tests [info] - should correctly execute recursive Fibonacci(10) program [info] RegisterFileTest: [info] RegisterFile [info] - should correctly read previously written register values [info] - should keep x0 hardwired to zero (RISC-V compliance) [info] - should support write-through (read during write cycle) [info] QuicksortTest: [info] Single Cycle CPU - Integration Tests [info] - should correctly execute Quicksort algorithm on 10 numbers [info] Run completed in 20 seconds, 523 milliseconds. [info] Total number of tests run: 9 [info] Suites: completed 7, aborted 0 [info] Tests: succeeded 9, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. ``` ### RISCOF Compliance Test ``` Validating RISCOF installation... RISCOF found: /Users/winston/miniconda3/envs/chisel/bin/riscof Version: RISC-V Architectural Test Framework., version 1.25.3 Running RISCOF compliance tests for 1-single-cycle (RV32I)... Running RISCOF compliance tests for 1-single-cycle... Using config: config-1-single-cycle.ini Using RISCOF: /Users/winston/miniconda3/envs/chisel/bin/riscof Using toolchain: Starting compliance test run at Mon Dec 8 14:14:03 CST 2025 This may take 10-15 minutes for the full test suite... INFO | ****** RISCOF: RISC-V Architectural Test Framework 1.25.3 ******* INFO | using riscv_isac version : 0.18.0 INFO | using riscv_config version : 3.18.3 INFO | Reading configuration from: /Users/winston/Documents/ca2025-HW3/tests/config-1-single-cycle.ini INFO | Preparing Models INFO | Input-ISA file INFO | ISACheck: Loading input file: /Users/winston/Documents/ca2025-HW3/tests/mycpu_plugin/mycpu_isa_rv32i.yaml INFO | ISACheck: Load Schema /Users/winston/miniconda3/envs/chisel/lib/python3.13/site-packages/riscv_config/schemas/schema_isa.yaml INFO | ISACheck: Processing Hart:0 INFO | ISACheck: Initiating Validation for Hart:0 INFO | ISACheck: No errors for Hart:0 INFO | ISACheck: Updating fields node for each CSR in Hart:0 INFO | ISACheck: Dumping out Normalized Checked YAML: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_1sc/mycpu_isa_rv32i_checked.yaml INFO | Input-Platform file INFO | Loading input file: /Users/winston/Documents/ca2025-HW3/tests/mycpu_plugin/mycpu_platform.yaml INFO | Load Schema /Users/winston/miniconda3/envs/chisel/lib/python3.13/site-packages/riscv_config/schemas/schema_platform.yaml INFO | Initiating Validation INFO | No Syntax errors in Input Platform Yaml. :) INFO | Dumping out Normalized Checked YAML: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_1sc/mycpu_platform_checked.yaml INFO | Generating database for suite: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite INFO | Database File Generated: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_1sc/database.yaml INFO | Env path set to/Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/env INFO | Running Build for DUT INFO | Running Build for Reference INFO | Selecting Tests. INFO | Running Tests on DUT. INFO | === BATCH MODE: Preparing 41 tests === INFO | Compiling test 1/41: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/add-01.S ... INFO | Compiling test 41/41: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign1-jalr-01.S INFO | === Generating batch test file with 41 tests === INFO | === Running all 41 tests in single SBT session === INFO | [1/41] Running: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/add-01.S ... INFO | [41/41] Running: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign1-jalr-01.S INFO | Batch test completed. Full log: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_1sc/batch_test.log INFO | Results: 41 passed, 0 failed INFO | Running Tests on Reference Model. INFO | Reference signature generated: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_1sc/rv32i_m/I/src/add-01.S/ref/Reference-rv32emu.signature ... INFO | Reference signature generated: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_1sc/rv32i_m/privilege/src/misalign1-jalr-01.S/ref/Reference-rv32emu.signature INFO | Initiating signature checking. INFO | Following 41 tests have been run : INFO | TEST NAME : COMMIT ID : STATUS INFO | /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/add-01.S : - : Passed ... INFO | Test report generated at /Users/winston/Documents/ca2025-HW3/tests/riscof_work_1sc/report.html. INFO | Opening test report in web-browser βœ… Compliance tests complete. Results in riscof_work_1sc/ Completion time: Mon Dec 8 14:16:28 CST 2025 Copying results to results/ directory... Cleaning up auto-generated RISCOF test files... βœ… Compliance tests complete. Results in results/ πŸ“Š View report: results/report.html ``` ## RISC-V CPU with MMIO Peripherals and Trap Handling * **Extensions**: Based on the single-cycle design, adds the Zicsr extension (CSR registers) and the Machine-mode privilege architecture. * **Peripherals & Interrupts**: Integrates Timer, UART, and VGA peripherals via MMIO, and introduces the CLINT (Core-Local Interrupt Controller) to handle hardware interrupts and software traps. * **Atomicity**: Ensures the atomicity of interrupt handling and CSR updates; CLINT write operations take priority over CPU instructions. ### Exercises * **CSR.scala:** * `Exercise 10`: Implement the CSR register lookup table (mapping addresses to mstatus, mepc, etc.). * `Exercise 11`: Implement CSR write priority logic to prioritize CLINT updates. * **WriteBack.scala:** * `Exercise 12` (WriteBack Source Selection): Extend the write-back multiplexer to include CSR read data (RegWriteSource.CSR) as a source, enabling the result of CSR instructions to be written to the register file. * **MemoryAccess.scala:** * `Exercise 12` (Load Data Extension): Implement sign and zero extension for load instructions (LB, LBU, LH, LHU). This requires extracting the correct byte or halfword based on the address alignment (mem_address_index) and extending it to 32 bits. * **CLINT.scala:** * `Exercise 13`: Implement mstatus state transition for interrupt entry (save MIE to MPIE). * `Exercise 14`: Implement mstatus restoration for trap return (MRET). * **InstructionFetch.scala:** * `Exercise 15`: Implement PC update logic with interrupt assertions as the highest priority. ### Testcases * **Module Tests** * `ExecuteTest (CSR)`: Extended to verify the read/modify/write logic of CSR instructions (csrw, csrr, etc.). * `TimerTest`: Verifies if the Timer peripheral's MMIO registers (limit, enable) can be correctly read and written. * `UartMMIOTest`: Tests the UART peripheral's transmit (TX) and receive (RX) functionality and its interrupt flags. * **CLINTCSRTest**: * `External Interrupt`: Simulates an external interrupt trigger to verify mstatus/mepc/mcause updates and the mret return flow. *`Environmental Instructions`: Verifies the triggering and jumping of exception instructions ecall and ebreak. * **Integration Tests** (CPUTest.scala) * `InterruptTrapTest`: Executes irqtrap.asmbin to simulate an interrupt, verifying the CPU correctly jumps to the Trap Handler and returns, while checking CSR states. * Includes basic tests like `FibonacciTest` and `QuicksortTest` to ensure backward compatibility. ### Test Result ``` [info] ByteAccessTest: [info] [CPU] Byte access program [info] - should store and load single byte [info] CLINTCSRTest: [info] [CLINT] Machine-mode interrupt flow [info] - should handle external interrupt [info] - should handle environmental instructions [info] UartMMIOTest: [info] [UART] Comprehensive TX+RX test [info] - should pass all TX and RX tests [info] ExecuteTest: [info] [Execute] CSR write-back [info] - should produce correct data for csr write [info] FibonacciTest: [info] [CPU] Fibonacci program [info] - should calculate recursively fibonacci(10) [info] TimerTest: [info] [Timer] MMIO registers [info] - should read and write the limit [info] InterruptTrapTest: [info] [CPU] Interrupt trap flow [info] - should jump to trap handler and then return [info] QuicksortTest: [info] [CPU] Quicksort program [info] - should quicksort 10 numbers [info] Run completed in 21 seconds, 129 milliseconds. [info] Total number of tests run: 9 [info] Suites: completed 8, aborted 0 [info] Tests: succeeded 9, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. ``` ### RISCOF Compliance Test ``` Validating RISCOF installation... RISCOF found: /Users/winston/miniconda3/envs/chisel/bin/riscof Version: RISC-V Architectural Test Framework., version 1.25.3 Running RISCOF compliance tests for 2-mmio-trap (RV32I + Zicsr)... Running RISCOF compliance tests for 2-mmio-trap... Using config: config-2-mmio-trap.ini Using RISCOF: /Users/winston/miniconda3/envs/chisel/bin/riscof Using toolchain: Starting compliance test run at Mon Dec 8 14:45:47 CST 2025 This may take 10-15 minutes for the full test suite... INFO | ****** RISCOF: RISC-V Architectural Test Framework 1.25.3 ******* INFO | using riscv_isac version : 0.18.0 INFO | using riscv_config version : 3.18.3 INFO | Reading configuration from: /Users/winston/Documents/ca2025-HW3/tests/config-2-mmio-trap.ini INFO | Preparing Models INFO | Input-ISA file INFO | ISACheck: Loading input file: /Users/winston/Documents/ca2025-HW3/tests/mycpu_plugin/mycpu_isa_rv32i_zicsr.yaml INFO | ISACheck: Load Schema /Users/winston/miniconda3/envs/chisel/lib/python3.13/site-packages/riscv_config/schemas/schema_isa.yaml INFO | ISACheck: Processing Hart:0 INFO | ISACheck: Initiating Validation for Hart:0 INFO | ISACheck: No errors for Hart:0 INFO | ISACheck: Updating fields node for each CSR in Hart:0 INFO | ISACheck: Dumping out Normalized Checked YAML: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_2mt/mycpu_isa_rv32i_zicsr_checked.yaml INFO | Input-Platform file INFO | Loading input file: /Users/winston/Documents/ca2025-HW3/tests/mycpu_plugin/mycpu_platform.yaml INFO | Load Schema /Users/winston/miniconda3/envs/chisel/lib/python3.13/site-packages/riscv_config/schemas/schema_platform.yaml INFO | Initiating Validation INFO | No Syntax errors in Input Platform Yaml. :) INFO | Dumping out Normalized Checked YAML: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_2mt/mycpu_platform_checked.yaml INFO | Generating database for suite: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite INFO | Database File Generated: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_2mt/database.yaml INFO | Env path set to/Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/env INFO | Running Build for DUT INFO | Running Build for Reference INFO | Selecting Tests. INFO | Running Tests on DUT. INFO | === BATCH MODE: Preparing 119 tests === INFO | Compiling test 1/119: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/add-01.S INFO | Compiling test 2/119: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/addi-01.S ... INFO | /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign2-jalr-01.S : - : Passed INFO | Test report generated at /Users/winston/Documents/ca2025-HW3/tests/riscof_work_2mt/report.html. INFO | Opening test report in web-browser βœ… Compliance tests complete. Results in riscof_work_2mt/ Completion time: Mon Dec 8 14:42:35 CST 2025 Copying results to results/ directory... Cleaning up auto-generated RISCOF test files... βœ… Compliance tests complete. Results in results/ πŸ“Š View report: results/report.html ``` ### Nyancat VGA Display Demo ``` 🐱 Starting VGA demo with nyancat animation... Display: 640Γ—480@72Hz with SDL2 visualization Program: nyancat.asmbin (12-frame nyancat animation) Note: Frame upload + animation takes significant time Duration: 500M cycles (~5 minutes, includes full animation) cd verilog/verilator/obj_dir && ./VTop -vga -instruction ../../../src/main/resources/nyancat.asmbin -time 500000000 [SDL2] Window opened: 640x480 'VGA Display - MyCPU' [SDL2] Press ESC or close window to stop simulation early Simulation progress: 1% Simulation progress: 2% Simulation progress: 3% ... Simulation progress: 96% Simulation progress: 97% Simulation progress: 98% Simulation progress: 99% Simulation progress: 100% βœ… Demo complete! You should have seen animated nyancat. ``` ![image](https://hackmd.io/_uploads/HJdjkTffZx.png) ## Pipelined RISC-V CPU * **Performance Optimization**: Splits the execution process into multiple stages (3 or 5 stages) to improve clock frequency and instruction throughput, reducing CPI. * **Multiple Implementations**: Provides various pipeline versions, ranging from basic Stall mechanisms to advanced Data Forwarding and Early Branch Resolution in the ID stage. * **Hazard Handling**: Implements a complete Hazard Unit to detect and resolve Data Hazards and Control Hazards. ### Exercises * **ALU.scala:** * `Exercise 16`: Implement the remaining ALU operations, including shift operations (sll, srl, sra), comparison operations (slt, sltu), and logical operations (xor, or, and). * **fivestage_final/Forwarding.scala:** * `Exercise 17`: Implement data forwarding logic for the EX stage to resolve RAW hazards for rs1 and rs2 using data from MEM and WB stages. * `Exercise 18`: Implement data forwarding logic for the ID stage to enable early branch resolution by forwarding operands from MEM and WB stages. * **fivestage_final/Control.scala:** * `Exercise 19`: Implement pipeline hazard detection logic to identify load-use hazards and jump dependencies, asserting pc_stall, if_stall, and id_flush signals when necessary. * **fivestage_final/IF2ID.scala:** * `Exercise 20`: Implement the stall and flush logic for the IF/ID pipeline registers (instruction, address, and interrupt flag), ensuring NOPs are inserted during a flush. ### Testcases * **Basic & Peripheral Tests** * `PipelineRegisterTest`: Verifies the stall and flush mechanisms of pipeline registers (e.g., IF/ID, ID/EX). * `PipelineUartTest`: Verifies UART peripheral MMIO read/write functions within the pipelined architecture. * **Program Execution Tests** (PipelineProgramTest) * `Basic Programs`: Executes fibonacci, quicksort, sb to ensure correct basic instruction execution in the pipeline. * `Hazard Test` (hazard.asmbin): Tests basic Data Hazards (RAW) and Control Hazards to verify the correctness of Forwarding or Stall mechanisms. * `Hazard Extended` (hazard_extended.asmbin): A comprehensive hazard test covering WAW, Load-Use Hazards, consecutive Loads, branch condition dependencies, JAL return address dependencies, CSR read/write dependencies, and more complex scenarios. * `Trap Test` (irqtrap.asmbin): Verifies the interrupt flow in the pipeline architecture, specifically the pipeline flush behavior when a Trap occurs. ### Test Result ``` [info] PipelineProgramTest: [info] Three-stage Pipelined CPU [info] - should calculate recursively fibonacci(10) [info] - should quicksort 10 numbers [info] - should store and load single byte [info] - should solve data and control hazards [info] - should handle all hazard types comprehensively [info] - should handle machine-mode traps [info] Five-stage Pipelined CPU with Stalling [info] - should calculate recursively fibonacci(10) [info] - should quicksort 10 numbers [info] - should store and load single byte [info] - should solve data and control hazards [info] - should handle all hazard types comprehensively [info] - should handle machine-mode traps [info] Five-stage Pipelined CPU with Forwarding [info] - should calculate recursively fibonacci(10) [info] - should quicksort 10 numbers [info] - should store and load single byte [info] - should solve data and control hazards [info] - should handle all hazard types comprehensively [info] - should handle machine-mode traps [info] Five-stage Pipelined CPU with Reduced Branch Delay [info] - should calculate recursively fibonacci(10) [info] - should quicksort 10 numbers [info] - should store and load single byte [info] - should solve data and control hazards [info] - should handle all hazard types comprehensively [info] - should handle machine-mode traps [info] PipelineUartTest: [info] Three-stage Pipelined CPU UART Comprehensive Test [info] - should pass all TX and RX tests [info] Five-stage Pipelined CPU with Stalling UART Comprehensive Test [info] - should pass all TX and RX tests [info] Five-stage Pipelined CPU with Forwarding UART Comprehensive Test [info] - should pass all TX and RX tests [info] Five-stage Pipelined CPU with Reduced Branch Delay UART Comprehensive Test [info] - should pass all TX and RX tests [info] PipelineRegisterTest: [info] Pipeline Register [info] - should be able to stall and flush [info] Run completed in 1 minute, 8 seconds. [info] Total number of tests run: 29 [info] Suites: completed 3, aborted 0 [info] Tests: succeeded 29, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. ``` ### RISCOF Compliance Test ``` Validating RISCOF installation... RISCOF found: /Users/winston/miniconda3/envs/chisel/bin/riscof Version: RISC-V Architectural Test Framework., version 1.25.3 Running RISCOF compliance tests for 3-pipeline (RV32I + Zicsr)... Running RISCOF compliance tests for 3-pipeline... Using config: config-3-pipeline.ini Using RISCOF: /Users/winston/miniconda3/envs/chisel/bin/riscof Using toolchain: Starting compliance test run at Mon Dec 8 14:47:31 CST 2025 This may take 10-15 minutes for the full test suite... INFO | ****** RISCOF: RISC-V Architectural Test Framework 1.25.3 ******* INFO | using riscv_isac version : 0.18.0 INFO | using riscv_config version : 3.18.3 INFO | Reading configuration from: /Users/winston/Documents/ca2025-HW3/tests/config-3-pipeline.ini INFO | Preparing Models INFO | Input-ISA file INFO | ISACheck: Loading input file: /Users/winston/Documents/ca2025-HW3/tests/mycpu_plugin/mycpu_isa_rv32i_zicsr.yaml INFO | ISACheck: Load Schema /Users/winston/miniconda3/envs/chisel/lib/python3.13/site-packages/riscv_config/schemas/schema_isa.yaml INFO | ISACheck: Processing Hart:0 INFO | ISACheck: Initiating Validation for Hart:0 INFO | ISACheck: No errors for Hart:0 INFO | ISACheck: Updating fields node for each CSR in Hart:0 INFO | ISACheck: Dumping out Normalized Checked YAML: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_3pl/mycpu_isa_rv32i_zicsr_checked.yaml INFO | Input-Platform file INFO | Loading input file: /Users/winston/Documents/ca2025-HW3/tests/mycpu_plugin/mycpu_platform.yaml INFO | Load Schema /Users/winston/miniconda3/envs/chisel/lib/python3.13/site-packages/riscv_config/schemas/schema_platform.yaml INFO | Initiating Validation INFO | No Syntax errors in Input Platform Yaml. :) INFO | Dumping out Normalized Checked YAML: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_3pl/mycpu_platform_checked.yaml INFO | Generating database for suite: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite INFO | Database File Generated: /Users/winston/Documents/ca2025-HW3/tests/riscof_work_3pl/database.yaml INFO | Env path set to/Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/env INFO | Running Build for DUT INFO | Running Build for Reference INFO | Selecting Tests. INFO | Running Tests on DUT. INFO | === BATCH MODE: Preparing 119 tests === INFO | Compiling test 1/119: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/add-01.S INFO | Compiling test 2/119: /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/addi-01.S ... INFO | /Users/winston/Documents/ca2025-HW3/tests/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign2-jalr-01.S : - : Passed INFO | Test report generated at /Users/winston/Documents/ca2025-HW3/tests/riscof_work_3pl/report.html. INFO | Opening test report in web-browser βœ… Compliance tests complete. Results in riscof_work_3pl/ Completion time: Mon Dec 8 14:53:18 CST 2025 Copying results to results/ directory... Cleaning up auto-generated RISCOF test files... βœ… Compliance tests complete. Results in results/ πŸ“Š View report: results/report.html ``` ### Hazard Detection Summary and Analysis (Exercise 21) * ==**Q1:**== Why do we need to stall for load-use hazards? A: Data from a Load instruction is only obtained in the MEM stage. If the very next instruction needs to use this value in the ID/EX stage, it cannot be forwarded in time. The pipeline must stall for one cycle to wait for the data. * ==**Q2:**== What is the difference between "stall" and "flush" operations? A: Stall freezes the pipeline, keeping the current state (PC remains unchanged) to wait for data. Flush clears the pipeline registers, discarding the current instruction (turning it into a NOP) to handle incorrect predictions or insert bubbles. * ==**Q3:**== Why does jump instruction with register dependency need stall? A: The jump target is calculated in the ID stage. If the dependent register value is still being calculated or read in the EX or MEM stage, the ID stage cannot access the correct value immediately, requiring a stall. * ==**Q4:**== In this design, why is branch penalty only 1 cycle instead of 2? A: Because this design uses ID stage branch resolution. Once a jump is decided in the ID (2nd) stage, only the incorrectly fetched instruction in the IF stage needs to be flushed, resulting in a 1-cycle penalty. * ==**Q5:**== What would happen if we removed the hazard detection logic entirely? A: Data hazards would result in reading old values, and control hazards would cause the execution of instructions from the wrong path, causing the CPU to malfunction. * ==**Q6:**== Complete the stall condition summary: * Stall is needed when: 1. A Load-Use hazard occurs, or an ID jump instruction depends on an EX result. 2. An ID jump instruction depends on a MEM stage Load result. * Flush is needed when: 1. A branch is taken or a jump is executed in the ID stage. ## Run HW2 on RISC-V Pipelined CPU ### Modifications 1. Remove `ecall` instruction because we are running program on bare metal and there are no system call supported. 2. Write all the result to absolute memory address directly when the program finished. 3. Extend Scala test program for hanoi.asmbin. ### Code #### hanoi.S ```asm= .text .globl _start _start: li x2, 0x2000 # Fix disk positions (BLANK 1-3: neutralize x5 effect) # BLANK 1: Fix position at x2+20 sw x0, 20(x2) # BLANK 2: Fix position at x2+24 sw x0, 24(x2) # BLANK 3: Fix position at x2+28 sw x0, 28(x2) addi x8, x0, 1 game_loop: # BLANK 4: Check loop termination (2^3 moves) addi x5, x0, 8 beq x8, x5, finish_game # Gray code formula: gray(n) = n XOR (n >> k) # BLANK 5: What is k for Gray code? srli x5, x8, 1 # BLANK 6: Complete Gray(n) calculation xor x6, x8, x5 # BLANK 7-8: Calculate previous value and its shift addi x7, x8, -1 srli x28, x7, 1 # BLANK 9: Generate Gray(n-1) xor x7, x7, x28 # BLANK 10: Which bits changed? xor x5, x6, x7 # Initialize disk number addi x9, x0, 0 # BLANK 11: Mask for testing LSB andi x6, x5, 1 # BLANK 12: Branch if disk 0 moves bne x6, x0, disk_found # BLANK 13: Set disk 1 addi x9, x0, 1 # BLANK 14: Test second bit with proper mask andi x6, x5, 2 bne x6, x0, disk_found # BLANK 15: Last disk number addi x9, x0, 2 disk_found: # BLANK 16: Check impossible pattern (multiple bits) andi x30, x5, 5 addi x31, x0, 5 beq x30, x31, pattern_match jal x0, continue_move pattern_match: continue_move: # BLANK 17: Word-align disk index (multiply by what?) slli x5, x9, 2 # BLANK 18: Base offset for disk array addi x5, x5, 20 add x5, x2, x5 lw x18, 0(x5) bne x9, x0, handle_large # BLANK 19: Small disk moves by how many positions? addi x19, x18, 2 # BLANK 20: Number of pegs addi x6, x0, 3 blt x19, x6, display_move sub x19, x19, x6 jal x0, display_move handle_large: # BLANK 21: Load reference disk position lw x6, 20(x2) # BLANK 22: Sum of all peg indices (0+1+2) addi x19, x0, 3 sub x19, x19, x18 sub x19, x19, x6 display_move: # BLANK 26: Calculate storage offset slli x5, x9, 2 addi x5, x5, 20 add x5, x2, x5 # BLANK 27: Update disk position sw x19, 0(x5) # BLANK 28-29: Increment counter and loop addi x8, x8, 1 jal x0, game_loop finish_game: li x5, 4 sw x8, 0(x5) # Total steps # Disk 0 Position (Offset 20) -> 0x8 lw x6, 20(x2) sw x6, 4(x5) # Disk 1 Position (Offset 24) -> 0xC lw x6, 24(x2) sw x6, 8(x5) # Disk 2 Position (Offset 28) -> 0x10 lw x6, 28(x2) sw x6, 12(x5) loop: j loop ``` #### PipelineProgramTest.scala ```diff ... for (i <- 1 to 1000) { c.clock.step() c.io.mem_debug_read_address.poke((i * 4).U) } c.io.csr_debug_read_address.poke(CSRRegister.MSTATUS) c.clock.step() c.io.csr_debug_read_data.expect(0x1888.U) c.io.csr_debug_read_address.poke(CSRRegister.MCAUSE) c.clock.step() val cause = c.io.csr_debug_read_data.peek().litValue assert(mcauseAcceptable.contains(cause), f"unexpected mcause 0x${cause}%x") c.io.mem_debug_read_address.poke(0x4.U) c.clock.step() c.io.mem_debug_read_data.expect(0x2022L.U) } } + it should "solve hanoi tower (3 disks)" in { + runProgram("hanoi.asmbin", cfg) { c => + c.clock.setTimeout(0) + c.clock.step(50000) + c.io.regs_debug_read_address.poke(8.U) + c.clock.step() + c.io.regs_debug_read_data.expect(8.U) + } + } } } ``` #### Makefile ```diff BINS = \ fibonacci.asmbin \ + hanoi.asmbin \ hazard.asmbin \ quicksort.asmbin \ sb.asmbin \ uart.asmbin \ irqtrap.asmbin ``` ### Analysis To check to simulate `hanoi.S` on MyCPU, go to `3-pipeline/csrc` and execute instruction below to generate `hanoi.asmbin` in `3-pipeline/src/resources` ```bash make CROSS_COMPILE=riscv64-unknown-elf- hanoi.asmbinv make update ``` Execute instruction below to generate waveform (`trace.vcd`) and `memory_dump.txt` (from address 0~256) ```bash make sim SIM_ARGS="-instruction src/main/resources/hanoi.asmbin -signature 0 256 memory_dump.txt" ``` #### memory_dump.txt ``` 00000000 00000008 // total step 00000002 // disk 1 location (peg) 00000002 // disk 2 location (peg) 00000002 // disk 3 location (peg) 00000000 ... 00000000 ``` - Total step is initialized to 1. It tells that this project spend 7 step to finish moving disks. - The location of three disk should be the same in the end. ### Test Result ``` sbt "project pipeline" "testOnly riscv.PipelineProgramTest -- -z hanoi" [info] welcome to sbt 1.10.7 (Eclipse Adoptium Java 11.0.29) [info] loading project definition from /Users/winston/Documents/ca2025-HW3/project/project/project [info] loading settings for project ca2025-hw3-build-build from metals.sbt... [info] loading project definition from /Users/winston/Documents/ca2025-HW3/project/project [info] loading settings for project ca2025-hw3-build from metals.sbt... [info] loading project definition from /Users/winston/Documents/ca2025-HW3/project [success] Generated .bloop/ca2025-hw3-build.json [success] Total time: 1 s, completed 2025εΉ΄12月10ζ—₯ δΈ‹εˆ4:23:02 [info] loading settings for project root from build.sbt... [info] set current project to mycpu-root (in build file:/Users/winston/Documents/ca2025-HW3/) [info] set current project to mycpu-pipeline (in build file:/Users/winston/Documents/ca2025-HW3/) [info] PipelineProgramTest: [info] Three-stage Pipelined CPU [info] - should solve hanoi tower (3 disks) [info] Five-stage Pipelined CPU with Stalling [info] - should solve hanoi tower (3 disks) [info] Five-stage Pipelined CPU with Forwarding [info] - should solve hanoi tower (3 disks) [info] Five-stage Pipelined CPU with Reduced Branch Delay [info] - should solve hanoi tower (3 disks) [info] Run completed in 12 seconds, 270 milliseconds. [info] Total number of tests run: 4 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 4, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. ``` ## References - [Lab3: Construct a RISC-V CPU with Chisel](https://hackmd.io/@sysprog/B1Qxu2UkZx) - [Chisel Bootcamp](https://github.com/freechipsproject/chisel-bootcamp) - [MacOS 15+η‰ˆζœ¬iverilog+GtkWAVE](https://blog.csdn.net/m0_51389066/article/details/146957073)