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 } 56 }) 57 58 val ifu = Module(new IFU) 59 val ibuffer = Module(new Ibuffer) 60 val l1plusPrefetcher = Module(new L1plusPrefetcher) 61 val instrUncache = outer.instrUncache.module 62 63 val needFlush = io.backend.redirect_cfiUpdate.valid 64 65 // from backend 66 ifu.io.redirect <> io.backend.redirect_cfiUpdate 67 ifu.io.bp_ctrl <> RegNext(io.csrCtrl.bp_ctrl) 68 ifu.io.commitUpdate <> io.backend.commit_cfiUpdate 69 ifu.io.ftqEnqPtr <> io.backend.ftqEnqPtr 70 ifu.io.ftqLeftOne <> io.backend.ftqLeftOne 71 // to icache 72 val grantClientId = clientId(io.icacheMemGrant.bits.id) 73 val grantEntryId = entryId(io.icacheMemGrant.bits.id) 74 ifu.io.icacheMemGrant.valid := io.icacheMemGrant.valid && grantClientId === icacheMissQueueId.U 75 ifu.io.icacheMemGrant.bits := io.icacheMemGrant.bits 76 ifu.io.icacheMemGrant.bits.id := Cat(0.U(clientIdWidth.W), grantEntryId) 77 l1plusPrefetcher.io.mem_grant.valid := io.icacheMemGrant.valid && grantClientId === l1plusPrefetcherId.U 78 l1plusPrefetcher.io.mem_grant.bits := io.icacheMemGrant.bits 79 l1plusPrefetcher.io.mem_grant.bits.id := Cat(0.U(clientIdWidth.W), grantEntryId) 80 assert(RegNext(!l1plusPrefetcher.io.mem_grant.valid || (l1plusPrefetcher.io.mem_grant.ready && grantClientId === l1plusPrefetcherId.U))) 81 io.icacheMemGrant.ready := Mux(grantClientId === icacheMissQueueId.U, 82 ifu.io.icacheMemGrant.ready, 83 l1plusPrefetcher.io.mem_grant.ready) 84 ifu.io.fencei := RegNext(io.fencei) 85 86 87 instrUncache.io.req <> ifu.io.mmio_acquire 88 instrUncache.io.resp <> ifu.io.mmio_grant 89 instrUncache.io.flush <> ifu.io.mmio_flush 90 // to tlb 91 ifu.io.sfence := RegNext(io.sfence) 92 ifu.io.tlbCsr := RegNext(io.tlbCsr) 93 // from icache and l1plus prefetcher 94 io.l1plusFlush := ifu.io.l1plusFlush 95 l1plusPrefetcher.io.in.valid := ifu.io.prefetchTrainReq.valid 96 l1plusPrefetcher.io.in.bits := ifu.io.prefetchTrainReq.bits 97 l1plusPrefetcher.io.enable := RegNext(io.csrCtrl.l1plus_pf_enable) 98 val memAcquireArb = Module(new Arbiter(new L1plusCacheReq, nClients)) 99 memAcquireArb.io.in(icacheMissQueueId) <> ifu.io.icacheMemAcq 100 memAcquireArb.io.in(icacheMissQueueId).bits.id := Cat(icacheMissQueueId.U(clientIdWidth.W), 101 entryId(ifu.io.icacheMemAcq.bits.id)) 102 memAcquireArb.io.in(l1plusPrefetcherId) <> l1plusPrefetcher.io.mem_acquire 103 memAcquireArb.io.in(l1plusPrefetcherId).bits.id := Cat(l1plusPrefetcherId.U(clientIdWidth.W), 104 entryId(l1plusPrefetcher.io.mem_acquire.bits.id)) 105 io.icacheMemAcq <> memAcquireArb.io.out 106 // itlb to ptw 107 io.ptw <> ifu.io.ptw 108 // ifu to ibuffer 109 ibuffer.io.in <> ifu.io.fetchPacket 110 // backend to ibuffer 111 ibuffer.io.flush := needFlush 112 // ibuffer to backend 113 io.backend.cfVec <> ibuffer.io.out 114 // ifu to backend 115 io.backend.fetchInfo <> ifu.io.toFtq 116 117 io.error <> RegNext(RegNext(ifu.io.error)) 118 119 // for(out <- ibuffer.io.out){ 120 // XSInfo(out.fire(), 121 // p"inst:${Hexadecimal(out.bits.instr)} pc:${Hexadecimal(out.bits.pc)}\n" 122 // ) 123 // } 124 125 val frontendBubble = PopCount((0 until DecodeWidth).map(i => io.backend.cfVec(i).ready && !ibuffer.io.out(i).valid)) 126 XSPerfAccumulate("FrontendBubble", frontendBubble) 127 128 io.frontendInfo.ibufFull := RegNext(ibuffer.io.full) 129} 130