1*1d8f4dcbSJay/*************************************************************************************** 2*1d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*1d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*1d8f4dcbSJay* 5*1d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 6*1d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*1d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 8*1d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 9*1d8f4dcbSJay* 10*1d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*1d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*1d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*1d8f4dcbSJay* 14*1d8f4dcbSJay* See the Mulan PSL v2 for more details. 15*1d8f4dcbSJay***************************************************************************************/ 16*1d8f4dcbSJay 17*1d8f4dcbSJaypackage xiangshan.frontend.icache 18*1d8f4dcbSJay 19*1d8f4dcbSJayimport chipsalliance.rocketchip.config.Parameters 20*1d8f4dcbSJayimport chisel3._ 21*1d8f4dcbSJayimport chisel3.util._ 22*1d8f4dcbSJayimport freechips.rocketchip.tilelink.ClientStates 23*1d8f4dcbSJayimport xiangshan._ 24*1d8f4dcbSJayimport xiangshan.cache.mmu._ 25*1d8f4dcbSJayimport utils._ 26*1d8f4dcbSJayimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 27*1d8f4dcbSJay 28*1d8f4dcbSJayclass ICacheMainPipeReq(implicit p: Parameters) extends ICacheBundle 29*1d8f4dcbSJay{ 30*1d8f4dcbSJay val vaddr = UInt(VAddrBits.W) 31*1d8f4dcbSJay def vsetIdx = get_idx(vaddr) 32*1d8f4dcbSJay} 33*1d8f4dcbSJay 34*1d8f4dcbSJayclass ICacheMainPipeResp(implicit p: Parameters) extends ICacheBundle 35*1d8f4dcbSJay{ 36*1d8f4dcbSJay val vaddr = UInt(VAddrBits.W) 37*1d8f4dcbSJay val readData = UInt(blockBits.W) 38*1d8f4dcbSJay val paddr = UInt(PAddrBits.W) 39*1d8f4dcbSJay val tlbExcp = new Bundle{ 40*1d8f4dcbSJay val pageFault = Bool() 41*1d8f4dcbSJay val accessFault = Bool() 42*1d8f4dcbSJay val mmio = Bool() 43*1d8f4dcbSJay } 44*1d8f4dcbSJay} 45*1d8f4dcbSJay 46*1d8f4dcbSJayclass ICacheMainPipeBundle(implicit p: Parameters) extends ICacheBundle 47*1d8f4dcbSJay{ 48*1d8f4dcbSJay val req = Flipped(DecoupledIO(new ICacheMainPipeReq)) 49*1d8f4dcbSJay val resp = ValidIO(new ICacheMainPipeResp) 50*1d8f4dcbSJay} 51*1d8f4dcbSJay 52*1d8f4dcbSJayclass ICacheMetaReqBundle(implicit p: Parameters) extends ICacheBundle{ 53*1d8f4dcbSJay val toIMeta = Decoupled(new ICacheReadBundle) 54*1d8f4dcbSJay val fromIMeta = Input(new ICacheMetaRespBundle) 55*1d8f4dcbSJay} 56*1d8f4dcbSJay 57*1d8f4dcbSJayclass ICacheDataReqBundle(implicit p: Parameters) extends ICacheBundle{ 58*1d8f4dcbSJay val toIData = Decoupled(new ICacheReadBundle) 59*1d8f4dcbSJay val fromIData = Input(new ICacheDataRespBundle) 60*1d8f4dcbSJay} 61*1d8f4dcbSJay 62*1d8f4dcbSJayclass ICacheMSHRBundle(implicit p: Parameters) extends ICacheBundle{ 63*1d8f4dcbSJay val toMSHR = Decoupled(new ICacheMissReq) 64*1d8f4dcbSJay val fromMSHR = Flipped(ValidIO(new ICacheMissResp)) 65*1d8f4dcbSJay} 66*1d8f4dcbSJay 67*1d8f4dcbSJayclass ICachePMPBundle(implicit p: Parameters) extends ICacheBundle{ 68*1d8f4dcbSJay val req = Valid(new PMPReqBundle()) 69*1d8f4dcbSJay val resp = Input(new PMPRespBundle()) 70*1d8f4dcbSJay} 71*1d8f4dcbSJay 72*1d8f4dcbSJayclass ICachePerfInfo(implicit p: Parameters) extends ICacheBundle{ 73*1d8f4dcbSJay val only_0_hit = Bool() 74*1d8f4dcbSJay val only_0_miss = Bool() 75*1d8f4dcbSJay val hit_0_hit_1 = Bool() 76*1d8f4dcbSJay val hit_0_miss_1 = Bool() 77*1d8f4dcbSJay val miss_0_hit_1 = Bool() 78*1d8f4dcbSJay val miss_0_miss_1 = Bool() 79*1d8f4dcbSJay val bank_hit = Vec(2,Bool()) 80*1d8f4dcbSJay val hit = Bool() 81*1d8f4dcbSJay} 82*1d8f4dcbSJay 83*1d8f4dcbSJayclass ICacheMainPipeInterface(implicit p: Parameters) extends ICacheBundle { 84*1d8f4dcbSJay /* internal interface */ 85*1d8f4dcbSJay val metaArray = new ICacheMetaReqBundle 86*1d8f4dcbSJay val dataArray = new ICacheDataReqBundle 87*1d8f4dcbSJay val mshr = Vec(PortNumber, new ICacheMSHRBundle) 88*1d8f4dcbSJay /* outside interface */ 89*1d8f4dcbSJay val fetch = Vec(PortNumber, new ICacheMainPipeBundle) 90*1d8f4dcbSJay val pmp = Vec(PortNumber, new ICachePMPBundle) 91*1d8f4dcbSJay val itlb = Vec(PortNumber, new BlockTlbRequestIO) 92*1d8f4dcbSJay val respStall = Input(Bool()) 93*1d8f4dcbSJay val toReleaseUnit = Vec(2, Decoupled(new ReleaseReq)) 94*1d8f4dcbSJay val victimInfor = new Bundle() { 95*1d8f4dcbSJay val s1 = Vec(2, Output(new ICacheVictimInfor())) 96*1d8f4dcbSJay val s2 = Vec(2, Output(new ICacheVictimInfor())) 97*1d8f4dcbSJay } 98*1d8f4dcbSJay val setInfor = new Bundle(){ 99*1d8f4dcbSJay val s1 = Vec(2, Output(new ICacheSetInfor())) 100*1d8f4dcbSJay val s2 = Vec(2, Output(new ICacheSetInfor())) 101*1d8f4dcbSJay } 102*1d8f4dcbSJay val perfInfo = Output(new ICachePerfInfo) 103*1d8f4dcbSJay} 104*1d8f4dcbSJay 105*1d8f4dcbSJayclass ICacheMainPipe(implicit p: Parameters) extends ICacheModule 106*1d8f4dcbSJay{ 107*1d8f4dcbSJay val io = IO(new ICacheMainPipeInterface) 108*1d8f4dcbSJay 109*1d8f4dcbSJay val (fromIFU, toIFU) = (io.fetch.map(_.req), io.fetch.map(_.resp)) 110*1d8f4dcbSJay val (toMeta, toData, metaResp, dataResp) = (io.metaArray.toIMeta, io.dataArray.toIData, io.metaArray.fromIMeta, io.dataArray.fromIData) 111*1d8f4dcbSJay val (toMSHR, fromMSHR) = (io.mshr.map(_.toMSHR), io.mshr.map(_.fromMSHR)) 112*1d8f4dcbSJay val (toITLB, fromITLB) = (io.itlb.map(_.req), io.itlb.map(_.resp)) 113*1d8f4dcbSJay val (toPMP, fromPMP) = (io.pmp.map(_.req), io.pmp.map(_.resp)) 114*1d8f4dcbSJay 115*1d8f4dcbSJay def generatePipeControl(lastFire: Bool, thisFire: Bool, thisFlush: Bool, lastFlush: Bool): Bool = { 116*1d8f4dcbSJay val valid = RegInit(false.B) 117*1d8f4dcbSJay when(thisFlush) {valid := false.B} 118*1d8f4dcbSJay .elsewhen(lastFire && !lastFlush) {valid := true.B} 119*1d8f4dcbSJay .elsewhen(thisFire) {valid := false.B} 120*1d8f4dcbSJay valid 121*1d8f4dcbSJay } 122*1d8f4dcbSJay 123*1d8f4dcbSJay def ResultHoldBypass[T<:Data](data: T, valid: Bool): T = { 124*1d8f4dcbSJay Mux(valid, data, RegEnable(data, valid)) 125*1d8f4dcbSJay } 126*1d8f4dcbSJay 127*1d8f4dcbSJay val s0_ready, s1_ready, s2_ready = WireInit(false.B) 128*1d8f4dcbSJay val s0_fire, s1_fire , s2_fire = WireInit(false.B) 129*1d8f4dcbSJay 130*1d8f4dcbSJay //Stage 1 131*1d8f4dcbSJay val s0_valid = fromIFU.map(_.valid).reduce(_||_) 132*1d8f4dcbSJay val s0_req_vaddr = VecInit(fromIFU.map(_.bits.vaddr)) 133*1d8f4dcbSJay val s0_req_vsetIdx = VecInit(fromIFU.map(_.bits.vsetIdx)) 134*1d8f4dcbSJay val s0_only_fisrt = fromIFU(0).valid && !fromIFU(0).valid 135*1d8f4dcbSJay val s0_double_line = fromIFU(0).valid && fromIFU(1).valid 136*1d8f4dcbSJay 137*1d8f4dcbSJay s0_fire := s0_valid && s1_ready 138*1d8f4dcbSJay 139*1d8f4dcbSJay //fetch: send addr to Meta/TLB and Data simultaneously 140*1d8f4dcbSJay val fetch_req = List(toMeta, toData) 141*1d8f4dcbSJay for(i <- 0 until 2) { 142*1d8f4dcbSJay fetch_req(i).valid := s0_fire 143*1d8f4dcbSJay fetch_req(i).bits.isDoubleLine := s0_double_line 144*1d8f4dcbSJay fetch_req(i).bits.vSetIdx := s0_req_vsetIdx 145*1d8f4dcbSJay } 146*1d8f4dcbSJay //TODO: fix GTimer() condition 147*1d8f4dcbSJay fromIFU.map(_.ready := fetch_req(0).ready && fetch_req(1).ready && s1_ready && GTimer() > 500.U) 148*1d8f4dcbSJay 149*1d8f4dcbSJay 150*1d8f4dcbSJay// XSPerfAccumulate("ifu_bubble_ftq_not_valid", !f0_valid ) 151*1d8f4dcbSJay// XSPerfAccumulate("ifu_bubble_pipe_stall", f0_valid && fetch_req(0).ready && fetch_req(1).ready && !s1_ready ) 152*1d8f4dcbSJay// XSPerfAccumulate("ifu_bubble_sram_0_busy", f0_valid && !fetch_req(0).ready ) 153*1d8f4dcbSJay// XSPerfAccumulate("ifu_bubble_sram_1_busy", f0_valid && !fetch_req(1).ready ) 154*1d8f4dcbSJay 155*1d8f4dcbSJay //--------------------------------------------- 156*1d8f4dcbSJay // Fetch Stage 2 : 157*1d8f4dcbSJay // * Send req to ITLB and TLB Response (Get Paddr) 158*1d8f4dcbSJay // * ICache Response (Get Meta and Data) 159*1d8f4dcbSJay // * Hit Check (Generate hit signal and hit vector) 160*1d8f4dcbSJay // * Get victim way 161*1d8f4dcbSJay //--------------------------------------------- 162*1d8f4dcbSJay 163*1d8f4dcbSJay //TODO: handle fetch exceptions 164*1d8f4dcbSJay 165*1d8f4dcbSJay val tlbRespAllValid = WireInit(false.B) 166*1d8f4dcbSJay 167*1d8f4dcbSJay val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = false.B, lastFlush = false.B) 168*1d8f4dcbSJay 169*1d8f4dcbSJay val s1_req_vaddr = RegEnable(next = s0_req_vaddr, enable = s0_fire) 170*1d8f4dcbSJay val s1_req_vsetIdx = RegEnable(next = s0_req_vsetIdx, enable = s0_fire) 171*1d8f4dcbSJay val s1_only_fisrt = RegEnable(next = s0_only_fisrt, enable = s0_fire) 172*1d8f4dcbSJay val s1_double_line = RegEnable(next = s0_double_line, enable = s0_fire) 173*1d8f4dcbSJay 174*1d8f4dcbSJay s1_ready := s2_ready && tlbRespAllValid || !s1_valid 175*1d8f4dcbSJay s1_fire := s1_valid && tlbRespAllValid && s2_ready 176*1d8f4dcbSJay 177*1d8f4dcbSJay toITLB(0).valid := s1_valid 178*1d8f4dcbSJay toITLB(0).bits.size := 3.U // TODO: fix the size 179*1d8f4dcbSJay toITLB(0).bits.vaddr := s1_req_vaddr(0) 180*1d8f4dcbSJay toITLB(0).bits.debug.pc := s1_req_vaddr(0) 181*1d8f4dcbSJay 182*1d8f4dcbSJay toITLB(1).valid := s1_valid && s1_double_line 183*1d8f4dcbSJay toITLB(1).bits.size := 3.U // TODO: fix the size 184*1d8f4dcbSJay toITLB(1).bits.vaddr := s1_req_vaddr(1) 185*1d8f4dcbSJay toITLB(1).bits.debug.pc := s1_req_vaddr(1) 186*1d8f4dcbSJay 187*1d8f4dcbSJay toITLB.map{port => 188*1d8f4dcbSJay port.bits.cmd := TlbCmd.exec 189*1d8f4dcbSJay port.bits.robIdx := DontCare 190*1d8f4dcbSJay port.bits.debug.isFirstIssue := DontCare 191*1d8f4dcbSJay } 192*1d8f4dcbSJay 193*1d8f4dcbSJay fromITLB.map(_.ready := true.B) 194*1d8f4dcbSJay 195*1d8f4dcbSJay val (tlbRespValid, tlbRespPAddr) = (fromITLB.map(_.valid), VecInit(fromITLB.map(_.bits.paddr))) 196*1d8f4dcbSJay val (tlbRespMiss) = fromITLB.map(port => port.bits.miss && port.valid) 197*1d8f4dcbSJay val (tlbExcpPF, tlbExcpAF) = (fromITLB.map(port => port.bits.excp.pf.instr && port.valid), 198*1d8f4dcbSJay fromITLB.map(port => (port.bits.excp.af.instr) && port.valid)) 199*1d8f4dcbSJay 200*1d8f4dcbSJay tlbRespAllValid := tlbRespValid(0) && (tlbRespValid(1) || !s1_double_line) 201*1d8f4dcbSJay 202*1d8f4dcbSJay val s1_req_paddr = tlbRespPAddr 203*1d8f4dcbSJay val s1_req_ptags = VecInit(s1_req_paddr.map(get_phy_tag(_))) 204*1d8f4dcbSJay 205*1d8f4dcbSJay val s1_meta_ptags = ResultHoldBypass(data = metaResp.tags, valid = RegNext(toMeta.fire())) 206*1d8f4dcbSJay val s1_meta_cohs = ResultHoldBypass(data = metaResp.cohs, valid = RegNext(toMeta.fire())) 207*1d8f4dcbSJay val s1_data_cacheline = ResultHoldBypass(data = dataResp.datas, valid = RegNext(toData.fire())) 208*1d8f4dcbSJay 209*1d8f4dcbSJay val s1_tag_eq_vec = VecInit((0 until PortNumber).map( p => VecInit((0 until nWays).map( w => s1_meta_ptags(p)(w) === s1_req_ptags(p) )))) 210*1d8f4dcbSJay val s1_tag_match_vec = VecInit((0 until PortNumber).map( k => VecInit(s1_tag_eq_vec(k).zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s1_meta_cohs(k)(w).isValid()}))) 211*1d8f4dcbSJay val s1_tag_match = VecInit(s1_tag_match_vec.map(vector => ParallelOR(vector))) 212*1d8f4dcbSJay 213*1d8f4dcbSJay val s1_port_hit = VecInit(Seq(s1_tag_match(0) && s1_valid && !tlbExcpPF(0) && !tlbExcpAF(0), s1_tag_match(1) && s1_valid && s1_double_line && !tlbExcpPF(1) && !tlbExcpAF(1) )) 214*1d8f4dcbSJay val s1_bank_miss = VecInit(Seq(!s1_tag_match(0) && s1_valid && !tlbExcpPF(0) && !tlbExcpAF(0), !s1_tag_match(1) && s1_valid && s1_double_line && !tlbExcpPF(1) && !tlbExcpAF(1) )) 215*1d8f4dcbSJay val s1_hit = (s1_port_hit(0) && s1_port_hit(1)) || (!s1_double_line && s1_port_hit(0)) 216*1d8f4dcbSJay 217*1d8f4dcbSJay /** choose victim cacheline */ 218*1d8f4dcbSJay val replacers = Seq.fill(PortNumber)(ReplacementPolicy.fromString(cacheParams.replacer,nWays,nSets/PortNumber)) 219*1d8f4dcbSJay val s1_victim_oh = ResultHoldBypass(data = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(s1_req_vsetIdx(i)))}), valid = RegNext(toMeta.fire())) 220*1d8f4dcbSJay 221*1d8f4dcbSJay val s1_victim_coh = VecInit(s1_victim_oh.zipWithIndex.map {case(oh, port) => Mux1H(oh, s1_meta_cohs(port))}) 222*1d8f4dcbSJay val s1_victim_tag = VecInit(s1_victim_oh.zipWithIndex.map {case(oh, port) => Mux1H(oh, s1_meta_ptags(port))}) 223*1d8f4dcbSJay val s1_victim_data = VecInit(s1_victim_oh.zipWithIndex.map {case(oh, port) => Mux1H(oh, s1_data_cacheline(port))}) 224*1d8f4dcbSJay val s1_need_replace = VecInit(s1_victim_coh.zipWithIndex.map{case(coh, port) => coh.isValid() && s1_bank_miss(port)}) 225*1d8f4dcbSJay 226*1d8f4dcbSJay (0 until PortNumber).map{ i => 227*1d8f4dcbSJay io.victimInfor.s1(i).valid := s1_valid && s1_need_replace(i) 228*1d8f4dcbSJay io.victimInfor.s1(i).ptag := s1_victim_tag(i) 229*1d8f4dcbSJay io.victimInfor.s1(i).vidx := get_idx(s1_req_vaddr(i)) 230*1d8f4dcbSJay } 231*1d8f4dcbSJay 232*1d8f4dcbSJay (0 until PortNumber).map{ i => 233*1d8f4dcbSJay io.setInfor.s1(i).valid := s1_bank_miss(i) 234*1d8f4dcbSJay io.setInfor.s1(i).vidx := s1_req_vsetIdx(i) 235*1d8f4dcbSJay } 236*1d8f4dcbSJay 237*1d8f4dcbSJay assert(PopCount(s1_tag_match_vec(0)) <= 1.U && PopCount(s1_tag_match_vec(1)) <= 1.U, "Multiple hit in main pipe") 238*1d8f4dcbSJay 239*1d8f4dcbSJay val touch_sets = Seq.fill(2)(Wire(Vec(2, UInt(log2Ceil(nSets/2).W)))) 240*1d8f4dcbSJay val touch_ways = Seq.fill(2)(Wire(Vec(2, Valid(UInt(log2Ceil(nWays).W)))) ) 241*1d8f4dcbSJay 242*1d8f4dcbSJay ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)} 243*1d8f4dcbSJay 244*1d8f4dcbSJay val s1_hit_data = VecInit(s1_data_cacheline.zipWithIndex.map { case(bank, i) => 245*1d8f4dcbSJay val port_hit_data = Mux1H(s1_tag_match_vec(i).asUInt, bank) 246*1d8f4dcbSJay port_hit_data 247*1d8f4dcbSJay }) 248*1d8f4dcbSJay 249*1d8f4dcbSJay (0 until nWays).map{ w => 250*1d8f4dcbSJay XSPerfAccumulate("line_0_hit_way_" + Integer.toString(w, 10), s1_fire && s1_port_hit(0) && OHToUInt(s1_tag_match_vec(0)) === w.U) 251*1d8f4dcbSJay } 252*1d8f4dcbSJay 253*1d8f4dcbSJay (0 until nWays).map{ w => 254*1d8f4dcbSJay XSPerfAccumulate("line_0_victim_way_" + Integer.toString(w, 10), s1_fire && !s1_port_hit(0) && OHToUInt(s1_victim_oh(0)) === w.U) 255*1d8f4dcbSJay } 256*1d8f4dcbSJay 257*1d8f4dcbSJay (0 until nWays).map{ w => 258*1d8f4dcbSJay XSPerfAccumulate("line_1_hit_way_" + Integer.toString(w, 10), s1_fire && s1_double_line && s1_port_hit(1) && OHToUInt(s1_tag_match_vec(1)) === w.U) 259*1d8f4dcbSJay } 260*1d8f4dcbSJay 261*1d8f4dcbSJay (0 until nWays).map{ w => 262*1d8f4dcbSJay XSPerfAccumulate("line_1_victim_way_" + Integer.toString(w, 10), s1_fire && s1_double_line && !s1_port_hit(1) && OHToUInt(s1_victim_oh(1)) === w.U) 263*1d8f4dcbSJay } 264*1d8f4dcbSJay 265*1d8f4dcbSJay XSPerfAccumulate("ifu_bubble_s1_tlb_miss", s1_valid && !tlbRespAllValid ) 266*1d8f4dcbSJay 267*1d8f4dcbSJay //--------------------------------------------- 268*1d8f4dcbSJay // Fetch Stage 2 : 269*1d8f4dcbSJay // * get data from last stage (hit from s1_hit_data/miss from missQueue response) 270*1d8f4dcbSJay // * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!! 271*1d8f4dcbSJay // * cut cacheline(s) and send to PreDecode 272*1d8f4dcbSJay // * check if prediction is right (branch target and type, jump direction and type , jal target ) 273*1d8f4dcbSJay //--------------------------------------------- 274*1d8f4dcbSJay val s2_fetch_finish = Wire(Bool()) 275*1d8f4dcbSJay 276*1d8f4dcbSJay val s2_valid = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = false.B, lastFlush = false.B) 277*1d8f4dcbSJay val s2_miss_available = Wire(Bool()) 278*1d8f4dcbSJay 279*1d8f4dcbSJay s2_ready := (s2_valid && s2_fetch_finish && !io.respStall) || (!s2_valid && s2_miss_available) 280*1d8f4dcbSJay s2_fire := s2_valid && s2_fetch_finish && !io.respStall 281*1d8f4dcbSJay 282*1d8f4dcbSJay val pmpExcpAF = fromPMP.map(port => port.instr) 283*1d8f4dcbSJay val mmio = fromPMP.map(port => port.mmio) // TODO: handle it 284*1d8f4dcbSJay 285*1d8f4dcbSJay val (s2_req_paddr , s2_req_vaddr) = (RegEnable(next = s1_req_paddr, enable = s1_fire), RegEnable(next = s1_req_vaddr, enable = s1_fire)) 286*1d8f4dcbSJay val s2_req_vsetIdx = RegEnable(next = s1_req_vsetIdx, enable = s1_fire) 287*1d8f4dcbSJay val s2_req_ptags = RegEnable(next = s1_req_ptags, enable = s1_fire) 288*1d8f4dcbSJay val s2_only_fisrt = RegEnable(next = s1_only_fisrt, enable = s1_fire) 289*1d8f4dcbSJay val s2_double_line = RegEnable(next = s1_double_line, enable = s1_fire) 290*1d8f4dcbSJay val s2_hit = RegEnable(next = s1_hit , enable = s1_fire) 291*1d8f4dcbSJay val s2_port_hit = RegEnable(next = s1_port_hit, enable = s1_fire) 292*1d8f4dcbSJay val s2_bank_miss = RegEnable(next = s1_bank_miss, enable = s1_fire) 293*1d8f4dcbSJay 294*1d8f4dcbSJay val sec_meet_vec = Wire(Vec(2, Bool())) 295*1d8f4dcbSJay val s2_fixed_hit_vec = VecInit((0 until 2).map(i => s2_port_hit(i) || sec_meet_vec(i))) 296*1d8f4dcbSJay val s2_fixed_hit = (s2_valid && s2_fixed_hit_vec(0) && s2_fixed_hit_vec(1) && s2_double_line) || (s2_valid && s2_fixed_hit_vec(0) && !s2_double_line) 297*1d8f4dcbSJay 298*1d8f4dcbSJay //replacement 299*1d8f4dcbSJay val s2_waymask = RegEnable(next = s1_victim_oh, enable = s1_fire) 300*1d8f4dcbSJay val s2_victim_coh = RegEnable(next = s1_victim_coh, enable = s1_fire) 301*1d8f4dcbSJay val s2_victim_tag = RegEnable(next = s1_victim_tag, enable = s1_fire) 302*1d8f4dcbSJay val s2_victim_data = RegEnable(next = s1_victim_data, enable = s1_fire) 303*1d8f4dcbSJay val s2_need_replace = RegEnable(next = s1_need_replace, enable = s1_fire) 304*1d8f4dcbSJay val s2_has_replace = s2_need_replace.asUInt.orR 305*1d8f4dcbSJay 306*1d8f4dcbSJay /*** exception and pmp logic ***/ 307*1d8f4dcbSJay //exception information 308*1d8f4dcbSJay val s2_except_pf = RegEnable(next = VecInit(tlbExcpPF), enable = s1_fire) 309*1d8f4dcbSJay val s2_except_af = VecInit(RegEnable(next = VecInit(tlbExcpAF), enable = s1_fire).zip(pmpExcpAF).map(a => a._1 || DataHoldBypass(a._2, RegNext(s1_fire)).asBool)) 310*1d8f4dcbSJay val s2_except = VecInit((0 until 2).map{i => s2_except_pf(i) || s2_except_af(i)}) 311*1d8f4dcbSJay val s2_has_except = s2_valid && (s2_except_af.reduce(_||_) || s2_except_pf.reduce(_||_)) 312*1d8f4dcbSJay //MMIO 313*1d8f4dcbSJay val s2_mmio = DataHoldBypass(io.pmp(0).resp.mmio && !s2_except_af(0) && !s2_except_pf(0), RegNext(s1_fire)).asBool() 314*1d8f4dcbSJay 315*1d8f4dcbSJay io.pmp.zipWithIndex.map { case (p, i) => 316*1d8f4dcbSJay p.req.valid := s2_fire 317*1d8f4dcbSJay p.req.bits.addr := s2_req_paddr(i) 318*1d8f4dcbSJay p.req.bits.size := 3.U // TODO 319*1d8f4dcbSJay p.req.bits.cmd := TlbCmd.exec 320*1d8f4dcbSJay } 321*1d8f4dcbSJay 322*1d8f4dcbSJay /*** cacheline miss logic ***/ 323*1d8f4dcbSJay val wait_idle :: wait_queue_ready :: wait_send_req :: wait_two_resp :: wait_0_resp :: wait_1_resp :: wait_one_resp ::wait_finish :: Nil = Enum(8) 324*1d8f4dcbSJay val wait_state = RegInit(wait_idle) 325*1d8f4dcbSJay 326*1d8f4dcbSJay val port_miss_fix = VecInit(Seq(fromMSHR(0).fire() && !s2_port_hit(0), fromMSHR(1).fire() && s2_double_line && !s2_port_hit(1) )) 327*1d8f4dcbSJay 328*1d8f4dcbSJay class MissSlot(implicit p: Parameters) extends XSBundle with HasICacheParameters { 329*1d8f4dcbSJay val m_vSetIdx = UInt(idxBits.W) 330*1d8f4dcbSJay val m_pTag = UInt(tagBits.W) 331*1d8f4dcbSJay val m_data = UInt(blockBits.W) 332*1d8f4dcbSJay } 333*1d8f4dcbSJay 334*1d8f4dcbSJay val missSlot = Seq.fill(2)(RegInit(0.U.asTypeOf(new MissSlot))) 335*1d8f4dcbSJay val m_invalid :: m_valid :: m_refilled :: m_flushed :: m_wait_sec_miss :: m_check_final ::Nil = Enum(6) 336*1d8f4dcbSJay val missStateQueue = RegInit(VecInit(Seq.fill(2)(m_invalid)) ) 337*1d8f4dcbSJay val reservedRefillData = Wire(Vec(2, UInt(blockBits.W))) 338*1d8f4dcbSJay 339*1d8f4dcbSJay s2_miss_available := VecInit(missStateQueue.map(entry => entry === m_invalid || entry === m_wait_sec_miss)).reduce(_&&_) 340*1d8f4dcbSJay 341*1d8f4dcbSJay val fix_sec_miss = Wire(Vec(4, Bool())) 342*1d8f4dcbSJay val sec_meet_0_miss = fix_sec_miss(0) || fix_sec_miss(2) 343*1d8f4dcbSJay val sec_meet_1_miss = fix_sec_miss(1) || fix_sec_miss(3) 344*1d8f4dcbSJay sec_meet_vec := VecInit(Seq(sec_meet_0_miss,sec_meet_1_miss )) 345*1d8f4dcbSJay 346*1d8f4dcbSJay //only raise at the first cycle of s2_valid 347*1d8f4dcbSJay val only_0_miss = RegNext(s1_fire) && !s2_hit && !s2_double_line && !s2_has_except && !sec_meet_0_miss && !s2_mmio 348*1d8f4dcbSJay val only_0_hit = RegNext(s1_fire) && s2_hit && !s2_double_line && !s2_mmio 349*1d8f4dcbSJay val hit_0_hit_1 = RegNext(s1_fire) && s2_hit && s2_double_line && !s2_mmio 350*1d8f4dcbSJay val hit_0_miss_1 = RegNext(s1_fire) && !s2_port_hit(1) && !sec_meet_1_miss && (s2_port_hit(0) || sec_meet_0_miss) && s2_double_line && !s2_has_except && !s2_mmio 351*1d8f4dcbSJay val miss_0_hit_1 = RegNext(s1_fire) && !s2_port_hit(0) && !sec_meet_0_miss && (s2_port_hit(1) || sec_meet_1_miss) && s2_double_line && !s2_has_except && !s2_mmio 352*1d8f4dcbSJay val miss_0_miss_1 = RegNext(s1_fire) && !s2_port_hit(0) && !s2_port_hit(1) && !sec_meet_0_miss && !sec_meet_1_miss && s2_double_line && !s2_has_except && !s2_mmio 353*1d8f4dcbSJay 354*1d8f4dcbSJay val hit_0_except_1 = RegNext(s1_fire) && s2_double_line && !s2_except(0) && s2_except(1) && s2_port_hit(0) 355*1d8f4dcbSJay val miss_0_except_1 = RegNext(s1_fire) && s2_double_line && !s2_except(0) && s2_except(1) && !s2_port_hit(0) 356*1d8f4dcbSJay val except_0 = RegNext(s1_fire) && s2_except(0) 357*1d8f4dcbSJay 358*1d8f4dcbSJay def holdReleaseLatch(valid: Bool, release: Bool, flush: Bool): Bool ={ 359*1d8f4dcbSJay val bit = RegInit(false.B) 360*1d8f4dcbSJay when(flush) { bit := false.B } 361*1d8f4dcbSJay .elsewhen(valid && !release) { bit := true.B } 362*1d8f4dcbSJay .elsewhen(release) { bit := false.B} 363*1d8f4dcbSJay bit || valid 364*1d8f4dcbSJay } 365*1d8f4dcbSJay 366*1d8f4dcbSJay val miss_0_hit_1_latch = holdReleaseLatch(valid = miss_0_hit_1, release = s2_fire, flush = false.B) 367*1d8f4dcbSJay val miss_0_miss_1_latch = holdReleaseLatch(valid = miss_0_miss_1, release = s2_fire, flush = false.B) 368*1d8f4dcbSJay val only_0_miss_latch = holdReleaseLatch(valid = only_0_miss, release = s2_fire, flush = false.B) 369*1d8f4dcbSJay val hit_0_miss_1_latch = holdReleaseLatch(valid = hit_0_miss_1, release = s2_fire, flush = false.B) 370*1d8f4dcbSJay 371*1d8f4dcbSJay val miss_0_except_1_latch = holdReleaseLatch(valid = miss_0_except_1, release = s2_fire, flush = false.B) 372*1d8f4dcbSJay val except_0_latch = holdReleaseLatch(valid = except_0, release = s2_fire, flush = false.B) 373*1d8f4dcbSJay val hit_0_except_1_latch = holdReleaseLatch(valid = hit_0_except_1, release = s2_fire, flush = false.B) 374*1d8f4dcbSJay 375*1d8f4dcbSJay val only_0_hit_latch = holdReleaseLatch(valid = only_0_hit, release = s2_fire, flush = false.B) 376*1d8f4dcbSJay val hit_0_hit_1_latch = holdReleaseLatch(valid = hit_0_hit_1, release = s2_fire, flush = false.B) 377*1d8f4dcbSJay 378*1d8f4dcbSJay 379*1d8f4dcbSJay def waitSecondComeIn(missState: UInt): Bool = (missState === m_wait_sec_miss) 380*1d8f4dcbSJay 381*1d8f4dcbSJay // deal with secondary miss when s1 enter f2 382*1d8f4dcbSJay def getMissSituat(slotNum : Int, missNum : Int ) :Bool = { 383*1d8f4dcbSJay RegNext(s1_fire) && (missSlot(slotNum).m_vSetIdx === s2_req_vsetIdx(missNum)) && (missSlot(slotNum).m_pTag === s2_req_ptags(missNum)) && !s2_port_hit(missNum) && waitSecondComeIn(missStateQueue(slotNum)) && !s2_mmio 384*1d8f4dcbSJay } 385*1d8f4dcbSJay 386*1d8f4dcbSJay val miss_0_s2_0 = getMissSituat(slotNum = 0, missNum = 0) 387*1d8f4dcbSJay val miss_0_s2_1 = getMissSituat(slotNum = 0, missNum = 1) 388*1d8f4dcbSJay val miss_1_s2_0 = getMissSituat(slotNum = 1, missNum = 0) 389*1d8f4dcbSJay val miss_1_s2_1 = getMissSituat(slotNum = 1, missNum = 1) 390*1d8f4dcbSJay 391*1d8f4dcbSJay val miss_0_s2_0_latch = holdReleaseLatch(valid = miss_0_s2_0, release = s2_fire, flush = false.B) 392*1d8f4dcbSJay val miss_0_s2_1_latch = holdReleaseLatch(valid = miss_0_s2_1, release = s2_fire, flush = false.B) 393*1d8f4dcbSJay val miss_1_s2_0_latch = holdReleaseLatch(valid = miss_1_s2_0, release = s2_fire, flush = false.B) 394*1d8f4dcbSJay val miss_1_s2_1_latch = holdReleaseLatch(valid = miss_1_s2_1, release = s2_fire, flush = false.B) 395*1d8f4dcbSJay 396*1d8f4dcbSJay 397*1d8f4dcbSJay val slot_0_solve = fix_sec_miss(0) || fix_sec_miss(1) 398*1d8f4dcbSJay val slot_1_solve = fix_sec_miss(2) || fix_sec_miss(3) 399*1d8f4dcbSJay val slot_slove = VecInit(Seq(slot_0_solve, slot_1_solve)) 400*1d8f4dcbSJay 401*1d8f4dcbSJay fix_sec_miss := VecInit(Seq(miss_0_s2_0_latch, miss_0_s2_1_latch, miss_1_s2_0_latch, miss_1_s2_1_latch)) 402*1d8f4dcbSJay 403*1d8f4dcbSJay reservedRefillData(0) := DataHoldBypass(data = missSlot(0).m_data, valid = miss_0_s2_0 || miss_0_s2_1) 404*1d8f4dcbSJay reservedRefillData(1) := DataHoldBypass(data = missSlot(1).m_data, valid = miss_1_s2_0 || miss_1_s2_1) 405*1d8f4dcbSJay 406*1d8f4dcbSJay switch(wait_state){ 407*1d8f4dcbSJay is(wait_idle){ 408*1d8f4dcbSJay when(miss_0_except_1_latch){ 409*1d8f4dcbSJay wait_state := Mux(toMSHR(0).ready, wait_queue_ready ,wait_idle ) 410*1d8f4dcbSJay }.elsewhen( only_0_miss_latch || miss_0_hit_1_latch){ 411*1d8f4dcbSJay wait_state := Mux(toMSHR(0).ready, wait_queue_ready ,wait_idle ) 412*1d8f4dcbSJay }.elsewhen(hit_0_miss_1_latch){ 413*1d8f4dcbSJay wait_state := Mux(toMSHR(1).ready, wait_queue_ready ,wait_idle ) 414*1d8f4dcbSJay }.elsewhen( miss_0_miss_1_latch ){ 415*1d8f4dcbSJay wait_state := Mux(toMSHR(0).ready && toMSHR(1).ready, wait_queue_ready ,wait_idle) 416*1d8f4dcbSJay } 417*1d8f4dcbSJay } 418*1d8f4dcbSJay 419*1d8f4dcbSJay is(wait_queue_ready){ 420*1d8f4dcbSJay wait_state := wait_send_req 421*1d8f4dcbSJay } 422*1d8f4dcbSJay 423*1d8f4dcbSJay is(wait_send_req) { 424*1d8f4dcbSJay when(miss_0_except_1_latch || only_0_miss_latch || hit_0_miss_1_latch || miss_0_hit_1_latch){ 425*1d8f4dcbSJay wait_state := wait_one_resp 426*1d8f4dcbSJay }.elsewhen( miss_0_miss_1_latch ){ 427*1d8f4dcbSJay wait_state := wait_two_resp 428*1d8f4dcbSJay } 429*1d8f4dcbSJay } 430*1d8f4dcbSJay 431*1d8f4dcbSJay is(wait_one_resp) { 432*1d8f4dcbSJay when( (miss_0_except_1_latch ||only_0_miss_latch || miss_0_hit_1_latch) && fromMSHR(0).fire()){ 433*1d8f4dcbSJay wait_state := wait_finish 434*1d8f4dcbSJay }.elsewhen( hit_0_miss_1_latch && fromMSHR(1).fire()){ 435*1d8f4dcbSJay wait_state := wait_finish 436*1d8f4dcbSJay } 437*1d8f4dcbSJay } 438*1d8f4dcbSJay 439*1d8f4dcbSJay is(wait_two_resp) { 440*1d8f4dcbSJay when(fromMSHR(0).fire() && fromMSHR(1).fire()){ 441*1d8f4dcbSJay wait_state := wait_finish 442*1d8f4dcbSJay }.elsewhen( !fromMSHR(0).fire() && fromMSHR(1).fire() ){ 443*1d8f4dcbSJay wait_state := wait_0_resp 444*1d8f4dcbSJay }.elsewhen(fromMSHR(0).fire() && !fromMSHR(1).fire()){ 445*1d8f4dcbSJay wait_state := wait_1_resp 446*1d8f4dcbSJay } 447*1d8f4dcbSJay } 448*1d8f4dcbSJay 449*1d8f4dcbSJay is(wait_0_resp) { 450*1d8f4dcbSJay when(fromMSHR(0).fire()){ 451*1d8f4dcbSJay wait_state := wait_finish 452*1d8f4dcbSJay } 453*1d8f4dcbSJay } 454*1d8f4dcbSJay 455*1d8f4dcbSJay is(wait_1_resp) { 456*1d8f4dcbSJay when(fromMSHR(1).fire()){ 457*1d8f4dcbSJay wait_state := wait_finish 458*1d8f4dcbSJay } 459*1d8f4dcbSJay } 460*1d8f4dcbSJay 461*1d8f4dcbSJay is(wait_finish) { 462*1d8f4dcbSJay when(s2_fire) {wait_state := wait_idle } 463*1d8f4dcbSJay } 464*1d8f4dcbSJay } 465*1d8f4dcbSJay 466*1d8f4dcbSJay 467*1d8f4dcbSJay (0 until 2).map { i => 468*1d8f4dcbSJay if(i == 1) toMSHR(i).valid := (hit_0_miss_1_latch || miss_0_miss_1_latch) && wait_state === wait_queue_ready && !s2_mmio 469*1d8f4dcbSJay else toMSHR(i).valid := (only_0_miss_latch || miss_0_hit_1_latch || miss_0_miss_1_latch || miss_0_except_1_latch) && wait_state === wait_queue_ready && !s2_mmio 470*1d8f4dcbSJay toMSHR(i).bits.paddr := s2_req_paddr(i) 471*1d8f4dcbSJay toMSHR(i).bits.vaddr := s2_req_vaddr(i) 472*1d8f4dcbSJay toMSHR(i).bits.waymask := s2_waymask(i) 473*1d8f4dcbSJay toMSHR(i).bits.coh := s2_victim_coh(i) 474*1d8f4dcbSJay 475*1d8f4dcbSJay 476*1d8f4dcbSJay when(toMSHR(i).fire() && missStateQueue(i) === m_invalid){ 477*1d8f4dcbSJay missStateQueue(i) := m_valid 478*1d8f4dcbSJay missSlot(i).m_vSetIdx := s2_req_vsetIdx(i) 479*1d8f4dcbSJay missSlot(i).m_pTag := get_phy_tag(s2_req_paddr(i)) 480*1d8f4dcbSJay } 481*1d8f4dcbSJay 482*1d8f4dcbSJay when(fromMSHR(i).fire() && missStateQueue(i) === m_valid ){ 483*1d8f4dcbSJay missStateQueue(i) := m_refilled 484*1d8f4dcbSJay missSlot(i).m_data := fromMSHR(i).bits.data 485*1d8f4dcbSJay } 486*1d8f4dcbSJay 487*1d8f4dcbSJay 488*1d8f4dcbSJay when(s2_fire && missStateQueue(i) === m_refilled){ 489*1d8f4dcbSJay missStateQueue(i) := m_wait_sec_miss 490*1d8f4dcbSJay } 491*1d8f4dcbSJay 492*1d8f4dcbSJay //only the first cycle to check whether meet the secondary miss 493*1d8f4dcbSJay when(missStateQueue(i) === m_wait_sec_miss){ 494*1d8f4dcbSJay //the seondary req has been fix by this slot and another also hit || the secondary req for other cacheline and hit 495*1d8f4dcbSJay when((slot_slove(i) && s2_fire) || (!slot_slove(i) && s2_fire) ) { 496*1d8f4dcbSJay missStateQueue(i) := m_invalid 497*1d8f4dcbSJay } 498*1d8f4dcbSJay //the seondary req has been fix by this slot but another miss/f3 not ready || the seondary req for other cacheline and miss 499*1d8f4dcbSJay .elsewhen((slot_slove(i) && !s2_fire && s2_valid) || (s2_valid && !slot_slove(i) && !s2_fire) ){ 500*1d8f4dcbSJay missStateQueue(i) := m_check_final 501*1d8f4dcbSJay } 502*1d8f4dcbSJay } 503*1d8f4dcbSJay 504*1d8f4dcbSJay when(missStateQueue(i) === m_check_final && toMSHR(i).fire()){ 505*1d8f4dcbSJay missStateQueue(i) := m_valid 506*1d8f4dcbSJay missSlot(i).m_vSetIdx := s2_req_vsetIdx(i) 507*1d8f4dcbSJay missSlot(i).m_pTag := get_phy_tag(s2_req_paddr(i)) 508*1d8f4dcbSJay }.elsewhen(missStateQueue(i) === m_check_final) { 509*1d8f4dcbSJay missStateQueue(i) := m_invalid 510*1d8f4dcbSJay } 511*1d8f4dcbSJay } 512*1d8f4dcbSJay 513*1d8f4dcbSJay 514*1d8f4dcbSJay val release_idle :: release_wait_fire ::Nil = Enum(2) 515*1d8f4dcbSJay val release_state = RegInit(VecInit(Seq.fill(2)(release_idle)) ) 516*1d8f4dcbSJay val s2_need_release = VecInit((0 until PortNumber).map(i =>s2_valid && s2_need_replace(i) && !s2_mmio && !s2_except_af(i) && !s2_except_pf(i))) 517*1d8f4dcbSJay 518*1d8f4dcbSJay val toRealseUnit = io.toReleaseUnit 519*1d8f4dcbSJay 520*1d8f4dcbSJay 521*1d8f4dcbSJay (0 until 2).map{ i => 522*1d8f4dcbSJay switch(release_state(i)){ 523*1d8f4dcbSJay is(release_idle){ 524*1d8f4dcbSJay when(s2_need_release(i)){ 525*1d8f4dcbSJay release_state(i) := Mux(toRealseUnit(i).fire() , release_wait_fire ,release_idle ) 526*1d8f4dcbSJay } 527*1d8f4dcbSJay } 528*1d8f4dcbSJay 529*1d8f4dcbSJay is(release_wait_fire){ 530*1d8f4dcbSJay when(s2_fire){ release_state(i) := release_idle} 531*1d8f4dcbSJay } 532*1d8f4dcbSJay } 533*1d8f4dcbSJay 534*1d8f4dcbSJay toRealseUnit(i).valid := s2_valid && s2_need_release(i) && (release_state(i) === release_idle) 535*1d8f4dcbSJay toRealseUnit(i).bits.addr := get_block_addr(Cat(s2_victim_tag(i), get_untag(s2_req_vaddr(i))) ) 536*1d8f4dcbSJay toRealseUnit(i).bits.param := s2_victim_coh(i).onCacheControl(M_FLUSH)._2 537*1d8f4dcbSJay toRealseUnit(i).bits.voluntary := true.B 538*1d8f4dcbSJay toRealseUnit(i).bits.hasData := s2_victim_coh(i) === ClientStates.Dirty 539*1d8f4dcbSJay toRealseUnit(i).bits.dirty := s2_victim_coh(i) === ClientStates.Dirty 540*1d8f4dcbSJay toRealseUnit(i).bits.data := s2_victim_data(i) 541*1d8f4dcbSJay toRealseUnit(i).bits.waymask := s2_waymask(i) 542*1d8f4dcbSJay toRealseUnit(i).bits.vidx := s2_req_vsetIdx(i) 543*1d8f4dcbSJay } 544*1d8f4dcbSJay 545*1d8f4dcbSJay (0 until PortNumber).map{ i => 546*1d8f4dcbSJay io.victimInfor.s2(i).valid := s2_valid && s2_need_release(i) 547*1d8f4dcbSJay io.victimInfor.s2(i).ptag := s2_victim_tag(i) 548*1d8f4dcbSJay io.victimInfor.s2(i).vidx := get_idx(s2_req_vaddr(i)) 549*1d8f4dcbSJay } 550*1d8f4dcbSJay 551*1d8f4dcbSJay (0 until PortNumber).map{ i => 552*1d8f4dcbSJay io.setInfor.s2(i).valid := s2_bank_miss(i) && s2_valid 553*1d8f4dcbSJay io.setInfor.s2(i).vidx := s1_req_vsetIdx(i) 554*1d8f4dcbSJay } 555*1d8f4dcbSJay 556*1d8f4dcbSJay val miss_all_fix = wait_state === wait_finish 557*1d8f4dcbSJay val release_all_fix = VecInit((0 until PortNumber).map(i => !s2_need_release(i) || release_state(i) === release_wait_fire)) 558*1d8f4dcbSJay s2_fetch_finish := ((s2_valid && s2_fixed_hit) || miss_all_fix || hit_0_except_1_latch || except_0_latch || s2_mmio) && release_all_fix.reduce(_&&_) 559*1d8f4dcbSJay 560*1d8f4dcbSJay XSPerfAccumulate("ifu_bubble_s2_miss", s2_valid && !s2_fetch_finish ) 561*1d8f4dcbSJay 562*1d8f4dcbSJay (touch_ways zip touch_sets).zipWithIndex.map{ case((t_w,t_s), i) => 563*1d8f4dcbSJay t_s(0) := s1_req_vsetIdx(i) 564*1d8f4dcbSJay t_w(0).valid := s1_port_hit(i) 565*1d8f4dcbSJay t_w(0).bits := OHToUInt(s1_tag_match_vec(i)) 566*1d8f4dcbSJay 567*1d8f4dcbSJay t_s(1) := s2_req_vsetIdx(i) 568*1d8f4dcbSJay t_w(1).valid := s2_valid && !s2_port_hit(i) 569*1d8f4dcbSJay t_w(1).bits := OHToUInt(s2_waymask(i)) 570*1d8f4dcbSJay } 571*1d8f4dcbSJay 572*1d8f4dcbSJay val s2_hit_datas = RegEnable(next = s1_hit_data, enable = s1_fire) 573*1d8f4dcbSJay val s2_datas = Wire(Vec(2, UInt(blockBits.W))) 574*1d8f4dcbSJay 575*1d8f4dcbSJay s2_datas.zipWithIndex.map{case(bank,i) => 576*1d8f4dcbSJay if(i == 0) bank := Mux(s2_port_hit(i), s2_hit_datas(i),Mux(miss_0_s2_0_latch,reservedRefillData(0), Mux(miss_1_s2_0_latch,reservedRefillData(1), missSlot(0).m_data))) 577*1d8f4dcbSJay else bank := Mux(s2_port_hit(i), s2_hit_datas(i),Mux(miss_0_s2_1_latch,reservedRefillData(0), Mux(miss_1_s2_1_latch,reservedRefillData(1), missSlot(1).m_data))) 578*1d8f4dcbSJay } 579*1d8f4dcbSJay 580*1d8f4dcbSJay 581*1d8f4dcbSJay (0 until PortNumber).map{ i => 582*1d8f4dcbSJay if(i ==0) toIFU(i).valid := s2_fire 583*1d8f4dcbSJay else toIFU(i).valid := s2_fire && s2_double_line 584*1d8f4dcbSJay toIFU(i).bits.readData := s2_datas(i) 585*1d8f4dcbSJay toIFU(i).bits.paddr := s2_req_paddr(i) 586*1d8f4dcbSJay toIFU(i).bits.vaddr := s2_req_vaddr(i) 587*1d8f4dcbSJay toIFU(i).bits.tlbExcp.pageFault := s2_except_pf(i) 588*1d8f4dcbSJay toIFU(i).bits.tlbExcp.accessFault := s2_except_af(i) 589*1d8f4dcbSJay toIFU(i).bits.tlbExcp.mmio := s2_mmio 590*1d8f4dcbSJay } 591*1d8f4dcbSJay 592*1d8f4dcbSJay io.perfInfo.only_0_hit := only_0_miss_latch 593*1d8f4dcbSJay io.perfInfo.only_0_miss := only_0_miss_latch 594*1d8f4dcbSJay io.perfInfo.hit_0_hit_1 := hit_0_hit_1_latch 595*1d8f4dcbSJay io.perfInfo.hit_0_miss_1 := hit_0_miss_1_latch 596*1d8f4dcbSJay io.perfInfo.miss_0_hit_1 := miss_0_hit_1_latch 597*1d8f4dcbSJay io.perfInfo.miss_0_miss_1 := miss_0_miss_1_latch 598*1d8f4dcbSJay io.perfInfo.bank_hit(0) := only_0_miss_latch || hit_0_hit_1_latch || hit_0_miss_1_latch || hit_0_except_1_latch 599*1d8f4dcbSJay io.perfInfo.bank_hit(1) := miss_0_hit_1_latch || hit_0_hit_1_latch 600*1d8f4dcbSJay io.perfInfo.hit := hit_0_hit_1_latch 601*1d8f4dcbSJay} 602