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