1*b92f8445Sssszwic/*************************************************************************************** 2*b92f8445Sssszwic * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*b92f8445Sssszwic * Copyright (c) 2020-2021 Peng Cheng Laboratory 4*b92f8445Sssszwic * 5*b92f8445Sssszwic * XiangShan is licensed under Mulan PSL v2. 6*b92f8445Sssszwic * You can use this software according to the terms and conditions of the Mulan PSL v2. 7*b92f8445Sssszwic * You may obtain a copy of Mulan PSL v2 at: 8*b92f8445Sssszwic * http://license.coscl.org.cn/MulanPSL2 9*b92f8445Sssszwic * 10*b92f8445Sssszwic * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*b92f8445Sssszwic * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*b92f8445Sssszwic * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*b92f8445Sssszwic * 14*b92f8445Sssszwic * See the Mulan PSL v2 for more details. 15*b92f8445Sssszwic ***************************************************************************************/ 16*b92f8445Sssszwic 17*b92f8445Sssszwicpackage xiangshan.frontend.icache 18*b92f8445Sssszwic 19*b92f8445Sssszwicimport org.chipsalliance.cde.config.Parameters 20*b92f8445Sssszwicimport chisel3._ 21*b92f8445Sssszwicimport chisel3.util._ 22*b92f8445Sssszwicimport difftest._ 23*b92f8445Sssszwicimport freechips.rocketchip.tilelink._ 24*b92f8445Sssszwicimport utils._ 25*b92f8445Sssszwicimport xiangshan.cache.mmu._ 26*b92f8445Sssszwicimport xiangshan.frontend._ 27*b92f8445Sssszwicimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 28*b92f8445Sssszwicimport huancun.PreferCacheKey 29*b92f8445Sssszwicimport xiangshan.XSCoreParamsKey 30*b92f8445Sssszwicimport utility._ 31*b92f8445Sssszwic 32*b92f8445Sssszwicclass WayLookupInfo(implicit p: Parameters) extends ICacheBundle { 33*b92f8445Sssszwic val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 34*b92f8445Sssszwic val waymask = Vec(PortNumber, UInt(nWays.W)) 35*b92f8445Sssszwic val ptag = Vec(PortNumber, UInt(tagBits.W)) 36*b92f8445Sssszwic val gpaddr = Vec(PortNumber, UInt(GPAddrBits.W)) 37*b92f8445Sssszwic val excp_tlb_af = Vec(PortNumber, Bool()) 38*b92f8445Sssszwic val excp_tlb_pf = Vec(PortNumber, Bool()) 39*b92f8445Sssszwic val excp_tlb_gpf = Vec(PortNumber, Bool()) 40*b92f8445Sssszwic val meta_errors = Vec(PortNumber, Bool()) 41*b92f8445Sssszwic} 42*b92f8445Sssszwic 43*b92f8445Sssszwic 44*b92f8445Sssszwic// class WayLookupRead(implicit p: Parameters) extends ICacheBundle { 45*b92f8445Sssszwic// val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 46*b92f8445Sssszwic// val waymask = Vec(PortNumber, UInt(nWays.W)) 47*b92f8445Sssszwic// val ptag = Vec(PortNumber, UInt(tagBits.W)) 48*b92f8445Sssszwic// val excp_tlb_af = Vec(PortNumber, Bool()) 49*b92f8445Sssszwic// val excp_tlb_pf = Vec(PortNumber, Bool()) 50*b92f8445Sssszwic// } 51*b92f8445Sssszwic 52*b92f8445Sssszwic// class WayLookupWrite(implicit p: Parameters) extends ICacheBundle { 53*b92f8445Sssszwic// val vSetIdx = Vec(PortNumber, UInt(idxBits.W)) 54*b92f8445Sssszwic// val ptag = Vec(PortNumber, UInt(tagBits.W)) 55*b92f8445Sssszwic// val waymask = Vec(PortNumber, UInt(nWays.W)) 56*b92f8445Sssszwic// val excp_tlb_af = Vec(PortNumber, Bool()) 57*b92f8445Sssszwic// val excp_tlb_pf = Vec(PortNumber, Bool()) 58*b92f8445Sssszwic// } 59*b92f8445Sssszwic 60*b92f8445Sssszwicclass WayLookupInterface(implicit p: Parameters) extends ICacheBundle { 61*b92f8445Sssszwic val flush = Input(Bool()) 62*b92f8445Sssszwic val read = DecoupledIO(new WayLookupInfo) 63*b92f8445Sssszwic val write = Flipped(DecoupledIO(new WayLookupInfo)) 64*b92f8445Sssszwic val update = Flipped(ValidIO(new ICacheMissResp)) 65*b92f8445Sssszwic} 66*b92f8445Sssszwic 67*b92f8445Sssszwicclass WayLookup(implicit p: Parameters) extends ICacheModule { 68*b92f8445Sssszwic val io = IO(new WayLookupInterface) 69*b92f8445Sssszwic 70*b92f8445Sssszwic class WayLookupPtr(implicit p: Parameters) extends CircularQueuePtr[WayLookupPtr](nWayLookupSize) 71*b92f8445Sssszwic object WayLookupPtr { 72*b92f8445Sssszwic def apply(f: Bool, v: UInt)(implicit p: Parameters): WayLookupPtr = { 73*b92f8445Sssszwic val ptr = Wire(new WayLookupPtr) 74*b92f8445Sssszwic ptr.flag := f 75*b92f8445Sssszwic ptr.value := v 76*b92f8445Sssszwic ptr 77*b92f8445Sssszwic } 78*b92f8445Sssszwic } 79*b92f8445Sssszwic 80*b92f8445Sssszwic val entries = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf((new WayLookupInfo).cloneType)))) 81*b92f8445Sssszwic val readPtr = RegInit(WayLookupPtr(false.B, 0.U)) 82*b92f8445Sssszwic val writePtr = RegInit(WayLookupPtr(false.B, 0.U)) 83*b92f8445Sssszwic 84*b92f8445Sssszwic val empty = readPtr === writePtr 85*b92f8445Sssszwic val full = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag) 86*b92f8445Sssszwic 87*b92f8445Sssszwic when(io.flush) { 88*b92f8445Sssszwic writePtr.value := 0.U 89*b92f8445Sssszwic writePtr.flag := false.B 90*b92f8445Sssszwic }.elsewhen(io.write.fire) { 91*b92f8445Sssszwic writePtr := writePtr + 1.U 92*b92f8445Sssszwic } 93*b92f8445Sssszwic 94*b92f8445Sssszwic when(io.flush) { 95*b92f8445Sssszwic readPtr.value := 0.U 96*b92f8445Sssszwic readPtr.flag := false.B 97*b92f8445Sssszwic }.elsewhen(io.read.fire) { 98*b92f8445Sssszwic readPtr := readPtr + 1.U 99*b92f8445Sssszwic } 100*b92f8445Sssszwic 101*b92f8445Sssszwic /** 102*b92f8445Sssszwic ****************************************************************************** 103*b92f8445Sssszwic * update 104*b92f8445Sssszwic ****************************************************************************** 105*b92f8445Sssszwic */ 106*b92f8445Sssszwic val hits = Wire(Vec(nWayLookupSize, Bool())) 107*b92f8445Sssszwic entries.zip(hits).foreach{case(entry, hit) => 108*b92f8445Sssszwic val hit_vec = Wire(Vec(PortNumber, Bool())) 109*b92f8445Sssszwic (0 until PortNumber).foreach { i => 110*b92f8445Sssszwic val vset_same = (io.update.bits.vSetIdx === entry.vSetIdx(i)) && !io.update.bits.corrupt && io.update.valid 111*b92f8445Sssszwic val ptag_same = getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i) 112*b92f8445Sssszwic val way_same = io.update.bits.waymask === entry.waymask(i) 113*b92f8445Sssszwic when(vset_same) { 114*b92f8445Sssszwic when(ptag_same) { 115*b92f8445Sssszwic // miss -> hit 116*b92f8445Sssszwic entry.waymask(i) := io.update.bits.waymask 117*b92f8445Sssszwic // also clear previously found errors since data/metaArray is refilled 118*b92f8445Sssszwic entry.meta_errors(i) := false.B 119*b92f8445Sssszwic }.elsewhen(way_same) { 120*b92f8445Sssszwic // data is overwritten: hit -> miss 121*b92f8445Sssszwic entry.waymask(i) := 0.U 122*b92f8445Sssszwic // do not clear previously found errors since way_same might be unreliable when error occurs 123*b92f8445Sssszwic } 124*b92f8445Sssszwic } 125*b92f8445Sssszwic hit_vec(i) := vset_same && (ptag_same || way_same) 126*b92f8445Sssszwic } 127*b92f8445Sssszwic hit := hit_vec.reduce(_||_) 128*b92f8445Sssszwic } 129*b92f8445Sssszwic 130*b92f8445Sssszwic /** 131*b92f8445Sssszwic ****************************************************************************** 132*b92f8445Sssszwic * read 133*b92f8445Sssszwic ****************************************************************************** 134*b92f8445Sssszwic */ 135*b92f8445Sssszwic val bypass = empty && io.write.valid 136*b92f8445Sssszwic io.read.valid := !empty || io.write.valid 137*b92f8445Sssszwic io.read.bits := Mux(bypass, io.write.bits, entries(readPtr.value)) 138*b92f8445Sssszwic 139*b92f8445Sssszwic /** 140*b92f8445Sssszwic ****************************************************************************** 141*b92f8445Sssszwic * write 142*b92f8445Sssszwic ****************************************************************************** 143*b92f8445Sssszwic */ 144*b92f8445Sssszwic io.write.ready := !full 145*b92f8445Sssszwic when(io.write.fire) { 146*b92f8445Sssszwic entries(writePtr.value) := io.write.bits 147*b92f8445Sssszwic } 148*b92f8445Sssszwic} 149