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)).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 // A fake commit 171 // TODO: difftest 6 insts per cycle 172 val commit = RegNext(RegNext(RegNext(true.B))) 173 val pc = WireInit("h80000000".U) 174 val inst = WireInit("h66666666".U) 175 176 if(!p.FPGAPlatform){ 177 BoringUtils.addSource(commit, "difftestCommit") 178 BoringUtils.addSource(pc, "difftestThisPC") 179 BoringUtils.addSource(inst, "difftestThisINST") 180 BoringUtils.addSource(tmp, "difftestIsMMIO") 181 BoringUtils.addSource(tmp, "difftestIsRVC") 182 BoringUtils.addSource(tmp, "difftestIntrNO") 183 BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs") 184 BoringUtils.addSource(tmp, "difftestMode") 185 BoringUtils.addSource(tmp, "difftestMstatus") 186 BoringUtils.addSource(tmp, "difftestSstatus") 187 BoringUtils.addSource(tmp, "difftestMepc") 188 BoringUtils.addSource(tmp, "difftestSepc") 189 BoringUtils.addSource(tmp, "difftestMcause") 190 BoringUtils.addSource(tmp, "difftestScause") 191 } 192 193} 194