xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision bfaa63b3cbc5a21ac0471b2ea2cff3c84419c834)
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  ExcitingUtils.addSource(causeNO, "difftestCausefromCSR")
674
675  val raiseExceptionIntr = io.exception.valid
676  val retTarget = Wire(UInt(VAddrBits.W))
677  val trapTarget = Wire(UInt(VAddrBits.W))
678  ExcitingUtils.addSource(trapTarget, "trapTarget")
679  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
680  io.redirect := DontCare
681  io.redirectValid := valid && func === CSROpType.jmp && !isEcall
682  io.redirect.target := retTarget
683  io.flushPipe := resetSatp
684
685  XSDebug(io.redirectValid, "redirect to %x, pc=%x\n", io.redirect.target, io.cfIn.pc)
686
687  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)
688  XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode)
689
690  // Branch control
691
692  val deleg = Mux(raiseIntr, mideleg , medeleg)
693  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
694  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
695  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
696
697  trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
698  retTarget := DontCare
699  // val illegalEret = TODO
700
701  when (valid && isMret) {
702    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
703    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
704    mstatusNew.ie.m := mstatusOld.pie.m
705    priviledgeMode := mstatusOld.mpp
706    mstatusNew.pie.m := true.B
707    mstatusNew.mpp := ModeU
708    mstatusNew.mprv := 0.U
709    mstatus := mstatusNew.asUInt
710//    lr := false.B
711    retTarget := mepc(VAddrBits-1, 0)
712  }
713
714  when (valid && isSret && !illegalSModeSret) {
715    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
716    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
717    mstatusNew.ie.s := mstatusOld.pie.s
718    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
719    mstatusNew.pie.s := true.B
720    mstatusNew.spp := ModeU
721    mstatus := mstatusNew.asUInt
722    mstatusNew.mprv := 0.U
723    // lr := false.B
724    retTarget := sepc(VAddrBits-1, 0)
725  }
726
727  when (valid && isUret) {
728    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
729    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
730    // mstatusNew.mpp.m := ModeU //TODO: add mode U
731    mstatusNew.ie.u := mstatusOld.pie.u
732    priviledgeMode := ModeU
733    mstatusNew.pie.u := true.B
734    mstatus := mstatusNew.asUInt
735    retTarget := uepc(VAddrBits-1, 0)
736  }
737
738  when (raiseExceptionIntr) {
739    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
740    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
741
742    when (delegS) {
743      scause := causeNO
744      sepc := SignExt(io.exception.bits.cf.pc, XLEN)
745      mstatusNew.spp := priviledgeMode
746      mstatusNew.pie.s := mstatusOld.ie.s
747      mstatusNew.ie.s := false.B
748      priviledgeMode := ModeS
749      when(tvalWen){stval := 0.U}
750      // trapTarget := stvec(VAddrBits-1. 0)
751    }.otherwise {
752      mcause := causeNO
753      mepc := SignExt(io.exception.bits.cf.pc, XLEN)
754      mstatusNew.mpp := priviledgeMode
755      mstatusNew.pie.m := mstatusOld.ie.m
756      mstatusNew.ie.m := false.B
757      priviledgeMode := ModeM
758      when(tvalWen){mtval := 0.U}
759      // trapTarget := mtvec(VAddrBits-1. 0)
760    }
761
762    mstatus := mstatusNew.asUInt
763  }
764
765  io.in.ready := true.B
766  io.out.valid := valid
767
768
769  XSDebug(io.redirectValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
770    io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
771  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",
772    io.redirectValid, io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
773  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc)
774
775
776  // perfcnt
777
778  val perfCntList = Map(
779//    "Mcycle"      -> (0xb00, "perfCntCondMcycle"     ),
780//    "Minstret"    -> (0xb02, "perfCntCondMinstret"   ),
781    "MbpInstr"    -> (0xb03, "perfCntCondMbpInstr"   ),
782    "MbpRight"    -> (0xb04, "perfCntCondMbpRight"   ),
783    "MbpWrong"    -> (0xb05, "perfCntCondMbpWrong"   ),
784    "MbpBRight"   -> (0xb06, "perfCntCondMbpBRight"   ),
785    "MbpBWrong"   -> (0xb07, "perfCntCondMbpBWrong"   ),
786    "MbpJRight"   -> (0xb08, "perfCntCondMbpJRight"   ),
787    "MbpJWrong"   -> (0xb09, "perfCntCondMbpJWrong"   ),
788    "MbpIRight"   -> (0xb0a, "perfCntCondMbpIRight"   ),
789    "MbpIWrong"   -> (0xb0b, "perfCntCondMbpIWrong"   ),
790    "MbpRRight"   -> (0xb0c, "perfCntCondMbpRRight"   ),
791    "MbpRWrong"   -> (0xb0d, "perfCntCondMbpRWrong"   ),
792    "DpqReplay"   -> (0xb0e, "perfCntCondDpqReplay"   ),
793    "RoqWalk"     -> (0xb0f, "perfCntCondRoqWalk"     ),
794    "RoqWaitInt"  -> (0xb10, "perfCntCondRoqWaitInt"  ),
795    "RoqWaitFp"   -> (0xb11, "perfCntCondRoqWaitFp"   ),
796    "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ),
797    "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"),
798    "Dp1Empty"    -> (0xb14, "perfCntCondDp1Empty"    ),
799    "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0"     ),
800    "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1"     ),
801    "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2"     ),
802    "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3"     ),
803    "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0"    ),
804    "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1"    ),
805    "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2"    ),
806    "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3"    ),
807    "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0"     ),
808    "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0"    ),
809    "PtwReqCnt"   -> (0xb25, "perfCntPtwReqCnt"       ),
810    "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt"     ),
811    "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit"     ),
812    "ICacheReq"   -> (0xb28, "perfCntIcacheReqCnt"     ),
813    "ICacheMiss"   -> (0xb29, "perfCntIcacheMissCnt"     )
814//    "Custom1"     -> (0xb1b, "Custom1"             ),
815//    "Custom2"     -> (0xb1c, "Custom2"             ),
816//    "Custom3"     -> (0xb1d, "Custom3"             ),
817//    "Custom4"     -> (0xb1e, "Custom4"             ),
818//    "Custom5"     -> (0xb1f, "Custom5"             ),
819//    "Custom6"     -> (0xb20, "Custom6"             ),
820//    "Custom7"     -> (0xb21, "Custom7"             ),
821//    "Custom8"     -> (0xb22, "Custom8"             ),
822//    "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
823  )
824  val perfCntCond = List.fill(0x80)(WireInit(false.B))
825  (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
826
827//  ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf)
828  perfCntList.foreach {
829    case (_, (address, boringId)) =>
830      if(hasPerfCnt){
831        ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
832      }
833//      if (!hasPerfCnt) {
834//        // do not enable perfcnts except for Mcycle and Minstret
835//        if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) {
836//          perfCntCond(address & 0x7f) := false.B
837//        }
838//      }
839  }
840
841  val xstrap = WireInit(false.B)
842  if(!env.FPGAPlatform && EnableBPU){
843    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
844  }
845  def readWithScala(addr: Int): UInt = mapping(addr)._1
846
847  if (!env.FPGAPlatform) {
848
849    // display all perfcnt when nooptrap is executed
850    when (xstrap) {
851      printf("======== PerfCnt =========\n")
852      perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) =>
853        printf("%d <- " + str + "\n", readWithScala(address))
854      }
855    }
856
857    // for differential testing
858//    BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode")
859//    BoringUtils.addSource(RegNext(mstatus), "difftestMstatus")
860//    BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus")
861//    BoringUtils.addSource(RegNext(mepc), "difftestMepc")
862//    BoringUtils.addSource(RegNext(sepc), "difftestSepc")
863//    BoringUtils.addSource(RegNext(mcause), "difftestMcause")
864//    BoringUtils.addSource(RegNext(scause), "difftestScause")
865    BoringUtils.addSource(priviledgeMode, "difftestMode")
866    BoringUtils.addSource(mstatus, "difftestMstatus")
867    BoringUtils.addSource(mstatus & sstatusRmask, "difftestSstatus")
868    BoringUtils.addSource(mepc, "difftestMepc")
869    BoringUtils.addSource(sepc, "difftestSepc")
870    BoringUtils.addSource(mtval, "difftestMtval")
871    BoringUtils.addSource(stval, "difftestStval")
872    BoringUtils.addSource(mcause, "difftestMcause")
873    BoringUtils.addSource(scause, "difftestScause")
874    BoringUtils.addSource(satp, "difftestSatp")
875    BoringUtils.addSource(mipReg, "difftestMip")
876    BoringUtils.addSource(mie, "difftestMie")
877    BoringUtils.addSource(mscratch, "difftestMscratch")
878    BoringUtils.addSource(sscratch, "difftestSscratch")
879    BoringUtils.addSource(mideleg, "difftestMideleg")
880    BoringUtils.addSource(medeleg, "difftestMedeleg")
881  } else {
882//    BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt")
883  }
884}
885