xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/RFWBConflictChecker.scala (revision e4e52e7d0a79872a08d291b5ff115fb3c2cbe7d2)
139c59369SXuan Hupackage xiangshan.backend.datapath
239c59369SXuan Hu
383ba63b3SXuan Huimport org.chipsalliance.cde.config.Parameters
439c59369SXuan Huimport chisel3._
539c59369SXuan Huimport chisel3.util._
639c59369SXuan Huimport utils.OptionWrapper
739c59369SXuan Huimport utils.SeqUtils.MixedVec2
839c59369SXuan Huimport xiangshan.backend.BackendParams
9*e4e52e7dSsinsanctionimport xiangshan.backend.datapath.DataConfig._
1039c59369SXuan Huimport xiangshan.backend.datapath.WbConfig.{NoWB, PregWB}
1139c59369SXuan Huimport xiangshan.backend.regfile.PregParams
1239c59369SXuan Hu
1339c59369SXuan Hucase class RFWBCollideCheckerParams (
1439c59369SXuan Hu  inWbCfgs: Seq[Seq[Set[PregWB]]],
1539c59369SXuan Hu  pregParams: PregParams,
1639c59369SXuan Hu) {
1739c59369SXuan Hu  def genInputBundle: MixedVec2[DecoupledIO[RFWBCollideCheckerBundle]] = {
1839c59369SXuan Hu    val pregWidth = pregParams.addrWidth
1939c59369SXuan Hu    utils.SeqUtils.mapToMixedVec2(this.filteredCfgs, (wb: PregWB) => DecoupledIO(new RFWBCollideCheckerBundle(wb, pregWidth)))
2039c59369SXuan Hu  }
2139c59369SXuan Hu
2239c59369SXuan Hu  def filteredCfgs: Seq[Seq[PregWB]] = inWbCfgs.map(_.map(x =>
2339c59369SXuan Hu    if (x.map(_.dataCfg).contains(pregParams.dataCfg))
2439c59369SXuan Hu      x.find(x => x.dataCfg == pregParams.dataCfg).get
2539c59369SXuan Hu    else
2639c59369SXuan Hu      NoWB()
2739c59369SXuan Hu  ))
2839c59369SXuan Hu
2939c59369SXuan Hu  def portMax = filteredCfgs.flatten.map(_.port).max
3039c59369SXuan Hu}
3139c59369SXuan Hu
3239c59369SXuan Huclass RFWBCollideCheckerBundle(var wbCfg: Option[PregWB], pregWidth: Int) extends Bundle {
3339c59369SXuan Hu
3439c59369SXuan Hu  def this(wbCfg_ : PregWB, pregWidth_ : Int) = this(Some(wbCfg_), pregWidth_)
3539c59369SXuan Hu
3639c59369SXuan Hu  def this(pregWidth_ : Int) = this(None, pregWidth_)
3739c59369SXuan Hu}
3839c59369SXuan Hu
3939c59369SXuan Huclass RFWBCollideCheckerIO(val params: RFWBCollideCheckerParams)(implicit p: Parameters) extends Bundle {
4039c59369SXuan Hu  private val pregWidth = params.pregParams.addrWidth
4139c59369SXuan Hu  val in: MixedVec2[DecoupledIO[RFWBCollideCheckerBundle]] = Flipped(params.genInputBundle)
4239c59369SXuan Hu  val out = Vec(params.portMax + 1, Valid(new RFWBCollideCheckerBundle(pregWidth)))
4339c59369SXuan Hu}
4439c59369SXuan Hu
452aaa83c0Sxiaofeibao-xjtuprivate object ArbiterCtrl {
462aaa83c0Sxiaofeibao-xjtu  def apply(request: Seq[Bool]): Seq[Bool] = request.length match {
472aaa83c0Sxiaofeibao-xjtu    case 0 => Seq()
482aaa83c0Sxiaofeibao-xjtu    case 1 => Seq(true.B)
499b40a181Ssinsanction    case _ => request.head +: request.tail.init.scanLeft(request.head)(_ || _).map(!_)
502aaa83c0Sxiaofeibao-xjtu  }
512aaa83c0Sxiaofeibao-xjtu}
522aaa83c0Sxiaofeibao-xjtu
532aaa83c0Sxiaofeibao-xjtu// when io.in.valid is false.B, io.in.ready is true.B
542aaa83c0Sxiaofeibao-xjtuclass WBArbiter[T <: Data](val gen: T, val n: Int) extends Module {
552aaa83c0Sxiaofeibao-xjtu  val io = IO(new ArbiterIO(gen, n))
562aaa83c0Sxiaofeibao-xjtu
579b40a181Ssinsanction  // These parameters are not carefully set, and may be improved in the future
589b40a181Ssinsanction  private val CounterWidth = 3
599b40a181Ssinsanction  private val CounterThreshold = 7
609b40a181Ssinsanction
619b40a181Ssinsanction  /* To avoid some weird deadlock caused by delay of og0Cancel */
629b40a181Ssinsanction  // Use a saturation counter to record the number of consecutive failed requests for each input port
639b40a181Ssinsanction  // When a counter reaches the threshold, mark it as full
649b40a181Ssinsanction  // Port marked as full will be prioritized the next time it sends a request
659b40a181Ssinsanction
669b40a181Ssinsanction  val cancelCounter      = RegInit(VecInit(Seq.fill(n)(0.U(CounterWidth.W))))
679b40a181Ssinsanction  val isFull             = RegInit(VecInit(Seq.fill(n)(false.B)))
689b40a181Ssinsanction  val cancelCounterNext  = Wire(Vec(n, UInt(CounterWidth.W)))
699b40a181Ssinsanction  val isFullNext         = Wire(Vec(n, Bool()))
709b40a181Ssinsanction  val hasFull            = RegInit(false.B)
719b40a181Ssinsanction  val hasFullReq         = Wire(Bool())
729b40a181Ssinsanction  val finalValid         = Wire(Vec(n, Bool()))
739b40a181Ssinsanction
749b40a181Ssinsanction  cancelCounter := cancelCounterNext
759b40a181Ssinsanction  isFull        := isFullNext
769b40a181Ssinsanction  hasFull       := isFullNext.asUInt.orR
779b40a181Ssinsanction  hasFullReq    := io.in.zip(isFull).map{case (in, full) => in.valid && full}.reduce(_ || _)
789b40a181Ssinsanction
799b40a181Ssinsanction  cancelCounterNext.zip(isFullNext).zip(cancelCounter).zip(isFull).zipWithIndex.foreach{ case ((((cntNext, fullNext), cnt), full), i) =>
809b40a181Ssinsanction    when (io.in(i).valid && !io.in(i).ready) {
819b40a181Ssinsanction      cntNext   := Mux(cnt === CounterThreshold.U, CounterThreshold.U, cnt + 1.U)
82d88aed57Ssinsanction      fullNext  := cnt(CounterWidth - 1, 1).andR  // counterNext === CounterThreshold.U
839b40a181Ssinsanction    }.elsewhen (io.in(i).valid && io.in(i).ready) {
849b40a181Ssinsanction      cntNext   := 0.U
859b40a181Ssinsanction      fullNext  := false.B
869b40a181Ssinsanction    }.otherwise {
879b40a181Ssinsanction      cntNext   := cnt
889b40a181Ssinsanction      fullNext  := full
899b40a181Ssinsanction    }
909b40a181Ssinsanction  }
919b40a181Ssinsanction
929b40a181Ssinsanction  finalValid := io.in.zipWithIndex.map{ case (in, i) => in.valid && (!hasFull || !hasFullReq || isFull(i)) }
939b40a181Ssinsanction
942aaa83c0Sxiaofeibao-xjtu  io.chosen := (n - 1).asUInt
952aaa83c0Sxiaofeibao-xjtu  io.out.bits := io.in(n - 1).bits
962aaa83c0Sxiaofeibao-xjtu  for (i <- n - 2 to 0 by -1) {
979b40a181Ssinsanction    when(finalValid(i)) {
982aaa83c0Sxiaofeibao-xjtu      io.chosen := i.asUInt
992aaa83c0Sxiaofeibao-xjtu      io.out.bits := io.in(i).bits
1002aaa83c0Sxiaofeibao-xjtu    }
1012aaa83c0Sxiaofeibao-xjtu  }
1022aaa83c0Sxiaofeibao-xjtu
1039b40a181Ssinsanction  // in_valid    grant      ready
1049b40a181Ssinsanction  // 0           *          1
1059b40a181Ssinsanction  // 1           0          0
1069b40a181Ssinsanction  // 1           1          1
1079b40a181Ssinsanction  val grant = ArbiterCtrl(finalValid)
1089d536e01Ssinsanction  for (((in, g), v) <- io.in.zip(grant).zip(finalValid))
1099d536e01Ssinsanction    in.ready := (g && v || !in.valid) && io.out.ready
1109b40a181Ssinsanction  io.out.valid := !grant.last || finalValid.last
1112aaa83c0Sxiaofeibao-xjtu}
1122aaa83c0Sxiaofeibao-xjtu
11347af51e7Ssinsanction// used in WbDataPath
11447af51e7Ssinsanctionclass RealWBArbiter[T <: Data](val gen: T, val n: Int) extends Module {
11547af51e7Ssinsanction  val io = IO(new ArbiterIO(gen, n))
11647af51e7Ssinsanction
11747af51e7Ssinsanction  io.chosen := (n - 1).asUInt
11847af51e7Ssinsanction  io.out.bits := io.in(n - 1).bits
11947af51e7Ssinsanction  for (i <- n - 2 to 0 by -1) {
12047af51e7Ssinsanction    when(io.in(i).valid) {
12147af51e7Ssinsanction      io.chosen := i.asUInt
12247af51e7Ssinsanction      io.out.bits := io.in(i).bits
12347af51e7Ssinsanction    }
12447af51e7Ssinsanction  }
12547af51e7Ssinsanction
12647af51e7Ssinsanction  val grant = ArbiterCtrl(io.in.map(_.valid))
12747af51e7Ssinsanction  for ((in, g) <- io.in.zip(grant))
12847af51e7Ssinsanction    in.ready := (g || !in.valid) && io.out.ready
12947af51e7Ssinsanction  io.out.valid := !grant.last || io.in.last.valid
13047af51e7Ssinsanction}
13147af51e7Ssinsanction
1323ff8f291Sxiaofeibao-xjtuabstract class RFWBCollideCheckerBase(params: RFWBCollideCheckerParams)(implicit p: Parameters) extends Module {
1333ff8f291Sxiaofeibao-xjtu  protected def portRange: Range
1343ff8f291Sxiaofeibao-xjtu
1353ff8f291Sxiaofeibao-xjtu  val io = IO(new RFWBCollideCheckerIO(params))
1363ff8f291Sxiaofeibao-xjtu  dontTouch(io)
1373ff8f291Sxiaofeibao-xjtu
1383ff8f291Sxiaofeibao-xjtu  protected val pregParams = params.pregParams
1393ff8f291Sxiaofeibao-xjtu  protected val pregWidth = pregParams.addrWidth
1403ff8f291Sxiaofeibao-xjtu
1413ff8f291Sxiaofeibao-xjtu  protected val inGroup = io.in
1423ff8f291Sxiaofeibao-xjtu    .flatten
1433ff8f291Sxiaofeibao-xjtu    .groupBy(_.bits.wbCfg.get.port)
1443ff8f291Sxiaofeibao-xjtu    .map(x => (x._1, x._2.sortBy(_.bits.wbCfg.get.priority)))
1453ff8f291Sxiaofeibao-xjtu
1462aaa83c0Sxiaofeibao-xjtu  protected val arbiters: Seq[Option[WBArbiter[RFWBCollideCheckerBundle]]] = portRange.map { portIdx =>
14739c59369SXuan Hu    OptionWrapper(
14839c59369SXuan Hu      inGroup.isDefinedAt(portIdx),
1492aaa83c0Sxiaofeibao-xjtu      Module(new WBArbiter(
15039c59369SXuan Hu        new RFWBCollideCheckerBundle(pregWidth),
15139c59369SXuan Hu        inGroup(portIdx).size
15239c59369SXuan Hu      ))
15339c59369SXuan Hu    )
15439c59369SXuan Hu  }
15539c59369SXuan Hu
15639c59369SXuan Hu  // connection of IntWB or VfWB
15739c59369SXuan Hu  arbiters.zipWithIndex.foreach { case (arb, portIdx) =>
15839c59369SXuan Hu    if (arb.nonEmpty) {
15939c59369SXuan Hu      arb.get.io.in.zip(inGroup(portIdx)).foreach { case (arbiterIn, ioIn) =>
16039c59369SXuan Hu        arbiterIn <> ioIn
16139c59369SXuan Hu      }
16239c59369SXuan Hu    }
16339c59369SXuan Hu  }
16439c59369SXuan Hu
16539c59369SXuan Hu  // connection of NoWB
16639c59369SXuan Hu  io.in.map(_.map(x =>
16739c59369SXuan Hu    if (x.bits.wbCfg.get.isInstanceOf[NoWB]) {
16839c59369SXuan Hu      x.ready := true.B
16939c59369SXuan Hu    }
17039c59369SXuan Hu  ))
17139c59369SXuan Hu
17239c59369SXuan Hu  io.out.zip(arbiters).foreach { case (out, arb) =>
17339c59369SXuan Hu    if (arb.nonEmpty) {
17439c59369SXuan Hu      val arbOut = arb.get.io.out
17539c59369SXuan Hu      arbOut.ready := true.B
17639c59369SXuan Hu      out.valid := arbOut.valid
17739c59369SXuan Hu      out.bits := arbOut.bits
17839c59369SXuan Hu    } else {
17939c59369SXuan Hu      out := 0.U.asTypeOf(out)
18039c59369SXuan Hu    }
18139c59369SXuan Hu  }
18239c59369SXuan Hu}
18339c59369SXuan Hu
18439c59369SXuan Huclass IntRFWBCollideChecker(
18539c59369SXuan Hu  backendParams: BackendParams
18639c59369SXuan Hu)(implicit
18739c59369SXuan Hu  p:Parameters
18839c59369SXuan Hu) extends RFWBCollideCheckerBase(RFWBCollideCheckerParams(backendParams.getAllWbCfgs, backendParams.intPregParams)) {
18939c59369SXuan Hu  override protected def portRange: Range = 0 to backendParams.getWbPortIndices(IntData()).max
19039c59369SXuan Hu}
19139c59369SXuan Hu
19260f0c5aeSxiaofeibaoclass FpRFWBCollideChecker(
19360f0c5aeSxiaofeibao  backendParams: BackendParams
19460f0c5aeSxiaofeibao)(implicit
19560f0c5aeSxiaofeibao  p:Parameters
19660f0c5aeSxiaofeibao) extends RFWBCollideCheckerBase(RFWBCollideCheckerParams(backendParams.getAllWbCfgs, backendParams.fpPregParams)) {
19760f0c5aeSxiaofeibao  override protected def portRange: Range = 0 to backendParams.getWbPortIndices(FpData()).max
19860f0c5aeSxiaofeibao}
19960f0c5aeSxiaofeibao
20039c59369SXuan Huclass VfRFWBCollideChecker(
20139c59369SXuan Hu  backendParams: BackendParams
20239c59369SXuan Hu)(implicit
20339c59369SXuan Hu  p:Parameters
20439c59369SXuan Hu) extends RFWBCollideCheckerBase(RFWBCollideCheckerParams(backendParams.getAllWbCfgs, backendParams.vfPregParams)) {
20539c59369SXuan Hu  override protected def portRange: Range = 0 to backendParams.getWbPortIndices(VecData()).max
20639c59369SXuan Hu}
207*e4e52e7dSsinsanction
208*e4e52e7dSsinsanctionclass V0RFWBCollideChecker(
209*e4e52e7dSsinsanction  backendParams: BackendParams
210*e4e52e7dSsinsanction)(implicit
211*e4e52e7dSsinsanction  p:Parameters
212*e4e52e7dSsinsanction) extends RFWBCollideCheckerBase(RFWBCollideCheckerParams(backendParams.getAllWbCfgs, backendParams.v0PregParams)) {
213*e4e52e7dSsinsanction  override protected def portRange: Range = 0 to backendParams.getWbPortIndices(V0Data()).max
214*e4e52e7dSsinsanction}
215*e4e52e7dSsinsanction
216*e4e52e7dSsinsanctionclass VlRFWBCollideChecker(
217*e4e52e7dSsinsanction  backendParams: BackendParams
218*e4e52e7dSsinsanction)(implicit
219*e4e52e7dSsinsanction  p:Parameters
220*e4e52e7dSsinsanction) extends RFWBCollideCheckerBase(RFWBCollideCheckerParams(backendParams.getAllWbCfgs, backendParams.vlPregParams)) {
221*e4e52e7dSsinsanction  override protected def portRange: Range = 0 to backendParams.getWbPortIndices(VlData()).max
222*e4e52e7dSsinsanction}
223