From 7bb8b993aefa9ed00f8829acff389e9e54ed22a7 Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Wed, 12 Nov 2025 18:02:14 +0100 Subject: [PATCH] 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 + } } } }