1569b279fSLingrui98/*************************************************************************************** 2569b279fSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3569b279fSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 4569b279fSLingrui98* 5569b279fSLingrui98* XiangShan is licensed under Mulan PSL v2. 6569b279fSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 7569b279fSLingrui98* You may obtain a copy of Mulan PSL v2 at: 8569b279fSLingrui98* http://license.coscl.org.cn/MulanPSL2 9569b279fSLingrui98* 10569b279fSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11569b279fSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12569b279fSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13569b279fSLingrui98* 14569b279fSLingrui98* See the Mulan PSL v2 for more details. 15569b279fSLingrui98***************************************************************************************/ 16569b279fSLingrui98package xiangshan.frontend 17569b279fSLingrui98 18569b279fSLingrui98import chipsalliance.rocketchip.config.Parameters 19569b279fSLingrui98import chisel3._ 20569b279fSLingrui98import chisel3.util._ 21569b279fSLingrui98import xiangshan._ 22569b279fSLingrui98import utils._ 23*3c02ee8fSwakafaimport utility._ 24569b279fSLingrui98import chisel3.experimental.chiselName 2576e02f07SLingrui98import xiangshan.cache.mmu.CAMTemplate 26569b279fSLingrui98 27569b279fSLingrui98class WrBypass[T <: Data](gen: T, val numEntries: Int, val idxWidth: Int, 28569b279fSLingrui98 val numWays: Int = 1, val tagWidth: Int = 0)(implicit p: Parameters) extends XSModule { 29569b279fSLingrui98 require(numEntries >= 0) 30569b279fSLingrui98 require(idxWidth > 0) 31569b279fSLingrui98 require(numWays >= 1) 32569b279fSLingrui98 require(tagWidth >= 0) 33569b279fSLingrui98 def hasTag = tagWidth > 0 34569b279fSLingrui98 def multipleWays = numWays > 1 35569b279fSLingrui98 val io = IO(new Bundle { 36569b279fSLingrui98 val wen = Input(Bool()) 37569b279fSLingrui98 val write_idx = Input(UInt(idxWidth.W)) 38569b279fSLingrui98 val write_tag = if (hasTag) Some(Input(UInt(tagWidth.W))) else None 39569b279fSLingrui98 val write_data = Input(Vec(numWays, gen)) 40569b279fSLingrui98 val write_way_mask = if (multipleWays) Some(Input(Vec(numWays, Bool()))) else None 41569b279fSLingrui98 42569b279fSLingrui98 val hit = Output(Bool()) 43569b279fSLingrui98 val hit_data = Vec(numWays, Valid(gen)) 44569b279fSLingrui98 }) 45569b279fSLingrui98 46569b279fSLingrui98 class WrBypassPtr extends CircularQueuePtr[WrBypassPtr](numEntries){ 47569b279fSLingrui98 } 48569b279fSLingrui98 4976e02f07SLingrui98 class Idx_Tag extends Bundle { 5076e02f07SLingrui98 val idx = UInt(idxWidth.W) 5176e02f07SLingrui98 val tag = if (hasTag) Some(UInt(tagWidth.W)) else None 5276e02f07SLingrui98 def apply(idx: UInt, tag: UInt) = { 5376e02f07SLingrui98 this.idx := idx 5476e02f07SLingrui98 this.tag.map(_ := tag) 5576e02f07SLingrui98 } 5676e02f07SLingrui98 } 5776e02f07SLingrui98 val idx_tag_cam = Module(new CAMTemplate(new Idx_Tag, numEntries, 1)) 5876e02f07SLingrui98 val data_mem = Mem(numEntries, Vec(numWays, gen)) 59569b279fSLingrui98 60569b279fSLingrui98 val valids = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, Bool())))) 6102585c22SLingrui98 val ever_written = RegInit(0.U.asTypeOf(Vec(numEntries, Bool()))) 62569b279fSLingrui98 63569b279fSLingrui98 val enq_ptr = RegInit(0.U.asTypeOf(new WrBypassPtr)) 64569b279fSLingrui98 val enq_idx = enq_ptr.value 65569b279fSLingrui98 6676e02f07SLingrui98 idx_tag_cam.io.r.req(0)(io.write_idx, io.write_tag.getOrElse(0.U)) 6702585c22SLingrui98 val hits_oh = idx_tag_cam.io.r.resp(0).zip(ever_written).map {case (h, ew) => h && ew} 6876e02f07SLingrui98 val hit_idx = OHToUInt(hits_oh) 6976e02f07SLingrui98 val hit = hits_oh.reduce(_||_) 70569b279fSLingrui98 71569b279fSLingrui98 io.hit := hit 72569b279fSLingrui98 for (i <- 0 until numWays) { 7376e02f07SLingrui98 io.hit_data(i).valid := Mux1H(hits_oh, valids)(i) 7476e02f07SLingrui98 io.hit_data(i).bits := data_mem.read(hit_idx)(i) 75569b279fSLingrui98 } 76569b279fSLingrui98 7776e02f07SLingrui98 val full_mask = Fill(numWays, 1.U(1.W)).asTypeOf(Vec(numWays, Bool())) 7876e02f07SLingrui98 val update_way_mask = io.write_way_mask.getOrElse(full_mask) 7976e02f07SLingrui98 8076e02f07SLingrui98 // write data on every request 8176e02f07SLingrui98 when (io.wen) { 8276e02f07SLingrui98 val data_write_idx = Mux(hit, hit_idx, enq_idx) 8376e02f07SLingrui98 data_mem.write(data_write_idx, io.write_data, update_way_mask) 8476e02f07SLingrui98 } 8576e02f07SLingrui98 8676e02f07SLingrui98 // update valids 87569b279fSLingrui98 for (i <- 0 until numWays) { 88569b279fSLingrui98 when (io.wen) { 89569b279fSLingrui98 when (hit) { 9076e02f07SLingrui98 when (update_way_mask(i)) { 91569b279fSLingrui98 valids(hit_idx)(i) := true.B 92569b279fSLingrui98 } 93569b279fSLingrui98 }.otherwise { 9402585c22SLingrui98 ever_written(enq_idx) := true.B 95569b279fSLingrui98 valids(enq_idx)(i) := false.B 9676e02f07SLingrui98 when (update_way_mask(i)) { 97569b279fSLingrui98 valids(enq_idx)(i) := true.B 9876e02f07SLingrui98 } 99569b279fSLingrui98 } 100569b279fSLingrui98 } 101569b279fSLingrui98 } 102569b279fSLingrui98 10376e02f07SLingrui98 val enq_en = io.wen && !hit 10476e02f07SLingrui98 idx_tag_cam.io.w.valid := enq_en 10576e02f07SLingrui98 idx_tag_cam.io.w.bits.index := enq_idx 10676e02f07SLingrui98 idx_tag_cam.io.w.bits.data(io.write_idx, io.write_tag.getOrElse(0.U)) 10776e02f07SLingrui98 enq_ptr := enq_ptr + enq_en 108569b279fSLingrui98 109569b279fSLingrui98 XSPerfAccumulate("wrbypass_hit", io.wen && hit) 110569b279fSLingrui98 XSPerfAccumulate("wrbypass_miss", io.wen && !hit) 111569b279fSLingrui98 112569b279fSLingrui98 XSDebug(io.wen && hit, p"wrbypass hit entry #${hit_idx}, idx ${io.write_idx}" + 113569b279fSLingrui98 p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n") 114569b279fSLingrui98 XSDebug(io.wen && !hit, p"wrbypass enq entry #${enq_idx}, idx ${io.write_idx}" + 115569b279fSLingrui98 p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n") 116569b279fSLingrui98} 117