1b92f8445Sssszwic/*************************************************************************************** 2b92f8445Sssszwic * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3b92f8445Sssszwic * Copyright (c) 2020-2021 Peng Cheng Laboratory 4b92f8445Sssszwic * 5b92f8445Sssszwic * XiangShan is licensed under Mulan PSL v2. 6b92f8445Sssszwic * You can use this software according to the terms and conditions of the Mulan PSL v2. 7b92f8445Sssszwic * You may obtain a copy of Mulan PSL v2 at: 8b92f8445Sssszwic * http://license.coscl.org.cn/MulanPSL2 9b92f8445Sssszwic * 10b92f8445Sssszwic * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11b92f8445Sssszwic * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12b92f8445Sssszwic * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13b92f8445Sssszwic * 14b92f8445Sssszwic * See the Mulan PSL v2 for more details. 15b92f8445Sssszwic ***************************************************************************************/ 16b92f8445Sssszwic 17b92f8445Sssszwicpackage xiangshan.frontend.icache 18b92f8445Sssszwic 19b92f8445Sssszwicimport org.chipsalliance.cde.config.Parameters 20b92f8445Sssszwicimport chisel3._ 21b92f8445Sssszwicimport chisel3.util._ 22b92f8445Sssszwicimport utility._ 23b92f8445Sssszwic 24*91946104Sxu_zh/* WayLookupEntry is for internal storage, while WayLookupInfo is for interface 25*91946104Sxu_zh * Notes: 26*91946104Sxu_zh * 1. there must be a flush (caused by guest page fault) after excp_tlb_gpf === true.B, 27*91946104Sxu_zh * so, we need only the first excp_tlb_gpf and the corresponding gpaddr. 28*91946104Sxu_zh * to save area, we separate those signals from WayLookupEntry and store only once. 29*91946104Sxu_zh */ 30*91946104Sxu_zhclass WayLookupEntry(implicit p: Parameters) extends ICacheBundle { 31*91946104Sxu_zh val vSetIdx : Vec[UInt] = Vec(PortNumber, UInt(idxBits.W)) 32*91946104Sxu_zh val waymask : Vec[UInt] = Vec(PortNumber, UInt(nWays.W)) 33*91946104Sxu_zh val ptag : Vec[UInt] = Vec(PortNumber, UInt(tagBits.W)) 34*91946104Sxu_zh val excp_tlb_af : Vec[Bool] = Vec(PortNumber, Bool()) 35*91946104Sxu_zh val excp_tlb_pf : Vec[Bool] = Vec(PortNumber, Bool()) 36*91946104Sxu_zh val meta_errors : Vec[Bool] = Vec(PortNumber, Bool()) 37*91946104Sxu_zh} 38*91946104Sxu_zh 39*91946104Sxu_zhclass WayLookupGPFEntry(implicit p: Parameters) extends ICacheBundle { 40*91946104Sxu_zh val excp_tlb_gpf : Vec[Bool] = Vec(PortNumber, Bool()) 41*91946104Sxu_zh val gpaddr : UInt = UInt(GPAddrBits.W) 42*91946104Sxu_zh 43*91946104Sxu_zh def hasGPF: Bool = excp_tlb_gpf.asUInt.orR 44*91946104Sxu_zh} 45*91946104Sxu_zh 46b92f8445Sssszwicclass WayLookupInfo(implicit p: Parameters) extends ICacheBundle { 47*91946104Sxu_zh val entry = new WayLookupEntry 48*91946104Sxu_zh val gpf = new WayLookupGPFEntry 49*91946104Sxu_zh 50*91946104Sxu_zh // for compatibility 51*91946104Sxu_zh def vSetIdx : Vec[UInt] = entry.vSetIdx 52*91946104Sxu_zh def waymask : Vec[UInt] = entry.waymask 53*91946104Sxu_zh def ptag : Vec[UInt] = entry.ptag 54*91946104Sxu_zh def excp_tlb_af : Vec[Bool] = entry.excp_tlb_af 55*91946104Sxu_zh def excp_tlb_pf : Vec[Bool] = entry.excp_tlb_pf 56*91946104Sxu_zh def meta_errors : Vec[Bool] = entry.meta_errors 57*91946104Sxu_zh def excp_tlb_gpf : Vec[Bool] = gpf.excp_tlb_gpf 58*91946104Sxu_zh def gpaddr : UInt = gpf.gpaddr 59b92f8445Sssszwic} 60b92f8445Sssszwic 61b92f8445Sssszwic 62b92f8445Sssszwic// class WayLookupRead(implicit p: Parameters) extends ICacheBundle { 63b92f8445Sssszwic// val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 64b92f8445Sssszwic// val waymask = Vec(PortNumber, UInt(nWays.W)) 65b92f8445Sssszwic// val ptag = Vec(PortNumber, UInt(tagBits.W)) 66b92f8445Sssszwic// val excp_tlb_af = Vec(PortNumber, Bool()) 67b92f8445Sssszwic// val excp_tlb_pf = Vec(PortNumber, Bool()) 68b92f8445Sssszwic// } 69b92f8445Sssszwic 70b92f8445Sssszwic// class WayLookupWrite(implicit p: Parameters) extends ICacheBundle { 71b92f8445Sssszwic// val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 72b92f8445Sssszwic// val ptag = Vec(PortNumber, UInt(tagBits.W)) 73b92f8445Sssszwic// val waymask = Vec(PortNumber, UInt(nWays.W)) 74b92f8445Sssszwic// val excp_tlb_af = Vec(PortNumber, Bool()) 75b92f8445Sssszwic// val excp_tlb_pf = Vec(PortNumber, Bool()) 76b92f8445Sssszwic// } 77b92f8445Sssszwic 78b92f8445Sssszwicclass WayLookupInterface(implicit p: Parameters) extends ICacheBundle { 79b92f8445Sssszwic val flush = Input(Bool()) 80b92f8445Sssszwic val read = DecoupledIO(new WayLookupInfo) 81b92f8445Sssszwic val write = Flipped(DecoupledIO(new WayLookupInfo)) 82b92f8445Sssszwic val update = Flipped(ValidIO(new ICacheMissResp)) 83b92f8445Sssszwic} 84b92f8445Sssszwic 85b92f8445Sssszwicclass WayLookup(implicit p: Parameters) extends ICacheModule { 86*91946104Sxu_zh val io: WayLookupInterface = IO(new WayLookupInterface) 87b92f8445Sssszwic 88b92f8445Sssszwic class WayLookupPtr(implicit p: Parameters) extends CircularQueuePtr[WayLookupPtr](nWayLookupSize) 89*91946104Sxu_zh private object WayLookupPtr { 90b92f8445Sssszwic def apply(f: Bool, v: UInt)(implicit p: Parameters): WayLookupPtr = { 91b92f8445Sssszwic val ptr = Wire(new WayLookupPtr) 92b92f8445Sssszwic ptr.flag := f 93b92f8445Sssszwic ptr.value := v 94b92f8445Sssszwic ptr 95b92f8445Sssszwic } 96b92f8445Sssszwic } 97b92f8445Sssszwic 98*91946104Sxu_zh private val entries = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf(new WayLookupEntry)))) 99*91946104Sxu_zh private val readPtr = RegInit(WayLookupPtr(false.B, 0.U)) 100*91946104Sxu_zh private val writePtr = RegInit(WayLookupPtr(false.B, 0.U)) 101b92f8445Sssszwic 102*91946104Sxu_zh private val empty = readPtr === writePtr 103*91946104Sxu_zh private val full = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag) 104b92f8445Sssszwic 105b92f8445Sssszwic when(io.flush) { 106b92f8445Sssszwic writePtr.value := 0.U 107b92f8445Sssszwic writePtr.flag := false.B 108b92f8445Sssszwic }.elsewhen(io.write.fire) { 109b92f8445Sssszwic writePtr := writePtr + 1.U 110b92f8445Sssszwic } 111b92f8445Sssszwic 112b92f8445Sssszwic when(io.flush) { 113b92f8445Sssszwic readPtr.value := 0.U 114b92f8445Sssszwic readPtr.flag := false.B 115b92f8445Sssszwic }.elsewhen(io.read.fire) { 116b92f8445Sssszwic readPtr := readPtr + 1.U 117b92f8445Sssszwic } 118b92f8445Sssszwic 119*91946104Sxu_zh private val gpf_entry = RegInit(0.U.asTypeOf(new WayLookupGPFEntry)) 120*91946104Sxu_zh private val gpfPtr = RegInit(WayLookupPtr(false.B, 0.U)) 121*91946104Sxu_zh 122*91946104Sxu_zh when(io.flush) { 123*91946104Sxu_zh // we don't need to reset gpfPtr, since the valid is actually gpf_entries.excp_tlb_gpf 124*91946104Sxu_zh gpf_entry := 0.U.asTypeOf(new WayLookupGPFEntry) 125*91946104Sxu_zh } 126*91946104Sxu_zh 127b92f8445Sssszwic /** 128b92f8445Sssszwic ****************************************************************************** 129b92f8445Sssszwic * update 130b92f8445Sssszwic ****************************************************************************** 131b92f8445Sssszwic */ 132*91946104Sxu_zh private val hits = Wire(Vec(nWayLookupSize, Bool())) 133b92f8445Sssszwic entries.zip(hits).foreach{ case(entry, hit) => 134b92f8445Sssszwic val hit_vec = Wire(Vec(PortNumber, Bool())) 135b92f8445Sssszwic (0 until PortNumber).foreach { i => 136b92f8445Sssszwic val vset_same = (io.update.bits.vSetIdx === entry.vSetIdx(i)) && !io.update.bits.corrupt && io.update.valid 137b92f8445Sssszwic val ptag_same = getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i) 138b92f8445Sssszwic val way_same = io.update.bits.waymask === entry.waymask(i) 139b92f8445Sssszwic when(vset_same) { 140b92f8445Sssszwic when(ptag_same) { 141b92f8445Sssszwic // miss -> hit 142b92f8445Sssszwic entry.waymask(i) := io.update.bits.waymask 143b92f8445Sssszwic // also clear previously found errors since data/metaArray is refilled 144b92f8445Sssszwic entry.meta_errors(i) := false.B 145b92f8445Sssszwic }.elsewhen(way_same) { 146b92f8445Sssszwic // data is overwritten: hit -> miss 147b92f8445Sssszwic entry.waymask(i) := 0.U 148b92f8445Sssszwic // do not clear previously found errors since way_same might be unreliable when error occurs 149b92f8445Sssszwic } 150b92f8445Sssszwic } 151b92f8445Sssszwic hit_vec(i) := vset_same && (ptag_same || way_same) 152b92f8445Sssszwic } 153b92f8445Sssszwic hit := hit_vec.reduce(_||_) 154b92f8445Sssszwic } 155b92f8445Sssszwic 156b92f8445Sssszwic /** 157b92f8445Sssszwic ****************************************************************************** 158b92f8445Sssszwic * read 159b92f8445Sssszwic ****************************************************************************** 160b92f8445Sssszwic */ 161b92f8445Sssszwic io.read.valid := !empty || io.write.valid 162*91946104Sxu_zh when (empty && io.write.valid) { // bypass 163*91946104Sxu_zh io.read.bits := io.write.bits 164*91946104Sxu_zh }.otherwise { 165*91946104Sxu_zh io.read.bits.entry := entries(readPtr.value) 166*91946104Sxu_zh io.read.bits.gpf := Mux(readPtr === gpfPtr, gpf_entry, 0.U.asTypeOf(new WayLookupGPFEntry)) 167*91946104Sxu_zh } 168b92f8445Sssszwic 169b92f8445Sssszwic /** 170b92f8445Sssszwic ****************************************************************************** 171b92f8445Sssszwic * write 172b92f8445Sssszwic ****************************************************************************** 173b92f8445Sssszwic */ 174b92f8445Sssszwic io.write.ready := !full 175b92f8445Sssszwic when(io.write.fire) { 176*91946104Sxu_zh entries(writePtr.value) := io.write.bits.entry 177*91946104Sxu_zh // save gpf iff no gpf is already saved 178*91946104Sxu_zh when(!gpf_entry.hasGPF && io.write.bits.gpf.hasGPF) { 179*91946104Sxu_zh gpf_entry := io.write.bits.gpf 180*91946104Sxu_zh gpfPtr := writePtr 181*91946104Sxu_zh } 182b92f8445Sssszwic } 183b92f8445Sssszwic} 184