xref: /XiangShan/src/main/scala/xiangshan/mem/vector/VSegmentUnit.scala (revision 82674533125d3d049f50148b1d9e215e1463f136)
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.FuType
29import freechips.rocketchip.diplomacy.BufferParams
30import xiangshan.cache.mmu._
31import xiangshan.cache._
32import xiangshan.cache.wpu.ReplayCarry
33import xiangshan.backend.fu.util.SdtrigExt
34import xiangshan.ExceptionNO._
35import xiangshan.backend.fu.vector.Bundles.VConfig
36import xiangshan.backend.fu.vector.Utils.VecDataToMaskDataVec
37
38class VSegmentBundle(implicit p: Parameters) extends VLSUBundle
39{
40  val vaddr            = UInt(VAddrBits.W)
41  val uop              = new DynInst
42  val paddr            = UInt(PAddrBits.W)
43  val mask             = UInt(VLEN.W)
44  val valid            = Bool()
45  val alignedType      = UInt(alignTypeBits.W)
46  val vl               = UInt(elemIdxBits.W)
47  val vlmaxInVd        = UInt(elemIdxBits.W)
48  val vlmaxMaskInVd    = UInt(elemIdxBits.W)
49  // for exception
50  val vstart           = UInt(elemIdxBits.W)
51  val exceptionvaddr   = UInt(VAddrBits.W)
52  val exception_va     = Bool()
53  val exception_pa     = Bool()
54}
55
56class VSegmentUop(implicit p: Parameters) extends VLSUBundle{
57  val pdest            = UInt(VLEN.W)
58  val vecWen           = Bool()
59  val uopIdx           = UopIdx()
60
61}
62
63class VSegmentUnit (implicit p: Parameters) extends VLSUModule
64  with HasDCacheParameters
65  with MemoryOpConstants
66  with SdtrigExt
67  with HasLoadHelper
68{
69  val io               = IO(new VSegmentUnitIO)
70
71  val maxSize          = VSegmentBufferSize
72
73  class VSegUPtr(implicit p: Parameters) extends CircularQueuePtr[VSegUPtr](maxSize){
74  }
75
76  object VSegUPtr {
77    def apply(f: Bool, v: UInt)(implicit p: Parameters): VSegUPtr = {
78      val ptr           = Wire(new VSegUPtr)
79      ptr.flag         := f
80      ptr.value        := v
81      ptr
82    }
83  }
84
85  // buffer uop
86  val instMicroOp       = Reg(new VSegmentBundle)
87  val data              = Reg(Vec(maxSize, UInt(VLEN.W)))
88  val uopq              = Reg(Vec(maxSize, new VSegmentUop))
89  val stride            = Reg(Vec(maxSize, UInt(VLEN.W)))
90  val allocated         = RegInit(VecInit(Seq.fill(maxSize)(false.B)))
91  val enqPtr            = RegInit(0.U.asTypeOf(new VSegUPtr))
92  val deqPtr            = RegInit(0.U.asTypeOf(new VSegUPtr))
93  val stridePtr         = WireInit(0.U.asTypeOf(new VSegUPtr)) // for select stride/index
94
95  val segmentIdx        = RegInit(0.U(elemIdxBits.W))
96  val fieldIdx          = RegInit(0.U(fieldBits.W))
97  val segmentOffset     = RegInit(0.U(VAddrBits.W))
98  val splitPtr          = RegInit(0.U.asTypeOf(new VSegUPtr)) // for select load/store data
99  val splitPtrNext      = WireInit(0.U.asTypeOf(new VSegUPtr))
100
101  val exception_va      = WireInit(false.B)
102  val exception_pa      = WireInit(false.B)
103
104  val maxSegIdx         = instMicroOp.vl - 1.U
105  val maxNfields        = instMicroOp.uop.vpu.nf
106
107  XSError(segmentIdx > maxSegIdx, s"segmentIdx > vl, something error!\n")
108  XSError(fieldIdx > maxNfields, s"fieldIdx > nfields, something error!\n")
109
110  // MicroOp
111  val baseVaddr                       = instMicroOp.vaddr
112  val alignedType                     = instMicroOp.alignedType
113  val fuType                          = instMicroOp.uop.fuType
114  val mask                            = instMicroOp.mask
115  val exceptionVec                    = instMicroOp.uop.exceptionVec
116  val issueEew                        = instMicroOp.uop.vpu.veew
117  val issueLmul                       = instMicroOp.uop.vpu.vtype.vlmul
118  val issueSew                        = instMicroOp.uop.vpu.vtype.vsew
119  val issueEmul                       = EewLog2(issueEew) - issueSew + issueLmul
120  val elemIdxInVd                     = segmentIdx & instMicroOp.vlmaxMaskInVd
121  val issueInstType                   = Cat(true.B, instMicroOp.uop.fuOpType(6, 5)) // always segment instruction
122  val issueVLMAXLog2                  = GenVLMAXLog2(
123    Mux(issueLmul.asSInt > 0.S, 0.U, issueLmul),
124    Mux(isIndexed(issueInstType), issueSew(1, 0), issueEew(1, 0))
125  ) // max element number log2 in vd
126  val issueVlMax                      = instMicroOp.vlmaxInVd // max elementIdx in vd
127  val issueMaxIdxInIndex              = GenVLMAX(Mux(issueEmul.asSInt > 0.S, 0.U, issueEmul), issueEew(1, 0)) // index element index in index register
128  val issueMaxIdxInIndexMask          = GenVlMaxMask(issueMaxIdxInIndex, elemIdxBits)
129  val issueMaxIdxInIndexLog2          = GenVLMAXLog2(Mux(issueEmul.asSInt > 0.S, 0.U, issueEmul), issueEew(1, 0))
130  val issueIndexIdx                   = segmentIdx & issueMaxIdxInIndexMask
131  val segmentActive                   = (mask & UIntToOH(segmentIdx)).orR
132
133  // Segment instruction's FSM
134  /*
135  * s_idle: wait request
136  * s_flush_sbuffer_req: flush sbuffer
137  * s_wait_flush_sbuffer_resp: wait sbuffer empty
138  * s_tlb_req: request tlb
139  * s_wait_tlb_resp: wait tlb resp
140  * s_pm: check pmp
141  * s_cache_req: request cache
142  * s_cache_resp: wait cache resp
143  * s_latch_and_merge_data: for read data
144  * s_send_data: for send write data
145  * s_finish:
146  * */
147  val s_idle :: s_flush_sbuffer_req :: s_wait_flush_sbuffer_resp :: s_tlb_req :: s_wait_tlb_resp :: s_pm ::s_cache_req :: s_cache_resp :: s_latch_and_merge_data :: s_send_data :: s_finish :: Nil = Enum(11)
148  val state             = RegInit(s_idle)
149  val stateNext         = WireInit(s_idle)
150  val sbufferEmpty      = io.flush_sbuffer.empty
151
152  /**
153   * state update
154   */
155  state  := stateNext
156
157  /**
158   * state transfer
159   */
160  when(state === s_idle){
161    stateNext := Mux(isAfter(enqPtr, deqPtr), s_flush_sbuffer_req, s_idle)
162  }.elsewhen(state === s_flush_sbuffer_req){
163    stateNext := Mux(sbufferEmpty, s_tlb_req, s_wait_flush_sbuffer_resp) // if sbuffer is empty, go to query tlb
164
165  }.elsewhen(state === s_wait_flush_sbuffer_resp){
166    stateNext := Mux(sbufferEmpty, s_tlb_req, s_wait_flush_sbuffer_resp)
167
168  }.elsewhen(state === s_tlb_req){
169    stateNext := Mux(segmentActive, s_wait_tlb_resp, Mux(FuType.isVLoad(instMicroOp.uop.fuType), s_latch_and_merge_data, s_send_data))
170
171  }.elsewhen(state === s_wait_tlb_resp){
172    stateNext := Mux(!io.dtlb.resp.bits.miss && io.dtlb.resp.fire, s_pm, s_tlb_req)
173
174  }.elsewhen(state === s_pm){
175    /* if is vStore, send data to sbuffer, so don't need query dcache */
176    stateNext := Mux(exception_pa || exception_va,
177                     s_finish,
178                     Mux(FuType.isVLoad(instMicroOp.uop.fuType), s_cache_req, s_send_data))
179
180  }.elsewhen(state === s_cache_req){
181    stateNext := Mux(io.rdcache.req.fire, s_cache_resp, s_cache_req)
182
183  }.elsewhen(state === s_cache_resp){
184    when(io.rdcache.resp.fire) {
185      when(io.rdcache.resp.bits.miss) {
186        stateNext := s_cache_req
187      }.otherwise {
188        stateNext := Mux(FuType.isVLoad(instMicroOp.uop.fuType), s_latch_and_merge_data, s_send_data)
189      }
190    }.otherwise{
191      stateNext := s_cache_resp
192    }
193    /* if segment is inactive, don't need to wait access all of the field */
194  }.elsewhen(state === s_latch_and_merge_data) {
195    when((segmentIdx === maxSegIdx) && (fieldIdx === maxNfields) ||
196      ((segmentIdx === maxSegIdx) && !segmentActive)) {
197
198      stateNext := s_finish // segment instruction finish
199    }.otherwise {
200      stateNext := s_tlb_req // need continue
201    }
202    /* if segment is inactive, don't need to wait access all of the field */
203  }.elsewhen(state === s_send_data) { // when sbuffer accept data
204    when(!io.sbuffer.fire && segmentActive) {
205      stateNext := s_send_data
206    }.elsewhen(((segmentIdx === maxSegIdx) && (fieldIdx === maxNfields)) ||
207               ((segmentIdx === maxSegIdx) && !segmentActive)) {
208
209      stateNext := s_finish // segment instruction finish
210    }.otherwise {
211      stateNext := s_tlb_req // need continue
212    }
213  }.elsewhen(state === s_finish){ // writeback uop
214    stateNext := Mux(distanceBetween(enqPtr, deqPtr) === 0.U, s_idle, s_finish)
215
216  }.otherwise{
217    stateNext := s_idle
218    XSError(true.B, s"Unknown state!\n")
219  }
220
221  /*************************************************************************
222   *                            enqueue logic
223   *************************************************************************/
224  io.in.ready                         := true.B
225  val fuOpType                         = io.in.bits.uop.fuOpType
226  val vtype                            = io.in.bits.uop.vpu.vtype
227  val mop                              = fuOpType(6, 5)
228  val instType                         = Cat(true.B, mop)
229  val eew                              = io.in.bits.uop.vpu.veew
230  val sew                              = vtype.vsew
231  val lmul                             = vtype.vlmul
232  val vl                               = instMicroOp.vl
233  val vm                               = instMicroOp.uop.vpu.vm
234  val vstart                           = instMicroOp.uop.vpu.vstart
235  val srcMask                          = GenFlowMask(Mux(vm, Fill(VLEN, 1.U(1.W)), io.in.bits.src_mask), vstart, vl, true)
236  // first uop enqueue, we need to latch microOp of segment instruction
237  when(io.in.fire && !instMicroOp.valid){
238    val vlmaxInVd                      = GenVLMAX(Mux(lmul.asSInt > 0.S, 0.U, lmul), Mux(isIndexed(instType), sew(1, 0), eew(1, 0))) // element number in a vd
239    instMicroOp.vaddr                 := io.in.bits.src_rs1(VAddrBits - 1, 0)
240    instMicroOp.valid                 := true.B // if is first uop
241    instMicroOp.alignedType           := Mux(isIndexed(instType), sew(1, 0), eew(1, 0))
242    instMicroOp.uop                   := io.in.bits.uop
243    instMicroOp.mask                  := srcMask
244    instMicroOp.vstart                := 0.U
245    instMicroOp.vlmaxInVd             := vlmaxInVd
246    instMicroOp.vlmaxMaskInVd         := GenVlMaxMask(vlmaxInVd, elemIdxBits) // for merge data
247    instMicroOp.vl                    := io.in.bits.src_vl.asTypeOf(VConfig()).vl
248    segmentOffset                     := 0.U
249  }
250  // latch data
251  when(io.in.fire){
252    data(enqPtr.value)                := io.in.bits.src_vs3
253    stride(enqPtr.value)              := io.in.bits.src_stride
254    uopq(enqPtr.value).uopIdx         := io.in.bits.uop.vpu.vuopIdx
255    uopq(enqPtr.value).pdest          := io.in.bits.uop.pdest
256    uopq(enqPtr.value).vecWen         := io.in.bits.uop.vecWen
257  }
258
259  // update enqptr, only 1 port
260  when(io.in.fire){
261    enqPtr                            := enqPtr + 1.U
262  }
263
264  /*************************************************************************
265   *                            output logic
266   *************************************************************************/
267
268  val indexStride                     = IndexAddr( // index for indexed instruction
269                                                    index = stride(stridePtr.value),
270                                                    flow_inner_idx = issueIndexIdx,
271                                                    eew = issueEew
272                                                  )
273  val realSegmentOffset               = Mux(isIndexed(issueInstType),
274                                            indexStride,
275                                            segmentOffset)
276  val vaddr                           = baseVaddr + (fieldIdx << alignedType).asUInt + realSegmentOffset
277  /**
278   * tlb req and tlb resq
279   */
280
281  // query DTLB IO Assign
282  io.dtlb.req                         := DontCare
283  io.dtlb.resp.ready                  := true.B
284  io.dtlb.req.valid                   := state === s_tlb_req && segmentActive
285  io.dtlb.req.bits.cmd                := Mux(FuType.isVLoad(fuType), TlbCmd.read, TlbCmd.write)
286  io.dtlb.req.bits.vaddr              := vaddr
287  io.dtlb.req.bits.size               := instMicroOp.alignedType(2,0)
288  io.dtlb.req.bits.memidx.is_ld       := FuType.isVLoad(fuType)
289  io.dtlb.req.bits.memidx.is_st       := FuType.isVStore(fuType)
290  io.dtlb.req.bits.debug.robIdx       := instMicroOp.uop.robIdx
291  io.dtlb.req.bits.no_translate       := false.B
292  io.dtlb.req.bits.debug.pc           := instMicroOp.uop.pc
293  io.dtlb.req.bits.debug.isFirstIssue := DontCare
294  io.dtlb.req_kill                    := false.B
295
296  // tlb resp
297  when(io.dtlb.resp.fire && state === s_wait_tlb_resp){
298      exceptionVec(storePageFault)    := io.dtlb.resp.bits.excp(0).pf.st
299      exceptionVec(loadPageFault)     := io.dtlb.resp.bits.excp(0).pf.ld
300      exceptionVec(storeAccessFault)  := io.dtlb.resp.bits.excp(0).af.st
301      exceptionVec(loadAccessFault)   := io.dtlb.resp.bits.excp(0).af.ld
302      when(!io.dtlb.resp.bits.miss){
303        instMicroOp.paddr             := io.dtlb.resp.bits.paddr(0)
304      }
305  }
306  // pmp
307  // NOTE: only handle load/store exception here, if other exception happens, don't send here
308  val pmp = WireInit(io.pmpResp)
309  when(state === s_pm){
310    exception_va := exceptionVec(storePageFault) || exceptionVec(loadPageFault) ||
311    exceptionVec(storeAccessFault) || exceptionVec(loadAccessFault)
312    exception_pa := pmp.st || pmp.ld
313
314    instMicroOp.exception_pa       := exception_pa
315    instMicroOp.exception_va       := exception_va
316    // update storeAccessFault bit
317    exceptionVec(loadAccessFault)  := exceptionVec(loadAccessFault) || pmp.ld
318    exceptionVec(storeAccessFault) := exceptionVec(storeAccessFault) || pmp.st
319
320    when(exception_va || exception_pa){
321      instMicroOp.exceptionvaddr     := vaddr
322      instMicroOp.vl                 := segmentIdx // for exception
323      instMicroOp.vstart             := segmentIdx // for exception
324    }
325  }
326
327  /**
328   * flush sbuffer IO Assign
329   */
330  io.flush_sbuffer.valid           := !sbufferEmpty && (state === s_flush_sbuffer_req)
331
332
333  /**
334   * merge data for load
335   */
336  val cacheData = LookupTree(vaddr(3,0), List(
337    "b0000".U -> io.rdcache.resp.bits.data_delayed(63,    0),
338    "b0001".U -> io.rdcache.resp.bits.data_delayed(63,    8),
339    "b0010".U -> io.rdcache.resp.bits.data_delayed(63,   16),
340    "b0011".U -> io.rdcache.resp.bits.data_delayed(63,   24),
341    "b0100".U -> io.rdcache.resp.bits.data_delayed(63,   32),
342    "b0101".U -> io.rdcache.resp.bits.data_delayed(63,   40),
343    "b0110".U -> io.rdcache.resp.bits.data_delayed(63,   48),
344    "b0111".U -> io.rdcache.resp.bits.data_delayed(63,   56),
345    "b1000".U -> io.rdcache.resp.bits.data_delayed(127,  64),
346    "b1001".U -> io.rdcache.resp.bits.data_delayed(127,  72),
347    "b1010".U -> io.rdcache.resp.bits.data_delayed(127,  80),
348    "b1011".U -> io.rdcache.resp.bits.data_delayed(127,  88),
349    "b1100".U -> io.rdcache.resp.bits.data_delayed(127,  96),
350    "b1101".U -> io.rdcache.resp.bits.data_delayed(127, 104),
351    "b1110".U -> io.rdcache.resp.bits.data_delayed(127, 112),
352    "b1111".U -> io.rdcache.resp.bits.data_delayed(127, 120)
353  ))
354  val pickData  = rdataVecHelper(alignedType(1,0), cacheData)
355  val mergedData = mergeDataWithElemIdx(
356    oldData = data(splitPtr.value),
357    newData = Seq(pickData),
358    alignedType = alignedType(1,0),
359    elemIdx = Seq(elemIdxInVd),
360    valids = Seq(true.B)
361  )
362  when(state === s_latch_and_merge_data && segmentActive){
363    data(splitPtr.value) := mergedData
364  }
365  /**
366   * split data for store
367   * */
368  val splitData = genVSData(
369    data = data(splitPtr.value),
370    elemIdx = elemIdxInVd,
371    alignedType = alignedType
372  )
373  val flowData  = genVWdata(splitData, alignedType) // TODO: connect vstd, pass vector data
374  val wmask     = genVWmask(vaddr, alignedType(1, 0)) & Fill(VLENB, segmentActive)
375
376  /**
377   * rdcache req, write request don't need to query dcache, because we write element to sbuffer
378   */
379  io.rdcache.req                    := DontCare
380  io.rdcache.req.valid              := state === s_cache_req && FuType.isVLoad(fuType)
381  io.rdcache.req.bits.cmd           := MemoryOpConstants.M_XRD
382  io.rdcache.req.bits.vaddr         := vaddr
383  io.rdcache.req.bits.mask          := mask
384  io.rdcache.req.bits.data          := flowData
385  io.rdcache.pf_source              := LOAD_SOURCE.U
386  io.rdcache.req.bits.id            := DontCare
387  io.rdcache.resp.ready             := true.B
388  io.rdcache.s1_paddr_dup_lsu       := instMicroOp.paddr
389  io.rdcache.s1_paddr_dup_dcache    := instMicroOp.paddr
390  io.rdcache.s1_kill                := false.B
391  io.rdcache.s2_kill                := false.B
392  if (env.FPGAPlatform){
393    io.rdcache.s0_pc                := DontCare
394    io.rdcache.s1_pc                := DontCare
395    io.rdcache.s2_pc                := DontCare
396  }else{
397    io.rdcache.s0_pc                := instMicroOp.uop.pc
398    io.rdcache.s1_pc                := instMicroOp.uop.pc
399    io.rdcache.s2_pc                := instMicroOp.uop.pc
400  }
401  io.rdcache.replacementUpdated     := false.B
402  io.rdcache.is128Req               := false.B
403
404
405  /**
406   * write data to sbuffer
407   * */
408
409  io.sbuffer.bits                  := DontCare
410  io.sbuffer.valid                 := state === s_send_data && segmentActive
411  io.sbuffer.bits.vecValid         := state === s_send_data && segmentActive
412  io.sbuffer.bits.mask             := wmask
413  io.sbuffer.bits.data             := flowData
414  io.sbuffer.bits.vaddr            := vaddr
415  io.sbuffer.bits.cmd              := MemoryOpConstants.M_XWR
416  io.sbuffer.bits.id               := DontCare
417  io.sbuffer.bits.addr             := instMicroOp.paddr
418
419  /**
420   * update ptr
421   * */
422  private val fieldActiveWirteFinish = io.sbuffer.fire && segmentActive // writedata finish and is a active segment
423  XSError(io.sbuffer.fire && !segmentActive, "Attempt write inactive segment to sbuffer, something wrong!\n")
424
425  private val segmentInactiveFinish = ((state === s_latch_and_merge_data) || (state === s_send_data)) && !segmentActive
426
427  val splitPtrOffset = Mux(lmul.asSInt < 0.S, 1.U, (1.U << lmul).asUInt)
428  splitPtrNext :=
429    Mux(fieldIdx === maxNfields || !segmentActive, // if segment is active, need to complete this segment, otherwise jump to next segment
430     (deqPtr + ((segmentIdx +& 1.U) >> issueVLMAXLog2).asUInt), // segment finish
431     (splitPtr + splitPtrOffset)) // next field
432  dontTouch(issueVLMAXLog2)
433  dontTouch(splitPtrNext)
434  dontTouch(stridePtr)
435
436  // update splitPtr
437  when(state === s_latch_and_merge_data || (state === s_send_data && (fieldActiveWirteFinish || !segmentActive))){
438    splitPtr := splitPtrNext
439  }.elsewhen(io.in.fire && !instMicroOp.valid){
440    splitPtr := deqPtr // initial splitPtr
441  }
442
443  // update stridePtr, only use in index
444  val strideOffset = Mux(isIndexed(issueInstType), segmentIdx >> issueMaxIdxInIndexLog2, 0.U)
445  stridePtr       := deqPtr + strideOffset
446
447  // update fieldIdx
448  when(io.in.fire && !instMicroOp.valid){ // init
449    fieldIdx := 0.U
450  }.elsewhen(state === s_latch_and_merge_data && segmentActive ||
451            (state === s_send_data && fieldActiveWirteFinish)){ // only if segment is active
452
453    /* next segment, only if segment complete */
454    fieldIdx := Mux(fieldIdx === maxNfields, 0.U, fieldIdx + 1.U)
455  }.elsewhen(segmentInactiveFinish){ // segment is inactive, go to next segment
456    fieldIdx := 0.U
457  }
458  //update segmentIdx
459  when(io.in.fire && !instMicroOp.valid){
460    segmentIdx := 0.U
461  }.elsewhen(fieldIdx === maxNfields && (state === s_latch_and_merge_data || (state === s_send_data && fieldActiveWirteFinish)) &&
462             segmentIdx =/= maxSegIdx){ // next segment, only if segment is active
463
464    segmentIdx := segmentIdx + 1.U
465  }.elsewhen(segmentInactiveFinish && segmentIdx =/= maxSegIdx){ // if segment is inactive, go to next segment
466    segmentIdx := segmentIdx + 1.U
467  }
468
469  //update segmentOffset
470  /* when segment is active or segment is inactive, increase segmentOffset */
471  when((fieldIdx === maxNfields && (state === s_latch_and_merge_data || (state === s_send_data && fieldActiveWirteFinish))) ||
472       segmentInactiveFinish){
473
474    segmentOffset := segmentOffset + Mux(isUnitStride(issueInstType), (maxNfields +& 1.U) << issueEew(1, 0), stride(stridePtr.value))
475  }
476
477  //update deqPtr
478  when(io.uopwriteback.fire){
479    deqPtr := deqPtr + 1.U
480  }
481
482  /*************************************************************************
483   *                            dequeue logic
484   *************************************************************************/
485  val vdIdxInField = GenUopIdxInField(Mux(isIndexed(instType), issueLmul, issueEmul), uopq(deqPtr.value).uopIdx)
486  /*select mask of vd, maybe remove in feature*/
487  val realEw        = Mux(isIndexed(issueInstType), issueSew(1, 0), issueEew(1, 0))
488  val maskDataVec: Vec[UInt] = VecDataToMaskDataVec(instMicroOp.mask, realEw)
489  val maskUsed      = maskDataVec(vdIdxInField)
490
491  when(stateNext === s_idle){
492    instMicroOp.valid := false.B
493  }
494  io.uopwriteback.valid               := (state === s_finish) && distanceBetween(enqPtr, deqPtr) =/= 0.U
495  io.uopwriteback.bits.uop            := instMicroOp.uop
496  io.uopwriteback.bits.mask.get       := instMicroOp.mask
497  io.uopwriteback.bits.data           := data(deqPtr.value)
498  io.uopwriteback.bits.vdIdx.get      := vdIdxInField
499  io.uopwriteback.bits.uop.vpu.vl     := instMicroOp.vl
500  io.uopwriteback.bits.uop.vpu.vstart := instMicroOp.vstart
501  io.uopwriteback.bits.uop.vpu.vmask  := maskUsed
502  io.uopwriteback.bits.uop.pdest      := uopq(deqPtr.value).pdest
503  io.uopwriteback.bits.debug          := DontCare
504  io.uopwriteback.bits.vdIdxInField.get := vdIdxInField
505  io.uopwriteback.bits.uop.vpu.vuopIdx  := uopq(deqPtr.value).uopIdx
506  io.uopwriteback.bits.uop.vecWen     := uopq(deqPtr.value).vecWen
507
508  //to RS
509  io.feedback.valid                   := state === s_finish && distanceBetween(enqPtr, deqPtr) =/= 0.U
510  io.feedback.bits.hit                := true.B
511  io.feedback.bits.robIdx             := instMicroOp.uop.robIdx
512  io.feedback.bits.sourceType         := DontCare
513  io.feedback.bits.flushState         := DontCare
514  io.feedback.bits.dataInvalidSqIdx   := DontCare
515  io.feedback.bits.uopIdx.get         := uopq(deqPtr.value).uopIdx
516
517  // exception
518  io.exceptionAddr                    := DontCare // TODO: fix it when handle exception
519}
520
521