xref: /XiangShan/src/main/scala/xiangshan/backend/issue/BypassNetwork.scala (revision f320e0f01bd645f0a3045a8a740e60dd770734a9)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.backend.issue
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import xiangshan._
23import utils._
24
25
26class BypassInfo(numWays: Int, dataBits: Int, optBuf: Boolean = false) extends Bundle {
27  val validWidth = (if (optBuf) dataBits else 1)
28
29  val valid = Vec(numWays, UInt(validWidth.W))
30  val data = UInt(dataBits.W)
31
32  override def cloneType: BypassInfo.this.type =
33    new BypassInfo(numWays, dataBits, optBuf).asInstanceOf[this.type]
34}
35
36class BypassNetworkIO(numWays: Int, numBypass: Int, dataBits: Int) extends Bundle {
37  val hold = Input(Bool())
38  val source = Vec(numWays, Input(UInt(dataBits.W)))
39  val target = Vec(numWays, Output(UInt(dataBits.W)))
40  val bypass = Vec(numBypass, Input(new BypassInfo(numWays, dataBits)))
41
42  override def cloneType: BypassNetworkIO.this.type =
43    new BypassNetworkIO(numWays, numBypass, dataBits).asInstanceOf[this.type]
44}
45
46class BypassNetwork(numWays: Int, numBypass: Int, dataBits: Int, optBuf: Boolean)(implicit p: Parameters)
47  extends XSModule {
48  val io = IO(new BypassNetworkIO(numWays, numBypass, dataBits))
49
50  val target_reg = Reg(Vec(numWays, UInt(dataBits.W)))
51  val bypass_reg = Reg(Vec(numBypass, new BypassInfo(numWays, dataBits, optBuf)))
52
53  when (io.hold) {
54    target_reg := io.target
55    if (optBuf) {
56      bypass_reg.map(_.valid.map(_ := 0.U))
57    }
58    else {
59      bypass_reg.map(_.valid.map(_ := false.B))
60    }
61  }.otherwise {
62    target_reg := io.source
63    for ((by_reg, by_io) <- bypass_reg.zip(io.bypass)) {
64      by_reg.data := by_io.data
65      if (optBuf) {
66        // duplicate bypass mask to avoid too many FO4s and hurting timing
67        by_reg.valid := VecInit(by_io.valid.map(v => Cat(Seq.fill(dataBits)(v))))
68      }
69      else {
70        by_reg.valid := by_io.valid
71      }
72    }
73  }
74
75  // bypass data to target
76  for (i <- 0 until numWays) {
77    if (optBuf) {
78      val bypassData = VecInit((0 until dataBits).map(j => {
79        val mask = VecInit(bypass_reg.map(_.valid(i)(j)))
80        Mux(mask.asUInt.orR, Mux1H(mask, bypass_reg.map(_.data(j))), target_reg(i)(j))
81      })).asUInt
82      io.target(i) := bypassData
83    }
84    else {
85      val mask = VecInit(bypass_reg.map(_.valid(i).asBool))
86      io.target(i) := Mux(mask.asUInt.orR, Mux1H(mask, bypass_reg.map(_.data)), target_reg(i))
87
88      XSError(PopCount(mask) > 1.U, p"bypass mask ${Binary(mask.asUInt)} is not one-hot\n")
89      mask.zipWithIndex.map { case (m, j) =>
90        XSDebug(mask(j), p"target($i) bypassed from $j:0x${Hexadecimal(bypass_reg(j).data)}\n")
91      }
92    }
93  }
94}
95