diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index bb8fbaf..b551703 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -16,6 +16,11 @@ class CUInterface extends Bundle { // True if the decoded instruction is a jump val is_jump = Output(Bool()) + // DMem connections + val memory_size = Input(DMemSize()) + val memory_en = Input(Bool()) + val memory_we = Input(Bool()) + // Muxers // The naming convention is as follows : mux_xxx_yyy. // If the signal is hot, xxx is selected otherwise yyy is selected @@ -43,7 +48,7 @@ class CUInterface extends Bundle { } object OpType extends ChiselEnum { - val U, I, IR, J, B = Value + val U, I, IR, J, B, S = Value } object OpCode extends ChiselEnum { @@ -78,6 +83,9 @@ object OpCode extends ChiselEnum { // Type B val OpBranch = "b1100011".U + + // Type S + val OpStore = "b0100011".U } class ControlUnit() extends Module { @@ -87,6 +95,9 @@ class ControlUnit() extends Module { io.alu_opcode := AluOpCode.Add io.optype := OpType.U io.is_jump := false.B; + io.memory_size := DMemSize.Word + io.memory_en := false.B + io.memory_we := false.B io.mux_alu_imm := true.B; io.mux_rega_pc := true.B; io.mux_regb_imm := true.B; @@ -164,6 +175,11 @@ class ControlUnit() extends Module { io.optype := OpType.B; opBranch(funct3, io); } + + is(OpCode.OpStore) { + io.optype := OpType.S + opStore(funct3, io); + } } // Implements functions for all instruction of the opImm kind @@ -389,4 +405,30 @@ class ControlUnit() extends Module { io.is_jump := true.B; } } + // Implements functions for all instruction of the OpStore kind + def opStore(funct3: UInt, io: CUInterface) = { + // Meaning of Funct3 in the context of an OpStore instruction + object Funct3 extends ChiselEnum { + val SB = "b000".U + val SH = "b001".U + val SW = "b010".U + } + + io.alu_opcode := AluOpCode.Add + io.mux_alu_imm := true.B + io.mux_rega_pc := true.B + io.mux_regb_imm := false.B + io.memory_we := true.B + switch(funct3) { + is(Funct3.SB) { + io.memory_size := DMemSize.Byte + } + is(Funct3.SH) { + io.memory_size := DMemSize.Half + } + is(Funct3.SW) { + io.memory_size := DMemSize.Word + } + } + } } diff --git a/src/main/scala/projet/DMem.scala b/src/main/scala/projet/DMem.scala new file mode 100644 index 0000000..b152ff4 --- /dev/null +++ b/src/main/scala/projet/DMem.scala @@ -0,0 +1,50 @@ +package projet + +import chisel3._ +import chisel3.util.switch +import chisel3.util.is + +object DMemSize extends ChiselEnum { + val Byte, Half, Word = Value +} + +class DMem extends Module { + val io = IO(new Bundle { + val dbus = Flipped(new BusInterface) + // The size of the input data + val size = Input(DMemSize()) + val en = Input(Bool()) + val we = Input(Bool()) + val addr = Input(UInt(32.W)) + val data_in = Input(UInt(32.W)) + + val data_out = Output(UInt(32.W)) + }) + io.dbus.addr := io.addr; + io.dbus.en := io.en; + + val bytes_enabled = VecInit(false.B, false.B, false.B, false.B) + val data = WireInit(0.U) + when(io.we) { + switch(io.size) { + is(DMemSize.Byte) { + bytes_enabled(io.addr(1, 0)) := true.B + data := (io.data_in << (io.addr(1) * 16.U)) << + (io.addr(1) * 8.U) + } + is(DMemSize.Half) { + bytes_enabled(io.addr(1) * 2.U(2.W)) := true.B + bytes_enabled(io.addr(1) * 2.U(2.W) + 1.U(2.W)) := true.B + data := io.data_in << (io.addr(1) * 16.U) + } + is(DMemSize.Word) { + bytes_enabled := + VecInit(true.B, true.B, true.B, true.B) + data := io.data_in + } + } + } + io.dbus.be := bytes_enabled + + io.dbus.wdata := data +} diff --git a/src/main/scala/projet/ImmediateDecoder.scala b/src/main/scala/projet/ImmediateDecoder.scala index 354c7a3..6a31e4d 100644 --- a/src/main/scala/projet/ImmediateDecoder.scala +++ b/src/main/scala/projet/ImmediateDecoder.scala @@ -36,6 +36,11 @@ class ImmediateDecoder extends Module { io.instruction(11, 8), 0.U ) + val imm_s = Cat( + Fill(20, io.instruction(31)), + io.instruction(31, 25), + io.instruction(11, 7) + ) switch(io.op_type) { is(OpType.U) { @@ -53,5 +58,8 @@ class ImmediateDecoder extends Module { is(OpType.B) { io.immediate := imm_b } + is(OpType.S) { + io.immediate := imm_s + } } } diff --git a/src/main/scala/projet/Rv32i.scala b/src/main/scala/projet/Rv32i.scala index 1c38f33..835481f 100644 --- a/src/main/scala/projet/Rv32i.scala +++ b/src/main/scala/projet/Rv32i.scala @@ -22,6 +22,11 @@ class Rv32i(sim: Boolean = true) extends Module { val alu = Module(new Alu()); val immediate_decoder = Module(new ImmediateDecoder()); val control_unit = Module(new ControlUnit()); + val dmem = Module(new DMem()); + dmem.io.dbus <> io.dbus + dmem.io.en := control_unit.io.memory_en + dmem.io.we := control_unit.io.memory_we + dmem.io.size := control_unit.io.memory_size control_unit.io.alu_comp_result := alu.io.comp_result @@ -90,13 +95,10 @@ class Rv32i(sim: Boolean = true) extends Module { writeback_line ); - io.dbus.addr := 0.U; - io.dbus.wdata := 0.U; - io.dbus.be := VecInit(false.B, false.B, false.B, false.B) - io.dbus.en := false.B; + dmem.io.data_in := rs2 + dmem.io.addr := writeback_line io.ibus.wdata := 0.U; io.ibus.be := VecInit(false.B, false.B, false.B, false.B) - // locally(sim) }