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