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
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:
parent
3bfc5a3c90
commit
cbea99c932
|
|
@ -33,12 +33,12 @@ object PreDecodeInst {
|
||||||
|
|
||||||
val brTable = Array(
|
val brTable = Array(
|
||||||
// C_JAL -> List(BrType.jal),
|
// C_JAL -> List(BrType.jal),
|
||||||
C_EBREAK -> List(BrType.notCFI), // c.ebreak should not be decoded as jalr, higher priority than c.jalr
|
C_EBREAK -> List(BrType.NotCfi), // c.ebreak should not be decoded as jalr, higher priority than c.jalr
|
||||||
C_J -> List(BrType.jal),
|
C_J -> List(BrType.Jal),
|
||||||
C_JALR -> List(BrType.jalr),
|
C_JALR -> List(BrType.Jalr),
|
||||||
C_BRANCH -> List(BrType.branch),
|
C_BRANCH -> List(BrType.Branch),
|
||||||
JAL -> List(BrType.jal),
|
JAL -> List(BrType.Jal),
|
||||||
JALR -> List(BrType.jalr),
|
JALR -> List(BrType.Jalr),
|
||||||
BRANCH -> List(BrType.branch)
|
BRANCH -> List(BrType.Branch)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,9 @@ object Itype extends NamedUInt(4) {
|
||||||
def jumpTypeGen(brType: UInt, rd: OpRegType, rs: OpRegType): UInt = {
|
def jumpTypeGen(brType: UInt, rd: OpRegType, rs: OpRegType): UInt = {
|
||||||
|
|
||||||
val isEqualRdRs = rd === rs
|
val isEqualRdRs = rd === rs
|
||||||
val isJal = brType === BrType.jal
|
val isJal = brType === BrType.Jal
|
||||||
val isJalr = brType === BrType.jalr
|
val isJalr = brType === BrType.Jalr
|
||||||
val isBranch = brType === BrType.branch
|
val isBranch = brType === BrType.Branch
|
||||||
|
|
||||||
// push to RAS when rd is link, pop from RAS when rs is link
|
// 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
|
def isUninferableCall = isJalr && rd.isLink && (!rs.isLink || rs.isLink && isEqualRdRs) //8 push
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import ftq.FtqRedirectSramEntry
|
||||||
import ftq.FtqRfComponents
|
import ftq.FtqRfComponents
|
||||||
import org.chipsalliance.cde.config.Parameters
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import utility._
|
import utility._
|
||||||
import utils.NamedUInt
|
import utils.EnumUInt
|
||||||
import xiangshan._
|
import xiangshan._
|
||||||
import xiangshan.backend.GPAMemEntry
|
import xiangshan.backend.GPAMemEntry
|
||||||
import xiangshan.backend.fu.PMPRespBundle
|
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 {
|
class FtqToPrefetchBundle(implicit p: Parameters) extends XSBundle {
|
||||||
val req: FtqICacheInfo = new FtqICacheInfo
|
val req: FtqICacheInfo = new FtqICacheInfo
|
||||||
val backendException: UInt = ExceptionType()
|
val backendException: ExceptionType = new ExceptionType
|
||||||
}
|
}
|
||||||
|
|
||||||
class FtqToFetchBundle(implicit p: Parameters) extends XSBundle with HasICacheParameters {
|
class FtqToFetchBundle(implicit p: Parameters) extends XSBundle with HasICacheParameters {
|
||||||
|
|
@ -152,138 +152,94 @@ class mmioCommitRead(implicit p: Parameters) extends XSBundle {
|
||||||
val mmioLastCommit = Input(Bool())
|
val mmioLastCommit = Input(Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
object ExceptionType extends NamedUInt(2) {
|
class ExceptionType extends Bundle {
|
||||||
def none: UInt = "b00".U(width.W)
|
val value: UInt = ExceptionType.Value()
|
||||||
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
|
|
||||||
|
|
||||||
def hasException(e: UInt): Bool = e =/= none
|
def isNone: Bool = value === ExceptionType.Value.None
|
||||||
def hasException(e: Vec[UInt]): Bool = e.map(_ =/= none).reduce(_ || _)
|
def isPf: Bool = value === ExceptionType.Value.Pf
|
||||||
def hasException(e: IndexedSeq[UInt]): Bool = hasException(VecInit(e))
|
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(
|
assert(
|
||||||
PopCount(VecInit(has_pf, has_gpf, has_af)) <= 1.U,
|
PopCount(VecInit(hasPf, hasGpf, hasAf)) <= 1.U,
|
||||||
"ExceptionType.fromOH receives input that is not one-hot: pf=%d, gpf=%d, af=%d",
|
"ExceptionType receives input that is not one-hot: pf=%d, gpf=%d, af=%d",
|
||||||
has_pf,
|
hasPf,
|
||||||
has_gpf,
|
hasGpf,
|
||||||
has_af
|
hasAf
|
||||||
)
|
)
|
||||||
// input is at-most-one-hot encoded, so we don't worry about priority here.
|
// input is at-most-one-hot encoded, so we don't worry about priority here.
|
||||||
MuxCase(
|
MuxCase(
|
||||||
none,
|
None,
|
||||||
Seq(
|
Seq(
|
||||||
has_pf -> pf,
|
hasPf -> Pf,
|
||||||
has_gpf -> gpf,
|
hasGpf -> Gpf,
|
||||||
has_af -> af
|
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
|
// 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)
|
require(useDup >= 0 && useDup < resp.excp.length)
|
||||||
// itlb is guaranteed to respond at most one exception
|
// itlb is guaranteed to respond at most one exception
|
||||||
fromOH(
|
apply(
|
||||||
resp.excp(useDup).pf.instr,
|
hasPf = resp.excp(useDup).pf.instr,
|
||||||
resp.excp(useDup).gpf.instr,
|
hasGpf = resp.excp(useDup).gpf.instr,
|
||||||
resp.excp(useDup).af.instr
|
hasAf = resp.excp(useDup).af.instr
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// raise af if pmp check failed
|
// raise af if pmp check failed
|
||||||
def fromPMPResp(resp: PMPRespBundle): UInt =
|
def fromPmpResp(resp: PMPRespBundle): ExceptionType =
|
||||||
Mux(resp.instr, af, none)
|
apply(hasAf = resp.instr)
|
||||||
|
|
||||||
// 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
|
object BrType extends EnumUInt(4) {
|
||||||
*
|
def NotCfi: UInt = 0.U(width.W)
|
||||||
* Exceptions that are further to the left in the parameter list have higher priority
|
def Branch: UInt = 1.U(width.W)
|
||||||
* @example
|
def Jal: UInt = 2.U(width.W)
|
||||||
* {{{
|
def Jalr: UInt = 3.U(width.W)
|
||||||
* 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)): _*)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PreDecodeInfo extends Bundle { // 8 bit
|
class PreDecodeInfo extends Bundle { // 8 bit
|
||||||
|
|
@ -293,10 +249,10 @@ class PreDecodeInfo extends Bundle { // 8 bit
|
||||||
val isCall = Bool()
|
val isCall = Bool()
|
||||||
val isRet = Bool()
|
val isRet = Bool()
|
||||||
// val excType = UInt(3.W)
|
// val excType = UInt(3.W)
|
||||||
def isBr = brType === BrType.branch
|
def isBr = brType === BrType.Branch
|
||||||
def isJal = brType === BrType.jal
|
def isJal = brType === BrType.Jal
|
||||||
def isJalr = brType === BrType.jalr
|
def isJalr = brType === BrType.Jalr
|
||||||
def notCFI = brType === BrType.notCFI
|
def notCFI = brType === BrType.NotCfi
|
||||||
}
|
}
|
||||||
|
|
||||||
class FetchToIBuffer(implicit p: Parameters) extends XSBundle {
|
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 foldpc = Vec(PredictWidth, UInt(MemPredPCWidth.W))
|
||||||
val ftqOffset = Vec(PredictWidth, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))
|
val ftqOffset = Vec(PredictWidth, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W)))
|
||||||
val backendException = Vec(PredictWidth, Bool())
|
val backendException = Vec(PredictWidth, Bool())
|
||||||
val exceptionType = Vec(PredictWidth, ExceptionType())
|
val exceptionType = Vec(PredictWidth, new ExceptionType)
|
||||||
val crossPageIPFFix = Vec(PredictWidth, Bool())
|
val crossPageIPFFix = Vec(PredictWidth, Bool())
|
||||||
val illegalInstr = Vec(PredictWidth, Bool())
|
val illegalInstr = Vec(PredictWidth, Bool())
|
||||||
val triggered = Vec(PredictWidth, TriggerAction())
|
val triggered = Vec(PredictWidth, TriggerAction())
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,41 @@ class IBufferIO(implicit p: Parameters) extends XSBundle {
|
||||||
val stallReason = new StallReasonIO(DecodeWidth)
|
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 {
|
class IBufEntry(implicit p: Parameters) extends XSBundle {
|
||||||
val inst = UInt(32.W)
|
val inst = UInt(32.W)
|
||||||
val pc = PrunedAddr(VAddrBits)
|
val pc = PrunedAddr(VAddrBits)
|
||||||
|
|
@ -109,48 +144,6 @@ class IBufEntry(implicit p: Parameters) extends XSBundle {
|
||||||
cf.debug_seqNum := debug_seqNum
|
cf.debug_seqNum := debug_seqNum
|
||||||
cf
|
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 {
|
class IBuffer(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper with HasPerfEvents {
|
||||||
|
|
|
||||||
|
|
@ -159,13 +159,13 @@ class Ftq(implicit p: Parameters) extends FtqModule
|
||||||
// raises IPF or IAF, which is ifuWbPtr_write or IfuPtr_write.
|
// 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
|
// 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.
|
// 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))
|
val backendPcFaultPtr = RegInit(FtqPtr(false.B, 0.U))
|
||||||
when(fromBackendRedirect.valid) {
|
when(fromBackendRedirect.valid) {
|
||||||
backendException := ExceptionType.fromOH(
|
backendException := ExceptionType(
|
||||||
has_pf = fromBackendRedirect.bits.cfiUpdate.backendIPF,
|
hasPf = fromBackendRedirect.bits.cfiUpdate.backendIPF,
|
||||||
has_gpf = fromBackendRedirect.bits.cfiUpdate.backendIGPF,
|
hasGpf = fromBackendRedirect.bits.cfiUpdate.backendIGPF,
|
||||||
has_af = fromBackendRedirect.bits.cfiUpdate.backendIAF
|
hasAf = fromBackendRedirect.bits.cfiUpdate.backendIAF
|
||||||
)
|
)
|
||||||
when(
|
when(
|
||||||
fromBackendRedirect.bits.cfiUpdate.backendIPF || fromBackendRedirect.bits.cfiUpdate.backendIGPF ||
|
fromBackendRedirect.bits.cfiUpdate.backendIPF || fromBackendRedirect.bits.cfiUpdate.backendIGPF ||
|
||||||
|
|
@ -174,7 +174,7 @@ class Ftq(implicit p: Parameters) extends FtqModule
|
||||||
backendPcFaultPtr := ifuWbPtr_write
|
backendPcFaultPtr := ifuWbPtr_write
|
||||||
}
|
}
|
||||||
}.elsewhen(ifuWbPtr =/= backendPcFaultPtr) {
|
}.elsewhen(ifuWbPtr =/= backendPcFaultPtr) {
|
||||||
backendException := ExceptionType.none
|
backendException := ExceptionType.None
|
||||||
}
|
}
|
||||||
|
|
||||||
// **********************************************************************
|
// **********************************************************************
|
||||||
|
|
@ -473,7 +473,7 @@ class Ftq(implicit p: Parameters) extends FtqModule
|
||||||
copy.ftqIdx := ifuPtr
|
copy.ftqIdx := ifuPtr
|
||||||
}
|
}
|
||||||
io.toICache.fetchReq.bits.isBackendException :=
|
io.toICache.fetchReq.bits.isBackendException :=
|
||||||
ExceptionType.hasException(backendException) && backendPcFaultPtr === ifuPtr
|
backendException.hasException && backendPcFaultPtr === ifuPtr
|
||||||
|
|
||||||
io.toICache.prefetchReq.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr
|
io.toICache.prefetchReq.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr
|
||||||
io.toICache.prefetchReq.bits.req.fromFtqPcBundle(toPrefetchPcBundle)
|
io.toICache.prefetchReq.bits.req.fromFtqPcBundle(toPrefetchPcBundle)
|
||||||
|
|
@ -481,7 +481,7 @@ class Ftq(implicit p: Parameters) extends FtqModule
|
||||||
io.toICache.prefetchReq.bits.backendException := Mux(
|
io.toICache.prefetchReq.bits.backendException := Mux(
|
||||||
backendPcFaultPtr === pfPtr,
|
backendPcFaultPtr === pfPtr,
|
||||||
backendException,
|
backendException,
|
||||||
ExceptionType.none
|
ExceptionType.None
|
||||||
)
|
)
|
||||||
// io.toICache.fetchReq.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr
|
// io.toICache.fetchReq.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr
|
||||||
// io.toICache.fetchReq.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) =>
|
// io.toICache.fetchReq.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) =>
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ class ICacheRespBundle(implicit p: Parameters) extends ICacheBundle {
|
||||||
val vAddr: Vec[PrunedAddr] = Vec(PortNumber, PrunedAddr(VAddrBits))
|
val vAddr: Vec[PrunedAddr] = Vec(PortNumber, PrunedAddr(VAddrBits))
|
||||||
val data: UInt = UInt(blockBits.W)
|
val data: UInt = UInt(blockBits.W)
|
||||||
val pAddr: Vec[PrunedAddr] = Vec(PortNumber, PrunedAddr(PAddrBits))
|
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 pmpMmio: Vec[Bool] = Vec(PortNumber, Bool())
|
||||||
val itlbPbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W))
|
val itlbPbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W))
|
||||||
val isBackendException: Bool = Bool()
|
val isBackendException: Bool = Bool()
|
||||||
|
|
@ -185,7 +185,7 @@ class PrefetchReqBundle(implicit p: Parameters) extends ICacheBundle {
|
||||||
val nextlineStart: PrunedAddr = PrunedAddr(VAddrBits)
|
val nextlineStart: PrunedAddr = PrunedAddr(VAddrBits)
|
||||||
val ftqIdx: FtqPtr = new FtqPtr
|
val ftqIdx: FtqPtr = new FtqPtr
|
||||||
val isSoftPrefetch: Bool = Bool()
|
val isSoftPrefetch: Bool = Bool()
|
||||||
val backendException: UInt = ExceptionType()
|
val backendException: ExceptionType = new ExceptionType
|
||||||
|
|
||||||
def crossCacheline: Bool = startAddr(blockOffBits - 1) === 1.U
|
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 vSetIdx: Vec[UInt] = Vec(PortNumber, UInt(idxBits.W))
|
||||||
val waymask: Vec[UInt] = Vec(PortNumber, UInt(nWays.W))
|
val waymask: Vec[UInt] = Vec(PortNumber, UInt(nWays.W))
|
||||||
val pTag: Vec[UInt] = Vec(PortNumber, UInt(tagBits.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 itlbPbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W))
|
||||||
val metaCodes: Vec[UInt] = Vec(PortNumber, UInt(ICacheMetaCodeBits.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 vSetIdx: Vec[UInt] = entry.vSetIdx
|
||||||
def waymask: Vec[UInt] = entry.waymask
|
def waymask: Vec[UInt] = entry.waymask
|
||||||
def pTag: Vec[UInt] = entry.pTag
|
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 itlbPbmt: Vec[UInt] = entry.itlbPbmt
|
||||||
def metaCodes: Vec[UInt] = entry.metaCodes
|
def metaCodes: Vec[UInt] = entry.metaCodes
|
||||||
def gpAddr: PrunedAddr = gpf.gpAddr
|
def gpAddr: PrunedAddr = gpf.gpAddr
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import freechips.rocketchip.regmapper.RegReadFn
|
||||||
import freechips.rocketchip.regmapper.RegWriteFn
|
import freechips.rocketchip.regmapper.RegWriteFn
|
||||||
import freechips.rocketchip.tilelink.TLRegisterNode
|
import freechips.rocketchip.tilelink.TLRegisterNode
|
||||||
import org.chipsalliance.cde.config.Parameters
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import utils.NamedUInt
|
import utils.EnumUInt
|
||||||
import xiangshan.frontend.PrunedAddrInit
|
import xiangshan.frontend.PrunedAddrInit
|
||||||
|
|
||||||
// currently for ECC control only
|
// currently for ECC control only
|
||||||
|
|
@ -61,7 +61,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e
|
||||||
|
|
||||||
// eccCtrl.ierror: inject error code
|
// eccCtrl.ierror: inject error code
|
||||||
private def nInjError: Int = 8
|
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 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 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
|
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
|
// eccCtrl.istatus: inject status
|
||||||
private def nInjStatus: Int = 8
|
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 Idle: UInt = 0.U(width.W)
|
||||||
def Working: UInt = 1.U(width.W)
|
def Working: UInt = 1.U(width.W)
|
||||||
def Injected: UInt = 2.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
|
// eccCtrl.itarget: inject target
|
||||||
private def nInjTarget: Int = 4
|
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 MetaArray: UInt = 0.U(width.W)
|
||||||
def DataArray: UInt = 2.U(width.W)
|
def DataArray: UInt = 2.U(width.W)
|
||||||
@unused
|
@unused
|
||||||
|
|
@ -151,7 +151,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e
|
||||||
|
|
||||||
// inject FSM
|
// inject FSM
|
||||||
private def nInjectFsmState: Int = 5
|
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()`
|
// 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
|
// but we want UpperCamelCase for constants for better readability, so we dont use Enum() here
|
||||||
def Idle: UInt = 0.U(width.W)
|
def Idle: UInt = 0.U(width.W)
|
||||||
|
|
|
||||||
|
|
@ -224,14 +224,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
|
||||||
p.bits.size := 3.U
|
p.bits.size := 3.U
|
||||||
p.bits.cmd := TlbCmd.exec
|
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))
|
private val s1_pmpMmio = VecInit(fromPmp.map(_.mmio))
|
||||||
|
|
||||||
// merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next
|
// merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next
|
||||||
private val s1_exceptionOut = ExceptionType.merge(
|
private val s1_exceptionOut = VecInit((s1_itlbException zip s1_pmpException).map { case (i, p) => i || p })
|
||||||
s1_itlbException,
|
|
||||||
s1_pmpException
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
|
|
@ -418,7 +415,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
|
||||||
private val s2_shouldFetch = VecInit((0 until PortNumber).map { i =>
|
private val s2_shouldFetch = VecInit((0 until PortNumber).map { i =>
|
||||||
(!s2_hits(i) || s2_corruptRefetch(i)) &&
|
(!s2_hits(i) || s2_corruptRefetch(i)) &&
|
||||||
(if (i == 0) true.B else s2_doubleline) &&
|
(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(_ && _)
|
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(_ || _)
|
private val s2_fetchFinish = !s2_shouldFetch.reduce(_ || _)
|
||||||
|
|
||||||
// also raise af if l2 corrupt is detected
|
// 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
|
// 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
|
// merge s2 exceptions, itlb/pmp has the highest priority, then l2
|
||||||
private val s2_exceptionOut = ExceptionType.merge(
|
private val s2_exceptionOut = VecInit((s2_exception zip s2_l2Exception).map { case (in, l2) => in || l2 })
|
||||||
s2_exception, // includes itlb/pmp exception
|
|
||||||
s2_l2Exception
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
|
|
@ -468,7 +462,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
|
||||||
toIfu.bits.pAddr := s2_pAddr
|
toIfu.bits.pAddr := s2_pAddr
|
||||||
(0 until PortNumber).foreach { i =>
|
(0 until PortNumber).foreach { i =>
|
||||||
val needThisLine = if (i == 0) true.B else s2_doubleline
|
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.pmpMmio(i) := Mux(needThisLine, s2_pmpMmio(i), false.B)
|
||||||
toIfu.bits.itlbPbmt(i) := Mux(needThisLine, s2_itlbPbmt(i), Pbmt.pma)
|
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.hit0Miss1 := s2_hits(0) && !s2_hits(1) && s2_doubleline
|
||||||
io.perf.miss0Hit1 := !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.miss0Miss1 := !s2_hits(0) && !s2_hits(1) && s2_doubleline
|
||||||
io.perf.hit0Except1 := 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) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline
|
io.perf.miss0Except1 := !s2_hits(0) && s2_exception(1).hasException && s2_doubleline
|
||||||
io.perf.bankHit(0) := s2_hits(0)
|
io.perf.bankHit(0) := s2_hits(0)
|
||||||
io.perf.bankHit(1) := s2_hits(1) && s2_doubleline
|
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))
|
io.perf.hit := s2_hits(0) && (!s2_doubleline || s2_hits(1))
|
||||||
|
|
||||||
/** <PERF> fetch bubble generated by icache miss */
|
/** <PERF> fetch bubble generated by icache miss */
|
||||||
|
|
@ -553,7 +547,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule
|
||||||
*/
|
*/
|
||||||
if (env.EnableDifftest) {
|
if (env.EnableDifftest) {
|
||||||
val discards = (0 until PortNumber).map { i =>
|
val discards = (0 until PortNumber).map { i =>
|
||||||
ExceptionType.hasException(toIfu.bits.exception(i)) ||
|
toIfu.bits.exception(i).hasException ||
|
||||||
toIfu.bits.pmpMmio(i) ||
|
toIfu.bits.pmpMmio(i) ||
|
||||||
Pbmt.isUncache(toIfu.bits.itlbPbmt(i))
|
Pbmt.isUncache(toIfu.bits.itlbPbmt(i))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,12 @@ import utility.DataHoldBypass
|
||||||
import utility.PriorityMuxDefault
|
import utility.PriorityMuxDefault
|
||||||
import utility.ValidHold
|
import utility.ValidHold
|
||||||
import utility.XSPerfAccumulate
|
import utility.XSPerfAccumulate
|
||||||
import utils.NamedUInt
|
import utils.EnumUInt
|
||||||
import xiangshan.cache.mmu.Pbmt
|
import xiangshan.cache.mmu.Pbmt
|
||||||
import xiangshan.cache.mmu.TlbCmd
|
import xiangshan.cache.mmu.TlbCmd
|
||||||
import xiangshan.cache.mmu.TlbRequestIO
|
import xiangshan.cache.mmu.TlbRequestIO
|
||||||
import xiangshan.cache.mmu.ValidHoldBypass // FIXME: should move this to utility?
|
import xiangshan.cache.mmu.ValidHoldBypass // FIXME: should move this to utility?
|
||||||
import xiangshan.frontend.ExceptionType
|
import xiangshan.frontend.ExceptionType
|
||||||
import xiangshan.frontend.PrunedAddr
|
|
||||||
import xiangshan.frontend.PrunedAddrInit
|
import xiangshan.frontend.PrunedAddrInit
|
||||||
import xiangshan.frontend.ftq.BpuFlushInfo
|
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 val s1_backendException = RegEnable(s0_backendException, 0.U.asTypeOf(s0_backendException), s0_fire)
|
||||||
|
|
||||||
private def nS1FsmState: Int = 5
|
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 Idle: UInt = 0.U(width.W)
|
||||||
def ItlbResend: UInt = 1.U(width.W)
|
def ItlbResend: UInt = 1.U(width.W)
|
||||||
def MetaResend: UInt = 2.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))
|
Mux(tlbValidPulse(i), s1_pAddrWire(i), s1_pAddrReg(i))
|
||||||
})
|
})
|
||||||
private val s1_itlbExceptionRaw = VecInit((0 until PortNumber).map { 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 =>
|
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))
|
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
|
// 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
|
// 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
|
// 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(
|
private val s1_itlbException = VecInit((s1_backendException zip s1_itlbExceptionRaw).map { case (b, i) => b || i })
|
||||||
s1_backendException,
|
|
||||||
s1_itlbExceptionRaw
|
|
||||||
)
|
|
||||||
// debug
|
// debug
|
||||||
dontTouch(s1_itlbExceptionRaw)
|
dontTouch(s1_itlbExceptionRaw)
|
||||||
dontTouch(s1_itlbException)
|
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 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
|
* 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(
|
private val s1_gpAddr = PriorityMuxDefault(
|
||||||
s1_itlbExceptionIsGpf zip (0 until PortNumber).map(i => s1_gpAddrRaw(i) - (i << blockOffBits).U),
|
s1_itlbExceptionIsGpf zip (0 until PortNumber).map(i => s1_gpAddrRaw(i) - (i << blockOffBits).U),
|
||||||
0.U.asTypeOf(s1_gpAddrRaw(0))
|
0.U.asTypeOf(s1_gpAddrRaw(0))
|
||||||
|
|
@ -326,7 +322,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule
|
||||||
toWayLookup.bits.itlbException(i) := Mux(
|
toWayLookup.bits.itlbException(i) := Mux(
|
||||||
excpValid,
|
excpValid,
|
||||||
s1_itlbException(i), // includes backend exception
|
s1_itlbException(i), // includes backend exception
|
||||||
ExceptionType.none
|
ExceptionType.None
|
||||||
)
|
)
|
||||||
toWayLookup.bits.itlbPbmt(i) := Mux(excpValid, s1_itlbPbmt(i), Pbmt.pma)
|
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.size := 3.U
|
||||||
p.bits.cmd := TlbCmd.exec
|
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))
|
private val s1_pmpMmio = VecInit(fromPmp.map(_.mmio))
|
||||||
|
|
||||||
// merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next
|
// 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
|
// here, itlb exception includes backend exception
|
||||||
private val s1_exceptionOut = ExceptionType.merge(
|
private val s1_exceptionOut = VecInit((s1_itlbException zip s1_pmpException).map { case (i, p) => i || p })
|
||||||
s1_itlbException, // includes backend exception
|
|
||||||
s1_pmpException
|
|
||||||
)
|
|
||||||
|
|
||||||
// merge pmp mmio and itlb pbmt
|
// merge pmp mmio and itlb pbmt
|
||||||
private val s1_isMmio = VecInit((s1_pmpMmio zip s1_itlbPbmt).map { case (mmio, 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 =>
|
private val s2_miss = VecInit((0 until PortNumber).map { i =>
|
||||||
!s2_hits(i) && (if (i == 0) true.B else s2_doubleline) &&
|
!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(_ && _)
|
s2_isMmio.take(i + 1).map(!_).reduce(_ && _)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ class ICacheWayLookup(implicit p: Parameters) extends ICacheModule with ICacheMi
|
||||||
io.write.ready := !full && !gpfStall
|
io.write.ready := !full && !gpfStall
|
||||||
when(io.write.fire) {
|
when(io.write.fire) {
|
||||||
entries(writePtr.value) := io.write.bits.entry
|
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
|
// if gpfEntry is bypassed, we don't need to save it
|
||||||
// note this will override the read (L156)
|
// note this will override the read (L156)
|
||||||
gpfEntry.valid := !(canBypass && io.read.fire)
|
gpfEntry.valid := !(canBypass && io.read.fire)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ package xiangshan.frontend.ifu
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
import org.chipsalliance.cde.config.Parameters
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import utils.NamedUInt
|
import utils.EnumUInt
|
||||||
import xiangshan.frontend.PrunedAddr
|
import xiangshan.frontend.PrunedAddr
|
||||||
|
|
||||||
/* ***
|
/* ***
|
||||||
|
|
@ -32,14 +32,14 @@ import xiangshan.frontend.PrunedAddr
|
||||||
* *** */
|
* *** */
|
||||||
|
|
||||||
/* ***** PreDecode ***** */
|
/* ***** PreDecode ***** */
|
||||||
object PreDecodeFaultType extends NamedUInt(3) {
|
object PreDecodeFaultType extends EnumUInt(7) {
|
||||||
def noFault: UInt = "b000".U(width.W)
|
def NoFault: UInt = 0.U(width.W)
|
||||||
def jalFault: UInt = "b001".U(width.W) // not CFI taken or invalid instruction taken
|
def JalFault: UInt = 1.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 RetFault: UInt = 2.U(width.W) // not CFI taken or invalid instruction taken
|
||||||
def targetFault: UInt = "b011".U(width.W)
|
def TargetFault: UInt = 3.U(width.W)
|
||||||
def notCfiFault: UInt = "b100".U(width.W) // not CFI taken or invalid instruction taken
|
def NotCfiFault: UInt = 4.U(width.W) // not CFI taken or invalid instruction taken
|
||||||
def invalidTaken: UInt = "b101".U(width.W)
|
def InvalidTaken: UInt = 5.U(width.W)
|
||||||
def jalrFault: UInt = "b110".U(width.W)
|
def JalrFault: UInt = 6.U(width.W)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ***** Ifu last half ***** */
|
/* ***** Ifu last half ***** */
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@ trait PreDecodeHelper extends HasXSParameter {
|
||||||
def isLink(reg: UInt): Bool = reg === 1.U || reg === 5.U
|
def isLink(reg: UInt): Bool = reg === 1.U || reg === 5.U
|
||||||
|
|
||||||
def getBrType(inst: UInt): UInt =
|
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) = {
|
def getBrInfo(inst: UInt): (UInt, Bool, Bool) = {
|
||||||
val brType = getBrType(inst)
|
val brType = getBrType(inst)
|
||||||
val rd = Mux(isRVC(inst), inst(12), inst(11, 7))
|
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 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 isCall = (brType === BrType.Jal && !isRVC(inst) || brType === BrType.Jalr) && isLink(rd) // Only for RV64
|
||||||
val isRet = brType === BrType.jalr && isLink(rs) && !isCall
|
val isRet = brType === BrType.Jalr && isLink(rs) && !isCall
|
||||||
(brType, isCall, isRet)
|
(brType, isCall, isRet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import utility.XSDebug
|
||||||
import utility.XSError
|
import utility.XSError
|
||||||
import utility.XSPerfAccumulate
|
import utility.XSPerfAccumulate
|
||||||
import utility.XSPerfHistogram
|
import utility.XSPerfHistogram
|
||||||
import utils.NamedUInt
|
import utils.EnumUInt
|
||||||
import xiangshan.FrontendTdataDistributeIO
|
import xiangshan.FrontendTdataDistributeIO
|
||||||
import xiangshan.RedirectLevel
|
import xiangshan.RedirectLevel
|
||||||
import xiangshan.RobCommitInfo
|
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
|
// FIXME: raise af if one fetch block crosses the cacheable/un-cacheable boundary, might not correct
|
||||||
private val s2_mmioMismatchException = VecInit(Seq(
|
private val s2_mmioMismatchException = VecInit(Seq(
|
||||||
ExceptionType.none, // mark the exception only on the second line
|
ExceptionType.None, // mark the exception only on the second line
|
||||||
Mux(
|
ExceptionType(hasAf =
|
||||||
// not double-line, skip check
|
// if not double-line, skip check
|
||||||
!fromICache.bits.doubleline || (
|
fromICache.bits.doubleline && (
|
||||||
// is double-line, ask for consistent pmp_mmio and itlb_pbmt value
|
// is double-line, ask for consistent pmp_mmio and itlb_pbmt value
|
||||||
fromICache.bits.pmpMmio(0) === fromICache.bits.pmpMmio(1) &&
|
fromICache.bits.pmpMmio(0) =/= fromICache.bits.pmpMmio(1) ||
|
||||||
fromICache.bits.itlbPbmt(0) === fromICache.bits.itlbPbmt(1)
|
fromICache.bits.itlbPbmt(0) =/= fromICache.bits.itlbPbmt(1)
|
||||||
),
|
)
|
||||||
ExceptionType.none,
|
|
||||||
ExceptionType.af
|
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
// merge exceptions
|
// 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
|
// we need only the first port, as the second is asked to be the same
|
||||||
private val s2_pmpMmio = fromICache.bits.pmpMmio(0)
|
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_instrRange = s2_jumpRange & s2_ftrRange
|
||||||
private val s2_exceptionVec = VecInit((0 until PredictWidth).map(i =>
|
private val s2_exceptionVec = VecInit((0 until PredictWidth).map(i =>
|
||||||
MuxCase(
|
MuxCase(
|
||||||
ExceptionType.none,
|
ExceptionType.None,
|
||||||
Seq(
|
Seq(
|
||||||
!isNextLine(s2_pc(i), s2_ftqReq.startAddr) -> s2_exception(0),
|
!isNextLine(s2_pc(i), s2_ftqReq.startAddr) -> s2_exception(0),
|
||||||
(isNextLine(s2_pc(i), s2_ftqReq.startAddr) && s2_doubleline) -> s2_exception(1)
|
(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 =>
|
private val s2_crossPageExceptionVec = VecInit((0 until PredictWidth).map { i =>
|
||||||
Mux(
|
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),
|
s2_exception(1),
|
||||||
ExceptionType.none
|
ExceptionType.None
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
XSPerfAccumulate("fetch_bubble_icache_not_resp", s2_valid && !icacheRespAllValid)
|
XSPerfAccumulate("fetch_bubble_icache_not_resp", s2_valid && !icacheRespAllValid)
|
||||||
|
|
@ -563,7 +561,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
|
||||||
|
|
||||||
/* *** mmio *** */
|
/* *** mmio *** */
|
||||||
private def nMmioFsmState = 11
|
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 Idle: UInt = 0.U(width.W)
|
||||||
def WaitLastCommit: UInt = 1.U(width.W)
|
def WaitLastCommit: UInt = 1.U(width.W)
|
||||||
def SendReq: UInt = 2.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 mmioState = RegInit(MmioFsmState.Idle)
|
||||||
|
|
||||||
private val mmioData = RegInit(VecInit(Seq.fill(2)(0.U(16.W))))
|
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 mmioIsRvc = RegInit(false.B)
|
||||||
private val mmioHasResend = RegInit(false.B)
|
private val mmioHasResend = RegInit(false.B)
|
||||||
private val mmioResendAddr = RegInit(PrunedAddrInit(0.U(PAddrBits.W)))
|
private val mmioResendAddr = RegInit(PrunedAddrInit(0.U(PAddrBits.W)))
|
||||||
|
|
@ -591,7 +589,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
|
||||||
private def mmioReset(): Unit = {
|
private def mmioReset(): Unit = {
|
||||||
mmioState := MmioFsmState.Idle
|
mmioState := MmioFsmState.Idle
|
||||||
mmioData.foreach(_ := 0.U)
|
mmioData.foreach(_ := 0.U)
|
||||||
mmioException := ExceptionType.none
|
mmioException := ExceptionType.None
|
||||||
mmioIsRvc := false.B
|
mmioIsRvc := false.B
|
||||||
mmioHasResend := false.B
|
mmioHasResend := false.B
|
||||||
mmioResendAddr := PrunedAddrInit(0.U(PAddrBits.W))
|
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
|
// do mmio fetch only when pmp/pbmt shows it is a un-cacheable address and no exception occurs
|
||||||
private val s3_reqIsMmio =
|
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 =>
|
private val mmioCommit = VecInit(io.robCommits.map { commit =>
|
||||||
commit.valid && commit.bits.ftqIdx === s3_ftqReq.ftqIdx && commit.bits.ftqOffset === 0.U
|
commit.valid && commit.bits.ftqIdx === s3_ftqReq.ftqIdx && commit.bits.ftqOffset === 0.U
|
||||||
}).asUInt.orR
|
}).asUInt.orR
|
||||||
|
|
@ -682,9 +680,9 @@ class Ifu(implicit p: Parameters) extends IfuModule
|
||||||
is(MmioFsmState.WaitResp) {
|
is(MmioFsmState.WaitResp) {
|
||||||
when(fromUncache.fire) {
|
when(fromUncache.fire) {
|
||||||
val respIsRVC = isRVC(fromUncache.bits.data(1, 0))
|
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
|
// 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)
|
mmioState := Mux(needResend, MmioFsmState.SendTlb, MmioFsmState.WaitCommit)
|
||||||
mmioException := exception
|
mmioException := exception
|
||||||
mmioIsRvc := respIsRVC
|
mmioIsRvc := respIsRVC
|
||||||
|
|
@ -702,16 +700,13 @@ class Ifu(implicit p: Parameters) extends IfuModule
|
||||||
when(io.itlb.resp.fire) {
|
when(io.itlb.resp.fire) {
|
||||||
// we are using a blocked tlb, so resp.fire must have !resp.bits.miss
|
// 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")
|
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
|
// if itlb re-check respond pbmt mismatch with previous check, must be access fault
|
||||||
val pbmtMismatchException = Mux(
|
val pbmtMismatchException = ExceptionType(hasAf = io.itlb.resp.bits.pbmt(0) =/= s3_itlbPbmt)
|
||||||
io.itlb.resp.bits.pbmt(0) =/= s3_itlbPbmt,
|
// merge, itlbException has higher priority
|
||||||
ExceptionType.af,
|
val exception = itlbException || pbmtMismatchException
|
||||||
ExceptionType.none
|
|
||||||
)
|
|
||||||
val exception = ExceptionType.merge(tlbException, pbmtMismatchException)
|
|
||||||
// if tlb has exception, abort checking pmp, just send instr & exception to iBuffer and wait for commit
|
// 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
|
// also save itlb response
|
||||||
mmioException := exception
|
mmioException := exception
|
||||||
mmioResendAddr := io.itlb.resp.bits.paddr(0)
|
mmioResendAddr := io.itlb.resp.bits.paddr(0)
|
||||||
|
|
@ -721,16 +716,13 @@ class Ifu(implicit p: Parameters) extends IfuModule
|
||||||
}
|
}
|
||||||
|
|
||||||
is(MmioFsmState.SendPmp) {
|
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
|
// if pmp re-check respond mismatch with previous check, must be access fault
|
||||||
val mmioMismatchException = Mux(
|
val mmioMismatchException = ExceptionType(hasAf = io.pmp.resp.mmio =/= s3_pmpMmio)
|
||||||
io.pmp.resp.mmio =/= s3_pmpMmio,
|
// merge, pmpException has higher priority
|
||||||
ExceptionType.af,
|
val exception = pmpException || mmioMismatchException
|
||||||
ExceptionType.none
|
|
||||||
)
|
|
||||||
val exception = ExceptionType.merge(pmpException, mmioMismatchException)
|
|
||||||
// if pmp has exception, abort sending request, just send instr & exception to iBuffer and wait for commit
|
// 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
|
// also save pmp response
|
||||||
mmioException := exception
|
mmioException := exception
|
||||||
}
|
}
|
||||||
|
|
@ -742,7 +734,7 @@ class Ifu(implicit p: Parameters) extends IfuModule
|
||||||
is(MmioFsmState.WaitResendResp) {
|
is(MmioFsmState.WaitResendResp) {
|
||||||
when(fromUncache.fire) {
|
when(fromUncache.fire) {
|
||||||
mmioState := MmioFsmState.WaitCommit
|
mmioState := MmioFsmState.WaitCommit
|
||||||
mmioException := ExceptionType.fromTilelink(fromUncache.bits.corrupt)
|
mmioException := ExceptionType(hasAf = fromUncache.bits.corrupt)
|
||||||
mmioData(1) := fromUncache.bits.data(15, 0)
|
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
|
a.valid := checkerOutStage1.fixedTaken(i) && !s3_reqIsMmio
|
||||||
}
|
}
|
||||||
io.toIBuffer.bits.foldpc := s3_foldPc
|
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.
|
// backendException only needs to be set for the first instruction.
|
||||||
// Other instructions in the same block may have pf or af set,
|
// 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.
|
// 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 0 => s3_isBackendException
|
||||||
case _ => false.B
|
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.illegalInstr := s3_ill
|
||||||
io.toIBuffer.bits.triggered := s3_triggered
|
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
|
// s3_gpAddr is valid iff gpf is detected
|
||||||
io.toBackend.gpaddrMem_wen := s3_toIBufferValid && Mux(
|
io.toBackend.gpaddrMem_wen := s3_toIBufferValid && Mux(
|
||||||
s3_reqIsMmio,
|
s3_reqIsMmio,
|
||||||
mmioException === ExceptionType.gpf,
|
mmioException.isGpf,
|
||||||
s3_exception.map(_ === ExceptionType.gpf).reduce(_ || _)
|
s3_exception.map(_.isGpf).reduce(_ || _)
|
||||||
)
|
)
|
||||||
io.toBackend.gpaddrMem_waddr := s3_ftqReq.ftqIdx.value
|
io.toBackend.gpaddrMem_waddr := s3_ftqReq.ftqIdx.value
|
||||||
io.toBackend.gpaddrMem_wdata.gpaddr := Mux(s3_reqIsMmio, mmioResendGpAddr.toUInt, s3_gpAddr.toUInt)
|
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
|
io.toIBuffer.bits.exceptionType(0) := mmioException
|
||||||
// exception can happen in next page only when resend
|
// 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.illegalInstr(0) := mmioRvcExpander.io.ill
|
||||||
|
|
||||||
io.toIBuffer.bits.enqEnable := s3_mmioRange.asUInt
|
io.toIBuffer.bits.enqEnable := s3_mmioRange.asUInt
|
||||||
|
|
@ -1053,12 +1047,12 @@ class Ifu(implicit p: Parameters) extends IfuModule
|
||||||
|
|
||||||
/* write back flush type */
|
/* write back flush type */
|
||||||
private val checkFaultType = wbCheckResultStage2.faultType
|
private val checkFaultType = wbCheckResultStage2.faultType
|
||||||
private val checkJalFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.jalFault).reduce(_ || _)
|
private val checkJalFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.JalFault).reduce(_ || _)
|
||||||
private val checkJalrFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.jalrFault).reduce(_ || _)
|
private val checkJalrFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.JalrFault).reduce(_ || _)
|
||||||
private val checkRetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.retFault).reduce(_ || _)
|
private val checkRetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.RetFault).reduce(_ || _)
|
||||||
private val checkTargetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.targetFault).reduce(_ || _)
|
private val checkTargetFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.TargetFault).reduce(_ || _)
|
||||||
private val checkNotCFIFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.notCfiFault).reduce(_ || _)
|
private val checkNotCFIFault = wbValid && checkFaultType.map(_ === PreDecodeFaultType.NotCfiFault).reduce(_ || _)
|
||||||
private val checkInvalidTaken = wbValid && checkFaultType.map(_ === PreDecodeFaultType.invalidTaken).reduce(_ || _)
|
private val checkInvalidTaken = wbValid && checkFaultType.map(_ === PreDecodeFaultType.InvalidTaken).reduce(_ || _)
|
||||||
|
|
||||||
XSPerfAccumulate("predecode_flush_jalFault", checkJalFault)
|
XSPerfAccumulate("predecode_flush_jalFault", checkJalFault)
|
||||||
XSPerfAccumulate("predecode_flush_jalrFault", checkJalrFault)
|
XSPerfAccumulate("predecode_flush_jalrFault", checkJalrFault)
|
||||||
|
|
|
||||||
|
|
@ -139,14 +139,14 @@ class PredChecker(implicit p: Parameters) extends IfuModule {
|
||||||
|
|
||||||
io.resp.stage2Out.faultType.zipWithIndex.foreach { case (faultType, i) =>
|
io.resp.stage2Out.faultType.zipWithIndex.foreach { case (faultType, i) =>
|
||||||
faultType := MuxCase(
|
faultType := MuxCase(
|
||||||
PreDecodeFaultType.noFault,
|
PreDecodeFaultType.NoFault,
|
||||||
Seq(
|
Seq(
|
||||||
jalFaultVecNext(i) -> PreDecodeFaultType.jalFault,
|
jalFaultVecNext(i) -> PreDecodeFaultType.JalFault,
|
||||||
jalrFaultVecNext(i) -> PreDecodeFaultType.jalrFault,
|
jalrFaultVecNext(i) -> PreDecodeFaultType.JalrFault,
|
||||||
retFaultVecNext(i) -> PreDecodeFaultType.retFault,
|
retFaultVecNext(i) -> PreDecodeFaultType.RetFault,
|
||||||
targetFault(i) -> PreDecodeFaultType.targetFault,
|
targetFault(i) -> PreDecodeFaultType.TargetFault,
|
||||||
notCFITakenNext(i) -> PreDecodeFaultType.notCfiFault,
|
notCFITakenNext(i) -> PreDecodeFaultType.NotCfiFault,
|
||||||
invalidTakenNext(i) -> PreDecodeFaultType.invalidTaken
|
invalidTakenNext(i) -> PreDecodeFaultType.InvalidTaken
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import freechips.rocketchip.tilelink.TLBundleA
|
||||||
import freechips.rocketchip.tilelink.TLBundleD
|
import freechips.rocketchip.tilelink.TLBundleD
|
||||||
import freechips.rocketchip.tilelink.TLEdgeOut
|
import freechips.rocketchip.tilelink.TLEdgeOut
|
||||||
import org.chipsalliance.cde.config.Parameters
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import utils.NamedUInt
|
import utils.EnumUInt
|
||||||
|
|
||||||
// One miss entry deals with one mmio request
|
// One miss entry deals with one mmio request
|
||||||
class InstrUncacheEntry(edge: TLEdgeOut)(implicit p: Parameters) extends InstrUncacheModule {
|
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))
|
val io: InstrUncacheEntryIO = IO(new InstrUncacheEntryIO(edge))
|
||||||
|
|
||||||
private def nState: Int = 4
|
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 Invalid: UInt = 0.U(width.W)
|
||||||
def RefillReq: UInt = 1.U(width.W)
|
def RefillReq: UInt = 1.U(width.W)
|
||||||
def RefillResp: UInt = 2.U(width.W)
|
def RefillResp: UInt = 2.U(width.W)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue