diff --git a/.asm-lsp.toml b/.asm-lsp.toml new file mode 100644 index 0000000..81418b3 --- /dev/null +++ b/.asm-lsp.toml @@ -0,0 +1,8 @@ +[default_config] +version = "0.10.1" +assembler = "gas" +instruction_set = "riscv" + +[default_config.opts] +diagnostics = true +default_diagnostics = true diff --git a/bench/addi.s b/bench/addi.s new file mode 100644 index 0000000..bf10d14 --- /dev/null +++ b/bench/addi.s @@ -0,0 +1,18 @@ +# expected: dead0000, dead0001, fffff800, ffffffff, 00000000 + .text +_start: + lui x2, 0xdead0 + lui x3, 0x0 + + # Add 0 + addi x31, x2, 0x0 + + # Basic addition + addi x31, x2, 0x1 + + # Sign extension + addi x31, x3, -2048 + addi x31, x3, -1 + + # Overflow + addi x31, x31, 0x1 diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index d50a437..b83b8ae 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -8,32 +8,52 @@ class CUInterface extends Bundle { val instruction = Input(UInt(32.W)) val reg_file_we = Output(Bool()) val alu_opcode = Output(AluOpCode()) + val optype = Output(OpType()) - val mux_imm_alu = Output(Bool()) + val mux_alu_imm = Output(Bool()) + val mux_rega_pc = Output(Bool()) } -object OPCode extends ChiselEnum { +object OpType extends ChiselEnum { + val U, I = Value +} + +object OpCode extends ChiselEnum { val LUI = 0b0110111.U val AUIPC = 0b0010111.U + val ADDI = 0b0010011.U } class ControlUnit() extends Module { - import OPCode._ + import OpCode._ val io = IO(new CUInterface()) io.reg_file_we := false.B io.alu_opcode := AluOpCode.Add - io.mux_imm_alu := false.B; + io.optype := OpType.U + io.mux_alu_imm := true.B; + io.mux_rega_pc := true.B; switch(io.instruction(6, 0)) { + + // U instructions is(LUI) { io.reg_file_we := true.B - io.mux_imm_alu := false.B; + io.mux_alu_imm := false.B + io.optype := OpType.U } is(AUIPC) { io.alu_opcode := AluOpCode.Add io.reg_file_we := true.B - io.mux_imm_alu := true.B; + io.mux_rega_pc := false.B + io.optype := OpType.U + } + + // I instructions + is(ADDI) { + io.alu_opcode := AluOpCode.Add + io.reg_file_we := true.B + io.optype := OpType.I } } } diff --git a/src/main/scala/projet/ImmediateDecoder.scala b/src/main/scala/projet/ImmediateDecoder.scala new file mode 100644 index 0000000..6098d8f --- /dev/null +++ b/src/main/scala/projet/ImmediateDecoder.scala @@ -0,0 +1,31 @@ +package projet + +import chisel3._ +import chisel3.util.switch +import chisel3.util.is +import chisel3.util.Cat +import chisel3.util.Fill + +class ImmediateDecoder extends Module { + import projet.OpType + + val io = IO(new Bundle { + val op_type = Input(OpType()) + val instruction = Input(UInt(32.W)) + val immediate = Output(UInt(32.W)) + }) + io.immediate := 0.U + + // Decode imm-u + 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)); + switch(io.op_type) { + is(OpType.U) { + io.immediate := imm_u + } + is(OpType.I) { + io.immediate := imm_i + } + } +} diff --git a/src/main/scala/projet/RegFile.scala b/src/main/scala/projet/RegFile.scala index d2a366e..3a7354c 100644 --- a/src/main/scala/projet/RegFile.scala +++ b/src/main/scala/projet/RegFile.scala @@ -25,25 +25,21 @@ class RegFile(sim: Boolean = false) extends Module { } when(io.we && io.rd_addr =/= 0.U) { - regs(io.rd_addr) := io.rd_data + regs(io.rd_addr) := io.rd_data } io.rs1_data := regs(io.rs1_addr) io.rs2_data := regs(io.rs2_addr) // 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) + io.valid_x31.get := false.B + } + io.x31 := "hDEADC0DE".U + when(io.we && io.rd_addr === 31.U) { + io.x31 := io.rd_data + if (sim) { + io.valid_x31.get := true.B + } } } diff --git a/src/main/scala/projet/Rv32i.scala b/src/main/scala/projet/Rv32i.scala index 9b70d7b..e7e12fa 100644 --- a/src/main/scala/projet/Rv32i.scala +++ b/src/main/scala/projet/Rv32i.scala @@ -1,7 +1,6 @@ package projet import chisel3._ -import chisel3.util.Cat class Rv32i(sim: Boolean = true) extends Module { val io = IO(new Bundle { @@ -18,12 +17,15 @@ 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 + io.valid_x31.get := reg_file.io.valid_x31.get && Delay.Delay(!reset.asBool, 1, false.B) } val alu = Module(new Alu()); + val immediate_decoder = Module(new ImmediateDecoder()); val control_unit = Module(new ControlUnit()); + immediate_decoder.io.instruction := instruction + immediate_decoder.io.op_type := control_unit.io.optype alu.io.opcode := control_unit.io.alu_opcode; reg_file.io.we := control_unit.io.reg_file_we @@ -49,16 +51,19 @@ class Rv32i(sim: Boolean = true) extends Module { val rd = instruction(11, 7) reg_file.io.rd_addr := rd - // Decode imm-u - val imm_u = Cat(instruction(31, 12), 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); - + val imm = immediate_decoder.io.immediate + + alu.io.a := Mux( + control_unit.io.mux_rega_pc, + reg_file.io.rs1_data, + execute_pc + ); + alu.io.b := imm; + + reg_file.io.rd_data := Mux(control_unit.io.mux_alu_imm, alu.io.out, imm); + io.dbus.addr := 0.U; io.dbus.wdata := 0.U; io.dbus.be := VecInit(false.B, false.B, false.B, false.B)