1*24519898SXuan Hu/*************************************************************************************** 2*24519898SXuan Hu* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*24519898SXuan Hu* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*24519898SXuan Hu* 5*24519898SXuan Hu* XiangShan is licensed under Mulan PSL v2. 6*24519898SXuan Hu* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*24519898SXuan Hu* You may obtain a copy of Mulan PSL v2 at: 8*24519898SXuan Hu* http://license.coscl.org.cn/MulanPSL2 9*24519898SXuan Hu* 10*24519898SXuan Hu* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*24519898SXuan Hu* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*24519898SXuan Hu* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*24519898SXuan Hu* 14*24519898SXuan Hu* See the Mulan PSL v2 for more details. 15*24519898SXuan Hu***************************************************************************************/ 16*24519898SXuan Hu 17*24519898SXuan Hupackage xiangshan.backend 18*24519898SXuan Hu 19*24519898SXuan Huimport chipsalliance.rocketchip.config.Parameters 20*24519898SXuan Huimport chisel3._ 21*24519898SXuan Huimport chisel3.util._ 22*24519898SXuan Huimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 23*24519898SXuan Huimport utility._ 24*24519898SXuan Huimport utils._ 25*24519898SXuan Huimport xiangshan.ExceptionNO._ 26*24519898SXuan Huimport xiangshan._ 27*24519898SXuan Huimport xiangshan.backend.Bundles.{DecodedInst, DynInst, ExceptionInfo, ExuOutput} 28*24519898SXuan Huimport xiangshan.backend.ctrlblock.{MemCtrl, RedirectGenerator} 29*24519898SXuan Huimport xiangshan.backend.datapath.DataConfig.VAddrData 30*24519898SXuan Huimport xiangshan.backend.decode.{DecodeStage, FusionDecoder} 31*24519898SXuan Huimport xiangshan.backend.dispatch.{Dispatch, DispatchQueue} 32*24519898SXuan Huimport xiangshan.backend.fu.PFEvent 33*24519898SXuan Huimport xiangshan.backend.fu.vector.Bundles.VType 34*24519898SXuan Huimport xiangshan.backend.rename.{Rename, RenameTableWrapper} 35*24519898SXuan Huimport xiangshan.backend.rob.{Rob, RobCSRIO, RobLsqIO} 36*24519898SXuan Huimport xiangshan.frontend.{FtqRead, Ftq_RF_Components} 37*24519898SXuan Hu 38*24519898SXuan Huclass CtrlToFtqIO(implicit p: Parameters) extends XSBundle { 39*24519898SXuan Hu def numRedirect = backendParams.numRedirect 40*24519898SXuan Hu val rob_commits = Vec(CommitWidth, Valid(new RobCommitInfo)) 41*24519898SXuan Hu val redirect = Valid(new Redirect) 42*24519898SXuan Hu} 43*24519898SXuan Hu 44*24519898SXuan Huclass CtrlBlock(params: BackendParams)(implicit p: Parameters) extends LazyModule { 45*24519898SXuan Hu val rob = LazyModule(new Rob(params)) 46*24519898SXuan Hu 47*24519898SXuan Hu lazy val module = new CtrlBlockImp(this)(p, params) 48*24519898SXuan Hu 49*24519898SXuan Hu} 50*24519898SXuan Hu 51*24519898SXuan Huclass CtrlBlockImp( 52*24519898SXuan Hu override val wrapper: CtrlBlock 53*24519898SXuan Hu)(implicit 54*24519898SXuan Hu p: Parameters, 55*24519898SXuan Hu params: BackendParams 56*24519898SXuan Hu) extends LazyModuleImp(wrapper) 57*24519898SXuan Hu with HasXSParameter 58*24519898SXuan Hu with HasCircularQueuePtrHelper 59*24519898SXuan Hu with HasPerfEvents 60*24519898SXuan Hu{ 61*24519898SXuan Hu val pcMemRdIndexes = new NamedIndexes(Seq( 62*24519898SXuan Hu "exu" -> params.numPcReadPort, 63*24519898SXuan Hu "redirect" -> 1, 64*24519898SXuan Hu "memPred" -> 1, 65*24519898SXuan Hu "robFlush" -> 1, 66*24519898SXuan Hu "load" -> params.LduCnt, 67*24519898SXuan Hu )) 68*24519898SXuan Hu 69*24519898SXuan Hu private val numPcMemReadForExu = params.numPcReadPort 70*24519898SXuan Hu private val numPcMemRead = pcMemRdIndexes.maxIdx 71*24519898SXuan Hu 72*24519898SXuan Hu private val numTargetMemRead = numPcMemReadForExu 73*24519898SXuan Hu 74*24519898SXuan Hu println(s"pcMem read num: $numPcMemRead") 75*24519898SXuan Hu println(s"pcMem read num for exu: $numPcMemReadForExu") 76*24519898SXuan Hu println(s"targetMem read num: $numTargetMemRead") 77*24519898SXuan Hu 78*24519898SXuan Hu val io = IO(new CtrlBlockIO()) 79*24519898SXuan Hu 80*24519898SXuan Hu val decode = Module(new DecodeStage) 81*24519898SXuan Hu val fusionDecoder = Module(new FusionDecoder) 82*24519898SXuan Hu val rat = Module(new RenameTableWrapper) 83*24519898SXuan Hu val rename = Module(new Rename) 84*24519898SXuan Hu val dispatch = Module(new Dispatch) 85*24519898SXuan Hu val intDq = Module(new DispatchQueue(dpParams.IntDqSize, RenameWidth, dpParams.IntDqDeqWidth)) 86*24519898SXuan Hu val fpDq = Module(new DispatchQueue(dpParams.FpDqSize, RenameWidth, dpParams.FpDqDeqWidth)) 87*24519898SXuan Hu val lsDq = Module(new DispatchQueue(dpParams.LsDqSize, RenameWidth, dpParams.LsDqDeqWidth)) 88*24519898SXuan Hu val redirectGen = Module(new RedirectGenerator) 89*24519898SXuan Hu private val pcMem = Module(new SyncDataModuleTemplate(new Ftq_RF_Components, FtqSize, numPcMemRead, 1, "BackendPC")) 90*24519898SXuan Hu private val targetMem = Module(new SyncDataModuleTemplate(UInt(VAddrData().dataWidth.W), FtqSize, numTargetMemRead, 1)) 91*24519898SXuan Hu private val rob = wrapper.rob.module 92*24519898SXuan Hu private val memCtrl = Module(new MemCtrl(params)) 93*24519898SXuan Hu 94*24519898SXuan Hu private val disableFusion = decode.io.csrCtrl.singlestep || !decode.io.csrCtrl.fusion_enable 95*24519898SXuan Hu 96*24519898SXuan Hu private val s0_robFlushRedirect = rob.io.flushOut 97*24519898SXuan Hu private val s1_robFlushRedirect = Wire(Valid(new Redirect)) 98*24519898SXuan Hu s1_robFlushRedirect.valid := RegNext(s0_robFlushRedirect.valid) 99*24519898SXuan Hu s1_robFlushRedirect.bits := RegEnable(s0_robFlushRedirect.bits, s0_robFlushRedirect.valid) 100*24519898SXuan Hu 101*24519898SXuan Hu pcMem.io.raddr(pcMemRdIndexes("robFlush").head) := s0_robFlushRedirect.bits.ftqIdx.value 102*24519898SXuan Hu private val s1_robFlushPc = pcMem.io.rdata(pcMemRdIndexes("robFlush").head).getPc(RegNext(s0_robFlushRedirect.bits.ftqOffset)) 103*24519898SXuan Hu private val s3_redirectGen = redirectGen.io.stage2Redirect 104*24519898SXuan Hu private val s1_s3_redirect = Mux(s1_robFlushRedirect.valid, s1_robFlushRedirect, s3_redirectGen) 105*24519898SXuan Hu private val s2_s4_pendingRedirectValid = RegInit(false.B) 106*24519898SXuan Hu when (s1_s3_redirect.valid) { 107*24519898SXuan Hu s2_s4_pendingRedirectValid := true.B 108*24519898SXuan Hu }.elsewhen (RegNext(io.frontend.toFtq.redirect.valid)) { 109*24519898SXuan Hu s2_s4_pendingRedirectValid := false.B 110*24519898SXuan Hu } 111*24519898SXuan Hu 112*24519898SXuan Hu // Redirect will be RegNext at ExuBlocks and IssueBlocks 113*24519898SXuan Hu val s2_s4_redirect = RegNextWithEnable(s1_s3_redirect) 114*24519898SXuan Hu val s3_s5_redirect = RegNextWithEnable(s2_s4_redirect) 115*24519898SXuan Hu 116*24519898SXuan Hu private val delayedNotFlushedWriteBack = io.fromWB.wbData.map(x => { 117*24519898SXuan Hu val valid = x.valid 118*24519898SXuan Hu val killedByOlder = x.bits.robIdx.needFlush(Seq(s1_s3_redirect, s2_s4_redirect, s3_s5_redirect)) 119*24519898SXuan Hu val delayed = Wire(Valid(new ExuOutput(x.bits.params))) 120*24519898SXuan Hu delayed.valid := RegNext(valid && !killedByOlder) 121*24519898SXuan Hu delayed.bits := RegEnable(x.bits, x.valid) 122*24519898SXuan Hu delayed 123*24519898SXuan Hu }) 124*24519898SXuan Hu 125*24519898SXuan Hu private val exuPredecode = VecInit( 126*24519898SXuan Hu delayedNotFlushedWriteBack.filter(_.bits.redirect.nonEmpty).map(x => x.bits.predecodeInfo.get) 127*24519898SXuan Hu ) 128*24519898SXuan Hu 129*24519898SXuan Hu private val exuRedirects: IndexedSeq[ValidIO[Redirect]] = delayedNotFlushedWriteBack.filter(_.bits.redirect.nonEmpty).map(x => { 130*24519898SXuan Hu val out = Wire(Valid(new Redirect())) 131*24519898SXuan Hu out.valid := x.valid && x.bits.redirect.get.valid && x.bits.redirect.get.bits.cfiUpdate.isMisPred 132*24519898SXuan Hu out.bits := x.bits.redirect.get.bits 133*24519898SXuan Hu out 134*24519898SXuan Hu }) 135*24519898SXuan Hu 136*24519898SXuan Hu private val memViolation = io.fromMem.violation 137*24519898SXuan Hu val loadReplay = Wire(ValidIO(new Redirect)) 138*24519898SXuan Hu loadReplay.valid := RegNext(memViolation.valid && 139*24519898SXuan Hu !memViolation.bits.robIdx.needFlush(Seq(s1_s3_redirect, s2_s4_redirect)) 140*24519898SXuan Hu ) 141*24519898SXuan Hu loadReplay.bits := RegEnable(memViolation.bits, memViolation.valid) 142*24519898SXuan Hu 143*24519898SXuan Hu val pdestReverse = rob.io.commits.info.map(info => info.pdest).reverse 144*24519898SXuan Hu 145*24519898SXuan Hu pcMem.io.raddr(pcMemRdIndexes("redirect").head) := redirectGen.io.redirectPcRead.ptr.value 146*24519898SXuan Hu redirectGen.io.redirectPcRead.data := pcMem.io.rdata(pcMemRdIndexes("redirect").head).getPc(RegNext(redirectGen.io.redirectPcRead.offset)) 147*24519898SXuan Hu pcMem.io.raddr(pcMemRdIndexes("memPred").head) := redirectGen.io.memPredPcRead.ptr.value 148*24519898SXuan Hu redirectGen.io.memPredPcRead.data := pcMem.io.rdata(pcMemRdIndexes("memPred").head).getPc(RegNext(redirectGen.io.memPredPcRead.offset)) 149*24519898SXuan Hu 150*24519898SXuan Hu for ((pcMemIdx, i) <- pcMemRdIndexes("load").zipWithIndex) { 151*24519898SXuan Hu pcMem.io.raddr(pcMemIdx) := io.memLdPcRead(i).ptr.value 152*24519898SXuan Hu io.memLdPcRead(i).data := pcMem.io.rdata(pcMemIdx).getPc(RegNext(io.memLdPcRead(i).offset)) 153*24519898SXuan Hu } 154*24519898SXuan Hu 155*24519898SXuan Hu redirectGen.io.hartId := io.fromTop.hartId 156*24519898SXuan Hu redirectGen.io.exuRedirect := exuRedirects 157*24519898SXuan Hu redirectGen.io.exuOutPredecode := exuPredecode // garded by exuRedirect.valid 158*24519898SXuan Hu redirectGen.io.loadReplay <> loadReplay 159*24519898SXuan Hu 160*24519898SXuan Hu redirectGen.io.robFlush := s1_robFlushRedirect.valid 161*24519898SXuan Hu 162*24519898SXuan Hu val s6_frontendFlushValid = DelayN(s1_robFlushRedirect.valid, 5) 163*24519898SXuan Hu val frontendFlushBits = RegEnable(s1_robFlushRedirect.bits, s1_robFlushRedirect.valid) // ?? 164*24519898SXuan Hu // When ROB commits an instruction with a flush, we notify the frontend of the flush without the commit. 165*24519898SXuan Hu // Flushes to frontend may be delayed by some cycles and commit before flush causes errors. 166*24519898SXuan Hu // Thus, we make all flush reasons to behave the same as exceptions for frontend. 167*24519898SXuan Hu for (i <- 0 until CommitWidth) { 168*24519898SXuan Hu // why flushOut: instructions with flushPipe are not commited to frontend 169*24519898SXuan Hu // If we commit them to frontend, it will cause flush after commit, which is not acceptable by frontend. 170*24519898SXuan Hu val s1_isCommit = rob.io.commits.commitValid(i) && rob.io.commits.isCommit && !s0_robFlushRedirect.valid 171*24519898SXuan Hu io.frontend.toFtq.rob_commits(i).valid := RegNext(s1_isCommit) 172*24519898SXuan Hu io.frontend.toFtq.rob_commits(i).bits := RegEnable(rob.io.commits.info(i), s1_isCommit) 173*24519898SXuan Hu } 174*24519898SXuan Hu io.frontend.toFtq.redirect.valid := s6_frontendFlushValid || s3_redirectGen.valid 175*24519898SXuan Hu io.frontend.toFtq.redirect.bits := Mux(s6_frontendFlushValid, frontendFlushBits, s3_redirectGen.bits) 176*24519898SXuan Hu // Be careful here: 177*24519898SXuan Hu // T0: rob.io.flushOut, s0_robFlushRedirect 178*24519898SXuan Hu // T1: s1_robFlushRedirect, rob.io.exception.valid 179*24519898SXuan Hu // T2: csr.redirect.valid 180*24519898SXuan Hu // T3: csr.exception.valid 181*24519898SXuan Hu // T4: csr.trapTarget 182*24519898SXuan Hu // T5: ctrlBlock.trapTarget 183*24519898SXuan Hu // T6: io.frontend.toFtq.stage2Redirect.valid 184*24519898SXuan Hu val s2_robFlushPc = RegEnable(Mux(s1_robFlushRedirect.bits.flushItself(), 185*24519898SXuan Hu s1_robFlushPc, // replay inst 186*24519898SXuan Hu s1_robFlushPc + 4.U // flush pipe 187*24519898SXuan Hu ), s1_robFlushRedirect.valid) 188*24519898SXuan Hu private val s2_csrIsXRet = io.robio.csr.isXRet 189*24519898SXuan Hu private val s5_csrIsTrap = DelayN(rob.io.exception.valid, 4) 190*24519898SXuan Hu private val s2_s5_trapTargetFromCsr = io.robio.csr.trapTarget 191*24519898SXuan Hu 192*24519898SXuan Hu val flushTarget = Mux(s2_csrIsXRet || s5_csrIsTrap, s2_s5_trapTargetFromCsr, s2_robFlushPc) 193*24519898SXuan Hu when (s6_frontendFlushValid) { 194*24519898SXuan Hu io.frontend.toFtq.redirect.bits.level := RedirectLevel.flush 195*24519898SXuan Hu io.frontend.toFtq.redirect.bits.cfiUpdate.target := RegNext(flushTarget) 196*24519898SXuan Hu } 197*24519898SXuan Hu 198*24519898SXuan Hu if (env.EnableTopDown) { 199*24519898SXuan Hu val stage2Redirect_valid_when_pending = s2_s4_pendingRedirectValid && s1_s3_redirect.valid 200*24519898SXuan Hu 201*24519898SXuan Hu val stage2_redirect_cycles = RegInit(false.B) // frontend_bound->fetch_lantency->stage2_redirect 202*24519898SXuan Hu val MissPredPending = RegInit(false.B); val branch_resteers_cycles = RegInit(false.B) // frontend_bound->fetch_lantency->stage2_redirect->branch_resteers 203*24519898SXuan Hu val RobFlushPending = RegInit(false.B); val robFlush_bubble_cycles = RegInit(false.B) // frontend_bound->fetch_lantency->stage2_redirect->robflush_bubble 204*24519898SXuan Hu val LdReplayPending = RegInit(false.B); val ldReplay_bubble_cycles = RegInit(false.B) // frontend_bound->fetch_lantency->stage2_redirect->ldReplay_bubble 205*24519898SXuan Hu 206*24519898SXuan Hu when(redirectGen.io.isMisspreRedirect) { MissPredPending := true.B } 207*24519898SXuan Hu when(s1_robFlushRedirect.valid) { RobFlushPending := true.B } 208*24519898SXuan Hu when(redirectGen.io.loadReplay.valid) { LdReplayPending := true.B } 209*24519898SXuan Hu 210*24519898SXuan Hu when (RegNext(io.frontend.toFtq.redirect.valid)) { 211*24519898SXuan Hu when(s2_s4_pendingRedirectValid) { stage2_redirect_cycles := true.B } 212*24519898SXuan Hu when(MissPredPending) { MissPredPending := false.B; branch_resteers_cycles := true.B } 213*24519898SXuan Hu when(RobFlushPending) { RobFlushPending := false.B; robFlush_bubble_cycles := true.B } 214*24519898SXuan Hu when(LdReplayPending) { LdReplayPending := false.B; ldReplay_bubble_cycles := true.B } 215*24519898SXuan Hu } 216*24519898SXuan Hu 217*24519898SXuan Hu when(VecInit(decode.io.out.map(x => x.valid)).asUInt.orR){ 218*24519898SXuan Hu when(stage2_redirect_cycles) { stage2_redirect_cycles := false.B } 219*24519898SXuan Hu when(branch_resteers_cycles) { branch_resteers_cycles := false.B } 220*24519898SXuan Hu when(robFlush_bubble_cycles) { robFlush_bubble_cycles := false.B } 221*24519898SXuan Hu when(ldReplay_bubble_cycles) { ldReplay_bubble_cycles := false.B } 222*24519898SXuan Hu } 223*24519898SXuan Hu 224*24519898SXuan Hu XSPerfAccumulate("stage2_redirect_cycles", stage2_redirect_cycles) 225*24519898SXuan Hu XSPerfAccumulate("branch_resteers_cycles", branch_resteers_cycles) 226*24519898SXuan Hu XSPerfAccumulate("robFlush_bubble_cycles", robFlush_bubble_cycles) 227*24519898SXuan Hu XSPerfAccumulate("ldReplay_bubble_cycles", ldReplay_bubble_cycles) 228*24519898SXuan Hu XSPerfAccumulate("s2Redirect_pend_cycles", stage2Redirect_valid_when_pending) 229*24519898SXuan Hu } 230*24519898SXuan Hu 231*24519898SXuan Hu // vtype commit 232*24519898SXuan Hu decode.io.commitVType.bits := io.fromDataPath.vtype 233*24519898SXuan Hu decode.io.commitVType.valid := RegNext(rob.io.isVsetFlushPipe) 234*24519898SXuan Hu 235*24519898SXuan Hu io.toDataPath.vtypeAddr := rob.io.vconfigPdest 236*24519898SXuan Hu 237*24519898SXuan Hu // vtype walk 238*24519898SXuan Hu val isVsetSeq = rob.io.commits.walkValid.zip(rob.io.commits.info).map { case (valid, info) => valid && info.isVset }.reverse 239*24519898SXuan Hu val walkVTypeReverse = rob.io.commits.info.map(info => info.vtype).reverse 240*24519898SXuan Hu val walkVType = PriorityMux(isVsetSeq, walkVTypeReverse) 241*24519898SXuan Hu 242*24519898SXuan Hu decode.io.walkVType.bits := walkVType.asTypeOf(new VType) 243*24519898SXuan Hu decode.io.walkVType.valid := rob.io.commits.isWalk && isVsetSeq.reduce(_ || _) 244*24519898SXuan Hu 245*24519898SXuan Hu decode.io.isRedirect := s1_s3_redirect.valid 246*24519898SXuan Hu 247*24519898SXuan Hu decode.io.in.zip(io.frontend.cfVec).foreach { case (decodeIn, frontendCf) => 248*24519898SXuan Hu decodeIn.valid := frontendCf.valid 249*24519898SXuan Hu frontendCf.ready := decodeIn.ready 250*24519898SXuan Hu decodeIn.bits.connectCtrlFlow(frontendCf.bits) 251*24519898SXuan Hu } 252*24519898SXuan Hu decode.io.csrCtrl := RegNext(io.csrCtrl) 253*24519898SXuan Hu decode.io.intRat <> rat.io.intReadPorts 254*24519898SXuan Hu decode.io.fpRat <> rat.io.fpReadPorts 255*24519898SXuan Hu decode.io.vecRat <> rat.io.vecReadPorts 256*24519898SXuan Hu decode.io.fusion := 0.U.asTypeOf(decode.io.fusion) // Todo 257*24519898SXuan Hu 258*24519898SXuan Hu val decodeHasException = decode.io.out.map(x => x.bits.exceptionVec(instrPageFault) || x.bits.exceptionVec(instrAccessFault)) 259*24519898SXuan Hu // fusion decoder 260*24519898SXuan Hu for (i <- 0 until DecodeWidth) { 261*24519898SXuan Hu fusionDecoder.io.in(i).valid := decode.io.out(i).valid && !(decodeHasException(i) || disableFusion) 262*24519898SXuan Hu fusionDecoder.io.in(i).bits := decode.io.out(i).bits.instr 263*24519898SXuan Hu if (i > 0) { 264*24519898SXuan Hu fusionDecoder.io.inReady(i - 1) := decode.io.out(i).ready 265*24519898SXuan Hu } 266*24519898SXuan Hu } 267*24519898SXuan Hu 268*24519898SXuan Hu private val decodePipeRename = Wire(Vec(RenameWidth, DecoupledIO(new DecodedInst))) 269*24519898SXuan Hu 270*24519898SXuan Hu for (i <- 0 until RenameWidth) { 271*24519898SXuan Hu PipelineConnect(decode.io.out(i), decodePipeRename(i), rename.io.in(i).ready, 272*24519898SXuan Hu s1_s3_redirect.valid || s2_s4_pendingRedirectValid, moduleName = Some("decodePipeRenameModule")) 273*24519898SXuan Hu 274*24519898SXuan Hu decodePipeRename(i).ready := rename.io.in(i).ready 275*24519898SXuan Hu rename.io.in(i).valid := decodePipeRename(i).valid && !fusionDecoder.io.clear(i) 276*24519898SXuan Hu rename.io.in(i).bits := decodePipeRename(i).bits 277*24519898SXuan Hu } 278*24519898SXuan Hu 279*24519898SXuan Hu for (i <- 0 until RenameWidth - 1) { 280*24519898SXuan Hu fusionDecoder.io.dec(i) := decodePipeRename(i).bits 281*24519898SXuan Hu rename.io.fusionInfo(i) := fusionDecoder.io.info(i) 282*24519898SXuan Hu 283*24519898SXuan Hu // update the first RenameWidth - 1 instructions 284*24519898SXuan Hu decode.io.fusion(i) := fusionDecoder.io.out(i).valid && rename.io.out(i).fire 285*24519898SXuan Hu when (fusionDecoder.io.out(i).valid) { 286*24519898SXuan Hu fusionDecoder.io.out(i).bits.update(rename.io.in(i).bits) 287*24519898SXuan Hu // TODO: remove this dirty code for ftq update 288*24519898SXuan Hu val sameFtqPtr = rename.io.in(i).bits.ftqPtr.value === rename.io.in(i + 1).bits.ftqPtr.value 289*24519898SXuan Hu val ftqOffset0 = rename.io.in(i).bits.ftqOffset 290*24519898SXuan Hu val ftqOffset1 = rename.io.in(i + 1).bits.ftqOffset 291*24519898SXuan Hu val ftqOffsetDiff = ftqOffset1 - ftqOffset0 292*24519898SXuan Hu val cond1 = sameFtqPtr && ftqOffsetDiff === 1.U 293*24519898SXuan Hu val cond2 = sameFtqPtr && ftqOffsetDiff === 2.U 294*24519898SXuan Hu val cond3 = !sameFtqPtr && ftqOffset1 === 0.U 295*24519898SXuan Hu val cond4 = !sameFtqPtr && ftqOffset1 === 1.U 296*24519898SXuan Hu rename.io.in(i).bits.commitType := Mux(cond1, 4.U, Mux(cond2, 5.U, Mux(cond3, 6.U, 7.U))) 297*24519898SXuan Hu XSError(!cond1 && !cond2 && !cond3 && !cond4, p"new condition $sameFtqPtr $ftqOffset0 $ftqOffset1\n") 298*24519898SXuan Hu } 299*24519898SXuan Hu 300*24519898SXuan Hu } 301*24519898SXuan Hu 302*24519898SXuan Hu // memory dependency predict 303*24519898SXuan Hu // when decode, send fold pc to mdp 304*24519898SXuan Hu private val mdpFlodPcVec = Wire(Vec(DecodeWidth, UInt(MemPredPCWidth.W))) 305*24519898SXuan Hu for (i <- 0 until DecodeWidth) { 306*24519898SXuan Hu mdpFlodPcVec(i) := Mux( 307*24519898SXuan Hu decode.io.out(i).fire, 308*24519898SXuan Hu decode.io.in(i).bits.foldpc, 309*24519898SXuan Hu rename.io.in(i).bits.foldpc 310*24519898SXuan Hu ) 311*24519898SXuan Hu } 312*24519898SXuan Hu 313*24519898SXuan Hu // currently, we only update mdp info when isReplay 314*24519898SXuan Hu memCtrl.io.redirect := s1_s3_redirect 315*24519898SXuan Hu memCtrl.io.csrCtrl := io.csrCtrl // RegNext in memCtrl 316*24519898SXuan Hu memCtrl.io.stIn := io.fromMem.stIn // RegNext in memCtrl 317*24519898SXuan Hu memCtrl.io.memPredUpdate := redirectGen.io.memPredUpdate // RegNext in memCtrl 318*24519898SXuan Hu memCtrl.io.mdpFlodPcVec := mdpFlodPcVec 319*24519898SXuan Hu memCtrl.io.dispatchLFSTio <> dispatch.io.lfst 320*24519898SXuan Hu 321*24519898SXuan Hu rat.io.redirect := s1_s3_redirect.valid 322*24519898SXuan Hu rat.io.robCommits := rob.io.rabCommits 323*24519898SXuan Hu rat.io.diffCommits := rob.io.diffCommits 324*24519898SXuan Hu rat.io.intRenamePorts := rename.io.intRenamePorts 325*24519898SXuan Hu rat.io.fpRenamePorts := rename.io.fpRenamePorts 326*24519898SXuan Hu rat.io.vecRenamePorts := rename.io.vecRenamePorts 327*24519898SXuan Hu 328*24519898SXuan Hu rename.io.redirect := s1_s3_redirect 329*24519898SXuan Hu rename.io.robCommits <> rob.io.rabCommits 330*24519898SXuan Hu rename.io.waittable := (memCtrl.io.waitTable2Rename zip decode.io.out).map{ case(waittable2rename, decodeOut) => 331*24519898SXuan Hu RegEnable(waittable2rename, decodeOut.fire) 332*24519898SXuan Hu } 333*24519898SXuan Hu rename.io.ssit := memCtrl.io.ssit2Rename 334*24519898SXuan Hu rename.io.intReadPorts := VecInit(rat.io.intReadPorts.map(x => VecInit(x.map(_.data)))) 335*24519898SXuan Hu rename.io.fpReadPorts := VecInit(rat.io.fpReadPorts.map(x => VecInit(x.map(_.data)))) 336*24519898SXuan Hu rename.io.vecReadPorts := VecInit(rat.io.vecReadPorts.map(x => VecInit(x.map(_.data)))) 337*24519898SXuan Hu rename.io.debug_int_rat := rat.io.debug_int_rat 338*24519898SXuan Hu rename.io.debug_fp_rat := rat.io.debug_fp_rat 339*24519898SXuan Hu rename.io.debug_vec_rat := rat.io.debug_vec_rat 340*24519898SXuan Hu rename.io.debug_vconfig_rat := rat.io.debug_vconfig_rat 341*24519898SXuan Hu 342*24519898SXuan Hu // pipeline between rename and dispatch 343*24519898SXuan Hu for (i <- 0 until RenameWidth) { 344*24519898SXuan Hu PipelineConnect(rename.io.out(i), dispatch.io.fromRename(i), dispatch.io.recv(i), s1_s3_redirect.valid) 345*24519898SXuan Hu } 346*24519898SXuan Hu 347*24519898SXuan Hu dispatch.io.hartId := io.fromTop.hartId 348*24519898SXuan Hu dispatch.io.redirect := s1_s3_redirect 349*24519898SXuan Hu dispatch.io.enqRob <> rob.io.enq 350*24519898SXuan Hu dispatch.io.singleStep := RegNext(io.csrCtrl.singlestep) 351*24519898SXuan Hu 352*24519898SXuan Hu intDq.io.enq <> dispatch.io.toIntDq 353*24519898SXuan Hu intDq.io.redirect <> s2_s4_redirect 354*24519898SXuan Hu 355*24519898SXuan Hu fpDq.io.enq <> dispatch.io.toFpDq 356*24519898SXuan Hu fpDq.io.redirect <> s2_s4_redirect 357*24519898SXuan Hu 358*24519898SXuan Hu lsDq.io.enq <> dispatch.io.toLsDq 359*24519898SXuan Hu lsDq.io.redirect <> s2_s4_redirect 360*24519898SXuan Hu 361*24519898SXuan Hu io.toIssueBlock.intUops <> intDq.io.deq 362*24519898SXuan Hu io.toIssueBlock.vfUops <> fpDq.io.deq 363*24519898SXuan Hu io.toIssueBlock.memUops <> lsDq.io.deq 364*24519898SXuan Hu io.toIssueBlock.allocPregs <> dispatch.io.allocPregs 365*24519898SXuan Hu io.toIssueBlock.flush <> s2_s4_redirect 366*24519898SXuan Hu 367*24519898SXuan Hu pcMem.io.wen.head := RegNext(io.frontend.fromFtq.pc_mem_wen) 368*24519898SXuan Hu pcMem.io.waddr.head := RegNext(io.frontend.fromFtq.pc_mem_waddr) 369*24519898SXuan Hu pcMem.io.wdata.head := RegNext(io.frontend.fromFtq.pc_mem_wdata) 370*24519898SXuan Hu targetMem.io.wen.head := RegNext(io.frontend.fromFtq.pc_mem_wen) 371*24519898SXuan Hu targetMem.io.waddr.head := RegNext(io.frontend.fromFtq.pc_mem_waddr) 372*24519898SXuan Hu targetMem.io.wdata.head := RegNext(io.frontend.fromFtq.pc_mem_wdata.startAddr) 373*24519898SXuan Hu 374*24519898SXuan Hu private val jumpPcVec : Vec[UInt] = Wire(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W))) 375*24519898SXuan Hu private val jumpTargetReadVec : Vec[UInt] = Wire(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W))) 376*24519898SXuan Hu private val jumpTargetVec : Vec[UInt] = Wire(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W))) 377*24519898SXuan Hu io.toIssueBlock.pcVec := jumpPcVec 378*24519898SXuan Hu io.toIssueBlock.targetVec := jumpTargetVec 379*24519898SXuan Hu 380*24519898SXuan Hu io.toDataPath.flush := s2_s4_redirect 381*24519898SXuan Hu io.toExuBlock.flush := s2_s4_redirect 382*24519898SXuan Hu 383*24519898SXuan Hu for ((pcMemIdx, i) <- pcMemRdIndexes("exu").zipWithIndex) { 384*24519898SXuan Hu pcMem.io.raddr(pcMemIdx) := intDq.io.deqNext(i).ftqPtr.value 385*24519898SXuan Hu jumpPcVec(i) := pcMem.io.rdata(pcMemIdx).getPc(RegNext(intDq.io.deqNext(i).ftqOffset)) 386*24519898SXuan Hu } 387*24519898SXuan Hu 388*24519898SXuan Hu val dqOuts = Seq(io.toIssueBlock.intUops) ++ Seq(io.toIssueBlock.vfUops) ++ Seq(io.toIssueBlock.memUops) 389*24519898SXuan Hu dqOuts.zipWithIndex.foreach { case (dqOut, dqIdx) => 390*24519898SXuan Hu dqOut.map(_.bits.pc).zipWithIndex.map{ case (pc, portIdx) => 391*24519898SXuan Hu if(params.allSchdParams(dqIdx).numPcReadPort > 0){ 392*24519898SXuan Hu val realJumpPcVec = jumpPcVec.drop(params.allSchdParams.take(dqIdx).map(_.numPcReadPort).sum).take(params.allSchdParams(dqIdx).numPcReadPort) 393*24519898SXuan Hu pc := realJumpPcVec(portIdx) 394*24519898SXuan Hu } 395*24519898SXuan Hu } 396*24519898SXuan Hu } 397*24519898SXuan Hu 398*24519898SXuan Hu private val newestTarget: UInt = io.frontend.fromFtq.newest_entry_target 399*24519898SXuan Hu for (i <- 0 until numTargetMemRead) { 400*24519898SXuan Hu val targetPtr = intDq.io.deqNext(i).ftqPtr 401*24519898SXuan Hu // target pc stored in next entry 402*24519898SXuan Hu targetMem.io.raddr(i) := (targetPtr + 1.U).value 403*24519898SXuan Hu jumpTargetReadVec(i) := targetMem.io.rdata(i) 404*24519898SXuan Hu val needNewestTarget = RegNext(targetPtr === io.frontend.fromFtq.newest_entry_ptr) 405*24519898SXuan Hu jumpTargetVec(i) := Mux( 406*24519898SXuan Hu needNewestTarget, 407*24519898SXuan Hu RegNext(newestTarget), 408*24519898SXuan Hu jumpTargetReadVec(i) 409*24519898SXuan Hu ) 410*24519898SXuan Hu } 411*24519898SXuan Hu 412*24519898SXuan Hu rob.io.hartId := io.fromTop.hartId 413*24519898SXuan Hu rob.io.redirect := s1_s3_redirect 414*24519898SXuan Hu rob.io.writeback := delayedNotFlushedWriteBack 415*24519898SXuan Hu 416*24519898SXuan Hu io.redirect := s1_s3_redirect 417*24519898SXuan Hu 418*24519898SXuan Hu // rob to int block 419*24519898SXuan Hu io.robio.csr <> rob.io.csr 420*24519898SXuan Hu // When wfi is disabled, it will not block ROB commit. 421*24519898SXuan Hu rob.io.csr.wfiEvent := io.robio.csr.wfiEvent 422*24519898SXuan Hu rob.io.wfi_enable := decode.io.csrCtrl.wfi_enable 423*24519898SXuan Hu 424*24519898SXuan Hu io.toTop.cpuHalt := DelayN(rob.io.cpu_halt, 5) 425*24519898SXuan Hu 426*24519898SXuan Hu io.robio.csr.perfinfo.retiredInstr <> RegNext(rob.io.csr.perfinfo.retiredInstr) 427*24519898SXuan Hu io.robio.exception := rob.io.exception 428*24519898SXuan Hu io.robio.exception.bits.pc := s1_robFlushPc 429*24519898SXuan Hu 430*24519898SXuan Hu // rob to mem block 431*24519898SXuan Hu io.robio.lsq <> rob.io.lsq 432*24519898SXuan Hu 433*24519898SXuan Hu io.debug_int_rat := rat.io.diff_int_rat 434*24519898SXuan Hu io.debug_fp_rat := rat.io.diff_fp_rat 435*24519898SXuan Hu io.debug_vec_rat := rat.io.diff_vec_rat 436*24519898SXuan Hu io.debug_vconfig_rat := rat.io.diff_vconfig_rat 437*24519898SXuan Hu 438*24519898SXuan Hu io.perfInfo.ctrlInfo.robFull := RegNext(rob.io.robFull) 439*24519898SXuan Hu io.perfInfo.ctrlInfo.intdqFull := RegNext(intDq.io.dqFull) 440*24519898SXuan Hu io.perfInfo.ctrlInfo.fpdqFull := RegNext(fpDq.io.dqFull) 441*24519898SXuan Hu io.perfInfo.ctrlInfo.lsdqFull := RegNext(lsDq.io.dqFull) 442*24519898SXuan Hu 443*24519898SXuan Hu val pfevent = Module(new PFEvent) 444*24519898SXuan Hu pfevent.io.distribute_csr := RegNext(io.csrCtrl.distribute_csr) 445*24519898SXuan Hu val csrevents = pfevent.io.hpmevent.slice(8,16) 446*24519898SXuan Hu 447*24519898SXuan Hu val perfinfo = IO(new Bundle(){ 448*24519898SXuan Hu val perfEventsRs = Input(Vec(params.IqCnt, new PerfEvent)) 449*24519898SXuan Hu val perfEventsEu0 = Input(Vec(6, new PerfEvent)) 450*24519898SXuan Hu val perfEventsEu1 = Input(Vec(6, new PerfEvent)) 451*24519898SXuan Hu }) 452*24519898SXuan Hu 453*24519898SXuan Hu val allPerfEvents = Seq(decode, rename, dispatch, intDq, fpDq, lsDq, rob).flatMap(_.getPerf) 454*24519898SXuan Hu val hpmEvents = allPerfEvents ++ perfinfo.perfEventsEu0 ++ perfinfo.perfEventsEu1 ++ perfinfo.perfEventsRs 455*24519898SXuan Hu val perfEvents = HPerfMonitor(csrevents, hpmEvents).getPerfEvents 456*24519898SXuan Hu generatePerfEvent() 457*24519898SXuan Hu} 458*24519898SXuan Hu 459*24519898SXuan Huclass CtrlBlockIO()(implicit p: Parameters, params: BackendParams) extends XSBundle { 460*24519898SXuan Hu val fromTop = new Bundle { 461*24519898SXuan Hu val hartId = Input(UInt(8.W)) 462*24519898SXuan Hu } 463*24519898SXuan Hu val toTop = new Bundle { 464*24519898SXuan Hu val cpuHalt = Output(Bool()) 465*24519898SXuan Hu } 466*24519898SXuan Hu val frontend = Flipped(new FrontendToCtrlIO()) 467*24519898SXuan Hu val toIssueBlock = new Bundle { 468*24519898SXuan Hu val flush = ValidIO(new Redirect) 469*24519898SXuan Hu val allocPregs = Vec(RenameWidth, Output(new ResetPregStateReq)) 470*24519898SXuan Hu val intUops = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new DynInst)) 471*24519898SXuan Hu val vfUops = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new DynInst)) 472*24519898SXuan Hu val memUops = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new DynInst)) 473*24519898SXuan Hu val pcVec = Output(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W))) 474*24519898SXuan Hu val targetVec = Output(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W))) 475*24519898SXuan Hu } 476*24519898SXuan Hu val fromDataPath = new Bundle{ 477*24519898SXuan Hu val vtype = Input(new VType) 478*24519898SXuan Hu } 479*24519898SXuan Hu val toDataPath = new Bundle { 480*24519898SXuan Hu val vtypeAddr = Output(UInt(PhyRegIdxWidth.W)) 481*24519898SXuan Hu val flush = ValidIO(new Redirect) 482*24519898SXuan Hu } 483*24519898SXuan Hu val toExuBlock = new Bundle { 484*24519898SXuan Hu val flush = ValidIO(new Redirect) 485*24519898SXuan Hu } 486*24519898SXuan Hu val fromWB = new Bundle { 487*24519898SXuan Hu val wbData = Flipped(MixedVec(params.genWrite2CtrlBundles)) 488*24519898SXuan Hu } 489*24519898SXuan Hu val redirect = ValidIO(new Redirect) 490*24519898SXuan Hu val fromMem = new Bundle { 491*24519898SXuan Hu val stIn = Vec(params.StaCnt, Flipped(ValidIO(new DynInst))) // use storeSetHit, ssid, robIdx 492*24519898SXuan Hu val violation = Flipped(ValidIO(new Redirect)) 493*24519898SXuan Hu } 494*24519898SXuan Hu val memLdPcRead = Vec(params.LduCnt, Flipped(new FtqRead(UInt(VAddrBits.W)))) 495*24519898SXuan Hu val csrCtrl = Input(new CustomCSRCtrlIO) 496*24519898SXuan Hu val robio = new Bundle { 497*24519898SXuan Hu val csr = new RobCSRIO 498*24519898SXuan Hu val exception = ValidIO(new ExceptionInfo) 499*24519898SXuan Hu val lsq = new RobLsqIO 500*24519898SXuan Hu } 501*24519898SXuan Hu 502*24519898SXuan Hu val perfInfo = Output(new Bundle{ 503*24519898SXuan Hu val ctrlInfo = new Bundle { 504*24519898SXuan Hu val robFull = Bool() 505*24519898SXuan Hu val intdqFull = Bool() 506*24519898SXuan Hu val fpdqFull = Bool() 507*24519898SXuan Hu val lsdqFull = Bool() 508*24519898SXuan Hu } 509*24519898SXuan Hu }) 510*24519898SXuan Hu val debug_int_rat = Vec(32, Output(UInt(PhyRegIdxWidth.W))) 511*24519898SXuan Hu val debug_fp_rat = Vec(32, Output(UInt(PhyRegIdxWidth.W))) 512*24519898SXuan Hu val debug_vec_rat = Vec(32, Output(UInt(PhyRegIdxWidth.W))) 513*24519898SXuan Hu val debug_vconfig_rat = Output(UInt(PhyRegIdxWidth.W)) // TODO: use me 514*24519898SXuan Hu 515*24519898SXuan Hu} 516*24519898SXuan Hu 517*24519898SXuan Huclass NamedIndexes(namedCnt: Seq[(String, Int)]) { 518*24519898SXuan Hu require(namedCnt.map(_._1).distinct.size == namedCnt.size, "namedCnt should not have the same name") 519*24519898SXuan Hu 520*24519898SXuan Hu val maxIdx = namedCnt.map(_._2).sum 521*24519898SXuan Hu val nameRangeMap: Map[String, (Int, Int)] = namedCnt.indices.map { i => 522*24519898SXuan Hu val begin = namedCnt.slice(0, i).map(_._2).sum 523*24519898SXuan Hu val end = begin + namedCnt(i)._2 524*24519898SXuan Hu (namedCnt(i)._1, (begin, end)) 525*24519898SXuan Hu }.toMap 526*24519898SXuan Hu 527*24519898SXuan Hu def apply(name: String): Seq[Int] = { 528*24519898SXuan Hu require(nameRangeMap.contains(name)) 529*24519898SXuan Hu nameRangeMap(name)._1 until nameRangeMap(name)._2 530*24519898SXuan Hu } 531*24519898SXuan Hu} 532