1ad3ba452Szhanglinjuan/*************************************************************************************** 2ad3ba452Szhanglinjuan* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3ad3ba452Szhanglinjuan* Copyright (c) 2020-2021 Peng Cheng Laboratory 4ad3ba452Szhanglinjuan* 5ad3ba452Szhanglinjuan* XiangShan is licensed under Mulan PSL v2. 6ad3ba452Szhanglinjuan* You can use this software according to the terms and conditions of the Mulan PSL v2. 7ad3ba452Szhanglinjuan* You may obtain a copy of Mulan PSL v2 at: 8ad3ba452Szhanglinjuan* http://license.coscl.org.cn/MulanPSL2 9ad3ba452Szhanglinjuan* 10ad3ba452Szhanglinjuan* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11ad3ba452Szhanglinjuan* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12ad3ba452Szhanglinjuan* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13ad3ba452Szhanglinjuan* 14ad3ba452Szhanglinjuan* See the Mulan PSL v2 for more details. 15ad3ba452Szhanglinjuan***************************************************************************************/ 16ad3ba452Szhanglinjuan 17ad3ba452Szhanglinjuanpackage xiangshan.mem 18ad3ba452Szhanglinjuan 19ad3ba452Szhanglinjuanimport chipsalliance.rocketchip.config.Parameters 20ad3ba452Szhanglinjuanimport chisel3._ 21ad3ba452Szhanglinjuanimport chisel3.util._ 22ad3ba452Szhanglinjuanimport xiangshan._ 23ad3ba452Szhanglinjuanimport utils._ 24ad3ba452Szhanglinjuanimport xiangshan.cache._ 25ad3ba452Szhanglinjuanimport difftest._ 26*74ea8036SJeniusimport freechips.rocketchip.util._ 27ad3ba452Szhanglinjuan 28ad3ba452Szhanglinjuanclass SbufferFlushBundle extends Bundle { 29ad3ba452Szhanglinjuan val valid = Output(Bool()) 30ad3ba452Szhanglinjuan val empty = Input(Bool()) 31ad3ba452Szhanglinjuan} 32ad3ba452Szhanglinjuan 33ad3ba452Szhanglinjuantrait HasSbufferConst extends HasXSParameter { 34ad3ba452Szhanglinjuan val EvictCycles = 1 << 20 35ad3ba452Szhanglinjuan val SbufferReplayDelayCycles = 16 36ad3ba452Szhanglinjuan require(isPow2(EvictCycles)) 37ad3ba452Szhanglinjuan val EvictCountBits = log2Up(EvictCycles+1) 38ad3ba452Szhanglinjuan val MissqReplayCountBits = log2Up(SbufferReplayDelayCycles) + 1 39ad3ba452Szhanglinjuan 40ad3ba452Szhanglinjuan val SbufferIndexWidth: Int = log2Up(StoreBufferSize) 41ad3ba452Szhanglinjuan // paddr = ptag + offset 42ad3ba452Szhanglinjuan val CacheLineBytes: Int = CacheLineSize / 8 43ad3ba452Szhanglinjuan val CacheLineWords: Int = CacheLineBytes / DataBytes 44ad3ba452Szhanglinjuan val OffsetWidth: Int = log2Up(CacheLineBytes) 45ad3ba452Szhanglinjuan val WordsWidth: Int = log2Up(CacheLineWords) 46ad3ba452Szhanglinjuan val PTagWidth: Int = PAddrBits - OffsetWidth 47ad3ba452Szhanglinjuan val VTagWidth: Int = VAddrBits - OffsetWidth 48ad3ba452Szhanglinjuan val WordOffsetWidth: Int = PAddrBits - WordsWidth 49ad3ba452Szhanglinjuan} 50ad3ba452Szhanglinjuan 51ad3ba452Szhanglinjuanclass SbufferEntryState (implicit p: Parameters) extends SbufferBundle { 52ad3ba452Szhanglinjuan val state_valid = Bool() // this entry is active 53ad3ba452Szhanglinjuan val state_inflight = Bool() // sbuffer is trying to write this entry to dcache 54a98b054bSWilliam Wang val w_timeout = Bool() // with timeout resp, waiting for resend store pipeline req timeout 55a98b054bSWilliam Wang val w_sameblock_inflight = Bool() // same cache block dcache req is inflight 56a98b054bSWilliam Wang val s_recheck_inflight = Bool() // recheck if same cache block dcache req is inflight 57ad3ba452Szhanglinjuan 58ad3ba452Szhanglinjuan def isInvalid(): Bool = !state_valid 59ad3ba452Szhanglinjuan def isValid(): Bool = state_valid 60ad3ba452Szhanglinjuan def isActive(): Bool = state_valid && !state_inflight 61ad3ba452Szhanglinjuan def isInflight(): Bool = state_inflight 62a98b054bSWilliam Wang def isDcacheReqCandidate(): Bool = state_valid && !state_inflight && !w_sameblock_inflight 63ad3ba452Szhanglinjuan} 64ad3ba452Szhanglinjuan 65ad3ba452Szhanglinjuanclass SbufferBundle(implicit p: Parameters) extends XSBundle with HasSbufferConst 66ad3ba452Szhanglinjuan 67ad3ba452Szhanglinjuanclass DataWriteReq(implicit p: Parameters) extends SbufferBundle { 6867c26c34SWilliam Wang // val idx = UInt(SbufferIndexWidth.W) 6967c26c34SWilliam Wang val wvec = UInt(StoreBufferSize.W) 70ad3ba452Szhanglinjuan val mask = UInt((DataBits/8).W) 71ad3ba452Szhanglinjuan val data = UInt(DataBits.W) 72ad3ba452Szhanglinjuan val wordOffset = UInt(WordOffsetWidth.W) 73ca18a0b4SWilliam Wang val wline = Bool() 74ad3ba452Szhanglinjuan} 75ad3ba452Szhanglinjuan 76ad3ba452Szhanglinjuanclass SbufferData(implicit p: Parameters) extends XSModule with HasSbufferConst { 77ad3ba452Szhanglinjuan val io = IO(new Bundle(){ 7846f74b57SHaojin Tang val writeReq = Vec(EnsbufferWidth, Flipped(ValidIO(new DataWriteReq))) 79ad3ba452Szhanglinjuan val dataOut = Output(Vec(StoreBufferSize, Vec(CacheLineWords, Vec(DataBytes, UInt(8.W))))) 80ad3ba452Szhanglinjuan }) 81ad3ba452Szhanglinjuan 82ad3ba452Szhanglinjuan val data = Reg(Vec(StoreBufferSize, Vec(CacheLineWords, Vec(DataBytes, UInt(8.W))))) 83ad3ba452Szhanglinjuan 84ad3ba452Szhanglinjuan val req = io.writeReq 85ad3ba452Szhanglinjuan 8646f74b57SHaojin Tang for(i <- 0 until EnsbufferWidth) { 87ad3ba452Szhanglinjuan when(req(i).valid){ 8867c26c34SWilliam Wang for(line <- 0 until StoreBufferSize){ 89ca18a0b4SWilliam Wang for(word <- 0 until CacheLineWords){ 90ca18a0b4SWilliam Wang for(byte <- 0 until DataBytes){ 91ca18a0b4SWilliam Wang when( 9267c26c34SWilliam Wang req(i).bits.wvec(line) && ( 93ca18a0b4SWilliam Wang req(i).bits.mask(byte) && (req(i).bits.wordOffset(WordsWidth-1, 0) === word.U) || 94ca18a0b4SWilliam Wang req(i).bits.wline 9567c26c34SWilliam Wang ) 96ca18a0b4SWilliam Wang ){ 9767c26c34SWilliam Wang data(line)(word)(byte) := req(i).bits.data(byte*8+7, byte*8) 9867c26c34SWilliam Wang } 99ca18a0b4SWilliam Wang } 100ad3ba452Szhanglinjuan } 101ad3ba452Szhanglinjuan } 102ad3ba452Szhanglinjuan } 103ad3ba452Szhanglinjuan } 104ad3ba452Szhanglinjuan 105ad3ba452Szhanglinjuan io.dataOut := data 106ad3ba452Szhanglinjuan} 107ad3ba452Szhanglinjuan 1081ca0e4f3SYinan Xuclass Sbuffer(implicit p: Parameters) extends DCacheModule with HasSbufferConst with HasPerfEvents { 109ad3ba452Szhanglinjuan val io = IO(new Bundle() { 1105668a921SJiawei Lin val hartId = Input(UInt(8.W)) 11146f74b57SHaojin Tang val in = Vec(EnsbufferWidth, Flipped(Decoupled(new DCacheWordReqWithVaddr))) 112ad3ba452Szhanglinjuan val dcache = Flipped(new DCacheToSbufferIO) 113ad3ba452Szhanglinjuan val forward = Vec(LoadPipelineWidth, Flipped(new LoadForwardQueryIO)) 114ad3ba452Szhanglinjuan val sqempty = Input(Bool()) 115ad3ba452Szhanglinjuan val flush = Flipped(new SbufferFlushBundle) 116ad3ba452Szhanglinjuan val csrCtrl = Flipped(new CustomCSRCtrlIO) 117ad3ba452Szhanglinjuan }) 118ad3ba452Szhanglinjuan 119ad3ba452Szhanglinjuan val dataModule = Module(new SbufferData) 120ad3ba452Szhanglinjuan dataModule.io.writeReq <> DontCare 121ad3ba452Szhanglinjuan val writeReq = dataModule.io.writeReq 122ad3ba452Szhanglinjuan 123ad3ba452Szhanglinjuan val ptag = Reg(Vec(StoreBufferSize, UInt(PTagWidth.W))) 124ad3ba452Szhanglinjuan val vtag = Reg(Vec(StoreBufferSize, UInt(VTagWidth.W))) 125ad3ba452Szhanglinjuan val mask = Reg(Vec(StoreBufferSize, Vec(CacheLineWords, Vec(DataBytes, Bool())))) 126a98b054bSWilliam Wang val waitInflightMask = Reg(Vec(StoreBufferSize, UInt(StoreBufferSize.W))) 127ad3ba452Szhanglinjuan val data = dataModule.io.dataOut 128ad3ba452Szhanglinjuan val stateVec = RegInit(VecInit(Seq.fill(StoreBufferSize)(0.U.asTypeOf(new SbufferEntryState)))) 129ad3ba452Szhanglinjuan val cohCount = RegInit(VecInit(Seq.fill(StoreBufferSize)(0.U(EvictCountBits.W)))) 130ad3ba452Szhanglinjuan val missqReplayCount = RegInit(VecInit(Seq.fill(StoreBufferSize)(0.U(MissqReplayCountBits.W)))) 131ad3ba452Szhanglinjuan 13296b1e495SWilliam Wang val willSendDcacheReq = Wire(Bool()) 13396b1e495SWilliam Wang 134ad3ba452Szhanglinjuan /* 135ad3ba452Szhanglinjuan idle --[flush] --> drain --[buf empty]--> idle 136ad3ba452Szhanglinjuan --[buf full]--> replace --[dcache resp]--> idle 137ad3ba452Szhanglinjuan */ 138ad3ba452Szhanglinjuan // x_drain_all: drain store queue and sbuffer 139ad3ba452Szhanglinjuan // x_drain_sbuffer: drain sbuffer only, block store queue to sbuffer write 140ad3ba452Szhanglinjuan val x_idle :: x_replace :: x_drain_all :: x_drain_sbuffer :: Nil = Enum(4) 141ad3ba452Szhanglinjuan def needDrain(state: UInt): Bool = 142ad3ba452Szhanglinjuan state(1) 143ad3ba452Szhanglinjuan val sbuffer_state = RegInit(x_idle) 144ad3ba452Szhanglinjuan 145ad3ba452Szhanglinjuan // ---------------------- Store Enq Sbuffer --------------------- 146ad3ba452Szhanglinjuan 147ad3ba452Szhanglinjuan def getPTag(pa: UInt): UInt = 148ad3ba452Szhanglinjuan pa(PAddrBits - 1, PAddrBits - PTagWidth) 149ad3ba452Szhanglinjuan 150ad3ba452Szhanglinjuan def getVTag(va: UInt): UInt = 151ad3ba452Szhanglinjuan va(VAddrBits - 1, VAddrBits - VTagWidth) 152ad3ba452Szhanglinjuan 153ad3ba452Szhanglinjuan def getWord(pa: UInt): UInt = 154ad3ba452Szhanglinjuan pa(PAddrBits-1, 3) 155ad3ba452Szhanglinjuan 156ad3ba452Szhanglinjuan def getWordOffset(pa: UInt): UInt = 157ad3ba452Szhanglinjuan pa(OffsetWidth-1, 3) 158ad3ba452Szhanglinjuan 159ad3ba452Szhanglinjuan def getAddr(ptag: UInt): UInt = 160ad3ba452Szhanglinjuan Cat(ptag, 0.U((PAddrBits - PTagWidth).W)) 161ad3ba452Szhanglinjuan 162ad3ba452Szhanglinjuan def getByteOffset(offect: UInt): UInt = 163ad3ba452Szhanglinjuan Cat(offect(OffsetWidth - 1, 3), 0.U(3.W)) 164ad3ba452Szhanglinjuan 165ad3ba452Szhanglinjuan def isOneOf(key: UInt, seq: Seq[UInt]): Bool = 166ad3ba452Szhanglinjuan if(seq.isEmpty) false.B else Cat(seq.map(_===key)).orR() 167ad3ba452Szhanglinjuan 168ad3ba452Szhanglinjuan def widthMap[T <: Data](f: Int => T) = (0 until StoreBufferSize) map f 169ad3ba452Szhanglinjuan 170ad3ba452Szhanglinjuan // sbuffer entry count 171ad3ba452Szhanglinjuan 172ad3ba452Szhanglinjuan val plru = new PseudoLRU(StoreBufferSize) 17346f74b57SHaojin Tang val accessIdx = Wire(Vec(EnsbufferWidth + 1, Valid(UInt(SbufferIndexWidth.W)))) 174ad3ba452Szhanglinjuan 175ad3ba452Szhanglinjuan val replaceIdx = plru.way 176ad3ba452Szhanglinjuan plru.access(accessIdx) 177ad3ba452Szhanglinjuan 178ad3ba452Szhanglinjuan //-------------------------cohCount----------------------------- 179ad3ba452Szhanglinjuan // insert and merge: cohCount=0 180ad3ba452Szhanglinjuan // every cycle cohCount+=1 181ad3ba452Szhanglinjuan // if cohCount(EvictCountBits-1)==1, evict 182ad3ba452Szhanglinjuan val cohTimeOutMask = VecInit(widthMap(i => cohCount(i)(EvictCountBits - 1) && stateVec(i).isActive())) 183ad3ba452Szhanglinjuan val (cohTimeOutIdx, cohHasTimeOut) = PriorityEncoderWithFlag(cohTimeOutMask) 184ad3ba452Szhanglinjuan val missqReplayTimeOutMask = VecInit(widthMap(i => missqReplayCount(i)(MissqReplayCountBits - 1) && stateVec(i).w_timeout)) 18596b1e495SWilliam Wang val (missqReplayTimeOutIdx, missqReplayMayHasTimeOut) = PriorityEncoderWithFlag(missqReplayTimeOutMask) 18696b1e495SWilliam Wang val missqReplayHasTimeOut = RegNext(missqReplayMayHasTimeOut) && !RegNext(willSendDcacheReq) 18796b1e495SWilliam Wang val missqReplayTimeOutIdxReg = RegEnable(missqReplayTimeOutIdx, missqReplayMayHasTimeOut) 188ad3ba452Szhanglinjuan 189ad3ba452Szhanglinjuan val activeMask = VecInit(stateVec.map(s => s.isActive())) 190ad3ba452Szhanglinjuan val drainIdx = PriorityEncoder(activeMask) 191ad3ba452Szhanglinjuan 192ad3ba452Szhanglinjuan val inflightMask = VecInit(stateVec.map(s => s.isInflight())) 193ad3ba452Szhanglinjuan 194ad3ba452Szhanglinjuan val inptags = io.in.map(in => getPTag(in.bits.addr)) 195ad3ba452Szhanglinjuan val invtags = io.in.map(in => getVTag(in.bits.vaddr)) 19646f74b57SHaojin Tang val sameTag = Seq.tabulate(io.in.length)(x => Seq.tabulate(io.in.length)(y => inptags(x) === inptags(y))) 19746f74b57SHaojin Tang val words = (0 until EnsbufferWidth).map(i => getWord(io.in(i).bits.addr)) 19846f74b57SHaojin Tang val sameWord = Seq.tabulate(EnsbufferWidth)(x => Seq.tabulate(EnsbufferWidth)(y => words(x) === words(y))) 199ad3ba452Szhanglinjuan 200ad3ba452Szhanglinjuan // merge condition 20146f74b57SHaojin Tang val mergeMask = Wire(Vec(EnsbufferWidth, Vec(StoreBufferSize, Bool()))) 20267c26c34SWilliam Wang val mergeIdx = mergeMask.map(PriorityEncoder(_)) // avoid using mergeIdx for better timing 203ad3ba452Szhanglinjuan val canMerge = mergeMask.map(ParallelOR(_)) 20467c26c34SWilliam Wang val mergeVec = mergeMask.map(_.asUInt) 205ad3ba452Szhanglinjuan 20646f74b57SHaojin Tang for(i <- 0 until EnsbufferWidth){ 207ad3ba452Szhanglinjuan mergeMask(i) := widthMap(j => 208ad3ba452Szhanglinjuan inptags(i) === ptag(j) && activeMask(j) 209ad3ba452Szhanglinjuan ) 21067c26c34SWilliam Wang assert(!(PopCount(mergeMask(i).asUInt) > 1.U && io.in(i).fire())) 211ad3ba452Szhanglinjuan } 212ad3ba452Szhanglinjuan 213ad3ba452Szhanglinjuan // insert condition 214ad3ba452Szhanglinjuan // firstInsert: the first invalid entry 215ad3ba452Szhanglinjuan // if first entry canMerge or second entry has the same ptag with the first entry, 216ad3ba452Szhanglinjuan // secondInsert equal the first invalid entry, otherwise, the second invalid entry 217ad3ba452Szhanglinjuan val invalidMask = VecInit(stateVec.map(s => s.isInvalid())) 21846f74b57SHaojin Tang val remInvalidMask = GetRemBits(EnsbufferWidth)(invalidMask.asUInt) 219ad3ba452Szhanglinjuan 22067c26c34SWilliam Wang def getFirstOneOH(input: UInt): UInt = { 22167c26c34SWilliam Wang assert(input.getWidth > 1) 22267c26c34SWilliam Wang val output = WireInit(VecInit(input.asBools)) 22367c26c34SWilliam Wang (1 until input.getWidth).map(i => { 22467c26c34SWilliam Wang output(i) := !input(i - 1, 0).orR && input(i) 22567c26c34SWilliam Wang }) 22667c26c34SWilliam Wang output.asUInt 22767c26c34SWilliam Wang } 22867c26c34SWilliam Wang 22946f74b57SHaojin Tang val remRawInsertVec = remInvalidMask.map(getFirstOneOH(_)) 23046f74b57SHaojin Tang val remRawInsert = remInvalidMask.map(PriorityEncoderWithFlag(_)).unzip 23146f74b57SHaojin Tang val (remRawInsertIdx, remCanInsert) = (remRawInsert._1, VecInit(remRawInsert._2)) 23246f74b57SHaojin Tang val remInsertIdx = VecInit(remRawInsertIdx.zipWithIndex.map { case (raw, idx) => 23346f74b57SHaojin Tang if (EnsbufferWidth > 1) Cat(raw, idx.U(log2Ceil(EnsbufferWidth).W)) 23446f74b57SHaojin Tang else raw 23546f74b57SHaojin Tang }) // slow to generate, for debug only 23646f74b57SHaojin Tang val remInsertVec = VecInit(GetRemBits.reverse(EnsbufferWidth)(remRawInsertVec)) 237ad3ba452Szhanglinjuan 23846f74b57SHaojin Tang val enbufferSelReg = RegInit(0.U(log2Up(EnsbufferWidth).W)) 23946f74b57SHaojin Tang if (EnsbufferWidth > 1) when(io.in(0).valid) { 24046f74b57SHaojin Tang enbufferSelReg := enbufferSelReg + 1.U 241ad3ba452Szhanglinjuan } 242ad3ba452Szhanglinjuan 24346f74b57SHaojin Tang val insertIdxs = (0 until EnsbufferWidth).map(i => 24446f74b57SHaojin Tang PriorityMuxDefault(if (i == 0) Seq(0.B -> 0.U) else (0 until i).map(j => sameTag(i)(j) -> remInsertIdx(enbufferSelReg + j.U)), remInsertIdx(enbufferSelReg + i.U)) 24567c26c34SWilliam Wang ) // slow to generate, for debug only 24646f74b57SHaojin Tang val insertVecs = (0 until EnsbufferWidth).map(i => 24746f74b57SHaojin Tang PriorityMuxDefault(if (i == 0) Seq(0.B -> 0.U) else (0 until i).map(j => sameTag(i)(j) -> remInsertVec(enbufferSelReg + j.U)), remInsertVec(enbufferSelReg + i.U)) 24867c26c34SWilliam Wang ) // slow to generate, for debug only 24946f74b57SHaojin Tang val canInserts = (0 until EnsbufferWidth).map(i => 25046f74b57SHaojin Tang PriorityMuxDefault(if (i == 0) Seq(0.B -> 0.B) else (0 until i).map(j => sameTag(i)(j) -> remCanInsert(enbufferSelReg + j.U)), remCanInsert(enbufferSelReg + i.U)) 25146f74b57SHaojin Tang ).map(_ && sbuffer_state =/= x_drain_sbuffer) 25296b1e495SWilliam Wang val forward_need_uarch_drain = WireInit(false.B) 25396b1e495SWilliam Wang val merge_need_uarch_drain = WireInit(false.B) 25496b1e495SWilliam Wang val do_uarch_drain = RegNext(forward_need_uarch_drain) || RegNext(RegNext(merge_need_uarch_drain)) 255ad3ba452Szhanglinjuan XSPerfAccumulate("do_uarch_drain", do_uarch_drain) 256ad3ba452Szhanglinjuan 25746f74b57SHaojin Tang (0 until EnsbufferWidth).foreach(i => 25846f74b57SHaojin Tang io.in(i).ready := canInserts(i) && (if (i == 0) 1.B else !sameWord(0)(i) && io.in(i - 1).ready) 25946f74b57SHaojin Tang ) 260ad3ba452Szhanglinjuan 26167c26c34SWilliam Wang def wordReqToBufLine(req: DCacheWordReq, reqptag: UInt, reqvtag: UInt, insertIdx: UInt, insertVec: UInt, wordOffset: UInt, flushMask: Bool): Unit = { 26267c26c34SWilliam Wang assert(UIntToOH(insertIdx) === insertVec) 263a98b054bSWilliam Wang val sameBlockInflightMask = genSameBlockInflightMask(reqptag) 26467c26c34SWilliam Wang (0 until StoreBufferSize).map(entryIdx => { 26567c26c34SWilliam Wang when(insertVec(entryIdx)){ 26667c26c34SWilliam Wang stateVec(entryIdx).state_valid := true.B 26767c26c34SWilliam Wang stateVec(entryIdx).w_sameblock_inflight := sameBlockInflightMask.orR // set w_sameblock_inflight when a line is first allocated 268a98b054bSWilliam Wang when(sameBlockInflightMask.orR){ 26967c26c34SWilliam Wang waitInflightMask(entryIdx) := sameBlockInflightMask 270a98b054bSWilliam Wang } 27167c26c34SWilliam Wang cohCount(entryIdx) := 0.U 27296b1e495SWilliam Wang // missqReplayCount(insertIdx) := 0.U 27367c26c34SWilliam Wang ptag(entryIdx) := reqptag 27467c26c34SWilliam Wang vtag(entryIdx) := reqvtag // update vtag iff a new sbuffer line is allocated 275ad3ba452Szhanglinjuan when(flushMask){ 276ad3ba452Szhanglinjuan for(j <- 0 until CacheLineWords){ 277ad3ba452Szhanglinjuan for(i <- 0 until DataBytes){ 27867c26c34SWilliam Wang mask(entryIdx)(j)(i) := false.B 279ad3ba452Szhanglinjuan } 280ad3ba452Szhanglinjuan } 281ad3ba452Szhanglinjuan } 282ad3ba452Szhanglinjuan for(i <- 0 until DataBytes){ 283ad3ba452Szhanglinjuan when(req.mask(i)){ 28467c26c34SWilliam Wang mask(entryIdx)(wordOffset)(i) := true.B 285ad3ba452Szhanglinjuan } 286ad3ba452Szhanglinjuan } 287ad3ba452Szhanglinjuan } 28867c26c34SWilliam Wang }) 28967c26c34SWilliam Wang } 290ad3ba452Szhanglinjuan 29167c26c34SWilliam Wang def mergeWordReq(req: DCacheWordReq, reqptag: UInt, reqvtag: UInt, mergeIdx: UInt, mergeVec: UInt, wordOffset: UInt): Unit = { 29267c26c34SWilliam Wang assert(UIntToOH(mergeIdx) === mergeVec) 29367c26c34SWilliam Wang (0 until StoreBufferSize).map(entryIdx => { 29467c26c34SWilliam Wang when(mergeVec(entryIdx)) { 29567c26c34SWilliam Wang cohCount(entryIdx) := 0.U 29667c26c34SWilliam Wang // missqReplayCount(entryIdx) := 0.U 297ad3ba452Szhanglinjuan for(i <- 0 until DataBytes){ 298ad3ba452Szhanglinjuan when(req.mask(i)){ 29967c26c34SWilliam Wang mask(entryIdx)(wordOffset)(i) := true.B 30067c26c34SWilliam Wang // data(entryIdx)(wordOffset)(i) := req.data(i*8+7, i*8) 301ad3ba452Szhanglinjuan } 302ad3ba452Szhanglinjuan } 303ad3ba452Szhanglinjuan // check if vtag is the same, if not, trigger sbuffer flush 30467c26c34SWilliam Wang when(reqvtag =/= vtag(entryIdx)) { 305ad3ba452Szhanglinjuan XSDebug("reqvtag =/= sbufvtag req(vtag %x ptag %x) sbuffer(vtag %x ptag %x)\n", 306ad3ba452Szhanglinjuan reqvtag << OffsetWidth, 307ad3ba452Szhanglinjuan reqptag << OffsetWidth, 30867c26c34SWilliam Wang vtag(entryIdx) << OffsetWidth, 30967c26c34SWilliam Wang ptag(entryIdx) << OffsetWidth 310ad3ba452Szhanglinjuan ) 31196b1e495SWilliam Wang merge_need_uarch_drain := true.B 312ad3ba452Szhanglinjuan } 313ad3ba452Szhanglinjuan } 31467c26c34SWilliam Wang }) 31567c26c34SWilliam Wang } 316ad3ba452Szhanglinjuan 31746f74b57SHaojin Tang for(((in, wordOffset), i) <- io.in.zip(words).zipWithIndex){ 318ad3ba452Szhanglinjuan writeReq(i).valid := in.fire() 319ad3ba452Szhanglinjuan writeReq(i).bits.wordOffset := wordOffset 320ad3ba452Szhanglinjuan writeReq(i).bits.mask := in.bits.mask 321ad3ba452Szhanglinjuan writeReq(i).bits.data := in.bits.data 322ca18a0b4SWilliam Wang writeReq(i).bits.wline := in.bits.wline 32346f74b57SHaojin Tang val debug_insertIdx = insertIdxs(i) 32446f74b57SHaojin Tang val insertVec = insertVecs(i) 32567c26c34SWilliam Wang assert(!((PopCount(insertVec) > 1.U) && in.fire())) 32667c26c34SWilliam Wang val insertIdx = OHToUInt(insertVec) 32746f74b57SHaojin Tang val flushMask = if(i == 0) true.B else (0 until i).map(j => !sameTag(i)(j)).reduce(_ && _) 32846f74b57SHaojin Tang flushMask.suggestName(s"flushMask_${i}") 329ad3ba452Szhanglinjuan accessIdx(i).valid := RegNext(in.fire()) 330ad3ba452Szhanglinjuan accessIdx(i).bits := RegNext(Mux(canMerge(i), mergeIdx(i), insertIdx)) 331ad3ba452Szhanglinjuan when(in.fire()){ 332ad3ba452Szhanglinjuan when(canMerge(i)){ 33367c26c34SWilliam Wang // writeReq(i).bits.idx := mergeIdx(i) 33467c26c34SWilliam Wang writeReq(i).bits.wvec := mergeVec(i) 33567c26c34SWilliam Wang mergeWordReq(in.bits, inptags(i), invtags(i), mergeIdx(i), mergeVec(i), wordOffset) 336ad3ba452Szhanglinjuan XSDebug(p"merge req $i to line [${mergeIdx(i)}]\n") 337ad3ba452Szhanglinjuan }.otherwise({ 33867c26c34SWilliam Wang // writeReq(i).bits.idx := insertIdx 33967c26c34SWilliam Wang writeReq(i).bits.wvec := insertVec 34067c26c34SWilliam Wang wordReqToBufLine(in.bits, inptags(i), invtags(i), insertIdx, insertVec, wordOffset, flushMask) 341ad3ba452Szhanglinjuan XSDebug(p"insert req $i to line[$insertIdx]\n") 34267c26c34SWilliam Wang assert(debug_insertIdx === insertIdx) 343ad3ba452Szhanglinjuan }) 344ad3ba452Szhanglinjuan } 345ad3ba452Szhanglinjuan } 346ad3ba452Szhanglinjuan 347ad3ba452Szhanglinjuan 348ad3ba452Szhanglinjuan for(i <- 0 until StoreBufferSize){ 349ad3ba452Szhanglinjuan XSDebug(stateVec(i).isValid(), 350ad3ba452Szhanglinjuan p"[$i] timeout:${cohCount(i)(EvictCountBits-1)} state:${stateVec(i)}\n" 351ad3ba452Szhanglinjuan ) 352ad3ba452Szhanglinjuan } 353ad3ba452Szhanglinjuan 354ad3ba452Szhanglinjuan for((req, i) <- io.in.zipWithIndex){ 355ad3ba452Szhanglinjuan XSDebug(req.fire(), 356ad3ba452Szhanglinjuan p"accept req [$i]: " + 357ad3ba452Szhanglinjuan p"addr:${Hexadecimal(req.bits.addr)} " + 358ad3ba452Szhanglinjuan p"mask:${Binary(req.bits.mask)} " + 359ad3ba452Szhanglinjuan p"data:${Hexadecimal(req.bits.data)}\n" 360ad3ba452Szhanglinjuan ) 361ad3ba452Szhanglinjuan XSDebug(req.valid && !req.ready, 362ad3ba452Szhanglinjuan p"req [$i] blocked by sbuffer\n" 363ad3ba452Szhanglinjuan ) 364ad3ba452Szhanglinjuan } 365ad3ba452Szhanglinjuan 366ad3ba452Szhanglinjuan // ---------------------- Send Dcache Req --------------------- 367ad3ba452Szhanglinjuan 368ad3ba452Szhanglinjuan val sbuffer_empty = Cat(invalidMask).andR() 369ad3ba452Szhanglinjuan val sq_empty = !Cat(io.in.map(_.valid)).orR() 370ad3ba452Szhanglinjuan val empty = sbuffer_empty && sq_empty 371ad3ba452Szhanglinjuan val threshold = RegNext(io.csrCtrl.sbuffer_threshold +& 1.U) 372ad3ba452Szhanglinjuan val validCount = PopCount(activeMask) 373ad3ba452Szhanglinjuan val do_eviction = RegNext(validCount >= threshold || validCount === (StoreBufferSize-1).U, init = false.B) 374ad3ba452Szhanglinjuan require((StoreBufferThreshold + 1) <= StoreBufferSize) 375ad3ba452Szhanglinjuan 376ad3ba452Szhanglinjuan XSDebug(p"validCount[$validCount]\n") 377ad3ba452Szhanglinjuan 378ad3ba452Szhanglinjuan io.flush.empty := RegNext(empty && io.sqempty) 379ad3ba452Szhanglinjuan // lru.io.flush := sbuffer_state === x_drain_all && empty 380ad3ba452Szhanglinjuan switch(sbuffer_state){ 381ad3ba452Szhanglinjuan is(x_idle){ 382ad3ba452Szhanglinjuan when(io.flush.valid){ 383ad3ba452Szhanglinjuan sbuffer_state := x_drain_all 384ad3ba452Szhanglinjuan }.elsewhen(do_uarch_drain){ 385ad3ba452Szhanglinjuan sbuffer_state := x_drain_sbuffer 386ad3ba452Szhanglinjuan }.elsewhen(do_eviction){ 387ad3ba452Szhanglinjuan sbuffer_state := x_replace 388ad3ba452Szhanglinjuan } 389ad3ba452Szhanglinjuan } 390ad3ba452Szhanglinjuan is(x_drain_all){ 391ad3ba452Szhanglinjuan when(empty){ 392ad3ba452Szhanglinjuan sbuffer_state := x_idle 393ad3ba452Szhanglinjuan } 394ad3ba452Szhanglinjuan } 395ad3ba452Szhanglinjuan is(x_drain_sbuffer){ 396a98b054bSWilliam Wang when(io.flush.valid){ 397a98b054bSWilliam Wang sbuffer_state := x_drain_all 398a98b054bSWilliam Wang }.elsewhen(sbuffer_empty){ 399ad3ba452Szhanglinjuan sbuffer_state := x_idle 400ad3ba452Szhanglinjuan } 401ad3ba452Szhanglinjuan } 402ad3ba452Szhanglinjuan is(x_replace){ 403ad3ba452Szhanglinjuan when(io.flush.valid){ 404ad3ba452Szhanglinjuan sbuffer_state := x_drain_all 405ad3ba452Szhanglinjuan }.elsewhen(do_uarch_drain){ 406ad3ba452Szhanglinjuan sbuffer_state := x_drain_sbuffer 407ad3ba452Szhanglinjuan }.elsewhen(!do_eviction){ 408ad3ba452Szhanglinjuan sbuffer_state := x_idle 409ad3ba452Szhanglinjuan } 410ad3ba452Szhanglinjuan } 411ad3ba452Szhanglinjuan } 412ad3ba452Szhanglinjuan XSDebug(p"sbuffer state:${sbuffer_state} do eviction:${do_eviction} empty:${empty}\n") 413ad3ba452Szhanglinjuan 414ad3ba452Szhanglinjuan def noSameBlockInflight(idx: UInt): Bool = { 415ad3ba452Szhanglinjuan // stateVec(idx) itself must not be s_inflight 416ad3ba452Szhanglinjuan !Cat(widthMap(i => inflightMask(i) && ptag(idx) === ptag(i))).orR() 417ad3ba452Szhanglinjuan } 418ad3ba452Szhanglinjuan 419a98b054bSWilliam Wang def genSameBlockInflightMask(ptag_in: UInt): UInt = { 420a98b054bSWilliam Wang val mask = VecInit(widthMap(i => inflightMask(i) && ptag_in === ptag(i))).asUInt // quite slow, use it with care 421a98b054bSWilliam Wang assert(!(PopCount(mask) > 1.U)) 422a98b054bSWilliam Wang mask 423a98b054bSWilliam Wang } 424a98b054bSWilliam Wang 425a98b054bSWilliam Wang def haveSameBlockInflight(ptag_in: UInt): Bool = { 426a98b054bSWilliam Wang genSameBlockInflightMask(ptag_in).orR 427a98b054bSWilliam Wang } 428a98b054bSWilliam Wang 429ad3ba452Szhanglinjuan val need_drain = needDrain(sbuffer_state) 430ad3ba452Szhanglinjuan val need_replace = do_eviction || (sbuffer_state === x_replace) 431ad3ba452Szhanglinjuan val evictionIdx = Mux(missqReplayHasTimeOut, 43296b1e495SWilliam Wang missqReplayTimeOutIdxReg, 433ad3ba452Szhanglinjuan Mux(need_drain, 434ad3ba452Szhanglinjuan drainIdx, 435ad3ba452Szhanglinjuan Mux(cohHasTimeOut, cohTimeOutIdx, replaceIdx) 436ad3ba452Szhanglinjuan ) 437ad3ba452Szhanglinjuan ) 438ad3ba452Szhanglinjuan 439ad3ba452Szhanglinjuan /* 440ad3ba452Szhanglinjuan If there is a inflight dcache req which has same ptag with evictionIdx's ptag, 441ad3ba452Szhanglinjuan current eviction should be blocked. 442ad3ba452Szhanglinjuan */ 443ad3ba452Szhanglinjuan val prepareValid = missqReplayHasTimeOut || 444a98b054bSWilliam Wang stateVec(evictionIdx).isDcacheReqCandidate() && (need_drain || cohHasTimeOut || need_replace) 445a98b054bSWilliam Wang assert(!(stateVec(evictionIdx).isDcacheReqCandidate && !noSameBlockInflight(evictionIdx))) 446ad3ba452Szhanglinjuan val prepareValidReg = RegInit(false.B) 447ad3ba452Szhanglinjuan // when canSendDcacheReq, send dcache req stored in pipeline reg to dcache 448ad3ba452Szhanglinjuan val canSendDcacheReq = io.dcache.req.ready || !prepareValidReg 449ad3ba452Szhanglinjuan // when willSendDcacheReq, read dcache req data and store them in a pipeline reg 45096b1e495SWilliam Wang willSendDcacheReq := prepareValid && canSendDcacheReq 451ad3ba452Szhanglinjuan when(io.dcache.req.fire()){ 452ad3ba452Szhanglinjuan prepareValidReg := false.B 453ad3ba452Szhanglinjuan } 454ad3ba452Szhanglinjuan when(canSendDcacheReq){ 455ad3ba452Szhanglinjuan prepareValidReg := prepareValid 456ad3ba452Szhanglinjuan } 457ad3ba452Szhanglinjuan when(willSendDcacheReq){ 458ad3ba452Szhanglinjuan stateVec(evictionIdx).state_inflight := true.B 459ad3ba452Szhanglinjuan stateVec(evictionIdx).w_timeout := false.B 460ad3ba452Szhanglinjuan // stateVec(evictionIdx).s_pipe_req := true.B 461ad3ba452Szhanglinjuan XSDebug(p"$evictionIdx will be sent to Dcache\n") 462ad3ba452Szhanglinjuan } 463ad3ba452Szhanglinjuan XSDebug(p"need drain:$need_drain cohHasTimeOut: $cohHasTimeOut need replace:$need_replace\n") 464ad3ba452Szhanglinjuan XSDebug(p"drainIdx:$drainIdx tIdx:$cohTimeOutIdx replIdx:$replaceIdx " + 465ad3ba452Szhanglinjuan p"blocked:${!noSameBlockInflight(evictionIdx)} v:${activeMask(evictionIdx)}\n") 466ad3ba452Szhanglinjuan XSDebug(p"prepareValid:$prepareValid evictIdx:$evictionIdx dcache ready:${io.dcache.req.ready}\n") 467ad3ba452Szhanglinjuan // Note: if other dcache req in the same block are inflight, 468ad3ba452Szhanglinjuan // the lru update may not accurate 46946f74b57SHaojin Tang accessIdx(EnsbufferWidth).valid := invalidMask(replaceIdx) || ( 470ad3ba452Szhanglinjuan need_replace && !need_drain && !cohHasTimeOut && !missqReplayHasTimeOut && canSendDcacheReq && activeMask(replaceIdx)) 47146f74b57SHaojin Tang accessIdx(EnsbufferWidth).bits := replaceIdx 472005e809bSJiuyang Liu val evictionIdxReg = RegEnable(evictionIdx, willSendDcacheReq) 473005e809bSJiuyang Liu val evictionPTag = RegEnable(ptag(evictionIdx), willSendDcacheReq) 474005e809bSJiuyang Liu val evictionVTag = RegEnable(vtag(evictionIdx), willSendDcacheReq) 475ad3ba452Szhanglinjuan 476ad3ba452Szhanglinjuan io.dcache.req.valid := prepareValidReg 477ad3ba452Szhanglinjuan io.dcache.req.bits := DontCare 478ad3ba452Szhanglinjuan io.dcache.req.bits.cmd := MemoryOpConstants.M_XWR 479ad3ba452Szhanglinjuan io.dcache.req.bits.addr := getAddr(evictionPTag) 480ad3ba452Szhanglinjuan io.dcache.req.bits.vaddr := getAddr(evictionVTag) 481ad3ba452Szhanglinjuan io.dcache.req.bits.data := data(evictionIdxReg).asUInt 482ad3ba452Szhanglinjuan io.dcache.req.bits.mask := mask(evictionIdxReg).asUInt 483ad3ba452Szhanglinjuan io.dcache.req.bits.id := evictionIdxReg 484ad3ba452Szhanglinjuan 485ad3ba452Szhanglinjuan when (io.dcache.req.fire()) { 486ad3ba452Szhanglinjuan assert(!(io.dcache.req.bits.vaddr === 0.U)) 487ad3ba452Szhanglinjuan assert(!(io.dcache.req.bits.addr === 0.U)) 488ad3ba452Szhanglinjuan } 489ad3ba452Szhanglinjuan 490ad3ba452Szhanglinjuan XSDebug(io.dcache.req.fire(), 491ad3ba452Szhanglinjuan p"send buf [$evictionIdxReg] to Dcache, req fire\n" 492ad3ba452Szhanglinjuan ) 493ad3ba452Szhanglinjuan 494ad3ba452Szhanglinjuan // update sbuffer status according to dcache resp source 495ad3ba452Szhanglinjuan 496a98b054bSWilliam Wang def id_to_sbuffer_id(id: UInt): UInt = { 497a98b054bSWilliam Wang require(id.getWidth >= log2Up(StoreBufferSize)) 498a98b054bSWilliam Wang id(log2Up(StoreBufferSize)-1, 0) 499a98b054bSWilliam Wang } 500a98b054bSWilliam Wang 501ad3ba452Szhanglinjuan // hit resp 502ad3ba452Szhanglinjuan io.dcache.hit_resps.map(resp => { 503ad3ba452Szhanglinjuan val dcache_resp_id = resp.bits.id 504ad3ba452Szhanglinjuan when (resp.fire()) { 505ad3ba452Szhanglinjuan stateVec(dcache_resp_id).state_inflight := false.B 506ad3ba452Szhanglinjuan stateVec(dcache_resp_id).state_valid := false.B 507ad3ba452Szhanglinjuan assert(!resp.bits.replay) 508ad3ba452Szhanglinjuan assert(!resp.bits.miss) // not need to resp if miss, to be opted 509ad3ba452Szhanglinjuan assert(stateVec(dcache_resp_id).state_inflight === true.B) 510ad3ba452Szhanglinjuan } 511a98b054bSWilliam Wang 512a98b054bSWilliam Wang // Update w_sameblock_inflight flag is delayed for 1 cycle 513a98b054bSWilliam Wang // 514a98b054bSWilliam Wang // When a new req allocate a new line in sbuffer, sameblock_inflight check will ignore 515a98b054bSWilliam Wang // current dcache.hit_resps. Then, in the next cycle, we have plenty of time to check 516a98b054bSWilliam Wang // if the same block is still inflight 517a98b054bSWilliam Wang (0 until StoreBufferSize).map(i => { 518a98b054bSWilliam Wang when( 519a98b054bSWilliam Wang stateVec(i).w_sameblock_inflight && 520a98b054bSWilliam Wang stateVec(i).state_valid && 521a98b054bSWilliam Wang RegNext(resp.fire()) && 522a98b054bSWilliam Wang waitInflightMask(i) === UIntToOH(RegNext(id_to_sbuffer_id(dcache_resp_id))) 523a98b054bSWilliam Wang ){ 524a98b054bSWilliam Wang stateVec(i).w_sameblock_inflight := false.B 525a98b054bSWilliam Wang } 526ad3ba452Szhanglinjuan }) 527a98b054bSWilliam Wang }) 528a98b054bSWilliam Wang 529ad3ba452Szhanglinjuan 530ad3ba452Szhanglinjuan // replay resp 531ad3ba452Szhanglinjuan val replay_resp_id = io.dcache.replay_resp.bits.id 532ad3ba452Szhanglinjuan when (io.dcache.replay_resp.fire()) { 533ad3ba452Szhanglinjuan missqReplayCount(replay_resp_id) := 0.U 534ad3ba452Szhanglinjuan stateVec(replay_resp_id).w_timeout := true.B 535ad3ba452Szhanglinjuan // waiting for timeout 536ad3ba452Szhanglinjuan assert(io.dcache.replay_resp.bits.replay) 537ad3ba452Szhanglinjuan assert(stateVec(replay_resp_id).state_inflight === true.B) 538ad3ba452Szhanglinjuan } 539ad3ba452Szhanglinjuan 540ad3ba452Szhanglinjuan // TODO: reuse cohCount 541ad3ba452Szhanglinjuan (0 until StoreBufferSize).map(i => { 542ad3ba452Szhanglinjuan when(stateVec(i).w_timeout && stateVec(i).state_inflight && !missqReplayCount(i)(MissqReplayCountBits-1)) { 543ad3ba452Szhanglinjuan missqReplayCount(i) := missqReplayCount(i) + 1.U 544ad3ba452Szhanglinjuan } 545ad3ba452Szhanglinjuan when(activeMask(i) && !cohTimeOutMask(i)){ 546ad3ba452Szhanglinjuan cohCount(i) := cohCount(i)+1.U 547ad3ba452Szhanglinjuan } 548ad3ba452Szhanglinjuan }) 549ad3ba452Szhanglinjuan 5501545277aSYinan Xu if (env.EnableDifftest) { 551ad3ba452Szhanglinjuan // hit resp 552ad3ba452Szhanglinjuan io.dcache.hit_resps.zipWithIndex.map{case (resp, index) => { 553ad3ba452Szhanglinjuan val difftest = Module(new DifftestSbufferEvent) 554ad3ba452Szhanglinjuan val dcache_resp_id = resp.bits.id 555ad3ba452Szhanglinjuan difftest.io.clock := clock 5565668a921SJiawei Lin difftest.io.coreid := io.hartId 557ad3ba452Szhanglinjuan difftest.io.index := index.U 558ad3ba452Szhanglinjuan difftest.io.sbufferResp := RegNext(resp.fire()) 559ad3ba452Szhanglinjuan difftest.io.sbufferAddr := RegNext(getAddr(ptag(dcache_resp_id))) 560ad3ba452Szhanglinjuan difftest.io.sbufferData := RegNext(data(dcache_resp_id).asTypeOf(Vec(CacheLineBytes, UInt(8.W)))) 561ad3ba452Szhanglinjuan difftest.io.sbufferMask := RegNext(mask(dcache_resp_id).asUInt) 562ad3ba452Szhanglinjuan }} 563ad3ba452Szhanglinjuan } 564ad3ba452Szhanglinjuan 565ad3ba452Szhanglinjuan // ---------------------- Load Data Forward --------------------- 566ad3ba452Szhanglinjuan val mismatch = Wire(Vec(LoadPipelineWidth, Bool())) 56746f74b57SHaojin Tang XSPerfAccumulate("vaddr_match_failed", mismatch.reduce(_ || _)) 568ad3ba452Szhanglinjuan for ((forward, i) <- io.forward.zipWithIndex) { 569ad3ba452Szhanglinjuan val vtag_matches = VecInit(widthMap(w => vtag(w) === getVTag(forward.vaddr))) 570ad3ba452Szhanglinjuan val ptag_matches = VecInit(widthMap(w => ptag(w) === getPTag(forward.paddr))) 571ad3ba452Szhanglinjuan val tag_matches = vtag_matches 572ad3ba452Szhanglinjuan val tag_mismatch = RegNext(forward.valid) && VecInit(widthMap(w => 573ad3ba452Szhanglinjuan RegNext(vtag_matches(w)) =/= RegNext(ptag_matches(w)) && RegNext((activeMask(w) || inflightMask(w))) 574ad3ba452Szhanglinjuan )).asUInt.orR 575ad3ba452Szhanglinjuan mismatch(i) := tag_mismatch 576ad3ba452Szhanglinjuan when (tag_mismatch) { 577ad3ba452Szhanglinjuan XSDebug("forward tag mismatch: pmatch %x vmatch %x vaddr %x paddr %x\n", 578ad3ba452Szhanglinjuan RegNext(ptag_matches.asUInt), 579ad3ba452Szhanglinjuan RegNext(vtag_matches.asUInt), 580ad3ba452Szhanglinjuan RegNext(forward.vaddr), 581ad3ba452Szhanglinjuan RegNext(forward.paddr) 582ad3ba452Szhanglinjuan ) 58396b1e495SWilliam Wang forward_need_uarch_drain := true.B 584ad3ba452Szhanglinjuan } 585ad3ba452Szhanglinjuan val valid_tag_matches = widthMap(w => tag_matches(w) && activeMask(w)) 586ad3ba452Szhanglinjuan val inflight_tag_matches = widthMap(w => tag_matches(w) && inflightMask(w)) 587ad3ba452Szhanglinjuan val line_offset_mask = UIntToOH(getWordOffset(forward.paddr)) 588ad3ba452Szhanglinjuan 589ad3ba452Szhanglinjuan val valid_tag_match_reg = valid_tag_matches.map(RegNext(_)) 590ad3ba452Szhanglinjuan val inflight_tag_match_reg = inflight_tag_matches.map(RegNext(_)) 591ad3ba452Szhanglinjuan val line_offset_reg = RegNext(line_offset_mask) 592a98b054bSWilliam Wang val forward_mask_candidate_reg = RegEnable( 593a98b054bSWilliam Wang VecInit(mask.map(entry => entry(getWordOffset(forward.paddr)))), 594a98b054bSWilliam Wang forward.valid 595a98b054bSWilliam Wang ) 59696b1e495SWilliam Wang val forward_data_candidate_reg = RegEnable( 59796b1e495SWilliam Wang VecInit(data.map(entry => entry(getWordOffset(forward.paddr)))), 59896b1e495SWilliam Wang forward.valid 59996b1e495SWilliam Wang ) 600ad3ba452Szhanglinjuan 601a98b054bSWilliam Wang val selectedValidMask = Mux1H(valid_tag_match_reg, forward_mask_candidate_reg) 60296b1e495SWilliam Wang val selectedValidData = Mux1H(valid_tag_match_reg, forward_data_candidate_reg) 603a98b054bSWilliam Wang selectedValidMask.suggestName("selectedValidMask_"+i) 60496b1e495SWilliam Wang selectedValidData.suggestName("selectedValidData_"+i) 605ad3ba452Szhanglinjuan 606a98b054bSWilliam Wang val selectedInflightMask = Mux1H(inflight_tag_match_reg, forward_mask_candidate_reg) 60796b1e495SWilliam Wang val selectedInflightData = Mux1H(inflight_tag_match_reg, forward_data_candidate_reg) 608a98b054bSWilliam Wang selectedInflightMask.suggestName("selectedInflightMask_"+i) 60996b1e495SWilliam Wang selectedInflightData.suggestName("selectedInflightData_"+i) 610ad3ba452Szhanglinjuan 611a98b054bSWilliam Wang // currently not being used 612ad3ba452Szhanglinjuan val selectedInflightMaskFast = Mux1H(line_offset_mask, Mux1H(inflight_tag_matches, mask).asTypeOf(Vec(CacheLineWords, Vec(DataBytes, Bool())))) 613ad3ba452Szhanglinjuan val selectedValidMaskFast = Mux1H(line_offset_mask, Mux1H(valid_tag_matches, mask).asTypeOf(Vec(CacheLineWords, Vec(DataBytes, Bool())))) 614ad3ba452Szhanglinjuan 615ad3ba452Szhanglinjuan forward.dataInvalid := false.B // data in store line merge buffer is always ready 616ad3ba452Szhanglinjuan forward.matchInvalid := tag_mismatch // paddr / vaddr cam result does not match 617ad3ba452Szhanglinjuan for (j <- 0 until DataBytes) { 618ad3ba452Szhanglinjuan forward.forwardMask(j) := false.B 619ad3ba452Szhanglinjuan forward.forwardData(j) := DontCare 620ad3ba452Szhanglinjuan 621ad3ba452Szhanglinjuan // valid entries have higher priority than inflight entries 622ad3ba452Szhanglinjuan when(selectedInflightMask(j)) { 623ad3ba452Szhanglinjuan forward.forwardMask(j) := true.B 624ad3ba452Szhanglinjuan forward.forwardData(j) := selectedInflightData(j) 625ad3ba452Szhanglinjuan } 626ad3ba452Szhanglinjuan when(selectedValidMask(j)) { 627ad3ba452Szhanglinjuan forward.forwardMask(j) := true.B 628ad3ba452Szhanglinjuan forward.forwardData(j) := selectedValidData(j) 629ad3ba452Szhanglinjuan } 630ad3ba452Szhanglinjuan 631ad3ba452Szhanglinjuan forward.forwardMaskFast(j) := selectedInflightMaskFast(j) || selectedValidMaskFast(j) 632ad3ba452Szhanglinjuan } 633ad3ba452Szhanglinjuan } 634ad3ba452Szhanglinjuan 635ad3ba452Szhanglinjuan for (i <- 0 until StoreBufferSize) { 63696b1e495SWilliam Wang XSDebug("sbf entry " + i + " : ptag %x vtag %x valid %x active %x inflight %x w_timeout %x\n", 637ad3ba452Szhanglinjuan ptag(i) << OffsetWidth, 638ad3ba452Szhanglinjuan vtag(i) << OffsetWidth, 639ad3ba452Szhanglinjuan stateVec(i).isValid(), 640ad3ba452Szhanglinjuan activeMask(i), 641ad3ba452Szhanglinjuan inflightMask(i), 642ad3ba452Szhanglinjuan stateVec(i).w_timeout 643ad3ba452Szhanglinjuan ) 644ad3ba452Szhanglinjuan } 645ad3ba452Szhanglinjuan 646b6d53cefSWilliam Wang val perf_valid_entry_count = RegNext(PopCount(VecInit(stateVec.map(s => !s.isInvalid())).asUInt)) 647ad3ba452Szhanglinjuan XSPerfHistogram("util", perf_valid_entry_count, true.B, 0, StoreBufferSize, 1) 648ad3ba452Szhanglinjuan XSPerfAccumulate("sbuffer_req_valid", PopCount(VecInit(io.in.map(_.valid)).asUInt)) 649ad3ba452Szhanglinjuan XSPerfAccumulate("sbuffer_req_fire", PopCount(VecInit(io.in.map(_.fire())).asUInt)) 650ad3ba452Szhanglinjuan XSPerfAccumulate("sbuffer_merge", PopCount(VecInit(io.in.zipWithIndex.map({case (in, i) => in.fire() && canMerge(i)})).asUInt)) 651ad3ba452Szhanglinjuan XSPerfAccumulate("sbuffer_newline", PopCount(VecInit(io.in.zipWithIndex.map({case (in, i) => in.fire() && !canMerge(i)})).asUInt)) 652ad3ba452Szhanglinjuan XSPerfAccumulate("dcache_req_valid", io.dcache.req.valid) 653ad3ba452Szhanglinjuan XSPerfAccumulate("dcache_req_fire", io.dcache.req.fire()) 654ad3ba452Szhanglinjuan XSPerfAccumulate("sbuffer_idle", sbuffer_state === x_idle) 655ad3ba452Szhanglinjuan XSPerfAccumulate("sbuffer_flush", sbuffer_state === x_drain_sbuffer) 656ad3ba452Szhanglinjuan XSPerfAccumulate("sbuffer_replace", sbuffer_state === x_replace) 65746f74b57SHaojin Tang (0 until EnsbufferWidth).foreach(i => XSPerfAccumulate(s"canInserts_${i}", canInserts(i))) 65896b1e495SWilliam Wang XSPerfAccumulate("mainpipe_resp_valid", io.dcache.main_pipe_hit_resp.fire()) 65996b1e495SWilliam Wang XSPerfAccumulate("refill_resp_valid", io.dcache.refill_hit_resp.fire()) 66096b1e495SWilliam Wang XSPerfAccumulate("replay_resp_valid", io.dcache.replay_resp.fire()) 66196b1e495SWilliam Wang XSPerfAccumulate("coh_timeout", cohHasTimeOut) 66296b1e495SWilliam Wang 66396b1e495SWilliam Wang // val (store_latency_sample, store_latency) = TransactionLatencyCounter(io.lsu.req.fire(), io.lsu.resp.fire()) 66496b1e495SWilliam Wang // XSPerfHistogram("store_latency", store_latency, store_latency_sample, 0, 100, 10) 66596b1e495SWilliam Wang // XSPerfAccumulate("store_req", io.lsu.req.fire()) 666cd365d4cSrvcoresjw 667cd365d4cSrvcoresjw val perfEvents = Seq( 668cd365d4cSrvcoresjw ("sbuffer_req_valid ", PopCount(VecInit(io.in.map(_.valid)).asUInt) ), 669cd365d4cSrvcoresjw ("sbuffer_req_fire ", PopCount(VecInit(io.in.map(_.fire())).asUInt) ), 670cd365d4cSrvcoresjw ("sbuffer_merge ", PopCount(VecInit(io.in.zipWithIndex.map({case (in, i) => in.fire() && canMerge(i)})).asUInt) ), 671cd365d4cSrvcoresjw ("sbuffer_newline ", PopCount(VecInit(io.in.zipWithIndex.map({case (in, i) => in.fire() && !canMerge(i)})).asUInt) ), 672cd365d4cSrvcoresjw ("dcache_req_valid ", io.dcache.req.valid ), 673cd365d4cSrvcoresjw ("dcache_req_fire ", io.dcache.req.fire() ), 67496b1e495SWilliam Wang ("sbuffer_idle ", sbuffer_state === x_idle ), 67596b1e495SWilliam Wang ("sbuffer_flush ", sbuffer_state === x_drain_sbuffer ), 67696b1e495SWilliam Wang ("sbuffer_replace ", sbuffer_state === x_replace ), 67796b1e495SWilliam Wang ("mpipe_resp_valid ", io.dcache.main_pipe_hit_resp.fire() ), 67896b1e495SWilliam Wang ("refill_resp_valid ", io.dcache.refill_hit_resp.fire() ), 67996b1e495SWilliam Wang ("replay_resp_valid ", io.dcache.replay_resp.fire() ), 68096b1e495SWilliam Wang ("coh_timeout ", cohHasTimeOut ), 6811ca0e4f3SYinan Xu ("sbuffer_1_4_valid ", (perf_valid_entry_count < (StoreBufferSize.U/4.U)) ), 6821ca0e4f3SYinan Xu ("sbuffer_2_4_valid ", (perf_valid_entry_count > (StoreBufferSize.U/4.U)) & (perf_valid_entry_count <= (StoreBufferSize.U/2.U)) ), 6831ca0e4f3SYinan Xu ("sbuffer_3_4_valid ", (perf_valid_entry_count > (StoreBufferSize.U/2.U)) & (perf_valid_entry_count <= (StoreBufferSize.U*3.U/4.U))), 684cd365d4cSrvcoresjw ("sbuffer_full_valid", (perf_valid_entry_count > (StoreBufferSize.U*3.U/4.U))) 685cd365d4cSrvcoresjw ) 6861ca0e4f3SYinan Xu generatePerfEvent() 687cd365d4cSrvcoresjw 688ad3ba452Szhanglinjuan} 689