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