1package system 2 3import chipsalliance.rocketchip.config.Parameters 4import device.{AXI4Plic, AXI4Timer, TLTimer} 5import chisel3._ 6import chisel3.util._ 7import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp} 8import freechips.rocketchip.tilelink.{BankBinder, TLBuffer, TLBundleParameters, TLCacheCork, TLClientNode, TLFilter, TLFuzzer, TLIdentityNode, TLToAXI4, TLWidthWidget, TLXbar} 9import utils.{DataDontCareNode, DebugIdentityNode} 10import utils.XSInfo 11import xiangshan.{DifftestBundle, HasXSParameter, XSBundle, XSCore} 12import xiangshan.cache.prefetch._ 13import sifive.blocks.inclusivecache.{CacheParameters, InclusiveCache, InclusiveCacheMicroParameters} 14import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp} 15import freechips.rocketchip.devices.tilelink.{DevNullParams, TLError} 16import freechips.rocketchip.amba.axi4.{AXI4Deinterleaver, AXI4Fragmenter, AXI4IdIndexer, AXI4IdentityNode, AXI4ToTL, AXI4UserYanker} 17import freechips.rocketchip.diplomaticobjectmodel.logicaltree.GenericLogicalTreeNode 18import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkParameters, IntSinkPortParameters, IntSinkPortSimple} 19import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, BusErrors, L1BusErrors} 20 21case class SoCParameters 22( 23 NumCores: Integer = 1, 24 EnableILA: Boolean = false, 25 HasL2Cache: Boolean = false, 26 HasPrefetch: Boolean = false 27) 28 29trait HasSoCParameter extends HasXSParameter{ 30 val soc = top.Parameters.get.socParameters 31 val NumCores = soc.NumCores 32 val EnableILA = soc.EnableILA 33 val HasL2cache = soc.HasL2Cache 34 val HasPrefetch = soc.HasPrefetch 35} 36 37class ILABundle extends Bundle {} 38 39 40class L1CacheErrorInfo extends XSBundle{ 41 val paddr = Valid(UInt(PAddrBits.W)) 42 // for now, we only detect ecc 43 val ecc_error = Valid(Bool()) 44} 45 46class XSL1BusErrors(val nCores: Int) extends BusErrors { 47 val icache = Vec(nCores, new L1CacheErrorInfo) 48 val l1plus = Vec(nCores, new L1CacheErrorInfo) 49 val dcache = Vec(nCores, new L1CacheErrorInfo) 50 51 override def toErrorList: List[Option[(ValidIO[UInt], String, String)]] = 52 List.tabulate(nCores){i => 53 List( 54 Some(icache(i).paddr, s"IBUS_$i", s"Icache_$i bus error"), 55 Some(icache(i).ecc_error, s"I_ECC_$i", s"Icache_$i ecc error"), 56 Some(l1plus(i).paddr, s"L1PLUS_$i", s"L1PLUS_$i bus error"), 57 Some(l1plus(i).ecc_error, s"L1PLUS_ECC_$i", s"L1PLUS_$i ecc error"), 58 Some(dcache(i).paddr, s"DBUS_$i", s"Dcache_$i bus error"), 59 Some(dcache(i).ecc_error, s"D_ECC_$i", s"Dcache_$i ecc error") 60 ) 61 }.flatten 62} 63 64class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter { 65 // CPU Cores 66 private val xs_core = Seq.fill(NumCores)(LazyModule(new XSCore())) 67 68 // L1 to L2 network 69 // ------------------------------------------------- 70 private val l2_xbar = Seq.fill(NumCores)(TLXbar()) 71 72 private val l2cache = Seq.fill(NumCores)(LazyModule(new InclusiveCache( 73 CacheParameters( 74 level = 2, 75 ways = L2NWays, 76 sets = L2NSets, 77 blockBytes = L2BlockSize, 78 beatBytes = L1BusWidth / 8, // beatBytes = l1BusDataWidth / 8 79 replacement = "plru", 80 cacheName = s"L2", 81 uncachedGet = true, 82 enablePerf = env.EnablePerfDebug && !env.FPGAPlatform 83 ), 84 InclusiveCacheMicroParameters( 85 writeBytes = 32 86 ) 87 ))) 88 89 private val l2prefetcher = Seq.fill(NumCores)(LazyModule(new L2Prefetcher())) 90 91 // L2 to L3 network 92 // ------------------------------------------------- 93 private val l3_xbar = TLXbar() 94 95 private val l3_node = LazyModule(new InclusiveCache( 96 CacheParameters( 97 level = 3, 98 ways = L3NWays, 99 sets = L3NSets, 100 blockBytes = L3BlockSize, 101 beatBytes = L2BusWidth / 8, 102 replacement = "plru", 103 cacheName = "L3", 104 uncachedGet = false, 105 enablePerf = env.EnablePerfDebug && !env.FPGAPlatform 106 ), 107 InclusiveCacheMicroParameters( 108 writeBytes = 32 109 ) 110 )).node 111 112 // L3 to memory network 113 // ------------------------------------------------- 114 private val memory_xbar = TLXbar() 115 private val mmioXbar = TLXbar() 116 117 // only mem, dma and extDev are visible externally 118 val mem = Seq.fill(L3NBanks)(AXI4IdentityNode()) 119 val dma = AXI4IdentityNode() 120 val extDev = AXI4IdentityNode() 121 122 // connections 123 // ------------------------------------------------- 124 for (i <- 0 until NumCores) { 125 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).memBlock.dcache.clientNode 126 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).l1pluscache.clientNode 127 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).ptw.node 128 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := l2prefetcher(i).clientNode 129 130 mmioXbar := TLBuffer() := DebugIdentityNode() := xs_core(i).memBlock.uncache.clientNode 131 mmioXbar := TLBuffer() := DebugIdentityNode() := xs_core(i).frontend.instrUncache.clientNode 132 l2cache(i).node := DataDontCareNode(a = true, b = true) := TLBuffer() := DebugIdentityNode() := l2_xbar(i) 133 l3_xbar := TLBuffer() := DebugIdentityNode() := l2cache(i).node 134 } 135 136 // DMA should not go to MMIO 137 val mmioRange = AddressSet(base = 0x0000000000L, mask = 0x007fffffffL) 138 // AXI4ToTL needs a TLError device to route error requests, 139 // add one here to make it happy. 140 val tlErrorParams = DevNullParams( 141 address = Seq(mmioRange), 142 maxAtomic = 8, 143 maxTransfer = 64) 144 val tlError = LazyModule(new TLError(params = tlErrorParams, beatBytes = L2BusWidth / 8)) 145 private val tlError_xbar = TLXbar() 146 tlError_xbar := 147 AXI4ToTL() := 148 AXI4UserYanker(Some(1)) := 149 AXI4Fragmenter() := 150 AXI4IdIndexer(1) := 151 dma 152 tlError.node := tlError_xbar 153 154 l3_xbar := 155 TLBuffer() := 156 DebugIdentityNode() := 157 tlError_xbar 158 159 val bankedNode = 160 BankBinder(L3NBanks, L3BlockSize) :*= l3_node :*= TLBuffer() :*= DebugIdentityNode() :*= l3_xbar 161 162 for(i <- 0 until L3NBanks) { 163 mem(i) := 164 AXI4UserYanker() := 165 TLToAXI4() := 166 TLWidthWidget(L3BusWidth / 8) := 167 TLBuffer() := 168 TLCacheCork() := 169 bankedNode 170 } 171 172 private val clint = LazyModule(new TLTimer( 173 Seq(AddressSet(0x38000000L, 0x0000ffffL)), 174 sim = !env.FPGAPlatform 175 )) 176 177 clint.node := mmioXbar 178 extDev := AXI4UserYanker() := TLToAXI4() := mmioXbar 179 180 val fakeTreeNode = new GenericLogicalTreeNode 181 182 val beu = LazyModule( 183 new BusErrorUnit(new XSL1BusErrors(NumCores), BusErrorUnitParams(0x38010000), fakeTreeNode)) 184 beu.node := mmioXbar 185 186 class BeuSinkNode()(implicit p: Parameters) extends LazyModule { 187 val intSinkNode = IntSinkNode(IntSinkPortSimple()) 188 lazy val module = new LazyModuleImp(this){ 189 val interrupt = IO(Output(Bool())) 190 interrupt := intSinkNode.in.head._1.head 191 } 192 } 193 val beuSink = LazyModule(new BeuSinkNode()) 194 beuSink.intSinkNode := beu.intNode 195 196 val plic = LazyModule(new AXI4Plic( 197 Seq(AddressSet(0x3c000000L, 0x03ffffffL)), 198 sim = !env.FPGAPlatform 199 )) 200 plic.node := AXI4UserYanker() := TLToAXI4() := mmioXbar 201 202 lazy val module = new LazyModuleImp(this){ 203 val io = IO(new Bundle{ 204 val extIntrs = Input(UInt(NrExtIntr.W)) 205 // val meip = Input(Vec(NumCores, Bool())) 206 val ila = if(env.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None 207 }) 208 val difftestIO0 = IO(new DifftestBundle()) 209 val difftestIO1 = IO(new DifftestBundle()) 210 val difftestIO = Seq(difftestIO0, difftestIO1) 211 212 val trapIO0 = IO(new xiangshan.TrapIO()) 213 val trapIO1 = IO(new xiangshan.TrapIO()) 214 val trapIO = Seq(trapIO0, trapIO1) 215 216 plic.module.io.extra.get.intrVec <> RegNext(beuSink.module.interrupt) 217 218 for (i <- 0 until NumCores) { 219 xs_core(i).module.io.hartId := i.U 220 xs_core(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i) 221 xs_core(i).module.io.externalInterrupt.msip := clint.module.io.msip(i) 222 beu.module.io.errors.l1plus(i) := RegNext(xs_core(i).module.io.l1plus_error) 223 beu.module.io.errors.icache(i) := RegNext(xs_core(i).module.io.icache_error) 224 beu.module.io.errors.dcache(i) := RegNext(xs_core(i).module.io.dcache_error) 225 // xs_core(i).module.io.externalInterrupt.meip := RegNext(RegNext(io.meip(i))) 226 xs_core(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i) 227 l2prefetcher(i).module.io.enable := RegNext(xs_core(i).module.io.l2_pf_enable) 228 l2prefetcher(i).module.io.in <> l2cache(i).module.io 229 } 230 231 difftestIO0 <> xs_core(0).module.difftestIO 232 difftestIO1 <> DontCare 233 trapIO0 <> xs_core(0).module.trapIO 234 trapIO1 <> DontCare 235 236 if (env.DualCore) { 237 difftestIO1 <> xs_core(1).module.difftestIO 238 trapIO1 <> xs_core(1).module.trapIO 239 } 240 // do not let dma AXI signals optimized out 241 dontTouch(dma.out.head._1) 242 dontTouch(extDev.out.head._1) 243 dontTouch(io.extIntrs) 244 } 245 246} 247