xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision f57f7f2aa52bf8c9d7952402ff7d36066bf8e1b3)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan
18
19import org.chipsalliance.cde.config
20import org.chipsalliance.cde.config.Parameters
21import chisel3._
22import chisel3.util._
23import freechips.rocketchip.diplomacy.{BundleBridgeSource, LazyModule, LazyModuleImp}
24import freechips.rocketchip.tile.HasFPUParameters
25import system.HasSoCParameter
26import utils._
27import utility._
28import xiangshan.backend._
29import xiangshan.backend.exu.{ExuConfig, Wb2Ctrl, WbArbiterWrapper}
30import xiangshan.frontend._
31import xiangshan.mem.L1PrefetchFuzzer
32
33import scala.collection.mutable.ListBuffer
34
35abstract class XSModule(implicit val p: Parameters) extends Module
36  with HasXSParameter
37  with HasFPUParameters
38
39//remove this trait after impl module logic
40trait NeedImpl {
41  this: RawModule =>
42  protected def IO[T <: Data](iodef: T): T = {
43    println(s"[Warn]: (${this.name}) please reomve 'NeedImpl' after implement this module")
44    val io = chisel3.IO(iodef)
45    io <> DontCare
46    io
47  }
48}
49
50class WritebackSourceParams(
51  var exuConfigs: Seq[Seq[ExuConfig]] = Seq()
52 ) {
53  def length: Int = exuConfigs.length
54  def ++(that: WritebackSourceParams): WritebackSourceParams = {
55    new WritebackSourceParams(exuConfigs ++ that.exuConfigs)
56  }
57}
58
59trait HasWritebackSource {
60  val writebackSourceParams: Seq[WritebackSourceParams]
61  final def writebackSource(sourceMod: HasWritebackSourceImp): Seq[Seq[Valid[ExuOutput]]] = {
62    require(sourceMod.writebackSource.isDefined, "should not use Valid[ExuOutput]")
63    val source = sourceMod.writebackSource.get
64    require(source.length == writebackSourceParams.length, "length mismatch between sources")
65    for ((s, p) <- source.zip(writebackSourceParams)) {
66      require(s.length == p.length, "params do not match with the exuOutput")
67    }
68    source
69  }
70  final def writebackSource1(sourceMod: HasWritebackSourceImp): Seq[Seq[DecoupledIO[ExuOutput]]] = {
71    require(sourceMod.writebackSource1.isDefined, "should not use DecoupledIO[ExuOutput]")
72    val source = sourceMod.writebackSource1.get
73    require(source.length == writebackSourceParams.length, "length mismatch between sources")
74    for ((s, p) <- source.zip(writebackSourceParams)) {
75      require(s.length == p.length, "params do not match with the exuOutput")
76    }
77    source
78  }
79  val writebackSourceImp: HasWritebackSourceImp
80}
81
82trait HasWritebackSourceImp {
83  def writebackSource: Option[Seq[Seq[Valid[ExuOutput]]]] = None
84  def writebackSource1: Option[Seq[Seq[DecoupledIO[ExuOutput]]]] = None
85}
86
87trait HasWritebackSink {
88  // Caches all sources. The selected source will be the one with smallest length.
89  var writebackSinks = ListBuffer.empty[(Seq[HasWritebackSource], Seq[Int])]
90  def addWritebackSink(source: Seq[HasWritebackSource], index: Option[Seq[Int]] = None): HasWritebackSink = {
91    val realIndex = if (index.isDefined) index.get else Seq.fill(source.length)(0)
92    writebackSinks += ((source, realIndex))
93    this
94  }
95
96  def writebackSinksParams: Seq[WritebackSourceParams] = {
97    writebackSinks.map{ case (s, i) => s.zip(i).map(x => x._1.writebackSourceParams(x._2)).reduce(_ ++ _) }.toSeq
98  }
99  final def writebackSinksMod(
100     thisMod: Option[HasWritebackSource] = None,
101     thisModImp: Option[HasWritebackSourceImp] = None
102   ): Seq[Seq[HasWritebackSourceImp]] = {
103    require(thisMod.isDefined == thisModImp.isDefined)
104    writebackSinks.map(_._1.map(source =>
105      if (thisMod.isDefined && source == thisMod.get) thisModImp.get else source.writebackSourceImp)
106    ).toSeq
107  }
108  final def writebackSinksImp(
109    thisMod: Option[HasWritebackSource] = None,
110    thisModImp: Option[HasWritebackSourceImp] = None
111  ): Seq[Seq[ValidIO[ExuOutput]]] = {
112    val sourceMod = writebackSinksMod(thisMod, thisModImp)
113    writebackSinks.zip(sourceMod).map{ case ((s, i), m) =>
114      s.zip(i).zip(m).flatMap(x => x._1._1.writebackSource(x._2)(x._1._2))
115    }.toSeq
116  }
117  def selWritebackSinks(func: WritebackSourceParams => Int): Int = {
118    writebackSinksParams.zipWithIndex.minBy(params => func(params._1))._2
119  }
120  def generateWritebackIO(
121    thisMod: Option[HasWritebackSource] = None,
122    thisModImp: Option[HasWritebackSourceImp] = None
123   ): Unit
124}
125
126abstract class XSBundle(implicit val p: Parameters) extends Bundle
127  with HasXSParameter
128
129abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule
130  with HasXSParameter with HasExuWbHelper
131{
132  override def shouldBeInlined: Boolean = false
133  // outer facing nodes
134  val frontend = LazyModule(new Frontend())
135  val csrOut = BundleBridgeSource(Some(() => new DistributedCSRIO()))
136
137  val memBlock = LazyModule(new MemBlock()(p.alter((site, here, up) => {
138    case XSCoreParamsKey => up(XSCoreParamsKey).copy(
139      IssQueSize = IssQueSize * (if (Enable3Load3Store) 3 else 2) // exuBlocks.head.scheduler.getMemRsEntries
140    )
141  })))
142
143  val backend = LazyModule(new Backend(memBlock)(p))
144
145  memBlock.frontendBridge.icache_node := frontend.icache.clientNode
146  memBlock.frontendBridge.instr_uncache_node := frontend.instrUncache.clientNode
147}
148
149class XSCore()(implicit p: config.Parameters) extends XSCoreBase
150  with HasXSDts
151{
152  lazy val module = new XSCoreImp(this)
153}
154
155class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer)
156  with HasXSParameter
157  with HasSoCParameter {
158  val io = IO(new Bundle {
159    val hartId = Input(UInt(hartIdLen.W))
160    val reset_vector = Input(UInt(PAddrBits.W))
161    val cpu_halt = Output(Bool())
162    val l2_pf_enable = Output(Bool())
163    val perfEvents = Input(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent))
164    val beu_errors = Output(new XSL1BusErrors())
165    val l2_hint = Input(Valid(new L2ToL1Hint()))
166    val l2PfqBusy = Input(Bool())
167    val debugTopDown = new Bundle {
168      val robHeadPaddr = Valid(UInt(PAddrBits.W))
169      val l2MissMatch = Input(Bool())
170      val l3MissMatch = Input(Bool())
171    }
172  })
173
174  println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}")
175
176  private val frontend = outer.frontend.module
177  private val backend = outer.backend.module
178  private val memBlock = outer.memBlock.module
179
180  frontend.io.hartId  := memBlock.io.inner_hartId
181  backend.io.hartId := memBlock.io.inner_hartId
182  memBlock.io.hartId := io.hartId
183  memBlock.io.outer_reset_vector := io.reset_vector
184  frontend.io.reset_vector := memBlock.io.inner_reset_vector
185
186  memBlock.io.inner_cpu_halt := backend.io.cpu_halt
187  io.cpu_halt := memBlock.io.outer_cpu_halt
188
189  backend.io.memBlock.writeback <> memBlock.io.mem_to_ooo.writeback
190
191  // memblock error exception writeback, 1 cycle after normal writeback
192  backend.io.memBlock.s3_delayed_load_error <> memBlock.io.s3_delayed_load_error
193
194  memBlock.io.inner_beu_errors_icache <> frontend.io.error.toL1BusErrorUnitInfo()
195  io.beu_errors.icache <> memBlock.io.outer_beu_errors_icache
196  io.beu_errors.dcache <> memBlock.io.error.toL1BusErrorUnitInfo()
197  io.beu_errors.l2 <> DontCare
198
199  frontend.io.backend <> backend.io.frontend.frontend2Ctrl
200  frontend.io.sfence <> backend.io.frontend.sfence
201  frontend.io.tlbCsr <> backend.io.frontend.tlbCsr
202  frontend.io.csrCtrl <> backend.io.frontend.csrCtrl
203  frontend.io.fencei := backend.io.frontend.fencei
204
205  backend.io.memBlock.stIn <> memBlock.io.mem_to_ooo.stIn
206  backend.io.memBlock.memoryViolation <> memBlock.io.mem_to_ooo.memoryViolation
207  backend.io.memBlock.enqLsq <> memBlock.io.ooo_to_mem.enqLsq
208  backend.io.memBlock.lcommit := memBlock.io.mem_to_ooo.lqDeq
209  backend.io.memBlock.scommit := memBlock.io.mem_to_ooo.sqDeq
210  backend.io.memBlock.lqCancelCnt := memBlock.io.mem_to_ooo.lqCancelCnt
211  backend.io.memBlock.sqCancelCnt := memBlock.io.mem_to_ooo.sqCancelCnt
212  backend.io.memBlock.otherFastWakeup <> memBlock.io.mem_to_ooo.otherFastWakeup
213  backend.io.memBlock.stIssuePtr := memBlock.io.mem_to_ooo.stIssuePtr
214
215  memBlock.io.ooo_to_mem.issue <> backend.io.memBlock.issue
216  memBlock.io.ooo_to_mem.loadFastMatch <> backend.io.memBlock.loadFastMatch
217  memBlock.io.ooo_to_mem.loadFastFuOpType <> backend.io.memBlock.loadFastFuOpType
218  memBlock.io.ooo_to_mem.loadFastImm <> backend.io.memBlock.loadFastImm
219  memBlock.io.ooo_to_mem.loadPc <> backend.io.memBlock.loadPc
220  memBlock.io.ooo_to_mem.storePc <> backend.io.memBlock.storePc
221
222  backend.io.perf <> DontCare
223  backend.io.perf.memInfo <> memBlock.io.memInfo
224  backend.io.perf.frontendInfo <> frontend.io.frontendInfo
225
226  backend.io.externalInterrupt := memBlock.io.externalInterrupt
227
228  backend.io.distributedUpdate(0).w.valid := memBlock.io.mem_to_ooo.csrUpdate.w.valid
229  backend.io.distributedUpdate(0).w.bits := memBlock.io.mem_to_ooo.csrUpdate.w.bits
230  backend.io.distributedUpdate(1).w.valid := frontend.io.csrUpdate.w.valid
231  backend.io.distributedUpdate(1).w.bits := frontend.io.csrUpdate.w.bits
232
233  backend.io.memBlock.sfence <> memBlock.io.ooo_to_mem.sfence
234  memBlock.io.fetch_to_mem.itlb <> frontend.io.ptw
235  memBlock.io.ooo_to_mem.flushSb := backend.io.memBlock.fenceToSbuffer.flushSb
236  backend.io.memBlock.fenceToSbuffer.sbIsEmpty := memBlock.io.mem_to_ooo.sbIsEmpty
237
238  memBlock.io.redirect <> backend.io.memBlock.redirect
239  memBlock.io.rsfeedback <> backend.io.memBlock.rsfeedback
240  memBlock.io.ooo_to_mem.csrCtrl <> backend.io.memBlock.csrCtrl
241  memBlock.io.ooo_to_mem.tlbCsr <> backend.io.memBlock.tlbCsr
242
243  memBlock.io.ooo_to_mem.lsqio.lcommit    := backend.io.memBlock.lsqio.rob.lcommit
244  memBlock.io.ooo_to_mem.lsqio.scommit    := backend.io.memBlock.lsqio.rob.scommit
245  memBlock.io.ooo_to_mem.lsqio.pendingld  := backend.io.memBlock.lsqio.rob.pendingld
246  memBlock.io.ooo_to_mem.lsqio.pendingst  := backend.io.memBlock.lsqio.rob.pendingst
247  memBlock.io.ooo_to_mem.lsqio.commit     := backend.io.memBlock.lsqio.rob.commit
248  memBlock.io.ooo_to_mem.lsqio.pendingPtr := backend.io.memBlock.lsqio.rob.pendingPtr
249
250  backend.io.memBlock.lsqio.exceptionAddr.vaddr := memBlock.io.mem_to_ooo.lsqio.vaddr
251  backend.io.memBlock.lsqio.rob.mmio      := memBlock.io.mem_to_ooo.lsqio.mmio
252  backend.io.memBlock.lsqio.rob.uop       := memBlock.io.mem_to_ooo.lsqio.uop
253  backend.io.memBlock.lsqio.lqCanAccept   := memBlock.io.mem_to_ooo.lsqio.lqCanAccept
254  backend.io.memBlock.lsqio.sqCanAccept   := memBlock.io.mem_to_ooo.lsqio.sqCanAccept
255
256  memBlock.io.ooo_to_mem.isStore := backend.io.memBlock.lsqio.exceptionAddr.isStore
257  memBlock.io.debug_ls <> backend.io.memBlock.debug_ls
258  memBlock.io.mem_to_ooo.lsTopdownInfo <> backend.io.memBlock.lsTopdownInfo
259
260  memBlock.io.l2_hint.valid := io.l2_hint.valid
261  memBlock.io.l2_hint.bits.sourceId := io.l2_hint.bits.sourceId
262  memBlock.io.l2_hint.bits.isKeyword := io.l2_hint.bits.isKeyword
263  memBlock.io.l2PfqBusy := io.l2PfqBusy
264  memBlock.io.int2vlsu <> DontCare
265  memBlock.io.vec2vlsu <> DontCare
266  memBlock.io.vlsu2vec <> DontCare
267  memBlock.io.vlsu2int <> DontCare
268  memBlock.io.vlsu2ctrl <> DontCare
269
270  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
271  memBlock.io.inner_l2_pf_enable := backend.io.l2_pf_enable
272  io.l2_pf_enable := memBlock.io.outer_l2_pf_enable
273
274  // top-down info
275  memBlock.io.debugTopDown.robHeadVaddr := backend.io.debugTopDown.fromRob.robHeadVaddr
276  frontend.io.debugTopDown.robHeadVaddr := backend.io.debugTopDown.fromRob.robHeadVaddr
277  io.debugTopDown.robHeadPaddr := backend.io.debugTopDown.fromRob.robHeadPaddr
278  backend.io.debugTopDown.fromCore.l2MissMatch := io.debugTopDown.l2MissMatch
279  backend.io.debugTopDown.fromCore.l3MissMatch := io.debugTopDown.l3MissMatch
280  backend.io.debugTopDown.fromCore.fromMem := memBlock.io.debugTopDown.toCore
281  memBlock.io.debugRolling := backend.io.debugRolling
282
283  // Modules are reset one by one
284  // val resetTree = ResetGenNode(
285  //   Seq(
286  //     ModuleNode(memBlock),
287  //     ResetGenNode(Seq(
288  //       ModuleNode(exuBlocks.head),
289  //       ResetGenNode(
290  //         exuBlocks.tail.map(m => ModuleNode(m)) :+ ModuleNode(outer.wbArbiter.module)
291  //       ),
292  //       ResetGenNode(Seq(
293  //         ModuleNode(ctrlBlock),
294  //         ResetGenNode(Seq(
295  //           ModuleNode(frontend)
296  //         ))
297  //       ))
298  //     ))
299  //   )
300  // )
301
302  // ResetGen(resetTree, reset, !debugOpts.FPGAPlatform)
303  if (debugOpts.FPGAPlatform) {
304    frontend.reset := memBlock.reset_io_frontend
305    backend.reset := memBlock.reset_io_backend
306  }
307
308}
309