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