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 lsuExeUnits.foreach(_.io.dmem <> io.dmem) 73 74 io.frontend.redirect <> redirect 75 io.frontend.commits <> roq.io.commits 76 77 decode.io.in <> io.frontend.cfVec 78 brq.io.roqRedirect <> roq.io.redirect 79 brq.io.enqReqs <> decode.io.toBrq 80 for(i <- bjUnits.indices){ 81 brq.io.exuRedirect(i).bits := bjUnits(i).io.out.bits 82 brq.io.exuRedirect(i).valid := bjUnits(i).io.out.fire() 83 } 84 decode.io.brMasks <> brq.io.brMasks 85 decode.io.brTags <> brq.io.brTags 86 decBuf.io.in <> decode.io.out 87 88 rename.io.redirect <> redirect 89 rename.io.roqCommits <> roq.io.commits 90 rename.io.in <> decBuf.io.out 91 92 dispatch1.io.redirect <> redirect 93 dispatch1.io.in <> rename.io.out 94 roq.io.brqRedirect <> brq.io.redirect 95 roq.io.dp1Req <> dispatch1.io.toRoq 96 dispatch1.io.roqIdxs <> roq.io.roqIdxs 97 98 dispatch2.io.in <> dispatch1.io.out 99 dispatch2.io.intPregRdy <> rename.io.intPregRdy 100 dispatch2.io.fpPregRdy <> rename.io.fpPregRdy 101 intRf.io.readPorts <> dispatch2.io.readIntRf 102 rename.io.intRfReadAddr <> dispatch2.io.readIntRf.map(_.addr) 103 fpRf.io.readPorts <> dispatch2.io.readFpRf 104 rename.io.fpRfReadAddr <> dispatch2.io.readFpRf.map(_.addr) 105 106 107 val exeWbReqs = exeUnits.map(_.io.out) 108 val wbIntReqs = (bruExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits)).map(_.io.out) 109 val wbFpReqs = (fmacExeUnits ++ fmiscExeUnits ++ fmiscDivSqrtExeUnits).map(_.io.out) 110 val intWbArb = Module(new WriteBackArbMtoN(wbIntReqs.length, NRWritePorts)) 111 val fpWbArb = Module(new WriteBackArbMtoN(wbFpReqs.length, NRWritePorts)) 112 val wbIntResults = intWbArb.io.out 113 val wbFpResults = fpWbArb.io.out 114 115 def exuOutToRfWrite(x: Valid[ExuOutput]) = { 116 val rfWrite = Wire(new RfWritePort) 117 rfWrite.wen := x.valid 118 rfWrite.addr := x.bits.uop.pdest 119 rfWrite.data := x.bits.data 120 rfWrite 121 } 122 123 intWbArb.io.in <> wbIntReqs 124 intRf.io.writePorts <> wbIntResults.map(exuOutToRfWrite) 125 126 fpWbArb.io.in <> wbFpReqs 127 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 128 129 rename.io.wbIntResults <> wbIntResults 130 rename.io.wbFpResults <> wbFpResults 131 132 roq.io.exeWbResults.zip(exeWbReqs).foreach({case (x,y) => { 133 x.bits := y.bits 134 x.valid := y.fire() 135 }}) 136 137 138 // TODO: Remove sink and source 139 val tmp = WireInit(0.U) 140 val sinks = Array[String]( 141 "DTLBFINISH", 142 "DTLBPF", 143 "DTLBENABLE", 144 "perfCntCondMdcacheLoss", 145 "perfCntCondMl2cacheLoss", 146 "perfCntCondMdcacheHit", 147 "lsuMMIO", 148 "perfCntCondMl2cacheHit", 149 "perfCntCondMl2cacheReq", 150 "mtip", 151 "perfCntCondMdcacheReq", 152 "meip" 153 ) 154 for (s <- sinks){ BoringUtils.addSink(tmp, s) } 155 156} 157