1*09c6f1ddSLingrui98/*************************************************************************************** 2*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*09c6f1ddSLingrui98* 5*09c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2. 6*09c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*09c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at: 8*09c6f1ddSLingrui98* http://license.coscl.org.cn/MulanPSL2 9*09c6f1ddSLingrui98* 10*09c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*09c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*09c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*09c6f1ddSLingrui98* 14*09c6f1ddSLingrui98* See the Mulan PSL v2 for more details. 15*09c6f1ddSLingrui98***************************************************************************************/ 16*09c6f1ddSLingrui98 17*09c6f1ddSLingrui98package xiangshan.frontend 18*09c6f1ddSLingrui98 19*09c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters 20*09c6f1ddSLingrui98import chisel3._ 21*09c6f1ddSLingrui98import chisel3.util._ 22*09c6f1ddSLingrui98import xiangshan._ 23*09c6f1ddSLingrui98import xiangshan.cache._ 24*09c6f1ddSLingrui98import xiangshan.cache.mmu._ 25*09c6f1ddSLingrui98import chisel3.experimental.verification 26*09c6f1ddSLingrui98import utils._ 27*09c6f1ddSLingrui98 28*09c6f1ddSLingrui98trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{ 29*09c6f1ddSLingrui98 def mmioBusWidth = 64 30*09c6f1ddSLingrui98 def mmioBusBytes = mmioBusWidth /8 31*09c6f1ddSLingrui98 def mmioBeats = FetchWidth * 4 * 8 / mmioBusWidth 32*09c6f1ddSLingrui98 def mmioMask = VecInit(List.fill(PredictWidth)(true.B)).asUInt 33*09c6f1ddSLingrui98 def mmioBusAligned(pc :UInt): UInt = align(pc, mmioBusBytes) 34*09c6f1ddSLingrui98} 35*09c6f1ddSLingrui98 36*09c6f1ddSLingrui98trait HasIFUConst extends HasXSParameter { 37*09c6f1ddSLingrui98 def align(pc: UInt, bytes: Int): UInt = Cat(pc(VAddrBits-1, log2Ceil(bytes)), 0.U(log2Ceil(bytes).W)) 38*09c6f1ddSLingrui98 // def groupAligned(pc: UInt) = align(pc, groupBytes) 39*09c6f1ddSLingrui98 // def packetAligned(pc: UInt) = align(pc, packetBytes) 40*09c6f1ddSLingrui98} 41*09c6f1ddSLingrui98 42*09c6f1ddSLingrui98class IfuToFtqIO(implicit p:Parameters) extends XSBundle { 43*09c6f1ddSLingrui98 val pdWb = Valid(new PredecodeWritebackBundle) 44*09c6f1ddSLingrui98} 45*09c6f1ddSLingrui98 46*09c6f1ddSLingrui98class FtqInterface(implicit p: Parameters) extends XSBundle { 47*09c6f1ddSLingrui98 val fromFtq = Flipped(new FtqToIfuIO) 48*09c6f1ddSLingrui98 val toFtq = new IfuToFtqIO 49*09c6f1ddSLingrui98} 50*09c6f1ddSLingrui98 51*09c6f1ddSLingrui98class ICacheInterface(implicit p: Parameters) extends XSBundle { 52*09c6f1ddSLingrui98 val toIMeta = Decoupled(new ICacheReadBundle) 53*09c6f1ddSLingrui98 val toIData = Decoupled(new ICacheReadBundle) 54*09c6f1ddSLingrui98 val toMissQueue = Vec(2,Decoupled(new ICacheMissReq)) 55*09c6f1ddSLingrui98 val fromIMeta = Input(new ICacheMetaRespBundle) 56*09c6f1ddSLingrui98 val fromIData = Input(new ICacheDataRespBundle) 57*09c6f1ddSLingrui98 val fromMissQueue = Vec(2,Flipped(Decoupled(new ICacheMissResp))) 58*09c6f1ddSLingrui98} 59*09c6f1ddSLingrui98 60*09c6f1ddSLingrui98class NewIFUIO(implicit p: Parameters) extends XSBundle { 61*09c6f1ddSLingrui98 val ftqInter = new FtqInterface 62*09c6f1ddSLingrui98 val icacheInter = new ICacheInterface 63*09c6f1ddSLingrui98 val toIbuffer = Decoupled(new FetchToIBuffer) 64*09c6f1ddSLingrui98 val iTLBInter = Vec(2, new BlockTlbRequestIO) 65*09c6f1ddSLingrui98} 66*09c6f1ddSLingrui98 67*09c6f1ddSLingrui98// record the situation in which fallThruAddr falls into 68*09c6f1ddSLingrui98// the middle of an RVI inst 69*09c6f1ddSLingrui98class LastHalfInfo(implicit p: Parameters) extends XSBundle { 70*09c6f1ddSLingrui98 val valid = Bool() 71*09c6f1ddSLingrui98 val middlePC = UInt(VAddrBits.W) 72*09c6f1ddSLingrui98 def matchThisBlock(startAddr: UInt) = valid && middlePC === startAddr 73*09c6f1ddSLingrui98} 74*09c6f1ddSLingrui98 75*09c6f1ddSLingrui98class IfuToPreDecode(implicit p: Parameters) extends XSBundle { 76*09c6f1ddSLingrui98 val data = if(HasCExtension) Vec(PredictWidth + 1, UInt(16.W)) else Vec(PredictWidth, UInt(32.W)) 77*09c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 78*09c6f1ddSLingrui98 val fallThruAddr = UInt(VAddrBits.W) 79*09c6f1ddSLingrui98 val fallThruError = Bool() 80*09c6f1ddSLingrui98 val isDoubleLine = Bool() 81*09c6f1ddSLingrui98 val ftqOffset = Valid(UInt(log2Ceil(PredictWidth).W)) 82*09c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 83*09c6f1ddSLingrui98 val pageFault = Vec(2, Bool()) 84*09c6f1ddSLingrui98 val accessFault = Vec(2, Bool()) 85*09c6f1ddSLingrui98 val instValid = Bool() 86*09c6f1ddSLingrui98 val lastHalfMatch = Bool() 87*09c6f1ddSLingrui98 val oversize = Bool() 88*09c6f1ddSLingrui98} 89*09c6f1ddSLingrui98 90*09c6f1ddSLingrui98class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters 91*09c6f1ddSLingrui98{ 92*09c6f1ddSLingrui98 println(s"icache ways: ${nWays} sets:${nSets}") 93*09c6f1ddSLingrui98 val io = IO(new NewIFUIO) 94*09c6f1ddSLingrui98 val (toFtq, fromFtq) = (io.ftqInter.toFtq, io.ftqInter.fromFtq) 95*09c6f1ddSLingrui98 val (toMeta, toData, meta_resp, data_resp) = (io.icacheInter.toIMeta, io.icacheInter.toIData, io.icacheInter.fromIMeta, io.icacheInter.fromIData) 96*09c6f1ddSLingrui98 val (toMissQueue, fromMissQueue) = (io.icacheInter.toMissQueue, io.icacheInter.fromMissQueue) 97*09c6f1ddSLingrui98 val (toITLB, fromITLB) = (VecInit(io.iTLBInter.map(_.req)), VecInit(io.iTLBInter.map(_.resp))) 98*09c6f1ddSLingrui98 99*09c6f1ddSLingrui98 def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits) 100*09c6f1ddSLingrui98 101*09c6f1ddSLingrui98 def isLastInCacheline(fallThruAddr: UInt): Bool = fallThruAddr(blockOffBits - 1, 1) === 0.U 102*09c6f1ddSLingrui98 103*09c6f1ddSLingrui98 104*09c6f1ddSLingrui98 //--------------------------------------------- 105*09c6f1ddSLingrui98 // Fetch Stage 1 : 106*09c6f1ddSLingrui98 // * Send req to ICache Meta/Data 107*09c6f1ddSLingrui98 // * Check whether need 2 line fetch 108*09c6f1ddSLingrui98 //--------------------------------------------- 109*09c6f1ddSLingrui98 110*09c6f1ddSLingrui98 val f0_valid = fromFtq.req.valid 111*09c6f1ddSLingrui98 val f0_ftq_req = fromFtq.req.bits 112*09c6f1ddSLingrui98 val f0_situation = VecInit(Seq(isCrossLineReq(f0_ftq_req.startAddr, f0_ftq_req.fallThruAddr), isLastInCacheline(f0_ftq_req.fallThruAddr))) 113*09c6f1ddSLingrui98 val f0_doubleLine = f0_situation(0) || f0_situation(1) 114*09c6f1ddSLingrui98 val f0_vSetIdx = VecInit(get_idx((f0_ftq_req.startAddr)), get_idx(f0_ftq_req.fallThruAddr)) 115*09c6f1ddSLingrui98 val f0_fire = fromFtq.req.fire() 116*09c6f1ddSLingrui98 117*09c6f1ddSLingrui98 val f0_flush, f1_flush, f2_flush, f3_flush = WireInit(false.B) 118*09c6f1ddSLingrui98 val from_bpu_f0_flush, from_bpu_f1_flush, from_bpu_f2_flush, from_bpu_f3_flush = WireInit(false.B) 119*09c6f1ddSLingrui98 120*09c6f1ddSLingrui98 from_bpu_f0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(f0_ftq_req.ftqIdx) || 121*09c6f1ddSLingrui98 fromFtq.flushFromBpu.shouldFlushByStage3(f0_ftq_req.ftqIdx) 122*09c6f1ddSLingrui98 123*09c6f1ddSLingrui98 val f3_redirect = WireInit(false.B) 124*09c6f1ddSLingrui98 f3_flush := fromFtq.redirect.valid 125*09c6f1ddSLingrui98 f2_flush := f3_flush || f3_redirect 126*09c6f1ddSLingrui98 f1_flush := f2_flush || from_bpu_f1_flush 127*09c6f1ddSLingrui98 f0_flush := f1_flush || from_bpu_f0_flush 128*09c6f1ddSLingrui98 129*09c6f1ddSLingrui98 val f1_ready, f2_ready, f3_ready = WireInit(false.B) 130*09c6f1ddSLingrui98 131*09c6f1ddSLingrui98 //fetch: send addr to Meta/TLB and Data simultaneously 132*09c6f1ddSLingrui98 val fetch_req = List(toMeta, toData) 133*09c6f1ddSLingrui98 for(i <- 0 until 2) { 134*09c6f1ddSLingrui98 fetch_req(i).valid := f0_fire 135*09c6f1ddSLingrui98 fetch_req(i).bits.isDoubleLine := f0_doubleLine 136*09c6f1ddSLingrui98 fetch_req(i).bits.vSetIdx := f0_vSetIdx 137*09c6f1ddSLingrui98 } 138*09c6f1ddSLingrui98 139*09c6f1ddSLingrui98 fromFtq.req.ready := fetch_req(0).ready && fetch_req(1).ready && f1_ready && GTimer() > 500.U 140*09c6f1ddSLingrui98 141*09c6f1ddSLingrui98 //--------------------------------------------- 142*09c6f1ddSLingrui98 // Fetch Stage 2 : 143*09c6f1ddSLingrui98 // * Send req to ITLB and TLB Response (Get Paddr) 144*09c6f1ddSLingrui98 // * ICache Response (Get Meta and Data) 145*09c6f1ddSLingrui98 // * Hit Check (Generate hit signal and hit vector) 146*09c6f1ddSLingrui98 // * Get victim way 147*09c6f1ddSLingrui98 //--------------------------------------------- 148*09c6f1ddSLingrui98 149*09c6f1ddSLingrui98 //TODO: handle fetch exceptions 150*09c6f1ddSLingrui98 151*09c6f1ddSLingrui98 val tlbRespAllValid = WireInit(false.B) 152*09c6f1ddSLingrui98 153*09c6f1ddSLingrui98 val f1_valid = RegInit(false.B) 154*09c6f1ddSLingrui98 val f1_ftq_req = RegEnable(next = f0_ftq_req, enable=f0_fire) 155*09c6f1ddSLingrui98 val f1_situation = RegEnable(next = f0_situation, enable=f0_fire) 156*09c6f1ddSLingrui98 val f1_doubleLine = RegEnable(next = f0_doubleLine, enable=f0_fire) 157*09c6f1ddSLingrui98 val f1_vSetIdx = RegEnable(next = f0_vSetIdx, enable=f0_fire) 158*09c6f1ddSLingrui98 val f1_fire = f1_valid && tlbRespAllValid && f2_ready 159*09c6f1ddSLingrui98 160*09c6f1ddSLingrui98 f1_ready := f2_ready && tlbRespAllValid || !f1_valid 161*09c6f1ddSLingrui98 162*09c6f1ddSLingrui98 from_bpu_f1_flush := fromFtq.flushFromBpu.shouldFlushByStage3(f1_ftq_req.ftqIdx) 163*09c6f1ddSLingrui98 164*09c6f1ddSLingrui98 val preDecoder = Module(new PreDecode) 165*09c6f1ddSLingrui98 val (preDecoderIn, preDecoderOut) = (preDecoder.io.in, preDecoder.io.out) 166*09c6f1ddSLingrui98 167*09c6f1ddSLingrui98 //flush generate and to Ftq 168*09c6f1ddSLingrui98 val predecodeOutValid = WireInit(false.B) 169*09c6f1ddSLingrui98 170*09c6f1ddSLingrui98 when(f1_flush) {f1_valid := false.B} 171*09c6f1ddSLingrui98 .elsewhen(f0_fire && !f0_flush) {f1_valid := true.B} 172*09c6f1ddSLingrui98 .elsewhen(f1_fire) {f1_valid := false.B} 173*09c6f1ddSLingrui98 174*09c6f1ddSLingrui98 toITLB(0).valid := f1_valid 175*09c6f1ddSLingrui98 toITLB(0).bits.vaddr := align(f1_ftq_req.startAddr, blockBytes) 176*09c6f1ddSLingrui98 toITLB(0).bits.debug.pc := align(f1_ftq_req.startAddr, blockBytes) 177*09c6f1ddSLingrui98 178*09c6f1ddSLingrui98 toITLB(1).valid := f1_valid && f1_doubleLine 179*09c6f1ddSLingrui98 toITLB(1).bits.vaddr := align(f1_ftq_req.fallThruAddr, blockBytes) 180*09c6f1ddSLingrui98 toITLB(1).bits.debug.pc := align(f1_ftq_req.fallThruAddr, blockBytes) 181*09c6f1ddSLingrui98 182*09c6f1ddSLingrui98 toITLB.map{port => 183*09c6f1ddSLingrui98 port.bits.cmd := TlbCmd.exec 184*09c6f1ddSLingrui98 port.bits.roqIdx := DontCare 185*09c6f1ddSLingrui98 port.bits.debug.isFirstIssue := DontCare 186*09c6f1ddSLingrui98 } 187*09c6f1ddSLingrui98 188*09c6f1ddSLingrui98 fromITLB.map(_.ready := true.B) 189*09c6f1ddSLingrui98 190*09c6f1ddSLingrui98 val (tlbRespValid, tlbRespPAddr) = (fromITLB.map(_.valid), VecInit(fromITLB.map(_.bits.paddr))) 191*09c6f1ddSLingrui98 val (tlbRespMiss, tlbRespMMIO) = (fromITLB.map(port => port.bits.miss && port.valid), fromITLB.map(port => port.bits.mmio && port.valid)) 192*09c6f1ddSLingrui98 val (tlbExcpPF, tlbExcpAF) = (fromITLB.map(port => port.bits.excp.pf.instr && port.valid), fromITLB.map(port => port.bits.excp.af.instr && port.valid)) 193*09c6f1ddSLingrui98 194*09c6f1ddSLingrui98 tlbRespAllValid := tlbRespValid(0) && (tlbRespValid(1) || !f1_doubleLine) 195*09c6f1ddSLingrui98 196*09c6f1ddSLingrui98 val f1_pAddrs = tlbRespPAddr //TODO: Temporary assignment 197*09c6f1ddSLingrui98 val f1_pTags = VecInit(f1_pAddrs.map(get_tag(_))) 198*09c6f1ddSLingrui98 val (f1_tags, f1_cacheline_valid, f1_datas) = (meta_resp.tags, meta_resp.valid, data_resp.datas) 199*09c6f1ddSLingrui98 val bank0_hit_vec = VecInit(f1_tags(0).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(0)(i) && way_tag === f1_pTags(0) }) 200*09c6f1ddSLingrui98 val bank1_hit_vec = VecInit(f1_tags(1).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(1)(i) && way_tag === f1_pTags(1) }) 201*09c6f1ddSLingrui98 val (bank0_hit,bank1_hit) = (ParallelOR(bank0_hit_vec) && !tlbExcpPF(0) && !tlbExcpAF(0), ParallelOR(bank1_hit_vec) && !tlbExcpPF(1) && !tlbExcpAF(1)) 202*09c6f1ddSLingrui98 val f1_hit = (bank0_hit && bank1_hit && f1_valid && f1_doubleLine) || (f1_valid && !f1_doubleLine && bank0_hit) 203*09c6f1ddSLingrui98 val f1_bank_hit_vec = VecInit(Seq(bank0_hit_vec, bank1_hit_vec)) 204*09c6f1ddSLingrui98 val f1_bank_hit = VecInit(Seq(bank0_hit, bank1_hit)) 205*09c6f1ddSLingrui98 206*09c6f1ddSLingrui98 val replacers = Seq.fill(2)(ReplacementPolicy.fromString(Some("random"),nWays,nSets/2)) 207*09c6f1ddSLingrui98 val f1_victim_masks = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(f1_vSetIdx(i)))}) 208*09c6f1ddSLingrui98 209*09c6f1ddSLingrui98 val touch_sets = Seq.fill(2)(Wire(Vec(2, UInt(log2Ceil(nSets/2).W)))) 210*09c6f1ddSLingrui98 val touch_ways = Seq.fill(2)(Wire(Vec(2, Valid(UInt(log2Ceil(nWays).W)))) ) 211*09c6f1ddSLingrui98 212*09c6f1ddSLingrui98 ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)} 213*09c6f1ddSLingrui98 214*09c6f1ddSLingrui98 val f1_hit_data = VecInit(f1_datas.zipWithIndex.map { case(bank, i) => 215*09c6f1ddSLingrui98 val bank_hit_data = Mux1H(f1_bank_hit_vec(i).asUInt, bank) 216*09c6f1ddSLingrui98 bank_hit_data 217*09c6f1ddSLingrui98 }) 218*09c6f1ddSLingrui98 219*09c6f1ddSLingrui98 220*09c6f1ddSLingrui98 //--------------------------------------------- 221*09c6f1ddSLingrui98 // Fetch Stage 3 : 222*09c6f1ddSLingrui98 // * get data from last stage (hit from f1_hit_data/miss from missQueue response) 223*09c6f1ddSLingrui98 // * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!! 224*09c6f1ddSLingrui98 // * cut cacheline(s) and send to PreDecode 225*09c6f1ddSLingrui98 // * check if prediction is right (branch target and type, jump direction and type , jal target ) 226*09c6f1ddSLingrui98 //--------------------------------------------- 227*09c6f1ddSLingrui98 val f2_fetchFinish = Wire(Bool()) 228*09c6f1ddSLingrui98 229*09c6f1ddSLingrui98 val f2_valid = RegInit(false.B) 230*09c6f1ddSLingrui98 val f2_ftq_req = RegEnable(next = f1_ftq_req, enable = f1_fire) 231*09c6f1ddSLingrui98 val f2_situation = RegEnable(next = f1_situation, enable=f1_fire) 232*09c6f1ddSLingrui98 val f2_doubleLine = RegEnable(next = f1_doubleLine, enable=f1_fire) 233*09c6f1ddSLingrui98 val f2_fire = f2_valid && f2_fetchFinish && f3_ready 234*09c6f1ddSLingrui98 235*09c6f1ddSLingrui98 f2_ready := (f3_ready && f2_fetchFinish) || !f2_valid 236*09c6f1ddSLingrui98 237*09c6f1ddSLingrui98 when(f2_flush) {f2_valid := false.B} 238*09c6f1ddSLingrui98 .elsewhen(f1_fire && !f1_flush) {f2_valid := true.B } 239*09c6f1ddSLingrui98 .elsewhen(f2_fire) {f2_valid := false.B} 240*09c6f1ddSLingrui98 241*09c6f1ddSLingrui98 242*09c6f1ddSLingrui98 val f2_pAddrs = RegEnable(next = f1_pAddrs, enable = f1_fire) 243*09c6f1ddSLingrui98 val f2_hit = RegEnable(next = f1_hit , enable = f1_fire) 244*09c6f1ddSLingrui98 val f2_bank_hit = RegEnable(next = f1_bank_hit, enable = f1_fire) 245*09c6f1ddSLingrui98 val f2_miss = f2_valid && !f2_hit 246*09c6f1ddSLingrui98 val (f2_vSetIdx, f2_pTags) = (RegEnable(next = f1_vSetIdx, enable = f1_fire), RegEnable(next = f1_pTags, enable = f1_fire)) 247*09c6f1ddSLingrui98 val f2_waymask = RegEnable(next = f1_victim_masks, enable = f1_fire) 248*09c6f1ddSLingrui98 //exception information 249*09c6f1ddSLingrui98 val f2_except_pf = RegEnable(next = VecInit(tlbExcpPF), enable = f1_fire) 250*09c6f1ddSLingrui98 val f2_except_af = RegEnable(next = VecInit(tlbExcpAF), enable = f1_fire) 251*09c6f1ddSLingrui98 val f2_except = VecInit((0 until 2).map{i => f2_except_pf(i) || f2_except_af(i)}) 252*09c6f1ddSLingrui98 val f2_has_except = f2_valid && (f2_except_af.reduce(_||_) || f2_except_pf.reduce(_||_)) 253*09c6f1ddSLingrui98 254*09c6f1ddSLingrui98 //instruction 255*09c6f1ddSLingrui98 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) 256*09c6f1ddSLingrui98 val wait_state = RegInit(wait_idle) 257*09c6f1ddSLingrui98 258*09c6f1ddSLingrui98 fromMissQueue.map{port => port.ready := true.B} 259*09c6f1ddSLingrui98 260*09c6f1ddSLingrui98 val (miss0_resp, miss1_resp) = (fromMissQueue(0).fire(), fromMissQueue(1).fire()) 261*09c6f1ddSLingrui98 val (bank0_fix, bank1_fix) = (miss0_resp && !f2_bank_hit(0), miss1_resp && f2_doubleLine && !f2_bank_hit(1)) 262*09c6f1ddSLingrui98 263*09c6f1ddSLingrui98 val only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except 264*09c6f1ddSLingrui98 val (hit_0_miss_1 , miss_0_hit_1, miss_0_miss_1) = ( (f2_valid && !f2_bank_hit(1) && f2_bank_hit(0) && f2_doubleLine && !f2_has_except), 265*09c6f1ddSLingrui98 (f2_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine && !f2_has_except), 266*09c6f1ddSLingrui98 (f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except), 267*09c6f1ddSLingrui98 ) 268*09c6f1ddSLingrui98 269*09c6f1ddSLingrui98 val hit_0_except_1 = f2_valid && f2_doubleLine && !f2_except(0) && f2_except(1) && f2_bank_hit(0) 270*09c6f1ddSLingrui98 val miss_0_except_1 = f2_valid && f2_doubleLine && !f2_except(0) && f2_except(1) && !f2_bank_hit(0) 271*09c6f1ddSLingrui98 //val fetch0_except_1 = hit_0_except_1 || miss_0_except_1 272*09c6f1ddSLingrui98 val except_0 = f2_valid && f2_except(0) 273*09c6f1ddSLingrui98 274*09c6f1ddSLingrui98 val f2_mq_datas = Reg(Vec(2, UInt(blockBits.W))) 275*09c6f1ddSLingrui98 276*09c6f1ddSLingrui98 when(fromMissQueue(0).fire) {f2_mq_datas(0) := fromMissQueue(0).bits.data} 277*09c6f1ddSLingrui98 when(fromMissQueue(1).fire) {f2_mq_datas(1) := fromMissQueue(1).bits.data} 278*09c6f1ddSLingrui98 279*09c6f1ddSLingrui98 switch(wait_state){ 280*09c6f1ddSLingrui98 is(wait_idle){ 281*09c6f1ddSLingrui98 when(miss_0_except_1){ 282*09c6f1ddSLingrui98 wait_state := Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle ) 283*09c6f1ddSLingrui98 }.elsewhen( only_0_miss || miss_0_hit_1){ 284*09c6f1ddSLingrui98 wait_state := Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle ) 285*09c6f1ddSLingrui98 }.elsewhen(hit_0_miss_1){ 286*09c6f1ddSLingrui98 wait_state := Mux(toMissQueue(1).ready, wait_queue_ready ,wait_idle ) 287*09c6f1ddSLingrui98 }.elsewhen( miss_0_miss_1 ){ 288*09c6f1ddSLingrui98 wait_state := Mux(toMissQueue(0).ready && toMissQueue(1).ready, wait_queue_ready ,wait_idle) 289*09c6f1ddSLingrui98 } 290*09c6f1ddSLingrui98 } 291*09c6f1ddSLingrui98 292*09c6f1ddSLingrui98 //TODO: naive logic for wait icache response 293*09c6f1ddSLingrui98 is(wait_queue_ready){ 294*09c6f1ddSLingrui98 wait_state := wait_send_req 295*09c6f1ddSLingrui98 } 296*09c6f1ddSLingrui98 297*09c6f1ddSLingrui98 is(wait_send_req) { 298*09c6f1ddSLingrui98 when(miss_0_except_1 || only_0_miss || hit_0_miss_1 || miss_0_hit_1){ 299*09c6f1ddSLingrui98 wait_state := wait_one_resp 300*09c6f1ddSLingrui98 }.elsewhen( miss_0_miss_1 ){ 301*09c6f1ddSLingrui98 wait_state := wait_two_resp 302*09c6f1ddSLingrui98 } 303*09c6f1ddSLingrui98 } 304*09c6f1ddSLingrui98 305*09c6f1ddSLingrui98 is(wait_one_resp) { 306*09c6f1ddSLingrui98 when( (miss_0_except_1 ||only_0_miss || miss_0_hit_1) && fromMissQueue(0).fire()){ 307*09c6f1ddSLingrui98 wait_state := wait_finish 308*09c6f1ddSLingrui98 }.elsewhen( hit_0_miss_1 && fromMissQueue(1).fire()){ 309*09c6f1ddSLingrui98 wait_state := wait_finish 310*09c6f1ddSLingrui98 } 311*09c6f1ddSLingrui98 } 312*09c6f1ddSLingrui98 313*09c6f1ddSLingrui98 is(wait_two_resp) { 314*09c6f1ddSLingrui98 when(fromMissQueue(0).fire() && fromMissQueue(1).fire()){ 315*09c6f1ddSLingrui98 wait_state := wait_finish 316*09c6f1ddSLingrui98 }.elsewhen( !fromMissQueue(0).fire() && fromMissQueue(1).fire() ){ 317*09c6f1ddSLingrui98 wait_state := wait_0_resp 318*09c6f1ddSLingrui98 }.elsewhen(fromMissQueue(0).fire() && !fromMissQueue(1).fire()){ 319*09c6f1ddSLingrui98 wait_state := wait_1_resp 320*09c6f1ddSLingrui98 } 321*09c6f1ddSLingrui98 } 322*09c6f1ddSLingrui98 323*09c6f1ddSLingrui98 is(wait_0_resp) { 324*09c6f1ddSLingrui98 when(fromMissQueue(0).fire()){ 325*09c6f1ddSLingrui98 wait_state := wait_finish 326*09c6f1ddSLingrui98 } 327*09c6f1ddSLingrui98 } 328*09c6f1ddSLingrui98 329*09c6f1ddSLingrui98 is(wait_1_resp) { 330*09c6f1ddSLingrui98 when(fromMissQueue(1).fire()){ 331*09c6f1ddSLingrui98 wait_state := wait_finish 332*09c6f1ddSLingrui98 } 333*09c6f1ddSLingrui98 } 334*09c6f1ddSLingrui98 335*09c6f1ddSLingrui98 is(wait_finish) { 336*09c6f1ddSLingrui98 when(f2_fire) {wait_state := wait_idle } 337*09c6f1ddSLingrui98 } 338*09c6f1ddSLingrui98 } 339*09c6f1ddSLingrui98 340*09c6f1ddSLingrui98 when(f2_flush) { wait_state := wait_idle } 341*09c6f1ddSLingrui98 342*09c6f1ddSLingrui98 (0 until 2).map { i => 343*09c6f1ddSLingrui98 if(i == 1) toMissQueue(i).valid := (hit_0_miss_1 || miss_0_miss_1) && wait_state === wait_queue_ready 344*09c6f1ddSLingrui98 else toMissQueue(i).valid := (only_0_miss || miss_0_hit_1 || miss_0_miss_1) && wait_state === wait_queue_ready 345*09c6f1ddSLingrui98 toMissQueue(i).bits.addr := f2_pAddrs(i) 346*09c6f1ddSLingrui98 toMissQueue(i).bits.vSetIdx := f2_vSetIdx(i) 347*09c6f1ddSLingrui98 toMissQueue(i).bits.waymask := f2_waymask(i) 348*09c6f1ddSLingrui98 toMissQueue(i).bits.clientID :=0.U 349*09c6f1ddSLingrui98 } 350*09c6f1ddSLingrui98 351*09c6f1ddSLingrui98 val miss_all_fix = (wait_state === wait_finish) 352*09c6f1ddSLingrui98 353*09c6f1ddSLingrui98 f2_fetchFinish := ((f2_valid && f2_hit) || miss_all_fix || hit_0_except_1 || except_0) 354*09c6f1ddSLingrui98 355*09c6f1ddSLingrui98 356*09c6f1ddSLingrui98 (touch_ways zip touch_sets).zipWithIndex.map{ case((t_w,t_s), i) => 357*09c6f1ddSLingrui98 t_s(0) := f1_vSetIdx(i) 358*09c6f1ddSLingrui98 t_w(0).valid := f1_bank_hit(i) 359*09c6f1ddSLingrui98 t_w(0).bits := OHToUInt(f1_bank_hit_vec(i)) 360*09c6f1ddSLingrui98 361*09c6f1ddSLingrui98 t_s(1) := f2_vSetIdx(i) 362*09c6f1ddSLingrui98 t_w(1).valid := f2_valid && !f2_bank_hit(i) 363*09c6f1ddSLingrui98 t_w(1).bits := OHToUInt(f2_waymask(i)) 364*09c6f1ddSLingrui98 } 365*09c6f1ddSLingrui98 366*09c6f1ddSLingrui98 val sec_miss_reg = RegInit(0.U.asTypeOf(Vec(4, Bool()))) 367*09c6f1ddSLingrui98 val reservedRefillData = Reg(Vec(2, UInt(blockBits.W))) 368*09c6f1ddSLingrui98 val f2_hit_datas = RegEnable(next = f1_hit_data, enable = f1_fire) 369*09c6f1ddSLingrui98 val f2_datas = Wire(Vec(2, UInt(blockBits.W))) 370*09c6f1ddSLingrui98 371*09c6f1ddSLingrui98 f2_datas.zipWithIndex.map{case(bank,i) => 372*09c6f1ddSLingrui98 if(i == 0) bank := Mux(f2_bank_hit(i), f2_hit_datas(i),Mux(sec_miss_reg(2),reservedRefillData(1),Mux(sec_miss_reg(0),reservedRefillData(0), f2_mq_datas(i)))) 373*09c6f1ddSLingrui98 else bank := Mux(f2_bank_hit(i), f2_hit_datas(i),Mux(sec_miss_reg(3),reservedRefillData(1),Mux(sec_miss_reg(1),reservedRefillData(0), f2_mq_datas(i)))) 374*09c6f1ddSLingrui98 } 375*09c6f1ddSLingrui98 376*09c6f1ddSLingrui98 val f2_jump_valids = Fill(PredictWidth, !preDecoderOut.cfiOffset.valid) | Fill(PredictWidth, 1.U(1.W)) >> (~preDecoderOut.cfiOffset.bits) 377*09c6f1ddSLingrui98 val f2_predecode_valids = VecInit(preDecoderOut.pd.map(instr => instr.valid)).asUInt & f2_jump_valids 378*09c6f1ddSLingrui98 379*09c6f1ddSLingrui98 def cut(cacheline: UInt, start: UInt) : Vec[UInt] ={ 380*09c6f1ddSLingrui98 if(HasCExtension){ 381*09c6f1ddSLingrui98 val result = Wire(Vec(PredictWidth + 1, UInt(16.W))) 382*09c6f1ddSLingrui98 val dataVec = cacheline.asTypeOf(Vec(blockBytes * 2/ 2, UInt(16.W))) 383*09c6f1ddSLingrui98 val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 1)) 384*09c6f1ddSLingrui98 (0 until PredictWidth + 1).foreach( i => 385*09c6f1ddSLingrui98 result(i) := dataVec(startPtr + i.U) 386*09c6f1ddSLingrui98 ) 387*09c6f1ddSLingrui98 result 388*09c6f1ddSLingrui98 } else { 389*09c6f1ddSLingrui98 val result = Wire(Vec(PredictWidth, UInt(32.W)) ) 390*09c6f1ddSLingrui98 val dataVec = cacheline.asTypeOf(Vec(blockBytes * 2/ 4, UInt(32.W))) 391*09c6f1ddSLingrui98 val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 2)) 392*09c6f1ddSLingrui98 (0 until PredictWidth).foreach( i => 393*09c6f1ddSLingrui98 result(i) := dataVec(startPtr + i.U) 394*09c6f1ddSLingrui98 ) 395*09c6f1ddSLingrui98 result 396*09c6f1ddSLingrui98 } 397*09c6f1ddSLingrui98 } 398*09c6f1ddSLingrui98 399*09c6f1ddSLingrui98 val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_ftq_req.startAddr ) 400*09c6f1ddSLingrui98 401*09c6f1ddSLingrui98 // deal with secondary miss in f1 402*09c6f1ddSLingrui98 val f2_0_f1_0 = ((f2_valid && !f2_bank_hit(0)) && f1_valid && (get_block_addr(f2_ftq_req.startAddr) === get_block_addr(f1_ftq_req.startAddr))) 403*09c6f1ddSLingrui98 val f2_0_f1_1 = ((f2_valid && !f2_bank_hit(0)) && f1_valid && f1_doubleLine && (get_block_addr(f2_ftq_req.startAddr) === get_block_addr(f1_ftq_req.startAddr + blockBytes.U))) 404*09c6f1ddSLingrui98 val f2_1_f1_0 = ((f2_valid && !f2_bank_hit(1) && f2_doubleLine) && f1_valid && (get_block_addr(f2_ftq_req.startAddr+ blockBytes.U) === get_block_addr(f1_ftq_req.startAddr) )) 405*09c6f1ddSLingrui98 val f2_1_f1_1 = ((f2_valid && !f2_bank_hit(1) && f2_doubleLine) && f1_valid && f1_doubleLine && (get_block_addr(f2_ftq_req.startAddr+ blockBytes.U) === get_block_addr(f1_ftq_req.startAddr + blockBytes.U) )) 406*09c6f1ddSLingrui98 407*09c6f1ddSLingrui98 val isSameLine = f2_0_f1_0 || f2_0_f1_1 || f2_1_f1_0 || f2_1_f1_1 408*09c6f1ddSLingrui98 val sec_miss_sit = VecInit(Seq(f2_0_f1_0, f2_0_f1_1, f2_1_f1_0, f2_1_f1_1)) 409*09c6f1ddSLingrui98 val hasSecMiss = RegInit(false.B) 410*09c6f1ddSLingrui98 411*09c6f1ddSLingrui98 when(f2_flush){ 412*09c6f1ddSLingrui98 sec_miss_reg.map(sig => sig := false.B) 413*09c6f1ddSLingrui98 hasSecMiss := false.B 414*09c6f1ddSLingrui98 }.elsewhen(isSameLine && !f1_flush && f2_fire){ 415*09c6f1ddSLingrui98 sec_miss_reg.zipWithIndex.map{case(sig, i) => sig := sec_miss_sit(i)} 416*09c6f1ddSLingrui98 hasSecMiss := true.B 417*09c6f1ddSLingrui98 }.elsewhen((!isSameLine || f1_flush) && hasSecMiss && f2_fire){ 418*09c6f1ddSLingrui98 sec_miss_reg.map(sig => sig := false.B) 419*09c6f1ddSLingrui98 hasSecMiss := false.B 420*09c6f1ddSLingrui98 } 421*09c6f1ddSLingrui98 422*09c6f1ddSLingrui98 when((f2_0_f1_0 || f2_0_f1_1) && f2_fire){ 423*09c6f1ddSLingrui98 reservedRefillData(0) := f2_mq_datas(0) 424*09c6f1ddSLingrui98 } 425*09c6f1ddSLingrui98 426*09c6f1ddSLingrui98 when((f2_1_f1_0 || f2_1_f1_1) && f2_fire){ 427*09c6f1ddSLingrui98 reservedRefillData(1) := f2_mq_datas(1) 428*09c6f1ddSLingrui98 } 429*09c6f1ddSLingrui98 430*09c6f1ddSLingrui98 431*09c6f1ddSLingrui98 //--------------------------------------------- 432*09c6f1ddSLingrui98 // Fetch Stage 4 : 433*09c6f1ddSLingrui98 // * get data from last stage (hit from f1_hit_data/miss from missQueue response) 434*09c6f1ddSLingrui98 // * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!! 435*09c6f1ddSLingrui98 // * cut cacheline(s) and send to PreDecode 436*09c6f1ddSLingrui98 // * check if prediction is right (branch target and type, jump direction and type , jal target ) 437*09c6f1ddSLingrui98 //--------------------------------------------- 438*09c6f1ddSLingrui98 val f3_valid = RegInit(false.B) 439*09c6f1ddSLingrui98 val f3_ftq_req = RegEnable(next = f2_ftq_req, enable=f2_fire) 440*09c6f1ddSLingrui98 val f3_situation = RegEnable(next = f2_situation, enable=f2_fire) 441*09c6f1ddSLingrui98 val f3_doubleLine = RegEnable(next = f2_doubleLine, enable=f2_fire) 442*09c6f1ddSLingrui98 val f3_fire = io.toIbuffer.fire() 443*09c6f1ddSLingrui98 444*09c6f1ddSLingrui98 when(f3_flush) {f3_valid := false.B} 445*09c6f1ddSLingrui98 .elsewhen(f2_fire && !f2_flush) {f3_valid := true.B } 446*09c6f1ddSLingrui98 .elsewhen(io.toIbuffer.fire()) {f3_valid := false.B} 447*09c6f1ddSLingrui98 448*09c6f1ddSLingrui98 f3_ready := io.toIbuffer.ready || !f2_valid 449*09c6f1ddSLingrui98 450*09c6f1ddSLingrui98 val f3_cut_data = RegEnable(next = f2_cut_data, enable=f2_fire) 451*09c6f1ddSLingrui98 val f3_except_pf = RegEnable(next = f2_except_pf, enable = f2_fire) 452*09c6f1ddSLingrui98 val f3_except_af = RegEnable(next = f2_except_af, enable = f2_fire) 453*09c6f1ddSLingrui98 val f3_hit = RegEnable(next = f2_hit , enable = f2_fire) 454*09c6f1ddSLingrui98 455*09c6f1ddSLingrui98 val f3_lastHalf = RegInit(0.U.asTypeOf(new LastHalfInfo)) 456*09c6f1ddSLingrui98 val f3_lastHalfMatch = f3_lastHalf.matchThisBlock(f3_ftq_req.startAddr) 457*09c6f1ddSLingrui98 val f3_except = VecInit((0 until 2).map{i => f3_except_pf(i) || f3_except_af(i)}) 458*09c6f1ddSLingrui98 val f3_has_except = f3_valid && (f3_except_af.reduce(_||_) || f3_except_pf.reduce(_||_)) 459*09c6f1ddSLingrui98 460*09c6f1ddSLingrui98 461*09c6f1ddSLingrui98 preDecoderIn.instValid := f3_valid && !f3_has_except 462*09c6f1ddSLingrui98 preDecoderIn.data := f3_cut_data 463*09c6f1ddSLingrui98 preDecoderIn.startAddr := f3_ftq_req.startAddr 464*09c6f1ddSLingrui98 preDecoderIn.fallThruAddr := f3_ftq_req.fallThruAddr 465*09c6f1ddSLingrui98 preDecoderIn.fallThruError := f3_ftq_req.fallThruError 466*09c6f1ddSLingrui98 preDecoderIn.isDoubleLine := f3_doubleLine 467*09c6f1ddSLingrui98 preDecoderIn.ftqOffset := f3_ftq_req.ftqOffset 468*09c6f1ddSLingrui98 preDecoderIn.target := f3_ftq_req.target 469*09c6f1ddSLingrui98 preDecoderIn.oversize := f3_ftq_req.oversize 470*09c6f1ddSLingrui98 preDecoderIn.lastHalfMatch := f3_lastHalfMatch 471*09c6f1ddSLingrui98 preDecoderIn.pageFault := f3_except_pf 472*09c6f1ddSLingrui98 preDecoderIn.accessFault := f3_except_af 473*09c6f1ddSLingrui98 474*09c6f1ddSLingrui98 475*09c6f1ddSLingrui98 // TODO: What if next packet does not match? 476*09c6f1ddSLingrui98 when (f3_flush) { 477*09c6f1ddSLingrui98 f3_lastHalf.valid := false.B 478*09c6f1ddSLingrui98 }.elsewhen (io.toIbuffer.fire()) { 479*09c6f1ddSLingrui98 f3_lastHalf.valid := preDecoderOut.hasLastHalf 480*09c6f1ddSLingrui98 f3_lastHalf.middlePC := preDecoderOut.realEndPC 481*09c6f1ddSLingrui98 } 482*09c6f1ddSLingrui98 483*09c6f1ddSLingrui98 val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt 484*09c6f1ddSLingrui98 485*09c6f1ddSLingrui98 io.toIbuffer.valid := f3_valid 486*09c6f1ddSLingrui98 io.toIbuffer.bits.instrs := preDecoderOut.instrs 487*09c6f1ddSLingrui98 io.toIbuffer.bits.valid := f3_predecode_range & preDecoderOut.instrRange.asUInt 488*09c6f1ddSLingrui98 io.toIbuffer.bits.pd := preDecoderOut.pd 489*09c6f1ddSLingrui98 io.toIbuffer.bits.ftqPtr := f3_ftq_req.ftqIdx 490*09c6f1ddSLingrui98 io.toIbuffer.bits.pc := preDecoderOut.pc 491*09c6f1ddSLingrui98 io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i)} 492*09c6f1ddSLingrui98 io.toIbuffer.bits.foldpc := preDecoderOut.pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth)) 493*09c6f1ddSLingrui98 io.toIbuffer.bits.ipf := preDecoderOut.pageFault 494*09c6f1ddSLingrui98 io.toIbuffer.bits.acf := preDecoderOut.accessFault 495*09c6f1ddSLingrui98 io.toIbuffer.bits.crossPageIPFFix := preDecoderOut.crossPageIPF 496*09c6f1ddSLingrui98 497*09c6f1ddSLingrui98 //Write back to Ftq 498*09c6f1ddSLingrui98 val finishFetchMaskReg = RegNext(f3_valid && !(f2_fire && !f2_flush)) 499*09c6f1ddSLingrui98 500*09c6f1ddSLingrui98 toFtq.pdWb.valid := !finishFetchMaskReg && f3_valid 501*09c6f1ddSLingrui98 toFtq.pdWb.bits.pc := preDecoderOut.pc 502*09c6f1ddSLingrui98 toFtq.pdWb.bits.pd := preDecoderOut.pd 503*09c6f1ddSLingrui98 toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid := f3_predecode_range(i)} 504*09c6f1ddSLingrui98 toFtq.pdWb.bits.ftqIdx := f3_ftq_req.ftqIdx 505*09c6f1ddSLingrui98 toFtq.pdWb.bits.ftqOffset := f3_ftq_req.ftqOffset.bits 506*09c6f1ddSLingrui98 toFtq.pdWb.bits.misOffset := preDecoderOut.misOffset 507*09c6f1ddSLingrui98 toFtq.pdWb.bits.cfiOffset := preDecoderOut.cfiOffset 508*09c6f1ddSLingrui98 toFtq.pdWb.bits.target := preDecoderOut.target 509*09c6f1ddSLingrui98 toFtq.pdWb.bits.jalTarget := preDecoderOut.jalTarget 510*09c6f1ddSLingrui98 toFtq.pdWb.bits.instrRange := preDecoderOut.instrRange 511*09c6f1ddSLingrui98 512*09c6f1ddSLingrui98 val predecodeFlush = preDecoderOut.misOffset.valid && f3_valid 513*09c6f1ddSLingrui98 val predecodeFlushReg = RegNext(predecodeFlush && !(f2_fire && !f2_flush)) 514*09c6f1ddSLingrui98 515*09c6f1ddSLingrui98 f3_redirect := !predecodeFlushReg && predecodeFlush 516*09c6f1ddSLingrui98 517*09c6f1ddSLingrui98 // Performance Counter 518*09c6f1ddSLingrui98 XSPerfAccumulate("req", io.toIbuffer.fire() ) 519*09c6f1ddSLingrui98 XSPerfAccumulate("miss", io.toIbuffer.fire() && !f3_hit ) 520*09c6f1ddSLingrui98 XSPerfAccumulate("frontendFlush", f3_redirect ) 521*09c6f1ddSLingrui98 XSPerfAccumulate("only_0_miss", only_0_miss ) 522*09c6f1ddSLingrui98 XSPerfAccumulate("hit_0_miss_1", hit_0_miss_1 ) 523*09c6f1ddSLingrui98 XSPerfAccumulate("miss_0_hit_1", miss_0_hit_1 ) 524*09c6f1ddSLingrui98 XSPerfAccumulate("miss_0_miss_1", miss_0_miss_1 ) 525*09c6f1ddSLingrui98 XSPerfAccumulate("crossLine", io.toIbuffer.fire() && f3_situation(0) ) 526*09c6f1ddSLingrui98 XSPerfAccumulate("lastInLin", io.toIbuffer.fire() && f3_situation(1) ) 527*09c6f1ddSLingrui98} 528