xref: /XiangShan/src/main/scala/xiangshan/mem/Bundles.scala (revision 800ac0f1d01fac5d118955113cd5a0cc7844aff4)
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