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