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