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 lsuExeUnits.foreach(_.io.dmem <> io.dmem) 72 73 io.frontend.redirect <> redirect 74 io.frontend.commits <> roq.io.commits 75 76 decode.io.in <> io.frontend.cfVec 77 brq.io.roqRedirect <> roq.io.redirect 78 brq.io.enqReqs <> decode.io.toBrq 79 for(i <- bjUnits.indices){ 80 brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits 81 brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire() 82 } 83 decode.io.brMasks <> brq.io.brMasks 84 decode.io.brTags <> brq.io.brTags 85 decBuf.io.in <> decode.io.out 86 87 rename.io.redirect <> redirect 88 rename.io.roqCommits <> roq.io.commits 89 rename.io.in <> decBuf.io.out 90 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) 91 rename.io.fpRfReadAddr <> dispatch.io.readFpRf.map(_.addr) 92 rename.io.intPregRdy <> dispatch.io.intPregRdy 93 rename.io.fpPregRdy <> dispatch.io.fpPregRdy 94 95 dispatch.io.redirect <> redirect 96 dispatch.io.fromRename <> rename.io.out 97 98 roq.io.brqRedirect <> brq.io.redirect 99 roq.io.dp1Req <> dispatch.io.toRoq 100 dispatch.io.roqIdxs <> roq.io.roqIdxs 101 102 intRf.io.readPorts <> dispatch.io.readIntRf 103 fpRf.io.readPorts <> dispatch.io.readFpRf 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.zip(exeWbReqs).foreach({case (x,y) => { 131 x.bits := y.bits 132 x.valid := y.fire() 133 }}) 134 135 136 // TODO: Remove sink and source 137 val tmp = WireInit(0.U) 138 val sinks = Array[String]( 139 "DTLBFINISH", 140 "DTLBPF", 141 "DTLBENABLE", 142 "perfCntCondMdcacheLoss", 143 "perfCntCondMl2cacheLoss", 144 "perfCntCondMdcacheHit", 145 "lsuMMIO", 146 "perfCntCondMl2cacheHit", 147 "perfCntCondMl2cacheReq", 148 "mtip", 149 "perfCntCondMdcacheReq", 150 "meip" 151 ) 152 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 153 154 // A fake commit 155 // TODO: difftest 6 insts per cycle 156 val commit = RegNext(RegNext(RegNext(true.B))) 157 val pc = WireInit("h80000000".U) 158 val inst = WireInit("h66666666".U) 159 160 if(!p.FPGAPlatform){ 161 BoringUtils.addSource(commit, "difftestCommit") 162 BoringUtils.addSource(pc, "difftestThisPC") 163 BoringUtils.addSource(inst, "difftestThisINST") 164 BoringUtils.addSource(tmp, "difftestIsMMIO") 165 BoringUtils.addSource(tmp, "difftestIsRVC") 166 BoringUtils.addSource(tmp, "difftestIntrNO") 167 BoringUtils.addSource(VecInit(Seq.fill(64)(tmp)), "difftestRegs") 168 BoringUtils.addSource(tmp, "difftestMode") 169 BoringUtils.addSource(tmp, "difftestMstatus") 170 BoringUtils.addSource(tmp, "difftestSstatus") 171 BoringUtils.addSource(tmp, "difftestMepc") 172 BoringUtils.addSource(tmp, "difftestSepc") 173 BoringUtils.addSource(tmp, "difftestMcause") 174 BoringUtils.addSource(tmp, "difftestScause") 175 } 176 177} 178