From a5d9d5a08ccd2245525a7af3f1802791855c4fb9 Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Mon, 25 Sep 2023 01:39:47 +0800 Subject: [PATCH] implement new decoder TODO: need - release version of chisel 3.6.1, 5.1 - Zb/Zbk support - riscv-opcode path configurable --- .../rocket/CustomInstructions.scala | 1 + .../scala/{ => deprecate}/rocket/Decode.scala | 1 + .../{ => deprecate}/rocket/IDecode.scala | 1 + .../{ => deprecate}/rocket/Instructions.scala | 1 + src/main/scala/rocket/Decoder.scala | 982 ++++++++++++++++++ src/main/scala/rocket/RocketCore.scala | 563 ++++++---- 6 files changed, 1330 insertions(+), 219 deletions(-) rename src/main/scala/{ => deprecate}/rocket/CustomInstructions.scala (98%) rename src/main/scala/{ => deprecate}/rocket/Decode.scala (98%) rename src/main/scala/{ => deprecate}/rocket/IDecode.scala (99%) rename src/main/scala/{ => deprecate}/rocket/Instructions.scala (99%) create mode 100644 src/main/scala/rocket/Decoder.scala 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 new file mode 100644 index 00000000000..237fb1e10f9 --- /dev/null +++ b/src/main/scala/rocket/Decoder.scala @@ -0,0 +1,982 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Jiuyang Liu + +package org.chipsalliance.rocketcore.decoder + +import chisel3._ +import chisel3.util.BitPat +import chisel3.util.experimental.decode._ +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. +trait UOP { + def width: Int + + def dontCare: BitPat = BitPat.dontCare(width) + + def chiselType: TPE = UInt(width.W) + + def encode(lit: Int): BitPat = BitPat(lit.U(width.W)) + + def encode(strLit: String): BitPat = BitPat(strLit.U(width.W)) + + type TPE = UInt +} + +trait UOPDecodeField[T <: DecodePattern] extends DecodeField[T, UInt] { + def uopType: UOP + + def chiselType: UInt = uopType.chiselType +} + +/** DecodePattern for an RISC-V instruction */ +case class RocketDecodePattern(instruction: Instruction) extends DecodePattern { + def isRoCC: Boolean = instruction.instructionSet.name == "rv_rocc" + + override def bitPat: BitPat = BitPat("b"+instruction.encoding.toString) +} + +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")) + ) + + 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")) + ) +} + +/** Parameter for InstructionDecoder + * @param instructions Instructions supported by + * @param pipelinedMul + * @param fenceIFlushDCache + */ +case class InstructionDecoderParameter( + instructions: Seq[Instruction], + // uarch configurations on rocket decoder + 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.map(_.instructionSet.name).exists(_.startsWith("rv32_")) + + private def xLen64: Boolean = instructions.map(_.instructionSet.name).exists(_.startsWith("rv64_")) + + 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 useFPU = !fLen0 + private val useRoCC = hasAnySetIn("rv_rocc") + private val useMulDiv = hasAnySetIn("rv_m", "rv64_m") + + private val instructionDecodePatterns: Seq[RocketDecodePattern] = instructions.map(RocketDecodePattern.apply) + private val instructionDecodeFields: Seq[DecodeField[RocketDecodePattern, _ <: Data]] = Seq( + isLegal, isBranch, isJal, isJalr, rxs2, rxs1, selAlu2, selAlu1, selImm, aluDoubleWords, mem, memCommand, wxd, csr, fenceI, fence, amo, + ) ++ + (if (useABLU) Seq(abluFn, zbk, zkn, zks) else Some(aluFn)) ++ + (if (useFPU) Seq(fp, rfs1, rfs2, rfs3, wfd, dp) else None) ++ + (if (useMulDiv) if (p.pipelinedMul) Seq(mul, div) else Seq(div) else None) ++ + (if (useRoCC) Some(rocc) else None) + + val table: DecodeTable[RocketDecodePattern] = new DecodeTable[RocketDecodePattern]( + instructionDecodePatterns, + instructionDecodeFields + ) + + object isLegal extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "legal" + + override def default: BitPat = n + + // should always be true + override def genTable(op: RocketDecodePattern): BitPat = y + } + + object fp extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "fp" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.instructionSet.name match { + // format: off + case s if Seq( + "rv_d", "rv64_d", + "rv_f", "rv64_f", + "rv_q", "rv64_q", + "rv_zfh", "rv64_zfh", "rv_d_zfh", "rv_q_zfh", + ).contains(s) => y + case _ => n + // format: on + } + } + + object dp extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "dp" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.instructionSet.name match { + // format: off + case s if Seq("rv_d", "rv_d_zfh", "rv64_d").contains(s) => y + case _ => n + // format: on + } + } + + object isBranch extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "branch" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("bne", "beq", "blt", "bltu", "bge", "bgeu").contains(i) => y + case _ => n + // format: on + } + } + + object isJal extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "jal" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("jal").contains(i) => y + case _ => n + // format: on + } + } + + object isJalr extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "jalr" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("jalr").contains(i) => y + case _ => n + // format: on + } + } + + object rxs2 extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "rxs2" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + case i if Seq("bne", "beq", "blt", "bltu", "bge", "bgeu", "sb", "sh", "sw", "add", "sub", "slt", "sltu", "and", "or", "xor", "sll", "srl", "sra", "czero.eqz", "czero.nez", "sfence.vma", "hfence.vvma", "hfence.gvma", "hsv.b", "hsv.h", "hsv.w", "sd", "addw", "subw", "sllw", "srlw", "sraw", "hsv.d", "mul", "mulh", "mulhu", "mulhsu", "div", "divu", "rem", "remu", "mulw", "divw", "divuw", "remw", "remuw", "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", "sh1add", "sh2add", "sh3add", "add.uw", "sh1add.uw", "sh2add.uw", "sh3add.uw", "andn", "orn", "xnor", "ror", "rol", "rorw", "rolw", "max", "maxu", "min", "minu", "pack", "packh", "packw", "clmul", "clmulh", "clmulr", "xperm8", "xperm4", "bclr", "bext", "binv", "bset", "aes32dsi", "aes32dsmi", "aes64ds", "aes64dsm", "aes64im", "aes64ks2", "aes32esi", "aes32esmi", "aes64es", "aes64esm", "sha512sig0l", "sha512sig1l", "sha512sig0h", "sha512sig1h", "sha512sum0r", "sha512sum1r", "sm4ed", "sm4ks", "custom0.rs1.rs2", "custom0.rd.rs1.rs2", "custom1.rs1.rs2", "custom1.rd.rs1.rs2", "custom2.rs1.rs2", "custom2.rd.rs1.rs2", "custom3.rs1.rs2", "custom3.rd.rs1.rs2").contains(i) => y + case _ => n + } + } + + object rxs1 extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "rxs1" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + case i if Seq("bne", "beq", "blt", "bltu", "bge", "bgeu", "jalr", "lb", "lh", "lw", "lbu", "lhu", "sb", "sh", "sw", "addi", "slti", "sltiu", "andi", "ori", "xori", "add", "sub", "slt", "sltu", "and", "or", "xor", "sll", "srl", "sra", "csrrw", "csrrs", "csrrc", "czero.eqz", "czero.nez", "cflush.d.l1", "cdiscard.d.l1", "sfence.vma", "hfence.vvma", "hfence.gvma", "hlv.b", "hlv.bu", "hlv.h", "hlv.hu", "hlvx.hu", "hlv.w", "hlvx.wu", "hsv.b", "hsv.h", "hsv.w", "srli", "srai", "ld", "lwu", "sd", "slli", "srli", "srai", "addiw", "slliw", "srliw", "sraiw", "addw", "subw", "sllw", "srlw", "sraw", "hlv.d", "hsv.d", "hlv.wu", "mul", "mulh", "mulhu", "mulhsu", "div", "divu", "rem", "remu", "mulw", "divw", "divuw", "remw", "remuw", "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", "fmv.h.x", "fcvt.h.w", "fcvt.h.wu", "flh", "fsh", "fmv.w.x", "fcvt.s.w", "fcvt.s.wu", "flw", "fsw", "fcvt.d.w", "fcvt.d.wu", "fld", "fsd", "fcvt.h.l", "fcvt.h.lu", "fcvt.s.l", "fcvt.s.lu", "fmv.d.x", "fcvt.d.l", "fcvt.d.lu", "sh1add", "sh2add", "sh3add", "add.uw", "slli.uw", "sh1add.uw", "sh2add.uw", "sh3add.uw", "andn", "orn", "xnor", "ror", "rol", "rori", "rori", "rorw", "rolw", "roriw", "clz", "ctz", "cpop", "clzw", "ctzw", "cpopw", "max", "maxu", "min", "minu", "sext.h", "sext.b", "zext.h", "zext.h", "orc.b", "rev8", "rev8", "pack", "packh", "brev8", "packw", "zip", "unzip", "clmul", "clmulh", "clmulr", "xperm8", "xperm4", "bclr", "bext", "binv", "bset", "bclri", "bexti", "binvi", "bseti", "bclri", "bexti", "binvi", "bseti", "aes32dsi", "aes32dsmi", "aes64ds", "aes64dsm", "aes64im", "aes64ks1i", "aes64ks2", "aes32esi", "aes32esmi", "aes64es", "aes64esm", "sha256sig0", "sha256sig1", "sha256sum0", "sha256sum1", "sha512sig0l", "sha512sig1l", "sha512sig0h", "sha512sig1h", "sha512sum0r", "sha512sum1r", "sha512sig0", "sha512sig1", "sha512sum0", "sha512sum1", "sm4ed", "sm4ks", "sm3p0", "sm3p1", "custom0.rs1", "custom0.rs1.rs2", "custom0.rd.rs1", "custom0.rd.rs1.rs2", "custom1.rs1", "custom1.rs1.rs2", "custom1.rd.rs1", "custom1.rd.rs1.rs2", "custom2.rs1", "custom2.rs1.rs2", "custom2.rd.rs1", "custom2.rd.rs1.rs2", "custom3.rs1", "custom3.rs1.rs2", "custom3.rd.rs1", "custom3.rd.rs1.rs2").contains(i) => y + case i if Seq("ecall", "ebreak", "mret", "wfi", "cease", "sret", "dret", "nmret").contains(i) => dc + case _ => n + } + } + + object fenceI extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "fence_i" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("fence.i").contains(i) => y + case _ => n + // format: on + } + } + + object fence extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "fence" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("fence").contains(i) => y + case _ => n + // format: on + } + } + + object amo extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "amo" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.instructionSet.name match { + // format: off + case s if Seq("rv_a", "rv64_a").contains(s) => y + case _ => n + // format: on + } + } + + + object zbk extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "zbk" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.instructionSet.name match { + // format: off + case s if Seq("rv_zbc", "rv_zbkx").contains(s) => y + case _ => n + // format: on + } + } + + 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 + case _ => n + // format: on + } + + } + + object zks extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "zks" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.instructionSet.name match { + // format: off + case s if Seq("rv_zksed").contains(s) => y + case _ => n + // format: on + } + } + + object aluDoubleWords extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "alu_dw" + + override def genTable(op: RocketDecodePattern): BitPat = { + op.instruction.name match { + // format: off + case i if Seq("bne", "beq", "blt", "bltu", "bge", "bgeu", "jal", "jalr", "auipc", "lb", "lh", "lw", "lbu", "lhu", "sb", "sh", "sw", "lui", "addi", "slti", "sltiu", "andi", "ori", "xori", "add", "sub", "slt", "sltu", "and", "or", "xor", "sll", "srl", "sra", "csrrw", "csrrs", "csrrc", "csrrwi", "csrrsi", "csrrci", "czero.eqz", "czero.nez", "sfence.vma", "hfence.vvma", "hfence.gvma", "hlv.b", "hlv.bu", "hlv.h", "hlv.hu", "hlvx.hu", "hlv.w", "hlvx.wu", "hsv.b", "hsv.h", "hsv.w", "ld", "lwu", "sd", "slli", "srli", "srai", "hlv.d", "hsv.d", "hlv.wu", "mul", "mulh", "mulhu", "mulhsu", "div", "divu", "rem", "remu", "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", "sh1add", "sh2add", "sh3add", "andn", "orn", "xnor", "ror", "rol", "rori", "clz", "ctz", "cpop", "max", "maxu", "min", "minu", "sext.h", "sext.b", "zext.h", "orc.b", "rev8", "pack", "packh", "brev8", "clmul", "clmulh", "clmulr", "xperm8", "xperm4", "bclr", "bext", "binv", "bset", "bclri", "bexti", "binvi", "bseti", "aes64ds", "aes64dsm", "aes64im", "aes64ks1i", "aes64ks2", "aes64es", "aes64esm", "add.uw", "slli.uw", "sh1add.uw", "sh2add.uw", "sh3add.uw").contains(i) => y + case i if Seq("addiw", "slliw", "srliw", "sraiw", "addw", "subw", "sllw", "srlw", "sraw", "mulw", "divw", "divuw", "remw", "remuw", "rorw", "rolw", "roriw", "clzw", "ctzw", "cpopw", "packw").contains(i) => n + case _ => dc + // format: on + } + } + } + + object mem extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "mem" + + override def default: BitPat = n + + override def genTable(op: RocketDecodePattern): BitPat = { + 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", "sfence.vma").contains(i) => y + case i if Seq("fence.i").contains(i) && p.fenceIFlushDCache => y + case _ => n + // format: on + } + } + } + + object rfs1 extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "rfs1" + + override def genTable(op: RocketDecodePattern): BitPat = { + op.instruction.name match { + // format: off + case i if Seq("fcvt.s.h", "fcvt.h.s", "fsgnj.h", "fsgnjx.h", "fsgnjn.h", "fmin.h", "fmax.h", "fadd.h", "fsub.h", "fmul.h", "fmadd.h", "fmsub.h", "fnmadd.h", "fnmsub.h", "fclass.h", "fmv.x.h", "fcvt.w.h", "fcvt.wu.h", "feq.h", "flt.h", "fle.h", "fdiv.h", "fsqrt.h", "fsgnj.s", "fsgnjx.s", "fsgnjn.s", "fmin.s", "fmax.s", "fadd.s", "fsub.s", "fmul.s", "fmadd.s", "fmsub.s", "fnmadd.s", "fnmsub.s", "fclass.s", "fmv.x.w", "fcvt.w.s", "fcvt.wu.s", "feq.s", "flt.s", "fle.s", "fdiv.s", "fsqrt.s", "fcvt.s.d", "fcvt.d.s", "fsgnj.d", "fsgnjx.d", "fsgnjn.d", "fmin.d", "fmax.d", "fadd.d", "fsub.d", "fmul.d", "fmadd.d", "fmsub.d", "fnmadd.d", "fnmsub.d", "fclass.d", "fcvt.w.d", "fcvt.wu.d", "feq.d", "flt.d", "fle.d", "fdiv.d", "fsqrt.d", "fcvt.d.h", "fcvt.h.d", "fcvt.l.h", "fcvt.lu.h", "fcvt.l.s", "fcvt.lu.s", "fmv.x.d", "fcvt.l.d", "fcvt.lu.d").contains(i) => y + case _ => n + // format: on + } + } + } + + object rfs2 extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "rfs2" + + override def genTable(op: RocketDecodePattern): BitPat = { + op.instruction.name match { + // format: off + case i if Seq("fsgnj.h", "fsgnjx.h", "fsgnjn.h", "fmin.h", "fmax.h", "fadd.h", "fsub.h", "fmul.h", "fmadd.h", "fmsub.h", "fnmadd.h", "fnmsub.h", "feq.h", "flt.h", "fle.h", "fdiv.h", "fsqrt.h", "fsgnj.s", "fsgnjx.s", "fsgnjn.s", "fmin.s", "fmax.s", "fadd.s", "fsub.s", "fmul.s", "fmadd.s", "fmsub.s", "fnmadd.s", "fnmsub.s", "feq.s", "flt.s", "fle.s", "fdiv.s", "fsqrt.s", "fsgnj.d", "fsgnjx.d", "fsgnjn.d", "fmin.d", "fmax.d", "fadd.d", "fsub.d", "fmul.d", "fmadd.d", "fmsub.d", "fnmadd.d", "fnmsub.d", "feq.d", "flt.d", "fle.d", "fdiv.d", "fsqrt.d").contains(i) => y + case _ => n + // format: on + } + } + } + + object rfs3 extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "rfs3" + + override def genTable(op: RocketDecodePattern): BitPat = + op.instruction.name match { + // format: off + case i if Seq("fmadd.h", "fmsub.h", "fnmadd.h", "fnmsub.h", "fmadd.s", "fmsub.s", "fnmadd.s", "fnmsub.s", "fmadd.d", "fmsub.d", "fnmadd.d", "fnmsub.d").contains(i) => y + case _ => n + // format: on + } + } + + object wfd extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "wfd" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("fcvt.s.h", "fcvt.h.s", "fsgnj.h", "fsgnjx.h", "fsgnjn.h", "fmin.h", "fmax.h", "fadd.h", "fsub.h", "fmul.h", "fmadd.h", "fmsub.h", "fnmadd.h", "fnmsub.h", "fmv.h.x", "fcvt.h.w", "fcvt.h.wu", "flh", "fdiv.h", "fsqrt.h", "fsgnj.s", "fsgnjx.s", "fsgnjn.s", "fmin.s", "fmax.s", "fadd.s", "fsub.s", "fmul.s", "fmadd.s", "fmsub.s", "fnmadd.s", "fnmsub.s", "fmv.w.x", "fcvt.s.w", "fcvt.s.wu", "flw", "fdiv.s", "fsqrt.s", "fcvt.s.d", "fcvt.d.s", "fsgnj.d", "fsgnjx.d", "fsgnjn.d", "fmin.d", "fmax.d", "fadd.d", "fsub.d", "fmul.d", "fmadd.d", "fmsub.d", "fnmadd.d", "fnmsub.d", "fcvt.d.w", "fcvt.d.wu", "fld", "fdiv.d", "fsqrt.d", "fcvt.d.h", "fcvt.h.d", "fcvt.h.l", "fcvt.h.lu", "fcvt.s.l", "fcvt.s.lu", "fmv.d.x", "fcvt.d.l", "fcvt.d.lu").contains(i) => y + case _ => n + // format: on + } + } + + object mul extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "mul" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("mul", "mulh", "mulhu", "mulhsu", "mulw").contains(i) => y + case _ => n + // format: on + } + } + + object div extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "div" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + 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 + // format: on + } + } + + object wxd extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "wxd" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + // TODO: filter out rd + case i if Seq("jal", "jalr", "auipc", "lb", "lh", "lw", "lbu", "lhu", "lui", "addi", "slti", "sltiu", "andi", "ori", "xori", "add", "sub", "slt", "sltu", "and", "or", "xor", "sll", "srl", "sra", "csrrw", "csrrs", "csrrc", "csrrwi", "csrrsi", "csrrci", "czero.eqz", "czero.nez", "hlv.b", "hlv.bu", "hlv.h", "hlv.hu", "hlvx.hu", "hlv.w", "hlvx.wu", "slli", "srli", "srai", "ld", "lwu", "slli", "srli", "srai", "addiw", "slliw", "srliw", "sraiw", "addw", "subw", "sllw", "srlw", "sraw", "hlv.d", "hlv.wu", "mul", "mulh", "mulhu", "mulhsu", "div", "divu", "rem", "remu", "mulw", "divw", "divuw", "remw", "remuw", "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", "fclass.h", "fmv.x.h", "fcvt.w.h", "fcvt.wu.h", "feq.h", "flt.h", "fle.h", "fclass.s", "fmv.x.w", "fcvt.w.s", "fcvt.wu.s", "feq.s", "flt.s", "fle.s", "fclass.d", "fcvt.w.d", "fcvt.wu.d", "feq.d", "flt.d", "fle.d", "fcvt.l.h", "fcvt.lu.h", "fcvt.l.s", "fcvt.lu.s", "fmv.x.d", "fcvt.l.d", "fcvt.lu.d", "sh1add", "sh2add", "sh3add", "add.uw", "slli.uw", "sh1add.uw", "sh2add.uw", "sh3add.uw", "andn", "orn", "xnor", "ror", "rol", "rori", "rori", "rorw", "rolw", "roriw", "clz", "ctz", "cpop", "clzw", "ctzw", "cpopw", "max", "maxu", "min", "minu", "sext.h", "sext.b", "zext.h", "zext.h", "orc.b", "rev8", "rev8", "pack", "packh", "brev8", "packw", "zip", "unzip", "clmul", "clmulh", "clmulr", "xperm8", "xperm4", "bclr", "bext", "binv", "bset", "bclri", "bexti", "binvi", "bseti", "bclri", "bexti", "binvi", "bseti", "aes32dsi", "aes32dsmi", "aes64ds", "aes64dsm", "aes64im", "aes64ks1i", "aes64ks2", "aes32esi", "aes32esmi", "aes64es", "aes64esm", "sha256sig0", "sha256sig1", "sha256sum0", "sha256sum1", "sha512sig0l", "sha512sig1l", "sha512sig0h", "sha512sig1h", "sha512sum0r", "sha512sum1r", "sha512sig0", "sha512sig1", "sha512sum0", "sha512sum1", "sm4ed", "sm4ks", "sm3p0", "sm3p1", "custom0.rd", "custom0.rd.rs1", "custom0.rd.rs1.rs2", "custom1.rd", "custom1.rd.rs1", "custom1.rd.rs1.rs2", "custom2.rd", "custom2.rd.rs1", "custom2.rd.rs1.rs2", "custom3.rd", "custom3.rd.rs1", "custom3.rd.rs1.rs2").contains(i) => y + case _ => n + // format: on + } + } + + // UOPs + + object UOPMEM extends UOP { + def width = 5 + + def xrd: BitPat = encode("b00000") + + def xwr: BitPat = encode("b00001") + + def pfr: BitPat = encode("b00010") + + def pfw: BitPat = encode("b00011") + + def xaSwap: BitPat = encode("b00100") + + def flushAll: BitPat = encode("b00101") + + def xlr: BitPat = encode("b00110") + + def xsc: BitPat = encode("b00111") + + def xaAdd: BitPat = encode("b01000") + + def xaXor: BitPat = encode("b01001") + + def xaOr: BitPat = encode("b01010") + + def xaAnd: BitPat = encode("b01011") + + def xaMin: BitPat = encode("b01100") + + def xaMax: BitPat = encode("b01101") + + def xaMinu: BitPat = encode("b01110") + + def xaMaxu: BitPat = encode("b01111") + + // TODO: unused + def flush: BitPat = encode("b10000") + + // TODO: unused + def pwr: BitPat = encode("b10001") + + // TODO: unused + def produce: BitPat = encode("b10010") + + // TODO: unused + def clean: BitPat = encode("b10011") + + def sfence: BitPat = encode("b10100") + + def hfencev: BitPat = encode("b10101") + + def hfenceg: BitPat = encode("b10110") + + def wok: BitPat = encode("b10111") + + def hlvx: BitPat = encode("b10000") + } + + object memCommand extends UOPDecodeField[RocketDecodePattern] { + override def name: String = "mem_cmd" + + override def genTable(op: RocketDecodePattern): BitPat = { + op.instruction.name match { + // format: off + 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("fsd", "fsh", "fsw", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "sb", "sd", "sh", "sw").contains(i) => UOPMEM.xwr + case i if Seq("amoswap.d", "amoswap.w").contains(i) => UOPMEM.xaSwap + 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("sc.d", "sc.w").contains(i) => UOPMEM.xsc + case i if Seq("amoadd.d", "amoadd.w").contains(i) => UOPMEM.xaAdd + case i if Seq("amoxor.d", "amoxor.w").contains(i) => UOPMEM.xaXor + case i if Seq("amoor.d", "amoor.w").contains(i) => UOPMEM.xaOr + case i if Seq("amoand.d", "amoand.w").contains(i) => UOPMEM.xaAnd + case i if Seq("amomin.d", "amomin.w").contains(i) => UOPMEM.xaMin + case i if Seq("amomax.d", "amomax.w").contains(i) => UOPMEM.xaMax + case i if Seq("amominu.d", "amominu.w").contains(i) => UOPMEM.xaMinu + case i if Seq("amomaxu.d", "amomaxu.w").contains(i) => UOPMEM.xaMaxu + case i if Seq("sfence.vma").contains(i) => UOPMEM.sfence + case i if Seq("hfence.vvma").contains(i) => UOPMEM.hfencev + case i if Seq("hfence.gvma").contains(i) => UOPMEM.hfenceg + case i if Seq("hlvx.hu", "hlvx.wu").contains(i) => UOPMEM.hlvx + case _ => UOPMEM.dontCare + // format: on + } + } + + override def uopType: UOPMEM.type = UOPMEM + } + + object UOPCSR extends UOP { + def width = 3 + + def n: BitPat = encode(0) + + def r: BitPat = encode(2) + + def i: BitPat = encode(4) + + def w: BitPat = encode(5) + + def s: BitPat = encode(6) + + def c: BitPat = encode(7) + } + + object csr extends UOPDecodeField[RocketDecodePattern] { + override def name: String = "csr" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + // TODO: default should be N? + case i if Seq("bne", "beq", "blt", "bltu", "bge", "bgeu", "jal", "jalr", "auipc", "lb", "lh", "lw", "lbu", "lhu", "sb", "sh", "sw", "lui", "addi", "slti", "sltiu", "andi", "ori", "xori", "add", "sub", "slt", "sltu", "and", "or", "xor", "sll", "srl", "sra", "fence", "fence.i", "czero.eqz", "czero.nez", "slli", "srli", "srai", "ld", "lwu", "sd", "slli", "srli", "srai", "addiw", "slliw", "srliw", "sraiw", "addw", "subw", "sllw", "srlw", "sraw", "mul", "mulh", "mulhu", "mulhsu", "div", "divu", "rem", "remu", "mulw", "divw", "divuw", "remw", "remuw", "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", "fcvt.s.h", "fcvt.h.s", "fsgnj.h", "fsgnjx.h", "fsgnjn.h", "fmin.h", "fmax.h", "fadd.h", "fsub.h", "fmul.h", "fmadd.h", "fmsub.h", "fnmadd.h", "fnmsub.h", "fclass.h", "fmv.x.h", "fcvt.w.h", "fcvt.wu.h", "feq.h", "flt.h", "fle.h", "fmv.h.x", "fcvt.h.w", "fcvt.h.wu", "flh", "fsh", "fdiv.h", "fsqrt.h", "fsgnj.s", "fsgnjx.s", "fsgnjn.s", "fmin.s", "fmax.s", "fadd.s", "fsub.s", "fmul.s", "fmadd.s", "fmsub.s", "fnmadd.s", "fnmsub.s", "fclass.s", "fmv.x.w", "fcvt.w.s", "fcvt.wu.s", "feq.s", "flt.s", "fle.s", "fmv.w.x", "fcvt.s.w", "fcvt.s.wu", "flw", "fsw", "fdiv.s", "fsqrt.s", "fcvt.s.d", "fcvt.d.s", "fsgnj.d", "fsgnjx.d", "fsgnjn.d", "fmin.d", "fmax.d", "fadd.d", "fsub.d", "fmul.d", "fmadd.d", "fmsub.d", "fnmadd.d", "fnmsub.d", "fclass.d", "fcvt.w.d", "fcvt.wu.d", "feq.d", "flt.d", "fle.d", "fcvt.d.w", "fcvt.d.wu", "fld", "fsd", "fdiv.d", "fsqrt.d", "fcvt.d.h", "fcvt.h.d", "fcvt.l.h", "fcvt.lu.h", "fcvt.h.l", "fcvt.h.lu", "fcvt.l.s", "fcvt.lu.s", "fcvt.s.l", "fcvt.s.lu", "fmv.x.d", "fcvt.l.d", "fcvt.lu.d", "fmv.d.x", "fcvt.d.l", "fcvt.d.lu", "sh1add", "sh2add", "sh3add", "add.uw", "slli.uw", "sh1add.uw", "sh2add.uw", "sh3add.uw", "andn", "orn", "xnor", "ror", "rol", "rori", "rori", "rorw", "rolw", "roriw", "clz", "ctz", "cpop", "clzw", "ctzw", "cpopw", "max", "maxu", "min", "minu", "sext.h", "sext.b", "zext.h", "zext.h", "orc.b", "rev8", "rev8", "pack", "packh", "brev8", "packw", "zip", "unzip", "clmul", "clmulh", "clmulr", "xperm8", "xperm4", "bclr", "bext", "binv", "bset", "bclri", "bexti", "binvi", "bseti", "bclri", "bexti", "binvi", "bseti", "aes32dsi", "aes32dsmi", "aes64ds", "aes64dsm", "aes64im", "aes64ks1i", "aes64ks2", "aes32esi", "aes32esmi", "aes64es", "aes64esm", "sha256sig0", "sha256sig1", "sha256sum0", "sha256sum1", "sha512sig0l", "sha512sig1l", "sha512sig0h", "sha512sig1h", "sha512sum0r", "sha512sum1r", "sha512sig0", "sha512sig1", "sha512sum0", "sha512sum1", "sm4ed", "sm4ks", "sm3p0", "sm3p1", "custom0", "custom0.rs1", "custom0.rs1.rs2", "custom0.rd", "custom0.rd.rs1", "custom0.rd.rs1.rs2", "custom1", "custom1.rs1", "custom1.rs1.rs2", "custom1.rd", "custom1.rd.rs1", "custom1.rd.rs1.rs2", "custom2", "custom2.rs1", "custom2.rs1.rs2", "custom2.rd", "custom2.rd.rs1", "custom2.rd.rs1.rs2", "custom3", "custom3.rs1", "custom3.rs1.rs2", "custom3.rd", "custom3.rd.rs1", "custom3.rd.rs1.rs2").contains(i) => UOPCSR.n + 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("csrrw", "csrrwi").contains(i) => UOPCSR.w + case i if Seq("csrrs", "csrrsi").contains(i) => UOPCSR.s + case i if Seq("csrrc", "csrrci").contains(i) => UOPCSR.c + case _ => UOPCSR.dontCare + // format: on + } + + override def uopType: UOPCSR.type = UOPCSR + } + + object UOPALU extends UOP { + def width = 4 + + def add: BitPat = encode(0) + + def sl: BitPat = encode(1) + + def seq: BitPat = encode(2) + + def sne: BitPat = encode(3) + + def xor: BitPat = encode(4) + + def sr: BitPat = encode(5) + + def or: BitPat = encode(6) + + def and: BitPat = encode(7) + + def czeqz: BitPat = encode(8) + + def cznez: BitPat = encode(9) + + def sub: BitPat = encode(10) + + def sra: BitPat = encode(11) + + def slt: BitPat = encode(12) + + def sge: BitPat = encode(13) + + def sltu: BitPat = encode(14) + + 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").contains(i) => UOPALU.add + case i if Seq("and", "andi").contains(i) => UOPALU.and + case i if Seq("or", "ori").contains(i) => UOPALU.or + case i if Seq("beq").contains(i) => UOPALU.seq + 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("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 + case i if Seq("sra", "srai", "srai", "sraiw", "sraw").contains(i) => UOPALU.sra + case i if Seq("sub", "subw").contains(i) => UOPALU.sub + case i if Seq("xor", "xori").contains(i) => UOPALU.xor + + // rv_m + case i if Seq("mul", "mulw").contains(i) => UOPALU.mul + case i if Seq("mulh").contains(i) => UOPALU.mulh + case i if Seq("mulhu").contains(i) => UOPALU.mulhu + case i if Seq("mulhsu").contains(i) => UOPALU.mulhsu + case i if Seq("div", "divw").contains(i) => UOPALU.div + case i if Seq("divu", "divuw").contains(i) => UOPALU.divu + case i if Seq("rem", "remw").contains(i) => UOPALU.rem + case i if Seq("remu", "remuw").contains(i) => UOPALU.remu + + case i if Seq("czero.eqz").contains(i) => UOPALU.czeqz + case i if Seq("czero.nez").contains(i) => UOPALU.cznez + case _ => UOPALU.dontCare + // format: on + } + + override def uopType: UOPALU.type = UOPALU + } + + object UOPABLU extends UOP { + def width = 39 + + def add: BitPat = encode("b000000000000000000001000000000000000001") + + def sl: BitPat = encode("b000000000110000000001000000000000000010") + + def seq: BitPat = encode("b001000000000000000001000000000001000000") + + def sne: BitPat = encode("b001100000000000000001000000000001000000") + + def xor: BitPat = encode("b000000000000000000001000000000000001000") + + def sr: BitPat = encode("b000000000000000000001000000000000000010") + + def or: BitPat = encode("b000000000000000000001000000000000010000") + + def and: BitPat = encode("b000000000000000000001000000000000000100") + + def czeqz: BitPat = encode(8) + + def cznez: BitPat = encode(9) + + def sub: BitPat = encode("b000000000000000110001000000000000000001") + + def sra: BitPat = encode("b000000000000100000001000000000000000010") + + def slt: BitPat = encode("b000000000000000110001000000000001000000") + + def sge: BitPat = encode("b000100000000000110001000000000001000000") + + def sltu: BitPat = encode("b000010000000000110001000000000001000000") + + def sgeu: BitPat = encode("b000110000000000110001000000000001000000") + + def adduw: BitPat = encode("b000000000000010000001000000000000000001") + + def slliuw: BitPat = encode("b000000000110010000001000000000000000010") + + def sh1add: BitPat = encode("b000000000000000000010000000000000000001") + + def sh1adduw: BitPat = encode("b000000000000010000010000000000000000001") + + def sh2add: BitPat = encode("b000000000000000000100000000000000000001") + + def sh2adduw: BitPat = encode("b000000000000010000100000000000000000001") + + def sh3add: BitPat = encode("b000000000000000001000000000000000000001") + + def sh3adduw: BitPat = encode("b000000000000010001000000000000000000001") + + def ror: BitPat = encode("b000000000001000000001000000000000000010") + + def rol: BitPat = encode("b000000000111000000001000000000000000010") + + def andn: BitPat = encode("b000000000000000100001000000000000000100") + + def orn: BitPat = encode("b000000000000000100001000000000000010000") + + def xnor: BitPat = encode("b000000000000000100001000000000000001000") + + def rev8: BitPat = encode("b000000000000000000001000001000000000000") + + def orcb: BitPat = encode("b100000000000000000001000010000000000000") + + def sextb: BitPat = encode("b000000000000000000001000000100000000000") + + def sexth: BitPat = encode("b010000000000000000001000000010000000000") + + def zexth: BitPat = encode("b000000000000000000001000000010000000000") + + def max: BitPat = encode("b000000000000000110001000000000010000000") + + def maxu: BitPat = encode("b000010000000000110001000000000010000000") + + def min: BitPat = encode("b000100000000000110001000000000010000000") + + def minu: BitPat = encode("b000110000000000110001000000000010000000") + + def cpop: BitPat = encode("b000000000000000000001000000000100000000") + + def clz: BitPat = encode("b000001101111000000001000000001000000000") + + def ctz: BitPat = encode("b000001101000000000001000000001000000000") + + def bclr: BitPat = encode("b000001110100001000001000000000000000100") + + def bext: BitPat = encode("b000001000100001000001000000000000100000") + + def binv: BitPat = encode("b000001000100001000001000000000000001000") + + def bset: BitPat = encode("b000001000100001000001000000000000010000") + + def brev8: BitPat = encode("b000000000000000000001000010000000000000") + + def pack: BitPat = encode("b000000000000000000001000100000000000000") + + def packh: BitPat = encode("b000000000000000000001001000000000000000") + + def zip: BitPat = encode("b000000000000000000001010000000000000000") + + def unzip: BitPat = encode("b000000000000000000001100000000000000000") + + def clmul: BitPat = encode("b00001") + + def clmulr: BitPat = encode("b00010") + + def clmulh: BitPat = encode("b00100") + + def xperm8: BitPat = encode("b01000") + + def xperm4: BitPat = encode("b10000") + + def aesds: BitPat = encode("b00100001000000001") + + def aesdsm: BitPat = encode("b00000010000000001") + + def aeses: BitPat = encode("b00110001000000001") + + def aesesm: BitPat = encode("b00010010000000001") + + def aesim: BitPat = encode("b10000010000000001") + + def aesks1: BitPat = encode("b01010100000000001") + + def aesks2: BitPat = encode("b00001000000000001") + + def sha256sig0: BitPat = encode("b00000001000000010") + + def sha256sig1: BitPat = encode("b00000001000000100") + + def sha256sum0: BitPat = encode("b00000001000001000") + + def sha256sum1: BitPat = encode("b00000001000010000") + + def sha512sig0: BitPat = encode("b00000001000100000") + + def sha512sig1: BitPat = encode("b00000001001000000") + + def sha512sum0: BitPat = encode("b00000001010000000") + + def sha512sum1: BitPat = encode("b00000001100000000") + + def sm4ed: BitPat = encode("b0101") + + def sm4ks: BitPat = encode("b0001") + + def sm3p0: BitPat = encode("b1010") + + def sm3p1: BitPat = encode("b0010") + + 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 abluFn 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").contains(i) => UOPABLU.add + case i if Seq("add.uw").contains(i) => UOPABLU.adduw + case i if Seq("aes32dsi", "aes64ds").contains(i) => UOPABLU.aesds + case i if Seq("aes32dsmi", "aes64dsm").contains(i) => UOPABLU.aesdsm + case i if Seq("aes32esi", "aes64es").contains(i) => UOPABLU.aeses + case i if Seq("aes32esmi", "aes64esm").contains(i) => UOPABLU.aesesm + case i if Seq("aes64im").contains(i) => UOPABLU.aesim + case i if Seq("aes64ks1i", "aes64ks2").contains(i) => UOPABLU.aesks1 + case i if Seq("and", "andi").contains(i) => UOPABLU.and + case i if Seq("andn").contains(i) => UOPABLU.andn + case i if Seq("bclr", "bclri", "bclri").contains(i) => UOPABLU.bclr + case i if Seq("bext", "bexti", "bexti").contains(i) => UOPABLU.bext + case i if Seq("binv", "binvi", "binvi").contains(i) => UOPABLU.binv + case i if Seq("brev8").contains(i) => UOPABLU.brev8 + case i if Seq("bset", "bseti", "bseti").contains(i) => UOPABLU.bset + case i if Seq("clmul").contains(i) => UOPABLU.clmul + case i if Seq("clmulh").contains(i) => UOPABLU.clmulh + case i if Seq("clmulr").contains(i) => UOPABLU.clmulr + case i if Seq("clz", "clzw").contains(i) => UOPABLU.clz + case i if Seq("cpop", "cpopw").contains(i) => UOPABLU.cpop + case i if Seq("ctz", "ctzw").contains(i) => UOPABLU.ctz + case i if Seq("czero.eqz", "czero.nez").contains(i) => UOPABLU.czeqz + case i if Seq("div", "divw").contains(i) => UOPABLU.div + case i if Seq("divu", "divuw").contains(i) => UOPABLU.divu + case i if Seq("max").contains(i) => UOPABLU.max + case i if Seq("maxu").contains(i) => UOPABLU.maxu + case i if Seq("min").contains(i) => UOPABLU.min + case i if Seq("minu").contains(i) => UOPABLU.minu + case i if Seq("mul", "mulw").contains(i) => UOPABLU.mul + case i if Seq("mulh").contains(i) => UOPABLU.mulh + case i if Seq("mulhsu").contains(i) => UOPABLU.mulhsu + case i if Seq("mulhu").contains(i) => UOPABLU.mulhu + case i if Seq("or", "ori").contains(i) => UOPABLU.or + case i if Seq("orc.b").contains(i) => UOPABLU.orcb + case i if Seq("orn").contains(i) => UOPABLU.orn + case i if Seq("pack", "packw").contains(i) => UOPABLU.pack + case i if Seq("packh").contains(i) => UOPABLU.packh + case i if Seq("rem", "remw").contains(i) => UOPABLU.rem + case i if Seq("remu", "remuw").contains(i) => UOPABLU.remu + case i if Seq("rev8", "rev8").contains(i) => UOPABLU.rev8 + case i if Seq("rol", "rolw").contains(i) => UOPABLU.rol + case i if Seq("ror", "rori", "rori", "roriw", "rorw").contains(i) => UOPABLU.ror + case i if Seq("beq").contains(i) => UOPABLU.seq + case i if Seq("sext.b").contains(i) => UOPABLU.sextb + case i if Seq("sext.h").contains(i) => UOPABLU.sexth + case i if Seq("bge").contains(i) => UOPABLU.sge + case i if Seq("bgeu").contains(i) => UOPABLU.sgeu + case i if Seq("sh1add").contains(i) => UOPABLU.sh1add + case i if Seq("sh1add.uw").contains(i) => UOPABLU.sh1adduw + case i if Seq("sh2add").contains(i) => UOPABLU.sh2add + case i if Seq("sh2add.uw").contains(i) => UOPABLU.sh2adduw + case i if Seq("sh3add").contains(i) => UOPABLU.sh3add + case i if Seq("sh3add.uw").contains(i) => UOPABLU.sh3adduw + case i if Seq("sha256sig0").contains(i) => UOPABLU.sha256sig0 + case i if Seq("sha256sig1").contains(i) => UOPABLU.sha256sig1 + case i if Seq("sha256sum0").contains(i) => UOPABLU.sha256sum0 + case i if Seq("sha256sum1").contains(i) => UOPABLU.sha256sum1 + case i if Seq("sha512sig0", "sha512sig0h", "sha512sig0l").contains(i) => UOPABLU.sha512sig0 + case i if Seq("sha512sig1", "sha512sig1h", "sha512sig1l").contains(i) => UOPABLU.sha512sig1 + case i if Seq("sha512sum0", "sha512sum0r").contains(i) => UOPABLU.sha512sum0 + case i if Seq("sha512sum1", "sha512sum1r").contains(i) => UOPABLU.sha512sum1 + case i if Seq("sll", "slli", "slli", "slliw", "sllw").contains(i) => UOPABLU.sl + case i if Seq("slli.uw").contains(i) => UOPABLU.slliuw + case i if Seq("blt", "slt", "slti").contains(i) => UOPABLU.slt + case i if Seq("bltu", "sltiu", "sltu").contains(i) => UOPABLU.sltu + case i if Seq("sm3p0").contains(i) => UOPABLU.sm3p0 + case i if Seq("sm3p1").contains(i) => UOPABLU.sm3p1 + case i if Seq("sm4ed").contains(i) => UOPABLU.sm4ed + case i if Seq("sm4ks").contains(i) => UOPABLU.sm4ks + case i if Seq("bne").contains(i) => UOPABLU.sne + case i if Seq("srl", "srli", "srli", "srliw", "srlw").contains(i) => UOPABLU.sr + case i if Seq("sra", "srai", "srai", "sraiw", "sraw").contains(i) => UOPABLU.sra + case i if Seq("sub", "subw").contains(i) => UOPABLU.sub + case i if Seq("unzip").contains(i) => UOPABLU.unzip + case i if Seq("xnor").contains(i) => UOPABLU.xnor + case i if Seq("xor", "xori").contains(i) => UOPABLU.xor + case i if Seq("xperm4").contains(i) => UOPABLU.xperm4 + case i if Seq("xperm8").contains(i) => UOPABLU.xperm8 + case i if Seq("zext.h").contains(i) => UOPABLU.zexth + case i if Seq("zip").contains(i) => UOPABLU.zip + case _ => UOPABLU.dontCare + // format: on + } + + override def uopType: UOPALU.type = UOPALU + } + + object UOPIMM extends UOP { + def width = 3 + + def s: BitPat = encode(0) + + def sb: BitPat = encode(1) + + def u: BitPat = encode(2) + + def uj: BitPat = encode(3) + + def i: BitPat = encode(4) + + def z: BitPat = encode(5) + } + + object selImm extends UOPDecodeField[RocketDecodePattern] { + override def name: String = "sel_imm" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("addi", "addiw", "aes64ks1i", "andi", "bclri", "bclri", "bexti", "bexti", "binvi", "binvi", "bseti", "bseti", "fld", "flh", "flw", "hsv.b", "hsv.d", "hsv.h", "hsv.w", "jalr", "lb", "lbu", "ld", "lh", "lhu", "lw", "lwu", "ori", "rori", "rori", "roriw", "slli", "slli", "slli.uw", "slliw", "slti", "sltiu", "srai", "srai", "sraiw", "srli", "srli", "srliw", "xori").contains(i) => UOPIMM.i + case i if Seq("fsd", "fsh", "fsw", "sb", "sd", "sh", "sw").contains(i) => UOPIMM.s + case i if Seq("beq", "bge", "bgeu", "blt", "bltu", "bne").contains(i) => UOPIMM.sb + case i if Seq("auipc", "lui").contains(i) => UOPIMM.u + case i if Seq("jal").contains(i) => UOPIMM.uj + case i if Seq("csrrci", "csrrsi", "csrrwi").contains(i) => UOPIMM.z + case _ => UOPIMM.dontCare + // format: on + } + + override def uopType: UOPIMM.type = UOPIMM + } + + object UOPA1 extends UOP { + def width = 2 + + def zero: BitPat = encode(0) + + def rs1: BitPat = encode(1) + + def pc: BitPat = encode(2) + } + + object selAlu1 extends UOPDecodeField[RocketDecodePattern] { + override def name: String = "sel_alu1" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + 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.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 _ => UOPA1.dontCare + } + + override def uopType: UOPA1.type = UOPA1 + } + + 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) + } + + object selAlu2 extends UOPDecodeField[RocketDecodePattern] { + override def name: String = "sel_alu2" + + override def genTable(op: RocketDecodePattern): BitPat = op.instruction.name match { + // format: off + case i if Seq("addi", "addiw", "aes64ks1i", "andi", "auipc", "bclri", "bclri", "bexti", "bexti", "binvi", "binvi", "bseti", "bseti", "csrrci", "csrrsi", "csrrwi", "fld", "flh", "flw", "fsd", "fsh", "fsw", "jalr", "lb", "lbu", "ld", "lh", "lhu", "lui", "lw", "lwu", "ori", "rori", "rori", "roriw", "sb", "sd", "sh", "slli", "slli.uw", "slliw", "slti", "sltiu", "srai", "srai", "sraiw", "srli", "srli", "srliw", "sw", "xori").contains(i) => UOPA2.imm + case i if Seq("add", "add.uw", "addw", "aes32dsi", "aes32dsmi", "aes32esi", "aes32esmi", "aes64ds", "aes64dsm", "aes64es", "aes64esm", "aes64im", "aes64ks2", "and", "andn", "bclr", "beq", "bext", "bge", "bgeu", "binv", "blt", "bltu", "bne", "bset", "clmul", "clmulh", "clmulr", "czero.eqz", "czero.nez", "div", "divu", "divuw", "divw", "max", "maxu", "min", "minu", "mul", "mulh", "mulhsu", "mulhu", "mulw", "or", "orn", "pack", "packh", "packw", "rem", "remu", "remuw", "remw", "rol", "rolw", "ror", "rorw", "sh1add", "sh1add.uw", "sh2add", "sh2add.uw", "sh3add", "sh3add.uw", "sha512sig0h", "sha512sig0l", "sha512sig1h", "sha512sig1l", "sha512sum0r", "sha512sum1r", "sll", "sllw", "slt", "sltu", "sm4ed", "sm4ks", "sra", "sraw", "srl", "srlw", "sub", "subw", "xnor", "xor", "xperm4", "xperm8").contains(i) => UOPA2.rs2 + case i if Seq("jal").contains(i) => UOPA2.size + case i if Seq("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", "cdiscard.d.l1", "cflush.d.l1", "csrrc", "csrrs", "csrrw", "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", "lr.d", "lr.w", "sc.d", "sc.w", "sfence.vma").contains(i) => UOPA2.zero + case i => UOPA2.dontCare + } + + override def uopType: UOPA2.type = UOPA2 + } + + // Custom extensions + + /** Rocket Custom Coprocessor, add FU at commit stage */ + object rocc extends BoolDecodeField[RocketDecodePattern] { + override def name: String = "rocc" + + override def genTable(op: RocketDecodePattern): BitPat = if (op.isRoCC) y else n + } +} diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 34f16d273c3..bac5c3c768b 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,7 @@ 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 ) extends CoreParams { val lgPauseCycles = 5 val haveFSDirty = false @@ -132,7 +133,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 +141,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 && !Option.when(usingFPU)(id_ctrl(decoder.fp)).getOrElse(false.B)), + ("store", () => id_ctrl(decoder.mem) && id_ctrl(decoder.memCommand) === M_XWR && !Option.when(usingFPU)(id_ctrl(decoder.fp)).getOrElse(false.B)), + ("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) || Option.when(usingFPU)(id_ctrl(decoder.fp)).getOrElse(false.B) || Option.when(usingMulDiv && pipelinedMul)(id_ctrl(decoder.mul)).getOrElse(false.B) || Option.when(usingMulDiv)(id_ctrl(decoder.div)).getOrElse(false.B) || 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.fp) && io.fpu.dec.ldst && io.fpu.dec.wen), + ("fp store", () => id_ctrl(decoder.fp) && io.fpu.dec.ldst && !io.fpu.dec.wen), + ("fp add", () => id_ctrl(decoder.fp) && io.fpu.dec.fma && io.fpu.dec.swap23), + ("fp mul", () => id_ctrl(decoder.fp) && io.fpu.dec.fma && !io.fpu.dec.swap23 && !io.fpu.dec.ren3), + ("fp mul-add", () => id_ctrl(decoder.fp) && io.fpu.dec.fma && io.fpu.dec.ren3), + ("fp div/sqrt", () => id_ctrl(decoder.fp) && (io.fpu.dec.div || io.fpu.dec.sqrt)), + ("fp other", () => id_ctrl(decoder.fp) && !(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 && (Option.when(pipelinedMul)(ex_ctrl(decoder.mul)).getOrElse(false.B) || ex_ctrl(decoder.div)) || id_mem_hazard && (Option.when(pipelinedMul)(mem_ctrl(decoder.mul)).getOrElse(false.B) || 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.fp) || id_mem_hazard && mem_ctrl(decoder.fp) || id_wb_hazard && wb_ctrl(decoder.fp) || id_ctrl(decoder.fp) && 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 +183,128 @@ 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( + // TODO: configurable + (org.chipsalliance.rvdecoderdb.fromFile.instructions(os.pwd / "dependencies" / "riscv-opcodes") ++ + // TODO: select rocc instructions via configuration. + org.chipsalliance.rocketcore.decoder.CustomInstructions.roccSet ++ + org.chipsalliance.rocketcore.decoder.CustomInstructions.rocketSet) + .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") => true + // 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 + // Debug + case s if s.contains("rv_sdext") => usingDebug + + // 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 + // custom + case s if s.contains("rv_rocket") => i.name match { + case "c.flush.d.l1" => coreParams.haveCFlush + case "c.discard.d.l1" => coreParams.haveCFlush + case "cease" => rocketParams.haveCease + } + case s if s.contains("rv_rocc") => usingRoCC + case _ => false + } + } + .filter { + // special case for rv32 pseudo from rv64 + case i if i.pseudoFrom.isDefined && Seq("slli", "srli", "srai").contains(i.name) => true + case i if i.pseudoFrom.isDefined => false + case _ => true + } + .toSeq + .distinct, + pipelinedMul, + tile.dcache.flushOnFenceI + ) + val decoder = new org.chipsalliance.rocketcore.decoder.InstructionDecoder(decoderParameter) + val decoderModule = Module(new RawModule { + override def desiredName: String = "RocketDecoder" + val instruction = IO(Input(UInt(32.W))) + val output = IO(Output(decoder.table.bundle)) + output := decoder.table.decode(instruction) + }) + + val id_ctrl: DecodeBundle = WireDefault(decoderModule.output) + 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 +377,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) + decoderModule.instruction := id_inst(0) val lgNXRegs = if (coreParams.useRVE) 4 else 5 val regAddrMask = (1 << lgNXRegs) - 1 @@ -298,7 +389,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 +397,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) || + Option.when(usingMulDiv)(Option.when(pipelinedMul)(id_ctrl(decoder.mul)).getOrElse(false.B) || id_ctrl(decoder.div) && !csr.io.status.isa('m'-'a')).getOrElse(false.B) || + id_ctrl(decoder.amo) && !csr.io.status.isa('a'-'a') || + Option.when(usingFPU)(id_ctrl(decoder.fp) && (csr.io.decode(0).fp_illegal || io.fpu.illegal_rm)).getOrElse(false.B) || + Option.when(usingFPU)(id_ctrl(decoder.dp) && !csr.io.status.isa('d'-'a')).getOrElse(false.B) || 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) || + Option.when(usingRoCC)(id_ctrl(decoder.rocc) && csr.io.decode(0).rocc_illegal).getOrElse(false.B) || 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 +427,15 @@ 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))) + val id_rocc_busy = Option.when(usingRoCC)( + io.rocc.busy || ex_reg_valid && ex_ctrl(decoder.rocc) || + mem_reg_valid && mem_ctrl(decoder.rocc) || wb_reg_valid && wb_ctrl(decoder.rocc) + ) + val id_do_fence = WireDefault(id_rocc_busy.getOrElse(false.B) && 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) || Option.when(usingRoCC)(id_ctrl(decoder.rocc)).getOrElse(false.B)))) val bpu = Module(new BreakpointUnit(nBreakpoints)) bpu.io.status := csr.io.status @@ -387,9 +481,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 +493,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 +506,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 +522,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 +532,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 @@ -446,16 +540,17 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) } // multiplier and divider + // TODO: waive them if !usingMulDiv 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 && Option.when(usingMulDiv)(ex_ctrl(decoder.div)).getOrElse(false.B) + 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 +563,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 +625,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 || + Option.when(usingMulDiv)(ex_ctrl(decoder.div)).getOrElse(false.B) && !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 +644,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 +671,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 @@ -591,22 +686,27 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) mem_reg_hls_or_dv := io.dmem.req.bits.dv 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) - -> alu.io.out, - )) + mem_reg_wdata := { + if (usingABLU) Mux1H(Seq( + 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, + )) else 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) || Option.when(usingRoCC)(ex_ctrl(decoder.rocc)).getOrElse(false.B) || ex_sfence)) { + val size = if(usingRoCC) { + Mux(ex_ctrl(decoder.rocc), log2Ceil(xLen/8).U, ex_reg_mem_size) + } else { + 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,12 +729,12 @@ 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 replay_mem = dcache_kill_mem || mem_reg_replay || fpu_kill_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 = Option.when(usingFPU)(mem_reg_valid && mem_ctrl(decoder.fp) && io.fpu.nack_mem) + val replay_mem = dcache_kill_mem || mem_reg_replay || fpu_kill_mem.getOrElse(false.B) 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) - val ctrl_killm = killm_common || mem_xcpt || fpu_kill_mem + val ctrl_killm = killm_common || mem_xcpt || fpu_kill_mem.getOrElse(false.B) // writeback stage wb_reg_valid := !ctrl_killm @@ -644,8 +744,11 @@ 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 := { + if (usingFPU) Mux(!mem_reg_xcpt && mem_ctrl(decoder.fp) && mem_ctrl(decoder.wxd), io.fpu.toint_data, mem_int_wdata) + else mem_int_wdata + } + when (Option.when(usingRoCC)(mem_ctrl(decoder.rocc)).getOrElse(false.B) || mem_reg_sfence) { wb_reg_rs2 := mem_reg_rs2 } wb_reg_cause := mem_cause @@ -653,8 +756,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 +765,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,12 +790,12 @@ 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 = Option.when(usingMulDiv)(wb_ctrl(decoder.div)).getOrElse(false.B) || wb_dcache_miss || Option.when(usingRoCC)(wb_ctrl(decoder.rocc)).getOrElse(false.B) 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 = Option.when(usingRoCC)(wb_reg_valid && wb_ctrl(decoder.rocc) && !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 + val replay_wb = replay_wb_common || replay_wb_rocc.getOrElse(false.B) || replay_wb_csr take_pc_wb := replay_wb || wb_xcpt || csr.io.eret || wb_reg_flush_pipe // writeback arbitration @@ -731,13 +834,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(Option.when(usingMulDiv && pipelinedMul)(wb_ctrl(decoder.mul)).getOrElse(false.B), mul.map(_.io.resp.bits.data).getOrElse(wb_reg_wdata), wb_reg_wdata)))) when (rf_wen) { rf.write(rf_waddr, rf_wdata) } @@ -782,7 +885,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 +895,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)) + Option.when(usingFPU)(wb_ctrl(decoder.wfd) || (wb_ctrl(decoder.wxd) && wb_waddr =/= 0.U)).getOrElse(false.B) && !csr.io.trace(0).exception, + wb_ctrl(decoder.wxd) && wb_wen && !wb_set_sboard, + wb_waddr + Mux(Option.when(usingFPU)(wb_ctrl(decoder.wfd)).getOrElse(false.B), 32.U, 0.U)) io.trace.insns(0) := DebugROB.popTrace(clock, reset, io.hartid) @@ -811,9 +914,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 +933,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 id_ex_hazard = ex_reg_valid && (data_hazard_ex && ex_cannot_bypass || fp_data_hazard_ex) + val ex_cannot_bypass = ex_ctrl(decoder.csr) =/= CSR.N || ex_ctrl(decoder.isJalr) || ex_ctrl(decoder.mem) || Option.when(usingMulDiv && pipelinedMul)(ex_ctrl(decoder.mul)).getOrElse(false.B) || Option.when(usingMulDiv)(ex_ctrl(decoder.div)).getOrElse(false.B) || Option.when(usingFPU)(ex_ctrl(decoder.fp)).getOrElse(false.B) || Option.when(usingRoCC)(ex_ctrl(decoder.rocc)).getOrElse(false.B) + val data_hazard_ex = ex_ctrl(decoder.wxd) && checkHazards(hazard_targets, _ === ex_waddr) + val fp_data_hazard_ex = Option.when(usingFPU)(id_ctrl(decoder.fp) && 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.getOrElse(false.B)) // 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 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 + val mem_cannot_bypass = mem_ctrl(decoder.csr) =/= CSR.N || mem_ctrl(decoder.mem) && mem_mem_cmd_bh || Option.when(usingMulDiv && pipelinedMul)(mem_ctrl(decoder.mul)).getOrElse(false.B) || Option.when(usingMulDiv)(mem_ctrl(decoder.div)).getOrElse(false.B) || Option.when(usingFPU)(mem_ctrl(decoder.fp)).getOrElse(false.B) || Option.when(usingRoCC)(mem_ctrl(decoder.rocc)).getOrElse(false.B) + val data_hazard_mem = mem_ctrl(decoder.wxd) && checkHazards(hazard_targets, _ === mem_waddr) + val fp_data_hazard_mem = Option.when(usingFPU)(id_ctrl(decoder.fp) && 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.getOrElse(false.B)) + 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 = Option.when(usingFPU)(id_ctrl(decoder.fp) && wb_ctrl(decoder.wfd) && checkHazards(fp_hazard_targets, _ === wb_waddr)).getOrElse(false.B) 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) @@ -865,17 +968,17 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) blocked := !io.dmem.req.ready && io.dmem.clock_enabled && !io.dmem.perf.grant && (blocked || io.dmem.req.valid || io.dmem.s2_nack) blocked && !io.dmem.perf.grant } - val rocc_blocked = Reg(Bool()) - rocc_blocked := !wb_xcpt && !io.rocc.cmd.ready && (io.rocc.cmd.valid || rocc_blocked) + val rocc_blocked = Option.when(usingRoCC)(Reg(Bool())) + rocc_blocked.foreach(_ := !wb_xcpt && !io.rocc.cmd.ready && (io.rocc.cmd.valid || rocc_blocked.get)) val ctrl_stalld = 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 + Option.when(usingFPU)(id_ctrl(decoder.fp) && id_stall_fpu).getOrElse(false.B) || + id_ctrl(decoder.mem) && dcache_blocked || // reduce activity during D$ misses + Option.when(usingRoCC)(id_ctrl(decoder.rocc) && rocc_blocked.get).getOrElse(false.B) || // reduce activity while RoCC is busy + Option.when(usingMulDiv)(id_ctrl(decoder.div) && (!(div.io.req.ready || (div.io.resp.valid && !wb_wxd)) || div.io.req.valid)).getOrElse(false.B) || // reduce odds of replay !clock_en || id_do_fence || csr.io.csr_stall || @@ -889,7 +992,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 +1012,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,28 +1026,41 @@ 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.killx := ctrl_killx - io.fpu.killm := killm_common - io.fpu.inst := id_inst(0) - io.fpu.fromint_data := ex_rs(0) - io.fpu.dmem_resp_val := dmem_resp_valid && dmem_resp_fpu - io.fpu.dmem_resp_data := (if (minFLen == 32) io.dmem.resp.bits.data_word_bypass else io.dmem.resp.bits.data) - io.fpu.dmem_resp_type := io.dmem.resp.bits.size - 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) + if(usingFPU) { + io.fpu.valid := !ctrl_killd && id_ctrl(decoder.fp) + io.fpu.killx := ctrl_killx + io.fpu.killm := killm_common + io.fpu.inst := id_inst(0) + io.fpu.fromint_data := ex_rs(0) + io.fpu.dmem_resp_val := dmem_resp_valid && dmem_resp_fpu + io.fpu.dmem_resp_data := (if (minFLen == 32) io.dmem.resp.bits.data_word_bypass else io.dmem.resp.bits.data) + io.fpu.dmem_resp_type := io.dmem.resp.bits.size + io.fpu.dmem_resp_tag := dmem_resp_waddr + io.fpu.keep_clock_enabled := io.ptw.customCSRs.disableCoreClockGate + } else { + io.fpu.valid := DontCare + io.fpu.killx := DontCare + io.fpu.killm := DontCare + io.fpu.inst := DontCare + io.fpu.fromint_data := DontCare + io.fpu.dmem_resp_val := DontCare + io.fpu.dmem_resp_data := DontCare + io.fpu.dmem_resp_type := DontCare + io.fpu.dmem_resp_tag := DontCare + io.fpu.keep_clock_enabled := DontCare + } + + io.dmem.req.valid := ex_reg_valid && ex_ctrl(decoder.mem) + val ex_dcache_tag = Cat(ex_waddr, Option.when(usingFPU)(ex_ctrl(decoder.fp)).getOrElse(false.B)) 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,20 +1073,29 @@ 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 := Option.when(usingFPU)(Mux(mem_ctrl(decoder.fp), Fill((xLen max fLen) / fLen, io.fpu.store_data), mem_reg_rs2)).getOrElse(mem_reg_rs2) io.dmem.s1_data.mask := DontCare - io.dmem.s1_kill := killm_common || mem_ldst_xcpt || fpu_kill_mem + io.dmem.s1_kill := killm_common || mem_ldst_xcpt || fpu_kill_mem.getOrElse(false.B) 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.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()) - io.rocc.cmd.bits.rs1 := wb_reg_wdata - io.rocc.cmd.bits.rs2 := wb_reg_rs2 + if (usingRoCC) { + io.rocc.cmd.valid := wb_reg_valid && wb_ctrl(decoder.rocc) && !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()) + io.rocc.cmd.bits.rs1 := wb_reg_wdata + io.rocc.cmd.bits.rs2 := wb_reg_rs2 + } else { + io.rocc.cmd.valid := DontCare + io.rocc.exception := DontCare + io.rocc.cmd.bits.status := DontCare + io.rocc.cmd.bits.inst := DontCare + io.rocc.cmd.bits.rs1 := DontCare + io.rocc.cmd.bits.rs2 := DontCare + } // gate the clock val unpause = csr.io.time(rocketParams.lgPauseCycles-1, 0) === 0.U || csr.io.inhibit_cycle || io.dmem.perf.release || take_pc @@ -1018,8 +1143,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 = Option.when(usingFPU)(wb_ctrl(decoder.wfd)).getOrElse(false.B) + val wxd = wb_ctrl(decoder.wxd) val has_data = wb_wen && !wb_set_sboard when (t.valid && !t.exception) { @@ -1046,13 +1171,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) || Option.when(usingFPU)(wb_ctrl(decoder.wfd)).getOrElse(false.B), 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) || Option.when(usingFPU)(wb_ctrl(decoder.rfs1)).getOrElse(false.B), coreMonitorBundle.rd0src, 0.U), + Mux(wb_ctrl(decoder.rxs1) || Option.when(usingFPU)(wb_ctrl(decoder.rfs1)).getOrElse(false.B), coreMonitorBundle.rd0val, 0.U), + Mux(wb_ctrl(decoder.rxs2) || Option.when(usingFPU)(wb_ctrl(decoder.rfs2)).getOrElse(false.B), coreMonitorBundle.rd1src, 0.U), + Mux(wb_ctrl(decoder.rxs2) || Option.when(usingFPU)(wb_ctrl(decoder.rfs2)).getOrElse(false.B), coreMonitorBundle.rd1val, 0.U), coreMonitorBundle.inst, coreMonitorBundle.inst) } }