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