1b92f8445Sssszwic/*************************************************************************************** 2*6c106319Sxu_zh* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3*6c106319Sxu_zh* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 4b92f8445Sssszwic* Copyright (c) 2020-2021 Peng Cheng Laboratory 5b92f8445Sssszwic* 6b92f8445Sssszwic* XiangShan is licensed under Mulan PSL v2. 7b92f8445Sssszwic* You can use this software according to the terms and conditions of the Mulan PSL v2. 8b92f8445Sssszwic* You may obtain a copy of Mulan PSL v2 at: 9b92f8445Sssszwic* http://license.coscl.org.cn/MulanPSL2 10b92f8445Sssszwic* 11b92f8445Sssszwic* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12b92f8445Sssszwic* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13b92f8445Sssszwic* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14b92f8445Sssszwic* 15b92f8445Sssszwic* See the Mulan PSL v2 for more details. 16b92f8445Sssszwic***************************************************************************************/ 17b92f8445Sssszwic 18b92f8445Sssszwicpackage xiangshan.frontend.icache 19b92f8445Sssszwic 20b92f8445Sssszwicimport chisel3._ 21b92f8445Sssszwicimport chisel3.util._ 22cf7d6b7aSMuziimport org.chipsalliance.cde.config.Parameters 23b92f8445Sssszwicimport utility._ 24002c10a4SYanqin Liimport xiangshan.cache.mmu.Pbmt 25cf7d6b7aSMuziimport xiangshan.frontend.ExceptionType 26b92f8445Sssszwic 2791946104Sxu_zh/* WayLookupEntry is for internal storage, while WayLookupInfo is for interface 2891946104Sxu_zh * Notes: 2991946104Sxu_zh * 1. there must be a flush (caused by guest page fault) after excp_tlb_gpf === true.B, 3091946104Sxu_zh * so, we need only the first excp_tlb_gpf and the corresponding gpaddr. 3191946104Sxu_zh * to save area, we separate those signals from WayLookupEntry and store only once. 3291946104Sxu_zh */ 3391946104Sxu_zhclass WayLookupEntry(implicit p: Parameters) extends ICacheBundle { 3491946104Sxu_zh val vSetIdx: Vec[UInt] = Vec(PortNumber, UInt(idxBits.W)) 3591946104Sxu_zh val waymask: Vec[UInt] = Vec(PortNumber, UInt(nWays.W)) 3691946104Sxu_zh val ptag: Vec[UInt] = Vec(PortNumber, UInt(tagBits.W)) 3788895b11Sxu_zh val itlb_exception: Vec[UInt] = Vec(PortNumber, UInt(ExceptionType.width.W)) 38002c10a4SYanqin Li val itlb_pbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W)) 398966a895Sxu_zh val meta_codes: Vec[UInt] = Vec(PortNumber, UInt(ICacheMetaCodeBits.W)) 4091946104Sxu_zh} 4191946104Sxu_zh 4291946104Sxu_zhclass WayLookupGPFEntry(implicit p: Parameters) extends ICacheBundle { 43415fcbe2Sxu_zh // NOTE: we don't use GPAddrBits here, refer to ICacheMainPipe.scala L43-48 and PR#3795 44dd980d61SXu, Zefan val gpaddr: UInt = UInt(PAddrBitsMax.W) 45ad415ae0SXiaokun-Pei val isForVSnonLeafPTE: Bool = Bool() 4691946104Sxu_zh} 4791946104Sxu_zh 48b92f8445Sssszwicclass WayLookupInfo(implicit p: Parameters) extends ICacheBundle { 4991946104Sxu_zh val entry = new WayLookupEntry 5091946104Sxu_zh val gpf = new WayLookupGPFEntry 5191946104Sxu_zh 5291946104Sxu_zh // for compatibility 5391946104Sxu_zh def vSetIdx: Vec[UInt] = entry.vSetIdx 5491946104Sxu_zh def waymask: Vec[UInt] = entry.waymask 5591946104Sxu_zh def ptag: Vec[UInt] = entry.ptag 5688895b11Sxu_zh def itlb_exception: Vec[UInt] = entry.itlb_exception 57002c10a4SYanqin Li def itlb_pbmt: Vec[UInt] = entry.itlb_pbmt 588966a895Sxu_zh def meta_codes: Vec[UInt] = entry.meta_codes 5991946104Sxu_zh def gpaddr: UInt = gpf.gpaddr 60ad415ae0SXiaokun-Pei def isForVSnonLeafPTE: Bool = gpf.isForVSnonLeafPTE 61b92f8445Sssszwic} 62b92f8445Sssszwic 63b92f8445Sssszwicclass WayLookupInterface(implicit p: Parameters) extends ICacheBundle { 64415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 65415fcbe2Sxu_zh val read: DecoupledIO[WayLookupInfo] = DecoupledIO(new WayLookupInfo) 66415fcbe2Sxu_zh val write: DecoupledIO[WayLookupInfo] = Flipped(DecoupledIO(new WayLookupInfo)) 67415fcbe2Sxu_zh val update: Valid[ICacheMissResp] = Flipped(ValidIO(new ICacheMissResp)) 68b92f8445Sssszwic} 69b92f8445Sssszwic 70*6c106319Sxu_zhclass WayLookup(implicit p: Parameters) extends ICacheModule with HasICacheECCHelper { 7191946104Sxu_zh val io: WayLookupInterface = IO(new WayLookupInterface) 72b92f8445Sssszwic 73415fcbe2Sxu_zh class WayLookupPtr extends CircularQueuePtr[WayLookupPtr](nWayLookupSize) 7491946104Sxu_zh private object WayLookupPtr { 75415fcbe2Sxu_zh def apply(f: Bool, v: UInt): WayLookupPtr = { 76b92f8445Sssszwic val ptr = Wire(new WayLookupPtr) 77b92f8445Sssszwic ptr.flag := f 78b92f8445Sssszwic ptr.value := v 79b92f8445Sssszwic ptr 80b92f8445Sssszwic } 81b92f8445Sssszwic } 82b92f8445Sssszwic 8391946104Sxu_zh private val entries = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf(new WayLookupEntry)))) 8491946104Sxu_zh private val readPtr = RegInit(WayLookupPtr(false.B, 0.U)) 8591946104Sxu_zh private val writePtr = RegInit(WayLookupPtr(false.B, 0.U)) 86b92f8445Sssszwic 8791946104Sxu_zh private val empty = readPtr === writePtr 8891946104Sxu_zh private val full = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag) 89b92f8445Sssszwic 90b92f8445Sssszwic when(io.flush) { 91b92f8445Sssszwic writePtr.value := 0.U 92b92f8445Sssszwic writePtr.flag := false.B 93b92f8445Sssszwic }.elsewhen(io.write.fire) { 94b92f8445Sssszwic writePtr := writePtr + 1.U 95b92f8445Sssszwic } 96b92f8445Sssszwic 97b92f8445Sssszwic when(io.flush) { 98b92f8445Sssszwic readPtr.value := 0.U 99b92f8445Sssszwic readPtr.flag := false.B 100b92f8445Sssszwic }.elsewhen(io.read.fire) { 101b92f8445Sssszwic readPtr := readPtr + 1.U 102b92f8445Sssszwic } 103b92f8445Sssszwic 10488895b11Sxu_zh private val gpf_entry = RegInit(0.U.asTypeOf(Valid(new WayLookupGPFEntry))) 10591946104Sxu_zh private val gpfPtr = RegInit(WayLookupPtr(false.B, 0.U)) 106b7a4433dSxu_zh private val gpf_hit = gpfPtr === readPtr && gpf_entry.valid 10791946104Sxu_zh 10891946104Sxu_zh when(io.flush) { 10991946104Sxu_zh // we don't need to reset gpfPtr, since the valid is actually gpf_entries.excp_tlb_gpf 11088895b11Sxu_zh gpf_entry.valid := false.B 11188895b11Sxu_zh gpf_entry.bits := 0.U.asTypeOf(new WayLookupGPFEntry) 11291946104Sxu_zh } 11391946104Sxu_zh 114b92f8445Sssszwic /** 115b92f8445Sssszwic ****************************************************************************** 116b92f8445Sssszwic * update 117b92f8445Sssszwic ****************************************************************************** 118b92f8445Sssszwic */ 11991946104Sxu_zh private val hits = Wire(Vec(nWayLookupSize, Bool())) 120b92f8445Sssszwic entries.zip(hits).foreach { case (entry, hit) => 121b92f8445Sssszwic val hit_vec = Wire(Vec(PortNumber, Bool())) 122b92f8445Sssszwic (0 until PortNumber).foreach { i => 123b92f8445Sssszwic val vset_same = (io.update.bits.vSetIdx === entry.vSetIdx(i)) && !io.update.bits.corrupt && io.update.valid 124b92f8445Sssszwic val ptag_same = getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i) 125b92f8445Sssszwic val way_same = io.update.bits.waymask === entry.waymask(i) 126b92f8445Sssszwic when(vset_same) { 127b92f8445Sssszwic when(ptag_same) { 128b92f8445Sssszwic // miss -> hit 129b92f8445Sssszwic entry.waymask(i) := io.update.bits.waymask 1308966a895Sxu_zh // also update meta_codes 131415fcbe2Sxu_zh // NOTE: we have getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i), 132415fcbe2Sxu_zh // so we can use entry.ptag(i) for better timing 1335ce94708Sxu_zh entry.meta_codes(i) := encodeMetaECC(entry.ptag(i)) 134b92f8445Sssszwic }.elsewhen(way_same) { 135b92f8445Sssszwic // data is overwritten: hit -> miss 136b92f8445Sssszwic entry.waymask(i) := 0.U 137415fcbe2Sxu_zh // don't care meta_codes, since it's not used for a missed request 138b92f8445Sssszwic } 139b92f8445Sssszwic } 140b92f8445Sssszwic hit_vec(i) := vset_same && (ptag_same || way_same) 141b92f8445Sssszwic } 142b92f8445Sssszwic hit := hit_vec.reduce(_ || _) 143b92f8445Sssszwic } 144b92f8445Sssszwic 145b92f8445Sssszwic /** 146b92f8445Sssszwic ****************************************************************************** 147b92f8445Sssszwic * read 148b92f8445Sssszwic ****************************************************************************** 149b92f8445Sssszwic */ 150b7a4433dSxu_zh // if the entry is empty, but there is a valid write, we can bypass it to read port (maybe timing critical) 151b7a4433dSxu_zh private val can_bypass = empty && io.write.valid 152b92f8445Sssszwic io.read.valid := !empty || io.write.valid 153b7a4433dSxu_zh when(can_bypass) { 15491946104Sxu_zh io.read.bits := io.write.bits 155b7a4433dSxu_zh }.otherwise { // can't bypass 15691946104Sxu_zh io.read.bits.entry := entries(readPtr.value) 157b7a4433dSxu_zh when(gpf_hit) { // ptr match && entry valid 158b7a4433dSxu_zh io.read.bits.gpf := gpf_entry.bits 159415fcbe2Sxu_zh // also clear gpf_entry.valid when it's read, note this will be overridden by write (L175) 160b7a4433dSxu_zh when(io.read.fire) { 161b7a4433dSxu_zh gpf_entry.valid := false.B 162b7a4433dSxu_zh } 163b7a4433dSxu_zh }.otherwise { // gpf not hit 164b7a4433dSxu_zh io.read.bits.gpf := 0.U.asTypeOf(new WayLookupGPFEntry) 165b7a4433dSxu_zh } 16691946104Sxu_zh } 167b92f8445Sssszwic 168b92f8445Sssszwic /** 169b92f8445Sssszwic ****************************************************************************** 170b92f8445Sssszwic * write 171b92f8445Sssszwic ****************************************************************************** 172b92f8445Sssszwic */ 173415fcbe2Sxu_zh // if there is a valid gpf to be read, we should stall write 174b7a4433dSxu_zh private val gpf_stall = gpf_entry.valid && !(io.read.fire && gpf_hit) 175b7a4433dSxu_zh io.write.ready := !full && !gpf_stall 176b92f8445Sssszwic when(io.write.fire) { 17791946104Sxu_zh entries(writePtr.value) := io.write.bits.entry 178b7a4433dSxu_zh when(io.write.bits.itlb_exception.map(_ === ExceptionType.gpf).reduce(_ || _)) { 179b7a4433dSxu_zh // if gpf_entry is bypassed, we don't need to save it 180b7a4433dSxu_zh // note this will override the read (L156) 181b7a4433dSxu_zh gpf_entry.valid := !(can_bypass && io.read.fire) 18288895b11Sxu_zh gpf_entry.bits := io.write.bits.gpf 18391946104Sxu_zh gpfPtr := writePtr 18491946104Sxu_zh } 185b92f8445Sssszwic } 186b92f8445Sssszwic} 187