contributed by < ranvd
>
OS: Ubuntu 20.04
JDK: 11
After reviewing the lecture materials, I have developed a more comprehensive understanding of single-cycle CPU design. This knowledge proves valuable as I delve deeper into reading source code
The terminal outputs provided below are the built-in tests from the ca2023-lab project. These outputs demonstrate that MyCPU functions correctly ather the modifications are made.
[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: 21 s, completed Nov 30, 2023, 12:05:26 PM
During the unit testing phase, I discovered that the testing code for instruction decoding did not evaluate the memory_write_enable
and memory_read_enable
wires. This omission could result in an incomplete unit test. To address this issue, I have modified the testing code to include additional checks for the mentioned wires.
class InstructionDecoderTest extends AnyFlatSpec with ChiselScalatestTester {
behavior.of("InstructionDecoder of Single Cycle CPU")
it should "produce correct control signal" in {
test(new InstructionDecode).withAnnotations(TestAnnotations.annos) { c =>
c.io.instruction.poke(0x00a02223L.U) // S-type
c.io.ex_aluop1_source.expect(ALUOp1Source.Register)
c.io.ex_aluop2_source.expect(ALUOp2Source.Immediate)
c.io.regs_reg1_read_address.expect(0.U)
c.io.regs_reg2_read_address.expect(10.U)
+ c.io.memory_read_enable.expect(0.U)
+ c.io.memory_write_enable.expect(1.U)
c.clock.step()
c.io.instruction.poke(0x000022b7L.U) // lui
c.io.regs_reg1_read_address.expect(0.U)
c.io.ex_aluop1_source.expect(ALUOp1Source.Register)
c.io.ex_aluop2_source.expect(ALUOp2Source.Immediate)
+ c.io.memory_read_enable.expect(0.U)
+ c.io.memory_write_enable.expect(0.U)
c.clock.step()
c.io.instruction.poke(0x002081b3L.U) // add
c.io.ex_aluop1_source.expect(ALUOp1Source.Register)
c.io.ex_aluop2_source.expect(ALUOp2Source.Register)
+ c.io.memory_read_enable.expect(0.U)
+ c.io.memory_write_enable.expect(0.U)
c.clock.step()
}
}
}
After successfully passing all built-in tests, I proceeded to modify my C code in homework2. I implemented a mechanism to write the return value into the memory address 0x4
. This allows me to conveniently verify the expected behavior of my code by observing the memory value. The retrieved value can be easily obtained through the mem_debug_read_data
wire.
The function in my homework2 is designed to count the position of the first occurrence of the \0
byte in the input. For the testing input of 0x1120304455007788
, the expected output is 5. The observed result at memory address 0x4
match with our expectations, confirming the code work correctly in MyCPU. (As the picuture shown below)
The source code provided below represents the Instruction Fetch interface. By monitoring the input/output, it becomes apparent that this stage is responsible not only for handling PC+4 but also for executing branch movements.
Our primary task is to control the value in the PC register by assessing whether a jump/branch instruction was executed in the previous instruction.
class InstructionFetch extends Module {
val io = IO(new Bundle {
val jump_flag_id = Input(Bool())
val jump_address_id = Input(UInt(Parameters.AddrWidth))
val instruction_read_data = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val instruction_address = Output(UInt(Parameters.AddrWidth))
val instruction = Output(UInt(Parameters.InstructionWidth))
})
Subsequently, I progressed to the instruction decode stage. Upon tracing the source code, I identified that two signals, memory read and write, were missing. I addressed this by introducing a multiplexer to appropriately control these signals.
Next, I proceeded to the execution stage. Drawing from my previous experience, I quickly identified that the ALU signals were missing. I applied a multiplexer to control the alu.io.op1
and alu.io.op2
signals. Subsequently, I'm considering how to assign values to the alu.io.func
signal, since there are complexity conditions to evaluate.
After a while, I realized that all necessary operations were handled in alu_ctrl
. I then established a direct connection, linking the signal from alu_ctrl
to alu
.
In the final step, within the CPU module, my focus was on connecting the missing signals to their respective positions.
After all proccess above, the single cycle CPU are done. And there aren't too much thing I should do for capabling the code to MyCPU.
The Makefile and linker script are ready to use, all the work we need to do is removing the priviledge insruction in the code.
At first, my Ubuntu version is 22.04 with JDK 8 as the sbt offical website suggest. And I found that what ever I do, I can only pass the unit test. Then I switch the JDK to JDK 11 the issue still there.
Then I downgrade my system to Ubuntu 20.04 with JDK 11. The code work fine as expect. Maybe there is something wrong on the Lab3 guideline?
Allow me not providing any error message here. It's time consuming for me to reproduce the same error message, since I should update my system to 22.04 to check if there exist the same problem.
Maybe I will check it in near future.