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 system 18 19import org.chipsalliance.cde.config.{Field, Parameters} 20import chisel3._ 21import chisel3.util._ 22import device.{DebugModule, TLPMA, TLPMAIO} 23import freechips.rocketchip.amba.axi4._ 24import freechips.rocketchip.devices.debug.DebugModuleKey 25import freechips.rocketchip.devices.tilelink._ 26import freechips.rocketchip.diplomacy.{AddressSet, IdRange, InModuleBody, LazyModule, LazyModuleImp, MemoryDevice, RegionType, SimpleDevice, TransferSizes} 27import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} 28import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup} 29import freechips.rocketchip.tilelink._ 30import freechips.rocketchip.util.AsyncQueueParams 31import huancun._ 32import top.BusPerfMonitor 33import utility.{ReqSourceKey, TLClientsMerger, TLEdgeBuffer, TLLogger} 34import xiangshan.backend.fu.{MemoryRange, PMAConfigEntry, PMAConst} 35import xiangshan.{DebugOptionsKey, PMParameKey, XSTileKey} 36import coupledL2.{EnableCHI, L2Param} 37import coupledL2.tl2chi.CHIIssue 38import openLLC.OpenLLCParam 39 40case object SoCParamsKey extends Field[SoCParameters] 41 42case class SoCParameters 43( 44 EnableILA: Boolean = false, 45 PAddrBits: Int = 48, 46 PmemRanges: Seq[MemoryRange] = Seq(MemoryRange(0x80000000L, 0x80000000000L)), 47 PMAConfigs: Seq[PMAConfigEntry] = Seq( 48 PMAConfigEntry(0x0L, range = 0x1000000000000L, a = 3), 49 PMAConfigEntry(0x80000000000L, c = true, atomic = true, a = 1, x = true, w = true, r = true), 50 PMAConfigEntry(0x80000000L, a = 1, w = true, r = true), 51 PMAConfigEntry(0x3A000000L, a = 1), 52 PMAConfigEntry(0x39002000L, a = 1, w = true, r = true), 53 PMAConfigEntry(0x39000000L, a = 1, w = true, r = true), 54 PMAConfigEntry(0x38022000L, a = 1, w = true, r = true), 55 PMAConfigEntry(0x38021000L, a = 1, x = true, w = true, r = true), 56 PMAConfigEntry(0x38020000L, a = 1, w = true, r = true), 57 PMAConfigEntry(0x30050000L, a = 1, w = true, r = true), // FIXME: GPU space is cacheable? 58 PMAConfigEntry(0x30010000L, a = 1, w = true, r = true), 59 PMAConfigEntry(0x20000000L, a = 1, x = true, w = true, r = true), 60 PMAConfigEntry(0x10000000L, a = 1, w = true, r = true), 61 PMAConfigEntry(0) 62 ), 63 CLINTRange: AddressSet = AddressSet(0x38000000L, CLINTConsts.size - 1), 64 BEURange: AddressSet = AddressSet(0x38010000L, 0xfff), 65 PLICRange: AddressSet = AddressSet(0x3c000000L, PLICConsts.size(PLICConsts.maxMaxHarts) - 1), 66 PLLRange: AddressSet = AddressSet(0x3a000000L, 0xfff), 67 UARTLiteForDTS: Boolean = true, // should be false in SimMMIO 68 extIntrs: Int = 64, 69 L3NBanks: Int = 4, 70 L3CacheParamsOpt: Option[HCCacheParameters] = Some(HCCacheParameters( 71 name = "L3", 72 level = 3, 73 ways = 8, 74 sets = 2048 // 1MB per bank 75 )), 76 OpenLLCParamsOpt: Option[OpenLLCParam] = None, 77 XSTopPrefix: Option[String] = None, 78 NodeIDWidthList: Map[String, Int] = Map( 79 "B" -> 7, 80 "E.b" -> 11 81 ), 82 NumHart: Int = 64, 83 NumIRFiles: Int = 7, 84 NumIRSrc: Int = 256, 85 UseXSNoCTop: Boolean = false, 86 UseXSNoCDiffTop: Boolean = false, 87 IMSICUseTL: Boolean = false, 88 EnableCHIAsyncBridge: Option[AsyncQueueParams] = Some(AsyncQueueParams(depth = 16, sync = 3, safe = false)), 89 EnableClintAsyncBridge: Option[AsyncQueueParams] = Some(AsyncQueueParams(depth = 1, sync = 3, safe = false)) 90){ 91 require( 92 L3CacheParamsOpt.isDefined ^ OpenLLCParamsOpt.isDefined || L3CacheParamsOpt.isEmpty && OpenLLCParamsOpt.isEmpty, 93 "Atmost one of L3CacheParamsOpt and OpenLLCParamsOpt should be defined" 94 ) 95 // L3 configurations 96 val L3InnerBusWidth = 256 97 val L3BlockSize = 64 98 // on chip network configurations 99 val L3OuterBusWidth = 256 100 val UARTLiteRange = AddressSet(0x40600000, if (UARTLiteForDTS) 0x3f else 0xf) 101} 102 103trait HasSoCParameter { 104 implicit val p: Parameters 105 106 val soc = p(SoCParamsKey) 107 val debugOpts = p(DebugOptionsKey) 108 val tiles = p(XSTileKey) 109 val enableCHI = p(EnableCHI) 110 val issue = p(CHIIssue) 111 112 val NumCores = tiles.size 113 val EnableILA = soc.EnableILA 114 115 // Parameters for trace extension 116 val TraceTraceGroupNum = tiles.head.traceParams.TraceGroupNum 117 val TraceCauseWidth = tiles.head.XLEN 118 val TraceTvalWidth = tiles.head.traceParams.IaddrWidth 119 val TracePrivWidth = tiles.head.traceParams.PrivWidth 120 val TraceIaddrWidth = tiles.head.traceParams.IaddrWidth 121 val TraceItypeWidth = tiles.head.traceParams.ItypeWidth 122 val TraceIretireWidthCompressed = log2Up(tiles.head.RenameWidth * tiles.head.CommitWidth * 2) 123 val TraceIlastsizeWidth = tiles.head.traceParams.IlastsizeWidth 124 125 // L3 configurations 126 val L3InnerBusWidth = soc.L3InnerBusWidth 127 val L3BlockSize = soc.L3BlockSize 128 val L3NBanks = soc.L3NBanks 129 130 // on chip network configurations 131 val L3OuterBusWidth = soc.L3OuterBusWidth 132 133 val NrExtIntr = soc.extIntrs 134 135 val SetIpNumValidSize = soc.NumHart * soc.NumIRFiles 136 137 val NumIRSrc = soc.NumIRSrc 138 139 val EnableCHIAsyncBridge = if (enableCHI && soc.EnableCHIAsyncBridge.isDefined) 140 soc.EnableCHIAsyncBridge else None 141 val EnableClintAsyncBridge = soc.EnableClintAsyncBridge 142} 143 144trait HasPeripheralRanges { 145 implicit val p: Parameters 146 147 private def soc = p(SoCParamsKey) 148 private def dm = p(DebugModuleKey) 149 private def pmParams = p(PMParameKey) 150 151 private def mmpma = pmParams.mmpma 152 153 def onChipPeripheralRanges: Map[String, AddressSet] = Map( 154 "CLINT" -> soc.CLINTRange, 155 "BEU" -> soc.BEURange, 156 "PLIC" -> soc.PLICRange, 157 "PLL" -> soc.PLLRange, 158 "UART" -> soc.UARTLiteRange, 159 "DEBUG" -> dm.get.address, 160 "MMPMA" -> AddressSet(mmpma.address, mmpma.mask) 161 ) ++ ( 162 if (soc.L3CacheParamsOpt.map(_.ctrl.isDefined).getOrElse(false)) 163 Map("L3CTL" -> AddressSet(soc.L3CacheParamsOpt.get.ctrl.get.address, 0xffff)) 164 else 165 Map() 166 ) 167 168 def peripheralRange = onChipPeripheralRanges.values.foldLeft(Seq(AddressSet(0x0, 0x7fffffffL))) { (acc, x) => 169 acc.flatMap(_.subtract(x)) 170 } 171} 172 173class ILABundle extends Bundle {} 174 175 176abstract class BaseSoC()(implicit p: Parameters) extends LazyModule with HasSoCParameter with HasPeripheralRanges { 177 val bankedNode = Option.when(!enableCHI)(BankBinder(L3NBanks, L3BlockSize)) 178 val peripheralXbar = Option.when(!enableCHI)(TLXbar()) 179 val l3_xbar = Option.when(!enableCHI)(TLXbar()) 180 val l3_banked_xbar = Option.when(!enableCHI)(TLXbar()) 181 182 val soc_xbar = Option.when(enableCHI)(AXI4Xbar()) 183} 184 185// We adapt the following three traits from rocket-chip. 186// Source: rocket-chip/src/main/scala/subsystem/Ports.scala 187trait HaveSlaveAXI4Port { 188 this: BaseSoC => 189 190 val idBits = 14 191 192 val l3FrontendAXI4Node = AXI4MasterNode(Seq(AXI4MasterPortParameters( 193 Seq(AXI4MasterParameters( 194 name = "dma", 195 id = IdRange(0, 1 << idBits) 196 )) 197 ))) 198 199 if (l3_xbar.isDefined) { 200 val errorDevice = LazyModule(new TLError( 201 params = DevNullParams( 202 address = Seq(AddressSet(0x0, 0x7fffffffL)), 203 maxAtomic = 8, 204 maxTransfer = 64), 205 beatBytes = L3InnerBusWidth / 8 206 )) 207 errorDevice.node := 208 l3_xbar.get := 209 TLFIFOFixer() := 210 TLWidthWidget(32) := 211 AXI4ToTL() := 212 AXI4UserYanker(Some(1)) := 213 AXI4Fragmenter() := 214 AXI4Buffer() := 215 AXI4Buffer() := 216 AXI4IdIndexer(1) := 217 l3FrontendAXI4Node 218 } 219 220 val dma = InModuleBody { 221 l3FrontendAXI4Node.makeIOs() 222 } 223} 224 225trait HaveAXI4MemPort { 226 this: BaseSoC => 227 val device = new MemoryDevice 228 // 48-bit physical address 229 val memRange = AddressSet(0x00000000L, 0xffffffffffffL).subtract(AddressSet(0x0L, 0x7fffffffL)) 230 val memAXI4SlaveNode = AXI4SlaveNode(Seq( 231 AXI4SlavePortParameters( 232 slaves = Seq( 233 AXI4SlaveParameters( 234 address = memRange, 235 regionType = RegionType.UNCACHED, 236 executable = true, 237 supportsRead = TransferSizes(1, L3BlockSize), 238 supportsWrite = TransferSizes(1, L3BlockSize), 239 interleavedId = Some(0), 240 resources = device.reg("mem") 241 ) 242 ), 243 beatBytes = L3OuterBusWidth / 8, 244 requestKeys = if (debugOpts.FPGAPlatform) Seq() else Seq(ReqSourceKey), 245 ) 246 )) 247 248 val mem_xbar = TLXbar() 249 val l3_mem_pmu = BusPerfMonitor(name = "L3_Mem", enable = !debugOpts.FPGAPlatform && !enableCHI, stat_latency = true) 250 val axi4mem_node = AXI4IdentityNode() 251 252 if (enableCHI) { 253 axi4mem_node := 254 soc_xbar.get 255 } else { 256 mem_xbar :=* 257 TLBuffer.chainNode(2) := 258 TLCacheCork() := 259 l3_mem_pmu := 260 TLClientsMerger() := 261 TLXbar() :=* 262 bankedNode.get 263 264 mem_xbar := 265 TLWidthWidget(8) := 266 TLBuffer.chainNode(3, name = Some("PeripheralXbar_to_MemXbar_buffer")) := 267 peripheralXbar.get 268 269 axi4mem_node := 270 TLToAXI4() := 271 TLSourceShrinker(64) := 272 TLWidthWidget(L3OuterBusWidth / 8) := 273 TLBuffer.chainNode(2) := 274 mem_xbar 275 } 276 277 memAXI4SlaveNode := 278 AXI4Buffer() := 279 AXI4Buffer() := 280 AXI4Buffer() := 281 AXI4IdIndexer(idBits = 14) := 282 AXI4UserYanker() := 283 AXI4Deinterleaver(L3BlockSize) := 284 axi4mem_node 285 286 val memory = InModuleBody { 287 memAXI4SlaveNode.makeIOs() 288 } 289} 290 291trait HaveAXI4PeripheralPort { this: BaseSoC => 292 val uartDevice = new SimpleDevice("serial", Seq("xilinx,uartlite")) 293 val uartParams = AXI4SlaveParameters( 294 address = Seq(soc.UARTLiteRange), 295 regionType = RegionType.UNCACHED, 296 supportsRead = TransferSizes(1, 32), 297 supportsWrite = TransferSizes(1, 32), 298 resources = uartDevice.reg 299 ) 300 val peripheralNode = AXI4SlaveNode(Seq(AXI4SlavePortParameters( 301 Seq(AXI4SlaveParameters( 302 address = peripheralRange, 303 regionType = RegionType.UNCACHED, 304 supportsRead = TransferSizes(1, 32), 305 supportsWrite = TransferSizes(1, 32), 306 interleavedId = Some(0) 307 ), uartParams), 308 beatBytes = 8 309 ))) 310 311 val axi4peripheral_node = AXI4IdentityNode() 312 val error_xbar = Option.when(enableCHI)(TLXbar()) 313 314 peripheralNode := 315 AXI4UserYanker() := 316 AXI4IdIndexer(idBits = 2) := 317 AXI4Buffer() := 318 AXI4Buffer() := 319 AXI4Buffer() := 320 AXI4Buffer() := 321 AXI4UserYanker() := 322 // AXI4Deinterleaver(8) := 323 axi4peripheral_node 324 325 if (enableCHI) { 326 val error = LazyModule(new TLError( 327 params = DevNullParams( 328 address = Seq(AddressSet(0x1000000000000L, 0xffffffffffffL)), 329 maxAtomic = 8, 330 maxTransfer = 64), 331 beatBytes = 8 332 )) 333 error.node := error_xbar.get 334 axi4peripheral_node := 335 AXI4Deinterleaver(8) := 336 TLToAXI4() := 337 error_xbar.get := 338 TLBuffer.chainNode(2, Some("llc_to_peripheral_buffer")) := 339 TLFIFOFixer() := 340 TLWidthWidget(L3OuterBusWidth / 8) := 341 AXI4ToTL() := 342 AXI4UserYanker() := 343 soc_xbar.get 344 } else { 345 axi4peripheral_node := 346 AXI4Deinterleaver(8) := 347 TLToAXI4() := 348 TLBuffer.chainNode(3) := 349 peripheralXbar.get 350 } 351 352 val peripheral = InModuleBody { 353 peripheralNode.makeIOs() 354 } 355 356} 357 358class MemMisc()(implicit p: Parameters) extends BaseSoC 359 with HaveAXI4MemPort 360 with PMAConst 361 with HaveAXI4PeripheralPort 362{ 363 364 val peripheral_ports = Option.when(!enableCHI)(Array.fill(NumCores) { TLTempNode() }) 365 val core_to_l3_ports = Option.when(!enableCHI)(Array.fill(NumCores) { TLTempNode() }) 366 367 val l3_in = TLTempNode() 368 val l3_out = TLTempNode() 369 370 val device_xbar = Option.when(enableCHI)(TLXbar()) 371 device_xbar.foreach(_ := error_xbar.get) 372 373 if (l3_banked_xbar.isDefined) { 374 l3_in :*= TLEdgeBuffer(_ => true, Some("L3_in_buffer")) :*= l3_banked_xbar.get 375 l3_banked_xbar.get := TLBuffer.chainNode(2) := l3_xbar.get 376 } 377 bankedNode match { 378 case Some(bankBinder) => 379 bankBinder :*= TLLogger("MEM_L3", !debugOpts.FPGAPlatform && debugOpts.AlwaysBasicDB) :*= l3_out 380 case None => 381 } 382 383 if(soc.L3CacheParamsOpt.isEmpty){ 384 l3_out :*= l3_in 385 } 386 387 if (!enableCHI) { 388 for (port <- peripheral_ports.get) { 389 peripheralXbar.get := TLBuffer.chainNode(2, Some("L2_to_L3_peripheral_buffer")) := port 390 } 391 } 392 393 core_to_l3_ports.foreach { case _ => 394 for ((core_out, i) <- core_to_l3_ports.get.zipWithIndex){ 395 l3_banked_xbar.get :=* 396 TLLogger(s"L3_L2_$i", !debugOpts.FPGAPlatform && debugOpts.AlwaysBasicDB) :=* 397 TLBuffer() := 398 core_out 399 } 400 } 401 402 val clint = LazyModule(new CLINT(CLINTParams(soc.CLINTRange.base), 8)) 403 if (enableCHI) { clint.node := device_xbar.get } 404 else { clint.node := peripheralXbar.get } 405 406 class IntSourceNodeToModule(val num: Int)(implicit p: Parameters) extends LazyModule { 407 val sourceNode = IntSourceNode(IntSourcePortSimple(num, ports = 1, sources = 1)) 408 class IntSourceNodeToModuleImp(wrapper: LazyModule) extends LazyModuleImp(wrapper) { 409 val in = IO(Input(Vec(num, Bool()))) 410 in.zip(sourceNode.out.head._1).foreach{ case (i, s) => s := i } 411 } 412 lazy val module = new IntSourceNodeToModuleImp(this) 413 } 414 415 val plic = LazyModule(new TLPLIC(PLICParams(soc.PLICRange.base), 8)) 416 val plicSource = LazyModule(new IntSourceNodeToModule(NrExtIntr)) 417 418 plic.intnode := plicSource.sourceNode 419 if (enableCHI) { plic.node := device_xbar.get } 420 else { plic.node := peripheralXbar.get } 421 422 val pll_node = TLRegisterNode( 423 address = Seq(soc.PLLRange), 424 device = new SimpleDevice("pll_ctrl", Seq()), 425 beatBytes = 8, 426 concurrency = 1 427 ) 428 if (enableCHI) { pll_node := device_xbar.get } 429 else { pll_node := peripheralXbar.get } 430 431 val debugModule = LazyModule(new DebugModule(NumCores)(p)) 432 if (enableCHI) { 433 debugModule.debug.node := device_xbar.get 434 // TODO: l3_xbar 435 debugModule.debug.dmInner.dmInner.sb2tlOpt.foreach { sb2tl => 436 error_xbar.get := sb2tl.node 437 } 438 } else { 439 debugModule.debug.node := peripheralXbar.get 440 debugModule.debug.dmInner.dmInner.sb2tlOpt.foreach { sb2tl => 441 l3_xbar.get := TLBuffer() := TLWidthWidget(1) := sb2tl.node 442 } 443 } 444 445 val pma = LazyModule(new TLPMA) 446 if (enableCHI) { 447 pma.node := TLBuffer.chainNode(4) := device_xbar.get 448 } else { 449 pma.node := TLBuffer.chainNode(4) := peripheralXbar.get 450 } 451 452 class SoCMiscImp(wrapper: LazyModule) extends LazyModuleImp(wrapper) { 453 454 val debug_module_io = IO(new debugModule.DebugModuleIO) 455 val ext_intrs = IO(Input(UInt(NrExtIntr.W))) 456 val rtc_clock = IO(Input(Bool())) 457 val pll0_lock = IO(Input(Bool())) 458 val pll0_ctrl = IO(Output(Vec(6, UInt(32.W)))) 459 val cacheable_check = IO(new TLPMAIO) 460 val clintTime = IO(Output(ValidIO(UInt(64.W)))) 461 462 debugModule.module.io <> debug_module_io 463 464 // sync external interrupts 465 require(plicSource.module.in.length == ext_intrs.getWidth) 466 for ((plic_in, interrupt) <- plicSource.module.in.zip(ext_intrs.asBools)) { 467 val ext_intr_sync = RegInit(0.U(3.W)) 468 ext_intr_sync := Cat(ext_intr_sync(1, 0), interrupt) 469 plic_in := ext_intr_sync(2) 470 } 471 472 pma.module.io <> cacheable_check 473 474 // positive edge sampling of the lower-speed rtc_clock 475 val rtcTick = RegInit(0.U(3.W)) 476 rtcTick := Cat(rtcTick(1, 0), rtc_clock) 477 clint.module.io.rtcTick := rtcTick(1) && !rtcTick(2) 478 479 val pll_ctrl_regs = Seq.fill(6){ RegInit(0.U(32.W)) } 480 val pll_lock = RegNext(next = pll0_lock, init = false.B) 481 482 clintTime := clint.module.io.time 483 484 pll0_ctrl <> VecInit(pll_ctrl_regs) 485 486 pll_node.regmap( 487 0x000 -> RegFieldGroup( 488 "Pll", Some("PLL ctrl regs"), 489 pll_ctrl_regs.zipWithIndex.map{ 490 case (r, i) => RegField(32, r, RegFieldDesc( 491 s"PLL_ctrl_$i", 492 desc = s"PLL ctrl register #$i" 493 )) 494 } :+ RegField.r(32, Cat(0.U(31.W), pll_lock), RegFieldDesc( 495 "PLL_lock", 496 "PLL lock register" 497 )) 498 ) 499 ) 500 } 501 502 lazy val module = new SoCMiscImp(this) 503} 504 505class SoCMisc()(implicit p: Parameters) extends MemMisc 506 with HaveSlaveAXI4Port 507 508