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