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