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