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