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 18import xiangshan.mem._ 19 20 21/** Backend Pipeline: 22 * Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe 23 */ 24class Backend(implicit val p: XSConfig) extends XSModule 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 val mem = Flipped(new MemToBackendIO) 31 }) 32 33 34 val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit)) 35 val jmpExeUnit = Module(new JmpExeUnit) 36 val mulExeUnits = Array.tabulate(exuParameters.MulCnt)(_ => Module(new MulExeUnit)) 37 val mduExeUnits = Array.tabulate(exuParameters.MduCnt)(_ => Module(new MulDivExeUnit)) 38 // val fmacExeUnits = Array.tabulate(exuParameters.FmacCnt)(_ => Module(new Fmac)) 39 // val fmiscExeUnits = Array.tabulate(exuParameters.FmiscCnt)(_ => Module(new Fmisc)) 40 // val fmiscDivSqrtExeUnits = Array.tabulate(exuParameters.FmiscDivSqrtCnt)(_ => Module(new FmiscDivSqrt)) 41 val lsuExeUnits = Array.tabulate(exuParameters.StuCnt)(_ => Module(new LsExeUnit)) 42 val exeUnits = jmpExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits ++ lsuExeUnits) 43 exeUnits.foreach(_.io.exception := DontCare) 44 exeUnits.foreach(_.io.dmem := DontCare) 45 exeUnits.foreach(_.io.mcommit := DontCare) 46 47 val decode = Module(new DecodeStage) 48 val brq = Module(new Brq) 49 val decBuf = Module(new DecodeBuffer) 50 val rename = Module(new Rename) 51 val dispatch = Module(new Dispatch(exeUnits.map(_.config))) 52 val roq = Module(new Roq) 53 val intRf = Module(new Regfile( 54 numReadPorts = NRReadPorts, 55 numWirtePorts = NRWritePorts, 56 hasZero = true 57 )) 58 val fpRf = Module(new Regfile( 59 numReadPorts = NRReadPorts, 60 numWirtePorts = NRWritePorts, 61 hasZero = false 62 )) 63 64 // backend redirect, flush pipeline 65 val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect) 66 67 val redirectInfo = Wire(new RedirectInfo) 68 // exception or misprediction 69 redirectInfo.valid := roq.io.redirect.valid || brq.io.out.valid 70 redirectInfo.misPred := !roq.io.redirect.valid && brq.io.redirect.valid 71 redirectInfo.redirect := redirect.bits 72 73 var iqInfo = new StringBuilder 74 val issueQueues = exeUnits.zipWithIndex.map({ case (eu, i) => 75 def needBypass(cfg: ExuConfig): Boolean = cfg.enableBypass 76 77 val bypassCnt = exeUnits.map(_.config).count(needBypass) 78 def needWakeup(cfg: ExuConfig): Boolean = 79 (cfg.readIntRf && cfg.writeIntRf) || (cfg.readFpRf && cfg.writeFpRf) 80 81 val wakeupCnt = exeUnits.map(_.config).count(needWakeup) 82 assert(!(needBypass(eu.config) && !needWakeup(eu.config))) // needBypass but dont needWakeup is not allowed 83 val iq = Module(new IssueQueue( 84 eu.config, 85 wakeupCnt, 86 bypassCnt, 87 eu.config.enableBypass, 88 fifo = eu.config.supportedFuncUnits.contains(FunctionUnit.lsuCfg) 89 )) 90 iq.io.redirect <> redirect 91 iq.io.numExist <> dispatch.io.numExist(i) 92 iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i) 93 iq.io.enqData <> dispatch.io.enqIQData(i) 94 for( 95 (wakeUpPort, exuOut) <- 96 iq.io.wakeUpPorts.zip(exeUnits.filter(e => needWakeup(e.config)).map(_.io.out)) 97 ){ 98 wakeUpPort.bits := exuOut.bits 99 wakeUpPort.valid := exuOut.valid 100 } 101 iqInfo ++= { 102 s"[$i] ${eu.name} Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt" + 103 s" Supported Function:[" + 104 s"${ 105 eu.config.supportedFuncUnits.map( 106 fu => FuType.functionNameMap(fu.fuType.litValue())).mkString(", " 107 ) 108 }]\n" 109 } 110 eu.io.in <> iq.io.deq 111 eu.io.redirect <> redirect 112 iq 113 }) 114 115 val bypassQueues = issueQueues.filter(_.enableBypass) 116 val bypassUnits = exeUnits.filter(_.config.enableBypass) 117 issueQueues.foreach(iq => { 118 for (i <- iq.io.bypassUops.indices) { 119 iq.io.bypassData(i).bits := bypassUnits(i).io.out.bits 120 iq.io.bypassData(i).valid := bypassUnits(i).io.out.valid 121 } 122 iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop) 123 }) 124 125 lsuExeUnits.foreach(_.io.dmem <> DontCare) // TODO 126 lsuExeUnits.foreach(_.io.mcommit <> roq.io.mcommit) 127 io.mem.mcommit := roq.io.mcommit 128 io.mem.ldin := DontCare // TODO 129 io.mem.stin := DontCare // TODO 130 jmpExeUnit.io.exception.valid := roq.io.redirect.valid 131 jmpExeUnit.io.exception.bits := roq.io.exception 132 133 io.frontend.redirectInfo <> redirectInfo 134 io.frontend.inOrderBrInfo <> brq.io.inOrderBrInfo 135 136 decode.io.in <> io.frontend.cfVec 137 brq.io.roqRedirect <> roq.io.redirect 138 brq.io.bcommit := roq.io.bcommit 139 brq.io.enqReqs <> decode.io.toBrq 140 for ((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.config.hasRedirect))) { 141 x.bits := y.io.out.bits 142 x.valid := y.io.out.fire() && y.io.out.bits.redirectValid 143 } 144 decode.io.brTags <> brq.io.brTags 145 decBuf.io.redirect <> redirect 146 decBuf.io.in <> decode.io.out 147 148 rename.io.redirect <> redirect 149 rename.io.roqCommits <> roq.io.commits 150 rename.io.in <> decBuf.io.out 151 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) 152 rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr) 153 rename.io.intPregRdy <> dispatch.io.intPregRdy 154 rename.io.fpPregRdy <> dispatch.io.fpPregRdy 155 156 dispatch.io.redirect <> redirect 157 dispatch.io.fromRename <> rename.io.out 158 159 roq.io.brqRedirect <> brq.io.redirect 160 roq.io.dp1Req <> dispatch.io.toRoq 161 dispatch.io.roqIdxs <> roq.io.roqIdxs 162 io.mem.dp1Req <> dispatch.io.toMoq 163 dispatch.io.moqIdxs <> io.mem.moqIdxs 164 165 intRf.io.readPorts <> dispatch.io.readIntRf 166 fpRf.io.readPorts <> dispatch.io.readFpRf 167 168 val exeWbReqs = exeUnits.map(_.io.out) 169 170 val wbIntIdx = exeUnits.zipWithIndex.filter(_._1.config.writeIntRf).map(_._2) 171 val wbFpIdx = exeUnits.zipWithIndex.filter(_._1.config.writeFpRf).map(_._2) 172 173 val wbu = Module(new Wbu(wbIntIdx, wbFpIdx)) 174 wbu.io.in <> exeWbReqs 175 176 val wbIntResults = wbu.io.toIntRf 177 val wbFpResults = wbu.io.toFpRf 178 179 def exuOutToRfWrite(x: Valid[ExuOutput]): RfWritePort = { 180 val rfWrite = Wire(new RfWritePort) 181 rfWrite.wen := x.valid 182 rfWrite.addr := x.bits.uop.pdest 183 rfWrite.data := x.bits.data 184 rfWrite 185 } 186 187 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 188 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 189 190 rename.io.wbIntResults <> wbIntResults 191 rename.io.wbFpResults <> wbFpResults 192 193 roq.io.exeWbResults.take(exeWbReqs.length).zip(wbu.io.toRoq).foreach(x => x._1 := x._2) 194 roq.io.exeWbResults.last := brq.io.out 195 196 197 // TODO: Remove sink and source 198 val tmp = WireInit(0.U) 199 val sinks = Array[String]( 200 "DTLBFINISH", 201 "DTLBPF", 202 "DTLBENABLE", 203 "perfCntCondMdcacheLoss", 204 "perfCntCondMl2cacheLoss", 205 "perfCntCondMdcacheHit", 206 "lsuMMIO", 207 "perfCntCondMl2cacheHit", 208 "perfCntCondMl2cacheReq", 209 "mtip", 210 "perfCntCondMdcacheReq", 211 "meip" 212 ) 213 for (s <- sinks) { 214 BoringUtils.addSink(tmp, s) 215 } 216 217 val debugIntReg, debugFpReg = WireInit(VecInit(Seq.fill(32)(0.U(XLEN.W)))) 218 BoringUtils.addSink(debugIntReg, "DEBUG_INT_ARCH_REG") 219 BoringUtils.addSink(debugFpReg, "DEBUG_FP_ARCH_REG") 220 val debugArchReg = WireInit(VecInit(debugIntReg ++ debugFpReg)) 221 if (!p.FPGAPlatform) { 222 BoringUtils.addSource(debugArchReg, "difftestRegs") 223 } 224 225 print(iqInfo) 226 227} 228