diff --git a/src/main/scala/rocket/CustomInstructions.scala b/src/main/scala/deprecate/rocket/CustomInstructions.scala similarity index 98% rename from src/main/scala/rocket/CustomInstructions.scala rename to src/main/scala/deprecate/rocket/CustomInstructions.scala index b4cada00bee..d476630294e 100644 --- a/src/main/scala/rocket/CustomInstructions.scala +++ b/src/main/scala/deprecate/rocket/CustomInstructions.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.rocket import chisel3.util._ +import freechips.rocketchip.rocket._ object CustomInstructions { def MNRET = BitPat("b01110000001000000000000001110011") diff --git a/src/main/scala/rocket/Decode.scala b/src/main/scala/deprecate/rocket/Decode.scala similarity index 98% rename from src/main/scala/rocket/Decode.scala rename to src/main/scala/deprecate/rocket/Decode.scala index 7ea8580372d..d9a052ef93a 100644 --- a/src/main/scala/rocket/Decode.scala +++ b/src/main/scala/deprecate/rocket/Decode.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util.BitPat import chisel3.util.experimental.decode._ +import freechips.rocketchip.rocket._ object DecodeLogic { diff --git a/src/main/scala/rocket/IDecode.scala b/src/main/scala/deprecate/rocket/IDecode.scala similarity index 99% rename from src/main/scala/rocket/IDecode.scala rename to src/main/scala/deprecate/rocket/IDecode.scala index 50db5dda926..befb7df5c44 100644 --- a/src/main/scala/rocket/IDecode.scala +++ b/src/main/scala/deprecate/rocket/IDecode.scala @@ -7,6 +7,7 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.util._ +import freechips.rocketchip.rocket._ import Instructions._ import CustomInstructions._ diff --git a/src/main/scala/rocket/Instructions.scala b/src/main/scala/deprecate/rocket/Instructions.scala similarity index 99% rename from src/main/scala/rocket/Instructions.scala rename to src/main/scala/deprecate/rocket/Instructions.scala index adf1183388f..48339fffc24 100644 --- a/src/main/scala/rocket/Instructions.scala +++ b/src/main/scala/deprecate/rocket/Instructions.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.rocket import chisel3.util._ +import freechips.rocketchip.rocket._ /* make EXTENSIONS="rv_* rv64*" inst.chisel */ diff --git a/src/main/scala/rocket/Decoder.scala b/src/main/scala/rocket/Decoder.scala index de2871a9bd0..57d4cc94942 100644 --- a/src/main/scala/rocket/Decoder.scala +++ b/src/main/scala/rocket/Decoder.scala @@ -6,7 +6,7 @@ package org.chipsalliance.rocketcore.decoder import chisel3._ import chisel3.util.BitPat import chisel3.util.experimental.decode._ -import org.chipsalliance.rvdecoderdb.{Instruction, InstructionSet, Utils} +import org.chipsalliance.rvdecoderdb.{Encoding, Instruction, InstructionSet, Utils} // behave like ChiselEnum, but for compatibility, use UInt for now. // This is going to be upstreamed to Chisel in the future. @@ -31,40 +31,96 @@ trait UOPDecodeField[T <: DecodePattern] extends DecodeField[T, UInt] { } /** DecodePattern for an RISC-V instruction */ -trait RocketDecodePattern extends DecodePattern { - def instruction: Instruction - - def isRoCC = false +case class RocketDecodePattern(instruction: Instruction) extends DecodePattern { + def isRoCC: Boolean = instruction.instructionSet.name == "rv_rocc" override def bitPat: BitPat = BitPat(instruction.encoding.toString) } -/** factory to generate the rocket core decoder. */ -abstract class InstructionDecoder { - val instructions: Seq[Instruction] - - /** if this is true, use div block for mul. */ - val pipelinedMul: Boolean +// FIXME: Encoding +object CustomInstructions { + private def rocket(name: String, encoding: Encoding) = + Instruction(name, encoding, Seq(), Seq(InstructionSet("rv_rocket")), None, false, true) + + val rocketSet = Seq( + rocket("c.flush.d.l1", Encoding.fromString("111111000000?????000000001110011")), + rocket("c.discard.d.l1", Encoding.fromString("111111000010?????000000001110011")), + rocket("cease", Encoding.fromString("00110000010100000000000001110011")) + ).map(RocketDecodePattern.apply) + + private def rocc(name: String, encoding: Encoding) = + Instruction(name, encoding, Seq(), Seq(InstructionSet("rv_rocc")), None, false, true) + val roccSet = Seq( + rocc("custom0", Encoding.fromString("?????????????????000?????0001011")), + rocc("custom0.rs1", Encoding.fromString("?????????????????010?????0001011")), + rocc("custom0.rs1.rs2", Encoding.fromString("?????????????????011?????0001011")), + rocc("custom0.rd", Encoding.fromString("?????????????????100?????0001011")), + rocc("custom0.rd.rs1", Encoding.fromString("?????????????????110?????0001011")), + rocc("custom0.rd.rs1.rs2", Encoding.fromString("?????????????????111?????0001011")), + rocc("custom1", Encoding.fromString("?????????????????000?????0101011")), + rocc("custom1.rs1", Encoding.fromString("?????????????????010?????0101011")), + rocc("custom1.rs1.rs2", Encoding.fromString("?????????????????011?????0101011")), + rocc("custom1.rd", Encoding.fromString("?????????????????100?????0101011")), + rocc("custom1.rd.rs1", Encoding.fromString("?????????????????110?????0101011")), + rocc("custom1.rd.rs1.rs2", Encoding.fromString("?????????????????111?????0101011")), + rocc("custom2", Encoding.fromString("?????????????????000?????1011011")), + rocc("custom2.rs1", Encoding.fromString("?????????????????010?????1011011")), + rocc("custom2.rs1.rs2", Encoding.fromString("?????????????????011?????1011011")), + rocc("custom2.rd", Encoding.fromString("?????????????????100?????1011011")), + rocc("custom2.rd.rs1", Encoding.fromString("?????????????????110?????1011011")), + rocc("custom2.rd.rs1.rs2", Encoding.fromString("?????????????????111?????1011011")), + rocc("custom3", Encoding.fromString("?????????????????000?????1111011")), + rocc("custom3.rs1", Encoding.fromString("?????????????????010?????1111011")), + rocc("custom3.rs1.rs2", Encoding.fromString("?????????????????011?????1111011")), + rocc("custom3.rd", Encoding.fromString("?????????????????100?????1111011")), + rocc("custom3.rd.rs1", Encoding.fromString("?????????????????110?????1111011")), + rocc("custom3.rd.rs1.rs2", Encoding.fromString("?????????????????111?????1111011")) + ).map(RocketDecodePattern.apply) +} - /** if this is true, use ablu for ALU which supports zb zk */ - val useABLU: Boolean - val instructionDecodePatterns: Seq[RocketDecodePattern] = instructions.map(instr => - new RocketDecodePattern { - override def instruction: Instruction = instr - } - ) - val instructionDecodeFields: Seq[DecodeField[RocketDecodePattern, _ <: Data]] = Seq( +/** Parameter for InstructionDecoder + * @param instructions Instructions supported by + * @param pipelinedMul + * @param fenceIFlushDCache + */ +case class InstructionDecoderParameter( + instructions: Seq[Instruction], + pipelinedMul: Boolean, + fenceIFlushDCache: Boolean + ) +/** factory to generate the rocket core decoder. */ +class InstructionDecoder(p: InstructionDecoderParameter) { + private val instructions = p.instructions + + // functions below is my little reminder, which is used for future rocket core refactoring, just keep it, I'll remove it later in the future. + private def hasAnySetIn(sets: String*): Boolean = sets.exists(set => instructions.flatMap(_.instructionSets.map(_.name)).exists(_.contains(set))) + private def xLen32: Boolean = instructions.flatMap(_.instructionSets.map(_.name)).exists(_.startsWith("rv32_")) + private def xLen64: Boolean = instructions.flatMap(_.instructionSets.map(_.name)).exists(_.startsWith("rv64_")) + require(Seq(xLen32, xLen64).count(a => a) == 1, "rocket cannot support both rv32 and rv64 in the same time") + private def fLen0: Boolean = !fLen32 && !fLen64 + private def fLen32: Boolean = hasAnySetIn("rv_f", "rv32_f", "rv64_f") + private def fLen64: Boolean = hasAnySetIn("rv_d", "rv32_d", "rv64_d") + private def zfh: Boolean = hasAnySetIn("rv_zfh", "rv64_zfh", "rv_d_zfh") + private def usingAtomics: Boolean = hasAnySetIn("rv_a", "rv64_a") + private def usingBitManip: Boolean = hasAnySetIn("rv_zba", "rv64_zba", "rv_zbb", "rv32_zbb", "rv64_zbb", "rv_zbc", "rv_zbs") + private def usingBitManipCrypto: Boolean = hasAnySetIn("rv_zbkb", "rv32_zbkb", "rv64_zbkb", "rv_zbkc", "rv_zbkx") + private def usingCryptoNIST: Boolean = hasAnySetIn("rv32_zknd", "rv64_zknd", "rv32_zkne", "rv64_zkne", "rv_zknh", "rv32_zknh", "rv64_zknh", "rv_zkn", "rv32_zkn", "rv64_zkn") + private def usingCryptoSM: Boolean = hasAnySetIn("rv_zksed", "rv_zksh", "rv_zks", "rv32_zks", "rv64_zks", "rv_zk") + private def usingConditionalZero = hasAnySetIn("rv_zicond") + + /** use ablu for ALU which supports zb zk */ + private val useABLU: Boolean = usingBitManip || usingBitManipCrypto || usingCryptoNIST || usingCryptoSM + + private val instructionDecodePatterns: Seq[RocketDecodePattern] = instructions.map(RocketDecodePattern.apply) + private val instructionDecodeFields: Seq[DecodeField[RocketDecodePattern, _ <: Data]] = Seq( isLegal, - useFPU, + isFPU, isRoCC, isBranch, isJal, isJalr, - readRs2, - readRs1, - zbk, - zkn, - zks, + rxs2, + rxs1, selAlu2, selAlu1, selImm, @@ -82,9 +138,12 @@ abstract class InstructionDecoder { fenceI, fence, amo, - dp + dp, + // TODO: refactor ABLU encoding in the future. + zbk, + zkn, + zks, ) ++ (if (useABLU) Some(abluFn) else Some(aluFn)) - val sets: Seq[InstructionSet] = instructions.map(_.instructionSets.head) val table: DecodeTable[RocketDecodePattern] = new DecodeTable[RocketDecodePattern]( instructionDecodePatterns, @@ -92,9 +151,7 @@ abstract class InstructionDecoder { ) { // FIXME: in Chisel override val table: TruthTable = TruthTable( - instructionDecodePatterns.map { op => - op.bitPat -> instructionDecodeFields.reverse.map(_.genTable(op)).reduce(_ ## _) - }, + instructionDecodePatterns.map(op =>op.bitPat -> instructionDecodeFields.reverse.map(_.genTable(op)).reduce(_ ## _)), instructionDecodeFields.reverse.map(_.dc).reduce(_ ## _) ) } @@ -108,7 +165,7 @@ abstract class InstructionDecoder { override def genTable(op: RocketDecodePattern): BitPat = y } - object useFPU extends BoolDecodeField[RocketDecodePattern] { + object isFPU extends BoolDecodeField[RocketDecodePattern] { override def name: String = "fp" override def dc: BitPat = n @@ -149,13 +206,13 @@ abstract class InstructionDecoder { } } - object readRs2 extends BoolDecodeField[RocketDecodePattern] { + object rxs2 extends BoolDecodeField[RocketDecodePattern] { override def name: String = "rxs2" override def genTable(op: RocketDecodePattern): BitPat = if (Utils.readRs2(op.instruction)) y else n } - object readRs1 extends BoolDecodeField[RocketDecodePattern] { + object rxs1 extends BoolDecodeField[RocketDecodePattern] { override def name: String = "rxs1" override def genTable(op: RocketDecodePattern): BitPat = if (Utils.readRs1(op.instruction)) y else n @@ -208,6 +265,7 @@ abstract class InstructionDecoder { object zkn extends BoolDecodeField[RocketDecodePattern] { override def name: String = "zkn" + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.instructionSet.name match { // format: off case s if Seq("rv32_zknd", "rv64_zknd", "rv32_zkne", "rv64_zkne", "rv_zknh", "rv32_zknh", "rv64_zknh", "rv_zksed").contains(s) => y @@ -242,6 +300,7 @@ abstract class InstructionDecoder { object aluDoubleWords extends BoolDecodeField[RocketDecodePattern] { override def name: String = "alu_dw" + override def genTable(op: RocketDecodePattern): BitPat = { op.instruction.name match { // format: off @@ -260,6 +319,7 @@ abstract class InstructionDecoder { op.instruction.name match { // format: off case i if Seq("lb", "lh", "lw", "lbu", "lhu", "sb", "sh", "sw", "hlv_b", "hlv_bu", "hlv_h", "hlv_hu", "hlv_w", "hsv_b", "hsv_h", "hsv_w", "ld", "lwu", "sd", "hlv_d", "hsv_d", "hlv_wu", "amoadd_w", "amoxor_w", "amoswap_w", "amoand_w", "amoor_w", "amomin_w", "amominu_w", "amomax_w", "amomaxu_w", "lr_w", "sc_w", "amoadd_d", "amoswap_d", "amoxor_d", "amoand_d", "amoor_d", "amomin_d", "amominu_d", "amomax_d", "amomaxu_d", "lr_d", "sc_d", "flh", "fsh", "flw", "fsw", "fld", "fsd").contains(i) => y + case i if Seq("fence.i").contains(i) && p.fenceIFlushDCache => y case _ => dc // format: on } @@ -318,7 +378,7 @@ abstract class InstructionDecoder { object mul extends BoolDecodeField[RocketDecodePattern] { override def name: String = "mul" - override def genTable(op: RocketDecodePattern): BitPat = if (!pipelinedMul) n + override def genTable(op: RocketDecodePattern): BitPat = if (!p.pipelinedMul) n else { op.instruction.name match { // format: off @@ -334,15 +394,16 @@ abstract class InstructionDecoder { override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { // format: off - case i if Seq("mul", "mulh", "mulhu", "mulhsu", "mulw").contains(i) && !pipelinedMul => y + case i if Seq("mul", "mulh", "mulhu", "mulhsu", "mulw").contains(i) && !p.pipelinedMul => y case i if Seq("div", "divu", "rem", "remu", "divw", "divuw", "remw", "remuw").contains(i) => y - case _ => n + case _ => n // format: on } } object wxd extends BoolDecodeField[RocketDecodePattern] { override def name: String = "wxd" + override def genTable(op: RocketDecodePattern): BitPat = if (Utils.writeRd(op.instruction)) y else n } @@ -416,10 +477,11 @@ abstract class InstructionDecoder { case i if Seq("amoor.d", "amoor.w").contains(i) => UOPMEM.xaOr case i if Seq("amoswap.d", "amoswap.w").contains(i) => UOPMEM.xaSwap case i if Seq("amoxor.d", "amoxor.w").contains(i) => UOPMEM.xaXor + case i if Seq("fence.i").contains(i) && p.fenceIFlushDCache => UOPMEM.flushAll case i if Seq("lr.d", "lr.w").contains(i) => UOPMEM.xlr case i if Seq("fld", "flh", "flw", "hlv.b", "hlv.bu", "hlv.d", "hlv.h", "hlv.hu", "hlv.w", "hlv.wu", "lb", "lbu", "ld", "lh", "lhu", "lw", "lwu").contains(i) => UOPMEM.xrd case i if Seq("sc.d", "sc.w").contains(i) => UOPMEM.xsc - case i if Seq("fsd", "fsh", "fsw", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "sb", "sd", "sh", "sw").contains(i)=> UOPMEM.xwr + case i if Seq("fsd", "fsh", "fsw", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "sb", "sd", "sh", "sw").contains(i) => UOPMEM.xwr case _ => UOPMEM.dontCare // format: on } @@ -450,7 +512,7 @@ abstract class InstructionDecoder { override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { // format: off case i if Seq("csrrc", "csrrci").contains(i) => UOPCSR.c - case i if Seq("cdiscard.d.l1", "cease", "cflush.d.l1", "dret", "ebreak", "ecall", "hfence.gvma", "hfence.vvma", "hlv.b", "hlv.bu", "hlv.d", "hlv.h", "hlv.hu", "hlv.w", "hlv.wu", "hlvx.hu", "hlvx.wu", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "mnret", "mret", "sfence.vma", "sret", "wfi").contains(i) => UOPCSR.i + case i if Seq("cdiscard.d.l1", "cease", "cflush.d.l1", "dret", "ebreak", "ecall", "hfence.gvma", "hfence.vvma", "hlv.b", "hlv.bu", "hlv.d", "hlv.h", "hlv.hu", "hlv.w", "hlv.wu", "hlvx.hu", "hlvx.wu", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "mnret", "mret", "sfence.vma", "sret", "wfi", "cease").contains(i) => UOPCSR.i case i if Seq("csrrs", "csrrsi").contains(i) => UOPCSR.s case i if Seq("csrrw", "csrrwi").contains(i) => UOPCSR.w case _ => UOPCSR.dontCare @@ -496,17 +558,25 @@ abstract class InstructionDecoder { def sgeu: BitPat = encode(15) def div: BitPat = xor + def divu: BitPat = sr + def rem: BitPat = or + def remu: BitPat = and + def mul: BitPat = add + def mulh: BitPat = sl + def mulhsu: BitPat = seq + def mulhu: BitPat = sne } object aluFn extends UOPDecodeField[RocketDecodePattern] { override def name: String = "alu_fn" + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { // format: off case i if Seq("add", "addi", "addiw", "addw", "amoadd.d", "amoadd.w", "amoand.d", "amoand.w", "amomax.d", "amomax.w", "amomaxu.d", "amomaxu.w", "amomin.d", "amomin.w", "amominu.d", "amominu.w", "amoor.d", "amoor.w", "amoswap.d", "amoswap.w", "amoxor.d", "amoxor.w", "auipc", "cdiscard.d.l1", "cflush.d.l1", "csrrc", "csrrci", "csrrs", "csrrsi", "csrrw", "csrrwi", "fld", "flh", "flw", "fsd", "fsh", "fsw", "hfence.gvma", "hfence.vvma", "hlv.b", "hlv.bu", "hlv.d", "hlv.h", "hlv.hu", "hlv.w", "hlv.wu", "hlvx.hu", "hlvx.wu", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "jal", "jalr", "lb", "lbu", "ld", "lh", "lhu", "lr.d", "lr.w", "lui", "lw", "lwu", "sb", "sc.d", "sc.w", "sd", "sfence.vma", "sh", "sw", "and", "andi").contains(i) => UOPALU.add @@ -523,7 +593,7 @@ abstract class InstructionDecoder { case i if Seq("bge").contains(i) => UOPALU.sge case i if Seq("bgeu").contains(i) => UOPALU.sgeu case i if Seq("sll", "slli", "slli", "slliw", "sllw").contains(i) => UOPALU.sl - case i if Seq("blt" ,"slt" ,"slti").contains(i) => UOPALU.slt + case i if Seq("blt", "slt", "slti").contains(i) => UOPALU.slt case i if Seq("bltu", "sltiu", "sltu").contains(i) => UOPALU.sltu case i if Seq("bne").contains(i) => UOPALU.sne case i if Seq("srl", "srli", "srli", "srliw", "srlw").contains(i) => UOPALU.sr @@ -533,6 +603,7 @@ abstract class InstructionDecoder { case _ => UOPALU.dontCare // format: on } + override def uopType: UOPALU.type = UOPALU } @@ -848,7 +919,7 @@ abstract class InstructionDecoder { case i if Seq("auipc", "jal").contains(i) => UOPA1.pc case i if Seq("add", "add.uw", "addi", "addiw", "addw", "aes32dsi", "aes32dsmi", "aes32esi", "aes32esmi", "aes64ds", "aes64dsm", "aes64es", "aes64esm", "aes64im", "aes64ks1i", "aes64ks2", "amoadd.d", "amoadd.w", "amoand.d", "amoand.w", "amomax.d", "amomax.w", "amomaxu.d", "amomaxu.w", "amomin.d", "amomin.w", "amominu.d", "amominu.w", "amoor.d", "amoor.w", "amoswap.d", "amoswap.w", "amoxor.d", "amoxor.w", "and", "andi", "andn", "bclr", "bclri", "bclri", "beq", "bext", "bexti", "bexti", "bge", "bgeu", "binv", "binvi", "binvi", "blt", "bltu", "bne", "brev8", "bset", "bseti", "bseti", "cdiscard.d.l1", "cflush.d.l1", "clmul", "clmulh", "clmulr", "clz", "clzw", "cpop", "cpopw", "csrrc", "csrrs", "csrrw", "ctz", "ctzw", "czero.eqz", "czero.nez", "div", "divu", "divuw", "divw", "fcvt.d.l", "fcvt.d.lu", "fcvt.d.w", "fcvt.d.wu", "fcvt.h.l", "fcvt.h.lu", "fcvt.h.w", "fcvt.h.wu", "fcvt.s.l", "fcvt.s.lu", "fcvt.s.w", "fcvt.s.wu", "fld", "flh", "flw", "fmv.d.x", "fmv.h.x", "fmv.w.x", "fsd", "fsh", "fsw", "hfence.gvma", "hfence.vvma", "hlv.b", "hlv.bu", "hlv.d", "hlv.h", "hlv.hu", "hlv.w", "hlv.wu", "hlvx.hu", "hlvx.wu", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "jalr", "lb", "lbu", "ld", "lh", "lhu", "lr.d", "lr.w", "lw", "lwu", "max", "maxu", "min", "minu", "mul", "mulh", "mulhsu", "mulhu", "mulw", "or", "orc.b", "ori", "orn", "pack", "packh", "packw", "rem", "remu", "remuw", "remw", "rev8", "rev8", "rol", "rolw", "ror", "rori", "rori", "roriw", "rorw", "sb", "sc.d", "sc.w", "sd", "sext.b", "sext.h", "sfence.vma", "sh", "sh1add", "sh1add.uw", "sh2add", "sh2add.uw", "sh3add", "sh3add.uw", "sha256sig0", "sha256sig1", "sha256sum0", "sha256sum1", "sha512sig0", "sha512sig0h", "sha512sig0l", "sha512sig1", "sha512sig1h", "sha512sig1l", "sha512sum0", "sha512sum0r", "sha512sum1", "sha512sum1r", "sll", "slli", "slli", "slli.uw", "slliw", "sllw", "slt", "slti", "sltiu", "sltu", "sm3p0", "sm3p1", "sm4ed", "sm4ks", "sra", "srai", "srai", "sraiw", "sraw", "srl", "srli", "srli", "srliw", "srlw", "sub", "subw", "sw", "unzip", "xnor", "xor", "xori", "xperm4", "xperm8", "zext.h", "zext.h", "zip").contains(i) => UOPA1.rs1 case i if Seq("csrrci", "csrrsi", "csrrwi", "lui").contains(i) => UOPA1.zero - case i => UOPA1.dontCare + case _ => UOPA1.dontCare } override def uopType: UOPA1.type = UOPA1 @@ -856,9 +927,13 @@ abstract class InstructionDecoder { object UOPA2 extends UOP { def width = 2 + def zero: BitPat = encode(0) + def size: BitPat = encode(1) + def rs2: BitPat = encode(2) + def imm: BitPat = encode(3) } @@ -878,6 +953,7 @@ abstract class InstructionDecoder { } // Custom extensions + /** Rocket Custom Coprocessor, add FU at commit stage */ object isRoCC extends BoolDecodeField[RocketDecodePattern] { override def name: String = "rocc" diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 34f16d273c3..bf2df8efa12 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ +import chisel3.util.experimental.decode.DecodeBundle import chisel3.withClock import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tile._ @@ -54,7 +55,8 @@ case class RocketCoreParams( fpu: Option[FPUParams] = Some(FPUParams()), debugROB: Boolean = false, // if enabled, uses a C++ debug ROB to generate trace-with-wdata haveCease: Boolean = true, // non-standard CEASE instruction - haveSimTimeout: Boolean = true // add plusarg for simulation timeout + haveSimTimeout: Boolean = true, // add plusarg for simulation timeout + riscvOpcodesPath: os.Path = os.pwd / "dependencies" / "riscv-opcodes" ) extends CoreParams { val lgPauseCycles = 5 val haveFSDirty = false @@ -132,7 +134,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) if (!rocketParams.clockGate) clock else ClockGate(clock, clock_en, "rocket_clock_gate") - class RocketImpl { // entering gated-clock domain + class RocketImpl { impl => // entering gated-clock domain // performance counters def pipelineIDToWB[T <: Data](x: T): T = @@ -140,39 +142,39 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val perfEvents = new EventSets(Seq( new EventSet((mask, hits) => Mux(wb_xcpt, mask(0), wb_valid && pipelineIDToWB((mask & hits).orR)), Seq( ("exception", () => false.B), - ("load", () => id_ctrl.mem && id_ctrl.mem_cmd === M_XRD && !id_ctrl.fp), - ("store", () => id_ctrl.mem && id_ctrl.mem_cmd === M_XWR && !id_ctrl.fp), - ("amo", () => usingAtomics.B && id_ctrl.mem && (isAMO(id_ctrl.mem_cmd) || id_ctrl.mem_cmd.isOneOf(M_XLR, M_XSC))), - ("system", () => id_ctrl.csr =/= CSR.N), - ("arith", () => id_ctrl.wxd && !(id_ctrl.jal || id_ctrl.jalr || id_ctrl.mem || id_ctrl.fp || id_ctrl.mul || id_ctrl.div || id_ctrl.csr =/= CSR.N)), - ("branch", () => id_ctrl.branch), - ("jal", () => id_ctrl.jal), - ("jalr", () => id_ctrl.jalr)) + ("load", () => id_ctrl(decoder.mem) && id_ctrl(decoder.memCommand) === M_XRD && !id_ctrl(decoder.isFPU)), + ("store", () => id_ctrl(decoder.mem) && id_ctrl(decoder.memCommand) === M_XWR && !id_ctrl(decoder.isFPU)), + ("amo", () => usingAtomics.B && id_ctrl(decoder.mem) && (isAMO(id_ctrl(decoder.memCommand)) || id_ctrl(decoder.memCommand).isOneOf(M_XLR, M_XSC))), + ("system", () => id_ctrl(decoder.csr) =/= CSR.N), + ("arith", () => id_ctrl(decoder.wxd) && !(id_ctrl(decoder.isJal) || id_ctrl(decoder.isJalr) || id_ctrl(decoder.mem) || id_ctrl(decoder.isFPU) || id_ctrl(decoder.mul) || id_ctrl(decoder.div) || id_ctrl(decoder.csr) =/= CSR.N)), + ("branch", () => id_ctrl(decoder.isBranch)), + ("jal", () => id_ctrl(decoder.isJal)), + ("jalr", () => id_ctrl(decoder.isJalr))) ++ (if (!usingMulDiv) Seq() else Seq( - ("mul", () => if (pipelinedMul) id_ctrl.mul else id_ctrl.div && (id_ctrl.alu_fn & aluFn.FN_DIV) =/= aluFn.FN_DIV), - ("div", () => if (pipelinedMul) id_ctrl.div else id_ctrl.div && (id_ctrl.alu_fn & aluFn.FN_DIV) === aluFn.FN_DIV))) + ("mul", () => if (pipelinedMul) id_ctrl(decoder.mul) else id_ctrl(decoder.div) && (id_ctrl(decoder.aluFn) & aluFn.FN_DIV) =/= aluFn.FN_DIV), + ("div", () => if (pipelinedMul) id_ctrl(decoder.div) else id_ctrl(decoder.div) && (id_ctrl(decoder.aluFn) & aluFn.FN_DIV) === aluFn.FN_DIV))) ++ (if (!usingFPU) Seq() else Seq( - ("fp load", () => id_ctrl.fp && io.fpu.dec.ldst && io.fpu.dec.wen), - ("fp store", () => id_ctrl.fp && io.fpu.dec.ldst && !io.fpu.dec.wen), - ("fp add", () => id_ctrl.fp && io.fpu.dec.fma && io.fpu.dec.swap23), - ("fp mul", () => id_ctrl.fp && io.fpu.dec.fma && !io.fpu.dec.swap23 && !io.fpu.dec.ren3), - ("fp mul-add", () => id_ctrl.fp && io.fpu.dec.fma && io.fpu.dec.ren3), - ("fp div/sqrt", () => id_ctrl.fp && (io.fpu.dec.div || io.fpu.dec.sqrt)), - ("fp other", () => id_ctrl.fp && !(io.fpu.dec.ldst || io.fpu.dec.fma || io.fpu.dec.div || io.fpu.dec.sqrt))))), + ("fp load", () => id_ctrl(decoder.isFPU) && io.fpu.dec.ldst && io.fpu.dec.wen), + ("fp store", () => id_ctrl(decoder.isFPU) && io.fpu.dec.ldst && !io.fpu.dec.wen), + ("fp add", () => id_ctrl(decoder.isFPU) && io.fpu.dec.fma && io.fpu.dec.swap23), + ("fp mul", () => id_ctrl(decoder.isFPU) && io.fpu.dec.fma && !io.fpu.dec.swap23 && !io.fpu.dec.ren3), + ("fp mul-add", () => id_ctrl(decoder.isFPU) && io.fpu.dec.fma && io.fpu.dec.ren3), + ("fp div/sqrt", () => id_ctrl(decoder.isFPU) && (io.fpu.dec.div || io.fpu.dec.sqrt)), + ("fp other", () => id_ctrl(decoder.isFPU) && !(io.fpu.dec.ldst || io.fpu.dec.fma || io.fpu.dec.div || io.fpu.dec.sqrt))))), new EventSet((mask, hits) => (mask & hits).orR, Seq( - ("load-use interlock", () => id_ex_hazard && ex_ctrl.mem || id_mem_hazard && mem_ctrl.mem || id_wb_hazard && wb_ctrl.mem), + ("load-use interlock", () => id_ex_hazard && ex_ctrl(decoder.mem) || id_mem_hazard && mem_ctrl(decoder.mem) || id_wb_hazard && wb_ctrl(decoder.mem)), ("long-latency interlock", () => id_sboard_hazard), - ("csr interlock", () => id_ex_hazard && ex_ctrl.csr =/= CSR.N || id_mem_hazard && mem_ctrl.csr =/= CSR.N || id_wb_hazard && wb_ctrl.csr =/= CSR.N), + ("csr interlock", () => id_ex_hazard && ex_ctrl(decoder.csr) =/= CSR.N || id_mem_hazard && mem_ctrl(decoder.csr) =/= CSR.N || id_wb_hazard && wb_ctrl(decoder.csr) =/= CSR.N), ("I$ blocked", () => icache_blocked), - ("D$ blocked", () => id_ctrl.mem && dcache_blocked), + ("D$ blocked", () => id_ctrl(decoder.mem) && dcache_blocked), ("branch misprediction", () => take_pc_mem && mem_direction_misprediction), ("control-flow target misprediction", () => take_pc_mem && mem_misprediction && mem_cfi && !mem_direction_misprediction && !icache_blocked), ("flush", () => wb_reg_flush_pipe), ("replay", () => replay_wb)) ++ (if (!usingMulDiv) Seq() else Seq( - ("mul/div interlock", () => id_ex_hazard && (ex_ctrl.mul || ex_ctrl.div) || id_mem_hazard && (mem_ctrl.mul || mem_ctrl.div) || id_wb_hazard && wb_ctrl.div))) + ("mul/div interlock", () => id_ex_hazard && (ex_ctrl(decoder.mul) || ex_ctrl(decoder.div)) || id_mem_hazard && (mem_ctrl(decoder.mul) || mem_ctrl(decoder.div)) || id_wb_hazard && wb_ctrl(decoder.div)))) ++ (if (!usingFPU) Seq() else Seq( - ("fp interlock", () => id_ex_hazard && ex_ctrl.fp || id_mem_hazard && mem_ctrl.fp || id_wb_hazard && wb_ctrl.fp || id_ctrl.fp && id_stall_fpu)))), + ("fp interlock", () => id_ex_hazard && ex_ctrl(decoder.isFPU) || id_mem_hazard && mem_ctrl(decoder.isFPU) || id_wb_hazard && wb_ctrl(decoder.isFPU) || id_ctrl(decoder.isFPU) && id_stall_fpu)))), new EventSet((mask, hits) => (mask & hits).orR, Seq( ("I$ miss", () => io.imem.perf.acquire), ("D$ miss", () => io.dmem.perf.acquire), @@ -182,38 +184,110 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) ("L2 TLB miss", () => io.ptw.perf.l2miss))))) val pipelinedMul = usingMulDiv && mulDivParams.mulUnroll == xLen - val decode_table = { - (if (usingMulDiv) new MDecode(pipelinedMul, aluFn) +: (xLen > 32).option(new M64Decode(pipelinedMul, aluFn)).toSeq else Nil) ++: - (if (usingAtomics) new ADecode(aluFn) +: (xLen > 32).option(new A64Decode(aluFn)).toSeq else Nil) ++: - (if (fLen >= 32) new FDecode(aluFn) +: (xLen > 32).option(new F64Decode(aluFn)).toSeq else Nil) ++: - (if (fLen >= 64) new DDecode(aluFn) +: (xLen > 32).option(new D64Decode(aluFn)).toSeq else Nil) ++: - (if (minFLen == 16) new HDecode(aluFn) +: (xLen > 32).option(new H64Decode(aluFn)).toSeq ++: (fLen >= 64).option(new HDDecode(aluFn)).toSeq else Nil) ++: - (usingRoCC.option(new RoCCDecode(aluFn))) ++: - (if (usingBitManip) new ZBADecode +: (xLen == 64).option(new ZBA64Decode).toSeq ++: new ZBBMDecode +: new ZBBORCBDecode +: new ZBCRDecode +: new ZBSDecode +: (xLen == 32).option(new ZBS32Decode).toSeq ++: (xLen == 64).option(new ZBS64Decode).toSeq ++: new ZBBSEDecode +: new ZBBCDecode +: (xLen == 64).option(new ZBBC64Decode).toSeq else Nil) ++: - (if (usingBitManip && !usingBitManipCrypto) (xLen == 32).option(new ZBBZE32Decode).toSeq ++: (xLen == 64).option(new ZBBZE64Decode).toSeq else Nil) ++: - (if (usingBitManip || usingBitManipCrypto) new ZBBNDecode +: new ZBCDecode +: new ZBBRDecode +: (xLen == 32).option(new ZBBR32Decode).toSeq ++: (xLen == 64).option(new ZBBR64Decode).toSeq ++: (xLen == 32).option(new ZBBREV832Decode).toSeq ++: (xLen == 64).option(new ZBBREV864Decode).toSeq else Nil) ++: - (if (usingBitManipCrypto) new ZBKXDecode +: new ZBKBDecode +: (xLen == 32).option(new ZBKB32Decode).toSeq ++: (xLen == 64).option(new ZBKB64Decode).toSeq else Nil) ++: - (if (usingCryptoNIST) (xLen == 32).option(new ZKND32Decode).toSeq ++: (xLen == 64).option(new ZKND64Decode).toSeq else Nil) ++: - (if (usingCryptoNIST) (xLen == 32).option(new ZKNE32Decode).toSeq ++: (xLen == 64).option(new ZKNE64Decode).toSeq else Nil) ++: - (if (usingCryptoNIST) new ZKNHDecode +: (xLen == 32).option(new ZKNH32Decode).toSeq ++: (xLen == 64).option(new ZKNH64Decode).toSeq else Nil) ++: - (usingCryptoSM.option(new ZKSDecode)) ++: - (if (xLen == 32) new I32Decode(aluFn) else new I64Decode(aluFn)) +: - (usingVM.option(new SVMDecode(aluFn))) ++: - (usingSupervisor.option(new SDecode(aluFn))) ++: - (usingHypervisor.option(new HypervisorDecode(aluFn))) ++: - ((usingHypervisor && (xLen == 64)).option(new Hypervisor64Decode(aluFn))) ++: - (usingDebug.option(new DebugDecode(aluFn))) ++: - (usingNMI.option(new NMIDecode(aluFn))) ++: - (usingConditionalZero.option(new ConditionalZeroDecode(aluFn))) ++: - Seq(new FenceIDecode(tile.dcache.flushOnFenceI, aluFn)) ++: - coreParams.haveCFlush.option(new CFlushDecode(tile.dcache.canSupportCFlushLine, aluFn)) ++: - rocketParams.haveCease.option(new CeaseDecode(aluFn)) ++: - Seq(new IDecode(aluFn)) - } flatMap(_.table) - - val ex_ctrl = Reg(new IntCtrlSigs(aluFn)) - val mem_ctrl = Reg(new IntCtrlSigs(aluFn)) - val wb_ctrl = Reg(new IntCtrlSigs(aluFn)) + + val decoderParameter = org.chipsalliance.rocketcore.decoder.InstructionDecoderParameter( + org.chipsalliance.rvdecoderdb.fromFile(rocketParams.riscvOpcodesPath) + .filter { i => + i.instructionSets.map(_.name) match { + // I + case s if s.contains("rv_i") => true + case s if s.contains("rv32_i") => xLen == 32 + case s if s.contains("rv64_i") => xLen == 64 + // M + case s if s.contains("rv_m") => usingMulDiv + case s if s.contains("rv64_m") => (xLen == 64) && usingMulDiv + // A + case s if s.contains("rv_a") => usingAtomics + case s if s.contains("rv64_a") => (xLen == 64) && usingAtomics + // ZICSR + case s if s.contains("rv_zicsr") => true + // ZIFENCEI + case s if s.contains("rv_zifencei") => true + // F + case s if s.contains("rv_f") => !(fLen == 0) + case s if s.contains("rv64_f") => (xLen == 64) && !(fLen == 0) + // D + case s if s.contains("rv_d") => (fLen == 64) + case s if s.contains("rv64_d") => (xLen == 64) && (fLen == 64) + // ZFH + case s if s.contains("rv_zfh") => minFLen == 16 + case s if s.contains("rv64_zfh") => (xLen == 64) && (minFLen == 16) + case s if s.contains("rv_d_zfh") => (fLen == 64) && (minFLen == 16) + // Priv: + case s if s.contains("rv_system") => i.name match { + case "wfi" => true + case "mret" => true + case "dret" => usingDebug + } + // Supervisor + case s if s.contains("rv_s") => i.name match { + // if support superviosr but don't support virtual memory, raise illinstr. + case s if s.contains("sfence.vma") => usingVM + case s if s.contains("sret") => usingSupervisor + } + case s if s.contains("rv_smrnmi") => usingNMI + // Hypervisor + case s if s.contains("rv_h") => usingHypervisor + case s if s.contains("rv64_h") => (xLen == 64) && usingHypervisor + + // TODO: + // Bit Manipulation, RocketChip doesn't provide a fine-grand Bit-Manipulation and Crypto support for now. + // We will support it in the future. + case s if s.contains("rv_zba") => usingBitManip + case s if s.contains("rv64_zba") => (xLen == 64) && usingBitManip + case s if s.contains("rv_zbb") => usingBitManip + case s if s.contains("rv32_zbb") => (xLen == 32) && usingBitManip + case s if s.contains("rv64_zbb") => (xLen == 64) && usingBitManip + case s if s.contains("rv_zbc") => usingBitManip + case s if s.contains("rv_zbs") => usingBitManip + // Cryptography Extensions + case s if s.contains("rv_zbkb") => usingBitManipCrypto + case s if s.contains("rv32_zbkb") => (xLen == 32) && usingBitManipCrypto + case s if s.contains("rv64_zbkb") => (xLen == 64) && usingBitManipCrypto + // These two are subset to zbkb + case s if s.contains("rv_zbkc") => usingBitManipCrypto + case s if s.contains("rv_zbkx") => usingBitManipCrypto + // NIST + case s if s.contains("rv32_zknd") => (xLen == 32) && usingCryptoNIST + case s if s.contains("rv64_zknd") => (xLen == 64) && usingCryptoNIST + case s if s.contains("rv32_zkne") => (xLen == 32) && usingCryptoNIST + case s if s.contains("rv64_zkne") => (xLen == 64) && usingCryptoNIST + case s if s.contains("rv_zknh") => usingCryptoNIST + case s if s.contains("rv32_zknh") => (xLen == 32) && usingCryptoNIST + case s if s.contains("rv64_zknh") => (xLen == 64) && usingCryptoNIST + case s if s.contains("rv_zkn") => usingCryptoNIST + case s if s.contains("rv32_zkn") => (xLen == 32) && usingCryptoNIST + case s if s.contains("rv64_zkn") => (xLen == 64) && usingCryptoNIST + // SM + case s if s.contains("rv_zksed") => usingCryptoSM + case s if s.contains("rv_zksh") => usingCryptoSM + case s if s.contains("rv_zks") => usingCryptoSM + case s if s.contains("rv32_zks") => (xLen == 32) && usingCryptoSM + case s if s.contains("rv64_zks") => (xLen == 64) && usingCryptoSM + case s if s.contains("rv_zk") => usingCryptoSM && usingCryptoNIST + // NIST && SM + case s if s.contains("rv32_zk") => (xLen == 32) && usingCryptoSM && usingCryptoNIST + case s if s.contains("rv64_zk") => (xLen == 64) && usingCryptoSM && usingCryptoNIST + + // unratified but supported. + case s if s.contains("rv_zicond") => usingConditionalZero + + // TODO: Rocket Custom Instructions + // coreParams.haveCFlush.option(new CFlushDecode(tile.dcache.canSupportCFlushLine, aluFn)) ++: + // rocketParams.haveCease.option(new CeaseDecode(aluFn)) ++: + // (usingRoCC.option(new RoCCDecode(aluFn))) ++: + case _ => false + } + } + .toSeq, + pipelinedMul, + tile.dcache.flushOnFenceI + ) + val decoder = new org.chipsalliance.rocketcore.decoder.InstructionDecoder(decoderParameter) + + val ex_ctrl: DecodeBundle = Reg(decoder.table.bundle) + val mem_ctrl: DecodeBundle = Reg(decoder.table.bundle) + val wb_ctrl: DecodeBundle = Reg(decoder.table.bundle) val ex_reg_xcpt_interrupt = Reg(Bool()) val ex_reg_valid = Reg(Bool()) @@ -286,7 +360,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) require(decodeWidth == 1 /* TODO */ && retireWidth == decodeWidth) require(!(coreParams.useRVE && coreParams.fpu.nonEmpty), "Can't select both RVE and floating-point") require(!(coreParams.useRVE && coreParams.useHypervisor), "Can't select both RVE and Hypervisor") - val id_ctrl = Wire(new IntCtrlSigs(aluFn)).decode(id_inst(0), decode_table) + val id_ctrl: DecodeBundle = Wire(decoder.table.decode(id_inst(0))) val lgNXRegs = if (coreParams.useRVE) 4 else 5 val regAddrMask = (1 << lgNXRegs) - 1 @@ -298,7 +372,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val id_load_use = Wire(Bool()) val id_reg_fence = RegInit(false.B) - val id_ren = IndexedSeq(id_ctrl.rxs1, id_ctrl.rxs2) + val id_ren = IndexedSeq(id_ctrl(decoder.rxs1), id_ctrl(decoder.rxs2)) val id_raddr = IndexedSeq(id_raddr1, id_raddr2) val rf = new RegFile(regAddrMask, xLen) val id_rs = id_raddr.map(rf.read _) @@ -306,27 +380,29 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val id_npc = (ibuf.io.pc.asSInt + ImmGen(IMM_UJ, id_inst(0))).asUInt val csr = Module(new CSRFile(perfEvents, coreParams.customCSRs.decls, tile.roccCSRs.flatten)) - val id_csr_en = id_ctrl.csr.isOneOf(CSR.S, CSR.C, CSR.W) - val id_system_insn = id_ctrl.csr === CSR.I - val id_csr_ren = id_ctrl.csr.isOneOf(CSR.S, CSR.C) && id_expanded_inst(0).rs1 === 0.U - val id_csr = Mux(id_system_insn && id_ctrl.mem, CSR.N, Mux(id_csr_ren, CSR.R, id_ctrl.csr)) + // TODO: additional decode out? + val id_csr_en = id_ctrl(decoder.csr).isOneOf(CSR.S, CSR.C, CSR.W) + + val id_system_insn = id_ctrl(decoder.csr) === CSR.I + val id_csr_ren = id_ctrl(decoder.csr).isOneOf(CSR.S, CSR.C) && id_expanded_inst(0).rs1 === 0.U + val id_csr = Mux(id_system_insn && id_ctrl(decoder.mem), CSR.N, Mux(id_csr_ren, CSR.R, id_ctrl(decoder.csr))) val id_csr_flush = id_system_insn || (id_csr_en && !id_csr_ren && csr.io.decode(0).write_flush) - val id_illegal_rnum = if (usingCryptoNIST) (id_ctrl.zkn && aluFn.isKs1(id_ctrl.alu_fn) && id_inst(0)(23,20) > 0xA.U(4.W)) else false.B - val id_illegal_insn = !id_ctrl.legal || - (id_ctrl.mul || id_ctrl.div) && !csr.io.status.isa('m'-'a') || - id_ctrl.amo && !csr.io.status.isa('a'-'a') || - id_ctrl.fp && (csr.io.decode(0).fp_illegal || io.fpu.illegal_rm) || - id_ctrl.dp && !csr.io.status.isa('d'-'a') || + val id_illegal_rnum = if (usingCryptoNIST) id_ctrl(decoder.zkn) && aluFn.isKs1(id_ctrl(decoder.abluFn)) && id_inst(0)(23,20) > 0xA.U(4.W) else false.B + val id_illegal_insn = !id_ctrl(decoder.isLegal) || + (id_ctrl(decoder.mul) || id_ctrl(decoder.div)) && !csr.io.status.isa('m'-'a') || + id_ctrl(decoder.amo) && !csr.io.status.isa('a'-'a') || + id_ctrl(decoder.isFPU) && (csr.io.decode(0).fp_illegal || io.fpu.illegal_rm) || + id_ctrl(decoder.dp) && !csr.io.status.isa('d'-'a') || ibuf.io.inst(0).bits.rvc && !csr.io.status.isa('c'-'a') || - id_raddr2_illegal && id_ctrl.rxs2 || - id_raddr1_illegal && id_ctrl.rxs1 || - id_waddr_illegal && id_ctrl.wxd || - id_ctrl.rocc && csr.io.decode(0).rocc_illegal || + id_raddr2_illegal && id_ctrl(decoder.rxs2) || + id_raddr1_illegal && id_ctrl(decoder.rxs1) || + id_waddr_illegal && id_ctrl(decoder.wxd) || + id_ctrl(decoder.isRoCC) && csr.io.decode(0).rocc_illegal || id_csr_en && (csr.io.decode(0).read_illegal || !id_csr_ren && csr.io.decode(0).write_illegal) || !ibuf.io.inst(0).bits.rvc && (id_system_insn && csr.io.decode(0).system_illegal) || id_illegal_rnum - val id_virtual_insn = id_ctrl.legal && + val id_virtual_insn = id_ctrl(decoder.isLegal) && ((id_csr_en && !(!id_csr_ren && csr.io.decode(0).write_illegal) && csr.io.decode(0).virtual_access_illegal) || (!ibuf.io.inst(0).bits.rvc && id_system_insn && csr.io.decode(0).virtual_system_illegal)) // stall decode for fences (now, for AMO.rl; later, for AMO.aq and FENCE) @@ -334,14 +410,14 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val id_amo_rl = id_inst(0)(25) val id_fence_pred = id_inst(0)(27,24) val id_fence_succ = id_inst(0)(23,20) - val id_fence_next = id_ctrl.fence || id_ctrl.amo && id_amo_aq + val id_fence_next = id_ctrl(decoder.fence) || id_ctrl(decoder.amo) && id_amo_aq val id_mem_busy = !io.dmem.ordered || io.dmem.req.valid when (!id_mem_busy) { id_reg_fence := false.B } val id_rocc_busy = usingRoCC.B && - (io.rocc.busy || ex_reg_valid && ex_ctrl.rocc || - mem_reg_valid && mem_ctrl.rocc || wb_reg_valid && wb_ctrl.rocc) - val id_do_fence = WireDefault(id_rocc_busy && id_ctrl.fence || - id_mem_busy && (id_ctrl.amo && id_amo_rl || id_ctrl.fence_i || id_reg_fence && (id_ctrl.mem || id_ctrl.rocc))) + (io.rocc.busy || ex_reg_valid && ex_ctrl(decoder.isRoCC) || + mem_reg_valid && mem_ctrl(decoder.isRoCC) || wb_reg_valid && wb_ctrl(decoder.isRoCC)) + val id_do_fence = WireDefault(id_rocc_busy && id_ctrl(decoder.fence) || + id_mem_busy && (id_ctrl(decoder.amo) && id_amo_rl || id_ctrl(decoder.fenceI) || id_reg_fence && (id_ctrl(decoder.mem) || id_ctrl(decoder.isRoCC)))) val bpu = Module(new BreakpointUnit(nBreakpoints)) bpu.io.status := csr.io.status @@ -387,9 +463,9 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val wb_waddr = wb_reg_inst(11,7) & regAddrMask.U val bypass_sources = IndexedSeq( (true.B, 0.U, 0.U), // treat reading x0 as a bypass - (ex_reg_valid && ex_ctrl.wxd, ex_waddr, mem_reg_wdata), - (mem_reg_valid && mem_ctrl.wxd && !mem_ctrl.mem, mem_waddr, wb_reg_wdata), - (mem_reg_valid && mem_ctrl.wxd, mem_waddr, dcache_bypass_data)) + (ex_reg_valid && ex_ctrl(decoder.wxd), ex_waddr, mem_reg_wdata), + (mem_reg_valid && mem_ctrl(decoder.wxd) && !mem_ctrl(decoder.mem), mem_waddr, wb_reg_wdata), + (mem_reg_valid && mem_ctrl(decoder.wxd), mem_waddr, dcache_bypass_data)) val id_bypass_src = id_raddr.map(raddr => bypass_sources.map(s => s._1 && s._2 === raddr)) // execute stage @@ -399,11 +475,11 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val ex_reg_rs_msb = Reg(Vec(id_raddr.size, UInt())) val ex_rs = for (i <- 0 until id_raddr.size) yield Mux(ex_reg_rs_bypass(i), bypass_mux(ex_reg_rs_lsb(i)), Cat(ex_reg_rs_msb(i), ex_reg_rs_lsb(i))) - val ex_imm = ImmGen(ex_ctrl.sel_imm, ex_reg_inst) - val ex_op1 = MuxLookup(ex_ctrl.sel_alu1, 0.S, Seq( + val ex_imm = ImmGen(ex_ctrl(decoder.selImm), ex_reg_inst) + val ex_op1 = MuxLookup(ex_ctrl(decoder.selAlu1), 0.S, Seq( A1_RS1 -> ex_rs(0).asSInt, A1_PC -> ex_reg_pc.asSInt)) - val ex_op2 = MuxLookup(ex_ctrl.sel_alu2, 0.S, Seq( + val ex_op2 = MuxLookup(ex_ctrl(decoder.selAlu2), 0.S, Seq( A2_RS2 -> ex_rs(1).asSInt, A2_IMM -> ex_imm, A2_SIZE -> Mux(ex_reg_rvc, 2.S, 4.S))) @@ -412,15 +488,15 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) case _: ABLUFN => new ABLU case _: ALUFN => new ALU }) - alu.io.dw := ex_ctrl.alu_dw - alu.io.fn := ex_ctrl.alu_fn + alu.io.dw := ex_ctrl(decoder.aluDoubleWords) + alu.io.fn := ex_ctrl(decoder.aluFn) alu.io.in2 := ex_op2.asUInt alu.io.in1 := ex_op1.asUInt val ex_zbk_wdata = if (!usingBitManipCrypto && !usingBitManip) 0.U else { val zbk = Module(new BitManipCrypto(xLen)) - zbk.io.fn := ex_ctrl.alu_fn - zbk.io.dw := ex_ctrl.alu_dw + zbk.io.fn := ex_ctrl(decoder.aluFn) + zbk.io.dw := ex_ctrl(decoder.aluDoubleWords) zbk.io.rs1 := ex_op1.asUInt zbk.io.rs2 := ex_op2.asUInt zbk.io.rd @@ -428,7 +504,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val ex_zkn_wdata = if (!usingCryptoNIST) 0.U else { val zkn = Module(new CryptoNIST(xLen)) - zkn.io.fn := ex_ctrl.alu_fn + zkn.io.fn := ex_ctrl(decoder.aluFn) zkn.io.hl := ex_reg_inst(27) zkn.io.bs := ex_reg_inst(31,30) zkn.io.rs1 := ex_op1.asUInt @@ -438,7 +514,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val ex_zks_wdata = if (!usingCryptoSM) 0.U else { val zks = Module(new CryptoSM(xLen)) - zks.io.fn := ex_ctrl.alu_fn + zks.io.fn := ex_ctrl(decoder.aluFn) zks.io.bs := ex_reg_inst(31,30) zks.io.rs1 := ex_op1.asUInt zks.io.rs2 := ex_op2.asUInt @@ -447,15 +523,15 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) // multiplier and divider val div = Module(new MulDiv(if (pipelinedMul) mulDivParams.copy(mulUnroll = 0) else mulDivParams, width = xLen, aluFn = aluFn)) - div.io.req.valid := ex_reg_valid && ex_ctrl.div - div.io.req.bits.dw := ex_ctrl.alu_dw - div.io.req.bits.fn := ex_ctrl.alu_fn + div.io.req.valid := ex_reg_valid && ex_ctrl(decoder.div) + div.io.req.bits.dw := ex_ctrl(decoder.aluDoubleWords) + div.io.req.bits.fn := ex_ctrl(decoder.aluFn) div.io.req.bits.in1 := ex_rs(0) div.io.req.bits.in2 := ex_rs(1) div.io.req.bits.tag := ex_waddr val mul = pipelinedMul.option { val m = Module(new PipelinedMultiplier(xLen, 2, aluFn = aluFn)) - m.io.req.valid := ex_reg_valid && ex_ctrl.mul + m.io.req.valid := ex_reg_valid && ex_ctrl(decoder.mul) m.io.req.bits := div.io.req.bits m } @@ -468,36 +544,36 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) when (!ctrl_killd) { ex_ctrl := id_ctrl ex_reg_rvc := ibuf.io.inst(0).bits.rvc - ex_ctrl.csr := id_csr - when (id_ctrl.fence && id_fence_succ === 0.U) { id_reg_pause := true.B } + ex_ctrl(decoder.csr) := id_csr + when (id_ctrl(decoder.fence) && id_fence_succ === 0.U) { id_reg_pause := true.B } when (id_fence_next) { id_reg_fence := true.B } when (id_xcpt) { // pass PC down ALU writeback pipeline for badaddr - ex_ctrl.alu_fn := aluFn.FN_ADD - ex_ctrl.alu_dw := DW_XPR - ex_ctrl.sel_alu1 := A1_RS1 // badaddr := instruction - ex_ctrl.sel_alu2 := A2_ZERO + ex_ctrl(decoder.aluFn) := aluFn.FN_ADD + ex_ctrl(decoder.aluDoubleWords) := DW_XPR + ex_ctrl(decoder.selAlu1) := A1_RS1 // badaddr := instruction + ex_ctrl(decoder.selAlu2) := A2_ZERO when (id_xcpt1.asUInt.orR) { // badaddr := PC+2 - ex_ctrl.sel_alu1 := A1_PC - ex_ctrl.sel_alu2 := A2_SIZE + ex_ctrl(decoder.selAlu1) := A1_PC + ex_ctrl(decoder.selAlu2) := A2_SIZE ex_reg_rvc := true.B } when (bpu.io.xcpt_if || id_xcpt0.asUInt.orR) { // badaddr := PC - ex_ctrl.sel_alu1 := A1_PC - ex_ctrl.sel_alu2 := A2_ZERO + ex_ctrl(decoder.selAlu1) := A1_PC + ex_ctrl(decoder.selAlu2) := A2_ZERO } } - ex_reg_flush_pipe := id_ctrl.fence_i || id_csr_flush + ex_reg_flush_pipe := id_ctrl(decoder.fenceI) || id_csr_flush ex_reg_load_use := id_load_use - ex_reg_hls := usingHypervisor.B && id_system_insn && id_ctrl.mem_cmd.isOneOf(M_XRD, M_XWR, M_HLVX) + ex_reg_hls := usingHypervisor.B && id_system_insn && id_ctrl(decoder.memCommand).isOneOf(M_XRD, M_XWR, M_HLVX) ex_reg_mem_size := Mux(usingHypervisor.B && id_system_insn, id_inst(0)(27, 26), id_inst(0)(13, 12)) - when (id_ctrl.mem_cmd.isOneOf(M_SFENCE, M_HFENCEV, M_HFENCEG, M_FLUSH_ALL)) { + when (id_ctrl(decoder.memCommand).isOneOf(M_SFENCE, M_HFENCEV, M_HFENCEG, M_FLUSH_ALL)) { ex_reg_mem_size := Cat(id_raddr2 =/= 0.U, id_raddr1 =/= 0.U) } - when (id_ctrl.mem_cmd === M_SFENCE && csr.io.status.v) { - ex_ctrl.mem_cmd := M_HFENCEV + when (id_ctrl(decoder.memCommand) === M_SFENCE && csr.io.status.v) { + ex_ctrl(decoder.memCommand) := M_HFENCEV } if (tile.dcache.flushOnFenceI) { - when (id_ctrl.fence_i) { + when (id_ctrl(decoder.fenceI)) { ex_reg_mem_size := 0.U } } @@ -530,15 +606,15 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) // replay inst in ex stage? val ex_pc_valid = ex_reg_valid || ex_reg_replay || ex_reg_xcpt_interrupt - val wb_dcache_miss = wb_ctrl.mem && !io.dmem.resp.valid - val replay_ex_structural = ex_ctrl.mem && !io.dmem.req.ready || - ex_ctrl.div && !div.io.req.ready + val wb_dcache_miss = wb_ctrl(decoder.mem) && !io.dmem.resp.valid + val replay_ex_structural = ex_ctrl(decoder.mem) && !io.dmem.req.ready || + ex_ctrl(decoder.div) && !div.io.req.ready val replay_ex_load_use = wb_dcache_miss && ex_reg_load_use val replay_ex = ex_reg_replay || (ex_reg_valid && (replay_ex_structural || replay_ex_load_use)) val ctrl_killx = take_pc_mem_wb || replay_ex || !ex_reg_valid // detect 2-cycle load-use delay for LB/LH/SC - val ex_slow_bypass = ex_ctrl.mem_cmd === M_XSC || ex_reg_mem_size < 2.U - val ex_sfence = usingVM.B && ex_ctrl.mem && (ex_ctrl.mem_cmd === M_SFENCE || ex_ctrl.mem_cmd === M_HFENCEV || ex_ctrl.mem_cmd === M_HFENCEG) + val ex_slow_bypass = ex_ctrl(decoder.memCommand) === M_XSC || ex_reg_mem_size < 2.U + val ex_sfence = usingVM.B && ex_ctrl(decoder.mem) && (ex_ctrl(decoder.memCommand) === M_SFENCE || ex_ctrl(decoder.memCommand) === M_HFENCEV || ex_ctrl(decoder.memCommand) === M_HFENCEG) val (ex_xcpt, ex_cause) = checkExceptions(List( (ex_reg_xcpt_interrupt || ex_reg_xcpt, ex_reg_cause))) @@ -549,18 +625,18 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) // memory stage val mem_pc_valid = mem_reg_valid || mem_reg_replay || mem_reg_xcpt_interrupt val mem_br_target = mem_reg_pc.asSInt + - Mux(mem_ctrl.branch && mem_br_taken, ImmGen(IMM_SB, mem_reg_inst), - Mux(mem_ctrl.jal, ImmGen(IMM_UJ, mem_reg_inst), + Mux(mem_ctrl(decoder.isBranch) && mem_br_taken, ImmGen(IMM_SB, mem_reg_inst), + Mux(mem_ctrl(decoder.isJal), ImmGen(IMM_UJ, mem_reg_inst), Mux(mem_reg_rvc, 2.S, 4.S))) - val mem_npc = (Mux(mem_ctrl.jalr || mem_reg_sfence, encodeVirtualAddress(mem_reg_wdata, mem_reg_wdata).asSInt, mem_br_target) & (-2).S).asUInt + val mem_npc = (Mux(mem_ctrl(decoder.isJalr) || mem_reg_sfence, encodeVirtualAddress(mem_reg_wdata, mem_reg_wdata).asSInt, mem_br_target) & (-2).S).asUInt val mem_wrong_npc = Mux(ex_pc_valid, mem_npc =/= ex_reg_pc, Mux(ibuf.io.inst(0).valid || ibuf.io.imem.valid, mem_npc =/= ibuf.io.pc, true.B)) val mem_npc_misaligned = !csr.io.status.isa('c'-'a') && mem_npc(1) && !mem_reg_sfence - val mem_int_wdata = Mux(!mem_reg_xcpt && (mem_ctrl.jalr ^ mem_npc_misaligned), mem_br_target, mem_reg_wdata.asSInt).asUInt - val mem_cfi = mem_ctrl.branch || mem_ctrl.jalr || mem_ctrl.jal - val mem_cfi_taken = (mem_ctrl.branch && mem_br_taken) || mem_ctrl.jalr || mem_ctrl.jal - val mem_direction_misprediction = mem_ctrl.branch && mem_br_taken =/= (usingBTB.B && mem_reg_btb_resp.taken) + val mem_int_wdata = Mux(!mem_reg_xcpt && (mem_ctrl(decoder.isJalr) ^ mem_npc_misaligned), mem_br_target, mem_reg_wdata.asSInt).asUInt + val mem_cfi = mem_ctrl(decoder.isBranch) || mem_ctrl(decoder.isJalr) || mem_ctrl(decoder.isJal) + val mem_cfi_taken = (mem_ctrl(decoder.isBranch) && mem_br_taken) || mem_ctrl(decoder.isJalr) || mem_ctrl(decoder.isJal) + val mem_direction_misprediction = mem_ctrl(decoder.isBranch) && mem_br_taken =/= (usingBTB.B && mem_reg_btb_resp.taken) val mem_misprediction = if (usingBTB) mem_wrong_npc else mem_cfi_taken take_pc_mem := mem_reg_valid && !mem_reg_xcpt && (mem_misprediction || mem_reg_sfence) @@ -576,8 +652,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) }.elsewhen (ex_pc_valid) { mem_ctrl := ex_ctrl mem_reg_rvc := ex_reg_rvc - mem_reg_load := ex_ctrl.mem && isRead(ex_ctrl.mem_cmd) - mem_reg_store := ex_ctrl.mem && isWrite(ex_ctrl.mem_cmd) + mem_reg_load := ex_ctrl(decoder.mem) && isRead(ex_ctrl(decoder.memCommand)) + mem_reg_store := ex_ctrl(decoder.mem) && isWrite(ex_ctrl(decoder.memCommand)) mem_reg_sfence := ex_sfence mem_reg_btb_resp := ex_reg_btb_resp mem_reg_flush_pipe := ex_reg_flush_pipe @@ -592,21 +668,21 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) mem_reg_pc := ex_reg_pc // IDecode ensured they are 1H mem_reg_wdata := Mux1H(Seq( - ex_ctrl.zbk -> ex_zbk_wdata, - ex_ctrl.zkn -> ex_zkn_wdata, - ex_ctrl.zks -> ex_zks_wdata, - (!ex_ctrl.zbk && !ex_ctrl.zkn && !ex_ctrl.zks) + ex_ctrl(decoder.zbk) -> ex_zbk_wdata, + ex_ctrl(decoder.zkn) -> ex_zkn_wdata, + ex_ctrl(decoder.zks) -> ex_zks_wdata, + (!ex_ctrl(decoder.zbk) && !ex_ctrl(decoder.zkn) && !ex_ctrl(decoder.zks)) -> alu.io.out, )) mem_br_taken := alu.io.cmp_out - when (ex_ctrl.rxs2 && (ex_ctrl.mem || ex_ctrl.rocc || ex_sfence)) { - val size = Mux(ex_ctrl.rocc, log2Ceil(xLen/8).U, ex_reg_mem_size) + when (ex_ctrl(decoder.rxs2) && (ex_ctrl(decoder.mem) || ex_ctrl(decoder.isRoCC) || ex_sfence)) { + val size = Mux(ex_ctrl(decoder.isRoCC), log2Ceil(xLen/8).U, ex_reg_mem_size) mem_reg_rs2 := new StoreGen(size, 0.U, ex_rs(1), coreDataBytes).data } - when (ex_ctrl.jalr && csr.io.status.debug) { + when (ex_ctrl(decoder.isJalr) && csr.io.status.debug) { // flush I$ on D-mode JALR to effect uncached fetch without D$ flush - mem_ctrl.fence_i := true.B + mem_ctrl(decoder.fenceI) := true.B mem_reg_flush_pipe := true.B } } @@ -629,8 +705,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) )).distinct coverExceptions(mem_xcpt, mem_cause, "MEMORY", memCoverCauses) - val dcache_kill_mem = mem_reg_valid && mem_ctrl.wxd && io.dmem.replay_next // structural hazard on writeback port - val fpu_kill_mem = mem_reg_valid && mem_ctrl.fp && io.fpu.nack_mem + val dcache_kill_mem = mem_reg_valid && mem_ctrl(decoder.wxd) && io.dmem.replay_next // structural hazard on writeback port + val fpu_kill_mem = mem_reg_valid && mem_ctrl(decoder.isFPU) && io.fpu.nack_mem val replay_mem = dcache_kill_mem || mem_reg_replay || fpu_kill_mem val killm_common = dcache_kill_mem || take_pc_wb || mem_reg_xcpt || !mem_reg_valid div.io.kill := killm_common && RegNext(div.io.req.fire) @@ -644,8 +720,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) when (mem_pc_valid) { wb_ctrl := mem_ctrl wb_reg_sfence := mem_reg_sfence - wb_reg_wdata := Mux(!mem_reg_xcpt && mem_ctrl.fp && mem_ctrl.wxd, io.fpu.toint_data, mem_int_wdata) - when (mem_ctrl.rocc || mem_reg_sfence) { + wb_reg_wdata := Mux(!mem_reg_xcpt && mem_ctrl(decoder.isFPU) && mem_ctrl(decoder.wxd), io.fpu.toint_data, mem_int_wdata) + when (mem_ctrl(decoder.isRoCC) || mem_reg_sfence) { wb_reg_rs2 := mem_reg_rs2 } wb_reg_cause := mem_cause @@ -653,8 +729,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) wb_reg_raw_inst := mem_reg_raw_inst wb_reg_mem_size := mem_reg_mem_size wb_reg_hls_or_dv := mem_reg_hls_or_dv - wb_reg_hfence_v := mem_ctrl.mem_cmd === M_HFENCEV - wb_reg_hfence_g := mem_ctrl.mem_cmd === M_HFENCEG + wb_reg_hfence_v := mem_ctrl(decoder.memCommand) === M_HFENCEV + wb_reg_hfence_g := mem_ctrl(decoder.memCommand) === M_HFENCEG wb_reg_pc := mem_reg_pc wb_reg_wphit := mem_reg_wphit | bpu.io.bpwatch.map { bpw => (bpw.rvalid(0) && mem_reg_load) || (bpw.wvalid(0) && mem_reg_store) } @@ -662,14 +738,14 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) val (wb_xcpt, wb_cause) = checkExceptions(List( (wb_reg_xcpt, wb_reg_cause), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.pf.st, Causes.store_page_fault.U), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.pf.ld, Causes.load_page_fault.U), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.gf.st, Causes.store_guest_page_fault.U), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.gf.ld, Causes.load_guest_page_fault.U), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.ae.st, Causes.store_access.U), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.ae.ld, Causes.load_access.U), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.ma.st, Causes.misaligned_store.U), - (wb_reg_valid && wb_ctrl.mem && io.dmem.s2_xcpt.ma.ld, Causes.misaligned_load.U) + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.pf.st, Causes.store_page_fault.U), + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.pf.ld, Causes.load_page_fault.U), + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.gf.st, Causes.store_guest_page_fault.U), + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.gf.ld, Causes.load_guest_page_fault.U), + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.ae.st, Causes.store_access.U), + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.ae.ld, Causes.load_access.U), + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.ma.st, Causes.misaligned_store.U), + (wb_reg_valid && wb_ctrl(decoder.mem) && io.dmem.s2_xcpt.ma.ld, Causes.misaligned_load.U) )) val wbCoverCauses = List( @@ -687,10 +763,10 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) coverExceptions(wb_xcpt, wb_cause, "WRITEBACK", wbCoverCauses) val wb_pc_valid = wb_reg_valid || wb_reg_replay || wb_reg_xcpt - val wb_wxd = wb_reg_valid && wb_ctrl.wxd - val wb_set_sboard = wb_ctrl.div || wb_dcache_miss || wb_ctrl.rocc + val wb_wxd = wb_reg_valid && wb_ctrl(decoder.wxd) + val wb_set_sboard = wb_ctrl(decoder.div) || wb_dcache_miss || wb_ctrl(decoder.isRoCC) val replay_wb_common = io.dmem.s2_nack || wb_reg_replay - val replay_wb_rocc = wb_reg_valid && wb_ctrl.rocc && !io.rocc.cmd.ready + val replay_wb_rocc = wb_reg_valid && wb_ctrl(decoder.isRoCC) && !io.rocc.cmd.ready val replay_wb_csr: Bool = wb_reg_valid && csr.io.rw_stall val replay_wb = replay_wb_common || replay_wb_rocc || replay_wb_csr take_pc_wb := replay_wb || wb_xcpt || csr.io.eret || wb_reg_flush_pipe @@ -731,13 +807,13 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) } val wb_valid = wb_reg_valid && !replay_wb && !wb_xcpt - val wb_wen = wb_valid && wb_ctrl.wxd + val wb_wen = wb_valid && wb_ctrl(decoder.wxd) val rf_wen = wb_wen || ll_wen val rf_waddr = Mux(ll_wen, ll_waddr, wb_waddr) val rf_wdata = Mux(dmem_resp_valid && dmem_resp_xpu, io.dmem.resp.bits.data(xLen-1, 0), Mux(ll_wen, ll_wdata, - Mux(wb_ctrl.csr =/= CSR.N, csr.io.rw.rdata, - Mux(wb_ctrl.mul, mul.map(_.io.resp.bits.data).getOrElse(wb_reg_wdata), + Mux(wb_ctrl(decoder.csr) =/= CSR.N, csr.io.rw.rdata, + Mux(wb_ctrl(decoder.mul), mul.map(_.io.resp.bits.data).getOrElse(wb_reg_wdata), wb_reg_wdata)))) when (rf_wen) { rf.write(rf_waddr, rf_wdata) } @@ -782,7 +858,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) io.ptw.gstatus := csr.io.gstatus io.ptw.pmp := csr.io.pmp csr.io.rw.addr := wb_reg_inst(31,20) - csr.io.rw.cmd := CSR.maskCmd(wb_reg_valid, wb_ctrl.csr) + csr.io.rw.cmd := CSR.maskCmd(wb_reg_valid, wb_ctrl(decoder.csr)) csr.io.rw.wdata := wb_reg_wdata io.rocc.csrs <> csr.io.roccCSRs io.trace.time := csr.io.time @@ -792,9 +868,9 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) csr_trace_with_wdata.wdata.get := rf_wdata DebugROB.pushTrace(clock, reset, io.hartid, csr_trace_with_wdata, - (wb_ctrl.wfd || (wb_ctrl.wxd && wb_waddr =/= 0.U)) && !csr.io.trace(0).exception, - wb_ctrl.wxd && wb_wen && !wb_set_sboard, - wb_waddr + Mux(wb_ctrl.wfd, 32.U, 0.U)) + (wb_ctrl(decoder.wfd) || (wb_ctrl(decoder.wxd) && wb_waddr =/= 0.U)) && !csr.io.trace(0).exception, + wb_ctrl(decoder.wxd) && wb_wen && !wb_set_sboard, + wb_waddr + Mux(wb_ctrl(decoder.wfd), 32.U, 0.U)) io.trace.insns(0) := DebugROB.popTrace(clock, reset, io.hartid) @@ -811,9 +887,9 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) iobpw.ivalid.foreach(_ := false.B) } - val hazard_targets = Seq((id_ctrl.rxs1 && id_raddr1 =/= 0.U, id_raddr1), - (id_ctrl.rxs2 && id_raddr2 =/= 0.U, id_raddr2), - (id_ctrl.wxd && id_waddr =/= 0.U, id_waddr)) + val hazard_targets = Seq((id_ctrl(decoder.rxs1) && id_raddr1 =/= 0.U, id_raddr1), + (id_ctrl(decoder.rxs2) && id_raddr2 =/= 0.U, id_raddr2), + (id_ctrl(decoder.wxd) && id_waddr =/= 0.U, id_waddr)) val fp_hazard_targets = Seq((io.fpu.dec.ren1, id_raddr1), (io.fpu.dec.ren2, id_raddr2), (io.fpu.dec.ren3, id_raddr3), @@ -830,29 +906,29 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) sboard.set(wb_set_sboard && wb_wen, wb_waddr) // stall for RAW/WAW hazards on CSRs, loads, AMOs, and mul/div in execute stage. - val ex_cannot_bypass = ex_ctrl.csr =/= CSR.N || ex_ctrl.jalr || ex_ctrl.mem || ex_ctrl.mul || ex_ctrl.div || ex_ctrl.fp || ex_ctrl.rocc - val data_hazard_ex = ex_ctrl.wxd && checkHazards(hazard_targets, _ === ex_waddr) - val fp_data_hazard_ex = id_ctrl.fp && ex_ctrl.wfd && checkHazards(fp_hazard_targets, _ === ex_waddr) + val ex_cannot_bypass = ex_ctrl(decoder.csr) =/= CSR.N || ex_ctrl(decoder.isJalr) || ex_ctrl(decoder.mem) || ex_ctrl(decoder.mul) || ex_ctrl(decoder.div) || ex_ctrl(decoder.isFPU) || ex_ctrl(decoder.isRoCC) + val data_hazard_ex = ex_ctrl(decoder.wxd) && checkHazards(hazard_targets, _ === ex_waddr) + val fp_data_hazard_ex = id_ctrl(decoder.isFPU) && ex_ctrl(decoder.wfd) && checkHazards(fp_hazard_targets, _ === ex_waddr) val id_ex_hazard = ex_reg_valid && (data_hazard_ex && ex_cannot_bypass || fp_data_hazard_ex) // stall for RAW/WAW hazards on CSRs, LB/LH, and mul/div in memory stage. val mem_mem_cmd_bh = if (fastLoadWord) (!fastLoadByte).B && mem_reg_slow_bypass else true.B - val mem_cannot_bypass = mem_ctrl.csr =/= CSR.N || mem_ctrl.mem && mem_mem_cmd_bh || mem_ctrl.mul || mem_ctrl.div || mem_ctrl.fp || mem_ctrl.rocc - val data_hazard_mem = mem_ctrl.wxd && checkHazards(hazard_targets, _ === mem_waddr) - val fp_data_hazard_mem = id_ctrl.fp && mem_ctrl.wfd && checkHazards(fp_hazard_targets, _ === mem_waddr) + val mem_cannot_bypass = mem_ctrl(decoder.csr) =/= CSR.N || mem_ctrl(decoder.mem) && mem_mem_cmd_bh || mem_ctrl(decoder.mul) || mem_ctrl(decoder.div) || mem_ctrl(decoder.isFPU) || mem_ctrl(decoder.isRoCC) + val data_hazard_mem = mem_ctrl(decoder.wxd) && checkHazards(hazard_targets, _ === mem_waddr) + val fp_data_hazard_mem = id_ctrl(decoder.isFPU) && mem_ctrl(decoder.wfd) && checkHazards(fp_hazard_targets, _ === mem_waddr) val id_mem_hazard = mem_reg_valid && (data_hazard_mem && mem_cannot_bypass || fp_data_hazard_mem) - id_load_use := mem_reg_valid && data_hazard_mem && mem_ctrl.mem + id_load_use := mem_reg_valid && data_hazard_mem && mem_ctrl(decoder.mem) // stall for RAW/WAW hazards on load/AMO misses and mul/div in writeback. - val data_hazard_wb = wb_ctrl.wxd && checkHazards(hazard_targets, _ === wb_waddr) - val fp_data_hazard_wb = id_ctrl.fp && wb_ctrl.wfd && checkHazards(fp_hazard_targets, _ === wb_waddr) + val data_hazard_wb = wb_ctrl(decoder.wxd) && checkHazards(hazard_targets, _ === wb_waddr) + val fp_data_hazard_wb = id_ctrl(decoder.isFPU) && wb_ctrl(decoder.wfd) && checkHazards(fp_hazard_targets, _ === wb_waddr) val id_wb_hazard = wb_reg_valid && (data_hazard_wb && wb_set_sboard || fp_data_hazard_wb) val id_stall_fpu = if (usingFPU) { val fp_sboard = new Scoreboard(32) - fp_sboard.set((wb_dcache_miss && wb_ctrl.wfd || io.fpu.sboard_set) && wb_valid, wb_waddr) + fp_sboard.set((wb_dcache_miss && wb_ctrl(decoder.wfd) || io.fpu.sboard_set) && wb_valid, wb_waddr) fp_sboard.clear(dmem_resp_replay && dmem_resp_fpu, dmem_resp_waddr) fp_sboard.clear(io.fpu.sboard_clr, io.fpu.sboard_clra) @@ -872,10 +948,10 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) id_ex_hazard || id_mem_hazard || id_wb_hazard || id_sboard_hazard || csr.io.singleStep && (ex_reg_valid || mem_reg_valid || wb_reg_valid) || id_csr_en && csr.io.decode(0).fp_csr && !io.fpu.fcsr_rdy || - id_ctrl.fp && id_stall_fpu || - id_ctrl.mem && dcache_blocked || // reduce activity during D$ misses - id_ctrl.rocc && rocc_blocked || // reduce activity while RoCC is busy - id_ctrl.div && (!(div.io.req.ready || (div.io.resp.valid && !wb_wxd)) || div.io.req.valid) || // reduce odds of replay + id_ctrl(decoder.isFPU) && id_stall_fpu || + id_ctrl(decoder.mem) && dcache_blocked || // reduce activity during D$ misses + id_ctrl(decoder.isRoCC) && rocc_blocked || // reduce activity while RoCC is busy + id_ctrl(decoder.div) && (!(div.io.req.ready || (div.io.resp.valid && !wb_wxd)) || div.io.req.valid) || // reduce odds of replay !clock_en || id_do_fence || csr.io.csr_stall || @@ -889,7 +965,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) Mux(wb_xcpt || csr.io.eret, csr.io.evec, // exception or [m|s]ret Mux(replay_wb, wb_reg_pc, // replay mem_npc)) // flush or branch misprediction - io.imem.flush_icache := wb_reg_valid && wb_ctrl.fence_i && !io.dmem.s2_nack + io.imem.flush_icache := wb_reg_valid && wb_ctrl(decoder.fenceI) && !io.dmem.s2_nack io.imem.might_request := { imem_might_request_reg := ex_pc_valid || mem_pc_valid || io.ptw.customCSRs.disableICacheClockGate imem_might_request_reg @@ -909,9 +985,9 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) io.imem.btb_update.valid := mem_reg_valid && !take_pc_wb && mem_wrong_npc && (!mem_cfi || mem_cfi_taken) io.imem.btb_update.bits.isValid := mem_cfi io.imem.btb_update.bits.cfiType := - Mux((mem_ctrl.jal || mem_ctrl.jalr) && mem_waddr(0), CFIType.call, - Mux(mem_ctrl.jalr && (mem_reg_inst(19,15) & regAddrMask.U) === BitPat("b00?01"), CFIType.ret, - Mux(mem_ctrl.jal || mem_ctrl.jalr, CFIType.jump, + Mux((mem_ctrl(decoder.isJal) || mem_ctrl(decoder.isJalr)) && mem_waddr(0), CFIType.call, + Mux(mem_ctrl(decoder.isJalr) && (mem_reg_inst(19,15) & regAddrMask.U) === BitPat("b00?01"), CFIType.ret, + Mux(mem_ctrl(decoder.isJal) || mem_ctrl(decoder.isJalr), CFIType.jump, CFIType.branch))) io.imem.btb_update.bits.target := io.imem.req.bits.pc io.imem.btb_update.bits.br_pc := (if (usingCompressed) mem_reg_pc + Mux(mem_reg_rvc, 0.U, 2.U) else mem_reg_pc) @@ -923,13 +999,13 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) io.imem.bht_update.bits.pc := io.imem.btb_update.bits.pc io.imem.bht_update.bits.taken := mem_br_taken io.imem.bht_update.bits.mispredict := mem_wrong_npc - io.imem.bht_update.bits.branch := mem_ctrl.branch + io.imem.bht_update.bits.branch := mem_ctrl(decoder.isBranch) io.imem.bht_update.bits.prediction := mem_reg_btb_resp.bht // Connect RAS in Frontend io.imem.ras_update := DontCare - io.fpu.valid := !ctrl_killd && id_ctrl.fp + io.fpu.valid := !ctrl_killd && id_ctrl(decoder.isFPU) io.fpu.killx := ctrl_killx io.fpu.killm := killm_common io.fpu.inst := id_inst(0) @@ -940,11 +1016,11 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) io.fpu.dmem_resp_tag := dmem_resp_waddr io.fpu.keep_clock_enabled := io.ptw.customCSRs.disableCoreClockGate - io.dmem.req.valid := ex_reg_valid && ex_ctrl.mem - val ex_dcache_tag = Cat(ex_waddr, ex_ctrl.fp) + io.dmem.req.valid := ex_reg_valid && ex_ctrl(decoder.mem) + val ex_dcache_tag = Cat(ex_waddr, ex_ctrl(decoder.isFPU)) require(coreParams.dcacheReqTagBits >= ex_dcache_tag.getWidth) io.dmem.req.bits.tag := ex_dcache_tag - io.dmem.req.bits.cmd := ex_ctrl.mem_cmd + io.dmem.req.bits.cmd := ex_ctrl(decoder.memCommand) io.dmem.req.bits.size := ex_reg_mem_size io.dmem.req.bits.signed := !Mux(ex_reg_hls, ex_reg_inst(20), ex_reg_inst(14)) io.dmem.req.bits.phys := false.B @@ -957,15 +1033,15 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) io.dmem.req.bits.data := DontCare io.dmem.req.bits.mask := DontCare - io.dmem.s1_data.data := (if (fLen == 0) mem_reg_rs2 else Mux(mem_ctrl.fp, Fill((xLen max fLen) / fLen, io.fpu.store_data), mem_reg_rs2)) + io.dmem.s1_data.data := (if (fLen == 0) mem_reg_rs2 else Mux(mem_ctrl(decoder.isFPU), Fill((xLen max fLen) / fLen, io.fpu.store_data), mem_reg_rs2)) io.dmem.s1_data.mask := DontCare io.dmem.s1_kill := killm_common || mem_ldst_xcpt || fpu_kill_mem io.dmem.s2_kill := false.B // don't let D$ go to sleep if we're probably going to use it soon - io.dmem.keep_clock_enabled := ibuf.io.inst(0).valid && id_ctrl.mem && !csr.io.csr_stall + io.dmem.keep_clock_enabled := ibuf.io.inst(0).valid && id_ctrl(decoder.mem) && !csr.io.csr_stall - io.rocc.cmd.valid := wb_reg_valid && wb_ctrl.rocc && !replay_wb_common + io.rocc.cmd.valid := wb_reg_valid && wb_ctrl(decoder.isRoCC) && !replay_wb_common io.rocc.exception := wb_xcpt && csr.io.status.xs.orR io.rocc.cmd.bits.status := csr.io.status io.rocc.cmd.bits.inst := wb_reg_inst.asTypeOf(new RoCCInstruction()) @@ -1018,8 +1094,8 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) if (enableCommitLog) { val t = csr.io.trace(0) val rd = wb_waddr - val wfd = wb_ctrl.wfd - val wxd = wb_ctrl.wxd + val wfd = wb_ctrl(decoder.wfd) + val wxd = wb_ctrl(decoder.wxd) val has_data = wb_wen && !wb_set_sboard when (t.valid && !t.exception) { @@ -1046,13 +1122,13 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) printf("C%d: %d [%d] pc=[%x] W[r%d=%x][%d] R[r%d=%x] R[r%d=%x] inst=[%x] DASM(%x)\n", io.hartid, coreMonitorBundle.timer, coreMonitorBundle.valid, coreMonitorBundle.pc, - Mux(wb_ctrl.wxd || wb_ctrl.wfd, coreMonitorBundle.wrdst, 0.U), + Mux(wb_ctrl(decoder.wxd) || wb_ctrl(decoder.wfd), coreMonitorBundle.wrdst, 0.U), Mux(coreMonitorBundle.wrenx, coreMonitorBundle.wrdata, 0.U), coreMonitorBundle.wrenx, - Mux(wb_ctrl.rxs1 || wb_ctrl.rfs1, coreMonitorBundle.rd0src, 0.U), - Mux(wb_ctrl.rxs1 || wb_ctrl.rfs1, coreMonitorBundle.rd0val, 0.U), - Mux(wb_ctrl.rxs2 || wb_ctrl.rfs2, coreMonitorBundle.rd1src, 0.U), - Mux(wb_ctrl.rxs2 || wb_ctrl.rfs2, coreMonitorBundle.rd1val, 0.U), + Mux(wb_ctrl(decoder.rxs1) || wb_ctrl(decoder.rfs1), coreMonitorBundle.rd0src, 0.U), + Mux(wb_ctrl(decoder.rxs1) || wb_ctrl(decoder.rfs1), coreMonitorBundle.rd0val, 0.U), + Mux(wb_ctrl(decoder.rxs2) || wb_ctrl(decoder.rfs2), coreMonitorBundle.rd1src, 0.U), + Mux(wb_ctrl(decoder.rxs2) || wb_ctrl(decoder.rfs2), coreMonitorBundle.rd1val, 0.U), coreMonitorBundle.inst, coreMonitorBundle.inst) } }