xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/WbArbiter.scala (revision 08373300e7dc356da02def6f35eae78b429872a7)
1730cfbc0SXuan Hupackage xiangshan.backend.datapath
2730cfbc0SXuan Hu
383ba63b3SXuan Huimport org.chipsalliance.cde.config.Parameters
4730cfbc0SXuan Huimport chisel3._
5730cfbc0SXuan Huimport chisel3.util._
6*08373300SAnzoimport difftest.{DiffFpWriteback, DiffIntWriteback, DiffVecV0Writeback, DiffVecWriteback, DifftestModule}
7bb2f3f51STang Haojinimport utility.XSError
8730cfbc0SXuan Huimport xiangshan.backend.BackendParams
9730cfbc0SXuan Huimport xiangshan.backend.Bundles.{ExuOutput, WriteBackBundle}
1045d40ce7Ssinsanctionimport xiangshan.backend.datapath.DataConfig._
11730cfbc0SXuan Huimport xiangshan.backend.regfile.RfWritePortWithConfig
12730cfbc0SXuan Huimport xiangshan.{Redirect, XSBundle, XSModule}
1345d40ce7Ssinsanctionimport xiangshan.SrcType.v0
14e43bb916SXuan Huimport xiangshan.backend.fu.vector.Bundles.Vstart
15730cfbc0SXuan Hu
16b08b7dc3Sfdyclass WbArbiterDispatcherIO[T <: Data](private val gen: T, n: Int) extends Bundle {
17b08b7dc3Sfdy  val in = Flipped(DecoupledIO(gen))
18b08b7dc3Sfdy
19b08b7dc3Sfdy  val out = Vec(n, DecoupledIO(gen))
20b08b7dc3Sfdy}
21b08b7dc3Sfdy
22c1e19666Sxiaofeibao-xjtuclass WbArbiterDispatcher[T <: Data](private val gen: T, n: Int, acceptCond: T => (Seq[Bool], Bool))
23b08b7dc3Sfdy                           (implicit p: Parameters)
24b08b7dc3Sfdy  extends Module {
25b08b7dc3Sfdy
26b08b7dc3Sfdy  val io = IO(new WbArbiterDispatcherIO(gen, n))
27b08b7dc3Sfdy
28c1e19666Sxiaofeibao-xjtu  private val acceptVec: Vec[Bool] = VecInit(acceptCond(io.in.bits)._1)
29b08b7dc3Sfdy
30c83747bfSYangyu Chen  XSError(io.in.valid && PopCount(acceptVec) > 1.U, p"[ExeUnit] accept vec should no more than 1, ${Binary(acceptVec.asUInt)} ")
31b08b7dc3Sfdy
32b08b7dc3Sfdy  io.out.zipWithIndex.foreach { case (out, i) =>
33b08b7dc3Sfdy    out.valid := acceptVec(i) && io.in.valid
34b08b7dc3Sfdy    out.bits := io.in.bits
35b08b7dc3Sfdy  }
36b08b7dc3Sfdy
37c1e19666Sxiaofeibao-xjtu  io.in.ready := Cat(io.out.zip(acceptVec).map{ case(out, canAccept) => out.ready && canAccept}).orR || acceptCond(io.in.bits)._2
38b08b7dc3Sfdy}
39b08b7dc3Sfdy
40730cfbc0SXuan Huclass WbArbiterIO()(implicit p: Parameters, params: WbArbiterParams) extends XSBundle {
41730cfbc0SXuan Hu  val flush = Flipped(ValidIO(new Redirect))
42730cfbc0SXuan Hu  val in: MixedVec[DecoupledIO[WriteBackBundle]] = Flipped(params.genInput)
43730cfbc0SXuan Hu  val out: MixedVec[ValidIO[WriteBackBundle]] = params.genOutput
44730cfbc0SXuan Hu
4583ba63b3SXuan Hu  def inGroup: Map[Int, Seq[DecoupledIO[WriteBackBundle]]] = in.groupBy(_.bits.params.port).map(x => (x._1, x._2.sortBy(_.bits.params.priority).toSeq))
46730cfbc0SXuan Hu}
47730cfbc0SXuan Hu
4845d40ce7Ssinsanctionclass RealWBCollideChecker(params: WbArbiterParams)(implicit p: Parameters) extends XSModule {
49730cfbc0SXuan Hu  val io = IO(new WbArbiterIO()(p, params))
50bcf0356aSXuan Hu
5183ba63b3SXuan Hu  private val inGroup: Map[Int, Seq[DecoupledIO[WriteBackBundle]]] = io.inGroup
52730cfbc0SXuan Hu
5347af51e7Ssinsanction  private val arbiters: Seq[Option[RealWBArbiter[WriteBackBundle]]] = Seq.tabulate(params.numOut) { x => {
54730cfbc0SXuan Hu    if (inGroup.contains(x)) {
5547af51e7Ssinsanction      Some(Module(new RealWBArbiter(new WriteBackBundle(inGroup.values.head.head.bits.params, backendParams), inGroup(x).length)))
56730cfbc0SXuan Hu    } else {
57730cfbc0SXuan Hu      None
58730cfbc0SXuan Hu    }
59730cfbc0SXuan Hu  }}
60730cfbc0SXuan Hu
61730cfbc0SXuan Hu  arbiters.zipWithIndex.foreach { case (arb, i) =>
62730cfbc0SXuan Hu    if (arb.nonEmpty) {
63730cfbc0SXuan Hu      arb.get.io.in.zip(inGroup(i)).foreach { case (arbIn, wbIn) =>
64730cfbc0SXuan Hu        arbIn <> wbIn
65730cfbc0SXuan Hu      }
66730cfbc0SXuan Hu    }
67730cfbc0SXuan Hu  }
68730cfbc0SXuan Hu
69730cfbc0SXuan Hu  io.out.zip(arbiters).foreach { case (wbOut, arb) =>
70730cfbc0SXuan Hu    if (arb.nonEmpty) {
71730cfbc0SXuan Hu      val arbOut = arb.get.io.out
72730cfbc0SXuan Hu      arbOut.ready := true.B
73730cfbc0SXuan Hu      wbOut.valid := arbOut.valid
74730cfbc0SXuan Hu      wbOut.bits := arbOut.bits
75730cfbc0SXuan Hu    } else {
76730cfbc0SXuan Hu      wbOut := 0.U.asTypeOf(wbOut)
77730cfbc0SXuan Hu    }
78730cfbc0SXuan Hu  }
79730cfbc0SXuan Hu
80730cfbc0SXuan Hu  def getInOutMap: Map[Int, Int] = {
81730cfbc0SXuan Hu    (params.wbCfgs.indices zip params.wbCfgs.map(_.port)).toMap
82730cfbc0SXuan Hu  }
83730cfbc0SXuan Hu}
84730cfbc0SXuan Hu
85730cfbc0SXuan Huclass WbDataPathIO()(implicit p: Parameters, params: BackendParams) extends XSBundle {
86730cfbc0SXuan Hu  val flush = Flipped(ValidIO(new Redirect()))
87730cfbc0SXuan Hu
88730cfbc0SXuan Hu  val fromTop = new Bundle {
89730cfbc0SXuan Hu    val hartId = Input(UInt(8.W))
90730cfbc0SXuan Hu  }
91730cfbc0SXuan Hu
92730cfbc0SXuan Hu  val fromIntExu: MixedVec[MixedVec[DecoupledIO[ExuOutput]]] = Flipped(params.intSchdParams.get.genExuOutputDecoupledBundle)
93730cfbc0SXuan Hu
9460f0c5aeSxiaofeibao  val fromFpExu: MixedVec[MixedVec[DecoupledIO[ExuOutput]]] = Flipped(params.fpSchdParams.get.genExuOutputDecoupledBundle)
9560f0c5aeSxiaofeibao
96730cfbc0SXuan Hu  val fromVfExu: MixedVec[MixedVec[DecoupledIO[ExuOutput]]] = Flipped(params.vfSchdParams.get.genExuOutputDecoupledBundle)
97730cfbc0SXuan Hu
98730cfbc0SXuan Hu  val fromMemExu: MixedVec[MixedVec[DecoupledIO[ExuOutput]]] = Flipped(params.memSchdParams.get.genExuOutputDecoupledBundle)
99730cfbc0SXuan Hu
100e43bb916SXuan Hu  val fromCSR = Input(new Bundle {
101e43bb916SXuan Hu    val vstart = Vstart()
102e43bb916SXuan Hu  })
103e43bb916SXuan Hu
10439c59369SXuan Hu  val toIntPreg = Flipped(MixedVec(Vec(params.numPregWb(IntData()),
105730cfbc0SXuan Hu    new RfWritePortWithConfig(params.intPregParams.dataCfg, params.intPregParams.addrWidth))))
106730cfbc0SXuan Hu
10760f0c5aeSxiaofeibao  val toFpPreg = Flipped(MixedVec(Vec(params.numPregWb(FpData()),
10860f0c5aeSxiaofeibao    new RfWritePortWithConfig(params.fpPregParams.dataCfg, params.fpPregParams.addrWidth))))
10960f0c5aeSxiaofeibao
11039c59369SXuan Hu  val toVfPreg = Flipped(MixedVec(Vec(params.numPregWb(VecData()),
111730cfbc0SXuan Hu    new RfWritePortWithConfig(params.vfPregParams.dataCfg, params.vfPregParams.addrWidth))))
112730cfbc0SXuan Hu
11345d40ce7Ssinsanction  val toV0Preg = Flipped(MixedVec(Vec(params.numPregWb(V0Data()),
11445d40ce7Ssinsanction    new RfWritePortWithConfig(params.v0PregParams.dataCfg, params.v0PregParams.addrWidth))))
11545d40ce7Ssinsanction
11645d40ce7Ssinsanction  val toVlPreg = Flipped(MixedVec(Vec(params.numPregWb(VlData()),
11745d40ce7Ssinsanction    new RfWritePortWithConfig(params.vlPregParams.dataCfg, params.vlPregParams.addrWidth))))
11845d40ce7Ssinsanction
119730cfbc0SXuan Hu  val toCtrlBlock = new Bundle {
120730cfbc0SXuan Hu    val writeback: MixedVec[ValidIO[ExuOutput]] = params.genWrite2CtrlBundles
121730cfbc0SXuan Hu  }
122730cfbc0SXuan Hu}
123730cfbc0SXuan Hu
124730cfbc0SXuan Huclass WbDataPath(params: BackendParams)(implicit p: Parameters) extends XSModule {
125730cfbc0SXuan Hu  val io = IO(new WbDataPathIO()(p, params))
126730cfbc0SXuan Hu
127e703da02SzhanglyGit  // split
128a4d1b2d1Sgood-circle  val fromExuPre = collection.mutable.Seq() ++ (io.fromIntExu ++ io.fromFpExu ++ io.fromVfExu ++ io.fromMemExu).flatten
1291f3d1b4dSXuan Hu  val fromExuVld: Seq[DecoupledIO[ExuOutput]] = fromExuPre.filter(_.bits.params.hasVLoadFu).toSeq
130b7c799beSzhanglyGit  val vldMgu: Seq[VldMergeUnit] = fromExuVld.map(x => Module(new VldMergeUnit(x.bits.params)))
131b7c799beSzhanglyGit  vldMgu.zip(fromExuVld).foreach{ case (mgu, exu) =>
132b7c799beSzhanglyGit    mgu.io.flush := io.flush
133b7c799beSzhanglyGit    mgu.io.writeback <> exu
134e43bb916SXuan Hu    // Since xs will flush pipe, when vstart is not 0 and execute vector mem inst, the value of vstart in CSR is the
135e43bb916SXuan Hu    // first element of this vector instruction. When exception occurs, the vstart in writeback bundle is the new one,
136e43bb916SXuan Hu    // So this vstart should never be used as the beginning of vector mem operation.
137e43bb916SXuan Hu    mgu.io.writeback.bits.vls.get.vpu.vstart := io.fromCSR.vstart
138b7c799beSzhanglyGit  }
139b7c799beSzhanglyGit  val wbReplaceVld = fromExuPre
140b7c799beSzhanglyGit  val vldIdx: Seq[Int] = vldMgu.map(x => fromExuPre.indexWhere(_.bits.params == x.params))
141b7c799beSzhanglyGit  println("vldIdx: " + vldIdx)
142b7c799beSzhanglyGit  vldIdx.zip(vldMgu).foreach{ case (id, wb) =>
143b7c799beSzhanglyGit    wbReplaceVld.update(id, wb.io.writebackAfterMerge)
144b7c799beSzhanglyGit  }
145b7c799beSzhanglyGit  val fromExu = Wire(chiselTypeOf(MixedVecInit(wbReplaceVld.toSeq)))
14646908ecfSXuan Hu
14746908ecfSXuan Hu  // io.fromExuPre ------------------------------------------------------------> fromExu
14846908ecfSXuan Hu  //               \                                                         /
14946908ecfSXuan Hu  //                -> vldMgu.io.writeback -> vldMgu.io.writebackAfterMerge /
1506d11c058Ssinsanction  (fromExu zip wbReplaceVld).foreach { case (sink, source) =>
1516d11c058Ssinsanction    sink.valid := source.valid
1526d11c058Ssinsanction    sink.bits := source.bits
1536d11c058Ssinsanction    source.ready := sink.ready
1546d11c058Ssinsanction  }
15546908ecfSXuan Hu
1566d11c058Ssinsanction  // fromExu -> ArbiterInput
157c1e19666Sxiaofeibao-xjtu  val intArbiterInputsWire = Wire(chiselTypeOf(fromExu))
1586d11c058Ssinsanction  val intArbiterInputsWireY = intArbiterInputsWire.filter(_.bits.params.writeIntRf)
1596d11c058Ssinsanction  val intArbiterInputsWireN = intArbiterInputsWire.filterNot(_.bits.params.writeIntRf)
1606d11c058Ssinsanction
16160f0c5aeSxiaofeibao  val fpArbiterInputsWire = Wire(chiselTypeOf(fromExu))
16260f0c5aeSxiaofeibao  val fpArbiterInputsWireY = fpArbiterInputsWire.filter(_.bits.params.writeFpRf)
16360f0c5aeSxiaofeibao  val fpArbiterInputsWireN = fpArbiterInputsWire.filterNot(_.bits.params.writeFpRf)
16460f0c5aeSxiaofeibao
1656d11c058Ssinsanction  val vfArbiterInputsWire = Wire(chiselTypeOf(fromExu))
1666d11c058Ssinsanction  val vfArbiterInputsWireY = vfArbiterInputsWire.filter(_.bits.params.writeVfRf)
1676d11c058Ssinsanction  val vfArbiterInputsWireN = vfArbiterInputsWire.filterNot(_.bits.params.writeVfRf)
168b08b7dc3Sfdy
16945d40ce7Ssinsanction  val v0ArbiterInputsWire = Wire(chiselTypeOf(fromExu))
17045d40ce7Ssinsanction  val v0ArbiterInputsWireY = v0ArbiterInputsWire.filter(_.bits.params.writeV0Rf)
17145d40ce7Ssinsanction  val v0ArbiterInputsWireN = v0ArbiterInputsWire.filterNot(_.bits.params.writeV0Rf)
17245d40ce7Ssinsanction
17345d40ce7Ssinsanction  val vlArbiterInputsWire = Wire(chiselTypeOf(fromExu))
17445d40ce7Ssinsanction  val vlArbiterInputsWireY = vlArbiterInputsWire.filter(_.bits.params.writeVlRf)
17545d40ce7Ssinsanction  val vlArbiterInputsWireN = vlArbiterInputsWire.filterNot(_.bits.params.writeVlRf)
17645d40ce7Ssinsanction
177c1e19666Sxiaofeibao-xjtu  def acceptCond(exuOutput: ExuOutput): (Seq[Bool], Bool) = {
17845d40ce7Ssinsanction    val intWen = exuOutput.intWen.getOrElse(false.B)
17945d40ce7Ssinsanction    val fpwen  = exuOutput.fpWen.getOrElse(false.B)
18045d40ce7Ssinsanction    val vecWen = exuOutput.vecWen.getOrElse(false.B)
18145d40ce7Ssinsanction    val v0Wen  = exuOutput.v0Wen.getOrElse(false.B)
18245d40ce7Ssinsanction    val vlWen  = exuOutput.vlWen.getOrElse(false.B)
18345d40ce7Ssinsanction    (Seq(intWen, fpwen, vecWen, v0Wen, vlWen), !intWen && !fpwen && !vecWen && !v0Wen && !vlWen)
184b08b7dc3Sfdy  }
185b08b7dc3Sfdy
18645d40ce7Ssinsanction  intArbiterInputsWire.zip(fpArbiterInputsWire).zip(vfArbiterInputsWire).zip(v0ArbiterInputsWire).zip(vlArbiterInputsWire).zip(fromExu).foreach {
18745d40ce7Ssinsanction    case (((((intArbiterInput, fpArbiterInput), vfArbiterInput), v0ArbiterInput), vlArbiterInput), exuOut) =>
1886d11c058Ssinsanction      val writeCond = acceptCond(exuOut.bits)
1892e49ee76Ssinsanction      val intWrite = Wire(Bool())
19060f0c5aeSxiaofeibao      val fpWrite = Wire(Bool())
1912e49ee76Ssinsanction      val vfWrite = Wire(Bool())
19245d40ce7Ssinsanction      val v0Write = Wire(Bool())
19345d40ce7Ssinsanction      val vlWrite = Wire(Bool())
1942e49ee76Ssinsanction      val notWrite = Wire(Bool())
1952e49ee76Ssinsanction
1962e49ee76Ssinsanction      intWrite := exuOut.valid && writeCond._1(0)
19760f0c5aeSxiaofeibao      fpWrite := exuOut.valid && writeCond._1(1)
19860f0c5aeSxiaofeibao      vfWrite := exuOut.valid && writeCond._1(2)
19945d40ce7Ssinsanction      v0Write := exuOut.valid && writeCond._1(3)
20045d40ce7Ssinsanction      vlWrite := exuOut.valid && writeCond._1(4)
2012e49ee76Ssinsanction      notWrite := writeCond._2
2026d11c058Ssinsanction
2036d11c058Ssinsanction      intArbiterInput.valid := intWrite
2046d11c058Ssinsanction      intArbiterInput.bits := exuOut.bits
20560f0c5aeSxiaofeibao      fpArbiterInput.valid := fpWrite
20660f0c5aeSxiaofeibao      fpArbiterInput.bits := exuOut.bits
2076d11c058Ssinsanction      vfArbiterInput.valid := vfWrite
2086d11c058Ssinsanction      vfArbiterInput.bits := exuOut.bits
20945d40ce7Ssinsanction      v0ArbiterInput.valid := v0Write
21045d40ce7Ssinsanction      v0ArbiterInput.bits := exuOut.bits
21145d40ce7Ssinsanction      vlArbiterInput.valid := vlWrite
21245d40ce7Ssinsanction      vlArbiterInput.bits := exuOut.bits
2136d11c058Ssinsanction
2142e49ee76Ssinsanction      if (exuOut.bits.params.writeIntRf && exuOut.bits.params.isVfExeUnit) {
2152e49ee76Ssinsanction        intWrite := RegNext(exuOut.valid && writeCond._1(0))
2162e49ee76Ssinsanction        intArbiterInput.bits := RegEnable(exuOut.bits, exuOut.valid)
2172e49ee76Ssinsanction      }
2182e49ee76Ssinsanction
2196d11c058Ssinsanction      println(s"[WbDataPath] exu: ${exuOut.bits.params.exuIdx}, uncertain: ${exuOut.bits.params.hasUncertainLatency}, certain: ${exuOut.bits.params.latencyCertain}")
2206d11c058Ssinsanction
2216d11c058Ssinsanction      // only EXUs with uncertain latency need result of arbiter
2226d11c058Ssinsanction      // the result data can be maintained until getting success in arbiter
2236d11c058Ssinsanction      if (exuOut.bits.params.hasUncertainLatency) {
22445d40ce7Ssinsanction        exuOut.ready := intArbiterInput.ready && intWrite || fpArbiterInput.ready && fpWrite || vfArbiterInput.ready && vfWrite || v0ArbiterInput.ready && v0Write || vlArbiterInput.ready && vlWrite || notWrite
2256d11c058Ssinsanction      } else {
2266d11c058Ssinsanction        exuOut.ready := true.B
2276d11c058Ssinsanction
2286d11c058Ssinsanction        // for EXUs with certain latency, if the request fails in arbiter, the result data will be permanently lost
2296d11c058Ssinsanction        when (intWrite) {
2306d11c058Ssinsanction          assert(intArbiterInput.ready, s"exu ${exuOut.bits.params.exuIdx} failed to write int regfile\n")
2316d11c058Ssinsanction        }
23260f0c5aeSxiaofeibao        when(fpWrite) {
23360f0c5aeSxiaofeibao          assert(fpArbiterInput.ready, s"exu ${exuOut.bits.params.exuIdx} failed to write fp regfile\n")
23460f0c5aeSxiaofeibao        }
2356d11c058Ssinsanction        when (vfWrite) {
2366d11c058Ssinsanction          assert(vfArbiterInput.ready, s"exu ${exuOut.bits.params.exuIdx} failed to write vf regfile\n")
2376d11c058Ssinsanction        }
23845d40ce7Ssinsanction        when (v0Write) {
23945d40ce7Ssinsanction          assert(v0ArbiterInput.ready, s"exu ${exuOut.bits.params.exuIdx} failed to write v0 regfile\n")
24045d40ce7Ssinsanction        }
24145d40ce7Ssinsanction        when (vlWrite) {
24245d40ce7Ssinsanction          assert(vlArbiterInput.ready, s"exu ${exuOut.bits.params.exuIdx} failed to write vl regfile\n")
24345d40ce7Ssinsanction        }
2446d11c058Ssinsanction      }
2456d11c058Ssinsanction      // the ports not writting back pregs are always ready
2466d11c058Ssinsanction      // the ports set highest priority are always ready
2476d11c058Ssinsanction      if (exuOut.bits.params.hasNoDataWB || exuOut.bits.params.isHighestWBPriority) {
2486d11c058Ssinsanction        exuOut.ready := true.B
249b08b7dc3Sfdy      }
250b08b7dc3Sfdy  }
251b08b7dc3Sfdy  intArbiterInputsWireN.foreach(_.ready := false.B)
25260f0c5aeSxiaofeibao  fpArbiterInputsWireN.foreach(_.ready := false.B)
253b08b7dc3Sfdy  vfArbiterInputsWireN.foreach(_.ready := false.B)
25445d40ce7Ssinsanction  v0ArbiterInputsWireN.foreach(_.ready := false.B)
25545d40ce7Ssinsanction  vlArbiterInputsWireN.foreach(_.ready := false.B)
256b08b7dc3Sfdy
257730cfbc0SXuan Hu  println(s"[WbDataPath] write int preg: " +
258730cfbc0SXuan Hu    s"IntExu(${io.fromIntExu.flatten.count(_.bits.params.writeIntRf)}) " +
25960f0c5aeSxiaofeibao    s"FpExu(${io.fromFpExu.flatten.count(_.bits.params.writeIntRf)}) " +
260730cfbc0SXuan Hu    s"VfExu(${io.fromVfExu.flatten.count(_.bits.params.writeIntRf)}) " +
261730cfbc0SXuan Hu    s"MemExu(${io.fromMemExu.flatten.count(_.bits.params.writeIntRf)})"
262730cfbc0SXuan Hu  )
26360f0c5aeSxiaofeibao  println(s"[WbDataPath] write fp preg: " +
26460f0c5aeSxiaofeibao    s"IntExu(${io.fromIntExu.flatten.count(_.bits.params.writeFpRf)}) " +
26560f0c5aeSxiaofeibao    s"FpExu(${io.fromFpExu.flatten.count(_.bits.params.writeFpRf)}) " +
26660f0c5aeSxiaofeibao    s"VfExu(${io.fromVfExu.flatten.count(_.bits.params.writeFpRf)}) " +
26760f0c5aeSxiaofeibao    s"MemExu(${io.fromMemExu.flatten.count(_.bits.params.writeFpRf)})"
26860f0c5aeSxiaofeibao  )
269730cfbc0SXuan Hu  println(s"[WbDataPath] write vf preg: " +
270730cfbc0SXuan Hu    s"IntExu(${io.fromIntExu.flatten.count(_.bits.params.writeVfRf)}) " +
27160f0c5aeSxiaofeibao    s"FpExu(${io.fromFpExu.flatten.count(_.bits.params.writeVfRf)}) " +
272730cfbc0SXuan Hu    s"VfExu(${io.fromVfExu.flatten.count(_.bits.params.writeVfRf)}) " +
273730cfbc0SXuan Hu    s"MemExu(${io.fromMemExu.flatten.count(_.bits.params.writeVfRf)})"
274730cfbc0SXuan Hu  )
27545d40ce7Ssinsanction  println(s"[WbDataPath] write v0 preg: " +
27645d40ce7Ssinsanction    s"IntExu(${io.fromIntExu.flatten.count(_.bits.params.writeV0Rf)}) " +
27745d40ce7Ssinsanction    s"FpExu(${io.fromFpExu.flatten.count(_.bits.params.writeV0Rf)}) " +
27845d40ce7Ssinsanction    s"VfExu(${io.fromVfExu.flatten.count(_.bits.params.writeV0Rf)}) " +
27945d40ce7Ssinsanction    s"MemExu(${io.fromMemExu.flatten.count(_.bits.params.writeV0Rf)})"
28045d40ce7Ssinsanction  )
28145d40ce7Ssinsanction  println(s"[WbDataPath] write vl preg: " +
28245d40ce7Ssinsanction    s"IntExu(${io.fromIntExu.flatten.count(_.bits.params.writeVlRf)}) " +
28345d40ce7Ssinsanction    s"FpExu(${io.fromFpExu.flatten.count(_.bits.params.writeVlRf)}) " +
28445d40ce7Ssinsanction    s"VfExu(${io.fromVfExu.flatten.count(_.bits.params.writeVlRf)}) " +
28545d40ce7Ssinsanction    s"MemExu(${io.fromMemExu.flatten.count(_.bits.params.writeVlRf)})"
28645d40ce7Ssinsanction  )
287730cfbc0SXuan Hu
2886d11c058Ssinsanction  // wb arbiter
28945d40ce7Ssinsanction  private val intWbArbiter = Module(new RealWBCollideChecker(params.getIntWbArbiterParams))
29045d40ce7Ssinsanction  private val fpWbArbiter = Module(new RealWBCollideChecker(params.getFpWbArbiterParams))
29145d40ce7Ssinsanction  private val vfWbArbiter = Module(new RealWBCollideChecker(params.getVfWbArbiterParams))
29245d40ce7Ssinsanction  private val v0WbArbiter = Module(new RealWBCollideChecker(params.getV0WbArbiterParams))
29345d40ce7Ssinsanction  private val vlWbArbiter = Module(new RealWBCollideChecker(params.getVlWbArbiterParams))
294730cfbc0SXuan Hu  println(s"[WbDataPath] int preg write back port num: ${intWbArbiter.io.out.size}, active port: ${intWbArbiter.io.inGroup.keys.toSeq.sorted}")
29560f0c5aeSxiaofeibao  println(s"[WbDataPath] fp preg write back port num: ${fpWbArbiter.io.out.size}, active port: ${fpWbArbiter.io.inGroup.keys.toSeq.sorted}")
296730cfbc0SXuan Hu  println(s"[WbDataPath] vf preg write back port num: ${vfWbArbiter.io.out.size}, active port: ${vfWbArbiter.io.inGroup.keys.toSeq.sorted}")
29745d40ce7Ssinsanction  println(s"[WbDataPath] v0 preg write back port num: ${v0WbArbiter.io.out.size}, active port: ${v0WbArbiter.io.inGroup.keys.toSeq.sorted}")
29845d40ce7Ssinsanction  println(s"[WbDataPath] vl preg write back port num: ${vlWbArbiter.io.out.size}, active port: ${vlWbArbiter.io.inGroup.keys.toSeq.sorted}")
299730cfbc0SXuan Hu
300730cfbc0SXuan Hu  // module assign
301730cfbc0SXuan Hu  intWbArbiter.io.flush <> io.flush
30260f0c5aeSxiaofeibao  require(intWbArbiter.io.in.size == intArbiterInputsWireY.size, s"intWbArbiter input size: ${intWbArbiter.io.in.size}, all int wb size: ${intArbiterInputsWireY.size}")
303b08b7dc3Sfdy  intWbArbiter.io.in.zip(intArbiterInputsWireY).foreach { case (arbiterIn, in) =>
3045c5405a5SXuan Hu    arbiterIn.valid := in.valid && in.bits.intWen.get
305730cfbc0SXuan Hu    in.ready := arbiterIn.ready
306618b89e6Slewislzh    arbiterIn.bits.fromExuOutput(in.bits, "int")
307730cfbc0SXuan Hu  }
308730cfbc0SXuan Hu  private val intWbArbiterOut = intWbArbiter.io.out
309730cfbc0SXuan Hu
31060f0c5aeSxiaofeibao  fpWbArbiter.io.flush <> io.flush
31160f0c5aeSxiaofeibao  require(fpWbArbiter.io.in.size == fpArbiterInputsWireY.size, s"fpWbArbiter input size: ${fpWbArbiter.io.in.size}, all fp wb size: ${fpArbiterInputsWireY.size}")
31260f0c5aeSxiaofeibao  fpWbArbiter.io.in.zip(fpArbiterInputsWireY).foreach { case (arbiterIn, in) =>
31360f0c5aeSxiaofeibao    arbiterIn.valid := in.valid && (in.bits.fpWen.getOrElse(false.B))
31460f0c5aeSxiaofeibao    in.ready := arbiterIn.ready
315618b89e6Slewislzh    arbiterIn.bits.fromExuOutput(in.bits, "fp")
31660f0c5aeSxiaofeibao  }
31760f0c5aeSxiaofeibao  private val fpWbArbiterOut = fpWbArbiter.io.out
31860f0c5aeSxiaofeibao
319730cfbc0SXuan Hu  vfWbArbiter.io.flush <> io.flush
320b08b7dc3Sfdy  require(vfWbArbiter.io.in.size == vfArbiterInputsWireY.size, s"vfWbArbiter input size: ${vfWbArbiter.io.in.size}, all vf wb size: ${vfArbiterInputsWireY.size}")
321b08b7dc3Sfdy  vfWbArbiter.io.in.zip(vfArbiterInputsWireY).foreach { case (arbiterIn, in) =>
32260f0c5aeSxiaofeibao    arbiterIn.valid := in.valid && (in.bits.vecWen.getOrElse(false.B))
323730cfbc0SXuan Hu    in.ready := arbiterIn.ready
324618b89e6Slewislzh    arbiterIn.bits.fromExuOutput(in.bits, "vf")
325730cfbc0SXuan Hu  }
326730cfbc0SXuan Hu  private val vfWbArbiterOut = vfWbArbiter.io.out
327730cfbc0SXuan Hu
32845d40ce7Ssinsanction  v0WbArbiter.io.flush <> io.flush
32945d40ce7Ssinsanction  require(v0WbArbiter.io.in.size == v0ArbiterInputsWireY.size, s"v0WbArbiter input size: ${v0WbArbiter.io.in.size}, all v0 wb size: ${v0ArbiterInputsWireY.size}")
33045d40ce7Ssinsanction  v0WbArbiter.io.in.zip(v0ArbiterInputsWireY).foreach { case (arbiterIn, in) =>
33145d40ce7Ssinsanction    arbiterIn.valid := in.valid && (in.bits.v0Wen.getOrElse(false.B))
33245d40ce7Ssinsanction    in.ready := arbiterIn.ready
333618b89e6Slewislzh    arbiterIn.bits.fromExuOutput(in.bits, "v0")
33445d40ce7Ssinsanction  }
33545d40ce7Ssinsanction  private val v0WbArbiterOut = v0WbArbiter.io.out
33645d40ce7Ssinsanction
33745d40ce7Ssinsanction  vlWbArbiter.io.flush <> io.flush
33845d40ce7Ssinsanction  require(vlWbArbiter.io.in.size == vlArbiterInputsWireY.size, s"vlWbArbiter input size: ${vlWbArbiter.io.in.size}, all vl wb size: ${vlArbiterInputsWireY.size}")
33945d40ce7Ssinsanction  vlWbArbiter.io.in.zip(vlArbiterInputsWireY).foreach { case (arbiterIn, in) =>
34045d40ce7Ssinsanction    arbiterIn.valid := in.valid && (in.bits.vlWen.getOrElse(false.B))
34145d40ce7Ssinsanction    in.ready := arbiterIn.ready
342618b89e6Slewislzh    arbiterIn.bits.fromExuOutput(in.bits, "vl")
34345d40ce7Ssinsanction  }
34445d40ce7Ssinsanction  private val vlWbArbiterOut = vlWbArbiter.io.out
34545d40ce7Ssinsanction
3466d11c058Ssinsanction  // WB -> CtrlBlock
34783ba63b3SXuan Hu  private val intExuInputs = io.fromIntExu.flatten.toSeq
34883ba63b3SXuan Hu  private val intExuWBs = WireInit(MixedVecInit(intExuInputs))
34960f0c5aeSxiaofeibao  private val fpExuInputs = io.fromFpExu.flatten.toSeq
35060f0c5aeSxiaofeibao  private val fpExuWBs = WireInit(MixedVecInit(fpExuInputs))
35183ba63b3SXuan Hu  private val vfExuInputs = io.fromVfExu.flatten.toSeq
35283ba63b3SXuan Hu  private val vfExuWBs = WireInit(MixedVecInit(vfExuInputs))
35383ba63b3SXuan Hu  private val memExuInputs = io.fromMemExu.flatten.toSeq
35483ba63b3SXuan Hu  private val memExuWBs = WireInit(MixedVecInit(memExuInputs))
355730cfbc0SXuan Hu
356730cfbc0SXuan Hu  // only fired port can write back to ctrl block
357730cfbc0SXuan Hu  (intExuWBs zip intExuInputs).foreach { case (wb, input) => wb.valid := input.fire }
35860f0c5aeSxiaofeibao  (fpExuWBs zip fpExuInputs).foreach { case (wb, input) => wb.valid := input.fire }
359730cfbc0SXuan Hu  (vfExuWBs zip vfExuInputs).foreach { case (wb, input) => wb.valid := input.fire }
360730cfbc0SXuan Hu  (memExuWBs zip memExuInputs).foreach { case (wb, input) => wb.valid := input.fire }
361730cfbc0SXuan Hu
362730cfbc0SXuan Hu  // io assign
36383ba63b3SXuan Hu  private val toIntPreg: MixedVec[RfWritePortWithConfig] = MixedVecInit(intWbArbiterOut.map(x => x.bits.asIntRfWriteBundle(x.fire)).toSeq)
36460f0c5aeSxiaofeibao  private val toFpPreg: MixedVec[RfWritePortWithConfig] = MixedVecInit(fpWbArbiterOut.map(x => x.bits.asFpRfWriteBundle(x.fire)).toSeq)
36583ba63b3SXuan Hu  private val toVfPreg: MixedVec[RfWritePortWithConfig] = MixedVecInit(vfWbArbiterOut.map(x => x.bits.asVfRfWriteBundle(x.fire)).toSeq)
36645d40ce7Ssinsanction  private val toV0Preg: MixedVec[RfWritePortWithConfig] = MixedVecInit(v0WbArbiterOut.map(x => x.bits.asV0RfWriteBundle(x.fire)).toSeq)
36745d40ce7Ssinsanction  private val toVlPreg: MixedVec[RfWritePortWithConfig] = MixedVecInit(vlWbArbiterOut.map(x => x.bits.asVlRfWriteBundle(x.fire)).toSeq)
368730cfbc0SXuan Hu
36960f0c5aeSxiaofeibao  private val wb2Ctrl = intExuWBs ++ fpExuWBs ++ vfExuWBs ++ memExuWBs
370730cfbc0SXuan Hu
371730cfbc0SXuan Hu  io.toIntPreg := toIntPreg
37260f0c5aeSxiaofeibao  io.toFpPreg := toFpPreg
373730cfbc0SXuan Hu  io.toVfPreg := toVfPreg
37445d40ce7Ssinsanction  io.toV0Preg := toV0Preg
37545d40ce7Ssinsanction  io.toVlPreg := toVlPreg
376730cfbc0SXuan Hu  io.toCtrlBlock.writeback.zip(wb2Ctrl).foreach { case (sink, source) =>
377730cfbc0SXuan Hu    sink.valid := source.valid
378730cfbc0SXuan Hu    sink.bits := source.bits
379730cfbc0SXuan Hu    source.ready := true.B
380730cfbc0SXuan Hu  }
381730cfbc0SXuan Hu
3826d11c058Ssinsanction  // debug
3836d11c058Ssinsanction  if(backendParams.debugEn) {
3846d11c058Ssinsanction    dontTouch(intArbiterInputsWire)
38560f0c5aeSxiaofeibao    dontTouch(fpArbiterInputsWire)
3866d11c058Ssinsanction    dontTouch(vfArbiterInputsWire)
38745d40ce7Ssinsanction    dontTouch(v0ArbiterInputsWire)
38845d40ce7Ssinsanction    dontTouch(vlArbiterInputsWire)
3896d11c058Ssinsanction  }
3906d11c058Ssinsanction
3916d11c058Ssinsanction  // difftest
392730cfbc0SXuan Hu  if (env.EnableDifftest || env.AlwaysBasicDiff) {
393730cfbc0SXuan Hu    intWbArbiterOut.foreach(out => {
394a66aed53SXuan Hu      val difftest = DifftestModule(new DiffIntWriteback(IntPhyRegs))
39583ba63b3SXuan Hu      difftest.coreid := io.fromTop.hartId
39683ba63b3SXuan Hu      difftest.valid := out.fire && out.bits.rfWen
39783ba63b3SXuan Hu      difftest.address := out.bits.pdest
39883ba63b3SXuan Hu      difftest.data := out.bits.data
399730cfbc0SXuan Hu    })
400730cfbc0SXuan Hu  }
401730cfbc0SXuan Hu
402730cfbc0SXuan Hu  if (env.EnableDifftest || env.AlwaysBasicDiff) {
40360f0c5aeSxiaofeibao    fpWbArbiterOut.foreach(out => {
40460f0c5aeSxiaofeibao      val difftest = DifftestModule(new DiffFpWriteback(FpPhyRegs))
40583ba63b3SXuan Hu      difftest.coreid := io.fromTop.hartId
40683ba63b3SXuan Hu      difftest.valid := out.fire // all fp instr will write fp rf
40783ba63b3SXuan Hu      difftest.address := out.bits.pdest
40883ba63b3SXuan Hu      difftest.data := out.bits.data
409730cfbc0SXuan Hu    })
410730cfbc0SXuan Hu  }
411730cfbc0SXuan Hu
41260f0c5aeSxiaofeibao  if (env.EnableDifftest || env.AlwaysBasicDiff) {
41360f0c5aeSxiaofeibao    vfWbArbiterOut.foreach(out => {
41460f0c5aeSxiaofeibao      val difftest = DifftestModule(new DiffVecWriteback(VfPhyRegs))
41560f0c5aeSxiaofeibao      difftest.coreid := io.fromTop.hartId
41660f0c5aeSxiaofeibao      difftest.valid := out.fire
41760f0c5aeSxiaofeibao      difftest.address := out.bits.pdest
418*08373300SAnzo      difftest.data(0) := out.bits.data(63, 0)
419*08373300SAnzo      difftest.data(1) := out.bits.data(127, 64)
420*08373300SAnzo    })
421*08373300SAnzo  }
422*08373300SAnzo
423*08373300SAnzo  if (env.EnableDifftest || env.AlwaysBasicDiff) {
424*08373300SAnzo    v0WbArbiterOut.foreach(out => {
425*08373300SAnzo      val difftest = DifftestModule(new DiffVecV0Writeback(V0PhyRegs))
426*08373300SAnzo      difftest.coreid := io.fromTop.hartId
427*08373300SAnzo      difftest.valid := out.fire
428*08373300SAnzo      difftest.address := out.bits.pdest
429*08373300SAnzo      difftest.data(0) := out.bits.data(63, 0)
430*08373300SAnzo      difftest.data(1) := out.bits.data(127, 64)
43160f0c5aeSxiaofeibao    })
43260f0c5aeSxiaofeibao  }
433730cfbc0SXuan Hu}
434730cfbc0SXuan Hu
435730cfbc0SXuan Hu
436730cfbc0SXuan Hu
437730cfbc0SXuan Hu
438