Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zcb: Code Size Reduction Extension #3362

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/main/scala/rocket/Instructions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,26 @@ object Instructions {
def C_J = BitPat("b????????????????101???????????01")
def C_JALR = BitPat("b????????????????1001?????0000010")
def C_JR = BitPat("b????????????????1000?????0000010")
def C_LBU = BitPat("b????????????????100000????????00")
jerryz123 marked this conversation as resolved.
Show resolved Hide resolved
def C_LD = BitPat("b????????????????011???????????00")
def C_LDSP = BitPat("b????????????????011???????????10")
def C_LH = BitPat("b????????????????100001???1????00")
def C_LHU = BitPat("b????????????????100001???0????00")
def C_LI = BitPat("b????????????????010???????????01")
def C_LUI = BitPat("b????????????????011???????????01")
def C_LW = BitPat("b????????????????010???????????00")
def C_LWSP = BitPat("b????????????????010???????????10")
def C_MUL = BitPat("b????????????????100111???10???01")
def C_MV = BitPat("b????????????????1000??????????10")
def C_NOP = BitPat("b????????????????000?00000?????01")
def C_NOT = BitPat("b????????????????100111???1110101")
def C_OR = BitPat("b????????????????100011???10???01")
def C_SB = BitPat("b????????????????100010????????00")
def C_SD = BitPat("b????????????????111???????????00")
def C_SDSP = BitPat("b????????????????111???????????10")
def C_SEXT_B = BitPat("b????????????????100111???1100101")
def C_SEXT_H = BitPat("b????????????????100111???1101101")
def C_SH = BitPat("b????????????????100011???0????00")
def C_SLLI = BitPat("b????????????????000???????????10")
def C_SRAI = BitPat("b????????????????100?01????????01")
def C_SRLI = BitPat("b????????????????100?00????????01")
Expand All @@ -95,6 +104,9 @@ object Instructions {
def C_SW = BitPat("b????????????????110???????????00")
def C_SWSP = BitPat("b????????????????110???????????10")
def C_XOR = BitPat("b????????????????100011???01???01")
def C_ZEXT_B = BitPat("b????????????????100111???1100001")
def C_ZEXT_H = BitPat("b????????????????100111???1101001")
def C_ZEXT_W = BitPat("b????????????????100111???1110001")
def CBO_CLEAN = BitPat("b000000000001?????010000000001111")
def CBO_FLUSH = BitPat("b000000000010?????010000000001111")
def CBO_INVAL = BitPat("b000000000000?????010000000001111")
Expand Down Expand Up @@ -1729,4 +1741,4 @@ object CSRs {
res += mhpmcounter31h
res.toArray
}
}
}
74 changes: 64 additions & 10 deletions src/main/scala/rocket/RVC.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ class ExpandedInstruction extends Bundle {
val rs3 = UInt(5.W)
}

class RVCDecoder(x: UInt, xLen: Int, useAddiForMv: Boolean = false) {
/* Parameters for RVCDecoder
- Zcb extension contains the compressed I-type (c.lbu, lhu, lh, sb, sh) , M-type (c.mul)
and Bit Manip instructions.
- **usingCompressedSuiteB** parameter is used to enable/disable "Zcb" extension in RocketCore.
- If Zcb is enabled, furthur **usingBitManip** and **usingMulDiv** parameters (if set as True) are used to decode
the corresponding BitManip and M type Instructions.
- If **usingCompressedSuiteB** parameter is not set (i.e. False), decoder will give "unimp"
instruction if it encounters any Zcb instruction. Same is true for **usingBitManip** and **usingMulDiv**.
*/

class RVCDecoder(x: UInt, xLen: Int, useAddiForMv: Boolean = false, usingBitManip: Boolean = false, usingMulDiv: Boolean = false, usingCompressedSuiteB: Boolean = false) {
ZenithalHourlyRate marked this conversation as resolved.
Show resolved Hide resolved
def inst(bits: UInt, rd: UInt = x(11,7), rs1: UInt = x(19,15), rs2: UInt = x(24,20), rs3: UInt = x(31,27)) = {
val res = Wire(new ExpandedInstruction)
res.bits := bits
Expand All @@ -32,6 +42,8 @@ class RVCDecoder(x: UInt, xLen: Int, useAddiForMv: Boolean = false) {
def rs2 = x(6,2)
def rd = x(11,7)
def addi4spnImm = Cat(x(10,7), x(12,11), x(5), x(6), 0.U(2.W))
def lbImm = Cat(x(5), x(6))
def lhImm = Cat(x(5), 0.U(1.W))
def lwImm = Cat(x(5), x(12,10), x(6), 0.U(2.W))
def ldImm = Cat(x(6,5), x(12,10), 0.U(3.W))
def lwspImm = Cat(x(3,2), x(12), x(6,4), 0.U(2.W))
Expand Down Expand Up @@ -60,15 +72,27 @@ class RVCDecoder(x: UInt, xLen: Int, useAddiForMv: Boolean = false) {
if (xLen == 32) inst(Cat(lwImm, rs1p, 2.U(3.W), rs2p, 0x07.U(7.W)), rs2p, rs1p, rs2p)
else ld
}
def unimp = inst(Cat(lwImm >> 5, rs2p, rs1p, 2.U(3.W), lwImm(4,0), 0x3F.U(7.W)), rs2p, rs1p, rs2p)
def zcb_q0 = {
if (usingCompressedSuiteB){
def lbu = Cat(lbImm, rs1p, 4.U(3.W), rs2p, 0x03.U(7.W))
def lh = {
val func3 = Mux(x(6), 1.U(3.W), 5.U(3.W))
Cat(lhImm, rs1p, func3, rs2p, 0x03.U(7.W))
}
def sb = Cat(rs2p, rs1p, 0.U(3.W), 0.U(3.W), lbImm(1,0), 0x23.U(7.W))
def sh = Cat(rs2p, rs1p, 1.U(3.W), 0.U(3.W), lhImm(1,0), 0x23.U(7.W))
inst(Seq(lbu, lh, sb, sh)(x(11,10)), rs2p, rs1p, rs2p)
}
else inst(Cat(lwImm >> 5, rs2p, rs1p, 2.U(3.W), lwImm(4,0), 0x3F.U(7.W)), rs2p, rs1p, rs2p) // unimp
}
def sd = inst(Cat(ldImm >> 5, rs2p, rs1p, 3.U(3.W), ldImm(4,0), 0x23.U(7.W)), rs2p, rs1p, rs2p)
def sw = inst(Cat(lwImm >> 5, rs2p, rs1p, 2.U(3.W), lwImm(4,0), 0x23.U(7.W)), rs2p, rs1p, rs2p)
def fsd = inst(Cat(ldImm >> 5, rs2p, rs1p, 3.U(3.W), ldImm(4,0), 0x27.U(7.W)), rs2p, rs1p, rs2p)
def fsw = {
if (xLen == 32) inst(Cat(lwImm >> 5, rs2p, rs1p, 2.U(3.W), lwImm(4,0), 0x27.U(7.W)), rs2p, rs1p, rs2p)
else sd
}
Seq(addi4spn, fld, lw, flw, unimp, fsd, sw, fsw)
Seq(addi4spn, fld, lw, flw, zcb_q0, fsd, sw, fsw)
Copy link
Contributor

@ZenithalHourlyRate ZenithalHourlyRate May 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zcb should be populated with conditions

For example, c.zext.b should be added only when usingBitManip, and c.mul should be populated only when usingMulDiv, zext.w should be added only when RV64. This could save a tiny bit of area.

Other insts like c.lbu and c.not will always be added as I or E are always present. This default behavior will add area overhead for end users as they may not use it. I think we provide an option like usingCompressedBitManip to control this behavior. Asking @jerryz123 for advice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A mistake. Should @jerryz123.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameters to the RVCDecode object should be added that disable the Zcb/Zcmp/Zcmt extensions if not needed.

Copy link
Author

@Abdulwadoodd Abdulwadoodd May 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jerryz123 , @ZenithalHourlyRate
In order to enable/disable Zcb, usingCompressedSuiteB parameter is added and routed (along with usingMulDiv and usingBitManip) to RVCDecoder to apply the condition on the corresponding instructions.

}

def q1 = {
Expand Down Expand Up @@ -96,15 +120,45 @@ class RVCDecoder(x: UInt, xLen: Int, useAddiForMv: Boolean = false) {
def bnez = inst(Cat(bImm(12), bImm(10,5), x0, rs1p, 1.U(3.W), bImm(4,1), bImm(11), 0x63.U(7.W)), x0, rs1p, x0)
def arith = {
def srli = Cat(shamt, rs1p, 5.U(3.W), rs1p, 0x13.U(7.W))
def srai = srli | (1 << 30).U
def srai = Cat(0x10.U, srli)
def andi = Cat(addiImm, rs1p, 7.U(3.W), rs1p, 0x13.U(7.W))
def rtype = {
val funct = Seq(0.U, 4.U, 6.U, 7.U, 0.U, 0.U, 2.U, 3.U)(Cat(x(12), x(6,5)))
val funct = Seq(0.U, 4.U, 6.U, 7.U, 0.U, 0.U, 0.U, 3.U)(Cat(x(12), x(6,5)))
val sub = Mux(x(6,5) === 0.U, (1 << 30).U, 0.U)
val opc = Mux(x(12), 0x3B.U(7.W), 0x33.U(7.W))
Cat(rs2p, rs1p, funct, rs1p, opc) | sub
val opc = Mux(x(12), Mux(x(6), 0x33.U(7.W), 0x3B.U(7.W)), 0x33.U(7.W))
def mul = {
if(usingMulDiv && usingCompressedSuiteB) Mux(Cat(x(12), x(6,5)) === 6.U, (1 << 25).U, 0.U)
else 0.U
}
def zca = Cat(rs2p, rs1p, funct, rs1p, opc) | sub | mul
def zcb_q1 = {
def unimp = Cat(lwImm >> 5, rs2p, rs1p, 2.U(3.W), lwImm(4,0), 0x3F.U(7.W))
if(usingCompressedSuiteB){
def zextb = Cat(0xFF.U, rs1p, 7.U(3.W), rs1p, 0x13.U(7.W))
def not = Cat(0xFFF.U, rs1p, 4.U(3.W), rs1p, 0x13.U(7.W))
def sextb = Cat(0x604.U, rs1p, 1.U(3.W), rs1p, 0x13.U(7.W))
def sexth = Cat(0x605.U, rs1p, 1.U(3.W), rs1p, 0x13.U(7.W))
def zextw = Cat(4.U, x0, rs1p, 0.U(3.W), rs1p, 0x3B.U(7.W))
def zexth = {
val zexth_common = Cat(0x80.U, rs1p, 4.U(3.W), rs1p)
if (xLen == 32) Cat(zexth_common, 0x33.U(7.W))
else Cat(zexth_common, 0x3B.U(7.W))
}
if(usingBitManip){
Seq(zextb, sextb, zexth, sexth, zextw, not, unimp, unimp)(x(4,2))
} else {
Mux (x(4,2)=== 5.U, not, Mux (x(4,2) === 0.U, zextb, unimp))
}
}
else unimp
}
Mux(Cat(x(12), x(6,5)) === 7.U, zcb_q1, zca)
}
def op2 = {
if(usingCompressedSuiteB) Mux(Cat(x(15,10), x(6,2)) === 0x4FC.U, x0, rs2p)
else rs2p
}
inst(Seq(srli, srai, andi, rtype)(x(11,10)), rs1p, rs1p, rs2p)
inst(Seq(srli, srai, andi, rtype)(x(11,10)), rs1p, rs1p, op2)
}
Seq(addi, jal, li, lui, arith, j, beqz, bnez)
}
Expand Down Expand Up @@ -164,9 +218,9 @@ class RVCExpander(useAddiForMv: Boolean = false)(implicit val p: Parameters) ext

if (usingCompressed) {
io.rvc := io.in(1,0) =/= 3.U
io.out := new RVCDecoder(io.in, p(XLen), useAddiForMv).decode
io.out := new RVCDecoder(io.in, p(XLen), useAddiForMv, usingBitManip, usingMulDiv, usingCompressedSuiteB).decode
} else {
io.rvc := false.B
io.out := new RVCDecoder(io.in, p(XLen), useAddiForMv).passthrough
io.out := new RVCDecoder(io.in, p(XLen), useAddiForMv, usingBitManip, usingMulDiv, usingCompressedSuiteB).passthrough
}
}
1 change: 1 addition & 0 deletions src/main/scala/rocket/RocketCore.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ case class RocketCoreParams(
useAtomics: Boolean = true,
useAtomicsOnlyForIO: Boolean = false,
useCompressed: Boolean = true,
useCompressedSuiteB: Boolean = false,
useRVE: Boolean = false,
useSCIE: Boolean = false,
useBitManip: Boolean = false,
Expand Down
4 changes: 4 additions & 0 deletions src/main/scala/tile/BaseTile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ trait HasNonDiplomaticTileParameters {
Option.when(tileParams.core.useConditionalZero)(Seq("zicond")) ++
Some(Seq("zicsr", "zifencei", "zihpm")) ++
Option.when(tileParams.core.fpu.nonEmpty && tileParams.core.fpu.get.fLen >= 16 && tileParams.core.fpu.get.minFLen <= 16)(Seq("zfh")) ++
Option.when(tileParams.core.useCompressed)(Seq("zca")) ++
Option.when(tileParams.core.useCompressedSuiteB)(Seq("zcb")) ++
Option.when(tileParams.core.useCompressed && tileParams.core.fpu.nonEmpty && tileParams.core.fpu.get.fLen > 32)(Seq("zcd")) ++
Option.when(tileParams.core.useCompressed && tileParams.core.fpu.nonEmpty)(Seq("zcf")) ++
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes currently for rocket when fpu.nonEmpty F-ext will always be enabled

val insns = (minFLen, fLen) match {
case (32, 32) => f
case (16, 32) => h ++ f
case (32, 64) => f ++ d
case (16, 64) => h ++ f ++ d ++ fcvt_hd

But the consistency is not kept everywhere, e.g. misa has a different way

val f = if (tileParams.core.fpu.nonEmpty) "f" else ""

(if (fLen >= 32) "F" else "") +

To reduce such inconsistency, I believe we should finish this TODO? Are you interested in this TODO? If so, things should be done in another PR.

// TODO merge with isaString in CSR.scala

Option.when(tileParams.core.useBitManip)(Seq("zba", "zbb", "zbc")) ++
Option.when(tileParams.core.hasBitManipCrypto)(Seq("zbkb", "zbkc", "zbkx")) ++
Option.when(tileParams.core.useBitManip)(Seq("zbs")) ++
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/tile/Core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ trait CoreParams {
val useAtomics: Boolean
val useAtomicsOnlyForIO: Boolean
val useCompressed: Boolean
val useCompressedSuiteB: Boolean
val useBitManip: Boolean
val useBitManipCrypto: Boolean
val useVector: Boolean = false
Expand Down Expand Up @@ -86,6 +87,7 @@ trait HasCoreParameters extends HasTileParameters {
val usingAtomicsOnlyForIO = coreParams.useAtomicsOnlyForIO
val usingAtomicsInCache = usingAtomics && !usingAtomicsOnlyForIO
val usingCompressed = coreParams.useCompressed
val usingCompressedSuiteB = coreParams.useCompressedSuiteB && usingCompressed
val usingBitManip = coreParams.useBitManip
val usingBitManipCrypto = coreParams.hasBitManipCrypto
val usingVector = coreParams.useVector
Expand Down