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