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.issue.IssueQueue 15import xiangshan.backend.regfile.{Regfile, RfWritePort} 16import xiangshan.backend.roq.Roq 17 18 19/** Backend Pipeline: 20 * Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe 21 */ 22class Backend(implicit val p: XSConfig) extends XSModule 23 with HasExeUnits 24 with NeedImpl 25{ 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) 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(x: Exu): Boolean = eu.enableBypass 61 val bypassCnt = exeUnits.count(needBypass)//if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0 62 def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf) 63 val wakeupCnt = exeUnits.count(needWakeup) 64 assert(!(needBypass(eu) && !needWakeup(eu))) // needBypass but dont needWakeup is not allowed 65 val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt, eu.fixedDelay, fifo = eu.fuTypeInt == FuType.ldu.litValue())) 66 iq.io.redirect <> redirect 67 iq.io.numExist <> dispatch.io.numExist(i) 68 iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i) 69 iq.io.enqData <> dispatch.io.enqIQData(i) 70 val wuUnitsOut = exeUnits.filter(e => needWakeup(e)).map(_.io.out) 71 for(i <- iq.io.wakeUpPorts.indices) { 72 iq.io.wakeUpPorts(i).bits <> wuUnitsOut(i).bits 73 iq.io.wakeUpPorts(i).valid := wuUnitsOut(i).valid 74 } 75 println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt") 76 eu.io.in <> iq.io.deq 77 eu.io.redirect <> redirect 78 iq 79 }) 80 81 val bypassQueues = issueQueues.filter(_.bypassCnt > 0) 82 val bypassUnits = exeUnits.filter(_.enableBypass) 83 bypassQueues.foreach(iq => { 84 for(i <- iq.io.bypassUops.indices) { 85 iq.io.bypassData(i).bits := bypassUnits(i).io.out.bits 86 iq.io.bypassData(i).valid := bypassUnits(i).io.out.valid 87 } 88 iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop) 89 }) 90 // val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue()) 91 // aluQueues.foreach(aluQ => { 92 // aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop) 93 // aluQ.io.bypassData <> aluExeUnits.map(_.io.out) 94 // }) 95 96 lsuExeUnits.foreach(_.io.dmem <> io.dmem) 97 lsuExeUnits.foreach(_.io.scommit <> roq.io.scommit) 98 99 io.frontend.redirectInfo <> redirectInfo 100 io.frontend.commits <> roq.io.commits 101 102 decode.io.in <> io.frontend.cfVec 103 brq.io.roqRedirect <> roq.io.redirect 104 brq.io.enqReqs <> decode.io.toBrq 105 for((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.hasRedirect))){ 106 x.bits := y.io.out.bits 107 x.valid := y.io.out.fire() && y.io.out.bits.redirectValid 108 } 109 decode.io.brTags <> brq.io.brTags 110 decBuf.io.redirect <> redirect 111 decBuf.io.in <> decode.io.out 112 113 rename.io.redirect <> redirect 114 rename.io.roqCommits <> roq.io.commits 115 rename.io.in <> decBuf.io.out 116 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) 117 rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr) 118 rename.io.intPregRdy <> dispatch.io.intPregRdy 119 rename.io.fpPregRdy <> dispatch.io.fpPregRdy 120 121 dispatch.io.redirect <> redirect 122 dispatch.io.fromRename <> rename.io.out 123 124 roq.io.brqRedirect <> brq.io.redirect 125 roq.io.dp1Req <> dispatch.io.toRoq 126 dispatch.io.roqIdxs <> roq.io.roqIdxs 127 128 intRf.io.readPorts <> dispatch.io.readIntRf 129 fpRf.io.readPorts <> dispatch.io.readFpRf 130 131 val exeWbReqs = exeUnits.map(_.io.out) 132 133 val wbIntIdx = exeUnits.zipWithIndex.filter(_._1.writeIntRf).map(_._2) 134 val wbFpIdx = exeUnits.zipWithIndex.filter(_._1.writeFpRf).map(_._2) 135 136 val wbu = Module(new Wbu(wbIntIdx, wbFpIdx)) 137 wbu.io.in <> exeWbReqs 138 139 val wbIntResults = wbu.io.toIntRf 140 val wbFpResults = wbu.io.toFpRf 141 142 def exuOutToRfWrite(x: Valid[ExuOutput]): RfWritePort = { 143 val rfWrite = Wire(new RfWritePort) 144 rfWrite.wen := x.valid 145 rfWrite.addr := x.bits.uop.pdest 146 rfWrite.data := x.bits.data 147 rfWrite 148 } 149 150 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 151 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 152 153 rename.io.wbIntResults <> wbIntResults 154 rename.io.wbFpResults <> wbFpResults 155 156 roq.io.exeWbResults.take(exeWbReqs.length).zip(wbu.io.toRoq).foreach(x => x._1 := x._2) 157 roq.io.exeWbResults.last := brq.io.out 158 159 160 // TODO: Remove sink and source 161 val tmp = WireInit(0.U) 162 val sinks = Array[String]( 163 "DTLBFINISH", 164 "DTLBPF", 165 "DTLBENABLE", 166 "perfCntCondMdcacheLoss", 167 "perfCntCondMl2cacheLoss", 168 "perfCntCondMdcacheHit", 169 "lsuMMIO", 170 "perfCntCondMl2cacheHit", 171 "perfCntCondMl2cacheReq", 172 "mtip", 173 "perfCntCondMdcacheReq", 174 "meip" 175 ) 176 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 177 178 val debugIntReg, debugFpReg = WireInit(VecInit(Seq.fill(32)(0.U(XLEN.W)))) 179 BoringUtils.addSink(debugIntReg, "DEBUG_INT_ARCH_REG") 180 BoringUtils.addSink(debugFpReg, "DEBUG_FP_ARCH_REG") 181 val debugArchReg = WireInit(VecInit(debugIntReg ++ debugFpReg)) 182 if(!p.FPGAPlatform){ 183 BoringUtils.addSource(debugArchReg, "difftestRegs") 184 } 185 186} 187