xref: /XiangShan/src/main/scala/system/SoC.scala (revision 737d2306bccc0406801b261d3dbaee7d6424665a)
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