141d8d239Shappy-lx/*************************************************************************************** 241d8d239Shappy-lx* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 341d8d239Shappy-lx* Copyright (c) 2020-2021 Peng Cheng Laboratory 441d8d239Shappy-lx* 541d8d239Shappy-lx* XiangShan is licensed under Mulan PSL v2. 641d8d239Shappy-lx* You can use this software according to the terms and conditions of the Mulan PSL v2. 741d8d239Shappy-lx* You may obtain a copy of Mulan PSL v2 at: 841d8d239Shappy-lx* http://license.coscl.org.cn/MulanPSL2 941d8d239Shappy-lx* 1041d8d239Shappy-lx* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1141d8d239Shappy-lx* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1241d8d239Shappy-lx* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1341d8d239Shappy-lx* 1441d8d239Shappy-lx* See the Mulan PSL v2 for more details. 1541d8d239Shappy-lx***************************************************************************************/ 1641d8d239Shappy-lx 1741d8d239Shappy-lxpackage xiangshan.mem 1841d8d239Shappy-lx 1941d8d239Shappy-lximport org.chipsalliance.cde.config.Parameters 2041d8d239Shappy-lximport chisel3._ 2141d8d239Shappy-lximport chisel3.util._ 2241d8d239Shappy-lximport utils._ 2341d8d239Shappy-lximport utility._ 2441d8d239Shappy-lximport xiangshan._ 259e12e8edScz4eimport xiangshan.ExceptionNO._ 269e12e8edScz4eimport xiangshan.frontend.FtqPtr 2741d8d239Shappy-lximport xiangshan.backend.fu.FuConfig._ 2841d8d239Shappy-lximport xiangshan.backend.fu.fpu.FPU 2941d8d239Shappy-lximport xiangshan.backend.rob.RobLsqIO 3041d8d239Shappy-lximport xiangshan.backend.rob.RobPtr 31b240e1c0SAnzoooooimport xiangshan.backend.Bundles._ 32282dd18cSsfencevmaimport xiangshan.backend.fu.FuConfig.StaCfg 33b240e1c0SAnzoooooimport xiangshan.backend.fu.FuType.isVStore 349e12e8edScz4eimport xiangshan.mem.Bundles._ 359e12e8edScz4eimport xiangshan.cache._ 369e12e8edScz4eimport xiangshan.cache.wpu.ReplayCarry 3741d8d239Shappy-lx 3841d8d239Shappy-lxclass StoreMisalignBuffer(implicit p: Parameters) extends XSModule 3941d8d239Shappy-lx with HasCircularQueuePtrHelper 4041d8d239Shappy-lx{ 4141d8d239Shappy-lx private val enqPortNum = StorePipelineWidth 4241d8d239Shappy-lx private val maxSplitNum = 2 4341d8d239Shappy-lx 4441d8d239Shappy-lx require(maxSplitNum == 2) 4541d8d239Shappy-lx 4641d8d239Shappy-lx private val SB = "b00".U(2.W) 4741d8d239Shappy-lx private val SH = "b01".U(2.W) 4841d8d239Shappy-lx private val SW = "b10".U(2.W) 4941d8d239Shappy-lx private val SD = "b11".U(2.W) 5041d8d239Shappy-lx 5141d8d239Shappy-lx // encode of how many bytes to shift or truncate 5241d8d239Shappy-lx private val BYTE0 = "b000".U(3.W) 5341d8d239Shappy-lx private val BYTE1 = "b001".U(3.W) 5441d8d239Shappy-lx private val BYTE2 = "b010".U(3.W) 5541d8d239Shappy-lx private val BYTE3 = "b011".U(3.W) 5641d8d239Shappy-lx private val BYTE4 = "b100".U(3.W) 5741d8d239Shappy-lx private val BYTE5 = "b101".U(3.W) 5841d8d239Shappy-lx private val BYTE6 = "b110".U(3.W) 5941d8d239Shappy-lx private val BYTE7 = "b111".U(3.W) 6041d8d239Shappy-lx 6141d8d239Shappy-lx def getMask(sizeEncode: UInt) = LookupTree(sizeEncode, List( 6241d8d239Shappy-lx SB -> 0x1.U, 6341d8d239Shappy-lx SH -> 0x3.U, 6441d8d239Shappy-lx SW -> 0xf.U, 6541d8d239Shappy-lx SD -> 0xff.U 6641d8d239Shappy-lx )) 6741d8d239Shappy-lx 68b240e1c0SAnzooooo def selectOldest[T <: LsPipelineBundle](valid: Seq[Bool], bits: Seq[T], index: Seq[UInt]): (Seq[Bool], Seq[T], Seq[UInt]) = { 6941d8d239Shappy-lx assert(valid.length == bits.length) 7041d8d239Shappy-lx if (valid.length == 0 || valid.length == 1) { 71b240e1c0SAnzooooo (valid, bits, index) 7241d8d239Shappy-lx } else if (valid.length == 2) { 7341d8d239Shappy-lx val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0))))) 74b240e1c0SAnzooooo val resIndex = Seq.fill(2)(Wire(chiselTypeOf(index(0)))) 7541d8d239Shappy-lx for (i <- res.indices) { 7641d8d239Shappy-lx res(i).valid := valid(i) 7741d8d239Shappy-lx res(i).bits := bits(i) 78b240e1c0SAnzooooo resIndex(i) := index(i) 7941d8d239Shappy-lx } 8041d8d239Shappy-lx val oldest = Mux(valid(0) && valid(1), 8141d8d239Shappy-lx Mux(isAfter(bits(0).uop.robIdx, bits(1).uop.robIdx) || 8241d8d239Shappy-lx (isNotBefore(bits(0).uop.robIdx, bits(1).uop.robIdx) && bits(0).uop.uopIdx > bits(1).uop.uopIdx), res(1), res(0)), 8341d8d239Shappy-lx Mux(valid(0) && !valid(1), res(0), res(1))) 84b240e1c0SAnzooooo 85b240e1c0SAnzooooo val oldestIndex = Mux(valid(0) && valid(1), 86b240e1c0SAnzooooo Mux(isAfter(bits(0).uop.robIdx, bits(1).uop.robIdx) || 87b240e1c0SAnzooooo (bits(0).uop.robIdx === bits(1).uop.robIdx && bits(0).uop.uopIdx > bits(1).uop.uopIdx), resIndex(1), resIndex(0)), 88b240e1c0SAnzooooo Mux(valid(0) && !valid(1), resIndex(0), resIndex(1))) 89b240e1c0SAnzooooo (Seq(oldest.valid), Seq(oldest.bits), Seq(oldestIndex)) 9041d8d239Shappy-lx } else { 91b240e1c0SAnzooooo val left = selectOldest(valid.take(valid.length / 2), bits.take(bits.length / 2), index.take(index.length / 2)) 92b240e1c0SAnzooooo val right = selectOldest(valid.takeRight(valid.length - (valid.length / 2)), bits.takeRight(bits.length - (bits.length / 2)), index.takeRight(index.length - (index.length / 2))) 93b240e1c0SAnzooooo selectOldest(left._1 ++ right._1, left._2 ++ right._2, left._3 ++ right._3) 9441d8d239Shappy-lx } 9541d8d239Shappy-lx } 9641d8d239Shappy-lx 9741d8d239Shappy-lx val io = IO(new Bundle() { 9841d8d239Shappy-lx val redirect = Flipped(Valid(new Redirect)) 994ec1f462Scz4e val enq = Vec(enqPortNum, Flipped(new MisalignBufferEnqIO)) 10041d8d239Shappy-lx val rob = Flipped(new RobLsqIO) 10141d8d239Shappy-lx val splitStoreReq = Decoupled(new LsPipelineBundle) 10241d8d239Shappy-lx val splitStoreResp = Flipped(Valid(new SqWriteBundle)) 10341d8d239Shappy-lx val writeBack = Decoupled(new MemExuOutput) 104b240e1c0SAnzooooo val vecWriteBack = Vec(VecStorePipelineWidth, Decoupled(new VecPipelineFeedbackIO(isVStore = true))) 105b240e1c0SAnzooooo val storeOutValid = Input(Bool()) 106b240e1c0SAnzooooo val storeVecOutValid = Input(Bool()) 10741d8d239Shappy-lx val overwriteExpBuf = Output(new XSBundle { 10841d8d239Shappy-lx val valid = Bool() 10946e9ee74SHaoyuan Feng val vaddr = UInt(XLEN.W) 11046e9ee74SHaoyuan Feng val isHyper = Bool() 11146e9ee74SHaoyuan Feng val gpaddr = UInt(XLEN.W) 112ad415ae0SXiaokun-Pei val isForVSnonLeafPTE = Bool() 11341d8d239Shappy-lx }) 11441d8d239Shappy-lx val sqControl = new StoreMaBufToSqControlIO 115b240e1c0SAnzooooo 116b240e1c0SAnzooooo val toVecStoreMergeBuffer = Vec(VecStorePipelineWidth, new StoreMaBufToVecStoreMergeBufferIO) 117b240e1c0SAnzooooo val full = Bool() 11841d8d239Shappy-lx }) 11941d8d239Shappy-lx 12041d8d239Shappy-lx io.rob.mmio := 0.U.asTypeOf(Vec(LoadPipelineWidth, Bool())) 12141d8d239Shappy-lx io.rob.uop := 0.U.asTypeOf(Vec(LoadPipelineWidth, new DynInst)) 12241d8d239Shappy-lx 123b240e1c0SAnzooooo class StoreMisalignBufferEntry(implicit p: Parameters) extends LsPipelineBundle { 124b240e1c0SAnzooooo val portIndex = UInt(log2Up(enqPortNum).W) 125b240e1c0SAnzooooo } 12641d8d239Shappy-lx val req_valid = RegInit(false.B) 127b240e1c0SAnzooooo val req = Reg(new StoreMisalignBufferEntry) 128b240e1c0SAnzooooo 129b240e1c0SAnzooooo val cross4KBPageBoundary = Wire(Bool()) 130b240e1c0SAnzooooo val needFlushPipe = RegInit(false.B) 13141d8d239Shappy-lx 132acc50f3bSAnzo // buffer control: 133acc50f3bSAnzo // - s_idle: Idle 134acc50f3bSAnzo // - s_split: Split miss-aligned store into aligned stores 135acc50f3bSAnzo // - s_req: Send split store to sta and get result from sta 136acc50f3bSAnzo // - s_resp: Responds to a split store access request 137acc50f3bSAnzo // - s_wb: writeback yo rob/vecMergeBuffer 138acc50f3bSAnzo // - s_block: Wait for this instr to reach the head of Rob. 139acc50f3bSAnzo val s_idle :: s_split :: s_req :: s_resp :: s_wb :: s_block :: Nil = Enum(6) 140acc50f3bSAnzo val bufferState = RegInit(s_idle) 141acc50f3bSAnzo 14241d8d239Shappy-lx // enqueue 14341d8d239Shappy-lx // s1: 1444ec1f462Scz4e val s1_req = VecInit(io.enq.map(_.req.bits)) 1454ec1f462Scz4e val s1_valid = VecInit(io.enq.map(x => x.req.valid)) 14641d8d239Shappy-lx 1474ec1f462Scz4e val s1_index = (0 until io.enq.length).map(_.asUInt) 148b240e1c0SAnzooooo val reqSel = selectOldest(s1_valid, s1_req, s1_index) 14941d8d239Shappy-lx 150b240e1c0SAnzooooo val reqSelValid = reqSel._1(0) 151b240e1c0SAnzooooo val reqSelBits = reqSel._2(0) 152b240e1c0SAnzooooo val reqSelPort = reqSel._3(0) 153b240e1c0SAnzooooo 154b240e1c0SAnzooooo val reqRedirect = reqSelBits.uop.robIdx.needFlush(io.redirect) 155b240e1c0SAnzooooo 156b240e1c0SAnzooooo val canEnq = !req_valid && !reqRedirect && reqSelValid 157acc50f3bSAnzo val robMatch = req_valid && io.rob.pendingst && (io.rob.pendingPtr === req.uop.robIdx) 158acc50f3bSAnzo 1594ec1f462Scz4e val s2_canEnq = GatedRegNext(canEnq) 1604ec1f462Scz4e val s2_reqSelPort = GatedRegNext(reqSelPort) 1614ec1f462Scz4e val misalign_can_split = Wire(Bool()) 1624ec1f462Scz4e misalign_can_split := Mux(s2_canEnq, (0 until enqPortNum).map { 1634ec1f462Scz4e case i => !io.enq(i).revoke && s2_reqSelPort === i.U 1644ec1f462Scz4e }.reduce(_|_), GatedRegNext(misalign_can_split)) 1654ec1f462Scz4e 166b240e1c0SAnzooooo when(canEnq) { 167b240e1c0SAnzooooo connectSamePort(req, reqSelBits) 168b240e1c0SAnzooooo req.portIndex := reqSelPort 1694ec1f462Scz4e req_valid := true.B 170b240e1c0SAnzooooo } 171b240e1c0SAnzooooo val cross4KBPageEnq = WireInit(false.B) 172b240e1c0SAnzooooo when (cross4KBPageBoundary && !reqRedirect) { 173acc50f3bSAnzo when( 1744ec1f462Scz4e reqSelValid && 175acc50f3bSAnzo (isAfter(req.uop.robIdx, reqSelBits.uop.robIdx) || (isNotBefore(req.uop.robIdx, reqSelBits.uop.robIdx) && req.uop.uopIdx > reqSelBits.uop.uopIdx)) && 176acc50f3bSAnzo bufferState === s_idle 177acc50f3bSAnzo ) { 178b240e1c0SAnzooooo connectSamePort(req, reqSelBits) 179b240e1c0SAnzooooo req.portIndex := reqSelPort 180b240e1c0SAnzooooo cross4KBPageEnq := true.B 181b240e1c0SAnzooooo needFlushPipe := true.B 182b240e1c0SAnzooooo } .otherwise { 183b240e1c0SAnzooooo req := req 184b240e1c0SAnzooooo cross4KBPageEnq := false.B 185b240e1c0SAnzooooo } 18641d8d239Shappy-lx } 18741d8d239Shappy-lx 188b240e1c0SAnzooooo val reqSelCanEnq = UIntToOH(reqSelPort) 189b240e1c0SAnzooooo 1904ec1f462Scz4e io.enq.zipWithIndex.map{ 1914ec1f462Scz4e case (reqPort, index) => reqPort.req.ready := reqSelCanEnq(index) && (!req_valid || cross4KBPageBoundary && cross4KBPageEnq) 19241d8d239Shappy-lx } 19341d8d239Shappy-lx 194b240e1c0SAnzooooo io.toVecStoreMergeBuffer.zipWithIndex.map{ 195b240e1c0SAnzooooo case (toStMB, index) => { 196b240e1c0SAnzooooo toStMB.flush := req_valid && cross4KBPageBoundary && cross4KBPageEnq && UIntToOH(req.portIndex)(index) 197b240e1c0SAnzooooo toStMB.mbIndex := req.mbIndex 19841d8d239Shappy-lx } 199b240e1c0SAnzooooo } 200b240e1c0SAnzooooo io.full := req_valid 20141d8d239Shappy-lx 202acc50f3bSAnzo //logic 20341d8d239Shappy-lx val splitStoreReqs = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new LsPipelineBundle)))) 20441d8d239Shappy-lx val splitStoreResp = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new SqWriteBundle)))) 205b240e1c0SAnzooooo val isCrossPage = RegInit(false.B) 206282dd18cSsfencevma val exceptionVec = RegInit(0.U.asTypeOf(ExceptionVec())) 20741d8d239Shappy-lx val unSentStores = RegInit(0.U(maxSplitNum.W)) 20841d8d239Shappy-lx val unWriteStores = RegInit(0.U(maxSplitNum.W)) 20941d8d239Shappy-lx val curPtr = RegInit(0.U(log2Ceil(maxSplitNum).W)) 21041d8d239Shappy-lx 21141d8d239Shappy-lx // if there is exception or mmio in split store 21241d8d239Shappy-lx val globalException = RegInit(false.B) 21335bb7796SAnzo val globalUncache = RegInit(false.B) 21435bb7796SAnzo 21535bb7796SAnzo // debug info 21641d8d239Shappy-lx val globalMMIO = RegInit(false.B) 21735bb7796SAnzo val globalNC = RegInit(false.B) 21841d8d239Shappy-lx 219da51a7acSAnzo val hasException = io.splitStoreResp.bits.vecActive && !io.splitStoreResp.bits.need_rep && 220da51a7acSAnzo ExceptionNO.selectByFu(io.splitStoreResp.bits.uop.exceptionVec, StaCfg).asUInt.orR || TriggerAction.isDmode(io.splitStoreResp.bits.uop.trigger) 22135bb7796SAnzo val isUncache = (io.splitStoreResp.bits.mmio || io.splitStoreResp.bits.nc) && !io.splitStoreResp.bits.need_rep 22241d8d239Shappy-lx 223b240e1c0SAnzooooo io.sqControl.toStoreQueue.crossPageWithHit := io.sqControl.toStoreMisalignBuffer.sqPtr === req.uop.sqIdx && isCrossPage 224b240e1c0SAnzooooo io.sqControl.toStoreQueue.crossPageCanDeq := !isCrossPage || bufferState === s_block 225b240e1c0SAnzooooo io.sqControl.toStoreQueue.paddr := Cat(splitStoreResp(1).paddr(splitStoreResp(1).paddr.getWidth - 1, 3), 0.U(3.W)) 226b240e1c0SAnzooooo 227b240e1c0SAnzooooo io.sqControl.toStoreQueue.withSameUop := io.sqControl.toStoreMisalignBuffer.uop.robIdx === req.uop.robIdx && io.sqControl.toStoreMisalignBuffer.uop.uopIdx === req.uop.uopIdx && req.isvec && robMatch && isCrossPage 228b240e1c0SAnzooooo 229acc50f3bSAnzo //state transition 23041d8d239Shappy-lx switch(bufferState) { 23141d8d239Shappy-lx is (s_idle) { 2324ec1f462Scz4e when(cross4KBPageBoundary && misalign_can_split) { 23341d8d239Shappy-lx when(robMatch) { 23441d8d239Shappy-lx bufferState := s_split 235b240e1c0SAnzooooo isCrossPage := true.B 23641d8d239Shappy-lx } 237b240e1c0SAnzooooo } .otherwise { 2384ec1f462Scz4e when (req_valid && misalign_can_split) { 239b240e1c0SAnzooooo bufferState := s_split 240b240e1c0SAnzooooo isCrossPage := false.B 241b240e1c0SAnzooooo } 242b240e1c0SAnzooooo } 24341d8d239Shappy-lx } 24441d8d239Shappy-lx 24541d8d239Shappy-lx is (s_split) { 24641d8d239Shappy-lx bufferState := s_req 24741d8d239Shappy-lx } 24841d8d239Shappy-lx 24941d8d239Shappy-lx is (s_req) { 25041d8d239Shappy-lx when (io.splitStoreReq.fire) { 25141d8d239Shappy-lx bufferState := s_resp 25241d8d239Shappy-lx } 25341d8d239Shappy-lx } 25441d8d239Shappy-lx 25541d8d239Shappy-lx is (s_resp) { 256*4a02bbdaSAnzo val needDelay = WireInit(false.B) 257*4a02bbdaSAnzo 25841d8d239Shappy-lx when (io.splitStoreResp.valid) { 25941d8d239Shappy-lx val clearOh = UIntToOH(curPtr) 26035bb7796SAnzo when (hasException || isUncache) { 26141d8d239Shappy-lx // commit directly when exception ocurs 26241d8d239Shappy-lx // if any split store reaches mmio space, delegate to software storeAddrMisaligned exception 26341d8d239Shappy-lx bufferState := s_wb 26441d8d239Shappy-lx globalException := hasException 26535bb7796SAnzo globalUncache := isUncache 26635bb7796SAnzo globalMMIO := io.splitStoreResp.bits.mmio 26735bb7796SAnzo globalNC := io.splitStoreResp.bits.nc 268b240e1c0SAnzooooo } .elsewhen(io.splitStoreResp.bits.need_rep || (unSentStores & (~clearOh).asUInt).orR) { 26941d8d239Shappy-lx // need replay or still has unsent requests 27041d8d239Shappy-lx bufferState := s_req 27141d8d239Shappy-lx } .otherwise { 272*4a02bbdaSAnzo // got result, goto calculate data and control sq. 273*4a02bbdaSAnzo // Wait a beat to get misalign writeback aligned raw rollback. 274*4a02bbdaSAnzo needDelay := true.B 275*4a02bbdaSAnzo bufferState := s_resp 27641d8d239Shappy-lx } 27741d8d239Shappy-lx } 278*4a02bbdaSAnzo 279*4a02bbdaSAnzo when (RegNextN(needDelay, RAWTotalDelayCycles)) { 280*4a02bbdaSAnzo bufferState := s_wb 281*4a02bbdaSAnzo } 28241d8d239Shappy-lx } 28341d8d239Shappy-lx 28441d8d239Shappy-lx is (s_wb) { 285b240e1c0SAnzooooo when (req.isvec) { 286b240e1c0SAnzooooo when (io.vecWriteBack.map(x => x.fire).reduce( _ || _)) { 28741d8d239Shappy-lx bufferState := s_idle 28841d8d239Shappy-lx req_valid := false.B 28941d8d239Shappy-lx curPtr := 0.U 29041d8d239Shappy-lx unSentStores := 0.U 29141d8d239Shappy-lx unWriteStores := 0.U 29241d8d239Shappy-lx globalException := false.B 29335bb7796SAnzo globalUncache := false.B 294b240e1c0SAnzooooo isCrossPage := false.B 295b240e1c0SAnzooooo needFlushPipe := false.B 29635bb7796SAnzo 29735bb7796SAnzo globalMMIO := false.B 29835bb7796SAnzo globalNC := false.B 299b240e1c0SAnzooooo } 30075efee3dSAnzo 30175efee3dSAnzo }.otherwise { 30235bb7796SAnzo when (io.writeBack.fire && (!isCrossPage || globalUncache || globalException)) { 303b240e1c0SAnzooooo bufferState := s_idle 304b240e1c0SAnzooooo req_valid := false.B 305b240e1c0SAnzooooo curPtr := 0.U 306b240e1c0SAnzooooo unSentStores := 0.U 307b240e1c0SAnzooooo unWriteStores := 0.U 308b240e1c0SAnzooooo globalException := false.B 30935bb7796SAnzo globalUncache := false.B 310b240e1c0SAnzooooo isCrossPage := false.B 311b240e1c0SAnzooooo needFlushPipe := false.B 31235bb7796SAnzo 31335bb7796SAnzo globalMMIO := false.B 31435bb7796SAnzo globalNC := false.B 315b240e1c0SAnzooooo } .elsewhen(io.writeBack.fire && isCrossPage) { 316b240e1c0SAnzooooo bufferState := s_block 317b240e1c0SAnzooooo } .otherwise { 318b240e1c0SAnzooooo bufferState := s_wb 319b240e1c0SAnzooooo } 32075efee3dSAnzo 32175efee3dSAnzo } 322b240e1c0SAnzooooo } 323b240e1c0SAnzooooo 324b240e1c0SAnzooooo is (s_block) { 325b240e1c0SAnzooooo when (io.sqControl.toStoreMisalignBuffer.doDeq) { 326b240e1c0SAnzooooo bufferState := s_idle 327b240e1c0SAnzooooo req_valid := false.B 328b240e1c0SAnzooooo curPtr := 0.U 329b240e1c0SAnzooooo unSentStores := 0.U 330b240e1c0SAnzooooo unWriteStores := 0.U 331b240e1c0SAnzooooo globalException := false.B 33235bb7796SAnzo globalUncache := false.B 333b240e1c0SAnzooooo isCrossPage := false.B 33435bb7796SAnzo needFlushPipe := false.B 33535bb7796SAnzo 33635bb7796SAnzo globalMMIO := false.B 33735bb7796SAnzo globalNC := false.B 33841d8d239Shappy-lx } 33941d8d239Shappy-lx } 34041d8d239Shappy-lx } 34141d8d239Shappy-lx 342b240e1c0SAnzooooo val alignedType = Mux(req.isvec, req.alignedType(1,0), req.uop.fuOpType(1, 0)) 343b240e1c0SAnzooooo 344b240e1c0SAnzooooo val highAddress = LookupTree(alignedType, List( 34541d8d239Shappy-lx SB -> 0.U, 34641d8d239Shappy-lx SH -> 1.U, 34741d8d239Shappy-lx SW -> 3.U, 34841d8d239Shappy-lx SD -> 7.U 34941d8d239Shappy-lx )) + req.vaddr(4, 0) 350b240e1c0SAnzooooo 351b240e1c0SAnzooooo val highPageAddress = LookupTree(alignedType, List( 352b240e1c0SAnzooooo SB -> 0.U, 353b240e1c0SAnzooooo SH -> 1.U, 354b240e1c0SAnzooooo SW -> 3.U, 355b240e1c0SAnzooooo SD -> 7.U 356b240e1c0SAnzooooo )) + req.vaddr(12, 0) 35741d8d239Shappy-lx // to see if (vaddr + opSize - 1) and vaddr are in the same 16 bytes region 35841d8d239Shappy-lx val cross16BytesBoundary = req_valid && (highAddress(4) =/= req.vaddr(4)) 359b240e1c0SAnzooooo cross4KBPageBoundary := req_valid && (highPageAddress(12) =/= req.vaddr(12)) 36041d8d239Shappy-lx val aligned16BytesAddr = (req.vaddr >> 4) << 4// req.vaddr & ~("b1111".U) 36141d8d239Shappy-lx val aligned16BytesSel = req.vaddr(3, 0) 36241d8d239Shappy-lx 36341d8d239Shappy-lx // meta of 128 bit store 36441d8d239Shappy-lx val new128Store = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 36541d8d239Shappy-lx // meta of split loads 36641d8d239Shappy-lx val lowAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 36741d8d239Shappy-lx val highAddrStore = WireInit(0.U.asTypeOf(new LsPipelineBundle)) 36841d8d239Shappy-lx // final lowResult = Cat(`lowResultWidth` of store data, 0.U(make it to fill total length of Vlen)) 36941d8d239Shappy-lx val lowResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 37041d8d239Shappy-lx // final highResult = Zero extend to Vlen(`highResultWidth` of (store data >> lowResultWidth)) 37141d8d239Shappy-lx val highResultWidth = RegInit(0.U(3.W)) // how many bytes should we take from the store data 37241d8d239Shappy-lx 37341d8d239Shappy-lx when (bufferState === s_split) { 37441d8d239Shappy-lx when (!cross16BytesBoundary) { 375b240e1c0SAnzooooo assert(false.B, s"There should be no non-aligned access that does not cross 16Byte boundaries.") 37641d8d239Shappy-lx } .otherwise { 37741d8d239Shappy-lx // split this unaligned store into `maxSplitNum` aligned stores 37841d8d239Shappy-lx unWriteStores := Fill(maxSplitNum, 1.U(1.W)) 37941d8d239Shappy-lx unSentStores := Fill(maxSplitNum, 1.U(1.W)) 38041d8d239Shappy-lx curPtr := 0.U 38141d8d239Shappy-lx lowAddrStore.uop := req.uop 38241d8d239Shappy-lx lowAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 38341d8d239Shappy-lx highAddrStore.uop := req.uop 38441d8d239Shappy-lx highAddrStore.uop.exceptionVec(storeAddrMisaligned) := false.B 38541d8d239Shappy-lx 386b240e1c0SAnzooooo switch (alignedType(1, 0)) { 38741d8d239Shappy-lx is (SB) { 38841d8d239Shappy-lx assert(false.B, "lb should not trigger miss align") 38941d8d239Shappy-lx } 39041d8d239Shappy-lx 39141d8d239Shappy-lx is (SH) { 39241d8d239Shappy-lx lowAddrStore.uop.fuOpType := SB 39341d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr 39441d8d239Shappy-lx lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 39541d8d239Shappy-lx lowResultWidth := BYTE1 39641d8d239Shappy-lx 39741d8d239Shappy-lx highAddrStore.uop.fuOpType := SB 39841d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 1.U 39941d8d239Shappy-lx highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 40041d8d239Shappy-lx highResultWidth := BYTE1 40141d8d239Shappy-lx } 40241d8d239Shappy-lx 40341d8d239Shappy-lx is (SW) { 40441d8d239Shappy-lx switch (req.vaddr(1, 0)) { 40541d8d239Shappy-lx is ("b00".U) { 40641d8d239Shappy-lx assert(false.B, "should not trigger miss align") 40741d8d239Shappy-lx } 40841d8d239Shappy-lx 40941d8d239Shappy-lx is ("b01".U) { 41041d8d239Shappy-lx lowAddrStore.uop.fuOpType := SW 41141d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr - 1.U 41241d8d239Shappy-lx lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 41341d8d239Shappy-lx lowResultWidth := BYTE3 41441d8d239Shappy-lx 41541d8d239Shappy-lx highAddrStore.uop.fuOpType := SB 41641d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 3.U 41741d8d239Shappy-lx highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 41841d8d239Shappy-lx highResultWidth := BYTE1 41941d8d239Shappy-lx } 42041d8d239Shappy-lx 42141d8d239Shappy-lx is ("b10".U) { 42241d8d239Shappy-lx lowAddrStore.uop.fuOpType := SH 42341d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr 42441d8d239Shappy-lx lowAddrStore.mask := 0x3.U << lowAddrStore.vaddr(3, 0) 42541d8d239Shappy-lx lowResultWidth := BYTE2 42641d8d239Shappy-lx 42741d8d239Shappy-lx highAddrStore.uop.fuOpType := SH 42841d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 2.U 42941d8d239Shappy-lx highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 43041d8d239Shappy-lx highResultWidth := BYTE2 43141d8d239Shappy-lx } 43241d8d239Shappy-lx 43341d8d239Shappy-lx is ("b11".U) { 43441d8d239Shappy-lx lowAddrStore.uop.fuOpType := SB 43541d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr 43641d8d239Shappy-lx lowAddrStore.mask := 0x1.U << lowAddrStore.vaddr(3, 0) 43741d8d239Shappy-lx lowResultWidth := BYTE1 43841d8d239Shappy-lx 43941d8d239Shappy-lx highAddrStore.uop.fuOpType := SW 44041d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 1.U 44141d8d239Shappy-lx highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 44241d8d239Shappy-lx highResultWidth := BYTE3 44341d8d239Shappy-lx } 44441d8d239Shappy-lx } 44541d8d239Shappy-lx } 44641d8d239Shappy-lx 44741d8d239Shappy-lx is (SD) { 44841d8d239Shappy-lx switch (req.vaddr(2, 0)) { 44941d8d239Shappy-lx is ("b000".U) { 45041d8d239Shappy-lx assert(false.B, "should not trigger miss align") 45141d8d239Shappy-lx } 45241d8d239Shappy-lx 45341d8d239Shappy-lx is ("b001".U) { 45441d8d239Shappy-lx lowAddrStore.uop.fuOpType := SD 45541d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr - 1.U 45641d8d239Shappy-lx lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 45741d8d239Shappy-lx lowResultWidth := BYTE7 45841d8d239Shappy-lx 45941d8d239Shappy-lx highAddrStore.uop.fuOpType := SB 46041d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 7.U 46141d8d239Shappy-lx highAddrStore.mask := 0x1.U << highAddrStore.vaddr(3, 0) 46241d8d239Shappy-lx highResultWidth := BYTE1 46341d8d239Shappy-lx } 46441d8d239Shappy-lx 46541d8d239Shappy-lx is ("b010".U) { 46641d8d239Shappy-lx lowAddrStore.uop.fuOpType := SD 46741d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr - 2.U 46841d8d239Shappy-lx lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 46941d8d239Shappy-lx lowResultWidth := BYTE6 47041d8d239Shappy-lx 47141d8d239Shappy-lx highAddrStore.uop.fuOpType := SH 47241d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 6.U 47341d8d239Shappy-lx highAddrStore.mask := 0x3.U << highAddrStore.vaddr(3, 0) 47441d8d239Shappy-lx highResultWidth := BYTE2 47541d8d239Shappy-lx } 47641d8d239Shappy-lx 47741d8d239Shappy-lx is ("b011".U) { 47841d8d239Shappy-lx lowAddrStore.uop.fuOpType := SD 47941d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr - 3.U 48041d8d239Shappy-lx lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 48141d8d239Shappy-lx lowResultWidth := BYTE5 48241d8d239Shappy-lx 48341d8d239Shappy-lx highAddrStore.uop.fuOpType := SW 48441d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 5.U 48541d8d239Shappy-lx highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 48641d8d239Shappy-lx highResultWidth := BYTE3 48741d8d239Shappy-lx } 48841d8d239Shappy-lx 48941d8d239Shappy-lx is ("b100".U) { 49041d8d239Shappy-lx lowAddrStore.uop.fuOpType := SW 49141d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr 49241d8d239Shappy-lx lowAddrStore.mask := 0xf.U << lowAddrStore.vaddr(3, 0) 49341d8d239Shappy-lx lowResultWidth := BYTE4 49441d8d239Shappy-lx 49541d8d239Shappy-lx highAddrStore.uop.fuOpType := SW 49641d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 4.U 49741d8d239Shappy-lx highAddrStore.mask := 0xf.U << highAddrStore.vaddr(3, 0) 49841d8d239Shappy-lx highResultWidth := BYTE4 49941d8d239Shappy-lx } 50041d8d239Shappy-lx 50141d8d239Shappy-lx is ("b101".U) { 50241d8d239Shappy-lx lowAddrStore.uop.fuOpType := SD 50341d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr - 5.U 50441d8d239Shappy-lx lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 50541d8d239Shappy-lx lowResultWidth := BYTE3 50641d8d239Shappy-lx 50741d8d239Shappy-lx highAddrStore.uop.fuOpType := SD 50841d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 3.U 50941d8d239Shappy-lx highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 51041d8d239Shappy-lx highResultWidth := BYTE5 51141d8d239Shappy-lx } 51241d8d239Shappy-lx 51341d8d239Shappy-lx is ("b110".U) { 51441d8d239Shappy-lx lowAddrStore.uop.fuOpType := SD 51541d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr - 6.U 51641d8d239Shappy-lx lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 51741d8d239Shappy-lx lowResultWidth := BYTE2 51841d8d239Shappy-lx 51941d8d239Shappy-lx highAddrStore.uop.fuOpType := SD 52041d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 2.U 52141d8d239Shappy-lx highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 52241d8d239Shappy-lx highResultWidth := BYTE6 52341d8d239Shappy-lx } 52441d8d239Shappy-lx 52541d8d239Shappy-lx is ("b111".U) { 52641d8d239Shappy-lx lowAddrStore.uop.fuOpType := SD 52741d8d239Shappy-lx lowAddrStore.vaddr := req.vaddr - 7.U 52841d8d239Shappy-lx lowAddrStore.mask := 0xff.U << lowAddrStore.vaddr(3, 0) 52941d8d239Shappy-lx lowResultWidth := BYTE1 53041d8d239Shappy-lx 53141d8d239Shappy-lx highAddrStore.uop.fuOpType := SD 53241d8d239Shappy-lx highAddrStore.vaddr := req.vaddr + 1.U 53341d8d239Shappy-lx highAddrStore.mask := 0xff.U << highAddrStore.vaddr(3, 0) 53441d8d239Shappy-lx highResultWidth := BYTE7 53541d8d239Shappy-lx } 53641d8d239Shappy-lx } 53741d8d239Shappy-lx } 53841d8d239Shappy-lx } 53941d8d239Shappy-lx 54041d8d239Shappy-lx splitStoreReqs(0) := lowAddrStore 54141d8d239Shappy-lx splitStoreReqs(1) := highAddrStore 54241d8d239Shappy-lx } 54341d8d239Shappy-lx } 54441d8d239Shappy-lx 54541d8d239Shappy-lx io.splitStoreReq.valid := req_valid && (bufferState === s_req) 54641d8d239Shappy-lx io.splitStoreReq.bits := splitStoreReqs(curPtr) 547562eaa0cSAnzooooo io.splitStoreReq.bits.isvec := req.isvec 5484c5e04f2Shappy-lx // Restore the information of H extension store 5494c5e04f2Shappy-lx // bit encoding: | hsv 1 | store 00 | size(2bit) | 5504c5e04f2Shappy-lx val reqIsHsv = LSUOpType.isHsv(req.uop.fuOpType) 551b240e1c0SAnzooooo io.splitStoreReq.bits.uop.fuOpType := Mux(req.isvec, req.uop.fuOpType, Cat(reqIsHsv, 0.U(2.W), splitStoreReqs(curPtr).uop.fuOpType(1, 0))) 552b240e1c0SAnzooooo io.splitStoreReq.bits.alignedType := Mux(req.isvec, splitStoreReqs(curPtr).uop.fuOpType(1, 0), req.alignedType) 553b240e1c0SAnzooooo io.splitStoreReq.bits.isFinalSplit := curPtr(0) 55441d8d239Shappy-lx 55541d8d239Shappy-lx when (io.splitStoreResp.valid) { 556282dd18cSsfencevma val resp = io.splitStoreResp.bits 55741d8d239Shappy-lx splitStoreResp(curPtr) := io.splitStoreResp.bits 55835bb7796SAnzo when (isUncache) { 55941d8d239Shappy-lx unWriteStores := 0.U 56041d8d239Shappy-lx unSentStores := 0.U 561e7ab4635SHuijin Li exceptionVec := ExceptionNO.selectByFu(0.U.asTypeOf(exceptionVec.cloneType), StaCfg) 56241d8d239Shappy-lx // delegate to software 563282dd18cSsfencevma exceptionVec(storeAddrMisaligned) := true.B 56441d8d239Shappy-lx } .elsewhen (hasException) { 56541d8d239Shappy-lx unWriteStores := 0.U 56641d8d239Shappy-lx unSentStores := 0.U 567282dd18cSsfencevma StaCfg.exceptionOut.map(no => exceptionVec(no) := exceptionVec(no) || resp.uop.exceptionVec(no)) 56841d8d239Shappy-lx } .elsewhen (!io.splitStoreResp.bits.need_rep) { 569b240e1c0SAnzooooo unSentStores := unSentStores & (~UIntToOH(curPtr)).asUInt 57041d8d239Shappy-lx curPtr := curPtr + 1.U 571282dd18cSsfencevma exceptionVec := 0.U.asTypeOf(ExceptionVec()) 57241d8d239Shappy-lx } 57341d8d239Shappy-lx } 57441d8d239Shappy-lx 57541d8d239Shappy-lx val splitStoreData = RegInit(VecInit(List.fill(maxSplitNum)(0.U.asTypeOf(new XSBundle { 57641d8d239Shappy-lx val wdata = UInt(VLEN.W) 57741d8d239Shappy-lx val wmask = UInt((VLEN / 8).W) 57841d8d239Shappy-lx })))) 57941d8d239Shappy-lx 58041d8d239Shappy-lx val wmaskLow = Wire(Vec(VLEN / 8, Bool())) 58141d8d239Shappy-lx val wmaskHigh = Wire(Vec(VLEN / 8, Bool())) 58241d8d239Shappy-lx (0 until (VLEN / 8)).map { 58341d8d239Shappy-lx case i => { 58441d8d239Shappy-lx when (i.U < highResultWidth) { 58541d8d239Shappy-lx wmaskHigh(i) := true.B 58641d8d239Shappy-lx } .otherwise { 58741d8d239Shappy-lx wmaskHigh(i) := false.B 58841d8d239Shappy-lx } 58941d8d239Shappy-lx when (i.U < lowResultWidth) { 59041d8d239Shappy-lx wmaskLow(i) := true.B 59141d8d239Shappy-lx } .otherwise { 59241d8d239Shappy-lx wmaskLow(i) := false.B 59341d8d239Shappy-lx } 59441d8d239Shappy-lx } 59541d8d239Shappy-lx } 59641d8d239Shappy-lx 597b240e1c0SAnzooooo io.writeBack.valid := req_valid && (bufferState === s_wb) && !io.storeOutValid && !req.isvec 59841d8d239Shappy-lx io.writeBack.bits.uop := req.uop 599282dd18cSsfencevma io.writeBack.bits.uop.exceptionVec := DontCare 60035bb7796SAnzo StaCfg.exceptionOut.map(no => io.writeBack.bits.uop.exceptionVec(no) := (globalUncache || globalException) && exceptionVec(no)) 601b240e1c0SAnzooooo io.writeBack.bits.uop.flushPipe := needFlushPipe 60241d8d239Shappy-lx io.writeBack.bits.uop.replayInst := false.B 603b240e1c0SAnzooooo io.writeBack.bits.data := DontCare 604bd3e32c1Ssinsanction io.writeBack.bits.isFromLoadUnit := DontCare 60541d8d239Shappy-lx io.writeBack.bits.debug.isMMIO := globalMMIO 60635bb7796SAnzo io.writeBack.bits.debug.isNC := globalNC 60741d8d239Shappy-lx io.writeBack.bits.debug.isPerfCnt := false.B 60841d8d239Shappy-lx io.writeBack.bits.debug.paddr := req.paddr 60941d8d239Shappy-lx io.writeBack.bits.debug.vaddr := req.vaddr 61041d8d239Shappy-lx 611b240e1c0SAnzooooo io.vecWriteBack.zipWithIndex.map{ 612b240e1c0SAnzooooo case (wb, index) => { 613b240e1c0SAnzooooo wb.valid := req_valid && (bufferState === s_wb) && req.isvec && !io.storeVecOutValid && UIntToOH(req.portIndex)(index) 614b240e1c0SAnzooooo 615b240e1c0SAnzooooo wb.bits.mBIndex := req.mbIndex 616b240e1c0SAnzooooo wb.bits.hit := true.B 617b240e1c0SAnzooooo wb.bits.isvec := true.B 618b240e1c0SAnzooooo wb.bits.sourceType := RSFeedbackType.tlbMiss 619b240e1c0SAnzooooo wb.bits.flushState := DontCare 620b240e1c0SAnzooooo wb.bits.trigger := TriggerAction.None 621b240e1c0SAnzooooo wb.bits.mmio := globalMMIO 622b240e1c0SAnzooooo wb.bits.exceptionVec := ExceptionNO.selectByFu(exceptionVec, VstuCfg) 623da51a7acSAnzo wb.bits.hasException := globalException 624b240e1c0SAnzooooo wb.bits.usSecondInv := req.usSecondInv 625b240e1c0SAnzooooo wb.bits.vecFeedback := true.B 626b240e1c0SAnzooooo wb.bits.elemIdx := req.elemIdx 627b240e1c0SAnzooooo wb.bits.alignedType := req.alignedType 628b240e1c0SAnzooooo wb.bits.mask := req.mask 629b240e1c0SAnzooooo wb.bits.vaddr := req.vaddr 630b240e1c0SAnzooooo wb.bits.vaNeedExt := req.vaNeedExt 631b240e1c0SAnzooooo wb.bits.gpaddr := req.gpaddr 632b240e1c0SAnzooooo wb.bits.isForVSnonLeafPTE := req.isForVSnonLeafPTE 633b240e1c0SAnzooooo wb.bits.vstart := req.uop.vpu.vstart 634b240e1c0SAnzooooo wb.bits.vecTriggerMask := 0.U 63535bb7796SAnzo wb.bits.nc := globalNC 636b240e1c0SAnzooooo } 637b240e1c0SAnzooooo } 63841d8d239Shappy-lx 63941d8d239Shappy-lx val flush = req_valid && req.uop.robIdx.needFlush(io.redirect) 64041d8d239Shappy-lx 641b240e1c0SAnzooooo when (flush) { 64241d8d239Shappy-lx bufferState := s_idle 643b240e1c0SAnzooooo req_valid := Mux(cross4KBPageEnq && cross4KBPageBoundary && !reqRedirect, req_valid, false.B) 64441d8d239Shappy-lx curPtr := 0.U 64541d8d239Shappy-lx unSentStores := 0.U 64641d8d239Shappy-lx unWriteStores := 0.U 64741d8d239Shappy-lx globalException := false.B 64835bb7796SAnzo globalUncache := false.B 649b240e1c0SAnzooooo isCrossPage := false.B 650b240e1c0SAnzooooo needFlushPipe := false.B 65135bb7796SAnzo 65235bb7796SAnzo globalMMIO := false.B 65335bb7796SAnzo globalNC := false.B 65441d8d239Shappy-lx } 65541d8d239Shappy-lx 65641d8d239Shappy-lx // NOTE: spectial case (unaligned store cross page, page fault happens in next page) 65741d8d239Shappy-lx // if exception happens in the higher page address part, overwrite the storeExceptionBuffer vaddr 6586444fe09Sgood-circle val shouldOverwrite = req_valid && cross16BytesBoundary && globalException && (curPtr === 1.U) 6596444fe09Sgood-circle val overwriteExpBuf = GatedValidRegNext(shouldOverwrite) 6606444fe09Sgood-circle val overwriteVaddr = RegEnable(splitStoreResp(curPtr).vaddr, shouldOverwrite) 6616444fe09Sgood-circle val overwriteIsHyper = RegEnable(splitStoreResp(curPtr).isHyper, shouldOverwrite) 6626444fe09Sgood-circle val overwriteGpaddr = RegEnable(splitStoreResp(curPtr).gpaddr, shouldOverwrite) 6636444fe09Sgood-circle val overwriteIsForVSnonLeafPTE = RegEnable(splitStoreResp(curPtr).isForVSnonLeafPTE, shouldOverwrite) 66441d8d239Shappy-lx 665b240e1c0SAnzooooo //TODO In theory, there is no need to overwrite, but for now, the signal is retained in the code in this way. 666b240e1c0SAnzooooo // and the signal will be removed after sufficient verification. 667b240e1c0SAnzooooo io.overwriteExpBuf.valid := false.B 66846e9ee74SHaoyuan Feng io.overwriteExpBuf.vaddr := overwriteVaddr 66946e9ee74SHaoyuan Feng io.overwriteExpBuf.isHyper := overwriteIsHyper 670a53daa0fSHaoyuan Feng io.overwriteExpBuf.gpaddr := overwriteGpaddr 671ad415ae0SXiaokun-Pei io.overwriteExpBuf.isForVSnonLeafPTE := overwriteIsForVSnonLeafPTE 67241d8d239Shappy-lx 67341d8d239Shappy-lx XSPerfAccumulate("alloc", RegNext(!req_valid) && req_valid) 67441d8d239Shappy-lx XSPerfAccumulate("flush", flush) 67541d8d239Shappy-lx XSPerfAccumulate("flush_idle", flush && (bufferState === s_idle)) 67641d8d239Shappy-lx XSPerfAccumulate("flush_non_idle", flush && (bufferState =/= s_idle)) 67741d8d239Shappy-lx} 678