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