xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision 35ee668dfaa9d1512c3dfbcc845d4c6a4c4ec9be)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*
4* XiangShan is licensed under Mulan PSL v2.
5* You can use this software according to the terms and conditions of the Mulan PSL v2.
6* You may obtain a copy of Mulan PSL v2 at:
7*          http://license.coscl.org.cn/MulanPSL2
8*
9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12*
13* See the Mulan PSL v2 for more details.
14***************************************************************************************/
15
16package xiangshan
17
18import chisel3._
19import chisel3.util._
20import xiangshan.backend._
21import xiangshan.backend.fu.HasExceptionNO
22import xiangshan.backend.exu.Wb
23import xiangshan.frontend._
24import xiangshan.mem._
25import xiangshan.cache.{DCacheParameters, L1plusCacheWrapper, L1plusCacheParameters, PTWWrapper, PTWRepeater, PTWFilter}
26import xiangshan.cache.prefetch._
27import chipsalliance.rocketchip.config
28import chipsalliance.rocketchip.config.Parameters
29import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
30import freechips.rocketchip.tile.HasFPUParameters
31import system.{HasSoCParameter, L1CacheErrorInfo}
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  val memBlock = LazyModule(new MemBlock)
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(0, 1, 2, 5, 6, 7, 8), Seq()),
82    (MulDivExeUnitCfg, exuParameters.MduCnt, Seq(0, 1, 2, 5, 6, 7, 8), Seq()),
83    (JumpExeUnitCfg, 1, Seq(), Seq()),
84    (FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(3, 4)),
85    (FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq(3, 4)),
86    (LdExeUnitCfg, 1, Seq(0, 5, 6), Seq()),
87    (LdExeUnitCfg, 1, Seq(0, 5, 6), Seq()),
88    (StExeUnitCfg, 1, Seq(), Seq()),
89    (StExeUnitCfg, 1, Seq(), Seq())
90  )
91  // allow mdu and fmisc to have 2*numDeq enqueue ports
92  val intDpPorts = (0 until exuParameters.AluCnt).map(i => {
93    if (i < exuParameters.JmpCnt) Seq((0, i), (1, i), (2, i))
94    else if (i < 2*exuParameters.MduCnt) Seq((0, i), (1, i))
95    else Seq((0, i))
96  })
97  val fpDpPorts = (0 until exuParameters.FmacCnt).map(i => {
98    if (i < 2*exuParameters.FmiscCnt) Seq((3, i), (4, i))
99    else Seq((4, i))
100  })
101  val lsDpPorts = Seq(
102    Seq((5, 0)),
103    Seq((6, 0)),
104    Seq((7, 0)),
105    Seq((8, 0))
106  )
107  val dispatchPorts = intDpPorts ++ fpDpPorts ++ lsDpPorts
108
109  val scheduler = LazyModule(new Scheduler(schedulePorts, dispatchPorts))
110
111}
112
113class XSCore()(implicit p: config.Parameters) extends XSCoreBase
114  with HasXSDts
115{
116  lazy val module = new XSCoreImp(this)
117}
118
119class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer)
120  with HasXSParameter
121  with HasSoCParameter
122  with HasExeBlockHelper {
123  val io = IO(new Bundle {
124    val hartId = Input(UInt(64.W))
125    val externalInterrupt = new ExternalInterruptIO
126    val l2_pf_enable = Output(Bool())
127    val l1plus_error, icache_error, dcache_error = Output(new L1CacheErrorInfo)
128  })
129
130  println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}")
131  AddressSpace.checkMemmap()
132  AddressSpace.printMemmap()
133
134  // to fast wake up fp, mem rs
135  val intBlockFastWakeUp = intExuConfigs.filter(_.hasCertainLatency)
136  val intBlockSlowWakeUp = intExuConfigs.filter(_.hasUncertainlatency)
137
138  val ctrlBlock = Module(new CtrlBlock)
139
140  val integerBlock = Module(new IntegerBlock)
141  val floatBlock = Module(new FloatBlock)
142
143  val frontend = outer.frontend.module
144  val memBlock = outer.memBlock.module
145  val l1pluscache = outer.l1pluscache.module
146  val ptw = outer.ptw.module
147  val scheduler = outer.scheduler.module
148
149  val allWriteback = integerBlock.io.writeback ++ floatBlock.io.writeback ++ memBlock.io.writeback
150  val intConfigs = exuConfigs.filter(_.writeIntRf)
151  val intArbiter = Module(new Wb(intConfigs, NRIntWritePorts, isFp = false))
152  val intWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeIntRf).map(_._1)
153  // set default value for ready
154  integerBlock.io.writeback.map(_.ready := true.B)
155  floatBlock.io.writeback.map(_.ready := true.B)
156  memBlock.io.writeback.map(_.ready := true.B)
157  intArbiter.io.in.zip(intWriteback).foreach { case (arb, wb) =>
158    arb.valid := wb.valid && !wb.bits.uop.ctrl.fpWen
159    arb.bits := wb.bits
160    when (arb.valid) {
161      wb.ready := arb.ready
162    }
163  }
164
165  val fpArbiter = Module(new Wb(exuConfigs.filter(_.writeFpRf), NRFpWritePorts, isFp = true))
166  val fpWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeFpRf).map(_._1)
167  fpArbiter.io.in.zip(fpWriteback).foreach{ case (arb, wb) =>
168    arb.valid := wb.valid && wb.bits.uop.ctrl.fpWen
169    arb.bits := wb.bits
170    when (arb.valid) {
171      wb.ready := arb.ready
172    }
173  }
174
175  io.l1plus_error <> l1pluscache.io.error
176  io.icache_error <> frontend.io.error
177  io.dcache_error <> memBlock.io.error
178
179  frontend.io.backend <> ctrlBlock.io.frontend
180  frontend.io.sfence <> integerBlock.io.fenceio.sfence
181  frontend.io.tlbCsr <> integerBlock.io.csrio.tlb
182  frontend.io.csrCtrl <> integerBlock.io.csrio.customCtrl
183
184  frontend.io.icacheMemAcq <> l1pluscache.io.req
185  l1pluscache.io.resp <> frontend.io.icacheMemGrant
186  l1pluscache.io.flush := frontend.io.l1plusFlush
187  frontend.io.fencei := integerBlock.io.fenceio.fencei
188
189  ctrlBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl
190  ctrlBlock.io.exuRedirect <> integerBlock.io.exuRedirect
191  ctrlBlock.io.stIn <> memBlock.io.stIn
192  ctrlBlock.io.stOut <> memBlock.io.stOut
193  ctrlBlock.io.memoryViolation <> memBlock.io.memoryViolation
194  ctrlBlock.io.enqLsq <> memBlock.io.enqLsq
195  // TODO
196  ctrlBlock.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out)
197
198  scheduler.io.redirect <> ctrlBlock.io.redirect
199  scheduler.io.flush <> ctrlBlock.io.flush
200  scheduler.io.allocate <> ctrlBlock.io.enqIQ
201  scheduler.io.issue <> integerBlock.io.issue ++ floatBlock.io.issue ++ memBlock.io.issue
202  // TODO arbiter
203  scheduler.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out)
204
205  scheduler.io.replay <> memBlock.io.replay
206  scheduler.io.rsIdx <> memBlock.io.rsIdx
207  scheduler.io.isFirstIssue <> memBlock.io.isFirstIssue
208  scheduler.io.stData <> memBlock.io.stData
209  scheduler.io.otherFastWakeup <> memBlock.io.otherFastWakeup
210  scheduler.io.jumpPc <> ctrlBlock.io.jumpPc
211  scheduler.io.jalr_target <> ctrlBlock.io.jalr_target
212  scheduler.io.stIssuePtr <> memBlock.io.stIssuePtr
213  scheduler.io.debug_fp_rat <> ctrlBlock.io.debug_fp_rat
214  scheduler.io.debug_int_rat <> ctrlBlock.io.debug_int_rat
215  scheduler.io.readIntRf <> ctrlBlock.io.readIntRf
216  scheduler.io.readFpRf <> ctrlBlock.io.readFpRf
217
218  integerBlock.io.redirect <> ctrlBlock.io.redirect
219  integerBlock.io.flush <> ctrlBlock.io.flush
220  integerBlock.io.csrio.hartId <> io.hartId
221  integerBlock.io.csrio.perf <> DontCare
222  integerBlock.io.csrio.perf.retiredInstr <> ctrlBlock.io.roqio.toCSR.perfinfo.retiredInstr
223  integerBlock.io.csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
224  integerBlock.io.csrio.perf.memInfo <> memBlock.io.memInfo
225  integerBlock.io.csrio.perf.frontendInfo <> frontend.io.frontendInfo
226
227  integerBlock.io.csrio.fpu.fflags <> ctrlBlock.io.roqio.toCSR.fflags
228  integerBlock.io.csrio.fpu.isIllegal := false.B
229  integerBlock.io.csrio.fpu.dirty_fs <> ctrlBlock.io.roqio.toCSR.dirty_fs
230  integerBlock.io.csrio.fpu.frm <> floatBlock.io.frm
231  integerBlock.io.csrio.exception <> ctrlBlock.io.roqio.exception
232  integerBlock.io.csrio.isXRet <> ctrlBlock.io.roqio.toCSR.isXRet
233  integerBlock.io.csrio.trapTarget <> ctrlBlock.io.roqio.toCSR.trapTarget
234  integerBlock.io.csrio.interrupt <> ctrlBlock.io.roqio.toCSR.intrBitSet
235  integerBlock.io.csrio.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr
236  integerBlock.io.csrio.externalInterrupt <> io.externalInterrupt
237
238  floatBlock.io.redirect <> ctrlBlock.io.redirect
239  floatBlock.io.flush <> ctrlBlock.io.flush
240
241  integerBlock.io.fenceio.sfence <> memBlock.io.sfence
242  integerBlock.io.fenceio.sbuffer <> memBlock.io.fenceToSbuffer
243
244  memBlock.io.redirect <> ctrlBlock.io.redirect
245  memBlock.io.flush <> ctrlBlock.io.flush
246  memBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl
247  memBlock.io.tlbCsr <> integerBlock.io.csrio.tlb
248  memBlock.io.lsqio.roq <> ctrlBlock.io.roqio.lsq
249  memBlock.io.lsqio.exceptionAddr.lsIdx.lqIdx := ctrlBlock.io.roqio.exception.bits.uop.lqIdx
250  memBlock.io.lsqio.exceptionAddr.lsIdx.sqIdx := ctrlBlock.io.roqio.exception.bits.uop.sqIdx
251  memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.roqio.exception.bits.uop.ctrl.commitType)
252
253  val itlbRepeater = Module(new PTWRepeater(2))
254  val dtlbRepeater = if (usePTWRepeater) {
255    Module(new PTWRepeater(LoadPipelineWidth + StorePipelineWidth))
256  } else {
257    Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, PtwMissQueueSize))
258  }
259  itlbRepeater.io.tlb <> frontend.io.ptw
260  dtlbRepeater.io.tlb <> memBlock.io.ptw
261  itlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence
262  dtlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence
263  ptw.io.tlb(0) <> itlbRepeater.io.ptw
264  ptw.io.tlb(1) <> dtlbRepeater.io.ptw
265  ptw.io.sfence <> integerBlock.io.fenceio.sfence
266  ptw.io.csr <> integerBlock.io.csrio.tlb
267
268  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
269  assert(l2PrefetcherParameters._type == "bop")
270  io.l2_pf_enable := integerBlock.io.csrio.customCtrl.l2_pf_enable
271
272  val l1plus_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
273  l1pluscache.reset := l1plus_reset_gen.io.out
274
275  val ptw_reset_gen = Module(new ResetGen(2, !debugOpts.FPGAPlatform))
276  ptw.reset := ptw_reset_gen.io.out
277  itlbRepeater.reset := ptw_reset_gen.io.out
278  dtlbRepeater.reset := ptw_reset_gen.io.out
279
280  val memBlock_reset_gen = Module(new ResetGen(3, !debugOpts.FPGAPlatform))
281  memBlock.reset := memBlock_reset_gen.io.out
282
283  val intBlock_reset_gen = Module(new ResetGen(4, !debugOpts.FPGAPlatform))
284  integerBlock.reset := intBlock_reset_gen.io.out
285
286  val fpBlock_reset_gen = Module(new ResetGen(5, !debugOpts.FPGAPlatform))
287  floatBlock.reset := fpBlock_reset_gen.io.out
288
289  val ctrlBlock_reset_gen = Module(new ResetGen(6, !debugOpts.FPGAPlatform))
290  ctrlBlock.reset := ctrlBlock_reset_gen.io.out
291
292  val frontend_reset_gen = Module(new ResetGen(7, !debugOpts.FPGAPlatform))
293  frontend.reset := frontend_reset_gen.io.out
294}
295