xref: /XiangShan/src/main/scala/top/Top.scala (revision 2bd5334d599214aada6adb3b2be60148f5ec76cd)
1package top
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import utils._
7import system._
8import chisel3.stage.ChiselGeneratorAnnotation
9import chipsalliance.rocketchip.config._
10import device.{AXI4Plic, TLTimer}
11import freechips.rocketchip.diplomacy._
12import freechips.rocketchip.tilelink._
13import freechips.rocketchip.amba.axi4._
14import freechips.rocketchip.devices.tilelink.{DevNullParams, TLError}
15import freechips.rocketchip.diplomaticobjectmodel.logicaltree.GenericLogicalTreeNode
16import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkPortSimple}
17import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, XLen}
18import sifive.blocks.inclusivecache.{InclusiveCache, InclusiveCacheMicroParameters, CacheParameters}
19import xiangshan.cache.prefetch.L2Prefetcher
20
21
22class XSCoreWithL2()(implicit p: Parameters) extends LazyModule
23  with HasXSParameter with HasSoCParameter {
24  private val core = LazyModule(new XSCore())
25  private val l2prefetcher = LazyModule(new L2Prefetcher())
26  private val l2xbar = TLXbar()
27  private val l2cache = if (useFakeL2Cache) null else LazyModule(new InclusiveCache(
28    CacheParameters(
29      level = 2,
30      ways = L2NWays,
31      sets = L2NSets,
32      blockBytes = L2BlockSize,
33      beatBytes = L1BusWidth / 8, // beatBytes = l1BusDataWidth / 8
34      cacheName = s"L2",
35      uncachedGet = true,
36      enablePerf = false
37    ),
38    InclusiveCacheMicroParameters(
39      memCycles = 25,
40      writeBytes = 32
41    ),
42    fpga = debugOpts.FPGAPlatform
43  ))
44
45  val memory_port = TLIdentityNode()
46  val uncache = TLXbar()
47
48  if (!useFakeDCache) {
49    l2xbar := TLBuffer() := core.memBlock.dcache.clientNode
50  }
51  if (!useFakeL1plusCache) {
52    l2xbar := TLBuffer() := core.l1pluscache.clientNode
53  }
54  if (!useFakePTW) {
55    l2xbar := TLBuffer() := core.ptw.node
56  }
57  l2xbar := TLBuffer() := l2prefetcher.clientNode
58  if (useFakeL2Cache) {
59    memory_port := l2xbar
60  }
61  else {
62    l2cache.node := TLBuffer() := l2xbar
63    memory_port := l2cache.node
64  }
65
66  uncache := TLBuffer() := core.frontend.instrUncache.clientNode
67  uncache := TLBuffer() := core.memBlock.uncache.clientNode
68
69  lazy val module = new LazyModuleImp(this) {
70    val io = IO(new Bundle {
71      val hartId = Input(UInt(64.W))
72      val externalInterrupt = new ExternalInterruptIO
73      val l1plus_error, icache_error, dcache_error = new L1CacheErrorInfo
74    })
75
76    core.module.io.hartId := io.hartId
77    core.module.io.externalInterrupt := io.externalInterrupt
78    l2prefetcher.module.io.enable := core.module.io.l2_pf_enable
79    if (useFakeL2Cache) {
80      l2prefetcher.module.io.in := DontCare
81    }
82    else {
83      l2prefetcher.module.io.in <> l2cache.module.io
84    }
85    io.l1plus_error <> core.module.io.l1plus_error
86    io.icache_error <> core.module.io.icache_error
87    io.dcache_error <> core.module.io.dcache_error
88
89    val core_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
90    core.module.reset := core_reset_gen.io.out
91
92    val l2_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
93    l2prefetcher.module.reset := l2_reset_gen.io.out
94    if (!useFakeL2Cache) {
95      l2cache.module.reset := l2_reset_gen.io.out
96    }
97  }
98}
99
100abstract class BaseXSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
101  val bankedNode = BankBinder(L3NBanks, L3BlockSize)
102  val peripheralXbar = TLXbar()
103  val l3_xbar = TLXbar()
104}
105
106// We adapt the following three traits from rocket-chip.
107// Source: rocket-chip/src/main/scala/subsystem/Ports.scala
108trait HaveSlaveAXI4Port {
109  this: BaseXSSoc =>
110
111  val idBits = 16
112
113  val l3FrontendAXI4Node = AXI4MasterNode(Seq(AXI4MasterPortParameters(
114    Seq(AXI4MasterParameters(
115      name = "dma",
116      id = IdRange(0, 1 << idBits)
117    ))
118  )))
119  private val errorDevice = LazyModule(new TLError(
120    params = DevNullParams(
121      address = Seq(AddressSet(0x0, 0x7fffffffL)),
122      maxAtomic = 8,
123      maxTransfer = 64),
124    beatBytes = L3InnerBusWidth / 8
125  ))
126  private val error_xbar = TLXbar()
127
128  error_xbar :=
129    AXI4ToTL() :=
130    AXI4UserYanker(Some(1)) :=
131    AXI4Fragmenter() :=
132    AXI4IdIndexer(1) :=
133    l3FrontendAXI4Node
134  errorDevice.node := error_xbar
135  l3_xbar :=
136    TLBuffer() :=
137    error_xbar
138
139  val dma = InModuleBody {
140    l3FrontendAXI4Node.makeIOs()
141  }
142}
143
144trait HaveAXI4MemPort {
145  this: BaseXSSoc =>
146  // 40-bit physical address
147  val memRange = AddressSet(0x00000000L, 0xffffffffffL).subtract(AddressSet(0x0L, 0x7fffffffL))
148  val memAXI4SlaveNode = AXI4SlaveNode(Seq(
149    AXI4SlavePortParameters(
150      slaves = Seq(
151        AXI4SlaveParameters(
152          address = memRange,
153          regionType = RegionType.UNCACHED,
154          executable = true,
155          supportsRead = TransferSizes(1, L3BlockSize),
156          supportsWrite = TransferSizes(1, L3BlockSize),
157          interleavedId = Some(0)
158        )
159      ),
160      beatBytes = L3OuterBusWidth / 8
161    )
162  ))
163
164  val mem_xbar = TLXbar()
165  mem_xbar :=* TLBuffer() :=* TLCacheCork() :=* bankedNode
166  memAXI4SlaveNode :=
167    AXI4UserYanker() :=
168    AXI4Deinterleaver(L3BlockSize) :=
169    TLToAXI4() :=
170    TLWidthWidget(L3OuterBusWidth / 8) :=
171    mem_xbar
172
173  val memory = InModuleBody {
174    memAXI4SlaveNode.makeIOs()
175  }
176}
177
178
179trait HaveAXI4PeripheralPort { this: BaseXSSoc =>
180  // on-chip devices: 0x3800_000 - 0x3fff_ffff
181  val onChipPeripheralRange = AddressSet(0x38000000L, 0x07ffffffL)
182  val peripheralRange = AddressSet(0x0, 0x7fffffff).subtract(onChipPeripheralRange)
183  val peripheralNode = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
184    Seq(AXI4SlaveParameters(
185      address = peripheralRange,
186      regionType = RegionType.UNCACHED,
187      supportsRead = TransferSizes(1, 8),
188      supportsWrite = TransferSizes(1, 8),
189      interleavedId = Some(0)
190    )),
191    beatBytes = 8
192  )))
193
194  peripheralNode :=
195    AXI4UserYanker() :=
196    AXI4Deinterleaver(8) :=
197    TLToAXI4() :=
198    peripheralXbar
199
200  val peripheral = InModuleBody {
201    peripheralNode.makeIOs()
202  }
203
204}
205
206class XSTop()(implicit p: Parameters) extends XSTopWithoutDMA
207  with HaveSlaveAXI4Port
208
209class XSTopWithoutDMA()(implicit p: Parameters) extends BaseXSSoc()
210  with HaveAXI4MemPort
211  with HaveAXI4PeripheralPort
212{
213
214  println(s"FPGASoC cores: $NumCores banks: $L3NBanks block size: $L3BlockSize bus size: $L3OuterBusWidth")
215
216  val core_with_l2 = soc.cores.map(coreParams =>
217    LazyModule(new XSCoreWithL2()(p.alterPartial({
218      case XSCoreParamsKey => coreParams
219    })))
220  )
221
222  for (i <- 0 until NumCores) {
223    peripheralXbar := TLBuffer() := core_with_l2(i).uncache
224    l3_xbar := TLBuffer() := core_with_l2(i).memory_port
225  }
226
227  private val clint = LazyModule(new TLTimer(
228    Seq(AddressSet(0x38000000L, 0x0000ffffL)),
229    sim = !debugOpts.FPGAPlatform, NumCores
230  ))
231  clint.node := peripheralXbar
232
233  val fakeTreeNode = new GenericLogicalTreeNode
234  val beu = LazyModule(
235    new BusErrorUnit(new XSL1BusErrors(NumCores), BusErrorUnitParams(0x38010000), fakeTreeNode))
236  beu.node := peripheralXbar
237
238  class BeuSinkNode()(implicit p: Parameters) extends LazyModule {
239    val intSinkNode = IntSinkNode(IntSinkPortSimple())
240    lazy val module = new LazyModuleImp(this){
241      val interrupt = IO(Output(Bool()))
242      interrupt := intSinkNode.in.head._1.head
243    }
244  }
245  val beuSink = LazyModule(new BeuSinkNode())
246  beuSink.intSinkNode := beu.intNode
247
248  val plic = LazyModule(new AXI4Plic(
249    Seq(AddressSet(0x3c000000L, 0x03ffffffL)),
250    NumCores, NrExtIntr + 1,
251    !debugOpts.FPGAPlatform,
252  ))
253  plic.node := AXI4IdentityNode() := AXI4UserYanker() := TLToAXI4() := peripheralXbar
254
255  val l3cache = if (useFakeL3Cache) null else LazyModule(new InclusiveCache(
256    CacheParameters(
257      level = 3,
258      ways = L3NWays,
259      sets = L3NSets,
260      blockBytes = L3BlockSize,
261      beatBytes = L3InnerBusWidth / 8,
262      cacheName = "L3",
263      uncachedGet = false,
264      enablePerf = false
265    ),
266    InclusiveCacheMicroParameters(
267      memCycles = 25,
268      writeBytes = 32
269    ),
270    fpga = debugOpts.FPGAPlatform
271  ))
272  val l3Ignore = if (useFakeL3Cache) TLIgnoreNode() else null
273
274  if (useFakeL3Cache) {
275    bankedNode :*= l3Ignore :*= l3_xbar
276  }
277  else {
278    bankedNode :*= l3cache.node :*= TLBuffer() :*= l3_xbar
279  }
280
281  lazy val module = new LazyRawModuleImp(this) {
282    val io = IO(new Bundle {
283      val clock = Input(Bool())
284      val reset = Input(Bool())
285      val extIntrs = Input(UInt(NrExtIntr.W))
286      // val meip = Input(Vec(NumCores, Bool()))
287      val ila = if(debugOpts.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None
288    })
289    childClock := io.clock.asClock()
290
291    withClockAndReset(childClock, io.reset) {
292      val resetGen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
293      resetGen.suggestName("top_reset_gen")
294      childReset := resetGen.io.out
295    }
296
297    withClockAndReset(childClock, childReset) {
298      plic.module.io.extra.get.intrVec <> Cat(beuSink.module.interrupt, io.extIntrs)
299
300      for (i <- 0 until NumCores) {
301        val core_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
302        core_reset_gen.suggestName(s"core_${i}_reset_gen")
303        core_with_l2(i).module.reset := core_reset_gen.io.out
304        core_with_l2(i).module.io.hartId := i.U
305        core_with_l2(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i)
306        core_with_l2(i).module.io.externalInterrupt.msip := clint.module.io.msip(i)
307        core_with_l2(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i)
308        beu.module.io.errors.l1plus(i) := core_with_l2(i).module.io.l1plus_error
309        beu.module.io.errors.icache(i) := core_with_l2(i).module.io.icache_error
310        beu.module.io.errors.dcache(i) := core_with_l2(i).module.io.dcache_error
311      }
312
313      if (!useFakeL3Cache) {
314        val l3_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
315        l3_reset_gen.suggestName("l3_reset_gen")
316        l3cache.module.reset := l3_reset_gen.io.out
317      }
318    }
319  }
320}
321
322object TopMain extends App {
323  override def main(args: Array[String]): Unit = {
324    val (config, firrtlOpts) = ArgParser.parse(args)
325    XiangShanStage.execute(firrtlOpts, Seq(
326      ChiselGeneratorAnnotation(() => {
327        val soc = LazyModule(new XSTop()(config))
328        soc.module
329      })
330    ))
331  }
332}
333