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