Skip to content

Commit

Permalink
timing(csr): add 1 cycle to csr read/write
Browse files Browse the repository at this point in the history
  • Loading branch information
sinceforYy committed Nov 27, 2024
1 parent b00d582 commit 9816069
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 52 deletions.
46 changes: 30 additions & 16 deletions src/main/scala/xiangshan/backend/fu/NewCSR/InterruptFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,24 +166,35 @@ class InterruptFilter extends Module {
private val (mIidIdx, mPrioNum) = highIprio(mipriosSort, InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.MEI).U)
private val (hsIidIdx, hsPrioNum) = highIprio(hsipriosSort, InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.SEI).U)

private val mIidNum = findNum(mIidIdx)
private val hsIidNum = findNum(hsIidIdx)
private val mIidIdxReg = RegNext(mIidIdx)
private val mPrioNumReg = RegNext(mPrioNum)

private val mIidDefaultPrioHighMEI: Bool = mIidIdx < InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.MEI).U
private val mIidDefaultPrioLowMEI : Bool = mIidIdx > InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.MEI).U
private val hsIidIdxReg = RegNext(hsIidIdx)
private val hsPrioNumReg = RegNext(hsPrioNum)

private val hsIidDefaultPrioHighSEI: Bool = hsIidIdx < InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.SEI).U
private val hsIidDefaultPrioLowSEI : Bool = hsIidIdx > InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.SEI).U
private val mIidNum = findNum(mIidIdxReg)
private val hsIidNum = findNum(hsIidIdxReg)

val mtopiPrioNumReal = mPrioNum
val stopiPrioNumReal = hsPrioNum
private val mIidDefaultPrioHighMEI: Bool = mIidIdxReg < InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.MEI).U
private val mIidDefaultPrioLowMEI : Bool = mIidIdxReg > InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.MEI).U

private val hsIidDefaultPrioHighSEI: Bool = hsIidIdxReg < InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.SEI).U
private val hsIidDefaultPrioLowSEI : Bool = hsIidIdxReg > InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.SEI).U

val mtopiPrioNumReal = mPrioNumReg
val stopiPrioNumReal = hsPrioNumReg

val mtopiIsNotZeroReg = RegNext(mtopiIsNotZero)
val stopiIsNotZeroReg = RegNext(stopiIsNotZero)
val mIpriosIsZeroReg = RegNext(mIpriosIsZero)
val hsIpriosIsZeroReg = RegNext(hsIpriosIsZero)

// update mtopi
io.out.mtopi.IID := Mux(mtopiIsNotZero, mIidNum, 0.U)
io.out.mtopi.IID := Mux(mtopiIsNotZeroReg, mIidNum, 0.U)
io.out.mtopi.IPRIO := Mux(
mtopiIsNotZero,
mtopiIsNotZeroReg,
Mux(
mIpriosIsZero,
mIpriosIsZeroReg,
1.U,
Mux1H(Seq(
(mtopiPrioNumReal >= 1.U && mtopiPrioNumReal <= 255.U) -> mtopiPrioNumReal(7, 0),
Expand All @@ -195,11 +206,11 @@ class InterruptFilter extends Module {
)

// upadte stopi
io.out.stopi.IID := Mux(stopiIsNotZero, hsIidNum, 0.U)
io.out.stopi.IID := Mux(stopiIsNotZeroReg, hsIidNum, 0.U)
io.out.stopi.IPRIO := Mux(
stopiIsNotZero,
stopiIsNotZeroReg,
Mux(
hsIpriosIsZero,
hsIpriosIsZeroReg,
1.U,
Mux1H(Seq(
(stopiPrioNumReal >= 1.U && stopiPrioNumReal <= 255.U) -> stopiPrioNumReal(7, 0),
Expand All @@ -223,7 +234,10 @@ class InterruptFilter extends Module {

private val (vsIidIdx, vsPrioNum) = highIprio(hvipriosSort, InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.VSEI).U)

private val vsIidNum = findNum(vsIidIdx)
private val vsIidIdxReg = RegNext(vsIidIdx)
private val vsPrioNumReg = RegNext(vsPrioNum)

private val vsIidNum = findNum(vsIidIdxReg)

val iidCandidate123 = Wire(UInt(12.W))
val iidCandidate45 = Wire(UInt(12.W))
Expand All @@ -240,7 +254,7 @@ class InterruptFilter extends Module {
Candidate5 -> hvictl.IID.asUInt,
))
iprioCandidate45 := Mux1H(Seq(
Candidate4 -> vsPrioNum,
Candidate4 -> vsPrioNumReg,
Candidate5 -> hvictl.IPRIO.asUInt,
))

Expand Down
59 changes: 35 additions & 24 deletions src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class NewCSRInput(implicit p: Parameters) extends Bundle {
val ren = Bool()
val op = UInt(2.W)
val addr = UInt(12.W)
val waddrReg = UInt(12.W)
val src = UInt(64.W)
val wdata = UInt(64.W)
val mnret = Input(Bool())
Expand Down Expand Up @@ -232,11 +233,13 @@ class NewCSR(implicit val p: Parameters) extends Module
/* Alias of input signals */
val wen = io.in.bits.wen && valid
val addr = io.in.bits.addr
val wdata = io.in.bits.wdata

val ren = io.in.bits.ren && valid
val raddr = io.in.bits.addr

val waddrReg = io.in.bits.waddrReg
val wdataReg = io.in.bits.wdata

val hasTrap = io.fromRob.trap.valid
val trapVec = io.fromRob.trap.bits.trapVec
val trapPC = io.fromRob.trap.bits.pc
Expand Down Expand Up @@ -292,6 +295,9 @@ class NewCSR(implicit val p: Parameters) extends Module
val legalMNret = permitMod.io.out.hasLegalMNret
val legalDret = permitMod.io.out.hasLegalDret

private val wenLegalReg = RegEnable(wenLegal, false.B, io.in.fire)
val isModeVSReg = RegEnable(isModeVS, false.B, io.in.fire)

var csrRwMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] =
machineLevelCSRMap ++
supervisorLevelCSRMap ++
Expand Down Expand Up @@ -410,22 +416,23 @@ class NewCSR(implicit val p: Parameters) extends Module
pmpEntryMod.io.in.pmpCfg := cfgs.map(_.regOut.asInstanceOf[PMPCfgBundle])
pmpEntryMod.io.in.pmpAddr := pmpaddr.map(_.regOut.asInstanceOf[PMPAddrBundle])
pmpEntryMod.io.in.ren := ren
pmpEntryMod.io.in.wen := wenLegal
pmpEntryMod.io.in.wen := wenLegalReg
pmpEntryMod.io.in.addr := addr
pmpEntryMod.io.in.wdata := wdata
pmpEntryMod.io.in.waddr := waddrReg
pmpEntryMod.io.in.wdata := wdataReg

// Todo: all wen and wdata of CSRModule assigned in this for loop
for ((id, (wBundle, _)) <- csrRwMap) {
if (vsMapS.contains(id)) {
// VS access CSR by S: privState.isModeVS && addrMappedToVS === sMapVS(id).U
wBundle.wen := wenLegal && ((isModeVS && addr === vsMapS(id).U) || (!isModeVS && addr === id.U))
wBundle.wdata := wdata
wBundle.wen := wenLegalReg && ((isModeVSReg && waddrReg === vsMapS(id).U) || (!isModeVSReg && waddrReg === id.U))
wBundle.wdata := wdataReg
} else if (sMapVS.contains(id)) {
wBundle.wen := wenLegal && !isModeVS && addr === id.U
wBundle.wdata := wdata
wBundle.wen := wenLegalReg && !isModeVSReg && waddrReg === id.U
wBundle.wdata := wdataReg
} else {
wBundle.wen := wenLegal && addr === id.U
wBundle.wdata := wdata
wBundle.wen := wenLegalReg && waddrReg === id.U
wBundle.wdata := wdataReg
}
}

Expand Down Expand Up @@ -486,23 +493,23 @@ class NewCSR(implicit val p: Parameters) extends Module

miregiprios.foreach { mod =>
mod.w.wen := mireg.w.wen && (miselect.regOut.ALL.asUInt === mod.addr.U)
mod.w.wdata := wdata
mod.w.wdata := wdataReg
}

siregiprios.foreach { mod =>
mod.w.wen := sireg.w.wen && (siselect.regOut.ALL.asUInt === mod.addr.U)
mod.w.wdata := wdata
mod.w.wdata := wdataReg
}

mhartid.hartid := this.io.fromTop.hartId

cfgs.zipWithIndex.foreach { case (mod, i) =>
mod.w.wen := wenLegal && (addr === (0x3A0 + i / 8 * 2).U)
mod.w.wen := wenLegalReg && (waddrReg === (0x3A0 + i / 8 * 2).U)
mod.w.wdata := pmpEntryMod.io.out.pmpCfgWData(8*((i%8)+1)-1,8*(i%8))
}

pmpaddr.zipWithIndex.foreach{ case(mod, i) =>
mod.w.wen := wenLegal && (addr === (0x3B0 + i).U)
mod.w.wen := wenLegalReg && (waddrReg === (0x3B0 + i).U)
mod.w.wdata := pmpEntryMod.io.out.pmpAddrWData(i)
}

Expand Down Expand Up @@ -851,7 +858,7 @@ class NewCSR(implicit val p: Parameters) extends Module
)

// flush
val resetSatp = Cat(Seq(satp, vsatp, hgatp).map(_.addr.U === addr)).orR && wenLegal // write to satp will cause the pipeline be flushed
val resetSatp = Cat(Seq(satp, vsatp, hgatp).map(_.addr.U === waddrReg)).orR && wenLegalReg // write to satp will cause the pipeline be flushed

val floatStatusOnOff = mstatus.w.wen && (
mstatus.w.wdataFields.FS === ContextStatus.Off && mstatus.regOut.FS =/= ContextStatus.Off ||
Expand Down Expand Up @@ -980,9 +987,13 @@ class NewCSR(implicit val p: Parameters) extends Module
val normalCSRValid = state === s_idle && valid && !asyncAccess
val waitIMSICValid = state === s_waitIMSIC && fromAIA.rdata.valid

io.out.valid := normalCSRValid ||
waitIMSICValid ||
state === s_finish
val normalCSRValidReg = RegEnable(normalCSRValid, false.B, io.in.fire)
val waitIMSICValidReg = RegNext(waitIMSICValid)
val finishValidReg = RegNext(state === s_finish)

io.out.valid := normalCSRValidReg ||
waitIMSICValidReg ||
finishValidReg
io.out.bits.EX_II := DataHoldBypass(Mux1H(Seq(
normalCSRValid -> (permitMod.io.out.EX_II || noCSRIllegal),
waitIMSICValid -> imsic_EX_II,
Expand All @@ -991,7 +1002,7 @@ class NewCSR(implicit val p: Parameters) extends Module
normalCSRValid -> permitMod.io.out.EX_VI,
waitIMSICValid -> imsic_EX_VI,
)), false.B, normalCSRValid || waitIMSICValid)
io.out.bits.flushPipe := DataHoldBypass(flushPipe, false.B, io.in.fire)
io.out.bits.flushPipe := flushPipe

/** Prepare read data for output */
io.out.bits.rData := DataHoldBypass(
Expand Down Expand Up @@ -1070,7 +1081,7 @@ class NewCSR(implicit val p: Parameters) extends Module
debugMod.io.in.tdata2Selected := tdata2.rdata
debugMod.io.in.tdata1Update := tdata1Update
debugMod.io.in.tdata2Update := tdata2Update
debugMod.io.in.tdata1Wdata := wdata
debugMod.io.in.tdata1Wdata := wdataReg
debugMod.io.in.triggerCanRaiseBpExp := triggerCanRaiseBpExp

entryDebugMode := debugMod.io.out.hasDebugTrap && !debugMode
Expand All @@ -1095,9 +1106,9 @@ class NewCSR(implicit val p: Parameters) extends Module
}
tdata1RegVec.zip(tdata2RegVec).zipWithIndex.map { case ((mod1, mod2), idx) => {
mod1.w.wen := tdata1Update && (tselect.rdata === idx.U)
mod1.w.wdata := wdata
mod1.w.wdata := wdataReg
mod2.w.wen := tdata2Update && (tselect.rdata === idx.U)
mod2.w.wdata := wdata
mod2.w.wdata := wdataReg
}}

triggerFrontendChange := debugMod.io.out.triggerFrontendChange
Expand Down Expand Up @@ -1247,8 +1258,8 @@ class NewCSR(implicit val p: Parameters) extends Module
toAIA.addr.bits.v := imsicAddrPrivState.V

toAIA.wdata.valid := imsicWdataValid
toAIA.wdata.bits.op := io.in.bits.op
toAIA.wdata.bits.data := io.in.bits.src
toAIA.wdata.bits.op := RegEnable(io.in.bits.op, 0.U(2.W), io.in.fire)
toAIA.wdata.bits.data := RegEnable(io.in.bits.src, 0.U(64.W), io.in.fire)
toAIA.vgein := hstatus.regOut.VGEIN.asUInt
toAIA.mClaim := mtopei.w.wen
toAIA.sClaim := stopei.w.wen
Expand Down Expand Up @@ -1320,7 +1331,7 @@ class NewCSR(implicit val p: Parameters) extends Module
henvcfg.regOut.CBIE === EnvCBIE.Flush && (isModeVS || isModeVU)
)

io.distributedWenLegal := wenLegal
io.distributedWenLegal := wenLegalReg
io.status.criticalErrorState := criticalErrorState && !dcsr.regOut.CETRIG.asBool

val criticalErrors = Seq(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class PMPEntryHandleModule(implicit p: Parameters) extends PMPModule {
val ren = io.in.ren
val wen = io.in.wen
val addr = io.in.addr
val waddr = io.in.waddr
val wdata = io.in.wdata

val pmpMask = RegInit(VecInit(Seq.fill(p(PMParameKey).NumPMP)(0.U(PMPAddrBits.W))))
Expand All @@ -35,7 +36,7 @@ class PMPEntryHandleModule(implicit p: Parameters) extends PMPModule {
// write pmpCfg
val cfgVec = WireInit(VecInit(Seq.fill(8)(0.U.asTypeOf(new PMPCfgBundle))))
for (i <- 0 until (p(PMParameKey).NumPMP/8+1) by 2) {
when (wen && (addr === (0x3A0 + i).U)) {
when (wen && (waddr === (0x3A0 + i).U)) {
for (j <- cfgVec.indices) {
val cfgOldTmp = pmpEntry(8*i/2+j).cfg
val cfgNewTmp = Wire(new PMPCfgBundle)
Expand Down Expand Up @@ -64,7 +65,7 @@ class PMPEntryHandleModule(implicit p: Parameters) extends PMPModule {
pmpAddrW(i) := pmpEntry(i).addr.ADDRESS.asUInt
pmpAddrR(i) := pmpEntry(i).addr.ADDRESS.asUInt
// write pmpAddr
when (wen && (addr === (0x3B0 + i).U)) {
when (wen && (waddr === (0x3B0 + i).U)) {
if (i != (p(PMParameKey).NumPMP - 1)) {
val addrNextLocked: Bool = PMPCfgLField.addrLocked(pmpEntry(i).cfg, pmpEntry(i + 1).cfg)
pmpMask(i) := Mux(!addrNextLocked, pmpEntry(i).matchMask(wdata), pmpEntry(i).mask)
Expand All @@ -91,6 +92,7 @@ class PMPEntryHandleIOBundle(implicit p: Parameters) extends PMPBundle {
val wen = Bool()
val ren = Bool()
val addr = UInt(12.W)
val waddr = UInt(12.W)
val wdata = UInt(64.W)
val pmpCfg = Vec(NumPMP, new PMPCfgBundle)
val pmpAddr = Vec(NumPMP, new PMPAddrBundle)
Expand Down
24 changes: 14 additions & 10 deletions src/main/scala/xiangshan/backend/fu/wrapper/CSR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,19 @@ class CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
CSROpType.isCSRRSorRC(func)
)

private val waddrReg = RegEnable(addr, 0.U(12.W), io.in.fire)
private val wdataReg = RegEnable(wdata, 0.U(64.W), io.in.fire)

csrMod.io.in match {
case in =>
in.valid := valid
in.bits.wen := csrWen
in.bits.ren := csrRen
in.bits.op := CSROpType.getCSROp(func)
in.bits.addr := addr
in.bits.waddrReg := waddrReg
in.bits.src := src
in.bits.wdata := wdata
in.bits.wdata := wdataReg
in.bits.mret := isMret
in.bits.mnret := isMNret
in.bits.sret := isSret
Expand Down Expand Up @@ -272,13 +276,13 @@ class CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
/** initialize NewCSR's io_out_ready from wrapper's io */
csrMod.io.out.ready := io.out.ready

io.out.bits.res.redirect.get.valid := io.out.valid && DataHoldBypass(isXRet, false.B, io.in.fire)
io.out.bits.res.redirect.get.valid := io.out.valid && RegEnable(isXRet, false.B, io.in.fire)
val redirect = io.out.bits.res.redirect.get.bits
redirect := 0.U.asTypeOf(redirect)
redirect.level := RedirectLevel.flushAfter
redirect.robIdx := io.in.bits.ctrl.robIdx
redirect.ftqIdx := io.in.bits.ctrl.ftqIdx.get
redirect.ftqOffset := io.in.bits.ctrl.ftqOffset.get
redirect.robIdx := RegEnable(io.in.bits.ctrl.robIdx, io.in.fire)
redirect.ftqIdx := RegEnable(io.in.bits.ctrl.ftqIdx.get, io.in.fire)
redirect.ftqOffset := RegEnable(io.in.bits.ctrl.ftqOffset.get, io.in.fire)
redirect.cfiUpdate.predTaken := true.B
redirect.cfiUpdate.taken := true.B
redirect.cfiUpdate.target := csrMod.io.out.bits.targetPc.pc
Expand All @@ -288,18 +292,18 @@ class CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
// Only mispred will send redirect to frontend
redirect.cfiUpdate.isMisPred := true.B

connectNonPipedCtrlSingalForCSR
connectNonPipedCtrlSingal

override val criticalErrors = csrMod.getCriticalErrors
generateCriticalErrors()

// Todo: summerize all difftest skip condition
csrOut.isPerfCnt := io.out.valid && csrMod.io.out.bits.isPerfCnt && DataHoldBypass(func =/= CSROpType.jmp, false.B, io.in.fire)
csrOut.isPerfCnt := io.out.valid && csrMod.io.out.bits.isPerfCnt && RegEnable(func =/= CSROpType.jmp, false.B, io.in.fire)
csrOut.fpu.frm := csrMod.io.status.fpState.frm.asUInt
csrOut.vpu.vstart := csrMod.io.status.vecState.vstart.asUInt
csrOut.vpu.vxrm := csrMod.io.status.vecState.vxrm.asUInt

csrOut.isXRet := isXRetFlag
csrOut.isXRet := RegEnable(isXRetFlag, false.B, io.in.fire)

csrOut.trapTarget := csrMod.io.out.bits.targetPc
csrOut.interrupt := csrMod.io.status.interrupt
Expand Down Expand Up @@ -345,8 +349,8 @@ class CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
// distribute csr write signal
// write to frontend and memory
custom.distribute_csr.w.valid := csrMod.io.distributedWenLegal
custom.distribute_csr.w.bits.addr := addr
custom.distribute_csr.w.bits.data := wdata
custom.distribute_csr.w.bits.addr := waddrReg
custom.distribute_csr.w.bits.data := wdataReg
// rename single step
custom.singlestep := csrMod.io.status.singleStepFlag
// trigger
Expand Down

0 comments on commit 9816069

Please sign in to comment.