109c6f1ddSLingrui98/*************************************************************************************** 209c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 309c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory 409c6f1ddSLingrui98* 509c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2. 609c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2. 709c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at: 809c6f1ddSLingrui98* http://license.coscl.org.cn/MulanPSL2 909c6f1ddSLingrui98* 1009c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1109c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1209c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1309c6f1ddSLingrui98* 1409c6f1ddSLingrui98* See the Mulan PSL v2 for more details. 1509c6f1ddSLingrui98***************************************************************************************/ 1609c6f1ddSLingrui98 1709c6f1ddSLingrui98package xiangshan.frontend 1809c6f1ddSLingrui98 1909c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters 2009c6f1ddSLingrui98import chisel3._ 2109c6f1ddSLingrui98import chisel3.util._ 2209c6f1ddSLingrui98import xiangshan._ 2309c6f1ddSLingrui98import xiangshan.cache._ 2409c6f1ddSLingrui98import xiangshan.cache.mmu._ 2509c6f1ddSLingrui98import chisel3.experimental.verification 2609c6f1ddSLingrui98import utils._ 27b6982e83SLemoverimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 2809c6f1ddSLingrui98 2909c6f1ddSLingrui98trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{ 3009c6f1ddSLingrui98 def mmioBusWidth = 64 3109c6f1ddSLingrui98 def mmioBusBytes = mmioBusWidth / 8 320be662e4SJay def maxInstrLen = 32 3309c6f1ddSLingrui98} 3409c6f1ddSLingrui98 3509c6f1ddSLingrui98trait HasIFUConst extends HasXSParameter { 3609c6f1ddSLingrui98 def align(pc: UInt, bytes: Int): UInt = Cat(pc(VAddrBits-1, log2Ceil(bytes)), 0.U(log2Ceil(bytes).W)) 3709c6f1ddSLingrui98 // def groupAligned(pc: UInt) = align(pc, groupBytes) 3809c6f1ddSLingrui98 // def packetAligned(pc: UInt) = align(pc, packetBytes) 3909c6f1ddSLingrui98} 4009c6f1ddSLingrui98 4109c6f1ddSLingrui98class IfuToFtqIO(implicit p:Parameters) extends XSBundle { 4209c6f1ddSLingrui98 val pdWb = Valid(new PredecodeWritebackBundle) 4309c6f1ddSLingrui98} 4409c6f1ddSLingrui98 4509c6f1ddSLingrui98class FtqInterface(implicit p: Parameters) extends XSBundle { 4609c6f1ddSLingrui98 val fromFtq = Flipped(new FtqToIfuIO) 4709c6f1ddSLingrui98 val toFtq = new IfuToFtqIO 4809c6f1ddSLingrui98} 4909c6f1ddSLingrui98 500be662e4SJayclass UncacheInterface(implicit p: Parameters) extends XSBundle { 510be662e4SJay val fromUncache = Flipped(DecoupledIO(new InsUncacheResp)) 520be662e4SJay val toUncache = DecoupledIO( new InsUncacheReq ) 530be662e4SJay} 540be662e4SJay 5509c6f1ddSLingrui98class ICacheInterface(implicit p: Parameters) extends XSBundle { 5609c6f1ddSLingrui98 val toIMeta = Decoupled(new ICacheReadBundle) 5709c6f1ddSLingrui98 val toIData = Decoupled(new ICacheReadBundle) 5809c6f1ddSLingrui98 val toMissQueue = Vec(2,Decoupled(new ICacheMissReq)) 5909c6f1ddSLingrui98 val fromIMeta = Input(new ICacheMetaRespBundle) 6009c6f1ddSLingrui98 val fromIData = Input(new ICacheDataRespBundle) 6109c6f1ddSLingrui98 val fromMissQueue = Vec(2,Flipped(Decoupled(new ICacheMissResp))) 6209c6f1ddSLingrui98} 6309c6f1ddSLingrui98 6409c6f1ddSLingrui98class NewIFUIO(implicit p: Parameters) extends XSBundle { 6509c6f1ddSLingrui98 val ftqInter = new FtqInterface 6609c6f1ddSLingrui98 val icacheInter = new ICacheInterface 6709c6f1ddSLingrui98 val toIbuffer = Decoupled(new FetchToIBuffer) 6809c6f1ddSLingrui98 val iTLBInter = Vec(2, new BlockTlbRequestIO) 690be662e4SJay val uncacheInter = new UncacheInterface 70b6982e83SLemover val pmp = Vec(2, new Bundle { 71b6982e83SLemover val req = Valid(new PMPReqBundle()) 72ca2f90a6SLemover val resp = Flipped(new PMPRespBundle()) 73b6982e83SLemover }) 74a37fbf10SJay val rob_commits = Flipped(Vec(CommitWidth, Valid(new RobCommitInfo))) 7509c6f1ddSLingrui98} 7609c6f1ddSLingrui98 7709c6f1ddSLingrui98// record the situation in which fallThruAddr falls into 7809c6f1ddSLingrui98// the middle of an RVI inst 7909c6f1ddSLingrui98class LastHalfInfo(implicit p: Parameters) extends XSBundle { 8009c6f1ddSLingrui98 val valid = Bool() 8109c6f1ddSLingrui98 val middlePC = UInt(VAddrBits.W) 8209c6f1ddSLingrui98 def matchThisBlock(startAddr: UInt) = valid && middlePC === startAddr 8309c6f1ddSLingrui98} 8409c6f1ddSLingrui98 8509c6f1ddSLingrui98class IfuToPreDecode(implicit p: Parameters) extends XSBundle { 8609c6f1ddSLingrui98 val data = if(HasCExtension) Vec(PredictWidth + 1, UInt(16.W)) else Vec(PredictWidth, UInt(32.W)) 8709c6f1ddSLingrui98 val startAddr = UInt(VAddrBits.W) 8809c6f1ddSLingrui98 val fallThruAddr = UInt(VAddrBits.W) 8909c6f1ddSLingrui98 val fallThruError = Bool() 9009c6f1ddSLingrui98 val isDoubleLine = Bool() 9109c6f1ddSLingrui98 val ftqOffset = Valid(UInt(log2Ceil(PredictWidth).W)) 9209c6f1ddSLingrui98 val target = UInt(VAddrBits.W) 9309c6f1ddSLingrui98 val pageFault = Vec(2, Bool()) 9409c6f1ddSLingrui98 val accessFault = Vec(2, Bool()) 9509c6f1ddSLingrui98 val instValid = Bool() 9609c6f1ddSLingrui98 val lastHalfMatch = Bool() 9709c6f1ddSLingrui98 val oversize = Bool() 9809c6f1ddSLingrui98} 9909c6f1ddSLingrui98 10009c6f1ddSLingrui98class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters 10109c6f1ddSLingrui98{ 10209c6f1ddSLingrui98 println(s"icache ways: ${nWays} sets:${nSets}") 10309c6f1ddSLingrui98 val io = IO(new NewIFUIO) 10409c6f1ddSLingrui98 val (toFtq, fromFtq) = (io.ftqInter.toFtq, io.ftqInter.fromFtq) 10509c6f1ddSLingrui98 val (toMeta, toData, meta_resp, data_resp) = (io.icacheInter.toIMeta, io.icacheInter.toIData, io.icacheInter.fromIMeta, io.icacheInter.fromIData) 10609c6f1ddSLingrui98 val (toMissQueue, fromMissQueue) = (io.icacheInter.toMissQueue, io.icacheInter.fromMissQueue) 1070be662e4SJay val (toUncache, fromUncache) = (io.uncacheInter.toUncache , io.uncacheInter.fromUncache) 10809c6f1ddSLingrui98 val (toITLB, fromITLB) = (VecInit(io.iTLBInter.map(_.req)), VecInit(io.iTLBInter.map(_.resp))) 109b6982e83SLemover val fromPMP = io.pmp.map(_.resp) 11009c6f1ddSLingrui98 11109c6f1ddSLingrui98 def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits) 11209c6f1ddSLingrui98 11309c6f1ddSLingrui98 def isLastInCacheline(fallThruAddr: UInt): Bool = fallThruAddr(blockOffBits - 1, 1) === 0.U 11409c6f1ddSLingrui98 115b005f7c6SJay def ResultHoldBypass[T<:Data](data: T, valid: Bool): T = { 116b005f7c6SJay Mux(valid, data, RegEnable(data, valid)) 117b005f7c6SJay } 11809c6f1ddSLingrui98 11909c6f1ddSLingrui98 //--------------------------------------------- 12009c6f1ddSLingrui98 // Fetch Stage 1 : 12109c6f1ddSLingrui98 // * Send req to ICache Meta/Data 12209c6f1ddSLingrui98 // * Check whether need 2 line fetch 12309c6f1ddSLingrui98 //--------------------------------------------- 12409c6f1ddSLingrui98 12509c6f1ddSLingrui98 val f0_valid = fromFtq.req.valid 12609c6f1ddSLingrui98 val f0_ftq_req = fromFtq.req.bits 12709c6f1ddSLingrui98 val f0_situation = VecInit(Seq(isCrossLineReq(f0_ftq_req.startAddr, f0_ftq_req.fallThruAddr), isLastInCacheline(f0_ftq_req.fallThruAddr))) 12809c6f1ddSLingrui98 val f0_doubleLine = f0_situation(0) || f0_situation(1) 12909c6f1ddSLingrui98 val f0_vSetIdx = VecInit(get_idx((f0_ftq_req.startAddr)), get_idx(f0_ftq_req.fallThruAddr)) 13009c6f1ddSLingrui98 val f0_fire = fromFtq.req.fire() 13109c6f1ddSLingrui98 13209c6f1ddSLingrui98 val f0_flush, f1_flush, f2_flush, f3_flush = WireInit(false.B) 13309c6f1ddSLingrui98 val from_bpu_f0_flush, from_bpu_f1_flush, from_bpu_f2_flush, from_bpu_f3_flush = WireInit(false.B) 13409c6f1ddSLingrui98 13509c6f1ddSLingrui98 from_bpu_f0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(f0_ftq_req.ftqIdx) || 13609c6f1ddSLingrui98 fromFtq.flushFromBpu.shouldFlushByStage3(f0_ftq_req.ftqIdx) 13709c6f1ddSLingrui98 13809c6f1ddSLingrui98 val f3_redirect = WireInit(false.B) 13909c6f1ddSLingrui98 f3_flush := fromFtq.redirect.valid 14009c6f1ddSLingrui98 f2_flush := f3_flush || f3_redirect 14109c6f1ddSLingrui98 f1_flush := f2_flush || from_bpu_f1_flush 14209c6f1ddSLingrui98 f0_flush := f1_flush || from_bpu_f0_flush 14309c6f1ddSLingrui98 14409c6f1ddSLingrui98 val f1_ready, f2_ready, f3_ready = WireInit(false.B) 14509c6f1ddSLingrui98 14609c6f1ddSLingrui98 //fetch: send addr to Meta/TLB and Data simultaneously 14709c6f1ddSLingrui98 val fetch_req = List(toMeta, toData) 14809c6f1ddSLingrui98 for(i <- 0 until 2) { 14909c6f1ddSLingrui98 fetch_req(i).valid := f0_fire 15009c6f1ddSLingrui98 fetch_req(i).bits.isDoubleLine := f0_doubleLine 15109c6f1ddSLingrui98 fetch_req(i).bits.vSetIdx := f0_vSetIdx 15209c6f1ddSLingrui98 } 15309c6f1ddSLingrui98 15409c6f1ddSLingrui98 fromFtq.req.ready := fetch_req(0).ready && fetch_req(1).ready && f1_ready && GTimer() > 500.U 15509c6f1ddSLingrui98 156f7c29b0aSJinYue XSPerfAccumulate("ifu_bubble_ftq_not_valid", !f0_valid ) 157f7c29b0aSJinYue XSPerfAccumulate("ifu_bubble_pipe_stall", f0_valid && fetch_req(0).ready && fetch_req(1).ready && !f1_ready ) 158f7c29b0aSJinYue XSPerfAccumulate("ifu_bubble_sram_0_busy", f0_valid && !fetch_req(0).ready ) 159f7c29b0aSJinYue XSPerfAccumulate("ifu_bubble_sram_1_busy", f0_valid && !fetch_req(1).ready ) 160f7c29b0aSJinYue 16109c6f1ddSLingrui98 //--------------------------------------------- 16209c6f1ddSLingrui98 // Fetch Stage 2 : 16309c6f1ddSLingrui98 // * Send req to ITLB and TLB Response (Get Paddr) 16409c6f1ddSLingrui98 // * ICache Response (Get Meta and Data) 16509c6f1ddSLingrui98 // * Hit Check (Generate hit signal and hit vector) 16609c6f1ddSLingrui98 // * Get victim way 16709c6f1ddSLingrui98 //--------------------------------------------- 16809c6f1ddSLingrui98 16909c6f1ddSLingrui98 //TODO: handle fetch exceptions 17009c6f1ddSLingrui98 17109c6f1ddSLingrui98 val tlbRespAllValid = WireInit(false.B) 17209c6f1ddSLingrui98 17309c6f1ddSLingrui98 val f1_valid = RegInit(false.B) 17409c6f1ddSLingrui98 val f1_ftq_req = RegEnable(next = f0_ftq_req, enable=f0_fire) 17509c6f1ddSLingrui98 val f1_situation = RegEnable(next = f0_situation, enable=f0_fire) 17609c6f1ddSLingrui98 val f1_doubleLine = RegEnable(next = f0_doubleLine, enable=f0_fire) 17709c6f1ddSLingrui98 val f1_vSetIdx = RegEnable(next = f0_vSetIdx, enable=f0_fire) 17809c6f1ddSLingrui98 val f1_fire = f1_valid && tlbRespAllValid && f2_ready 17909c6f1ddSLingrui98 18009c6f1ddSLingrui98 f1_ready := f2_ready && tlbRespAllValid || !f1_valid 18109c6f1ddSLingrui98 18209c6f1ddSLingrui98 from_bpu_f1_flush := fromFtq.flushFromBpu.shouldFlushByStage3(f1_ftq_req.ftqIdx) 18309c6f1ddSLingrui98 18409c6f1ddSLingrui98 val preDecoder = Module(new PreDecode) 18509c6f1ddSLingrui98 val (preDecoderIn, preDecoderOut) = (preDecoder.io.in, preDecoder.io.out) 18609c6f1ddSLingrui98 18709c6f1ddSLingrui98 //flush generate and to Ftq 18809c6f1ddSLingrui98 val predecodeOutValid = WireInit(false.B) 18909c6f1ddSLingrui98 19009c6f1ddSLingrui98 when(f1_flush) {f1_valid := false.B} 19109c6f1ddSLingrui98 .elsewhen(f0_fire && !f0_flush) {f1_valid := true.B} 19209c6f1ddSLingrui98 .elsewhen(f1_fire) {f1_valid := false.B} 19309c6f1ddSLingrui98 19409c6f1ddSLingrui98 toITLB(0).valid := f1_valid 195b6982e83SLemover toITLB(0).bits.size := 3.U // TODO: fix the size 196a37fbf10SJay toITLB(0).bits.vaddr := f1_ftq_req.startAddr 197a37fbf10SJay toITLB(0).bits.debug.pc := f1_ftq_req.startAddr 19809c6f1ddSLingrui98 19909c6f1ddSLingrui98 toITLB(1).valid := f1_valid && f1_doubleLine 200b6982e83SLemover toITLB(1).bits.size := 3.U // TODO: fix the size 201a37fbf10SJay toITLB(1).bits.vaddr := f1_ftq_req.fallThruAddr 202a37fbf10SJay toITLB(1).bits.debug.pc := f1_ftq_req.fallThruAddr 20309c6f1ddSLingrui98 20409c6f1ddSLingrui98 toITLB.map{port => 20509c6f1ddSLingrui98 port.bits.cmd := TlbCmd.exec 2069aca92b9SYinan Xu port.bits.robIdx := DontCare 20709c6f1ddSLingrui98 port.bits.debug.isFirstIssue := DontCare 20809c6f1ddSLingrui98 } 20909c6f1ddSLingrui98 21009c6f1ddSLingrui98 fromITLB.map(_.ready := true.B) 21109c6f1ddSLingrui98 21209c6f1ddSLingrui98 val (tlbRespValid, tlbRespPAddr) = (fromITLB.map(_.valid), VecInit(fromITLB.map(_.bits.paddr))) 213ca2f90a6SLemover val (tlbRespMiss) = (fromITLB.map(port => port.bits.miss && port.valid)) 214b6982e83SLemover val (tlbExcpPF, tlbExcpAF) = (fromITLB.map(port => port.bits.excp.pf.instr && port.valid), 215b6982e83SLemover fromITLB.map(port => (port.bits.excp.af.instr) && port.valid)) //TODO: Temp treat mmio req as access fault 216b6982e83SLemover 21709c6f1ddSLingrui98 tlbRespAllValid := tlbRespValid(0) && (tlbRespValid(1) || !f1_doubleLine) 21809c6f1ddSLingrui98 219b005f7c6SJay val f1_pAddrs = tlbRespPAddr 22003c39bdeSJinYue val f1_pTags = VecInit(f1_pAddrs.map(get_phy_tag(_))) 221b005f7c6SJay 222b005f7c6SJay val f1_tags = ResultHoldBypass(data = meta_resp.tags, valid = RegNext(toMeta.fire())) 223b005f7c6SJay val f1_cacheline_valid = ResultHoldBypass(data = meta_resp.valid, valid = RegNext(toMeta.fire())) 224b005f7c6SJay val f1_datas = ResultHoldBypass(data = data_resp.datas, valid = RegNext(toData.fire())) 225b005f7c6SJay 22609c6f1ddSLingrui98 val bank0_hit_vec = VecInit(f1_tags(0).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(0)(i) && way_tag === f1_pTags(0) }) 22709c6f1ddSLingrui98 val bank1_hit_vec = VecInit(f1_tags(1).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(1)(i) && way_tag === f1_pTags(1) }) 22809c6f1ddSLingrui98 val (bank0_hit,bank1_hit) = (ParallelOR(bank0_hit_vec) && !tlbExcpPF(0) && !tlbExcpAF(0), ParallelOR(bank1_hit_vec) && !tlbExcpPF(1) && !tlbExcpAF(1)) 22909c6f1ddSLingrui98 val f1_hit = (bank0_hit && bank1_hit && f1_valid && f1_doubleLine) || (f1_valid && !f1_doubleLine && bank0_hit) 23009c6f1ddSLingrui98 val f1_bank_hit_vec = VecInit(Seq(bank0_hit_vec, bank1_hit_vec)) 23109c6f1ddSLingrui98 val f1_bank_hit = VecInit(Seq(bank0_hit, bank1_hit)) 23209c6f1ddSLingrui98 2330be662e4SJay 23409c6f1ddSLingrui98 val replacers = Seq.fill(2)(ReplacementPolicy.fromString(Some("random"),nWays,nSets/2)) 23509c6f1ddSLingrui98 val f1_victim_masks = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(f1_vSetIdx(i)))}) 23609c6f1ddSLingrui98 23709c6f1ddSLingrui98 val touch_sets = Seq.fill(2)(Wire(Vec(2, UInt(log2Ceil(nSets/2).W)))) 23809c6f1ddSLingrui98 val touch_ways = Seq.fill(2)(Wire(Vec(2, Valid(UInt(log2Ceil(nWays).W)))) ) 23909c6f1ddSLingrui98 24009c6f1ddSLingrui98 ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)} 24109c6f1ddSLingrui98 24209c6f1ddSLingrui98 val f1_hit_data = VecInit(f1_datas.zipWithIndex.map { case(bank, i) => 24309c6f1ddSLingrui98 val bank_hit_data = Mux1H(f1_bank_hit_vec(i).asUInt, bank) 24409c6f1ddSLingrui98 bank_hit_data 24509c6f1ddSLingrui98 }) 24609c6f1ddSLingrui98 247f7c29b0aSJinYue (0 until nWays).map{ w => 248f7c29b0aSJinYue XSPerfAccumulate("line_0_hit_way_" + Integer.toString(w, 10), f1_fire && f1_bank_hit(0) && OHToUInt(f1_bank_hit_vec(0)) === w.U) 249f7c29b0aSJinYue } 250f7c29b0aSJinYue 251f7c29b0aSJinYue (0 until nWays).map{ w => 252f7c29b0aSJinYue XSPerfAccumulate("line_0_victim_way_" + Integer.toString(w, 10), f1_fire && !f1_bank_hit(0) && OHToUInt(f1_victim_masks(0)) === w.U) 253f7c29b0aSJinYue } 254f7c29b0aSJinYue 255f7c29b0aSJinYue (0 until nWays).map{ w => 256f7c29b0aSJinYue XSPerfAccumulate("line_1_hit_way_" + Integer.toString(w, 10), f1_fire && f1_doubleLine && f1_bank_hit(1) && OHToUInt(f1_bank_hit_vec(1)) === w.U) 257f7c29b0aSJinYue } 258f7c29b0aSJinYue 259f7c29b0aSJinYue (0 until nWays).map{ w => 260f7c29b0aSJinYue XSPerfAccumulate("line_1_victim_way_" + Integer.toString(w, 10), f1_fire && f1_doubleLine && !f1_bank_hit(1) && OHToUInt(f1_victim_masks(1)) === w.U) 261f7c29b0aSJinYue } 262f7c29b0aSJinYue 263f7c29b0aSJinYue XSPerfAccumulate("ifu_bubble_f1_tlb_miss", f1_valid && !tlbRespAllValid ) 26409c6f1ddSLingrui98 26509c6f1ddSLingrui98 //--------------------------------------------- 26609c6f1ddSLingrui98 // Fetch Stage 3 : 26709c6f1ddSLingrui98 // * get data from last stage (hit from f1_hit_data/miss from missQueue response) 26809c6f1ddSLingrui98 // * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!! 26909c6f1ddSLingrui98 // * cut cacheline(s) and send to PreDecode 27009c6f1ddSLingrui98 // * check if prediction is right (branch target and type, jump direction and type , jal target ) 27109c6f1ddSLingrui98 //--------------------------------------------- 27209c6f1ddSLingrui98 val f2_fetchFinish = Wire(Bool()) 27309c6f1ddSLingrui98 27409c6f1ddSLingrui98 val f2_valid = RegInit(false.B) 27509c6f1ddSLingrui98 val f2_ftq_req = RegEnable(next = f1_ftq_req, enable = f1_fire) 27609c6f1ddSLingrui98 val f2_situation = RegEnable(next = f1_situation, enable=f1_fire) 27709c6f1ddSLingrui98 val f2_doubleLine = RegEnable(next = f1_doubleLine, enable=f1_fire) 27809c6f1ddSLingrui98 val f2_fire = f2_valid && f2_fetchFinish && f3_ready 27909c6f1ddSLingrui98 28009c6f1ddSLingrui98 when(f2_flush) {f2_valid := false.B} 28109c6f1ddSLingrui98 .elsewhen(f1_fire && !f1_flush) {f2_valid := true.B } 28209c6f1ddSLingrui98 .elsewhen(f2_fire) {f2_valid := false.B} 28309c6f1ddSLingrui98 284b6982e83SLemover val pmpExcpAF = fromPMP.map(port => port.instr) 285ca2f90a6SLemover val mmio = fromPMP.map(port => port.mmio) // TODO: handle it 28609c6f1ddSLingrui98 2870be662e4SJay 28809c6f1ddSLingrui98 val f2_pAddrs = RegEnable(next = f1_pAddrs, enable = f1_fire) 28909c6f1ddSLingrui98 val f2_hit = RegEnable(next = f1_hit , enable = f1_fire) 29009c6f1ddSLingrui98 val f2_bank_hit = RegEnable(next = f1_bank_hit, enable = f1_fire) 29109c6f1ddSLingrui98 val f2_miss = f2_valid && !f2_hit 29209c6f1ddSLingrui98 val (f2_vSetIdx, f2_pTags) = (RegEnable(next = f1_vSetIdx, enable = f1_fire), RegEnable(next = f1_pTags, enable = f1_fire)) 29309c6f1ddSLingrui98 val f2_waymask = RegEnable(next = f1_victim_masks, enable = f1_fire) 29409c6f1ddSLingrui98 //exception information 29509c6f1ddSLingrui98 val f2_except_pf = RegEnable(next = VecInit(tlbExcpPF), enable = f1_fire) 296b6982e83SLemover val f2_except_af = VecInit(RegEnable(next = VecInit(tlbExcpAF), enable = f1_fire).zip(pmpExcpAF).map(a => a._1 || DataHoldBypass(a._2, RegNext(f1_fire)).asBool)) 29709c6f1ddSLingrui98 val f2_except = VecInit((0 until 2).map{i => f2_except_pf(i) || f2_except_af(i)}) 29809c6f1ddSLingrui98 val f2_has_except = f2_valid && (f2_except_af.reduce(_||_) || f2_except_pf.reduce(_||_)) 299a37fbf10SJay val f2_mmio = io.pmp(0).resp.mmio && !f2_except_af(0) && !f2_except_pf(0) && f2_valid 300a37fbf10SJay 301a37fbf10SJay f2_ready := (f3_ready && f2_fetchFinish) || !f2_valid 302a37fbf10SJay 3030be662e4SJay 304b6982e83SLemover io.pmp.zipWithIndex.map { case (p, i) => 305b6982e83SLemover p.req.valid := f2_fire 306b6982e83SLemover p.req.bits.addr := f2_pAddrs(i) 307b6982e83SLemover p.req.bits.size := 3.U // TODO 308b6982e83SLemover p.req.bits.cmd := TlbCmd.exec 309b6982e83SLemover } 31009c6f1ddSLingrui98 31109c6f1ddSLingrui98 //instruction 312a37fbf10SJay 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) 31309c6f1ddSLingrui98 val wait_state = RegInit(wait_idle) 31409c6f1ddSLingrui98 31509c6f1ddSLingrui98 fromMissQueue.map{port => port.ready := true.B} 31609c6f1ddSLingrui98 31709c6f1ddSLingrui98 val (miss0_resp, miss1_resp) = (fromMissQueue(0).fire(), fromMissQueue(1).fire()) 31809c6f1ddSLingrui98 val (bank0_fix, bank1_fix) = (miss0_resp && !f2_bank_hit(0), miss1_resp && f2_doubleLine && !f2_bank_hit(1)) 31909c6f1ddSLingrui98 3200be662e4SJay val only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except && !f2_mmio 3210be662e4SJay val only_0_hit = f2_valid && f2_hit && !f2_doubleLine && !f2_mmio 3220be662e4SJay val hit_0_hit_1 = f2_valid && f2_hit && f2_doubleLine && !f2_mmio 3230be662e4SJay 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 && !f2_mmio), 3240be662e4SJay (f2_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine && !f2_has_except && !f2_mmio), 3250be662e4SJay (f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except && !f2_mmio), 32609c6f1ddSLingrui98 ) 32709c6f1ddSLingrui98 32809c6f1ddSLingrui98 val hit_0_except_1 = f2_valid && f2_doubleLine && !f2_except(0) && f2_except(1) && f2_bank_hit(0) 32909c6f1ddSLingrui98 val miss_0_except_1 = f2_valid && f2_doubleLine && !f2_except(0) && f2_except(1) && !f2_bank_hit(0) 33009c6f1ddSLingrui98 //val fetch0_except_1 = hit_0_except_1 || miss_0_except_1 33109c6f1ddSLingrui98 val except_0 = f2_valid && f2_except(0) 33209c6f1ddSLingrui98 33309c6f1ddSLingrui98 val f2_mq_datas = Reg(Vec(2, UInt(blockBits.W))) 33409c6f1ddSLingrui98 33509c6f1ddSLingrui98 when(fromMissQueue(0).fire) {f2_mq_datas(0) := fromMissQueue(0).bits.data} 33609c6f1ddSLingrui98 when(fromMissQueue(1).fire) {f2_mq_datas(1) := fromMissQueue(1).bits.data} 33709c6f1ddSLingrui98 33809c6f1ddSLingrui98 switch(wait_state){ 33909c6f1ddSLingrui98 is(wait_idle){ 340a37fbf10SJay when(miss_0_except_1){ 34109c6f1ddSLingrui98 wait_state := Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle ) 34209c6f1ddSLingrui98 }.elsewhen( only_0_miss || miss_0_hit_1){ 34309c6f1ddSLingrui98 wait_state := Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle ) 34409c6f1ddSLingrui98 }.elsewhen(hit_0_miss_1){ 34509c6f1ddSLingrui98 wait_state := Mux(toMissQueue(1).ready, wait_queue_ready ,wait_idle ) 34609c6f1ddSLingrui98 }.elsewhen( miss_0_miss_1 ){ 34709c6f1ddSLingrui98 wait_state := Mux(toMissQueue(0).ready && toMissQueue(1).ready, wait_queue_ready ,wait_idle) 34809c6f1ddSLingrui98 } 34909c6f1ddSLingrui98 } 35009c6f1ddSLingrui98 35109c6f1ddSLingrui98 //TODO: naive logic for wait icache response 35209c6f1ddSLingrui98 is(wait_queue_ready){ 35309c6f1ddSLingrui98 wait_state := wait_send_req 35409c6f1ddSLingrui98 } 35509c6f1ddSLingrui98 35609c6f1ddSLingrui98 is(wait_send_req) { 35709c6f1ddSLingrui98 when(miss_0_except_1 || only_0_miss || hit_0_miss_1 || miss_0_hit_1){ 35809c6f1ddSLingrui98 wait_state := wait_one_resp 35909c6f1ddSLingrui98 }.elsewhen( miss_0_miss_1 ){ 36009c6f1ddSLingrui98 wait_state := wait_two_resp 36109c6f1ddSLingrui98 } 36209c6f1ddSLingrui98 } 36309c6f1ddSLingrui98 36409c6f1ddSLingrui98 is(wait_one_resp) { 36509c6f1ddSLingrui98 when( (miss_0_except_1 ||only_0_miss || miss_0_hit_1) && fromMissQueue(0).fire()){ 36609c6f1ddSLingrui98 wait_state := wait_finish 36709c6f1ddSLingrui98 }.elsewhen( hit_0_miss_1 && fromMissQueue(1).fire()){ 36809c6f1ddSLingrui98 wait_state := wait_finish 36909c6f1ddSLingrui98 } 37009c6f1ddSLingrui98 } 37109c6f1ddSLingrui98 37209c6f1ddSLingrui98 is(wait_two_resp) { 37309c6f1ddSLingrui98 when(fromMissQueue(0).fire() && fromMissQueue(1).fire()){ 37409c6f1ddSLingrui98 wait_state := wait_finish 37509c6f1ddSLingrui98 }.elsewhen( !fromMissQueue(0).fire() && fromMissQueue(1).fire() ){ 37609c6f1ddSLingrui98 wait_state := wait_0_resp 37709c6f1ddSLingrui98 }.elsewhen(fromMissQueue(0).fire() && !fromMissQueue(1).fire()){ 37809c6f1ddSLingrui98 wait_state := wait_1_resp 37909c6f1ddSLingrui98 } 38009c6f1ddSLingrui98 } 38109c6f1ddSLingrui98 38209c6f1ddSLingrui98 is(wait_0_resp) { 38309c6f1ddSLingrui98 when(fromMissQueue(0).fire()){ 38409c6f1ddSLingrui98 wait_state := wait_finish 38509c6f1ddSLingrui98 } 38609c6f1ddSLingrui98 } 38709c6f1ddSLingrui98 38809c6f1ddSLingrui98 is(wait_1_resp) { 38909c6f1ddSLingrui98 when(fromMissQueue(1).fire()){ 39009c6f1ddSLingrui98 wait_state := wait_finish 39109c6f1ddSLingrui98 } 39209c6f1ddSLingrui98 } 39309c6f1ddSLingrui98 39409c6f1ddSLingrui98 is(wait_finish) { 39509c6f1ddSLingrui98 when(f2_fire) {wait_state := wait_idle } 39609c6f1ddSLingrui98 } 39709c6f1ddSLingrui98 } 39809c6f1ddSLingrui98 39909c6f1ddSLingrui98 when(f2_flush) { wait_state := wait_idle } 40009c6f1ddSLingrui98 40109c6f1ddSLingrui98 (0 until 2).map { i => 40209c6f1ddSLingrui98 if(i == 1) toMissQueue(i).valid := (hit_0_miss_1 || miss_0_miss_1) && wait_state === wait_queue_ready 403eee4cb5cSJay else toMissQueue(i).valid := (only_0_miss || miss_0_hit_1 || miss_0_miss_1 || miss_0_except_1) && wait_state === wait_queue_ready 40409c6f1ddSLingrui98 toMissQueue(i).bits.addr := f2_pAddrs(i) 40509c6f1ddSLingrui98 toMissQueue(i).bits.vSetIdx := f2_vSetIdx(i) 40609c6f1ddSLingrui98 toMissQueue(i).bits.waymask := f2_waymask(i) 40709c6f1ddSLingrui98 toMissQueue(i).bits.clientID :=0.U 40809c6f1ddSLingrui98 } 40909c6f1ddSLingrui98 4100be662e4SJay 41109c6f1ddSLingrui98 val miss_all_fix = (wait_state === wait_finish) 41209c6f1ddSLingrui98 413a37fbf10SJay f2_fetchFinish := ((f2_valid && f2_hit) || (f2_valid && f2_mmio) || miss_all_fix || hit_0_except_1 || except_0) 41409c6f1ddSLingrui98 415f7c29b0aSJinYue XSPerfAccumulate("ifu_bubble_f2_miss", f2_valid && !f2_fetchFinish ) 41609c6f1ddSLingrui98 41709c6f1ddSLingrui98 (touch_ways zip touch_sets).zipWithIndex.map{ case((t_w,t_s), i) => 41809c6f1ddSLingrui98 t_s(0) := f1_vSetIdx(i) 41909c6f1ddSLingrui98 t_w(0).valid := f1_bank_hit(i) 42009c6f1ddSLingrui98 t_w(0).bits := OHToUInt(f1_bank_hit_vec(i)) 42109c6f1ddSLingrui98 42209c6f1ddSLingrui98 t_s(1) := f2_vSetIdx(i) 42309c6f1ddSLingrui98 t_w(1).valid := f2_valid && !f2_bank_hit(i) 42409c6f1ddSLingrui98 t_w(1).bits := OHToUInt(f2_waymask(i)) 42509c6f1ddSLingrui98 } 42609c6f1ddSLingrui98 42709c6f1ddSLingrui98 val sec_miss_reg = RegInit(0.U.asTypeOf(Vec(4, Bool()))) 42809c6f1ddSLingrui98 val reservedRefillData = Reg(Vec(2, UInt(blockBits.W))) 42909c6f1ddSLingrui98 val f2_hit_datas = RegEnable(next = f1_hit_data, enable = f1_fire) 43009c6f1ddSLingrui98 val f2_datas = Wire(Vec(2, UInt(blockBits.W))) 43109c6f1ddSLingrui98 43209c6f1ddSLingrui98 f2_datas.zipWithIndex.map{case(bank,i) => 43309c6f1ddSLingrui98 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)))) 43409c6f1ddSLingrui98 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)))) 43509c6f1ddSLingrui98 } 43609c6f1ddSLingrui98 43709c6f1ddSLingrui98 val f2_jump_valids = Fill(PredictWidth, !preDecoderOut.cfiOffset.valid) | Fill(PredictWidth, 1.U(1.W)) >> (~preDecoderOut.cfiOffset.bits) 43809c6f1ddSLingrui98 val f2_predecode_valids = VecInit(preDecoderOut.pd.map(instr => instr.valid)).asUInt & f2_jump_valids 43909c6f1ddSLingrui98 44009c6f1ddSLingrui98 def cut(cacheline: UInt, start: UInt) : Vec[UInt] ={ 44109c6f1ddSLingrui98 if(HasCExtension){ 44209c6f1ddSLingrui98 val result = Wire(Vec(PredictWidth + 1, UInt(16.W))) 44309c6f1ddSLingrui98 val dataVec = cacheline.asTypeOf(Vec(blockBytes * 2/ 2, UInt(16.W))) 44409c6f1ddSLingrui98 val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 1)) 44509c6f1ddSLingrui98 (0 until PredictWidth + 1).foreach( i => 44609c6f1ddSLingrui98 result(i) := dataVec(startPtr + i.U) 44709c6f1ddSLingrui98 ) 44809c6f1ddSLingrui98 result 44909c6f1ddSLingrui98 } else { 45009c6f1ddSLingrui98 val result = Wire(Vec(PredictWidth, UInt(32.W)) ) 45109c6f1ddSLingrui98 val dataVec = cacheline.asTypeOf(Vec(blockBytes * 2/ 4, UInt(32.W))) 45209c6f1ddSLingrui98 val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 2)) 45309c6f1ddSLingrui98 (0 until PredictWidth).foreach( i => 45409c6f1ddSLingrui98 result(i) := dataVec(startPtr + i.U) 45509c6f1ddSLingrui98 ) 45609c6f1ddSLingrui98 result 45709c6f1ddSLingrui98 } 45809c6f1ddSLingrui98 } 45909c6f1ddSLingrui98 46009c6f1ddSLingrui98 val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_ftq_req.startAddr ) 46109c6f1ddSLingrui98 46209c6f1ddSLingrui98 // deal with secondary miss in f1 46309c6f1ddSLingrui98 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))) 46409c6f1ddSLingrui98 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))) 46509c6f1ddSLingrui98 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) )) 46609c6f1ddSLingrui98 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) )) 46709c6f1ddSLingrui98 46809c6f1ddSLingrui98 val isSameLine = f2_0_f1_0 || f2_0_f1_1 || f2_1_f1_0 || f2_1_f1_1 46909c6f1ddSLingrui98 val sec_miss_sit = VecInit(Seq(f2_0_f1_0, f2_0_f1_1, f2_1_f1_0, f2_1_f1_1)) 47009c6f1ddSLingrui98 val hasSecMiss = RegInit(false.B) 47109c6f1ddSLingrui98 47209c6f1ddSLingrui98 when(f2_flush){ 47309c6f1ddSLingrui98 sec_miss_reg.map(sig => sig := false.B) 47409c6f1ddSLingrui98 hasSecMiss := false.B 47509c6f1ddSLingrui98 }.elsewhen(isSameLine && !f1_flush && f2_fire){ 47609c6f1ddSLingrui98 sec_miss_reg.zipWithIndex.map{case(sig, i) => sig := sec_miss_sit(i)} 47709c6f1ddSLingrui98 hasSecMiss := true.B 47809c6f1ddSLingrui98 }.elsewhen((!isSameLine || f1_flush) && hasSecMiss && f2_fire){ 47909c6f1ddSLingrui98 sec_miss_reg.map(sig => sig := false.B) 48009c6f1ddSLingrui98 hasSecMiss := false.B 48109c6f1ddSLingrui98 } 48209c6f1ddSLingrui98 48309c6f1ddSLingrui98 when((f2_0_f1_0 || f2_0_f1_1) && f2_fire){ 48409c6f1ddSLingrui98 reservedRefillData(0) := f2_mq_datas(0) 48509c6f1ddSLingrui98 } 48609c6f1ddSLingrui98 48709c6f1ddSLingrui98 when((f2_1_f1_0 || f2_1_f1_1) && f2_fire){ 48809c6f1ddSLingrui98 reservedRefillData(1) := f2_mq_datas(1) 48909c6f1ddSLingrui98 } 49009c6f1ddSLingrui98 49109c6f1ddSLingrui98 49209c6f1ddSLingrui98 //--------------------------------------------- 49309c6f1ddSLingrui98 // Fetch Stage 4 : 49409c6f1ddSLingrui98 // * get data from last stage (hit from f1_hit_data/miss from missQueue response) 49509c6f1ddSLingrui98 // * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!! 49609c6f1ddSLingrui98 // * cut cacheline(s) and send to PreDecode 49709c6f1ddSLingrui98 // * check if prediction is right (branch target and type, jump direction and type , jal target ) 49809c6f1ddSLingrui98 //--------------------------------------------- 49909c6f1ddSLingrui98 val f3_valid = RegInit(false.B) 50009c6f1ddSLingrui98 val f3_ftq_req = RegEnable(next = f2_ftq_req, enable=f2_fire) 50109c6f1ddSLingrui98 val f3_situation = RegEnable(next = f2_situation, enable=f2_fire) 50209c6f1ddSLingrui98 val f3_doubleLine = RegEnable(next = f2_doubleLine, enable=f2_fire) 50309c6f1ddSLingrui98 50409c6f1ddSLingrui98 val f3_cut_data = RegEnable(next = f2_cut_data, enable=f2_fire) 50509c6f1ddSLingrui98 val f3_except_pf = RegEnable(next = f2_except_pf, enable = f2_fire) 50609c6f1ddSLingrui98 val f3_except_af = RegEnable(next = f2_except_af, enable = f2_fire) 50709c6f1ddSLingrui98 val f3_hit = RegEnable(next = f2_hit , enable = f2_fire) 5080be662e4SJay val f3_mmio = RegEnable(next = f2_mmio , enable = f2_fire) 50909c6f1ddSLingrui98 510*aa695f76SJay //assert((f3_ftq_req.startAddr + 34.U) >= f3_ftq_req.fallThruAddr, "Fall through address exceeds the limit") 511*aa695f76SJay 51209c6f1ddSLingrui98 val f3_lastHalf = RegInit(0.U.asTypeOf(new LastHalfInfo)) 51309c6f1ddSLingrui98 val f3_lastHalfMatch = f3_lastHalf.matchThisBlock(f3_ftq_req.startAddr) 51409c6f1ddSLingrui98 val f3_except = VecInit((0 until 2).map{i => f3_except_pf(i) || f3_except_af(i)}) 51509c6f1ddSLingrui98 val f3_has_except = f3_valid && (f3_except_af.reduce(_||_) || f3_except_pf.reduce(_||_)) 516a37fbf10SJay val f3_pAddrs = RegEnable(next = f2_pAddrs, enable = f2_fire) 517a37fbf10SJay 518a37fbf10SJay val f3_mmio_data = Reg(UInt(maxInstrLen.W)) 519a37fbf10SJay 520a37fbf10SJay val f3_data = if(HasCExtension) Wire(Vec(PredictWidth + 1, UInt(16.W))) else Wire(Vec(PredictWidth, UInt(32.W))) 521a37fbf10SJay f3_data := f3_cut_data 522a37fbf10SJay when(f3_mmio && f3_valid && !f3_except_af(0) && !f3_except_pf(0)){ 523a37fbf10SJay f3_data(0) := f3_mmio_data(15, 0) 524a37fbf10SJay f3_data(1) := f3_mmio_data(31, 16) 525a37fbf10SJay } 52609c6f1ddSLingrui98 527f7c29b0aSJinYue //performance counter 528f7c29b0aSJinYue val f3_only_0_hit = RegEnable(next = only_0_hit, enable = f2_fire) 529f7c29b0aSJinYue val f3_only_0_miss = RegEnable(next = only_0_miss, enable = f2_fire) 530f7c29b0aSJinYue val f3_hit_0_hit_1 = RegEnable(next = hit_0_hit_1, enable = f2_fire) 531f7c29b0aSJinYue val f3_hit_0_miss_1 = RegEnable(next = hit_0_miss_1, enable = f2_fire) 532f7c29b0aSJinYue val f3_miss_0_hit_1 = RegEnable(next = miss_0_hit_1, enable = f2_fire) 533f7c29b0aSJinYue val f3_miss_0_miss_1 = RegEnable(next = miss_0_miss_1, enable = f2_fire) 534f7c29b0aSJinYue 535a37fbf10SJay val mmio_idle :: mmio_send_req :: mmio_w_resp :: mmio_resend :: mmio_resend_w_resp :: mmio_w_commit :: Nil = Enum(6) 536a37fbf10SJay val mmio_state = RegInit(mmio_idle) 537a37fbf10SJay 538a37fbf10SJay val f3_req_is_mmio = f3_mmio && f3_valid && !f3_except_af(0) 539a37fbf10SJay val mmio_has_commited = VecInit(io.rob_commits.map{commit => commit.valid && commit.bits.ftqIdx === f3_ftq_req.ftqIdx && commit.bits.ftqOffset === 0.U}).asUInt.orR 540a37fbf10SJay val f3_mmio_req_commit = f3_req_is_mmio && mmio_state === mmio_w_commit && mmio_has_commited 541a37fbf10SJay 542a37fbf10SJay val f3_mmio_to_commit = f3_req_is_mmio && mmio_state === mmio_w_commit 543a37fbf10SJay val f3_mmio_to_commit_next = RegNext(f3_mmio_to_commit) 544a37fbf10SJay val f3_mmio_can_go = f3_mmio_to_commit && !f3_mmio_to_commit_next 545a37fbf10SJay 546a37fbf10SJay when(f3_flush && !f3_req_is_mmio) {f3_valid := false.B} 547a37fbf10SJay .elsewhen(f2_fire && !f2_flush) {f3_valid := true.B } 548a37fbf10SJay .elsewhen(io.toIbuffer.fire() && !f3_req_is_mmio) {f3_valid := false.B} 549a37fbf10SJay .elsewhen{f3_req_is_mmio && f3_mmio_req_commit} {f3_valid := false.B} 550a37fbf10SJay 551a37fbf10SJay val f3_mmio_use_seq_pc = RegInit(false.B) 552a37fbf10SJay 553a37fbf10SJay val (redirect_ftqIdx, redirect_ftqOffset) = (fromFtq.redirect.bits.ftqIdx,fromFtq.redirect.bits.ftqOffset) 554a37fbf10SJay val redirect_mmio_req = fromFtq.redirect.valid && redirect_ftqIdx === f3_ftq_req.ftqIdx && redirect_ftqOffset === 0.U 555a37fbf10SJay 556a37fbf10SJay when(RegNext(f2_fire && !f2_flush) && f3_req_is_mmio) { f3_mmio_use_seq_pc := true.B } 557a37fbf10SJay .elsewhen(redirect_mmio_req) { f3_mmio_use_seq_pc := false.B } 558a37fbf10SJay 559a37fbf10SJay f3_ready := Mux(f3_req_is_mmio, io.toIbuffer.ready && f3_mmio_req_commit || !f3_valid , io.toIbuffer.ready || !f3_valid) 560a37fbf10SJay 561a37fbf10SJay when(fromUncache.fire()) {f3_mmio_data := fromUncache.bits.data} 562a37fbf10SJay 563a37fbf10SJay 564a37fbf10SJay switch(mmio_state){ 565a37fbf10SJay is(mmio_idle){ 566a37fbf10SJay when(f3_mmio && f3_valid && !f3_except_af(0) && !f3_except_pf(0)){ 567a37fbf10SJay mmio_state := mmio_send_req 568a37fbf10SJay } 569a37fbf10SJay } 570a37fbf10SJay 571a37fbf10SJay is(mmio_send_req){ 572a37fbf10SJay mmio_state := Mux(toUncache.fire(), mmio_w_resp, mmio_send_req ) 573a37fbf10SJay } 574a37fbf10SJay 575a37fbf10SJay is(mmio_w_resp){ 576a37fbf10SJay when(fromUncache.fire()){ 577a37fbf10SJay val isRVC = fromUncache.bits.data(1,0) =/= 3.U 578a37fbf10SJay mmio_state := Mux(isRVC, mmio_resend , mmio_w_commit) 579a37fbf10SJay } 580a37fbf10SJay } 581a37fbf10SJay 582a37fbf10SJay is(mmio_resend){ 583a37fbf10SJay mmio_state := Mux(toUncache.fire(), mmio_resend_w_resp, mmio_resend ) 584a37fbf10SJay } 585a37fbf10SJay 586a37fbf10SJay is(mmio_resend_w_resp){ 587a37fbf10SJay when(fromUncache.fire()){ 588a37fbf10SJay mmio_state := mmio_w_commit 589a37fbf10SJay } 590a37fbf10SJay } 591a37fbf10SJay 592a37fbf10SJay is(mmio_w_commit){ 593a37fbf10SJay when(mmio_has_commited){ 594a37fbf10SJay mmio_state := mmio_idle 595a37fbf10SJay } 596a37fbf10SJay } 597a37fbf10SJay } 598a37fbf10SJay 599a37fbf10SJay toUncache.valid := ((mmio_state === mmio_send_req) || (mmio_state === mmio_resend)) && f3_req_is_mmio 600a37fbf10SJay toUncache.bits.addr := Mux((mmio_state === mmio_resend), f3_pAddrs(0) + 2.U, f3_pAddrs(0)) 601a37fbf10SJay fromUncache.ready := true.B 602a37fbf10SJay 603f7c29b0aSJinYue val f3_bank_hit = RegEnable(next = f2_bank_hit, enable = f2_fire) 604f7c29b0aSJinYue val f3_req_0 = io.toIbuffer.fire() 605f7c29b0aSJinYue val f3_req_1 = io.toIbuffer.fire() && f3_doubleLine 606f7c29b0aSJinYue val f3_hit_0 = io.toIbuffer.fire() & f3_bank_hit(0) 607f7c29b0aSJinYue val f3_hit_1 = io.toIbuffer.fire() && f3_doubleLine & f3_bank_hit(1) 608f7c29b0aSJinYue 60909c6f1ddSLingrui98 preDecoderIn.instValid := f3_valid && !f3_has_except 610a37fbf10SJay preDecoderIn.data := f3_data 61109c6f1ddSLingrui98 preDecoderIn.startAddr := f3_ftq_req.startAddr 61209c6f1ddSLingrui98 preDecoderIn.fallThruAddr := f3_ftq_req.fallThruAddr 61309c6f1ddSLingrui98 preDecoderIn.fallThruError := f3_ftq_req.fallThruError 61409c6f1ddSLingrui98 preDecoderIn.isDoubleLine := f3_doubleLine 61509c6f1ddSLingrui98 preDecoderIn.ftqOffset := f3_ftq_req.ftqOffset 61609c6f1ddSLingrui98 preDecoderIn.target := f3_ftq_req.target 61709c6f1ddSLingrui98 preDecoderIn.oversize := f3_ftq_req.oversize 61809c6f1ddSLingrui98 preDecoderIn.lastHalfMatch := f3_lastHalfMatch 61909c6f1ddSLingrui98 preDecoderIn.pageFault := f3_except_pf 62009c6f1ddSLingrui98 preDecoderIn.accessFault := f3_except_af 62109c6f1ddSLingrui98 62209c6f1ddSLingrui98 62309c6f1ddSLingrui98 // TODO: What if next packet does not match? 62409c6f1ddSLingrui98 when (f3_flush) { 62509c6f1ddSLingrui98 f3_lastHalf.valid := false.B 62609c6f1ddSLingrui98 }.elsewhen (io.toIbuffer.fire()) { 62709c6f1ddSLingrui98 f3_lastHalf.valid := preDecoderOut.hasLastHalf 62809c6f1ddSLingrui98 f3_lastHalf.middlePC := preDecoderOut.realEndPC 62909c6f1ddSLingrui98 } 63009c6f1ddSLingrui98 63109c6f1ddSLingrui98 val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt 6320be662e4SJay val f3_mmio_range = VecInit((0 until PredictWidth).map(i => if(i ==0) true.B else false.B)) 63309c6f1ddSLingrui98 634a37fbf10SJay io.toIbuffer.valid := f3_valid && (!f3_req_is_mmio || f3_mmio_can_go) 63509c6f1ddSLingrui98 io.toIbuffer.bits.instrs := preDecoderOut.instrs 636a37fbf10SJay io.toIbuffer.bits.valid := Mux(f3_req_is_mmio, f3_mmio_range.asUInt, f3_predecode_range & preDecoderOut.instrRange.asUInt) 63709c6f1ddSLingrui98 io.toIbuffer.bits.pd := preDecoderOut.pd 63809c6f1ddSLingrui98 io.toIbuffer.bits.ftqPtr := f3_ftq_req.ftqIdx 63909c6f1ddSLingrui98 io.toIbuffer.bits.pc := preDecoderOut.pc 640a37fbf10SJay io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i) && !f3_req_is_mmio} 64109c6f1ddSLingrui98 io.toIbuffer.bits.foldpc := preDecoderOut.pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth)) 64209c6f1ddSLingrui98 io.toIbuffer.bits.ipf := preDecoderOut.pageFault 64309c6f1ddSLingrui98 io.toIbuffer.bits.acf := preDecoderOut.accessFault 64409c6f1ddSLingrui98 io.toIbuffer.bits.crossPageIPFFix := preDecoderOut.crossPageIPF 64509c6f1ddSLingrui98 64609c6f1ddSLingrui98 //Write back to Ftq 647a37fbf10SJay val f3_cache_fetch = f3_valid && !(f2_fire && !f2_flush) 648a37fbf10SJay val finishFetchMaskReg = RegNext(f3_cache_fetch) 649a37fbf10SJay 65009c6f1ddSLingrui98 6510be662e4SJay val f3_mmio_missOffset = Wire(ValidUndirectioned(UInt(log2Ceil(PredictWidth).W))) 652a37fbf10SJay f3_mmio_missOffset.valid := f3_req_is_mmio 6530be662e4SJay f3_mmio_missOffset.bits := 0.U 6540be662e4SJay 655a37fbf10SJay toFtq.pdWb.valid := (!finishFetchMaskReg && f3_valid && !f3_req_is_mmio) || (f3_mmio_req_commit && f3_mmio_use_seq_pc) 65609c6f1ddSLingrui98 toFtq.pdWb.bits.pc := preDecoderOut.pc 65709c6f1ddSLingrui98 toFtq.pdWb.bits.pd := preDecoderOut.pd 658a37fbf10SJay toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid := Mux(f3_req_is_mmio, f3_mmio_range(i), f3_predecode_range(i))} 65909c6f1ddSLingrui98 toFtq.pdWb.bits.ftqIdx := f3_ftq_req.ftqIdx 66009c6f1ddSLingrui98 toFtq.pdWb.bits.ftqOffset := f3_ftq_req.ftqOffset.bits 661a37fbf10SJay toFtq.pdWb.bits.misOffset := Mux(f3_req_is_mmio, f3_mmio_missOffset, preDecoderOut.misOffset) 66209c6f1ddSLingrui98 toFtq.pdWb.bits.cfiOffset := preDecoderOut.cfiOffset 663a37fbf10SJay toFtq.pdWb.bits.target := Mux(f3_req_is_mmio,Mux((f3_mmio_data(1,0) =/= 3.U), f3_ftq_req.startAddr + 2.U , f3_ftq_req.startAddr + 4.U) ,preDecoderOut.target) 66409c6f1ddSLingrui98 toFtq.pdWb.bits.jalTarget := preDecoderOut.jalTarget 665a37fbf10SJay toFtq.pdWb.bits.instrRange := Mux(f3_req_is_mmio, f3_mmio_range, preDecoderOut.instrRange) 66609c6f1ddSLingrui98 667a37fbf10SJay val predecodeFlush = preDecoderOut.misOffset.valid && f3_valid 66809c6f1ddSLingrui98 val predecodeFlushReg = RegNext(predecodeFlush && !(f2_fire && !f2_flush)) 66909c6f1ddSLingrui98 670cd365d4cSrvcoresjw val perfinfo = IO(new Bundle(){ 671cd365d4cSrvcoresjw val perfEvents = Output(new PerfEventsBundle(15)) 672cd365d4cSrvcoresjw }) 673cd365d4cSrvcoresjw 674cd365d4cSrvcoresjw val perfEvents = Seq( 675cd365d4cSrvcoresjw ("frontendFlush ", f3_redirect ), 676cd365d4cSrvcoresjw ("ifu_req ", io.toIbuffer.fire() ), 677cd365d4cSrvcoresjw ("ifu_miss ", io.toIbuffer.fire() && !f3_hit ), 678cd365d4cSrvcoresjw ("ifu_req_cacheline_0 ", f3_req_0 ), 679cd365d4cSrvcoresjw ("ifu_req_cacheline_1 ", f3_req_1 ), 680cd365d4cSrvcoresjw ("ifu_req_cacheline_0_hit ", f3_hit_1 ), 681cd365d4cSrvcoresjw ("ifu_req_cacheline_1_hit ", f3_hit_1 ), 682cd365d4cSrvcoresjw ("only_0_hit ", f3_only_0_hit && io.toIbuffer.fire() ), 683cd365d4cSrvcoresjw ("only_0_miss ", f3_only_0_miss && io.toIbuffer.fire() ), 684cd365d4cSrvcoresjw ("hit_0_hit_1 ", f3_hit_0_hit_1 && io.toIbuffer.fire() ), 685cd365d4cSrvcoresjw ("hit_0_miss_1 ", f3_hit_0_miss_1 && io.toIbuffer.fire() ), 686cd365d4cSrvcoresjw ("miss_0_hit_1 ", f3_miss_0_hit_1 && io.toIbuffer.fire() ), 687cd365d4cSrvcoresjw ("miss_0_miss_1 ", f3_miss_0_miss_1 && io.toIbuffer.fire() ), 688cd365d4cSrvcoresjw ("cross_line_block ", io.toIbuffer.fire() && f3_situation(0) ), 689cd365d4cSrvcoresjw ("fall_through_is_cacheline_end", io.toIbuffer.fire() && f3_situation(1) ), 690cd365d4cSrvcoresjw ) 691cd365d4cSrvcoresjw 692cd365d4cSrvcoresjw for (((perf_out,(perf_name,perf)),i) <- perfinfo.perfEvents.perf_events.zip(perfEvents).zipWithIndex) { 693cd365d4cSrvcoresjw perf_out.incr_step := RegNext(perf) 694cd365d4cSrvcoresjw } 695f7c29b0aSJinYue 696a37fbf10SJay f3_redirect := (!predecodeFlushReg && predecodeFlush && !f3_req_is_mmio) || (f3_mmio_req_commit && f3_mmio_use_seq_pc) 69709c6f1ddSLingrui98 698f7c29b0aSJinYue XSPerfAccumulate("ifu_req", io.toIbuffer.fire() ) 699f7c29b0aSJinYue XSPerfAccumulate("ifu_miss", io.toIbuffer.fire() && !f3_hit ) 700f7c29b0aSJinYue XSPerfAccumulate("ifu_req_cacheline_0", f3_req_0 ) 701f7c29b0aSJinYue XSPerfAccumulate("ifu_req_cacheline_1", f3_req_1 ) 702f7c29b0aSJinYue XSPerfAccumulate("ifu_req_cacheline_0_hit", f3_hit_0 ) 703f7c29b0aSJinYue XSPerfAccumulate("ifu_req_cacheline_1_hit", f3_hit_1 ) 70409c6f1ddSLingrui98 XSPerfAccumulate("frontendFlush", f3_redirect ) 705f7c29b0aSJinYue XSPerfAccumulate("only_0_hit", f3_only_0_hit && io.toIbuffer.fire() ) 706f7c29b0aSJinYue XSPerfAccumulate("only_0_miss", f3_only_0_miss && io.toIbuffer.fire() ) 707f7c29b0aSJinYue XSPerfAccumulate("hit_0_hit_1", f3_hit_0_hit_1 && io.toIbuffer.fire() ) 708f7c29b0aSJinYue XSPerfAccumulate("hit_0_miss_1", f3_hit_0_miss_1 && io.toIbuffer.fire() ) 709f7c29b0aSJinYue XSPerfAccumulate("miss_0_hit_1", f3_miss_0_hit_1 && io.toIbuffer.fire() ) 710f7c29b0aSJinYue XSPerfAccumulate("miss_0_miss_1", f3_miss_0_miss_1 && io.toIbuffer.fire() ) 711f7c29b0aSJinYue XSPerfAccumulate("cross_line_block", io.toIbuffer.fire() && f3_situation(0) ) 712f7c29b0aSJinYue XSPerfAccumulate("fall_through_is_cacheline_end", io.toIbuffer.fire() && f3_situation(1) ) 71309c6f1ddSLingrui98} 714