xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision 8e03e0692d6147c75ee687a03e6d7de6e141937e)
1package xiangshan
2
3import chisel3._
4import chisel3.util._
5import top.Parameters
6import xiangshan.backend._
7import xiangshan.backend.dispatch.DispatchParameters
8import xiangshan.backend.exu.ExuParameters
9import xiangshan.frontend._
10import xiangshan.mem._
11import xiangshan.backend.fu.HasExceptionNO
12import xiangshan.cache.{ICache, DCache, L1plusCache, DCacheParameters, ICacheParameters, L1plusCacheParameters, PTW, Uncache}
13import chipsalliance.rocketchip.config
14import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, AddressSet}
15import freechips.rocketchip.tilelink.{TLBundleParameters, TLCacheCork, TLBuffer, TLClientNode, TLIdentityNode, TLXbar, TLWidthWidget, TLFilter, TLToAXI4}
16import freechips.rocketchip.devices.tilelink.{TLError, DevNullParams}
17import sifive.blocks.inclusivecache.{CacheParameters, InclusiveCache, InclusiveCacheMicroParameters}
18import freechips.rocketchip.amba.axi4.{AXI4ToTL, AXI4IdentityNode, AXI4UserYanker, AXI4Fragmenter, AXI4IdIndexer, AXI4Deinterleaver}
19import utils._
20
21case class XSCoreParameters
22(
23  XLEN: Int = 64,
24  HasMExtension: Boolean = true,
25  HasCExtension: Boolean = true,
26  HasDiv: Boolean = true,
27  HasICache: Boolean = true,
28  HasDCache: Boolean = true,
29  EnableStoreQueue: Boolean = true,
30  AddrBits: Int = 64,
31  VAddrBits: Int = 39,
32  PAddrBits: Int = 40,
33  HasFPU: Boolean = true,
34  FectchWidth: Int = 8,
35  EnableBPU: Boolean = true,
36  EnableBPD: Boolean = true,
37  EnableRAS: Boolean = true,
38  EnableLB: Boolean = true,
39  EnableLoop: Boolean = true,
40  HistoryLength: Int = 64,
41  BtbSize: Int = 2048,
42  JbtacSize: Int = 1024,
43  JbtacBanks: Int = 8,
44  RasSize: Int = 16,
45  CacheLineSize: Int = 512,
46  UBtbWays: Int = 16,
47  BtbWays: Int = 2,
48  IBufSize: Int = 64,
49  DecodeWidth: Int = 6,
50  RenameWidth: Int = 6,
51  CommitWidth: Int = 6,
52  BrqSize: Int = 12,
53  IssQueSize: Int = 8,
54  NRPhyRegs: Int = 128,
55  NRIntReadPorts: Int = 14,
56  NRIntWritePorts: Int = 8,
57  NRFpReadPorts: Int = 14,
58  NRFpWritePorts: Int = 8,
59  EnableUnifiedLSQ: Boolean = false,
60  LsroqSize: Int = 16,
61  LoadQueueSize: Int = 12,
62  StoreQueueSize: Int = 10,
63  RoqSize: Int = 32,
64  dpParams: DispatchParameters = DispatchParameters(
65    DqEnqWidth = 4,
66    IntDqSize = 24,
67    FpDqSize = 16,
68    LsDqSize = 16,
69    IntDqDeqWidth = 4,
70    FpDqDeqWidth = 4,
71    LsDqDeqWidth = 4,
72    IntDqReplayWidth = 4,
73    FpDqReplayWidth = 4,
74    LsDqReplayWidth = 4
75  ),
76  exuParameters: ExuParameters = ExuParameters(
77    JmpCnt = 1,
78    AluCnt = 4,
79    MulCnt = 0,
80    MduCnt = 2,
81    FmacCnt = 4,
82    FmiscCnt = 2,
83    FmiscDivSqrtCnt = 0,
84    LduCnt = 2,
85    StuCnt = 2
86  ),
87  LoadPipelineWidth: Int = 2,
88  StorePipelineWidth: Int = 2,
89  StoreBufferSize: Int = 16,
90  RefillSize: Int = 512,
91  TlbEntrySize: Int = 32,
92  TlbL2EntrySize: Int = 256, // or 512
93  PtwL1EntrySize: Int = 16,
94  PtwL2EntrySize: Int = 256,
95  NumPerfCounters: Int = 16
96)
97
98trait HasXSParameter {
99
100  val core = Parameters.get.coreParameters
101  val env = Parameters.get.envParameters
102
103  val XLEN = core.XLEN
104  val HasMExtension = core.HasMExtension
105  val HasCExtension = core.HasCExtension
106  val HasDiv = core.HasDiv
107  val HasIcache = core.HasICache
108  val HasDcache = core.HasDCache
109  val EnableStoreQueue = core.EnableStoreQueue
110  val AddrBits = core.AddrBits // AddrBits is used in some cases
111  val VAddrBits = core.VAddrBits // VAddrBits is Virtual Memory addr bits
112  val PAddrBits = core.PAddrBits // PAddrBits is Phyical Memory addr bits
113  val AddrBytes = AddrBits / 8 // unused
114  val DataBits = XLEN
115  val DataBytes = DataBits / 8
116  val HasFPU = core.HasFPU
117  val FetchWidth = core.FectchWidth
118  val PredictWidth = FetchWidth * 2
119  val EnableBPU = core.EnableBPU
120  val EnableBPD = core.EnableBPD // enable backing predictor(like Tage) in BPUStage3
121  val EnableRAS = core.EnableRAS
122  val EnableLB = core.EnableLB
123  val EnableLoop = core.EnableLoop
124  val HistoryLength = core.HistoryLength
125  val BtbSize = core.BtbSize
126  // val BtbWays = 4
127  val BtbBanks = PredictWidth
128  // val BtbSets = BtbSize / BtbWays
129  val JbtacSize = core.JbtacSize
130  val JbtacBanks = core.JbtacBanks
131  val RasSize = core.RasSize
132  val CacheLineSize = core.CacheLineSize
133  val CacheLineHalfWord = CacheLineSize / 16
134  val ExtHistoryLength = HistoryLength + 64
135  val UBtbWays = core.UBtbWays
136  val BtbWays = core.BtbWays
137  val IBufSize = core.IBufSize
138  val DecodeWidth = core.DecodeWidth
139  val RenameWidth = core.RenameWidth
140  val CommitWidth = core.CommitWidth
141  val BrqSize = core.BrqSize
142  val IssQueSize = core.IssQueSize
143  val BrTagWidth = log2Up(BrqSize)
144  val NRPhyRegs = core.NRPhyRegs
145  val PhyRegIdxWidth = log2Up(NRPhyRegs)
146  val RoqSize = core.RoqSize
147  val EnableUnifiedLSQ = core.EnableUnifiedLSQ
148  val LsroqSize = core.LsroqSize // 64
149  val InnerLsroqIdxWidth = log2Up(LsroqSize)
150  val LsroqIdxWidth = InnerLsroqIdxWidth + 1
151  val LoadQueueSize = core.LoadQueueSize
152  val StoreQueueSize = core.StoreQueueSize
153  val dpParams = core.dpParams
154  val ReplayWidth = dpParams.IntDqReplayWidth + dpParams.FpDqReplayWidth + dpParams.LsDqReplayWidth
155  val exuParameters = core.exuParameters
156  val NRIntReadPorts = core.NRIntReadPorts
157  val NRIntWritePorts = core.NRIntWritePorts
158  val NRMemReadPorts = exuParameters.LduCnt + 2*exuParameters.StuCnt
159  val NRFpReadPorts = core.NRFpReadPorts
160  val NRFpWritePorts = core.NRFpWritePorts
161  val LoadPipelineWidth = core.LoadPipelineWidth
162  val StorePipelineWidth = core.StorePipelineWidth
163  val StoreBufferSize = core.StoreBufferSize
164  val RefillSize = core.RefillSize
165  val DTLBWidth = core.LoadPipelineWidth + core.StorePipelineWidth
166  val TlbEntrySize = core.TlbEntrySize
167  val TlbL2EntrySize = core.TlbL2EntrySize
168  val PtwL1EntrySize = core.PtwL1EntrySize
169  val PtwL2EntrySize = core.PtwL2EntrySize
170  val NumPerfCounters = core.NumPerfCounters
171
172  val icacheParameters = ICacheParameters(
173    nMissEntries = 2
174  )
175
176  val l1plusCacheParameters = L1plusCacheParameters(
177    tagECC = Some("secded"),
178    dataECC = Some("secded"),
179    nMissEntries = 8
180  )
181
182  val dcacheParameters = DCacheParameters(
183    tagECC = Some("secded"),
184    dataECC = Some("secded"),
185    nMissEntries = 16,
186    nLoadMissEntries = 8,
187    nStoreMissEntries = 8
188  )
189
190  val LRSCCycles = 100
191
192
193  // cache hierarchy configurations
194  val l1BusDataWidth = 256
195
196  // L2 configurations
197  val L1BusWidth = 256
198  val L2Size = 512 * 1024 // 512KB
199  val L2BlockSize = 64
200  val L2NWays = 8
201  val L2NSets = L2Size / L2BlockSize / L2NWays
202
203  // L3 configurations
204  val L2BusWidth = 256
205  val L3Size = 4 * 1024 * 1024 // 4MB
206  val L3BlockSize = 64
207  val L3NBanks = 4
208  val L3NWays = 8
209  val L3NSets = L3Size / L3BlockSize / L3NBanks / L3NWays
210
211  // on chip network configurations
212  val L3BusWidth = 256
213}
214
215trait HasXSLog { this: RawModule =>
216  implicit val moduleName: String = this.name
217}
218
219abstract class XSModule extends MultiIOModule
220  with HasXSParameter
221  with HasExceptionNO
222  with HasXSLog
223{
224  def io: Record
225}
226
227//remove this trait after impl module logic
228trait NeedImpl { this: RawModule =>
229  override protected def IO[T <: Data](iodef: T): T = {
230    println(s"[Warn]: (${this.name}) please reomve 'NeedImpl' after implement this module")
231    val io = chisel3.experimental.IO(iodef)
232    io <> DontCare
233    io
234  }
235}
236
237abstract class XSBundle extends Bundle
238  with HasXSParameter
239
240case class EnviromentParameters
241(
242  FPGAPlatform: Boolean = true,
243  EnableDebug: Boolean = false
244)
245
246object AddressSpace extends HasXSParameter {
247  // (start, size)
248  // address out of MMIO will be considered as DRAM
249  def mmio = List(
250    (0x30000000L, 0x10000000L),  // internal devices, such as CLINT and PLIC
251    (0x40000000L, 0x40000000L) // external devices
252  )
253
254  def isMMIO(addr: UInt): Bool = mmio.map(range => {
255    require(isPow2(range._2))
256    val bits = log2Up(range._2)
257    (addr ^ range._1.U)(PAddrBits-1, bits) === 0.U
258  }).reduce(_ || _)
259}
260
261
262
263class XSCore()(implicit p: config.Parameters) extends LazyModule with HasXSParameter {
264
265  // inner nodes
266  val dcache = LazyModule(new DCache())
267  val uncache = LazyModule(new Uncache())
268  val l1pluscache = LazyModule(new L1plusCache())
269  val ptw = LazyModule(new PTW())
270
271  // out facing nodes
272  val mem = Seq.fill(L3NBanks)(AXI4IdentityNode())
273  val dma = AXI4IdentityNode()
274  val mmio = uncache.clientNode
275
276  // L1 to L2 network
277  // -------------------------------------------------
278  private val l2_xbar = TLXbar()
279
280  private val l2 = LazyModule(new InclusiveCache(
281    CacheParameters(
282      level = 2,
283      ways = L2NWays,
284      sets = L2NSets,
285      blockBytes = L2BlockSize,
286      beatBytes = L1BusWidth / 8, // beatBytes = l1BusDataWidth / 8
287      cacheName = s"L2"
288    ),
289    InclusiveCacheMicroParameters(
290      writeBytes = 8
291    )
292  ))
293
294  l2_xbar := TLBuffer() := DebugIdentityNode() := dcache.clientNode
295  l2_xbar := TLBuffer() := DebugIdentityNode() := l1pluscache.clientNode
296  l2_xbar := TLBuffer() := DebugIdentityNode() := ptw.node
297  l2.node := TLBuffer() := DebugIdentityNode() := l2_xbar
298
299
300  // L2 to L3 network
301  // -------------------------------------------------
302  private val l3_xbar = TLXbar()
303
304  private val l3_banks = (0 until L3NBanks) map (i =>
305      LazyModule(new InclusiveCache(
306        CacheParameters(
307          level = 3,
308          ways = L3NWays,
309          sets = L3NSets,
310          blockBytes = L3BlockSize,
311          beatBytes = L2BusWidth / 8,
312          cacheName = s"L3_$i"
313        ),
314      InclusiveCacheMicroParameters(
315        writeBytes = 8
316      )
317    )))
318
319  l3_xbar := TLBuffer() := DebugIdentityNode() := l2.node
320
321  // DMA should not go to MMIO
322  val mmioRange = AddressSet(base = 0x0000000000L, mask = 0x007fffffffL)
323  // AXI4ToTL needs a TLError device to route error requests,
324  // add one here to make it happy.
325  val tlErrorParams = DevNullParams(
326    address = Seq(mmioRange),
327    maxAtomic = 8,
328    maxTransfer = 64)
329  val tlError = LazyModule(new TLError(params = tlErrorParams, beatBytes = L2BusWidth / 8))
330  private val tlError_xbar = TLXbar()
331  tlError_xbar :=
332    AXI4ToTL() :=
333    AXI4UserYanker(Some(1)) :=
334    AXI4Fragmenter() :=
335    AXI4IdIndexer(1) :=
336    dma
337  tlError.node := tlError_xbar
338
339  l3_xbar :=
340    TLBuffer() :=
341    DebugIdentityNode() :=
342    tlError_xbar
343
344  def bankFilter(bank: Int) = AddressSet(
345    base = bank * L3BlockSize,
346    mask = ~BigInt((L3NBanks -1) * L3BlockSize))
347
348  for(i <- 0 until L3NBanks) {
349    val filter = TLFilter(TLFilter.mSelectIntersect(bankFilter(i)))
350    l3_banks(i).node := TLBuffer() := DebugIdentityNode() := filter := l3_xbar
351  }
352
353
354  // L3 to memory network
355  // -------------------------------------------------
356  private val memory_xbar = TLXbar()
357
358  for(i <- 0 until L3NBanks) {
359    mem(i) :=
360      AXI4UserYanker() :=
361      TLToAXI4() :=
362      TLWidthWidget(L3BusWidth / 8) :=
363      TLCacheCork() :=
364      DebugIdentityNode() :=
365      l3_banks(i).node
366  }
367
368  lazy val module = new XSCoreImp(this)
369}
370
371class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer) with HasXSParameter {
372  val io = IO(new Bundle {
373    val externalInterrupt = new ExternalInterruptIO
374  })
375
376  val front = Module(new Frontend)
377  val backend = Module(new Backend)
378  val mem = Module(new Memend)
379
380  val dcache = outer.dcache.module
381  val uncache = outer.uncache.module
382  val l1pluscache = outer.l1pluscache.module
383  val ptw = outer.ptw.module
384  val icache = Module(new ICache)
385
386  front.io.backend <> backend.io.frontend
387  front.io.icacheResp <> icache.io.resp
388  front.io.icacheToTlb <> icache.io.tlb
389  icache.io.req <> front.io.icacheReq
390  icache.io.flush <> front.io.icacheFlush
391
392  icache.io.mem_acquire <> l1pluscache.io.req
393  l1pluscache.io.resp <> icache.io.mem_grant
394  l1pluscache.io.flush := icache.io.l1plusflush
395  icache.io.fencei := backend.io.fencei
396
397  mem.io.backend   <> backend.io.mem
398  io.externalInterrupt <> backend.io.externalInterrupt
399
400  ptw.io.tlb(0) <> mem.io.ptw
401  ptw.io.tlb(1) <> front.io.ptw
402  ptw.io.sfence <> backend.io.mem.sfence//sfence
403  ptw.io.csr <> backend.io.tlbCsrIO
404
405  dcache.io.lsu.load    <> mem.io.loadUnitToDcacheVec
406  dcache.io.lsu.lsroq   <> mem.io.loadMiss
407  dcache.io.lsu.atomics <> mem.io.atomics
408  dcache.io.lsu.store   <> mem.io.sbufferToDcache
409  uncache.io.lsroq      <> mem.io.uncache
410
411}
412