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.{Dispatch1, Dispatch2} 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 dispatch1 = Module(new Dispatch1) 38 val roq = Module(new Roq) 39 val dispatch2 = Module(new Dispatch2) 40 val intRf = Module(new Regfile( 41 numReadPorts = NRReadPorts, 42 numWirtePorts = NRWritePorts, 43 hasZero = true 44 )) 45 val fpRf = Module(new Regfile( 46 numReadPorts = NRReadPorts, 47 numWirtePorts = NRWritePorts, 48 hasZero = false 49 )) 50 val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect) 51 val issueQueues = exeUnits.zipWithIndex.map({ case(eu, i) => 52 def needBypass(x: Exu): Boolean = (eu.enableBypass) 53 val bypassCnt = exeUnits.count(needBypass)//if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0 54 def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf) 55 val wakeupCnt = exeUnits.count(needWakeup) 56 assert(!(needBypass(eu) && !needWakeup(eu))) // needBypass but dont needWakeup is not allowed 57 val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt, eu.fixedDelay)) 58 iq.io.redirect <> redirect 59 iq.io.enqCtrl <> dispatch2.io.enqIQCtrl(i) 60 iq.io.enqData <> dispatch2.io.enqIQData(i) 61 val wuUnitsOut = exeUnits.filter(e => needWakeup(e)).map(_.io.out) 62 for(i <- iq.io.wakeUpPorts.indices) { 63 iq.io.wakeUpPorts(i).bits <> wuUnitsOut(i).bits 64 iq.io.wakeUpPorts(i).valid := wuUnitsOut(i).valid 65 } 66 println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt") 67 eu.io.in <> iq.io.deq 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 io.frontend.redirect <> redirect 87 io.frontend.commits <> roq.io.commits 88 89 decode.io.in <> io.frontend.cfVec 90 brq.io.roqRedirect <> roq.io.redirect 91 brq.io.enqReqs <> decode.io.toBrq 92 decode.io.brMasks <> brq.io.brMasks 93 decode.io.brTags <> brq.io.brTags 94 decBuf.io.in <> decode.io.out 95 96 rename.io.redirect <> redirect 97 rename.io.roqCommits <> roq.io.commits 98 rename.io.in <> decBuf.io.out 99 100 dispatch1.io.redirect <> redirect 101 dispatch1.io.in <> rename.io.out 102 roq.io.brqRedirect <> brq.io.redirect 103 roq.io.dp1Req <> dispatch1.io.toRoq 104 dispatch1.io.roqIdxs <> roq.io.roqIdxs 105 106 dispatch2.io.in <> dispatch1.io.out 107 dispatch2.io.intPregRdy <> rename.io.intPregRdy 108 dispatch2.io.fpPregRdy <> rename.io.fpPregRdy 109 intRf.io.readPorts <> dispatch2.io.readIntRf 110 rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr) 111 fpRf.io.readPorts <> dispatch2.io.readFpRf 112 rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr) 113 114 115 val exeWbReqs = exeUnits.map(_.io.out) 116 val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out) 117 val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out) 118 val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts)) 119 val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts)) 120 val wbIntResults = intWbArb.io.out 121 val wbFpResults = fpWbArb.io.out 122 123 def exuOutToRfWrite(x: Valid[ExuOutput]) = { 124 val rfWrite = Wire(new RfWritePort) 125 rfWrite.wen := x.valid 126 rfWrite.addr := x.bits.uop.pdest 127 rfWrite.data := x.bits.data 128 rfWrite 129 } 130 131 intWbArb.io.in <> wbIntReqs 132 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 133 134 fpWbArb.io.in <> wbFpReqs 135 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 136 137 rename.io.wbIntResults <> wbIntResults 138 rename.io.wbFpResults <> wbFpResults 139 140 roq.io.exeWbResults <> exeWbReqs 141 142 143 // TODO: Remove sink and source 144 val tmp = WireInit(0.U) 145 val sinks = Array[String]( 146 "DTLBFINISH", 147 "DTLBPF", 148 "DTLBENABLE", 149 "perfCntCondMdcacheLoss", 150 "perfCntCondMl2cacheLoss", 151 "perfCntCondMdcacheHit", 152 "lsuMMIO", 153 "perfCntCondMl2cacheHit", 154 "perfCntCondMl2cacheReq", 155 "mtip", 156 "perfCntCondMdcacheReq", 157 "meip" 158 ) 159 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 160 161 // A fake commit 162 // TODO: difftest 6 insts per cycle 163 val commit = RegNext(RegNext(RegNext(true.B))) 164 val pc = WireInit("h80000000".U) 165 val inst = WireInit("h66666666".U) 166 167 if(!p.FPGAPlatform){ 168 BoringUtils.addSource(commit, "difftestCommit") 169 BoringUtils.addSource(pc, "difftestThisPC") 170 BoringUtils.addSource(inst, "difftestThisINST") 171 BoringUtils.addSource(tmp, "difftestIsMMIO") 172 BoringUtils.addSource(tmp, "difftestIsRVC") 173 BoringUtils.addSource(tmp, "difftestIntrNO") 174 BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs") 175 BoringUtils.addSource(tmp, "difftestMode") 176 BoringUtils.addSource(tmp, "difftestMstatus") 177 BoringUtils.addSource(tmp, "difftestSstatus") 178 BoringUtils.addSource(tmp, "difftestMepc") 179 BoringUtils.addSource(tmp, "difftestSepc") 180 BoringUtils.addSource(tmp, "difftestMcause") 181 BoringUtils.addSource(tmp, "difftestScause") 182 } 183 184} 185