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