1/*************************************************************************************** 2* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 4* Copyright (c) 2020-2021 Peng Cheng Laboratory 5* 6* XiangShan is licensed under Mulan PSL v2. 7* You can use this software according to the terms and conditions of the Mulan PSL v2. 8* You may obtain a copy of Mulan PSL v2 at: 9* http://license.coscl.org.cn/MulanPSL2 10* 11* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14* 15* See the Mulan PSL v2 for more details. 16***************************************************************************************/ 17 18package xiangshan.mem 19 20 21import org.chipsalliance.cde.config.Parameters 22import chisel3._ 23import chisel3.util._ 24import utility._ 25import utils._ 26import xiangshan._ 27import xiangshan.backend.Bundles._ 28import xiangshan.backend.rob.RobPtr 29import xiangshan.backend.fu.FenceToSbuffer 30import xiangshan.backend.fu.vector.Bundles._ 31import xiangshan.backend.Bundles._ 32import xiangshan.mem.prefetch.PrefetchReqBundle 33import xiangshan.cache._ 34import xiangshan.cache.wpu.ReplayCarry 35import xiangshan.cache.mmu._ 36import math._ 37 38object Bundles { 39 40 class LsPipelineBundle(implicit p: Parameters) extends XSBundle 41 with HasDCacheParameters 42 with HasVLSUParameters { 43 val uop = new DynInst 44 val vaddr = UInt(VAddrBits.W) 45 val fullva = UInt(XLEN.W) 46 val vaNeedExt = Bool() 47 val paddr = UInt(PAddrBits.W) 48 val gpaddr = UInt(XLEN.W) 49 val mask = UInt((VLEN/8).W) 50 val data = UInt((VLEN+1).W) 51 val wlineflag = Bool() // store write the whole cache line 52 val miss = Bool() 53 val tlbMiss = Bool() 54 val ptwBack = Bool() 55 val af = Bool() 56 val nc = Bool() 57 val mmio = Bool() 58 val memBackTypeMM = Bool() // 1: main memory, 0: IO 59 val atomic = Bool() 60 val hasException = Bool() 61 val isHyper = Bool() 62 val isForVSnonLeafPTE = Bool() 63 val isPrefetch = Bool() 64 val isHWPrefetch = Bool() 65 val forwardMask = Vec(VLEN/8, Bool()) 66 val forwardData = Vec(VLEN/8, UInt(8.W)) 67 val ldCancel = ValidUndirectioned(UInt(log2Ceil(LoadPipelineWidth).W)) 68 // val func = UInt(6.W) 69 70 // vector 71 val isvec = Bool() 72 val isLastElem = Bool() 73 val is128bit = Bool() 74 val uop_unit_stride_fof = Bool() 75 val usSecondInv = Bool() 76 val elemIdx = UInt(elemIdxBits.W) 77 val alignedType = UInt(alignTypeBits.W) 78 val mbIndex = UInt(max(vlmBindexBits, vsmBindexBits).W) 79 val reg_offset = UInt(vOffsetBits.W) 80 val elemIdxInsideVd = UInt(elemIdxBits.W) 81 val is_first_ele = Bool() 82 val vecBaseVaddr = UInt(VAddrBits.W) 83 val vecVaddrOffset = UInt(VAddrBits.W) 84 val vecTriggerMask = UInt((VLEN/8).W) 85 // 1: vector active element or scala mem operation, 0: vector not active element 86 val vecActive = Bool() 87 // val flowPtr = new VlflowPtr() // VLFlowQueue ptr 88 // val sflowPtr = new VsFlowPtr() // VSFlowQueue ptr 89 // val rob_idx_valid = Vec(2,Bool()) 90 // val inner_idx = Vec(2,UInt(3.W)) 91 // val rob_idx = Vec(2,new RobPtr) 92 // val offset = Vec(2,UInt(4.W)) 93 94 // replay 95 val isLoadReplay = Bool() 96 val isFastPath = Bool() 97 val isFastReplay = Bool() 98 val replayCarry = new ReplayCarry(nWays) 99 val isFirstIssue = Bool() 100 val hasROBEntry = Bool() 101 val mshrid = UInt(log2Up(cfg.nMissEntries).W) 102 val handledByMSHR= Bool() 103 val replacementUpdated = Bool() 104 val missDbUpdated = Bool() 105 val forward_tlDchannel = Bool() 106 val dcacheRequireReplay = Bool() 107 val delayedLoadError = Bool() 108 val lateKill = Bool() 109 val feedbacked = Bool() 110 val schedIndex = UInt(log2Up(LoadQueueReplaySize).W) 111 val tlbNoQuery = Bool() 112 113 // misalign 114 val isFrmMisAlignBuf = Bool() 115 val isMisalign = Bool() 116 val isFinalSplit = Bool() 117 val misalignWith16Byte = Bool() 118 val misalignNeedWakeUp = Bool() 119 val updateAddrValid = Bool() 120 121 def isSWPrefetch: Bool = isPrefetch && !isHWPrefetch 122 } 123 124 class LsPrefetchTrainBundle(implicit p: Parameters) extends LsPipelineBundle { 125 val meta_prefetch = UInt(L1PfSourceBits.W) 126 val meta_access = Bool() 127 128 def fromLsPipelineBundle(input: LsPipelineBundle, latch: Boolean = false, enable: Bool = true.B) = { 129 val inputReg = latch match { 130 case true => RegEnable(input, enable) 131 case false => input 132 } 133 connectSamePort(this, inputReg) 134 this.meta_prefetch := DontCare 135 this.meta_access := DontCare 136 } 137 138 def toPrefetchReqBundle(): PrefetchReqBundle = { 139 val res = Wire(new PrefetchReqBundle) 140 res.vaddr := this.vaddr 141 res.paddr := this.paddr 142 res.pc := this.uop.pc 143 res.miss := this.miss 144 res.pfHitStream := isFromStream(this.meta_prefetch) 145 res 146 } 147 } 148 149 class LqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { 150 // load inst replay informations 151 val rep_info = new LoadToLsqReplayIO 152 val nc_with_data = Bool() // nc access with data 153 // queue entry data, except flag bits, will be updated if writeQueue is true, 154 // valid bit in LqWriteBundle will be ignored 155 val data_wen_dup = Vec(6, Bool()) // dirty reg dup 156 157 def fromLsPipelineBundle(input: LsPipelineBundle, latch: Boolean = false, enable: Bool = true.B) = { 158 val inputReg = latch match { 159 case true => RegEnable(input, enable) 160 case false => input 161 } 162 connectSamePort(this, inputReg) 163 this.rep_info := DontCare 164 this.data_wen_dup := DontCare 165 } 166 } 167 168 class SqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { 169 val need_rep = Bool() 170 } 171 172 class LoadForwardQueryIO(implicit p: Parameters) extends XSBundle { 173 val vaddr = Output(UInt(VAddrBits.W)) 174 val paddr = Output(UInt(PAddrBits.W)) 175 val mask = Output(UInt((VLEN/8).W)) 176 val uop = Output(new DynInst) // for replay 177 val pc = Output(UInt(VAddrBits.W)) //for debug 178 val valid = Output(Bool()) 179 180 val forwardMaskFast = Input(Vec((VLEN/8), Bool())) // resp to load_s1 181 val forwardMask = Input(Vec((VLEN/8), Bool())) // resp to load_s2 182 val forwardData = Input(Vec((VLEN/8), UInt(8.W))) // resp to load_s2 183 184 // val lqIdx = Output(UInt(LoadQueueIdxWidth.W)) 185 val sqIdx = Output(new SqPtr) 186 187 // dataInvalid suggests store to load forward found forward should happen, 188 // but data is not available for now. If dataInvalid, load inst should 189 // be replayed from RS. Feedback type should be RSFeedbackType.dataInvalid 190 val dataInvalid = Input(Bool()) // Addr match, but data is not valid for now 191 192 // matchInvalid suggests in store to load forward logic, paddr cam result does 193 // to equal to vaddr cam result. If matchInvalid, a microarchitectural exception 194 // should be raised to flush SQ and committed sbuffer. 195 val matchInvalid = Input(Bool()) // resp to load_s2 196 197 // addrInvalid suggests store to load forward found forward should happen, 198 // but address (SSID) is not available for now. If addrInvalid, load inst should 199 // be replayed from RS. Feedback type should be RSFeedbackType.addrInvalid 200 val addrInvalid = Input(Bool()) 201 } 202 203 // LoadForwardQueryIO used in load pipeline 204 // 205 // Difference between PipeLoadForwardQueryIO and LoadForwardQueryIO: 206 // PipeIO use predecoded sqIdxMask for better forward timing 207 class PipeLoadForwardQueryIO(implicit p: Parameters) extends LoadForwardQueryIO { 208 // val sqIdx = Output(new SqPtr) // for debug, should not be used in pipeline for timing reasons 209 // sqIdxMask is calcuated in earlier stage for better timing 210 val sqIdxMask = Output(UInt(StoreQueueSize.W)) 211 212 // dataInvalid: addr match, but data is not valid for now 213 val dataInvalidFast = Input(Bool()) // resp to load_s1 214 // val dataInvalid = Input(Bool()) // resp to load_s2 215 val dataInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 216 val addrInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 217 } 218 219 // Query load queue for ld-ld violation 220 // 221 // Req should be send in load_s1 222 // Resp will be generated 1 cycle later 223 // 224 // Note that query req may be !ready, as dcache is releasing a block 225 // If it happens, a replay from rs is needed. 226 class LoadNukeQueryReqBundle(implicit p: Parameters) extends XSBundle { // provide lqIdx 227 val uop = new DynInst 228 // mask: load's data mask. 229 val mask = UInt((VLEN/8).W) 230 231 // paddr: load's paddr. 232 val paddr = UInt(PAddrBits.W) 233 // dataInvalid: load data is invalid. 234 val data_valid = Bool() 235 // nc: is NC access 236 val is_nc = Bool() 237 } 238 239 class LoadNukeQueryRespBundle(implicit p: Parameters) extends XSBundle { 240 // rep_frm_fetch: ld-ld violation check success, replay from fetch. 241 val rep_frm_fetch = Bool() 242 } 243 244 class LoadNukeQueryIO(implicit p: Parameters) extends XSBundle { 245 val req = Decoupled(new LoadNukeQueryReqBundle) 246 val resp = Flipped(Valid(new LoadNukeQueryRespBundle)) 247 val revoke = Output(Bool()) 248 } 249 250 class StoreNukeQueryBundle(implicit p: Parameters) extends XSBundle { 251 // robIdx: Requestor's (a store instruction) rob index for match logic. 252 val robIdx = new RobPtr 253 254 // paddr: requestor's (a store instruction) physical address for match logic. 255 val paddr = UInt(PAddrBits.W) 256 257 // mask: requestor's (a store instruction) data width mask for match logic. 258 val mask = UInt((VLEN/8).W) 259 260 // matchLine: if store is vector 128-bits, load unit need to compare 128-bits vaddr. 261 val matchLine = Bool() 262 } 263 264 class StoreMaBufToSqControlIO(implicit p: Parameters) extends XSBundle { 265 // from storeMisalignBuffer to storeQueue, control it's sbuffer write 266 val toStoreQueue = Output(new XSBundle { 267 // This entry is a cross page 268 val crossPageWithHit = Bool() 269 val crossPageCanDeq = Bool() 270 // High page Paddr 271 val paddr = UInt(PAddrBits.W) 272 273 val withSameUop = Bool() 274 }) 275 // from storeQueue to storeMisalignBuffer, provide detail info of this store 276 val toStoreMisalignBuffer = Input(new XSBundle { 277 val sqPtr = new SqPtr 278 val doDeq = Bool() 279 280 val uop = new DynInst() 281 }) 282 } 283 284 class StoreMaBufToVecStoreMergeBufferIO(implicit p: Parameters) extends VLSUBundle{ 285 val mbIndex = Output(UInt(vsmBindexBits.W)) 286 val flush = Output(Bool()) 287 } 288 289 // Store byte valid mask write bundle 290 // 291 // Store byte valid mask write to SQ takes 2 cycles 292 class StoreMaskBundle(implicit p: Parameters) extends XSBundle { 293 val sqIdx = new SqPtr 294 val mask = UInt((VLEN/8).W) 295 } 296 297 class LoadDataFromDcacheBundle(implicit p: Parameters) extends DCacheBundle { 298 // old dcache: optimize data sram read fanout 299 // val bankedDcacheData = Vec(DCacheBanks, UInt(64.W)) 300 // val bank_oh = UInt(DCacheBanks.W) 301 302 // new dcache 303 val respDcacheData = UInt(VLEN.W) 304 val forwardMask = Vec(VLEN/8, Bool()) 305 val forwardData = Vec(VLEN/8, UInt(8.W)) 306 val uop = new DynInst // for data selection, only fwen and fuOpType are used 307 val addrOffset = UInt(4.W) // for data selection 308 309 // forward tilelink D channel 310 val forward_D = Bool() 311 val forwardData_D = Vec(VLEN/8, UInt(8.W)) 312 313 // forward mshr data 314 val forward_mshr = Bool() 315 val forwardData_mshr = Vec(VLEN/8, UInt(8.W)) 316 317 val forward_result_valid = Bool() 318 319 def mergeTLData(): UInt = { 320 // merge TL D or MSHR data at load s2 321 val dcache_data = respDcacheData 322 val use_D = forward_D && forward_result_valid 323 val use_mshr = forward_mshr && forward_result_valid 324 Mux( 325 use_D || use_mshr, 326 Mux( 327 use_D, 328 forwardData_D.asUInt, 329 forwardData_mshr.asUInt 330 ), 331 dcache_data 332 ) 333 } 334 335 def mergeLsqFwdData(dcacheData: UInt): UInt = { 336 // merge dcache and lsq forward data at load s3 337 val rdataVec = VecInit((0 until VLEN / 8).map(j => 338 Mux(forwardMask(j), forwardData(j), dcacheData(8*(j+1)-1, 8*j)) 339 )) 340 rdataVec.asUInt 341 } 342 } 343 344 // Load writeback data from load queue (refill) 345 class LoadDataFromLQBundle(implicit p: Parameters) extends XSBundle { 346 val lqData = UInt(64.W) // load queue has merged data 347 val uop = new DynInst // for data selection, only fwen and fuOpType are used 348 val addrOffset = UInt(3.W) // for data selection 349 350 def mergedData(): UInt = { 351 lqData 352 } 353 } 354 355 // Bundle for load / store wait waking up 356 class MemWaitUpdateReqBundle(implicit p: Parameters) extends XSBundle { 357 val robIdx = Vec(backendParams.StaExuCnt, ValidIO(new RobPtr)) 358 val sqIdx = Vec(backendParams.StdCnt, ValidIO(new SqPtr)) 359 } 360 361} 362