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***************************************************************************************/ 16package xiangshan.frontend 17 18import chipsalliance.rocketchip.config.Parameters 19import chisel3._ 20import chisel3.util._ 21import xiangshan._ 22import utils._ 23import chisel3.experimental.chiselName 24 25class WrBypass[T <: Data](gen: T, val numEntries: Int, val idxWidth: Int, 26 val numWays: Int = 1, val tagWidth: Int = 0)(implicit p: Parameters) extends XSModule { 27 require(numEntries >= 0) 28 require(idxWidth > 0) 29 require(numWays >= 1) 30 require(tagWidth >= 0) 31 def hasTag = tagWidth > 0 32 def multipleWays = numWays > 1 33 val io = IO(new Bundle { 34 val wen = Input(Bool()) 35 val write_idx = Input(UInt(idxWidth.W)) 36 val write_tag = if (hasTag) Some(Input(UInt(tagWidth.W))) else None 37 val write_data = Input(Vec(numWays, gen)) 38 val write_way_mask = if (multipleWays) Some(Input(Vec(numWays, Bool()))) else None 39 40 val hit = Output(Bool()) 41 val hit_data = Vec(numWays, Valid(gen)) 42 }) 43 44 class WrBypassPtr extends CircularQueuePtr[WrBypassPtr](numEntries){ 45 override def cloneType = (new WrBypassPtr).asInstanceOf[this.type] 46 } 47 48 49 50 val tags = RegInit(0.U.asTypeOf((Vec(numEntries, UInt(tagWidth.W))))) 51 val idxes = RegInit(0.U.asTypeOf((Vec(numEntries, UInt(idxWidth.W))))) 52 val datas = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, gen)))) 53 val valids = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, Bool())))) 54 55 val enq_ptr = RegInit(0.U.asTypeOf(new WrBypassPtr)) 56 val enq_idx = enq_ptr.value 57 58 val hits = VecInit((0 until numEntries).map {i => 59 idxes(i) === io.write_idx && 60 tags(i) === io.write_tag.getOrElse(0.U) 61 }) 62 val hit = hits.reduce(_||_) 63 val hit_idx = ParallelPriorityEncoder(hits) 64 65 io.hit := hit 66 for (i <- 0 until numWays) { 67 io.hit_data(i).valid := valids(hit_idx)(i) 68 io.hit_data(i).bits := datas(hit_idx)(i) 69 } 70 71 for (i <- 0 until numWays) { 72 when (io.wen) { 73 val full_mask = Fill(numWays, 1.U(1.W)).asTypeOf(Vec(numWays, Bool())) 74 val update_this_way = io.write_way_mask.getOrElse(full_mask)(i) 75 when (hit) { 76 when (update_this_way) { 77 datas(hit_idx)(i) := io.write_data(i) 78 valids(hit_idx)(i) := true.B 79 } 80 }.otherwise { 81 valids(enq_idx)(i) := false.B 82 when (update_this_way) { 83 valids(enq_idx)(i) := true.B 84 datas(enq_idx)(i) := io.write_data(i) 85 } 86 } 87 } 88 89 } 90 91 when (io.wen && !hit) { 92 idxes(enq_idx) := io.write_idx 93 tags(enq_idx) := io.write_tag.getOrElse(0.U) 94 enq_ptr := enq_ptr + 1.U 95 } 96 97 XSPerfAccumulate("wrbypass_hit", io.wen && hit) 98 XSPerfAccumulate("wrbypass_miss", io.wen && !hit) 99 100 XSDebug(io.wen && hit, p"wrbypass hit entry #${hit_idx}, idx ${io.write_idx}" + 101 p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n") 102 XSDebug(io.wen && !hit, p"wrbypass enq entry #${enq_idx}, idx ${io.write_idx}" + 103 p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n") 104}