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