diff --git a/bench/tests/op/add.s b/bench/tests/op/add.s index 9dcef14..95a19b1 100644 --- a/bench/tests/op/add.s +++ b/bench/tests/op/add.s @@ -3,7 +3,7 @@ _start: lui x2, 0xdead0 lui x3, 0x0 - lui x4, 0x1 + addi x4, x0, 0x1 addi x5, x0, (-1) # Add 0 diff --git a/bench/tests/op/slt.s b/bench/tests/op/slt.s index 3f380ec..531da56 100644 --- a/bench/tests/op/slt.s +++ b/bench/tests/op/slt.s @@ -1,4 +1,4 @@ -# expected: 00000000, 00000001, 00000001, 00000000 +# expected: 00000000, 00000001, 00000000, 00000000 .text _start: addi x1, x0, (-1) diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index 363d981..b573d86 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -10,8 +10,12 @@ class CUInterface extends Bundle { val alu_opcode = Output(AluOpCode()) val optype = Output(OpType()) + // Muxers + // The naming convention is as follows : mux_xxx_yyy. + // If the signal is hot, xxx is selected otherwise yyy is selected val mux_alu_imm = Output(Bool()) val mux_rega_pc = Output(Bool()) + val mux_regb_imm = Output(Bool()) } object OpType extends ChiselEnum { @@ -26,7 +30,7 @@ object OpCode extends ChiselEnum { // Type I + Type IR // Instruction format - // xxx rd, rs1 imm + // xxx rd, rs1, imm // Perfomrs some operation with rs1 and immediate // and writes back to a register @@ -34,6 +38,14 @@ object OpCode extends ChiselEnum { // slti, sltiu val OpImm = 0b0010011.U + // Instruction format + // xxx rd, rs1, rs2 + // Perfomrs some operation with rs1 and rd2 + // and writes back to a register + + // add, and, or, xor, sll, srl, sra, slt, stlu + val OpR = 0b0110011.U; + } @@ -45,6 +57,7 @@ class ControlUnit() extends Module { io.optype := OpType.U io.mux_alu_imm := true.B; io.mux_rega_pc := true.B; + io.mux_regb_imm := true.B; // Decode instruction val opcode = io.instruction(6, 0); @@ -54,15 +67,16 @@ class ControlUnit() extends Module { switch(opcode) { // U instructions - is(OpCode.LUI) { - io.reg_file_we := true.B - io.mux_alu_imm := false.B + is(OpCode.LUI) { + io.reg_file_we := true.B // Write to regfile + io.mux_alu_imm := false.B // Send immy directly to refile io.optype := OpType.U } is(OpCode.AUIPC) { io.alu_opcode := AluOpCode.Add - io.reg_file_we := true.B - io.mux_rega_pc := false.B + io.reg_file_we := true.B // Write to regfile + io.mux_rega_pc := false.B // Send PC to ALU A + io.mux_alu_imm := false.B; // Send immu to ALU B io.optype := OpType.U } @@ -71,8 +85,16 @@ class ControlUnit() extends Module { io.reg_file_we := true.B opImm(funct3, funct7, io); } + + // OpR instructions + is(OpCode.OpR) { + io.reg_file_we := true.B + opR(funct3, funct7, io); + } } + + // Implements functions for all instruction of the opImm kind def opImm(funct3: UInt, funct7: UInt, io: CUInterface) = { @@ -98,6 +120,10 @@ class ControlUnit() extends Module { val SRLI = 0b0000000.U val SRAI = 0b0100000.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 @@ -162,6 +188,93 @@ class ControlUnit() extends Module { } } } + + + // 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 = 0b000.U + val AND = 0b111.U + val OR = 0b110.U + val XOR = 0b100.U + val SLL = 0b001.U + val SLT = 0b010.U + val SLTU = 0b011.U + + // Arithmetic op (discriminate by Funct7) + val SRL_SRA = 0b101.U + } + + // Meaning of Funct7 in the context of SHIFTR IR instructions + object IRFunct7 extends ChiselEnum + { + val SRL = 0b0000000.U + val SRA = 0b0100000.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) + { + io.alu_opcode := AluOpCode.Add + } + + 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 + } + } + } + } + } } diff --git a/src/main/scala/projet/Rv32i.scala b/src/main/scala/projet/Rv32i.scala index fcc27ef..1dcf7f6 100644 --- a/src/main/scala/projet/Rv32i.scala +++ b/src/main/scala/projet/Rv32i.scala @@ -64,7 +64,7 @@ class Rv32i(sim: Boolean = true) extends Module { reg_file.io.rs1_data, execute_pc ); - alu.io.b := imm; + alu.io.b := Mux(control_unit.io.mux_regb_imm, reg_file.io.rs2_data, imm); reg_file.io.rd_data := Mux(control_unit.io.mux_alu_imm, alu.io.out, imm);