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