xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision a3e876088a970fa1ef84da031edd9363593d0e9f)
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 chisel3._
20import chisel3.util._
21import xiangshan.backend._
22import xiangshan.backend.fu.HasExceptionNO
23import xiangshan.backend.exu.Wb
24import xiangshan.frontend._
25import xiangshan.cache.mmu._
26import xiangshan.cache.L1plusCacheWrapper
27import chipsalliance.rocketchip.config
28import chipsalliance.rocketchip.config.Parameters
29import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
30import freechips.rocketchip.tile.HasFPUParameters
31import system.{HasSoCParameter, L1CacheErrorInfo, SoCParamsKey}
32import utils._
33
34abstract class XSModule(implicit val p: Parameters) extends MultiIOModule
35  with HasXSParameter
36  with HasExceptionNO
37  with HasFPUParameters {
38  def io: Record
39}
40
41//remove this trait after impl module logic
42trait NeedImpl {
43  this: RawModule =>
44  override protected def IO[T <: Data](iodef: T): T = {
45    println(s"[Warn]: (${this.name}) please reomve 'NeedImpl' after implement this module")
46    val io = chisel3.experimental.IO(iodef)
47    io <> DontCare
48    io
49  }
50}
51
52abstract class XSBundle(implicit val p: Parameters) extends Bundle
53  with HasXSParameter
54
55case class EnviromentParameters
56(
57  FPGAPlatform: Boolean = true,
58  EnableDebug: Boolean = false,
59  EnablePerfDebug: Boolean = true,
60  DualCore: Boolean = false
61)
62
63abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule
64  with HasXSParameter
65{
66  // outer facing nodes
67  val frontend = LazyModule(new Frontend())
68  val l1pluscache = LazyModule(new L1plusCacheWrapper())
69  val ptw = LazyModule(new PTWWrapper())
70
71
72  // TODO: better RS organization
73  // generate rs according to number of function units
74  require(exuParameters.JmpCnt == 1)
75  require(exuParameters.MduCnt <= exuParameters.AluCnt && exuParameters.MduCnt > 0)
76  require(exuParameters.FmiscCnt <= exuParameters.FmacCnt && exuParameters.FmiscCnt > 0)
77  require(exuParameters.LduCnt == 2 && exuParameters.StuCnt == 2)
78  // one RS every 2 MDUs
79  val schedulePorts = Seq(
80    // exuCfg, numDeq, intFastWakeupTarget, fpFastWakeupTarget
81    (AluExeUnitCfg, exuParameters.AluCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg, JumpExeUnitCfg, LdExeUnitCfg, StExeUnitCfg), Seq()),
82    (MulDivExeUnitCfg, exuParameters.MduCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg, JumpExeUnitCfg, LdExeUnitCfg, StExeUnitCfg), Seq()),
83    (JumpExeUnitCfg, 1, Seq(), Seq()),
84    (FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)),
85    (FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)),
86    (LdExeUnitCfg, exuParameters.LduCnt, Seq(AluExeUnitCfg, LdExeUnitCfg), Seq()),
87    (StExeUnitCfg, exuParameters.StuCnt, Seq(), Seq())
88  )
89  // allow mdu and fmisc to have 2*numDeq enqueue ports
90  val intDpPorts = (0 until exuParameters.AluCnt).map(i => {
91    if (i < exuParameters.JmpCnt) Seq((0, i), (1, i), (2, i))
92    else if (i < 2*exuParameters.MduCnt) Seq((0, i), (1, i))
93    else Seq((0, i))
94  })
95  val fpDpPorts = (0 until exuParameters.FmacCnt).map(i => {
96    if (i < 2*exuParameters.FmiscCnt) Seq((3, i), (4, i))
97    else Seq((4, i))
98  })
99  val lsDpPorts = Seq(
100    Seq((5, 0)),
101    Seq((5, 1)),
102    Seq((6, 0)),
103    Seq((6, 1))
104  )
105  val dispatchPorts = intDpPorts ++ fpDpPorts ++ lsDpPorts
106
107  val mappedSchedulePorts = schedulePorts.map(port => {
108    val intWakeup = port._3.flatMap(cfg => schedulePorts.zipWithIndex.filter(_._1._1 == cfg).map(_._2))
109    val fpWakeup = port._4.flatMap(cfg => schedulePorts.zipWithIndex.filter(_._1._1 == cfg).map(_._2))
110    (port._1, port._2, intWakeup, fpWakeup)
111  })
112
113  val scheduler = LazyModule(new Scheduler(mappedSchedulePorts, dispatchPorts))
114
115  val memBlock = LazyModule(new MemBlock()(p.alter((site, here, up) => {
116    case XSCoreParamsKey => up(XSCoreParamsKey).copy(
117      IssQueSize = scheduler.memRsEntries.max
118    )
119  })))
120}
121
122class XSCore()(implicit p: config.Parameters) extends XSCoreBase
123  with HasXSDts
124{
125  lazy val module = new XSCoreImp(this)
126}
127
128class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer)
129  with HasXSParameter
130  with HasSoCParameter
131  with HasExeBlockHelper {
132  val io = IO(new Bundle {
133    val hartId = Input(UInt(64.W))
134    val externalInterrupt = new ExternalInterruptIO
135    val l2_pf_enable = Output(Bool())
136    val l1plus_error, icache_error, dcache_error = Output(new L1CacheErrorInfo)
137  })
138
139  println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}")
140  AddressSpace.checkMemmap()
141  AddressSpace.printMemmap()
142
143  // to fast wake up fp, mem rs
144  val intBlockFastWakeUp = intExuConfigs.filter(_.hasCertainLatency)
145  val intBlockSlowWakeUp = intExuConfigs.filter(_.hasUncertainlatency)
146
147  val ctrlBlock = Module(new CtrlBlock)
148
149  val integerBlock = Module(new IntegerBlock)
150  val floatBlock = Module(new FloatBlock)
151
152  val frontend = outer.frontend.module
153  val memBlock = outer.memBlock.module
154  val l1pluscache = outer.l1pluscache.module
155  val ptw = outer.ptw.module
156  val scheduler = outer.scheduler.module
157
158  val allWriteback = integerBlock.io.writeback ++ floatBlock.io.writeback ++ memBlock.io.writeback
159  val intConfigs = exuConfigs.filter(_.writeIntRf)
160  val intArbiter = Module(new Wb(intConfigs, NRIntWritePorts, isFp = false))
161  val intWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeIntRf).map(_._1)
162  // set default value for ready
163  integerBlock.io.writeback.map(_.ready := true.B)
164  floatBlock.io.writeback.map(_.ready := true.B)
165  memBlock.io.writeback.map(_.ready := true.B)
166  intArbiter.io.in.zip(intWriteback).foreach { case (arb, wb) =>
167    arb.valid := wb.valid && !wb.bits.uop.ctrl.fpWen
168    arb.bits := wb.bits
169    when (arb.valid) {
170      wb.ready := arb.ready
171    }
172  }
173
174  val fpArbiter = Module(new Wb(exuConfigs.filter(_.writeFpRf), NRFpWritePorts, isFp = true))
175  val fpWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeFpRf).map(_._1)
176  fpArbiter.io.in.zip(fpWriteback).foreach{ case (arb, wb) =>
177    arb.valid := wb.valid && wb.bits.uop.ctrl.fpWen
178    arb.bits := wb.bits
179    when (arb.valid) {
180      wb.ready := arb.ready
181    }
182  }
183
184  io.l1plus_error <> l1pluscache.io.error
185  io.icache_error <> frontend.io.error
186  io.dcache_error <> memBlock.io.error
187
188  frontend.io.backend <> ctrlBlock.io.frontend
189  frontend.io.sfence <> integerBlock.io.fenceio.sfence
190  frontend.io.tlbCsr <> integerBlock.io.csrio.tlb
191  frontend.io.csrCtrl <> integerBlock.io.csrio.customCtrl
192
193  frontend.io.icacheMemAcq <> l1pluscache.io.req
194  l1pluscache.io.resp <> frontend.io.icacheMemGrant
195  l1pluscache.io.flush := frontend.io.l1plusFlush
196  frontend.io.fencei := integerBlock.io.fenceio.fencei
197
198  ctrlBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl
199  ctrlBlock.io.exuRedirect <> integerBlock.io.exuRedirect
200  ctrlBlock.io.stIn <> memBlock.io.stIn
201  ctrlBlock.io.stOut <> memBlock.io.stOut
202  ctrlBlock.io.memoryViolation <> memBlock.io.memoryViolation
203  ctrlBlock.io.enqLsq <> memBlock.io.enqLsq
204  ctrlBlock.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out)
205
206  scheduler.io.redirect <> ctrlBlock.io.redirect
207  scheduler.io.flush <> ctrlBlock.io.flush
208  scheduler.io.allocate <> ctrlBlock.io.enqIQ
209  scheduler.io.issue <> integerBlock.io.issue ++ floatBlock.io.issue ++ memBlock.io.issue
210  scheduler.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out)
211
212  scheduler.io.replay <> memBlock.io.replay
213  scheduler.io.rsIdx <> memBlock.io.rsIdx
214  println(s"${scheduler.io.rsIdx(0).getWidth}, ${memBlock.io.rsIdx(0).getWidth}")
215  require(scheduler.io.rsIdx(0).getWidth == memBlock.io.rsIdx(0).getWidth)
216  scheduler.io.isFirstIssue <> memBlock.io.isFirstIssue
217  scheduler.io.stData <> memBlock.io.stData
218  scheduler.io.otherFastWakeup <> memBlock.io.otherFastWakeup
219  scheduler.io.jumpPc <> ctrlBlock.io.jumpPc
220  scheduler.io.jalr_target <> ctrlBlock.io.jalr_target
221  scheduler.io.stIssuePtr <> memBlock.io.stIssuePtr
222  scheduler.io.debug_fp_rat <> ctrlBlock.io.debug_fp_rat
223  scheduler.io.debug_int_rat <> ctrlBlock.io.debug_int_rat
224  scheduler.io.readIntRf <> ctrlBlock.io.readIntRf
225  scheduler.io.readFpRf <> ctrlBlock.io.readFpRf
226
227  integerBlock.io.redirect <> ctrlBlock.io.redirect
228  integerBlock.io.flush <> ctrlBlock.io.flush
229  integerBlock.io.csrio.hartId <> io.hartId
230  integerBlock.io.csrio.perf <> DontCare
231  integerBlock.io.csrio.perf.retiredInstr <> ctrlBlock.io.roqio.toCSR.perfinfo.retiredInstr
232  integerBlock.io.csrio.perf.bpuInfo <> ctrlBlock.io.perfInfo.bpuInfo
233  integerBlock.io.csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
234  integerBlock.io.csrio.perf.memInfo <> memBlock.io.memInfo
235  integerBlock.io.csrio.perf.frontendInfo <> frontend.io.frontendInfo
236
237  integerBlock.io.csrio.fpu.fflags <> ctrlBlock.io.roqio.toCSR.fflags
238  integerBlock.io.csrio.fpu.isIllegal := false.B
239  integerBlock.io.csrio.fpu.dirty_fs <> ctrlBlock.io.roqio.toCSR.dirty_fs
240  integerBlock.io.csrio.fpu.frm <> floatBlock.io.frm
241  integerBlock.io.csrio.exception <> ctrlBlock.io.roqio.exception
242  integerBlock.io.csrio.isXRet <> ctrlBlock.io.roqio.toCSR.isXRet
243  integerBlock.io.csrio.trapTarget <> ctrlBlock.io.roqio.toCSR.trapTarget
244  integerBlock.io.csrio.interrupt <> ctrlBlock.io.roqio.toCSR.intrBitSet
245  integerBlock.io.csrio.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr
246  integerBlock.io.csrio.externalInterrupt <> io.externalInterrupt
247
248  floatBlock.io.redirect <> ctrlBlock.io.redirect
249  floatBlock.io.flush <> ctrlBlock.io.flush
250
251  integerBlock.io.fenceio.sfence <> memBlock.io.sfence
252  integerBlock.io.fenceio.sbuffer <> memBlock.io.fenceToSbuffer
253
254  memBlock.io.redirect <> ctrlBlock.io.redirect
255  memBlock.io.flush <> ctrlBlock.io.flush
256  memBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl
257  memBlock.io.tlbCsr <> integerBlock.io.csrio.tlb
258  memBlock.io.lsqio.roq <> ctrlBlock.io.roqio.lsq
259  memBlock.io.lsqio.exceptionAddr.lsIdx.lqIdx := ctrlBlock.io.roqio.exception.bits.uop.lqIdx
260  memBlock.io.lsqio.exceptionAddr.lsIdx.sqIdx := ctrlBlock.io.roqio.exception.bits.uop.sqIdx
261  memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.roqio.exception.bits.uop.ctrl.commitType)
262
263  val itlbRepeater = Module(new PTWRepeater())
264  val dtlbRepeater = if (usePTWRepeater) {
265    Module(new PTWRepeater(LoadPipelineWidth + StorePipelineWidth))
266  } else {
267    Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, PtwMissQueueSize))
268  }
269  itlbRepeater.io.tlb <> frontend.io.ptw
270  dtlbRepeater.io.tlb <> memBlock.io.ptw
271  itlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence
272  dtlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence
273  ptw.io.tlb(0) <> itlbRepeater.io.ptw
274  ptw.io.tlb(1) <> dtlbRepeater.io.ptw
275  ptw.io.sfence <> integerBlock.io.fenceio.sfence
276  ptw.io.csr <> integerBlock.io.csrio.tlb
277
278  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
279  assert(l2PrefetcherParameters._type == "bop")
280  io.l2_pf_enable := integerBlock.io.csrio.customCtrl.l2_pf_enable
281
282  val l1plus_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
283  l1pluscache.reset := l1plus_reset_gen.io.out
284
285  val ptw_reset_gen = Module(new ResetGen(2, !debugOpts.FPGAPlatform))
286  ptw.reset := ptw_reset_gen.io.out
287  itlbRepeater.reset := ptw_reset_gen.io.out
288  dtlbRepeater.reset := ptw_reset_gen.io.out
289
290  val memBlock_reset_gen = Module(new ResetGen(3, !debugOpts.FPGAPlatform))
291  memBlock.reset := memBlock_reset_gen.io.out
292
293  val intBlock_reset_gen = Module(new ResetGen(4, !debugOpts.FPGAPlatform))
294  integerBlock.reset := intBlock_reset_gen.io.out
295
296  val fpBlock_reset_gen = Module(new ResetGen(5, !debugOpts.FPGAPlatform))
297  floatBlock.reset := fpBlock_reset_gen.io.out
298
299  val ctrlBlock_reset_gen = Module(new ResetGen(6, !debugOpts.FPGAPlatform))
300  ctrlBlock.reset := ctrlBlock_reset_gen.io.out
301
302  val frontend_reset_gen = Module(new ResetGen(7, !debugOpts.FPGAPlatform))
303  frontend.reset := frontend_reset_gen.io.out
304}
305