xref: /XiangShan/src/main/scala/xiangshan/L2Top.scala (revision c20095f4758f81fa539b635bca27a30716cd5079)
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
18
19import chisel3._
20import org.chipsalliance.cde.config._
21import chisel3.util.{Valid, ValidIO}
22import freechips.rocketchip.diplomacy._
23import freechips.rocketchip.interrupts._
24import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, BusErrors}
25import freechips.rocketchip.tilelink._
26import coupledL2.{L2ParamKey, CoupledL2}
27import system.HasSoCParameter
28import top.BusPerfMonitor
29import utility.{DelayN, ResetGen, TLClientsMerger, TLEdgeBuffer, TLLogger}
30
31class L1BusErrorUnitInfo(implicit val p: Parameters) extends Bundle with HasSoCParameter {
32  val ecc_error = Valid(UInt(soc.PAddrBits.W))
33}
34
35class XSL1BusErrors()(implicit val p: Parameters) extends BusErrors {
36  val icache = new L1BusErrorUnitInfo
37  val dcache = new L1BusErrorUnitInfo
38  val l2 = new L1BusErrorUnitInfo
39
40  override def toErrorList: List[Option[(ValidIO[UInt], String, String)]] =
41    List(
42      Some(icache.ecc_error, "I_ECC", "Icache ecc error"),
43      Some(dcache.ecc_error, "D_ECC", "Dcache ecc error"),
44      Some(l2.ecc_error, "L2_ECC", "L2Cache ecc error")
45    )
46}
47
48/**
49  *   L2Top contains everything between Core and XSTile-IO
50  */
51class L2Top()(implicit p: Parameters) extends LazyModule
52  with HasXSParameter
53  with HasSoCParameter
54{
55  def chainBuffer(depth: Int, n: String): (Seq[LazyModule], TLNode) = {
56    val buffers = Seq.fill(depth){ LazyModule(new TLBuffer()) }
57    buffers.zipWithIndex.foreach{ case (b, i) => {
58      b.suggestName(s"${n}_${i}")
59    }}
60    val node = buffers.map(_.node.asInstanceOf[TLNode]).reduce(_ :*=* _)
61    (buffers, node)
62  }
63  // =========== Components ============
64  val l1_xbar = TLXbar()
65  val mmio_xbar = TLXbar()
66  val mmio_port = TLIdentityNode() // to L3
67  val memory_port = TLIdentityNode()
68  val beu = LazyModule(new BusErrorUnit(
69    new XSL1BusErrors(), BusErrorUnitParams(0x38010000)
70  ))
71
72  val i_mmio_port = TLTempNode()
73  val d_mmio_port = TLTempNode()
74
75  val misc_l2_pmu = BusPerfMonitor(name = "Misc_L2", enable = !debugOpts.FPGAPlatform) // l1D & l1I & PTW
76  val l2_l3_pmu = BusPerfMonitor(name = "L2_L3", enable = !debugOpts.FPGAPlatform, stat_latency = true)
77  val xbar_l2_buffer = TLBuffer()
78
79  val enbale_tllog = !debugOpts.FPGAPlatform && debugOpts.AlwaysBasicDB
80  val l1d_logger = TLLogger(s"L2_L1D_${coreParams.HartId}", enbale_tllog)
81  val l1i_logger = TLLogger(s"L2_L1I_${coreParams.HartId}", enbale_tllog)
82  val ptw_logger = TLLogger(s"L2_PTW_${coreParams.HartId}", enbale_tllog)
83  val l1i_to_l2_buffer = LazyModule(new TLBuffer)
84  val ptw_to_l2_buffer = LazyModule(new TLBuffer)
85  val i_mmio_buffer = LazyModule(new TLBuffer)
86
87  val clint_int_node = IntIdentityNode()
88  val debug_int_node = IntIdentityNode()
89  val plic_int_node = IntIdentityNode()
90
91  val l2cache = coreParams.L2CacheParamsOpt.map(l2param =>
92    LazyModule(new CoupledL2()(new Config((_, _, _) => {
93      case L2ParamKey => l2param.copy(
94          hartIds = Seq(p(XSCoreParamsKey).HartId),
95          FPGAPlatform = debugOpts.FPGAPlatform
96        )
97    })))
98  )
99  val l2_binder = coreParams.L2CacheParamsOpt.map(_ => BankBinder(coreParams.L2NBanks, 64))
100
101  // =========== Connection ============
102  // l2 to l2_binder, then to memory_port
103  l2_binder match {
104    case Some(binder) =>
105      memory_port := l2_l3_pmu := TLClientsMerger() := TLXbar() :=* binder :*= l2cache.get.node
106    case None =>
107      memory_port := l1_xbar
108  }
109
110  mmio_xbar := TLBuffer.chainNode(2) := i_mmio_port
111  mmio_xbar := TLBuffer.chainNode(2) := d_mmio_port
112  beu.node := TLBuffer.chainNode(1) := mmio_xbar
113  mmio_port := TLBuffer() := mmio_xbar
114
115  class L2TopImp(wrapper: LazyModule) extends LazyModuleImp(wrapper) {
116    val beu_errors = IO(Input(chiselTypeOf(beu.module.io.errors)))
117    val reset_vector = IO(new Bundle {
118      val fromTile = Input(UInt(PAddrBits.W))
119      val toCore = Output(UInt(PAddrBits.W))
120    })
121    val hartId = IO(new Bundle() {
122      val fromTile = Input(UInt(64.W))
123      val toCore = Output(UInt(64.W))
124    })
125    val cpu_halt = IO(new Bundle() {
126      val fromCore = Input(Bool())
127      val toTile = Output(Bool())
128    })
129    val debugTopDown = IO(new Bundle() {
130      val robHeadPaddr = Flipped(Valid(UInt(36.W)))
131      val l2MissMatch = Output(Bool())
132    })
133
134    val resetDelayN = Module(new DelayN(UInt(PAddrBits.W), 5))
135
136    beu.module.io.errors <> beu_errors
137    resetDelayN.io.in := reset_vector.fromTile
138    reset_vector.toCore := resetDelayN.io.out
139    hartId.toCore := hartId.fromTile
140    cpu_halt.toTile := cpu_halt.fromCore
141    dontTouch(hartId)
142    dontTouch(cpu_halt)
143
144    val l2_hint = IO(ValidIO(UInt(32.W))) // TODO: parameterize this
145    if (l2cache.isDefined) {
146      l2_hint := l2cache.get.module.io.l2_hint
147      // debugTopDown <> l2cache.get.module.io.debugTopDown
148      l2cache.get.module.io.debugTopDown.robHeadPaddr := DontCare
149      l2cache.get.module.io.debugTopDown.robHeadPaddr.head := debugTopDown.robHeadPaddr
150      debugTopDown.l2MissMatch := l2cache.get.module.io.debugTopDown.l2MissMatch.head
151    } else {
152      l2_hint := 0.U.asTypeOf(l2_hint)
153      debugTopDown <> DontCare
154    }
155  }
156
157  lazy val module = new L2TopImp(this)
158}