1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import device.MsiInfoBundle 23import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 24import system.HasSoCParameter 25import utility._ 26import utils.{HPerfMonitor, HasPerfEvents, PerfEvent} 27import xiangshan._ 28import xiangshan.backend.Bundles.{DynInst, IssueQueueIQWakeUpBundle, LoadShouldCancel, MemExuInput, MemExuOutput, VPUCtrlSignals} 29import xiangshan.backend.ctrlblock.{DebugLSIO, LsTopdownInfo} 30import xiangshan.backend.datapath.DataConfig.{IntData, VecData, FpData} 31import xiangshan.backend.datapath.RdConfig.{IntRD, VfRD} 32import xiangshan.backend.datapath.WbConfig._ 33import xiangshan.backend.datapath.DataConfig._ 34import xiangshan.backend.datapath._ 35import xiangshan.backend.dispatch.CoreDispatchTopDownIO 36import xiangshan.backend.exu.ExuBlock 37import xiangshan.backend.fu.vector.Bundles.{VConfig, VType} 38import xiangshan.backend.fu.{FenceIO, FenceToSbuffer, FuConfig, FuType, PFEvent, PerfCounterIO} 39import xiangshan.backend.issue.EntryBundles._ 40import xiangshan.backend.issue.{CancelNetwork, Scheduler, SchedulerArithImp, SchedulerImpBase, SchedulerMemImp} 41import xiangshan.backend.rob.{RobCoreTopDownIO, RobDebugRollingIO, RobLsqIO, RobPtr} 42import xiangshan.frontend.{FtqPtr, FtqRead, PreDecodeInfo} 43import xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr} 44 45import scala.collection.mutable 46 47class Backend(val params: BackendParams)(implicit p: Parameters) extends LazyModule 48 with HasXSParameter { 49 50 override def shouldBeInlined: Boolean = false 51 52 // check read & write port config 53 params.configChecks 54 55 /* Only update the idx in mem-scheduler here 56 * Idx in other schedulers can be updated the same way if needed 57 * 58 * Also note that we filter out the 'stData issue-queues' when counting 59 */ 60 for ((ibp, idx) <- params.memSchdParams.get.issueBlockParams.filter(iq => iq.StdCnt == 0).zipWithIndex) { 61 ibp.updateIdx(idx) 62 } 63 64 println(params.iqWakeUpParams) 65 66 for ((schdCfg, i) <- params.allSchdParams.zipWithIndex) { 67 schdCfg.bindBackendParam(params) 68 } 69 70 for ((iqCfg, i) <- params.allIssueParams.zipWithIndex) { 71 iqCfg.bindBackendParam(params) 72 } 73 74 for ((exuCfg, i) <- params.allExuParams.zipWithIndex) { 75 exuCfg.bindBackendParam(params) 76 exuCfg.updateIQWakeUpConfigs(params.iqWakeUpParams) 77 exuCfg.updateExuIdx(i) 78 } 79 80 println("[Backend] ExuConfigs:") 81 for (exuCfg <- params.allExuParams) { 82 val fuConfigs = exuCfg.fuConfigs 83 val wbPortConfigs = exuCfg.wbPortConfigs 84 val immType = exuCfg.immType 85 86 println("[Backend] " + 87 s"${exuCfg.name}: " + 88 (if (exuCfg.fakeUnit) "fake, " else "") + 89 (if (exuCfg.hasLoadFu || exuCfg.hasHyldaFu) s"LdExuIdx(${backendParams.getLdExuIdx(exuCfg)})" else "") + 90 s"${fuConfigs.map(_.name).mkString("fu(s): {", ",", "}")}, " + 91 s"${wbPortConfigs.mkString("wb: {", ",", "}")}, " + 92 s"${immType.map(SelImm.mkString(_)).mkString("imm: {", ",", "}")}, " + 93 s"latMax(${exuCfg.latencyValMax}), ${exuCfg.fuLatancySet.mkString("lat: {", ",", "}")}, " + 94 s"srcReg(${exuCfg.numRegSrc})" 95 ) 96 require( 97 wbPortConfigs.collectFirst { case x: IntWB => x }.nonEmpty == 98 fuConfigs.map(_.writeIntRf).reduce(_ || _), 99 s"${exuCfg.name} int wb port has no priority" 100 ) 101 require( 102 wbPortConfigs.collectFirst { case x: FpWB => x }.nonEmpty == 103 fuConfigs.map(x => x.writeFpRf).reduce(_ || _), 104 s"${exuCfg.name} fp wb port has no priority" 105 ) 106 require( 107 wbPortConfigs.collectFirst { case x: VfWB => x }.nonEmpty == 108 fuConfigs.map(x => x.writeVecRf).reduce(_ || _), 109 s"${exuCfg.name} vec wb port has no priority" 110 ) 111 } 112 113 println(s"[Backend] all fu configs") 114 for (cfg <- FuConfig.allConfigs) { 115 println(s"[Backend] $cfg") 116 } 117 118 println(s"[Backend] Int RdConfigs: ExuName(Priority)") 119 for ((port, seq) <- params.getRdPortParams(IntData())) { 120 println(s"[Backend] port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}") 121 } 122 123 println(s"[Backend] Int WbConfigs: ExuName(Priority)") 124 for ((port, seq) <- params.getWbPortParams(IntData())) { 125 println(s"[Backend] port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}") 126 } 127 128 println(s"[Backend] Fp RdConfigs: ExuName(Priority)") 129 for ((port, seq) <- params.getRdPortParams(FpData())) { 130 println(s"[Backend] port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}") 131 } 132 133 println(s"[Backend] Fp WbConfigs: ExuName(Priority)") 134 for ((port, seq) <- params.getWbPortParams(FpData())) { 135 println(s"[Backend] port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}") 136 } 137 138 println(s"[Backend] Vf RdConfigs: ExuName(Priority)") 139 for ((port, seq) <- params.getRdPortParams(VecData())) { 140 println(s"[Backend] port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}") 141 } 142 143 println(s"[Backend] Vf WbConfigs: ExuName(Priority)") 144 for ((port, seq) <- params.getWbPortParams(VecData())) { 145 println(s"[Backend] port($port): ${seq.map(x => params.getExuName(x._1) + "(" + x._2.toString + ")").mkString(",")}") 146 } 147 148 println(s"[Backend] Dispatch Configs:") 149 println(s"[Backend] Load IQ enq width(${params.numLoadDp}), Store IQ enq width(${params.numStoreDp})") 150 println(s"[Backend] Load DP width(${LSQLdEnqWidth}), Store DP width(${LSQStEnqWidth})") 151 152 params.updateCopyPdestInfo 153 println(s"[Backend] copyPdestInfo ${params.copyPdestInfo}") 154 params.allExuParams.map(_.copyNum) 155 val ctrlBlock = LazyModule(new CtrlBlock(params)) 156 val pcTargetMem = LazyModule(new PcTargetMem(params)) 157 val intScheduler = params.intSchdParams.map(x => LazyModule(new Scheduler(x))) 158 val fpScheduler = params.fpSchdParams.map(x => LazyModule(new Scheduler(x))) 159 val vfScheduler = params.vfSchdParams.map(x => LazyModule(new Scheduler(x))) 160 val memScheduler = params.memSchdParams.map(x => LazyModule(new Scheduler(x))) 161 val dataPath = LazyModule(new DataPath(params)) 162 val intExuBlock = params.intSchdParams.map(x => LazyModule(new ExuBlock(x))) 163 val fpExuBlock = params.fpSchdParams.map(x => LazyModule(new ExuBlock(x))) 164 val vfExuBlock = params.vfSchdParams.map(x => LazyModule(new ExuBlock(x))) 165 val wbFuBusyTable = LazyModule(new WbFuBusyTable(params)) 166 167 lazy val module = new BackendImp(this) 168} 169 170class BackendImp(override val wrapper: Backend)(implicit p: Parameters) extends LazyModuleImp(wrapper) 171 with HasXSParameter 172 with HasPerfEvents { 173 implicit private val params: BackendParams = wrapper.params 174 175 val io = IO(new BackendIO()(p, wrapper.params)) 176 177 private val ctrlBlock = wrapper.ctrlBlock.module 178 private val pcTargetMem = wrapper.pcTargetMem.module 179 private val intScheduler: SchedulerImpBase = wrapper.intScheduler.get.module 180 private val fpScheduler = wrapper.fpScheduler.get.module 181 private val vfScheduler = wrapper.vfScheduler.get.module 182 private val memScheduler = wrapper.memScheduler.get.module 183 private val dataPath = wrapper.dataPath.module 184 private val intExuBlock = wrapper.intExuBlock.get.module 185 private val fpExuBlock = wrapper.fpExuBlock.get.module 186 private val vfExuBlock = wrapper.vfExuBlock.get.module 187 private val og2ForVector = Module(new Og2ForVector(params)) 188 private val bypassNetwork = Module(new BypassNetwork) 189 private val wbDataPath = Module(new WbDataPath(params)) 190 private val wbFuBusyTable = wrapper.wbFuBusyTable.module 191 192 private val iqWakeUpMappedBundle: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] = ( 193 intScheduler.io.toSchedulers.wakeupVec ++ 194 fpScheduler.io.toSchedulers.wakeupVec ++ 195 vfScheduler.io.toSchedulers.wakeupVec ++ 196 memScheduler.io.toSchedulers.wakeupVec 197 ).map(x => (x.bits.exuIdx, x)).toMap 198 199 println(s"[Backend] iq wake up keys: ${iqWakeUpMappedBundle.keys}") 200 201 wbFuBusyTable.io.in.intSchdBusyTable := intScheduler.io.wbFuBusyTable 202 wbFuBusyTable.io.in.fpSchdBusyTable := fpScheduler.io.wbFuBusyTable 203 wbFuBusyTable.io.in.vfSchdBusyTable := vfScheduler.io.wbFuBusyTable 204 wbFuBusyTable.io.in.memSchdBusyTable := memScheduler.io.wbFuBusyTable 205 intScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.intRespRead 206 fpScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.fpRespRead 207 vfScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.vfRespRead 208 memScheduler.io.fromWbFuBusyTable.fuBusyTableRead := wbFuBusyTable.io.out.memRespRead 209 dataPath.io.wbConfictRead := wbFuBusyTable.io.out.wbConflictRead 210 211 private val og1Cancel = dataPath.io.og1Cancel 212 private val og0Cancel = dataPath.io.og0Cancel 213 private val vlIsZero = intExuBlock.io.vlIsZero.get 214 private val vlIsVlmax = intExuBlock.io.vlIsVlmax.get 215 216 ctrlBlock.io.intIQValidNumVec := intScheduler.io.intIQValidNumVec 217 ctrlBlock.io.fpIQValidNumVec := fpScheduler.io.fpIQValidNumVec 218 ctrlBlock.io.fromTop.hartId := io.fromTop.hartId 219 ctrlBlock.io.frontend <> io.frontend 220 ctrlBlock.io.fromCSR.toDecode := intExuBlock.io.csrToDecode.get 221 ctrlBlock.io.fromWB.wbData <> wbDataPath.io.toCtrlBlock.writeback 222 ctrlBlock.io.fromMem.stIn <> io.mem.stIn 223 ctrlBlock.io.fromMem.violation <> io.mem.memoryViolation 224 ctrlBlock.io.lqCanAccept := io.mem.lqCanAccept 225 ctrlBlock.io.sqCanAccept := io.mem.sqCanAccept 226 ctrlBlock.io.csrCtrl <> intExuBlock.io.csrio.get.customCtrl 227 ctrlBlock.io.robio.csr.intrBitSet := intExuBlock.io.csrio.get.interrupt 228 ctrlBlock.io.robio.csr.trapTarget := intExuBlock.io.csrio.get.trapTarget 229 ctrlBlock.io.robio.csr.isXRet := intExuBlock.io.csrio.get.isXRet 230 ctrlBlock.io.robio.csr.wfiEvent := intExuBlock.io.csrio.get.wfi_event 231 ctrlBlock.io.robio.lsq <> io.mem.robLsqIO 232 ctrlBlock.io.robio.lsTopdownInfo <> io.mem.lsTopdownInfo 233 ctrlBlock.io.robio.debug_ls <> io.mem.debugLS 234 ctrlBlock.io.debugEnqLsq.canAccept := io.mem.lsqEnqIO.canAccept 235 ctrlBlock.io.debugEnqLsq.resp := io.mem.lsqEnqIO.resp 236 ctrlBlock.io.debugEnqLsq.req := memScheduler.io.memIO.get.lsqEnqIO.req 237 ctrlBlock.io.debugEnqLsq.needAlloc := memScheduler.io.memIO.get.lsqEnqIO.needAlloc 238 239 intScheduler.io.fromTop.hartId := io.fromTop.hartId 240 intScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 241 intScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 242 intScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.intUops 243 intScheduler.io.intWriteBack := wbDataPath.io.toIntPreg 244 intScheduler.io.fpWriteBack := 0.U.asTypeOf(intScheduler.io.fpWriteBack) 245 intScheduler.io.vfWriteBack := 0.U.asTypeOf(intScheduler.io.vfWriteBack) 246 intScheduler.io.v0WriteBack := 0.U.asTypeOf(intScheduler.io.v0WriteBack) 247 intScheduler.io.vlWriteBack := 0.U.asTypeOf(intScheduler.io.vlWriteBack) 248 intScheduler.io.fromDataPath.resp := dataPath.io.toIntIQ 249 intScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 250 intScheduler.io.fromDataPath.og0Cancel := og0Cancel 251 intScheduler.io.fromDataPath.og1Cancel := og1Cancel 252 intScheduler.io.ldCancel := io.mem.ldCancel 253 intScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.take(params.getIntExuRCWriteSize) 254 intScheduler.io.vlWriteBackInfo.vlIsZero := false.B 255 intScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B 256 257 fpScheduler.io.fromTop.hartId := io.fromTop.hartId 258 fpScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 259 fpScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 260 fpScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.fpUops 261 fpScheduler.io.intWriteBack := 0.U.asTypeOf(fpScheduler.io.intWriteBack) 262 fpScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg 263 fpScheduler.io.vfWriteBack := 0.U.asTypeOf(fpScheduler.io.vfWriteBack) 264 fpScheduler.io.v0WriteBack := 0.U.asTypeOf(fpScheduler.io.v0WriteBack) 265 fpScheduler.io.vlWriteBack := 0.U.asTypeOf(fpScheduler.io.vlWriteBack) 266 fpScheduler.io.fromDataPath.resp := dataPath.io.toFpIQ 267 fpScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 268 fpScheduler.io.fromDataPath.og0Cancel := og0Cancel 269 fpScheduler.io.fromDataPath.og1Cancel := og1Cancel 270 fpScheduler.io.ldCancel := io.mem.ldCancel 271 fpScheduler.io.vlWriteBackInfo.vlIsZero := false.B 272 fpScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B 273 274 memScheduler.io.fromTop.hartId := io.fromTop.hartId 275 memScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 276 memScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 277 memScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.memUops 278 memScheduler.io.intWriteBack := wbDataPath.io.toIntPreg 279 memScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg 280 memScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg 281 memScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg 282 memScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg 283 memScheduler.io.fromMem.get.scommit := io.mem.sqDeq 284 memScheduler.io.fromMem.get.lcommit := io.mem.lqDeq 285 memScheduler.io.fromMem.get.wakeup := io.mem.wakeup 286 memScheduler.io.fromMem.get.sqDeqPtr := io.mem.sqDeqPtr 287 memScheduler.io.fromMem.get.lqDeqPtr := io.mem.lqDeqPtr 288 memScheduler.io.fromMem.get.sqCancelCnt := io.mem.sqCancelCnt 289 memScheduler.io.fromMem.get.lqCancelCnt := io.mem.lqCancelCnt 290 memScheduler.io.fromMem.get.stIssuePtr := io.mem.stIssuePtr 291 require(memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.length == io.mem.stIn.length) 292 memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.zip(io.mem.stIn).foreach { case (sink, source) => 293 sink.valid := source.valid 294 sink.bits := source.bits.robIdx 295 } 296 memScheduler.io.fromMem.get.memWaitUpdateReq.sqIdx := DontCare // TODO 297 memScheduler.io.fromDataPath.resp := dataPath.io.toMemIQ 298 memScheduler.io.fromMem.get.ldaFeedback := io.mem.ldaIqFeedback 299 memScheduler.io.fromMem.get.staFeedback := io.mem.staIqFeedback 300 memScheduler.io.fromMem.get.hyuFeedback := io.mem.hyuIqFeedback 301 memScheduler.io.fromMem.get.vstuFeedback := io.mem.vstuIqFeedback 302 memScheduler.io.fromMem.get.vlduFeedback := io.mem.vlduIqFeedback 303 memScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 304 memScheduler.io.fromDataPath.og0Cancel := og0Cancel 305 memScheduler.io.fromDataPath.og1Cancel := og1Cancel 306 memScheduler.io.ldCancel := io.mem.ldCancel 307 memScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.takeRight(params.getMemExuRCWriteSize) 308 memScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero 309 memScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax 310 311 vfScheduler.io.fromTop.hartId := io.fromTop.hartId 312 vfScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 313 vfScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 314 vfScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.vfUops 315 vfScheduler.io.intWriteBack := 0.U.asTypeOf(vfScheduler.io.intWriteBack) 316 vfScheduler.io.fpWriteBack := 0.U.asTypeOf(vfScheduler.io.fpWriteBack) 317 vfScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg 318 vfScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg 319 vfScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg 320 vfScheduler.io.fromDataPath.resp := dataPath.io.toVfIQ 321 vfScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 322 vfScheduler.io.fromDataPath.og0Cancel := og0Cancel 323 vfScheduler.io.fromDataPath.og1Cancel := og1Cancel 324 vfScheduler.io.ldCancel := io.mem.ldCancel 325 vfScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero 326 vfScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax 327 vfScheduler.io.fromOg2.get := og2ForVector.io.toVfIQ 328 329 dataPath.io.hartId := io.fromTop.hartId 330 dataPath.io.flush := ctrlBlock.io.toDataPath.flush 331 332 dataPath.io.fromIntIQ <> intScheduler.io.toDataPathAfterDelay 333 dataPath.io.fromFpIQ <> fpScheduler.io.toDataPathAfterDelay 334 dataPath.io.fromVfIQ <> vfScheduler.io.toDataPathAfterDelay 335 dataPath.io.fromMemIQ <> memScheduler.io.toDataPathAfterDelay 336 337 dataPath.io.ldCancel := io.mem.ldCancel 338 339 println(s"[Backend] wbDataPath.io.toIntPreg: ${wbDataPath.io.toIntPreg.size}, dataPath.io.fromIntWb: ${dataPath.io.fromIntWb.size}") 340 println(s"[Backend] wbDataPath.io.toVfPreg: ${wbDataPath.io.toVfPreg.size}, dataPath.io.fromFpWb: ${dataPath.io.fromVfWb.size}") 341 dataPath.io.fromIntWb := wbDataPath.io.toIntPreg 342 dataPath.io.fromFpWb := wbDataPath.io.toFpPreg 343 dataPath.io.fromVfWb := wbDataPath.io.toVfPreg 344 dataPath.io.fromV0Wb := wbDataPath.io.toV0Preg 345 dataPath.io.fromVlWb := wbDataPath.io.toVlPreg 346 dataPath.io.debugIntRat .foreach(_ := ctrlBlock.io.debug_int_rat.get) 347 dataPath.io.debugFpRat .foreach(_ := ctrlBlock.io.debug_fp_rat.get) 348 dataPath.io.debugVecRat .foreach(_ := ctrlBlock.io.debug_vec_rat.get) 349 dataPath.io.debugV0Rat .foreach(_ := ctrlBlock.io.debug_v0_rat.get) 350 dataPath.io.debugVlRat .foreach(_ := ctrlBlock.io.debug_vl_rat.get) 351 dataPath.io.fromBypassNetwork := bypassNetwork.io.toDataPath 352 353 og2ForVector.io.flush := ctrlBlock.io.toDataPath.flush 354 og2ForVector.io.ldCancel := io.mem.ldCancel 355 og2ForVector.io.fromOg1NoReg <> dataPath.io.toVecExu 356 og2ForVector.io.fromOg1ImmInfo := dataPath.io.og1ImmInfo.zip(params.allExuParams).filter(_._2.isVfExeUnit).map(_._1) 357 358 bypassNetwork.io.fromDataPath.int <> dataPath.io.toIntExu 359 bypassNetwork.io.fromDataPath.fp <> dataPath.io.toFpExu 360 bypassNetwork.io.fromDataPath.vf <> og2ForVector.io.toVfExu 361 bypassNetwork.io.fromDataPath.mem <> dataPath.io.toMemExu 362 bypassNetwork.io.fromDataPath.immInfo := dataPath.io.og1ImmInfo 363 bypassNetwork.io.fromDataPath.immInfo.zip(params.allExuParams).filter(_._2.isVfExeUnit).map(_._1).zip(og2ForVector.io.toVfImmInfo).map{ 364 case (vfImmInfo, og2ImmInfo) => vfImmInfo := og2ImmInfo 365 } 366 bypassNetwork.io.fromDataPath.rcData := dataPath.io.toBypassNetworkRCData 367 bypassNetwork.io.fromExus.connectExuOutput(_.int)(intExuBlock.io.out) 368 bypassNetwork.io.fromExus.connectExuOutput(_.fp)(fpExuBlock.io.out) 369 bypassNetwork.io.fromExus.connectExuOutput(_.vf)(vfExuBlock.io.out) 370 371 require(bypassNetwork.io.fromExus.mem.flatten.size == io.mem.writeBack.size, 372 s"bypassNetwork.io.fromExus.mem.flatten.size(${bypassNetwork.io.fromExus.mem.flatten.size}: ${bypassNetwork.io.fromExus.mem.map(_.size)}, " + 373 s"io.mem.writeback(${io.mem.writeBack.size})" 374 ) 375 bypassNetwork.io.fromExus.mem.flatten.zip(io.mem.writeBack).foreach { case (sink, source) => 376 sink.valid := source.valid 377 sink.bits.intWen := source.bits.uop.rfWen && FuType.isLoad(source.bits.uop.fuType) 378 sink.bits.pdest := source.bits.uop.pdest 379 sink.bits.data := source.bits.data 380 } 381 382 383 intExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 384 for (i <- 0 until intExuBlock.io.in.length) { 385 for (j <- 0 until intExuBlock.io.in(i).length) { 386 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.int(i)(j).bits.loadDependency, io.mem.ldCancel) 387 NewPipelineConnect( 388 bypassNetwork.io.toExus.int(i)(j), intExuBlock.io.in(i)(j), intExuBlock.io.in(i)(j).fire, 389 Mux( 390 bypassNetwork.io.toExus.int(i)(j).fire, 391 bypassNetwork.io.toExus.int(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 392 intExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 393 ), 394 Option("bypassNetwork2intExuBlock") 395 ) 396 } 397 } 398 399 pcTargetMem.io.fromFrontendFtq := io.frontend.fromFtq 400 pcTargetMem.io.toDataPath <> dataPath.io.fromPcTargetMem 401 402 private val csrin = intExuBlock.io.csrin.get 403 csrin.hartId := io.fromTop.hartId 404 csrin.msiInfo.valid := RegNext(io.fromTop.msiInfo.valid) 405 csrin.msiInfo.bits := RegEnable(io.fromTop.msiInfo.bits, io.fromTop.msiInfo.valid) 406 csrin.clintTime.valid := RegNext(io.fromTop.clintTime.valid) 407 csrin.clintTime.bits := RegEnable(io.fromTop.clintTime.bits, io.fromTop.clintTime.valid) 408 csrin.trapInstInfo := ctrlBlock.io.toCSR.trapInstInfo 409 410 private val csrio = intExuBlock.io.csrio.get 411 csrio.hartId := io.fromTop.hartId 412 csrio.fpu.fflags := ctrlBlock.io.robio.csr.fflags 413 csrio.fpu.isIllegal := false.B // Todo: remove it 414 csrio.fpu.dirty_fs := ctrlBlock.io.robio.csr.dirty_fs 415 csrio.vpu <> WireDefault(0.U.asTypeOf(csrio.vpu)) // Todo 416 417 val fromIntExuVsetVType = intExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType)))) 418 val fromVfExuVsetVType = vfExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType)))) 419 val fromVsetVType = Mux(fromIntExuVsetVType.valid, fromIntExuVsetVType.bits, fromVfExuVsetVType.bits) 420 val vsetvlVType = RegEnable(fromVsetVType, 0.U.asTypeOf(new VType), fromIntExuVsetVType.valid || fromVfExuVsetVType.valid) 421 ctrlBlock.io.toDecode.vsetvlVType := vsetvlVType 422 423 val commitVType = ctrlBlock.io.robio.commitVType.vtype 424 val hasVsetvl = ctrlBlock.io.robio.commitVType.hasVsetvl 425 val vtype = VType.toVtypeStruct(Mux(hasVsetvl, vsetvlVType, commitVType.bits)).asUInt 426 427 // csr not store the value of vl, so when using difftest we assign the value of vl to debugVl 428 val debugVl_s0 = WireInit(UInt(VlData().dataWidth.W), 0.U) 429 val debugVl_s1 = WireInit(UInt(VlData().dataWidth.W), 0.U) 430 debugVl_s0 := dataPath.io.debugVl.getOrElse(0.U.asTypeOf(UInt(VlData().dataWidth.W))) 431 debugVl_s1 := RegNext(debugVl_s0) 432 csrio.vpu.set_vxsat := ctrlBlock.io.robio.csr.vxsat 433 csrio.vpu.set_vstart.valid := ctrlBlock.io.robio.csr.vstart.valid 434 csrio.vpu.set_vstart.bits := ctrlBlock.io.robio.csr.vstart.bits 435 ctrlBlock.io.toDecode.vstart := csrio.vpu.vstart 436 //Todo here need change design 437 csrio.vpu.set_vtype.valid := commitVType.valid 438 csrio.vpu.set_vtype.bits := ZeroExt(vtype, XLEN) 439 csrio.vpu.vl := ZeroExt(debugVl_s1, XLEN) 440 csrio.vpu.dirty_vs := ctrlBlock.io.robio.csr.dirty_vs 441 csrio.exception := ctrlBlock.io.robio.exception 442 csrio.memExceptionVAddr := io.mem.exceptionAddr.vaddr 443 csrio.memExceptionGPAddr := io.mem.exceptionAddr.gpaddr 444 csrio.externalInterrupt := RegNext(io.fromTop.externalInterrupt) 445 csrio.perf <> io.perf 446 csrio.perf.retiredInstr <> ctrlBlock.io.robio.csr.perfinfo.retiredInstr 447 csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo 448 private val fenceio = intExuBlock.io.fenceio.get 449 io.fenceio <> fenceio 450 451 // to fpExuBlock 452 fpExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 453 for (i <- 0 until fpExuBlock.io.in.length) { 454 for (j <- 0 until fpExuBlock.io.in(i).length) { 455 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.fp(i)(j).bits.loadDependency, io.mem.ldCancel) 456 NewPipelineConnect( 457 bypassNetwork.io.toExus.fp(i)(j), fpExuBlock.io.in(i)(j), fpExuBlock.io.in(i)(j).fire, 458 Mux( 459 bypassNetwork.io.toExus.fp(i)(j).fire, 460 bypassNetwork.io.toExus.fp(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 461 fpExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 462 ), 463 Option("bypassNetwork2fpExuBlock") 464 ) 465 } 466 } 467 468 vfExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 469 for (i <- 0 until vfExuBlock.io.in.size) { 470 for (j <- 0 until vfExuBlock.io.in(i).size) { 471 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.vf(i)(j).bits.loadDependency, io.mem.ldCancel) 472 NewPipelineConnect( 473 bypassNetwork.io.toExus.vf(i)(j), vfExuBlock.io.in(i)(j), vfExuBlock.io.in(i)(j).fire, 474 Mux( 475 bypassNetwork.io.toExus.vf(i)(j).fire, 476 bypassNetwork.io.toExus.vf(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 477 vfExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 478 ), 479 Option("bypassNetwork2vfExuBlock") 480 ) 481 482 } 483 } 484 485 intExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 486 fpExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 487 fpExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm) 488 vfExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 489 vfExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm) 490 491 wbDataPath.io.flush := ctrlBlock.io.redirect 492 wbDataPath.io.fromTop.hartId := io.fromTop.hartId 493 wbDataPath.io.fromIntExu <> intExuBlock.io.out 494 wbDataPath.io.fromFpExu <> fpExuBlock.io.out 495 wbDataPath.io.fromVfExu <> vfExuBlock.io.out 496 wbDataPath.io.fromMemExu.flatten.zip(io.mem.writeBack).foreach { case (sink, source) => 497 sink.valid := source.valid 498 source.ready := sink.ready 499 sink.bits.data := VecInit(Seq.fill(sink.bits.params.wbPathNum)(source.bits.data)) 500 sink.bits.pdest := source.bits.uop.pdest 501 sink.bits.robIdx := source.bits.uop.robIdx 502 sink.bits.intWen.foreach(_ := source.bits.uop.rfWen) 503 sink.bits.fpWen.foreach(_ := source.bits.uop.fpWen) 504 sink.bits.vecWen.foreach(_ := source.bits.uop.vecWen) 505 sink.bits.v0Wen.foreach(_ := source.bits.uop.v0Wen) 506 sink.bits.vlWen.foreach(_ := source.bits.uop.vlWen) 507 sink.bits.exceptionVec.foreach(_ := source.bits.uop.exceptionVec) 508 sink.bits.flushPipe.foreach(_ := source.bits.uop.flushPipe) 509 sink.bits.replay.foreach(_ := source.bits.uop.replayInst) 510 sink.bits.debug := source.bits.debug 511 sink.bits.debugInfo := source.bits.uop.debugInfo 512 sink.bits.lqIdx.foreach(_ := source.bits.uop.lqIdx) 513 sink.bits.sqIdx.foreach(_ := source.bits.uop.sqIdx) 514 sink.bits.predecodeInfo.foreach(_ := source.bits.uop.preDecodeInfo) 515 sink.bits.vls.foreach(x => { 516 x.vdIdx := source.bits.vdIdx.get 517 x.vdIdxInField := source.bits.vdIdxInField.get 518 x.vpu := source.bits.uop.vpu 519 x.oldVdPsrc := source.bits.uop.psrc(2) 520 x.isIndexed := VlduType.isIndexed(source.bits.uop.fuOpType) 521 x.isMasked := VlduType.isMasked(source.bits.uop.fuOpType) 522 }) 523 sink.bits.trigger.foreach(_ := source.bits.uop.trigger) 524 } 525 526 // to mem 527 private val memIssueParams = params.memSchdParams.get.issueBlockParams 528 private val memExuBlocksHasLDU = memIssueParams.map(_.exuBlockParams.map(x => x.hasLoadFu || x.hasHyldaFu)) 529 private val memExuBlocksHasVecLoad = memIssueParams.map(_.exuBlockParams.map(x => x.hasVLoadFu)) 530 println(s"[Backend] memExuBlocksHasLDU: $memExuBlocksHasLDU") 531 println(s"[Backend] memExuBlocksHasVecLoad: $memExuBlocksHasVecLoad") 532 533 private val toMem = Wire(bypassNetwork.io.toExus.mem.cloneType) 534 for (i <- toMem.indices) { 535 for (j <- toMem(i).indices) { 536 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.mem(i)(j).bits.loadDependency, io.mem.ldCancel) 537 val issueTimeout = 538 if (memExuBlocksHasLDU(i)(j)) 539 Counter(0 until 16, toMem(i)(j).valid && !toMem(i)(j).fire, bypassNetwork.io.toExus.mem(i)(j).fire)._2 540 else 541 false.B 542 543 if (memScheduler.io.loadFinalIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) { 544 memScheduler.io.loadFinalIssueResp(i)(j).valid := issueTimeout 545 memScheduler.io.loadFinalIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType 546 memScheduler.io.loadFinalIssueResp(i)(j).bits.resp := RespType.block 547 memScheduler.io.loadFinalIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx 548 memScheduler.io.loadFinalIssueResp(i)(j).bits.uopIdx.foreach(_ := toMem(i)(j).bits.vpu.get.vuopIdx) 549 memScheduler.io.loadFinalIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get) 550 memScheduler.io.loadFinalIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get) 551 } 552 553 NewPipelineConnect( 554 bypassNetwork.io.toExus.mem(i)(j), toMem(i)(j), toMem(i)(j).fire, 555 Mux( 556 bypassNetwork.io.toExus.mem(i)(j).fire, 557 bypassNetwork.io.toExus.mem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 558 toMem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || issueTimeout 559 ), 560 Option("bypassNetwork2toMemExus") 561 ) 562 563 if (memScheduler.io.memAddrIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) { 564 memScheduler.io.memAddrIssueResp(i)(j).valid := toMem(i)(j).fire && FuType.isLoad(toMem(i)(j).bits.fuType) 565 memScheduler.io.memAddrIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType 566 memScheduler.io.memAddrIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx 567 memScheduler.io.memAddrIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get) 568 memScheduler.io.memAddrIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get) 569 memScheduler.io.memAddrIssueResp(i)(j).bits.resp := RespType.success // for load inst, firing at toMem means issuing successfully 570 } 571 572 if (memScheduler.io.vecLoadIssueResp(i).nonEmpty && memExuBlocksHasVecLoad(i)(j)) { 573 memScheduler.io.vecLoadIssueResp(i)(j) match { 574 case resp => 575 resp.valid := toMem(i)(j).fire && VlduType.isVecLd(toMem(i)(j).bits.fuOpType) 576 resp.bits.fuType := toMem(i)(j).bits.fuType 577 resp.bits.robIdx := toMem(i)(j).bits.robIdx 578 resp.bits.uopIdx.get := toMem(i)(j).bits.vpu.get.vuopIdx 579 resp.bits.sqIdx.get := toMem(i)(j).bits.sqIdx.get 580 resp.bits.lqIdx.get := toMem(i)(j).bits.lqIdx.get 581 resp.bits.resp := RespType.success 582 } 583 if (backendParams.debugEn){ 584 dontTouch(memScheduler.io.vecLoadIssueResp(i)(j)) 585 } 586 } 587 } 588 } 589 590 io.mem.redirect := ctrlBlock.io.redirect 591 io.mem.issueUops.zip(toMem.flatten).foreach { case (sink, source) => 592 val enableMdp = Constantin.createRecord("EnableMdp", true) 593 sink.valid := source.valid 594 source.ready := sink.ready 595 sink.bits.iqIdx := source.bits.iqIdx 596 sink.bits.isFirstIssue := source.bits.isFirstIssue 597 sink.bits.uop := 0.U.asTypeOf(sink.bits.uop) 598 sink.bits.src := 0.U.asTypeOf(sink.bits.src) 599 sink.bits.src.zip(source.bits.src).foreach { case (l, r) => l := r} 600 sink.bits.uop.fuType := source.bits.fuType 601 sink.bits.uop.fuOpType := source.bits.fuOpType 602 sink.bits.uop.imm := source.bits.imm 603 sink.bits.uop.robIdx := source.bits.robIdx 604 sink.bits.uop.pdest := source.bits.pdest 605 sink.bits.uop.rfWen := source.bits.rfWen.getOrElse(false.B) 606 sink.bits.uop.fpWen := source.bits.fpWen.getOrElse(false.B) 607 sink.bits.uop.vecWen := source.bits.vecWen.getOrElse(false.B) 608 sink.bits.uop.v0Wen := source.bits.v0Wen.getOrElse(false.B) 609 sink.bits.uop.vlWen := source.bits.vlWen.getOrElse(false.B) 610 sink.bits.uop.flushPipe := source.bits.flushPipe.getOrElse(false.B) 611 sink.bits.uop.pc := source.bits.pc.getOrElse(0.U) 612 sink.bits.uop.loadWaitBit := Mux(enableMdp, source.bits.loadWaitBit.getOrElse(false.B), false.B) 613 sink.bits.uop.waitForRobIdx := Mux(enableMdp, source.bits.waitForRobIdx.getOrElse(0.U.asTypeOf(new RobPtr)), 0.U.asTypeOf(new RobPtr)) 614 sink.bits.uop.storeSetHit := Mux(enableMdp, source.bits.storeSetHit.getOrElse(false.B), false.B) 615 sink.bits.uop.loadWaitStrict := Mux(enableMdp, source.bits.loadWaitStrict.getOrElse(false.B), false.B) 616 sink.bits.uop.ssid := Mux(enableMdp, source.bits.ssid.getOrElse(0.U(SSIDWidth.W)), 0.U(SSIDWidth.W)) 617 sink.bits.uop.lqIdx := source.bits.lqIdx.getOrElse(0.U.asTypeOf(new LqPtr)) 618 sink.bits.uop.sqIdx := source.bits.sqIdx.getOrElse(0.U.asTypeOf(new SqPtr)) 619 sink.bits.uop.ftqPtr := source.bits.ftqIdx.getOrElse(0.U.asTypeOf(new FtqPtr)) 620 sink.bits.uop.ftqOffset := source.bits.ftqOffset.getOrElse(0.U) 621 sink.bits.uop.debugInfo := source.bits.perfDebugInfo 622 sink.bits.uop.vpu := source.bits.vpu.getOrElse(0.U.asTypeOf(new VPUCtrlSignals)) 623 sink.bits.uop.preDecodeInfo := source.bits.preDecode.getOrElse(0.U.asTypeOf(new PreDecodeInfo)) 624 sink.bits.uop.numLsElem := source.bits.numLsElem.getOrElse(0.U) // Todo: remove this bundle, keep only the one below 625 sink.bits.flowNum.foreach(_ := source.bits.numLsElem.get) 626 } 627 io.mem.loadFastMatch := memScheduler.io.toMem.get.loadFastMatch.map(_.fastMatch) 628 io.mem.loadFastImm := memScheduler.io.toMem.get.loadFastMatch.map(_.fastImm) 629 io.mem.tlbCsr := csrio.tlb 630 io.mem.csrCtrl := csrio.customCtrl 631 io.mem.sfence := fenceio.sfence 632 io.mem.isStoreException := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.commitType) 633 io.mem.isVlsException := ctrlBlock.io.robio.exception.bits.vls 634 require(io.mem.loadPcRead.size == params.LduCnt) 635 io.mem.loadPcRead.zipWithIndex.foreach { case (loadPcRead, i) => 636 loadPcRead := ctrlBlock.io.memLdPcRead(i).data 637 ctrlBlock.io.memLdPcRead(i).valid := io.mem.issueLda(i).valid 638 ctrlBlock.io.memLdPcRead(i).ptr := io.mem.issueLda(i).bits.uop.ftqPtr 639 ctrlBlock.io.memLdPcRead(i).offset := io.mem.issueLda(i).bits.uop.ftqOffset 640 } 641 642 io.mem.storePcRead.zipWithIndex.foreach { case (storePcRead, i) => 643 storePcRead := ctrlBlock.io.memStPcRead(i).data 644 ctrlBlock.io.memStPcRead(i).valid := io.mem.issueSta(i).valid 645 ctrlBlock.io.memStPcRead(i).ptr := io.mem.issueSta(i).bits.uop.ftqPtr 646 ctrlBlock.io.memStPcRead(i).offset := io.mem.issueSta(i).bits.uop.ftqOffset 647 } 648 649 io.mem.hyuPcRead.zipWithIndex.foreach( { case (hyuPcRead, i) => 650 hyuPcRead := ctrlBlock.io.memHyPcRead(i).data 651 ctrlBlock.io.memHyPcRead(i).valid := io.mem.issueHylda(i).valid 652 ctrlBlock.io.memHyPcRead(i).ptr := io.mem.issueHylda(i).bits.uop.ftqPtr 653 ctrlBlock.io.memHyPcRead(i).offset := io.mem.issueHylda(i).bits.uop.ftqOffset 654 }) 655 656 ctrlBlock.io.robio.robHeadLsIssue := io.mem.issueUops.map(deq => deq.fire && deq.bits.uop.robIdx === ctrlBlock.io.robio.robDeqPtr).reduce(_ || _) 657 658 // mem io 659 io.mem.lsqEnqIO <> memScheduler.io.memIO.get.lsqEnqIO 660 io.mem.robLsqIO <> ctrlBlock.io.robio.lsq 661 662 io.frontendSfence := fenceio.sfence 663 io.frontendTlbCsr := csrio.tlb 664 io.frontendCsrCtrl := csrio.customCtrl 665 666 io.tlb <> csrio.tlb 667 668 io.csrCustomCtrl := csrio.customCtrl 669 670 io.toTop.cpuHalted := false.B // TODO: implement cpu halt 671 672 io.debugTopDown.fromRob := ctrlBlock.io.debugTopDown.fromRob 673 ctrlBlock.io.debugTopDown.fromCore := io.debugTopDown.fromCore 674 675 io.debugRolling := ctrlBlock.io.debugRolling 676 677 if(backendParams.debugEn) { 678 dontTouch(memScheduler.io) 679 dontTouch(dataPath.io.toMemExu) 680 dontTouch(wbDataPath.io.fromMemExu) 681 } 682 683 // reset tree 684 if (p(DebugOptionsKey).ResetGen) { 685 val rightResetTree = ResetGenNode(Seq( 686 ModuleNode(dataPath), 687 ModuleNode(intExuBlock), 688 ModuleNode(fpExuBlock), 689 ModuleNode(vfExuBlock), 690 ModuleNode(bypassNetwork), 691 ModuleNode(wbDataPath) 692 )) 693 val leftResetTree = ResetGenNode(Seq( 694 ModuleNode(pcTargetMem), 695 ModuleNode(intScheduler), 696 ModuleNode(fpScheduler), 697 ModuleNode(vfScheduler), 698 ModuleNode(memScheduler), 699 ModuleNode(og2ForVector), 700 ModuleNode(wbFuBusyTable), 701 ResetGenNode(Seq( 702 ModuleNode(ctrlBlock), 703 ResetGenNode(Seq( 704 CellNode(io.frontendReset) 705 )) 706 )) 707 )) 708 ResetGen(leftResetTree, reset, sim = false) 709 ResetGen(rightResetTree, reset, sim = false) 710 } else { 711 io.frontendReset := DontCare 712 } 713 714 // perf events 715 val pfevent = Module(new PFEvent) 716 pfevent.io.distribute_csr := RegNext(csrio.customCtrl.distribute_csr) 717 val csrevents = pfevent.io.hpmevent.slice(8,16) 718 719 val ctrlBlockPerf = ctrlBlock.getPerfEvents 720 val intSchedulerPerf = intScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 721 val fpSchedulerPerf = fpScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 722 val vecSchedulerPerf = vfScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 723 val memSchedulerPerf = memScheduler.asInstanceOf[SchedulerMemImp].getPerfEvents 724 725 val perfBackend = Seq() 726 // let index = 0 be no event 727 val allPerfEvents = Seq(("noEvent", 0.U)) ++ ctrlBlockPerf ++ intSchedulerPerf ++ fpSchedulerPerf ++ vecSchedulerPerf ++ memSchedulerPerf ++ perfBackend 728 729 730 if (printEventCoding) { 731 for (((name, inc), i) <- allPerfEvents.zipWithIndex) { 732 println("backend perfEvents Set", name, inc, i) 733 } 734 } 735 736 val allPerfInc = allPerfEvents.map(_._2.asTypeOf(new PerfEvent)) 737 val perfEvents = HPerfMonitor(csrevents, allPerfInc).getPerfEvents 738 csrio.perf.perfEventsBackend := VecInit(perfEvents.map(_._2.asTypeOf(new PerfEvent))) 739 generatePerfEvent() 740} 741 742class BackendMemIO(implicit p: Parameters, params: BackendParams) extends XSBundle { 743 // Since fast load replay always use load unit 0, Backend flips two load port to avoid conflicts 744 val flippedLda = true 745 // params alias 746 private val LoadQueueSize = VirtualLoadQueueSize 747 // In/Out // Todo: split it into one-direction bundle 748 val lsqEnqIO = Flipped(new LsqEnqIO) 749 val robLsqIO = new RobLsqIO 750 val ldaIqFeedback = Vec(params.LduCnt, Flipped(new MemRSFeedbackIO)) 751 val staIqFeedback = Vec(params.StaCnt, Flipped(new MemRSFeedbackIO)) 752 val hyuIqFeedback = Vec(params.HyuCnt, Flipped(new MemRSFeedbackIO)) 753 val vstuIqFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true))) 754 val vlduIqFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true))) 755 val ldCancel = Vec(params.LdExuCnt, Input(new LoadCancelIO)) 756 val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst))) 757 val loadPcRead = Vec(params.LduCnt, Output(UInt(VAddrBits.W))) 758 val storePcRead = Vec(params.StaCnt, Output(UInt(VAddrBits.W))) 759 val hyuPcRead = Vec(params.HyuCnt, Output(UInt(VAddrBits.W))) 760 // Input 761 val writebackLda = Vec(params.LduCnt, Flipped(DecoupledIO(new MemExuOutput))) 762 val writebackSta = Vec(params.StaCnt, Flipped(DecoupledIO(new MemExuOutput))) 763 val writebackStd = Vec(params.StdCnt, Flipped(DecoupledIO(new MemExuOutput))) 764 val writebackHyuLda = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput))) 765 val writebackHyuSta = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput))) 766 val writebackVldu = Vec(params.VlduCnt, Flipped(DecoupledIO(new MemExuOutput(true)))) 767 768 val s3_delayed_load_error = Input(Vec(LoadPipelineWidth, Bool())) 769 val stIn = Input(Vec(params.StaExuCnt, ValidIO(new DynInst()))) 770 val memoryViolation = Flipped(ValidIO(new Redirect)) 771 val exceptionAddr = Input(new Bundle { 772 val vaddr = UInt(VAddrBits.W) 773 val gpaddr = UInt(GPAddrBits.W) 774 }) 775 val sqDeq = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) 776 val lqDeq = Input(UInt(log2Up(CommitWidth + 1).W)) 777 val sqDeqPtr = Input(new SqPtr) 778 val lqDeqPtr = Input(new LqPtr) 779 780 val lqCancelCnt = Input(UInt(log2Up(VirtualLoadQueueSize + 1).W)) 781 val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W)) 782 783 val lqCanAccept = Input(Bool()) 784 val sqCanAccept = Input(Bool()) 785 786 val otherFastWakeup = Flipped(Vec(params.LduCnt + params.HyuCnt, ValidIO(new DynInst))) 787 val stIssuePtr = Input(new SqPtr()) 788 789 val debugLS = Flipped(Output(new DebugLSIO)) 790 791 val lsTopdownInfo = Vec(params.LduCnt + params.HyuCnt, Flipped(Output(new LsTopdownInfo))) 792 // Output 793 val redirect = ValidIO(new Redirect) // rob flush MemBlock 794 val issueLda = MixedVec(Seq.fill(params.LduCnt)(DecoupledIO(new MemExuInput()))) 795 val issueSta = MixedVec(Seq.fill(params.StaCnt)(DecoupledIO(new MemExuInput()))) 796 val issueStd = MixedVec(Seq.fill(params.StdCnt)(DecoupledIO(new MemExuInput()))) 797 val issueHylda = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput()))) 798 val issueHysta = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput()))) 799 val issueVldu = MixedVec(Seq.fill(params.VlduCnt)(DecoupledIO(new MemExuInput(true)))) 800 801 val loadFastMatch = Vec(params.LduCnt, Output(UInt(params.LduCnt.W))) 802 val loadFastImm = Vec(params.LduCnt, Output(UInt(12.W))) // Imm_I 803 804 val tlbCsr = Output(new TlbCsrBundle) 805 val csrCtrl = Output(new CustomCSRCtrlIO) 806 val sfence = Output(new SfenceBundle) 807 val isStoreException = Output(Bool()) 808 val isVlsException = Output(Bool()) 809 810 // ATTENTION: The issue ports' sequence order should be the same as IQs' deq config 811 private [backend] def issueUops: Seq[DecoupledIO[MemExuInput]] = { 812 issueSta ++ 813 issueHylda ++ issueHysta ++ 814 issueLda ++ 815 issueVldu ++ 816 issueStd 817 }.toSeq 818 819 // ATTENTION: The writeback ports' sequence order should be the same as IQs' deq config 820 private [backend] def writeBack: Seq[DecoupledIO[MemExuOutput]] = { 821 writebackSta ++ 822 writebackHyuLda ++ writebackHyuSta ++ 823 writebackLda ++ 824 writebackVldu ++ 825 writebackStd 826 } 827} 828 829class TopToBackendBundle(implicit p: Parameters) extends XSBundle { 830 val hartId = Output(UInt(hartIdLen.W)) 831 val externalInterrupt = Output(new ExternalInterruptIO) 832 val msiInfo = Output(ValidIO(new MsiInfoBundle)) 833 val clintTime = Output(ValidIO(UInt(64.W))) 834} 835 836class BackendToTopBundle extends Bundle { 837 val cpuHalted = Output(Bool()) 838} 839 840class BackendIO(implicit p: Parameters, params: BackendParams) extends XSBundle with HasSoCParameter { 841 val fromTop = Flipped(new TopToBackendBundle) 842 843 val toTop = new BackendToTopBundle 844 845 val fenceio = new FenceIO 846 // Todo: merge these bundles into BackendFrontendIO 847 val frontend = Flipped(new FrontendToCtrlIO) 848 val frontendSfence = Output(new SfenceBundle) 849 val frontendCsrCtrl = Output(new CustomCSRCtrlIO) 850 val frontendTlbCsr = Output(new TlbCsrBundle) 851 val frontendReset = Output(Reset()) 852 853 val mem = new BackendMemIO 854 855 val perf = Input(new PerfCounterIO) 856 857 val tlb = Output(new TlbCsrBundle) 858 859 val csrCustomCtrl = Output(new CustomCSRCtrlIO) 860 861 val debugTopDown = new Bundle { 862 val fromRob = new RobCoreTopDownIO 863 val fromCore = new CoreDispatchTopDownIO 864 } 865 val debugRolling = new RobDebugRollingIO 866} 867