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.fu.FunctionUnit 15import xiangshan.backend.issue.{IssueQueue, RegfileReader, ReservedStation} 16import xiangshan.backend.regfile.{Regfile, RfWritePort} 17import xiangshan.backend.roq.Roq 18import xiangshan.mem._ 19 20 21/** Backend Pipeline: 22 * Decode -> Rename -> Dispatch-1 -> Dispatch-2 -> Issue -> Exe 23 */ 24class Backend(implicit val p: XSConfig) extends XSModule 25 with NeedImpl { 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 val mem = Flipped(new MemToBackendIO) 31 }) 32 33 34 val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit)) 35 val jmpExeUnit = Module(new JmpExeUnit) 36 val mulExeUnits = Array.tabulate(exuParameters.MulCnt)(_ => Module(new MulExeUnit)) 37 val mduExeUnits = Array.tabulate(exuParameters.MduCnt)(_ => Module(new MulDivExeUnit)) 38 // val fmacExeUnits = Array.tabulate(exuParameters.FmacCnt)(_ => Module(new Fmac)) 39 // val fmiscExeUnits = Array.tabulate(exuParameters.FmiscCnt)(_ => Module(new Fmisc)) 40 // val fmiscDivSqrtExeUnits = Array.tabulate(exuParameters.FmiscDivSqrtCnt)(_ => Module(new FmiscDivSqrt)) 41 val exeUnits = jmpExeUnit +: (aluExeUnits ++ mulExeUnits ++ mduExeUnits) 42 exeUnits.foreach(_.io.exception := DontCare) 43 exeUnits.foreach(_.io.dmem := DontCare) 44 exeUnits.foreach(_.io.mcommit := DontCare) 45 46 val decode = Module(new DecodeStage) 47 val brq = Module(new Brq) 48 val decBuf = Module(new DecodeBuffer) 49 val rename = Module(new Rename) 50 val dispatch = Module(new Dispatch(exeUnits.map(_.config))) 51 val roq = Module(new Roq) 52 val intRf = Module(new Regfile( 53 numReadPorts = NRIntReadPorts, 54 numWirtePorts = NRIntWritePorts, 55 hasZero = true 56 )) 57 val fpRf = Module(new Regfile( 58 numReadPorts = NRFpReadPorts, 59 numWirtePorts = NRFpWritePorts, 60 hasZero = false 61 )) 62 val memRf = Module(new Regfile( 63 numReadPorts = 2*exuParameters.StuCnt + exuParameters.LduCnt, 64 numWirtePorts = NRIntWritePorts, 65 hasZero = true, 66 isMemRf = true 67 )) 68 69 // backend redirect, flush pipeline 70 val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect) 71 72 val redirectInfo = Wire(new RedirectInfo) 73 // exception or misprediction 74 redirectInfo.valid := roq.io.redirect.valid || brq.io.out.valid 75 redirectInfo.misPred := !roq.io.redirect.valid && brq.io.redirect.valid 76 redirectInfo.redirect := redirect.bits 77 78 79 80 val memConfigs = 81 Seq.fill(exuParameters.LduCnt)(Exu.ldExeUnitCfg) ++ 82 Seq.fill(exuParameters.StuCnt)(Exu.stExeUnitCfg) 83 84 val exuConfigs = exeUnits.map(_.config) ++ memConfigs 85 86 val exeWbReqs = exeUnits.map(_.io.out) ++ io.mem.ldout ++ io.mem.stout 87 88 def needWakeup(cfg: ExuConfig): Boolean = 89 (cfg.readIntRf && cfg.writeIntRf) || (cfg.readFpRf && cfg.writeFpRf) 90 91 def needData(a: ExuConfig, b: ExuConfig): Boolean = 92 (a.readIntRf && b.writeIntRf) || (a.readFpRf && b.writeFpRf) 93 94 val reservedStations = exeUnits. 95 zipWithIndex. 96 map({ case (exu, i) => 97 98 val cfg = exu.config 99 100 val wakeUpDateVec = exuConfigs.zip(exeWbReqs).filter(x => needData(cfg, x._1)).map(_._2) 101 val bypassCnt = exuConfigs.count(c => c.enableBypass && needData(cfg, c)) 102 103 println(s"exu:${cfg.name} wakeupCnt:${wakeUpDateVec.length} bypassCnt:$bypassCnt") 104 105 val rs = Module(new ReservedStation( 106 cfg, wakeUpDateVec.length, bypassCnt, cfg.enableBypass, false 107 )) 108 rs.io.redirect <> redirect 109 rs.io.numExist <> dispatch.io.numExist(i) 110 rs.io.enqCtrl <> dispatch.io.enqIQCtrl(i) 111 rs.io.enqData <> dispatch.io.enqIQData(i) 112 for( 113 (wakeUpPort, exuOut) <- 114 rs.io.wakeUpPorts.zip(wakeUpDateVec) 115 ){ 116 wakeUpPort.bits := exuOut.bits 117 wakeUpPort.valid := exuOut.valid 118 } 119 120 exu.io.in <> rs.io.deq 121 exu.io.redirect <> redirect 122 rs 123 }) 124 125 for( rs <- reservedStations){ 126 rs.io.bypassUops <> reservedStations. 127 filter(x => x.enableBypass && needData(rs.exuCfg, x.exuCfg)). 128 map(_.io.selectedUop) 129 130 val bypassDataVec = exuConfigs.zip(exeWbReqs). 131 filter(x => x._1.enableBypass && needData(rs.exuCfg, x._1)).map(_._2) 132 133 for(i <- bypassDataVec.indices){ 134 rs.io.bypassData(i).valid := bypassDataVec(i).valid 135 rs.io.bypassData(i).bits := bypassDataVec(i).bits 136 } 137 } 138 139 val issueQueues = exuConfigs. 140 zipWithIndex. 141 takeRight(exuParameters.LduCnt + exuParameters.StuCnt). 142 map({case (cfg, i) => 143 val wakeUpDateVec = exuConfigs.zip(exeWbReqs).filter(x => needData(cfg, x._1)).map(_._2) 144 val bypassUopVec = reservedStations.filter(r => r.exuCfg.enableBypass && needData(cfg, r.exuCfg)).map(_.io.selectedUop) 145 val iq = Module(new IssueQueue( 146 cfg, wakeUpDateVec.length, bypassUopVec.length 147 )) 148 println(s"exu:${cfg.name} wakeupCnt:${wakeUpDateVec.length} bypassCnt:${bypassUopVec.length}") 149 iq.io.redirect <> redirect 150 iq.io.enq <> dispatch.io.enqIQCtrl(i) 151 dispatch.io.numExist(i) := iq.io.numExist 152 for( 153 (wakeUpPort, exuOut) <- 154 iq.io.wakeUpPorts.zip(wakeUpDateVec) 155 ){ 156 wakeUpPort.bits := exuOut.bits 157 wakeUpPort.valid := exuOut.valid 158 } 159 iq.io.bypassUops <> bypassUopVec 160 iq 161 }) 162 163 val rfReader = Module(new RegfileReader(memConfigs, exeWbReqs.length)) 164 rfReader.io.in <> issueQueues.map(_.io.deq) 165 rfReader.io.bypasses <> exeWbReqs 166 167 io.mem.mcommit := roq.io.mcommit 168 io.mem.ldin <> rfReader.io.out.take(exuParameters.LduCnt) 169 io.mem.stin <> rfReader.io.out.takeRight(exuParameters.StuCnt) 170 jmpExeUnit.io.exception.valid := roq.io.redirect.valid 171 jmpExeUnit.io.exception.bits := roq.io.exception 172 173 io.frontend.redirectInfo <> redirectInfo 174 io.frontend.inOrderBrInfo <> brq.io.inOrderBrInfo 175 176 decode.io.in <> io.frontend.cfVec 177 brq.io.roqRedirect <> roq.io.redirect 178 brq.io.bcommit := roq.io.bcommit 179 brq.io.enqReqs <> decode.io.toBrq 180 for ((x, y) <- brq.io.exuRedirect.zip(exeUnits.filter(_.config.hasRedirect))) { 181 x.bits := y.io.out.bits 182 x.valid := y.io.out.fire() && y.io.out.bits.redirectValid 183 } 184 decode.io.brTags <> brq.io.brTags 185 decBuf.io.redirect <> redirect 186 decBuf.io.in <> decode.io.out 187 188 rename.io.redirect <> redirect 189 rename.io.roqCommits <> roq.io.commits 190 rename.io.in <> decBuf.io.out 191 rename.io.intRfReadAddr <> dispatch.io.readIntRf.map(_.addr) ++ issueQueues.flatMap(_.io.intRfReadAddr) 192 rename.io.intPregRdy <> dispatch.io.intPregRdy ++ issueQueues.flatMap(_.io.intSrcRdy) 193 rename.io.fpRfReadAddr <> DontCare //TODO 194 rename.io.fpPregRdy <> DontCare //TODO 195 dispatch.io.fpPregRdy <> DontCare //TODO 196 issueQueues.flatMap(_.io.fpSrcRdy).foreach(_ := DontCare)//TODO 197 dispatch.io.redirect <> redirect 198 dispatch.io.fromRename <> rename.io.out 199 200 roq.io.brqRedirect <> brq.io.redirect 201 roq.io.dp1Req <> dispatch.io.toRoq 202 dispatch.io.roqIdxs <> roq.io.roqIdxs 203 io.mem.dp1Req <> dispatch.io.toMoq 204 dispatch.io.moqIdxs <> io.mem.moqIdxs 205 206 intRf.io.readPorts <> dispatch.io.readIntRf 207 fpRf.io.readPorts <> DontCare // TODO 208 dispatch.io.readFpRf <> DontCare //TODO 209 rfReader.io.readFpRf <> DontCare // TODO 210 memRf.io.readPorts <> rfReader.io.readIntRf 211 212 val wbIntIdx = exuConfigs.zipWithIndex.filter(_._1.writeIntRf).map(_._2) 213 val wbFpIdx = exuConfigs.zipWithIndex.filter(_._1.writeFpRf).map(_._2) 214 215 val wbu = Module(new Wbu(wbIntIdx, wbFpIdx)) 216 wbu.io.in <> exeWbReqs 217 218 val wbIntResults = wbu.io.toIntRf 219 val wbFpResults = wbu.io.toFpRf 220 221 def exuOutToRfWrite(x: Valid[ExuOutput]): RfWritePort = { 222 val rfWrite = Wire(new RfWritePort) 223 rfWrite.wen := x.valid 224 rfWrite.addr := x.bits.uop.pdest 225 rfWrite.data := x.bits.data 226 rfWrite 227 } 228 val intRfWrite = wbIntResults.map(exuOutToRfWrite) 229 intRf.io.writePorts <> intRfWrite 230 memRf.io.writePorts <> intRfWrite 231 fpRf.io.writePorts <> wbFpResults.map(exuOutToRfWrite) 232 233 rename.io.wbIntResults <> wbIntResults 234 rename.io.wbFpResults <> wbFpResults 235 236 roq.io.exeWbResults.take(exeWbReqs.length).zip(wbu.io.toRoq).foreach(x => x._1 := x._2) 237 roq.io.exeWbResults.last := brq.io.out 238 239 240 // TODO: Remove sink and source 241 val tmp = WireInit(0.U) 242 val sinks = Array[String]( 243 "DTLBFINISH", 244 "DTLBPF", 245 "DTLBENABLE", 246 "perfCntCondMdcacheLoss", 247 "perfCntCondMl2cacheLoss", 248 "perfCntCondMdcacheHit", 249 "lsuMMIO", 250 "perfCntCondMl2cacheHit", 251 "perfCntCondMl2cacheReq", 252 "mtip", 253 "perfCntCondMdcacheReq", 254 "meip" 255 ) 256 for (s <- sinks) { 257 BoringUtils.addSink(tmp, s) 258 } 259 260 val debugIntReg, debugFpReg = WireInit(VecInit(Seq.fill(32)(0.U(XLEN.W)))) 261 BoringUtils.addSink(debugIntReg, "DEBUG_INT_ARCH_REG") 262 BoringUtils.addSink(debugFpReg, "DEBUG_FP_ARCH_REG") 263 val debugArchReg = WireInit(VecInit(debugIntReg ++ debugFpReg)) 264 if (!p.FPGAPlatform) { 265 BoringUtils.addSource(debugArchReg, "difftestRegs") 266 } 267 268} 269