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