xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/BypassNetwork.scala (revision bb2f3f51dd67f6e16e0cc1ffe43368c9fc7e4aef)
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, ExuOH, ExuOutput, ExuVec, ImmInfo}
10import xiangshan.backend.issue.{FpScheduler, ImmExtractor, IntScheduler, MemScheduler, VfScheduler}
11import xiangshan.backend.datapath.DataConfig.RegDataMaxWidth
12import xiangshan.backend.decode.ImmUnion
13
14class BypassNetworkIO()(implicit p: Parameters, params: BackendParams) extends XSBundle {
15  // params
16  private val intSchdParams = params.schdParams(IntScheduler())
17  private val fpSchdParams = params.schdParams(FpScheduler())
18  private val vfSchdParams = params.schdParams(VfScheduler())
19  private val memSchdParams = params.schdParams(MemScheduler())
20
21  val fromDataPath = new FromDataPath
22  val toExus = new ToExus
23  val fromExus = new FromExus
24
25  class FromDataPath extends Bundle {
26    val int: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(intSchdParams.genExuInputBundle)
27    val fp : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(fpSchdParams.genExuInputBundle)
28    val vf : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(vfSchdParams.genExuInputBundle)
29    val mem: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(memSchdParams.genExuInputBundle)
30    val immInfo: Vec[ImmInfo] = Input(Vec(params.allExuParams.size, new ImmInfo))
31  }
32
33  class ToExus extends Bundle {
34    val int: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = intSchdParams.genExuInputBundle
35    val fp : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = fpSchdParams.genExuInputBundle
36    val vf : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = vfSchdParams.genExuInputBundle
37    val mem: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = memSchdParams.genExuInputBundle
38  }
39
40  class FromExus extends Bundle {
41    val int: MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(intSchdParams.genExuBypassValidBundle)
42    val fp : MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(fpSchdParams.genExuBypassValidBundle)
43    val vf : MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(vfSchdParams.genExuBypassValidBundle)
44    val mem: MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(memSchdParams.genExuBypassValidBundle)
45
46    def connectExuOutput(
47      getSinkVecN: FromExus => MixedVec[MixedVec[ValidIO[ExuBypassBundle]]]
48    )(
49      sourceVecN: MixedVec[MixedVec[DecoupledIO[ExuOutput]]]
50    ): Unit = {
51      getSinkVecN(this).zip(sourceVecN).foreach { case (sinkVec, sourcesVec) =>
52        sinkVec.zip(sourcesVec).foreach { case (sink, source) =>
53          sink.valid := source.valid
54          sink.bits.pdest := source.bits.pdest
55          sink.bits.data := source.bits.data(0)
56        }
57      }
58    }
59  }
60}
61
62class BypassNetwork()(implicit p: Parameters, params: BackendParams) extends XSModule {
63  val io: BypassNetworkIO = IO(new BypassNetworkIO)
64
65  private val fromDPs: Seq[DecoupledIO[ExuInput]] = (io.fromDataPath.int ++ io.fromDataPath.fp ++ io.fromDataPath.vf ++ io.fromDataPath.mem).flatten.toSeq
66  private val fromExus: Seq[ValidIO[ExuBypassBundle]] = (io.fromExus.int ++ io.fromExus.fp ++ io.fromExus.vf ++ io.fromExus.mem).flatten.toSeq
67  private val toExus: Seq[DecoupledIO[ExuInput]] = (io.toExus.int ++ io.toExus.fp ++ io.toExus.vf ++ io.toExus.mem).flatten.toSeq
68  private val immInfo = io.fromDataPath.immInfo
69
70  // (exuIdx, srcIdx, bypassExuIdx)
71  private val forwardOrBypassValidVec3: MixedVec[Vec[Vec[Bool]]] = MixedVecInit(
72    fromDPs.map { (x: DecoupledIO[ExuInput]) =>
73      val wakeUpSourceIdx = x.bits.params.iqWakeUpSinkPairs.map(x => x.source.getExuParam(params.allExuParams).exuIdx)
74      val mask = Wire(chiselTypeOf(x.bits.l1ExuOH.getOrElse(VecInit(Seq.fill(x.bits.params.numRegSrc max 1)(VecInit(0.U(ExuVec.width.W).asBools))))))
75      mask.map{ case m =>
76        val vecMask = Wire(Vec(m.getWidth, Bool()))
77        vecMask.zipWithIndex.map{ case(v, i) =>
78          if (wakeUpSourceIdx.contains(i)) v := true.B else v := false.B
79        }
80        m := vecMask
81      }
82      println(s"[BypassNetwork] ${x.bits.params.name} numRegSrc: ${x.bits.params.numRegSrc}")
83      VecInit(x.bits.l1ExuOH.getOrElse(
84        // TODO: remove tmp max 1 for fake HYU1
85        VecInit(Seq.fill(x.bits.params.numRegSrc max 1)(VecInit(0.U(ExuVec.width.W).asBools)))
86      ).zip(mask).map{ case (l,m) =>
87        VecInit(l.zip(m).map(x => x._1 && x._2))
88      })
89    }
90  )
91
92  private val forwardDataVec: Vec[UInt] = VecInit(
93    fromExus.map(x => ZeroExt(x.bits.data, RegDataMaxWidth))
94  )
95
96  private val bypassDataVec = VecInit(
97    fromExus.map(x => ZeroExt(RegEnable(x.bits.data, x.valid), RegDataMaxWidth))
98  )
99
100  private val intExuNum = params.intSchdParams.get.numExu
101  private val fpExuNum  = params.fpSchdParams.get.numExu
102  private val vfExuNum  = params.vfSchdParams.get.numExu
103  private val memExuNum = params.memSchdParams.get.numExu
104
105  println(s"[BypassNetwork] allExuNum: ${toExus.size} intExuNum: ${intExuNum} fpExuNum: ${fpExuNum} vfExuNum: ${vfExuNum} memExuNum: ${memExuNum}")
106
107  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)
108  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)
109
110  private val bypass2ValidVec3 = MixedVecInit(
111    fromDPsHasBypass2Sink.map(forwardOrBypassValidVec3(_)).map(exu => VecInit(exu.map(l1ExuOH =>
112      VecInit(fromDPsHasBypass2Source.map(l1ExuOH(_))).asUInt
113    )))
114  )
115  if(params.debugEn){
116    dontTouch(bypass2ValidVec3)
117  }
118  private val bypass2DateEn = VecInit(
119    fromExus.map(x => GatedValidRegNext(x.valid))
120  ).asUInt
121  private val bypass2DataVec = if (fromDPsHasBypass2Source.length == 0) VecInit(Seq(0.U)) else VecInit(
122    fromDPsHasBypass2Source.map(x => RegEnable(bypassDataVec(x), bypass2DateEn(x).asBool))
123  )
124
125  println(s"[BypassNetwork] HasBypass2SourceExuNum: ${fromDPsHasBypass2Source.size} HasBypass2SinkExuNum: ${fromDPsHasBypass2Sink.size} bypass2DataVecSize: ${bypass2DataVec.length}")
126  println(s"[BypassNetwork] HasBypass2SourceExu: ${fromDPsHasBypass2Source}")
127  println(s"[BypassNetwork] HasBypass2SinkExu: ${fromDPsHasBypass2Sink}")
128
129  toExus.zip(fromDPs).foreach { case (sink, source) =>
130    sink <> source
131  }
132
133  toExus.zipWithIndex.foreach { case (exuInput, exuIdx) =>
134    exuInput.bits.src.zipWithIndex.foreach { case (src, srcIdx) =>
135      val imm = ImmExtractor(
136        immInfo(exuIdx).imm,
137        immInfo(exuIdx).immType,
138        exuInput.bits.params.destDataBitsMax,
139        exuInput.bits.params.immType.map(_.litValue)
140      )
141      val immLoadSrc0 = SignExt(ImmUnion.U.toImm32(immInfo(exuIdx).imm(immInfo(exuIdx).imm.getWidth - 1, ImmUnion.I.len)), XLEN)
142      val exuParm = exuInput.bits.params
143      val isIntScheduler = exuParm.isIntExeUnit
144      val isReadVfRf= exuParm.readVfRf
145      val dataSource = exuInput.bits.dataSources(srcIdx)
146      val isWakeUpSink = params.allIssueParams.filter(_.exuBlockParams.contains(exuParm)).head.exuBlockParams.map(_.isIQWakeUpSink).reduce(_ || _)
147      val readForward = if (isWakeUpSink) dataSource.readForward else false.B
148      val readBypass = if (isWakeUpSink) dataSource.readBypass else false.B
149      val readZero = if (isIntScheduler) dataSource.readZero else false.B
150      val readV0 = if (srcIdx < 3 && isReadVfRf) dataSource.readV0 else false.B
151      val readRegOH = exuInput.bits.dataSources(srcIdx).readRegOH
152      val readImm = if (exuParm.immType.nonEmpty || exuParm.hasLoadExu) exuInput.bits.dataSources(srcIdx).readImm else false.B
153      val bypass2ExuIdx = fromDPsHasBypass2Sink.indexOf(exuIdx)
154      println(s"${exuParm.name}: bypass2ExuIdx is ${bypass2ExuIdx}")
155      val readBypass2 = if (bypass2ExuIdx >= 0) dataSource.readBypass2 else false.B
156      src := Mux1H(
157        Seq(
158          readForward    -> Mux1H(forwardOrBypassValidVec3(exuIdx)(srcIdx), forwardDataVec),
159          readBypass     -> Mux1H(forwardOrBypassValidVec3(exuIdx)(srcIdx), bypassDataVec),
160          readBypass2    -> (if (bypass2ExuIdx >= 0) Mux1H(bypass2ValidVec3(bypass2ExuIdx)(srcIdx), bypass2DataVec) else 0.U),
161          readZero       -> 0.U,
162          readV0         -> (if (srcIdx < 3 && isReadVfRf) exuInput.bits.src(3) else 0.U),
163          readRegOH      -> fromDPs(exuIdx).bits.src(srcIdx),
164          readImm        -> (if (exuParm.hasLoadExu && srcIdx == 0) immLoadSrc0 else imm)
165        )
166      )
167    }
168  }
169}
170