---
# System prepended metadata

title: 'Assignment 3: RISC-V CPU'

---

[toc]

# Assignment 3 : RISC-V CPU
contributed by [< jningmin >](https://github.com/jningmin/2025_computer_architecture_mycpu.git)
## 1-single-cycle
For example, I loaded the quicksort.asmbin file, simulate for 1000 cycles, and save the simulation waveform to the qsort.vcd file.

```C 
./run-verilator.sh -instruction src/main/resources/quicksort.asmbin -time 2000 -vcd qsort.vcd
```

If you want to run 1000 cycle, you have to set `-time` to twice of you cycle to set the maximum.
```S 
Disassembly of section .data:

00000000 <.data>:
       0:	00002197          	auipc	gp,0x2
       4:	82818193          	addi	gp,gp,-2008 # 0x1828
       8:	00001137          	lui	sp,0x1
       c:	00001297          	auipc	t0,0x1
```
![image](https://hackmd.io/_uploads/SJajA-pZbl.png)
You can observe that the signal io_instruction begins with 000000000 and 00002197. In the meantime,it aligns with the expected waveform.

### Checking some importent functions through waveform
#### Memory Access
```c 
1d4:	02112e23          	sw	ra,60(sp)
```
![image](https://hackmd.io/_uploads/r1zc2E6ZZe.png)
```c 
fc:	00072703          	lw	a4,0(a4)
```
![image](https://hackmd.io/_uploads/BJA5p4pb-x.png)

When `sw` io_memory_bundle_write_enable = 1,and when `lw` occurs io_memory_bundle_read_enable = 1 ,aligns with the expected waveform, and `writeStrobes_0`,`writeStrobes_1`,`writeStrobes_2`,`writeStrobes_3` all = 1 for `sw` and `lw`.
#### Write back
The control signal regs_write_source (from Decode stage) selects:
- RegWriteSource.ALUResult (0): Default, use ALU computation result
- RegWriteSource.Memory (1): Load instruction, use memory read data
- RegWriteSource.NextInstructionAddress (2): JAL/JALR, save return address
```c 
 60:	03010413          	addi	s0,sp,48
```
![image](https://hackmd.io/_uploads/H1sIWBpbZg.png)
```c 
 70:	fd842703          	lw	a4,-40(s0)
```
![image](https://hackmd.io/_uploads/HyzgGHTZ-e.png)

```c 
 a4:	0c00006f          	j	0x164
```
![image](https://hackmd.io/_uploads/r1xweST-Ze.png)


## 2-mmio-trap
![image](https://hackmd.io/_uploads/HJST63iWWx.png =150x)
---
### Test case error : UartMMIOTest
When I do `make test` and this error occurs:
```c
UartMMIOTest:

[info] [UART] Comprehensive TX+RX test
[info] - should pass all TX and RX tests *** FAILED ***
[info]   io_mem_debug_read_data=11 (0xb) did not equal expected=15 (0xf) (lines in UartMMIOTest.scala: 174, 161) (UartMMIOTest.scala:174)
```
It means there was a problem with the read path or data transfer.
So I went to check the whole code of my Memory Acess scala code (because at that time I still can't figure out how to observe the error through the waveform)

Turns out there are some problems in [CA25: Exercise 12]

original code : 
```c 
io.wb_memory_read_data := MuxLookup(io.funct3, 0.U)(
      Seq(
        // TODO: Complete LB (sign-extend byte)
        // Hint: Replicate sign bit, then concatenate with byte
        InstructionsTypeL.lb -> MuxLookup(mem_address_index, Cat(Fill(24, data(31)), data(31, 24)))(
          Seq(
            0.U -> Cat(Fill(24, data(7)), data(7, 0)),
            1.U -> Cat(Fill(24, data(15)), data(15, 8)),
            2.U -> Cat(Fill(24, data(23)), data(23, 16))
      )
    )
```
The new code utilizes the byte signals that already pre-computed in the MemoryAccess module, and sucessfuly eliminate this error.
```c 
io.wb_memory_read_data := MuxLookup(io.funct3, 0.U)(
      Seq(
        // TODO: Complete LB (sign-extend byte)
        // Hint: Replicate sign bit, then concatenate with byte
        InstructionsTypeL.lb -> MuxLookup(mem_address_index, Cat(Fill(24, data(31)), data(31, 24)))(
          Seq(
            0.U -> Cat(Fill(24, byte(7)), byte),
            1.U -> Cat(Fill(24, byte(7)), byte),
            2.U -> Cat(Fill(24, byte(7)), byte)
          )
        )
```

## 3-pipeline
### CA25: Exercise 21 
**Q1**: Why do we need to stall for load-use hazards?
>Hint: Consider data dependency and forwarding limitations

   A: [Because load instruction is only retrieved from memory at the end of MEM stage,
      when we are dealing hazard is using ex/mem or ex/wb, there is no way we can get data
      immediately from end of MEM stage to the front of its own EX stage. ]
      
**signal explaination**
-  Hazard Detection & Stalling:
    The process begins when the `io_stall_flag_ctrl` signal goes $\to \mathbf{1}$ at $161 \text{ ns}$. This is the essential signal confirming that your Hazard Detection Unit recognized the data dependency (the Load-Use).Simultaneously, the `io_pc_stall` signal goes $\to \mathbf{1}$. This is the direct command to pause the pipeline.
-  Pipeline pausing :
    As a result of `io_pc_stall` being high, the `pc[31:0]` value is frozen at $\mathbf{00001010}$ for the entire clock cycle (161 ns to 163 ns). This prevents the next instruction from being fetched.Similarly, the `io_id_instruction[31:0]` signal remains at $\mathbf{005082e3}$, confirming that the IF/ID pipeline register is frozen. This ensures the instruction that needs the loaded data remains in the ID stage for one extra cycle.
-  NOP Insertion 
    To prevent the frozen instruction from executing twice, a NOP bubble must be inserted into the ID/EX pipeline register.This is proven by the control signals `memory_read_enable_io_flush`, `reg1_data_io_flush`, and `regs_write_enable_io_flush` all going $\to \mathbf{1}$ during the stall cycle. In your design, these signals are used to clear or invalidate the ID/EX register's control bits, effectively forcing it to execute as a NOP.

![image](https://hackmd.io/_uploads/H1JB69MM-g.png)



  
**Q2**: What is the difference between "stall" and "flush" operations?
 >Hint: Compare their effects on pipeline registers and PC
 
   A: [Stall is like a pause, we stop and wait for the data we want to be available, and freezes the PC 
       and the IF/ID register, and clears the ID/EX register to insert a NOP bubble.
       Flush occurs when we get wrong next instruction, therefore we need to clear the wrong instruction
       that we fetched and set the pipeline registers to NOP.]
**signal explaination**   
- `if2id_io_stall`: When a Stall occurs, this signal goes $\to \mathbf{1}$, causing the PC (Program Counter) to be frozen, holding its previous value.
- `if2id_io_flush`: When a Flush occurs, this signal goes $\to \mathbf{1}$. The PC must jump to a new target address instead of being frozen.
- `pc[31:0]`: Stall: The PC value remains unchanged. Flush: The PC value jumps to a new branch or jump target address.
- 
**stall**
![image](https://hackmd.io/_uploads/ry7UJ2MMbe.png)

**flush**
![image](https://hackmd.io/_uploads/BJqNJ2fGWx.png)


**Q3**: Why does jump instruction with register dependency need stall?
>Hint: When is jump target address available?

   A: [Because it is a non condition jump instruction, it will always need to calculate its next instruction 
       address, and the jump target address will not determined until the end of the EX stage.]
**signal explaination**      
Observe whether the `PC[31:0]` stops updating , and check if the Jump target address has already been computed . While the PC is halted, confirm that a NOP bubble (flushes) is correctly injected into the pipeline.
![image](https://hackmd.io/_uploads/rk3tQ2fGWx.png)


  
**Q4**: In this design, why is branch penalty only 1 cycle instead of 2?
>Hint: Compare ID-stage vs EX-stage branch resolution
   A: [Because when branch or not is determined at EX stage, we need to flush 2 instruction following behind,
      but when branch or not is determined at ID stage, we will only need to flush 1 instruction, it's all 
      because of the  design implements ID stage forwarding. ]
   
**signal explaination**   
Branch penalty only 1 cycle.
![image](https://hackmd.io/_uploads/HJUmbQXfWx.png)


**Q5**: What would happen if we removed the hazard detection logic entirely?
   A: [The pipeline would continue to execute instructions without checking for dependencies, leading to incorrect program execution and results.]
   
   >Hint: Consider data hazards and control flow correctness
  
**Q6**: Complete the stall condition summary:

   Stall is needed when:
-  The instruction in the EX stage is a load ,and its destination register (rd_ex) is not x0
      and matches a source register (rs1_id or rs2_id) of the instruction in the ID stage. (EX stage condition)
- The instruction in the MEM stage is a Load , and the instruction in the ID stage is a Jump , and the Load destination (rd_mem) matches the Jump source .(MEM stage condition)  
  
Flush is needed when:
-  A branch instruction is resolved in the ID stage and is determined to be taken (misprediction),or an unconditional Jump (JALR or JAL) is executed. (Branch/Jump condition)
### Attempting to run the Assembly files from Assignment 2 on the MyCPU architecture.
```s 
make update
/home/userjning/riscv-none-elf-gcc/bin/riscv-none-elf-as -R -march=rv32i_zicsr -mabi=ilp32 -o hanoi_gray_bare.o hanoi_gray_bare.S
hanoi_gray_bare.S: Assembler messages:
hanoi_gray_bare.S: Warning: end of file not at end of a line; newline inserted
/home/userjning/riscv-none-elf-gcc/bin/riscv-none-elf-ld -o hanoi_gray_bare.elf -T link.lds --oformat=elf32-littleriscv hanoi_gray_bare.o
/home/userjning/riscv-none-elf-gcc/bin/riscv-none-elf-ld: hanoi_gray_bare.o: in function `_start':
(.text+0x0): undefined reference to `__stack_top'
/home/userjning/riscv-none-elf-gcc/bin/riscv-none-elf-ld: hanoi_gray_bare.o: in function `main':
(.text+0x34): undefined reference to `get_cycles'
/home/userjning/riscv-none-elf-gcc/bin/riscv-none-elf-ld: hanoi_gray_bare.o: in function `print_from_label':
(.text+0x23c): undefined reference to `get_cycles'
make: *** [Makefile:16: hanoi_gray_bare.elf] Error 1
```
"Only the code and data segments from the ELF file are required, while other segments can be disregarded. In the linker script, these two segments are allocated to contiguous addresses to streamline the implementation."
```c 
riscv-none-elf-objcopy -O binary --only-section=.text --only-section=.data stairs.elf stairs.asmbin

make sim SIM_ARGS="-instruction ../../../csrc/stairs.asmbin"
```
**Successful execution form hw2 program**
hw1_program

```s 
stairs.elf:     file format elf32-littleriscv


Disassembly of section .text:

00010000 <get_cycles>:
get_cycles():
   10000:	c80025f3          	rdcycleh	a1
   10004:	c0002573          	rdcycle	    a0
   10008:	c8002673          	rdcycleh	a2
   1000c:	fec59ae3          	bne	a1,a2,10000 <get_cycles>
   10010:	00008067          	ret
    ...
```
![image](https://hackmd.io/_uploads/rJJqcvVz-e.png)

quiz2_program
```s 
hanoi.elf:     file format elf32-littleriscv


Disassembly of section .text:

00010000 <get_cycles>:
   10000:	c80025f3          	rdcycleh	a1
   10004:	c0002573          	rdcycle	        a0
   10008:	c8002673          	rdcycleh	a2
   1000c:	fec59ae3          	bne	a1,a2,10000 <get_cycles>
   10010:	00008067          	ret

00010014 <get_instret>:
   10014:	c82025f3          	rdinstreth	a1
   10018:	c0202573          	rdinstret	a0
   1001c:	c8202673          	rdinstreth	a2
   10020:	fec59ae3          	bne	a1,a2,10014 <get_instret>
   10024:	00008067          	ret


```
![image](https://hackmd.io/_uploads/B14YRydG-l.png)
I observed that `io_instruction[31:0]` :`c0202573` signal becomes stable (00000000) in the waveform, but the` pc[31:0]` signal continues to update .
This usually means that the CPU has read an invalid or logical body from the instruction memory (approximately processed to a new bit), but is still reading an invalid or logical body from the execution memory, but is still reading an invalid or logical body from the execution processor itself.
![image](https://hackmd.io/_uploads/r1yxlguM-e.png)
After `bne` comes `ret`, and the PC should jump to the caller's address, but my PC is just incrementing by $PC+4$, which is the real problem.
So I went to check the `ret` finction in `control.scala` and `if2id.scala` .
Pull out signal in `if2id` and find out after a `flush`, all instruction returns 00000000.
![image](https://hackmd.io/_uploads/HkkSOgdfWe.png)


My original code:[CA25: Exercise 20]
```s 
// TODO: Complete the instantiation and connection
  // Hint: Use Module() to instantiate PipelineRegister with appropriate default
  val instruction = Module(new PipelineRegister(defaultValue = 0x00000013.U))
  instruction.io.in     := io.instruction
  instruction.io.stall  := io.stall
  instruction.io.flush  := io.flush
  io.output_instruction := instruction.io.out

  // For instruction address register:
  // - Flush: Output entry address (ProgramCounter.EntryAddress)
  // TODO: Complete the instantiation and connection
  val instruction_address = Module(new PipelineRegister(defaultValue = 0.U))
  instruction_address.io.in     := io.instruction_address
  instruction_address.io.stall  := io.stall
  instruction_address.io.flush  := io.flush
  io.output_instruction_address := instruction_address.io.out
```
After changing:
```s 
// TODO: Complete the instantiation and connection
  // Hint: Use Module() to instantiate PipelineRegister with appropriate default
  val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
  instruction.io.in     := io.instruction
  instruction.io.stall  := io.stall
  instruction.io.flush  := io.flush
  io.output_instruction := instruction.io.out

  // For instruction address register:
  // - Flush: Output entry address (ProgramCounter.EntryAddress)
  // TODO: Complete the instantiation and connection
  val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
  instruction_address.io.in     := io.instruction_address
  instruction_address.io.stall  := io.stall
  instruction_address.io.flush  := io.flush
  io.output_instruction_address := instruction_address.io.out
```
Still the same.
![image](https://hackmd.io/_uploads/B1CPTlOMbg.png)
alu.scala
```c 
 // Comparison Operations
    //
    is(ALUFunctions.slt) {
      // TODO: Implement signed comparison (Set Less Than)
      // Hint: Convert both operands to signed type then compare
      //   If op1 < op2 (signed), result is 1, otherwise 0
      io.result := Mux(io.op1.asSInt < io.op2.asSInt, 1.U, 0.U)
      
    }
    is(ALUFunctions.sltu) {
      // TODO: Implement unsigned comparison (Set Less Than Unsigned)
      // Hint: Directly compare unsigned values
      //   If op1 < op2 (unsigned), result is 1, otherwise 0
      io.result := Mux(io.op1.asUInt < io.op2.asUInt, 1.U, 0.U)
    }
```
After changing:
```c 
// Comparison Operations
    //
    is(ALUFunctions.slt) {
      // TODO: Implement signed comparison (Set Less Than)
      // Hint: Convert both operands to signed type then compare
      //   If op1 < op2 (signed), result is 1, otherwise 0
      io.result := (io.op1.asSInt < io.op2.asSInt).asUInt
      
    }
    is(ALUFunctions.sltu) {
      // TODO: Implement unsigned comparison (Set Less Than Unsigned)
      // Hint: Directly compare unsigned values
      //   If op1 < op2 (unsigned), result is 1, otherwise 0
      io.result := (io.op1 < io.op2).asUInt
    }
```
Still the same
![image](https://hackmd.io/_uploads/B1CPTlOMbg.png)

After all I assume this error have some connection with [issue 3](https://hackmd.io/f2M3DssDTWy3uYJNpmZojg#issue-3), because I tried everything that I thought might cause errror in scala code, so I think this might be related to my almost empty memory C drive, but I'm not sure.
## issue 1 
For `make compliance`

```c 
 - should pass test /home/userjning/ca_lab3/ca2025-mycpu/tests/riscv-arch-test/riscv-test-suite/rv32i_m/I/src/lui-01.S *** FAILED ***
[info]   java.lang.Exception: No RISC-V toolchain found. Set $RISCV or install to $HOME/riscv/toolchain
[info]   at riscv.compliance.ElfSignatureExtractor$.$anonfun$extractSignatureRange$10(ComplianceTestBase.scala:84)
[info]   at scala.Option.getOrElse(Option.scala:201)
[info]   at riscv.compliance.ElfSignatureExtractor$.readelfCmd$lzycompute$1(ComplianceTestBase.scala:84)
[info]   at riscv.compliance.ElfSignatureExtractor$.readelfCmd$1(ComplianceTestBase.scala:70)
[info]   at riscv.compliance.ElfSignatureExtractor$.extractSignatureRange(ComplianceTestBase.scala:95)
[info]   at riscv.compliance.ComplianceTestBase.runComplianceTest(ComplianceTestBase.scala:166)
[info]   at riscv.compliance.ComplianceTest.$anonfun$new$19(ComplianceTest.scala:176)
[info]   at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
[info]   at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
[info]   at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
```

```c 
[info] Run completed in 45 seconds, 961 milliseconds.
[info] Total number of tests run: 50
[info] Suites: completed 8, aborted 0
[info] Tests: succeeded 9, failed 41, canceled 0, ignored 0, pending 0
[info] *** 41 TESTS FAILED ***
```

It doesn't looks like my progam runs incorrectly, it looks like it didn't even generated.
So I check $Path in Makefile and tried to fix it.
Turns out setting path for riscv-none-elf-gcc is the real problem.

**After I changed path**
```c 
$ export RISCV=$HOME/riscv-none-elf-gcc
$ source $RISCV/setenv
$ echo $RISCV 
```

```c 
[info] Run completed in 7 minutes, 24 seconds.
[info] Total number of tests run: 50
[info] Suites: completed 8, aborted 0
[info] Tests: succeeded 50, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 445 s (07:25), completed Dec 1, 2025, 4:57:46 PM
```

It will save a results html like this,
![image](https://hackmd.io/_uploads/rkOWI6ibZg.png)


--- 
```c
Validating RISCOF installation...
RISCOF found: /home/userjning/.local/bin/riscof
   Version: RISC-V Architectural Test Framework., version 1.25.3

Running RISCOF compliance tests for 1-single-cycle (RV32I)...
/bin/sh: 1: ./run-compliance.sh: Permission denied
make: *** [Makefile:35: compliance] Error 126
```
---


## issue 2
Waveform tooks me a lot of time to understand and how to generate it.

Key signals to observe:

- io_instruction_address: Current PC value
- io_instruction: Fetched instruction
- io_memory_bundle_*: Memory interface signals
- inst_fetch_*, id_*, ex_*, mem_*, wb_*: Pipeline stage internals
```c 
WRITE_VCD=1 sbt singleCycle/test
```
After successful execution, the generated .vcd waveform archive will be stored in various subdirectories under the `test_run_dir` directory.
$\rightarrow$  `TestTopModule.vcd`



## issue 3
Physical Memory Protection (PMP) registers (38 tests)

```c 
 ERROR | Error evaluating verify condition (PMP['implemented']): name 'PMP' is not defined
```
Why all test passed, though I still duplicate error messages.

![image](https://hackmd.io/_uploads/rJDYrao-Zg.png)

I find these context in readme.md
```c 
### 3. config-3-pipeline.ini
- Project: 3-pipeline
- ISA Profile: RV32I + Zicsr (Base Integer + CSR Instructions)
- ISA Spec: `mycpu_plugin/mycpu_isa_rv32i_zicsr.yaml`
- Platform Spec: `mycpu_plugin/mycpu_platform.yaml`
- Test Count: 119 tests (RV32I + Zicsr + PMP)
```
So I check `mycpu_plugin/mycpu_platform.yaml` and  `mycpu_plugin/mycpu_isa_rv32i_zicsr.yaml` , and tried to add 
```c 
PMP:
  implemented: False
```
to see if it make differance, but it turns out the same.

Following on from the issues mentioned [above](https://hackmd.io/f2M3DssDTWy3uYJNpmZojg?stext=15025%3A51%3A0%3A1765458252%3AxNpjcL&both=), I decided to run my entire program on another computer, and it turns out **All PMP test cases passed**.
```c 
INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_all_entries_check-01.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_all_entries_check-02.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_all_entries_check-03.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_all_entries_check-04.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_A_all.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_A_off_all.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_A_tor_bot.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_A_tor_zero.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_L_access_all.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_L_modify_napot.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_L_modify_off.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_L_modify_tor.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_XWR_all-01.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_XWR_all-02.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_XWR_all-03.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_XWR_all-04.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_na4_all.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_napot_all.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_tor_all.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_tor_check-01.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_tor_check-02.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_cfg_tor_check-03.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_csr_walk.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_grain.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_grain_check.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_misaligned_na4.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_misaligned_napot.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_misaligned_off.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_misaligned_tor.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_na4_legal_lwxr.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_napot_legal_lwxr.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_priority.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_priority_off.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpm_tor_legal_lwxr.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_cfg_A_off.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_cfg_XWR.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_csr_access.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_mprv_check-01.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_mprv_check-02.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_na4_legal_lxwr.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_napot_legal_lxwr.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_none.S/ref/Reference-rv32emu.signature
    INFO | Reference signature generated: /home/ubuntu/j-cpu/2025_computer_architecture_mycpu/tests/riscof_work_3pl/rv32i_m/pmp/src/pmpu_tor_legal_lxwr.S/ref/Reference-rv32emu.signature

```
All cases passed.
```c 
INFO | Results: 119 passed, 0 failed
INFO | Running Tests on Reference Model
```
## What I learned from Bootcamp

-  Data Types and Structuring: Learned about Chisel's basic data types, including Bits, SInt (signed integers), UInt (unsigned integers), and Bool. Also, learned to use higher-order types like Bundles (similar to C structs for named fields) and Vecs (collections of the same type, acting as wire arrays) for organizing data flow,.
- Writing Hardware Generators: Learned how to write hardware generators in Chisel that take advantage of Scala's high-level programming language features .
- Unit Testing and Debugging: Acquired the ability to write unit tests for Chisel designs and learned how to generate waveform files during testing by setting the environment variable WRITE_VCD to 1.


  

