xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/BypassNetwork.scala (revision 042e89e414f8956a139ecd64336469a6a7b5ff6f)
1package xiangshan.backend.datapath
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.{GatedValidRegNext, SignExt, ZeroExt}
7import xiangshan.{XSBundle, XSModule}
8import xiangshan.backend.BackendParams
9import xiangshan.backend.Bundles.{ExuBypassBundle, ExuInput, ExuOutput, ExuVec, ImmInfo}
10import xiangshan.backend.issue.{FpScheduler, ImmExtractor, IntScheduler, MemScheduler, VfScheduler}
11import xiangshan.backend.datapath.DataConfig.RegDataMaxWidth
12import xiangshan.backend.decode.ImmUnion
13import xiangshan.backend.regcache._
14
15class BypassNetworkIO()(implicit p: Parameters, params: BackendParams) extends XSBundle {
16  // params
17  private val intSchdParams = params.schdParams(IntScheduler())
18  private val fpSchdParams = params.schdParams(FpScheduler())
19  private val vfSchdParams = params.schdParams(VfScheduler())
20  private val memSchdParams = params.schdParams(MemScheduler())
21
22  val fromDataPath = new FromDataPath
23  val toExus = new ToExus
24  val fromExus = new FromExus
25
26  class FromDataPath extends Bundle {
27    val int: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(intSchdParams.genExuInputBundle)
28    val fp : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(fpSchdParams.genExuInputBundle)
29    val vf : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(vfSchdParams.genExuInputBundle)
30    val mem: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(memSchdParams.genExuInputBundle)
31    val immInfo: Vec[ImmInfo] = Input(Vec(params.allExuParams.size, new ImmInfo))
32    val rcData: MixedVec[MixedVec[Vec[UInt]]] = MixedVec(
33      Seq(intSchdParams, fpSchdParams, vfSchdParams, memSchdParams).map(schd => schd.issueBlockParams.map(iq =>
34        MixedVec(iq.exuBlockParams.map(exu => Input(Vec(exu.numRegSrc, UInt(exu.srcDataBitsMax.W)))))
35      )).flatten
36    )
37  }
38
39  class ToExus extends Bundle {
40    val int: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = intSchdParams.genExuInputBundle
41    val fp : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = fpSchdParams.genExuInputBundle
42    val vf : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = vfSchdParams.genExuInputBundle
43    val mem: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = memSchdParams.genExuInputBundle
44  }
45
46  class FromExus extends Bundle {
47    val int: MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(intSchdParams.genExuBypassValidBundle)
48    val fp : MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(fpSchdParams.genExuBypassValidBundle)
49    val vf : MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(vfSchdParams.genExuBypassValidBundle)
50    val mem: MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(memSchdParams.genExuBypassValidBundle)
51
52    def connectExuOutput(
53      getSinkVecN: FromExus => MixedVec[MixedVec[ValidIO[ExuBypassBundle]]]
54    )(
55      sourceVecN: MixedVec[MixedVec[DecoupledIO[ExuOutput]]]
56    ): Unit = {
57      getSinkVecN(this).zip(sourceVecN).foreach { case (sinkVec, sourcesVec) =>
58        sinkVec.zip(sourcesVec).foreach { case (sink, source) =>
59          sink.valid := source.valid
60          sink.bits.intWen := source.bits.intWen.getOrElse(false.B)
61          sink.bits.pdest := source.bits.pdest
62          sink.bits.data := source.bits.data(0)
63        }
64      }
65    }
66  }
67
68  val toDataPath: Vec[RCWritePort] = Vec(params.getIntExuRCWriteSize + params.getMemExuRCWriteSize,
69    Flipped(new RCWritePort(params.intSchdParams.get.rfDataWidth, RegCacheIdxWidth, params.intSchdParams.get.pregIdxWidth, params.debugEn)))
70}
71
72class BypassNetwork()(implicit p: Parameters, params: BackendParams) extends XSModule {
73  val io: BypassNetworkIO = IO(new BypassNetworkIO)
74
75  private val fromDPs: Seq[DecoupledIO[ExuInput]] = (io.fromDataPath.int ++ io.fromDataPath.fp ++ io.fromDataPath.vf ++ io.fromDataPath.mem).flatten.toSeq
76  private val fromExus: Seq[ValidIO[ExuBypassBundle]] = (io.fromExus.int ++ io.fromExus.fp ++ io.fromExus.vf ++ io.fromExus.mem).flatten.toSeq
77  private val toExus: Seq[DecoupledIO[ExuInput]] = (io.toExus.int ++ io.toExus.fp ++ io.toExus.vf ++ io.toExus.mem).flatten.toSeq
78  private val fromDPsRCData: Seq[Vec[UInt]] = io.fromDataPath.rcData.flatten.toSeq
79  private val immInfo = io.fromDataPath.immInfo
80
81  println(s"[BypassNetwork] RCData num: ${fromDPsRCData.size}")
82
83  // (exuIdx, srcIdx, bypassExuIdx)
84  private val forwardOrBypassValidVec3: MixedVec[Vec[Vec[Bool]]] = MixedVecInit(
85    fromDPs.map { (x: DecoupledIO[ExuInput]) =>
86      println(s"[BypassNetwork] ${x.bits.params.name} numRegSrc: ${x.bits.params.numRegSrc}")
87      VecInit(x.bits.exuSources.map(_.map(_.toExuOH(x.bits.params))).getOrElse(
88        // TODO: remove tmp max 1 for fake HYU1
89        VecInit(Seq.fill(x.bits.params.numRegSrc max 1)(VecInit(0.U(params.numExu.W).asBools)))
90      ))
91    }
92  )
93
94  private val forwardDataVec: Vec[UInt] = VecInit(
95    fromExus.map(x => ZeroExt(x.bits.data, RegDataMaxWidth))
96  )
97
98  private val bypassDataVec = VecInit(
99    fromExus.map(x => ZeroExt(RegEnable(x.bits.data, x.valid), RegDataMaxWidth))
100  )
101
102  private val intExuNum = params.intSchdParams.get.numExu
103  private val fpExuNum  = params.fpSchdParams.get.numExu
104  private val vfExuNum  = params.vfSchdParams.get.numExu
105  private val memExuNum = params.memSchdParams.get.numExu
106
107  println(s"[BypassNetwork] allExuNum: ${toExus.size} intExuNum: ${intExuNum} fpExuNum: ${fpExuNum} vfExuNum: ${vfExuNum} memExuNum: ${memExuNum}")
108
109  private val fromDPsHasBypass2Source = fromDPs.filter(x => x.bits.params.isIQWakeUpSource && x.bits.params.writeVfRf && (x.bits.params.isVfExeUnit || x.bits.params.hasLoadExu)).map(_.bits.params.exuIdx)
110  private val fromDPsHasBypass2Sink   = fromDPs.filter(x => x.bits.params.isIQWakeUpSink && x.bits.params.readVfRf && (x.bits.params.isVfExeUnit || x.bits.params.isMemExeUnit)).map(_.bits.params.exuIdx)
111
112  private val bypass2ValidVec3 = MixedVecInit(
113    fromDPsHasBypass2Sink.map(forwardOrBypassValidVec3(_)).map(exu => VecInit(exu.map(exuOH =>
114      VecInit(fromDPsHasBypass2Source.map(exuOH(_))).asUInt
115    )))
116  )
117  if(params.debugEn){
118    dontTouch(bypass2ValidVec3)
119  }
120  private val bypass2DateEn = VecInit(
121    fromExus.map(x => GatedValidRegNext(x.valid))
122  ).asUInt
123  private val bypass2DataVec = if (fromDPsHasBypass2Source.length == 0) VecInit(Seq(0.U)) else VecInit(
124    fromDPsHasBypass2Source.map(x => RegEnable(bypassDataVec(x), bypass2DateEn(x).asBool))
125  )
126
127  println(s"[BypassNetwork] HasBypass2SourceExuNum: ${fromDPsHasBypass2Source.size} HasBypass2SinkExuNum: ${fromDPsHasBypass2Sink.size} bypass2DataVecSize: ${bypass2DataVec.length}")
128  println(s"[BypassNetwork] HasBypass2SourceExu: ${fromDPsHasBypass2Source}")
129  println(s"[BypassNetwork] HasBypass2SinkExu: ${fromDPsHasBypass2Sink}")
130
131  toExus.zip(fromDPs).foreach { case (sink, source) =>
132    sink <> source
133  }
134
135  toExus.zipWithIndex.foreach { case (exuInput, exuIdx) =>
136    exuInput.bits.src.zipWithIndex.foreach { case (src, srcIdx) =>
137      val imm = ImmExtractor(
138        immInfo(exuIdx).imm,
139        immInfo(exuIdx).immType,
140        exuInput.bits.params.destDataBitsMax,
141        exuInput.bits.params.immType.map(_.litValue)
142      )
143      val immLoadSrc0 = SignExt(ImmUnion.U.toImm32(immInfo(exuIdx).imm(immInfo(exuIdx).imm.getWidth - 1, ImmUnion.I.len)), XLEN)
144      val exuParm = exuInput.bits.params
145      val isIntScheduler = exuParm.isIntExeUnit
146      val isReadVfRf= exuParm.readVfRf
147      val dataSource = exuInput.bits.dataSources(srcIdx)
148      val isWakeUpSink = params.allIssueParams.filter(_.exuBlockParams.contains(exuParm)).head.exuBlockParams.map(_.isIQWakeUpSink).reduce(_ || _)
149      val readForward = if (isWakeUpSink) dataSource.readForward else false.B
150      val readBypass = if (isWakeUpSink) dataSource.readBypass else false.B
151      val readZero = if (isIntScheduler) dataSource.readZero else false.B
152      val readV0 = if (srcIdx < 3 && isReadVfRf) dataSource.readV0 else false.B
153      val readRegOH = exuInput.bits.dataSources(srcIdx).readRegOH
154      val readRegCache = if (exuParm.needReadRegCache) exuInput.bits.dataSources(srcIdx).readRegCache else false.B
155      val readImm = if (exuParm.immType.nonEmpty || exuParm.hasLoadExu) exuInput.bits.dataSources(srcIdx).readImm else false.B
156      val bypass2ExuIdx = fromDPsHasBypass2Sink.indexOf(exuIdx)
157      println(s"${exuParm.name}: bypass2ExuIdx is ${bypass2ExuIdx}")
158      val readBypass2 = if (bypass2ExuIdx >= 0) dataSource.readBypass2 else false.B
159      src := Mux1H(
160        Seq(
161          readForward    -> Mux1H(forwardOrBypassValidVec3(exuIdx)(srcIdx), forwardDataVec),
162          readBypass     -> Mux1H(forwardOrBypassValidVec3(exuIdx)(srcIdx), bypassDataVec),
163          readBypass2    -> (if (bypass2ExuIdx >= 0) Mux1H(bypass2ValidVec3(bypass2ExuIdx)(srcIdx), bypass2DataVec) else 0.U),
164          readZero       -> 0.U,
165          readV0         -> (if (srcIdx < 3 && isReadVfRf) exuInput.bits.src(3) else 0.U),
166          readRegOH      -> fromDPs(exuIdx).bits.src(srcIdx),
167          readRegCache   -> fromDPsRCData(exuIdx)(srcIdx),
168          readImm        -> (if (exuParm.hasLoadExu && srcIdx == 0) immLoadSrc0 else imm)
169        )
170      )
171    }
172  }
173
174  // to reg cache
175  private val forwardIntWenVec = VecInit(
176    fromExus.filter(_.bits.params.needWriteRegCache).map(x => x.valid && x.bits.intWen)
177  )
178  private val forwardTagVec = VecInit(
179    fromExus.filter(_.bits.params.needWriteRegCache).map(x => x.bits.pdest)
180  )
181
182  private val bypassIntWenVec = VecInit(
183    forwardIntWenVec.map(x => GatedValidRegNext(x))
184  )
185  private val bypassTagVec = VecInit(
186    forwardTagVec.zip(forwardIntWenVec).map(x => RegEnable(x._1, x._2))
187  )
188  private val bypassRCDataVec = VecInit(
189    fromExus.zip(bypassDataVec).filter(_._1.bits.params.needWriteRegCache).map(_._2)
190  )
191
192  println(s"[BypassNetwork] WriteRegCacheExuNum: ${forwardIntWenVec.size}")
193
194  io.toDataPath.zipWithIndex.foreach{ case (x, i) =>
195    x.wen := bypassIntWenVec(i)
196    x.addr := DontCare
197    x.data := bypassRCDataVec(i)
198    x.tag.foreach(_ := bypassTagVec(i))
199  }
200}
201