xref: /XiangShan/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala (revision 5c7674fe439b80ea3bb6c6207b7d169ed6183be5)
1package xiangshan.backend.issue
2
3import chipsalliance.rocketchip.config.Parameters
4import chisel3._
5import chisel3.util._
6import xiangshan._
7import utils._
8
9
10class BypassInfo(numWays: Int, dataBits: Int, optBuf: Boolean = false) extends Bundle {
11  val validWidth = (if (optBuf) dataBits else 1)
12
13  val valid = Vec(numWays, UInt(validWidth.W))
14  val data = UInt(dataBits.W)
15
16  override def cloneType: BypassInfo.this.type =
17    new BypassInfo(numWays, dataBits, optBuf).asInstanceOf[this.type]
18}
19
20class BypassNetworkIO(numWays: Int, numBypass: Int, dataBits: Int) extends Bundle {
21  val hold = Input(Bool())
22  val source = Vec(numWays, Input(UInt(dataBits.W)))
23  val target = Vec(numWays, Output(UInt(dataBits.W)))
24  val bypass = Vec(numBypass, Input(new BypassInfo(numWays, dataBits)))
25
26  override def cloneType: BypassNetworkIO.this.type =
27    new BypassNetworkIO(numWays, numBypass, dataBits).asInstanceOf[this.type]
28}
29
30class BypassNetwork(numWays: Int, numBypass: Int, dataBits: Int, optBuf: Boolean)(implicit p: Parameters)
31  extends XSModule {
32  val io = IO(new BypassNetworkIO(numWays, numBypass, dataBits))
33
34  val target_reg = Reg(Vec(numWays, UInt(dataBits.W)))
35  val bypass_reg = Reg(Vec(numBypass, new BypassInfo(numWays, dataBits, optBuf)))
36
37  when (io.hold) {
38    target_reg := io.target
39    if (optBuf) {
40      bypass_reg.map(_.valid.map(_ := 0.U))
41    }
42    else {
43      bypass_reg.map(_.valid.map(_ := false.B))
44    }
45  }.otherwise {
46    target_reg := io.source
47    for ((by_reg, by_io) <- bypass_reg.zip(io.bypass)) {
48      by_reg.data := by_io.data
49      if (optBuf) {
50        // duplicate bypass mask to avoid too many FO4s and hurting timing
51        by_reg.valid := VecInit(by_io.valid.map(v => Cat(Seq.fill(dataBits)(v))))
52      }
53      else {
54        by_reg.valid := by_io.valid
55      }
56    }
57  }
58
59  // bypass data to target
60  for (i <- 0 until numWays) {
61    if (optBuf) {
62      val bypassData = VecInit((0 until dataBits).map(j => {
63        val mask = VecInit(bypass_reg.map(_.valid(i)(j)))
64        Mux(mask.asUInt.orR, Mux1H(mask, bypass_reg.map(_.data(j))), target_reg(i)(j))
65      })).asUInt
66      io.target(i) := bypassData
67    }
68    else {
69      val mask = VecInit(bypass_reg.map(_.valid(i).asBool))
70      io.target(i) := Mux(mask.asUInt.orR, Mux1H(mask, bypass_reg.map(_.data)), target_reg(i))
71
72      XSError(PopCount(mask) > 1.U, p"bypass mask ${Binary(mask.asUInt)} is not one-hot\n")
73      mask.zipWithIndex.map { case (m, j) =>
74        XSDebug(mask(j), p"target($i) bypassed from $j:0x${Hexadecimal(bypass_reg(j).data)}\n")
75      }
76    }
77  }
78}
79