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