xref: /XiangShan/src/main/scala/xiangshan/mem/vector/VSplit.scala (revision 102b377b2a1e5d6078e230671ceb431c083e3861)
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.mem._
28import xiangshan.backend.fu.vector.Bundles._
29import xiangshan.backend.fu.FuConfig._
30
31
32class VSplitPipeline(isVStore: Boolean = false)(implicit p: Parameters) extends VLSUModule{
33  val io = IO(new VSplitPipelineIO(isVStore))
34  // will be override later
35  def us_whole_reg(fuOpType: UInt): Bool = false.B
36  def us_mask(fuOpType: UInt): Bool = false.B
37  def us_fof(fuOpType: UInt): Bool = false.B
38  //TODO vdIdxReg should no longer be useful, don't delete it for now
39  val vdIdxReg = RegInit(0.U(3.W))
40
41  val s1_ready = WireInit(false.B)
42  io.in.ready := s1_ready
43
44  /**-----------------------------------------------------------
45    * s0 stage
46    * decode and generate AlignedType, uop mask, preIsSplit
47    * ----------------------------------------------------------
48    */
49  val s0_uop = io.in.bits.uop
50  val s0_vtype = s0_uop.vpu.vtype
51  val s0_sew = s0_vtype.vsew
52  val s0_eew = s0_uop.vpu.veew
53  val s0_lmul = s0_vtype.vlmul
54  // when load whole register or unit-stride masked , emul should be 1
55  val s0_fuOpType = s0_uop.fuOpType
56  val s0_mop = s0_fuOpType(6, 5)
57  val s0_nf = Mux(us_whole_reg(s0_fuOpType), 0.U, s0_uop.vpu.nf)
58  val s0_vm = s0_uop.vpu.vm
59  val s0_emul = Mux(us_whole_reg(s0_fuOpType) ,GenUSWholeEmul(s0_uop.vpu.nf), Mux(us_mask(s0_fuOpType), 0.U(mulBits.W), EewLog2(s0_eew) - s0_sew + s0_lmul))
60  val s0_preIsSplit = !(isUnitStride(s0_mop) && !us_fof(s0_fuOpType))
61  val s0_nfield        = s0_nf +& 1.U
62
63  val s0_valid         = Wire(Bool())
64  val s0_kill          = io.in.bits.uop.robIdx.needFlush(io.redirect)
65  val s0_can_go        = s1_ready
66  val s0_fire          = s0_valid && s0_can_go
67  val s0_out           = Wire(new VLSBundle(isVStore))
68
69  val isUsWholeReg = isUnitStride(s0_mop) && us_whole_reg(s0_fuOpType)
70  val isMaskReg = isUnitStride(s0_mop) && us_mask(s0_fuOpType)
71  val isSegment = s0_nf =/= 0.U && !us_whole_reg(s0_fuOpType)
72  val instType = Cat(isSegment, s0_mop)
73  val uopIdx = io.in.bits.uop.vpu.vuopIdx
74  val uopIdxInField = GenUopIdxInField(instType, s0_emul, s0_lmul, uopIdx)
75  val vdIdxInField = GenVdIdxInField(instType, s0_emul, s0_lmul, uopIdxInField)
76  val lmulLog2 = Mux(s0_lmul.asSInt >= 0.S, 0.U, s0_lmul)
77  val emulLog2 = Mux(s0_emul.asSInt >= 0.S, 0.U, s0_emul)
78  val numEewLog2 = emulLog2 - EewLog2(s0_eew)
79  val numSewLog2 = lmulLog2 - s0_sew
80  val numFlowsSameVdLog2 = Mux(
81    isIndexed(instType),
82    log2Up(VLENB).U - s0_sew(1,0),
83    log2Up(VLENB).U - s0_eew(1,0)
84  )
85  // numUops = nf * max(lmul, emul)
86  val lmulLog2Pos = Mux(s0_lmul.asSInt < 0.S, 0.U, s0_lmul)
87  val emulLog2Pos = Mux(s0_emul.asSInt < 0.S, 0.U, s0_emul)
88  val numUops = Mux(
89    isIndexed(s0_mop) && s0_lmul.asSInt > s0_emul.asSInt,
90    (s0_nf +& 1.U) << lmulLog2Pos,
91    (s0_nf +& 1.U) << emulLog2Pos
92  )
93
94  val vvl = io.in.bits.src_vl.asTypeOf(VConfig()).vl
95  val evl = Mux(isUsWholeReg,
96                GenUSWholeRegVL(io.in.bits.uop.vpu.nf +& 1.U, s0_eew),
97                Mux(isMaskReg,
98                    GenUSMaskRegVL(vvl),
99                    vvl))
100  val vvstart = io.in.bits.uop.vpu.vstart
101  val alignedType = Mux(isIndexed(instType), s0_sew(1, 0), s0_eew(1, 0))
102  val broadenAligendType = Mux(s0_preIsSplit, Cat("b0".U, alignedType), "b100".U) // if is unit-stride, use 128-bits memory access
103  val flowsLog2 = GenRealFlowLog2(instType, s0_emul, s0_lmul, s0_eew, s0_sew)
104  val flowsPrevThisUop = (uopIdxInField << flowsLog2).asUInt // # of flows before this uop in a field
105  val flowsPrevThisVd = (vdIdxInField << numFlowsSameVdLog2).asUInt // # of flows before this vd in a field
106  val flowsIncludeThisUop = ((uopIdxInField +& 1.U) << flowsLog2).asUInt // # of flows before this uop besides this uop
107  val flowNum = io.in.bits.flowNum.get
108  // max index in vd, only use in index instructions for calculate index
109  val maxIdxInVdIndex = GenVLMAX(Mux(s0_emul.asSInt > 0.S, 0.U, s0_emul), s0_eew(1, 0))
110  val indexVlMaxInVd = GenVlMaxMask(maxIdxInVdIndex, elemIdxBits)
111
112  // For vectore indexed  instructions:
113  //  When emul is greater than lmul, multiple uop correspond to a Vd, e.g:
114  //    vsetvli	t1,t0,e8,m1,ta,ma    lmul = 1
115  //    vluxei16.v	v2,(a0),v8       emul = 2
116  //    In this case, we need to ensure the flownumis right shift by flowsPrevThisUop, However, the mask passed to mergebuff is right shift by flowsPrevThisVd e.g:
117  //      vl = 9
118  //      srcMask = 0x1FF
119  //      uopIdxInField = 0 and vdIdxInField = 0, flowMask = 0x00FF, toMergeBuffMask = 0x01FF
120  //      uopIdxInField = 1 and vdIdxInField = 0, flowMask = 0x0001, toMergeBuffMask = 0x01FF
121  //      uopIdxInField = 0 and vdIdxInField = 0, flowMask = 0x0000, toMergeBuffMask = 0x0000
122  //      uopIdxInField = 0 and vdIdxInField = 0, flowMask = 0x0000, toMergeBuffMask = 0x0000
123  val isSpecialIndexed = isIndexed(instType) && s0_emul.asSInt > s0_lmul.asSInt
124
125  val srcMask = GenFlowMask(Mux(s0_vm, Fill(VLEN, 1.U(1.W)), io.in.bits.src_mask), vvstart, evl, true)
126  val srcMaskShiftBits = Mux(isSpecialIndexed, flowsPrevThisUop, flowsPrevThisVd)
127
128  val flowMask = ((srcMask &
129    UIntToMask(flowsIncludeThisUop.asUInt, VLEN + 1) &
130    (~UIntToMask(flowsPrevThisUop.asUInt, VLEN)).asUInt
131  ) >> srcMaskShiftBits)(VLENB - 1, 0)
132  val indexedSrcMask = (srcMask >> flowsPrevThisVd).asUInt //only for index instructions
133
134  // Used to calculate the element index.
135  // See 'splitbuffer' for 'io.out.splitIdxOffset' and 'mergebuffer' for 'merge data'
136  val indexedSplitOffset = Mux(isSpecialIndexed, flowsPrevThisUop - flowsPrevThisVd, 0.U) // only for index instructions of emul > lmul
137  val vlmax = GenVLMAX(s0_lmul, s0_sew)
138
139  // connect
140  s0_out := DontCare
141  s0_out match {case x =>
142    x.uop := io.in.bits.uop
143    x.uop.vpu.vl := evl
144    x.uop.uopIdx := uopIdx
145    x.uop.numUops := numUops
146    x.uop.lastUop := (uopIdx +& 1.U) === numUops
147    x.uop.vpu.nf  := s0_nf
148    x.flowMask := flowMask
149    x.indexedSrcMask := indexedSrcMask // Only vector indexed instructions uses it
150    x.indexedSplitOffset := indexedSplitOffset
151    x.byteMask := GenUopByteMask(flowMask, Cat("b0".U, alignedType))(VLENB - 1, 0)
152    x.fof := isUnitStride(s0_mop) && us_fof(s0_fuOpType)
153    x.baseAddr := io.in.bits.src_rs1
154    x.stride := io.in.bits.src_stride
155    x.flowNum := flowNum
156    x.nfields := s0_nfield
157    x.vm := s0_vm
158    x.usWholeReg := isUsWholeReg
159    x.usMaskReg := isMaskReg
160    x.eew := s0_eew
161    x.sew := s0_sew
162    x.emul := s0_emul
163    x.lmul := s0_lmul
164    x.vlmax := Mux(isUsWholeReg, evl, vlmax)
165    x.instType := instType
166    x.data := io.in.bits.src_vs3
167    x.vdIdxInField := vdIdxInField
168    x.preIsSplit  := s0_preIsSplit
169    x.alignedType := broadenAligendType
170    x.indexVlMaxInVd := indexVlMaxInVd
171  }
172  s0_valid := io.in.valid && !s0_kill
173  /**-------------------------------------
174    * s1 stage
175    * ------------------------------------
176    * generate UopOffset
177    */
178  val s1_valid         = RegInit(false.B)
179  val s1_kill          = Wire(Bool())
180  val s1_in            = Wire(new VLSBundle(isVStore))
181  val s1_can_go        = io.out.ready && io.toMergeBuffer.req.ready
182  val s1_fire          = s1_valid && !s1_kill && s1_can_go
183
184  s1_ready         := s1_kill || !s1_valid || s1_can_go
185
186  when(s0_fire){
187    s1_valid := true.B
188  }.elsewhen(s1_fire){
189    s1_valid := false.B
190  }.elsewhen(s1_kill){
191    s1_valid := false.B
192  }
193  s1_in := RegEnable(s0_out, s0_fire)
194
195  val s1_flowNum          = s1_in.flowNum
196  val s1_uop              = s1_in.uop
197  val s1_uopidx           = s1_uop.vpu.vuopIdx
198  val s1_nf               = s1_uop.vpu.nf
199  val s1_nfields          = s1_in.nfields
200  val s1_eew              = s1_in.eew
201  val s1_emul             = s1_in.emul
202  val s1_lmul             = s1_in.lmul
203  val s1_instType         = s1_in.instType
204  val s1_stride           = s1_in.stride
205  val s1_vmask            = FillInterleaved(8, s1_in.byteMask)(VLEN-1, 0)
206  val s1_alignedType      = s1_in.alignedType
207  val s1_isSpecialIndexed = isIndexed(s1_instType) && s1_emul.asSInt > s1_lmul.asSInt
208  val s1_mask             = Mux(s1_isSpecialIndexed, s1_in.indexedSrcMask, s1_in.flowMask)
209  val s1_vdIdx            = s1_in.vdIdxInField
210  val s1_fof              = s1_in.fof
211  val s1_notIndexedStride = Mux( // stride for strided/unit-stride instruction
212    isStrided(s1_instType),
213    s1_stride(XLEN - 1, 0), // for strided load, stride = x[rs2]
214    s1_nfields << s1_eew(1, 0) // for unit-stride load, stride = eew * NFIELDS
215  )
216
217  val stride     = Mux(isIndexed(s1_instType), s1_stride, s1_notIndexedStride).asUInt // if is index instructions, get index when split
218  val uopOffset  = genVUopOffset(s1_instType, s1_fof, s1_uopidx, s1_nf, s1_eew(1, 0), stride, s1_alignedType)
219  val activeNum  = Mux(s1_in.preIsSplit, PopCount(s1_in.flowMask), s1_flowNum)
220
221  s1_kill               := s1_in.uop.robIdx.needFlush(io.redirect)
222
223  // query mergeBuffer
224  io.toMergeBuffer.req.valid             := io.out.ready && s1_valid// only can_go will get MergeBuffer entry
225  io.toMergeBuffer.req.bits.flowNum      := activeNum
226  io.toMergeBuffer.req.bits.data         := s1_in.data
227  io.toMergeBuffer.req.bits.uop          := s1_in.uop
228  io.toMergeBuffer.req.bits.mask         := s1_mask
229  io.toMergeBuffer.req.bits.vaddr        := DontCare
230  io.toMergeBuffer.req.bits.vdIdx        := s1_vdIdx  //TODO vdIdxReg should no longer be useful, don't delete it for now
231  io.toMergeBuffer.req.bits.fof          := s1_in.fof
232  io.toMergeBuffer.req.bits.vlmax        := s1_in.vlmax
233//   io.toMergeBuffer.req.bits.vdOffset :=
234
235  //TODO vdIdxReg should no longer be useful, don't delete it for now
236//  when (s1_in.uop.lastUop && s1_fire || s1_kill) {
237//    vdIdxReg := 0.U
238//  }.elsewhen(s1_fire) {
239//    vdIdxReg := vdIdxReg + 1.U
240//    XSError(vdIdxReg + 1.U === 0.U, s"Overflow! The number of vd should be less than 8\n")
241//  }
242  // out connect
243  io.out.valid          := s1_valid && io.toMergeBuffer.resp.valid && (activeNum =/= 0.U) // if activeNum == 0, this uop do nothing, can be killed.
244  io.out.bits           := s1_in
245  io.out.bits.uopOffset := uopOffset
246  io.out.bits.stride    := stride
247  io.out.bits.mBIndex   := io.toMergeBuffer.resp.bits.mBIndex
248
249  XSPerfAccumulate("split_out",     io.out.fire)
250  XSPerfAccumulate("pipe_block",    io.out.valid && !io.out.ready)
251  XSPerfAccumulate("mbuffer_block", s1_valid && io.out.ready && !io.toMergeBuffer.resp.valid)
252}
253
254abstract class VSplitBuffer(isVStore: Boolean = false)(implicit p: Parameters) extends VLSUModule{
255  val io = IO(new VSplitBufferIO(isVStore))
256  lazy val fuCfg    = if(isVStore) VstuCfg else VlduCfg
257
258  val uopq          = Reg(new VLSBundle(isVStore))
259  val allocated     = RegInit(false.B)
260  val needCancel    = WireInit(false.B)
261  val activeIssue   = Wire(Bool())
262  val inActiveIssue = Wire(Bool())
263  val splitFinish   = WireInit(false.B)
264
265  // for split
266  val splitIdx = RegInit(0.U(flowIdxBits.W))
267  val strideOffsetReg = RegInit(0.U(VLEN.W))
268
269  /**
270    * Redirect
271    */
272  val cancelEnq    = io.in.bits.uop.robIdx.needFlush(io.redirect)
273  val canEnqueue   = io.in.valid
274  val needEnqueue  = canEnqueue && !cancelEnq
275
276  // enqueue
277  val offset    = PopCount(needEnqueue)
278  val canAccept = !allocated || allocated && splitFinish && (activeIssue || inActiveIssue) // if is valid entry, need split finish and send last uop
279  io.in.ready  := canAccept
280  val doEnqueue = canAccept && needEnqueue
281
282  when(doEnqueue){
283    uopq := io.in.bits
284  }
285
286  //split uops
287  val issueValid       = allocated && !needCancel
288  val issueEntry       = uopq
289  val issueMbIndex     = issueEntry.mBIndex
290  val issueFlowNum     = issueEntry.flowNum
291  val issueBaseAddr    = issueEntry.baseAddr
292  val issueUop         = issueEntry.uop
293  val issueUopIdx      = issueUop.vpu.vuopIdx
294  val issueInstType    = issueEntry.instType
295  val issueUopOffset   = issueEntry.uopOffset
296  val issueEew         = issueEntry.eew
297  val issueSew         = issueEntry.sew
298  val issueLmul        = issueEntry.lmul
299  val issueEmul        = issueEntry.emul
300  val issueAlignedType = issueEntry.alignedType
301  val issuePreIsSplit  = issueEntry.preIsSplit
302  val issueByteMask    = issueEntry.byteMask
303  val issueVLMAXMask   = issueEntry.vlmax - 1.U
304  val issueIsWholeReg  = issueEntry.usWholeReg
305  val issueVLMAXLog2   = GenVLMAXLog2(issueEntry.lmul, issueSew)
306  val issueVlMaxInVd   = issueEntry.indexVlMaxInVd
307  val elemIdx = GenElemIdx(
308    instType = issueInstType,
309    emul = issueEmul,
310    lmul = issueLmul,
311    eew = issueEew,
312    sew = issueSew,
313    uopIdx = issueUopIdx,
314    flowIdx = splitIdx
315  ) // elemIdx inside an inst, for exception
316
317  val splitIdxOffset = issueEntry.indexedSplitOffset + splitIdx
318
319  val indexFlowInnerIdx = elemIdx & issueVlMaxInVd
320  val nfIdx = Mux(issueIsWholeReg, 0.U, elemIdx >> issueVLMAXLog2)
321  val fieldOffset = nfIdx << issueAlignedType // field offset inside a segment
322
323  val indexedStride    = IndexAddr( // index for indexed instruction
324    index = issueEntry.stride,
325    flow_inner_idx = indexFlowInnerIdx,
326    eew = issueEew
327  )
328  val issueStride = Mux(isIndexed(issueInstType), indexedStride, strideOffsetReg)
329  val vaddr = issueBaseAddr + issueUopOffset + issueStride
330  val mask = genVWmask128(vaddr ,issueAlignedType) // scala maske for flow
331  val flowMask = issueEntry.flowMask
332  val vecActive = (flowMask & UIntToOH(splitIdx)).orR
333  /*
334   * Unit-Stride split to one flow or two flow.
335   * for Unit-Stride, if uop's addr is aligned with 128-bits, split it to one flow, otherwise split two
336   */
337  val usLowBitsAddr    = getCheckAddrLowBits(issueBaseAddr, maxMemByteNum) + getCheckAddrLowBits(issueUopOffset, maxMemByteNum)
338  val usAligned128     = (getCheckAddrLowBits(usLowBitsAddr, maxMemByteNum) === 0.U)// addr 128-bit aligned
339  val usSplitMask      = genUSSplitMask(issueByteMask, splitIdx, getCheckAddrLowBits(usLowBitsAddr, maxMemByteNum))
340  val usNoSplit        = (usAligned128 || !getOverflowBit(getCheckAddrLowBits(usLowBitsAddr, maxMemByteNum) +& PopCount(usSplitMask), maxMemByteNum)) &&
341                          !issuePreIsSplit &&
342                          (splitIdx === 0.U)// unit-stride uop don't need to split into two flow
343  val usSplitVaddr     = genUSSplitAddr(vaddr, splitIdx)
344  val regOffset        = getCheckAddrLowBits(usLowBitsAddr, maxMemByteNum) // offset in 256-bits vd
345  XSError((splitIdx > 1.U && usNoSplit) || (splitIdx > 1.U && !issuePreIsSplit) , "Unit-Stride addr split error!\n")
346
347  // data
348  io.out.bits match { case x =>
349    x.uop                   := issueUop
350    x.uop.exceptionVec      := ExceptionNO.selectByFu(issueUop.exceptionVec, fuCfg)
351    x.vaddr                 := Mux(!issuePreIsSplit, usSplitVaddr, vaddr)
352    x.alignedType           := issueAlignedType
353    x.isvec                 := true.B
354    x.mask                  := Mux(!issuePreIsSplit, usSplitMask, mask)
355    x.reg_offset            := regOffset //for merge unit-stride data
356    x.vecActive             := Mux(!issuePreIsSplit, true.B, vecActive) // currently, unit-stride's flow always send to pipeline
357    x.is_first_ele          := DontCare
358    x.usSecondInv           := usNoSplit
359    x.elemIdx               := elemIdx
360    x.elemIdxInsideVd       := splitIdxOffset // if is Unit-Stride, elemIdx is the index of 2 splited mem request (for merge data)
361    x.uop_unit_stride_fof   := DontCare
362    x.isFirstIssue          := DontCare
363    x.mBIndex               := issueMbIndex
364  }
365
366  // redirect
367  needCancel := uopq.uop.robIdx.needFlush(io.redirect) && allocated
368
369 /* Execute logic */
370  /** Issue to scala pipeline**/
371  val allowIssue = io.out.ready
372  val issueCount = Mux(usNoSplit, 2.U, (PopCount(inActiveIssue) + PopCount(activeIssue))) // for dont need split unit-stride, issue two flow
373  splitFinish := splitIdx >= (issueFlowNum - issueCount)
374
375  // handshake
376  activeIssue := issueValid && allowIssue && (vecActive || !issuePreIsSplit) // active issue, current use in no unit-stride
377  inActiveIssue := issueValid && !vecActive && issuePreIsSplit
378  when (!issueEntry.uop.robIdx.needFlush(io.redirect)) {
379    when (!splitFinish) {
380      when (activeIssue || inActiveIssue) {
381        // The uop has not been entirly splited yet
382        splitIdx := splitIdx + issueCount
383        strideOffsetReg := Mux(!issuePreIsSplit, strideOffsetReg, strideOffsetReg + issueEntry.stride) // when normal unit-stride, don't use strideOffsetReg
384      }
385    }.otherwise {
386      when (activeIssue || inActiveIssue) {
387        // The uop is done spliting
388        splitIdx := 0.U(flowIdxBits.W) // initialize flowIdx
389        strideOffsetReg := 0.U
390      }
391    }
392  }.otherwise {
393    splitIdx := 0.U(flowIdxBits.W) // initialize flowIdx
394    strideOffsetReg := 0.U
395  }
396  // allocated
397  when(doEnqueue){ // if enqueue need to been cancelled, it will be false, so this have high priority
398    allocated := true.B
399  }.elsewhen(needCancel) { // redirect
400    allocated := false.B
401  }.elsewhen(splitFinish && (activeIssue || inActiveIssue)){ //dequeue
402    allocated := false.B
403  }
404
405  // out connect
406  io.out.valid := issueValid && (vecActive || !issuePreIsSplit) // TODO: inactive unit-stride uop do not send to pipeline
407
408  XSPerfAccumulate("out_valid",             io.out.valid)
409  XSPerfAccumulate("out_fire",              io.out.fire)
410  XSPerfAccumulate("out_fire_unitstride",   io.out.fire && !issuePreIsSplit)
411  XSPerfAccumulate("unitstride_vlenAlign",  io.out.fire && !issuePreIsSplit && getCheckAddrLowBits(io.out.bits.vaddr, maxMemByteNum) === 0.U)
412  XSPerfAccumulate("unitstride_invalid",    io.out.ready && issueValid && !issuePreIsSplit && PopCount(io.out.bits.mask).orR)
413}
414
415class VSSplitBufferImp(implicit p: Parameters) extends VSplitBuffer(isVStore = true){
416  // split data
417  val splitData = genVSData(
418        data = issueEntry.data.asUInt,
419        elemIdx = splitIdxOffset,
420        alignedType = issueAlignedType
421      )
422  val flowData = genVWdata(splitData, issueAlignedType)
423  val usSplitData      = genUSSplitData(issueEntry.data.asUInt, splitIdx, vaddr(3,0))
424
425  val sqIdx = issueUop.sqIdx + splitIdx
426  io.out.bits.uop.sqIdx := sqIdx
427
428  // send data to sq
429  val vstd = io.vstd.get
430  vstd.valid := issueValid && (vecActive || !issuePreIsSplit)
431  vstd.bits.uop := issueUop
432  vstd.bits.uop.sqIdx := sqIdx
433  vstd.bits.data := Mux(!issuePreIsSplit, usSplitData, flowData)
434  vstd.bits.debug := DontCare
435  vstd.bits.vdIdx.get := DontCare
436  vstd.bits.vdIdxInField.get := DontCare
437  vstd.bits.mask.get := Mux(!issuePreIsSplit, usSplitMask, mask)
438
439}
440
441class VLSplitBufferImp(implicit p: Parameters) extends VSplitBuffer(isVStore = false){
442  io.out.bits.uop.lqIdx := issueUop.lqIdx + splitIdx
443}
444
445class VSSplitPipelineImp(implicit p: Parameters) extends VSplitPipeline(isVStore = true){
446  override def us_whole_reg(fuOpType: UInt): Bool = fuOpType === VstuType.vsr
447  override def us_mask(fuOpType: UInt): Bool      = fuOpType === VstuType.vsm
448  override def us_fof(fuOpType: UInt): Bool       = false.B // dont have vector fof store
449}
450
451class VLSplitPipelineImp(implicit p: Parameters) extends VSplitPipeline(isVStore = false){
452
453  override def us_whole_reg(fuOpType: UInt): Bool = fuOpType === VlduType.vlr
454  override def us_mask(fuOpType: UInt): Bool      = fuOpType === VlduType.vlm
455  override def us_fof(fuOpType: UInt): Bool       = fuOpType === VlduType.vleff
456}
457
458class VLSplitImp(implicit p: Parameters) extends VLSUModule{
459  val io = IO(new VSplitIO(isVStore=false))
460  val splitPipeline = Module(new VLSplitPipelineImp())
461  val splitBuffer = Module(new VLSplitBufferImp())
462  // Split Pipeline
463  splitPipeline.io.in <> io.in
464  splitPipeline.io.redirect <> io.redirect
465  io.toMergeBuffer <> splitPipeline.io.toMergeBuffer
466
467  // Split Buffer
468  splitBuffer.io.in <> splitPipeline.io.out
469  splitBuffer.io.redirect <> io.redirect
470  io.out <> splitBuffer.io.out
471}
472
473class VSSplitImp(implicit p: Parameters) extends VLSUModule{
474  val io = IO(new VSplitIO(isVStore=true))
475  val splitPipeline = Module(new VSSplitPipelineImp())
476  val splitBuffer = Module(new VSSplitBufferImp())
477  // Split Pipeline
478  splitPipeline.io.in <> io.in
479  splitPipeline.io.redirect <> io.redirect
480  io.toMergeBuffer <> splitPipeline.io.toMergeBuffer
481
482  // Split Buffer
483  splitBuffer.io.in <> splitPipeline.io.out
484  splitBuffer.io.redirect <> io.redirect
485  io.out <> splitBuffer.io.out
486  io.vstd.get <> splitBuffer.io.vstd.get
487}
488
489