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