xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala (revision 25dc4a827ee27e3ccbaf02e8e5134872cba28fcd)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import xiangshan.backend.fu.NewCSR.CSRBundles._
6import xiangshan.backend.fu.NewCSR.CSRDefines._
7import xiangshan.backend.fu.NewCSR.CSRDefines.{
8  CSRROField => RO,
9  CSRRWField => RW,
10  CSRWARLField => WARL,
11  CSRWLRLField => WLRL,
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    rdata.VSSIE := hie.VSSIE
51    rdata.VSTIE := hie.VSTIE
52    rdata.VSEIE := hie.VSEIE
53    rdata.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    rdata.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    rdata.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    rdata.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    .setAddr(0x341)
111
112  val mcause = Module(new CSRModule("Mcause", new CauseBundle) with TrapEntryMEventSinkBundle)
113    .setAddr(0x342)
114
115  val mtval = Module(new CSRModule("Mtval") with TrapEntryMEventSinkBundle)
116    .setAddr(0x343)
117
118  val mip = Module(new CSRModule("Mip", new MipBundle) with HasMachineInterruptBundle with HasExternalInterruptBundle {
119    val fromMvip = IO(Flipped(new MvipToMip))
120    val fromSip = IO(Flipped(new SipToMip))
121
122    // When bit 9 of mvien is zero, the value of bit 9 of mvip is logically ORed into the readable value of mip.SEIP.
123    // 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.
124    rdata.SEIP := Mux(!mvien.SEIE.asUInt.asBool, reg.SEIP.asUInt.asBool | mvip.SEIP.asUInt.asBool | platformIRP.SEIP, platformIRP.SEIP)
125    when (wen && !mvien.SEIE.asUInt.asBool) { reg.SEIP := reg.SEIP }
126    when (fromMvip.SSIP.valid) { reg.SSIP := fromMvip.SSIP.bits }
127    when (fromMvip.STIP.valid) { reg.STIP := fromMvip.STIP.bits }
128    when (fromMvip.SEIP.valid) { reg.SEIP := fromMvip.SEIP.bits }
129    when (fromSip.SSIP.valid) { reg.SSIP := fromSip.SSIP.bits }
130
131    // MEIP is read-only in mip, and is set and cleared by a platform-specific interrupt controller.
132    rdata.MEIP := platformIRP.MEIP
133    // MTIP is read-only in mip, and is cleared by writing to the memory-mapped machine-mode timer compare register
134    rdata.MTIP := platformIRP.MTIP
135    // MSIP is read-only in mip, and is written by accesses to memory-mapped control registers,
136    // which are used by remote harts to provide machine-level interprocessor interrupts.
137    rdata.MSIP := platformIRP.MSIP
138  }).setAddr(0x344)
139
140  val mtinst = Module(new CSRModule("Mtinst") with TrapEntryMEventSinkBundle)
141    .setAddr(0x34A)
142
143  val mtval2 = Module(new CSRModule("Mtval2") with TrapEntryMEventSinkBundle)
144    .setAddr(0x34B)
145
146  val mseccfg = Module(new CSRModule("Mseccfg", new CSRBundle {
147    val PMM   = RO(33, 32)
148    val SSEED = RO(     9)
149    val USEED = RO(     8)
150    val RLB   = RO(     2)
151    val MMWP  = RO(     1)
152    val MML   = RO(     0)
153  })).setAddr(0x747)
154
155  val mcycle = Module(new CSRModule("Mcycle") with HasMachineCounterControlBundle {
156    reg.ALL := Mux(!mcountinhibit.CY.asUInt.asBool, reg.ALL.asUInt + 1.U, reg.ALL.asUInt)
157  }).setAddr(0xB00)
158
159  val minstret = Module(new CSRModule("Minstret") with HasMachineCounterControlBundle with HasInstCommitBundle {
160    reg.ALL := Mux(!mcountinhibit.IR.asUInt.asBool && commitValid, reg.ALL.asUInt + commitInstNum, reg.ALL.asUInt)
161  })
162
163  // Todo: guarded by mcountinhibit
164  val mhpmcounters: Seq[CSRModule[_]] = (3 to 0x1F).map(num =>
165    Module(new CSRModule(s"Mhpmcounter$num") {
166
167    }).setAddr(0xB00 + num)
168  )
169
170  val mvendorid = Module(new CSRModule("Mvendorid") { rdata.ALL := 0.U })
171    .setAddr(0xF11)
172
173  // architecture id for XiangShan is 25
174  // see https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md
175  val marchid = Module(new CSRModule("Marchid", new CSRBundle {
176    val ALL = MarchidField(63, 0).withReset(MarchidField.XSArchid)
177  })).setAddr(0xF12)
178
179  val machineLevelCSRMods: Seq[CSRModule[_]] = Seq(
180    mstatus,
181    misa,
182    medeleg,
183    mideleg,
184    mie,
185    mtvec,
186    mcounteren,
187    mvien,
188    mvip,
189    menvcfg,
190    mcountinhibit,
191    mscratch,
192    mepc,
193    mcause,
194    mtval,
195    mip,
196    mtinst,
197    mtval2,
198    mseccfg,
199    mcycle,
200    minstret,
201    mvendorid,
202    marchid,
203  ) ++ mhpmevents ++ mhpmcounters
204
205  val machineLevelCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], Data)] = SeqMap.from(
206    machineLevelCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata.asInstanceOf[CSRBundle].asUInt))).iterator
207  )
208
209  val machineLevelCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
210    machineLevelCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt)).iterator
211  )
212}
213
214class MstatusBundle extends CSRBundle {
215
216  val SIE  = CSRRWField     (1).withReset(0.U)
217  val MIE  = CSRRWField     (3).withReset(0.U)
218  val SPIE = CSRRWField     (5).withReset(0.U)
219  val UBE  = CSRROField     (6).withReset(0.U)
220  val MPIE = CSRRWField     (7).withReset(0.U)
221  val SPP  = CSRRWField     (8).withReset(0.U)
222  val VS   = ContextStatus  (10,  9).withReset(ContextStatus.Initial)
223  val MPP  = PrivMode       (12, 11).withReset(PrivMode.U)
224  val FS   = ContextStatus  (14, 13).withReset(ContextStatus.Initial)
225  val XS   = ContextStatusRO(16, 15).withReset(0.U)
226  val MPRV = CSRRWField     (17).withReset(0.U)
227  val SUM  = CSRRWField     (18).withReset(0.U)
228  val MXR  = CSRRWField     (19).withReset(0.U)
229  val TVM  = CSRRWField     (20).withReset(0.U)
230  val TW   = CSRRWField     (21).withReset(0.U)
231  val TSR  = CSRRWField     (22).withReset(0.U)
232  val UXL  = XLENField      (33, 32).withReset(XLENField.XLEN64)
233  val SXL  = XLENField      (35, 34).withReset(XLENField.XLEN64)
234  val SBE  = CSRROField     (36).withReset(0.U)
235  val MBE  = CSRROField     (37).withReset(0.U)
236  val GVA  = CSRRWField     (38).withReset(0.U)
237  val MPV  = VirtMode       (39).withReset(0.U)
238  val SD   = CSRROField     (63,
239    (_, _) => FS === ContextStatus.Dirty || VS === ContextStatus.Dirty
240  )
241}
242
243class MstatusModule extends CSRModule("MStatus", new MstatusBundle)
244  with TrapEntryMEventSinkBundle
245  with TrapEntryHSEventSinkBundle
246  with MretEventSinkBundle
247  with SretEventSinkBundle
248{
249  val mstatus = IO(Output(bundle))
250  val sstatus = IO(Output(new SstatusBundle))
251
252  val wAliasSstatus = IO(Input(new CSRAddrWriteBundle(new SstatusBundle)))
253
254  // write connection
255  this.wfn(reg)(Seq(wAliasSstatus))
256
257  // read connection
258  mstatus :|= reg
259  sstatus := mstatus
260  rdata := mstatus.asUInt
261}
262
263class MisaBundle extends CSRBundle {
264  // Todo: reset with ISA string
265  val A = RO( 0).withReset(1.U) // Atomic extension
266  val B = RO( 1).withReset(0.U) // Reserved
267  val C = RO( 2).withReset(1.U) // Compressed extension
268  val D = RO( 3).withReset(1.U) // Double-precision floating-point extension
269  val E = RO( 4).withReset(0.U) // RV32E/64E base ISA
270  val F = RO( 5).withReset(1.U) // Single-precision floating-point extension
271  val G = RO( 6).withReset(0.U) // Reserved
272  val H = RO( 7).withReset(1.U) // Hypervisor extension
273  val I = RO( 8).withReset(1.U) // RV32I/64I/128I base ISA
274  val J = RO( 9).withReset(0.U) // Reserved
275  val K = RO(10).withReset(0.U) // Reserved
276  val L = RO(11).withReset(0.U) // Reserved
277  val M = RO(12).withReset(1.U) // Integer Multiply/Divide extensi
278  val N = RO(13).withReset(0.U) // Tentatively reserved for User-Level Interrupts extension
279  val O = RO(14).withReset(0.U) // Reserved
280  val P = RO(15).withReset(0.U) // Tentatively reserved for Packed-SIMD extension
281  val Q = RO(16).withReset(0.U) // Quad-precision floating-point extension
282  val R = RO(17).withReset(0.U) // Reserved
283  val S = RO(18).withReset(1.U) // Supervisor mode implemented
284  val T = RO(19).withReset(0.U) // Reserved
285  val U = RO(20).withReset(1.U) // User mode implemented
286  val V = RO(21).withReset(1.U) // Vector extension
287  val W = RO(22).withReset(0.U) // Reserved
288  val X = RO(23).withReset(0.U) // Non-standard extensions present
289  val Y = RO(24).withReset(0.U) // Reserved
290  val Z = RO(25).withReset(0.U) // Reserved
291  val MXL = XLENField(63, 62).withReset(XLENField.XLEN64)
292
293  def getISAString = this.getFields.filter(x => x != MXL && x.init.litValue == 1).sortBy(_.lsb).map(x => ('A' + x.msb).toChar).mkString
294}
295
296class MedelegBundle extends ExceptionBundle {
297  this.EX_MCALL.setRO() // never delegate machine level ecall
298}
299
300class MidelegBundle extends InterruptBundle {
301  // Don't delegate Machine level interrupts
302  this.getM.foreach(_.setRO().withReset(0.U))
303  // Ref: 13.4.2. Machine Interrupt Delegation Register (mideleg)
304  // When the hypervisor extension is implemented, bits 10, 6, and 2 of mideleg (corresponding to the standard VS-level
305  // interrupts) are each read-only one.
306  this.getVS.foreach(_.setRO().withReset(1.U))
307  // bit 12 of mideleg (corresponding to supervisor-level guest external interrupts) is also read-only one.
308  // VS-level interrupts and guest external interrupts are always delegated past M-mode to HS-mode.
309  this.SGEI.setRO().withReset(1.U)
310}
311
312class MieBundle extends InterruptEnableBundle {
313  this.SGEIE.setRO()
314  this.getVS.foreach(_.setRO())
315}
316
317class MipBundle extends InterruptPendingBundle {
318  this.getM.foreach(_.setRO())
319}
320
321class MvienBundle extends CSRBundle {
322  // Ref: riscv interrupt spec - 5.3 Interrupt filtering and virtual interrupts for supervisor level
323  // It is strongly recommended that bit 9 of mvien be writable.
324  // It is strongly recommended that bit 1 of mvien also be writable.
325  val SSIE     = RW(1)
326  val SEIE     = RW(9)
327  val OTHERIE  = RW(63, 13)
328}
329
330class MvipBundle extends CSRBundle {
331  // When bit 1 of mvien is zero, bit 1(SSIP) of mvip is an alias of the same bit (SSIP) of mip.
332  // But when bit 1 of mvien is one, bit 1(SSIP) of mvip is a separate writable bit independent of mip.SSIP.
333  // When the value of bit 1 of mvien is changed from zero to one, the value of bit 1 of mvip becomes UNSPECIFIED.
334  val SSIP     = RW(1)
335  // Bit 5 of mvip is an alias of the same bit (STIP) in mip when that bit is writable in mip.
336  // When STIP is not writable in mip (such as when menvcfg.STCE = 1), bit 5 of mvip is read-only zero.
337  val STIP     = RW(5)
338  // When bit 9 of mvien is zero, bit 9 of mvip is an alias of the software-writable bit 9 of mip (SEIP).
339  // But when bit 9 of mvien is one, bit 9 of mvip is a writable bit independent of mip.SEIP.
340  // Unlike for bit 1, changing the value of bit 9 of mvien does not affect the value of bit 9 of mvip.
341  val SEIP     = RW(9)
342  val OTHERIP  = RW(63, 13)
343}
344
345class Epc extends CSRBundle {
346  // TODO: configure it with VAddrBits
347  val ALL = RW(63, 1)
348}
349
350class McountinhibitBundle extends CSRBundle {
351  val CY = RW(0)
352  val IR = RW(2)
353  val HPM3 = RW(31, 3)
354}
355
356object MarchidField extends CSREnum with ROApply {
357  val XSArchid = Value(25.U)
358}
359
360class MieToHie extends Bundle {
361  val VSSIE = ValidIO(RW(0))
362  val VSTIE = ValidIO(RW(0))
363  val VSEIE = ValidIO(RW(0))
364  val SGEIE = ValidIO(RW(0))
365}
366
367class MvipToMip extends Bundle {
368  val SSIP = ValidIO(RW(0))
369  val STIP = ValidIO(RW(0))
370  val SEIP = ValidIO(RW(0))
371}
372
373trait HasMachineInterruptBundle { self: CSRModule[_] =>
374  val mvien = IO(Input(new MvienBundle))
375  val mvip  = IO(Input(new MvipBundle))
376  val mip   = IO(Input(new MipBundle))
377  val mie   = IO(Input(new MieBundle))
378}
379
380trait HasMachineDelegBundle { self: CSRModule[_] =>
381  val mideleg = IO(Input(new MidelegBundle))
382  val medeleg = IO(Input(new MedelegBundle))
383}
384
385trait HasExternalInterruptBundle {
386  val platformIRP = IO(new Bundle {
387    val MEIP  = Input(Bool())
388    val MTIP  = Input(Bool())
389    val MSIP  = Input(Bool())
390    val SEIP  = Input(Bool())
391    val VSEIP = Input(Bool())
392    val VSTIP = Input(Bool())
393    val debugIP = Input(Bool())
394  })
395}
396
397trait HasMachineCounterControlBundle { self: CSRModule[_] =>
398  val mcountinhibit = IO(Input(new McountinhibitBundle))
399}
400
401trait HasInstCommitBundle {
402  val commitValid   = IO(Input(Bool()))
403  // need contain 8x8
404  val commitInstNum = IO(Input(UInt(7.W)))
405}