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