xref: /XiangShan/src/main/scala/system/SoC.scala (revision 87b0fcb0ce9371acdc670c6d1dc5226f5d9b45c9)
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.{BankBinder, TLBuffer, TLBundleParameters, TLCacheCork, TLClientNode, TLFilter, TLFuzzer, TLIdentityNode, TLToAXI4, TLWidthWidget, TLXbar}
9import utils.{DebugIdentityNode, DataDontCareNode}
10import utils.XSInfo
11import xiangshan.{HasXSParameter, XSCore, HasXSLog, DifftestBundle}
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}
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 XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
48  // CPU Cores
49  private val xs_core = Seq.fill(NumCores)(LazyModule(new XSCore()))
50
51  // L1 to L2 network
52  // -------------------------------------------------
53  private val l2_xbar = Seq.fill(NumCores)(TLXbar())
54
55  private val l2cache = Seq.fill(NumCores)(LazyModule(new InclusiveCache(
56    CacheParameters(
57      level = 2,
58      ways = L2NWays,
59      sets = L2NSets,
60      blockBytes = L2BlockSize,
61      beatBytes = L1BusWidth / 8, // beatBytes = l1BusDataWidth / 8
62      cacheName = s"L2"
63    ),
64    InclusiveCacheMicroParameters(
65      writeBytes = 32
66    )
67  )))
68
69  private val l2prefetcher = Seq.fill(NumCores)(LazyModule(new L2Prefetcher()))
70
71  // L2 to L3 network
72  // -------------------------------------------------
73  private val l3_xbar = TLXbar()
74
75  private val l3_node = LazyModule(new InclusiveCache(
76    CacheParameters(
77      level = 3,
78      ways = L3NWays,
79      sets = L3NSets,
80      blockBytes = L3BlockSize,
81      beatBytes = L2BusWidth / 8,
82      cacheName = "L3"
83    ),
84    InclusiveCacheMicroParameters(
85      writeBytes = 32
86    )
87  )).node
88
89  // L3 to memory network
90  // -------------------------------------------------
91  private val memory_xbar = TLXbar()
92  private val mmioXbar = TLXbar()
93
94  // only mem, dma and extDev are visible externally
95  val mem = Seq.fill(L3NBanks)(AXI4IdentityNode())
96  val dma = AXI4IdentityNode()
97  val extDev = AXI4IdentityNode()
98
99  // connections
100  // -------------------------------------------------
101  for (i <- 0 until NumCores) {
102    l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).memBlock.dcache.clientNode
103    l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).l1pluscache.clientNode
104    l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).ptw.node
105    // l2_xbar(i) := TLBuffer() := DebugIdentityNode() := xs_core(i).l2Prefetcher.clientNode
106    l2_xbar(i) := TLBuffer() := DebugIdentityNode() := l2prefetcher(i).clientNode
107    l2prefetcher(i).module.io.in <> l2cache(i).module.io
108
109    mmioXbar   := TLBuffer() := DebugIdentityNode() := xs_core(i).memBlock.uncache.clientNode
110    mmioXbar   := TLBuffer() := DebugIdentityNode() := xs_core(i).frontend.instrUncache.clientNode
111    l2cache(i).node := DataDontCareNode(a = true, b = true) := TLBuffer() := DebugIdentityNode() := l2_xbar(i)
112    l3_xbar := TLBuffer() := DebugIdentityNode() := l2cache(i).node
113  }
114
115  // DMA should not go to MMIO
116  val mmioRange = AddressSet(base = 0x0000000000L, mask = 0x007fffffffL)
117  // AXI4ToTL needs a TLError device to route error requests,
118  // add one here to make it happy.
119  val tlErrorParams = DevNullParams(
120    address = Seq(mmioRange),
121    maxAtomic = 8,
122    maxTransfer = 64)
123  val tlError = LazyModule(new TLError(params = tlErrorParams, beatBytes = L2BusWidth / 8))
124  private val tlError_xbar = TLXbar()
125  tlError_xbar :=
126    AXI4ToTL() :=
127    AXI4UserYanker(Some(1)) :=
128    AXI4Fragmenter() :=
129    AXI4IdIndexer(1) :=
130    dma
131  tlError.node := tlError_xbar
132
133  l3_xbar :=
134    TLBuffer() :=
135    DebugIdentityNode() :=
136    tlError_xbar
137
138  val bankedNode =
139    BankBinder(L3NBanks, L3BlockSize) :*= l3_node :*= TLBuffer() :*= DebugIdentityNode() :*= l3_xbar
140
141  for(i <- 0 until L3NBanks) {
142    mem(i) :=
143      AXI4UserYanker() :=
144      TLToAXI4() :=
145      TLWidthWidget(L3BusWidth / 8) :=
146      TLCacheCork() :=
147      bankedNode
148  }
149
150  private val clint = LazyModule(new TLTimer(
151    Seq(AddressSet(0x38000000L, 0x0000ffffL)),
152    sim = !env.FPGAPlatform
153  ))
154
155  clint.node := mmioXbar
156  extDev := AXI4UserYanker() := TLToAXI4() := mmioXbar
157
158  val plic = LazyModule(new AXI4Plic(
159    Seq(AddressSet(0x3c000000L, 0x03ffffffL)),
160    sim = !env.FPGAPlatform
161  ))
162  val plicIdentity = AXI4IdentityNode()
163  plic.node := plicIdentity := AXI4UserYanker() := TLToAXI4() := mmioXbar
164
165  lazy val module = new LazyModuleImp(this){
166    val io = IO(new Bundle{
167      val extIntrs = Input(UInt(NrExtIntr.W))
168      // val meip = Input(Vec(NumCores, Bool()))
169      val ila = if(env.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None
170    })
171    val difftestIO0 = IO(new DifftestBundle())
172    val difftestIO1 = IO(new DifftestBundle())
173    val difftestIO = Seq(difftestIO0, difftestIO1)
174
175    val trapIO0 = IO(new xiangshan.TrapIO())
176    val trapIO1 = IO(new xiangshan.TrapIO())
177    val trapIO = Seq(trapIO0, trapIO1)
178
179    plic.module.io.extra.get.intrVec <> RegNext(RegNext(io.extIntrs))
180
181    for (i <- 0 until NumCores) {
182      xs_core(i).module.io.hartId := i.U
183      xs_core(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i)
184      xs_core(i).module.io.externalInterrupt.msip := clint.module.io.msip(i)
185      // xs_core(i).module.io.externalInterrupt.meip := RegNext(RegNext(io.meip(i)))
186      xs_core(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i)
187      l2prefetcher(i).module.io.enable := xs_core(i).module.io.l2_pf_enable
188    }
189    difftestIO0 <> xs_core(0).module.difftestIO
190    difftestIO1 <> DontCare
191    trapIO0 <> xs_core(0).module.trapIO
192    trapIO1 <> DontCare
193
194    if (env.DualCore) {
195      difftestIO1 <> xs_core(1).module.difftestIO
196      trapIO1 <> xs_core(1).module.trapIO
197    }
198    // do not let dma AXI signals optimized out
199    dontTouch(dma.out.head._1)
200    dontTouch(extDev.out.head._1)
201    dontTouch(io.extIntrs)
202  }
203
204}
205