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.fu.FuConfig._ 26import xiangshan.backend.fu.fpu.FPU 27import xiangshan.backend.rob.RobLsqIO 28import xiangshan.cache._ 29import xiangshan.frontend.FtqPtr 30import xiangshan.ExceptionNO._ 31import xiangshan.cache.wpu.ReplayCarry 32import xiangshan.backend.rob.RobPtr 33import xiangshan.backend.Bundles.{MemExuOutput, DynInst} 34 35class StoreMisalignBuffer(implicit p: Parameters) extends XSModule 36 with HasCircularQueuePtrHelper 37{ 38 private val enqPortNum = StorePipelineWidth 39 private val maxSplitNum = 2 40 41 require(maxSplitNum == 2) 42 43 private val SB = "b00".U(2.W) 44 private val SH = "b01".U(2.W) 45 private val SW = "b10".U(2.W) 46 private val SD = "b11".U(2.W) 47 48 // encode of how many bytes to shift or truncate 49 private val BYTE0 = "b000".U(3.W) 50 private val BYTE1 = "b001".U(3.W) 51 private val BYTE2 = "b010".U(3.W) 52 private val BYTE3 = "b011".U(3.W) 53 private val BYTE4 = "b100".U(3.W) 54 private val BYTE5 = "b101".U(3.W) 55 private val BYTE6 = "b110".U(3.W) 56 private val BYTE7 = "b111".U(3.W) 57 58 def getMask(sizeEncode: UInt) = LookupTree(sizeEncode, List( 59 SB -> 0x1.U, 60 SH -> 0x3.U, 61 SW -> 0xf.U, 62 SD -> 0xff.U 63 )) 64 65 def selectOldest[T <: LsPipelineBundle](valid: Seq[Bool], bits: Seq[T]): (Seq[Bool], Seq[T]) = { 66 assert(valid.length == bits.length) 67 if (valid.length == 0 || valid.length == 1) { 68 (valid, bits) 69 } else if (valid.length == 2) { 70 val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0))))) 71 for (i <- res.indices) { 72 res(i).valid := valid(i) 73 res(i).bits := bits(i) 74 } 75 val oldest = Mux(valid(0) && valid(1), 76 Mux(isAfter(bits(0).uop.robIdx, bits(1).uop.robIdx) || 77 (isNotBefore(bits(0).uop.robIdx, bits(1).uop.robIdx) && bits(0).uop.uopIdx > bits(1).uop.uopIdx), res(1), res(0)), 78 Mux(valid(0) && !valid(1), res(0), res(1))) 79 (Seq(oldest.valid), Seq(oldest.bits)) 80 } else { 81 val left = selectOldest(valid.take(valid.length / 2), bits.take(bits.length / 2)) 82 val right = selectOldest(valid.takeRight(valid.length - (valid.length / 2)), bits.takeRight(bits.length - (bits.length / 2))) 83 selectOldest(left._1 ++ right._1, left._2 ++ right._2) 84 } 85 } 86 87 val io = IO(new Bundle() { 88 val redirect = Flipped(Valid(new Redirect)) 89 val req = Vec(enqPortNum, Flipped(Valid(new LsPipelineBundle))) 90 val rob = Flipped(new RobLsqIO) 91 val splitStoreReq = Decoupled(new LsPipelineBundle) 92 val splitStoreResp = Flipped(Valid(new SqWriteBundle)) 93 val writeBack = Decoupled(new MemExuOutput) 94 val overwriteExpBuf = Output(new XSBundle { 95 val valid = Bool() 96 val vaddr = UInt(VAddrBits.W) 97 }) 98 val sqControl = new StoreMaBufToSqControlIO 99 }) 100 101 io.rob.mmio := 0.U.asTypeOf(Vec(LoadPipelineWidth, Bool())) 102 io.rob.uop := 0.U.asTypeOf(Vec(LoadPipelineWidth, new DynInst)) 103 104 val req_valid = RegInit(false.B) 105 val req = Reg(new LsPipelineBundle) 106 107 // enqueue 108 // s1: 109 val s1_req = VecInit(io.req.map(_.bits)) 110 val s1_valid = VecInit(io.req.map(x => x.valid)) 111 112 // s2: delay 1 cycle 113 val s2_req = RegNext(s1_req) 114 val s2_valid = (0 until enqPortNum).map(i => 115 RegNext(s1_valid(i)) && 116 !s2_req(i).uop.robIdx.needFlush(RegNext(io.redirect)) && 117 !s2_req(i).uop.robIdx.needFlush(io.redirect) 118 ) 119 val s2_miss_aligned = s2_req.map(x => 120 x.uop.exceptionVec(storeAddrMisaligned) && !x.uop.exceptionVec(breakPoint) && !TriggerAction.isDmode(x.uop.trigger) 121 ) 122 123 val s2_enqueue = Wire(Vec(enqPortNum, Bool())) 124 for (w <- 0 until enqPortNum) { 125 s2_enqueue(w) := s2_valid(w) && s2_miss_aligned(w) 126 } 127 128 when (req_valid && req.uop.robIdx.needFlush(io.redirect)) { 129 req_valid := s2_enqueue.asUInt.orR 130 } .elsewhen (s2_enqueue.asUInt.orR) { 131 req_valid := req_valid || true.B 132 } 133 134 val reqSel = selectOldest(s2_enqueue, s2_req) 135 136 when (req_valid) { 137 req := Mux( 138 reqSel._1(0) && (isAfter(req.uop.robIdx, reqSel._2(0).uop.robIdx) || (isNotBefore(req.uop.robIdx, reqSel._2(0).uop.robIdx) && req.uop.uopIdx > reqSel._2(0).uop.uopIdx)), 139 reqSel._2(0), 140 req) 141 } .elsewhen (s2_enqueue.asUInt.orR) { 142 req := reqSel._2(0) 143 } 144 145 val robMatch = req_valid && io.rob.pendingst && (io.rob.pendingPtr === req.uop.robIdx) 146 147 // buffer control: 148 // - split miss-aligned store into aligned stores 149 // - send split store to sta and get result from sta 150 // - control sq write to sb 151 // - control sq write this store back 152 val s_idle :: s_split :: s_req :: s_resp :: s_cal :: s_sq_req :: s_wb :: s_wait :: Nil = Enum(8) 153 val bufferState = RegInit(s_idle) 154 val splitStoreReqs = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new LsPipelineBundle)))) 155 val splitStoreResp = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new SqWriteBundle)))) 156 val unSentStores = RegInit(0.U(maxSplitNum.W)) 157 val unWriteStores = RegInit(0.U(maxSplitNum.W)) 158 val curPtr = RegInit(0.U(log2Ceil(maxSplitNum).W)) 159 160 // if there is exception or mmio in split store 161 val globalException = RegInit(false.B) 162 val globalMMIO = RegInit(false.B) 163 164 val hasException = ExceptionNO.selectByFu(io.splitStoreResp.bits.uop.exceptionVec, StaCfg).asUInt.orR && !io.splitStoreResp.bits.need_rep 165 val isMMIO = io.splitStoreResp.bits.mmio && !io.splitStoreResp.bits.need_rep 166 167 switch(bufferState) { 168 is (s_idle) { 169 when (robMatch) { 170 bufferState := s_split 171 } 172 } 173 174 is (s_split) { 175 bufferState := s_req 176 } 177 178 is (s_req) { 179 when (io.splitStoreReq.fire) { 180 bufferState := s_resp 181 } 182 } 183 184 is (s_resp) { 185 when (io.splitStoreResp.valid) { 186 val clearOh = UIntToOH(curPtr) 187 when (hasException || isMMIO) { 188 // commit directly when exception ocurs 189 // if any split store reaches mmio space, delegate to software storeAddrMisaligned exception 190 bufferState := s_wb 191 globalException := hasException 192 globalMMIO := isMMIO 193 } .elsewhen(io.splitStoreResp.bits.need_rep || (unSentStores & ~clearOh).orR) { 194 // need replay or still has unsent requests 195 bufferState := s_req 196 } .otherwise { 197 // got result, goto calculate data and control sq 198 bufferState := s_cal 199 } 200 } 201 } 202 203 is (s_cal) { 204 when (io.sqControl.storeInfo.dataReady) { 205 bufferState := s_sq_req 206 curPtr := 0.U 207 } 208 } 209 210 is (s_sq_req) { 211 when (io.sqControl.storeInfo.completeSbTrans) { 212 when (!((unWriteStores & ~UIntToOH(curPtr)).orR)) { 213 bufferState := s_wb 214 } 215 } 216 } 217 218 is (s_wb) { 219 when (io.writeBack.fire) { 220 bufferState := s_wait 221 } 222 } 223 224 is (s_wait) { 225 when (io.rob.scommit =/= 0.U || req.uop.robIdx.needFlush(io.redirect)) { 226 // rob commits the unaligned store or handled the exception, reset all state 227 bufferState := s_idle 228 req_valid := false.B 229 curPtr := 0.U 230 unSentStores := 0.U 231 unWriteStores := 0.U 232 globalException := false.B 233 globalMMIO := false.B 234 } 235 } 236 } 237 238 val highAddress = LookupTree(req.uop.fuOpType(1, 0), List( 239 SB -> 0.U, 240 SH -> 1.U, 241 SW -> 3.U, 242 SD -> 7.U 243 )) + req.vaddr(4, 0) 244 // to see if (vaddr + opSize - 1) and vaddr are in the same 16 bytes region 245 val cross16BytesBoundary = req_valid && (highAddress(4) =/= req.vaddr(4)) 246 val aligned16BytesAddr = (req.vaddr >> 4) << 4// req.vaddr & ~("b1111".U) 247 val aligned16BytesSel = req.vaddr(3, 0) 248 249 // meta of 128 bit store 250 val new128Store = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 251 // meta of split loads 252 val lowAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 253 val highAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 254 // final lowResult = Cat(`lowResultWidth` of store data, 0.U(make it to fill total length of Vlen)) 255 val lowResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 256 // final highResult = Zero extend to Vlen(`highResultWidth` of (store data >> lowResultWidth)) 257 val highResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 258 259 when (bufferState === s_split) { 260 when (!cross16BytesBoundary) { 261 // change this unaligned store into a 128 bits store 262 unWriteStores := 1.U 263 unSentStores := 1.U 264 curPtr := 0.U 265 new128Store.vaddr := aligned16BytesAddr 266 // new128Store.mask := (getMask(req.uop.fuOpType(1, 0)) << aligned16BytesSel).asUInt 267 new128Store.mask := 0xffff.U 268 new128Store.uop := req.uop 269 new128Store.uop.exceptionVec(storeAddrMisaligned) := false.B 270 new128Store.is128bit := true.B 271 splitStoreReqs(0) := new128Store 272 } .otherwise { 273 // split this unaligned store into `maxSplitNum` aligned stores 274 unWriteStores := Fill(maxSplitNum, 1.U(1.W)) 275 unSentStores := Fill(maxSplitNum, 1.U(1.W)) 276 curPtr := 0.U 277 lowAddrStore.uop := req.uop 278 lowAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 279 highAddrStore.uop := req.uop 280 highAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 281 282 switch (req.uop.fuOpType(1, 0)) { 283 is (SB) { 284 assert(false.B, "lb should not trigger miss align") 285 } 286 287 is (SH) { 288 lowAddrStore.uop.fuOpType := SB 289 lowAddrStore.vaddr := req.vaddr 290 lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 291 lowResultWidth := BYTE1 292 293 highAddrStore.uop.fuOpType := SB 294 highAddrStore.vaddr := req.vaddr + 1.U 295 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 296 highResultWidth := BYTE1 297 } 298 299 is (SW) { 300 switch (req.vaddr(1, 0)) { 301 is ("b00".U) { 302 assert(false.B, "should not trigger miss align") 303 } 304 305 is ("b01".U) { 306 lowAddrStore.uop.fuOpType := SW 307 lowAddrStore.vaddr := req.vaddr - 1.U 308 lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 309 lowResultWidth := BYTE3 310 311 highAddrStore.uop.fuOpType := SB 312 highAddrStore.vaddr := req.vaddr + 3.U 313 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 314 highResultWidth := BYTE1 315 } 316 317 is ("b10".U) { 318 lowAddrStore.uop.fuOpType := SH 319 lowAddrStore.vaddr := req.vaddr 320 lowAddrStore.mask := 0x3.U << lowAddrStore.vaddr(3, 0) 321 lowResultWidth := BYTE2 322 323 highAddrStore.uop.fuOpType := SH 324 highAddrStore.vaddr := req.vaddr + 2.U 325 highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 326 highResultWidth := BYTE2 327 } 328 329 is ("b11".U) { 330 lowAddrStore.uop.fuOpType := SB 331 lowAddrStore.vaddr := req.vaddr 332 lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 333 lowResultWidth := BYTE1 334 335 highAddrStore.uop.fuOpType := SW 336 highAddrStore.vaddr := req.vaddr + 1.U 337 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 338 highResultWidth := BYTE3 339 } 340 } 341 } 342 343 is (SD) { 344 switch (req.vaddr(2, 0)) { 345 is ("b000".U) { 346 assert(false.B, "should not trigger miss align") 347 } 348 349 is ("b001".U) { 350 lowAddrStore.uop.fuOpType := SD 351 lowAddrStore.vaddr := req.vaddr - 1.U 352 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 353 lowResultWidth := BYTE7 354 355 highAddrStore.uop.fuOpType := SB 356 highAddrStore.vaddr := req.vaddr + 7.U 357 highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 358 highResultWidth := BYTE1 359 } 360 361 is ("b010".U) { 362 lowAddrStore.uop.fuOpType := SD 363 lowAddrStore.vaddr := req.vaddr - 2.U 364 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 365 lowResultWidth := BYTE6 366 367 highAddrStore.uop.fuOpType := SH 368 highAddrStore.vaddr := req.vaddr + 6.U 369 highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 370 highResultWidth := BYTE2 371 } 372 373 is ("b011".U) { 374 lowAddrStore.uop.fuOpType := SD 375 lowAddrStore.vaddr := req.vaddr - 3.U 376 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 377 lowResultWidth := BYTE5 378 379 highAddrStore.uop.fuOpType := SW 380 highAddrStore.vaddr := req.vaddr + 5.U 381 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 382 highResultWidth := BYTE3 383 } 384 385 is ("b100".U) { 386 lowAddrStore.uop.fuOpType := SW 387 lowAddrStore.vaddr := req.vaddr 388 lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 389 lowResultWidth := BYTE4 390 391 highAddrStore.uop.fuOpType := SW 392 highAddrStore.vaddr := req.vaddr + 4.U 393 highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 394 highResultWidth := BYTE4 395 } 396 397 is ("b101".U) { 398 lowAddrStore.uop.fuOpType := SD 399 lowAddrStore.vaddr := req.vaddr - 5.U 400 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 401 lowResultWidth := BYTE3 402 403 highAddrStore.uop.fuOpType := SD 404 highAddrStore.vaddr := req.vaddr + 3.U 405 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 406 highResultWidth := BYTE5 407 } 408 409 is ("b110".U) { 410 lowAddrStore.uop.fuOpType := SD 411 lowAddrStore.vaddr := req.vaddr - 6.U 412 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 413 lowResultWidth := BYTE2 414 415 highAddrStore.uop.fuOpType := SD 416 highAddrStore.vaddr := req.vaddr + 2.U 417 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 418 highResultWidth := BYTE6 419 } 420 421 is ("b111".U) { 422 lowAddrStore.uop.fuOpType := SD 423 lowAddrStore.vaddr := req.vaddr - 7.U 424 lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 425 lowResultWidth := BYTE1 426 427 highAddrStore.uop.fuOpType := SD 428 highAddrStore.vaddr := req.vaddr + 1.U 429 highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 430 highResultWidth := BYTE7 431 } 432 } 433 } 434 } 435 436 splitStoreReqs(0) := lowAddrStore 437 splitStoreReqs(1) := highAddrStore 438 } 439 } 440 441 io.splitStoreReq.valid := req_valid && (bufferState === s_req) 442 io.splitStoreReq.bits := splitStoreReqs(curPtr) 443 444 when (io.splitStoreResp.valid) { 445 splitStoreResp(curPtr) := io.splitStoreResp.bits 446 when (isMMIO) { 447 unWriteStores := 0.U 448 unSentStores := 0.U 449 splitStoreResp(curPtr).uop.exceptionVec := 0.U.asTypeOf(ExceptionVec()) 450 // delegate to software 451 splitStoreResp(curPtr).uop.exceptionVec(storeAddrMisaligned) := true.B 452 } .elsewhen (hasException) { 453 unWriteStores := 0.U 454 unSentStores := 0.U 455 } .elsewhen (!io.splitStoreResp.bits.need_rep) { 456 unSentStores := unSentStores & ~UIntToOH(curPtr) 457 curPtr := curPtr + 1.U 458 } 459 } 460 461 val splitStoreData = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new XSBundle { 462 val wdata = UInt(VLEN.W) 463 val wmask = UInt((VLEN / 8).W) 464 })))) 465 466 val unalignedStoreData = io.sqControl.storeInfo.data 467 val wmaskLow = Wire(Vec(VLEN / 8, Bool())) 468 val wmaskHigh = Wire(Vec(VLEN / 8, Bool())) 469 (0 until (VLEN / 8)).map { 470 case i => { 471 when (i.U < highResultWidth) { 472 wmaskHigh(i) := true.B 473 } .otherwise { 474 wmaskHigh(i) := false.B 475 } 476 when (i.U < lowResultWidth) { 477 wmaskLow(i) := true.B 478 } .otherwise { 479 wmaskLow(i) := false.B 480 } 481 } 482 } 483 484 when (bufferState === s_cal) { 485 when (!cross16BytesBoundary) { 486 splitStoreData(0).wdata := LookupTree(aligned16BytesSel, List( 487 "b0000".U -> unalignedStoreData, 488 "b0001".U -> Cat(unalignedStoreData, 0.U(( 1 * 8).W)), 489 "b0010".U -> Cat(unalignedStoreData, 0.U(( 2 * 8).W)), 490 "b0011".U -> Cat(unalignedStoreData, 0.U(( 3 * 8).W)), 491 "b0100".U -> Cat(unalignedStoreData, 0.U(( 4 * 8).W)), 492 "b0101".U -> Cat(unalignedStoreData, 0.U(( 5 * 8).W)), 493 "b0110".U -> Cat(unalignedStoreData, 0.U(( 6 * 8).W)), 494 "b0111".U -> Cat(unalignedStoreData, 0.U(( 7 * 8).W)), 495 "b1000".U -> Cat(unalignedStoreData, 0.U(( 8 * 8).W)), 496 "b1001".U -> Cat(unalignedStoreData, 0.U(( 9 * 8).W)), 497 "b1010".U -> Cat(unalignedStoreData, 0.U((10 * 8).W)), 498 "b1011".U -> Cat(unalignedStoreData, 0.U((11 * 8).W)), 499 "b1100".U -> Cat(unalignedStoreData, 0.U((12 * 8).W)), 500 "b1101".U -> Cat(unalignedStoreData, 0.U((13 * 8).W)), 501 "b1110".U -> Cat(unalignedStoreData, 0.U((14 * 8).W)), 502 "b1111".U -> Cat(unalignedStoreData, 0.U((15 * 8).W)) 503 ))(VLEN - 1, 0) 504 splitStoreData(0).wmask := getMask(req.uop.fuOpType(1, 0)) << aligned16BytesSel 505 } .otherwise { 506 // low 16bytes part 507 val catData = LookupTree(lowResultWidth, List( 508 BYTE0 -> unalignedStoreData, 509 BYTE1 -> Cat(unalignedStoreData, 0.U((8 * 15).W)), 510 BYTE2 -> Cat(unalignedStoreData, 0.U((8 * 14).W)), 511 BYTE3 -> Cat(unalignedStoreData, 0.U((8 * 13).W)), 512 BYTE4 -> Cat(unalignedStoreData, 0.U((8 * 12).W)), 513 BYTE5 -> Cat(unalignedStoreData, 0.U((8 * 11).W)), 514 BYTE6 -> Cat(unalignedStoreData, 0.U((8 * 10).W)), 515 BYTE7 -> Cat(unalignedStoreData, 0.U((8 * 9).W)) 516 )) 517 splitStoreData(0).wdata := catData(VLEN - 1, 0) 518 splitStoreData(0).wmask := VecInit(wmaskLow.reverse).asUInt 519 // high 16bytes part 520 val shiftData = LookupTree(lowResultWidth, List( 521 BYTE0 -> unalignedStoreData(VLEN - 1, 0), 522 BYTE1 -> unalignedStoreData(VLEN - 1, 8), 523 BYTE2 -> unalignedStoreData(VLEN - 1, 16), 524 BYTE3 -> unalignedStoreData(VLEN - 1, 24), 525 BYTE4 -> unalignedStoreData(VLEN - 1, 32), 526 BYTE5 -> unalignedStoreData(VLEN - 1, 40), 527 BYTE6 -> unalignedStoreData(VLEN - 1, 48), 528 BYTE7 -> unalignedStoreData(VLEN - 1, 56) 529 )) 530 splitStoreData(1).wdata := LookupTree(highResultWidth, List( 531 BYTE0 -> ZeroExt(shiftData, VLEN), 532 BYTE1 -> ZeroExt(shiftData(7, 0), VLEN), 533 BYTE2 -> ZeroExt(shiftData(15, 0), VLEN), 534 BYTE3 -> ZeroExt(shiftData(23, 0), VLEN), 535 BYTE4 -> ZeroExt(shiftData(31, 0), VLEN), 536 BYTE5 -> ZeroExt(shiftData(39, 0), VLEN), 537 BYTE6 -> ZeroExt(shiftData(47, 0), VLEN), 538 BYTE7 -> ZeroExt(shiftData(55, 0), VLEN) 539 )) 540 splitStoreData(1).wmask := wmaskHigh.asUInt 541 } 542 } 543 544 io.sqControl.control.hasException := req_valid && globalException 545 546 io.sqControl.control.writeSb := bufferState === s_sq_req 547 io.sqControl.control.wdata := splitStoreData(curPtr).wdata 548 io.sqControl.control.wmask := splitStoreData(curPtr).wmask 549 // the paddr and vaddr is not corresponding to the exact addr of 550 io.sqControl.control.paddr := splitStoreResp(curPtr).paddr 551 io.sqControl.control.vaddr := splitStoreResp(curPtr).vaddr 552 io.sqControl.control.last := !((unWriteStores & ~UIntToOH(curPtr)).orR) 553 554 when (bufferState === s_sq_req) { 555 when (io.sqControl.storeInfo.completeSbTrans) { 556 unWriteStores := unWriteStores & ~UIntToOH(curPtr) 557 curPtr := curPtr + 1.U 558 } 559 } 560 561 io.writeBack.valid := req_valid && (bufferState === s_wb) && io.sqControl.storeInfo.dataReady 562 io.writeBack.bits.uop := req.uop 563 io.writeBack.bits.uop.exceptionVec := Mux( 564 globalMMIO || globalException, 565 splitStoreResp(curPtr).uop.exceptionVec, 566 0.U.asTypeOf(ExceptionVec()) // TODO: is this ok? 567 ) 568 io.writeBack.bits.uop.flushPipe := Mux(globalMMIO || globalException, false.B, true.B) 569 io.writeBack.bits.uop.replayInst := false.B 570 io.writeBack.bits.data := unalignedStoreData 571 io.writeBack.bits.debug.isMMIO := globalMMIO 572 io.writeBack.bits.debug.isPerfCnt := false.B 573 io.writeBack.bits.debug.paddr := req.paddr 574 io.writeBack.bits.debug.vaddr := req.vaddr 575 576 io.sqControl.control.removeSq := req_valid && (bufferState === s_wait) && !(globalMMIO || globalException) && (io.rob.scommit =/= 0.U) 577 578 val flush = req_valid && req.uop.robIdx.needFlush(io.redirect) 579 580 when (flush && (bufferState =/= s_idle)) { 581 bufferState := s_idle 582 req_valid := false.B 583 curPtr := 0.U 584 unSentStores := 0.U 585 unWriteStores := 0.U 586 globalException := false.B 587 globalMMIO := false.B 588 } 589 590 // NOTE: spectial case (unaligned store cross page, page fault happens in next page) 591 // if exception happens in the higher page address part, overwrite the storeExceptionBuffer vaddr 592 val overwriteExpBuf = GatedValidRegNext(req_valid && cross16BytesBoundary && globalException && (curPtr === 1.U)) 593 val overwriteAddr = GatedRegNext(splitStoreResp(curPtr).vaddr) 594 595 io.overwriteExpBuf.valid := overwriteExpBuf 596 io.overwriteExpBuf.vaddr := overwriteAddr 597 598 XSPerfAccumulate("alloc", RegNext(!req_valid) && req_valid) 599 XSPerfAccumulate("flush", flush) 600 XSPerfAccumulate("flush_idle", flush && (bufferState === s_idle)) 601 XSPerfAccumulate("flush_non_idle", flush && (bufferState =/= s_idle)) 602}