xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/BypassNetwork.scala (revision 98ad9267c7cbf1fd86c7c865e868c080f168bd06)
1package xiangshan.backend.datapath
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.{SignExt, ZeroExt}
7import xiangshan.{XSBundle, XSModule}
8import xiangshan.backend.BackendParams
9import xiangshan.backend.Bundles.{ExuBypassBundle, ExuInput, ExuOH, ExuOutput, ImmInfo}
10import xiangshan.backend.issue.{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 vfSchdParams = params.schdParams(VfScheduler())
18  private val memSchdParams = params.schdParams(MemScheduler())
19
20  val fromDataPath = new FromDataPath
21  val toExus = new ToExus
22  val fromExus = new FromExus
23
24  class FromDataPath extends Bundle {
25    val int: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(intSchdParams.genExuInputBundle)
26    val vf : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(vfSchdParams.genExuInputBundle)
27    val mem: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = Flipped(memSchdParams.genExuInputBundle)
28    val immInfo: Vec[ImmInfo] = Input(Vec(params.allExuParams.size, new ImmInfo))
29  }
30
31  class ToExus extends Bundle {
32    val int: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = intSchdParams.genExuInputBundle
33    val vf : MixedVec[MixedVec[DecoupledIO[ExuInput]]] = vfSchdParams.genExuInputBundle
34    val mem: MixedVec[MixedVec[DecoupledIO[ExuInput]]] = memSchdParams.genExuInputBundle
35  }
36
37  class FromExus extends Bundle {
38    val int: MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(intSchdParams.genExuBypassValidBundle)
39    val vf : MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(vfSchdParams.genExuBypassValidBundle)
40    val mem: MixedVec[MixedVec[ValidIO[ExuBypassBundle]]] = Flipped(memSchdParams.genExuBypassValidBundle)
41
42    def connectExuOutput(
43      getSinkVecN: FromExus => MixedVec[MixedVec[ValidIO[ExuBypassBundle]]]
44    )(
45      sourceVecN: MixedVec[MixedVec[DecoupledIO[ExuOutput]]]
46    ): Unit = {
47      getSinkVecN(this).zip(sourceVecN).foreach { case (sinkVec, sourcesVec) =>
48        sinkVec.zip(sourcesVec).foreach { case (sink, source) =>
49          sink.valid := source.valid
50          sink.bits.pdest := source.bits.pdest
51          sink.bits.data := source.bits.data
52        }
53      }
54    }
55  }
56}
57
58class BypassNetwork()(implicit p: Parameters, params: BackendParams) extends XSModule {
59  val io: BypassNetworkIO = IO(new BypassNetworkIO)
60
61  private val fromDPs: Seq[DecoupledIO[ExuInput]] = (io.fromDataPath.int ++ io.fromDataPath.vf ++ io.fromDataPath.mem).flatten.toSeq
62  private val fromExus: Seq[ValidIO[ExuBypassBundle]] = (io.fromExus.int ++ io.fromExus.vf ++ io.fromExus.mem).flatten.toSeq
63  private val toExus: Seq[DecoupledIO[ExuInput]] = (io.toExus.int ++ io.toExus.vf ++ io.toExus.mem).flatten.toSeq
64  private val immInfo = io.fromDataPath.immInfo
65
66  // (exuIdx, srcIdx, bypassExuIdx)
67  private val forwardOrBypassValidVec3: MixedVec[Vec[UInt]] = MixedVecInit(
68    fromDPs.map { (x: DecoupledIO[ExuInput]) =>
69      println(s"[tmp-BypassNetwork] ${x.bits.params.name} numRegSrc: ${x.bits.params.numRegSrc}")
70      x.bits.l1ExuOH.getOrElse(
71        // TODO: remove tmp max 1 for fake HYU1
72        VecInit(Seq.fill(x.bits.params.numRegSrc max 1)(0.U(ExuOH.width.W)))
73      )
74    }
75  )
76
77  private val forwardDataVec: Vec[UInt] = VecInit(
78    fromExus.map(x => ZeroExt(x.bits.data, RegDataMaxWidth))
79  )
80
81  private val bypassDataVec = VecInit(
82    fromExus.map(x => ZeroExt(RegEnable(x.bits.data, x.valid), RegDataMaxWidth))
83  )
84
85  toExus.zip(fromDPs).foreach { case (sink, source) =>
86    sink <> source
87  }
88
89  toExus.zipWithIndex.foreach { case (exuInput, exuIdx) =>
90    exuInput.bits.src.zipWithIndex.foreach { case (src, srcIdx) =>
91      val imm = ImmExtractor(
92        immInfo(exuIdx).imm,
93        immInfo(exuIdx).immType,
94        exuInput.bits.params.dataBitsMax,
95        exuInput.bits.params.immType.map(_.litValue)
96      )
97      val immLoadSrc0 = SignExt(ImmUnion.U.toImm32(immInfo(exuIdx).imm(immInfo(exuIdx).imm.getWidth - 1, ImmUnion.I.len)), XLEN)
98      val exuParm = exuInput.bits.params
99      val isIntScheduler = exuParm.schdType.isInstanceOf[IntScheduler]
100      val dataSource = exuInput.bits.dataSources(srcIdx)
101      val isWakeUpSink = params.allIssueParams.filter(_.exuBlockParams.contains(exuParm)).head.exuBlockParams.map(_.isIQWakeUpSink).reduce(_ || _)
102      val readForward = if (isWakeUpSink) dataSource.readForward else false.B
103      val readBypass = if (isWakeUpSink) dataSource.readBypass else false.B
104      val readZero = if (isIntScheduler) dataSource.readZero else false.B
105      val readAnotherReg = if (isIntScheduler && exuParm.numRegSrc == 2 && srcIdx==1) dataSource.readAnotherReg else false.B
106      val readRegOH = exuInput.bits.dataSources(srcIdx).readRegOH
107      val readImm = if (exuParm.immType.nonEmpty || exuParm.hasLoadFu || exuParm.hasHyldaFu) exuInput.bits.dataSources(srcIdx).readImm else false.B
108      src := Mux1H(
109        Seq(
110          readForward    -> Mux1H(forwardOrBypassValidVec3(exuIdx)(srcIdx), forwardDataVec),
111          readBypass     -> Mux1H(forwardOrBypassValidVec3(exuIdx)(srcIdx), bypassDataVec),
112          readZero       -> 0.U,
113//          readAnotherReg -> fromDPs(exuIdx).bits.src(0),
114          readRegOH      -> fromDPs(exuIdx).bits.src(srcIdx),
115          readImm        -> (if (exuInput.bits.params.hasLoadExu && srcIdx == 0) immLoadSrc0 else imm)
116        )
117      )
118    }
119  }
120}
121