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