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.nc_with_data := DontCare 165 this.data_wen_dup := DontCare 166 } 167 } 168 169 class SqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { 170 val need_rep = Bool() 171 } 172 173 class LoadForwardQueryIO(implicit p: Parameters) extends XSBundle { 174 val vaddr = Output(UInt(VAddrBits.W)) 175 val paddr = Output(UInt(PAddrBits.W)) 176 val mask = Output(UInt((VLEN/8).W)) 177 val uop = Output(new DynInst) // for replay 178 val pc = Output(UInt(VAddrBits.W)) //for debug 179 val valid = Output(Bool()) 180 181 val forwardMaskFast = Input(Vec((VLEN/8), Bool())) // resp to load_s1 182 val forwardMask = Input(Vec((VLEN/8), Bool())) // resp to load_s2 183 val forwardData = Input(Vec((VLEN/8), UInt(8.W))) // resp to load_s2 184 185 // val lqIdx = Output(UInt(LoadQueueIdxWidth.W)) 186 val sqIdx = Output(new SqPtr) 187 188 // dataInvalid suggests store to load forward found forward should happen, 189 // but data is not available for now. If dataInvalid, load inst should 190 // be replayed from RS. Feedback type should be RSFeedbackType.dataInvalid 191 val dataInvalid = Input(Bool()) // Addr match, but data is not valid for now 192 193 // matchInvalid suggests in store to load forward logic, paddr cam result does 194 // to equal to vaddr cam result. If matchInvalid, a microarchitectural exception 195 // should be raised to flush SQ and committed sbuffer. 196 val matchInvalid = Input(Bool()) // resp to load_s2 197 198 // addrInvalid suggests store to load forward found forward should happen, 199 // but address (SSID) is not available for now. If addrInvalid, load inst should 200 // be replayed from RS. Feedback type should be RSFeedbackType.addrInvalid 201 val addrInvalid = Input(Bool()) 202 } 203 204 // LoadForwardQueryIO used in load pipeline 205 // 206 // Difference between PipeLoadForwardQueryIO and LoadForwardQueryIO: 207 // PipeIO use predecoded sqIdxMask for better forward timing 208 class PipeLoadForwardQueryIO(implicit p: Parameters) extends LoadForwardQueryIO { 209 // val sqIdx = Output(new SqPtr) // for debug, should not be used in pipeline for timing reasons 210 // sqIdxMask is calcuated in earlier stage for better timing 211 val sqIdxMask = Output(UInt(StoreQueueSize.W)) 212 213 // dataInvalid: addr match, but data is not valid for now 214 val dataInvalidFast = Input(Bool()) // resp to load_s1 215 // val dataInvalid = Input(Bool()) // resp to load_s2 216 val dataInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 217 val addrInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 218 } 219 220 // Query load queue for ld-ld violation 221 // 222 // Req should be send in load_s1 223 // Resp will be generated 1 cycle later 224 // 225 // Note that query req may be !ready, as dcache is releasing a block 226 // If it happens, a replay from rs is needed. 227 class LoadNukeQueryReqBundle(implicit p: Parameters) extends XSBundle { // provide lqIdx 228 val uop = new DynInst 229 // mask: load's data mask. 230 val mask = UInt((VLEN/8).W) 231 232 // paddr: load's paddr. 233 val paddr = UInt(PAddrBits.W) 234 // dataInvalid: load data is invalid. 235 val data_valid = Bool() 236 // nc: is NC access 237 val is_nc = Bool() 238 } 239 240 class LoadNukeQueryRespBundle(implicit p: Parameters) extends XSBundle { 241 // rep_frm_fetch: ld-ld violation check success, replay from fetch. 242 val rep_frm_fetch = Bool() 243 } 244 245 class LoadNukeQueryIO(implicit p: Parameters) extends XSBundle { 246 val req = Decoupled(new LoadNukeQueryReqBundle) 247 val resp = Flipped(Valid(new LoadNukeQueryRespBundle)) 248 val revoke = Output(Bool()) 249 } 250 251 class StoreNukeQueryBundle(implicit p: Parameters) extends XSBundle { 252 // robIdx: Requestor's (a store instruction) rob index for match logic. 253 val robIdx = new RobPtr 254 255 // paddr: requestor's (a store instruction) physical address for match logic. 256 val paddr = UInt(PAddrBits.W) 257 258 // mask: requestor's (a store instruction) data width mask for match logic. 259 val mask = UInt((VLEN/8).W) 260 261 // matchLine: if store is vector 128-bits, load unit need to compare 128-bits vaddr. 262 val matchLine = Bool() 263 } 264 265 class StoreMaBufToSqControlIO(implicit p: Parameters) extends XSBundle { 266 // from storeMisalignBuffer to storeQueue, control it's sbuffer write 267 val toStoreQueue = Output(new XSBundle { 268 // This entry is a cross page 269 val crossPageWithHit = Bool() 270 val crossPageCanDeq = Bool() 271 // High page Paddr 272 val paddr = UInt(PAddrBits.W) 273 274 val withSameUop = Bool() 275 }) 276 // from storeQueue to storeMisalignBuffer, provide detail info of this store 277 val toStoreMisalignBuffer = Input(new XSBundle { 278 val sqPtr = new SqPtr 279 val doDeq = Bool() 280 281 val uop = new DynInst() 282 }) 283 } 284 285 class StoreMaBufToVecStoreMergeBufferIO(implicit p: Parameters) extends VLSUBundle{ 286 val mbIndex = Output(UInt(vsmBindexBits.W)) 287 val flush = Output(Bool()) 288 } 289 290 // Store byte valid mask write bundle 291 // 292 // Store byte valid mask write to SQ takes 2 cycles 293 class StoreMaskBundle(implicit p: Parameters) extends XSBundle { 294 val sqIdx = new SqPtr 295 val mask = UInt((VLEN/8).W) 296 } 297 298 class LoadDataFromDcacheBundle(implicit p: Parameters) extends DCacheBundle { 299 // old dcache: optimize data sram read fanout 300 // val bankedDcacheData = Vec(DCacheBanks, UInt(64.W)) 301 // val bank_oh = UInt(DCacheBanks.W) 302 303 // new dcache 304 val respDcacheData = UInt(VLEN.W) 305 val forwardMask = Vec(VLEN/8, Bool()) 306 val forwardData = Vec(VLEN/8, UInt(8.W)) 307 val uop = new DynInst // for data selection, only fwen and fuOpType are used 308 val addrOffset = UInt(4.W) // for data selection 309 310 // forward tilelink D channel 311 val forward_D = Bool() 312 val forwardData_D = Vec(VLEN/8, UInt(8.W)) 313 314 // forward mshr data 315 val forward_mshr = Bool() 316 val forwardData_mshr = Vec(VLEN/8, UInt(8.W)) 317 318 val forward_result_valid = Bool() 319 320 def mergeTLData(): UInt = { 321 // merge TL D or MSHR data at load s2 322 val dcache_data = respDcacheData 323 val use_D = forward_D && forward_result_valid 324 val use_mshr = forward_mshr && forward_result_valid 325 Mux( 326 use_D || use_mshr, 327 Mux( 328 use_D, 329 forwardData_D.asUInt, 330 forwardData_mshr.asUInt 331 ), 332 dcache_data 333 ) 334 } 335 336 def mergeLsqFwdData(dcacheData: UInt): UInt = { 337 // merge dcache and lsq forward data at load s3 338 val rdataVec = VecInit((0 until VLEN / 8).map(j => 339 Mux(forwardMask(j), forwardData(j), dcacheData(8*(j+1)-1, 8*j)) 340 )) 341 rdataVec.asUInt 342 } 343 } 344 345 // Load writeback data from load queue (refill) 346 class LoadDataFromLQBundle(implicit p: Parameters) extends XSBundle { 347 val lqData = UInt(64.W) // load queue has merged data 348 val uop = new DynInst // for data selection, only fwen and fuOpType are used 349 val addrOffset = UInt(3.W) // for data selection 350 351 def mergedData(): UInt = { 352 lqData 353 } 354 } 355 356 // Bundle for load / store wait waking up 357 class MemWaitUpdateReqBundle(implicit p: Parameters) extends XSBundle { 358 val robIdx = Vec(backendParams.StaExuCnt, ValidIO(new RobPtr)) 359 val sqIdx = Vec(backendParams.StdCnt, ValidIO(new SqPtr)) 360 } 361 362 class MisalignBufferEnqIO(implicit p: Parameters) extends XSBundle { 363 val req = DecoupledIO(new LqWriteBundle) 364 val revoke = Output(Bool()) 365 } 366 367} 368