From d225894765bb59711ddd0ed35af25e977ab16978 Mon Sep 17 00:00:00 2001 From: supersurviveur Date: Mon, 10 Nov 2025 11:19:40 +0100 Subject: [PATCH 1/5] Required values in tests can be splitted on several lines --- src/test/scala/projet/ZzTopCommon.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/test/scala/projet/ZzTopCommon.scala b/src/test/scala/projet/ZzTopCommon.scala index 3025901..a8573ec 100644 --- a/src/test/scala/projet/ZzTopCommon.scala +++ b/src/test/scala/projet/ZzTopCommon.scala @@ -7,19 +7,21 @@ import chisel3.simulator.scalatest.ChiselSim object ZzTopCommon extends AnyFreeSpec with ChiselSim { def expectedValuesFromAsm(path: String): Seq[BigInt] = { - val line = - Source.fromFile(path).getLines().find(_.startsWith("# expected:")) - line match { - case Some(l) => - l.stripPrefix("# expected:") + Source + .fromFile(path) + .getLines() + .filter(_.startsWith("# expected:")) + .map( + _.stripPrefix("# expected:") .split(",") .map(_.trim) .filter(_.nonEmpty) .map(str => BigInt(str, 16)) .toSeq - case None => - Seq.empty - } + ) + .fold(Seq.empty)((acc, line) => { + acc.concat(line) + }) } def failTrace(msg: String = "Erreur", trace: ListBuffer[String]): Unit = { From 7bb8b993aefa9ed00f8829acff389e9e54ed22a7 Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Wed, 12 Nov 2025 18:02:14 +0100 Subject: [PATCH 2/5] Implements (mostly untested) rv64i) --- bench/tests/op/addiw.s | 9 +++- bench/tests/op/sraiw.s | 22 ++++++++ src/main/scala/projet/Alu.scala | 31 ++++++----- src/main/scala/projet/op/OpImmW.scala | 21 ++++++-- src/main/scala/projet/op/OpLoad.scala | 17 ++++++ src/main/scala/projet/op/OpR.scala | 1 - src/main/scala/projet/op/OpRW.scala | 71 ++++++++++++++++++++++++++ src/main/scala/projet/op/OpStore.scala | 4 ++ 8 files changed, 158 insertions(+), 18 deletions(-) create mode 100644 bench/tests/op/sraiw.s create mode 100644 src/main/scala/projet/op/OpRW.scala diff --git a/bench/tests/op/addiw.s b/bench/tests/op/addiw.s index 5943844..4f0293a 100644 --- a/bench/tests/op/addiw.s +++ b/bench/tests/op/addiw.s @@ -1,4 +1,4 @@ -# expected: 0000000000000000, FFFFFFFFFFFFFFFF, 0000000000000010 +# expected: 0000000000000000, FFFFFFFFFFFFFFFF, 0000000000000010, 0000000000000000 .text _start: # This test CANNOT use li as it uses addiw under the hood @@ -12,3 +12,10 @@ _start: # simple addition addi x1, x0, 8 addiw x31, x1, 8 + + # 32bits trim + lui x1, 0xFFFFF + slli x1, x1, 20 + addiw x31, x1, 0 + + diff --git a/bench/tests/op/sraiw.s b/bench/tests/op/sraiw.s new file mode 100644 index 0000000..dccc130 --- /dev/null +++ b/bench/tests/op/sraiw.s @@ -0,0 +1,22 @@ +# expected: 0000000000000000, 000000003fffffff, ffffffffc0000000, ffffffffffffffff, ffffffffffffffff + .text +_start: + # Test 1: 1 >> 1 => 0 + li x1, 1 + sraiw x31, x1, 1 # x31 = 0 + + # Test 2: 0x7fffffff >> 1 => 0x3fffffff + li x1, 0x7fffffff + sraiw x31, x1, 1 # x31 = 0x000000003fffffff + + # Test 3: 0x80000000 >> 1 => 0xc0000000 (sign-extended) + li x1, 0x80000000 + sraiw x31, x1, 1 # x31 = 0xffffffffc0000000 + + # Test 4: 0x80000000 >> 31 => 0xffffffff (-1) + li x1, 0x80000000 + sraiw x31, x1, 31 # x31 = 0xffffffffffffffff + + # Test 5: 0xffffffff >> 31 => 0xffffffff (-1) + li x1, -1 + sraiw x31, x1, 31 # x31 = 0xffffffffffffffff diff --git a/src/main/scala/projet/Alu.scala b/src/main/scala/projet/Alu.scala index 9f8b633..7b1a313 100644 --- a/src/main/scala/projet/Alu.scala +++ b/src/main/scala/projet/Alu.scala @@ -47,64 +47,69 @@ class Alu extends Module { switch(io.opcode) { is(Add) { - out := io.a + io.b; + out := op_a + op_b; } is(Sub) { - out := io.a - io.b; + out := op_a - op_b; } is(And) { - out := io.a & io.b; + out := op_a & op_b; } is(Or) { - out := io.a | io.b; + out := op_a | op_b; } is(Xor) { - out := io.a ^ io.b; + out := op_a ^ op_b; } is(ShiftLeft) { - out := io.a << io.b(5, 0); + out := op_a << op_b(5, 0); } is(ShiftRight) { - out := io.a >> io.b(5, 0); + out := op_a >> op_b(5, 0); } is(ShiftArithmeticRight) { // >> means arithmetic shift for SInts - out := (io.a.asSInt >> io.b(5, 0)).asUInt; + out := (op_a.asSInt >> op_b(5, 0)).asUInt; + // Signed shift on 32bit requires careful handling + when(io.word_mode) { + + out := (op_a(31, 0).asSInt >> op_b(5, 0)).asUInt + } } is(LessThanUnsigned) { - val less_than = io.a < io.b; + val less_than = op_a < op_b; out := less_than; io.comp_result := less_than; } is(LessThanSigned) { - val less_than = io.a.asSInt < io.b.asSInt + val less_than = op_a.asSInt < op_b.asSInt out := less_than io.comp_result := less_than; } is(GreaterEqualUnsigned) { - val geq_than = io.a >= io.b; + val geq_than = op_a >= op_b; out := geq_than io.comp_result := geq_than; } is(GreaterEqualSigned) { - val geq_than = io.a.asSInt >= io.b.asSInt + val geq_than = op_a.asSInt >= op_b.asSInt out := geq_than io.comp_result := geq_than; } is(Equal) { - io.comp_result := io.a === io.b; + io.comp_result := op_a === op_b; } } diff --git a/src/main/scala/projet/op/OpImmW.scala b/src/main/scala/projet/op/OpImmW.scala index 0a1463a..4b9cf5c 100644 --- a/src/main/scala/projet/op/OpImmW.scala +++ b/src/main/scala/projet/op/OpImmW.scala @@ -17,8 +17,7 @@ object OpImmW { val ADDIW = "b000".U val SLLIW = "b001".U - // Unimplemented - val SRLIW_SRAIW = "b101".U // Right shifts + val ShiftWordRight = "b101".U // Right shifts } io.optype := OpType.I; @@ -26,13 +25,29 @@ object OpImmW { io.mux_regb_imm := false.B; // OpImm are operations with imm, so send imm to ALU io.mux_alu_imm := true.B; io.mux_rega_pc := true.B; + io.alu_word_mode := true.B switch(funct3) { // Type I is(Funct3.ADDIW) { - io.alu_word_mode := true.B io.alu_opcode := AluOpCode.Add io.optype := OpType.I } + + is(Funct3.SLLIW) { + io.alu_opcode := AluOpCode.ShiftLeft + io.optype := OpType.I + } + + is(Funct3.ShiftWordRight) { + io.optype := OpType.IR + + // Second-to-last bit indicates arithmetic or logical shift + when(io.instruction(30)) { + io.alu_opcode := AluOpCode.ShiftArithmeticRight + }.otherwise { + io.alu_opcode := AluOpCode.ShiftRight + } + } } } } diff --git a/src/main/scala/projet/op/OpLoad.scala b/src/main/scala/projet/op/OpLoad.scala index 7e61b66..310e28e 100644 --- a/src/main/scala/projet/op/OpLoad.scala +++ b/src/main/scala/projet/op/OpLoad.scala @@ -15,11 +15,18 @@ object OpLoad { // Meaning of Funct3 in the context of an OpLoad instruction object Funct3 extends ChiselEnum { + // Zero extend val LB = "b000".U val LH = "b001".U val LW = "b010".U + + // Sign extend val LBU = "b100".U val LHU = "b101".U + val LWU = "b110".U + + // Arch width + val LD = "b011".U } io.optype := OpType.I @@ -55,6 +62,16 @@ object OpLoad { is(Funct3.LW) { io.memory_size := DMemSize.Word } + is(Funct3.LWU) { + io.memory_size := DMemSize.Word + io.memory_sign_extend := true.B; + } + + // Long load + is(Funct3.LD) { + io.memory_size := DMemSize.Long + io.memory_sign_extend := true.B; + } } } diff --git a/src/main/scala/projet/op/OpR.scala b/src/main/scala/projet/op/OpR.scala index 740da98..161ef6a 100644 --- a/src/main/scala/projet/op/OpR.scala +++ b/src/main/scala/projet/op/OpR.scala @@ -5,7 +5,6 @@ import chisel3.util.switch import projet.CUInterface import projet.AluOpCode import chisel3.util.is -import projet.OpType object OpR { // implements functions for all instruction of the opr kind diff --git a/src/main/scala/projet/op/OpRW.scala b/src/main/scala/projet/op/OpRW.scala new file mode 100644 index 0000000..2972c52 --- /dev/null +++ b/src/main/scala/projet/op/OpRW.scala @@ -0,0 +1,71 @@ +package projet.op + +import chisel3._ +import chisel3.util.switch +import projet.CUInterface +import projet.AluOpCode +import chisel3.util.is +import projet.OpType + +object OpRW { + // Implements functions for all instruction of the opImm, w kind + def opRW(io: CUInterface) = { + val funct3 = io.instruction(14, 12); + val funct7 = io.instruction(31, 25); + + // Meaning of Funct3 in the context of an OpImm instruction + object Funct3 extends ChiselEnum { + // Type I + val AdditionSubstraction = "b000".U + val SLLW = "b001".U + val ShiftRight = "b101".U + + // Unimplemented + val ShiftWordRight = "b101".U // Right shifts + } + + object AdditionSubstractionFunct7 extends ChiselEnum { + val ADDW = "b0000000".U + val SUBW = "b0100000".U + } + + object ShiftWordRightFunct7 extends ChiselEnum { + val SRLW = "b0000000".U + val SRAW = "b0100000".U + } + + io.reg_file_we := true.B // Write to regfile + io.alu_word_mode := true.B + io.mux_regb_imm := true.B; // OpImm are operations with imm, so send imm to ALU + io.mux_rega_pc := true.B; + io.mux_alu_imm := true.B; + switch(funct3) { + // Type I + is(Funct3.AdditionSubstraction) { + switch(funct7) { + is(AdditionSubstractionFunct7.ADDW) { + io.alu_opcode := AluOpCode.Add + } + is(AdditionSubstractionFunct7.SUBW) { + io.alu_opcode := AluOpCode.Sub + } + } + } + + is(Funct3.SLLW) { + io.alu_opcode := AluOpCode.ShiftLeft + } + + is(Funct3.ShiftWordRight) { + switch(funct7) { + is(ShiftWordRightFunct7.SRAW) { + io.alu_opcode := AluOpCode.ShiftArithmeticRight + } + is(ShiftWordRightFunct7.SRLW) { + io.alu_opcode := AluOpCode.ShiftRight + } + } + } + } + } +} diff --git a/src/main/scala/projet/op/OpStore.scala b/src/main/scala/projet/op/OpStore.scala index 5b69ec5..944c4d1 100644 --- a/src/main/scala/projet/op/OpStore.scala +++ b/src/main/scala/projet/op/OpStore.scala @@ -18,6 +18,7 @@ object OpStore { val SB = "b000".U val SH = "b001".U val SW = "b010".U + val SD = "b011".U } io.optype := OpType.S @@ -37,6 +38,9 @@ object OpStore { is(Funct3.SW) { io.memory_size := DMemSize.Word } + is(Funct3.SD) { + io.memory_size := DMemSize.Long + } } } } From c8cd44974f6c5822ed6987828369cd8a48e15752 Mon Sep 17 00:00:00 2001 From: supersurviveur Date: Thu, 13 Nov 2025 09:01:54 +0100 Subject: [PATCH 3/5] Fixs JALR instruction --- bench/tests/op/jalr.s | 1 + src/main/scala/projet/ControlUnit.scala | 8 ++++---- src/main/scala/projet/Rv64i.scala | 6 ++++-- src/main/scala/projet/op/OpBranch.scala | 2 +- src/main/scala/projet/op/OpRW.scala | 1 - 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/bench/tests/op/jalr.s b/bench/tests/op/jalr.s index 4cb4d55..af0f0b9 100644 --- a/bench/tests/op/jalr.s +++ b/bench/tests/op/jalr.s @@ -13,3 +13,4 @@ step2: jalr x0, 4(x2) # return to step1, but 1 further finish: nop + addi x31, x0, 0x0AB # This instruction should never be executed diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index a948783..7bbd464 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -53,7 +53,7 @@ class CUInterface extends Bundle { val mux_regpc_executepc = Output(Bool()) // Selects pc adder or write back for pc write - val mux_pcadder_writeback = Output(Bool()) + val mux_pcadder_jalrwriteback = Output(Bool()) // Selects pc or write back for register write val mux_writeback_pc = Output(Bool()) @@ -133,7 +133,7 @@ class ControlUnit() extends Module { io.mux_incrpc4_imm := true.B; io.mux_regpc_executepc := true.B; io.mux_writeback_pc := true.B; - io.mux_pcadder_writeback := true.B; + io.mux_pcadder_jalrwriteback := true.B; io.mux_executeout_dout := true.B; // Decode instruction @@ -171,7 +171,7 @@ class ControlUnit() extends Module { io.is_jump := true.B io.mux_incrpc4_imm := false.B; // Send the immediate in PC io.mux_regpc_executepc := false.B; // Add the immediate to the previous PC - io.mux_pcadder_writeback := true.B; + io.mux_pcadder_jalrwriteback := true.B; io.optype := OpType.J } @@ -186,7 +186,7 @@ class ControlUnit() extends Module { io.mux_regb_imm := false.B; // Send imm to ALU B io.mux_alu_imm := true.B; // Send alu out to write back line - io.mux_pcadder_writeback := false.B; // Set pc to writeback dest + io.mux_pcadder_jalrwriteback := false.B; // Set pc to writeback dest io.optype := OpType.I } diff --git a/src/main/scala/projet/Rv64i.scala b/src/main/scala/projet/Rv64i.scala index 3237248..b7f549b 100644 --- a/src/main/scala/projet/Rv64i.scala +++ b/src/main/scala/projet/Rv64i.scala @@ -119,6 +119,8 @@ class Rv64i(sim: Boolean = true) extends Module { // Select what to send on writeback line val execute_out = Mux(control_unit.io.mux_alu_imm, alu.io.out, imm); reg_execute_out := execute_out; + // Jalr line is directly the execute output + val jalr_line = execute_out reg_mux_executeout_dout := control_unit.io.mux_executeout_dout; @@ -131,9 +133,9 @@ class Rv64i(sim: Boolean = true) extends Module { // Writeback pipelining registers reg_pc := Mux( - Delay.Delay(control_unit.io.mux_pcadder_writeback, 1, true.B), + control_unit.io.mux_pcadder_jalrwriteback, pc_adder_out, - writeback_line + jalr_line ); dmem.io.data_in := rs2_data diff --git a/src/main/scala/projet/op/OpBranch.scala b/src/main/scala/projet/op/OpBranch.scala index e858e5e..e397e19 100644 --- a/src/main/scala/projet/op/OpBranch.scala +++ b/src/main/scala/projet/op/OpBranch.scala @@ -78,7 +78,7 @@ object OpBranch { // Branch if comparison is successful when(branch) { - io.mux_pcadder_writeback := true.B; + io.mux_pcadder_jalrwriteback := true.B; io.mux_incrpc4_imm := false.B; io.mux_regpc_executepc := false.B; io.is_jump := true.B; diff --git a/src/main/scala/projet/op/OpRW.scala b/src/main/scala/projet/op/OpRW.scala index 2972c52..6ded8d4 100644 --- a/src/main/scala/projet/op/OpRW.scala +++ b/src/main/scala/projet/op/OpRW.scala @@ -5,7 +5,6 @@ import chisel3.util.switch import projet.CUInterface import projet.AluOpCode import chisel3.util.is -import projet.OpType object OpRW { // Implements functions for all instruction of the opImm, w kind From 030149cbea139a5861c1bbb2885f8fb88ceb7730 Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Thu, 13 Nov 2025 09:49:18 +0100 Subject: [PATCH 4/5] Rv64i : passing test --- bench/tests/op/addw.s | 19 +++++++++++++++++ bench/tests/op/ld.s | 7 +++++++ bench/tests/op/lw.s | 6 +++++- bench/tests/op/lwu.s | 6 ++++++ bench/tests/op/sd.s | 9 +++++++++ bench/tests/op/slliw.s | 10 +++++++++ bench/tests/op/sllw.s | 16 +++++++++++++++ bench/tests/op/sraiw.s | 2 +- bench/tests/op/sraw.s | 27 +++++++++++++++++++++++++ bench/tests/op/srliw.s | 14 +++++++++++++ bench/tests/op/srlw.s | 22 ++++++++++++++++++++ bench/tests/op/subw.s | 19 +++++++++++++++++ src/main/scala/projet/ControlUnit.scala | 8 ++++++++ src/main/scala/projet/DMem.scala | 2 +- src/main/scala/projet/op/OpLoad.scala | 4 ++-- src/main/scala/projet/op/OpRW.scala | 1 - 16 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 bench/tests/op/addw.s create mode 100644 bench/tests/op/ld.s create mode 100644 bench/tests/op/lwu.s create mode 100644 bench/tests/op/sd.s create mode 100644 bench/tests/op/slliw.s create mode 100644 bench/tests/op/sllw.s create mode 100644 bench/tests/op/sraw.s create mode 100644 bench/tests/op/srliw.s create mode 100644 bench/tests/op/srlw.s create mode 100644 bench/tests/op/subw.s diff --git a/bench/tests/op/addw.s b/bench/tests/op/addw.s new file mode 100644 index 0000000..586bd94 --- /dev/null +++ b/bench/tests/op/addw.s @@ -0,0 +1,19 @@ +# expected: 0000000000000000, FFFFFFFFFFFFFFFF, 0000000000000010, 0000000000000000 + .text +_start: + # 0 addition + li x1, 0 + addw x31, x0, x1 + + # all bits addition + sign extension to 32 bits then 64 bits + li x1, 0x00000000FFFFFFFF + addw x31, x0, x1 + + # simple addition + li x1, 8 + li x2, 8 + addw x31, x1, x2 + + # 32bits trim + li x1, 0xFFFFFFFF00000000 + addw x31, x0, x1 diff --git a/bench/tests/op/ld.s b/bench/tests/op/ld.s new file mode 100644 index 0000000..55ee01d --- /dev/null +++ b/bench/tests/op/ld.s @@ -0,0 +1,7 @@ +# expected: 1023456789ABCDEF + .text +_start: + li x1, 0x1023456789ABCDEF + sd x1, 100(x0) + + ld x31, 100(x0) diff --git a/bench/tests/op/lw.s b/bench/tests/op/lw.s index 2876a82..71887bc 100644 --- a/bench/tests/op/lw.s +++ b/bench/tests/op/lw.s @@ -1,7 +1,11 @@ -# expected: 123451BC +# expected: 123451BC, FFFFFFFFF0000000 .text _start: lui x1, 0x12345 ori x1, x1, 0x1BC sw x1, 100(x0) lw x31, 100(x0) + + li x1, 0x00000000F0000000 + sw x1, 100(x0) + lw x31, 100(x0) diff --git a/bench/tests/op/lwu.s b/bench/tests/op/lwu.s new file mode 100644 index 0000000..390cc49 --- /dev/null +++ b/bench/tests/op/lwu.s @@ -0,0 +1,6 @@ +# expected: 00000000FFFFFFFF + .text +_start: + li x1, 0xFFFFFFFFFFFFFFFF + sw x1, 100(x0) + lwu x31, 100(x0) diff --git a/bench/tests/op/sd.s b/bench/tests/op/sd.s new file mode 100644 index 0000000..2515344 --- /dev/null +++ b/bench/tests/op/sd.s @@ -0,0 +1,9 @@ +# expected: 000000009ABCDEF0, 0000000012345678 + .text +_start: + li x1, 0x123456789ABCDEF0 + sd x1, 128(x0) + + lwu x31, 128(x0) + lwu x31, 132(x0) + diff --git a/bench/tests/op/slliw.s b/bench/tests/op/slliw.s new file mode 100644 index 0000000..6bd3e7d --- /dev/null +++ b/bench/tests/op/slliw.s @@ -0,0 +1,10 @@ +# expected: 0000000000000000, FFFFFFFF80000000 + .text +_start: + # Shift out of 32bits + li x1, 0x0000000080000000 + slliw x31, x1, 1 + + # Test sign extension + li x1, 0x0000000040000000 + slliw x31, x1, 1 diff --git a/bench/tests/op/sllw.s b/bench/tests/op/sllw.s new file mode 100644 index 0000000..561643b --- /dev/null +++ b/bench/tests/op/sllw.s @@ -0,0 +1,16 @@ +# expected: 0000000000000000, FFFFFFFF80000000, 0000000000000000 + .text +_start: + # Shift out of 32bits + li x1, 0x0000000080000000 + li x2, 1 + sllw x31, x1, x2 + + # Test sign extension + li x1, 0x0000000040000000 + li x2, 1 + sllw x31, x1, x2 + + li x1, 1 + li x2, 33 + sllw x31, x1, x2 diff --git a/bench/tests/op/sraiw.s b/bench/tests/op/sraiw.s index dccc130..4497746 100644 --- a/bench/tests/op/sraiw.s +++ b/bench/tests/op/sraiw.s @@ -1,4 +1,4 @@ -# expected: 0000000000000000, 000000003fffffff, ffffffffc0000000, ffffffffffffffff, ffffffffffffffff +# expected: 0000000000000000, 000000003FFFFFFF, FFFFFFFFC0000000, FFFFFFFFFFFFFFFF, FFFFFFFFFFFFFFFF .text _start: # Test 1: 1 >> 1 => 0 diff --git a/bench/tests/op/sraw.s b/bench/tests/op/sraw.s new file mode 100644 index 0000000..f226e79 --- /dev/null +++ b/bench/tests/op/sraw.s @@ -0,0 +1,27 @@ +# expected: 0000000000000000, 000000003FFFFFFF, FFFFFFFFC0000000, FFFFFFFFFFFFFFFF, FFFFFFFFFFFFFFFF + .text +_start: + # Test 1: 1 >> 1 => 0 + li x1, 1 + li x2, 1 + sraw x31, x1, x2 # x31 = 0 + + # Test 2: 0x7fffffff >> 1 => 0x3fffffff + li x1, 0x7fffffff + li x2, 1 + sraw x31, x1, x2 # x31 = 0x000000003fffffff + + # Test 3: 0x80000000 >> 1 => 0xc0000000 (sign-extended) + li x1, 0x80000000 + li x2, 1 + sraw x31, x1, x2 # x31 = 0xffffffffc0000000 + + # Test 4: 0x80000000 >> 31 => 0xffffffff (-1) + li x1, 0x80000000 + li x2, 31 + sraw x31, x1, x2 # x31 = 0xffffffffffffffff + + # Test 5: 0xffffffff >> 31 => 0xffffffff (-1) + li x1, -1 + li x2, 31 + sraw x31, x1, x2 # x31 = 0xffffffffffffffff diff --git a/bench/tests/op/srliw.s b/bench/tests/op/srliw.s new file mode 100644 index 0000000..a16e186 --- /dev/null +++ b/bench/tests/op/srliw.s @@ -0,0 +1,14 @@ +# expected: 0000000000000000, 000000003fffffff, 0000000040000000 + .text +_start: + # Test 1: 1 >> 1 => 0 + li x1, 1 + srliw x31, x1, 1 # x31 = 0 + + # Test 2: 0x7fffffff >> 1 => 0x3fffffff + li x1, 0x7fffffff + srliw x31, x1, 1 # x31 = 0x000000003fffffff + + # Test 3: 0x80000000 >> 1 => 0x40000000 (not sign-extended) + li x1, 0x80000000 + srliw x31, x1, 1 # x31 = 0xffffffffc0000000 diff --git a/bench/tests/op/srlw.s b/bench/tests/op/srlw.s new file mode 100644 index 0000000..bc2ba1d --- /dev/null +++ b/bench/tests/op/srlw.s @@ -0,0 +1,22 @@ +# expected: 0000000000000000, 000000003fffffff, 0000000040000000, 0000000000000000 + .text +_start: + # Test 1: 1 >> 1 => 0 + li x1, 1 + li x2, 1 + srlw x31, x1, x2 # x31 = 0 + + # Test 2: 0x7fffffff >> 1 => 0x3fffffff + li x1, 0x7fffffff + li x2, 1 + srlw x31, x1, x2 # x31 = 0x000000003fffffff + + # Test 3: 0x80000000 >> 1 => 0x40000000 (not sign-extended) + li x1, 0x80000000 + li x2, 1 + srlw x31, x1, x2 # x31 = 0xffffffffc0000000 + + li x1, 0x40000000 + li x2, 33 + srlw x31, x1, x2 + diff --git a/bench/tests/op/subw.s b/bench/tests/op/subw.s new file mode 100644 index 0000000..b9c3df3 --- /dev/null +++ b/bench/tests/op/subw.s @@ -0,0 +1,19 @@ +# expected: 0000000000000000, FFFFFFFFFFFFFFFF, 0000000000000004, 0000000000000000 + .text +_start: + # 0 sub + li x1, 0 + subw x31, x0, x1 + + # all bits sub + sign extension to 32 bits then 64 bits + li x1, 1 + subw x31, x0, x1 + + # simple subtraction + li x1, 8 + li x2, 4 + subw x31, x1, x2 + + # 32bits trim + li x1, 0xFFFFFFFF00000000 + subw x31, x1, x1 diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index a948783..9c93fd3 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -9,6 +9,7 @@ import projet.op.OpBranch import projet.op.OpStore import projet.op.OpLoad import projet.op.OpImmW +import projet.op.OpRW class CUInterface extends Bundle { val instruction = Input(UInt(32.W)) @@ -113,6 +114,9 @@ object OpCode extends ChiselEnum { // ~~ Rv64i ~~ val OpImmW = "b0011011".U + + // TypeR + val OpRW = "b0111011".U } class ControlUnit() extends Module { @@ -213,5 +217,9 @@ class ControlUnit() extends Module { is(OpCode.OpImmW) { OpImmW.opImmW(io); } + + is(OpCode.OpRW) { + OpRW.opRW(io); + } } } diff --git a/src/main/scala/projet/DMem.scala b/src/main/scala/projet/DMem.scala index 4094238..956e2dd 100644 --- a/src/main/scala/projet/DMem.scala +++ b/src/main/scala/projet/DMem.scala @@ -80,7 +80,7 @@ class DMem extends Module { } // Data out is available one cycle after the read request - val read_addr = Delay.Delay(io.addr, 2, 0.U); + val read_addr = Delay.Delay(io.addr, 1, 0.U); val read_sign_extend = Delay.Delay(io.sign_extend, 1, false.B); when(Delay.Delay(io.en && !io.we, 1, false.B)) { switch(Delay.Delay(io.size, 1, DMemSize.Byte)) { diff --git a/src/main/scala/projet/op/OpLoad.scala b/src/main/scala/projet/op/OpLoad.scala index 310e28e..40ae693 100644 --- a/src/main/scala/projet/op/OpLoad.scala +++ b/src/main/scala/projet/op/OpLoad.scala @@ -39,6 +39,7 @@ object OpLoad { io.reg_file_we := true.B io.memory_en := true.B io.memory_we := false.B + io.memory_sign_extend := false.B; switch(funct3) { // Byte load is(Funct3.LB) { @@ -61,16 +62,15 @@ object OpLoad { // Word load is(Funct3.LW) { io.memory_size := DMemSize.Word + io.memory_sign_extend := true.B; } is(Funct3.LWU) { io.memory_size := DMemSize.Word - io.memory_sign_extend := true.B; } // Long load is(Funct3.LD) { io.memory_size := DMemSize.Long - io.memory_sign_extend := true.B; } } } diff --git a/src/main/scala/projet/op/OpRW.scala b/src/main/scala/projet/op/OpRW.scala index 2972c52..6ded8d4 100644 --- a/src/main/scala/projet/op/OpRW.scala +++ b/src/main/scala/projet/op/OpRW.scala @@ -5,7 +5,6 @@ import chisel3.util.switch import projet.CUInterface import projet.AluOpCode import chisel3.util.is -import projet.OpType object OpRW { // Implements functions for all instruction of the opImm, w kind From 3958a6ad8f6ff8ac0bd3133bff1db598bed63052 Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Thu, 13 Nov 2025 10:13:23 +0100 Subject: [PATCH 5/5] Adds verilator flags (seemingly not working) --- build.sc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build.sc b/build.sc index ccfc53b..f5da2bc 100644 --- a/build.sc +++ b/build.sc @@ -51,6 +51,13 @@ object `TPchisel` extends SbtModule { m => ) val nproc = sys.env.get("NPROC").getOrElse("1"); + + override def forkEnv = T { + super.forkEnv() ++ Map( + "VERILATOR_FLAGS" -> "--O3 --noassert --no-coverage --x-assign fast --x-initial fast --trace-fst -CFLAGS -O3 -CFLAGS -march=native -CFLAGS -flto -LDFLAGS -flto --threads 4", + "VERILATOR_RECOMPILE" -> "false" + ) + } override def forkArgs = super.forkArgs() ++ Seq( "-Dscalatest.parallel.enabled=true", "-Dscalatest.parallel.mode=concurrent",