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 ctrlBlock.io.debugEnqLsq.iqAccept := memScheduler.io.memIO.get.lsqEnqIO.iqAccept 239 240 intScheduler.io.fromTop.hartId := io.fromTop.hartId 241 intScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 242 intScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 243 intScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.intUops 244 intScheduler.io.intWriteBack := wbDataPath.io.toIntPreg 245 intScheduler.io.fpWriteBack := 0.U.asTypeOf(intScheduler.io.fpWriteBack) 246 intScheduler.io.vfWriteBack := 0.U.asTypeOf(intScheduler.io.vfWriteBack) 247 intScheduler.io.v0WriteBack := 0.U.asTypeOf(intScheduler.io.v0WriteBack) 248 intScheduler.io.vlWriteBack := 0.U.asTypeOf(intScheduler.io.vlWriteBack) 249 intScheduler.io.fromDataPath.resp := dataPath.io.toIntIQ 250 intScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 251 intScheduler.io.fromDataPath.og0Cancel := og0Cancel 252 intScheduler.io.fromDataPath.og1Cancel := og1Cancel 253 intScheduler.io.ldCancel := io.mem.ldCancel 254 intScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.take(params.getIntExuRCWriteSize) 255 intScheduler.io.vlWriteBackInfo.vlIsZero := false.B 256 intScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B 257 258 fpScheduler.io.fromTop.hartId := io.fromTop.hartId 259 fpScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 260 fpScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 261 fpScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.fpUops 262 fpScheduler.io.intWriteBack := 0.U.asTypeOf(fpScheduler.io.intWriteBack) 263 fpScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg 264 fpScheduler.io.vfWriteBack := 0.U.asTypeOf(fpScheduler.io.vfWriteBack) 265 fpScheduler.io.v0WriteBack := 0.U.asTypeOf(fpScheduler.io.v0WriteBack) 266 fpScheduler.io.vlWriteBack := 0.U.asTypeOf(fpScheduler.io.vlWriteBack) 267 fpScheduler.io.fromDataPath.resp := dataPath.io.toFpIQ 268 fpScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 269 fpScheduler.io.fromDataPath.og0Cancel := og0Cancel 270 fpScheduler.io.fromDataPath.og1Cancel := og1Cancel 271 fpScheduler.io.ldCancel := io.mem.ldCancel 272 fpScheduler.io.vlWriteBackInfo.vlIsZero := false.B 273 fpScheduler.io.vlWriteBackInfo.vlIsVlmax := false.B 274 275 memScheduler.io.fromTop.hartId := io.fromTop.hartId 276 memScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 277 memScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 278 memScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.memUops 279 memScheduler.io.intWriteBack := wbDataPath.io.toIntPreg 280 memScheduler.io.fpWriteBack := wbDataPath.io.toFpPreg 281 memScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg 282 memScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg 283 memScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg 284 memScheduler.io.fromMem.get.scommit := io.mem.sqDeq 285 memScheduler.io.fromMem.get.lcommit := io.mem.lqDeq 286 memScheduler.io.fromMem.get.wakeup := io.mem.wakeup 287 memScheduler.io.fromMem.get.sqDeqPtr := io.mem.sqDeqPtr 288 memScheduler.io.fromMem.get.lqDeqPtr := io.mem.lqDeqPtr 289 memScheduler.io.fromMem.get.sqCancelCnt := io.mem.sqCancelCnt 290 memScheduler.io.fromMem.get.lqCancelCnt := io.mem.lqCancelCnt 291 memScheduler.io.fromMem.get.stIssuePtr := io.mem.stIssuePtr 292 require(memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.length == io.mem.stIn.length) 293 memScheduler.io.fromMem.get.memWaitUpdateReq.robIdx.zip(io.mem.stIn).foreach { case (sink, source) => 294 sink.valid := source.valid 295 sink.bits := source.bits.robIdx 296 } 297 memScheduler.io.fromMem.get.memWaitUpdateReq.sqIdx := DontCare // TODO 298 memScheduler.io.fromDataPath.resp := dataPath.io.toMemIQ 299 memScheduler.io.fromMem.get.ldaFeedback := io.mem.ldaIqFeedback 300 memScheduler.io.fromMem.get.staFeedback := io.mem.staIqFeedback 301 memScheduler.io.fromMem.get.hyuFeedback := io.mem.hyuIqFeedback 302 memScheduler.io.fromMem.get.vstuFeedback := io.mem.vstuIqFeedback 303 memScheduler.io.fromMem.get.vlduFeedback := io.mem.vlduIqFeedback 304 memScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 305 memScheduler.io.fromDataPath.og0Cancel := og0Cancel 306 memScheduler.io.fromDataPath.og1Cancel := og1Cancel 307 memScheduler.io.ldCancel := io.mem.ldCancel 308 memScheduler.io.fromDataPath.replaceRCIdx.get := dataPath.io.toWakeupQueueRCIdx.takeRight(params.getMemExuRCWriteSize) 309 memScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero 310 memScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax 311 memScheduler.io.fromOg2Resp.get := og2ForVector.io.toMemIQOg2Resp 312 313 vfScheduler.io.fromTop.hartId := io.fromTop.hartId 314 vfScheduler.io.fromCtrlBlock.flush := ctrlBlock.io.toIssueBlock.flush 315 vfScheduler.io.fromDispatch.allocPregs <> ctrlBlock.io.toIssueBlock.allocPregs 316 vfScheduler.io.fromDispatch.uops <> ctrlBlock.io.toIssueBlock.vfUops 317 vfScheduler.io.intWriteBack := 0.U.asTypeOf(vfScheduler.io.intWriteBack) 318 vfScheduler.io.fpWriteBack := 0.U.asTypeOf(vfScheduler.io.fpWriteBack) 319 vfScheduler.io.vfWriteBack := wbDataPath.io.toVfPreg 320 vfScheduler.io.v0WriteBack := wbDataPath.io.toV0Preg 321 vfScheduler.io.vlWriteBack := wbDataPath.io.toVlPreg 322 vfScheduler.io.fromDataPath.resp := dataPath.io.toVfIQ 323 vfScheduler.io.fromSchedulers.wakeupVec.foreach { wakeup => wakeup := iqWakeUpMappedBundle(wakeup.bits.exuIdx) } 324 vfScheduler.io.fromDataPath.og0Cancel := og0Cancel 325 vfScheduler.io.fromDataPath.og1Cancel := og1Cancel 326 vfScheduler.io.ldCancel := io.mem.ldCancel 327 vfScheduler.io.vlWriteBackInfo.vlIsZero := vlIsZero 328 vfScheduler.io.vlWriteBackInfo.vlIsVlmax := vlIsVlmax 329 vfScheduler.io.fromOg2Resp.get := og2ForVector.io.toVfIQOg2Resp 330 331 dataPath.io.hartId := io.fromTop.hartId 332 dataPath.io.flush := ctrlBlock.io.toDataPath.flush 333 334 dataPath.io.fromIntIQ <> intScheduler.io.toDataPathAfterDelay 335 dataPath.io.fromFpIQ <> fpScheduler.io.toDataPathAfterDelay 336 dataPath.io.fromVfIQ <> vfScheduler.io.toDataPathAfterDelay 337 dataPath.io.fromMemIQ <> memScheduler.io.toDataPathAfterDelay 338 339 dataPath.io.ldCancel := io.mem.ldCancel 340 341 println(s"[Backend] wbDataPath.io.toIntPreg: ${wbDataPath.io.toIntPreg.size}, dataPath.io.fromIntWb: ${dataPath.io.fromIntWb.size}") 342 println(s"[Backend] wbDataPath.io.toVfPreg: ${wbDataPath.io.toVfPreg.size}, dataPath.io.fromFpWb: ${dataPath.io.fromVfWb.size}") 343 dataPath.io.fromIntWb := wbDataPath.io.toIntPreg 344 dataPath.io.fromFpWb := wbDataPath.io.toFpPreg 345 dataPath.io.fromVfWb := wbDataPath.io.toVfPreg 346 dataPath.io.fromV0Wb := wbDataPath.io.toV0Preg 347 dataPath.io.fromVlWb := wbDataPath.io.toVlPreg 348 dataPath.io.diffIntRat.foreach(_ := ctrlBlock.io.diff_int_rat.get) 349 dataPath.io.diffFpRat .foreach(_ := ctrlBlock.io.diff_fp_rat.get) 350 dataPath.io.diffVecRat.foreach(_ := ctrlBlock.io.diff_vec_rat.get) 351 dataPath.io.diffV0Rat .foreach(_ := ctrlBlock.io.diff_v0_rat.get) 352 dataPath.io.diffVlRat .foreach(_ := ctrlBlock.io.diff_vl_rat.get) 353 dataPath.io.fromBypassNetwork := bypassNetwork.io.toDataPath 354 355 og2ForVector.io.flush := ctrlBlock.io.toDataPath.flush 356 og2ForVector.io.ldCancel := io.mem.ldCancel 357 og2ForVector.io.fromOg1VfArith <> dataPath.io.toVecExu 358 og2ForVector.io.fromOg1VecMem.zip(dataPath.io.toMemExu.zip(params.memSchdParams.get.issueBlockParams).filter(_._2.needOg2Resp).map(_._1)) 359 .foreach { 360 case (og1Mem, datapathMem) => og1Mem <> datapathMem 361 } 362 og2ForVector.io.fromOg1ImmInfo := dataPath.io.og1ImmInfo.zip(params.allExuParams).filter(_._2.needOg2).map(_._1) 363 364 println(s"[Backend] BypassNetwork OG1 Mem Size: ${bypassNetwork.io.fromDataPath.mem.zip(params.memSchdParams.get.issueBlockParams).filterNot(_._2.needOg2Resp).size}") 365 println(s"[Backend] BypassNetwork OG2 Mem Size: ${bypassNetwork.io.fromDataPath.mem.zip(params.memSchdParams.get.issueBlockParams).filter(_._2.needOg2Resp).size}") 366 println(s"[Backend] bypassNetwork.io.fromDataPath.mem: ${bypassNetwork.io.fromDataPath.mem.size}, dataPath.io.toMemExu: ${dataPath.io.toMemExu.size}") 367 bypassNetwork.io.fromDataPath.int <> dataPath.io.toIntExu 368 bypassNetwork.io.fromDataPath.fp <> dataPath.io.toFpExu 369 bypassNetwork.io.fromDataPath.vf <> og2ForVector.io.toVfArithExu 370 bypassNetwork.io.fromDataPath.mem.lazyZip(params.memSchdParams.get.issueBlockParams).lazyZip(dataPath.io.toMemExu).filterNot(_._2.needOg2Resp) 371 .map(x => (x._1, x._3)).foreach { 372 case (bypassMem, datapathMem) => bypassMem <> datapathMem 373 } 374 bypassNetwork.io.fromDataPath.mem.zip(params.memSchdParams.get.issueBlockParams).filter(_._2.needOg2Resp).map(_._1) 375 .zip(og2ForVector.io.toVecMemExu).foreach { 376 case (bypassMem, og2Mem) => bypassMem <> og2Mem 377 } 378 bypassNetwork.io.fromDataPath.immInfo := dataPath.io.og1ImmInfo 379 bypassNetwork.io.fromDataPath.immInfo.zip(params.allExuParams).filter(_._2.needOg2).map(_._1) 380 .zip(og2ForVector.io.toBypassNetworkImmInfo).foreach { 381 case (immInfo, og2ImmInfo) => immInfo := og2ImmInfo 382 } 383 bypassNetwork.io.fromDataPath.rcData := dataPath.io.toBypassNetworkRCData 384 bypassNetwork.io.fromExus.connectExuOutput(_.int)(intExuBlock.io.out) 385 bypassNetwork.io.fromExus.connectExuOutput(_.fp)(fpExuBlock.io.out) 386 bypassNetwork.io.fromExus.connectExuOutput(_.vf)(vfExuBlock.io.out) 387 388 require(bypassNetwork.io.fromExus.mem.flatten.size == io.mem.writeBack.size, 389 s"bypassNetwork.io.fromExus.mem.flatten.size(${bypassNetwork.io.fromExus.mem.flatten.size}: ${bypassNetwork.io.fromExus.mem.map(_.size)}, " + 390 s"io.mem.writeback(${io.mem.writeBack.size})" 391 ) 392 bypassNetwork.io.fromExus.mem.flatten.zip(io.mem.writeBack).foreach { case (sink, source) => 393 sink.valid := source.valid 394 sink.bits.intWen := source.bits.uop.rfWen && FuType.isLoad(source.bits.uop.fuType) 395 sink.bits.pdest := source.bits.uop.pdest 396 sink.bits.data := source.bits.data 397 } 398 399 400 intExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 401 for (i <- 0 until intExuBlock.io.in.length) { 402 for (j <- 0 until intExuBlock.io.in(i).length) { 403 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.int(i)(j).bits.loadDependency, io.mem.ldCancel) 404 NewPipelineConnect( 405 bypassNetwork.io.toExus.int(i)(j), intExuBlock.io.in(i)(j), intExuBlock.io.in(i)(j).fire, 406 Mux( 407 bypassNetwork.io.toExus.int(i)(j).fire, 408 bypassNetwork.io.toExus.int(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 409 intExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 410 ), 411 Option("bypassNetwork2intExuBlock") 412 ) 413 } 414 } 415 416 pcTargetMem.io.fromFrontendFtq := io.frontend.fromFtq 417 pcTargetMem.io.toDataPath <> dataPath.io.fromPcTargetMem 418 419 private val csrin = intExuBlock.io.csrin.get 420 csrin.hartId := io.fromTop.hartId 421 csrin.msiInfo.valid := RegNext(io.fromTop.msiInfo.valid) 422 csrin.msiInfo.bits := RegEnable(io.fromTop.msiInfo.bits, io.fromTop.msiInfo.valid) 423 csrin.clintTime.valid := RegNext(io.fromTop.clintTime.valid) 424 csrin.clintTime.bits := RegEnable(io.fromTop.clintTime.bits, io.fromTop.clintTime.valid) 425 csrin.trapInstInfo := ctrlBlock.io.toCSR.trapInstInfo 426 427 private val csrio = intExuBlock.io.csrio.get 428 csrio.hartId := io.fromTop.hartId 429 csrio.fpu.fflags := ctrlBlock.io.robio.csr.fflags 430 csrio.fpu.isIllegal := false.B // Todo: remove it 431 csrio.fpu.dirty_fs := ctrlBlock.io.robio.csr.dirty_fs 432 csrio.vpu <> WireDefault(0.U.asTypeOf(csrio.vpu)) // Todo 433 434 val fromIntExuVsetVType = intExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType)))) 435 val fromVfExuVsetVType = vfExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType)))) 436 val fromVsetVType = Mux(fromIntExuVsetVType.valid, fromIntExuVsetVType.bits, fromVfExuVsetVType.bits) 437 val vsetvlVType = RegEnable(fromVsetVType, 0.U.asTypeOf(new VType), fromIntExuVsetVType.valid || fromVfExuVsetVType.valid) 438 ctrlBlock.io.toDecode.vsetvlVType := vsetvlVType 439 440 val commitVType = ctrlBlock.io.robio.commitVType.vtype 441 val hasVsetvl = ctrlBlock.io.robio.commitVType.hasVsetvl 442 val vtype = VType.toVtypeStruct(Mux(hasVsetvl, vsetvlVType, commitVType.bits)).asUInt 443 444 // csr not store the value of vl, so when using difftest we assign the value of vl to debugVl 445 val debugVl_s0 = WireInit(UInt(VlData().dataWidth.W), 0.U) 446 val debugVl_s1 = WireInit(UInt(VlData().dataWidth.W), 0.U) 447 debugVl_s0 := dataPath.io.diffVl.getOrElse(0.U.asTypeOf(UInt(VlData().dataWidth.W))) 448 debugVl_s1 := RegNext(debugVl_s0) 449 csrio.vpu.set_vxsat := ctrlBlock.io.robio.csr.vxsat 450 csrio.vpu.set_vstart.valid := ctrlBlock.io.robio.csr.vstart.valid 451 csrio.vpu.set_vstart.bits := ctrlBlock.io.robio.csr.vstart.bits 452 ctrlBlock.io.toDecode.vstart := csrio.vpu.vstart 453 //Todo here need change design 454 csrio.vpu.set_vtype.valid := commitVType.valid 455 csrio.vpu.set_vtype.bits := ZeroExt(vtype, XLEN) 456 csrio.vpu.vl := ZeroExt(debugVl_s1, XLEN) 457 csrio.vpu.dirty_vs := ctrlBlock.io.robio.csr.dirty_vs 458 csrio.exception := ctrlBlock.io.robio.exception 459 csrio.robDeqPtr := ctrlBlock.io.robio.robDeqPtr 460 csrio.memExceptionVAddr := io.mem.exceptionAddr.vaddr 461 csrio.memExceptionGPAddr := io.mem.exceptionAddr.gpaddr 462 csrio.externalInterrupt := RegNext(io.fromTop.externalInterrupt) 463 csrio.perf <> io.perf 464 csrio.perf.retiredInstr <> ctrlBlock.io.robio.csr.perfinfo.retiredInstr 465 csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo 466 private val fenceio = intExuBlock.io.fenceio.get 467 io.fenceio <> fenceio 468 469 // to fpExuBlock 470 fpExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 471 for (i <- 0 until fpExuBlock.io.in.length) { 472 for (j <- 0 until fpExuBlock.io.in(i).length) { 473 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.fp(i)(j).bits.loadDependency, io.mem.ldCancel) 474 NewPipelineConnect( 475 bypassNetwork.io.toExus.fp(i)(j), fpExuBlock.io.in(i)(j), fpExuBlock.io.in(i)(j).fire, 476 Mux( 477 bypassNetwork.io.toExus.fp(i)(j).fire, 478 bypassNetwork.io.toExus.fp(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 479 fpExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 480 ), 481 Option("bypassNetwork2fpExuBlock") 482 ) 483 } 484 } 485 486 vfExuBlock.io.flush := ctrlBlock.io.toExuBlock.flush 487 for (i <- 0 until vfExuBlock.io.in.size) { 488 for (j <- 0 until vfExuBlock.io.in(i).size) { 489 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.vf(i)(j).bits.loadDependency, io.mem.ldCancel) 490 NewPipelineConnect( 491 bypassNetwork.io.toExus.vf(i)(j), vfExuBlock.io.in(i)(j), vfExuBlock.io.in(i)(j).fire, 492 Mux( 493 bypassNetwork.io.toExus.vf(i)(j).fire, 494 bypassNetwork.io.toExus.vf(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 495 vfExuBlock.io.in(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) 496 ), 497 Option("bypassNetwork2vfExuBlock") 498 ) 499 500 } 501 } 502 503 intExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 504 fpExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 505 fpExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm) 506 vfExuBlock.io.frm.foreach(_ := csrio.fpu.frm) 507 vfExuBlock.io.vxrm.foreach(_ := csrio.vpu.vxrm) 508 509 wbDataPath.io.flush := ctrlBlock.io.redirect 510 wbDataPath.io.fromTop.hartId := io.fromTop.hartId 511 wbDataPath.io.fromIntExu <> intExuBlock.io.out 512 wbDataPath.io.fromFpExu <> fpExuBlock.io.out 513 wbDataPath.io.fromVfExu <> vfExuBlock.io.out 514 wbDataPath.io.fromMemExu.flatten.zip(io.mem.writeBack).foreach { case (sink, source) => 515 sink.valid := source.valid 516 source.ready := sink.ready 517 sink.bits.data := VecInit(Seq.fill(sink.bits.params.wbPathNum)(source.bits.data)) 518 sink.bits.pdest := source.bits.uop.pdest 519 sink.bits.robIdx := source.bits.uop.robIdx 520 sink.bits.intWen.foreach(_ := source.bits.uop.rfWen) 521 sink.bits.fpWen.foreach(_ := source.bits.uop.fpWen) 522 sink.bits.vecWen.foreach(_ := source.bits.uop.vecWen) 523 sink.bits.v0Wen.foreach(_ := source.bits.uop.v0Wen) 524 sink.bits.vlWen.foreach(_ := source.bits.uop.vlWen) 525 sink.bits.exceptionVec.foreach(_ := source.bits.uop.exceptionVec) 526 sink.bits.flushPipe.foreach(_ := source.bits.uop.flushPipe) 527 sink.bits.replay.foreach(_ := source.bits.uop.replayInst) 528 sink.bits.debug := source.bits.debug 529 sink.bits.debugInfo := source.bits.uop.debugInfo 530 sink.bits.lqIdx.foreach(_ := source.bits.uop.lqIdx) 531 sink.bits.sqIdx.foreach(_ := source.bits.uop.sqIdx) 532 sink.bits.predecodeInfo.foreach(_ := source.bits.uop.preDecodeInfo) 533 sink.bits.vls.foreach(x => { 534 x.vdIdx := source.bits.vdIdx.get 535 x.vdIdxInField := source.bits.vdIdxInField.get 536 x.vpu := source.bits.uop.vpu 537 x.oldVdPsrc := source.bits.uop.psrc(2) 538 x.isIndexed := VlduType.isIndexed(source.bits.uop.fuOpType) 539 x.isMasked := VlduType.isMasked(source.bits.uop.fuOpType) 540 }) 541 sink.bits.trigger.foreach(_ := source.bits.uop.trigger) 542 } 543 544 // to mem 545 private val memIssueParams = params.memSchdParams.get.issueBlockParams 546 private val memExuBlocksHasLDU = memIssueParams.map(_.exuBlockParams.map(x => x.hasLoadFu || x.hasHyldaFu)) 547 private val memExuBlocksHasVecLoad = memIssueParams.map(_.exuBlockParams.map(x => x.hasVLoadFu)) 548 println(s"[Backend] memExuBlocksHasLDU: $memExuBlocksHasLDU") 549 println(s"[Backend] memExuBlocksHasVecLoad: $memExuBlocksHasVecLoad") 550 551 private val toMem = Wire(bypassNetwork.io.toExus.mem.cloneType) 552 for (i <- toMem.indices) { 553 for (j <- toMem(i).indices) { 554 val shouldLdCancel = LoadShouldCancel(bypassNetwork.io.toExus.mem(i)(j).bits.loadDependency, io.mem.ldCancel) 555 val issueTimeout = 556 if (memExuBlocksHasLDU(i)(j)) 557 Counter(0 until 16, toMem(i)(j).valid && !toMem(i)(j).fire, bypassNetwork.io.toExus.mem(i)(j).fire)._2 558 else 559 false.B 560 561 if (memScheduler.io.loadFinalIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) { 562 memScheduler.io.loadFinalIssueResp(i)(j).valid := issueTimeout 563 memScheduler.io.loadFinalIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType 564 memScheduler.io.loadFinalIssueResp(i)(j).bits.resp := RespType.block 565 memScheduler.io.loadFinalIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx 566 memScheduler.io.loadFinalIssueResp(i)(j).bits.uopIdx.foreach(_ := toMem(i)(j).bits.vpu.get.vuopIdx) 567 memScheduler.io.loadFinalIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get) 568 memScheduler.io.loadFinalIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get) 569 } 570 571 NewPipelineConnect( 572 bypassNetwork.io.toExus.mem(i)(j), toMem(i)(j), toMem(i)(j).fire, 573 Mux( 574 bypassNetwork.io.toExus.mem(i)(j).fire, 575 bypassNetwork.io.toExus.mem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || shouldLdCancel, 576 toMem(i)(j).bits.robIdx.needFlush(ctrlBlock.io.toExuBlock.flush) || issueTimeout 577 ), 578 Option("bypassNetwork2toMemExus") 579 ) 580 581 if (memScheduler.io.memAddrIssueResp(i).nonEmpty && memExuBlocksHasLDU(i)(j)) { 582 memScheduler.io.memAddrIssueResp(i)(j).valid := toMem(i)(j).fire && FuType.isLoad(toMem(i)(j).bits.fuType) 583 memScheduler.io.memAddrIssueResp(i)(j).bits.fuType := toMem(i)(j).bits.fuType 584 memScheduler.io.memAddrIssueResp(i)(j).bits.robIdx := toMem(i)(j).bits.robIdx 585 memScheduler.io.memAddrIssueResp(i)(j).bits.sqIdx.foreach(_ := toMem(i)(j).bits.sqIdx.get) 586 memScheduler.io.memAddrIssueResp(i)(j).bits.lqIdx.foreach(_ := toMem(i)(j).bits.lqIdx.get) 587 memScheduler.io.memAddrIssueResp(i)(j).bits.resp := RespType.success // for load inst, firing at toMem means issuing successfully 588 } 589 590 if (memScheduler.io.vecLoadIssueResp(i).nonEmpty && memExuBlocksHasVecLoad(i)(j)) { 591 memScheduler.io.vecLoadIssueResp(i)(j) match { 592 case resp => 593 resp.valid := toMem(i)(j).fire && VlduType.isVecLd(toMem(i)(j).bits.fuOpType) 594 resp.bits.fuType := toMem(i)(j).bits.fuType 595 resp.bits.robIdx := toMem(i)(j).bits.robIdx 596 resp.bits.uopIdx.get := toMem(i)(j).bits.vpu.get.vuopIdx 597 resp.bits.sqIdx.get := toMem(i)(j).bits.sqIdx.get 598 resp.bits.lqIdx.get := toMem(i)(j).bits.lqIdx.get 599 resp.bits.resp := RespType.success 600 } 601 if (backendParams.debugEn){ 602 dontTouch(memScheduler.io.vecLoadIssueResp(i)(j)) 603 } 604 } 605 } 606 } 607 608 io.mem.redirect := ctrlBlock.io.redirect 609 io.mem.issueUops.zip(toMem.flatten).foreach { case (sink, source) => 610 val enableMdp = Constantin.createRecord("EnableMdp", true) 611 sink.valid := source.valid 612 source.ready := sink.ready 613 sink.bits.iqIdx := source.bits.iqIdx 614 sink.bits.isFirstIssue := source.bits.isFirstIssue 615 sink.bits.uop := 0.U.asTypeOf(sink.bits.uop) 616 sink.bits.src := 0.U.asTypeOf(sink.bits.src) 617 sink.bits.src.zip(source.bits.src).foreach { case (l, r) => l := r} 618 sink.bits.uop.fuType := source.bits.fuType 619 sink.bits.uop.fuOpType := source.bits.fuOpType 620 sink.bits.uop.imm := source.bits.imm 621 sink.bits.uop.robIdx := source.bits.robIdx 622 sink.bits.uop.pdest := source.bits.pdest 623 sink.bits.uop.rfWen := source.bits.rfWen.getOrElse(false.B) 624 sink.bits.uop.fpWen := source.bits.fpWen.getOrElse(false.B) 625 sink.bits.uop.vecWen := source.bits.vecWen.getOrElse(false.B) 626 sink.bits.uop.v0Wen := source.bits.v0Wen.getOrElse(false.B) 627 sink.bits.uop.vlWen := source.bits.vlWen.getOrElse(false.B) 628 sink.bits.uop.flushPipe := source.bits.flushPipe.getOrElse(false.B) 629 sink.bits.uop.pc := source.bits.pc.getOrElse(0.U) 630 sink.bits.uop.loadWaitBit := Mux(enableMdp, source.bits.loadWaitBit.getOrElse(false.B), false.B) 631 sink.bits.uop.waitForRobIdx := Mux(enableMdp, source.bits.waitForRobIdx.getOrElse(0.U.asTypeOf(new RobPtr)), 0.U.asTypeOf(new RobPtr)) 632 sink.bits.uop.storeSetHit := Mux(enableMdp, source.bits.storeSetHit.getOrElse(false.B), false.B) 633 sink.bits.uop.loadWaitStrict := Mux(enableMdp, source.bits.loadWaitStrict.getOrElse(false.B), false.B) 634 sink.bits.uop.ssid := Mux(enableMdp, source.bits.ssid.getOrElse(0.U(SSIDWidth.W)), 0.U(SSIDWidth.W)) 635 sink.bits.uop.lqIdx := source.bits.lqIdx.getOrElse(0.U.asTypeOf(new LqPtr)) 636 sink.bits.uop.sqIdx := source.bits.sqIdx.getOrElse(0.U.asTypeOf(new SqPtr)) 637 sink.bits.uop.ftqPtr := source.bits.ftqIdx.getOrElse(0.U.asTypeOf(new FtqPtr)) 638 sink.bits.uop.ftqOffset := source.bits.ftqOffset.getOrElse(0.U) 639 sink.bits.uop.debugInfo := source.bits.perfDebugInfo 640 sink.bits.uop.vpu := source.bits.vpu.getOrElse(0.U.asTypeOf(new VPUCtrlSignals)) 641 sink.bits.uop.preDecodeInfo := source.bits.preDecode.getOrElse(0.U.asTypeOf(new PreDecodeInfo)) 642 sink.bits.uop.numLsElem := source.bits.numLsElem.getOrElse(0.U) // Todo: remove this bundle, keep only the one below 643 sink.bits.flowNum.foreach(_ := source.bits.numLsElem.get) 644 } 645 io.mem.loadFastMatch := memScheduler.io.toMem.get.loadFastMatch.map(_.fastMatch) 646 io.mem.loadFastImm := memScheduler.io.toMem.get.loadFastMatch.map(_.fastImm) 647 io.mem.tlbCsr := csrio.tlb 648 io.mem.csrCtrl := csrio.customCtrl 649 io.mem.sfence := fenceio.sfence 650 io.mem.isStoreException := CommitType.lsInstIsStore(ctrlBlock.io.robio.exception.bits.commitType) 651 io.mem.isVlsException := ctrlBlock.io.robio.exception.bits.vls 652 require(io.mem.loadPcRead.size == params.LduCnt) 653 io.mem.loadPcRead.zipWithIndex.foreach { case (loadPcRead, i) => 654 loadPcRead := ctrlBlock.io.memLdPcRead(i).data 655 ctrlBlock.io.memLdPcRead(i).valid := io.mem.issueLda(i).valid 656 ctrlBlock.io.memLdPcRead(i).ptr := io.mem.issueLda(i).bits.uop.ftqPtr 657 ctrlBlock.io.memLdPcRead(i).offset := io.mem.issueLda(i).bits.uop.ftqOffset 658 } 659 660 io.mem.storePcRead.zipWithIndex.foreach { case (storePcRead, i) => 661 storePcRead := ctrlBlock.io.memStPcRead(i).data 662 ctrlBlock.io.memStPcRead(i).valid := io.mem.issueSta(i).valid 663 ctrlBlock.io.memStPcRead(i).ptr := io.mem.issueSta(i).bits.uop.ftqPtr 664 ctrlBlock.io.memStPcRead(i).offset := io.mem.issueSta(i).bits.uop.ftqOffset 665 } 666 667 io.mem.hyuPcRead.zipWithIndex.foreach( { case (hyuPcRead, i) => 668 hyuPcRead := ctrlBlock.io.memHyPcRead(i).data 669 ctrlBlock.io.memHyPcRead(i).valid := io.mem.issueHylda(i).valid 670 ctrlBlock.io.memHyPcRead(i).ptr := io.mem.issueHylda(i).bits.uop.ftqPtr 671 ctrlBlock.io.memHyPcRead(i).offset := io.mem.issueHylda(i).bits.uop.ftqOffset 672 }) 673 674 ctrlBlock.io.robio.robHeadLsIssue := io.mem.issueUops.map(deq => deq.fire && deq.bits.uop.robIdx === ctrlBlock.io.robio.robDeqPtr).reduce(_ || _) 675 676 // mem io 677 io.mem.lsqEnqIO <> memScheduler.io.memIO.get.lsqEnqIO 678 io.mem.robLsqIO <> ctrlBlock.io.robio.lsq 679 680 io.frontendSfence := fenceio.sfence 681 io.frontendTlbCsr := csrio.tlb 682 io.frontendCsrCtrl := csrio.customCtrl 683 684 io.tlb <> csrio.tlb 685 686 io.csrCustomCtrl := csrio.customCtrl 687 688 io.toTop.cpuHalted := false.B // TODO: implement cpu halt 689 690 io.debugTopDown.fromRob := ctrlBlock.io.debugTopDown.fromRob 691 ctrlBlock.io.debugTopDown.fromCore := io.debugTopDown.fromCore 692 693 io.debugRolling := ctrlBlock.io.debugRolling 694 695 if(backendParams.debugEn) { 696 dontTouch(memScheduler.io) 697 dontTouch(dataPath.io.toMemExu) 698 dontTouch(wbDataPath.io.fromMemExu) 699 } 700 701 // reset tree 702 if (p(DebugOptionsKey).ResetGen) { 703 val rightResetTree = ResetGenNode(Seq( 704 ModuleNode(dataPath), 705 ModuleNode(intExuBlock), 706 ModuleNode(fpExuBlock), 707 ModuleNode(vfExuBlock), 708 ModuleNode(bypassNetwork), 709 ModuleNode(wbDataPath) 710 )) 711 val leftResetTree = ResetGenNode(Seq( 712 ModuleNode(pcTargetMem), 713 ModuleNode(intScheduler), 714 ModuleNode(fpScheduler), 715 ModuleNode(vfScheduler), 716 ModuleNode(memScheduler), 717 ModuleNode(og2ForVector), 718 ModuleNode(wbFuBusyTable), 719 ResetGenNode(Seq( 720 ModuleNode(ctrlBlock), 721 ResetGenNode(Seq( 722 CellNode(io.frontendReset) 723 )) 724 )) 725 )) 726 ResetGen(leftResetTree, reset, sim = false) 727 ResetGen(rightResetTree, reset, sim = false) 728 } else { 729 io.frontendReset := DontCare 730 } 731 732 // perf events 733 val pfevent = Module(new PFEvent) 734 pfevent.io.distribute_csr := RegNext(csrio.customCtrl.distribute_csr) 735 val csrevents = pfevent.io.hpmevent.slice(8,16) 736 737 val ctrlBlockPerf = ctrlBlock.getPerfEvents 738 val intSchedulerPerf = intScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 739 val fpSchedulerPerf = fpScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 740 val vecSchedulerPerf = vfScheduler.asInstanceOf[SchedulerArithImp].getPerfEvents 741 val memSchedulerPerf = memScheduler.asInstanceOf[SchedulerMemImp].getPerfEvents 742 743 val perfBackend = Seq() 744 // let index = 0 be no event 745 val allPerfEvents = Seq(("noEvent", 0.U)) ++ ctrlBlockPerf ++ intSchedulerPerf ++ fpSchedulerPerf ++ vecSchedulerPerf ++ memSchedulerPerf ++ perfBackend 746 747 748 if (printEventCoding) { 749 for (((name, inc), i) <- allPerfEvents.zipWithIndex) { 750 println("backend perfEvents Set", name, inc, i) 751 } 752 } 753 754 val allPerfInc = allPerfEvents.map(_._2.asTypeOf(new PerfEvent)) 755 val perfEvents = HPerfMonitor(csrevents, allPerfInc).getPerfEvents 756 csrio.perf.perfEventsBackend := VecInit(perfEvents.map(_._2.asTypeOf(new PerfEvent))) 757 generatePerfEvent() 758} 759 760class BackendMemIO(implicit p: Parameters, params: BackendParams) extends XSBundle { 761 // Since fast load replay always use load unit 0, Backend flips two load port to avoid conflicts 762 val flippedLda = true 763 // params alias 764 private val LoadQueueSize = VirtualLoadQueueSize 765 // In/Out // Todo: split it into one-direction bundle 766 val lsqEnqIO = Flipped(new LsqEnqIO) 767 val robLsqIO = new RobLsqIO 768 val ldaIqFeedback = Vec(params.LduCnt, Flipped(new MemRSFeedbackIO)) 769 val staIqFeedback = Vec(params.StaCnt, Flipped(new MemRSFeedbackIO)) 770 val hyuIqFeedback = Vec(params.HyuCnt, Flipped(new MemRSFeedbackIO)) 771 val vstuIqFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true))) 772 val vlduIqFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true))) 773 val ldCancel = Vec(params.LdExuCnt, Input(new LoadCancelIO)) 774 val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst))) 775 val loadPcRead = Vec(params.LduCnt, Output(UInt(VAddrBits.W))) 776 val storePcRead = Vec(params.StaCnt, Output(UInt(VAddrBits.W))) 777 val hyuPcRead = Vec(params.HyuCnt, Output(UInt(VAddrBits.W))) 778 // Input 779 val writebackLda = Vec(params.LduCnt, Flipped(DecoupledIO(new MemExuOutput))) 780 val writebackSta = Vec(params.StaCnt, Flipped(DecoupledIO(new MemExuOutput))) 781 val writebackStd = Vec(params.StdCnt, Flipped(DecoupledIO(new MemExuOutput))) 782 val writebackHyuLda = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput))) 783 val writebackHyuSta = Vec(params.HyuCnt, Flipped(DecoupledIO(new MemExuOutput))) 784 val writebackVldu = Vec(params.VlduCnt, Flipped(DecoupledIO(new MemExuOutput(true)))) 785 786 val s3_delayed_load_error = Input(Vec(LoadPipelineWidth, Bool())) 787 val stIn = Input(Vec(params.StaExuCnt, ValidIO(new DynInst()))) 788 val memoryViolation = Flipped(ValidIO(new Redirect)) 789 val exceptionAddr = Input(new Bundle { 790 val vaddr = UInt(VAddrBits.W) 791 val gpaddr = UInt(GPAddrBits.W) 792 }) 793 val sqDeq = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) 794 val lqDeq = Input(UInt(log2Up(CommitWidth + 1).W)) 795 val sqDeqPtr = Input(new SqPtr) 796 val lqDeqPtr = Input(new LqPtr) 797 798 val lqCancelCnt = Input(UInt(log2Up(VirtualLoadQueueSize + 1).W)) 799 val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W)) 800 801 val lqCanAccept = Input(Bool()) 802 val sqCanAccept = Input(Bool()) 803 804 val otherFastWakeup = Flipped(Vec(params.LduCnt + params.HyuCnt, ValidIO(new DynInst))) 805 val stIssuePtr = Input(new SqPtr()) 806 807 val debugLS = Flipped(Output(new DebugLSIO)) 808 809 val lsTopdownInfo = Vec(params.LduCnt + params.HyuCnt, Flipped(Output(new LsTopdownInfo))) 810 // Output 811 val redirect = ValidIO(new Redirect) // rob flush MemBlock 812 val issueLda = MixedVec(Seq.fill(params.LduCnt)(DecoupledIO(new MemExuInput()))) 813 val issueSta = MixedVec(Seq.fill(params.StaCnt)(DecoupledIO(new MemExuInput()))) 814 val issueStd = MixedVec(Seq.fill(params.StdCnt)(DecoupledIO(new MemExuInput()))) 815 val issueHylda = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput()))) 816 val issueHysta = MixedVec(Seq.fill(params.HyuCnt)(DecoupledIO(new MemExuInput()))) 817 val issueVldu = MixedVec(Seq.fill(params.VlduCnt)(DecoupledIO(new MemExuInput(true)))) 818 819 val loadFastMatch = Vec(params.LduCnt, Output(UInt(params.LduCnt.W))) 820 val loadFastImm = Vec(params.LduCnt, Output(UInt(12.W))) // Imm_I 821 822 val tlbCsr = Output(new TlbCsrBundle) 823 val csrCtrl = Output(new CustomCSRCtrlIO) 824 val sfence = Output(new SfenceBundle) 825 val isStoreException = Output(Bool()) 826 val isVlsException = Output(Bool()) 827 828 // ATTENTION: The issue ports' sequence order should be the same as IQs' deq config 829 private [backend] def issueUops: Seq[DecoupledIO[MemExuInput]] = { 830 issueSta ++ 831 issueHylda ++ issueHysta ++ 832 issueLda ++ 833 issueVldu ++ 834 issueStd 835 }.toSeq 836 837 // ATTENTION: The writeback ports' sequence order should be the same as IQs' deq config 838 private [backend] def writeBack: Seq[DecoupledIO[MemExuOutput]] = { 839 writebackSta ++ 840 writebackHyuLda ++ writebackHyuSta ++ 841 writebackLda ++ 842 writebackVldu ++ 843 writebackStd 844 } 845} 846 847class TopToBackendBundle(implicit p: Parameters) extends XSBundle { 848 val hartId = Output(UInt(hartIdLen.W)) 849 val externalInterrupt = Output(new ExternalInterruptIO) 850 val msiInfo = Output(ValidIO(new MsiInfoBundle)) 851 val clintTime = Output(ValidIO(UInt(64.W))) 852} 853 854class BackendToTopBundle extends Bundle { 855 val cpuHalted = Output(Bool()) 856} 857 858class BackendIO(implicit p: Parameters, params: BackendParams) extends XSBundle with HasSoCParameter { 859 val fromTop = Flipped(new TopToBackendBundle) 860 861 val toTop = new BackendToTopBundle 862 863 val fenceio = new FenceIO 864 // Todo: merge these bundles into BackendFrontendIO 865 val frontend = Flipped(new FrontendToCtrlIO) 866 val frontendSfence = Output(new SfenceBundle) 867 val frontendCsrCtrl = Output(new CustomCSRCtrlIO) 868 val frontendTlbCsr = Output(new TlbCsrBundle) 869 val frontendReset = Output(Reset()) 870 871 val mem = new BackendMemIO 872 873 val perf = Input(new PerfCounterIO) 874 875 val tlb = Output(new TlbCsrBundle) 876 877 val csrCustomCtrl = Output(new CustomCSRCtrlIO) 878 879 val debugTopDown = new Bundle { 880 val fromRob = new RobCoreTopDownIO 881 val fromCore = new CoreDispatchTopDownIO 882 } 883 val debugRolling = new RobDebugRollingIO 884} 885