contributed by < SUE3K
>
class Hello extends Module {
val io = IO(new Bundle {
val led = Output(UInt(1.W))
})
val CNT_MAX = (50000000 / 2 - 1).U;
val cntReg = RegInit(0.U(32.W))
val blkReg = RegInit(0.U(1.W))
cntReg := cntReg + 1.U
when(cntReg === CNT_MAX) {
cntReg := 0.U
blkReg := ~blkReg
}
io.led := blkReg
}
val CNT_MAX = (50000000 / 2 - 1).U;
//the upper limit of the counter in order to control the speed of LED switching.
cntReg := cntReg + 1.U
//The counter is incremented by 1 every cycle.
When the counting register reaches CNT_MAX (cntReg === CNT_MAX
) , execute
cntReg := 0.U
)blkReg
(blkReg := ~blkReg
)blkReg
to the LED output io.led
realizing the LED state switching. (io.led := blkReg
)enhance it by incorporating logic circuit.
We use Mux to incorporate some logic circuit, and make the code more concise and clear.
class Hello extends Module {
val io = IO(new Bundle {
val led = Output(UInt(1.W))
})
val CNT_MAX = (50000000 / 2 - 1).U;
val cntReg = RegInit(0.U(32.W))
val blkReg = RegInit(0.U(1.W))
cntReg := Mux(cntReg === CNT_MAX, 0.U, cntReg + 1.U)
io.led := Mux(cntReg === CNT_MAX, ~blkReg, blkReg)
}
For macOS
$ brew install verilator gtkwave
Install sbt
# 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.21-tem
$ sdk install sbt
But the latest version of "gtkwave" isn't compatable with macOS 14.
So I instead use Ubuntu to execute gtkwave.
Get the repository:
$ git clone https://github.com/SUE3K/ca2023-lab3
$ cd ca2023-lab3
We need to fill all blank to execute program.
$ sbt "testOnly riscv.singlecycle.InstructionFetchTest"
[info] InstructionFetchTest:
[info] InstructionFetch of Single Cycle CPU
[info] - should fetch instruction
[info] Run completed in 1 second, 588 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: 46 s, completed 2023年11月27日 上午12:33:36
Learn More →
When there is no jump signal, we execute pc+4 at 3ns.
$ sbt "testOnly riscv.singlecycle.InstructionDecodeTest"
idea3c@Ians-MacBook ca2023-lab3 % sbt "testOnly riscv.singlecycle.InstructionDecodeTest"
[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /Users/ian/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/Users/ian/ca2023-lab3/)
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for Test / testOnly
[success] Total time: 1 s, completed 2023年11月27日 上午12:34:19
Learn More →
opcode: 00A02223 -> binary : 0000 0000 1010 0000 0010 0010 0010 0011
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val rs1 = io.instruction(19, 15)
val rs2 = io.instruction(24, 20)
Here the instruction : 00A02223 is S-type.
Therefore activate the write_enable signal.
$ sbt "testOnly riscv.singlecycle.ExecuteTest"
[info] ExecuteTest:
[info] Execution of Single Cycle CPU
[info] - should execute correctly
[info] Run completed in 1 second, 714 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: 3 s, completed 2023年11月27日 上午12:34:55
Learn More →
According to the signals (aluop1_source, aluop2_source) to execute ALU
At the end of module, ALU will output the ruslt and signals(io_if_jump_flag, io_if_address)
Learn More →
% sbt "testOnly riscv.singlecycle.CPUTest"
[info] ExecuteTest:
[info] Execution of Single Cycle CPU
[info] - should execute correctly
[info] Run completed in 1 second, 714 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: 3 s, completed 2023年11月27日 上午12:34:55
After we filled in all blanks, let’s test it out.
$ sbt test
Output(macOS):
idea3c@Ians-MacBook ca2023-lab3 % sbt test
[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /Users/ian/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/Users/ian/ca2023-lab3/)
[info] InstructionFetchTest:
[info] InstructionFetch of Single Cycle CPU
[info] - should fetch instruction
[info] InstructionDecoderTest:
[info] InstructionDecoder of Single Cycle CPU
[info] - should produce correct control signal
[info] FibonacciTest:
[info] Single Cycle CPU
[info] - should recursively calculate Fibonacci(10) *** FAILED ***
[info] java.lang.IllegalArgumentException: requirement failed: /Users/ian/ca2023-lab3/verilog/fibonacci.asmbin.txt is not a relative path
[info] at scala.Predef$.require(Predef.scala:337)
[info] at os.RelPath$.apply(Path.scala:292)
[info] at treadle.executable.MemoryFileParser$.parse(Memory.scala:693)
[info] at treadle.executable.MemoryInitializer.$anonfun$handleInitializers$3(Memory.scala:644)
[info] at treadle.executable.MemoryInitializer.$anonfun$handleInitializers$3$adapted(Memory.scala:632)
[info] at scala.collection.immutable.List.foreach(List.scala:333)
[info] at treadle.executable.MemoryInitializer.handleInitializers(Memory.scala:632)
[info] at treadle.executable.MemoryInitializer.<init>(Memory.scala:612)
[info] at treadle.executable.ExecutionEngine.<init>(ExecutionEngine.scala:118)
[info] at treadle.executable.ExecutionEngine$.apply(ExecutionEngine.scala:662)
[info] ...
[info] ExecuteTest:
[info] Execution of Single Cycle CPU
[info] - should execute correctly
[info] QuicksortTest:
[info] ByteAccessTest:
[info] Single Cycle CPU
[info] Single Cycle CPU
[info] - should perform a quicksort on 10 numbers *** FAILED ***
[info] - should store and load a single byte *** FAILED ***
[info] java.lang.IllegalArgumentException: requirement failed: /Users/ian/ca2023-lab3/verilog/quicksort.asmbin.txt is not a relative path
[info] java.lang.IllegalArgumentException: requirement failed: /Users/ian/ca2023-lab3/verilog/sb.asmbin.txt is not a relative path
[info] at scala.Predef$.require(Predef.scala:337)
[info] at scala.Predef$.require(Predef.scala:337)
[info] at os.RelPath$.apply(Path.scala:292)
[info] at os.RelPath$.apply(Path.scala:292)
[info] at treadle.executable.MemoryFileParser$.parse(Memory.scala:693)
[info] at treadle.executable.MemoryFileParser$.parse(Memory.scala:693)
[info] at treadle.executable.MemoryInitializer.$anonfun$handleInitializers$3(Memory.scala:644)
[info] at treadle.executable.MemoryInitializer.$anonfun$handleInitializers$3(Memory.scala:644)
[info] at treadle.executable.MemoryInitializer.$anonfun$handleInitializers$3$adapted(Memory.scala:632)
[info] at treadle.executable.MemoryInitializer.$anonfun$handleInitializers$3$adapted(Memory.scala:632)
[info] at scala.collection.immutable.List.foreach(List.scala:333)
[info] at scala.collection.immutable.List.foreach(List.scala:333)
[info] at treadle.executable.MemoryInitializer.handleInitializers(Memory.scala:632)
[info] at treadle.executable.MemoryInitializer.handleInitializers(Memory.scala:632)
[info] at treadle.executable.MemoryInitializer.<init>(Memory.scala:612)
[info] at treadle.executable.ExecutionEngine.<init>(ExecutionEngine.scala:118)
[info] at treadle.executable.MemoryInitializer.<init>(Memory.scala:612)
[info] at treadle.executable.ExecutionEngine$.apply(ExecutionEngine.scala:662)
[info] at treadle.executable.ExecutionEngine.<init>(ExecutionEngine.scala:118)
[info] ...
[info] at treadle.executable.ExecutionEngine$.apply(ExecutionEngine.scala:662)
[info] ...
[info] RegisterFileTest:
[info] Register File of Single Cycle CPU
[info] - should read the written content
[info] - should x0 always be zero
[info] - should read the writing content
[info] Run completed in 2 seconds, 853 milliseconds.
[info] Total number of tests run: 9
[info] Suites: completed 7, aborted 0
[info] Tests: succeeded 6, failed 3, canceled 0, ignored 0, pending 0
[info] *** 3 TESTS FAILED ***
**[error] Failed tests:
[error] riscv.singlecycle.ByteAccessTest
[error] riscv.singlecycle.FibonacciTest
[error] riscv.singlecycle.QuicksortTest
[error] (Test / test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 4 s, completed 2023年11月27日 上午12:37:50**
Not sure why there are 3 TESTS FAILED on macOS.
But it can be executed successfully on Ubuntu.
Output(Ubuntu):
[info] welcome to sbt 1.9.7 (Temurin Java 1.8.0_392)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /home/ianli/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/home/ianli/ca2023-lab3/)
[info] ExecuteTest:
[info] Execution of Single Cycle CPU
[info] - should execute correctly
[info] QuicksortTest:
[info] Single Cycle CPU
[info] - should perform a quicksort on 10 numbers
[info] ByteAccessTest:
[info] Single Cycle CPU
[info] - should store and load a single byte
[info] FibonacciTest:
[info] Single Cycle CPU
[info] - should recursively calculate Fibonacci(10)
[info] InstructionFetchTest:
[info] InstructionFetch of Single Cycle CPU
[info] - should fetch instruction
[info] InstructionDecoderTest:
[info] InstructionDecoder of Single Cycle CPU
[info] - should produce correct control signal
[info] RegisterFileTest:
[info] Register File of Single Cycle CPU
[info] - should read the written content
[info] - should x0 always be zero
[info] - should read the writing content
[info] Run completed in 25 seconds, 108 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.
[success] Total time: 26 s, completed Nov 27, 2023 12:38:39 AM
/csrc
directory/src/main/resources
ianli@new:~/ca2023-lab3/csrc $ 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 fibonacci.o fibonacci.c
riscv-none-elf-ld -o fibonacci.elf -T link.lds --oformat=elf32-littleriscv fibonacci.o init.o
riscv-none-elf-objcopy -O binary -j .text -j .data fibonacci.elf fibonacci.asmbin
riscv-none-elf-gcc -O0 -Wall -march=rv32i_zicsr -mabi=ilp32 -c -o hello.o hello.c
riscv-none-elf-ld -o hello.elf -T link.lds --oformat=elf32-littleriscv hello.o init.o
riscv-none-elf-objcopy -O binary -j .text -j .data hello.elf hello.asmbin
riscv-none-elf-as -R -march=rv32i_zicsr -mabi=ilp32 -o mmio.o mmio.S
riscv-none-elf-ld -o mmio.elf -T link.lds --oformat=elf32-littleriscv mmio.o
riscv-none-elf-objcopy -O binary -j .text -j .data mmio.elf mmio.asmbin
riscv-none-elf-gcc -O0 -Wall -march=rv32i_zicsr -mabi=ilp32 -c -o quicksort.o quicksort.c
riscv-none-elf-ld -o quicksort.elf -T link.lds --oformat=elf32-littleriscv quicksort.o init.o
riscv-none-elf-objcopy -O binary -j .text -j .data quicksort.elf quicksort.asmbin
riscv-none-elf-as -R -march=rv32i_zicsr -mabi=ilp32 -o sb.o sb.S
riscv-none-elf-ld -o sb.elf -T link.lds --oformat=elf32-littleriscv sb.o
riscv-none-elf-objcopy -O binary -j .text -j .data sb.elf sb.asmbin
riscv-none-elf-as -R -march=rv32i_zicsr -mabi=ilp32 -o hw3_liu.o hw3_liu.S
riscv-none-elf-ld -o hw3_liu.elf -T link.lds --oformat=elf32-littleriscv hw3_liu.o
riscv-none-elf-objcopy -O binary -j .text -j .data hw3_liu.elf hw3_liu.asmbin
cp -f fibonacci.asmbin hello.asmbin mmio.asmbin quicksort.asmbin sb.asmbin hw3_liu.asmbin ../src/main/resources
rm quicksort.elf fibonacci.elf hw3_liu.elf hello.elf sb.elf init.o mmio.elf
Add some instructions to make it more suitable for MYCPU
.org 0
.global _start #starting address to linker
.set SYSEXIT, 93 #add exit function
.set SYSWRITE, 64 #add print function
li a7, SYSEXIT # "exit" syscall
ecall
Extend the CPUtest.scala
function to test my RISC-V assembly code.
Store the data into memory and verify the results at address 0x4
class Hw3Test extends AnyFlatSpec with ChiselScalatestTester {
behavior.of("Single Cycle CPU")
it should "HW2-RISC-VZ" in {
test(new TestTopModule("hw3_liu.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 1 to 50000) {
c.clock.step()
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)
}
}
}
Run test:
sbt "testOnly riscv.singlecycle.Hw3Test"
I couldn't pass the test at first.
ianli@new:~/ca2023-lab3 $ sbt "testOnly riscv.singlecycle.Hw3Test"
[info] welcome to sbt 1.9.7 (Temurin Java 1.8.0_392)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /home/ianli/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/home/ianli/ca2023-lab3/)
[info] Hw3Test:
[info] Single Cycle CPU
[info] - should HW2-RISC-V *** FAILED ***
[info] io_mem_debug_read_address=0 (0x0) did not equal expected=19 (0x1b) (lines in CPUTest.scala: 92, 84) (CPUTest.scala:92)
[info] Run completed in 5 seconds, 661 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 0, failed 1, canceled 0, ignored 0, pending 0
[info] *** 1 TEST FAILED ***
[error] Failed tests:
[error] riscv.singlecycle.Hw3Test
[error] (Test / testOnly) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 7 s, completed Nov 28, 2023 4:14:37 PM
So, I verified the test results by checking the waveform to ensure that the data was correctly written into the target register and memory address.
ianli@new:~/ca2023-lab3 $ sbt "testOnly riscv.singlecycle.Hw3Test"
[info] welcome to sbt 1.9.7 (Temurin Java 1.8.0_392)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /home/ianli/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/home/ianli/ca2023-lab3/)
[info] compiling 1 Scala source to /home/ianli/ca2023-lab3/target/scala-2.13/test-classes ...
[info] Hw3Test:
[info] Single Cycle CPU
[info] - Should HW2-RISC-V
[info] Run completed in 6 seconds, 2 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: 14 s, completed Nov 30, 2023 4:13:58 PM
ianli@new:~/ca2023-lab3 $ make verilator
sbt "runMain board.verilator.VerilogGenerator"
[info] welcome to sbt 1.9.7 (Temurin Java 1.8.0_392)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /home/ianli/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/home/ianli/ca2023-lab3/)
[info] running board.verilator.VerilogGenerator
[success] Total time: 5 s, completed Nov 28, 2023 5:14:44 PM
cd verilog/verilator && verilator --trace --exe --cc sim_main.cpp Top.v && make -C obj_dir -f VTop.mk
make[1]: Entering directory '/home/ianli/ca2023-lab3/verilog/verilator/obj_dir'
g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -c -o sim_main.o ../sim_main.cpp
../sim_main.cpp: In member function ‘void Simulator::parse_args(const std::vector<std::__cxx11::basic_string<char> >&)’:
../sim_main.cpp:136:13: warning: init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17’
136 | if (auto it = std::find(args.begin(), args.end(), "-halt");
| ^~~~
../sim_main.cpp:141:13: warning: init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17’
141 | if (auto it = std::find(args.begin(), args.end(), "-memory");
| ^~~~
../sim_main.cpp:146:13: warning: init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17’
146 | if (auto it = std::find(args.begin(), args.end(), "-time");
| ^~~~
../sim_main.cpp:151:13: warning: init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17’
151 | if (auto it = std::find(args.begin(), args.end(), "-vcd");
| ^~~~
../sim_main.cpp:156:13: warning: init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17’
156 | if (auto it = std::find(args.begin(), args.end(), "-signature");
| ^~~~
../sim_main.cpp:164:13: warning: init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17’
164 | if (auto it = std::find(args.begin(), args.end(), "-instruction");
| ^~~~
/usr/bin/perl /usr/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VTop.cpp > VTop__ALLcls.cpp
g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -c -o VTop__ALLcls.o VTop__ALLcls.cpp
/usr/bin/perl /usr/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VTop__Trace.cpp VTop__Syms.cpp VTop__Trace__Slow.cpp > VTop__ALLsup.cpp
g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -c -o VTop__ALLsup.o VTop__ALLsup.cpp
ar -cr VTop__ALL.a VTop__ALLcls.o VTop__ALLsup.o
ranlib VTop__ALL.a
g++ sim_main.o verilated.o verilated_vcd_c.o VTop__ALL.a -o VTop -lm -lstdc++
make[1]: Leaving directory '/home/ianli/ca2023-lab3/verilog/verilator/obj_dir'
Generate the dump.vcd
ianli@new:~/ca2023-lab3 $ ./run-verilator.sh -instruction src/main/resources/hw3_liu.asmbin -time 2000 -vcd dump.vcd
-time 2000
-memory 1048576
-instruction src/main/resources/hw3_liu.asmbin
[-------------------->] 100%
Tried checking the waveform to find the problem that caused the unsuccessful tests.
Successful waveform:
io_alu_result
calculate the answer = 19.io_memory_write_enable=1
start to write the data into memory address 0x4
.在SystemC中,有三種主要的進程類型,每種類型適用於不同的場景:
Jul 3, 2024contributed by <shhung><SUE3K> The detail can be accessed at branch pipeline Introduction In this project, we have refactored the single-cycle CPU from Assignment 3 into a 3-stage pipeline CPU. The original single-cycle CPU segmented the data path into five stages: Instruction Fetch, Instruction Decode, Execution, Memory Access, and Write-Back. Notably, the Instruction Decode stage included fetching necessary data from registers. Drawing inspiration from the srv32's 3-stage pipeline architecture, we reorganized our CPU into the following 3 stages: Stage 1 comprises Instruction Fetch and Instruction Decode Stage 2 involves Execution Stage 3 encompasses Memory Access and Write-Back
Feb 28, 2024contributed by < SUE3k > Find the position of MSB by CLZ We can find the position of MSB (Most Significant Bit) using CLZ (Count Leading Zeros) due to the following reasons: CLZ provides a straightforward way to determine the MSB without the need for complex bitwise shifting and comparison operations. It simplifies the process of finding the most significant bit in a number. CLZ efficiently finds the leftmost set bit, making it valuable for various applications across different platforms. Motivation When I learned that we were going to apply the Count Leading Zeros (CLZ) operation, my initial idea was that it had a connection with finding the Most Significant Bit (MSB). When we analyzing a binary digit, determining it MSB is not always straightforward. Instead, we often need to count the number of zeros preceding it one by one. It's quite non-intuitive and complex. Therefore, we can intuitively calculate CLZ first and then use that information to find the position of the MSB in a number. So we can immediately know what bit is the MSB.
Feb 28, 2024contributed By < SUE3K >
Nov 27, 2023or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up