xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/RFWBConflictChecker.scala (revision 2aaa83c0374a83bf896bf5106d9ce211df8ac6bb)
1package xiangshan.backend.datapath
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utils.OptionWrapper
7import utils.SeqUtils.MixedVec2
8import xiangshan.backend.BackendParams
9import xiangshan.backend.datapath.DataConfig.{IntData, VecData}
10import xiangshan.backend.datapath.WbConfig.{NoWB, PregWB}
11import xiangshan.backend.regfile.PregParams
12
13case class RFWBCollideCheckerParams (
14  inWbCfgs: Seq[Seq[Set[PregWB]]],
15  pregParams: PregParams,
16) {
17  def genInputBundle: MixedVec2[DecoupledIO[RFWBCollideCheckerBundle]] = {
18    val pregWidth = pregParams.addrWidth
19    utils.SeqUtils.mapToMixedVec2(this.filteredCfgs, (wb: PregWB) => DecoupledIO(new RFWBCollideCheckerBundle(wb, pregWidth)))
20  }
21
22  def filteredCfgs: Seq[Seq[PregWB]] = inWbCfgs.map(_.map(x =>
23    if (x.map(_.dataCfg).contains(pregParams.dataCfg))
24      x.find(x => x.dataCfg == pregParams.dataCfg).get
25    else
26      NoWB()
27  ))
28
29  def portMax = filteredCfgs.flatten.map(_.port).max
30}
31
32class RFWBCollideCheckerBundle(var wbCfg: Option[PregWB], pregWidth: Int) extends Bundle {
33
34  def this(wbCfg_ : PregWB, pregWidth_ : Int) = this(Some(wbCfg_), pregWidth_)
35
36  def this(pregWidth_ : Int) = this(None, pregWidth_)
37}
38
39class RFWBCollideCheckerIO(val params: RFWBCollideCheckerParams)(implicit p: Parameters) extends Bundle {
40  private val pregWidth = params.pregParams.addrWidth
41  val in: MixedVec2[DecoupledIO[RFWBCollideCheckerBundle]] = Flipped(params.genInputBundle)
42  val out = Vec(params.portMax + 1, Valid(new RFWBCollideCheckerBundle(pregWidth)))
43}
44
45abstract class RFWBCollideCheckerBase(params: RFWBCollideCheckerParams)(implicit p: Parameters) extends Module {
46  protected def portRange: Range
47
48  val io = IO(new RFWBCollideCheckerIO(params))
49  dontTouch(io)
50
51  protected val pregParams = params.pregParams
52  protected val pregWidth = pregParams.addrWidth
53
54  protected val inGroup = io.in
55    .flatten
56    .groupBy(_.bits.wbCfg.get.port)
57    .map(x => (x._1, x._2.sortBy(_.bits.wbCfg.get.priority)))
58
59  private object ArbiterCtrl {
60    def apply(request: Seq[Bool]): Seq[Bool] = request.length match {
61      case 0 => Seq()
62      case 1 => Seq(true.B)
63      case _ => true.B +: request.tail.init.scanLeft(request.head)(_ || _).map(!_)
64    }
65  }
66
67  // when io.in.valid is false.B, io.in.ready is true.B
68  class WBArbiter[T <: Data](val gen: T, val n: Int) extends Module {
69    val io = IO(new ArbiterIO(gen, n))
70
71    io.chosen := (n - 1).asUInt
72    io.out.bits := io.in(n - 1).bits
73    for (i <- n - 2 to 0 by -1) {
74      when(io.in(i).valid) {
75        io.chosen := i.asUInt
76        io.out.bits := io.in(i).bits
77      }
78    }
79
80    val grant = ArbiterCtrl(io.in.map(_.valid))
81    for ((in, g) <- io.in.zip(grant))
82      in.ready := (g || !in.valid) && io.out.ready
83    io.out.valid := !grant.last || io.in.last.valid
84  }
85
86  protected val arbiters: Seq[Option[WBArbiter[RFWBCollideCheckerBundle]]] = portRange.map { portIdx =>
87    OptionWrapper(
88      inGroup.isDefinedAt(portIdx),
89      Module(new WBArbiter(
90        new RFWBCollideCheckerBundle(pregWidth),
91        inGroup(portIdx).size
92      ))
93    )
94  }
95
96  // connection of IntWB or VfWB
97  arbiters.zipWithIndex.foreach { case (arb, portIdx) =>
98    if (arb.nonEmpty) {
99      arb.get.io.in.zip(inGroup(portIdx)).foreach { case (arbiterIn, ioIn) =>
100        arbiterIn <> ioIn
101      }
102    }
103  }
104
105  // connection of NoWB
106  io.in.map(_.map(x =>
107    if (x.bits.wbCfg.get.isInstanceOf[NoWB]) {
108      x.ready := true.B
109    }
110  ))
111
112  io.out.zip(arbiters).foreach { case (out, arb) =>
113    if (arb.nonEmpty) {
114      val arbOut = arb.get.io.out
115      arbOut.ready := true.B
116      out.valid := arbOut.valid
117      out.bits := arbOut.bits
118    } else {
119      out := 0.U.asTypeOf(out)
120    }
121  }
122}
123
124class IntRFWBCollideChecker(
125  backendParams: BackendParams
126)(implicit
127  p:Parameters
128) extends RFWBCollideCheckerBase(RFWBCollideCheckerParams(backendParams.getAllWbCfgs, backendParams.intPregParams)) {
129  override protected def portRange: Range = 0 to backendParams.getWbPortIndices(IntData()).max
130}
131
132class VfRFWBCollideChecker(
133  backendParams: BackendParams
134)(implicit
135  p:Parameters
136) extends RFWBCollideCheckerBase(RFWBCollideCheckerParams(backendParams.getAllWbCfgs, backendParams.vfPregParams)) {
137  override protected def portRange: Range = 0 to backendParams.getWbPortIndices(VecData()).max
138}
139