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 <> dispatch2.io.enqIQCtrl(i) 59 iq.io.enqData <> dispatch2.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.in <> decode.io.out 101 102 rename.io.redirect <> redirect 103 rename.io.roqCommits <> roq.io.commits 104 rename.io.in <> decBuf.io.out 105 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) 106 rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr) 107 rename.io.intPregRdy <> dispatch.io.intPregRdy 108 rename.io.fpPregRdy <> dispatch.io.fpPregRdy 109 110 dispatch.io.redirect <> redirect 111 dispatch.io.fromRename <> rename.io.out 112 113 roq.io.brqRedirect <> brq.io.redirect 114 roq.io.dp1Req <> dispatch.io.toRoq 115 dispatch.io.roqIdxs <> roq.io.roqIdxs 116 117 intRf.io.readPorts <> dispatch.io.readIntRf 118 fpRf.io.readPorts <> dispatch.io.readFpRf 119 120 val exeWbReqs = exeUnits.map(_.io.out) 121 val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out) 122 val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out) 123 val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts)) 124 val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts)) 125 val wbIntResults = intWbArb.io.out 126 val wbFpResults = fpWbArb.io.out 127 128 def exuOutToRfWrite(x: Valid[ExuOutput]) = { 129 val rfWrite = Wire(new RfWritePort) 130 rfWrite.wen := x.valid 131 rfWrite.addr := x.bits.uop.pdest 132 rfWrite.data := x.bits.data 133 rfWrite 134 } 135 136 intWbArb.io.in <> wbIntReqs 137 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 138 139 fpWbArb.io.in <> wbFpReqs 140 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 141 142 rename.io.wbIntResults <> wbIntResults 143 rename.io.wbFpResults <> wbFpResults 144 145 roq.io.exeWbResults.zip(exeWbReqs).foreach({case (x,y) => { 146 x.bits := y.bits 147 x.valid := y.fire() 148 }}) 149 150 151 // TODO: Remove sink and source 152 val tmp = WireInit(0.U) 153 val sinks = Array[String]( 154 "DTLBFINISH", 155 "DTLBPF", 156 "DTLBENABLE", 157 "perfCntCondMdcacheLoss", 158 "perfCntCondMl2cacheLoss", 159 "perfCntCondMdcacheHit", 160 "lsuMMIO", 161 "perfCntCondMl2cacheHit", 162 "perfCntCondMl2cacheReq", 163 "mtip", 164 "perfCntCondMdcacheReq", 165 "meip" 166 ) 167 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 168 169 // A fake commit 170 // TODO: difftest 6 insts per cycle 171 val commit = RegNext(RegNext(RegNext(true.B))) 172 val pc = WireInit("h80000000".U) 173 val inst = WireInit("h66666666".U) 174 175 if(!p.FPGAPlatform){ 176 BoringUtils.addSource(commit, "difftestCommit") 177 BoringUtils.addSource(pc, "difftestThisPC") 178 BoringUtils.addSource(inst, "difftestThisINST") 179 BoringUtils.addSource(tmp, "difftestIsMMIO") 180 BoringUtils.addSource(tmp, "difftestIsRVC") 181 BoringUtils.addSource(tmp, "difftestIntrNO") 182 BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs") 183 BoringUtils.addSource(tmp, "difftestMode") 184 BoringUtils.addSource(tmp, "difftestMstatus") 185 BoringUtils.addSource(tmp, "difftestSstatus") 186 BoringUtils.addSource(tmp, "difftestMepc") 187 BoringUtils.addSource(tmp, "difftestSepc") 188 BoringUtils.addSource(tmp, "difftestMcause") 189 BoringUtils.addSource(tmp, "difftestScause") 190 } 191 192} 193