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