xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala (revision 6306fe335c2bca9aa17b8975c11e0e6116b494fd)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import org.chipsalliance.cde.config.Parameters
6import utility.SignExt
7import xiangshan.backend.fu.NewCSR.CSRBundles._
8import xiangshan.backend.fu.NewCSR.CSRDefines._
9import xiangshan.backend.fu.NewCSR.CSRDefines.{
10  CSRROField => RO,
11  CSRRWField => RW,
12  _
13}
14import xiangshan.backend.fu.NewCSR.CSREvents._
15
16import scala.collection.immutable.SeqMap
17
18trait MachineLevel { self: NewCSR =>
19  val mstatus = Module(new MstatusModule)
20    .setAddr(0x300)
21
22  val misa = Module(new CSRModule("Misa", new MisaBundle))
23    .setAddr(0x301)
24
25  println(s"[CSR] supported isa ext: ${misa.bundle.getISAString}")
26
27  val medeleg = Module(new CSRModule("Medeleg", new MedelegBundle))
28    .setAddr(0x302)
29
30  val mideleg = Module(new CSRModule("Mideleg", new MidelegBundle))
31    .setAddr(0x303)
32
33  val mie = Module(new CSRModule("Mie", new MieBundle) with HypervisorBundle {
34    val toHie = IO(new MieToHie)
35    val fromSie = IO(Flipped(new SieToMie))
36
37    when (fromSie.SSIE.valid) { reg.SSIE := fromSie.SSIE.bits }
38    when (fromSie.STIE.valid) { reg.STIE := fromSie.STIE.bits }
39    when (fromSie.SEIE.valid) { reg.SEIE := fromSie.SEIE.bits }
40
41    toHie.VSSIE.valid := wen
42    toHie.VSTIE.valid := wen
43    toHie.VSEIE.valid := wen
44    toHie.SGEIE.valid := wen
45    toHie.VSSIE.bits := wdata.VSSIE
46    toHie.VSTIE.bits := wdata.VSTIE
47    toHie.VSEIE.bits := wdata.VSEIE
48    toHie.SGEIE.bits := wdata.SGEIE
49
50    regOut.VSSIE := hie.VSSIE
51    regOut.VSTIE := hie.VSTIE
52    regOut.VSEIE := hie.VSEIE
53    regOut.SGEIE := hie.SGEIE
54  }).setAddr(0x304)
55
56  val mtvec = Module(new CSRModule("Mtvec", new XtvecBundle))
57    .setAddr(0x305)
58
59  // Todo: support "Stimecmp/Vstimecmp" Extension, Version 1.0.0
60  // Todo: support Sscounterenw Extension
61  val mcounteren = Module(new CSRModule("Mcounteren", new Counteren))
62    .setAddr(0x306)
63
64  val mvien = Module(new CSRModule("Mvien", new MvienBundle))
65    .setAddr(0x308)
66
67  val mvip = Module(new CSRModule("Mvip", new MvipBundle) with HasMachineInterruptBundle {
68    val toMip = IO(new MvipToMip)
69
70    // When bit 1 of mvien is zero, bit 1(SSIP) of mvip is an alias of the same bit (SSIP) of mip.
71    // But when bit 1 of mvien is one, bit 1(SSIP) of mvip is a separate writable bit independent of mip.SSIP.
72    // When the value of bit 1 of mvien is changed from zero to one, the value of bit 1 of mvip becomes UNSPECIFIED.
73    // XS will keep the value in mvip.SSIP when mvien.SSIE is changed from zero to one
74    regOut.SSIP := Mux(!mvien.SSIE.asUInt.asBool, mip.SSIP, reg.SSIP)
75    toMip.SSIP.valid := wen && !mvien.SSIE.asUInt.asBool
76    toMip.SSIP.bits := wdata.SSIP
77    reg.SSIP := Mux(wen && mvien.SSIE.asUInt.asBool, wdata.SSIP, reg.SSIP)
78
79    // Bit 5 of mvip is an alias of the same bit (STIP) in mip when that bit is writable in mip.
80    // When STIP is not writable in mip (such as when menvcfg.STCE = 1), bit 5 of mvip is read-only zero.
81    // Todo: check mip writable when menvcfg.STCE = 1
82    regOut.STIP := mip.STIP
83    toMip.STIP.valid := wen
84    toMip.STIP.bits := wdata.STIP
85
86    // When bit 9 of mvien is zero, bit 9 of mvip is an alias of the software-writable bit 9 of mip (SEIP).
87    // But when bit 9 of mvien is one, bit 9 of mvip is a writable bit independent of mip.SEIP.
88    // Unlike for bit 1, changing the value of bit 9 of mvien does not affect the value of bit 9 of mvip.
89    regOut.SEIP := Mux(!mvien.SEIE.asUInt.asBool, mip.SEIP, reg.SEIP)
90    toMip.SEIP.valid := wen && !mvien.SEIE.asUInt.asBool
91    toMip.SEIP.bits := wdata.SEIP
92    reg.SEIP := Mux(wen && mvien.SEIE.asUInt.asBool, wdata.SEIP, reg.SEIP)
93  }).setAddr(0x309)
94
95  val menvcfg = Module(new CSRModule("Menvcfg", new Envcfg))
96    .setAddr(0x30A)
97
98  val mcountinhibit = Module(new CSRModule("Mcountinhibit", new McountinhibitBundle))
99    .setAddr(0x320)
100
101  val mhpmevents: Seq[CSRModule[_]] = (3 to 0x1F).map(num =>
102    Module(new CSRModule(s"Mhpmevent$num"))
103      .setAddr(0x320 + num)
104  )
105
106  val mscratch = Module(new CSRModule("Mscratch"))
107    .setAddr(0x340)
108
109  val mepc = Module(new CSRModule("Mepc", new Epc) with TrapEntryMEventSinkBundle {
110    rdata := SignExt(Cat(reg.epc.asUInt, 0.U(1.W)), XLEN)
111  })
112    .setAddr(0x341)
113
114  val mcause = Module(new CSRModule("Mcause", new CauseBundle) with TrapEntryMEventSinkBundle)
115    .setAddr(0x342)
116
117  val mtval = Module(new CSRModule("Mtval") with TrapEntryMEventSinkBundle)
118    .setAddr(0x343)
119
120  val mip = Module(new CSRModule("Mip", new MipBundle) with HasMachineInterruptBundle with HasExternalInterruptBundle {
121    val fromMvip = IO(Flipped(new MvipToMip))
122    val fromSip = IO(Flipped(new SipToMip))
123
124    // When bit 9 of mvien is zero, the value of bit 9 of mvip is logically ORed into the readable value of mip.SEIP.
125    // 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.
126    rdataFields.SEIP := Mux(!mvien.SEIE.asUInt.asBool, reg.SEIP.asUInt.asBool | mvip.SEIP.asUInt.asBool | platformIRP.SEIP, platformIRP.SEIP)
127    when (wen && !mvien.SEIE.asUInt.asBool) { reg.SEIP := reg.SEIP }
128    when (fromMvip.SSIP.valid) { reg.SSIP := fromMvip.SSIP.bits }
129    when (fromMvip.STIP.valid) { reg.STIP := fromMvip.STIP.bits }
130    when (fromMvip.SEIP.valid) { reg.SEIP := fromMvip.SEIP.bits }
131    when (fromSip.SSIP.valid) { reg.SSIP := fromSip.SSIP.bits }
132
133    // MEIP is read-only in mip, and is set and cleared by a platform-specific interrupt controller.
134    rdataFields.MEIP := platformIRP.MEIP
135    // MTIP is read-only in mip, and is cleared by writing to the memory-mapped machine-mode timer compare register
136    rdataFields.MTIP := platformIRP.MTIP
137    // MSIP is read-only in mip, and is written by accesses to memory-mapped control registers,
138    // which are used by remote harts to provide machine-level interprocessor interrupts.
139    rdataFields.MSIP := platformIRP.MSIP
140  }).setAddr(0x344)
141
142  val mtinst = Module(new CSRModule("Mtinst") with TrapEntryMEventSinkBundle)
143    .setAddr(0x34A)
144
145  val mtval2 = Module(new CSRModule("Mtval2") with TrapEntryMEventSinkBundle)
146    .setAddr(0x34B)
147
148  val mseccfg = Module(new CSRModule("Mseccfg", new CSRBundle {
149    val PMM   = RO(33, 32)
150    val SSEED = RO(     9)
151    val USEED = RO(     8)
152    val RLB   = RO(     2)
153    val MMWP  = RO(     1)
154    val MML   = RO(     0)
155  })).setAddr(0x747)
156
157  val mcycle = Module(new CSRModule("Mcycle") with HasMachineCounterControlBundle {
158    reg.ALL := Mux(!mcountinhibit.CY.asUInt.asBool, reg.ALL.asUInt + 1.U, reg.ALL.asUInt)
159  }).setAddr(0xB00)
160
161  val minstret = Module(new CSRModule("Minstret") with HasMachineCounterControlBundle with HasRobCommitBundle {
162    reg.ALL := Mux(!mcountinhibit.IR.asUInt.asBool && robCommit.instNum.valid, reg.ALL.asUInt + robCommit.instNum.bits, reg.ALL.asUInt)
163  })
164
165  // Todo: guarded by mcountinhibit
166  val mhpmcounters: Seq[CSRModule[_]] = (3 to 0x1F).map(num =>
167    Module(new CSRModule(s"Mhpmcounter$num") {
168
169    }).setAddr(0xB00 + num)
170  )
171
172  val mvendorid = Module(new CSRModule("Mvendorid") { rdata := 0.U })
173    .setAddr(0xF11)
174
175  // architecture id for XiangShan is 25
176  // see https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md
177  val marchid = Module(new CSRModule("Marchid", new CSRBundle {
178    val ALL = MarchidField(63, 0).withReset(MarchidField.XSArchid)
179  })).setAddr(0xF12)
180
181  val mimpid = Module(new CSRModule("Mimpid", new CSRBundle {
182    val ALL = RO(0).withReset(0.U)
183  }))
184    .setAddr(0xF13)
185
186  val mhartid = Module(new CSRModule("Mhartid", new CSRBundle {
187    val ALL = RO(7, 0)
188  }) {
189    val hartid = IO(Input(UInt(hartIdLen.W)))
190    this.reg.ALL := RegEnable(hartid, reset.asBool)
191  })
192    .setAddr(0xF14)
193
194  val mconfigptr = Module(new CSRModule("Mconfigptr"))
195    .setAddr(0xF15)
196
197  val machineLevelCSRMods: Seq[CSRModule[_]] = Seq(
198    mstatus,
199    misa,
200    medeleg,
201    mideleg,
202    mie,
203    mtvec,
204    mcounteren,
205    mvien,
206    mvip,
207    menvcfg,
208    mcountinhibit,
209    mscratch,
210    mepc,
211    mcause,
212    mtval,
213    mip,
214    mtinst,
215    mtval2,
216    mseccfg,
217    mcycle,
218    minstret,
219    mvendorid,
220    marchid,
221    mimpid,
222    mhartid,
223    mconfigptr,
224  ) ++ mhpmevents ++ mhpmcounters
225
226  val machineLevelCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], Data)] = SeqMap.from(
227    machineLevelCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata))).iterator
228  )
229
230  val machineLevelCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
231    machineLevelCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt)).iterator
232  )
233}
234
235class MstatusBundle extends CSRBundle {
236
237  val SIE  = CSRRWField     (1).withReset(0.U)
238  val MIE  = CSRRWField     (3).withReset(0.U)
239  val SPIE = CSRRWField     (5).withReset(0.U)
240  val UBE  = CSRROField     (6).withReset(0.U)
241  val MPIE = CSRRWField     (7).withReset(0.U)
242  val SPP  = CSRRWField     (8).withReset(0.U)
243  val VS   = ContextStatus  (10,  9).withReset(ContextStatus.Off)
244  val MPP  = PrivMode       (12, 11).withReset(PrivMode.U)
245  val FS   = ContextStatus  (14, 13).withReset(ContextStatus.Off)
246  val XS   = ContextStatusRO(16, 15).withReset(0.U)
247  val MPRV = CSRRWField     (17).withReset(0.U)
248  val SUM  = CSRRWField     (18).withReset(0.U)
249  val MXR  = CSRRWField     (19).withReset(0.U)
250  val TVM  = CSRRWField     (20).withReset(0.U)
251  val TW   = CSRRWField     (21).withReset(0.U)
252  val TSR  = CSRRWField     (22).withReset(0.U)
253  val UXL  = XLENField      (33, 32).withReset(XLENField.XLEN64)
254  val SXL  = XLENField      (35, 34).withReset(XLENField.XLEN64)
255  val SBE  = CSRROField     (36).withReset(0.U)
256  val MBE  = CSRROField     (37).withReset(0.U)
257  val GVA  = CSRRWField     (38).withReset(0.U)
258  val MPV  = VirtMode       (39).withReset(0.U)
259  val SD   = CSRROField     (63,
260    (_, _) => FS === ContextStatus.Dirty || VS === ContextStatus.Dirty
261  )
262}
263
264class MstatusModule(implicit override val p: Parameters) extends CSRModule("MStatus", new MstatusBundle)
265  with TrapEntryMEventSinkBundle
266  with TrapEntryHSEventSinkBundle
267  with DretEventSinkBundle
268  with MretEventSinkBundle
269  with SretEventSinkBundle
270  with HasRobCommitBundle
271{
272  val mstatus = IO(Output(bundle))
273  val sstatus = IO(Output(new SstatusBundle))
274
275  val wAliasSstatus = IO(Input(new CSRAddrWriteBundle(new SstatusBundle)))
276
277  // write connection
278  this.wfn(reg)(Seq(wAliasSstatus))
279
280  when (robCommit.fsDirty) {
281    assert(reg.FS =/= ContextStatus.Off, "The [m|s]status.FS should not be Off when set dirty, please check decode")
282    reg.FS := ContextStatus.Dirty
283  }
284
285  when (robCommit.vsDirty) {
286    assert(reg.VS =/= ContextStatus.Off, "The [m|s]status.VS should not be Off when set dirty, please check decode")
287    reg.VS := ContextStatus.Dirty
288  }
289
290  // read connection
291  mstatus :|= reg
292  sstatus := mstatus
293  rdata := mstatus.asUInt
294}
295
296class MisaBundle extends CSRBundle {
297  // Todo: reset with ISA string
298  val A = RO( 0).withReset(1.U) // Atomic extension
299  val B = RO( 1).withReset(0.U) // Reserved
300  val C = RO( 2).withReset(1.U) // Compressed extension
301  val D = RO( 3).withReset(1.U) // Double-precision floating-point extension
302  val E = RO( 4).withReset(0.U) // RV32E/64E base ISA
303  val F = RO( 5).withReset(1.U) // Single-precision floating-point extension
304  val G = RO( 6).withReset(0.U) // Reserved
305  val H = RO( 7).withReset(1.U) // Hypervisor extension
306  val I = RO( 8).withReset(1.U) // RV32I/64I/128I base ISA
307  val J = RO( 9).withReset(0.U) // Reserved
308  val K = RO(10).withReset(0.U) // Reserved
309  val L = RO(11).withReset(0.U) // Reserved
310  val M = RO(12).withReset(1.U) // Integer Multiply/Divide extensi
311  val N = RO(13).withReset(0.U) // Tentatively reserved for User-Level Interrupts extension
312  val O = RO(14).withReset(0.U) // Reserved
313  val P = RO(15).withReset(0.U) // Tentatively reserved for Packed-SIMD extension
314  val Q = RO(16).withReset(0.U) // Quad-precision floating-point extension
315  val R = RO(17).withReset(0.U) // Reserved
316  val S = RO(18).withReset(1.U) // Supervisor mode implemented
317  val T = RO(19).withReset(0.U) // Reserved
318  val U = RO(20).withReset(1.U) // User mode implemented
319  val V = RO(21).withReset(1.U) // Vector extension
320  val W = RO(22).withReset(0.U) // Reserved
321  val X = RO(23).withReset(0.U) // Non-standard extensions present
322  val Y = RO(24).withReset(0.U) // Reserved
323  val Z = RO(25).withReset(0.U) // Reserved
324  val MXL = XLENField(63, 62).withReset(XLENField.XLEN64)
325
326  def getISAString = this.getFields.filter(x => x != MXL && x.init.litValue == 1).sortBy(_.lsb).map(x => ('A' + x.msb).toChar).mkString
327}
328
329class MedelegBundle extends ExceptionBundle {
330  this.getALL.foreach(_.setRW().withReset(0.U))
331  this.EX_MCALL.setRO().withReset(0.U) // never delegate machine level ecall
332}
333
334class MidelegBundle extends InterruptBundle {
335  this.getALL.foreach(_.setRW().withReset(0.U))
336  // Don't delegate Machine level interrupts
337  this.getM.foreach(_.setRO().withReset(0.U))
338  // Ref: 13.4.2. Machine Interrupt Delegation Register (mideleg)
339  // When the hypervisor extension is implemented, bits 10, 6, and 2 of mideleg (corresponding to the standard VS-level
340  // interrupts) are each read-only one.
341  this.getVS.foreach(_.setRO().withReset(1.U))
342  // bit 12 of mideleg (corresponding to supervisor-level guest external interrupts) is also read-only one.
343  // VS-level interrupts and guest external interrupts are always delegated past M-mode to HS-mode.
344  this.SGEI.setRO().withReset(1.U)
345}
346
347class MieBundle extends InterruptEnableBundle {
348  this.getALL.foreach(_.setRW().withReset(0.U))
349  this.SGEIE.setRO().withReset(0.U)
350  this.getVS.foreach(_.setRO().withReset(0.U))
351  // Todo: remove this after more enable bits supported in NEMU
352  this.getSOC.foreach(_.setRO().withReset(0.U))
353}
354
355class MipBundle extends InterruptPendingBundle {
356  this.getALL.foreach(_.setRW().withReset(0.U))
357  this.getM.foreach(_.setRO().withReset(0.U))
358  // Todo: remove this after more enable bits supported in NEMU
359  this.getSOC.foreach(_.setRO().withReset(0.U))
360}
361
362class MvienBundle extends CSRBundle {
363  // Ref: riscv interrupt spec - 5.3 Interrupt filtering and virtual interrupts for supervisor level
364  // It is strongly recommended that bit 9 of mvien be writable.
365  // It is strongly recommended that bit 1 of mvien also be writable.
366  val SSIE     = RW(1)
367  val SEIE     = RW(9)
368  val OTHERIE  = RW(63, 13)
369}
370
371class MvipBundle extends CSRBundle {
372  // When bit 1 of mvien is zero, bit 1(SSIP) of mvip is an alias of the same bit (SSIP) of mip.
373  // But when bit 1 of mvien is one, bit 1(SSIP) of mvip is a separate writable bit independent of mip.SSIP.
374  // When the value of bit 1 of mvien is changed from zero to one, the value of bit 1 of mvip becomes UNSPECIFIED.
375  val SSIP     = RW(1)
376  // Bit 5 of mvip is an alias of the same bit (STIP) in mip when that bit is writable in mip.
377  // When STIP is not writable in mip (such as when menvcfg.STCE = 1), bit 5 of mvip is read-only zero.
378  val STIP     = RW(5)
379  // When bit 9 of mvien is zero, bit 9 of mvip is an alias of the software-writable bit 9 of mip (SEIP).
380  // But when bit 9 of mvien is one, bit 9 of mvip is a writable bit independent of mip.SEIP.
381  // Unlike for bit 1, changing the value of bit 9 of mvien does not affect the value of bit 9 of mvip.
382  val SEIP     = RW(9)
383  val OTHERIP  = RW(63, 13)
384}
385
386class Epc extends CSRBundle {
387  import CSRConfig._
388
389  val epc = RW(VaddrMaxWidth - 1, 1)
390}
391
392class McountinhibitBundle extends CSRBundle {
393  val CY = RW(0)
394  val IR = RW(2)
395  val HPM3 = RW(31, 3)
396}
397
398object MarchidField extends CSREnum with ROApply {
399  val XSArchid = Value(25.U)
400}
401
402class MieToHie extends Bundle {
403  val VSSIE = ValidIO(RW(0))
404  val VSTIE = ValidIO(RW(0))
405  val VSEIE = ValidIO(RW(0))
406  val SGEIE = ValidIO(RW(0))
407}
408
409class MvipToMip extends Bundle {
410  val SSIP = ValidIO(RW(0))
411  val STIP = ValidIO(RW(0))
412  val SEIP = ValidIO(RW(0))
413}
414
415trait HasMachineInterruptBundle { self: CSRModule[_] =>
416  val mvien = IO(Input(new MvienBundle))
417  val mvip  = IO(Input(new MvipBundle))
418  val mip   = IO(Input(new MipBundle))
419  val mie   = IO(Input(new MieBundle))
420}
421
422trait HasMachineDelegBundle { self: CSRModule[_] =>
423  val mideleg = IO(Input(new MidelegBundle))
424  val medeleg = IO(Input(new MedelegBundle))
425}
426
427trait HasExternalInterruptBundle {
428  val platformIRP = IO(new Bundle {
429    val MEIP  = Input(Bool())
430    val MTIP  = Input(Bool())
431    val MSIP  = Input(Bool())
432    val SEIP  = Input(Bool())
433    val VSEIP = Input(Bool())
434    val VSTIP = Input(Bool())
435    // debug interrupt from debug module
436    val debugIP = Input(Bool())
437  })
438}
439
440trait HasMachineCounterControlBundle { self: CSRModule[_] =>
441  val mcountinhibit = IO(Input(new McountinhibitBundle))
442}
443
444trait HasRobCommitBundle { self: CSRModule[_] =>
445  val robCommit = IO(Input(new RobCommitCSR))
446}