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