xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala (revision b03c55a5df5dc8793cb44b42dd60141566e57e78)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import org.chipsalliance.cde.config.Parameters
6import freechips.rocketchip.rocket.CSRs
7import utility.SignExt
8import utils.PerfEvent
9import xiangshan.backend.fu.NewCSR.CSRBundles._
10import xiangshan.backend.fu.NewCSR.CSRDefines._
11import xiangshan.backend.fu.NewCSR.CSRDefines.{CSRROField => RO, CSRRWField => RW, _}
12import xiangshan.backend.fu.NewCSR.CSREvents._
13import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._
14import xiangshan.backend.fu.NewCSR.ChiselRecordForField._
15import xiangshan.backend.fu.PerfCounterIO
16import xiangshan.backend.fu.NewCSR.CSRConfig._
17
18import scala.collection.immutable.SeqMap
19
20trait MachineLevel { self: NewCSR =>
21  val mstatus = Module(new MstatusModule)
22    .setAddr(CSRs.mstatus)
23
24  val misa = Module(new CSRModule("Misa", new MisaBundle))
25    .setAddr(CSRs.misa)
26
27  println(s"[CSR] supported isa ext: ${misa.bundle.getISAString}")
28
29  val medeleg = Module(new CSRModule("Medeleg", new MedelegBundle))
30    .setAddr(CSRs.medeleg)
31
32  val mideleg = Module(new CSRModule("Mideleg", new MidelegBundle))
33    .setAddr(CSRs.mideleg)
34
35  val mie = Module(new CSRModule("Mie", new MieBundle) with HasIpIeBundle {
36    val fromHie  = IO(Flipped(new HieToMie))
37    val fromSie  = IO(Flipped(new SieToMie))
38    val fromVSie = IO(Flipped(new VSieToMie))
39
40    // bit 1 SSIE
41    when (fromSie.SSIE.valid) {
42      reg.SSIE := fromSie.SSIE.bits
43    }
44
45    // bit 2 VSSIE
46    when (fromHie.VSSIE.valid || fromVSie.VSSIE.valid) {
47      reg.VSSIE := Mux1H(Seq(
48        fromHie .VSSIE.valid -> fromHie .VSSIE.bits,
49        fromVSie.VSSIE.valid -> fromVSie.VSSIE.bits,
50      ))
51    }
52
53    // bit 5 STIE
54    when(fromSie.STIE.valid) {
55      reg.STIE := fromSie.STIE.bits
56    }
57
58    // bit 6 VSTIE
59    when(fromHie.VSTIE.valid || fromVSie.VSTIE.valid) {
60      reg.VSTIE := Mux1H(Seq(
61        fromHie .VSTIE.valid -> fromHie .VSTIE.bits,
62        fromVSie.VSTIE.valid -> fromVSie.VSTIE.bits,
63      ))
64    }
65
66    // bit 9 SEIE
67    when(fromSie.SEIE.valid) {
68      reg.SEIE := fromSie.SEIE.bits
69    }
70
71    // bit 10 VSEIE
72    when(fromHie.VSEIE.valid || fromVSie.VSEIE.valid) {
73      reg.VSEIE := Mux1H(Seq(
74        fromHie .VSEIE.valid -> fromHie .VSEIE.bits,
75        fromVSie.VSEIE.valid -> fromVSie.VSEIE.bits,
76      ))
77    }
78
79    // bit 12 SGEIE
80    when(fromHie.SGEIE.valid) {
81      reg.SGEIE := fromHie.SGEIE.bits
82    }
83
84    // bit 13~63 LCIP
85    reg.getLocal lazyZip fromSie.getLocal lazyZip fromVSie.getLocal foreach { case (rLCIE, sieLCIE, vsieLCIE) =>
86      when (sieLCIE.valid || vsieLCIE.valid) {
87        rLCIE := Mux1H(Seq(
88          sieLCIE .valid -> sieLCIE .bits,
89          vsieLCIE.valid -> vsieLCIE.bits,
90        ))
91      }
92    }
93
94    // 14~63 read only 0
95    regOut.getLocal.filterNot(_.lsb == InterruptNO.COI).foreach(_ := 0.U)
96  }).setAddr(CSRs.mie)
97
98  val mtvec = Module(new CSRModule("Mtvec", new XtvecBundle))
99    .setAddr(CSRs.mtvec)
100
101  // Todo: support "Stimecmp/Vstimecmp" Extension, Version 1.0.0
102  // Todo: support Sscounterenw Extension
103  val mcounteren = Module(new CSRModule("Mcounteren", new Counteren))
104    .setAddr(CSRs.mcounteren)
105
106  val mvien = Module(new CSRModule("Mvien", new MvienBundle))
107    .setAddr(CSRs.mvien)
108
109  val mvip = Module(new CSRModule("Mvip", new MvipBundle)
110    with HasIpIeBundle
111    with HasMachineEnvBundle
112  {
113    val toMip = IO(new MvipToMip).connectZeroNonRW
114    val fromMip = IO(Flipped(new MipToMvip))
115    val fromSip = IO(Flipped(new SipToMvip))
116    val fromVSip = IO(Flipped(new VSipToMvip))
117
118    // When bit 1 of mvien is zero, bit 1(SSIP) of mvip is an alias of the same bit (SSIP) of mip.
119    // But when bit 1 of mvien is one, bit 1(SSIP) of mvip is a separate writable bit independent of mip.SSIP.
120    // When the value of bit 1 of mvien is changed from zero to one, the value of bit 1 of mvip becomes UNSPECIFIED.
121    // XiangShan will keep the value in mvip.SSIP when mvien.SSIE is changed from zero to one
122    reg.SSIP := Mux(wen && this.mvien.SSIE.asBool, wdata.SSIP, reg.SSIP)
123    regOut.SSIP := Mux(this.mvien.SSIE.asBool, reg.SSIP, this.mip.SSIP)
124    toMip.SSIP.valid := wen && !this.mvien.SSIE.asBool
125    toMip.SSIP.bits := wdata.SSIP
126
127    // Bit 5 of mvip is an alias of the same bit (STIP) in mip when that bit is writable in mip.
128    // When STIP is not writable in mip (such as when menvcfg.STCE = 1), bit 5 of mvip is read-only zero.
129    // Todo: check mip writable when menvcfg.STCE = 1
130    regOut.STIP := Mux(this.menvcfg.STCE.asBool, 0.U, this.mip.STIP.asBool)
131    // Don't update mip.STIP when menvcfg.STCE is 1
132    toMip.STIP.valid := wen && !this.menvcfg.STCE.asBool
133    toMip.STIP.bits := wdata.STIP
134
135    // When bit 9 of mvien is zero, bit 9 of mvip is an alias of the software-writable bit 9 of mip (SEIP).
136    // But when bit 9 of mvien is one, bit 9 of mvip is a writable bit independent of mip.SEIP.
137    // Unlike for bit 1, changing the value of bit 9 of mvien does not affect the value of bit 9 of mvip.
138    toMip.SEIP.valid := wen && !this.mvien.SEIE.asUInt.asBool
139    toMip.SEIP.bits := wdata.SEIP
140    when (fromMip.SEIP.valid) {
141      reg.SEIP := fromMip.SEIP.bits
142    }
143
144    // write from sip
145    when (fromSip.SSIP.valid) {
146      reg.SSIP := fromSip.SSIP.bits
147    }
148
149    reg.getLocal lazyZip fromSip.getLocal lazyZip fromVSip.getLocal foreach { case (rLCIP, sipLCIP, vsipLCIP) =>
150      // sip should assert valid when mideleg=0 && mvien=1
151      when (sipLCIP.valid || vsipLCIP.valid) {
152        rLCIP := Mux1H(Seq(
153          sipLCIP .valid -> sipLCIP .bits,
154          vsipLCIP.valid -> vsipLCIP.bits,
155        ))
156      }
157    }
158  }).setAddr(CSRs.mvip)
159
160  val menvcfg = Module(new CSRModule("Menvcfg", new MEnvCfg))
161    .setAddr(CSRs.menvcfg)
162
163  val mcountinhibit = Module(new CSRModule("Mcountinhibit", new McountinhibitBundle))
164    .setAddr(CSRs.mcountinhibit)
165
166  val mhpmevents: Seq[CSRModule[_]] = (3 to 0x1F).map(num =>
167    Module(new CSRModule(s"Mhpmevent$num", new MhpmeventBundle) with HasPerfEventBundle {
168      regOut := this.perfEvents(num - 3)
169    })
170      .setAddr(CSRs.mhpmevent3 - 3 + num)
171  )
172
173  val mscratch = Module(new CSRModule("Mscratch"))
174    .setAddr(CSRs.mscratch)
175
176  val mepc = Module(new CSRModule("Mepc", new Epc) with TrapEntryMEventSinkBundle {
177    rdata := SignExt(Cat(reg.epc.asUInt, 0.U(1.W)), XLEN)
178  })
179    .setAddr(CSRs.mepc)
180
181  val mcause = Module(new CSRModule("Mcause", new CauseBundle) with TrapEntryMEventSinkBundle)
182    .setAddr(CSRs.mcause)
183
184  val mtval = Module(new CSRModule("Mtval", new XtvalBundle) with TrapEntryMEventSinkBundle)
185    .setAddr(CSRs.mtval)
186
187  val mip = Module(new CSRModule("Mip", new MipBundle)
188    with HasIpIeBundle
189    with HasExternalInterruptBundle
190    with HasMachineEnvBundle
191    with HasLocalInterruptReqBundle
192    with HasAIABundle
193  {
194    // Alias write in
195    val fromMvip = IO(Flipped(new MvipToMip))
196    val fromSip  = IO(Flipped(new SipToMip))
197    val fromVSip = IO(Flipped(new VSipToMip))
198    // Alias write out
199    val toMvip   = IO(new MipToMvip).connectZeroNonRW
200    val toHvip   = IO(new MipToHvip).connectZeroNonRW
201
202    // bit 1 SSIP
203    when (fromMvip.SSIP.valid || fromSip.SSIP.valid) {
204      reg.SSIP := Mux1H(Seq(
205        fromMvip.SSIP.valid -> fromMvip.SSIP.bits,
206        fromSip .SSIP.valid -> fromSip .SSIP.bits,
207      ))
208    }
209
210    // bit 2 VSSIP reg in hvip
211    // alias of hvip.VSSIP
212    toHvip.VSSIP.valid := wen
213    toHvip.VSSIP.bits  := wdata.VSSIP
214    regOut.VSSIP := hvip.VSSIP
215
216    // bit 3 MSIP is read-only in mip, and is written by accesses to memory-mapped control registers,
217    // which are used by remote harts to provide machine-level interprocessor interrupts.
218    regOut.MSIP := platformIRP.MSIP
219
220    // bit 5 STIP
221    // If the stimecmp (supervisor-mode timer compare) register is implemented(menvcfg.STCE=1), STIP is read-only in mip.
222    regOut.STIP := Mux(this.menvcfg.STCE.asBool, platformIRP.STIP, reg.STIP.asBool)
223    when ((wen || fromMvip.STIP.valid) && !this.menvcfg.STCE) {
224      reg.STIP := Mux1H(Seq(
225        wen -> wdata.STIP,
226        fromMvip.STIP.valid -> fromMvip.STIP.bits,
227      ))
228    }
229
230    // bit 6 VSTIP
231    regOut.VSTIP := hvip.VSTIP || platformIRP.VSTIP
232
233    // bit 7 MTIP is read-only in mip, and is cleared by writing to the memory-mapped machine-mode timer compare register
234    regOut.MTIP := platformIRP.MTIP
235
236    // bit 9 SEIP
237    // When bit 9 of mvien is zero, the value of bit 9 of mvip is logically ORed into the readable value of mip.SEIP.
238    // when bit 9 of mvien is one, bit SEIP in mip is read-only and does not include the value of bit 9 of mvip.
239    //
240    // As explained in this issue(https://github.com/riscv/riscv-aia/issues/64),
241    // when mvien[9]=0, mip.SEIP is a software-writable bit and is special in its read value, which is the logical-OR of
242    // mip.SEIP reg and other source from the interrupt controller.
243    // mvip.SEIP is alias of mip.SEIP's reg part, and is independent of the other source from the interrupt controller.
244    //
245    // mip.SEIP is implemented as the alias of mvip.SEIP when mvien=0
246    // the read valid of SEIP is ORed by mvip.SEIP and the other source from the interrupt controller.
247
248    toMvip.SEIP.valid := wen && !this.mvien.SSIE
249    toMvip.SEIP.bits := wdata.SEIP
250    // When mvien.SEIE = 0, mip.SEIP is alias of mvip.SEIP.
251    // Otherwise, mip.SEIP is read only 0
252    regOut.SEIP := Mux(!this.mvien.SEIE, this.mvip.SEIP.asUInt, 0.U)
253    rdataFields.SEIP := regOut.SEIP || platformIRP.SEIP || aiaToCSR.seip
254
255    // bit 10 VSEIP
256    regOut.VSEIP := hvip.VSEIP || platformIRP.VSEIP || hgeip.asUInt(hstatusVGEIN.asUInt)
257
258    // bit 11 MEIP is read-only in mip, and is set and cleared by a platform-specific interrupt controller.
259    // MEIP can from PLIC and IMSIC
260    regOut.MEIP := platformIRP.MEIP || aiaToCSR.meip
261
262    // bit 12 SGEIP
263    regOut.SGEIP := Cat(hgeip.asUInt & hgeie.asUInt).orR
264
265    // bit 13 LCOFIP
266    reg.LCOFIP := lcofiReq
267    when (fromSip.LCOFIP.valid || fromVSip.LCOFIP.valid) {
268      reg.LCOFIP := Mux1H(Seq(
269        fromSip.LCOFIP.valid  -> fromSip.LCOFIP.bits,
270        fromVSip.LCOFIP.valid -> fromVSip.LCOFIP.bits,
271      ))
272    }
273  }).setAddr(CSRs.mip)
274
275  val mtinst = Module(new CSRModule("Mtinst", new XtinstBundle) with TrapEntryMEventSinkBundle)
276    .setAddr(CSRs.mtinst)
277
278  val mtval2 = Module(new CSRModule("Mtval2", new Mtval2Bundle) with TrapEntryMEventSinkBundle)
279    .setAddr(CSRs.mtval2)
280
281  val mseccfg = Module(new CSRModule("Mseccfg", new CSRBundle {
282    val PMM   = RO(33, 32)
283    val SSEED = RO(     9)
284    val USEED = RO(     8)
285    val RLB   = RO(     2)
286    val MMWP  = RO(     1)
287    val MML   = RO(     0)
288  })).setAddr(CSRs.mseccfg)
289
290  val mcycle = Module(new CSRModule("Mcycle") with HasMachineCounterControlBundle {
291    when(w.wen) {
292      reg := w.wdata
293    }.elsewhen(!this.mcountinhibit.CY.asUInt.asBool) {
294      reg := reg.ALL.asUInt + 1.U
295    }.otherwise {
296      reg := reg
297    }
298  }).setAddr(CSRs.mcycle)
299
300
301  val minstret = Module(new CSRModule("Minstret") with HasMachineCounterControlBundle with HasRobCommitBundle {
302    when(w.wen) {
303      reg := w.wdata
304    }.elsewhen(!this.mcountinhibit.IR && robCommit.instNum.valid) {
305      reg := reg.ALL.asUInt + robCommit.instNum.bits
306    }.otherwise {
307      reg := reg
308    }
309  }).setAddr(CSRs.minstret)
310
311  val mhpmcounters: Seq[CSRModule[_]] = (3 to 0x1F).map(num =>
312    Module(new CSRModule(s"Mhpmcounter$num", new MhpmcounterBundle) with HasMachineCounterControlBundle with HasPerfCounterBundle {
313      val countingInhibit = this.mcountinhibit.asUInt(num) | !countingEn
314      val counterAdd = reg.ALL.asUInt +& perf.value
315      when (w.wen) {
316        reg := w.wdata
317      }.elsewhen (perf.value =/= 0.U && !countingInhibit) {
318        reg := counterAdd.tail(1)
319      }.otherwise {
320        reg := reg
321      }
322      // Count overflow never results from writes to the mhpmcountern or mhpmeventn registers, only from
323      // hardware increments of counter registers.
324      toMhpmeventOF := !countingInhibit & counterAdd.head(1)
325    }).setAddr(CSRs.mhpmcounter3 - 3 + num)
326  )
327
328  val mvendorid = Module(new CSRModule("Mvendorid") { rdata := 0.U })
329    .setAddr(CSRs.mvendorid)
330
331  // architecture id for XiangShan is 25
332  // see https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md
333  val marchid = Module(new CSRModule("Marchid", new CSRBundle {
334    val ALL = MarchidField(63, 0).withReset(MarchidField.XSArchid)
335  })).setAddr(CSRs.marchid)
336
337  val mimpid = Module(new CSRModule("Mimpid", new CSRBundle {
338    val ALL = RO(0).withReset(0.U)
339  }))
340    .setAddr(CSRs.mimpid)
341
342  val mhartid = Module(new CSRModule("Mhartid", new CSRBundle {
343    val ALL = RO(7, 0)
344  }) {
345    val hartid = IO(Input(UInt(hartIdLen.W)))
346    this.reg.ALL := RegEnable(hartid, reset.asBool)
347  })
348    .setAddr(CSRs.mhartid)
349
350  val mconfigptr = Module(new CSRModule("Mconfigptr", new CSRBundle {
351    val ALL = RO(63, 0)
352  }))
353    .setAddr(CSRs.mconfigptr)
354
355  val mstateen0 = Module(new CSRModule("Mstateen", new MstateenBundle0)).setAddr(CSRs.mstateen0)
356
357  val machineLevelCSRMods: Seq[CSRModule[_]] = Seq(
358    mstatus,
359    misa,
360    medeleg,
361    mideleg,
362    mie,
363    mtvec,
364    mcounteren,
365    mvien,
366    mvip,
367    menvcfg,
368    mcountinhibit,
369    mscratch,
370    mepc,
371    mcause,
372    mtval,
373    mip,
374    mtinst,
375    mtval2,
376    mseccfg,
377    mcycle,
378    minstret,
379    mvendorid,
380    marchid,
381    mimpid,
382    mhartid,
383    mconfigptr,
384    mstateen0,
385  ) ++ mhpmevents ++ mhpmcounters
386
387  val machineLevelCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from(
388    machineLevelCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata))).iterator
389  )
390
391  val machineLevelCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
392    machineLevelCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt)).iterator
393  )
394
395  // read/write/update mhpmevents -> read/write/update perfEvents
396  val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++
397    List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++
398    List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++
399    List.fill(5)(RegInit("hc0300c0300".U(XLEN.W)))
400
401  mhpmevents.foreach { mod =>
402    mod match {
403      case m: HasPerfEventBundle =>
404        m.perfEvents := perfEvents
405      case _ =>
406    }
407  }
408
409}
410
411class MstatusBundle extends CSRBundle {
412
413  val SIE  = CSRRWField     (1).withReset(0.U)
414  val MIE  = CSRRWField     (3).withReset(0.U)
415  val SPIE = CSRRWField     (5).withReset(0.U)
416  val UBE  = CSRROField     (6).withReset(0.U)
417  val MPIE = CSRRWField     (7).withReset(0.U)
418  val SPP  = CSRRWField     (8).withReset(0.U)
419  val VS   = ContextStatus  (10,  9).withReset(ContextStatus.Off)
420  val MPP  = PrivMode       (12, 11).withReset(PrivMode.U)
421  val FS   = ContextStatus  (14, 13).withReset(ContextStatus.Off)
422  val XS   = ContextStatusRO(16, 15).withReset(0.U)
423  val MPRV = CSRRWField     (17).withReset(0.U)
424  val SUM  = CSRRWField     (18).withReset(0.U)
425  val MXR  = CSRRWField     (19).withReset(0.U)
426  val TVM  = CSRRWField     (20).withReset(0.U)
427  val TW   = CSRRWField     (21).withReset(0.U)
428  val TSR  = CSRRWField     (22).withReset(0.U)
429  val UXL  = XLENField      (33, 32).withReset(XLENField.XLEN64)
430  val SXL  = XLENField      (35, 34).withReset(XLENField.XLEN64)
431  val SBE  = CSRROField     (36).withReset(0.U)
432  val MBE  = CSRROField     (37).withReset(0.U)
433  val GVA  = CSRRWField     (38).withReset(0.U)
434  val MPV  = VirtMode       (39).withReset(0.U)
435  val SD   = CSRROField     (63,
436    (_, _) => FS === ContextStatus.Dirty || VS === ContextStatus.Dirty
437  )
438}
439
440class MstatusModule(implicit override val p: Parameters) extends CSRModule("MStatus", new MstatusBundle)
441  with TrapEntryMEventSinkBundle
442  with TrapEntryHSEventSinkBundle
443  with DretEventSinkBundle
444  with MretEventSinkBundle
445  with SretEventSinkBundle
446  with HasRobCommitBundle
447{
448  val mstatus = IO(Output(bundle))
449  val sstatus = IO(Output(new SstatusBundle))
450  val sstatusRdata = IO(Output(UInt(64.W)))
451
452  val wAliasSstatus = IO(Input(new CSRAddrWriteBundle(new SstatusBundle)))
453
454  // write connection
455  this.wfn(reg)(Seq(wAliasSstatus))
456
457  when (robCommit.fsDirty || writeFCSR) {
458    assert(reg.FS =/= ContextStatus.Off, "The [m|s]status.FS should not be Off when set dirty, please check decode")
459    reg.FS := ContextStatus.Dirty
460  }
461
462  when (robCommit.vsDirty || writeVCSR) {
463    assert(reg.VS =/= ContextStatus.Off, "The [m|s]status.VS should not be Off when set dirty, please check decode")
464    reg.VS := ContextStatus.Dirty
465  }
466
467  // read connection
468  mstatus :|= reg
469  sstatus := mstatus
470  rdata := mstatus.asUInt
471  sstatusRdata := sstatus.asUInt
472}
473
474class MisaBundle extends CSRBundle {
475  // Todo: reset with ISA string
476  val A = RO( 0).withReset(1.U) // Atomic extension
477  val B = RO( 1).withReset(0.U) // Reserved
478  val C = RO( 2).withReset(1.U) // Compressed extension
479  val D = RO( 3).withReset(1.U) // Double-precision floating-point extension
480  val E = RO( 4).withReset(0.U) // RV32E/64E base ISA
481  val F = RO( 5).withReset(1.U) // Single-precision floating-point extension
482  val G = RO( 6).withReset(0.U) // Reserved
483  val H = RO( 7).withReset(1.U) // Hypervisor extension
484  val I = RO( 8).withReset(1.U) // RV32I/64I/128I base ISA
485  val J = RO( 9).withReset(0.U) // Reserved
486  val K = RO(10).withReset(0.U) // Reserved
487  val L = RO(11).withReset(0.U) // Reserved
488  val M = RO(12).withReset(1.U) // Integer Multiply/Divide extensi
489  val N = RO(13).withReset(0.U) // Tentatively reserved for User-Level Interrupts extension
490  val O = RO(14).withReset(0.U) // Reserved
491  val P = RO(15).withReset(0.U) // Tentatively reserved for Packed-SIMD extension
492  val Q = RO(16).withReset(0.U) // Quad-precision floating-point extension
493  val R = RO(17).withReset(0.U) // Reserved
494  val S = RO(18).withReset(1.U) // Supervisor mode implemented
495  val T = RO(19).withReset(0.U) // Reserved
496  val U = RO(20).withReset(1.U) // User mode implemented
497  val V = RO(21).withReset(1.U) // Vector extension
498  val W = RO(22).withReset(0.U) // Reserved
499  val X = RO(23).withReset(0.U) // Non-standard extensions present
500  val Y = RO(24).withReset(0.U) // Reserved
501  val Z = RO(25).withReset(0.U) // Reserved
502  val MXL = XLENField(63, 62).withReset(XLENField.XLEN64)
503
504  def getISAString = this.getFields.filter(x => x != MXL && x.init.litValue == 1).sortBy(_.lsb).map(x => ('A' + x.msb).toChar).mkString
505}
506
507class MedelegBundle extends ExceptionBundle {
508  this.getALL.foreach(_.setRW().withReset(0.U))
509  this.EX_MCALL.setRO().withReset(0.U) // never delegate machine level ecall
510  this.EX_BP.setRO().withReset(0.U)    // Parter 5.4 in debug spec. tcontrol is implemented. medeleg [3] is hard-wired to 0.
511}
512
513class MidelegBundle extends InterruptBundle {
514  this.getALL.foreach(_.setRW().withReset(0.U))
515  // Don't delegate Machine level interrupts
516  this.getM.foreach(_.setRO().withReset(0.U))
517  // Ref: 13.4.2. Machine Interrupt Delegation Register (mideleg)
518  // When the hypervisor extension is implemented, bits 10, 6, and 2 of mideleg (corresponding to the standard VS-level
519  // interrupts) are each read-only one.
520  this.getVS.foreach(_.setRO().withReset(1.U))
521  // bit 12 of mideleg (corresponding to supervisor-level guest external interrupts) is also read-only one.
522  // VS-level interrupts and guest external interrupts are always delegated past M-mode to HS-mode.
523  this.SGEI.setRO().withReset(1.U)
524  this.getLocal.foreach(_.setRO().withReset(0.U))
525  this.LCOFI.setRW().withReset(0.U)
526}
527
528class MieBundle extends InterruptEnableBundle {
529  this.getNonLocal.foreach(_.setRW().withReset(0.U))
530}
531
532class MipBundle extends InterruptPendingBundle {
533  // Ref: riscv privileged spec - 18.4.3. Machine Interrupt (mip and mie) Registers
534  // Bits SGEIP, VSEIP, VSTIP, and VSSIP in mip are aliases for the same bits in hypervisor CSR hip
535  //
536  // We implement SGEIP, VSEIP, VSTIP, and VSSIP in mip are registers,
537  // while these bits in hip are aliases for the same bits in mip.
538  //
539  // Ref: riscv interrupt spec - 2.1 Machine-level CSRs
540  // Existing CSRs mie, mip, and mideleg are widended to 64 bits to support a total of 64 interrupt causes.
541  this.getHS.foreach(_.setRW().withReset(0.U))
542  this.getVS.foreach(_.setRW().withReset(0.U))
543  this.LCOFIP.setRW().withReset(0.U)
544}
545
546class MvienBundle extends InterruptEnableBundle {
547  // Ref: riscv interrupt spec - 5.3 Interrupt filtering and virtual interrupts for supervisor level
548  // It is strongly recommended that bit 9 of mvien be writable.
549  // It is strongly recommended that bit 1 of mvien also be writable.
550  // A bit in mvien can be set to 1 only for major interrupts 1, 9, and 13–63.
551  this.SSIE.setRW().withReset(0.U)
552  this.SEIE.setRW().withReset(0.U)
553  this.getLocal.foreach(_.setRW().withReset(0.U))
554}
555
556class MvipBundle extends InterruptPendingBundle {
557  this.getHS.foreach(_.setRW().withReset(0.U))
558  this.getLocal.foreach(_.setRW().withReset(0.U))
559}
560
561class Epc extends CSRBundle {
562  import CSRConfig._
563
564  val epc = RW(VaddrMaxWidth - 1, 1).withReset(0.U)
565}
566
567class McountinhibitBundle extends CSRBundle {
568  val CY = RW(0).withReset(0.U)
569  val IR = RW(2).withReset(0.U)
570  val HPM3 = RW(31, 3).withReset(0.U)
571}
572
573class Mtval2Bundle extends FieldInitBundle
574
575class MhpmcounterBundle extends FieldInitBundle
576
577// todo: for the future, delete bypass between mhpmevents and perfEvents
578class MhpmeventBundle extends CSRBundle {
579  val OF    = RW(63).withReset(0.U)
580  val MINH  = RW(62).withReset(0.U)
581  val SINH  = RW(61).withReset(0.U)
582  val UINH  = RW(60).withReset(0.U)
583  val VSINH = RW(59).withReset(0.U)
584  val VUINH = RW(58).withReset(0.U)
585}
586
587class MEnvCfg extends EnvCfg {
588  if (CSRConfig.EXT_SSTC) {
589    this.STCE.setRW().withReset(1.U)
590  }
591}
592
593object MarchidField extends CSREnum with ROApply {
594  val XSArchid = Value(25.U)
595}
596
597class MieToHie extends Bundle {
598  val VSSIE = ValidIO(RW(0))
599  val VSTIE = ValidIO(RW(0))
600  val VSEIE = ValidIO(RW(0))
601  val SGEIE = ValidIO(RW(0))
602}
603
604class MvipToMip extends IpValidBundle {
605  this.getHS.foreach(_.bits.setRW())
606}
607
608class HipToMip extends IpValidBundle {
609  // Only hip.VSSIP is writable
610  this.VSSIP.bits.setRW()
611}
612
613class VSipToMip extends IpValidBundle {
614  this.LCOFIP.bits.setRW()
615}
616
617class MipToHvip extends IpValidBundle {
618  this.VSSIP.bits.setRW()
619}
620
621class MipToMvip extends IpValidBundle {
622  this.SEIP.bits.setRW()
623}
624
625trait HasMipToAlias { self: CSRModule[_] =>
626  val mipAlias = Output(new MipBundle)
627}
628
629trait HasMachineDelegBundle { self: CSRModule[_] =>
630  val mideleg = IO(Input(new MidelegBundle))
631  val medeleg = IO(Input(new MedelegBundle))
632}
633
634trait HasExternalInterruptBundle {
635  val platformIRP = IO(new Bundle {
636    val MEIP  = Input(Bool())
637    val MTIP  = Input(Bool())
638    val MSIP  = Input(Bool())
639    val SEIP  = Input(Bool())
640    val STIP  = Input(Bool())
641    val VSEIP = Input(Bool())
642    val VSTIP = Input(Bool())
643    // debug interrupt from debug module
644    val debugIP = Input(Bool())
645  })
646}
647
648trait HasMachineCounterControlBundle { self: CSRModule[_] =>
649  val mcountinhibit = IO(Input(new McountinhibitBundle))
650}
651
652trait HasRobCommitBundle { self: CSRModule[_] =>
653  val robCommit = IO(Input(new RobCommitCSR))
654  val writeFCSR = IO(Input(Bool()))
655  val writeVCSR = IO(Input(Bool()))
656  val isVirtMode = IO(Input(Bool()))
657}
658
659trait HasMachineEnvBundle { self: CSRModule[_] =>
660  val menvcfg = IO(Input(new MEnvCfg))
661}
662
663trait HasPerfCounterBundle { self: CSRModule[_] =>
664  val countingEn    = IO(Input(Bool()))
665  val perf          = IO(Input(new PerfEvent))
666  val toMhpmeventOF = IO(Output(Bool()))
667}
668
669trait HasPerfEventBundle { self: CSRModule[_] =>
670  val perfEvents = IO(Input(Vec(perfCntNum, UInt(XLEN.W))))
671}
672
673trait HasLocalInterruptReqBundle { self: CSRModule[_] =>
674  val lcofiReq = IO(Input(Bool()))
675}