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 val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect) 50 val issueQueues = exeUnits.zipWithIndex.map({ case(eu, i) => 51 def needBypass(x: Exu): Boolean = (eu.enableBypass) 52 val bypassCnt = exeUnits.count(needBypass)//if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0 53 def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf) 54 val wakeupCnt = exeUnits.count(needWakeup) 55 assert(!(needBypass(eu) && !needWakeup(eu))) // needBypass but dont needWakeup is not allowed 56 val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt, eu.fixedDelay)) 57 iq.io.redirect <> redirect 58 iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i) 59 iq.io.enqData <> dispatch.io.enqIQData(i) 60 val wuUnitsOut = exeUnits.filter(e => needWakeup(e)).map(_.io.out) 61 for(i <- iq.io.wakeUpPorts.indices) { 62 iq.io.wakeUpPorts(i).bits <> wuUnitsOut(i).bits 63 iq.io.wakeUpPorts(i).valid := wuUnitsOut(i).valid 64 } 65 println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt") 66 eu.io.in <> iq.io.deq 67 eu.io.redirect <> redirect 68 iq 69 }) 70 71 val bypassQueues = issueQueues.filter(_.bypassCnt > 0) 72 val bypassUnits = exeUnits.filter(_.enableBypass) 73 bypassQueues.foreach(iq => { 74 for(i <- iq.io.bypassUops.indices) { 75 iq.io.bypassData(i).bits := bypassUnits(i).io.out.bits 76 iq.io.bypassData(i).valid := bypassUnits(i).io.out.valid 77 } 78 iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop) 79 }) 80 // val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue()) 81 // aluQueues.foreach(aluQ => { 82 // aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop) 83 // aluQ.io.bypassData <> aluExeUnits.map(_.io.out) 84 // }) 85 86 lsuExeUnits.foreach(_.io.dmem <> io.dmem) 87 88 io.frontend.redirect <> redirect 89 io.frontend.commits <> roq.io.commits 90 91 decode.io.in <> io.frontend.cfVec 92 brq.io.roqRedirect <> roq.io.redirect 93 brq.io.enqReqs <> decode.io.toBrq 94 for(i <- bjUnits.indices){ 95 brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits 96 brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire() 97 } 98 decode.io.brMasks <> brq.io.brMasks 99 decode.io.brTags <> brq.io.brTags 100 decBuf.io.redirect <> redirect 101 decBuf.io.in <> decode.io.out 102 103 rename.io.redirect <> redirect 104 rename.io.roqCommits <> roq.io.commits 105 rename.io.in <> decBuf.io.out 106 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) 107 rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr) 108 rename.io.intPregRdy <> dispatch.io.intPregRdy 109 rename.io.fpPregRdy <> dispatch.io.fpPregRdy 110 111 dispatch.io.redirect <> redirect 112 dispatch.io.fromRename <> rename.io.out 113 114 roq.io.brqRedirect <> brq.io.redirect 115 roq.io.dp1Req <> dispatch.io.toRoq 116 dispatch.io.roqIdxs <> roq.io.roqIdxs 117 118 intRf.io.readPorts <> dispatch.io.readIntRf 119 fpRf.io.readPorts <> dispatch.io.readFpRf 120 121 val exeWbReqs = exeUnits.map(_.io.out) 122 val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits ++ lsuExeUnits)).map(_.io.out) 123 val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out) 124 val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts)) 125 val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts)) 126 val wbIntResults = intWbArb.io.out 127 val wbFpResults = fpWbArb.io.out 128 129 def exuOutToRfWrite(x: Valid[ExuOutput]) = { 130 val rfWrite = Wire(new RfWritePort) 131 rfWrite.wen := x.valid 132 rfWrite.addr := x.bits.uop.pdest 133 rfWrite.data := x.bits.data 134 rfWrite 135 } 136 137 intWbArb.io.in <> wbIntReqs 138 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 139 140 fpWbArb.io.in <> wbFpReqs 141 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 142 143 rename.io.wbIntResults <> wbIntResults 144 rename.io.wbFpResults <> wbFpResults 145 146 roq.io.exeWbResults.zip(exeWbReqs).foreach({case (x,y) => { 147 x.bits := y.bits 148 x.valid := y.fire() 149 }}) 150 151 152 // TODO: Remove sink and source 153 val tmp = WireInit(0.U) 154 val sinks = Array[String]( 155 "DTLBFINISH", 156 "DTLBPF", 157 "DTLBENABLE", 158 "perfCntCondMdcacheLoss", 159 "perfCntCondMl2cacheLoss", 160 "perfCntCondMdcacheHit", 161 "lsuMMIO", 162 "perfCntCondMl2cacheHit", 163 "perfCntCondMl2cacheReq", 164 "mtip", 165 "perfCntCondMdcacheReq", 166 "meip" 167 ) 168 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 169 170} 171