diff --git a/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala b/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala index f2118f7af6..b44f9548f3 100644 --- a/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala +++ b/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala @@ -23,14 +23,12 @@ import xiangshan._ import utils._ -class BypassInfo(numWays: Int, dataBits: Int, optBuf: Boolean = false) extends Bundle { - val validWidth = (if (optBuf) dataBits else 1) - - val valid = Vec(numWays, UInt(validWidth.W)) +class BypassInfo(numWays: Int, dataBits: Int) extends Bundle { + val valid = Vec(numWays, Bool()) val data = UInt(dataBits.W) override def cloneType: BypassInfo.this.type = - new BypassInfo(numWays, dataBits, optBuf).asInstanceOf[this.type] + new BypassInfo(numWays, dataBits).asInstanceOf[this.type] } class BypassNetworkIO(numWays: Int, numBypass: Int, dataBits: Int) extends Bundle { @@ -43,52 +41,68 @@ class BypassNetworkIO(numWays: Int, numBypass: Int, dataBits: Int) extends Bundl new BypassNetworkIO(numWays, numBypass, dataBits).asInstanceOf[this.type] } -class BypassNetwork(numWays: Int, numBypass: Int, dataBits: Int, optBuf: Boolean)(implicit p: Parameters) +class BypassNetwork(numWays: Int, numBypass: Int, dataBits: Int)(implicit p: Parameters) extends XSModule { + val io = IO(new BypassNetworkIO(numWays, numBypass, dataBits)) + def doBypass(bypassValid: Seq[Bool], bypassData: Seq[UInt], baseData: UInt, debugIndex: Int = 0): UInt = { + val bypassVec = VecInit(bypassValid) + val target = Mux(bypassVec.asUInt.orR, Mux1H(bypassValid, bypassData), baseData) + + XSError(PopCount(bypassVec) > 1.U, p"bypass mask ${Binary(bypassVec.asUInt)} is not one-hot\n") + bypassVec.zipWithIndex.map { case (m, i) => + XSDebug(bypassVec(i), p"target($debugIndex) bypassed from $i:0x${Hexadecimal(bypassData(i))}\n") + } + + target + } + +} + +// Bypass at the right: RegNext(data) and compute the bypassed data at the next clock cycle +class BypassNetworkRight(numWays: Int, numBypass: Int, dataBits: Int)(implicit p: Parameters) + extends BypassNetwork(numWays, numBypass, dataBits) { + val target_reg = Reg(Vec(numWays, UInt(dataBits.W))) - val bypass_reg = Reg(Vec(numBypass, new BypassInfo(numWays, dataBits, optBuf))) + val bypass_reg = Reg(Vec(numBypass, new BypassInfo(numWays, dataBits))) when (io.hold) { target_reg := io.target - if (optBuf) { - bypass_reg.map(_.valid.map(_ := 0.U)) - } - else { - bypass_reg.map(_.valid.map(_ := false.B)) - } + bypass_reg.map(_.valid.map(_ := false.B)) }.otherwise { target_reg := io.source for ((by_reg, by_io) <- bypass_reg.zip(io.bypass)) { by_reg.data := by_io.data - if (optBuf) { - // duplicate bypass mask to avoid too many FO4s and hurting timing - by_reg.valid := VecInit(by_io.valid.map(v => Cat(Seq.fill(dataBits)(v)))) - } - else { - by_reg.valid := by_io.valid - } + by_reg.valid := by_io.valid } } // bypass data to target for (i <- 0 until numWays) { - if (optBuf) { - val bypassData = VecInit((0 until dataBits).map(j => { - val mask = VecInit(bypass_reg.map(_.valid(i)(j))) - Mux(mask.asUInt.orR, Mux1H(mask, bypass_reg.map(_.data(j))), target_reg(i)(j)) - })).asUInt - io.target(i) := bypassData - } - else { - val mask = VecInit(bypass_reg.map(_.valid(i).asBool)) - io.target(i) := Mux(mask.asUInt.orR, Mux1H(mask, bypass_reg.map(_.data)), target_reg(i)) - - XSError(PopCount(mask) > 1.U, p"bypass mask ${Binary(mask.asUInt)} is not one-hot\n") - mask.zipWithIndex.map { case (m, j) => - XSDebug(mask(j), p"target($i) bypassed from $j:0x${Hexadecimal(bypass_reg(j).data)}\n") - } + io.target(i) := doBypass(bypass_reg.map(_.valid(i)), bypass_reg.map(_.data), target_reg(i)) + } + +} + +// Bypass at the left: compute the bypassed data and RegNext(bypassed_data) +class BypassNetworkLeft(numWays: Int, numBypass: Int, dataBits: Int)(implicit p: Parameters) + extends BypassNetwork(numWays, numBypass, dataBits) { + + val bypassedData = Reg(io.target.cloneType) + + when (!io.hold) { + for ((by, i) <- bypassedData.zipWithIndex) { + by := doBypass(io.bypass.map(_.valid(i)), io.bypass.map(_.data), io.source(i)) } } + + io.target := bypassedData + +} + +object BypassNetwork { + def apply(numWays: Int, numBypass: Int, dataBits: Int, optFirstStage: Boolean)(implicit p: Parameters) = { + Module(new BypassNetworkLeft(numWays, numBypass, dataBits)) + } } diff --git a/src/main/scala/xiangshan/backend/issue/ReservationStation.scala b/src/main/scala/xiangshan/backend/issue/ReservationStation.scala index 1c39ae23c0..b0bb86569f 100644 --- a/src/main/scala/xiangshan/backend/issue/ReservationStation.scala +++ b/src/main/scala/xiangshan/backend/issue/ReservationStation.scala @@ -448,7 +448,7 @@ class ReservationStation(params: RSParams)(implicit p: Parameters) extends XSMod wakeupBypassMask(j) := VecInit(targetFastWakeupMatch.map(_ (j))) } - val bypassNetwork = Module(new BypassNetwork(params.numSrc, params.numFastWakeup, params.dataBits, params.optBuf)) + val bypassNetwork = BypassNetwork(params.numSrc, params.numFastWakeup, params.dataBits, params.optBuf) bypassNetwork.io.hold := !io.deq(i).ready bypassNetwork.io.source := s1_out(i).bits.src.take(params.numSrc) bypassNetwork.io.bypass.zip(wakeupBypassMask.zip(io.fastDatas)).foreach { case (by, (m, d)) =>