xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/RFReadArbiter.scala (revision bb2f3f51dd67f6e16e0cc1ffe43368c9fc7e4aef)
1package xiangshan.backend.datapath
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util.{Arbiter, DecoupledIO, RRArbiter, Valid, PopCount}
6import utils.SeqUtils.{MixedVec3, Seq3}
7import utils.{OptionWrapper, SeqUtils}
8import xiangshan.backend.BackendParams
9import xiangshan.backend.datapath.DataConfig._
10import xiangshan.backend.datapath.RdConfig._
11import xiangshan.backend.regfile.PregParams
12import utility._
13
14case class RFRdArbParams(
15  inRdCfgs: Seq3[RdConfig],
16  pregParams: PregParams,
17) {
18  require(inRdCfgs.nonEmpty)
19
20  def genInputBundle: MixedVec3[DecoupledIO[RFArbiterBundle]] = {
21    val pregWidth = pregParams.addrWidth
22    SeqUtils.mapToMixedVec3(this.inRdCfgs, (rd: RdConfig) => DecoupledIO(new RFArbiterBundle(rd, pregWidth)))
23  }
24
25  def portMax: Int = inRdCfgs.flatten.flatten.map(_.port).max
26}
27
28class RFArbiterBundle(var rdCfg: Option[RdConfig], pregWidth: Int) extends Bundle {
29  val addr = UInt(pregWidth.W)
30
31  def this(rdCfg_ : RdConfig, pregWidth_ : Int) = this(Some(rdCfg_), pregWidth_)
32
33  def this(pregWidth_ :Int) = this(None, pregWidth_)
34}
35
36class RFReadArbiterIO(params: RFRdArbParams)(implicit p: Parameters) extends Bundle {
37  private val pregWidth = params.pregParams.addrWidth
38  val in = Flipped(params.genInputBundle)
39  val out = Vec(params.portMax + 1, Valid(new RFArbiterBundle(pregWidth)))
40}
41
42abstract class RFReadArbiterBase(val params: RFRdArbParams)(implicit p: Parameters) extends Module {
43  protected def portRange: Range
44
45  val io = IO(new RFReadArbiterIO(params))
46  dontTouch(io)
47
48  protected val pregParams = params.pregParams
49  protected val pregWidth = pregParams.addrWidth
50
51  protected val inGroup: Map[Int, Seq[DecoupledIO[RFArbiterBundle]]] = io.in
52    .flatten.flatten
53    .groupBy(_.bits.rdCfg.get.port)
54    .map(x => (x._1, x._2.sortBy(_.bits.rdCfg.get.priority).toSeq))
55  protected val arbiters: Seq[Option[WBArbiter[RFArbiterBundle]]] = portRange.map { portIdx =>
56    Option.when(
57      inGroup.isDefinedAt(portIdx))(
58      Module(new WBArbiter(
59        new RFArbiterBundle(pregWidth),
60        inGroup(portIdx).size
61      ))
62    )
63  }
64
65  arbiters.zipWithIndex.foreach { case (arbiter, portIdx) =>
66    if (arbiter.nonEmpty) {
67      arbiter.get.io.in.zip(inGroup(portIdx)).foreach { case (arbiterIn, ioIn) =>
68        arbiterIn <> ioIn
69      }
70    }
71  }
72
73  if (params.pregParams.dataCfg.isInstanceOf[IntData]) {
74    val arbitersIn = arbiters.filter(_.nonEmpty).map(_.get.io.in)
75    val hasConflict = arbitersIn.map { case a =>
76      PopCount(a.map(_.valid)) > 1.U
77    }
78    for (i <- hasConflict.indices) {
79      XSPerfAccumulate(s"IntRFReadPort_${i}_Conflict", PopCount(hasConflict(i)))
80    }
81    val hasRead0 = arbitersIn.map { case a =>
82      a.map(x => x.valid && x.bits.addr === 0.U).reduce(_ || _)
83    }
84    val hasSameAddr = arbitersIn.map { case a =>
85      if (a.size == 2) a(0).valid && a(1).valid && a(0).bits.addr === a(1).bits.addr
86      else false.B
87    }
88    val hasRead0Conflict = hasConflict.zip(hasRead0).map(x => x._1 && x._2)
89    val hasReadSameAddrConflict = hasConflict.zip(hasSameAddr).map(x => x._1 && x._2)
90    XSPerfAccumulate("IntRFRead0_conflict_count", PopCount(hasRead0Conflict))
91    XSPerfAccumulate("IntRFReadSameAddr_conflict_count", PopCount(hasReadSameAddrConflict))
92  }
93
94  // connection of NoRD
95  io.in.map(_.map(_.map(x =>
96    if (x.bits.rdCfg.get.isInstanceOf[NoRD]) {
97      x.ready := true.B
98    }
99  )))
100
101  for (portIdx <- io.out.indices) {
102    val arb = arbiters(portIdx)
103    val out = io.out(portIdx)
104    if (arb.nonEmpty) {
105      val arbOut = arb.get.io.out
106      arbOut.ready := true.B
107      out.valid := arbOut.valid
108      out.bits := arbOut.bits
109    } else {
110      out := 0.U.asTypeOf(out)
111    }
112  }
113}
114
115class IntRFReadArbiter(
116  backendParams: BackendParams
117)(implicit
118  p: Parameters
119) extends RFReadArbiterBase(RFRdArbParams(backendParams.getRdCfgs[IntRD], backendParams.intPregParams)) {
120  override protected def portRange: Range = 0 to backendParams.getRdPortIndices(IntData()).max
121}
122
123class FpRFReadArbiter(
124  backendParams: BackendParams
125)(implicit
126  p: Parameters
127) extends RFReadArbiterBase(RFRdArbParams(backendParams.getRdCfgs[FpRD], backendParams.fpPregParams)) {
128  override protected def portRange: Range = 0 to backendParams.getRdPortIndices(FpData()).max
129}
130
131class VfRFReadArbiter(
132  backendParams: BackendParams
133)(implicit
134  p: Parameters
135) extends RFReadArbiterBase(RFRdArbParams(backendParams.getRdCfgs[VfRD], backendParams.vfPregParams)) {
136  override protected def portRange: Range = 0 to backendParams.getRdPortIndices(VecData()).max
137}
138
139class V0RFReadArbiter(
140  backendParams: BackendParams
141)(implicit
142  p: Parameters
143) extends RFReadArbiterBase(RFRdArbParams(backendParams.getRdCfgs[V0RD], backendParams.v0PregParams)) {
144  override protected def portRange: Range = 0 to backendParams.getRdPortIndices(V0Data()).max
145}
146
147class VlRFReadArbiter(
148  backendParams: BackendParams
149)(implicit
150  p: Parameters
151) extends RFReadArbiterBase(RFRdArbParams(backendParams.getRdCfgs[VlRD], backendParams.vlPregParams)) {
152  override protected def portRange: Range = 0 to backendParams.getRdPortIndices(VlData()).max
153}
154