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