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) - (if(eu.enableBypass) bypassCnt else 0) 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 iq.io.wakeUpPorts <> exeUnits.filter(e => needWakeup(e) && !needBypass(e)).map(_.io.out) 62 println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt") 63 eu.io.in <> iq.io.deq 64 iq 65 }) 66 67 val bypassQueues = issueQueues.filter(_.bypassCnt > 0) 68 val bypassUnits = exeUnits.filter(_.enableBypass) 69 bypassQueues.foreach(iq => { 70 iq.io.bypassUops <> bypassQueues.map(_.io.selectedUop) 71 iq.io.bypassData <> bypassUnits.map(_.io.out) 72 }) 73 // val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue()) 74 // aluQueues.foreach(aluQ => { 75 // aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop) 76 // aluQ.io.bypassData <> aluExeUnits.map(_.io.out) 77 // }) 78 79 io.frontend.redirect <> redirect 80 io.frontend.commits <> roq.io.commits 81 82 decode.io.in <> io.frontend.cfVec 83 brq.io.roqRedirect <> roq.io.redirect 84 brq.io.enqReqs <> decode.io.toBrq 85 decode.io.brMasks <> brq.io.brMasks 86 decode.io.brTags <> brq.io.brTags 87 decBuf.io.in <> decode.io.out 88 89 rename.io.redirect <> redirect 90 rename.io.roqCommits <> roq.io.commits 91 rename.io.in <> decBuf.io.out 92 93 dispatch1.io.redirect <> redirect 94 dispatch1.io.in <> rename.io.out 95 roq.io.brqRedirect <> brq.io.redirect 96 roq.io.dp1Req <> dispatch1.io.toRoq 97 dispatch1.io.roqIdxs <> roq.io.roqIdxs 98 99 dispatch2.io.in <> dispatch1.io.out 100 dispatch2.io.intPregRdy <> rename.io.intPregRdy 101 dispatch2.io.fpPregRdy <> rename.io.fpPregRdy 102 intRf.io.readPorts <> dispatch2.io.readIntRf 103 rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr) 104 fpRf.io.readPorts <> dispatch2.io.readFpRf 105 rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr) 106 107 108 val exeWbReqs = exeUnits.map(_.io.out) 109 val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out) 110 val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out) 111 val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts)) 112 val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts)) 113 val wbIntResults = intWbArb.io.out 114 val wbFpResults = fpWbArb.io.out 115 116 def exuOutToRfWrite(x: Valid[ExuOutput]) = { 117 val rfWrite = Wire(new RfWritePort) 118 rfWrite.wen := x.valid 119 rfWrite.addr := x.bits.uop.pdest 120 rfWrite.data := x.bits.data 121 rfWrite 122 } 123 124 intWbArb.io.in <> wbIntReqs 125 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 126 127 fpWbArb.io.in <> wbFpReqs 128 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 129 130 rename.io.wbIntResults <> wbIntResults 131 rename.io.wbFpResults <> wbFpResults 132 133 roq.io.exeWbResults <> exeWbReqs 134 135 136 // TODO: Remove sink and source 137 val tmp = WireInit(0.U) 138 val sinks = Array[String]( 139 "DTLBFINISH", 140 "DTLBPF", 141 "DTLBENABLE", 142 "perfCntCondMdcacheLoss", 143 "perfCntCondMl2cacheLoss", 144 "perfCntCondMdcacheHit", 145 "lsuMMIO", 146 "perfCntCondMl2cacheHit", 147 "perfCntCondMl2cacheReq", 148 "mtip", 149 "perfCntCondMdcacheReq", 150 "meip" 151 ) 152 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 153 154 // A fake commit 155 // TODO: difftest 6 insts per cycle 156 val commit = RegNext(RegNext(RegNext(true.B))) 157 val pc = WireInit("h80000000".U) 158 val inst = WireInit("h66666666".U) 159 160 if(!p.FPGAPlatform){ 161 BoringUtils.addSource(commit, "difftestCommit") 162 BoringUtils.addSource(pc, "difftestThisPC") 163 BoringUtils.addSource(inst, "difftestThisINST") 164 BoringUtils.addSource(tmp, "difftestIsMMIO") 165 BoringUtils.addSource(tmp, "difftestIsRVC") 166 BoringUtils.addSource(tmp, "difftestIntrNO") 167 BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs") 168 BoringUtils.addSource(tmp, "difftestMode") 169 BoringUtils.addSource(tmp, "difftestMstatus") 170 BoringUtils.addSource(tmp, "difftestSstatus") 171 BoringUtils.addSource(tmp, "difftestMepc") 172 BoringUtils.addSource(tmp, "difftestSepc") 173 BoringUtils.addSource(tmp, "difftestMcause") 174 BoringUtils.addSource(tmp, "difftestScause") 175 } 176 177} 178