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