xref: /XiangShan/src/main/scala/xiangshan/XSCore.scala (revision f320e0f01bd645f0a3045a8a740e60dd770734a9)
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}
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.bpuInfo <> ctrlBlock.io.perfInfo.bpuInfo
224  integerBlock.io.csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo
225  integerBlock.io.csrio.perf.memInfo <> memBlock.io.memInfo
226  integerBlock.io.csrio.perf.frontendInfo <> frontend.io.frontendInfo
227
228  integerBlock.io.csrio.fpu.fflags <> ctrlBlock.io.roqio.toCSR.fflags
229  integerBlock.io.csrio.fpu.isIllegal := false.B
230  integerBlock.io.csrio.fpu.dirty_fs <> ctrlBlock.io.roqio.toCSR.dirty_fs
231  integerBlock.io.csrio.fpu.frm <> floatBlock.io.frm
232  integerBlock.io.csrio.exception <> ctrlBlock.io.roqio.exception
233  integerBlock.io.csrio.isXRet <> ctrlBlock.io.roqio.toCSR.isXRet
234  integerBlock.io.csrio.trapTarget <> ctrlBlock.io.roqio.toCSR.trapTarget
235  integerBlock.io.csrio.interrupt <> ctrlBlock.io.roqio.toCSR.intrBitSet
236  integerBlock.io.csrio.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr
237  integerBlock.io.csrio.externalInterrupt <> io.externalInterrupt
238
239  floatBlock.io.redirect <> ctrlBlock.io.redirect
240  floatBlock.io.flush <> ctrlBlock.io.flush
241
242  integerBlock.io.fenceio.sfence <> memBlock.io.sfence
243  integerBlock.io.fenceio.sbuffer <> memBlock.io.fenceToSbuffer
244
245  memBlock.io.redirect <> ctrlBlock.io.redirect
246  memBlock.io.flush <> ctrlBlock.io.flush
247  memBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl
248  memBlock.io.tlbCsr <> integerBlock.io.csrio.tlb
249  memBlock.io.lsqio.roq <> ctrlBlock.io.roqio.lsq
250  memBlock.io.lsqio.exceptionAddr.lsIdx.lqIdx := ctrlBlock.io.roqio.exception.bits.uop.lqIdx
251  memBlock.io.lsqio.exceptionAddr.lsIdx.sqIdx := ctrlBlock.io.roqio.exception.bits.uop.sqIdx
252  memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.roqio.exception.bits.uop.ctrl.commitType)
253
254  val itlbRepeater = Module(new PTWRepeater())
255  val dtlbRepeater = if (usePTWRepeater) {
256    Module(new PTWRepeater(LoadPipelineWidth + StorePipelineWidth))
257  } else {
258    Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, PtwMissQueueSize))
259  }
260  itlbRepeater.io.tlb <> frontend.io.ptw
261  dtlbRepeater.io.tlb <> memBlock.io.ptw
262  itlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence
263  dtlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence
264  ptw.io.tlb(0) <> itlbRepeater.io.ptw
265  ptw.io.tlb(1) <> dtlbRepeater.io.ptw
266  ptw.io.sfence <> integerBlock.io.fenceio.sfence
267  ptw.io.csr <> integerBlock.io.csrio.tlb
268
269  // if l2 prefetcher use stream prefetch, it should be placed in XSCore
270  assert(l2PrefetcherParameters._type == "bop")
271  io.l2_pf_enable := integerBlock.io.csrio.customCtrl.l2_pf_enable
272
273  val l1plus_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform))
274  l1pluscache.reset := l1plus_reset_gen.io.out
275
276  val ptw_reset_gen = Module(new ResetGen(2, !debugOpts.FPGAPlatform))
277  ptw.reset := ptw_reset_gen.io.out
278  itlbRepeater.reset := ptw_reset_gen.io.out
279  dtlbRepeater.reset := ptw_reset_gen.io.out
280
281  val memBlock_reset_gen = Module(new ResetGen(3, !debugOpts.FPGAPlatform))
282  memBlock.reset := memBlock_reset_gen.io.out
283
284  val intBlock_reset_gen = Module(new ResetGen(4, !debugOpts.FPGAPlatform))
285  integerBlock.reset := intBlock_reset_gen.io.out
286
287  val fpBlock_reset_gen = Module(new ResetGen(5, !debugOpts.FPGAPlatform))
288  floatBlock.reset := fpBlock_reset_gen.io.out
289
290  val ctrlBlock_reset_gen = Module(new ResetGen(6, !debugOpts.FPGAPlatform))
291  ctrlBlock.reset := ctrlBlock_reset_gen.io.out
292
293  val frontend_reset_gen = Module(new ResetGen(7, !debugOpts.FPGAPlatform))
294  frontend.reset := frontend_reset_gen.io.out
295}
296