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