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