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.ExceptionNO._ 26import xiangshan.frontend.FtqPtr 27import xiangshan.backend.fu.FuConfig._ 28import xiangshan.backend.fu.fpu.FPU 29import xiangshan.backend.rob.RobLsqIO 30import xiangshan.backend.rob.RobPtr 31import xiangshan.backend.Bundles._ 32import xiangshan.backend.fu.FuConfig.StaCfg 33import xiangshan.backend.fu.FuType.isVStore 34import xiangshan.mem.Bundles._ 35import xiangshan.cache._ 36import xiangshan.cache.wpu.ReplayCarry 37 38class StoreMisalignBuffer(implicit p: Parameters) extends XSModule 39 with HasCircularQueuePtrHelper 40{ 41 private val enqPortNum = StorePipelineWidth 42 private val maxSplitNum = 2 43 44 require(maxSplitNum == 2) 45 46 private val SB = "b00".U(2.W) 47 private val SH = "b01".U(2.W) 48 private val SW = "b10".U(2.W) 49 private val SD = "b11".U(2.W) 50 51 // encode of how many bytes to shift or truncate 52 private val BYTE0 = "b000".U(3.W) 53 private val BYTE1 = "b001".U(3.W) 54 private val BYTE2 = "b010".U(3.W) 55 private val BYTE3 = "b011".U(3.W) 56 private val BYTE4 = "b100".U(3.W) 57 private val BYTE5 = "b101".U(3.W) 58 private val BYTE6 = "b110".U(3.W) 59 private val BYTE7 = "b111".U(3.W) 60 61 def getMask(sizeEncode: UInt) = LookupTree(sizeEncode, List( 62 SB -> 0x1.U, 63 SH -> 0x3.U, 64 SW -> 0xf.U, 65 SD -> 0xff.U 66 )) 67 68 def selectOldest[T <: LsPipelineBundle](valid: Seq[Bool], bits: Seq[T], index: Seq[UInt]): (Seq[Bool], Seq[T], Seq[UInt]) = { 69 assert(valid.length == bits.length) 70 if (valid.length == 0 || valid.length == 1) { 71 (valid, bits, index) 72 } else if (valid.length == 2) { 73 val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0))))) 74 val resIndex = Seq.fill(2)(Wire(chiselTypeOf(index(0)))) 75 for (i <- res.indices) { 76 res(i).valid := valid(i) 77 res(i).bits := bits(i) 78 resIndex(i) := index(i) 79 } 80 val oldest = Mux(valid(0) && valid(1), 81 Mux(isAfter(bits(0).uop.robIdx, bits(1).uop.robIdx) || 82 (isNotBefore(bits(0).uop.robIdx, bits(1).uop.robIdx) && bits(0).uop.uopIdx > bits(1).uop.uopIdx), res(1), res(0)), 83 Mux(valid(0) && !valid(1), res(0), res(1))) 84 85 val oldestIndex = Mux(valid(0) && valid(1), 86 Mux(isAfter(bits(0).uop.robIdx, bits(1).uop.robIdx) || 87 (bits(0).uop.robIdx === bits(1).uop.robIdx && bits(0).uop.uopIdx > bits(1).uop.uopIdx), resIndex(1), resIndex(0)), 88 Mux(valid(0) && !valid(1), resIndex(0), resIndex(1))) 89 (Seq(oldest.valid), Seq(oldest.bits), Seq(oldestIndex)) 90 } else { 91 val left = selectOldest(valid.take(valid.length / 2), bits.take(bits.length / 2), index.take(index.length / 2)) 92 val right = selectOldest(valid.takeRight(valid.length - (valid.length / 2)), bits.takeRight(bits.length - (bits.length / 2)), index.takeRight(index.length - (index.length / 2))) 93 selectOldest(left._1 ++ right._1, left._2 ++ right._2, left._3 ++ right._3) 94 } 95 } 96 97 val io = IO(new Bundle() { 98 val redirect = Flipped(Valid(new Redirect)) 99 val enq = Vec(enqPortNum, Flipped(new MisalignBufferEnqIO)) 100 val rob = Flipped(new RobLsqIO) 101 val splitStoreReq = Decoupled(new LsPipelineBundle) 102 val splitStoreResp = Flipped(Valid(new SqWriteBundle)) 103 val writeBack = Decoupled(new MemExuOutput) 104 val vecWriteBack = Vec(VecStorePipelineWidth, Decoupled(new VecPipelineFeedbackIO(isVStore = true))) 105 val storeOutValid = Input(Bool()) 106 val storeVecOutValid = Input(Bool()) 107 val overwriteExpBuf = Output(new XSBundle { 108 val valid = Bool() 109 val vaddr = UInt(XLEN.W) 110 val isHyper = Bool() 111 val gpaddr = UInt(XLEN.W) 112 val isForVSnonLeafPTE = Bool() 113 }) 114 val sqControl = new StoreMaBufToSqControlIO 115 116 val toVecStoreMergeBuffer = Vec(VecStorePipelineWidth, new StoreMaBufToVecStoreMergeBufferIO) 117 val full = Bool() 118 }) 119 120 io.rob.mmio := 0.U.asTypeOf(Vec(LoadPipelineWidth, Bool())) 121 io.rob.uop := 0.U.asTypeOf(Vec(LoadPipelineWidth, new DynInst)) 122 123 class StoreMisalignBufferEntry(implicit p: Parameters) extends LsPipelineBundle { 124 val portIndex = UInt(log2Up(enqPortNum).W) 125 } 126 val req_valid = RegInit(false.B) 127 val req = Reg(new StoreMisalignBufferEntry) 128 129 val cross4KBPageBoundary = Wire(Bool()) 130 val needFlushPipe = RegInit(false.B) 131 132 // buffer control: 133 // - s_idle: Idle 134 // - s_split: Split miss-aligned store into aligned stores 135 // - s_req: Send split store to sta and get result from sta 136 // - s_resp: Responds to a split store access request 137 // - s_wb: writeback yo rob/vecMergeBuffer 138 // - s_block: Wait for this instr to reach the head of Rob. 139 val s_idle :: s_split :: s_req :: s_resp :: s_wb :: s_block :: Nil = Enum(6) 140 val bufferState = RegInit(s_idle) 141 142 // enqueue 143 // s1: 144 val s1_req = VecInit(io.enq.map(_.req.bits)) 145 val s1_valid = VecInit(io.enq.map(x => x.req.valid)) 146 147 val s1_index = (0 until io.enq.length).map(_.asUInt) 148 val reqSel = selectOldest(s1_valid, s1_req, s1_index) 149 150 val reqSelValid = reqSel._1(0) 151 val reqSelBits = reqSel._2(0) 152 val reqSelPort = reqSel._3(0) 153 154 val reqRedirect = reqSelBits.uop.robIdx.needFlush(io.redirect) 155 156 val canEnq = !req_valid && !reqRedirect && reqSelValid 157 val robMatch = req_valid && io.rob.pendingst && (io.rob.pendingPtr === req.uop.robIdx) 158 159 val s2_canEnq = GatedRegNext(canEnq) 160 val s2_reqSelPort = GatedRegNext(reqSelPort) 161 val misalign_can_split = Wire(Bool()) 162 misalign_can_split := Mux(s2_canEnq, (0 until enqPortNum).map { 163 case i => !io.enq(i).revoke && s2_reqSelPort === i.U 164 }.reduce(_|_), GatedRegNext(misalign_can_split)) 165 166 when(canEnq) { 167 connectSamePort(req, reqSelBits) 168 req.portIndex := reqSelPort 169 req_valid := true.B 170 } 171 val cross4KBPageEnq = WireInit(false.B) 172 when (cross4KBPageBoundary && !reqRedirect) { 173 when( 174 reqSelValid && 175 (isAfter(req.uop.robIdx, reqSelBits.uop.robIdx) || (isNotBefore(req.uop.robIdx, reqSelBits.uop.robIdx) && req.uop.uopIdx > reqSelBits.uop.uopIdx)) && 176 bufferState === s_idle 177 ) { 178 connectSamePort(req, reqSelBits) 179 req.portIndex := reqSelPort 180 cross4KBPageEnq := true.B 181 needFlushPipe := true.B 182 } .otherwise { 183 req := req 184 cross4KBPageEnq := false.B 185 } 186 } 187 188 val reqSelCanEnq = UIntToOH(reqSelPort) 189 190 io.enq.zipWithIndex.map{ 191 case (reqPort, index) => reqPort.req.ready := reqSelCanEnq(index) && (!req_valid || cross4KBPageBoundary && cross4KBPageEnq) 192 } 193 194 io.toVecStoreMergeBuffer.zipWithIndex.map{ 195 case (toStMB, index) => { 196 toStMB.flush := req_valid && cross4KBPageBoundary && cross4KBPageEnq && UIntToOH(req.portIndex)(index) 197 toStMB.mbIndex := req.mbIndex 198 } 199 } 200 io.full := req_valid 201 202 //logic 203 val splitStoreReqs = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new LsPipelineBundle)))) 204 val splitStoreResp = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new SqWriteBundle)))) 205 val isCrossPage = RegInit(false.B) 206 val exceptionVec = RegInit(0.U.asTypeOf(ExceptionVec())) 207 val unSentStores = RegInit(0.U(maxSplitNum.W)) 208 val unWriteStores = RegInit(0.U(maxSplitNum.W)) 209 val curPtr = RegInit(0.U(log2Ceil(maxSplitNum).W)) 210 211 // if there is exception or mmio in split store 212 val globalException = RegInit(false.B) 213 val globalUncache = RegInit(false.B) 214 215 // debug info 216 val globalMMIO = RegInit(false.B) 217 val globalNC = RegInit(false.B) 218 219 val hasException = io.splitStoreResp.bits.vecActive && !io.splitStoreResp.bits.need_rep && 220 ExceptionNO.selectByFu(io.splitStoreResp.bits.uop.exceptionVec, StaCfg).asUInt.orR || TriggerAction.isDmode(io.splitStoreResp.bits.uop.trigger) 221 val isUncache = (io.splitStoreResp.bits.mmio || io.splitStoreResp.bits.nc) && !io.splitStoreResp.bits.need_rep 222 223 io.sqControl.toStoreQueue.crossPageWithHit := io.sqControl.toStoreMisalignBuffer.sqPtr === req.uop.sqIdx && isCrossPage 224 io.sqControl.toStoreQueue.crossPageCanDeq := !isCrossPage || bufferState === s_block 225 io.sqControl.toStoreQueue.paddr := Cat(splitStoreResp(1).paddr(splitStoreResp(1).paddr.getWidth - 1, 3), 0.U(3.W)) 226 227 io.sqControl.toStoreQueue.withSameUop := io.sqControl.toStoreMisalignBuffer.uop.robIdx === req.uop.robIdx && io.sqControl.toStoreMisalignBuffer.uop.uopIdx === req.uop.uopIdx && req.isvec && robMatch && isCrossPage 228 229 //state transition 230 switch(bufferState) { 231 is (s_idle) { 232 when(cross4KBPageBoundary && misalign_can_split) { 233 when(robMatch) { 234 bufferState := s_split 235 isCrossPage := true.B 236 } 237 } .otherwise { 238 when (req_valid && misalign_can_split) { 239 bufferState := s_split 240 isCrossPage := false.B 241 } 242 } 243 } 244 245 is (s_split) { 246 bufferState := s_req 247 } 248 249 is (s_req) { 250 when (io.splitStoreReq.fire) { 251 bufferState := s_resp 252 } 253 } 254 255 is (s_resp) { 256 when (io.splitStoreResp.valid) { 257 val clearOh = UIntToOH(curPtr) 258 when (hasException || isUncache) { 259 // commit directly when exception ocurs 260 // if any split store reaches mmio space, delegate to software storeAddrMisaligned exception 261 bufferState := s_wb 262 globalException := hasException 263 globalUncache := isUncache 264 globalMMIO := io.splitStoreResp.bits.mmio 265 globalNC := io.splitStoreResp.bits.nc 266 } .elsewhen(io.splitStoreResp.bits.need_rep || (unSentStores & (~clearOh).asUInt).orR) { 267 // need replay or still has unsent requests 268 bufferState := s_req 269 } .otherwise { 270 // got result, goto calculate data and control sq 271 bufferState := s_wb 272 } 273 } 274 } 275 276 is (s_wb) { 277 when (req.isvec) { 278 when (io.vecWriteBack.map(x => x.fire).reduce( _ || _)) { 279 bufferState := s_idle 280 req_valid := false.B 281 curPtr := 0.U 282 unSentStores := 0.U 283 unWriteStores := 0.U 284 globalException := false.B 285 globalUncache := false.B 286 isCrossPage := false.B 287 needFlushPipe := false.B 288 289 globalMMIO := false.B 290 globalNC := false.B 291 } 292 293 }.otherwise { 294 when (io.writeBack.fire && (!isCrossPage || globalUncache || globalException)) { 295 bufferState := s_idle 296 req_valid := false.B 297 curPtr := 0.U 298 unSentStores := 0.U 299 unWriteStores := 0.U 300 globalException := false.B 301 globalUncache := false.B 302 isCrossPage := false.B 303 needFlushPipe := false.B 304 305 globalMMIO := false.B 306 globalNC := false.B 307 } .elsewhen(io.writeBack.fire && isCrossPage) { 308 bufferState := s_block 309 } .otherwise { 310 bufferState := s_wb 311 } 312 313 } 314 } 315 316 is (s_block) { 317 when (io.sqControl.toStoreMisalignBuffer.doDeq) { 318 bufferState := s_idle 319 req_valid := false.B 320 curPtr := 0.U 321 unSentStores := 0.U 322 unWriteStores := 0.U 323 globalException := false.B 324 globalUncache := false.B 325 isCrossPage := false.B 326 needFlushPipe := false.B 327 328 globalMMIO := false.B 329 globalNC := false.B 330 } 331 } 332 } 333 334 val alignedType = Mux(req.isvec, req.alignedType(1,0), req.uop.fuOpType(1, 0)) 335 336 val highAddress = LookupTree(alignedType, List( 337 SB -> 0.U, 338 SH -> 1.U, 339 SW -> 3.U, 340 SD -> 7.U 341 )) + req.vaddr(4, 0) 342 343 val highPageAddress = LookupTree(alignedType, List( 344 SB -> 0.U, 345 SH -> 1.U, 346 SW -> 3.U, 347 SD -> 7.U 348 )) + req.vaddr(12, 0) 349 // to see if (vaddr + opSize - 1) and vaddr are in the same 16 bytes region 350 val cross16BytesBoundary = req_valid && (highAddress(4) =/= req.vaddr(4)) 351 cross4KBPageBoundary := req_valid && (highPageAddress(12) =/= req.vaddr(12)) 352 val aligned16BytesAddr = (req.vaddr >> 4) << 4// req.vaddr & ~("b1111".U) 353 val aligned16BytesSel = req.vaddr(3, 0) 354 355 // meta of 128 bit store 356 val new128Store = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 357 // meta of split loads 358 val lowAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 359 val highAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 360 // final lowResult = Cat(`lowResultWidth` of store data, 0.U(make it to fill total length of Vlen)) 361 val lowResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 362 // final highResult = Zero extend to Vlen(`highResultWidth` of (store data >> lowResultWidth)) 363 val highResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 364 365 when (bufferState === s_split) { 366 when (!cross16BytesBoundary) { 367 assert(false.B, s"There should be no non-aligned access that does not cross 16Byte boundaries.") 368 } .otherwise { 369 // split this unaligned store into `maxSplitNum` aligned stores 370 unWriteStores := Fill(maxSplitNum, 1.U(1.W)) 371 unSentStores := Fill(maxSplitNum, 1.U(1.W)) 372 curPtr := 0.U 373 lowAddrStore.uop := req.uop 374 lowAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 375 highAddrStore.uop := req.uop 376 highAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 377 378 switch (alignedType(1, 0)) { 379 is (SB) { 380 assert(false.B, "lb should not trigger miss align") 381 } 382 383 is (SH) { 384 lowAddrStore.uop.fuOpType := SB 385 lowAddrStore.vaddr := req.vaddr 386 lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 387 lowResultWidth := BYTE1 388 389 highAddrStore.uop.fuOpType := SB 390 highAddrStore.vaddr := req.vaddr + 1.U 391 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 392 highResultWidth := BYTE1 393 } 394 395 is (SW) { 396 switch (req.vaddr(1, 0)) { 397 is ("b00".U) { 398 assert(false.B, "should not trigger miss align") 399 } 400 401 is ("b01".U) { 402 lowAddrStore.uop.fuOpType := SW 403 lowAddrStore.vaddr := req.vaddr - 1.U 404 lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 405 lowResultWidth := BYTE3 406 407 highAddrStore.uop.fuOpType := SB 408 highAddrStore.vaddr := req.vaddr + 3.U 409 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 410 highResultWidth := BYTE1 411 } 412 413 is ("b10".U) { 414 lowAddrStore.uop.fuOpType := SH 415 lowAddrStore.vaddr := req.vaddr 416 lowAddrStore.mask := 0x3.U << lowAddrStore.vaddr(3, 0) 417 lowResultWidth := BYTE2 418 419 highAddrStore.uop.fuOpType := SH 420 highAddrStore.vaddr := req.vaddr + 2.U 421 highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 422 highResultWidth := BYTE2 423 } 424 425 is ("b11".U) { 426 lowAddrStore.uop.fuOpType := SB 427 lowAddrStore.vaddr := req.vaddr 428 lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 429 lowResultWidth := BYTE1 430 431 highAddrStore.uop.fuOpType := SW 432 highAddrStore.vaddr := req.vaddr + 1.U 433 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 434 highResultWidth := BYTE3 435 } 436 } 437 } 438 439 is (SD) { 440 switch (req.vaddr(2, 0)) { 441 is ("b000".U) { 442 assert(false.B, "should not trigger miss align") 443 } 444 445 is ("b001".U) { 446 lowAddrStore.uop.fuOpType := SD 447 lowAddrStore.vaddr := req.vaddr - 1.U 448 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 449 lowResultWidth := BYTE7 450 451 highAddrStore.uop.fuOpType := SB 452 highAddrStore.vaddr := req.vaddr + 7.U 453 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 454 highResultWidth := BYTE1 455 } 456 457 is ("b010".U) { 458 lowAddrStore.uop.fuOpType := SD 459 lowAddrStore.vaddr := req.vaddr - 2.U 460 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 461 lowResultWidth := BYTE6 462 463 highAddrStore.uop.fuOpType := SH 464 highAddrStore.vaddr := req.vaddr + 6.U 465 highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 466 highResultWidth := BYTE2 467 } 468 469 is ("b011".U) { 470 lowAddrStore.uop.fuOpType := SD 471 lowAddrStore.vaddr := req.vaddr - 3.U 472 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 473 lowResultWidth := BYTE5 474 475 highAddrStore.uop.fuOpType := SW 476 highAddrStore.vaddr := req.vaddr + 5.U 477 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 478 highResultWidth := BYTE3 479 } 480 481 is ("b100".U) { 482 lowAddrStore.uop.fuOpType := SW 483 lowAddrStore.vaddr := req.vaddr 484 lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 485 lowResultWidth := BYTE4 486 487 highAddrStore.uop.fuOpType := SW 488 highAddrStore.vaddr := req.vaddr + 4.U 489 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 490 highResultWidth := BYTE4 491 } 492 493 is ("b101".U) { 494 lowAddrStore.uop.fuOpType := SD 495 lowAddrStore.vaddr := req.vaddr - 5.U 496 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 497 lowResultWidth := BYTE3 498 499 highAddrStore.uop.fuOpType := SD 500 highAddrStore.vaddr := req.vaddr + 3.U 501 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 502 highResultWidth := BYTE5 503 } 504 505 is ("b110".U) { 506 lowAddrStore.uop.fuOpType := SD 507 lowAddrStore.vaddr := req.vaddr - 6.U 508 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 509 lowResultWidth := BYTE2 510 511 highAddrStore.uop.fuOpType := SD 512 highAddrStore.vaddr := req.vaddr + 2.U 513 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 514 highResultWidth := BYTE6 515 } 516 517 is ("b111".U) { 518 lowAddrStore.uop.fuOpType := SD 519 lowAddrStore.vaddr := req.vaddr - 7.U 520 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 521 lowResultWidth := BYTE1 522 523 highAddrStore.uop.fuOpType := SD 524 highAddrStore.vaddr := req.vaddr + 1.U 525 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 526 highResultWidth := BYTE7 527 } 528 } 529 } 530 } 531 532 splitStoreReqs(0) := lowAddrStore 533 splitStoreReqs(1) := highAddrStore 534 } 535 } 536 537 io.splitStoreReq.valid := req_valid && (bufferState === s_req) 538 io.splitStoreReq.bits := splitStoreReqs(curPtr) 539 io.splitStoreReq.bits.isvec := req.isvec 540 // Restore the information of H extension store 541 // bit encoding: | hsv 1 | store 00 | size(2bit) | 542 val reqIsHsv = LSUOpType.isHsv(req.uop.fuOpType) 543 io.splitStoreReq.bits.uop.fuOpType := Mux(req.isvec, req.uop.fuOpType, Cat(reqIsHsv, 0.U(2.W), splitStoreReqs(curPtr).uop.fuOpType(1, 0))) 544 io.splitStoreReq.bits.alignedType := Mux(req.isvec, splitStoreReqs(curPtr).uop.fuOpType(1, 0), req.alignedType) 545 io.splitStoreReq.bits.isFinalSplit := curPtr(0) 546 547 when (io.splitStoreResp.valid) { 548 val resp = io.splitStoreResp.bits 549 splitStoreResp(curPtr) := io.splitStoreResp.bits 550 when (isUncache) { 551 unWriteStores := 0.U 552 unSentStores := 0.U 553 exceptionVec := ExceptionNO.selectByFu(0.U.asTypeOf(exceptionVec.cloneType), StaCfg) 554 // delegate to software 555 exceptionVec(storeAddrMisaligned) := true.B 556 } .elsewhen (hasException) { 557 unWriteStores := 0.U 558 unSentStores := 0.U 559 StaCfg.exceptionOut.map(no => exceptionVec(no) := exceptionVec(no) || resp.uop.exceptionVec(no)) 560 } .elsewhen (!io.splitStoreResp.bits.need_rep) { 561 unSentStores := unSentStores & (~UIntToOH(curPtr)).asUInt 562 curPtr := curPtr + 1.U 563 exceptionVec := 0.U.asTypeOf(ExceptionVec()) 564 } 565 } 566 567 val splitStoreData = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new XSBundle { 568 val wdata = UInt(VLEN.W) 569 val wmask = UInt((VLEN / 8).W) 570 })))) 571 572 val wmaskLow = Wire(Vec(VLEN / 8, Bool())) 573 val wmaskHigh = Wire(Vec(VLEN / 8, Bool())) 574 (0 until (VLEN / 8)).map { 575 case i => { 576 when (i.U < highResultWidth) { 577 wmaskHigh(i) := true.B 578 } .otherwise { 579 wmaskHigh(i) := false.B 580 } 581 when (i.U < lowResultWidth) { 582 wmaskLow(i) := true.B 583 } .otherwise { 584 wmaskLow(i) := false.B 585 } 586 } 587 } 588 589 io.writeBack.valid := req_valid && (bufferState === s_wb) && !io.storeOutValid && !req.isvec 590 io.writeBack.bits.uop := req.uop 591 io.writeBack.bits.uop.exceptionVec := DontCare 592 StaCfg.exceptionOut.map(no => io.writeBack.bits.uop.exceptionVec(no) := (globalUncache || globalException) && exceptionVec(no)) 593 io.writeBack.bits.uop.flushPipe := needFlushPipe 594 io.writeBack.bits.uop.replayInst := false.B 595 io.writeBack.bits.data := DontCare 596 io.writeBack.bits.isFromLoadUnit := DontCare 597 io.writeBack.bits.debug.isMMIO := globalMMIO 598 io.writeBack.bits.debug.isNC := globalNC 599 io.writeBack.bits.debug.isPerfCnt := false.B 600 io.writeBack.bits.debug.paddr := req.paddr 601 io.writeBack.bits.debug.vaddr := req.vaddr 602 603 io.vecWriteBack.zipWithIndex.map{ 604 case (wb, index) => { 605 wb.valid := req_valid && (bufferState === s_wb) && req.isvec && !io.storeVecOutValid && UIntToOH(req.portIndex)(index) 606 607 wb.bits.mBIndex := req.mbIndex 608 wb.bits.hit := true.B 609 wb.bits.isvec := true.B 610 wb.bits.sourceType := RSFeedbackType.tlbMiss 611 wb.bits.flushState := DontCare 612 wb.bits.trigger := TriggerAction.None 613 wb.bits.mmio := globalMMIO 614 wb.bits.exceptionVec := ExceptionNO.selectByFu(exceptionVec, VstuCfg) 615 wb.bits.hasException := globalException 616 wb.bits.usSecondInv := req.usSecondInv 617 wb.bits.vecFeedback := true.B 618 wb.bits.elemIdx := req.elemIdx 619 wb.bits.alignedType := req.alignedType 620 wb.bits.mask := req.mask 621 wb.bits.vaddr := req.vaddr 622 wb.bits.vaNeedExt := req.vaNeedExt 623 wb.bits.gpaddr := req.gpaddr 624 wb.bits.isForVSnonLeafPTE := req.isForVSnonLeafPTE 625 wb.bits.vstart := req.uop.vpu.vstart 626 wb.bits.vecTriggerMask := 0.U 627 wb.bits.nc := globalNC 628 } 629 } 630 631 val flush = req_valid && req.uop.robIdx.needFlush(io.redirect) 632 633 when (flush) { 634 bufferState := s_idle 635 req_valid := Mux(cross4KBPageEnq && cross4KBPageBoundary && !reqRedirect, req_valid, false.B) 636 curPtr := 0.U 637 unSentStores := 0.U 638 unWriteStores := 0.U 639 globalException := false.B 640 globalUncache := false.B 641 isCrossPage := false.B 642 needFlushPipe := false.B 643 644 globalMMIO := false.B 645 globalNC := false.B 646 } 647 648 // NOTE: spectial case (unaligned store cross page, page fault happens in next page) 649 // if exception happens in the higher page address part, overwrite the storeExceptionBuffer vaddr 650 val shouldOverwrite = req_valid && cross16BytesBoundary && globalException && (curPtr === 1.U) 651 val overwriteExpBuf = GatedValidRegNext(shouldOverwrite) 652 val overwriteVaddr = RegEnable(splitStoreResp(curPtr).vaddr, shouldOverwrite) 653 val overwriteIsHyper = RegEnable(splitStoreResp(curPtr).isHyper, shouldOverwrite) 654 val overwriteGpaddr = RegEnable(splitStoreResp(curPtr).gpaddr, shouldOverwrite) 655 val overwriteIsForVSnonLeafPTE = RegEnable(splitStoreResp(curPtr).isForVSnonLeafPTE, shouldOverwrite) 656 657 //TODO In theory, there is no need to overwrite, but for now, the signal is retained in the code in this way. 658 // and the signal will be removed after sufficient verification. 659 io.overwriteExpBuf.valid := false.B 660 io.overwriteExpBuf.vaddr := overwriteVaddr 661 io.overwriteExpBuf.isHyper := overwriteIsHyper 662 io.overwriteExpBuf.gpaddr := overwriteGpaddr 663 io.overwriteExpBuf.isForVSnonLeafPTE := overwriteIsForVSnonLeafPTE 664 665 XSPerfAccumulate("alloc", RegNext(!req_valid) && req_valid) 666 XSPerfAccumulate("flush", flush) 667 XSPerfAccumulate("flush_idle", flush && (bufferState === s_idle)) 668 XSPerfAccumulate("flush_non_idle", flush && (bufferState =/= s_idle)) 669} 670