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