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