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