From 27794715233ebe8fb229840d19155e6f80d07f52 Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Thu, 6 Nov 2025 16:18:01 +0100 Subject: [PATCH] Stage 6: implementation, untested --- bench/{ => op}/addi.s | 0 bench/op/andi.s | 9 ++ bench/{ => op}/auipc.s | 0 bench/{ => op}/lui.s | 0 bench/op/ori.s | 4 + src/main/scala/projet/Alu.scala | 67 ++++++++--- src/main/scala/projet/ControlUnit.scala | 118 +++++++++++++++++-- src/main/scala/projet/ImmediateDecoder.scala | 8 +- src/main/scala/projet/Rv32i.scala | 6 +- 9 files changed, 180 insertions(+), 32 deletions(-) rename bench/{ => op}/addi.s (100%) create mode 100644 bench/op/andi.s rename bench/{ => op}/auipc.s (100%) rename bench/{ => op}/lui.s (100%) create mode 100644 bench/op/ori.s diff --git a/bench/addi.s b/bench/op/addi.s similarity index 100% rename from bench/addi.s rename to bench/op/addi.s diff --git a/bench/op/andi.s b/bench/op/andi.s new file mode 100644 index 0000000..7c35d05 --- /dev/null +++ b/bench/op/andi.s @@ -0,0 +1,9 @@ +# expected: 00000000, 00000010 + .text +_start: + addi x1, x0, 0x100 + andi x31, x1, 0x0FF + + addi x1, x0, -1 + andi x31, x1, 0x010 + diff --git a/bench/auipc.s b/bench/op/auipc.s similarity index 100% rename from bench/auipc.s rename to bench/op/auipc.s diff --git a/bench/lui.s b/bench/op/lui.s similarity index 100% rename from bench/lui.s rename to bench/op/lui.s diff --git a/bench/op/ori.s b/bench/op/ori.s new file mode 100644 index 0000000..18e85bf --- /dev/null +++ b/bench/op/ori.s @@ -0,0 +1,4 @@ +# expected: 00000000, 00000010 + .text +_start: + diff --git a/src/main/scala/projet/Alu.scala b/src/main/scala/projet/Alu.scala index 576a323..75717bb 100644 --- a/src/main/scala/projet/Alu.scala +++ b/src/main/scala/projet/Alu.scala @@ -4,29 +4,60 @@ import chisel3._ import chisel3.util.switch import chisel3.util.is -object AluOpCode extends ChiselEnum -{ - val Add = Value +object AluOpCode extends ChiselEnum { + val Add, And, Or, Xor, ShiftLeft, ShiftRight, ShiftArithmeticRight, + LessThanSigned, LessThanUnsigned = Value } class Alu extends Module { - import AluOpCode._ + import AluOpCode._ - val io = IO(new Bundle { - val a = Input(UInt(32.W)) - val b = Input(UInt(32.W)) - val out = Output(UInt(32.W)) - val opcode = Input(AluOpCode()) - }) + val io = IO(new Bundle { + val a = Input(UInt(32.W)) + val b = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + val opcode = Input(AluOpCode()) + }) - io.out := 0.U; - - switch(io.opcode) - { - is(Add) - { - io.out := io.a + io.b; + io.out := 0.U; + + switch(io.opcode) { + is(Add) { + io.out := io.a + io.b; + } + + is(And) { + io.out := io.a & io.b; + } + + is(Or) { + io.out := io.a | io.b; + } + + is(Xor) { + io.out := io.a ^ io.b; + } + + is(ShiftLeft) { + io.out := io.a << io.b(4, 0); + } + + is(ShiftRight) { + io.out := io.a >> io.b(4, 0); + } + + is(ShiftArithmeticRight) { + // >> means arithmetic shift for SInts + io.out := (io.a.asSInt >> io.b(4, 0)).asUInt; + } + + is(LessThanUnsigned) { + io.out := io.a < io.b + } + + is(LessThanSigned) { + io.out := io.a.asSInt < io.b.asSInt + } } - } } diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index b83b8ae..3ae43fd 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -15,18 +15,29 @@ class CUInterface extends Bundle { } object OpType extends ChiselEnum { - val U, I = Value + val U, I, IR = Value } object OpCode extends ChiselEnum { + // Type U val LUI = 0b0110111.U val AUIPC = 0b0010111.U - val ADDI = 0b0010011.U + + // Type I + Type IR + + // Instruction format + // xxx rd, rs1 imm + // Perfomrs some operation with rs1 and immediate + // and writes back to a register + + // addi, andi, ori, xori, slli, srli, srai, + // slti, sltiu + val OpImm = 0b0010011.U + } -class ControlUnit() extends Module { - import OpCode._ +class ControlUnit() extends Module { val io = IO(new CUInterface()) io.reg_file_we := false.B @@ -34,26 +45,111 @@ class ControlUnit() extends Module { io.optype := OpType.U io.mux_alu_imm := true.B; io.mux_rega_pc := true.B; - switch(io.instruction(6, 0)) { + + // Decode instruction + val opcode = io.instruction(6, 0); + val funct3 = io.instruction(14, 12); + val funct7 = io.instruction(31, 25); + + switch(opcode) { // U instructions - is(LUI) { + is(OpCode.LUI) { io.reg_file_we := true.B io.mux_alu_imm := false.B io.optype := OpType.U } - is(AUIPC) { + is(OpCode.AUIPC) { io.alu_opcode := AluOpCode.Add io.reg_file_we := true.B io.mux_rega_pc := false.B io.optype := OpType.U } - // I instructions - is(ADDI) { - io.alu_opcode := AluOpCode.Add + // OpImm instructions + is(OpCode.OpImm) { io.reg_file_we := true.B - io.optype := OpType.I + opImm(funct3, funct7, io); } } + + // Implements functions for all instruction of the opImm kind + def opImm(funct3: UInt, funct7: UInt, io: CUInterface) = + { + // Meaning of Funct3 in the context of an OpImm instruction + object Funct3 extends ChiselEnum + { + // Type I + val ADDI = 000.U + val SLTI = 010.U + val SLTIU = 011.U + val XORI = 100.U + val ORI = 110.U + val ANDI = 111.U + + // Type IR + val SLLI = 001.U + val SRLI_SRAI = 101.U // Right shifts + } + + // Meaning of Funct7 in the context of SHIFTR IR instructions + object IRFunct7 extends ChiselEnum + { + val SRLI = 0000000.U + val SRAI = 0100000.U + } + switch(funct3) + { + // Type I + is(Funct3.ADDI) + { + io.alu_opcode := AluOpCode.Add + io.optype := OpType.I + } + + is(Funct3.ANDI) + { + io.alu_opcode := AluOpCode.And + io.optype := OpType.I + } + + is(Funct3.ORI) + { + io.alu_opcode := AluOpCode.Or + io.optype := OpType.I + } + + is(Funct3.XORI) + { + io.alu_opcode := AluOpCode.Xor + io.optype := OpType.I + } + + is(Funct3.SLLI) + { + io.alu_opcode := AluOpCode.ShiftLeft + io.optype := OpType.I + } + + // Type IR + is(Funct3.SRLI_SRAI) + { + io.optype := OpType.IR + switch(funct7) + { + is(IRFunct7.SRLI) + { + io.alu_opcode := AluOpCode.ShiftRight + } + + is(IRFunct7.SRAI) + { + io.alu_opcode := AluOpCode.ShiftArithmeticRight + } + } + } + } + } } + + diff --git a/src/main/scala/projet/ImmediateDecoder.scala b/src/main/scala/projet/ImmediateDecoder.scala index 6098d8f..8affac9 100644 --- a/src/main/scala/projet/ImmediateDecoder.scala +++ b/src/main/scala/projet/ImmediateDecoder.scala @@ -16,10 +16,11 @@ class ImmediateDecoder extends Module { }) io.immediate := 0.U - // Decode imm-u + // Decode and construct immediates val imm_u = Cat(io.instruction(31, 12), 0.U(12.W)); - // Decode imm-i val imm_i = Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)); + val imm_ir = io.instruction(24, 20); + switch(io.op_type) { is(OpType.U) { io.immediate := imm_u @@ -27,5 +28,8 @@ class ImmediateDecoder extends Module { is(OpType.I) { io.immediate := imm_i } + is(OpType.IR) { + io.immediate := imm_ir + } } } diff --git a/src/main/scala/projet/Rv32i.scala b/src/main/scala/projet/Rv32i.scala index e7e12fa..fcc27ef 100644 --- a/src/main/scala/projet/Rv32i.scala +++ b/src/main/scala/projet/Rv32i.scala @@ -17,7 +17,11 @@ class Rv32i(sim: Boolean = true) extends Module { reg_file.io.rd_data := 0.U; io.x31 := reg_file.io.x31 if (sim) { - io.valid_x31.get := reg_file.io.valid_x31.get && Delay.Delay(!reset.asBool, 1, false.B) + io.valid_x31.get := reg_file.io.valid_x31.get && Delay.Delay( + !reset.asBool, + 1, + false.B + ) } val alu = Module(new Alu());