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