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