From 0ea6dc8c39f84d76e69c76fc61b642c1d4092a56 Mon Sep 17 00:00:00 2001 From: marko1616 Date: Tue, 12 Nov 2024 07:38:43 +0800 Subject: [PATCH] Support for Zicsr. --- TODO.md | 16 +- docs/update-log.md | 9 +- .../markorv/ControlStatusRegisters.scala | 106 +++++++----- src/main/scala/markorv/TopModule.scala | 16 ++ src/main/scala/markorv/WriteBack.scala | 10 +- src/main/scala/markorv/backend/MiscUnit.scala | 67 +++++++- .../scala/markorv/frontend/InstrDecoder.scala | 162 +++++++++++------- .../scala/markorv/frontend/InstrIssuer.scala | 16 +- tests/asmtst/zicsr.S | 12 ++ 9 files changed, 289 insertions(+), 125 deletions(-) create mode 100644 tests/asmtst/zicsr.S diff --git a/TODO.md b/TODO.md index 49586e3..47eb721 100644 --- a/TODO.md +++ b/TODO.md @@ -103,14 +103,14 @@
- Zicsr Extension Instructions - -- [ ] csrrw -- [ ] csrrs -- [ ] csrrc -- [ ] csrrwi -- [ ] csrrsi -- [ ] csrrci + Zicsr Extension Instructions + +- [x] csrrw +- [x] csrrs +- [x] csrrc +- [x] csrrwi +- [x] csrrsi +- [x] csrrci
diff --git a/docs/update-log.md b/docs/update-log.md index 7d8a6b6..cb750de 100644 --- a/docs/update-log.md +++ b/docs/update-log.md @@ -4,6 +4,7 @@ * ✅ Feat: Remove LSU state machine. * ✅ Feat: Better build and compile implementation. * ✅ Feat: Custom cpp & verilator based test workflow. +* ✅ Feat: Support for basic Zicsr. * 📚 Docs: Added readme. 🎉 **Version 0.1 Released!** 🎉 @@ -17,8 +18,8 @@ 📝 **Previously Unlogged Updates** 📝 -* ✅ Feat: support for Immediate Instructions -* ✅ Feat: support for Register-Register Instructions -* ✅ Feat: support for Memory Instructions -* ✅ Feat: support for Flow Control Instructions +* ✅ Feat: Support for Immediate Instructions +* ✅ Feat: Support for Register-Register Instructions +* ✅ Feat: Support for Memory Instructions +* ✅ Feat: Support for Flow Control Instructions * ✅ Feat: Implemented L1 Instruction Cache support diff --git a/src/main/scala/markorv/ControlStatusRegisters.scala b/src/main/scala/markorv/ControlStatusRegisters.scala index 4dc4bb5..a5dddc5 100644 --- a/src/main/scala/markorv/ControlStatusRegisters.scala +++ b/src/main/scala/markorv/ControlStatusRegisters.scala @@ -3,17 +3,25 @@ package markorv import chisel3._ import chisel3.util._ +class ControlStatusRegistersIO extends Bundle { + val read_addr = Input(UInt(12.W)) + val write_addr = Input(UInt(12.W)) + val write_en = Input(Bool()) + + val read_data = Output(UInt(64.W)) + val write_data = Input(UInt(64.W)) +} + class ControlStatusRegisters extends Module { val io = IO(new Bundle { - val read_addr = Input(UInt(12.W)) - val write_addr = Input(UInt(12.W)) - - val read_data = Output(UInt(64.W)) - val write_data = Input(UInt(64.W)) - val write_mask = Input(UInt(64.W)) + val csrio = new ControlStatusRegistersIO }) // While read write simultaneously shuould return old value. + // Machine custom register(MRW) + // For Zicsr test. + val MCUSTOMTST_ADDR = "h800".U(12.W) + // Machine infomations(MRO). val MVENDORID_ADDR = "hf11".U(12.W) val MARCHID_ADDR = "hf12".U(12.W) @@ -30,6 +38,8 @@ class ControlStatusRegisters extends Module { val MTVEC_ADDR = "h305".U(12.W) val MCOUNTEREN_ADDR = "h306".U(12.W) + val mcustomtst = RegInit("h0000000000000000".U(64.W)) + val mstatus = RegInit("h0000000000000000".U(64.W)) val misa = RegInit("h8000000000000100".U(64.W)) val medeleg = RegInit("h0000000000000000".U(64.W)) @@ -39,72 +49,82 @@ class ControlStatusRegisters extends Module { val mcounteren = RegInit("h00000000".U(32.W)) - io.read_data := 0.U - switch(io.read_addr) { + io.csrio.read_data := 0.U + switch(io.csrio.read_addr) { + is(MCUSTOMTST_ADDR) { + io.csrio.read_data := mcustomtst + } + is(MVENDORID_ADDR) { // Non-commercial. - io.read_data := "h0000000000000000".U + io.csrio.read_data := "h0000000000000000".U } is(MARCHID_ADDR) { // In development. - io.read_data := "h0000000000000000".U + io.csrio.read_data := "h0000000000000000".U } is(MIMPID_ADDR) { // In development. - io.read_data := "h0000000000000000".U + io.csrio.read_data := "h0000000000000000".U } is(MHARTID_ADDR) { // 0x0 - io.read_data := "h0000000000000000".U + io.csrio.read_data := "h0000000000000000".U } is(MCONFIGPTR_ADDR) { // TODO machine config - io.read_data := "h0000000000000000".U + io.csrio.read_data := "h0000000000000000".U } is(MSTATUS_ADDR) { - io.read_data := mstatus + io.csrio.read_data := mstatus } is(MISA_ADDR) { // RV64I - io.read_data := misa + io.csrio.read_data := misa } is(MEDELEG_ADDR) { - io.read_data := medeleg + io.csrio.read_data := medeleg } is(MIDELEG_ADDR) { - io.read_data := mideleg + io.csrio.read_data := mideleg } is(MCOUNTEREN_ADDR) { - io.read_data := mcounteren + io.csrio.read_data := mcounteren } } - switch(io.write_addr) { - is(MSTATUS_ADDR) { - // write mask shown that which fields is implemented. - val write_mask = "h0000000000000000".U - mstatus := write_mask & io.write_data - } - is(MISA_ADDR) { - // Can't write this to switch func for now. - } - is(MEDELEG_ADDR) { - // TODO S mode - medeleg := io.write_data - } - is(MIDELEG_ADDR) { - // TODO S mode - mideleg := io.write_data - } - is(MTVEC_ADDR) { - // mtvec mode >= 2 is Reserved - val write_mask = "hfffffffffffffffd".U - mtvec := write_mask & io.write_data - } - is(MCOUNTEREN_ADDR) { - // TODO counter - mcounteren := io.write_data + when(io.csrio.write_en) { + switch(io.csrio.write_addr) { + is(MCUSTOMTST_ADDR) { + mcustomtst := io.csrio.write_data + } + + is(MSTATUS_ADDR) { + // write mask shown that which fields is implemented. + val write_mask = "h0000000000000000".U + mstatus := write_mask & io.csrio.write_data + } + is(MISA_ADDR) { + // Can't write this to switch func for now. + } + is(MEDELEG_ADDR) { + // TODO S mode + medeleg := io.csrio.write_data + } + is(MIDELEG_ADDR) { + // TODO S mode + mideleg := io.csrio.write_data + } + is(MTVEC_ADDR) { + // mtvec mode >= 2 is Reserved + val write_mask = "hfffffffffffffffd".U + mtvec := write_mask & io.csrio.write_data + } + is(MCOUNTEREN_ADDR) { + // TODO counter + mcounteren := io.csrio.write_data + } } } } diff --git a/src/main/scala/markorv/TopModule.scala b/src/main/scala/markorv/TopModule.scala index 713a658..493d81e 100644 --- a/src/main/scala/markorv/TopModule.scala +++ b/src/main/scala/markorv/TopModule.scala @@ -38,8 +38,11 @@ class MarkoRvCore extends Module { val load_store_unit = Module(new LoadStoreUnit) val arithmetic_logic_unit = Module(new ArithmeticLogicUnit) val branch_unit = Module(new BranchUnit) + val misc_unit = Module(new MiscUnit) val register_file = Module(new RegFile) + val csr_file = Module(new ControlStatusRegisters) + val write_back = Module(new WriteBack) data_cache_warpper.io.cache_write_req <> data_cache.io.write_req @@ -98,6 +101,7 @@ class MarkoRvCore extends Module { write_back.io.reg_write <> register_file.io.write_addr write_back.io.write_data <> register_file.io.write_data + csr_file.io.csrio <> misc_unit.io.csrio register_file.io.flush := branch_unit.io.flush // Main pipeline. @@ -127,6 +131,12 @@ class MarkoRvCore extends Module { load_store_unit.io.outfire, branch_unit.io.flush ) + PipelineConnect( + instr_issuer.io.misc_out, + misc_unit.io.misc_instr, + misc_unit.io.outfire, + branch_unit.io.flush + ) PipelineConnect( instr_issuer.io.branch_out, branch_unit.io.branch_instr, @@ -153,6 +163,12 @@ class MarkoRvCore extends Module { write_back.io.outfires(2), branch_unit.io.flush ) + PipelineConnect( + misc_unit.io.write_back, + write_back.io.write_backs(3), + write_back.io.outfires(3), + branch_unit.io.flush + ) } object MarkoRvCore extends App { diff --git a/src/main/scala/markorv/WriteBack.scala b/src/main/scala/markorv/WriteBack.scala index 3011de7..83fba4c 100644 --- a/src/main/scala/markorv/WriteBack.scala +++ b/src/main/scala/markorv/WriteBack.scala @@ -5,9 +5,7 @@ import chisel3.util._ class WriteBack extends Module { val io = IO(new Bundle { - val write_backs = Vec( - 3, - Flipped(Decoupled(new Bundle { + val write_backs = Vec(4, Flipped(Decoupled(new Bundle { val reg = UInt(5.W) val data = UInt(64.W) })) @@ -16,10 +14,10 @@ class WriteBack extends Module { val reg_write = Output(UInt(5.W)) val write_data = Output(UInt(64.W)) - val outfires = Vec(3, Output(Bool())) + val outfires = Vec(4, Output(Bool())) }) - for (i <- 0 until 3) { + for (i <- 0 until 4) { io.write_backs(i).ready := true.B io.outfires(i) := true.B } @@ -28,7 +26,7 @@ class WriteBack extends Module { io.write_data := 0.U // Impossible to write back multiple times in one cycle. - for (i <- 0 until 3) { + for (i <- 0 until 4) { when(io.write_backs(i).valid) { io.reg_write := io.write_backs(i).bits.reg io.write_data := io.write_backs(i).bits.data diff --git a/src/main/scala/markorv/backend/MiscUnit.scala b/src/main/scala/markorv/backend/MiscUnit.scala index f45eeca..2b0bdfb 100644 --- a/src/main/scala/markorv/backend/MiscUnit.scala +++ b/src/main/scala/markorv/backend/MiscUnit.scala @@ -3,16 +3,17 @@ package markorv.backend import chisel3._ import chisel3.util._ +import markorv.ControlStatusRegistersIO import markorv.frontend.DecoderOutParams class MiscUnit extends Module { val io = IO(new Bundle { // misc_opcode encoding: - // Bit [4] AMO operate reserved. - // Bit [3] System operate(ecall ebrack etc) reserved. - // Bit [2] Fence operate(fence fence.i) reserved. - // Bit [1] Cache line operate(zicbox) reserved. - // Bit [0] CSR(zicsr) operate. + // Bit [2,0] == 4 AMO operate reserved. + // Bit [2,0] == 3 System operate(ecall ebrack etc) reserved. + // Bit [2,0] == 2 Fence operate(fence fence.i) reserved. + // Bit [2,0] == 1 Cache line operate(zicbox) reserved. + // Bit [2,0] == 0 CSR(zicsr) operate. Bit[3] = rs1 == x0 ? 1 : 0. val misc_instr = Flipped(Decoupled(new Bundle { val misc_opcode = UInt(5.W) val params = new DecoderOutParams(64) @@ -22,6 +23,62 @@ class MiscUnit extends Module { val reg = Input(UInt(5.W)) val data = Input(UInt(64.W)) }) + + val csrio = Flipped(new ControlStatusRegistersIO) + val outfire = Output(Bool()) }) + // M mode when reset. + val privilege_reg = RegInit(3.U(2.W)) + val opcode = io.misc_instr.bits.misc_opcode + val params = io.misc_instr.bits.params + + // Immediate shall handle by decoder. + val CSRRW = "b01".U + val CSRRS = "b10".U + val CSRRC = "b11".U + io.csrio.write_en := false.B + io.csrio.read_addr := 0.U + io.csrio.write_addr := 0.U + io.csrio.write_data := 0.U + + io.outfire := true.B + io.misc_instr.ready := true.B + io.write_back.valid := false.B + io.write_back.bits.reg := 0.U + io.write_back.bits.data := 0.U + + when(io.misc_instr.valid) { + when(opcode(2,0) === 0.U) { + val csr_src1 = params.source1 + val csr_addr = params.source2 + val csr_func = params.immediate + // If rs1 == x0 csrrc and csrrs shall not cause any side effect like illegal instruction exceptions. + val csr_ro = opcode(3) && csr_func =/= CSRRW + + // Reserved for illegal instruction exceptions. + val is_csr_read_only = csr_addr(11, 10) === 3.U + val has_privilege = privilege_reg > csr_addr(9, 8) + + io.csrio.read_addr := csr_addr + val csr_data = io.csrio.read_data + + io.csrio.write_en := ~csr_ro + io.csrio.write_addr := csr_addr + switch(csr_func(1, 0)) { + is(CSRRW) { + io.csrio.write_data := csr_src1 + } + is(CSRRS) { + io.csrio.write_data := csr_data | csr_src1 + } + is(CSRRC) { + io.csrio.write_data := csr_data & ~csr_src1 + } + } + io.write_back.valid := true.B + io.write_back.bits.reg := params.rd + io.write_back.bits.data := csr_data + } + } } diff --git a/src/main/scala/markorv/frontend/InstrDecoder.scala b/src/main/scala/markorv/frontend/InstrDecoder.scala index 41f97f7..f27e9f7 100644 --- a/src/main/scala/markorv/frontend/InstrDecoder.scala +++ b/src/main/scala/markorv/frontend/InstrDecoder.scala @@ -24,6 +24,7 @@ class IssueTask extends Bundle { val operate_unit = UInt(2.W) val alu_opcode = UInt(5.W) val lsu_opcode = UInt(5.W) + val misc_opcode = UInt(5.W) val branch_opcode = UInt(5.W) val pred_taken = Bool() val pred_pc = UInt(64.W) @@ -44,7 +45,6 @@ class InstrDecoder(data_width: Int = 64, addr_width: Int = 64) extends Module { val instr = Wire(UInt(32.W)) val pc = Wire(UInt(64.W)) - val opcode = Wire(UInt(7.W)) val valid_instr = Wire(Bool()) // 0 for alu 1 for lsu 2 for branch val operate_unit = Wire(UInt(2.W)) @@ -54,9 +54,28 @@ class InstrDecoder(data_width: Int = 64, addr_width: Int = 64) extends Module { 0.U.asTypeOf(new RegisterSourceRequests(data_width)) ) + val OP_LUI = "b0110111".U + val OP_AUIPC = "b0010111".U + val OP_IMM = "b0010011".U + val OP_IMM32 = "b0011011".U + val OP = "b0110011".U + val OP_32 = "b0111011".U + val OP_LOAD = "b0000011".U + val OP_STOR = "b0100011".U + val OP_JAL = "b1101111".U + val OP_JALR = "b1100111".U + val OP_BRANCH = "b1100011".U + val OP_SYSTEM = "b1110011".U + + val opcode = instr(6, 0) + val rd = instr(11, 7) + val rs1 = instr(19, 15) + val rs2 = instr(24, 20) + val funct3 = instr(14, 12) + val funct7 = instr(31, 25) + instr := io.instr_bundle.bits.instr pc := io.instr_bundle.bits.pc - opcode := instr(6, 0) valid_instr := false.B operate_unit := 0.U @@ -75,45 +94,45 @@ class InstrDecoder(data_width: Int = 64, addr_width: Int = 64) extends Module { when(io.instr_bundle.valid) { switch(opcode) { - is("b0110111".U) { + is(OP_LUI) { // lui issue_task.alu_opcode := 1.U params.source1 := (instr(31, 12) << 12).asSInt .pad(64) .asUInt params.source2 := 0.U - params.rd := instr(11, 7) + params.rd := rd valid_instr := true.B operate_unit := 0.U } - is("b0010111".U) { + is(OP_AUIPC) { // auipc issue_task.alu_opcode := 1.U params.source1 := (instr(31, 12) << 12).asSInt .pad(64) .asUInt params.source2 := pc - params.rd := instr(11, 7) + params.rd := rd valid_instr := true.B operate_unit := 0.U } - is("b0010011".U) { + is(OP_IMM) { // addi slti sltiu xori ori andi slli srli srai - when(instr(14, 12) === "b001".U) { + when(funct3 === "b001".U) { // slli issue_task.alu_opcode := "b00011".U params.source2 := (instr(25, 20).asSInt .pad(64)) .asUInt - }.elsewhen(instr(14, 12) === "b101".U && instr(30)) { + }.elsewhen(funct3 === "b101".U && instr(30)) { // srai issue_task.alu_opcode := "b01011".U params.source2 := (instr(25, 20).asSInt .pad(64)) .asUInt - }.elsewhen(instr(14, 12) === "b101".U) { + }.elsewhen(funct3 === "b101".U) { // srli issue_task.alu_opcode := "b01010".U params.source2 := (instr(25, 20).asSInt @@ -122,34 +141,34 @@ class InstrDecoder(data_width: Int = 64, addr_width: Int = 64) extends Module { }.otherwise { issue_task.alu_opcode := Cat( 0.U(1.W), - instr(14, 12), + funct3, 1.U(1.W) ) params.source2 := (instr(31, 20).asSInt .pad(64)) .asUInt } - reg_source_requests.source1 := instr(19, 15) - params.rd := instr(11, 7) + reg_source_requests.source1 := rs1 + params.rd := rd valid_instr := true.B operate_unit := 0.U } - is("b0011011".U) { + is(OP_IMM32) { // addiw slliw srliw sraiw - when(instr(14, 12) === "b001".U) { + when(funct3 === "b001".U) { // slliw issue_task.alu_opcode := "b10011".U params.source2 := (instr(25, 20).asSInt .pad(64)) .asUInt - }.elsewhen(instr(14, 12) === "b101".U && instr(30)) { + }.elsewhen(funct3 === "b101".U && instr(30)) { // sraiw issue_task.alu_opcode := "b11011".U params.source2 := (instr(25, 20).asSInt .pad(64)) .asUInt - }.elsewhen(instr(14, 12) === "b101".U) { + }.elsewhen(funct3 === "b101".U) { // srliw issue_task.alu_opcode := "b11010".U params.source2 := (instr(25, 20).asSInt @@ -158,142 +177,169 @@ class InstrDecoder(data_width: Int = 64, addr_width: Int = 64) extends Module { }.otherwise { issue_task.alu_opcode := Cat( 1.U(1.W), - instr(14, 12), + funct3, 1.U(1.W) ) params.source2 := (instr(31, 20).asSInt .pad(64)) .asUInt } - reg_source_requests.source1 := instr(19, 15) - params.rd := instr(11, 7) + reg_source_requests.source1 := rs1 + params.rd := rd valid_instr := true.B operate_unit := 0.U } - is("b0110011".U) { + is(OP) { // add sub slt sltu xor or and sll srl sra - when(instr(14, 12) === "b001".U) { + when(funct3 === "b001".U) { // sll issue_task.alu_opcode := "b00011".U - }.elsewhen(instr(14, 12) === "b101".U && instr(30)) { + }.elsewhen(funct3 === "b101".U && instr(30)) { // sra issue_task.alu_opcode := "b01011".U - }.elsewhen(instr(14, 12) === "b101".U) { + }.elsewhen(funct3 === "b101".U) { // srl issue_task.alu_opcode := "b01010".U - }.elsewhen(instr(14, 12) === "b000".U && instr(30)) { + }.elsewhen(funct3 === "b000".U && instr(30)) { // sub issue_task.alu_opcode := "b00000".U }.otherwise { issue_task.alu_opcode := Cat( 1.U(1.W), - instr(14, 12), + funct3, 1.U(1.W) ) } - reg_source_requests.source1 := instr(19, 15) - reg_source_requests.source2 := instr(24, 20) - params.rd := instr(11, 7) + reg_source_requests.source1 := rs1 + reg_source_requests.source2 := rs2 + params.rd := rd valid_instr := true.B operate_unit := 0.U } - is("b0111011".U) { + is(OP_32) { // addw subw sllw srlw sraw - when(instr(14, 12) === "b001".U) { + when(funct3 === "b001".U) { // sllw issue_task.alu_opcode := "b10011".U - }.elsewhen(instr(14, 12) === "b101".U && instr(30)) { + }.elsewhen(funct3 === "b101".U && instr(30)) { // sraw issue_task.alu_opcode := "b11011".U - }.elsewhen(instr(14, 12) === "b101".U) { + }.elsewhen(funct3 === "b101".U) { // srlw issue_task.alu_opcode := "b11010".U - }.elsewhen(instr(14, 12) === "b000".U && instr(30)) { + }.elsewhen(funct3 === "b000".U && instr(30)) { // subw issue_task.alu_opcode := "b10000".U }.otherwise { issue_task.alu_opcode := Cat( 1.U(1.W), - instr(14, 12), + funct3, 1.U(1.W) ) } - reg_source_requests.source1 := instr(19, 15) + reg_source_requests.source1 := rs1 reg_source_requests.source1_read_word := true.B - reg_source_requests.source2 := instr(24, 20) - params.rd := instr(11, 7) + reg_source_requests.source2 := rs2 + params.rd := rd valid_instr := true.B operate_unit := 0.U } - is("b0000011".U) { + is(OP_LOAD) { // Load Memory - issue_task.lsu_opcode := Cat("b00".U, instr(14, 12)) + issue_task.lsu_opcode := Cat("b00".U, funct3) params.immediate := instr(31, 20).asSInt .pad(64) .asUInt - reg_source_requests.source1 := instr(19, 15) + reg_source_requests.source1 := rs1 params.source2 := 0.U(data_width.W) - params.rd := instr(11, 7) + params.rd := rd valid_instr := true.B operate_unit := 1.U } - is("b0100011".U) { + is(OP_STOR) { // Store Memory - issue_task.lsu_opcode := Cat("b10".U, instr(14, 12)) + issue_task.lsu_opcode := Cat("b10".U, funct3) params.immediate := Cat( instr(31, 25), instr(11, 7) ).asSInt.pad(64).asUInt - reg_source_requests.source1 := instr(19, 15) - reg_source_requests.source2 := instr(24, 20) + reg_source_requests.source1 := rs1 + reg_source_requests.source2 := rs2 valid_instr := true.B operate_unit := 1.U } - is("b1101111".U) { + is(OP_JAL) { // jal issue_task.branch_opcode := "b00001".U issue_task.pred_taken := io.instr_bundle.bits.pred_taken issue_task.recovery_pc := io.instr_bundle.bits.recovery_pc params.pc := pc - params.rd := instr(11, 7) + params.rd := rd valid_instr := true.B - operate_unit := 2.U + operate_unit := 3.U } - is("b1100111".U) { + is(OP_JALR) { // jalr issue_task.branch_opcode := "b00011".U issue_task.pred_taken := io.instr_bundle.bits.pred_taken issue_task.pred_pc := io.instr_bundle.bits.pred_pc issue_task.recovery_pc := io.instr_bundle.bits.recovery_pc params.pc := pc - params.rd := instr(11, 7) + params.rd := rd - reg_source_requests.source1 := instr(19, 15) + reg_source_requests.source1 := rs1 params.immediate := instr(31, 20).asSInt .pad(64) .asUInt valid_instr := true.B - operate_unit := 2.U + operate_unit := 3.U } - is("b1100011".U) { + is(OP_BRANCH) { // branch - issue_task.branch_opcode := Cat(0.U, instr(14, 12), 0.U) + issue_task.branch_opcode := Cat(0.U, funct3, 0.U) issue_task.pred_taken := io.instr_bundle.bits.pred_taken issue_task.pred_pc := io.instr_bundle.bits.pred_pc issue_task.recovery_pc := io.instr_bundle.bits.recovery_pc - reg_source_requests.source1 := instr(19, 15) - reg_source_requests.source2 := instr(24, 20) + reg_source_requests.source1 := rs1 + reg_source_requests.source2 := rs2 valid_instr := true.B - operate_unit := 2.U + operate_unit := 3.U + } + is(OP_SYSTEM) { + // TODO ecall ebreak xret wfi sfence.vma + val func = funct3 + + when(func =/= 0.U) { + val is_imm = func(2) + + // CSR addr. + params.source2 := instr(31, 20) + when(rs1 === 0.U && ~is_imm) { + // Allow having write side effect. + issue_task.misc_opcode := "b01000".U + }.otherwise { + issue_task.misc_opcode := "b00000".U + } + when(is_imm) { + params.source1 := rs1.pad(64) + }.otherwise { + reg_source_requests.source1 := rs1 + } + params.immediate := func & "b011".U + params.rd := rd + + valid_instr := true.B + operate_unit := 2.U + } } } } diff --git a/src/main/scala/markorv/frontend/InstrIssuer.scala b/src/main/scala/markorv/frontend/InstrIssuer.scala index 002b467..b010909 100644 --- a/src/main/scala/markorv/frontend/InstrIssuer.scala +++ b/src/main/scala/markorv/frontend/InstrIssuer.scala @@ -19,6 +19,11 @@ class InstrIssueUnit extends Module { val params = new DecoderOutParams(64) }) + val misc_out = Decoupled(new Bundle { + val misc_opcode = UInt(5.W) + val params = new DecoderOutParams(64) + }) + val branch_out = Decoupled(new Bundle { val branch_opcode = UInt(5.W) val pred_taken = Bool() @@ -45,16 +50,20 @@ class InstrIssueUnit extends Module { val occupied_reg = Wire(Bool()) val exec_unit_ready = Wire(Bool()) occupied_reg := false.B - exec_unit_ready := io.lsu_out.ready && io.alu_out.ready && io.branch_out.ready + // Force exec order. + exec_unit_ready := io.lsu_out.ready && io.alu_out.ready && io.branch_out.ready && io.misc_out.ready io.lsu_out.valid := false.B io.alu_out.valid := false.B + io.misc_out.valid := false.B io.branch_out.valid := false.B io.lsu_out.bits.lsu_opcode := 0.U io.lsu_out.bits.params := 0.U.asTypeOf(new DecoderOutParams(64)) io.alu_out.bits.alu_opcode := 0.U io.alu_out.bits.params := 0.U.asTypeOf(new DecoderOutParams(64)) + io.misc_out.bits.misc_opcode := 0.U + io.misc_out.bits.params := 0.U.asTypeOf(new DecoderOutParams(64)) io.branch_out.bits.branch_opcode := 0.U io.branch_out.bits.pred_taken := false.B io.branch_out.bits.pred_pc := 0.U @@ -101,6 +110,11 @@ class InstrIssueUnit extends Module { io.lsu_out.bits.lsu_opcode := io.issue_task.bits.lsu_opcode io.lsu_out.bits.params := params }.elsewhen(io.issue_task.bits.operate_unit === 2.U && io.acquired) { + io.outfire := true.B + io.misc_out.valid := true.B + io.misc_out.bits.misc_opcode := io.issue_task.bits.misc_opcode + io.misc_out.bits.params := params + }.elsewhen(io.issue_task.bits.operate_unit === 3.U && io.acquired) { io.outfire := true.B io.branch_out.valid := true.B io.branch_out.bits.branch_opcode := io.issue_task.bits.branch_opcode diff --git a/tests/asmtst/zicsr.S b/tests/asmtst/zicsr.S new file mode 100644 index 0000000..a7b048a --- /dev/null +++ b/tests/asmtst/zicsr.S @@ -0,0 +1,12 @@ +li t0, 0x55 +csrrw a0, 0x800, t0 +li t0, 0x0F +csrrs a0, 0x800, t0 +li t0, 0x0F +csrrc a0, 0x800, t0 + +csrrsi a0, 0x800, 0x3 +csrrci a0, 0x800, 0x2 +csrrwi a0, 0x800, 0x1F + +csrr a0, 0x800 \ No newline at end of file