xref: /XiangShan/src/main/scala/xiangshan/mem/vector/VMergeBuffer.scala (revision d0d2c22d6f8c96ee7c45325f375b17a0243a8259)
1/***************************************************************************************
2  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3  * Copyright (c) 2020-2021 Peng Cheng Laboratory
4  *
5  * XiangShan is licensed under Mulan PSL v2.
6  * You can use this software according to the terms and conditions of the Mulan PSL v2.
7  * You may obtain a copy of Mulan PSL v2 at:
8  *          http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  *
14  * See the Mulan PSL v2 for more details.
15  ***************************************************************************************/
16
17package xiangshan.mem
18
19import org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import utils._
23import utility._
24import xiangshan._
25import xiangshan.backend.rob.RobPtr
26import xiangshan.backend.Bundles._
27import xiangshan.ExceptionNO._
28import xiangshan.mem._
29import xiangshan.backend.fu.FuType
30import xiangshan.backend.fu.FuConfig._
31import xiangshan.backend.datapath.NewPipelineConnect
32import freechips.rocketchip.diplomacy.BufferParams
33
34class MBufferBundle(implicit p: Parameters) extends VLSUBundle{
35  val data             = UInt(VLEN.W)
36  val mask             = UInt(VLENB.W)
37  val flowNum          = UInt(flowIdxBits.W)
38  val exceptionVec     = ExceptionVec()
39  val uop              = new DynInst
40  // val vdOffset         = UInt(vOffsetBits.W)
41  val sourceType       = VSFQFeedbackType()
42  val flushState       = Bool()
43  val vdIdx            = UInt(3.W)
44  val elemIdx          = UInt(elemIdxBits.W) // element index
45  // for exception
46  val vstart           = UInt(elemIdxBits.W)
47  val vl               = UInt(elemIdxBits.W)
48  val vaNeedExt        = Bool()
49  val vaddr            = UInt(XLEN.W)
50  val gpaddr           = UInt(GPAddrBits.W)
51  val isForVSnonLeafPTE= Bool()
52  val fof              = Bool()
53  val vlmax            = UInt(elemIdxBits.W)
54
55  def allReady(): Bool = (flowNum === 0.U)
56}
57
58abstract class BaseVMergeBuffer(isVStore: Boolean=false)(implicit p: Parameters) extends VLSUModule{
59  val io = IO(new VMergeBufferIO(isVStore))
60
61  // freeliset: store valid entries index.
62  // +---+---+--------------+-----+-----+
63  // | 0 | 1 |      ......  | n-2 | n-1 |
64  // +---+---+--------------+-----+-----+
65  val freeList: FreeList
66  val uopSize: Int
67  val enqWidth = io.fromSplit.length
68  val deqWidth = io.uopWriteback.length
69  val pipeWidth = io.fromPipeline.length
70  lazy val fuCfg = if (isVStore) VstuCfg else VlduCfg
71
72  def EnqConnect(source: MergeBufferReq, sink: MBufferBundle) = {
73    sink.data         := source.data
74    sink.mask         := source.mask
75    sink.flowNum      := source.flowNum
76    sink.exceptionVec := ExceptionNO.selectByFu(0.U.asTypeOf(ExceptionVec()), fuCfg)
77    sink.uop          := source.uop
78    sink.sourceType   := 0.U.asTypeOf(VSFQFeedbackType())
79    sink.flushState   := false.B
80    sink.vdIdx        := source.vdIdx
81    sink.elemIdx      := Fill(elemIdxBits, 1.U)
82    sink.fof          := source.fof
83    sink.vlmax        := source.vlmax
84    sink.vl           := source.uop.vpu.vl
85    sink.vaddr        := source.vaddr
86    sink.vstart       := 0.U
87  }
88  def DeqConnect(source: MBufferBundle): MemExuOutput = {
89    val sink               = WireInit(0.U.asTypeOf(new MemExuOutput(isVector = true)))
90    sink.data             := source.data
91    sink.mask.get         := source.mask
92    sink.uop              := source.uop
93    sink.uop.exceptionVec := ExceptionNO.selectByFu(source.exceptionVec, fuCfg)
94    sink.uop.vpu.vmask    := source.mask
95    sink.debug            := 0.U.asTypeOf(new DebugBundle)
96    sink.vdIdxInField.get := source.vdIdx // Mgu needs to use this.
97    sink.vdIdx.get        := source.vdIdx
98    sink.uop.vpu.vstart   := source.vstart
99    sink.uop.vpu.vl       := source.vl
100    sink
101  }
102  def ToLsqConnect(source: MBufferBundle): FeedbackToLsqIO = {
103    val sink                                 = WireInit(0.U.asTypeOf(new FeedbackToLsqIO))
104    val hasExp                               = ExceptionNO.selectByFu(source.exceptionVec, fuCfg).asUInt.orR
105    sink.robidx                             := source.uop.robIdx
106    sink.uopidx                             := source.uop.uopIdx
107    sink.feedback(VecFeedbacks.COMMIT)      := !hasExp
108    sink.feedback(VecFeedbacks.FLUSH)       := hasExp
109    sink.feedback(VecFeedbacks.LAST)        := true.B
110    sink.vstart                             := source.vstart // TODO: if lsq need vl for fof?
111    sink.vaddr                              := source.vaddr
112    sink.vaNeedExt                          := source.vaNeedExt
113    sink.gpaddr                             := source.gpaddr
114    sink.isForVSnonLeafPTE                  := source.isForVSnonLeafPTE
115    sink.vl                                 := source.vl
116    sink.exceptionVec                       := ExceptionNO.selectByFu(source.exceptionVec, fuCfg)
117    sink
118  }
119
120
121  val entries      = Reg(Vec(uopSize, new MBufferBundle))
122  val needCancel   = WireInit(VecInit(Seq.fill(uopSize)(false.B)))
123  val allocated    = RegInit(VecInit(Seq.fill(uopSize)(false.B)))
124  val freeMaskVec  = WireInit(VecInit(Seq.fill(uopSize)(false.B)))
125  val uopFinish    = RegInit(VecInit(Seq.fill(uopSize)(false.B)))
126  val needRSReplay = RegInit(VecInit(Seq.fill(uopSize)(false.B)))
127  // enq, from splitPipeline
128  // val allowEnqueue =
129  val cancelEnq    = io.fromSplit.map(_.req.bits.uop.robIdx.needFlush(io.redirect))
130  val canEnqueue   = io.fromSplit.map(_.req.valid)
131  val needEnqueue  = (0 until enqWidth).map{i =>
132    canEnqueue(i) && !cancelEnq(i)
133  }
134
135  val freeCount    = uopSize.U - freeList.io.validCount
136
137  for ((enq, i) <- io.fromSplit.zipWithIndex){
138    freeList.io.doAllocate(i) := false.B
139
140    freeList.io.allocateReq(i) := true.B
141
142    val offset    = PopCount(needEnqueue.take(i))
143    val canAccept = freeList.io.canAllocate(offset)
144    val enqIndex  = freeList.io.allocateSlot(offset)
145    enq.req.ready := freeCount >= (i + 1).U // for better timing
146
147    when(needEnqueue(i) && enq.req.ready){
148      freeList.io.doAllocate(i) := true.B
149      // enqueue
150      allocated(enqIndex)       := true.B
151      uopFinish(enqIndex)       := false.B
152      needRSReplay(enqIndex)    := false.B
153
154      EnqConnect(enq.req.bits, entries(enqIndex))// initial entry
155    }
156
157    enq.resp.bits.mBIndex := enqIndex
158    enq.resp.bits.fail    := false.B
159    enq.resp.valid        := freeCount >= (i + 1).U // for better timing
160  }
161
162  //redirect
163  for (i <- 0 until uopSize){
164    needCancel(i) := entries(i).uop.robIdx.needFlush(io.redirect) && allocated(i)
165    when (needCancel(i)) {
166      allocated(i)   := false.B
167      freeMaskVec(i) := true.B
168      uopFinish(i)   := false.B
169      needRSReplay(i):= false.B
170    }
171  }
172  freeList.io.free := freeMaskVec.asUInt
173  //pipelineWriteback
174  // handle the situation where multiple ports are going to write the same uop queue entry
175  val mergePortMatrix        = Wire(Vec(pipeWidth, Vec(pipeWidth, Bool())))
176  val mergedByPrevPortVec    = Wire(Vec(pipeWidth, Bool()))
177  (0 until pipeWidth).map{case i => (0 until pipeWidth).map{case j =>
178    mergePortMatrix(i)(j) := (j == i).B ||
179      (j > i).B &&
180      io.fromPipeline(j).bits.mBIndex === io.fromPipeline(i).bits.mBIndex &&
181      io.fromPipeline(j).valid
182  }}
183  (0 until pipeWidth).map{case i =>
184    mergedByPrevPortVec(i) := (i != 0).B && Cat((0 until i).map(j =>
185      io.fromPipeline(j).bits.mBIndex === io.fromPipeline(i).bits.mBIndex &&
186      io.fromPipeline(j).valid)).orR
187  }
188  dontTouch(mergePortMatrix)
189  dontTouch(mergedByPrevPortVec)
190
191  // for exception, select exception, when multi port writeback exception, we need select oldest one
192  def selectOldest[T <: VecPipelineFeedbackIO](valid: Seq[Bool], bits: Seq[T], sel: Seq[UInt]): (Seq[Bool], Seq[T], Seq[UInt]) = {
193    assert(valid.length == bits.length)
194    assert(valid.length == sel.length)
195    if (valid.length == 0 || valid.length == 1) {
196      (valid, bits, sel)
197    } else if (valid.length == 2) {
198      val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0)))))
199      for (i <- res.indices) {
200        res(i).valid := valid(i)
201        res(i).bits := bits(i)
202      }
203      val oldest = Mux(valid(0) && valid(1),
204        Mux(sel(0) < sel(1),
205            res(0), res(1)),
206        Mux(valid(0) && !valid(1), res(0), res(1)))
207      (Seq(oldest.valid), Seq(oldest.bits), Seq(0.U))
208    } else {
209      val left  = selectOldest(valid.take(valid.length / 2), bits.take(bits.length / 2), sel.take(sel.length / 2))
210      val right = selectOldest(valid.takeRight(valid.length - (valid.length / 2)), bits.takeRight(bits.length - (bits.length / 2)), sel.takeRight(sel.length - (sel.length / 2)))
211      selectOldest(left._1 ++ right._1, left._2 ++ right._2, left._3 ++ right._3)
212    }
213  }
214
215  val pipeValid        = io.fromPipeline.map(_.valid)
216  val pipeBits         = io.fromPipeline.map(_.bits)
217  val wbElemIdx        = pipeBits.map(_.elemIdx)
218  val wbMbIndex        = pipeBits.map(_.mBIndex)
219  val wbElemIdxInField = wbElemIdx.zip(wbMbIndex).map(x => x._1 & (entries(x._2).vlmax - 1.U))
220
221  val portHasExcp       = pipeBits.zip(mergePortMatrix).map{case (port, v) =>
222    (0 until pipeWidth).map{case i =>
223      val pipeHasExcep = ExceptionNO.selectByFu(port.exceptionVec, fuCfg).asUInt.orR
224      (v(i) && ((pipeHasExcep && io.fromPipeline(i).bits.mask.orR) || TriggerAction.isDmode(port.trigger))) // this port have exception or merged port have exception
225    }.reduce(_ || _)
226  }
227
228  for((pipewb, i) <- io.fromPipeline.zipWithIndex){
229    val entry               = entries(wbMbIndex(i))
230    val entryVeew           = entry.uop.vpu.veew
231    val entryIsUS           = LSUOpType.isAllUS(entry.uop.fuOpType)
232    val entryHasException   = ExceptionNO.selectByFu(entry.exceptionVec, fuCfg).asUInt.orR
233    val entryExcp           = entryHasException && entry.mask.orR
234    val entryVaddr          = entry.vaddr
235    val entryVstart         = entry.vstart
236    val entryElemIdx        = entry.elemIdx
237
238    val sel                    = selectOldest(mergePortMatrix(i), pipeBits, wbElemIdxInField)
239    val selPort                = sel._2
240    val selElemInfield         = selPort(0).elemIdx & (entries(wbMbIndex(i)).vlmax - 1.U)
241    val selExceptionVec        = selPort(0).exceptionVec
242    val selVaddr               = selPort(0).vaddr
243    val selElemIdx             = selPort(0).elemIdx
244
245    val isUSFirstUop           = !selPort(0).elemIdx.orR
246    // Only the first unaligned uop of unit-stride needs to be offset.
247    // When unaligned, the lowest bit of mask is 0.
248    //  example: 16'b1111_1111_1111_0000
249    val firstUnmask            = genVFirstUnmask(selPort(0).mask).asUInt
250    val vaddrOffset            = Mux(entryIsUS, firstUnmask, 0.U)
251    val vaddr                  = selVaddr + vaddrOffset
252    val vstart                 = Mux(entryIsUS, (selPort(0).vecVaddrOffset >> entryVeew).asUInt, selElemInfield)
253
254    // select oldest port to raise exception
255    when((((entryElemIdx >= selElemIdx) && entryExcp && portHasExcp(i)) || (!entryExcp && portHasExcp(i))) && pipewb.valid && !mergedByPrevPortVec(i)) {
256      entry.uop.trigger     := selPort(0).trigger
257      entry.elemIdx         := selElemIdx
258      when(!entry.fof || vstart === 0.U){
259        // For fof loads, if element 0 raises an exception, vl is not modified, and the trap is taken.
260        entry.vstart       := vstart
261        entry.exceptionVec := ExceptionNO.selectByFu(selExceptionVec, fuCfg)
262        entry.vaddr        := vaddr
263        entry.vaNeedExt    := selPort(0).vaNeedExt
264        entry.gpaddr       := selPort(0).gpaddr
265        entry.isForVSnonLeafPTE := selPort(0).isForVSnonLeafPTE
266      }.otherwise{
267        entry.vl           := Mux(entries(wbMbIndex(i)).vl > vstart, vstart, entries(wbMbIndex(i)).vl)
268      }
269    }
270  }
271
272  // for pipeline writeback
273  for((pipewb, i) <- io.fromPipeline.zipWithIndex){
274    val wbIndex          = pipewb.bits.mBIndex
275    val flowNumOffset    = Mux(pipewb.bits.usSecondInv,
276                               2.U,
277                               PopCount(mergePortMatrix(i)))
278    val sourceTypeNext   = entries(wbIndex).sourceType | pipewb.bits.sourceType
279    val hasExp           = ExceptionNO.selectByFu(pipewb.bits.exceptionVec, fuCfg).asUInt.orR
280
281    // if is VLoad, need latch 1 cycle to merge data. only flowNum and wbIndex need to latch
282    val latchWbValid     = if(isVStore) pipewb.valid else RegNext(pipewb.valid)
283    val latchWbIndex     = if(isVStore) wbIndex      else RegEnable(wbIndex, pipewb.valid)
284    val latchFlowNum     = if(isVStore) flowNumOffset else RegEnable(flowNumOffset, pipewb.valid)
285    val latchMergeByPre  = if(isVStore) mergedByPrevPortVec(i) else RegEnable(mergedByPrevPortVec(i), pipewb.valid)
286    when(latchWbValid && !latchMergeByPre){
287      entries(latchWbIndex).flowNum := entries(latchWbIndex).flowNum - latchFlowNum
288    }
289
290    when(pipewb.valid){
291      entries(wbIndex).sourceType   := sourceTypeNext
292      entries(wbIndex).flushState   := pipewb.bits.flushState
293    }
294    when(pipewb.valid && !pipewb.bits.hit){
295      needRSReplay(wbIndex) := true.B
296    }
297    pipewb.ready := true.B
298    XSError((entries(latchWbIndex).flowNum - latchFlowNum > entries(latchWbIndex).flowNum) && latchWbValid && !latchMergeByPre, "FlowWriteback overflow!!\n")
299    XSError(!allocated(latchWbIndex) && latchWbValid, "Writeback error flow!!\n")
300  }
301  // for inorder mem asscess
302  io.toSplit := DontCare
303
304  //uopwriteback(deq)
305  for (i <- 0 until uopSize){
306    when(allocated(i) && entries(i).allReady()){
307      uopFinish(i) := true.B
308    }
309  }
310   val selPolicy = SelectOne("circ", uopFinish, deqWidth) // select one entry to deq
311   private val pipelineOut              = Wire(Vec(deqWidth, DecoupledIO(new MemExuOutput(isVector = true))))
312   private val writeBackOut             = Wire(Vec(deqWidth, DecoupledIO(new MemExuOutput(isVector = true))))
313   private val writeBackOutExceptionVec = writeBackOut.map(_.bits.uop.exceptionVec)
314   for(((port, lsqport), i) <- (pipelineOut zip io.toLsq).zipWithIndex){
315    val canGo    = port.ready
316    val (selValid, selOHVec) = selPolicy.getNthOH(i + 1)
317    val entryIdx = OHToUInt(selOHVec)
318    val selEntry = entries(entryIdx)
319    val selAllocated = allocated(entryIdx)
320    val selFire  = selValid && canGo
321    when(selFire){
322      freeMaskVec(entryIdx) := selAllocated
323      allocated(entryIdx)   := false.B
324      uopFinish(entryIdx)   := false.B
325      needRSReplay(entryIdx):= false.B
326    }
327    //writeback connect
328    port.valid   := selFire && selAllocated && !needRSReplay(entryIdx) && !selEntry.uop.robIdx.needFlush(io.redirect)
329    port.bits    := DeqConnect(selEntry)
330    //to lsq
331    lsqport.bits := ToLsqConnect(selEntry) // when uopwriteback, free MBuffer entry, write to lsq
332    lsqport.valid:= selFire && selAllocated && !needRSReplay(entryIdx)
333    //to RS
334    val feedbackOut                       = WireInit(0.U.asTypeOf(io.feedback(i).bits)).suggestName(s"feedbackOut_${i}")
335    val feedbackValid                     = selFire && selAllocated
336    feedbackOut.hit                      := !needRSReplay(entryIdx)
337    feedbackOut.robIdx                   := selEntry.uop.robIdx
338    feedbackOut.sourceType               := selEntry.sourceType
339    feedbackOut.flushState               := selEntry.flushState
340    feedbackOut.dataInvalidSqIdx         := DontCare
341    feedbackOut.sqIdx                    := selEntry.uop.sqIdx
342    feedbackOut.lqIdx                    := selEntry.uop.lqIdx
343
344    io.feedback(i).valid                 := RegNext(feedbackValid)
345    io.feedback(i).bits                  := RegEnable(feedbackOut, feedbackValid)
346
347    NewPipelineConnect(
348      port, writeBackOut(i), writeBackOut(i).fire,
349      Mux(port.fire,
350        selEntry.uop.robIdx.needFlush(io.redirect),
351        writeBackOut(i).bits.uop.robIdx.needFlush(io.redirect)),
352      Option(s"VMergebufferPipelineConnect${i}")
353    )
354     io.uopWriteback(i)                  <> writeBackOut(i)
355     io.uopWriteback(i).bits.uop.exceptionVec := ExceptionNO.selectByFu(writeBackOutExceptionVec(i), fuCfg)
356   }
357
358  QueuePerf(uopSize, freeList.io.validCount, freeList.io.validCount === 0.U)
359}
360
361class VLMergeBufferImp(implicit p: Parameters) extends BaseVMergeBuffer(isVStore=false){
362  override lazy val uopSize = VlMergeBufferSize
363  println(s"VLMergeBuffer Size: ${VlMergeBufferSize}")
364  override lazy val freeList = Module(new FreeList(
365    size = uopSize,
366    allocWidth = VecLoadPipelineWidth,
367    freeWidth = deqWidth,
368    enablePreAlloc = false,
369    moduleName = "VLoad MergeBuffer freelist"
370  ))
371
372  //merge data
373  val flowWbElemIdx     = Wire(Vec(pipeWidth, UInt(elemIdxBits.W)))
374  val flowWbElemIdxInVd = Wire(Vec(pipeWidth, UInt(elemIdxBits.W)))
375  val pipewbValidReg    = Wire(Vec(pipeWidth, Bool()))
376  val wbIndexReg        = Wire(Vec(pipeWidth, UInt(vlmBindexBits.W)))
377  val mergeDataReg      = Wire(Vec(pipeWidth, UInt(VLEN.W)))
378
379  val maskWithexceptionMask = io.fromPipeline.map{ x=>
380    Mux(
381      TriggerAction.isExp(x.bits.trigger) || TriggerAction.isDmode(x.bits.trigger),
382      ~x.bits.vecTriggerMask,
383      Fill(x.bits.mask.getWidth, !ExceptionNO.selectByFuAndUnSelect(x.bits.exceptionVec, fuCfg, Seq(breakPoint)).asUInt.orR)
384    ).asUInt & x.bits.mask
385  }
386
387  for((pipewb, i) <- io.fromPipeline.zipWithIndex){
388    /** step0 **/
389    val wbIndex = pipewb.bits.mBIndex
390    val alignedType = pipewb.bits.alignedType
391    val elemIdxInsideVd = pipewb.bits.elemIdxInsideVd
392    flowWbElemIdx(i) := pipewb.bits.elemIdx
393    flowWbElemIdxInVd(i) := elemIdxInsideVd.get
394
395    val oldData = PriorityMux(Seq(
396      (pipewbValidReg(0) && (wbIndexReg(0) === wbIndex)) -> mergeDataReg(0),
397      (pipewbValidReg(1) && (wbIndexReg(1) === wbIndex)) -> mergeDataReg(1),
398      (pipewbValidReg(2) && (wbIndexReg(2) === wbIndex)) -> mergeDataReg(2),
399      true.B                                             -> entries(wbIndex).data // default use entries_data
400    ))
401    val mergedData = mergeDataWithElemIdx(
402      oldData = oldData,
403      newData = io.fromPipeline.map(_.bits.vecdata.get),
404      alignedType = alignedType(1,0),
405      elemIdx = flowWbElemIdxInVd,
406      valids = mergePortMatrix(i)
407    )
408    /* this only for unit-stride load data merge
409     * cycle0: broden 128-bits to 256-bits (max 6 to 1)
410     * cycle1: select 128-bits data from 256-bits (16 to 1)
411     */
412    val (brodenMergeData, brodenMergeMask)     = mergeDataByIndex(
413      data    = io.fromPipeline.map(_.bits.vecdata.get).drop(i),
414      mask    = maskWithexceptionMask.drop(i),
415      index   = io.fromPipeline(i).bits.elemIdxInsideVd.get,
416      valids  = mergePortMatrix(i).drop(i)
417    )
418    /** step1 **/
419    pipewbValidReg(i)      := RegNext(pipewb.valid)
420    wbIndexReg(i)          := RegEnable(wbIndex, pipewb.valid)
421    mergeDataReg(i)        := RegEnable(mergedData, pipewb.valid) // for not Unit-stride
422    val brodenMergeDataReg  = RegEnable(brodenMergeData, pipewb.valid) // only for Unit-stride
423    val brodenMergeMaskReg  = RegEnable(brodenMergeMask, pipewb.valid)
424    val mergedByPrevPortReg = RegEnable(mergedByPrevPortVec(i), pipewb.valid)
425    val regOffsetReg        = RegEnable(pipewb.bits.reg_offset.get, pipewb.valid) // only for Unit-stride
426    val isusMerge           = RegEnable(alignedType(2), pipewb.valid)
427
428    val usSelData           = Mux1H(UIntToOH(regOffsetReg), (0 until VLENB).map{case i => getNoAlignedSlice(brodenMergeDataReg, i, 128)})
429    val usSelMask           = Mux1H(UIntToOH(regOffsetReg), (0 until VLENB).map{case i => brodenMergeMaskReg(16 + i - 1, i)})
430    val usMergeData         = mergeDataByByte(entries(wbIndexReg(i)).data, usSelData, usSelMask)
431    when(pipewbValidReg(i) && !mergedByPrevPortReg){
432      entries(wbIndexReg(i)).data := Mux(isusMerge, usMergeData, mergeDataReg(i)) // if aligned(2) == 1, is Unit-Stride inst
433    }
434  }
435}
436
437class VSMergeBufferImp(implicit p: Parameters) extends BaseVMergeBuffer(isVStore=true){
438  override lazy val uopSize = VsMergeBufferSize
439  println(s"VSMergeBuffer Size: ${VsMergeBufferSize}")
440  override lazy val freeList = Module(new FreeList(
441    size = uopSize,
442    allocWidth = VecStorePipelineWidth,
443    freeWidth = deqWidth,
444    enablePreAlloc = false,
445    moduleName = "VStore MergeBuffer freelist"
446  ))
447  override def DeqConnect(source: MBufferBundle): MemExuOutput = {
448    val sink               = Wire(new MemExuOutput(isVector = true))
449    sink.data             := DontCare
450    sink.mask.get         := DontCare
451    sink.uop              := source.uop
452    sink.uop.exceptionVec := source.exceptionVec
453    sink.debug            := 0.U.asTypeOf(new DebugBundle)
454    sink.vdIdxInField.get := DontCare
455    sink.vdIdx.get        := DontCare
456    sink.uop.vpu.vstart   := source.vstart
457    sink
458  }
459}
460