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