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 org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import utility._ 25 26 27class BypassInfo(numWays: Int, dataBits: Int) extends Bundle { 28 val valid = Vec(numWays, Bool()) 29 val data = UInt(dataBits.W) 30} 31 32class BypassNetworkIO(numWays: Int, numBypass: Int, dataBits: Int) extends Bundle { 33 val hold = Input(Bool()) 34 val source = Vec(numWays, Input(UInt(dataBits.W))) 35 val target = Vec(numWays, Output(UInt(dataBits.W))) 36 val bypass = Vec(numBypass, Input(new BypassInfo(numWays, dataBits))) 37} 38 39class BypassNetwork(numWays: Int, numBypass: Int, dataBits: Int)(implicit p: Parameters) 40 extends XSModule { 41 42 val io = IO(new BypassNetworkIO(numWays, numBypass, dataBits)) 43 44 def doBypass(bypassValid: Seq[Bool], bypassData: Seq[UInt], baseData: UInt, debugIndex: Int = 0): UInt = { 45 val bypassVec = VecInit(bypassValid) 46 val target = Mux(bypassVec.asUInt.orR, ParallelMux(bypassValid, bypassData), baseData) 47 48 XSError(PopCount(bypassVec) > 1.U, p"bypass mask ${Binary(bypassVec.asUInt)} is not one-hot\n") 49 bypassVec.zipWithIndex.map { case (m, i) => 50 XSDebug(bypassVec(i), p"target($debugIndex) bypassed from $i:0x${Hexadecimal(bypassData(i))}\n") 51 } 52 53 target 54 } 55 56} 57 58// Bypass at the right: RegNext(data) and compute the bypassed data at the next clock cycle 59class BypassNetworkRight(numWays: Int, numBypass: Int, dataBits: Int)(implicit p: Parameters) 60 extends BypassNetwork(numWays, numBypass, dataBits) { 61 62 val last_cycle_hold = RegInit(false.B) 63 last_cycle_hold := io.hold 64 65 val target_reg = Reg(Vec(numWays, UInt(dataBits.W))) 66 val bypass_reg = Reg(Vec(numBypass, new BypassInfo(numWays, dataBits))) 67 68 // When last cycle holds the data, no need to update it. 69 when (io.hold && !last_cycle_hold) { 70 bypass_reg.map(_.valid.map(_ := false.B)) 71 target_reg := io.target 72 }.elsewhen(!io.hold) { 73 target_reg := io.source 74 for ((by_reg, by_io) <- bypass_reg.zip(io.bypass)) { 75 by_reg.data := by_io.data 76 by_reg.valid := by_io.valid 77 } 78 } 79 80 // bypass data to target 81 for (i <- 0 until numWays) { 82 io.target(i) := doBypass(bypass_reg.map(_.valid(i)), bypass_reg.map(_.data), target_reg(i)) 83 } 84 85} 86 87// Bypass at the left: compute the bypassed data and RegNext(bypassed_data) 88class BypassNetworkLeft(numWays: Int, numBypass: Int, dataBits: Int)(implicit p: Parameters) 89 extends BypassNetwork(numWays, numBypass, dataBits) { 90 91 val bypassedData = Reg(io.target.cloneType) 92 93 when (!io.hold) { 94 for ((by, i) <- bypassedData.zipWithIndex) { 95 by := doBypass(io.bypass.map(_.valid(i)), io.bypass.map(_.data), io.source(i)) 96 } 97 } 98 99 io.target := bypassedData 100 101} 102 103object BypassNetwork { 104 def apply( 105 numWays: Int, 106 numBypass: Int, 107 dataBits: Int, 108 optFirstStage: Boolean 109 )(implicit p: Parameters): BypassNetwork = { 110 if (optFirstStage) { 111 Module(new BypassNetworkLeft(numWays, numBypass, dataBits)) 112 } 113 else { 114 Module(new BypassNetworkRight(numWays, numBypass, dataBits)) 115 } 116 } 117} 118