xref: /XiangShan/src/main/scala/xiangshan/L2Top.scala (revision f57f7f2aa52bf8c9d7952402ff7d36066bf8e1b3)
14e12f40bSzhanglinjuan/***************************************************************************************
24e12f40bSzhanglinjuan  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
34e12f40bSzhanglinjuan  * Copyright (c) 2020-2021 Peng Cheng Laboratory
44e12f40bSzhanglinjuan  *
54e12f40bSzhanglinjuan  * XiangShan is licensed under Mulan PSL v2.
64e12f40bSzhanglinjuan  * You can use this software according to the terms and conditions of the Mulan PSL v2.
74e12f40bSzhanglinjuan  * You may obtain a copy of Mulan PSL v2 at:
84e12f40bSzhanglinjuan  *          http://license.coscl.org.cn/MulanPSL2
94e12f40bSzhanglinjuan  *
104e12f40bSzhanglinjuan  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
114e12f40bSzhanglinjuan  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
124e12f40bSzhanglinjuan  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
134e12f40bSzhanglinjuan  *
144e12f40bSzhanglinjuan  * See the Mulan PSL v2 for more details.
154e12f40bSzhanglinjuan  ***************************************************************************************/
164e12f40bSzhanglinjuan
174e12f40bSzhanglinjuanpackage xiangshan
184e12f40bSzhanglinjuan
194e12f40bSzhanglinjuanimport chisel3._
204e12f40bSzhanglinjuanimport org.chipsalliance.cde.config._
214e12f40bSzhanglinjuanimport chisel3.util.{Valid, ValidIO}
224e12f40bSzhanglinjuanimport freechips.rocketchip.diplomacy._
234e12f40bSzhanglinjuanimport freechips.rocketchip.interrupts._
244e12f40bSzhanglinjuanimport freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, BusErrors}
254e12f40bSzhanglinjuanimport freechips.rocketchip.tilelink._
264e12f40bSzhanglinjuanimport coupledL2.{L2ParamKey, CoupledL2}
274e12f40bSzhanglinjuanimport system.HasSoCParameter
284e12f40bSzhanglinjuanimport top.BusPerfMonitor
294e12f40bSzhanglinjuanimport utility.{DelayN, ResetGen, TLClientsMerger, TLEdgeBuffer, TLLogger}
304e12f40bSzhanglinjuan
314e12f40bSzhanglinjuanclass L1BusErrorUnitInfo(implicit val p: Parameters) extends Bundle with HasSoCParameter {
324e12f40bSzhanglinjuan  val ecc_error = Valid(UInt(soc.PAddrBits.W))
334e12f40bSzhanglinjuan}
344e12f40bSzhanglinjuan
354e12f40bSzhanglinjuanclass XSL1BusErrors()(implicit val p: Parameters) extends BusErrors {
364e12f40bSzhanglinjuan  val icache = new L1BusErrorUnitInfo
374e12f40bSzhanglinjuan  val dcache = new L1BusErrorUnitInfo
384e12f40bSzhanglinjuan  val l2 = new L1BusErrorUnitInfo
394e12f40bSzhanglinjuan
404e12f40bSzhanglinjuan  override def toErrorList: List[Option[(ValidIO[UInt], String, String)]] =
414e12f40bSzhanglinjuan    List(
424e12f40bSzhanglinjuan      Some(icache.ecc_error, "I_ECC", "Icache ecc error"),
434e12f40bSzhanglinjuan      Some(dcache.ecc_error, "D_ECC", "Dcache ecc error"),
444e12f40bSzhanglinjuan      Some(l2.ecc_error, "L2_ECC", "L2Cache ecc error")
454e12f40bSzhanglinjuan    )
464e12f40bSzhanglinjuan}
474e12f40bSzhanglinjuan
484e12f40bSzhanglinjuan/**
494e12f40bSzhanglinjuan  *   L2Top contains everything between Core and XSTile-IO
504e12f40bSzhanglinjuan  */
514e12f40bSzhanglinjuanclass L2Top()(implicit p: Parameters) extends LazyModule
524e12f40bSzhanglinjuan  with HasXSParameter
534e12f40bSzhanglinjuan  with HasSoCParameter
544e12f40bSzhanglinjuan{
554e12f40bSzhanglinjuan  def chainBuffer(depth: Int, n: String): (Seq[LazyModule], TLNode) = {
564e12f40bSzhanglinjuan    val buffers = Seq.fill(depth){ LazyModule(new TLBuffer()) }
574e12f40bSzhanglinjuan    buffers.zipWithIndex.foreach{ case (b, i) => {
584e12f40bSzhanglinjuan      b.suggestName(s"${n}_${i}")
594e12f40bSzhanglinjuan    }}
604e12f40bSzhanglinjuan    val node = buffers.map(_.node.asInstanceOf[TLNode]).reduce(_ :*=* _)
614e12f40bSzhanglinjuan    (buffers, node)
624e12f40bSzhanglinjuan  }
634e12f40bSzhanglinjuan  // =========== Components ============
644e12f40bSzhanglinjuan  val l1_xbar = TLXbar()
654e12f40bSzhanglinjuan  val mmio_xbar = TLXbar()
664e12f40bSzhanglinjuan  val mmio_port = TLIdentityNode() // to L3
674e12f40bSzhanglinjuan  val memory_port = TLIdentityNode()
684e12f40bSzhanglinjuan  val beu = LazyModule(new BusErrorUnit(
694e12f40bSzhanglinjuan    new XSL1BusErrors(), BusErrorUnitParams(0x38010000)
704e12f40bSzhanglinjuan  ))
714e12f40bSzhanglinjuan
724e12f40bSzhanglinjuan  val i_mmio_port = TLTempNode()
734e12f40bSzhanglinjuan  val d_mmio_port = TLTempNode()
744e12f40bSzhanglinjuan
754e12f40bSzhanglinjuan  val misc_l2_pmu = BusPerfMonitor(name = "Misc_L2", enable = !debugOpts.FPGAPlatform) // l1D & l1I & PTW
764e12f40bSzhanglinjuan  val l2_l3_pmu = BusPerfMonitor(name = "L2_L3", enable = !debugOpts.FPGAPlatform, stat_latency = true)
77c20095f4SChen Xi  val xbar_l2_buffer = TLBuffer()
784e12f40bSzhanglinjuan
794e12f40bSzhanglinjuan  val enbale_tllog = !debugOpts.FPGAPlatform && debugOpts.AlwaysBasicDB
804e12f40bSzhanglinjuan  val l1d_logger = TLLogger(s"L2_L1D_${coreParams.HartId}", enbale_tllog)
814e12f40bSzhanglinjuan  val l1i_logger = TLLogger(s"L2_L1I_${coreParams.HartId}", enbale_tllog)
824e12f40bSzhanglinjuan  val ptw_logger = TLLogger(s"L2_PTW_${coreParams.HartId}", enbale_tllog)
83c20095f4SChen Xi  val ptw_to_l2_buffer = LazyModule(new TLBuffer)
84c20095f4SChen Xi  val i_mmio_buffer = LazyModule(new TLBuffer)
854e12f40bSzhanglinjuan
864e12f40bSzhanglinjuan  val clint_int_node = IntIdentityNode()
874e12f40bSzhanglinjuan  val debug_int_node = IntIdentityNode()
884e12f40bSzhanglinjuan  val plic_int_node = IntIdentityNode()
894e12f40bSzhanglinjuan
904e12f40bSzhanglinjuan  val l2cache = coreParams.L2CacheParamsOpt.map(l2param =>
914e12f40bSzhanglinjuan    LazyModule(new CoupledL2()(new Config((_, _, _) => {
924e12f40bSzhanglinjuan      case L2ParamKey => l2param.copy(
934e12f40bSzhanglinjuan          hartIds = Seq(p(XSCoreParamsKey).HartId),
944e12f40bSzhanglinjuan          FPGAPlatform = debugOpts.FPGAPlatform
954e12f40bSzhanglinjuan        )
964e12f40bSzhanglinjuan    })))
974e12f40bSzhanglinjuan  )
984e12f40bSzhanglinjuan  val l2_binder = coreParams.L2CacheParamsOpt.map(_ => BankBinder(coreParams.L2NBanks, 64))
994e12f40bSzhanglinjuan
1004e12f40bSzhanglinjuan  // =========== Connection ============
1014e12f40bSzhanglinjuan  // l2 to l2_binder, then to memory_port
1024e12f40bSzhanglinjuan  l2_binder match {
1034e12f40bSzhanglinjuan    case Some(binder) =>
1044e12f40bSzhanglinjuan      memory_port := l2_l3_pmu := TLClientsMerger() := TLXbar() :=* binder :*= l2cache.get.node
1054e12f40bSzhanglinjuan    case None =>
1064e12f40bSzhanglinjuan      memory_port := l1_xbar
1074e12f40bSzhanglinjuan  }
1084e12f40bSzhanglinjuan
1094e12f40bSzhanglinjuan  mmio_xbar := TLBuffer.chainNode(2) := i_mmio_port
1104e12f40bSzhanglinjuan  mmio_xbar := TLBuffer.chainNode(2) := d_mmio_port
1114e12f40bSzhanglinjuan  beu.node := TLBuffer.chainNode(1) := mmio_xbar
1124e12f40bSzhanglinjuan  mmio_port := TLBuffer() := mmio_xbar
1134e12f40bSzhanglinjuan
1144e12f40bSzhanglinjuan  class L2TopImp(wrapper: LazyModule) extends LazyModuleImp(wrapper) {
1154e12f40bSzhanglinjuan    val beu_errors = IO(Input(chiselTypeOf(beu.module.io.errors)))
1164e12f40bSzhanglinjuan    val reset_vector = IO(new Bundle {
1174e12f40bSzhanglinjuan      val fromTile = Input(UInt(PAddrBits.W))
1184e12f40bSzhanglinjuan      val toCore = Output(UInt(PAddrBits.W))
1194e12f40bSzhanglinjuan    })
1204e12f40bSzhanglinjuan    val hartId = IO(new Bundle() {
1214e12f40bSzhanglinjuan      val fromTile = Input(UInt(64.W))
1224e12f40bSzhanglinjuan      val toCore = Output(UInt(64.W))
1234e12f40bSzhanglinjuan    })
1244e12f40bSzhanglinjuan    val cpu_halt = IO(new Bundle() {
1254e12f40bSzhanglinjuan      val fromCore = Input(Bool())
1264e12f40bSzhanglinjuan      val toTile = Output(Bool())
1274e12f40bSzhanglinjuan    })
1284e12f40bSzhanglinjuan    val debugTopDown = IO(new Bundle() {
1294e12f40bSzhanglinjuan      val robHeadPaddr = Flipped(Valid(UInt(36.W)))
1304e12f40bSzhanglinjuan      val l2MissMatch = Output(Bool())
1314e12f40bSzhanglinjuan    })
1324e12f40bSzhanglinjuan
1334e12f40bSzhanglinjuan    val resetDelayN = Module(new DelayN(UInt(PAddrBits.W), 5))
1344e12f40bSzhanglinjuan
1354e12f40bSzhanglinjuan    beu.module.io.errors <> beu_errors
1364e12f40bSzhanglinjuan    resetDelayN.io.in := reset_vector.fromTile
1374e12f40bSzhanglinjuan    reset_vector.toCore := resetDelayN.io.out
1384e12f40bSzhanglinjuan    hartId.toCore := hartId.fromTile
1394e12f40bSzhanglinjuan    cpu_halt.toTile := cpu_halt.fromCore
1404e12f40bSzhanglinjuan    dontTouch(hartId)
1414e12f40bSzhanglinjuan    dontTouch(cpu_halt)
1424e12f40bSzhanglinjuan
143d2945707SHuijin Li    val l2_hint = IO(ValidIO(new L2ToL1Hint())) // TODO: parameterize this
1444e12f40bSzhanglinjuan    if (l2cache.isDefined) {
1454e12f40bSzhanglinjuan      l2_hint := l2cache.get.module.io.l2_hint
1464e12f40bSzhanglinjuan      // debugTopDown <> l2cache.get.module.io.debugTopDown
1474e12f40bSzhanglinjuan      l2cache.get.module.io.debugTopDown.robHeadPaddr := DontCare
148*f57f7f2aSYangyu Chen      l2cache.get.module.io.hartId := hartId.fromTile
1494e12f40bSzhanglinjuan      l2cache.get.module.io.debugTopDown.robHeadPaddr.head := debugTopDown.robHeadPaddr
1504e12f40bSzhanglinjuan      debugTopDown.l2MissMatch := l2cache.get.module.io.debugTopDown.l2MissMatch.head
1514e12f40bSzhanglinjuan    } else {
1524e12f40bSzhanglinjuan      l2_hint := 0.U.asTypeOf(l2_hint)
1534e12f40bSzhanglinjuan      debugTopDown <> DontCare
1544e12f40bSzhanglinjuan    }
1554e12f40bSzhanglinjuan  }
1564e12f40bSzhanglinjuan
1574e12f40bSzhanglinjuan  lazy val module = new L2TopImp(this)
1584e12f40bSzhanglinjuan}