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.frontend.icache 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import difftest._ 23import freechips.rocketchip.tilelink._ 24import utils._ 25import xiangshan.cache.mmu._ 26import xiangshan.frontend._ 27import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 28import huancun.PreferCacheKey 29import xiangshan.XSCoreParamsKey 30import utility._ 31 32class WayLookupInfo(implicit p: Parameters) extends ICacheBundle { 33 val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 34 val waymask = Vec(PortNumber, UInt(nWays.W)) 35 val ptag = Vec(PortNumber, UInt(tagBits.W)) 36 val gpaddr = Vec(PortNumber, UInt(GPAddrBits.W)) 37 val excp_tlb_af = Vec(PortNumber, Bool()) 38 val excp_tlb_pf = Vec(PortNumber, Bool()) 39 val excp_tlb_gpf = Vec(PortNumber, Bool()) 40 val meta_errors = Vec(PortNumber, Bool()) 41} 42 43 44// class WayLookupRead(implicit p: Parameters) extends ICacheBundle { 45// val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 46// val waymask = Vec(PortNumber, UInt(nWays.W)) 47// val ptag = Vec(PortNumber, UInt(tagBits.W)) 48// val excp_tlb_af = Vec(PortNumber, Bool()) 49// val excp_tlb_pf = Vec(PortNumber, Bool()) 50// } 51 52// class WayLookupWrite(implicit p: Parameters) extends ICacheBundle { 53// val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 54// val ptag = Vec(PortNumber, UInt(tagBits.W)) 55// val waymask = Vec(PortNumber, UInt(nWays.W)) 56// val excp_tlb_af = Vec(PortNumber, Bool()) 57// val excp_tlb_pf = Vec(PortNumber, Bool()) 58// } 59 60class WayLookupInterface(implicit p: Parameters) extends ICacheBundle { 61 val flush = Input(Bool()) 62 val read = DecoupledIO(new WayLookupInfo) 63 val write = Flipped(DecoupledIO(new WayLookupInfo)) 64 val update = Flipped(ValidIO(new ICacheMissResp)) 65} 66 67class WayLookup(implicit p: Parameters) extends ICacheModule { 68 val io = IO(new WayLookupInterface) 69 70 class WayLookupPtr(implicit p: Parameters) extends CircularQueuePtr[WayLookupPtr](nWayLookupSize) 71 object WayLookupPtr { 72 def apply(f: Bool, v: UInt)(implicit p: Parameters): WayLookupPtr = { 73 val ptr = Wire(new WayLookupPtr) 74 ptr.flag := f 75 ptr.value := v 76 ptr 77 } 78 } 79 80 val entries = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf((new WayLookupInfo).cloneType)))) 81 val readPtr = RegInit(WayLookupPtr(false.B, 0.U)) 82 val writePtr = RegInit(WayLookupPtr(false.B, 0.U)) 83 84 val empty = readPtr === writePtr 85 val full = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag) 86 87 when(io.flush) { 88 writePtr.value := 0.U 89 writePtr.flag := false.B 90 }.elsewhen(io.write.fire) { 91 writePtr := writePtr + 1.U 92 } 93 94 when(io.flush) { 95 readPtr.value := 0.U 96 readPtr.flag := false.B 97 }.elsewhen(io.read.fire) { 98 readPtr := readPtr + 1.U 99 } 100 101 /** 102 ****************************************************************************** 103 * update 104 ****************************************************************************** 105 */ 106 val hits = Wire(Vec(nWayLookupSize, Bool())) 107 entries.zip(hits).foreach{case(entry, hit) => 108 val hit_vec = Wire(Vec(PortNumber, Bool())) 109 (0 until PortNumber).foreach { i => 110 val vset_same = (io.update.bits.vSetIdx === entry.vSetIdx(i)) && !io.update.bits.corrupt && io.update.valid 111 val ptag_same = getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i) 112 val way_same = io.update.bits.waymask === entry.waymask(i) 113 when(vset_same) { 114 when(ptag_same) { 115 // miss -> hit 116 entry.waymask(i) := io.update.bits.waymask 117 // also clear previously found errors since data/metaArray is refilled 118 entry.meta_errors(i) := false.B 119 }.elsewhen(way_same) { 120 // data is overwritten: hit -> miss 121 entry.waymask(i) := 0.U 122 // do not clear previously found errors since way_same might be unreliable when error occurs 123 } 124 } 125 hit_vec(i) := vset_same && (ptag_same || way_same) 126 } 127 hit := hit_vec.reduce(_||_) 128 } 129 130 /** 131 ****************************************************************************** 132 * read 133 ****************************************************************************** 134 */ 135 val bypass = empty && io.write.valid 136 io.read.valid := !empty || io.write.valid 137 io.read.bits := Mux(bypass, io.write.bits, entries(readPtr.value)) 138 139 /** 140 ****************************************************************************** 141 * write 142 ****************************************************************************** 143 */ 144 io.write.ready := !full 145 when(io.write.fire) { 146 entries(writePtr.value) := io.write.bits 147 } 148} 149