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