19e12e8edScz4e/*************************************************************************************** 29e12e8edScz4e* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 39e12e8edScz4e* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 49e12e8edScz4e* Copyright (c) 2020-2021 Peng Cheng Laboratory 59e12e8edScz4e* 69e12e8edScz4e* XiangShan is licensed under Mulan PSL v2. 79e12e8edScz4e* You can use this software according to the terms and conditions of the Mulan PSL v2. 89e12e8edScz4e* You may obtain a copy of Mulan PSL v2 at: 99e12e8edScz4e* http://license.coscl.org.cn/MulanPSL2 109e12e8edScz4e* 119e12e8edScz4e* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 129e12e8edScz4e* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 139e12e8edScz4e* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 149e12e8edScz4e* 159e12e8edScz4e* See the Mulan PSL v2 for more details. 169e12e8edScz4e***************************************************************************************/ 179e12e8edScz4e 189e12e8edScz4epackage xiangshan.mem 199e12e8edScz4e 209e12e8edScz4e 219e12e8edScz4eimport org.chipsalliance.cde.config.Parameters 229e12e8edScz4eimport chisel3._ 239e12e8edScz4eimport chisel3.util._ 249e12e8edScz4eimport utility._ 259e12e8edScz4eimport utils._ 269e12e8edScz4eimport xiangshan._ 279e12e8edScz4eimport xiangshan.backend.Bundles._ 289e12e8edScz4eimport xiangshan.backend.rob.RobPtr 299e12e8edScz4eimport xiangshan.backend.fu.FenceToSbuffer 309e12e8edScz4eimport xiangshan.backend.fu.vector.Bundles._ 319e12e8edScz4eimport xiangshan.backend.Bundles._ 329e12e8edScz4eimport xiangshan.mem.prefetch.PrefetchReqBundle 339e12e8edScz4eimport xiangshan.cache._ 349e12e8edScz4eimport xiangshan.cache.wpu.ReplayCarry 359e12e8edScz4eimport xiangshan.cache.mmu._ 369e12e8edScz4eimport math._ 379e12e8edScz4e 389e12e8edScz4eobject Bundles { 399e12e8edScz4e 409e12e8edScz4e class LsPipelineBundle(implicit p: Parameters) extends XSBundle 419e12e8edScz4e with HasDCacheParameters 429e12e8edScz4e with HasVLSUParameters { 439e12e8edScz4e val uop = new DynInst 449e12e8edScz4e val vaddr = UInt(VAddrBits.W) 459e12e8edScz4e val fullva = UInt(XLEN.W) 469e12e8edScz4e val vaNeedExt = Bool() 479e12e8edScz4e val paddr = UInt(PAddrBits.W) 489e12e8edScz4e val gpaddr = UInt(XLEN.W) 499e12e8edScz4e val mask = UInt((VLEN/8).W) 509e12e8edScz4e val data = UInt((VLEN+1).W) 519e12e8edScz4e val wlineflag = Bool() // store write the whole cache line 529e12e8edScz4e val miss = Bool() 539e12e8edScz4e val tlbMiss = Bool() 549e12e8edScz4e val ptwBack = Bool() 559e12e8edScz4e val af = Bool() 569e12e8edScz4e val nc = Bool() 579e12e8edScz4e val mmio = Bool() 589e12e8edScz4e val memBackTypeMM = Bool() // 1: main memory, 0: IO 599e12e8edScz4e val atomic = Bool() 609e12e8edScz4e val hasException = Bool() 6199ce5576Scz4e val isHyper = Bool() 6299ce5576Scz4e val isForVSnonLeafPTE = Bool() 639e12e8edScz4e val isPrefetch = Bool() 649e12e8edScz4e val isHWPrefetch = Bool() 6599ce5576Scz4e val forwardMask = Vec(VLEN/8, Bool()) 6699ce5576Scz4e val forwardData = Vec(VLEN/8, UInt(8.W)) 6799ce5576Scz4e val ldCancel = ValidUndirectioned(UInt(log2Ceil(LoadPipelineWidth).W)) 6899ce5576Scz4e // val func = UInt(6.W) 699e12e8edScz4e 709e12e8edScz4e // vector 719e12e8edScz4e val isvec = Bool() 729e12e8edScz4e val isLastElem = Bool() 739e12e8edScz4e val is128bit = Bool() 749e12e8edScz4e val uop_unit_stride_fof = Bool() 759e12e8edScz4e val usSecondInv = Bool() 769e12e8edScz4e val elemIdx = UInt(elemIdxBits.W) 779e12e8edScz4e val alignedType = UInt(alignTypeBits.W) 789e12e8edScz4e val mbIndex = UInt(max(vlmBindexBits, vsmBindexBits).W) 799e12e8edScz4e val reg_offset = UInt(vOffsetBits.W) 809e12e8edScz4e val elemIdxInsideVd = UInt(elemIdxBits.W) 819e12e8edScz4e val is_first_ele = Bool() 829e12e8edScz4e val vecBaseVaddr = UInt(VAddrBits.W) 839e12e8edScz4e val vecVaddrOffset = UInt(VAddrBits.W) 849e12e8edScz4e val vecTriggerMask = UInt((VLEN/8).W) 8599ce5576Scz4e // 1: vector active element or scala mem operation, 0: vector not active element 8699ce5576Scz4e val vecActive = Bool() 879e12e8edScz4e // val flowPtr = new VlflowPtr() // VLFlowQueue ptr 889e12e8edScz4e // val sflowPtr = new VsFlowPtr() // VSFlowQueue ptr 8999ce5576Scz4e // val rob_idx_valid = Vec(2,Bool()) 9099ce5576Scz4e // val inner_idx = Vec(2,UInt(3.W)) 9199ce5576Scz4e // val rob_idx = Vec(2,new RobPtr) 9299ce5576Scz4e // val offset = Vec(2,UInt(4.W)) 939e12e8edScz4e 9499ce5576Scz4e // replay 959e12e8edScz4e val isLoadReplay = Bool() 969e12e8edScz4e val isFastPath = Bool() 979e12e8edScz4e val isFastReplay = Bool() 989e12e8edScz4e val replayCarry = new ReplayCarry(nWays) 9999ce5576Scz4e val isFirstIssue = Bool() 10099ce5576Scz4e val hasROBEntry = Bool() 1019e12e8edScz4e val mshrid = UInt(log2Up(cfg.nMissEntries).W) 1029e12e8edScz4e val handledByMSHR= Bool() 1039e12e8edScz4e val replacementUpdated = Bool() 1049e12e8edScz4e val missDbUpdated = Bool() 1059e12e8edScz4e val forward_tlDchannel = Bool() 1069e12e8edScz4e val dcacheRequireReplay = Bool() 1079e12e8edScz4e val delayedLoadError = Bool() 1089e12e8edScz4e val lateKill = Bool() 1099e12e8edScz4e val feedbacked = Bool() 1109e12e8edScz4e val schedIndex = UInt(log2Up(LoadQueueReplaySize).W) 1119e12e8edScz4e val tlbNoQuery = Bool() 1129e12e8edScz4e 1139e12e8edScz4e // misalign 11499ce5576Scz4e val isFrmMisAlignBuf = Bool() 1159e12e8edScz4e val isMisalign = Bool() 1169e12e8edScz4e val isFinalSplit = Bool() 1179e12e8edScz4e val misalignWith16Byte = Bool() 1189e12e8edScz4e val misalignNeedWakeUp = Bool() 1199e12e8edScz4e val updateAddrValid = Bool() 12099ce5576Scz4e 12199ce5576Scz4e def isSWPrefetch: Bool = isPrefetch && !isHWPrefetch 1229e12e8edScz4e } 1239e12e8edScz4e 12499ce5576Scz4e class LsPrefetchTrainBundle(implicit p: Parameters) extends LsPipelineBundle { 1259e12e8edScz4e val meta_prefetch = UInt(L1PfSourceBits.W) 1269e12e8edScz4e val meta_access = Bool() 1279e12e8edScz4e 1289e12e8edScz4e def fromLsPipelineBundle(input: LsPipelineBundle, latch: Boolean = false, enable: Bool = true.B) = { 12999ce5576Scz4e val inputReg = latch match { 13099ce5576Scz4e case true => RegEnable(input, enable) 13199ce5576Scz4e case false => input 13299ce5576Scz4e } 13399ce5576Scz4e connectSamePort(this, inputReg) 13499ce5576Scz4e this.meta_prefetch := DontCare 13599ce5576Scz4e this.meta_access := DontCare 1369e12e8edScz4e } 1379e12e8edScz4e 13899ce5576Scz4e def toPrefetchReqBundle(): PrefetchReqBundle = { 1399e12e8edScz4e val res = Wire(new PrefetchReqBundle) 1409e12e8edScz4e res.vaddr := this.vaddr 1419e12e8edScz4e res.paddr := this.paddr 1429e12e8edScz4e res.pc := this.uop.pc 1439e12e8edScz4e res.miss := this.miss 1449e12e8edScz4e res.pfHitStream := isFromStream(this.meta_prefetch) 1459e12e8edScz4e res 1469e12e8edScz4e } 1479e12e8edScz4e } 1489e12e8edScz4e 1499e12e8edScz4e class LqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { 1509e12e8edScz4e // load inst replay informations 1519e12e8edScz4e val rep_info = new LoadToLsqReplayIO 152638f3d84SYanqin Li val nc_with_data = Bool() // nc access with data 1539e12e8edScz4e // queue entry data, except flag bits, will be updated if writeQueue is true, 1549e12e8edScz4e // valid bit in LqWriteBundle will be ignored 1559e12e8edScz4e val data_wen_dup = Vec(6, Bool()) // dirty reg dup 1569e12e8edScz4e 1579e12e8edScz4e def fromLsPipelineBundle(input: LsPipelineBundle, latch: Boolean = false, enable: Bool = true.B) = { 15899ce5576Scz4e val inputReg = latch match { 15999ce5576Scz4e case true => RegEnable(input, enable) 16099ce5576Scz4e case false => input 16199ce5576Scz4e } 16299ce5576Scz4e connectSamePort(this, inputReg) 16399ce5576Scz4e this.rep_info := DontCare 164*4ec1f462Scz4e this.nc_with_data := DontCare 16599ce5576Scz4e this.data_wen_dup := DontCare 1669e12e8edScz4e } 1679e12e8edScz4e } 1689e12e8edScz4e 1699e12e8edScz4e class SqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { 1709e12e8edScz4e val need_rep = Bool() 1719e12e8edScz4e } 1729e12e8edScz4e 1739e12e8edScz4e class LoadForwardQueryIO(implicit p: Parameters) extends XSBundle { 1749e12e8edScz4e val vaddr = Output(UInt(VAddrBits.W)) 1759e12e8edScz4e val paddr = Output(UInt(PAddrBits.W)) 1769e12e8edScz4e val mask = Output(UInt((VLEN/8).W)) 1779e12e8edScz4e val uop = Output(new DynInst) // for replay 1789e12e8edScz4e val pc = Output(UInt(VAddrBits.W)) //for debug 1799e12e8edScz4e val valid = Output(Bool()) 1809e12e8edScz4e 1819e12e8edScz4e val forwardMaskFast = Input(Vec((VLEN/8), Bool())) // resp to load_s1 1829e12e8edScz4e val forwardMask = Input(Vec((VLEN/8), Bool())) // resp to load_s2 1839e12e8edScz4e val forwardData = Input(Vec((VLEN/8), UInt(8.W))) // resp to load_s2 1849e12e8edScz4e 1859e12e8edScz4e // val lqIdx = Output(UInt(LoadQueueIdxWidth.W)) 1869e12e8edScz4e val sqIdx = Output(new SqPtr) 1879e12e8edScz4e 1889e12e8edScz4e // dataInvalid suggests store to load forward found forward should happen, 1899e12e8edScz4e // but data is not available for now. If dataInvalid, load inst should 1909e12e8edScz4e // be replayed from RS. Feedback type should be RSFeedbackType.dataInvalid 1919e12e8edScz4e val dataInvalid = Input(Bool()) // Addr match, but data is not valid for now 1929e12e8edScz4e 1939e12e8edScz4e // matchInvalid suggests in store to load forward logic, paddr cam result does 1949e12e8edScz4e // to equal to vaddr cam result. If matchInvalid, a microarchitectural exception 1959e12e8edScz4e // should be raised to flush SQ and committed sbuffer. 1969e12e8edScz4e val matchInvalid = Input(Bool()) // resp to load_s2 1979e12e8edScz4e 1989e12e8edScz4e // addrInvalid suggests store to load forward found forward should happen, 1999e12e8edScz4e // but address (SSID) is not available for now. If addrInvalid, load inst should 2009e12e8edScz4e // be replayed from RS. Feedback type should be RSFeedbackType.addrInvalid 2019e12e8edScz4e val addrInvalid = Input(Bool()) 2029e12e8edScz4e } 2039e12e8edScz4e 2049e12e8edScz4e // LoadForwardQueryIO used in load pipeline 2059e12e8edScz4e // 2069e12e8edScz4e // Difference between PipeLoadForwardQueryIO and LoadForwardQueryIO: 2079e12e8edScz4e // PipeIO use predecoded sqIdxMask for better forward timing 2089e12e8edScz4e class PipeLoadForwardQueryIO(implicit p: Parameters) extends LoadForwardQueryIO { 2099e12e8edScz4e // val sqIdx = Output(new SqPtr) // for debug, should not be used in pipeline for timing reasons 2109e12e8edScz4e // sqIdxMask is calcuated in earlier stage for better timing 2119e12e8edScz4e val sqIdxMask = Output(UInt(StoreQueueSize.W)) 2129e12e8edScz4e 2139e12e8edScz4e // dataInvalid: addr match, but data is not valid for now 2149e12e8edScz4e val dataInvalidFast = Input(Bool()) // resp to load_s1 2159e12e8edScz4e // val dataInvalid = Input(Bool()) // resp to load_s2 2169e12e8edScz4e val dataInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 2179e12e8edScz4e val addrInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 2189e12e8edScz4e } 2199e12e8edScz4e 2209e12e8edScz4e // Query load queue for ld-ld violation 2219e12e8edScz4e // 2229e12e8edScz4e // Req should be send in load_s1 2239e12e8edScz4e // Resp will be generated 1 cycle later 2249e12e8edScz4e // 2259e12e8edScz4e // Note that query req may be !ready, as dcache is releasing a block 2269e12e8edScz4e // If it happens, a replay from rs is needed. 22799ce5576Scz4e class LoadNukeQueryReqBundle(implicit p: Parameters) extends XSBundle { // provide lqIdx 2289e12e8edScz4e val uop = new DynInst 2299e12e8edScz4e // mask: load's data mask. 2309e12e8edScz4e val mask = UInt((VLEN/8).W) 2319e12e8edScz4e 2329e12e8edScz4e // paddr: load's paddr. 2339e12e8edScz4e val paddr = UInt(PAddrBits.W) 2349e12e8edScz4e // dataInvalid: load data is invalid. 2359e12e8edScz4e val data_valid = Bool() 2369e12e8edScz4e // nc: is NC access 2379e12e8edScz4e val is_nc = Bool() 2389e12e8edScz4e } 2399e12e8edScz4e 24099ce5576Scz4e class LoadNukeQueryRespBundle(implicit p: Parameters) extends XSBundle { 2419e12e8edScz4e // rep_frm_fetch: ld-ld violation check success, replay from fetch. 2429e12e8edScz4e val rep_frm_fetch = Bool() 2439e12e8edScz4e } 2449e12e8edScz4e 2459e12e8edScz4e class LoadNukeQueryIO(implicit p: Parameters) extends XSBundle { 24699ce5576Scz4e val req = Decoupled(new LoadNukeQueryReqBundle) 24799ce5576Scz4e val resp = Flipped(Valid(new LoadNukeQueryRespBundle)) 2489e12e8edScz4e val revoke = Output(Bool()) 2499e12e8edScz4e } 2509e12e8edScz4e 25199ce5576Scz4e class StoreNukeQueryBundle(implicit p: Parameters) extends XSBundle { 2529e12e8edScz4e // robIdx: Requestor's (a store instruction) rob index for match logic. 2539e12e8edScz4e val robIdx = new RobPtr 2549e12e8edScz4e 2559e12e8edScz4e // paddr: requestor's (a store instruction) physical address for match logic. 2569e12e8edScz4e val paddr = UInt(PAddrBits.W) 2579e12e8edScz4e 2589e12e8edScz4e // mask: requestor's (a store instruction) data width mask for match logic. 2599e12e8edScz4e val mask = UInt((VLEN/8).W) 2609e12e8edScz4e 2619e12e8edScz4e // matchLine: if store is vector 128-bits, load unit need to compare 128-bits vaddr. 2629e12e8edScz4e val matchLine = Bool() 2639e12e8edScz4e } 2649e12e8edScz4e 2659e12e8edScz4e class StoreMaBufToSqControlIO(implicit p: Parameters) extends XSBundle { 2669e12e8edScz4e // from storeMisalignBuffer to storeQueue, control it's sbuffer write 2679e12e8edScz4e val toStoreQueue = Output(new XSBundle { 2689e12e8edScz4e // This entry is a cross page 2699e12e8edScz4e val crossPageWithHit = Bool() 2709e12e8edScz4e val crossPageCanDeq = Bool() 2719e12e8edScz4e // High page Paddr 2729e12e8edScz4e val paddr = UInt(PAddrBits.W) 2739e12e8edScz4e 2749e12e8edScz4e val withSameUop = Bool() 2759e12e8edScz4e }) 2769e12e8edScz4e // from storeQueue to storeMisalignBuffer, provide detail info of this store 2779e12e8edScz4e val toStoreMisalignBuffer = Input(new XSBundle { 2789e12e8edScz4e val sqPtr = new SqPtr 2799e12e8edScz4e val doDeq = Bool() 2809e12e8edScz4e 2819e12e8edScz4e val uop = new DynInst() 2829e12e8edScz4e }) 2839e12e8edScz4e } 2849e12e8edScz4e 2859e12e8edScz4e class StoreMaBufToVecStoreMergeBufferIO(implicit p: Parameters) extends VLSUBundle{ 2869e12e8edScz4e val mbIndex = Output(UInt(vsmBindexBits.W)) 2879e12e8edScz4e val flush = Output(Bool()) 2889e12e8edScz4e } 2899e12e8edScz4e 2909e12e8edScz4e // Store byte valid mask write bundle 2919e12e8edScz4e // 2929e12e8edScz4e // Store byte valid mask write to SQ takes 2 cycles 2939e12e8edScz4e class StoreMaskBundle(implicit p: Parameters) extends XSBundle { 2949e12e8edScz4e val sqIdx = new SqPtr 2959e12e8edScz4e val mask = UInt((VLEN/8).W) 2969e12e8edScz4e } 2979e12e8edScz4e 2989e12e8edScz4e class LoadDataFromDcacheBundle(implicit p: Parameters) extends DCacheBundle { 2999e12e8edScz4e // old dcache: optimize data sram read fanout 3009e12e8edScz4e // val bankedDcacheData = Vec(DCacheBanks, UInt(64.W)) 3019e12e8edScz4e // val bank_oh = UInt(DCacheBanks.W) 3029e12e8edScz4e 3039e12e8edScz4e // new dcache 3049e12e8edScz4e val respDcacheData = UInt(VLEN.W) 3059e12e8edScz4e val forwardMask = Vec(VLEN/8, Bool()) 3069e12e8edScz4e val forwardData = Vec(VLEN/8, UInt(8.W)) 3079e12e8edScz4e val uop = new DynInst // for data selection, only fwen and fuOpType are used 3089e12e8edScz4e val addrOffset = UInt(4.W) // for data selection 3099e12e8edScz4e 3109e12e8edScz4e // forward tilelink D channel 3119e12e8edScz4e val forward_D = Bool() 3129e12e8edScz4e val forwardData_D = Vec(VLEN/8, UInt(8.W)) 3139e12e8edScz4e 3149e12e8edScz4e // forward mshr data 3159e12e8edScz4e val forward_mshr = Bool() 3169e12e8edScz4e val forwardData_mshr = Vec(VLEN/8, UInt(8.W)) 3179e12e8edScz4e 3189e12e8edScz4e val forward_result_valid = Bool() 3199e12e8edScz4e 3209e12e8edScz4e def mergeTLData(): UInt = { 3219e12e8edScz4e // merge TL D or MSHR data at load s2 3229e12e8edScz4e val dcache_data = respDcacheData 3239e12e8edScz4e val use_D = forward_D && forward_result_valid 3249e12e8edScz4e val use_mshr = forward_mshr && forward_result_valid 3259e12e8edScz4e Mux( 3269e12e8edScz4e use_D || use_mshr, 3279e12e8edScz4e Mux( 3289e12e8edScz4e use_D, 3299e12e8edScz4e forwardData_D.asUInt, 3309e12e8edScz4e forwardData_mshr.asUInt 3319e12e8edScz4e ), 3329e12e8edScz4e dcache_data 3339e12e8edScz4e ) 3349e12e8edScz4e } 3359e12e8edScz4e 3369e12e8edScz4e def mergeLsqFwdData(dcacheData: UInt): UInt = { 3379e12e8edScz4e // merge dcache and lsq forward data at load s3 3389e12e8edScz4e val rdataVec = VecInit((0 until VLEN / 8).map(j => 3399e12e8edScz4e Mux(forwardMask(j), forwardData(j), dcacheData(8*(j+1)-1, 8*j)) 3409e12e8edScz4e )) 3419e12e8edScz4e rdataVec.asUInt 3429e12e8edScz4e } 3439e12e8edScz4e } 3449e12e8edScz4e 3459e12e8edScz4e // Load writeback data from load queue (refill) 3469e12e8edScz4e class LoadDataFromLQBundle(implicit p: Parameters) extends XSBundle { 3479e12e8edScz4e val lqData = UInt(64.W) // load queue has merged data 3489e12e8edScz4e val uop = new DynInst // for data selection, only fwen and fuOpType are used 3499e12e8edScz4e val addrOffset = UInt(3.W) // for data selection 3509e12e8edScz4e 3519e12e8edScz4e def mergedData(): UInt = { 3529e12e8edScz4e lqData 3539e12e8edScz4e } 3549e12e8edScz4e } 3559e12e8edScz4e 3569e12e8edScz4e // Bundle for load / store wait waking up 35799ce5576Scz4e class MemWaitUpdateReqBundle(implicit p: Parameters) extends XSBundle { 3589e12e8edScz4e val robIdx = Vec(backendParams.StaExuCnt, ValidIO(new RobPtr)) 3599e12e8edScz4e val sqIdx = Vec(backendParams.StdCnt, ValidIO(new SqPtr)) 3609e12e8edScz4e } 3619e12e8edScz4e 362*4ec1f462Scz4e class MisalignBufferEnqIO(implicit p: Parameters) extends XSBundle { 363*4ec1f462Scz4e val req = DecoupledIO(new LqWriteBundle) 364*4ec1f462Scz4e val revoke = Output(Bool()) 365*4ec1f462Scz4e } 366*4ec1f462Scz4e 3679e12e8edScz4e} 368