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