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 409 private val csrio = intExuBlock.io.csrio.get 410 csrio.hartId := io.fromTop.hartId 411 csrio.fpu.fflags := ctrlBlock.io.robio.csr.fflags 412 csrio.fpu.isIllegal := false.B // Todo: remove it 413 csrio.fpu.dirty_fs := ctrlBlock.io.robio.csr.dirty_fs 414 csrio.vpu <> WireDefault(0.U.asTypeOf(csrio.vpu)) // Todo 415 416 val fromIntExuVsetVType = intExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType)))) 417 val fromVfExuVsetVType = vfExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType)))) 418 val fromVsetVType = Mux(fromIntExuVsetVType.valid, fromIntExuVsetVType.bits, fromVfExuVsetVType.bits) 419 val vsetvlVType = RegEnable(fromVsetVType, 0.U.asTypeOf(new VType), fromIntExuVsetVType.valid || fromVfExuVsetVType.valid) 420 ctrlBlock.io.toDecode.vsetvlVType := vsetvlVType 421 422 val commitVType = ctrlBlock.io.robio.commitVType.vtype 423 val hasVsetvl = ctrlBlock.io.robio.commitVType.hasVsetvl 424 val vtype = VType.toVtypeStruct(Mux(hasVsetvl, vsetvlVType, commitVType.bits)).asUInt 425 426 // csr not store the value of vl, so when using difftest we assign the value of vl to debugVl 427 val debugVl_s0 = WireInit(UInt(VlData().dataWidth.W), 0.U) 428 val debugVl_s1 = WireInit(UInt(VlData().dataWidth.W), 0.U) 429 debugVl_s0 := dataPath.io.debugVl.getOrElse(0.U.asTypeOf(UInt(VlData().dataWidth.W))) 430 debugVl_s1 := RegNext(debugVl_s0) 431 csrio.vpu.set_vxsat := ctrlBlock.io.robio.csr.vxsat 432 csrio.vpu.set_vstart.valid := ctrlBlock.io.robio.csr.vstart.valid 433 csrio.vpu.set_vstart.bits := ctrlBlock.io.robio.csr.vstart.bits 434 ctrlBlock.io.toDecode.vstart := csrio.vpu.vstart 435 //Todo here need change design 436 csrio.vpu.set_vtype.valid := commitVType.valid 437 csrio.vpu.set_vtype.bits := ZeroExt(vtype, XLEN) 438 csrio.vpu.vl := ZeroExt(debugVl_s1, XLEN) 439 csrio.vpu.dirty_vs := ctrlBlock.io.robio.csr.dirty_vs 440 csrio.exception := ctrlBlock.io.robio.exception 441 csrio.memExceptionVAddr := io.mem.exceptionAddr.vaddr 442 csrio.memExceptionGPAddr := io.mem.exceptionAddr.gpaddr 443 csrio.externalInterrupt := RegNext(io.fromTop.externalInterrupt) 444 csrio.perf <> io.perf 445 csrio.perf.retiredInstr <> ctrlBlock.io.robio.csr.perfinfo.retiredInstr 446 csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo 447 private val fenceio = intExuBlock.io.fenceio.get 448 io.fenceio <> fenceio 449 450 // to fpExuBlock 451 fpExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 452 for (i <- 0 until fpExuBlock.io.in.length) { 453 for (j <- 0 until fpExuBlock.io.in(i).length) { 454 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.fp(i)(j).bits.loadDependency, io.mem.ldCancel) 455 NewPipelineConnect( 456 bypassNetwork.io.toExus.fp(i)(j), fpExuBlock.io.in(i)(j), fpExuBlock.io.in(i)(j).fire, 457 Mux( 458 bypassNetwork.io.toExus.fp(i)(j).fire, 459 bypassNetwork.io.toExus.fp(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 460 fpExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 461 ), 462 Option("bypassNetwork2fpExuBlock") 463 ) 464 } 465 } 466 467 vfExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 468 for (i <- 0 until vfExuBlock.io.in.size) { 469 for (j <- 0 until vfExuBlock.io.in(i).size) { 470 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.vf(i)(j).bits.loadDependency, io.mem.ldCancel) 471 NewPipelineConnect( 472 bypassNetwork.io.toExus.vf(i)(j), vfExuBlock.io.in(i)(j), vfExuBlock.io.in(i)(j).fire, 473 Mux( 474 bypassNetwork.io.toExus.vf(i)(j).fire, 475 bypassNetwork.io.toExus.vf(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 476 vfExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 477 ), 478 Option("bypassNetwork2vfExuBlock") 479 ) 480 481 } 482 } 483 484 intExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 485 fpExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 486 fpExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm) 487 vfExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 488 vfExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm) 489 490 wbDataPath.io.flush := ctrlBlock.io.redirect 491 wbDataPath.io.fromTop.hartId := io.fromTop.hartId 492 wbDataPath.io.fromIntExu <> intExuBlock.io.out 493 wbDataPath.io.fromFpExu <> fpExuBlock.io.out 494 wbDataPath.io.fromVfExu <> vfExuBlock.io.out 495 wbDataPath.io.fromMemExu.flatten.zip(io.mem.writeBack).foreach { case (sink, source) => 496 sink.valid := source.valid 497 source.ready := sink.ready 498 sink.bits.data := VecInit(Seq.fill(sink.bits.params.wbPathNum)(source.bits.data)) 499 sink.bits.pdest := source.bits.uop.pdest 500 sink.bits.robIdx := source.bits.uop.robIdx 501 sink.bits.intWen.foreach(_ := source.bits.uop.rfWen) 502 sink.bits.fpWen.foreach(_ := source.bits.uop.fpWen) 503 sink.bits.vecWen.foreach(_ := source.bits.uop.vecWen) 504 sink.bits.v0Wen.foreach(_ := source.bits.uop.v0Wen) 505 sink.bits.vlWen.foreach(_ := source.bits.uop.vlWen) 506 sink.bits.exceptionVec.foreach(_ := source.bits.uop.exceptionVec) 507 sink.bits.flushPipe.foreach(_ := source.bits.uop.flushPipe) 508 sink.bits.replay.foreach(_ := source.bits.uop.replayInst) 509 sink.bits.debug := source.bits.debug 510 sink.bits.debugInfo := source.bits.uop.debugInfo 511 sink.bits.lqIdx.foreach(_ := source.bits.uop.lqIdx) 512 sink.bits.sqIdx.foreach(_ := source.bits.uop.sqIdx) 513 sink.bits.predecodeInfo.foreach(_ := source.bits.uop.preDecodeInfo) 514 sink.bits.vls.foreach(x => { 515 x.vdIdx := source.bits.vdIdx.get 516 x.vdIdxInField := source.bits.vdIdxInField.get 517 x.vpu := source.bits.uop.vpu 518 x.oldVdPsrc := source.bits.uop.psrc(2) 519 x.isIndexed := VlduType.isIndexed(source.bits.uop.fuOpType) 520 x.isMasked := VlduType.isMasked(source.bits.uop.fuOpType) 521 }) 522 sink.bits.trigger.foreach(_ := source.bits.uop.trigger) 523 } 524 525 // to mem 526 private val memIssueParams = params.memSchdParams.get.issueBlockParams 527 private val memExuBlocksHasLDU = memIssueParams.map(_.exuBlockParams.map(x => x.hasLoadFu || x.hasHyldaFu)) 528 private val memExuBlocksHasVecLoad = memIssueParams.map(_.exuBlockParams.map(x => x.hasVLoadFu)) 529 println(s"[Backend] memExuBlocksHasLDU: $memExuBlocksHasLDU") 530 println(s"[Backend] memExuBlocksHasVecLoad: $memExuBlocksHasVecLoad") 531 532 private val toMem = Wire(bypassNetwork.io.toExus.mem.cloneType) 533 for (i <- toMem.indices) { 534 for (j <- toMem(i).indices) { 535 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.mem(i)(j).bits.loadDependency, io.mem.ldCancel) 536 val issueTimeout = 537 if (memExuBlocksHasLDU(i)(j)) 538 Counter(0 until 16, toMem(i)(j).valid && !toMem(i)(j).fire, bypassNetwork.io.toExus.mem(i)(j).fire)._2 539 else 540 false.B 541 542 if (memScheduler.io.loadFinalIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) { 543 memScheduler.io.loadFinalIssueResp(i)(j).valid := issueTimeout 544 memScheduler.io.loadFinalIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType 545 memScheduler.io.loadFinalIssueResp(i)(j).bits.resp := RespType.block 546 memScheduler.io.loadFinalIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx 547 memScheduler.io.loadFinalIssueResp(i)(j).bits.uopIdx.foreach(_ := toMem(i)(j).bits.vpu.get.vuopIdx) 548 memScheduler.io.loadFinalIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get) 549 memScheduler.io.loadFinalIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get) 550 } 551 552 NewPipelineConnect( 553 bypassNetwork.io.toExus.mem(i)(j), toMem(i)(j), toMem(i)(j).fire, 554 Mux( 555 bypassNetwork.io.toExus.mem(i)(j).fire, 556 bypassNetwork.io.toExus.mem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 557 toMem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || issueTimeout 558 ), 559 Option("bypassNetwork2toMemExus") 560 ) 561 562 if (memScheduler.io.memAddrIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) { 563 memScheduler.io.memAddrIssueResp(i)(j).valid := toMem(i)(j).fire && FuType.isLoad(toMem(i)(j).bits.fuType) 564 memScheduler.io.memAddrIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType 565 memScheduler.io.memAddrIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx 566 memScheduler.io.memAddrIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get) 567 memScheduler.io.memAddrIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get) 568 memScheduler.io.memAddrIssueResp(i)(j).bits.resp := RespType.success // for load inst, firing at toMem means issuing successfully 569 } 570 571 if (memScheduler.io.vecLoadIssueResp(i).nonEmpty && memExuBlocksHasVecLoad(i)(j)) { 572 memScheduler.io.vecLoadIssueResp(i)(j) match { 573 case resp => 574 resp.valid := toMem(i)(j).fire && VlduType.isVecLd(toMem(i)(j).bits.fuOpType) 575 resp.bits.fuType := toMem(i)(j).bits.fuType 576 resp.bits.robIdx := toMem(i)(j).bits.robIdx 577 resp.bits.uopIdx.get := toMem(i)(j).bits.vpu.get.vuopIdx 578 resp.bits.sqIdx.get := toMem(i)(j).bits.sqIdx.get 579 resp.bits.lqIdx.get := toMem(i)(j).bits.lqIdx.get 580 resp.bits.resp := RespType.success 581 } 582 if (backendParams.debugEn){ 583 dontTouch(memScheduler.io.vecLoadIssueResp(i)(j)) 584 } 585 } 586 } 587 } 588 589 io.mem.redirect := ctrlBlock.io.redirect 590 io.mem.issueUops.zip(toMem.flatten).foreach { case (sink, source) => 591 val enableMdp = Constantin.createRecord("EnableMdp", true) 592 sink.valid := source.valid 593 source.ready := sink.ready 594 sink.bits.iqIdx := source.bits.iqIdx 595 sink.bits.isFirstIssue := source.bits.isFirstIssue 596 sink.bits.uop := 0.U.asTypeOf(sink.bits.uop) 597 sink.bits.src := 0.U.asTypeOf(sink.bits.src) 598 sink.bits.src.zip(source.bits.src).foreach { case (l, r) => l := r} 599 sink.bits.uop.fuType := source.bits.fuType 600 sink.bits.uop.fuOpType := source.bits.fuOpType 601 sink.bits.uop.imm := source.bits.imm 602 sink.bits.uop.robIdx := source.bits.robIdx 603 sink.bits.uop.pdest := source.bits.pdest 604 sink.bits.uop.rfWen := source.bits.rfWen.getOrElse(false.B) 605 sink.bits.uop.fpWen := source.bits.fpWen.getOrElse(false.B) 606 sink.bits.uop.vecWen := source.bits.vecWen.getOrElse(false.B) 607 sink.bits.uop.v0Wen := source.bits.v0Wen.getOrElse(false.B) 608 sink.bits.uop.vlWen := source.bits.vlWen.getOrElse(false.B) 609 sink.bits.uop.flushPipe := source.bits.flushPipe.getOrElse(false.B) 610 sink.bits.uop.pc := source.bits.pc.getOrElse(0.U) 611 sink.bits.uop.loadWaitBit := Mux(enableMdp, source.bits.loadWaitBit.getOrElse(false.B), false.B) 612 sink.bits.uop.waitForRobIdx := Mux(enableMdp, source.bits.waitForRobIdx.getOrElse(0.U.asTypeOf(new RobPtr)), 0.U.asTypeOf(new RobPtr)) 613 sink.bits.uop.storeSetHit := Mux(enableMdp, source.bits.storeSetHit.getOrElse(false.B), false.B) 614 sink.bits.uop.loadWaitStrict := Mux(enableMdp, source.bits.loadWaitStrict.getOrElse(false.B), false.B) 615 sink.bits.uop.ssid := Mux(enableMdp, source.bits.ssid.getOrElse(0.U(SSIDWidth.W)), 0.U(SSIDWidth.W)) 616 sink.bits.uop.lqIdx := source.bits.lqIdx.getOrElse(0.U.asTypeOf(new LqPtr)) 617 sink.bits.uop.sqIdx := source.bits.sqIdx.getOrElse(0.U.asTypeOf(new SqPtr)) 618 sink.bits.uop.ftqPtr := source.bits.ftqIdx.getOrElse(0.U.asTypeOf(new FtqPtr)) 619 sink.bits.uop.ftqOffset := source.bits.ftqOffset.getOrElse(0.U) 620 sink.bits.uop.debugInfo := source.bits.perfDebugInfo 621 sink.bits.uop.vpu := source.bits.vpu.getOrElse(0.U.asTypeOf(new VPUCtrlSignals)) 622 sink.bits.uop.preDecodeInfo := source.bits.preDecode.getOrElse(0.U.asTypeOf(new PreDecodeInfo)) 623 sink.bits.uop.numLsElem := source.bits.numLsElem.getOrElse(0.U) // Todo: remove this bundle, keep only the one below 624 sink.bits.flowNum.foreach(_ := source.bits.numLsElem.get) 625 } 626 io.mem.loadFastMatch := memScheduler.io.toMem.get.loadFastMatch.map(_.fastMatch) 627 io.mem.loadFastImm := memScheduler.io.toMem.get.loadFastMatch.map(_.fastImm) 628 io.mem.tlbCsr := csrio.tlb 629 io.mem.csrCtrl := csrio.customCtrl 630 io.mem.sfence := fenceio.sfence 631 io.mem.isStoreException := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.commitType) 632 io.mem.isVlsException := ctrlBlock.io.robio.exception.bits.vls 633 require(io.mem.loadPcRead.size == params.LduCnt) 634 io.mem.loadPcRead.zipWithIndex.foreach { case (loadPcRead, i) => 635 loadPcRead := ctrlBlock.io.memLdPcRead(i).data 636 ctrlBlock.io.memLdPcRead(i).valid := io.mem.issueLda(i).valid 637 ctrlBlock.io.memLdPcRead(i).ptr := io.mem.issueLda(i).bits.uop.ftqPtr 638 ctrlBlock.io.memLdPcRead(i).offset := io.mem.issueLda(i).bits.uop.ftqOffset 639 } 640 641 io.mem.storePcRead.zipWithIndex.foreach { case (storePcRead, i) => 642 storePcRead := ctrlBlock.io.memStPcRead(i).data 643 ctrlBlock.io.memStPcRead(i).valid := io.mem.issueSta(i).valid 644 ctrlBlock.io.memStPcRead(i).ptr := io.mem.issueSta(i).bits.uop.ftqPtr 645 ctrlBlock.io.memStPcRead(i).offset := io.mem.issueSta(i).bits.uop.ftqOffset 646 } 647 648 io.mem.hyuPcRead.zipWithIndex.foreach( { case (hyuPcRead, i) => 649 hyuPcRead := ctrlBlock.io.memHyPcRead(i).data 650 ctrlBlock.io.memHyPcRead(i).valid := io.mem.issueHylda(i).valid 651 ctrlBlock.io.memHyPcRead(i).ptr := io.mem.issueHylda(i).bits.uop.ftqPtr 652 ctrlBlock.io.memHyPcRead(i).offset := io.mem.issueHylda(i).bits.uop.ftqOffset 653 }) 654 655 ctrlBlock.io.robio.robHeadLsIssue := io.mem.issueUops.map(deq => deq.fire && deq.bits.uop.robIdx === ctrlBlock.io.robio.robDeqPtr).reduce(_ || _) 656 657 // mem io 658 io.mem.lsqEnqIO <> memScheduler.io.memIO.get.lsqEnqIO 659 io.mem.robLsqIO <> ctrlBlock.io.robio.lsq 660 661 io.frontendSfence := fenceio.sfence 662 io.frontendTlbCsr := csrio.tlb 663 io.frontendCsrCtrl := csrio.customCtrl 664 665 io.tlb <> csrio.tlb 666 667 io.csrCustomCtrl := csrio.customCtrl 668 669 io.toTop.cpuHalted := false.B // TODO: implement cpu halt 670 671 io.debugTopDown.fromRob := ctrlBlock.io.debugTopDown.fromRob 672 ctrlBlock.io.debugTopDown.fromCore := io.debugTopDown.fromCore 673 674 io.debugRolling := ctrlBlock.io.debugRolling 675 676 if(backendParams.debugEn) { 677 dontTouch(memScheduler.io) 678 dontTouch(dataPath.io.toMemExu) 679 dontTouch(wbDataPath.io.fromMemExu) 680 } 681 682 // reset tree 683 if (p(DebugOptionsKey).ResetGen) { 684 val rightResetTree = ResetGenNode(Seq( 685 ModuleNode(dataPath), 686 ModuleNode(intExuBlock), 687 ModuleNode(fpExuBlock), 688 ModuleNode(vfExuBlock), 689 ModuleNode(bypassNetwork), 690 ModuleNode(wbDataPath) 691 )) 692 val leftResetTree = ResetGenNode(Seq( 693 ModuleNode(pcTargetMem), 694 ModuleNode(intScheduler), 695 ModuleNode(fpScheduler), 696 ModuleNode(vfScheduler), 697 ModuleNode(memScheduler), 698 ModuleNode(og2ForVector), 699 ModuleNode(wbFuBusyTable), 700 ResetGenNode(Seq( 701 ModuleNode(ctrlBlock), 702 ResetGenNode(Seq( 703 CellNode(io.frontendReset) 704 )) 705 )) 706 )) 707 ResetGen(leftResetTree, reset, sim = false) 708 ResetGen(rightResetTree, reset, sim = false) 709 } else { 710 io.frontendReset := DontCare 711 } 712 713 // perf events 714 val pfevent = Module(new PFEvent) 715 pfevent.io.distribute_csr := RegNext(csrio.customCtrl.distribute_csr) 716 val csrevents = pfevent.io.hpmevent.slice(8,16) 717 718 val ctrlBlockPerf = ctrlBlock.getPerfEvents 719 val intSchedulerPerf = intScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 720 val fpSchedulerPerf = fpScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 721 val vecSchedulerPerf = vfScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 722 val memSchedulerPerf = memScheduler.asInstanceOf[SchedulerMemImp].getPerfEvents 723 724 val perfBackend = Seq() 725 // let index = 0 be no event 726 val allPerfEvents = Seq(("noEvent", 0.U)) ++ ctrlBlockPerf ++ intSchedulerPerf ++ fpSchedulerPerf ++ vecSchedulerPerf ++ memSchedulerPerf ++ perfBackend 727 728 729 if (printEventCoding) { 730 for (((name, inc), i) <- allPerfEvents.zipWithIndex) { 731 println("backend perfEvents Set", name, inc, i) 732 } 733 } 734 735 val allPerfInc = allPerfEvents.map(_._2.asTypeOf(new PerfEvent)) 736 val perfEvents = HPerfMonitor(csrevents, allPerfInc).getPerfEvents 737 csrio.perf.perfEventsBackend := VecInit(perfEvents.map(_._2.asTypeOf(new PerfEvent))) 738 generatePerfEvent() 739} 740 741class BackendMemIO(implicit p: Parameters, params: BackendParams) extends XSBundle { 742 // Since fast load replay always use load unit 0, Backend flips two load port to avoid conflicts 743 val flippedLda = true 744 // params alias 745 private val LoadQueueSize = VirtualLoadQueueSize 746 // In/Out // Todo: split it into one-direction bundle 747 val lsqEnqIO = Flipped(new LsqEnqIO) 748 val robLsqIO = new RobLsqIO 749 val ldaIqFeedback = Vec(params.LduCnt, Flipped(new MemRSFeedbackIO)) 750 val staIqFeedback = Vec(params.StaCnt, Flipped(new MemRSFeedbackIO)) 751 val hyuIqFeedback = Vec(params.HyuCnt, Flipped(new MemRSFeedbackIO)) 752 val vstuIqFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true))) 753 val vlduIqFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true))) 754 val ldCancel = Vec(params.LdExuCnt, Input(new LoadCancelIO)) 755 val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst))) 756 val loadPcRead = Vec(params.LduCnt, Output(UInt(VAddrBits.W))) 757 val storePcRead = Vec(params.StaCnt, Output(UInt(VAddrBits.W))) 758 val hyuPcRead = Vec(params.HyuCnt, Output(UInt(VAddrBits.W))) 759 // Input 760 val writebackLda = Vec(params.LduCnt, Flipped(DecoupledIO(new MemExuOutput))) 761 val writebackSta = Vec(params.StaCnt, Flipped(DecoupledIO(new MemExuOutput))) 762 val writebackStd = Vec(params.StdCnt, Flipped(DecoupledIO(new MemExuOutput))) 763 val writebackHyuLda = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput))) 764 val writebackHyuSta = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput))) 765 val writebackVldu = Vec(params.VlduCnt, Flipped(DecoupledIO(new MemExuOutput(true)))) 766 767 val s3_delayed_load_error = Input(Vec(LoadPipelineWidth, Bool())) 768 val stIn = Input(Vec(params.StaExuCnt, ValidIO(new DynInst()))) 769 val memoryViolation = Flipped(ValidIO(new Redirect)) 770 val exceptionAddr = Input(new Bundle { 771 val vaddr = UInt(VAddrBits.W) 772 val gpaddr = UInt(GPAddrBits.W) 773 }) 774 val sqDeq = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) 775 val lqDeq = Input(UInt(log2Up(CommitWidth + 1).W)) 776 val sqDeqPtr = Input(new SqPtr) 777 val lqDeqPtr = Input(new LqPtr) 778 779 val lqCancelCnt = Input(UInt(log2Up(VirtualLoadQueueSize + 1).W)) 780 val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W)) 781 782 val lqCanAccept = Input(Bool()) 783 val sqCanAccept = Input(Bool()) 784 785 val otherFastWakeup = Flipped(Vec(params.LduCnt + params.HyuCnt, ValidIO(new DynInst))) 786 val stIssuePtr = Input(new SqPtr()) 787 788 val debugLS = Flipped(Output(new DebugLSIO)) 789 790 val lsTopdownInfo = Vec(params.LduCnt + params.HyuCnt, Flipped(Output(new LsTopdownInfo))) 791 // Output 792 val redirect = ValidIO(new Redirect) // rob flush MemBlock 793 val issueLda = MixedVec(Seq.fill(params.LduCnt)(DecoupledIO(new MemExuInput()))) 794 val issueSta = MixedVec(Seq.fill(params.StaCnt)(DecoupledIO(new MemExuInput()))) 795 val issueStd = MixedVec(Seq.fill(params.StdCnt)(DecoupledIO(new MemExuInput()))) 796 val issueHylda = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput()))) 797 val issueHysta = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput()))) 798 val issueVldu = MixedVec(Seq.fill(params.VlduCnt)(DecoupledIO(new MemExuInput(true)))) 799 800 val loadFastMatch = Vec(params.LduCnt, Output(UInt(params.LduCnt.W))) 801 val loadFastImm = Vec(params.LduCnt, Output(UInt(12.W))) // Imm_I 802 803 val tlbCsr = Output(new TlbCsrBundle) 804 val csrCtrl = Output(new CustomCSRCtrlIO) 805 val sfence = Output(new SfenceBundle) 806 val isStoreException = Output(Bool()) 807 val isVlsException = Output(Bool()) 808 809 // ATTENTION: The issue ports' sequence order should be the same as IQs' deq config 810 private [backend] def issueUops: Seq[DecoupledIO[MemExuInput]] = { 811 issueSta ++ 812 issueHylda ++ issueHysta ++ 813 issueLda ++ 814 issueVldu ++ 815 issueStd 816 }.toSeq 817 818 // ATTENTION: The writeback ports' sequence order should be the same as IQs' deq config 819 private [backend] def writeBack: Seq[DecoupledIO[MemExuOutput]] = { 820 writebackSta ++ 821 writebackHyuLda ++ writebackHyuSta ++ 822 writebackLda ++ 823 writebackVldu ++ 824 writebackStd 825 } 826} 827 828class TopToBackendBundle(implicit p: Parameters) extends XSBundle { 829 val hartId = Output(UInt(hartIdLen.W)) 830 val externalInterrupt = Output(new ExternalInterruptIO) 831 val msiInfo = Output(ValidIO(new MsiInfoBundle)) 832 val clintTime = Output(ValidIO(UInt(64.W))) 833} 834 835class BackendToTopBundle extends Bundle { 836 val cpuHalted = Output(Bool()) 837} 838 839class BackendIO(implicit p: Parameters, params: BackendParams) extends XSBundle with HasSoCParameter { 840 val fromTop = Flipped(new TopToBackendBundle) 841 842 val toTop = new BackendToTopBundle 843 844 val fenceio = new FenceIO 845 // Todo: merge these bundles into BackendFrontendIO 846 val frontend = Flipped(new FrontendToCtrlIO) 847 val frontendSfence = Output(new SfenceBundle) 848 val frontendCsrCtrl = Output(new CustomCSRCtrlIO) 849 val frontendTlbCsr = Output(new TlbCsrBundle) 850 val frontendReset = Output(Reset()) 851 852 val mem = new BackendMemIO 853 854 val perf = Input(new PerfCounterIO) 855 856 val tlb = Output(new TlbCsrBundle) 857 858 val csrCustomCtrl = Output(new CustomCSRCtrlIO) 859 860 val debugTopDown = new Bundle { 861 val fromRob = new RobCoreTopDownIO 862 val fromCore = new CoreDispatchTopDownIO 863 } 864 val debugRolling = new RobDebugRollingIO 865} 866