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