xref: /XiangShan/src/main/scala/xiangshan/frontend/Frontend.scala (revision c6d439803a044ea209139672b25e35fe8d7f4aa0)
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