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 globalMMIO = RegInit(false.B) 214 215 val hasException = io.splitStoreResp.bits.vecActive && !io.splitStoreResp.bits.need_rep && 216 ExceptionNO.selectByFu(io.splitStoreResp.bits.uop.exceptionVec, StaCfg).asUInt.orR || TriggerAction.isDmode(io.splitStoreResp.bits.uop.trigger) 217 val isMMIO = io.splitStoreResp.bits.mmio && !io.splitStoreResp.bits.need_rep 218 219 io.sqControl.toStoreQueue.crossPageWithHit := io.sqControl.toStoreMisalignBuffer.sqPtr === req.uop.sqIdx && isCrossPage 220 io.sqControl.toStoreQueue.crossPageCanDeq := !isCrossPage || bufferState === s_block 221 io.sqControl.toStoreQueue.paddr := Cat(splitStoreResp(1).paddr(splitStoreResp(1).paddr.getWidth - 1, 3), 0.U(3.W)) 222 223 io.sqControl.toStoreQueue.withSameUop := io.sqControl.toStoreMisalignBuffer.uop.robIdx === req.uop.robIdx && io.sqControl.toStoreMisalignBuffer.uop.uopIdx === req.uop.uopIdx && req.isvec && robMatch && isCrossPage 224 225 //state transition 226 switch(bufferState) { 227 is (s_idle) { 228 when(cross4KBPageBoundary && misalign_can_split) { 229 when(robMatch) { 230 bufferState := s_split 231 isCrossPage := true.B 232 } 233 } .otherwise { 234 when (req_valid && misalign_can_split) { 235 bufferState := s_split 236 isCrossPage := false.B 237 } 238 } 239 } 240 241 is (s_split) { 242 bufferState := s_req 243 } 244 245 is (s_req) { 246 when (io.splitStoreReq.fire) { 247 bufferState := s_resp 248 } 249 } 250 251 is (s_resp) { 252 when (io.splitStoreResp.valid) { 253 val clearOh = UIntToOH(curPtr) 254 when (hasException || isMMIO) { 255 // commit directly when exception ocurs 256 // if any split store reaches mmio space, delegate to software storeAddrMisaligned exception 257 bufferState := s_wb 258 globalException := hasException 259 globalMMIO := isMMIO 260 } .elsewhen(io.splitStoreResp.bits.need_rep || (unSentStores & (~clearOh).asUInt).orR) { 261 // need replay or still has unsent requests 262 bufferState := s_req 263 } .otherwise { 264 // got result, goto calculate data and control sq 265 bufferState := s_wb 266 } 267 } 268 } 269 270 is (s_wb) { 271 when (req.isvec) { 272 when (io.vecWriteBack.map(x => x.fire).reduce( _ || _)) { 273 bufferState := s_idle 274 req_valid := false.B 275 curPtr := 0.U 276 unSentStores := 0.U 277 unWriteStores := 0.U 278 globalException := false.B 279 globalMMIO := false.B 280 isCrossPage := false.B 281 needFlushPipe := false.B 282 } 283 284 }.otherwise { 285 when (io.writeBack.fire && (!isCrossPage || globalMMIO || globalException)) { 286 bufferState := s_idle 287 req_valid := false.B 288 curPtr := 0.U 289 unSentStores := 0.U 290 unWriteStores := 0.U 291 globalException := false.B 292 globalMMIO := false.B 293 isCrossPage := false.B 294 needFlushPipe := false.B 295 } .elsewhen(io.writeBack.fire && isCrossPage) { 296 bufferState := s_block 297 } .otherwise { 298 bufferState := s_wb 299 } 300 301 } 302 } 303 304 is (s_block) { 305 when (io.sqControl.toStoreMisalignBuffer.doDeq) { 306 bufferState := s_idle 307 req_valid := false.B 308 curPtr := 0.U 309 unSentStores := 0.U 310 unWriteStores := 0.U 311 globalException := false.B 312 globalMMIO := false.B 313 isCrossPage := false.B 314 } 315 } 316 } 317 318 val alignedType = Mux(req.isvec, req.alignedType(1,0), req.uop.fuOpType(1, 0)) 319 320 val highAddress = LookupTree(alignedType, List( 321 SB -> 0.U, 322 SH -> 1.U, 323 SW -> 3.U, 324 SD -> 7.U 325 )) + req.vaddr(4, 0) 326 327 val highPageAddress = LookupTree(alignedType, List( 328 SB -> 0.U, 329 SH -> 1.U, 330 SW -> 3.U, 331 SD -> 7.U 332 )) + req.vaddr(12, 0) 333 // to see if (vaddr + opSize - 1) and vaddr are in the same 16 bytes region 334 val cross16BytesBoundary = req_valid && (highAddress(4) =/= req.vaddr(4)) 335 cross4KBPageBoundary := req_valid && (highPageAddress(12) =/= req.vaddr(12)) 336 val aligned16BytesAddr = (req.vaddr >> 4) << 4// req.vaddr & ~("b1111".U) 337 val aligned16BytesSel = req.vaddr(3, 0) 338 339 // meta of 128 bit store 340 val new128Store = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 341 // meta of split loads 342 val lowAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 343 val highAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 344 // final lowResult = Cat(`lowResultWidth` of store data, 0.U(make it to fill total length of Vlen)) 345 val lowResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 346 // final highResult = Zero extend to Vlen(`highResultWidth` of (store data >> lowResultWidth)) 347 val highResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 348 349 when (bufferState === s_split) { 350 when (!cross16BytesBoundary) { 351 assert(false.B, s"There should be no non-aligned access that does not cross 16Byte boundaries.") 352 } .otherwise { 353 // split this unaligned store into `maxSplitNum` aligned stores 354 unWriteStores := Fill(maxSplitNum, 1.U(1.W)) 355 unSentStores := Fill(maxSplitNum, 1.U(1.W)) 356 curPtr := 0.U 357 lowAddrStore.uop := req.uop 358 lowAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 359 highAddrStore.uop := req.uop 360 highAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 361 362 switch (alignedType(1, 0)) { 363 is (SB) { 364 assert(false.B, "lb should not trigger miss align") 365 } 366 367 is (SH) { 368 lowAddrStore.uop.fuOpType := SB 369 lowAddrStore.vaddr := req.vaddr 370 lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 371 lowResultWidth := BYTE1 372 373 highAddrStore.uop.fuOpType := SB 374 highAddrStore.vaddr := req.vaddr + 1.U 375 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 376 highResultWidth := BYTE1 377 } 378 379 is (SW) { 380 switch (req.vaddr(1, 0)) { 381 is ("b00".U) { 382 assert(false.B, "should not trigger miss align") 383 } 384 385 is ("b01".U) { 386 lowAddrStore.uop.fuOpType := SW 387 lowAddrStore.vaddr := req.vaddr - 1.U 388 lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 389 lowResultWidth := BYTE3 390 391 highAddrStore.uop.fuOpType := SB 392 highAddrStore.vaddr := req.vaddr + 3.U 393 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 394 highResultWidth := BYTE1 395 } 396 397 is ("b10".U) { 398 lowAddrStore.uop.fuOpType := SH 399 lowAddrStore.vaddr := req.vaddr 400 lowAddrStore.mask := 0x3.U << lowAddrStore.vaddr(3, 0) 401 lowResultWidth := BYTE2 402 403 highAddrStore.uop.fuOpType := SH 404 highAddrStore.vaddr := req.vaddr + 2.U 405 highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 406 highResultWidth := BYTE2 407 } 408 409 is ("b11".U) { 410 lowAddrStore.uop.fuOpType := SB 411 lowAddrStore.vaddr := req.vaddr 412 lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 413 lowResultWidth := BYTE1 414 415 highAddrStore.uop.fuOpType := SW 416 highAddrStore.vaddr := req.vaddr + 1.U 417 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 418 highResultWidth := BYTE3 419 } 420 } 421 } 422 423 is (SD) { 424 switch (req.vaddr(2, 0)) { 425 is ("b000".U) { 426 assert(false.B, "should not trigger miss align") 427 } 428 429 is ("b001".U) { 430 lowAddrStore.uop.fuOpType := SD 431 lowAddrStore.vaddr := req.vaddr - 1.U 432 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 433 lowResultWidth := BYTE7 434 435 highAddrStore.uop.fuOpType := SB 436 highAddrStore.vaddr := req.vaddr + 7.U 437 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 438 highResultWidth := BYTE1 439 } 440 441 is ("b010".U) { 442 lowAddrStore.uop.fuOpType := SD 443 lowAddrStore.vaddr := req.vaddr - 2.U 444 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 445 lowResultWidth := BYTE6 446 447 highAddrStore.uop.fuOpType := SH 448 highAddrStore.vaddr := req.vaddr + 6.U 449 highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 450 highResultWidth := BYTE2 451 } 452 453 is ("b011".U) { 454 lowAddrStore.uop.fuOpType := SD 455 lowAddrStore.vaddr := req.vaddr - 3.U 456 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 457 lowResultWidth := BYTE5 458 459 highAddrStore.uop.fuOpType := SW 460 highAddrStore.vaddr := req.vaddr + 5.U 461 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 462 highResultWidth := BYTE3 463 } 464 465 is ("b100".U) { 466 lowAddrStore.uop.fuOpType := SW 467 lowAddrStore.vaddr := req.vaddr 468 lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 469 lowResultWidth := BYTE4 470 471 highAddrStore.uop.fuOpType := SW 472 highAddrStore.vaddr := req.vaddr + 4.U 473 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 474 highResultWidth := BYTE4 475 } 476 477 is ("b101".U) { 478 lowAddrStore.uop.fuOpType := SD 479 lowAddrStore.vaddr := req.vaddr - 5.U 480 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 481 lowResultWidth := BYTE3 482 483 highAddrStore.uop.fuOpType := SD 484 highAddrStore.vaddr := req.vaddr + 3.U 485 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 486 highResultWidth := BYTE5 487 } 488 489 is ("b110".U) { 490 lowAddrStore.uop.fuOpType := SD 491 lowAddrStore.vaddr := req.vaddr - 6.U 492 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 493 lowResultWidth := BYTE2 494 495 highAddrStore.uop.fuOpType := SD 496 highAddrStore.vaddr := req.vaddr + 2.U 497 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 498 highResultWidth := BYTE6 499 } 500 501 is ("b111".U) { 502 lowAddrStore.uop.fuOpType := SD 503 lowAddrStore.vaddr := req.vaddr - 7.U 504 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 505 lowResultWidth := BYTE1 506 507 highAddrStore.uop.fuOpType := SD 508 highAddrStore.vaddr := req.vaddr + 1.U 509 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 510 highResultWidth := BYTE7 511 } 512 } 513 } 514 } 515 516 splitStoreReqs(0) := lowAddrStore 517 splitStoreReqs(1) := highAddrStore 518 } 519 } 520 521 io.splitStoreReq.valid := req_valid && (bufferState === s_req) 522 io.splitStoreReq.bits := splitStoreReqs(curPtr) 523 io.splitStoreReq.bits.isvec := req.isvec 524 // Restore the information of H extension store 525 // bit encoding: | hsv 1 | store 00 | size(2bit) | 526 val reqIsHsv = LSUOpType.isHsv(req.uop.fuOpType) 527 io.splitStoreReq.bits.uop.fuOpType := Mux(req.isvec, req.uop.fuOpType, Cat(reqIsHsv, 0.U(2.W), splitStoreReqs(curPtr).uop.fuOpType(1, 0))) 528 io.splitStoreReq.bits.alignedType := Mux(req.isvec, splitStoreReqs(curPtr).uop.fuOpType(1, 0), req.alignedType) 529 io.splitStoreReq.bits.isFinalSplit := curPtr(0) 530 531 when (io.splitStoreResp.valid) { 532 val resp = io.splitStoreResp.bits 533 splitStoreResp(curPtr) := io.splitStoreResp.bits 534 when (isMMIO) { 535 unWriteStores := 0.U 536 unSentStores := 0.U 537 exceptionVec := ExceptionNO.selectByFu(0.U.asTypeOf(exceptionVec.cloneType), StaCfg) 538 // delegate to software 539 exceptionVec(storeAddrMisaligned) := true.B 540 } .elsewhen (hasException) { 541 unWriteStores := 0.U 542 unSentStores := 0.U 543 StaCfg.exceptionOut.map(no => exceptionVec(no) := exceptionVec(no) || resp.uop.exceptionVec(no)) 544 } .elsewhen (!io.splitStoreResp.bits.need_rep) { 545 unSentStores := unSentStores & (~UIntToOH(curPtr)).asUInt 546 curPtr := curPtr + 1.U 547 exceptionVec := 0.U.asTypeOf(ExceptionVec()) 548 } 549 } 550 551 val splitStoreData = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new XSBundle { 552 val wdata = UInt(VLEN.W) 553 val wmask = UInt((VLEN / 8).W) 554 })))) 555 556 val wmaskLow = Wire(Vec(VLEN / 8, Bool())) 557 val wmaskHigh = Wire(Vec(VLEN / 8, Bool())) 558 (0 until (VLEN / 8)).map { 559 case i => { 560 when (i.U < highResultWidth) { 561 wmaskHigh(i) := true.B 562 } .otherwise { 563 wmaskHigh(i) := false.B 564 } 565 when (i.U < lowResultWidth) { 566 wmaskLow(i) := true.B 567 } .otherwise { 568 wmaskLow(i) := false.B 569 } 570 } 571 } 572 573 io.writeBack.valid := req_valid && (bufferState === s_wb) && !io.storeOutValid && !req.isvec 574 io.writeBack.bits.uop := req.uop 575 io.writeBack.bits.uop.exceptionVec := DontCare 576 StaCfg.exceptionOut.map(no => io.writeBack.bits.uop.exceptionVec(no) := (globalMMIO || globalException) && exceptionVec(no)) 577 io.writeBack.bits.uop.flushPipe := needFlushPipe 578 io.writeBack.bits.uop.replayInst := false.B 579 io.writeBack.bits.data := DontCare 580 io.writeBack.bits.isFromLoadUnit := DontCare 581 io.writeBack.bits.debug.isMMIO := globalMMIO 582 // FIXME lyq: temporarily set to false 583 io.writeBack.bits.debug.isNC := false.B 584 io.writeBack.bits.debug.isPerfCnt := false.B 585 io.writeBack.bits.debug.paddr := req.paddr 586 io.writeBack.bits.debug.vaddr := req.vaddr 587 588 io.vecWriteBack.zipWithIndex.map{ 589 case (wb, index) => { 590 wb.valid := req_valid && (bufferState === s_wb) && req.isvec && !io.storeVecOutValid && UIntToOH(req.portIndex)(index) 591 592 wb.bits.mBIndex := req.mbIndex 593 wb.bits.hit := true.B 594 wb.bits.isvec := true.B 595 wb.bits.sourceType := RSFeedbackType.tlbMiss 596 wb.bits.flushState := DontCare 597 wb.bits.trigger := TriggerAction.None 598 wb.bits.mmio := globalMMIO 599 wb.bits.exceptionVec := ExceptionNO.selectByFu(exceptionVec, VstuCfg) 600 wb.bits.hasException := globalException 601 wb.bits.usSecondInv := req.usSecondInv 602 wb.bits.vecFeedback := true.B 603 wb.bits.elemIdx := req.elemIdx 604 wb.bits.alignedType := req.alignedType 605 wb.bits.mask := req.mask 606 wb.bits.vaddr := req.vaddr 607 wb.bits.vaNeedExt := req.vaNeedExt 608 wb.bits.gpaddr := req.gpaddr 609 wb.bits.isForVSnonLeafPTE := req.isForVSnonLeafPTE 610 wb.bits.vstart := req.uop.vpu.vstart 611 wb.bits.vecTriggerMask := 0.U 612 wb.bits.nc := false.B 613 } 614 } 615 616 val flush = req_valid && req.uop.robIdx.needFlush(io.redirect) 617 618 when (flush) { 619 bufferState := s_idle 620 req_valid := Mux(cross4KBPageEnq && cross4KBPageBoundary && !reqRedirect, req_valid, false.B) 621 curPtr := 0.U 622 unSentStores := 0.U 623 unWriteStores := 0.U 624 globalException := false.B 625 globalMMIO := false.B 626 isCrossPage := false.B 627 needFlushPipe := false.B 628 } 629 630 // NOTE: spectial case (unaligned store cross page, page fault happens in next page) 631 // if exception happens in the higher page address part, overwrite the storeExceptionBuffer vaddr 632 val shouldOverwrite = req_valid && cross16BytesBoundary && globalException && (curPtr === 1.U) 633 val overwriteExpBuf = GatedValidRegNext(shouldOverwrite) 634 val overwriteVaddr = RegEnable(splitStoreResp(curPtr).vaddr, shouldOverwrite) 635 val overwriteIsHyper = RegEnable(splitStoreResp(curPtr).isHyper, shouldOverwrite) 636 val overwriteGpaddr = RegEnable(splitStoreResp(curPtr).gpaddr, shouldOverwrite) 637 val overwriteIsForVSnonLeafPTE = RegEnable(splitStoreResp(curPtr).isForVSnonLeafPTE, shouldOverwrite) 638 639 //TODO In theory, there is no need to overwrite, but for now, the signal is retained in the code in this way. 640 // and the signal will be removed after sufficient verification. 641 io.overwriteExpBuf.valid := false.B 642 io.overwriteExpBuf.vaddr := overwriteVaddr 643 io.overwriteExpBuf.isHyper := overwriteIsHyper 644 io.overwriteExpBuf.gpaddr := overwriteGpaddr 645 io.overwriteExpBuf.isForVSnonLeafPTE := overwriteIsForVSnonLeafPTE 646 647 XSPerfAccumulate("alloc", RegNext(!req_valid) && req_valid) 648 XSPerfAccumulate("flush", flush) 649 XSPerfAccumulate("flush_idle", flush && (bufferState === s_idle)) 650 XSPerfAccumulate("flush_non_idle", flush && (bufferState =/= s_idle)) 651} 652