From 62162c5e1df7ad20ee7842c4db947ae95839f4ca Mon Sep 17 00:00:00 2001 From: rewired <39949564+rewired-gh@users.noreply.github.com> Date: Sun, 7 May 2023 12:17:28 +0800 Subject: [PATCH] Implement Zicond extension (#3329) * Instructions: sync from riscv-opcodes (add zicond) * Zicond: implement czero.eqz, czero.nez * Zicond: fix implementation * Zicond: reduce code duplication * Add ISA extension when using Zicond * Fix ISA extensions ordering --- src/main/scala/rocket/ALU.scala | 17 ++- src/main/scala/rocket/IDecode.scala | 7 + src/main/scala/rocket/Instructions.scala | 184 +++++++++++++++++++++++ src/main/scala/rocket/RocketCore.scala | 3 + src/main/scala/tile/BaseTile.scala | 1 + src/main/scala/tile/Core.scala | 2 + 6 files changed, 212 insertions(+), 2 deletions(-) diff --git a/src/main/scala/rocket/ALU.scala b/src/main/scala/rocket/ALU.scala index 49a156fab53..68e7db4a98f 100644 --- a/src/main/scala/rocket/ALU.scala +++ b/src/main/scala/rocket/ALU.scala @@ -19,6 +19,8 @@ class ALUFN { def FN_SR = 5.U def FN_OR = 6.U def FN_AND = 7.U + def FN_CZEQZ = 8.U + def FN_CZNEZ = 9.U def FN_SUB = 10.U def FN_SRA = 11.U def FN_SLT = 12.U @@ -160,11 +162,22 @@ class ALU(implicit p: Parameters) extends AbstractALU(new ALUFN)(p) { val shout = Mux(io.fn === aluFn.FN_SR || io.fn === aluFn.FN_SRA, shout_r, 0.U) | Mux(io.fn === aluFn.FN_SL, shout_l, 0.U) + // CZEQZ, CZNEZ + val in2_not_zero = io.in2.orR + val cond_out = Option.when(usingConditionalZero)( + Mux((io.fn === aluFn.FN_CZEQZ && in2_not_zero) || (io.fn === aluFn.FN_CZNEZ && !in2_not_zero), io.in1, 0.U) + ) + // AND, OR, XOR val logic = Mux(io.fn === aluFn.FN_XOR || io.fn === aluFn.FN_OR, in1_xor_in2, 0.U) | Mux(io.fn === aluFn.FN_OR || io.fn === aluFn.FN_AND, io.in1 & io.in2, 0.U) - val shift_logic = (aluFn.isCmp(io.fn) && slt) | logic | shout - val out = Mux(io.fn === aluFn.FN_ADD || io.fn === aluFn.FN_SUB, io.adder_out, shift_logic) + + val shift_logic = (aluFn.isCmp (io.fn) && slt) | logic | shout + val shift_logic_cond = cond_out match { + case Some(co) => shift_logic | co + case _ => shift_logic + } + val out = Mux(io.fn === aluFn.FN_ADD || io.fn === aluFn.FN_SUB, io.adder_out, shift_logic_cond) io.out := out if (xLen > 32) { diff --git a/src/main/scala/rocket/IDecode.scala b/src/main/scala/rocket/IDecode.scala index cf99b2e99b6..7428b0e4661 100644 --- a/src/main/scala/rocket/IDecode.scala +++ b/src/main/scala/rocket/IDecode.scala @@ -135,6 +135,13 @@ class FenceIDecode(flushDCache: Boolean, aluFn: ALUFN = ALUFN())(implicit val p: FENCE_I-> List(Y,N,N,N,N,N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, aluFn.FN_X, v,cmd, N,N,N,N,N,N,N,CSR.N,Y,Y,N,N)) } +class ConditionalZeroDecode(aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants +{ + val table: Array[(BitPat, List[BitPat])] = Array( + CZERO_EQZ-> List(Y,N,N,N,N,N,Y,Y,N,N,N,N,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_CZEQZ, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N), + CZERO_NEZ-> List(Y,N,N,N,N,N,Y,Y,N,N,N,N,A2_RS2, A1_RS1, IMM_X, DW_XPR,aluFn.FN_CZNEZ, N,M_X, N,N,N,N,N,N,Y,CSR.N,N,N,N,N)) +} + class CFlushDecode(supportsFlushLine: Boolean, aluFn: ALUFN = ALUFN())(implicit val p: Parameters) extends DecodeConstants { private def zapRs1(x: BitPat) = if (supportsFlushLine) x else BitPat(x.value.U) diff --git a/src/main/scala/rocket/Instructions.scala b/src/main/scala/rocket/Instructions.scala index 07621f9a6b3..adf1183388f 100644 --- a/src/main/scala/rocket/Instructions.scala +++ b/src/main/scala/rocket/Instructions.scala @@ -112,6 +112,8 @@ object Instructions { def CSRRSI = BitPat("b?????????????????110?????1110011") def CSRRW = BitPat("b?????????????????001?????1110011") def CSRRWI = BitPat("b?????????????????101?????1110011") + def CZERO_EQZ = BitPat("b0000111??????????101?????0110011") + def CZERO_NEZ = BitPat("b0000111??????????111?????0110011") def CTZ = BitPat("b011000000001?????001?????0010011") def CTZW = BitPat("b011000000001?????001?????0011011") def DIV = BitPat("b0000001??????????100?????0110011") @@ -869,6 +871,7 @@ object CSRs { val vxrm = 0xa val vcsr = 0xf val seed = 0x15 + val jvt = 0x17 val cycle = 0xc00 val time = 0xc01 val instret = 0xc02 @@ -911,11 +914,19 @@ object CSRs { val stvec = 0x105 val scounteren = 0x106 val senvcfg = 0x10a + val sstateen0 = 0x10c + val sstateen1 = 0x10d + val sstateen2 = 0x10e + val sstateen3 = 0x10f val sscratch = 0x140 val sepc = 0x141 val scause = 0x142 val stval = 0x143 val sip = 0x144 + val stimecmp = 0x14d + val siselect = 0x150 + val sireg = 0x151 + val stopei = 0x15c val satp = 0x180 val scontext = 0x5a8 val vsstatus = 0x200 @@ -926,6 +937,10 @@ object CSRs { val vscause = 0x242 val vstval = 0x243 val vsip = 0x244 + val vstimecmp = 0x24d + val vsiselect = 0x250 + val vsireg = 0x251 + val vstopei = 0x25c val vsatp = 0x280 val hstatus = 0x600 val hedeleg = 0x602 @@ -934,14 +949,25 @@ object CSRs { val htimedelta = 0x605 val hcounteren = 0x606 val hgeie = 0x607 + val hvien = 0x608 + val hvictl = 0x609 val henvcfg = 0x60a + val hstateen0 = 0x60c + val hstateen1 = 0x60d + val hstateen2 = 0x60e + val hstateen3 = 0x60f val htval = 0x643 val hip = 0x644 val hvip = 0x645 + val hviprio1 = 0x646 + val hviprio2 = 0x647 val htinst = 0x64a val hgatp = 0x680 val hcontext = 0x6a8 val hgeip = 0xe12 + val vstopi = 0xeb0 + val scountovf = 0xda0 + val stopi = 0xdb0 val utvt = 0x7 val unxti = 0x45 val uintstatus = 0x46 @@ -964,7 +990,13 @@ object CSRs { val mie = 0x304 val mtvec = 0x305 val mcounteren = 0x306 + val mvien = 0x308 + val mvip = 0x309 val menvcfg = 0x30a + val mstateen0 = 0x30c + val mstateen1 = 0x30d + val mstateen2 = 0x30e + val mstateen3 = 0x30f val mcountinhibit = 0x320 val mscratch = 0x340 val mepc = 0x341 @@ -973,6 +1005,9 @@ object CSRs { val mip = 0x344 val mtinst = 0x34a val mtval2 = 0x34b + val miselect = 0x350 + val mireg = 0x351 + val mtopei = 0x35c val pmpcfg0 = 0x3a0 val pmpcfg1 = 0x3a1 val pmpcfg2 = 0x3a2 @@ -1131,8 +1166,24 @@ object CSRs { val mimpid = 0xf13 val mhartid = 0xf14 val mconfigptr = 0xf15 + val mtopi = 0xfb0 + val sieh = 0x114 + val siph = 0x154 + val stimecmph = 0x15d + val vsieh = 0x214 + val vsiph = 0x254 + val vstimecmph = 0x25d val htimedeltah = 0x615 + val hidelegh = 0x613 + val hvienh = 0x618 val henvcfgh = 0x61a + val hviph = 0x655 + val hviprio1h = 0x656 + val hviprio2h = 0x657 + val hstateen0h = 0x61c + val hstateen1h = 0x61d + val hstateen2h = 0x61e + val hstateen3h = 0x61f val cycleh = 0xc80 val timeh = 0xc81 val instreth = 0xc82 @@ -1166,7 +1217,49 @@ object CSRs { val hpmcounter30h = 0xc9e val hpmcounter31h = 0xc9f val mstatush = 0x310 + val midelegh = 0x313 + val mieh = 0x314 + val mvienh = 0x318 + val mviph = 0x319 val menvcfgh = 0x31a + val mstateen0h = 0x31c + val mstateen1h = 0x31d + val mstateen2h = 0x31e + val mstateen3h = 0x31f + val miph = 0x354 + val mhpmevent3h = 0x723 + val mhpmevent4h = 0x724 + val mhpmevent5h = 0x725 + val mhpmevent6h = 0x726 + val mhpmevent7h = 0x727 + val mhpmevent8h = 0x728 + val mhpmevent9h = 0x729 + val mhpmevent10h = 0x72a + val mhpmevent11h = 0x72b + val mhpmevent12h = 0x72c + val mhpmevent13h = 0x72d + val mhpmevent14h = 0x72e + val mhpmevent15h = 0x72f + val mhpmevent16h = 0x730 + val mhpmevent17h = 0x731 + val mhpmevent18h = 0x732 + val mhpmevent19h = 0x733 + val mhpmevent20h = 0x734 + val mhpmevent21h = 0x735 + val mhpmevent22h = 0x736 + val mhpmevent23h = 0x737 + val mhpmevent24h = 0x738 + val mhpmevent25h = 0x739 + val mhpmevent26h = 0x73a + val mhpmevent27h = 0x73b + val mhpmevent28h = 0x73c + val mhpmevent29h = 0x73d + val mhpmevent30h = 0x73e + val mhpmevent31h = 0x73f + val mnscratch = 0x740 + val mnepc = 0x741 + val mncause = 0x742 + val mnstatus = 0x744 val mseccfgh = 0x757 val mcycleh = 0xb80 val minstreth = 0xb82 @@ -1209,6 +1302,7 @@ object CSRs { res += vxrm res += vcsr res += seed + res += jvt res += cycle res += time res += instret @@ -1251,11 +1345,19 @@ object CSRs { res += stvec res += scounteren res += senvcfg + res += sstateen0 + res += sstateen1 + res += sstateen2 + res += sstateen3 res += sscratch res += sepc res += scause res += stval res += sip + res += stimecmp + res += siselect + res += sireg + res += stopei res += satp res += scontext res += vsstatus @@ -1266,6 +1368,10 @@ object CSRs { res += vscause res += vstval res += vsip + res += vstimecmp + res += vsiselect + res += vsireg + res += vstopei res += vsatp res += hstatus res += hedeleg @@ -1274,14 +1380,25 @@ object CSRs { res += htimedelta res += hcounteren res += hgeie + res += hvien + res += hvictl res += henvcfg + res += hstateen0 + res += hstateen1 + res += hstateen2 + res += hstateen3 res += htval res += hip res += hvip + res += hviprio1 + res += hviprio2 res += htinst res += hgatp res += hcontext res += hgeip + res += vstopi + res += scountovf + res += stopi res += utvt res += unxti res += uintstatus @@ -1304,7 +1421,13 @@ object CSRs { res += mie res += mtvec res += mcounteren + res += mvien + res += mvip res += menvcfg + res += mstateen0 + res += mstateen1 + res += mstateen2 + res += mstateen3 res += mcountinhibit res += mscratch res += mepc @@ -1313,6 +1436,9 @@ object CSRs { res += mip res += mtinst res += mtval2 + res += miselect + res += mireg + res += mtopei res += pmpcfg0 res += pmpcfg1 res += pmpcfg2 @@ -1471,12 +1597,28 @@ object CSRs { res += mimpid res += mhartid res += mconfigptr + res += mtopi res.toArray } val all32 = { val res = collection.mutable.ArrayBuffer(all:_*) + res += sieh + res += siph + res += stimecmph + res += vsieh + res += vsiph + res += vstimecmph res += htimedeltah + res += hidelegh + res += hvienh res += henvcfgh + res += hviph + res += hviprio1h + res += hviprio2h + res += hstateen0h + res += hstateen1h + res += hstateen2h + res += hstateen3h res += cycleh res += timeh res += instreth @@ -1510,7 +1652,49 @@ object CSRs { res += hpmcounter30h res += hpmcounter31h res += mstatush + res += midelegh + res += mieh + res += mvienh + res += mviph res += menvcfgh + res += mstateen0h + res += mstateen1h + res += mstateen2h + res += mstateen3h + res += miph + res += mhpmevent3h + res += mhpmevent4h + res += mhpmevent5h + res += mhpmevent6h + res += mhpmevent7h + res += mhpmevent8h + res += mhpmevent9h + res += mhpmevent10h + res += mhpmevent11h + res += mhpmevent12h + res += mhpmevent13h + res += mhpmevent14h + res += mhpmevent15h + res += mhpmevent16h + res += mhpmevent17h + res += mhpmevent18h + res += mhpmevent19h + res += mhpmevent20h + res += mhpmevent21h + res += mhpmevent22h + res += mhpmevent23h + res += mhpmevent24h + res += mhpmevent25h + res += mhpmevent26h + res += mhpmevent27h + res += mhpmevent28h + res += mhpmevent29h + res += mhpmevent30h + res += mhpmevent31h + res += mnscratch + res += mnepc + res += mncause + res += mnstatus res += mseccfgh res += mcycleh res += minstreth diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 5941c2c6155..6c01985aab3 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -29,6 +29,7 @@ case class RocketCoreParams( useBitManipCrypto: Boolean = false, useCryptoNIST: Boolean = false, useCryptoSM: Boolean = false, + useConditionalZero: Boolean = false, nLocalInterrupts: Int = 0, useNMI: Boolean = false, nBreakpoints: Int = 1, @@ -82,6 +83,7 @@ trait HasRocketCoreParameters extends HasCoreParameters { require(!fastLoadByte || fastLoadWord) require(!rocketParams.haveFSDirty, "rocket doesn't support setting fs dirty from outside, please disable haveFSDirty") + require(!(usingABLU && usingConditionalZero), "Zicond is not yet implemented in ABLU") } class RocketCustomCSRs(implicit p: Parameters) extends CustomCSRs with HasRocketCoreParameters { @@ -202,6 +204,7 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) ((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)) ++: Seq(new IDecode(aluFn)) diff --git a/src/main/scala/tile/BaseTile.scala b/src/main/scala/tile/BaseTile.scala index 07a063665bb..91471932b4e 100644 --- a/src/main/scala/tile/BaseTile.scala +++ b/src/main/scala/tile/BaseTile.scala @@ -110,6 +110,7 @@ trait HasNonDiplomaticTileParameters { // rdtime[h] is not implemented, and could be provided by software emulation // see https://github.com/chipsalliance/rocket-chip/issues/3207 //Some(Seq("zicntr")) ++ + 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.useBitManip)(Seq("zba", "zbb", "zbc")) ++ diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index 782034b704b..36847a9a0b0 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -29,6 +29,7 @@ trait CoreParams { val useCryptoNIST: Boolean val useCryptoSM: Boolean val useRVE: Boolean + val useConditionalZero: Boolean val mulDiv: Option[MulDivParams] val fpu: Option[FPUParams] val fetchWidth: Int @@ -91,6 +92,7 @@ trait HasCoreParameters extends HasTileParameters { val usingCryptoNIST = coreParams.useCryptoNIST val usingCryptoSM = coreParams.useCryptoSM val usingNMI = coreParams.useNMI + val usingConditionalZero = coreParams.useConditionalZero val retireWidth = coreParams.retireWidth val fetchWidth = coreParams.fetchWidth