xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala (revision 01cdded87283f55be427ca849d18baa3e9459c2d)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import freechips.rocketchip.rocket.CSRs
6import org.chipsalliance.cde.config.Parameters
7import top.{ArgParser, Generator}
8import xiangshan.backend.fu.NewCSR.CSRBundles.{PrivState, RobCommitCSR}
9import xiangshan.backend.fu.NewCSR.CSRDefines.{ContextStatus, PrivMode, VirtMode}
10import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._
11import xiangshan.backend.fu.NewCSR.CSREvents.{CSREvents, DretEventSinkBundle, EventUpdatePrivStateOutput, MretEventSinkBundle, SretEventSinkBundle, TrapEntryEventInput, TrapEntryHSEventSinkBundle, TrapEntryMEventSinkBundle, TrapEntryVSEventSinkBundle}
12import xiangshan.backend.fu.fpu.Bundles.Frm
13import xiangshan.backend.fu.vector.Bundles.{Vl, Vxrm, Vxsat}
14import xiangshan.{HasXSParameter, XSCoreParamsKey, XSTileKey}
15
16object CSRConfig {
17  final val GEILEN = 63
18
19  final val ASIDLEN = 16 // the length of ASID of XS implementation
20
21  final val ASIDMAX = 16 // the max value of ASIDLEN defined by spec
22
23  final val HIIDWidth = 12 // support Hvictl[27:16](IID)
24
25  final val VMIDLEN = 14 // the length of VMID of XS implementation
26
27  final val VMIDMAX = 14 // the max value of VMIDLEN defined by spec
28
29  // the width of VGEIN
30  final val VGEINWidth = 6
31
32  final val VaddrMaxWidth = 41 // only Sv39 and Sv39x4
33
34  final val XLEN = 64 // Todo: use XSParams
35
36  final val VLEN = 128
37
38  // Since we need macro to compute the width of CSR field, the input of macro should be the value that can be computed
39  // at compile time. The log2Up function cannot be used as meta-programming function, so we use litral value here
40  // log2Up(128 + 1), hold 0~128
41  final val VlWidth = 8
42}
43
44class NewCSR(implicit val p: Parameters) extends Module
45  with HasXSParameter
46  with MachineLevel
47  with SupervisorLevel
48  with HypervisorLevel
49  with VirtualSupervisorLevel
50  with Unprivileged
51  with CSRAIA
52  with HasExternalInterruptBundle
53  with SupervisorMachineAliasConnect
54  with CSREvents
55  with DebugLevel
56  with CSRCustom
57{
58
59  import CSRConfig._
60
61  val io = IO(new Bundle {
62    val in = Input(new Bundle {
63      val wen = Bool()
64      val ren = Bool()
65      val addr = UInt(12.W)
66      val wdata = UInt(64.W)
67    })
68    val fromMem = Input(new Bundle {
69      val excpVA  = UInt(VaddrMaxWidth.W)
70      val excpGPA = UInt(VaddrMaxWidth.W) // Todo: use guest physical address width
71    })
72    val fromRob = Input(new Bundle {
73      val trap = ValidIO(new Bundle {
74        val pc = UInt(VaddrMaxWidth.W)
75        val instr = UInt(32.W)
76        val trapVec = UInt(64.W)
77        val singleStep = Bool()
78        val crossPageIPFFix = Bool()
79        val isInterrupt = Bool()
80      })
81      val commit = Input(new RobCommitCSR)
82    })
83    val mret = Input(Bool())
84    val sret = Input(Bool())
85    val dret = Input(Bool())
86    val wfi  = Input(Bool())
87
88    val out = Output(new Bundle {
89      val EX_II = Bool()
90      val EX_VI = Bool()
91      val flushPipe = Bool()
92      val rData = UInt(64.W)
93      val targetPc = UInt(VaddrMaxWidth.W)
94      val regOut = UInt(64.W)
95      val privState = new PrivState
96      val interrupt = Bool()
97      val wfi_event = Bool()
98      val disableSfence = Bool()
99      // fp
100      val fpState = new Bundle {
101        val off = Bool()
102        val frm = Frm()
103      }
104      // vec
105      val vecState = new Bundle {
106        val vstart = Vl()
107        val vxsat = Vxsat()
108        val vxrm = Vxrm()
109        val vcsr = UInt(XLEN.W)
110        val vl = Vl()
111        val vtype = UInt(XLEN.W)
112        val vlenb = UInt(XLEN.W)
113        val off = Bool()
114      }
115      // perf
116      val isPerfCnt = Bool()
117      // debug
118      val debugMode = Bool()
119      val singleStepFlag = Bool()
120    })
121    // tlb
122    val tlb = Output(new Bundle {
123      val satp = UInt(XLEN.W)
124      val mxr = Bool()
125      val sum = Bool()
126      val imode = UInt(2.W)
127      val dmode = UInt(2.W)
128    })
129    // customCtrl
130    val customCtrl = Output(new Bundle {
131      val sbpctl = UInt(XLEN.W)
132      val spfctl = UInt(XLEN.W)
133      val slvpredctl = UInt(XLEN.W)
134      val smblockctl = UInt(XLEN.W)
135      val srnctl = UInt(XLEN.W)
136      val sdsid = UInt(XLEN.W)
137      val sfetchctl  = Bool()
138    })
139  })
140
141  val toAIA   = IO(Output(new CSRToAIABundle))
142  val fromAIA = IO(Flipped(Output(new AIAToCSRBundle)))
143
144  dontTouch(toAIA)
145  dontTouch(fromAIA)
146
147  val wen   = io.in.wen
148  val addr  = io.in.addr
149  val wdata = io.in.wdata
150
151  val ren   = io.in.ren
152  val raddr = io.in.addr
153
154  val hasTrap = io.fromRob.trap.valid
155  val trapVec = io.fromRob.trap.bits.trapVec
156  val trapPC = io.fromRob.trap.bits.pc
157  val trapIsInterrupt = io.fromRob.trap.bits.isInterrupt
158  val trapIsCrossPageIPF = io.fromRob.trap.bits.crossPageIPFFix
159
160  // CSR Privilege State
161  val PRVM = RegInit(PrivMode(0), PrivMode.M)
162  val V = RegInit(VirtMode(0), VirtMode.Off)
163  val debugMode = RegInit(false.B)
164
165  val permitMod = Module(new CSRPermitModule)
166
167  private val wenLegal = wen && !permitMod.io.out.illegal
168
169  val isCSRAccess = io.in.ren || io.in.wen
170  val isSret = io.sret
171  val isMret = io.mret
172  val isDret = io.dret
173  val isWfi  = io.wfi
174
175  var csrRwMap =
176    machineLevelCSRMap ++
177    supervisorLevelCSRMap ++
178    hypervisorCSRMap ++
179    virtualSupervisorCSRMap ++
180    unprivilegedCSRMap ++
181    debugCSRMap ++
182    aiaCSRMap ++
183    customCSRMap
184
185  val csrMods =
186    machineLevelCSRMods ++
187    supervisorLevelCSRMods ++
188    hypervisorCSRMods ++
189    virtualSupervisorCSRMods ++
190    unprivilegedCSRMods ++
191    debugCSRMods ++
192    aiaCSRMods ++
193    customCSRMods
194
195  var csrOutMap =
196    machineLevelCSROutMap ++
197    supervisorLevelCSROutMap ++
198    hypervisorCSROutMap ++
199    virtualSupervisorCSROutMap ++
200    unprivilegedCSROutMap ++
201    debugCSROutMap ++
202    aiaCSROutMap ++
203    customCSROutMap
204
205  val trapHandleMod = Module(new TrapHandleModule)
206
207  trapHandleMod.io.in.trapInfo.valid := hasTrap
208  trapHandleMod.io.in.trapInfo.bits.trapVec := trapVec.asUInt
209  trapHandleMod.io.in.trapInfo.bits.isInterrupt := trapIsInterrupt
210  trapHandleMod.io.in.privState.PRVM := PRVM
211  trapHandleMod.io.in.privState.V := V
212  trapHandleMod.io.in.mideleg := mideleg.regOut
213  trapHandleMod.io.in.medeleg := medeleg.regOut
214  trapHandleMod.io.in.hideleg := hideleg.regOut
215  trapHandleMod.io.in.hedeleg := hedeleg.regOut
216  trapHandleMod.io.in.mtvec := mtvec.regOut
217  trapHandleMod.io.in.stvec := stvec.regOut
218  trapHandleMod.io.in.vstvec := vstvec.regOut
219
220  val entryPrivState = trapHandleMod.io.out.entryPrivState
221
222  for ((id, (wBundle, _)) <- csrRwMap) {
223    wBundle.wen := wenLegal && addr === id.U
224    wBundle.wdata := wdata
225  }
226
227  // Todo: support set dirty only when fcsr has changed
228  private val writeFpState = wenLegal && Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _)
229  private val writeVecState = wenLegal && Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _)
230
231  permitMod.io.in.csrAccess.valid := isCSRAccess
232  permitMod.io.in.csrAccess.bits.wen := wen
233  permitMod.io.in.csrAccess.bits.addr := addr
234
235  permitMod.io.in.privState.V := V
236  permitMod.io.in.privState.PRVM := PRVM
237
238  permitMod.io.in.mret := isMret
239  permitMod.io.in.sret := isSret
240
241  permitMod.io.in.status.tsr := false.B
242  permitMod.io.in.status.vtsr := false.B
243
244  csrMods.foreach { mod =>
245    mod match {
246      case m: HypervisorBundle =>
247        m.hstatus := hstatus.regOut
248        m.hvip := hvip.regOut
249        m.hideleg := hideleg.regOut
250        m.hedeleg := hedeleg.regOut
251        m.hgeip := hgeip.regOut
252        m.hgeie := hgeie.regOut
253        m.hip := hip.regOut
254        m.hie := hie.regOut
255      case _ =>
256    }
257    mod match {
258      case m: HasMachineInterruptBundle =>
259        m.mvien := mvien.regOut
260        m.mvip := mvip.regOut
261        m.mip := mip.regOut
262        m.mie := mie.regOut
263      case _ =>
264    }
265    mod match {
266      case m: HasMachineDelegBundle =>
267        m.mideleg := mideleg.regOut
268        m.medeleg := medeleg.regOut
269      case _ =>
270    }
271    mod match {
272      case m: HasMachineCounterControlBundle =>
273        m.mcountinhibit := mcountinhibit.regOut
274      case _ =>
275    }
276    mod match {
277      case m: HasExternalInterruptBundle =>
278        m.platformIRP := this.platformIRP
279      case _ =>
280    }
281    mod match {
282      case m: HasRobCommitBundle =>
283        m.robCommit := io.fromRob.commit
284        m.robCommit.fsDirty := io.fromRob.commit.fsDirty || writeFpState
285        m.robCommit.vsDirty := io.fromRob.commit.vsDirty || writeVecState
286      case _ =>
287    }
288    mod match {
289      case m: TrapEntryMEventSinkBundle =>
290        m.trapToM := trapEntryMEvent.out
291      case _ =>
292    }
293    mod match {
294      case m: TrapEntryHSEventSinkBundle =>
295        m.trapToHS := trapEntryHSEvent.out
296      case _ =>
297    }
298    mod match {
299      case m: TrapEntryVSEventSinkBundle =>
300        m.trapToVS := trapEntryVSEvent.out
301      case _ =>
302    }
303    mod match {
304      case m: MretEventSinkBundle =>
305        m.retFromM := mretEvent.out
306      case _ =>
307    }
308    mod match {
309      case m: SretEventSinkBundle =>
310        m.retFromS := sretEvent.out
311      case _ =>
312    }
313    mod match {
314      case m: DretEventSinkBundle =>
315        m.retFromD := dretEvent.out
316      case _ =>
317    }
318    mod match {
319      case m: HasAIABundle =>
320        m.aiaToCSR.rdata.valid := fromAIA.rdata.valid
321        m.aiaToCSR.rdata.bits.data := fromAIA.rdata.bits.data
322        m.aiaToCSR.rdata.bits.illegal := fromAIA.rdata.bits.illegal
323        m.aiaToCSR.mtopei.valid := fromAIA.mtopei.valid
324        m.aiaToCSR.stopei.valid := fromAIA.stopei.valid
325        m.aiaToCSR.vstopei.valid := fromAIA.vstopei.valid
326        m.aiaToCSR.mtopei.bits := fromAIA.mtopei.bits
327        m.aiaToCSR.stopei.bits := fromAIA.stopei.bits
328        m.aiaToCSR.vstopei.bits := fromAIA.vstopei.bits
329      case _ =>
330    }
331  }
332
333  csrMods.foreach { mod =>
334    mod.commonIn.status := mstatus.mstatus
335    mod.commonIn.prvm := PRVM
336    mod.commonIn.v := V
337    mod.commonIn.hstatus := hstatus.rdata
338    println(s"${mod.modName}: ")
339    println(mod.dumpFields)
340  }
341
342  trapEntryMEvent.valid  := entryPrivState.isModeM
343  trapEntryHSEvent.valid := entryPrivState.isModeHS
344  trapEntryVSEvent.valid := entryPrivState.isModeVS
345
346  Seq(trapEntryMEvent, trapEntryHSEvent, trapEntryVSEvent).foreach { eMod =>
347    eMod.in match {
348      case in: TrapEntryEventInput =>
349        in.causeNO := trapHandleMod.io.out.causeNO
350        in.trapPc := trapPC
351        in.isCrossPageIPF := trapIsCrossPageIPF
352
353        in.iMode.PRVM := PRVM
354        in.iMode.V := V
355        in.dMode.PRVM := Mux(mstatus.rdata.MPRV.asBool, mstatus.rdata.MPP, PRVM)
356        in.dMode.V := Mux(mstatus.rdata.MPRV.asBool, mstatus.rdata.MPV, V)
357
358        in.privState.PRVM := PRVM
359        in.privState.V := V
360        in.mstatus := mstatus.regOut
361        in.hstatus := hstatus.regOut
362        in.sstatus := mstatus.sstatus
363        in.vsstatus := vsstatus.regOut
364        in.pcFromXtvec := trapHandleMod.io.out.pcFromXtvec
365
366        in.satp := satp.rdata
367        in.vsatp := vsatp.rdata
368
369        in.memExceptionVAddr := io.fromMem.excpVA
370        in.memExceptionGPAddr := io.fromMem.excpGPA
371    }
372  }
373
374  mretEvent.valid := isMret
375  mretEvent.in match {
376    case in =>
377      in.mstatus := mstatus.regOut
378      in.mepc := mepc.regOut
379  }
380
381  sretEvent.valid := isSret
382  sretEvent.in match {
383    case in =>
384      in.privState.PRVM := PRVM
385      in.privState.V := V
386      in.sstatus := mstatus.sstatus
387      in.hstatus := hstatus.regOut
388      in.vsstatus := vsstatus.regOut
389      in.sepc := sepc.regOut
390      in.vsepc := vsepc.regOut
391  }
392
393  dretEvent.valid := isDret
394  dretEvent.in match {
395    case in =>
396      in.dcsr := dcsr.regOut
397      in.dpc  := dpc.regOut
398      in.mstatus := mstatus.regOut
399  }
400
401  PRVM := MuxCase(
402    PRVM,
403    events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map {
404      x => x.out match {
405        case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.PRVM)
406      }
407    }
408  )
409
410  V := MuxCase(
411    V,
412    events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map {
413      x => x.out match {
414        case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.V)
415      }
416    }
417  )
418
419  // perf
420  val addrInPerfCnt = (addr >= CSRs.mcycle.U) && (addr <= CSRs.mhpmcounter31.U) ||
421    (addr >= mcountinhibit.addr.U) && (addr <= mhpmevents.last.addr.U) ||
422    (addr >= CSRs.cycle.U) && (addr <= CSRs.hpmcounter31.U) ||
423    (addr === CSRs.mip.U) ||
424    (addr === CSRs.hip.U)
425  // Todo: may be vsip and sip
426
427  // flush
428  val resetSatp = addr === satp.addr.U && wenLegal // write to satp will cause the pipeline be flushed
429
430  val wFcsrChangeRM = addr === fcsr.addr.U && wenLegal && wdata(7, 5) =/= fcsr.frm
431  val wFrmChangeRM  = addr === CSRs.frm.U  && wenLegal && wdata(2, 0) =/= fcsr.frm
432  val frmChange = wFcsrChangeRM || wFrmChangeRM
433
434  val wVcsrChangeRM = addr === CSRs.vcsr.U && wenLegal && wdata(2, 1) =/= vcsr.vxrm
435  val wVxrmChangeRM = addr === CSRs.vxrm.U && wenLegal && wdata(1, 0) =/= vcsr.vxrm
436  val vxrmChange = wVcsrChangeRM || wVxrmChangeRM
437
438  val flushPipe = resetSatp || frmChange || vxrmChange
439
440  // debug
441  val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable
442  debugMode := dretEvent.out.debugMode
443  debugIntrEnable := dretEvent.out.debugIntrEnable
444  val debugIntr = platformIRP.debugIP && debugIntrEnable
445
446  // interrupt
447  val disableInterrupt = debugMode || (dcsr.rdata.STEP.asBool && !dcsr.rdata.STEPIE.asBool)
448  val ideleg = mideleg.rdata.asUInt & mip.rdata.asUInt
449  def priviledgeEnableDetect(x: Bool): Bool = Mux(x, ((PRVM === PrivMode.S) && mstatus.rdata.SIE.asBool) || (PRVM < PrivMode.S),
450    ((PRVM === PrivMode.M) && mstatus.rdata.MIE.asBool) || (PRVM < PrivMode.M))
451
452  val intrVecEnable = Wire(Vec(12, Bool()))
453  intrVecEnable.zip(ideleg.asBools).map{ case(x, y) => x := priviledgeEnableDetect(y) && !disableInterrupt}
454  val intrVec = Cat(debugIntr && !debugMode, mie.rdata.asUInt(11, 0) & mip.rdata.asUInt & intrVecEnable.asUInt) // Todo: asUInt(11,0) is ok?
455  val intrBitSet = intrVec.orR
456
457  // fence
458  // csr access check, special case
459  val tvmNotPermit = PRVM === PrivMode.S && mstatus.rdata.TVM.asBool
460
461  private val rdata = Mux1H(csrRwMap.map { case (id, (_, rBundle)) =>
462    (raddr === id.U) -> rBundle.asUInt
463  })
464
465  private val regOut = Mux1H(csrOutMap.map { case (id, regOut) =>
466    (raddr === id.U) -> regOut
467  })
468
469  private val hasEvent = mretEvent.out.targetPc.valid || sretEvent.out.targetPc.valid || dretEvent.out.targetPc.valid ||
470    trapEntryMEvent.out.targetPc.valid || trapEntryHSEvent.out.targetPc.valid || trapEntryVSEvent.out.targetPc.valid
471
472  io.out.EX_II     := false.B // Todo
473  io.out.EX_VI     := false.B // Todo
474  io.out.flushPipe := flushPipe
475
476  io.out.rData := Mux(ren, rdata, 0.U)
477  io.out.regOut := regOut
478  io.out.targetPc := RegEnable(Mux1H(Seq(
479    mretEvent.out.targetPc.valid -> mretEvent.out.targetPc.bits,
480    sretEvent.out.targetPc.valid -> sretEvent.out.targetPc.bits,
481    dretEvent.out.targetPc.valid -> dretEvent.out.targetPc.bits,
482    trapEntryMEvent.out.targetPc.valid -> trapEntryMEvent.out.targetPc.bits,
483    trapEntryHSEvent.out.targetPc.valid -> trapEntryHSEvent.out.targetPc.bits,
484    trapEntryVSEvent.out.targetPc.valid -> trapEntryVSEvent.out.targetPc.bits,
485  )), hasEvent)
486
487  io.out.privState.PRVM := PRVM
488  io.out.privState.V    := V
489
490  io.out.fpState.frm := fcsr.frm
491  io.out.fpState.off := mstatus.rdata.FS === ContextStatus.Off
492  io.out.vecState.vstart := vstart.rdata.asUInt
493  io.out.vecState.vxsat := vcsr.vxsat
494  io.out.vecState.vxrm := vcsr.vxrm
495  io.out.vecState.vcsr := vcsr.rdata.asUInt
496  io.out.vecState.vl := vl.rdata.asUInt
497  io.out.vecState.vtype := vtype.rdata.asUInt // Todo: check correct
498  io.out.vecState.vlenb := vlenb.rdata.asUInt
499  io.out.vecState.off := mstatus.rdata.VS === ContextStatus.Off
500  io.out.isPerfCnt := addrInPerfCnt
501  io.out.interrupt := intrBitSet
502  io.out.wfi_event := debugIntr || (mie.rdata.asUInt & mip.rdata.asUInt).orR
503  io.out.debugMode := debugMode
504  io.out.disableSfence := tvmNotPermit || PRVM === PrivMode.U
505  io.out.singleStepFlag := !debugMode && dcsr.rdata.STEP
506
507  // Todo: record the last address to avoid xireg is different with xiselect
508  toAIA.addr.valid := isCSRAccess && Seq(miselect, siselect, vsiselect).map(
509    _.addr.U === addr
510  ).reduce(_ || _)
511  toAIA.addr.bits.addr := addr
512  toAIA.addr.bits.prvm := PRVM
513  toAIA.addr.bits.v := V
514  toAIA.vgein := hstatus.rdata.VGEIN.asUInt
515  toAIA.wdata.valid := isCSRAccess && Seq(mireg, sireg, vsireg).map(
516    _.addr.U === addr
517  ).reduce(_ || _)
518  toAIA.wdata.bits.data := wdata
519  toAIA.mClaim := isCSRAccess && mtopei.addr.U === addr
520  toAIA.sClaim := isCSRAccess && stopei.addr.U === addr
521  toAIA.vsClaim := isCSRAccess && vstopei.addr.U === addr
522
523  // tlb
524  io.tlb.satp := satp.rdata.asUInt
525  io.tlb.mxr := mstatus.rdata.MXR.asBool
526  io.tlb.sum := mstatus.rdata.SUM.asBool
527  io.tlb.imode := PRVM.asUInt
528  io.tlb.dmode := Mux((debugMode && dcsr.rdata.MPRVEN.asBool || !debugMode) && mstatus.rdata.MPRV.asBool, mstatus.rdata.MPP.asUInt, PRVM.asUInt)
529
530  // customCtrl
531  io.customCtrl.sbpctl := sbpctl.rdata.asUInt
532  io.customCtrl.spfctl := spfctl.rdata.asUInt
533  io.customCtrl.slvpredctl := slvpredctl.rdata.asUInt
534  io.customCtrl.smblockctl := smblockctl.rdata.asUInt
535  io.customCtrl.srnctl := srnctl.rdata.asUInt
536  io.customCtrl.sdsid := sdsid.rdata.asUInt
537  io.customCtrl.sfetchctl := sfetchctl.rdata.ICACHE_PARITY_ENABLE.asBool
538}
539
540trait SupervisorMachineAliasConnect { self: NewCSR with MachineLevel with SupervisorLevel =>
541  mip.fromMvip := mvip.toMip
542  mip.fromSip := sip.toMip
543  mie.fromSie := sie.toMie
544}
545
546object NewCSRMain extends App {
547  val (config, firrtlOpts, firtoolOpts) = ArgParser.parse(
548    args :+ "--disable-always-basic-diff" :+ "--dump-fir" :+ "--fpga-platform" :+ "--target" :+ "verilog")
549
550  val defaultConfig = config.alterPartial({
551    // Get XSCoreParams and pass it to the "small module"
552    case XSCoreParamsKey => config(XSTileKey).head
553  })
554
555  Generator.execute(
556    firrtlOpts :+ "--full-stacktrace" :+ "--target-dir" :+ "backend",
557    new NewCSR()(defaultConfig),
558    firtoolOpts
559  )
560
561  println("done")
562}