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