From 5df85799ef30aed020ddd3f26d3390a8f39d8641 Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Wed, 5 Nov 2025 18:40:27 +0100 Subject: [PATCH] Stage 4: Implements auipc --- bench/auipc.s | 6 +++++ src/main/scala/projet/Alu.scala | 32 +++++++++++++++++++++++++ src/main/scala/projet/ControlUnit.scala | 12 ++++++++++ src/main/scala/projet/RegFile.scala | 29 ++++++++++++---------- src/main/scala/projet/Rv32i.scala | 20 ++++++++++++---- 5 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 bench/auipc.s create mode 100644 src/main/scala/projet/Alu.scala diff --git a/bench/auipc.s b/bench/auipc.s new file mode 100644 index 0000000..c5155be --- /dev/null +++ b/bench/auipc.s @@ -0,0 +1,6 @@ +# expected: 0000a000,0000b004,0000c008 + .text +_start: + auipc x31, 0xa + auipc x31, 0xb + auipc x31, 0xc diff --git a/src/main/scala/projet/Alu.scala b/src/main/scala/projet/Alu.scala new file mode 100644 index 0000000..576a323 --- /dev/null +++ b/src/main/scala/projet/Alu.scala @@ -0,0 +1,32 @@ +package projet + +import chisel3._ +import chisel3.util.switch +import chisel3.util.is + +object AluOpCode extends ChiselEnum +{ + val Add = Value +} + +class Alu extends Module { + 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()) + }) + + io.out := 0.U; + + switch(io.opcode) + { + is(Add) + { + io.out := io.a + io.b; + } + } + +} diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index 8235a6f..d50a437 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -7,10 +7,14 @@ import chisel3.util.is class CUInterface extends Bundle { val instruction = Input(UInt(32.W)) val reg_file_we = Output(Bool()) + val alu_opcode = Output(AluOpCode()) + + val mux_imm_alu = Output(Bool()) } object OPCode extends ChiselEnum { val LUI = 0b0110111.U + val AUIPC = 0b0010111.U } class ControlUnit() extends Module { @@ -19,9 +23,17 @@ class ControlUnit() extends Module { val io = IO(new CUInterface()) io.reg_file_we := false.B + io.alu_opcode := AluOpCode.Add + io.mux_imm_alu := false.B; switch(io.instruction(6, 0)) { is(LUI) { io.reg_file_we := true.B + io.mux_imm_alu := false.B; + } + is(AUIPC) { + io.alu_opcode := AluOpCode.Add + io.reg_file_we := true.B + io.mux_imm_alu := true.B; } } } diff --git a/src/main/scala/projet/RegFile.scala b/src/main/scala/projet/RegFile.scala index 599297a..d2a366e 100644 --- a/src/main/scala/projet/RegFile.scala +++ b/src/main/scala/projet/RegFile.scala @@ -24,21 +24,26 @@ class RegFile(sim: Boolean = false) extends Module { } } - val valid = WireInit(false.B); when(io.we && io.rd_addr =/= 0.U) { - regs(io.rd_addr) := io.rd_data + regs(io.rd_addr) := io.rd_data + } - if (sim) { - when(io.rd_addr === 31.U) { - valid := true.B - } - } - } - if (sim) { - io.valid_x31.get := Delay.Delay(valid, 2, false.B) - } io.rs1_data := regs(io.rs1_addr) io.rs2_data := regs(io.rs2_addr) - io.x31 := regs(31) + // Simulation stuff + val valid = WireInit(false.B); + when(io.we && io.rd_addr === 31.U) + { + io.x31 := io.rd_data + if (sim) { + valid := true.B + } + }.otherwise + { + io.x31 := regs(31) + } + if (sim) { + io.valid_x31.get := Delay.Delay(valid, 1, false.B) + } } diff --git a/src/main/scala/projet/Rv32i.scala b/src/main/scala/projet/Rv32i.scala index c26d902..9b70d7b 100644 --- a/src/main/scala/projet/Rv32i.scala +++ b/src/main/scala/projet/Rv32i.scala @@ -13,22 +13,30 @@ class Rv32i(sim: Boolean = true) extends Module { val reg_pc = RegInit(0.U(32.W)); val reg_file = Module(new RegFile(sim)); + val instruction = io.ibus.rdata; + 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 } + + val alu = Module(new Alu()); val control_unit = Module(new ControlUnit()); + + alu.io.opcode := control_unit.io.alu_opcode; reg_file.io.we := control_unit.io.reg_file_we // Increment PC each clock reg_pc := reg_pc + 4.U; + // PC delayed to execute stage for auipc op + val execute_pc = Delay.Delay(reg_pc, 1, 0.U); + // Fetch instruction io.ibus.en := true.B; io.ibus.addr := reg_pc; - val instruction = io.ibus.rdata; control_unit.io.instruction := instruction; // Decode rs1 index @@ -42,11 +50,15 @@ class Rv32i(sim: Boolean = true) extends Module { reg_file.io.rd_addr := rd // Decode imm-u - val imm_u = instruction(31, 12) + val imm_u = Cat(instruction(31, 12), 0.U(12.W)); - // Send imm-u to the register file - reg_file.io.rd_data := Cat(imm_u, 0.U(12.W)) + // EXECUTE + + alu.io.a := execute_pc; + alu.io.b := imm_u; + reg_file.io.rd_data := Mux(control_unit.io.mux_imm_alu, alu.io.out, imm_u); + io.dbus.addr := 0.U; io.dbus.wdata := 0.U; io.dbus.be := VecInit(false.B, false.B, false.B, false.B)