1package system 2 3import chipsalliance.rocketchip.config.Parameters 4import device.{AXI4Timer, TLTimer, AXI4Plic} 5import chisel3._ 6import chisel3.util._ 7import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp} 8import freechips.rocketchip.tilelink.{TLBuffer, TLFuzzer, TLIdentityNode, TLXbar} 9import utils.DebugIdentityNode 10import utils.XSInfo 11import xiangshan.{HasXSParameter, XSCore, HasXSLog} 12import sifive.blocks.inclusivecache.{CacheParameters, InclusiveCache, InclusiveCacheMicroParameters} 13import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, AddressSet} 14import freechips.rocketchip.tilelink.{TLBundleParameters, TLCacheCork, TLBuffer, TLClientNode, TLIdentityNode, TLXbar, TLWidthWidget, TLFilter, TLToAXI4} 15import freechips.rocketchip.devices.tilelink.{TLError, DevNullParams} 16import freechips.rocketchip.amba.axi4.{AXI4ToTL, AXI4IdentityNode, AXI4UserYanker, AXI4Fragmenter, AXI4IdIndexer, AXI4Deinterleaver} 17 18case class SoCParameters 19( 20 NumCores: Integer = 1, 21 EnableILA: Boolean = false, 22 HasL2Cache: Boolean = false, 23 HasPrefetch: Boolean = false 24) 25 26trait HasSoCParameter extends HasXSParameter{ 27 val soc = top.Parameters.get.socParameters 28 val NumCores = soc.NumCores 29 val EnableILA = soc.EnableILA 30 val HasL2cache = soc.HasL2Cache 31 val HasPrefetch = soc.HasPrefetch 32} 33 34class ILABundle extends Bundle {} 35 36 37class DummyCore()(implicit p: Parameters) extends LazyModule { 38 val mem = TLFuzzer(nOperations = 10) 39 val mmio = TLFuzzer(nOperations = 10) 40 41 lazy val module = new LazyModuleImp(this){ 42 43 } 44} 45 46 47class BankAddressConvertor(index: Int, bankBits: Int, blockBits: Int, recover: Boolean = false)(implicit p: Parameters) extends LazyModule { 48 val node = TLIdentityNode() 49 50 def shrink(addr: UInt): UInt = { 51 val msb = addr.getWidth - 1 52 Cat(0.U(bankBits.W), addr(msb, bankBits + blockBits), addr(blockBits - 1, 0)) 53 } 54 55 def extend(addr: UInt): UInt = { 56 val msb = addr.getWidth - 1 57 Cat(addr(msb - bankBits, blockBits), index.U(bankBits.W), addr(blockBits - 1, 0)) 58 } 59 60 lazy val module = new LazyModuleImp(this) with HasXSLog { 61 (node.in zip node.out) foreach { case ((in, _), (out, _)) => 62 out <> in 63 if (!recover) { 64 out.a.bits.address := shrink(in.a.bits.address) 65 out.c.bits.address := shrink(in.c.bits.address) 66 in.b.bits.address := shrink(out.b.bits.address) 67 68 XSInfo(out.a.fire(), s"before bank $index A in addr %x -> out addr %x\n", in.a.bits.address, out.a.bits.address) 69 XSInfo(out.b.fire(), s"before bank $index B out addr %x -> in addr %x\n", out.b.bits.address, in.b.bits.address) 70 XSInfo(out.c.fire(), s"before bank $index C in addr %x -> out addr %x\n", in.c.bits.address, out.c.bits.address) 71 } 72 else { 73 out.a.bits.address := extend(in.a.bits.address) 74 out.c.bits.address := extend(in.c.bits.address) 75 in.b.bits.address := extend(out.b.bits.address) 76 77 XSInfo(out.a.fire(), s"after bank $index A in addr %x -> out addr %x\n", in.a.bits.address, out.a.bits.address) 78 XSInfo(out.b.fire(), s"after bank $index B out addr %x -> out addr %x\n", out.b.bits.address, in.b.bits.address) 79 XSInfo(out.c.fire(), s"after bank $index C in addr %x -> out addr %x\n", in.c.bits.address, out.c.bits.address) 80 } 81 } 82 } 83} 84 85object BankAddressConvertor { 86 def apply(index: Int, bankBits: Int, blockBits: Int, recover: Boolean)(implicit p: Parameters) = { 87 val bankAddressConvertor = LazyModule(new BankAddressConvertor(index, bankBits, blockBits, recover)) 88 bankAddressConvertor.node 89 } 90} 91 92class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter { 93 // CPU Cores 94 private val xs_core = Seq.fill(NumCores)(LazyModule(new XSCore())) 95 96 // L1 to L2 network 97 // ------------------------------------------------- 98 private val l2_xbar = Seq.fill(NumCores)(TLXbar()) 99 100 private val l2cache = Seq.fill(NumCores)(LazyModule(new InclusiveCache( 101 CacheParameters( 102 level = 2, 103 ways = L2NWays, 104 sets = L2NSets, 105 blockBytes = L2BlockSize, 106 beatBytes = L1BusWidth / 8, // beatBytes = l1BusDataWidth / 8 107 cacheName = s"L2" 108 ), 109 InclusiveCacheMicroParameters( 110 writeBytes = 8 111 ) 112 ))) 113 114 // L2 to L3 network 115 // ------------------------------------------------- 116 private val l3_xbar = TLXbar() 117 118 private val l3_banks = (0 until L3NBanks) map (i => 119 LazyModule(new InclusiveCache( 120 CacheParameters( 121 level = 3, 122 ways = L3NWays, 123 sets = L3NSets, 124 blockBytes = L3BlockSize, 125 beatBytes = L2BusWidth / 8, 126 cacheName = s"L3_$i" 127 ), 128 InclusiveCacheMicroParameters( 129 writeBytes = 8 130 ) 131 ))) 132 133 // L3 to memory network 134 // ------------------------------------------------- 135 private val memory_xbar = TLXbar() 136 private val mmioXbar = TLXbar() 137 138 // only mem, dma and extDev are visible externally 139 val mem = Seq.fill(L3NBanks)(AXI4IdentityNode()) 140 val dma = AXI4IdentityNode() 141 val extDev = AXI4IdentityNode() 142 143 // connections 144 // ------------------------------------------------- 145 for (i <- 0 until NumCores) { 146 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).memBlock.dcache.clientNode 147 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).l1pluscache.clientNode 148 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).ptw.node 149 l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).l2Prefetcher.clientNode 150 mmioXbar := TLBuffer() := DebugIdentityNode() := xs_core(i).memBlock.uncache.clientNode 151 l2cache(i).node := TLBuffer() := DebugIdentityNode() := l2_xbar(i) 152 l3_xbar := TLBuffer() := DebugIdentityNode() := l2cache(i).node 153 } 154 155 // DMA should not go to MMIO 156 val mmioRange = AddressSet(base = 0x0000000000L, mask = 0x007fffffffL) 157 // AXI4ToTL needs a TLError device to route error requests, 158 // add one here to make it happy. 159 val tlErrorParams = DevNullParams( 160 address = Seq(mmioRange), 161 maxAtomic = 8, 162 maxTransfer = 64) 163 val tlError = LazyModule(new TLError(params = tlErrorParams, beatBytes = L2BusWidth / 8)) 164 private val tlError_xbar = TLXbar() 165 tlError_xbar := 166 AXI4ToTL() := 167 AXI4UserYanker(Some(1)) := 168 AXI4Fragmenter() := 169 AXI4IdIndexer(1) := 170 dma 171 tlError.node := tlError_xbar 172 173 l3_xbar := 174 TLBuffer() := 175 DebugIdentityNode() := 176 tlError_xbar 177 178 def bankFilter(bank: Int) = AddressSet( 179 base = bank * L3BlockSize, 180 mask = ~BigInt((L3NBanks - 1) * L3BlockSize)) 181 182 for(i <- 0 until L3NBanks) { 183 val filter = TLFilter(TLFilter.mSelectIntersect(bankFilter(i))) 184 l3_banks(i).node := BankAddressConvertor(i, log2Ceil(L3NBanks), log2Ceil(L3BlockSize), recover = false) := TLBuffer() := DebugIdentityNode() := filter := l3_xbar 185 } 186 187 for(i <- 0 until L3NBanks) { 188 mem(i) := 189 AXI4UserYanker() := 190 TLToAXI4() := 191 TLWidthWidget(L3BusWidth / 8) := 192 TLCacheCork() := 193 BankAddressConvertor(i, log2Ceil(L3NBanks), log2Ceil(L3BlockSize), recover = true) := 194 l3_banks(i).node 195 } 196 197 private val clint = LazyModule(new TLTimer( 198 Seq(AddressSet(0x38000000L, 0x0000ffffL)), 199 sim = !env.FPGAPlatform 200 )) 201 202 clint.node := mmioXbar 203 extDev := AXI4UserYanker() := TLToAXI4() := mmioXbar 204 205 val plic = LazyModule(new AXI4Plic( 206 Seq(AddressSet(0x3c000000L, 0x03ffffffL)), 207 sim = !env.FPGAPlatform 208 )) 209 val plicIdentity = AXI4IdentityNode() 210 plic.node := plicIdentity := AXI4UserYanker() := TLToAXI4() := mmioXbar 211 212 lazy val module = new LazyModuleImp(this){ 213 val io = IO(new Bundle{ 214 val extIntrs = Input(Vec(NrExtIntr, Bool())) 215 // val meip = Input(Vec(NumCores, Bool())) 216 val ila = if(env.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None 217 }) 218 219 plic.module.io.extra.get.intrVec <> RegNext(RegNext(Cat(io.extIntrs))) 220 221 for (i <- 0 until NumCores) { 222 xs_core(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i) 223 xs_core(i).module.io.externalInterrupt.msip := clint.module.io.msip(i) 224 // xs_core(i).module.io.externalInterrupt.meip := RegNext(RegNext(io.meip(i))) 225 xs_core(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i) 226 } 227 // do not let dma AXI signals optimized out 228 chisel3.dontTouch(dma.out.head._1) 229 chisel3.dontTouch(extDev.out.head._1) 230 } 231 232} 233