xref: /XiangShan/src/main/scala/xiangshan/L2Top.scala (revision 4e12f40b2000d20984973eb847daa45fcab7abef)
1*4e12f40bSzhanglinjuan/***************************************************************************************
2*4e12f40bSzhanglinjuan  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*4e12f40bSzhanglinjuan  * Copyright (c) 2020-2021 Peng Cheng Laboratory
4*4e12f40bSzhanglinjuan  *
5*4e12f40bSzhanglinjuan  * XiangShan is licensed under Mulan PSL v2.
6*4e12f40bSzhanglinjuan  * You can use this software according to the terms and conditions of the Mulan PSL v2.
7*4e12f40bSzhanglinjuan  * You may obtain a copy of Mulan PSL v2 at:
8*4e12f40bSzhanglinjuan  *          http://license.coscl.org.cn/MulanPSL2
9*4e12f40bSzhanglinjuan  *
10*4e12f40bSzhanglinjuan  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11*4e12f40bSzhanglinjuan  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12*4e12f40bSzhanglinjuan  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*4e12f40bSzhanglinjuan  *
14*4e12f40bSzhanglinjuan  * See the Mulan PSL v2 for more details.
15*4e12f40bSzhanglinjuan  ***************************************************************************************/
16*4e12f40bSzhanglinjuan
17*4e12f40bSzhanglinjuanpackage xiangshan
18*4e12f40bSzhanglinjuan
19*4e12f40bSzhanglinjuanimport chisel3._
20*4e12f40bSzhanglinjuanimport org.chipsalliance.cde.config._
21*4e12f40bSzhanglinjuanimport chisel3.util.{Valid, ValidIO}
22*4e12f40bSzhanglinjuanimport freechips.rocketchip.diplomacy._
23*4e12f40bSzhanglinjuanimport freechips.rocketchip.interrupts._
24*4e12f40bSzhanglinjuanimport freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, BusErrors}
25*4e12f40bSzhanglinjuanimport freechips.rocketchip.tilelink._
26*4e12f40bSzhanglinjuanimport coupledL2.{L2ParamKey, CoupledL2}
27*4e12f40bSzhanglinjuanimport system.HasSoCParameter
28*4e12f40bSzhanglinjuanimport top.BusPerfMonitor
29*4e12f40bSzhanglinjuanimport utility.{DelayN, ResetGen, TLClientsMerger, TLEdgeBuffer, TLLogger}
30*4e12f40bSzhanglinjuan
31*4e12f40bSzhanglinjuanclass L1BusErrorUnitInfo(implicit val p: Parameters) extends Bundle with HasSoCParameter {
32*4e12f40bSzhanglinjuan  val ecc_error = Valid(UInt(soc.PAddrBits.W))
33*4e12f40bSzhanglinjuan}
34*4e12f40bSzhanglinjuan
35*4e12f40bSzhanglinjuanclass XSL1BusErrors()(implicit val p: Parameters) extends BusErrors {
36*4e12f40bSzhanglinjuan  val icache = new L1BusErrorUnitInfo
37*4e12f40bSzhanglinjuan  val dcache = new L1BusErrorUnitInfo
38*4e12f40bSzhanglinjuan  val l2 = new L1BusErrorUnitInfo
39*4e12f40bSzhanglinjuan
40*4e12f40bSzhanglinjuan  override def toErrorList: List[Option[(ValidIO[UInt], String, String)]] =
41*4e12f40bSzhanglinjuan    List(
42*4e12f40bSzhanglinjuan      Some(icache.ecc_error, "I_ECC", "Icache ecc error"),
43*4e12f40bSzhanglinjuan      Some(dcache.ecc_error, "D_ECC", "Dcache ecc error"),
44*4e12f40bSzhanglinjuan      Some(l2.ecc_error, "L2_ECC", "L2Cache ecc error")
45*4e12f40bSzhanglinjuan    )
46*4e12f40bSzhanglinjuan}
47*4e12f40bSzhanglinjuan
48*4e12f40bSzhanglinjuan/**
49*4e12f40bSzhanglinjuan  *   L2Top contains everything between Core and XSTile-IO
50*4e12f40bSzhanglinjuan  */
51*4e12f40bSzhanglinjuanclass L2Top()(implicit p: Parameters) extends LazyModule
52*4e12f40bSzhanglinjuan  with HasXSParameter
53*4e12f40bSzhanglinjuan  with HasSoCParameter
54*4e12f40bSzhanglinjuan{
55*4e12f40bSzhanglinjuan  def chainBuffer(depth: Int, n: String): (Seq[LazyModule], TLNode) = {
56*4e12f40bSzhanglinjuan    val buffers = Seq.fill(depth){ LazyModule(new TLBuffer()) }
57*4e12f40bSzhanglinjuan    buffers.zipWithIndex.foreach{ case (b, i) => {
58*4e12f40bSzhanglinjuan      b.suggestName(s"${n}_${i}")
59*4e12f40bSzhanglinjuan    }}
60*4e12f40bSzhanglinjuan    val node = buffers.map(_.node.asInstanceOf[TLNode]).reduce(_ :*=* _)
61*4e12f40bSzhanglinjuan    (buffers, node)
62*4e12f40bSzhanglinjuan  }
63*4e12f40bSzhanglinjuan  // =========== Components ============
64*4e12f40bSzhanglinjuan  val l1_xbar = TLXbar()
65*4e12f40bSzhanglinjuan  val mmio_xbar = TLXbar()
66*4e12f40bSzhanglinjuan  val mmio_port = TLIdentityNode() // to L3
67*4e12f40bSzhanglinjuan  val memory_port = TLIdentityNode()
68*4e12f40bSzhanglinjuan  val beu = LazyModule(new BusErrorUnit(
69*4e12f40bSzhanglinjuan    new XSL1BusErrors(), BusErrorUnitParams(0x38010000)
70*4e12f40bSzhanglinjuan  ))
71*4e12f40bSzhanglinjuan
72*4e12f40bSzhanglinjuan  val i_mmio_port = TLTempNode()
73*4e12f40bSzhanglinjuan  val d_mmio_port = TLTempNode()
74*4e12f40bSzhanglinjuan
75*4e12f40bSzhanglinjuan  val l1d_l2_bufferOpt = coreParams.dcacheParametersOpt.map(_ => LazyModule(new TLBuffer))
76*4e12f40bSzhanglinjuan  val l1d_l2_pmu = BusPerfMonitor(name = "L1d_L2", enable = !debugOpts.FPGAPlatform, stat_latency = true)
77*4e12f40bSzhanglinjuan  val misc_l2_pmu = BusPerfMonitor(name = "Misc_L2", enable = !debugOpts.FPGAPlatform) // l1D & l1I & PTW
78*4e12f40bSzhanglinjuan  val l2_l3_pmu = BusPerfMonitor(name = "L2_L3", enable = !debugOpts.FPGAPlatform, stat_latency = true)
79*4e12f40bSzhanglinjuan
80*4e12f40bSzhanglinjuan  val enbale_tllog = !debugOpts.FPGAPlatform && debugOpts.AlwaysBasicDB
81*4e12f40bSzhanglinjuan  val l1d_logger = TLLogger(s"L2_L1D_${coreParams.HartId}", enbale_tllog)
82*4e12f40bSzhanglinjuan  val l1i_logger = TLLogger(s"L2_L1I_${coreParams.HartId}", enbale_tllog)
83*4e12f40bSzhanglinjuan  val ptw_logger = TLLogger(s"L2_PTW_${coreParams.HartId}", enbale_tllog)
84*4e12f40bSzhanglinjuan
85*4e12f40bSzhanglinjuan  val clint_int_node = IntIdentityNode()
86*4e12f40bSzhanglinjuan  val debug_int_node = IntIdentityNode()
87*4e12f40bSzhanglinjuan  val plic_int_node = IntIdentityNode()
88*4e12f40bSzhanglinjuan
89*4e12f40bSzhanglinjuan  val l2cache = coreParams.L2CacheParamsOpt.map(l2param =>
90*4e12f40bSzhanglinjuan    LazyModule(new CoupledL2()(new Config((_, _, _) => {
91*4e12f40bSzhanglinjuan      case L2ParamKey => l2param.copy(
92*4e12f40bSzhanglinjuan          hartIds = Seq(p(XSCoreParamsKey).HartId),
93*4e12f40bSzhanglinjuan          FPGAPlatform = debugOpts.FPGAPlatform
94*4e12f40bSzhanglinjuan        )
95*4e12f40bSzhanglinjuan    })))
96*4e12f40bSzhanglinjuan  )
97*4e12f40bSzhanglinjuan  val l2_binder = coreParams.L2CacheParamsOpt.map(_ => BankBinder(coreParams.L2NBanks, 64))
98*4e12f40bSzhanglinjuan
99*4e12f40bSzhanglinjuan  // =========== Connection ============
100*4e12f40bSzhanglinjuan  // l2 to l2_binder, then to memory_port
101*4e12f40bSzhanglinjuan  l2_binder match {
102*4e12f40bSzhanglinjuan    case Some(binder) =>
103*4e12f40bSzhanglinjuan      memory_port := l2_l3_pmu := TLClientsMerger() := TLXbar() :=* binder :*= l2cache.get.node
104*4e12f40bSzhanglinjuan    case None =>
105*4e12f40bSzhanglinjuan      memory_port := l1_xbar
106*4e12f40bSzhanglinjuan  }
107*4e12f40bSzhanglinjuan
108*4e12f40bSzhanglinjuan  mmio_xbar := TLBuffer.chainNode(2) := i_mmio_port
109*4e12f40bSzhanglinjuan  mmio_xbar := TLBuffer.chainNode(2) := d_mmio_port
110*4e12f40bSzhanglinjuan  beu.node := TLBuffer.chainNode(1) := mmio_xbar
111*4e12f40bSzhanglinjuan  mmio_port := TLBuffer() := mmio_xbar
112*4e12f40bSzhanglinjuan
113*4e12f40bSzhanglinjuan  class L2TopImp(wrapper: LazyModule) extends LazyModuleImp(wrapper) {
114*4e12f40bSzhanglinjuan    val beu_errors = IO(Input(chiselTypeOf(beu.module.io.errors)))
115*4e12f40bSzhanglinjuan    val reset_vector = IO(new Bundle {
116*4e12f40bSzhanglinjuan      val fromTile = Input(UInt(PAddrBits.W))
117*4e12f40bSzhanglinjuan      val toCore = Output(UInt(PAddrBits.W))
118*4e12f40bSzhanglinjuan    })
119*4e12f40bSzhanglinjuan    val hartId = IO(new Bundle() {
120*4e12f40bSzhanglinjuan      val fromTile = Input(UInt(64.W))
121*4e12f40bSzhanglinjuan      val toCore = Output(UInt(64.W))
122*4e12f40bSzhanglinjuan    })
123*4e12f40bSzhanglinjuan    val cpu_halt = IO(new Bundle() {
124*4e12f40bSzhanglinjuan      val fromCore = Input(Bool())
125*4e12f40bSzhanglinjuan      val toTile = Output(Bool())
126*4e12f40bSzhanglinjuan    })
127*4e12f40bSzhanglinjuan    val debugTopDown = IO(new Bundle() {
128*4e12f40bSzhanglinjuan      val robHeadPaddr = Flipped(Valid(UInt(36.W)))
129*4e12f40bSzhanglinjuan      val l2MissMatch = Output(Bool())
130*4e12f40bSzhanglinjuan    })
131*4e12f40bSzhanglinjuan
132*4e12f40bSzhanglinjuan    val resetDelayN = Module(new DelayN(UInt(PAddrBits.W), 5))
133*4e12f40bSzhanglinjuan
134*4e12f40bSzhanglinjuan    beu.module.io.errors <> beu_errors
135*4e12f40bSzhanglinjuan    resetDelayN.io.in := reset_vector.fromTile
136*4e12f40bSzhanglinjuan    reset_vector.toCore := resetDelayN.io.out
137*4e12f40bSzhanglinjuan    hartId.toCore := hartId.fromTile
138*4e12f40bSzhanglinjuan    cpu_halt.toTile := cpu_halt.fromCore
139*4e12f40bSzhanglinjuan    dontTouch(hartId)
140*4e12f40bSzhanglinjuan    dontTouch(cpu_halt)
141*4e12f40bSzhanglinjuan
142*4e12f40bSzhanglinjuan    val l2_hint = IO(ValidIO(UInt(32.W))) // TODO: parameterize this
143*4e12f40bSzhanglinjuan    if (l2cache.isDefined) {
144*4e12f40bSzhanglinjuan      l2_hint := l2cache.get.module.io.l2_hint
145*4e12f40bSzhanglinjuan      // debugTopDown <> l2cache.get.module.io.debugTopDown
146*4e12f40bSzhanglinjuan      l2cache.get.module.io.debugTopDown.robHeadPaddr := DontCare
147*4e12f40bSzhanglinjuan      l2cache.get.module.io.debugTopDown.robHeadPaddr.head := debugTopDown.robHeadPaddr
148*4e12f40bSzhanglinjuan      debugTopDown.l2MissMatch := l2cache.get.module.io.debugTopDown.l2MissMatch.head
149*4e12f40bSzhanglinjuan    } else {
150*4e12f40bSzhanglinjuan      l2_hint := 0.U.asTypeOf(l2_hint)
151*4e12f40bSzhanglinjuan      debugTopDown <> DontCare
152*4e12f40bSzhanglinjuan    }
153*4e12f40bSzhanglinjuan  }
154*4e12f40bSzhanglinjuan
155*4e12f40bSzhanglinjuan  lazy val module = new L2TopImp(this)
156*4e12f40bSzhanglinjuan}