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