1package top 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import utils._ 7import system._ 8import chisel3.stage.ChiselGeneratorAnnotation 9import chipsalliance.rocketchip.config._ 10import device.{AXI4Plic, TLTimer} 11import freechips.rocketchip.diplomacy._ 12import freechips.rocketchip.tilelink._ 13import freechips.rocketchip.amba.axi4._ 14import freechips.rocketchip.devices.tilelink.{DevNullParams, TLError} 15import freechips.rocketchip.diplomaticobjectmodel.logicaltree.GenericLogicalTreeNode 16import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkPortSimple} 17import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, XLen} 18import sifive.blocks.inclusivecache.{InclusiveCache, InclusiveCacheMicroParameters, CacheParameters} 19import xiangshan.cache.prefetch.L2Prefetcher 20 21 22class XSCoreWithL2()(implicit p: Parameters) extends LazyModule 23 with HasXSParameter with HasSoCParameter { 24 private val core = LazyModule(new XSCore()) 25 private val l2prefetcher = LazyModule(new L2Prefetcher()) 26 private val l2xbar = TLXbar() 27 private val l2cache = if (useFakeL2Cache) null else LazyModule(new InclusiveCache( 28 CacheParameters( 29 level = 2, 30 ways = L2NWays, 31 sets = L2NSets, 32 blockBytes = L2BlockSize, 33 beatBytes = L1BusWidth / 8, // beatBytes = l1BusDataWidth / 8 34 cacheName = s"L2", 35 uncachedGet = true, 36 enablePerf = false 37 ), 38 InclusiveCacheMicroParameters( 39 memCycles = 25, 40 writeBytes = 32 41 ), 42 fpga = debugOpts.FPGAPlatform 43 )) 44 45 val memory_port = TLIdentityNode() 46 val uncache = TLXbar() 47 48 if (!useFakeDCache) { 49 l2xbar := TLBuffer() := core.memBlock.dcache.clientNode 50 } 51 if (!useFakeL1plusCache) { 52 l2xbar := TLBuffer() := core.l1pluscache.clientNode 53 } 54 if (!useFakePTW) { 55 l2xbar := TLBuffer() := core.ptw.node 56 } 57 l2xbar := TLBuffer() := l2prefetcher.clientNode 58 if (useFakeL2Cache) { 59 memory_port := l2xbar 60 } 61 else { 62 l2cache.node := TLBuffer() := l2xbar 63 memory_port := l2cache.node 64 } 65 66 uncache := TLBuffer() := core.frontend.instrUncache.clientNode 67 uncache := TLBuffer() := core.memBlock.uncache.clientNode 68 69 lazy val module = new LazyModuleImp(this) { 70 val io = IO(new Bundle { 71 val hartId = Input(UInt(64.W)) 72 val externalInterrupt = new ExternalInterruptIO 73 val l1plus_error, icache_error, dcache_error = new L1CacheErrorInfo 74 }) 75 76 core.module.io.hartId := io.hartId 77 core.module.io.externalInterrupt := io.externalInterrupt 78 l2prefetcher.module.io.enable := core.module.io.l2_pf_enable 79 if (useFakeL2Cache) { 80 l2prefetcher.module.io.in := DontCare 81 } 82 else { 83 l2prefetcher.module.io.in <> l2cache.module.io 84 } 85 io.l1plus_error <> core.module.io.l1plus_error 86 io.icache_error <> core.module.io.icache_error 87 io.dcache_error <> core.module.io.dcache_error 88 89 val core_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 90 core.module.reset := core_reset_gen.io.out 91 92 val l2_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 93 l2prefetcher.module.reset := l2_reset_gen.io.out 94 if (!useFakeL2Cache) { 95 l2cache.module.reset := l2_reset_gen.io.out 96 } 97 } 98} 99 100abstract class BaseXSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter { 101 val bankedNode = BankBinder(L3NBanks, L3BlockSize) 102 val peripheralXbar = TLXbar() 103 val l3_xbar = TLXbar() 104} 105 106// We adapt the following three traits from rocket-chip. 107// Source: rocket-chip/src/main/scala/subsystem/Ports.scala 108trait HaveSlaveAXI4Port { 109 this: BaseXSSoc => 110 111 val idBits = 16 112 113 val l3FrontendAXI4Node = AXI4MasterNode(Seq(AXI4MasterPortParameters( 114 Seq(AXI4MasterParameters( 115 name = "dma", 116 id = IdRange(0, 1 << idBits) 117 )) 118 ))) 119 private val errorDevice = LazyModule(new TLError( 120 params = DevNullParams( 121 address = Seq(AddressSet(0x0, 0x7fffffffL)), 122 maxAtomic = 8, 123 maxTransfer = 64), 124 beatBytes = L3InnerBusWidth / 8 125 )) 126 private val error_xbar = TLXbar() 127 128 error_xbar := 129 AXI4ToTL() := 130 AXI4UserYanker(Some(1)) := 131 AXI4Fragmenter() := 132 AXI4IdIndexer(1) := 133 l3FrontendAXI4Node 134 errorDevice.node := error_xbar 135 l3_xbar := 136 TLBuffer() := 137 error_xbar 138 139 val dma = InModuleBody { 140 l3FrontendAXI4Node.makeIOs() 141 } 142} 143 144trait HaveAXI4MemPort { 145 this: BaseXSSoc => 146 // 40-bit physical address 147 val memRange = AddressSet(0x00000000L, 0xffffffffffL).subtract(AddressSet(0x0L, 0x7fffffffL)) 148 val memAXI4SlaveNode = AXI4SlaveNode(Seq( 149 AXI4SlavePortParameters( 150 slaves = Seq( 151 AXI4SlaveParameters( 152 address = memRange, 153 regionType = RegionType.UNCACHED, 154 executable = true, 155 supportsRead = TransferSizes(1, L3BlockSize), 156 supportsWrite = TransferSizes(1, L3BlockSize), 157 interleavedId = Some(0) 158 ) 159 ), 160 beatBytes = L3OuterBusWidth / 8 161 ) 162 )) 163 164 val mem_xbar = TLXbar() 165 mem_xbar :=* TLBuffer() :=* TLCacheCork() :=* bankedNode 166 memAXI4SlaveNode := 167 AXI4UserYanker() := 168 AXI4Deinterleaver(L3BlockSize) := 169 TLToAXI4() := 170 TLWidthWidget(L3OuterBusWidth / 8) := 171 mem_xbar 172 173 val memory = InModuleBody { 174 memAXI4SlaveNode.makeIOs() 175 } 176} 177 178 179trait HaveAXI4PeripheralPort { this: BaseXSSoc => 180 // on-chip devices: 0x3800_000 - 0x3fff_ffff 181 val onChipPeripheralRange = AddressSet(0x38000000L, 0x07ffffffL) 182 val peripheralRange = AddressSet(0x0, 0x7fffffff).subtract(onChipPeripheralRange) 183 val peripheralNode = AXI4SlaveNode(Seq(AXI4SlavePortParameters( 184 Seq(AXI4SlaveParameters( 185 address = peripheralRange, 186 regionType = RegionType.UNCACHED, 187 supportsRead = TransferSizes(1, 8), 188 supportsWrite = TransferSizes(1, 8), 189 interleavedId = Some(0) 190 )), 191 beatBytes = 8 192 ))) 193 194 peripheralNode := 195 AXI4UserYanker() := 196 AXI4Deinterleaver(8) := 197 TLToAXI4() := 198 peripheralXbar 199 200 val peripheral = InModuleBody { 201 peripheralNode.makeIOs() 202 } 203 204} 205 206class XSTop()(implicit p: Parameters) extends XSTopWithoutDMA 207 with HaveSlaveAXI4Port 208 209class XSTopWithoutDMA()(implicit p: Parameters) extends BaseXSSoc() 210 with HaveAXI4MemPort 211 with HaveAXI4PeripheralPort 212{ 213 214 println(s"FPGASoC cores: $NumCores banks: $L3NBanks block size: $L3BlockSize bus size: $L3OuterBusWidth") 215 216 val core_with_l2 = soc.cores.map(coreParams => 217 LazyModule(new XSCoreWithL2()(p.alterPartial({ 218 case XSCoreParamsKey => coreParams 219 }))) 220 ) 221 222 for (i <- 0 until NumCores) { 223 peripheralXbar := TLBuffer() := core_with_l2(i).uncache 224 l3_xbar := TLBuffer() := core_with_l2(i).memory_port 225 } 226 227 private val clint = LazyModule(new TLTimer( 228 Seq(AddressSet(0x38000000L, 0x0000ffffL)), 229 sim = !debugOpts.FPGAPlatform, NumCores 230 )) 231 clint.node := peripheralXbar 232 233 val fakeTreeNode = new GenericLogicalTreeNode 234 val beu = LazyModule( 235 new BusErrorUnit(new XSL1BusErrors(NumCores), BusErrorUnitParams(0x38010000), fakeTreeNode)) 236 beu.node := peripheralXbar 237 238 class BeuSinkNode()(implicit p: Parameters) extends LazyModule { 239 val intSinkNode = IntSinkNode(IntSinkPortSimple()) 240 lazy val module = new LazyModuleImp(this){ 241 val interrupt = IO(Output(Bool())) 242 interrupt := intSinkNode.in.head._1.head 243 } 244 } 245 val beuSink = LazyModule(new BeuSinkNode()) 246 beuSink.intSinkNode := beu.intNode 247 248 val plic = LazyModule(new AXI4Plic( 249 Seq(AddressSet(0x3c000000L, 0x03ffffffL)), 250 NumCores, NrExtIntr + 1, 251 !debugOpts.FPGAPlatform, 252 )) 253 plic.node := AXI4IdentityNode() := AXI4UserYanker() := TLToAXI4() := peripheralXbar 254 255 val l3cache = if (useFakeL3Cache) null else LazyModule(new InclusiveCache( 256 CacheParameters( 257 level = 3, 258 ways = L3NWays, 259 sets = L3NSets, 260 blockBytes = L3BlockSize, 261 beatBytes = L3InnerBusWidth / 8, 262 cacheName = "L3", 263 uncachedGet = false, 264 enablePerf = false 265 ), 266 InclusiveCacheMicroParameters( 267 memCycles = 25, 268 writeBytes = 32 269 ), 270 fpga = debugOpts.FPGAPlatform 271 )) 272 val l3Ignore = if (useFakeL3Cache) TLIgnoreNode() else null 273 274 if (useFakeL3Cache) { 275 bankedNode :*= l3Ignore :*= l3_xbar 276 } 277 else { 278 bankedNode :*= l3cache.node :*= TLBuffer() :*= l3_xbar 279 } 280 281 lazy val module = new LazyRawModuleImp(this) { 282 val io = IO(new Bundle { 283 val clock = Input(Bool()) 284 val reset = Input(Bool()) 285 val extIntrs = Input(UInt(NrExtIntr.W)) 286 // val meip = Input(Vec(NumCores, Bool())) 287 val ila = if(debugOpts.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None 288 }) 289 childClock := io.clock.asClock() 290 291 withClockAndReset(childClock, io.reset) { 292 val resetGen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 293 resetGen.suggestName("top_reset_gen") 294 childReset := resetGen.io.out 295 } 296 297 withClockAndReset(childClock, childReset) { 298 plic.module.io.extra.get.intrVec <> Cat(beuSink.module.interrupt, io.extIntrs) 299 300 for (i <- 0 until NumCores) { 301 val core_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 302 core_reset_gen.suggestName(s"core_${i}_reset_gen") 303 core_with_l2(i).module.reset := core_reset_gen.io.out 304 core_with_l2(i).module.io.hartId := i.U 305 core_with_l2(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i) 306 core_with_l2(i).module.io.externalInterrupt.msip := clint.module.io.msip(i) 307 core_with_l2(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i) 308 beu.module.io.errors.l1plus(i) := core_with_l2(i).module.io.l1plus_error 309 beu.module.io.errors.icache(i) := core_with_l2(i).module.io.icache_error 310 beu.module.io.errors.dcache(i) := core_with_l2(i).module.io.dcache_error 311 } 312 313 if (!useFakeL3Cache) { 314 val l3_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 315 l3_reset_gen.suggestName("l3_reset_gen") 316 l3cache.module.reset := l3_reset_gen.io.out 317 } 318 } 319 } 320} 321 322class DefaultConfig(n: Int) extends Config((site, here, up) => { 323 case XLen => 64 324 case DebugOptionsKey => DebugOptions() 325 case SoCParamsKey => SoCParameters( 326 cores = List.tabulate(n){ i => XSCoreParameters(HartId = i) } 327 ) 328}) 329 330object TopMain extends App { 331 override def main(args: Array[String]): Unit = { 332 val numCores = if(args.contains("--dual-core")) 2 else 1 333 val otherArgs = args.filterNot(_ == "--dual-core") 334 implicit val config = new DefaultConfig(numCores) 335 XiangShanStage.execute(otherArgs, Seq( 336 ChiselGeneratorAnnotation(() => { 337 val soc = LazyModule(new XSTop()) 338 soc.module 339 }) 340 )) 341 } 342} 343