From 992cf37b9212fd51c2d3d62146ec70ebd9ea45de Mon Sep 17 00:00:00 2001 From: Albin Chaboissier Date: Wed, 12 Nov 2025 11:53:28 +0100 Subject: [PATCH] Moves control unit ops to separate files --- Makefile | 10 +- bench/tests/op/slli.s | 6 +- bench/tests/op/srli.s | 5 +- src/main/scala/projet/ControlUnit.scala | 371 ++---------------------- src/main/scala/projet/op/OpBranch.scala | 85 ++++++ src/main/scala/projet/op/OpImm.scala | 87 ++++++ src/main/scala/projet/op/OpImmW.scala | 36 +++ src/main/scala/projet/op/OpLoad.scala | 59 ++++ src/main/scala/projet/op/OpR.scala | 94 ++++++ src/main/scala/projet/op/OpStore.scala | 40 +++ 10 files changed, 438 insertions(+), 355 deletions(-) create mode 100644 src/main/scala/projet/op/OpBranch.scala create mode 100644 src/main/scala/projet/op/OpImm.scala create mode 100644 src/main/scala/projet/op/OpImmW.scala create mode 100644 src/main/scala/projet/op/OpLoad.scala create mode 100644 src/main/scala/projet/op/OpR.scala create mode 100644 src/main/scala/projet/op/OpStore.scala diff --git a/Makefile b/Makefile index fa63653..d2a242d 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,10 @@ CFLAGS :=$(ASFLAGS) ELFFLAGS :=$(ASFLAGS) $(MEM_DIR)/crt.o -Os -fno-unroll-loops ODFLAGS :=-j .text -j .rodata -j .data -s +## Paramètres de tests +TEST_MAX_RAM := 11000000 ## Limite de ram pour les tests en KB +TEST_MAX_PROCS := $$(($$(nproc) - 2)) ## Garde un processeur libre + .PRECIOUS: $(MEM_DIR)/%.elf .PHONY: synthese fpga clean compile autotest simulation @@ -103,7 +107,11 @@ mill: autotest: mill test-bench/mem/tests/$(PROG).mem ##! Lance la simulation automatique pour tous les tests ou juste celui fourni dans PROG testall: mill compile - @PROOT=$(PWD) NPROC=$(shell nproc) ./mill TPchisel.test.testOnly $(TOP_REP).ZzTopAllSpec + @# Limite le nombre de processeurs et la ram utilisée pour les tests parellèle + @( \ + ulimit -v $(TEST_MAX_RAM); \ + PROOT=$(PWD) taskset -c 0-$(TEST_MAX_PROCS) ./mill TPchisel.test.testOnly $(TOP_REP).ZzTopAllSpec \ + ) simulation: mill compile ##! Lance gtkwave sur le test fourni dans PROG @$(call check_vars,PROG) diff --git a/bench/tests/op/slli.s b/bench/tests/op/slli.s index e25bd68..e5df111 100644 --- a/bench/tests/op/slli.s +++ b/bench/tests/op/slli.s @@ -1,4 +1,5 @@ -# expected: 000003FC, 80000000, 00000000 +# expected: 000003FC, 80000000, 00000000, F000000000000000 + .text _start: addi x1, x0, 0x0FF @@ -9,3 +10,6 @@ _start: addi x1, x0, 0x0F0 slli x31, x1, 63 + + li x1, 0xF + slli x31, x1, 60 diff --git a/bench/tests/op/srli.s b/bench/tests/op/srli.s index 5bfb7be..c848b96 100644 --- a/bench/tests/op/srli.s +++ b/bench/tests/op/srli.s @@ -1,4 +1,4 @@ -# expected: 000000FF, 00000001, 00000000 +# expected: 000000FF, 00000001, 00000000, 000000000000000F .text _start: addi x1, x0, 0x3FC @@ -10,3 +10,6 @@ _start: lui x1, 0x0A000 srli x31, x1, 31 + + li x1, 0xF000000000000000 + srli x31, x1, 60 diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index 291c624..f9d984d 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -3,6 +3,12 @@ package projet import chisel3._ import chisel3.util.switch import chisel3.util.is +import projet.op.OpImm +import projet.op.OpR +import projet.op.OpBranch +import projet.op.OpStore +import projet.op.OpLoad +import projet.op.OpImmW class CUInterface extends Bundle { val instruction = Input(UInt(32.W)) @@ -57,7 +63,13 @@ class CUInterface extends Bundle { } object OpType extends ChiselEnum { - val U, I, IR, J, B, S = Value + val U, I, J, B, S = Value + + // Type IR is not defined in the RiscV specification + // but the immediate needs to be handled differently + // since the 31st bit indicates wether it is an + // arithmetic or logical shift + val IR = Value } object OpCode extends ChiselEnum { @@ -148,13 +160,13 @@ class ControlUnit() extends Module { // OpImm instructions is(OpCode.OpImm) { io.reg_file_we := true.B // Write to regfile - opImm(funct3, funct7, io); + OpImm.opImm(io) } // OpR instructions is(OpCode.OpR) { io.reg_file_we := true.B // Write to regfile - opR(funct3, funct7, io); + OpR.opR(io); } // J instructions @@ -191,368 +203,23 @@ class ControlUnit() extends Module { is(OpCode.OpBranch) { io.optype := OpType.B; - opBranch(funct3, io); + OpBranch.opBranch(io); } is(OpCode.OpStore) { io.optype := OpType.S - opStore(funct3, io); + OpStore.opStore(io); } is(OpCode.OpLoad) { io.optype := OpType.I - opLoad(funct3, io); + OpLoad.opLoad(io); } is(OpCode.OpImmW) { io.reg_file_we := true.B // Write to regfile io.optype := OpType.I - opImmW(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 = "b000".U - val SLTI = "b010".U - val SLTIU = "b011".U - val XORI = "b100".U - val ORI = "b110".U - val ANDI = "b111".U - - // Type IR - val SLLI = "b001".U - val SRLI_SRAI = "b101".U // Right shifts - } - - // Meaning of Funct7 in the context of SHIFTR IR instructions - object IRFunct7 extends ChiselEnum { - val SRLI = "b0000000".U - val SRAI = "b0100000".U - } - - 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 := false.B; - 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 - } - - is(Funct3.SLTI) { - io.alu_opcode := AluOpCode.LessThanSigned - io.optype := OpType.I - } - - is(Funct3.SLTIU) { - io.alu_opcode := AluOpCode.LessThanUnsigned - 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 - } - } - } - } - } - - // Implements functions for all instruction of the opR kind - def opR(funct3: UInt, funct7: UInt, io: CUInterface) = { - // Meaning of Funct3 in the context of an OpR instruction - object Funct3 extends ChiselEnum { - // Type I - val ADD_SUB = "b000".U - val AND = "b111".U - val OR = "b110".U - val XOR = "b100".U - val SLL = "b001".U - val SLT = "b010".U - val SLTU = "b011".U - - // Arithmetic op (discriminate by Funct7) - val SRL_SRA = "b101".U - } - - // Meaning of Funct7 in the context of SHIFTR IR instructions - object IRFunct7 extends ChiselEnum { - val SRL = "b0000000".U - val SRA = "b0100000".U - } - - object ADDFunct7 extends ChiselEnum { - val ADD = "b0000000".U - val SUB = "b0100000".U - } - - 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.ADD_SUB) { - switch(funct7) { - is(ADDFunct7.ADD) { - io.alu_opcode := AluOpCode.Add - } - is(ADDFunct7.SUB) { - io.alu_opcode := AluOpCode.Sub - } - } - } - - is(Funct3.AND) { - io.alu_opcode := AluOpCode.And - } - - is(Funct3.OR) { - io.alu_opcode := AluOpCode.Or - } - - is(Funct3.XOR) { - io.alu_opcode := AluOpCode.Xor - } - - is(Funct3.SLL) { - io.alu_opcode := AluOpCode.ShiftLeft - } - - is(Funct3.SLT) { - io.alu_opcode := AluOpCode.LessThanSigned - } - - is(Funct3.SLTU) { - io.alu_opcode := AluOpCode.LessThanUnsigned - } - - // Type IR - is(Funct3.SRL_SRA) { - switch(funct7) { - is(IRFunct7.SRL) { - io.alu_opcode := AluOpCode.ShiftRight - } - - is(IRFunct7.SRA) { - io.alu_opcode := AluOpCode.ShiftArithmeticRight - } - } - } - } - } - - // Implements functions for all instruction of the branch kind - def opBranch(funct3: UInt, io: CUInterface) = { - // Meaning of Funct3 in the context of an OpBranch instruction - object Funct3 extends ChiselEnum { - val BEQ = "b000".U - val BNE = "b001".U - val BLT = "b100".U - val BGE = "b101".U - val BLTU = "b110".U - val BGEU = "b111".U - } - - val branch = WireInit(false.B); - switch(funct3) { - is(Funct3.BEQ) { - // Send operands from registers to alu - io.alu_opcode := AluOpCode.Equal - io.mux_rega_pc := true.B; - io.mux_regb_imm := true.B; - branch := io.alu_comp_result - } - - is(Funct3.BNE) { - // Send operands from registers to alu - io.alu_opcode := AluOpCode.Equal - io.mux_rega_pc := true.B; - io.mux_regb_imm := true.B; - branch := ~io.alu_comp_result - } - - // Signed comparison - is(Funct3.BLT) { - // Send operands from registers to alu - io.alu_opcode := AluOpCode.LessThanSigned - io.mux_rega_pc := true.B; - io.mux_regb_imm := true.B; - branch := io.alu_comp_result - } - - is(Funct3.BGE) { - // Send operands from registers to alu - io.alu_opcode := AluOpCode.LessThanSigned - io.mux_rega_pc := true.B; - io.mux_regb_imm := true.B; - branch := ~io.alu_comp_result - } - - // Signed comparison - is(Funct3.BLTU) { - // Send operands from registers to alu - io.alu_opcode := AluOpCode.LessThanUnsigned - io.mux_rega_pc := true.B; - io.mux_regb_imm := true.B; - branch := io.alu_comp_result - } - - is(Funct3.BGEU) { - // Send operands from registers to alu - io.alu_opcode := AluOpCode.LessThanUnsigned - io.mux_rega_pc := true.B; - io.mux_regb_imm := true.B; - branch := ~io.alu_comp_result - } - } - - // Branch if comparison is successful - when(branch) { - io.mux_pcadder_writeback := true.B; - io.mux_incrpc4_imm := false.B; - io.mux_regpc_executepc := false.B; - 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 - io.memory_en := 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 - } - } - } - // Implements functions for all instruction of the OpLoad kind - def opLoad(funct3: UInt, io: CUInterface) = { - // Meaning of Funct3 in the context of an OpLoad instruction - object Funct3 extends ChiselEnum { - val LB = "b000".U - val LH = "b001".U - val LW = "b010".U - val LBU = "b100".U - val LHU = "b101".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.mux_writeback_pc := true.B; - io.mux_executeout_dout := false.B; - io.reg_file_we := true.B - io.memory_en := true.B - io.memory_we := false.B - switch(funct3) { - // Byte load - is(Funct3.LB) { - io.memory_size := DMemSize.Byte - io.memory_sign_extend := true.B; - } - is(Funct3.LBU) { - io.memory_size := DMemSize.Byte - } - - // Half load - is(Funct3.LH) { - io.memory_size := DMemSize.Half - io.memory_sign_extend := true.B; - } - is(Funct3.LHU) { - io.memory_size := DMemSize.Half - } - - // Word load - is(Funct3.LW) { - io.memory_size := DMemSize.Word - } - } - } - - // ~~~ EXTENSIONS ~~~ - - // ~~ Rv64i ~~ - - // Implements functions for all instruction of the opImm, w kind - def opImmW(funct3: UInt, funct7: UInt, io: CUInterface) = { - // Meaning of Funct3 in the context of an OpImm instruction - val _ = funct7; - object Funct3 extends ChiselEnum { - // Type I - val ADDIW = "b000".U - val SLLIW = "b001".U - - // Unimplemented - val SRLIW_SRAIW = "b101".U // Right shifts - } - - // Meaning of Funct7 in the context of SHIFTR IR instructions - // object IRFunct7 extends ChiselEnum { - // val SRLI = "b0000000".U - // val SRAI = "b0100000".U - // } - - 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; - switch(funct3) { - // Type I - is(Funct3.ADDIW) { - io.alu_word_mode := true.B - io.alu_opcode := AluOpCode.Add - io.optype := OpType.I - } + OpImmW.opImmW(io); } } } diff --git a/src/main/scala/projet/op/OpBranch.scala b/src/main/scala/projet/op/OpBranch.scala new file mode 100644 index 0000000..0653ac9 --- /dev/null +++ b/src/main/scala/projet/op/OpBranch.scala @@ -0,0 +1,85 @@ +package projet.op + +import chisel3._ +import chisel3.util.switch +import projet.CUInterface +import projet.AluOpCode +import chisel3.util.is + +object OpBranch { +// Implements functions for all instruction of the branch kind + def opBranch(io: CUInterface) = { + val funct3 = io.instruction(14, 12); + + // Meaning of Funct3 in the context of an OpBranch instruction + object Funct3 extends ChiselEnum { + val BEQ = "b000".U + val BNE = "b001".U + val BLT = "b100".U + val BGE = "b101".U + val BLTU = "b110".U + val BGEU = "b111".U + } + + val branch = WireInit(false.B); + switch(funct3) { + is(Funct3.BEQ) { + // Send operands from registers to alu + io.alu_opcode := AluOpCode.Equal + io.mux_rega_pc := true.B; + io.mux_regb_imm := true.B; + branch := io.alu_comp_result + } + + is(Funct3.BNE) { + // Send operands from registers to alu + io.alu_opcode := AluOpCode.Equal + io.mux_rega_pc := true.B; + io.mux_regb_imm := true.B; + branch := ~io.alu_comp_result + } + + // Signed comparison + is(Funct3.BLT) { + // Send operands from registers to alu + io.alu_opcode := AluOpCode.LessThanSigned + io.mux_rega_pc := true.B; + io.mux_regb_imm := true.B; + branch := io.alu_comp_result + } + + is(Funct3.BGE) { + // Send operands from registers to alu + io.alu_opcode := AluOpCode.LessThanSigned + io.mux_rega_pc := true.B; + io.mux_regb_imm := true.B; + branch := ~io.alu_comp_result + } + + // Signed comparison + is(Funct3.BLTU) { + // Send operands from registers to alu + io.alu_opcode := AluOpCode.LessThanUnsigned + io.mux_rega_pc := true.B; + io.mux_regb_imm := true.B; + branch := io.alu_comp_result + } + + is(Funct3.BGEU) { + // Send operands from registers to alu + io.alu_opcode := AluOpCode.LessThanUnsigned + io.mux_rega_pc := true.B; + io.mux_regb_imm := true.B; + branch := ~io.alu_comp_result + } + } + + // Branch if comparison is successful + when(branch) { + io.mux_pcadder_writeback := 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/OpImm.scala b/src/main/scala/projet/op/OpImm.scala new file mode 100644 index 0000000..6c1f75f --- /dev/null +++ b/src/main/scala/projet/op/OpImm.scala @@ -0,0 +1,87 @@ +package projet.op + +import chisel3._ +import chisel3.util.switch +import projet.CUInterface +import projet.AluOpCode +import projet.OpType +import chisel3.util.is + +object OpImm { +// Implements functions for all instruction of the opImm kind + def opImm(io: CUInterface) = { + val funct3 = io.instruction(14, 12); + + // Meaning of Funct3 in the context of an OpImm instruction + object Funct3 extends ChiselEnum { + val ADDI = "b000".U + val SLTI = "b010".U + val SLTIU = "b011".U + val XORI = "b100".U + val ORI = "b110".U + val ANDI = "b111".U + + // Shifts (Type IR) + val SLLI = "b001".U // Shift left + + // We do not use a "Funct7" here as technically, per the specification : + // (https://docs.riscv.org/reference/isa/unpriv/rv32.html#integer-register-immediate-instructions) + // it's not a funct7, but rather a bit at index 30 that indicates right shift kind + val ShiftRight = "b101".U + } + + 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 := false.B; + 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.SLTI) { + io.alu_opcode := AluOpCode.LessThanSigned + io.optype := OpType.I + } + + is(Funct3.SLTIU) { + io.alu_opcode := AluOpCode.LessThanUnsigned + io.optype := OpType.I + } + + // Type IR + is(Funct3.SLLI) { + io.alu_opcode := AluOpCode.ShiftLeft + io.optype := OpType.IR + } + + is(Funct3.ShiftRight) { + 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/OpImmW.scala b/src/main/scala/projet/op/OpImmW.scala new file mode 100644 index 0000000..d885713 --- /dev/null +++ b/src/main/scala/projet/op/OpImmW.scala @@ -0,0 +1,36 @@ +package projet.op + +import chisel3._ +import chisel3.util.switch +import projet.CUInterface +import projet.AluOpCode +import chisel3.util.is +import projet.OpType + +object OpImmW { + // Implements functions for all instruction of the opImm, w kind + def opImmW(io: CUInterface) = { + val funct3 = io.instruction(14, 12); + // Meaning of Funct3 in the context of an OpImm instruction + object Funct3 extends ChiselEnum { + // Type I + val ADDIW = "b000".U + val SLLIW = "b001".U + + // Unimplemented + val SRLIW_SRAIW = "b101".U // Right shifts + } + + 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; + switch(funct3) { + // Type I + is(Funct3.ADDIW) { + io.alu_word_mode := true.B + io.alu_opcode := AluOpCode.Add + io.optype := OpType.I + } + } + } +} diff --git a/src/main/scala/projet/op/OpLoad.scala b/src/main/scala/projet/op/OpLoad.scala new file mode 100644 index 0000000..c387aa1 --- /dev/null +++ b/src/main/scala/projet/op/OpLoad.scala @@ -0,0 +1,59 @@ +package projet.op + +import chisel3._ +import chisel3.util.switch +import projet.CUInterface +import projet.AluOpCode +import chisel3.util.is +import projet.DMemSize + +object OpLoad { + // Implements functions for all instruction of the OpLoad kind + def opLoad(io: CUInterface) = { + val funct3 = io.instruction(14, 12); + + // Meaning of Funct3 in the context of an OpLoad instruction + object Funct3 extends ChiselEnum { + val LB = "b000".U + val LH = "b001".U + val LW = "b010".U + val LBU = "b100".U + val LHU = "b101".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.mux_writeback_pc := true.B; + io.mux_executeout_dout := false.B; + io.reg_file_we := true.B + io.memory_en := true.B + io.memory_we := false.B + switch(funct3) { + // Byte load + is(Funct3.LB) { + io.memory_size := DMemSize.Byte + io.memory_sign_extend := true.B; + } + is(Funct3.LBU) { + io.memory_size := DMemSize.Byte + } + + // Half load + is(Funct3.LH) { + io.memory_size := DMemSize.Half + io.memory_sign_extend := true.B; + } + is(Funct3.LHU) { + io.memory_size := DMemSize.Half + } + + // Word load + is(Funct3.LW) { + io.memory_size := DMemSize.Word + } + } + } + +} diff --git a/src/main/scala/projet/op/OpR.scala b/src/main/scala/projet/op/OpR.scala new file mode 100644 index 0000000..e66b519 --- /dev/null +++ b/src/main/scala/projet/op/OpR.scala @@ -0,0 +1,94 @@ +package projet.op + +import chisel3._ +import chisel3.util.switch +import projet.CUInterface +import projet.AluOpCode +import chisel3.util.is + +object OpR { + // implements functions for all instruction of the opr kind + def opR(io: CUInterface) = { + val funct3 = io.instruction(14, 12); + val funct7 = io.instruction(31, 25); + + // Meaning of Funct3 in the context of an OpR instruction + object Funct3 extends ChiselEnum { + // Type I + val AdditionSubstraction = "b000".U + val AND = "b111".U + val OR = "b110".U + val XOR = "b100".U + val SLL = "b001".U + val SLT = "b010".U + val SLTU = "b011".U + + val ShiftRight = "b101".U + } + + // Meaning of Funct7 in the context of SHIFTR IR instructions + object ShiftRightFunct7 extends ChiselEnum { + val SRL = "b0000000".U + val SRA = "b0100000".U + } + + object AdditionSubstractionFunct7 extends ChiselEnum { + val ADD = "b0000000".U + val SUB = "b0100000".U + } + + 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.ADD) { + io.alu_opcode := AluOpCode.Add + } + is(AdditionSubstractionFunct7.SUB) { + io.alu_opcode := AluOpCode.Sub + } + } + } + + is(Funct3.AND) { + io.alu_opcode := AluOpCode.And + } + + is(Funct3.OR) { + io.alu_opcode := AluOpCode.Or + } + + is(Funct3.XOR) { + io.alu_opcode := AluOpCode.Xor + } + + is(Funct3.SLL) { + io.alu_opcode := AluOpCode.ShiftLeft + } + + is(Funct3.SLT) { + io.alu_opcode := AluOpCode.LessThanSigned + } + + is(Funct3.SLTU) { + io.alu_opcode := AluOpCode.LessThanUnsigned + } + + // Type IR + is(Funct3.ShiftRight) { + switch(funct7) { + is(ShiftRightFunct7.SRL) { + io.alu_opcode := AluOpCode.ShiftRight + } + + is(ShiftRightFunct7.SRA) { + io.alu_opcode := AluOpCode.ShiftArithmeticRight + } + } + } + } + } +} diff --git a/src/main/scala/projet/op/OpStore.scala b/src/main/scala/projet/op/OpStore.scala new file mode 100644 index 0000000..f48d1ba --- /dev/null +++ b/src/main/scala/projet/op/OpStore.scala @@ -0,0 +1,40 @@ +package projet.op + +import chisel3._ +import chisel3.util.switch +import projet.CUInterface +import projet.AluOpCode +import chisel3.util.is +import projet.DMemSize + +object OpStore { + // Implements functions for all instruction of the OpStore kind + def opStore(io: CUInterface) = { + val funct3 = io.instruction(14, 12); + + // 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 + io.memory_en := 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 + } + } + } +}