contributed by < fewletter >
I use the Ubuntu Linux 20.04.1 as my operating system.
Follow the command in lab3 use sdkman to install sbt.
Follow the command in Local Installation - Mac/Linux. It's important that we have install the Eclipse Temurin JDK 11 in the above command. However, the Note in Chisel Bootcamp shows that you should have JDK 8 installed to initialize the Chisel Bootcamp.
Note: Make sure you are using Java 8 (NOT Java 9) and have the JDK8 installed. Coursier/jupyter-scala does not appear to be compatible with Java 9 yet as of January 2018.
Follow the hint of the Note, I try to see what java version do I have.
Obviously, I install JDK 11 in my system, so the java version is 11.0.21
. Then I attempt to change the java version by the following command.
Then open another terminal to initialize jupyter notebook.
Take Module 2.2: Combinational Logic as example.
It seems that works well.
There are four files InstructionFetch.scala
, InstructionDecode.scala
, Execute.scala
, CPU.scala
need to be filled with the code and finish the test.
In the part, we can see that there are two ouputs InsAddr
and Ins
. InsAddr
depends on if the branch is detected from the execute phase. Ins
is to read the data from the instruction.
To validate the result, the following command is to generate the .vcd
file and view the waveform.
The waveform shows that
In this part, the main idea is to parse the information from the instruction like the figure .
Therefore, to fill the code, we should focus on the instruction type L and S. These both types are allowed to let the instruction to read or write from the memory.
Based on the following code, InstructionDecoderTest
tests S type, U type and R type instruction, so the io.memory_read_enable
has never been tested like the waveform shows.
To finish this part, it is important to parse the input instruction. In the figure below, ALU is determined by the singal of ALUFunct, and ALU inputs are depends on the ALUOp1Src
and ALUOp2Src
to determine whether they are register data or the instruction address and immediate.
The waveform shows the crucial part of the Execute phase that is ALU operations are depend on the ALUFunct.
To finish this part, it is important to figure out the inputs and the outputs of different phases of the CPU. First, take a look at the CPU.scala
, it is obvious that it lacks of the execution phase.
So, to accomplish the file, it is necessary to take a look in the execute phase of the cpu. There is no need to care what the relationship between the output and input, because Execute.scala
has done it by scratch. Instead it is need to be focus on how do the inputs come from the other phases.
Take sb.S
for example, the file is to test if that the register t0
has the value 0xDEADBEFF
and the regitser s2
has the value 0x15
.
Therefore focus on the how do the execute phase get the input in following two examples:
li t0, 0xDEADBEEF
li s2, 0x15
In HW2, the code doesn't fit the ISA in Mycpu, so I remove the get_cycles
and the system call in the assembly code.
Then change the Makefile in the ca2023/csrc
, the Makefile can generate the .asmbin
file from the .elf
directly.
Every time when the mul_clz.S
is modified, the following commands can generate a new .asmbin
file and update the .asmbin
file in the main test directory.
To test the assembly code of HW2, I prepare a mul_clzTest
to see if the result is stored in register s2
and s3
correctly. If the result is correct, the test should failed because the value isn't 0x0
.
Here is the result. Obviously that doesn't fit my expectation, so I begin to find where the problem is.
I modify the assembly code to only count the leading zeros of the data and the CPUTest to test if the register t5
and t6
are 0x3
and 0x7
.
CPUTest
Here is the result. The test still not pass.
So I view the waveform, I want to wee how these two lines behave in the waveform.
In 433 ns, the value in a0
(register_10
) is moved to the t5
(register_30
), but t6
(register_31
) is always zero. Therefore, it seems that the bug appears in these sentences.
Since that the number in specific register isn't right, I decide to view the waveform to see what happens.
The final instruction of the CPUTest is 0c030c63
, which can be translated to beq t1, zero, init_mul
. The situation means that only part of the assembly code is executed, so that is why I can't get the right result in the specific register. Finally I modify the time of the CPUTest, so the assembly code can pass the test with the accurate value.
The whole assembly code cost 3577 ns to accomplish, and the result is as same as the value I got in HW2.