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