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.Dispatch 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 dispatch = Module(new Dispatch) 38 val roq = Module(new Roq) 39 val intRf = Module(new Regfile( 40 numReadPorts = NRReadPorts, 41 numWirtePorts = NRWritePorts, 42 hasZero = true 43 )) 44 val fpRf = Module(new Regfile( 45 numReadPorts = NRReadPorts, 46 numWirtePorts = NRWritePorts, 47 hasZero = false 48 )) 49 val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect) 50 val issueQueues = exeUnits.zipWithIndex.map({ case(eu, i) => 51 def needWakeup(x: Exu): Boolean = (eu.readIntRf && x.writeIntRf) || (eu.readFpRf && x.writeFpRf) 52 val wakeupCnt = exeUnits.count(needWakeup) 53 val bypassCnt = if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0 54 val iq = Module(new IssueQueue(eu.fuTypeInt, wakeupCnt, bypassCnt)) 55 iq.io.redirect <> redirect 56 iq.io.enqCtrl <> dispatch.io.enqIQCtrl(i) 57 iq.io.enqData <> dispatch.io.enqIQData(i) 58 iq.io.wakeUpPorts <> exeUnits.filter(needWakeup).map(_.io.out) 59 println(s"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt") 60 eu.io.in <> iq.io.deq 61 eu.io.redirect <> redirect 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 for(i <- bjUnits.indices){ 78 brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits 79 brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire() 80 } 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 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) 89 rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr) 90 rename.io.intPregRdy <> dispatch.io.intPregRdy 91 rename.io.fpPregRdy <> dispatch.io.fpPregRdy 92 93 dispatch.io.redirect <> redirect 94 dispatch.io.fromRename <> rename.io.out 95 96 roq.io.brqRedirect <> brq.io.redirect 97 roq.io.dp1Req <> dispatch.io.toRoq 98 dispatch.io.roqIdxs <> roq.io.roqIdxs 99 100 intRf.io.readPorts <> dispatch.io.readIntRf 101 fpRf.io.readPorts <> dispatch.io.readFpRf 102 103 val exeWbReqs = exeUnits.map(_.io.out) 104 val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out) 105 val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out) 106 val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts)) 107 val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts)) 108 val wbIntResults = intWbArb.io.out 109 val wbFpResults = fpWbArb.io.out 110 111 def exuOutToRfWrite(x: Valid[ExuOutput]) = { 112 val rfWrite = Wire(new RfWritePort) 113 rfWrite.wen := x.valid 114 rfWrite.addr := x.bits.uop.pdest 115 rfWrite.data := x.bits.data 116 rfWrite 117 } 118 119 intWbArb.io.in <> wbIntReqs 120 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 121 122 fpWbArb.io.in <> wbFpReqs 123 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 124 125 rename.io.wbIntResults <> wbIntResults 126 rename.io.wbFpResults <> wbFpResults 127 128 roq.io.exeWbResults <> exeWbReqs 129 130 131 // TODO: Remove sink and source 132 val tmp = WireInit(0.U) 133 val sinks = Array[String]( 134 "DTLBFINISH", 135 "DTLBPF", 136 "DTLBENABLE", 137 "perfCntCondMdcacheLoss", 138 "perfCntCondMl2cacheLoss", 139 "perfCntCondMdcacheHit", 140 "lsuMMIO", 141 "perfCntCondMl2cacheHit", 142 "perfCntCondMl2cacheReq", 143 "mtip", 144 "perfCntCondMdcacheReq", 145 "meip" 146 ) 147 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 148 149 // A fake commit 150 // TODO: difftest 6 insts per cycle 151 val commit = RegNext(RegNext(RegNext(true.B))) 152 val pc = WireInit("h80000000".U) 153 val inst = WireInit("h66666666".U) 154 155 if(!p.FPGAPlatform){ 156 BoringUtils.addSource(commit, "difftestCommit") 157 BoringUtils.addSource(pc, "difftestThisPC") 158 BoringUtils.addSource(inst, "difftestThisINST") 159 BoringUtils.addSource(tmp, "difftestIsMMIO") 160 BoringUtils.addSource(tmp, "difftestIsRVC") 161 BoringUtils.addSource(tmp, "difftestIntrNO") 162 BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs") 163 BoringUtils.addSource(tmp, "difftestMode") 164 BoringUtils.addSource(tmp, "difftestMstatus") 165 BoringUtils.addSource(tmp, "difftestSstatus") 166 BoringUtils.addSource(tmp, "difftestMepc") 167 BoringUtils.addSource(tmp, "difftestSepc") 168 BoringUtils.addSource(tmp, "difftestMcause") 169 BoringUtils.addSource(tmp, "difftestScause") 170 } 171 172} 173