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