1package xiangshan.backend 2 3import bus.simplebus.SimpleBusUC 4import chisel3._ 5import chisel3.util._ 6import chisel3.util.experimental.BoringUtils 7import noop.MemMMUIO 8import xiangshan._ 9import xiangshan.backend.decode.{DecodeBuffer, DecodeStage} 10import xiangshan.backend.rename.Rename 11import xiangshan.backend.brq.Brq 12import xiangshan.backend.dispatch.Dispatch 13import xiangshan.backend.exu._ 14import xiangshan.backend.fu.FunctionUnit 15import xiangshan.backend.issue.IssueQueue 16import xiangshan.backend.regfile.{Regfile, RfWritePort} 17import xiangshan.backend.roq.Roq 18 19 20/** Backend Pipeline: 21 * Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe 22 */ 23class Backend(implicit val p: XSConfig) extends XSModule 24 with HasExeUnits 25 with NeedImpl { 26 val io = IO(new Bundle { 27 val dmem = new SimpleBusUC(addrBits = VAddrBits) 28 val memMMU = Flipped(new MemMMUIO) 29 val frontend = Flipped(new FrontendToBackendIO) 30 }) 31 32 33 val decode = Module(new DecodeStage) 34 val brq = Module(new Brq) 35 val decBuf = Module(new DecodeBuffer) 36 val rename = Module(new Rename) 37 val dispatch = Module(new Dispatch(exeUnits.map(_.config))) 38 val roq = Module(new Roq) 39 val intRf = Module(new Regfile( 40 numReadPorts = NRReadPorts, 41 numWirtePorts = NRWritePorts, 42 hasZero = true 43 )) 44 val fpRf = Module(new Regfile( 45 numReadPorts = NRReadPorts, 46 numWirtePorts = NRWritePorts, 47 hasZero = false 48 )) 49 50 // backend redirect, flush pipeline 51 val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect) 52 53 val redirectInfo = Wire(new RedirectInfo) 54 // exception or misprediction 55 redirectInfo.valid := roq.io.redirect.valid || brq.io.out.valid 56 redirectInfo.misPred := !roq.io.redirect.valid && brq.io.redirect.valid 57 redirectInfo.redirect := redirect.bits 58 59 val issueQueues = exeUnits.zipWithIndex.map({ case (eu, i) => 60 def needBypass(cfg: ExuConfig): Boolean = cfg.enableBypass 61 62 val bypassCnt = if(eu.config.enableBypass) exeUnits.map(_.config).count(needBypass) else 0 63 def needWakeup(cfg: ExuConfig): Boolean = 64 (cfg.readIntRf && cfg.writeIntRf) || (cfg.readFpRf && cfg.writeFpRf) 65 66 val wakeupCnt = exeUnits.map(_.config).count(needWakeup) 67 assert(!(needBypass(eu.config) && !needWakeup(eu.config))) // needBypass but dont needWakeup is not allowed 68 val iq = Module(new IssueQueue( 69 eu.config, 70 wakeupCnt, 71 bypassCnt, 72 fifo = eu.config.supportedFuncUnits.contains(FunctionUnit.lsuCfg) 73 )) 74 iq.io.redirect <> redirect 75 iq.io.numExist <> dispatch.io.numExist(i) 76 iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i) 77 iq.io.enqData <> dispatch.io.enqIQData(i) 78 val wuUnitsOut = exeUnits.filter(e => needWakeup(e.config)).map(_.io.out) 79 for (i <- iq.io.wakeUpPorts.indices) { 80 iq.io.wakeUpPorts(i).bits <> wuUnitsOut(i).bits 81 iq.io.wakeUpPorts(i).valid := wuUnitsOut(i).valid 82 } 83 println( 84 s"[$i] ${eu.name} Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt" + 85 s" Supported Function:[" + 86 s"${ 87 eu.config.supportedFuncUnits.map( 88 fu => FuType.functionNameMap(fu.fuType.litValue())).mkString(", " 89 ) 90 }]" 91 ) 92 eu.io.in <> iq.io.deq 93 eu.io.redirect <> redirect 94 iq 95 }) 96 97 val bypassQueues = issueQueues.filter(_.bypassCnt > 0) 98 val bypassUnits = exeUnits.filter(_.config.enableBypass) 99 bypassQueues.foreach(iq => { 100 for (i <- iq.io.bypassUops.indices) { 101 iq.io.bypassData(i).bits := bypassUnits(i).io.out.bits 102 iq.io.bypassData(i).valid := bypassUnits(i).io.out.valid 103 } 104 iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop) 105 }) 106 107 lsuExeUnits.foreach(_.io.dmem <> io.dmem) 108 lsuExeUnits.foreach(_.io.scommit <> roq.io.scommit) 109 110 io.frontend.redirectInfo <> redirectInfo 111 io.frontend.commits <> roq.io.commits 112 113 decode.io.in <> io.frontend.cfVec 114 brq.io.roqRedirect <> roq.io.redirect 115 brq.io.enqReqs <> decode.io.toBrq 116 for ((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.config.hasRedirect))) { 117 x.bits := y.io.out.bits 118 x.valid := y.io.out.fire() && y.io.out.bits.redirectValid 119 } 120 decode.io.brTags <> brq.io.brTags 121 decBuf.io.redirect <> redirect 122 decBuf.io.in <> decode.io.out 123 124 rename.io.redirect <> redirect 125 rename.io.roqCommits <> roq.io.commits 126 rename.io.in <> decBuf.io.out 127 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) 128 rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr) 129 rename.io.intPregRdy <> dispatch.io.intPregRdy 130 rename.io.fpPregRdy <> dispatch.io.fpPregRdy 131 132 dispatch.io.redirect <> redirect 133 dispatch.io.fromRename <> rename.io.out 134 135 roq.io.brqRedirect <> brq.io.redirect 136 roq.io.dp1Req <> dispatch.io.toRoq 137 dispatch.io.roqIdxs <> roq.io.roqIdxs 138 dispatch.io.roqIsEmpty := roq.io.roqIsEmpty 139 dispatch.io.isNoSpecExecCommit := roq.io.commits.head.valid 140 141 intRf.io.readPorts <> dispatch.io.readIntRf 142 fpRf.io.readPorts <> dispatch.io.readFpRf 143 144 val exeWbReqs = exeUnits.map(_.io.out) 145 146 val wbIntIdx = exeUnits.zipWithIndex.filter(_._1.config.writeIntRf).map(_._2) 147 val wbFpIdx = exeUnits.zipWithIndex.filter(_._1.config.writeFpRf).map(_._2) 148 149 val wbu = Module(new Wbu(wbIntIdx, wbFpIdx)) 150 wbu.io.in <> exeWbReqs 151 152 val wbIntResults = wbu.io.toIntRf 153 val wbFpResults = wbu.io.toFpRf 154 155 def exuOutToRfWrite(x: Valid[ExuOutput]): RfWritePort = { 156 val rfWrite = Wire(new RfWritePort) 157 rfWrite.wen := x.valid 158 rfWrite.addr := x.bits.uop.pdest 159 rfWrite.data := x.bits.data 160 rfWrite 161 } 162 163 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 164 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 165 166 rename.io.wbIntResults <> wbIntResults 167 rename.io.wbFpResults <> wbFpResults 168 169 roq.io.exeWbResults.take(exeWbReqs.length).zip(wbu.io.toRoq).foreach(x => x._1 := x._2) 170 roq.io.exeWbResults.last := brq.io.out 171 172 173 // TODO: Remove sink and source 174 val tmp = WireInit(0.U) 175 val sinks = Array[String]( 176 "DTLBFINISH", 177 "DTLBPF", 178 "DTLBENABLE", 179 "perfCntCondMdcacheLoss", 180 "perfCntCondMl2cacheLoss", 181 "perfCntCondMdcacheHit", 182 "lsuMMIO", 183 "perfCntCondMl2cacheHit", 184 "perfCntCondMl2cacheReq", 185 "mtip", 186 "perfCntCondMdcacheReq", 187 "meip" 188 ) 189 for (s <- sinks) { 190 BoringUtils.addSink(tmp, s) 191 } 192 193 val debugIntReg, debugFpReg = WireInit(VecInit(Seq.fill(32)(0.U(XLEN.W)))) 194 BoringUtils.addSink(debugIntReg, "DEBUG_INT_ARCH_REG") 195 BoringUtils.addSink(debugFpReg, "DEBUG_FP_ARCH_REG") 196 val debugArchReg = WireInit(VecInit(debugIntReg ++ debugFpReg)) 197 if (!p.FPGAPlatform) { 198 BoringUtils.addSource(debugArchReg, "difftestRegs") 199 } 200 201} 202