Try   HackMD

Assignment3: single-cycle RISC-V CPU

contributed by ???

Complete MyCPU

The architecture diagram of MyCPU

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

According to the architecture diagram's data path and control signal, complete MyCPU and verify it through testing.This project provides several tests.

[info] Run completed in 52 seconds, 294 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.

Waveform Analysis

Instruction Fetch

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

io_jump_address_id is set to 0x00001000
From 8ps to 10ps, io_jump_flag_id is 0, so pc=pc+1. At the start of 10ps, io_jump_flag_id becomes 1, therefore at clock = 1, pc = 0x00001000.

Instruction Decode

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

This website can convert machine code into RISC-V instructions :
https://luplab.gitlab.io/rvcodecjs/#q=0x000022B7&abi=false&isa=RV32I
0x00A02223 > sw x10, 4(x0), 0x000022B7 > lui x5, 2

At 2ps, the instruction decoder received the 0x00A02223 instruction, which is an SW instruction. Therefore, the instruction decoder sets the io_memory_write_enable to 1. SW instructions do not require reading the content of memory, so the instruction decoder sets io_memory_read_enable to 0.

At 4ps, the instruction decoder received the 0x000022B7 instruction, which is a lui instruction. Consequently, the instruction decoder sets the io_memory_read_enable to 1. Lui instructions do not require modifying the content of memory, therefore the instruction decoder sets io_memory_write_enable to 0.

Execution

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

In the Execution stage, the ALU needs to determine the operation to be executed and select the operands for the operation. In this example, the ALU selects reg1's data as op1 and reg2's data as op2.

Combining into a CPU

Connect the signals together according to the CPU architecture diagram.

Run my program on MyCPU

My Homework 2 program involves converting a floating-point matrix to a bfloat16 matrix and performing matrix multiplication.

  • Place the program into the csrc directory.
  • Add the program to the BINS variable in the Makefile.
  • Execute the 'make update' command. In the Makefile, gcc compiles .c files into .o (object files), then the ld linker links the object file with the linking script (link.lds) to generate an ELF executable file. As MyCPU doesn't have an operating system, it's necessary to use objcopy to convert the ELF file into a binary file.Because MyCPU is a bare machine, it requires using objcopy to convert the ELF file into a binary executable file.

Here is the result of running 'make update' using the homework 2 program. During the linking process, an error occurred because the program cannot contain multiplication, division operations, and variables of floating-point type. I spent a long time trying to resolve this until the teacher reminded me that MyCPU only supports the base instruction set (RV32I).

$ make update
riscv-none-elf-as -R -march=rv32i_zicsr -mabi=ilp32 -o init.o init.S
riscv-none-elf-gcc -O0 -Wall -march=rv32i_zicsr -mabi=ilp32 -c -o myprogram.o myprogram.c
riscv-none-elf-ld -o myprogram.elf -T link.lds --oformat=elf32-littleriscv myprogram.o init.o
riscv-none-elf-ld: myprogram.o: in function `.L4':
myprogram.c:(.text+0xbc): undefined reference to `__divsf3'
riscv-none-elf-ld: myprogram.c:(.text+0xd8): undefined reference to `__addsf3'
riscv-none-elf-ld: myprogram.o: in function `.L8':
myprogram.c:(.text+0x144): undefined reference to `__floatsisf'
riscv-none-elf-ld: myprogram.c:(.text+0x158): undefined reference to `__addsf3'
riscv-none-elf-ld: myprogram.o: in function `.L7':
myprogram.c:(.text+0x184): undefined reference to `__floatsisf'
riscv-none-elf-ld: myprogram.o: in function `main':
myprogram.c:(.text+0x23c): undefined reference to `__fixsfsi'
riscv-none-elf-ld: myprogram.c:(.text+0x25c): undefined reference to `__fixsfsi'
riscv-none-elf-ld: myprogram.c:(.text+0x284): undefined reference to `__addsf3'
riscv-none-elf-ld: myprogram.c:(.text+0x2a8): undefined reference to `__fixsfsi'
riscv-none-elf-ld: myprogram.c:(.text+0x2c8): undefined reference to `__fixsfsi'
riscv-none-elf-ld: myprogram.c:(.text+0x2f0): undefined reference to `__addsf3'
riscv-none-elf-ld: myprogram.c:(.text+0x314): undefined reference to `__fixsfsi'

I replaced the floating-point matrix in the homework 2 program with an integer matrix and used multiple additions instead of multiplication operations. Finally, I saved the results at memory address 4, 8, 12, and 16.

int multiplication(int a, int b){ int temp = 0; for(int i=0;i<b;i++){ temp += a; } return temp; } int main() { int a[2][2] = { {1, 2}, {3, 4} }; int b[2][2] = { {5, 6}, {7, 8} }; int c[2][2] = {0}; c[0][0] += multiplication(a[0][0], b[0][0]); c[0][0] += multiplication(a[0][1], b[1][0]); c[0][1] += multiplication(a[0][0], b[0][1]); c[0][1] += multiplication(a[0][1], b[1][1]); c[1][0] += multiplication(a[1][0], b[0][0]); c[1][0] += multiplication(a[1][1], b[1][0]); c[1][1] += multiplication(a[1][0], b[0][1]); c[1][1] += multiplication(a[1][1], b[1][1]); *((volatile int *) (4)) = c[0][0]; *((volatile int *) (8)) = c[0][1]; *((volatile int *) (12)) = c[1][0]; *((volatile int *) (16)) = c[1][0]; return 0; }
$ make update 
riscv-none-elf-as -R -march=rv32i_zicsr -mabi=ilp32 -o init.o init.S
riscv-none-elf-gcc -O0 -Wall -march=rv32i_zicsr -mabi=ilp32 -c -o myprogram.o myprogram.c
riscv-none-elf-ld -o myprogram.elf -T link.lds --oformat=elf32-littleriscv myprogram.o init.o
riscv-none-elf-objcopy -O binary -j .text -j .data myprogram.elf myprogram.asmbin
cp -f fibonacci.asmbin hello.asmbin mmio.asmbin quicksort.asmbin sb.asmbin fortestprint.asmbin myprogram.asmbin ../src/main/resources
rm init.o myprogram.elf
  • Extend the Scala code in “src/test/scala/riscv/singlecycle/CPUTest.scala” to include my program test items.
class myprogram extends AnyFlatSpec with ChiselScalatestTester {
  behavior.of("Single Cycle CPU")
  it should "matrix multipicaltion" in {
    test(new TestTopModule("myprogram.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
      for (i <- 1 to 50) {
        c.clock.step(1000)
        c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
      }

      c.io.mem_debug_read_address.poke(4.U)
      c.clock.step()
      c.io.mem_debug_read_data.expect(19.U)

      c.io.mem_debug_read_address.poke(8.U)
      c.clock.step()
      c.io.mem_debug_read_data.expect(22.U)

      c.io.mem_debug_read_address.poke(12.U)
      c.clock.step()
      c.io.mem_debug_read_data.expect(43.U)
      
      c.io.mem_debug_read_address.poke(16.U)
      c.clock.step()
      c.io.mem_debug_read_data.expect(50.U)

    }
  }
}
  • Run the command sbt "testOnly riscv.singlecycle.myprogram" to test my program.
$ sbt "testOnly riscv.singlecycle.myprogram"
[info] welcome to sbt 1.9.7 (Oracle Corporation Java 1.8.0_391)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /home/cheng/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/home/cheng/ca2023-lab3/)
[info] myprogram:
[info] Single Cycle CPU
[info] - should matrix multipicaltion
[info] Run completed in 14 seconds, 936 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.
[success] Total time: 17 s, completed Dec 1, 2023 7:18:56 PM