1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan.frontend 17import utils._ 18import chisel3._ 19import chisel3.util._ 20import chipsalliance.rocketchip.config.Parameters 21import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 22import xiangshan._ 23import xiangshan.cache._ 24import xiangshan.cache.prefetch.L1plusPrefetcher 25import xiangshan.backend.fu.HasExceptionNO 26import system.L1CacheErrorInfo 27 28 29class Frontend()(implicit p: Parameters) extends LazyModule with HasXSParameter{ 30 31 val instrUncache = LazyModule(new InstrUncache()) 32 33 lazy val module = new FrontendImp(this) 34} 35 36 37class FrontendImp (outer: Frontend) extends LazyModuleImp(outer) 38 with HasL1plusCacheParameters 39 with HasXSParameter 40 with HasExceptionNO 41{ 42 val io = IO(new Bundle() { 43 val icacheMemAcq = DecoupledIO(new L1plusCacheReq) 44 val icacheMemGrant = Flipped(DecoupledIO(new L1plusCacheResp)) 45 val l1plusFlush = Output(Bool()) 46 val fencei = Input(Bool()) 47 val ptw = new TlbPtwIO 48 val backend = new FrontendToBackendIO 49 val sfence = Input(new SfenceBundle) 50 val tlbCsr = Input(new TlbCsrBundle) 51 val csrCtrl = Input(new CustomCSRCtrlIO) 52 val error = new L1CacheErrorInfo 53 val frontendInfo = new Bundle { 54 val ibufFull = Output(Bool()) 55 val bpuInfo = new Bundle { 56 val bpRight = Output(UInt(XLEN.W)) 57 val bpWrong = Output(UInt(XLEN.W)) 58 } 59 } 60 }) 61 62 val ifu = Module(new IFU) 63 val ibuffer = Module(new Ibuffer) 64 val l1plusPrefetcher = Module(new L1plusPrefetcher) 65 val instrUncache = outer.instrUncache.module 66 val ftq = Module(new Ftq) 67 68 val needFlush = io.backend.redirect_cfiUpdate.valid 69 70 // from backend 71 ifu.io.redirect <> io.backend.redirect_cfiUpdate 72 ifu.io.bp_ctrl <> RegNext(io.csrCtrl.bp_ctrl) 73 ifu.io.commitUpdate <> ftq.io.commit_ftqEntry 74 ifu.io.ftqEnqPtr <> ftq.io.enqPtr 75 ifu.io.ftqLeftOne <> ftq.io.leftOne 76 // to icache 77 val grantClientId = clientId(io.icacheMemGrant.bits.id) 78 val grantEntryId = entryId(io.icacheMemGrant.bits.id) 79 ifu.io.icacheMemGrant.valid := io.icacheMemGrant.valid && grantClientId === icacheMissQueueId.U 80 ifu.io.icacheMemGrant.bits := io.icacheMemGrant.bits 81 ifu.io.icacheMemGrant.bits.id := Cat(0.U(clientIdWidth.W), grantEntryId) 82 l1plusPrefetcher.io.mem_grant.valid := io.icacheMemGrant.valid && grantClientId === l1plusPrefetcherId.U 83 l1plusPrefetcher.io.mem_grant.bits := io.icacheMemGrant.bits 84 l1plusPrefetcher.io.mem_grant.bits.id := Cat(0.U(clientIdWidth.W), grantEntryId) 85 assert(RegNext(!l1plusPrefetcher.io.mem_grant.valid || (l1plusPrefetcher.io.mem_grant.ready && grantClientId === l1plusPrefetcherId.U))) 86 io.icacheMemGrant.ready := Mux(grantClientId === icacheMissQueueId.U, 87 ifu.io.icacheMemGrant.ready, 88 l1plusPrefetcher.io.mem_grant.ready) 89 ifu.io.fencei := RegNext(io.fencei) 90 91 ftq.io.enq <> ifu.io.toFtq 92 ftq.io.roq_commits <> io.backend.toFtq.roq_commits 93 ftq.io.redirect <> io.backend.toFtq.redirect 94 ftq.io.flush := io.backend.toFtq.flush 95 ftq.io.flushIdx := io.backend.toFtq.flushIdx 96 ftq.io.flushOffset := io.backend.toFtq.flushOffset 97 ftq.io.frontendRedirect <> io.backend.toFtq.frontendRedirect 98 ftq.io.exuWriteback <> io.backend.toFtq.exuWriteback 99 io.backend.fromFtq.ftqRead <> ftq.io.ftqRead 100 io.backend.fromFtq.cfiRead <> ftq.io.cfiRead 101 io.frontendInfo.bpuInfo <> ftq.io.bpuInfo 102 103 104 instrUncache.io.req <> ifu.io.mmio_acquire 105 instrUncache.io.resp <> ifu.io.mmio_grant 106 instrUncache.io.flush <> ifu.io.mmio_flush 107 // to tlb 108 ifu.io.sfence := RegNext(io.sfence) 109 ifu.io.tlbCsr := RegNext(io.tlbCsr) 110 // from icache and l1plus prefetcher 111 io.l1plusFlush := ifu.io.l1plusFlush 112 l1plusPrefetcher.io.in.valid := ifu.io.prefetchTrainReq.valid 113 l1plusPrefetcher.io.in.bits := ifu.io.prefetchTrainReq.bits 114 l1plusPrefetcher.io.enable := RegNext(io.csrCtrl.l1plus_pf_enable) 115 val memAcquireArb = Module(new Arbiter(new L1plusCacheReq, nClients)) 116 memAcquireArb.io.in(icacheMissQueueId) <> ifu.io.icacheMemAcq 117 memAcquireArb.io.in(icacheMissQueueId).bits.id := Cat(icacheMissQueueId.U(clientIdWidth.W), 118 entryId(ifu.io.icacheMemAcq.bits.id)) 119 memAcquireArb.io.in(l1plusPrefetcherId) <> l1plusPrefetcher.io.mem_acquire 120 memAcquireArb.io.in(l1plusPrefetcherId).bits.id := Cat(l1plusPrefetcherId.U(clientIdWidth.W), 121 entryId(l1plusPrefetcher.io.mem_acquire.bits.id)) 122 io.icacheMemAcq <> memAcquireArb.io.out 123 // itlb to ptw 124 io.ptw <> ifu.io.ptw 125 // ifu to ibuffer 126 ibuffer.io.in <> ifu.io.fetchPacket 127 // backend to ibuffer 128 ibuffer.io.flush := needFlush 129 // ibuffer to backend 130 io.backend.cfVec <> ibuffer.io.out 131 132 io.error <> RegNext(RegNext(ifu.io.error)) 133 134 // for(out <- ibuffer.io.out){ 135 // XSInfo(out.fire(), 136 // p"inst:${Hexadecimal(out.bits.instr)} pc:${Hexadecimal(out.bits.pc)}\n" 137 // ) 138 // } 139 140 val frontendBubble = PopCount((0 until DecodeWidth).map(i => io.backend.cfVec(i).ready && !ibuffer.io.out(i).valid)) 141 XSPerfAccumulate("FrontendBubble", frontendBubble) 142 143 io.frontendInfo.ibufFull := RegNext(ibuffer.io.full) 144} 145