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