xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision 67559d9ee36fb58ee98413cb10eee63fc2e644ed)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.ExcitingUtils.{ConnectionType, Debug}
5import chisel3.util._
6import fpu.Fflags
7import utils._
8import xiangshan._
9import xiangshan.backend._
10import xiangshan.backend.fu.FunctionUnit._
11import utils.XSDebug
12
13trait HasCSRConst {
14  // User Trap Setup
15  val Ustatus       = 0x000
16  val Uie           = 0x004
17  val Utvec         = 0x005
18
19  // User Trap Handling
20  val Uscratch      = 0x040
21  val Uepc          = 0x041
22  val Ucause        = 0x042
23  val Utval         = 0x043
24  val Uip           = 0x044
25
26  // User Floating-Point CSRs (not implemented)
27  val Fflags        = 0x001
28  val Frm           = 0x002
29  val Fcsr          = 0x003
30
31  // User Counter/Timers
32  val Cycle         = 0xC00
33  val Time          = 0xC01
34  val Instret       = 0xC02
35
36  // Supervisor Trap Setup
37  val Sstatus       = 0x100
38  val Sedeleg       = 0x102
39  val Sideleg       = 0x103
40  val Sie           = 0x104
41  val Stvec         = 0x105
42  val Scounteren    = 0x106
43
44  // Supervisor Trap Handling
45  val Sscratch      = 0x140
46  val Sepc          = 0x141
47  val Scause        = 0x142
48  val Stval         = 0x143
49  val Sip           = 0x144
50
51  // Supervisor Protection and Translation
52  val Satp          = 0x180
53
54  // Machine Information Registers
55  val Mvendorid     = 0xF11
56  val Marchid       = 0xF12
57  val Mimpid        = 0xF13
58  val Mhartid       = 0xF14
59
60  // Machine Trap Setup
61  val Mstatus       = 0x300
62  val Misa          = 0x301
63  val Medeleg       = 0x302
64  val Mideleg       = 0x303
65  val Mie           = 0x304
66  val Mtvec         = 0x305
67  val Mcounteren    = 0x306
68
69  // Machine Trap Handling
70  val Mscratch      = 0x340
71  val Mepc          = 0x341
72  val Mcause        = 0x342
73  val Mtval         = 0x343
74  val Mip           = 0x344
75
76  // Machine Memory Protection
77  // TBD
78  val Pmpcfg0       = 0x3A0
79  val Pmpcfg1       = 0x3A1
80  val Pmpcfg2       = 0x3A2
81  val Pmpcfg3       = 0x3A3
82  val PmpaddrBase   = 0x3B0
83
84  // Machine Counter/Timers
85  // Currently, we uses perfcnt csr set instead of standard Machine Counter/Timers
86  // 0xB80 - 0x89F are also used as perfcnt csr
87
88  // Machine Counter Setup (not implemented)
89  // Debug/Trace Registers (shared with Debug Mode) (not implemented)
90  // Debug Mode Registers (not implemented)
91
92  def privEcall  = 0x000.U
93  def privEbreak = 0x001.U
94  def privMret   = 0x302.U
95  def privSret   = 0x102.U
96  def privUret   = 0x002.U
97
98  def ModeM     = 0x3.U
99  def ModeH     = 0x2.U
100  def ModeS     = 0x1.U
101  def ModeU     = 0x0.U
102
103  def IRQ_UEIP  = 0
104  def IRQ_SEIP  = 1
105  def IRQ_MEIP  = 3
106
107  def IRQ_UTIP  = 4
108  def IRQ_STIP  = 5
109  def IRQ_MTIP  = 7
110
111  def IRQ_USIP  = 8
112  def IRQ_SSIP  = 9
113  def IRQ_MSIP  = 11
114
115  val IntPriority = Seq(
116    IRQ_MEIP, IRQ_MSIP, IRQ_MTIP,
117    IRQ_SEIP, IRQ_SSIP, IRQ_STIP,
118    IRQ_UEIP, IRQ_USIP, IRQ_UTIP
119  )
120
121  def csrAccessPermissionCheck(addr: UInt, wen: Bool, mode: UInt): Bool = {
122    val readOnly = addr(11,10) === "b11".U
123    val lowestAccessPrivilegeLevel = addr(9,8)
124    mode >= lowestAccessPrivilegeLevel && !(wen && readOnly)
125  }
126}
127
128trait HasExceptionNO {
129  def instrAddrMisaligned = 0
130  def instrAccessFault    = 1
131  def illegalInstr        = 2
132  def breakPoint          = 3
133  def loadAddrMisaligned  = 4
134  def loadAccessFault     = 5
135  def storeAddrMisaligned = 6
136  def storeAccessFault    = 7
137  def ecallU              = 8
138  def ecallS              = 9
139  def ecallM              = 11
140  def instrPageFault      = 12
141  def loadPageFault       = 13
142  def storePageFault      = 15
143
144  val ExcPriority = Seq(
145      breakPoint, // TODO: different BP has different priority
146      instrPageFault,
147      instrAccessFault,
148      illegalInstr,
149      instrAddrMisaligned,
150      ecallM, ecallS, ecallU,
151      storePageFault,
152      loadPageFault,
153      storeAccessFault,
154      loadAccessFault,
155      storeAddrMisaligned,
156      loadAddrMisaligned
157  )
158}
159
160class FpuCsrIO extends XSBundle {
161  val fflags = Output(new Fflags)
162  val isIllegal = Output(Bool())
163  val dirty_fs = Output(Bool())
164  val frm = Input(UInt(3.W))
165}
166
167
168class PerfCounterIO extends XSBundle {
169  val value = Input(UInt(XLEN.W))
170}
171
172class CSRIO extends FunctionUnitIO[UInt, Null](csrCfg, len=64, extIn= FuOpType()) {
173  val cfIn = Input(new CtrlFlow)
174  val redirectOut = Output(new Redirect)
175  val redirectOutValid = Output(Bool())
176  val fpu_csr = Flipped(new FpuCsrIO)
177  val cfOut = Output(new CtrlFlow)
178  // from rob
179  val exception = Flipped(ValidIO(new MicroOp))
180  // for exception check
181  val instrValid = Input(Bool())
182  val flushPipe = Output(Bool())
183  // for differential testing
184//  val intrNO = Output(UInt(XLEN.W))
185  val wenFix = Output(Bool())
186
187  override def cloneType: CSRIO.this.type =
188    new CSRIO().asInstanceOf[this.type]
189
190  val perf = Vec(NumPerfCounters, new PerfCounterIO)
191  val memExceptionVAddr = Input(UInt(VAddrBits.W))
192  val trapTarget = Output(UInt(VAddrBits.W))
193  val mtip = Input(Bool())
194  val msip = Input(Bool())
195  val meip = Input(Bool())
196  val interrupt = Output(Bool())
197  val tlbCsrIO = Output(new TlbCsrBundle)
198}
199
200class CSR extends XSModule
201    with HasCSRConst
202{
203
204  val io = IO(new CSRIO)
205
206  io.cfOut := io.cfIn
207
208  val (valid, src1, src2, func) =
209    (io.in.valid, io.in.bits.src(0), io.in.bits.uop.ctrl.imm, io.in.bits.ext.get)
210
211  // CSR define
212
213  class Priv extends Bundle {
214    val m = Output(Bool())
215    val h = Output(Bool())
216    val s = Output(Bool())
217    val u = Output(Bool())
218  }
219
220  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
221
222  class MstatusStruct extends Bundle {
223    val sd = Output(UInt(1.W))
224
225    val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null
226    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
227    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
228    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
229
230    val tsr = Output(UInt(1.W))
231    val tw = Output(UInt(1.W))
232    val tvm = Output(UInt(1.W))
233    val mxr = Output(UInt(1.W))
234    val sum = Output(UInt(1.W))
235    val mprv = Output(UInt(1.W))
236    val xs = Output(UInt(2.W))
237    val fs = Output(UInt(2.W))
238    val mpp = Output(UInt(2.W))
239    val hpp = Output(UInt(2.W))
240    val spp = Output(UInt(1.W))
241    val pie = new Priv
242    val ie = new Priv
243    assert(this.getWidth == XLEN)
244  }
245
246  class SatpStruct extends Bundle {
247    val mode = UInt(4.W)
248    val asid = UInt(16.W)
249    val ppn  = UInt(44.W)
250  }
251
252  class Interrupt extends Bundle {
253    val e = new Priv
254    val t = new Priv
255    val s = new Priv
256  }
257
258  // Machine-Level CSRs
259
260  val mtvec = RegInit(UInt(XLEN.W), 0.U)
261  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
262  val mcause = RegInit(UInt(XLEN.W), 0.U)
263  val mtval = RegInit(UInt(XLEN.W), 0.U)
264  val mepc = Reg(UInt(XLEN.W))
265
266  val mie = RegInit(0.U(XLEN.W))
267  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
268  val mipReg  = RegInit(0.U.asTypeOf(new Interrupt).asUInt)
269  val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1)
270  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
271
272  def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt()
273  def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt()
274  var extList = List('a', 's', 'i', 'u')
275  if(HasMExtension){ extList = extList :+ 'm'}
276  if(HasCExtension){ extList = extList :+ 'c'}
277  if(HasFPU){ extList = extList ++ List('f', 'd')}
278  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
279  val misa = RegInit(UInt(XLEN.W), misaInitVal)
280  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
281  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
282
283  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
284  val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
285  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
286  val mhartid = RegInit(UInt(XLEN.W), 0.U) // the hardware thread running the code
287  val mstatus = RegInit(UInt(XLEN.W), "h00001800".U)
288  // val mstatus = RegInit(UInt(XLEN.W), "h8000c0100".U)
289  // mstatus Value Table
290  // | sd   |
291  // | pad1 |
292  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
293  // | uxl  | hardlinked to 00
294  // | pad0 |
295  // | tsr  |
296  // | tw   |
297  // | tvm  |
298  // | mxr  |
299  // | sum  |
300  // | mprv |
301  // | xs   | 00 |
302  // | fs   | 00 |
303  // | mpp  | 00 |
304  // | hpp  | 00 |
305  // | spp  | 0 |
306  // | pie  | 0000 | pie.h is used as UBE
307  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
308  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
309  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
310    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
311    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
312    mstatusNew
313  }
314
315  val mstatusMask = (~ZeroExt((
316    GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) |
317    GenMask(37) | // MBE
318    GenMask(36) | // SBE
319    GenMask(6)    // UBE
320  ), 64)).asUInt()
321
322  val medeleg = RegInit(UInt(XLEN.W), 0.U)
323  val mideleg = RegInit(UInt(XLEN.W), 0.U)
324  val mscratch = RegInit(UInt(XLEN.W), 0.U)
325
326  val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U)
327  val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U)
328  val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U)
329  val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U)
330  val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U)
331  val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U)
332  val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U)
333  val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U)
334
335  // Superviser-Level CSRs
336
337  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
338  val sstatusWmask = "hc6122".U
339  // Sstatus Write Mask
340  // -------------------------------------------------------
341  //    19           9   5     2
342  // 0  1100 0000 0001 0010 0010
343  // 0  c    0    1    2    2
344  // -------------------------------------------------------
345  val sstatusRmask = sstatusWmask | "h8000000300018000".U
346  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
347  val stvec = RegInit(UInt(XLEN.W), 0.U)
348  // val sie = RegInit(0.U(XLEN.W))
349  val sieMask = "h222".U & mideleg
350  val sipMask  = "h222".U & mideleg
351  val satp = RegInit(0.U(XLEN.W))
352  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
353  val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0
354  // val satp = RegInit(UInt(XLEN.W), 0.U)
355  val sepc = RegInit(UInt(XLEN.W), 0.U)
356  val scause = RegInit(UInt(XLEN.W), 0.U)
357  val stval = Reg(UInt(XLEN.W))
358  val sscratch = RegInit(UInt(XLEN.W), 0.U)
359  val scounteren = RegInit(UInt(XLEN.W), 0.U)
360
361  val tlbBundle = Wire(new TlbCsrBundle)
362  tlbBundle.satp := satp.asTypeOf(new SatpStruct)
363  io.tlbCsrIO := tlbBundle
364
365  // User-Level CSRs
366  val uepc = Reg(UInt(XLEN.W))
367
368  // fcsr
369  class FcsrStruct extends Bundle{
370    val reserved = UInt((XLEN-3-5).W)
371    val frm = UInt(3.W)
372    val fflags = UInt(5.W)
373    assert(this.getWidth == XLEN)
374  }
375  val fcsr = RegInit(0.U(XLEN.W))
376  // set mstatus->sd and mstatus->fs when true
377  val csrw_dirty_fp_state = WireInit(false.B)
378
379  def frm_wfn(wdata: UInt): UInt = {
380    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
381    csrw_dirty_fp_state := true.B
382    fcsrOld.frm := wdata(2,0)
383    fcsrOld.asUInt()
384  }
385  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
386
387  def fflags_wfn(wdata: UInt): UInt = {
388    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
389    csrw_dirty_fp_state := true.B
390    fcsrOld.fflags := wdata(4,0)
391    fcsrOld.asUInt()
392  }
393  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
394
395  def fcsr_wfn(wdata: UInt): UInt = {
396    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
397    csrw_dirty_fp_state := true.B
398    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
399  }
400
401  val fcsrMapping = Map(
402    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn, rfn = fflags_rfn),
403    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
404    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
405  )
406
407  // Atom LR/SC Control Bits
408//  val setLr = WireInit(Bool(), false.B)
409//  val setLrVal = WireInit(Bool(), false.B)
410//  val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check
411//  val lr = RegInit(Bool(), false.B)
412//  val lrAddr = RegInit(UInt(AddrBits.W), 0.U)
413//
414//  when(setLr){
415//    lr := setLrVal
416//    lrAddr := setLrAddr
417//  }
418
419  // Hart Priviledge Mode
420  val priviledgeMode = RegInit(UInt(2.W), ModeM)
421
422  // perfcnt
423  val hasPerfCnt = !env.FPGAPlatform
424  val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3
425  val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
426  val perfCntsLoMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb00 + i, perfCnts(i)))
427  val perfCntsHiMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32)))
428
429  // CSR reg map
430  val mapping = Map(
431
432    // User Trap Setup
433    // MaskedRegMap(Ustatus, ustatus),
434    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
435    // MaskedRegMap(Utvec, utvec),
436
437    // User Trap Handling
438    // MaskedRegMap(Uscratch, uscratch),
439    // MaskedRegMap(Uepc, uepc),
440    // MaskedRegMap(Ucause, ucause),
441    // MaskedRegMap(Utval, utval),
442    // MaskedRegMap(Uip, uip),
443
444    // User Counter/Timers
445    // MaskedRegMap(Cycle, cycle),
446    // MaskedRegMap(Time, time),
447    // MaskedRegMap(Instret, instret),
448
449    // Supervisor Trap Setup
450    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
451
452    // MaskedRegMap(Sedeleg, Sedeleg),
453    // MaskedRegMap(Sideleg, Sideleg),
454    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
455    MaskedRegMap(Stvec, stvec),
456    MaskedRegMap(Scounteren, scounteren),
457
458    // Supervisor Trap Handling
459    MaskedRegMap(Sscratch, sscratch),
460    MaskedRegMap(Sepc, sepc),
461    MaskedRegMap(Scause, scause),
462    MaskedRegMap(Stval, stval),
463    MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask),
464
465    // Supervisor Protection and Translation
466    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
467
468    // Machine Information Registers
469    MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable),
470    MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable),
471    MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable),
472    MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable),
473
474    // Machine Trap Setup
475    // MaskedRegMap(Mstatus, mstatus, "hffffffffffffffee".U, (x=>{printf("mstatus write: %x time: %d\n", x, GTimer()); x})),
476    MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask),
477    MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable
478    MaskedRegMap(Medeleg, medeleg, "hf3ff".U),
479    MaskedRegMap(Mideleg, mideleg, "h222".U),
480    MaskedRegMap(Mie, mie),
481    MaskedRegMap(Mtvec, mtvec),
482    MaskedRegMap(Mcounteren, mcounteren),
483
484    // Machine Trap Handling
485    MaskedRegMap(Mscratch, mscratch),
486    MaskedRegMap(Mepc, mepc),
487    MaskedRegMap(Mcause, mcause),
488    MaskedRegMap(Mtval, mtval),
489    MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable),
490
491    // Machine Memory Protection
492    MaskedRegMap(Pmpcfg0, pmpcfg0),
493    MaskedRegMap(Pmpcfg1, pmpcfg1),
494    MaskedRegMap(Pmpcfg2, pmpcfg2),
495    MaskedRegMap(Pmpcfg3, pmpcfg3),
496    MaskedRegMap(PmpaddrBase + 0, pmpaddr0),
497    MaskedRegMap(PmpaddrBase + 1, pmpaddr1),
498    MaskedRegMap(PmpaddrBase + 2, pmpaddr2),
499    MaskedRegMap(PmpaddrBase + 3, pmpaddr3)
500
501  ) ++
502    perfCntsLoMapping ++ (if (XLEN == 32) perfCntsHiMapping else Nil) ++
503    (if(HasFPU) fcsrMapping else Nil)
504
505  val addr = src2(11, 0)
506  val rdata = Wire(UInt(XLEN.W))
507  val csri = ZeroExt(io.cfIn.instr(19,15), XLEN) //unsigned imm for csri. [TODO]
508  val wdata = LookupTree(func, List(
509    CSROpType.wrt  -> src1,
510    CSROpType.set  -> (rdata | src1),
511    CSROpType.clr  -> (rdata & (~src1).asUInt()),
512    CSROpType.wrti -> csri,//TODO: csri --> src2
513    CSROpType.seti -> (rdata | csri),
514    CSROpType.clri -> (rdata & (~csri).asUInt())
515  ))
516
517  // satp wen check
518  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
519
520  // general CSR wen check
521  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
522  val permitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
523  // Writeable check is ingored.
524  // Currently, write to illegal csr addr will be ignored
525  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
526  io.out.bits.data := rdata
527  io.out.bits.uop := io.in.bits.uop
528
529  // Fix Mip/Sip write
530  val fixMapping = Map(
531    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
532    MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask)
533  )
534  val rdataDummy = Wire(UInt(XLEN.W))
535  MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata)
536
537  when(io.fpu_csr.fflags.asUInt() =/= 0.U){
538    fcsr := fflags_wfn(io.fpu_csr.fflags.asUInt())
539  }
540  // set fs and sd in mstatus
541  when(csrw_dirty_fp_state || io.fpu_csr.dirty_fs){
542    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
543    mstatusNew.fs := "b11".U
544    mstatusNew.sd := true.B
545    mstatus := mstatusNew.asUInt()
546  }
547  io.fpu_csr.frm := fcsr.asTypeOf(new FcsrStruct).frm
548
549  // CSR inst decode
550  val isEbreak = addr === privEbreak && func === CSROpType.jmp
551  val isEcall = addr === privEcall && func === CSROpType.jmp
552  val isMret = addr === privMret   && func === CSROpType.jmp
553  val isSret = addr === privSret   && func === CSROpType.jmp
554  val isUret = addr === privUret   && func === CSROpType.jmp
555
556  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func)
557  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
558
559  // Illegal priviledged operation list
560  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
561
562  // Illegal priviledged instruction check
563  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
564  val isIllegalAccess = !permitted
565  val isIllegalPrivOp = illegalSModeSret
566
567  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
568  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
569  // imem
570  // val imemPtev = true.B
571  // val imemPteu = true.B
572  // val imemPtex = true.B
573  // val imemReq = true.B
574  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
575  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
576  // assert(!hasInstrPageFault)
577
578  // dmem
579  // val dmemPtev = true.B
580  // val dmemPteu = true.B
581  // val dmemReq = true.B
582  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
583  // val dmemIsStore = true.B
584
585  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
586  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
587  // assert(!hasLoadPageFault)
588  // assert(!hasStorePageFault)
589
590  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
591  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
592  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
593  tlbBundle.priv.imode := priviledgeMode
594  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
595
596  val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid
597  val hasLoadPageFault = io.exception.bits.cf.exceptionVec(loadPageFault) && io.exception.valid
598  val hasStorePageFault = io.exception.bits.cf.exceptionVec(storePageFault) && io.exception.valid
599  val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned) && io.exception.valid
600  val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned) && io.exception.valid
601
602  // mtval write logic
603  val memExceptionAddr = SignExt(io.memExceptionVAddr, XLEN)
604  when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
605    val tval = Mux(
606      hasInstrPageFault,
607      Mux(
608        io.exception.bits.cf.crossPageIPFFix,
609        SignExt(io.exception.bits.cf.pc + 2.U, XLEN),
610        SignExt(io.exception.bits.cf.pc, XLEN)
611      ),
612      memExceptionAddr
613    )
614    when(priviledgeMode === ModeM){
615      mtval := tval
616    }.otherwise{
617      stval := tval
618    }
619  }
620
621  when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
622  {
623    mtval := memExceptionAddr
624  }
625
626  // Exception and Intr
627
628  // interrupts
629
630  val ideleg =  (mideleg & mip.asUInt)
631  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
632    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
633
634  val intrVecEnable = Wire(Vec(12, Bool()))
635  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
636  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
637  val intrBitSet = intrVec.orR()
638  io.interrupt := intrBitSet
639  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
640  val raiseIntr = intrBitSet && io.exception.valid
641  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO)
642
643  mipWire.t.m := io.mtip
644  mipWire.s.m := io.msip
645  mipWire.e.m := io.meip
646
647  // exceptions
648  val csrExceptionVec = Wire(Vec(16, Bool()))
649  csrExceptionVec.map(_ := false.B)
650  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
651  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
652  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
653  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
654  // Trigger an illegal instr exception when:
655  // * unimplemented csr is being read/written
656  // * csr access is illegal
657  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
658  csrExceptionVec(loadPageFault) := hasLoadPageFault
659  csrExceptionVec(storePageFault) := hasStorePageFault
660  val iduExceptionVec = io.cfIn.exceptionVec
661  val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
662  io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
663  io.wenFix := DontCare
664
665  val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt()
666  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
667  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
668  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
669  ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR")
670  ExcitingUtils.addSource(causeNO, "difftestCausefromCSR")
671
672  val raiseExceptionIntr = io.exception.valid
673  val retTarget = Wire(UInt(VAddrBits.W))
674  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
675  io.redirectOut := DontCare
676  io.redirectOutValid := valid && func === CSROpType.jmp && !isEcall
677  io.redirectOut.target := retTarget
678  io.flushPipe := resetSatp
679
680  XSDebug(io.redirectOutValid, "redirect to %x, pc=%x\n", io.redirectOut.target, io.cfIn.pc)
681
682  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",io.exception.bits.cf.pc, intrNO, io.exception.bits.cf.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
683  XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode)
684
685  // Branch control
686
687  val deleg = Mux(raiseIntr, mideleg , medeleg)
688  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
689  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
690  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
691
692  io.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
693  retTarget := DontCare
694  // val illegalEret = TODO
695
696  when (valid && isMret) {
697    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
698    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
699    mstatusNew.ie.m := mstatusOld.pie.m
700    priviledgeMode := mstatusOld.mpp
701    mstatusNew.pie.m := true.B
702    mstatusNew.mpp := ModeU
703    mstatusNew.mprv := 0.U
704    mstatus := mstatusNew.asUInt
705//    lr := false.B
706    retTarget := mepc(VAddrBits-1, 0)
707  }
708
709  when (valid && isSret && !illegalSModeSret) {
710    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
711    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
712    mstatusNew.ie.s := mstatusOld.pie.s
713    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
714    mstatusNew.pie.s := true.B
715    mstatusNew.spp := ModeU
716    mstatus := mstatusNew.asUInt
717    mstatusNew.mprv := 0.U
718    // lr := false.B
719    retTarget := sepc(VAddrBits-1, 0)
720  }
721
722  when (valid && isUret) {
723    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
724    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
725    // mstatusNew.mpp.m := ModeU //TODO: add mode U
726    mstatusNew.ie.u := mstatusOld.pie.u
727    priviledgeMode := ModeU
728    mstatusNew.pie.u := true.B
729    mstatus := mstatusNew.asUInt
730    retTarget := uepc(VAddrBits-1, 0)
731  }
732
733  when (raiseExceptionIntr) {
734    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
735    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
736
737    when (delegS) {
738      scause := causeNO
739      sepc := SignExt(io.exception.bits.cf.pc, XLEN)
740      mstatusNew.spp := priviledgeMode
741      mstatusNew.pie.s := mstatusOld.ie.s
742      mstatusNew.ie.s := false.B
743      priviledgeMode := ModeS
744      when(tvalWen){stval := 0.U}
745      // trapTarget := stvec(VAddrBits-1. 0)
746    }.otherwise {
747      mcause := causeNO
748      mepc := SignExt(io.exception.bits.cf.pc, XLEN)
749      mstatusNew.mpp := priviledgeMode
750      mstatusNew.pie.m := mstatusOld.ie.m
751      mstatusNew.ie.m := false.B
752      priviledgeMode := ModeM
753      when(tvalWen){mtval := 0.U}
754      // trapTarget := mtvec(VAddrBits-1. 0)
755    }
756
757    mstatus := mstatusNew.asUInt
758  }
759
760  io.in.ready := true.B
761  io.out.valid := valid
762
763
764  XSDebug(io.redirectOutValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
765    io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
766  XSDebug(raiseExceptionIntr && delegS, "Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
767    io.redirectOutValid, io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
768  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc)
769
770
771  // perfcnt
772
773  val perfCntList = Map(
774//    "Mcycle"      -> (0xb00, "perfCntCondMcycle"     ),
775//    "Minstret"    -> (0xb02, "perfCntCondMinstret"   ),
776    "MbpInstr"    -> (0xb03, "perfCntCondMbpInstr"   ),
777    "MbpRight"    -> (0xb04, "perfCntCondMbpRight"   ),
778    "MbpWrong"    -> (0xb05, "perfCntCondMbpWrong"   ),
779    "MbpBRight"   -> (0xb06, "perfCntCondMbpBRight"   ),
780    "MbpBWrong"   -> (0xb07, "perfCntCondMbpBWrong"   ),
781    "MbpJRight"   -> (0xb08, "perfCntCondMbpJRight"   ),
782    "MbpJWrong"   -> (0xb09, "perfCntCondMbpJWrong"   ),
783    "MbpIRight"   -> (0xb0a, "perfCntCondMbpIRight"   ),
784    "MbpIWrong"   -> (0xb0b, "perfCntCondMbpIWrong"   ),
785    "MbpRRight"   -> (0xb0c, "perfCntCondMbpRRight"   ),
786    "MbpRWrong"   -> (0xb0d, "perfCntCondMbpRWrong"   ),
787    "DpqReplay"   -> (0xb0e, "perfCntCondDpqReplay"   ),
788    "RoqWalk"     -> (0xb0f, "perfCntCondRoqWalk"     ),
789    "RoqWaitInt"  -> (0xb10, "perfCntCondRoqWaitInt"  ),
790    "RoqWaitFp"   -> (0xb11, "perfCntCondRoqWaitFp"   ),
791    "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ),
792    "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"),
793    "Dp1Empty"    -> (0xb14, "perfCntCondDp1Empty"    ),
794    "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0"     ),
795    "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1"     ),
796    "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2"     ),
797    "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3"     ),
798    "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0"    ),
799    "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1"    ),
800    "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2"    ),
801    "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3"    ),
802    "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0"     ),
803    "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0"    ),
804    "PtwReqCnt"   -> (0xb25, "perfCntPtwReqCnt"       ),
805    "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt"     ),
806    "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit"     ),
807    "ICacheReq"   -> (0xb28, "perfCntIcacheReqCnt"     ),
808    "ICacheMiss"   -> (0xb29, "perfCntIcacheMissCnt"     )
809//    "Custom1"     -> (0xb1b, "Custom1"             ),
810//    "Custom2"     -> (0xb1c, "Custom2"             ),
811//    "Custom3"     -> (0xb1d, "Custom3"             ),
812//    "Custom4"     -> (0xb1e, "Custom4"             ),
813//    "Custom5"     -> (0xb1f, "Custom5"             ),
814//    "Custom6"     -> (0xb20, "Custom6"             ),
815//    "Custom7"     -> (0xb21, "Custom7"             ),
816//    "Custom8"     -> (0xb22, "Custom8"             ),
817//    "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
818  )
819  val perfCntCond = List.fill(0x80)(WireInit(false.B))
820  (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
821
822//  ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf)
823  perfCntList.foreach {
824    case (_, (address, boringId)) =>
825      if(hasPerfCnt){
826        ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
827      }
828//      if (!hasPerfCnt) {
829//        // do not enable perfcnts except for Mcycle and Minstret
830//        if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) {
831//          perfCntCond(address & 0x7f) := false.B
832//        }
833//      }
834  }
835
836  val xstrap = WireInit(false.B)
837  if(!env.FPGAPlatform && EnableBPU){
838    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
839  }
840  def readWithScala(addr: Int): UInt = mapping(addr)._1
841
842  if (!env.FPGAPlatform) {
843
844    // display all perfcnt when nooptrap is executed
845    when (xstrap) {
846      printf("======== PerfCnt =========\n")
847      perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) =>
848        printf("%d <- " + str + "\n", readWithScala(address))
849      }
850    }
851
852    ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug)
853    ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug)
854    ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug)
855    ExcitingUtils.addSource(mepc, "difftestMepc", Debug)
856    ExcitingUtils.addSource(sepc, "difftestSepc", Debug)
857    ExcitingUtils.addSource(mtval, "difftestMtval", Debug)
858    ExcitingUtils.addSource(stval, "difftestStval", Debug)
859    ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug)
860    ExcitingUtils.addSource(stvec, "difftestStvec", Debug)
861    ExcitingUtils.addSource(mcause, "difftestMcause", Debug)
862    ExcitingUtils.addSource(scause, "difftestScause", Debug)
863    ExcitingUtils.addSource(satp, "difftestSatp", Debug)
864    ExcitingUtils.addSource(mipReg, "difftestMip", Debug)
865    ExcitingUtils.addSource(mie, "difftestMie", Debug)
866    ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug)
867    ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug)
868    ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug)
869    ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug)
870  } else {
871  }
872}
873