refactor(Frontend): replace NamedUInt with EnumUInt (#4529)
EMU Test / Changes Detection (push) Has been cancelled Details
EMU Test / Generate Verilog (push) Has been cancelled Details
EMU Test / EMU - Basics (push) Has been cancelled Details
EMU Test / EMU - CHI (push) Has been cancelled Details
EMU Test / EMU - Performance (push) Has been cancelled Details
EMU Test / EMU - MC (push) Has been cancelled Details
EMU Test / SIMV - Basics (push) Has been cancelled Details
EMU Test / Upload Artifacts (push) Has been cancelled Details
EMU Test / Check Submodules (push) Has been cancelled Details
EMU Test / Check Format (push) Has been cancelled Details

Use EnumUInt introduced by #4528 to do some compile-time check.

Also:
- add `class ExceptionType` to replace `ExceptionType.hasException(xxx)`
with `xxx.hasException`, etc.
- apply CamelCase to `BrType`.
This commit is contained in:
xu_zh 2025-05-24 17:53:22 +08:00 committed by GitHub
parent 3bfc5a3c90
commit cbea99c932
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 247 additions and 317 deletions

View File

@ -33,12 +33,12 @@ object PreDecodeInst {
val brTable = Array(
// C_JAL -> List(BrType.jal),
C_EBREAK -> List(BrType.notCFI), // c.ebreak should not be decoded as jalr, higher priority than c.jalr
C_J -> List(BrType.jal),
C_JALR -> List(BrType.jalr),
C_BRANCH -> List(BrType.branch),
JAL -> List(BrType.jal),
JALR -> List(BrType.jalr),
BRANCH -> List(BrType.branch)
C_EBREAK -> List(BrType.NotCfi), // c.ebreak should not be decoded as jalr, higher priority than c.jalr
C_J -> List(BrType.Jal),
C_JALR -> List(BrType.Jalr),
C_BRANCH -> List(BrType.Branch),
JAL -> List(BrType.Jal),
JALR -> List(BrType.Jalr),
BRANCH -> List(BrType.Branch)
)
}

View File

@ -82,9 +82,9 @@ object Itype extends NamedUInt(4) {
def jumpTypeGen(brType: UInt, rd: OpRegType, rs: OpRegType): UInt = {
val isEqualRdRs = rd === rs
val isJal = brType === BrType.jal
val isJalr = brType === BrType.jalr
val isBranch = brType === BrType.branch
val isJal = brType === BrType.Jal
val isJalr = brType === BrType.Jalr
val isBranch = brType === BrType.Branch
// push to RAS when rd is link, pop from RAS when rs is link
def isUninferableCall = isJalr && rd.isLink && (!rs.isLink || rs.isLink && isEqualRdRs) //8 push

View File

@ -24,7 +24,7 @@ import ftq.FtqRedirectSramEntry
import ftq.FtqRfComponents
import org.chipsalliance.cde.config.Parameters
import utility._
import utils.NamedUInt
import utils.EnumUInt
import xiangshan._
import xiangshan.backend.GPAMemEntry
import xiangshan.backend.fu.PMPRespBundle
@ -88,7 +88,7 @@ class FtqICacheInfo(implicit p: Parameters) extends XSBundle with HasICacheParam
class FtqToPrefetchBundle(implicit p: Parameters) extends XSBundle {
val req: FtqICacheInfo = new FtqICacheInfo
val backendException: UInt = ExceptionType()
val backendException: ExceptionType = new ExceptionType
}
class FtqToFetchBundle(implicit p: Parameters) extends XSBundle with HasICacheParameters {
@ -152,138 +152,94 @@ class mmioCommitRead(implicit p: Parameters) extends XSBundle {
val mmioLastCommit = Input(Bool())
}
object ExceptionType extends NamedUInt(2) {
def none: UInt = "b00".U(width.W)
def pf: UInt = "b01".U(width.W) // instruction page fault
def gpf: UInt = "b10".U(width.W) // instruction guest page fault
def af: UInt = "b11".U(width.W) // instruction access fault
class ExceptionType extends Bundle {
val value: UInt = ExceptionType.Value()
def hasException(e: UInt): Bool = e =/= none
def hasException(e: Vec[UInt]): Bool = e.map(_ =/= none).reduce(_ || _)
def hasException(e: IndexedSeq[UInt]): Bool = hasException(VecInit(e))
def isNone: Bool = value === ExceptionType.Value.None
def isPf: Bool = value === ExceptionType.Value.Pf
def isGpf: Bool = value === ExceptionType.Value.Gpf
def isAf: Bool = value === ExceptionType.Value.Af
def fromOH(has_pf: Bool, has_gpf: Bool, has_af: Bool): UInt = {
def hasException: Bool = value =/= ExceptionType.Value.None
/** merge exception from multiple sources, the leftmost one has higher priority
* @example {{{
* val itlbException = ExceptionType(io.itlb.resp.bits)
* val pmpException = ExceptionType(io.pmp.resp)
*
* // itlb has higher priority than pmp, as when itlb has exception, pAddr is not valid
* val exception = itlbException || pmpException
* }}}
*/
def ||(that: ExceptionType): ExceptionType =
Mux(this.hasException, this, that)
}
object ExceptionType {
private object Value extends EnumUInt(4) {
def None: UInt = 0.U(width.W)
def Pf: UInt = 1.U(width.W) // instruction page fault
def Gpf: UInt = 2.U(width.W) // instruction guest page fault
def Af: UInt = 3.U(width.W) // instruction access fault
}
def apply(that: UInt): ExceptionType = {
Value.assertLegal(that)
val e = Wire(new ExceptionType)
e.value := that
e
}
def None: ExceptionType = apply(Value.None)
def Pf: ExceptionType = apply(Value.Pf)
def Gpf: ExceptionType = apply(Value.Gpf)
def Af: ExceptionType = apply(Value.Af)
def apply(hasPf: Bool, hasGpf: Bool, hasAf: Bool): ExceptionType = {
assert(
PopCount(VecInit(has_pf, has_gpf, has_af)) <= 1.U,
"ExceptionType.fromOH receives input that is not one-hot: pf=%d, gpf=%d, af=%d",
has_pf,
has_gpf,
has_af
PopCount(VecInit(hasPf, hasGpf, hasAf)) <= 1.U,
"ExceptionType receives input that is not one-hot: pf=%d, gpf=%d, af=%d",
hasPf,
hasGpf,
hasAf
)
// input is at-most-one-hot encoded, so we don't worry about priority here.
MuxCase(
none,
None,
Seq(
has_pf -> pf,
has_gpf -> gpf,
has_af -> af
hasPf -> Pf,
hasGpf -> Gpf,
hasAf -> Af
)
)
}
// only af is used most frequently (pmp / ecc / tilelink), so we define a shortcut
// we cannot use default parameter in apply(), as it is overloaded and scala won't allow
def apply(hasAf: Bool): ExceptionType =
apply(hasPf = false.B, hasGpf = false.B, hasAf = hasAf)
// raise pf/gpf/af according to itlb response
def fromTlbResp(resp: TlbResp, useDup: Int = 0): UInt = {
def fromTlbResp(resp: TlbResp, useDup: Int = 0): ExceptionType = {
require(useDup >= 0 && useDup < resp.excp.length)
// itlb is guaranteed to respond at most one exception
fromOH(
resp.excp(useDup).pf.instr,
resp.excp(useDup).gpf.instr,
resp.excp(useDup).af.instr
apply(
hasPf = resp.excp(useDup).pf.instr,
hasGpf = resp.excp(useDup).gpf.instr,
hasAf = resp.excp(useDup).af.instr
)
}
// raise af if pmp check failed
def fromPMPResp(resp: PMPRespBundle): UInt =
Mux(resp.instr, af, none)
// raise af if meta/data array ecc check failed or l2 cache respond with tilelink corrupt
/* FIXME: RISC-V Machine ISA v1.13 (draft) introduced a "hardware error" exception, described as:
* > A Hardware Error exception is a synchronous exception triggered when corrupted or
* > uncorrectable data is accessed explicitly or implicitly by an instruction. In this context,
* > "data" encompasses all types of information used within a RISC-V hart. Upon a hardware
* > error exception, the xepc register is set to the address of the instruction that attempted to
* > access corrupted data, while the xtval register is set either to 0 or to the virtual address
* > of an instruction fetch, load, or store that attempted to access corrupted data. The priority
* > of Hardware Error exception is implementation-defined, but any given occurrence is
* > generally expected to be recognized at the point in the overall priority order at which the
* > hardware error is discovered.
* Maybe it's better to raise hardware error instead of access fault when ECC check failed.
* But it's draft and XiangShan backend does not implement this exception code yet, so we still raise af here.
*/
def fromECC(enable: Bool, corrupt: Bool): UInt =
Mux(enable && corrupt, af, none)
def fromTilelink(corrupt: Bool): UInt =
Mux(corrupt, af, none)
/**Generates exception mux tree
*
* Exceptions that are further to the left in the parameter list have higher priority
* @example
* {{{
* val itlb_exception = ExceptionType.fromTlbResp(io.itlb.resp.bits)
* // so as pmp_exception, meta_corrupt
* // ExceptionType.merge(itlb_exception, pmp_exception, meta_corrupt) is equivalent to:
* Mux(
* itlb_exception =/= none,
* itlb_exception,
* Mux(pmp_exception =/= none, pmp_exception, meta_corrupt)
* )
* }}}
*/
def merge(exceptions: UInt*): UInt = {
// // recursively generate mux tree
// if (exceptions.length == 1) {
// require(exceptions.head.getWidth == width)
// exceptions.head
// } else {
// Mux(exceptions.head =/= none, exceptions.head, merge(exceptions.tail: _*))
// }
// use MuxCase with default
exceptions.foreach(e => require(e.getWidth == width))
val mapping = exceptions.init.map(e => (e =/= none) -> e)
val default = exceptions.last
MuxCase(default, mapping)
}
/**Generates exception mux tree for multi-port exception vectors
*
* Exceptions that are further to the left in the parameter list have higher priority
* @example
* {{{
* val itlb_exception = VecInit((0 until PortNumber).map(i => ExceptionType.fromTlbResp(io.itlb(i).resp.bits)))
* // so as pmp_exception, meta_corrupt
* // ExceptionType.merge(itlb_exception, pmp_exception, meta_corrupt) is equivalent to:
* VecInit((0 until PortNumber).map(i => Mux(
* itlb_exception(i) =/= none,
* itlb_exception(i),
* Mux(pmp_exception(i) =/= none, pmp_exception(i), meta_corrupt(i))
* ))
* }}}
*/
def merge(exceptionVecs: Vec[UInt]*): Vec[UInt] = {
// // recursively generate mux tree
// if (exceptionVecs.length == 1) {
// exceptionVecs.head.foreach(e => require(e.getWidth == width))
// exceptionVecs.head
// } else {
// require(exceptionVecs.head.length == exceptionVecs.last.length)
// VecInit((exceptionVecs.head zip merge(exceptionVecs.tail: _*)).map{ case (high, low) =>
// Mux(high =/= none, high, low)
// })
// }
// merge port-by-port
val length = exceptionVecs.head.length
exceptionVecs.tail.foreach(vec => require(vec.length == length))
VecInit((0 until length).map(i => merge(exceptionVecs.map(_(i)): _*)))
}
def fromPmpResp(resp: PMPRespBundle): ExceptionType =
apply(hasAf = resp.instr)
}
object BrType extends NamedUInt(2) {
def notCFI: UInt = "b00".U(width.W)
def branch: UInt = "b01".U(width.W)
def jal: UInt = "b10".U(width.W)
def jalr: UInt = "b11".U(width.W)
object BrType extends EnumUInt(4) {
def NotCfi: UInt = 0.U(width.W)
def Branch: UInt = 1.U(width.W)
def Jal: UInt = 2.U(width.W)
def Jalr: UInt = 3.U(width.W)
}
class PreDecodeInfo extends Bundle { // 8 bit
@ -293,10 +249,10 @@ class PreDecodeInfo extends Bundle { // 8 bit
val isCall = Bool()
val isRet = Bool()
// val excType = UInt(3.W)
def isBr = brType === BrType.branch
def isJal = brType === BrType.jal
def isJalr = brType === BrType.jalr
def notCFI = brType === BrType.notCFI
def isBr = brType === BrType.Branch
def isJal = brType === BrType.Jal
def isJalr = brType === BrType.Jalr
def notCFI = brType === BrType.NotCfi
}
class FetchToIBuffer(implicit p: Parameters) extends XSBundle {
@ -307,7 +263,7 @@ class FetchToIBuffer(implicit p: Parameters) extends XSBundle {
val foldpc = Vec(PredictWidth, UInt(MemPredPCWidth.W))
val ftqOffset = Vec(PredictWidth, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))
val backendException = Vec(PredictWidth, Bool())
val exceptionType = Vec(PredictWidth, ExceptionType())
val exceptionType = Vec(PredictWidth, new ExceptionType)
val crossPageIPFFix = Vec(PredictWidth, Bool())
val illegalInstr = Vec(PredictWidth, Bool())
val triggered = Vec(PredictWidth, TriggerAction())

View File

@ -49,6 +49,41 @@ class IBufferIO(implicit p: Parameters) extends XSBundle {
val stallReason = new StallReasonIO(DecodeWidth)
}
object IBufferExceptionType extends EnumUInt(8) {
def None: UInt = "b000".U(width.W)
def NonCrossPF: UInt = "b001".U(width.W)
def NonCrossGPF: UInt = "b010".U(width.W)
def NonCrossAF: UInt = "b011".U(width.W)
def RvcII: UInt = "b100".U(width.W) // illegal instruction
def CrossPF: UInt = "b101".U(width.W)
def CrossGPF: UInt = "b110".U(width.W)
def CrossAF: UInt = "b111".U(width.W)
def cvtFromFetchExcpAndCrossPageAndRVCII(fetchExcp: ExceptionType, crossPage: Bool, rvcIll: Bool): UInt =
MuxCase(
0.U,
Seq(
crossPage -> Cat(1.U(1.W), fetchExcp.value),
fetchExcp.hasException -> fetchExcp.value,
rvcIll -> this.RvcII
)
)
def isRVCII(uint: UInt): Bool = {
this.checkInputWidth(uint)
uint(2) && uint(1, 0) === 0.U
}
def isCrossPage(uint: UInt): Bool = {
this.checkInputWidth(uint)
uint(2) && uint(1, 0) =/= 0.U
}
def isPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossPF(1, 0)
def isGPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossGPF(1, 0)
def isAF(uint: UInt): Bool = uint(1, 0) === this.NonCrossAF(1, 0)
}
class IBufEntry(implicit p: Parameters) extends XSBundle {
val inst = UInt(32.W)
val pc = PrunedAddr(VAddrBits)
@ -109,48 +144,6 @@ class IBufEntry(implicit p: Parameters) extends XSBundle {
cf.debug_seqNum := debug_seqNum
cf
}
object IBufferExceptionType extends NamedUInt(3) {
def None = "b000".U
def NonCrossPF = "b001".U
def NonCrossGPF = "b010".U
def NonCrossAF = "b011".U
// illegal instruction
def rvcII = "b100".U
def CrossPF = "b101".U
def CrossGPF = "b110".U
def CrossAF = "b111".U
def cvtFromFetchExcpAndCrossPageAndRVCII(fetchExcp: UInt, crossPage: Bool, rvcIll: Bool): UInt = {
require(
fetchExcp.getWidth == ExceptionType.width,
s"The width(${fetchExcp.getWidth}) of fetchExcp should be equal to " +
s"the width(${ExceptionType.width}) of frontend.ExceptionType."
)
MuxCase(
0.U,
Seq(
crossPage -> Cat(1.U(1.W), fetchExcp),
fetchExcp.orR -> fetchExcp,
rvcIll -> this.rvcII
)
)
}
def isRVCII(uint: UInt): Bool = {
this.checkInputWidth(uint)
uint(2) && uint(1, 0) === 0.U
}
def isCrossPage(uint: UInt): Bool = {
this.checkInputWidth(uint)
uint(2) && uint(1, 0) =/= 0.U
}
def isPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossPF(1, 0)
def isGPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossGPF(1, 0)
def isAF(uint: UInt): Bool = uint(1, 0) === this.NonCrossAF(1, 0)
}
}
class IBuffer(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper with HasPerfEvents {

View File

@ -159,13 +159,13 @@ class Ftq(implicit p: Parameters) extends FtqModule
// raises IPF or IAF, which is ifuWbPtr_write or IfuPtr_write.
// Only when IFU has written back that FTQ entry can backendIpf and backendIaf be false because this
// makes sure that IAF and IPF are correctly raised instead of being flushed by redirect requests.
val backendException = RegInit(ExceptionType.none)
val backendException = RegInit(ExceptionType.None)
val backendPcFaultPtr = RegInit(FtqPtr(false.B, 0.U))
when(fromBackendRedirect.valid) {
backendException := ExceptionType.fromOH(
has_pf = fromBackendRedirect.bits.cfiUpdate.backendIPF,
has_gpf = fromBackendRedirect.bits.cfiUpdate.backendIGPF,
has_af = fromBackendRedirect.bits.cfiUpdate.backendIAF
backendException := ExceptionType(
hasPf = fromBackendRedirect.bits.cfiUpdate.backendIPF,
hasGpf = fromBackendRedirect.bits.cfiUpdate.backendIGPF,
hasAf = fromBackendRedirect.bits.cfiUpdate.backendIAF
)
when(
fromBackendRedirect.bits.cfiUpdate.backendIPF || fromBackendRedirect.bits.cfiUpdate.backendIGPF ||
@ -174,7 +174,7 @@ class Ftq(implicit p: Parameters) extends FtqModule
backendPcFaultPtr := ifuWbPtr_write
}
}.elsewhen(ifuWbPtr =/= backendPcFaultPtr) {
backendException := ExceptionType.none
backendException := ExceptionType.None
}
// **********************************************************************
@ -473,7 +473,7 @@ class Ftq(implicit p: Parameters) extends FtqModule
copy.ftqIdx := ifuPtr
}
io.toICache.fetchReq.bits.isBackendException :=
ExceptionType.hasException(backendException) && backendPcFaultPtr === ifuPtr
backendException.hasException && backendPcFaultPtr === ifuPtr
io.toICache.prefetchReq.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr
io.toICache.prefetchReq.bits.req.fromFtqPcBundle(toPrefetchPcBundle)
@ -481,7 +481,7 @@ class Ftq(implicit p: Parameters) extends FtqModule
io.toICache.prefetchReq.bits.backendException := Mux(
backendPcFaultPtr === pfPtr,
backendException,
ExceptionType.none
ExceptionType.None
)
// io.toICache.fetchReq.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr
// io.toICache.fetchReq.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) =>

View File

@ -165,7 +165,7 @@ class ICacheRespBundle(implicit p: Parameters) extends ICacheBundle {
val vAddr: Vec[PrunedAddr] = Vec(PortNumber, PrunedAddr(VAddrBits))
val data: UInt = UInt(blockBits.W)
val pAddr: Vec[PrunedAddr] = Vec(PortNumber, PrunedAddr(PAddrBits))
val exception: Vec[UInt] = Vec(PortNumber, ExceptionType())
val exception: Vec[ExceptionType] = Vec(PortNumber, new ExceptionType)
val pmpMmio: Vec[Bool] = Vec(PortNumber, Bool())
val itlbPbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W))
val isBackendException: Bool = Bool()
@ -185,7 +185,7 @@ class PrefetchReqBundle(implicit p: Parameters) extends ICacheBundle {
val nextlineStart: PrunedAddr = PrunedAddr(VAddrBits)
val ftqIdx: FtqPtr = new FtqPtr
val isSoftPrefetch: Bool = Bool()
val backendException: UInt = ExceptionType()
val backendException: ExceptionType = new ExceptionType
def crossCacheline: Bool = startAddr(blockOffBits - 1) === 1.U
@ -217,7 +217,7 @@ class WayLookupEntry(implicit p: Parameters) extends ICacheBundle {
val vSetIdx: Vec[UInt] = Vec(PortNumber, UInt(idxBits.W))
val waymask: Vec[UInt] = Vec(PortNumber, UInt(nWays.W))
val pTag: Vec[UInt] = Vec(PortNumber, UInt(tagBits.W))
val itlbException: Vec[UInt] = Vec(PortNumber, ExceptionType())
val itlbException: Vec[ExceptionType] = Vec(PortNumber, new ExceptionType)
val itlbPbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W))
val metaCodes: Vec[UInt] = Vec(PortNumber, UInt(ICacheMetaCodeBits.W))
}
@ -236,7 +236,7 @@ class WayLookupBundle(implicit p: Parameters) extends ICacheBundle {
def vSetIdx: Vec[UInt] = entry.vSetIdx
def waymask: Vec[UInt] = entry.waymask
def pTag: Vec[UInt] = entry.pTag
def itlbException: Vec[UInt] = entry.itlbException
def itlbException: Vec[ExceptionType] = entry.itlbException
def itlbPbmt: Vec[UInt] = entry.itlbPbmt
def metaCodes: Vec[UInt] = entry.metaCodes
def gpAddr: PrunedAddr = gpf.gpAddr

View File

@ -27,7 +27,7 @@ import freechips.rocketchip.regmapper.RegReadFn
import freechips.rocketchip.regmapper.RegWriteFn
import freechips.rocketchip.tilelink.TLRegisterNode
import org.chipsalliance.cde.config.Parameters
import utils.NamedUInt
import utils.EnumUInt
import xiangshan.frontend.PrunedAddrInit
// currently for ECC control only
@ -61,7 +61,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e
// eccCtrl.ierror: inject error code
private def nInjError: Int = 8
private object EccCtrlInjError extends NamedUInt(log2Up(nInjError)) {
private object EccCtrlInjError extends EnumUInt(nInjError) {
def NotEnabled: UInt = 0.U(width.W) // try to inject when ECC check is not enabled
def TargetInvalid: UInt = 1.U(width.W) // try to inject to invalid(rsvd) eccCtrl.itarget
def NotFound: UInt = 2.U(width.W) // try to inject to eccIAddr.pAddr does not exist in ICache
@ -78,7 +78,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e
}
// eccCtrl.istatus: inject status
private def nInjStatus: Int = 8
private object EccCtrlInjStatus extends NamedUInt(log2Up(nInjStatus)) {
private object EccCtrlInjStatus extends EnumUInt(nInjStatus) {
def Idle: UInt = 0.U(width.W)
def Working: UInt = 1.U(width.W)
def Injected: UInt = 2.U(width.W)
@ -94,7 +94,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e
}
// eccCtrl.itarget: inject target
private def nInjTarget: Int = 4
private object EccCtrlInjTarget extends NamedUInt(log2Up(nInjTarget)) {
private object EccCtrlInjTarget extends EnumUInt(nInjTarget) {
def MetaArray: UInt = 0.U(width.W)
def DataArray: UInt = 2.U(width.W)
@unused
@ -151,7 +151,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e
// inject FSM
private def nInjectFsmState: Int = 5
private object InjectFsmState extends NamedUInt(log2Up(nInjectFsmState)) {
private object InjectFsmState extends EnumUInt(nInjectFsmState) {
// scala ask identifier that begins with uppercase cannot be used in pattern matching like `X :: Nil = Enum()`
// but we want UpperCamelCase for constants for better readability, so we dont use Enum() here
def Idle: UInt = 0.U(width.W)

View File

@ -224,14 +224,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
p.bits.size := 3.U
p.bits.cmd := TlbCmd.exec
}
private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPMPResp))
private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPmpResp))
private val s1_pmpMmio = VecInit(fromPmp.map(_.mmio))
// merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next
private val s1_exceptionOut = ExceptionType.merge(
s1_itlbException,
s1_pmpException
)
private val s1_exceptionOut = VecInit((s1_itlbException zip s1_pmpException).map { case (i, p) => i || p })
/**
******************************************************************************
@ -418,7 +415,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
private val s2_shouldFetch = VecInit((0 until PortNumber).map { i =>
(!s2_hits(i) || s2_corruptRefetch(i)) &&
(if (i == 0) true.B else s2_doubleline) &&
!ExceptionType.hasException(s2_exception.take(i + 1)) &&
s2_exception.take(i + 1).map(_.isNone).reduce(_ && _) &&
s2_isMmio.take(i + 1).map(!_).reduce(_ && _)
})
@ -446,14 +443,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
private val s2_fetchFinish = !s2_shouldFetch.reduce(_ || _)
// also raise af if l2 corrupt is detected
private val s2_l2Exception = VecInit(s2_l2Corrupt.map(ExceptionType.fromTilelink))
private val s2_l2Exception = VecInit(s2_l2Corrupt.map(corrupt => ExceptionType(hasAf = corrupt)))
// NOTE: do NOT raise af if meta/data corrupt is detected, they are automatically recovered by re-fetching from L2
// merge s2 exceptions, itlb has the highest priority, then l2
private val s2_exceptionOut = ExceptionType.merge(
s2_exception, // includes itlb/pmp exception
s2_l2Exception
)
// merge s2 exceptions, itlb/pmp has the highest priority, then l2
private val s2_exceptionOut = VecInit((s2_exception zip s2_l2Exception).map { case (in, l2) => in || l2 })
/**
******************************************************************************
@ -468,7 +462,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
toIfu.bits.pAddr := s2_pAddr
(0 until PortNumber).foreach { i =>
val needThisLine = if (i == 0) true.B else s2_doubleline
toIfu.bits.exception(i) := Mux(needThisLine, s2_exceptionOut(i), ExceptionType.none)
toIfu.bits.exception(i) := Mux(needThisLine, s2_exceptionOut(i), ExceptionType.None)
toIfu.bits.pmpMmio(i) := Mux(needThisLine, s2_pmpMmio(i), false.B)
toIfu.bits.itlbPbmt(i) := Mux(needThisLine, s2_itlbPbmt(i), Pbmt.pma)
}
@ -507,11 +501,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
io.perf.hit0Miss1 := s2_hits(0) && !s2_hits(1) && s2_doubleline
io.perf.miss0Hit1 := !s2_hits(0) && s2_hits(1) && s2_doubleline
io.perf.miss0Miss1 := !s2_hits(0) && !s2_hits(1) && s2_doubleline
io.perf.hit0Except1 := s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline
io.perf.miss0Except1 := !s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline
io.perf.hit0Except1 := s2_hits(0) && s2_exception(1).hasException && s2_doubleline
io.perf.miss0Except1 := !s2_hits(0) && s2_exception(1).hasException && s2_doubleline
io.perf.bankHit(0) := s2_hits(0)
io.perf.bankHit(1) := s2_hits(1) && s2_doubleline
io.perf.except0 := ExceptionType.hasException(s2_exception(0))
io.perf.except0 := s2_exception(0).hasException
io.perf.hit := s2_hits(0) && (!s2_doubleline || s2_hits(1))
/** <PERF> fetch bubble generated by icache miss */
@ -553,7 +547,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
*/
if (env.EnableDifftest) {
val discards = (0 until PortNumber).map { i =>
ExceptionType.hasException(toIfu.bits.exception(i)) ||
toIfu.bits.exception(i).hasException ||
toIfu.bits.pmpMmio(i) ||
Pbmt.isUncache(toIfu.bits.itlbPbmt(i))
}

View File

@ -22,13 +22,12 @@ import utility.DataHoldBypass
import utility.PriorityMuxDefault
import utility.ValidHold
import utility.XSPerfAccumulate
import utils.NamedUInt
import utils.EnumUInt
import xiangshan.cache.mmu.Pbmt
import xiangshan.cache.mmu.TlbCmd
import xiangshan.cache.mmu.TlbRequestIO
import xiangshan.cache.mmu.ValidHoldBypass // FIXME: should move this to utility?
import xiangshan.frontend.ExceptionType
import xiangshan.frontend.PrunedAddr
import xiangshan.frontend.PrunedAddrInit
import xiangshan.frontend.ftq.BpuFlushInfo
@ -117,7 +116,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
private val s1_backendException = RegEnable(s0_backendException, 0.U.asTypeOf(s0_backendException), s0_fire)
private def nS1FsmState: Int = 5
private object S1FsmState extends NamedUInt(log2Up(nS1FsmState)) {
private object S1FsmState extends EnumUInt(nS1FsmState) {
def Idle: UInt = 0.U(width.W)
def ItlbResend: UInt = 1.U(width.W)
def MetaResend: UInt = 2.U(width.W)
@ -185,7 +184,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
Mux(tlbValidPulse(i), s1_pAddrWire(i), s1_pAddrReg(i))
})
private val s1_itlbExceptionRaw = VecInit((0 until PortNumber).map { i =>
DataHoldBypass(ExceptionType.fromTlbResp(fromItlb(i).bits), 0.U(ExceptionType.width.W), tlbValidPulse(i))
DataHoldBypass(ExceptionType.fromTlbResp(fromItlb(i).bits), ExceptionType.None, tlbValidPulse(i))
})
private val s1_itlbPbmt = VecInit((0 until PortNumber).map { i =>
DataHoldBypass(fromItlb(i).bits.pbmt(0), 0.U.asTypeOf(fromItlb(i).bits.pbmt(0)), tlbValidPulse(i))
@ -207,10 +206,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
// merge backend exception and itlb exception
// for area concern, we don't have 64 bits vaddr in frontend, but spec asks page fault when high bits are not all 0/1
// this check is finished in backend, and passed to frontend with redirect, we see it as a part of itlb exception
private val s1_itlbException = ExceptionType.merge(
s1_backendException,
s1_itlbExceptionRaw
)
private val s1_itlbException = VecInit((s1_backendException zip s1_itlbExceptionRaw).map { case (b, i) => b || i })
// debug
dontTouch(s1_itlbExceptionRaw)
dontTouch(s1_itlbException)
@ -221,7 +217,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
* see GPAMem: https://github.com/OpenXiangShan/XiangShan/blob/344cf5d55568dd40cd658a9ee66047a505eeb504/src/main/scala/xiangshan/backend/GPAMem.scala#L33-L34
* see also: https://github.com/OpenXiangShan/XiangShan/blob/344cf5d55568dd40cd658a9ee66047a505eeb504/src/main/scala/xiangshan/frontend/IFU.scala#L374-L375
*/
private val s1_itlbExceptionIsGpf = VecInit(s1_itlbException.map(_ === ExceptionType.gpf))
private val s1_itlbExceptionIsGpf = VecInit(s1_itlbException.map(_.isGpf))
private val s1_gpAddr = PriorityMuxDefault(
s1_itlbExceptionIsGpf zip (0 until PortNumber).map(i => s1_gpAddrRaw(i) - (i << blockOffBits).U),
0.U.asTypeOf(s1_gpAddrRaw(0))
@ -326,7 +322,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
toWayLookup.bits.itlbException(i) := Mux(
excpValid,
s1_itlbException(i), // includes backend exception
ExceptionType.none
ExceptionType.None
)
toWayLookup.bits.itlbPbmt(i) := Mux(excpValid, s1_itlbPbmt(i), Pbmt.pma)
}
@ -359,15 +355,12 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
p.bits.size := 3.U
p.bits.cmd := TlbCmd.exec
}
private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPMPResp))
private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPmpResp))
private val s1_pmpMmio = VecInit(fromPmp.map(_.mmio))
// merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next
// for timing consideration, meta_corrupt is not merged, and it will NOT cancel prefetch
private val s1_exceptionOut = ExceptionType.merge(
s1_itlbException, // includes backend exception
s1_pmpException
)
// here, itlb exception includes backend exception
private val s1_exceptionOut = VecInit((s1_itlbException zip s1_pmpException).map { case (i, p) => i || p })
// merge pmp mmio and itlb pbmt
private val s1_isMmio = VecInit((s1_pmpMmio zip s1_itlbPbmt).map { case (mmio, pbmt) =>
@ -503,7 +496,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
*/
private val s2_miss = VecInit((0 until PortNumber).map { i =>
!s2_hits(i) && (if (i == 0) true.B else s2_doubleline) &&
!ExceptionType.hasException(s2_exception.take(i + 1)) &&
s2_exception.take(i + 1).map(_.isNone).reduce(_ && _) &&
s2_isMmio.take(i + 1).map(!_).reduce(_ && _)
})

View File

@ -123,7 +123,7 @@ class ICacheWayLookup(implicit p: Parameters) extends ICacheModule with ICacheMi
io.write.ready := !full && !gpfStall
when(io.write.fire) {
entries(writePtr.value) := io.write.bits.entry
when(io.write.bits.itlbException.map(_ === ExceptionType.gpf).reduce(_ || _)) {
when(io.write.bits.itlbException.map(_.isGpf).reduce(_ || _)) {
// if gpfEntry is bypassed, we don't need to save it
// note this will override the read (L156)
gpfEntry.valid := !(canBypass && io.read.fire)

View File

@ -18,7 +18,7 @@ package xiangshan.frontend.ifu
import chisel3._
import chisel3.util._
import org.chipsalliance.cde.config.Parameters
import utils.NamedUInt
import utils.EnumUInt
import xiangshan.frontend.PrunedAddr
/* ***
@ -32,14 +32,14 @@ import xiangshan.frontend.PrunedAddr
* *** */
/* ***** PreDecode ***** */
object PreDecodeFaultType extends NamedUInt(3) {
def noFault: UInt = "b000".U(width.W)
def jalFault: UInt = "b001".U(width.W) // not CFI taken or invalid instruction taken
def retFault: UInt = "b010".U(width.W) // not CFI taken or invalid instruction taken
def targetFault: UInt = "b011".U(width.W)
def notCfiFault: UInt = "b100".U(width.W) // not CFI taken or invalid instruction taken
def invalidTaken: UInt = "b101".U(width.W)
def jalrFault: UInt = "b110".U(width.W)
object PreDecodeFaultType extends EnumUInt(7) {
def NoFault: UInt = 0.U(width.W)
def JalFault: UInt = 1.U(width.W) // not CFI taken or invalid instruction taken
def RetFault: UInt = 2.U(width.W) // not CFI taken or invalid instruction taken
def TargetFault: UInt = 3.U(width.W)
def NotCfiFault: UInt = 4.U(width.W) // not CFI taken or invalid instruction taken
def InvalidTaken: UInt = 5.U(width.W)
def JalrFault: UInt = 6.U(width.W)
}
/* ***** Ifu last half ***** */

View File

@ -31,14 +31,14 @@ trait PreDecodeHelper extends HasXSParameter {
def isLink(reg: UInt): Bool = reg === 1.U || reg === 5.U
def getBrType(inst: UInt): UInt =
ListLookup(inst, List(BrType.notCFI), PreDecodeInst.brTable).head
ListLookup(inst, List(BrType.NotCfi), PreDecodeInst.brTable).head
def getBrInfo(inst: UInt): (UInt, Bool, Bool) = {
val brType = getBrType(inst)
val rd = Mux(isRVC(inst), inst(12), inst(11, 7))
val rs = Mux(isRVC(inst), Mux(brType === BrType.jal, 0.U, inst(11, 7)), inst(19, 15))
val isCall = (brType === BrType.jal && !isRVC(inst) || brType === BrType.jalr) && isLink(rd) // Only for RV64
val isRet = brType === BrType.jalr && isLink(rs) && !isCall
val rs = Mux(isRVC(inst), Mux(brType === BrType.Jal, 0.U, inst(11, 7)), inst(19, 15))
val isCall = (brType === BrType.Jal && !isRVC(inst) || brType === BrType.Jalr) && isLink(rd) // Only for RV64
val isRet = brType === BrType.Jalr && isLink(rs) && !isCall
(brType, isCall, isRet)
}

View File

@ -32,7 +32,7 @@ import utility.XSDebug
import utility.XSError
import utility.XSPerfAccumulate
import utility.XSPerfHistogram
import utils.NamedUInt
import utils.EnumUInt
import xiangshan.FrontendTdataDistributeIO
import xiangshan.RedirectLevel
import xiangshan.RobCommitInfo
@ -331,21 +331,19 @@ class Ifu(implicit p: Parameters) extends IfuModule
// FIXME: raise af if one fetch block crosses the cacheable/un-cacheable boundary, might not correct
private val s2_mmioMismatchException = VecInit(Seq(
ExceptionType.none, // mark the exception only on the second line
Mux(
// not double-line, skip check
!fromICache.bits.doubleline || (
ExceptionType.None, // mark the exception only on the second line
ExceptionType(hasAf =
// if not double-line, skip check
fromICache.bits.doubleline && (
// is double-line, ask for consistent pmp_mmio and itlb_pbmt value
fromICache.bits.pmpMmio(0) === fromICache.bits.pmpMmio(1) &&
fromICache.bits.itlbPbmt(0) === fromICache.bits.itlbPbmt(1)
),
ExceptionType.none,
ExceptionType.af
fromICache.bits.pmpMmio(0) =/= fromICache.bits.pmpMmio(1) ||
fromICache.bits.itlbPbmt(0) =/= fromICache.bits.itlbPbmt(1)
)
)
))
// merge exceptions
private val s2_exception = ExceptionType.merge(s2_exceptionIn, s2_mmioMismatchException)
private val s2_exception = VecInit((s2_exceptionIn zip s2_mmioMismatchException).map { case (in, m) => in || m })
// we need only the first port, as the second is asked to be the same
private val s2_pmpMmio = fromICache.bits.pmpMmio(0)
@ -379,7 +377,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
private val s2_instrRange = s2_jumpRange & s2_ftrRange
private val s2_exceptionVec = VecInit((0 until PredictWidth).map(i =>
MuxCase(
ExceptionType.none,
ExceptionType.None,
Seq(
!isNextLine(s2_pc(i), s2_ftqReq.startAddr) -> s2_exception(0),
(isNextLine(s2_pc(i), s2_ftqReq.startAddr) && s2_doubleline) -> s2_exception(1)
@ -454,9 +452,9 @@ class Ifu(implicit p: Parameters) extends IfuModule
*/
private val s2_crossPageExceptionVec = VecInit((0 until PredictWidth).map { i =>
Mux(
isLastInLine(s2_pc(i)) && !s2_pd(i).isRVC && s2_doubleline && !ExceptionType.hasException(s2_exception(0)),
isLastInLine(s2_pc(i)) && !s2_pd(i).isRVC && s2_doubleline && s2_exception(0).isNone,
s2_exception(1),
ExceptionType.none
ExceptionType.None
)
})
XSPerfAccumulate("fetch_bubble_icache_not_resp", s2_valid && !icacheRespAllValid)
@ -563,7 +561,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
/* *** mmio *** */
private def nMmioFsmState = 11
private object MmioFsmState extends NamedUInt(log2Up(nMmioFsmState)) {
private object MmioFsmState extends EnumUInt(nMmioFsmState) {
def Idle: UInt = 0.U(width.W)
def WaitLastCommit: UInt = 1.U(width.W)
def SendReq: UInt = 2.U(width.W)
@ -580,7 +578,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
private val mmioState = RegInit(MmioFsmState.Idle)
private val mmioData = RegInit(VecInit(Seq.fill(2)(0.U(16.W))))
private val mmioException = RegInit(0.U(ExceptionType.width.W))
private val mmioException = RegInit(ExceptionType.None)
private val mmioIsRvc = RegInit(false.B)
private val mmioHasResend = RegInit(false.B)
private val mmioResendAddr = RegInit(PrunedAddrInit(0.U(PAddrBits.W)))
@ -591,7 +589,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
private def mmioReset(): Unit = {
mmioState := MmioFsmState.Idle
mmioData.foreach(_ := 0.U)
mmioException := ExceptionType.none
mmioException := ExceptionType.None
mmioIsRvc := false.B
mmioHasResend := false.B
mmioResendAddr := PrunedAddrInit(0.U(PAddrBits.W))
@ -607,7 +605,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
// do mmio fetch only when pmp/pbmt shows it is a un-cacheable address and no exception occurs
private val s3_reqIsMmio =
s3_valid && (s3_pmpMmio || Pbmt.isUncache(s3_itlbPbmt)) && !ExceptionType.hasException(s3_exception)
s3_valid && (s3_pmpMmio || Pbmt.isUncache(s3_itlbPbmt)) && s3_exception.map(_.isNone).reduce(_ && _)
private val mmioCommit = VecInit(io.robCommits.map { commit =>
commit.valid && commit.bits.ftqIdx === s3_ftqReq.ftqIdx && commit.bits.ftqOffset === 0.U
}).asUInt.orR
@ -682,9 +680,9 @@ class Ifu(implicit p: Parameters) extends IfuModule
is(MmioFsmState.WaitResp) {
when(fromUncache.fire) {
val respIsRVC = isRVC(fromUncache.bits.data(1, 0))
val exception = ExceptionType.fromTilelink(fromUncache.bits.corrupt)
val exception = ExceptionType(hasAf = fromUncache.bits.corrupt)
// when response is not RVC, and lower bits of pAddr is 6 => request crosses 8B boundary, need resend
val needResend = !respIsRVC && s3_pAddr(0)(2, 1) === 3.U && !ExceptionType.hasException(exception)
val needResend = !respIsRVC && s3_pAddr(0)(2, 1) === 3.U && exception.isNone
mmioState := Mux(needResend, MmioFsmState.SendTlb, MmioFsmState.WaitCommit)
mmioException := exception
mmioIsRvc := respIsRVC
@ -702,16 +700,13 @@ class Ifu(implicit p: Parameters) extends IfuModule
when(io.itlb.resp.fire) {
// we are using a blocked tlb, so resp.fire must have !resp.bits.miss
assert(!io.itlb.resp.bits.miss, "blocked mode iTLB miss when resp.fire")
val tlbException = ExceptionType.fromTlbResp(io.itlb.resp.bits)
val itlbException = ExceptionType.fromTlbResp(io.itlb.resp.bits)
// if itlb re-check respond pbmt mismatch with previous check, must be access fault
val pbmtMismatchException = Mux(
io.itlb.resp.bits.pbmt(0) =/= s3_itlbPbmt,
ExceptionType.af,
ExceptionType.none
)
val exception = ExceptionType.merge(tlbException, pbmtMismatchException)
val pbmtMismatchException = ExceptionType(hasAf = io.itlb.resp.bits.pbmt(0) =/= s3_itlbPbmt)
// merge, itlbException has higher priority
val exception = itlbException || pbmtMismatchException
// if tlb has exception, abort checking pmp, just send instr & exception to iBuffer and wait for commit
mmioState := Mux(ExceptionType.hasException(exception), MmioFsmState.WaitCommit, MmioFsmState.SendPmp)
mmioState := Mux(exception.hasException, MmioFsmState.WaitCommit, MmioFsmState.SendPmp)
// also save itlb response
mmioException := exception
mmioResendAddr := io.itlb.resp.bits.paddr(0)
@ -721,16 +716,13 @@ class Ifu(implicit p: Parameters) extends IfuModule
}
is(MmioFsmState.SendPmp) {
val pmpException = ExceptionType.fromPMPResp(io.pmp.resp)
val pmpException = ExceptionType.fromPmpResp(io.pmp.resp)
// if pmp re-check respond mismatch with previous check, must be access fault
val mmioMismatchException = Mux(
io.pmp.resp.mmio =/= s3_pmpMmio,
ExceptionType.af,
ExceptionType.none
)
val exception = ExceptionType.merge(pmpException, mmioMismatchException)
val mmioMismatchException = ExceptionType(hasAf = io.pmp.resp.mmio =/= s3_pmpMmio)
// merge, pmpException has higher priority
val exception = pmpException || mmioMismatchException
// if pmp has exception, abort sending request, just send instr & exception to iBuffer and wait for commit
mmioState := Mux(ExceptionType.hasException(exception), MmioFsmState.WaitCommit, MmioFsmState.ResendReq)
mmioState := Mux(exception.hasException, MmioFsmState.WaitCommit, MmioFsmState.ResendReq)
// also save pmp response
mmioException := exception
}
@ -742,7 +734,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
is(MmioFsmState.WaitResendResp) {
when(fromUncache.fire) {
mmioState := MmioFsmState.WaitCommit
mmioException := ExceptionType.fromTilelink(fromUncache.bits.corrupt)
mmioException := ExceptionType(hasAf = fromUncache.bits.corrupt)
mmioData(1) := fromUncache.bits.data(15, 0)
}
}
@ -861,7 +853,9 @@ class Ifu(implicit p: Parameters) extends IfuModule
a.valid := checkerOutStage1.fixedTaken(i) && !s3_reqIsMmio
}
io.toIBuffer.bits.foldpc := s3_foldPc
io.toIBuffer.bits.exceptionType := ExceptionType.merge(s3_exceptionVec, s3_crossPageExceptionVec)
io.toIBuffer.bits.exceptionType := VecInit((s3_exceptionVec zip s3_crossPageExceptionVec).map { case (e, ce) =>
e || ce // merge, cross page fix has lower priority
})
// backendException only needs to be set for the first instruction.
// Other instructions in the same block may have pf or af set,
// which is a side effect of the first instruction and actually not necessary.
@ -869,7 +863,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
case 0 => s3_isBackendException
case _ => false.B
}
io.toIBuffer.bits.crossPageIPFFix := s3_crossPageExceptionVec.map(ExceptionType.hasException)
io.toIBuffer.bits.crossPageIPFFix := s3_crossPageExceptionVec.map(_.hasException)
io.toIBuffer.bits.illegalInstr := s3_ill
io.toIBuffer.bits.triggered := s3_triggered
@ -899,8 +893,8 @@ class Ifu(implicit p: Parameters) extends IfuModule
// s3_gpAddr is valid iff gpf is detected
io.toBackend.gpaddrMem_wen := s3_toIBufferValid && Mux(
s3_reqIsMmio,
mmioException === ExceptionType.gpf,
s3_exception.map(_ === ExceptionType.gpf).reduce(_ || _)
mmioException.isGpf,
s3_exception.map(_.isGpf).reduce(_ || _)
)
io.toBackend.gpaddrMem_waddr := s3_ftqReq.ftqIdx.value
io.toBackend.gpaddrMem_wdata.gpaddr := Mux(s3_reqIsMmio, mmioResendGpAddr.toUInt, s3_gpAddr.toUInt)
@ -951,7 +945,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
io.toIBuffer.bits.exceptionType(0) := mmioException
// exception can happen in next page only when resend
io.toIBuffer.bits.crossPageIPFFix(0) := mmioHasResend && ExceptionType.hasException(mmioException)
io.toIBuffer.bits.crossPageIPFFix(0) := mmioHasResend && mmioException.hasException
io.toIBuffer.bits.illegalInstr(0) := mmioRvcExpander.io.ill
io.toIBuffer.bits.enqEnable := s3_mmioRange.asUInt
@ -1053,12 +1047,12 @@ class Ifu(implicit p: Parameters) extends IfuModule
/* write back flush type */
private val checkFaultType = wbCheckResultStage2.faultType
private val checkJalFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.jalFault).reduce(_ || _)
private val checkJalrFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.jalrFault).reduce(_ || _)
private val checkRetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.retFault).reduce(_ || _)
private val checkTargetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.targetFault).reduce(_ || _)
private val checkNotCFIFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.notCfiFault).reduce(_ || _)
private val checkInvalidTaken = wbValid && checkFaultType.map(_ === PreDecodeFaultType.invalidTaken).reduce(_ || _)
private val checkJalFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.JalFault).reduce(_ || _)
private val checkJalrFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.JalrFault).reduce(_ || _)
private val checkRetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.RetFault).reduce(_ || _)
private val checkTargetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.TargetFault).reduce(_ || _)
private val checkNotCFIFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.NotCfiFault).reduce(_ || _)
private val checkInvalidTaken = wbValid && checkFaultType.map(_ === PreDecodeFaultType.InvalidTaken).reduce(_ || _)
XSPerfAccumulate("predecode_flush_jalFault", checkJalFault)
XSPerfAccumulate("predecode_flush_jalrFault", checkJalrFault)

View File

@ -139,14 +139,14 @@ class PredChecker(implicit p: Parameters) extends IfuModule {
io.resp.stage2Out.faultType.zipWithIndex.foreach { case (faultType, i) =>
faultType := MuxCase(
PreDecodeFaultType.noFault,
PreDecodeFaultType.NoFault,
Seq(
jalFaultVecNext(i) -> PreDecodeFaultType.jalFault,
jalrFaultVecNext(i) -> PreDecodeFaultType.jalrFault,
retFaultVecNext(i) -> PreDecodeFaultType.retFault,
targetFault(i) -> PreDecodeFaultType.targetFault,
notCFITakenNext(i) -> PreDecodeFaultType.notCfiFault,
invalidTakenNext(i) -> PreDecodeFaultType.invalidTaken
jalFaultVecNext(i) -> PreDecodeFaultType.JalFault,
jalrFaultVecNext(i) -> PreDecodeFaultType.JalrFault,
retFaultVecNext(i) -> PreDecodeFaultType.RetFault,
targetFault(i) -> PreDecodeFaultType.TargetFault,
notCFITakenNext(i) -> PreDecodeFaultType.NotCfiFault,
invalidTakenNext(i) -> PreDecodeFaultType.InvalidTaken
)
)
}

View File

@ -21,7 +21,7 @@ import freechips.rocketchip.tilelink.TLBundleA
import freechips.rocketchip.tilelink.TLBundleD
import freechips.rocketchip.tilelink.TLEdgeOut
import org.chipsalliance.cde.config.Parameters
import utils.NamedUInt
import utils.EnumUInt
// One miss entry deals with one mmio request
class InstrUncacheEntry(edge: TLEdgeOut)(implicit p: Parameters) extends InstrUncacheModule {
@ -40,7 +40,7 @@ class InstrUncacheEntry(edge: TLEdgeOut)(implicit p: Parameters) extends InstrUn
val io: InstrUncacheEntryIO = IO(new InstrUncacheEntryIO(edge))
private def nState: Int = 4
private object State extends NamedUInt(log2Up(nState)) {
private object State extends EnumUInt(nState) {
def Invalid: UInt = 0.U(width.W)
def RefillReq: UInt = 1.U(width.W)
def RefillResp: UInt = 2.U(width.W)