xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision b81fc38e8510d919ccf70419de6ea10b06295596)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.ExcitingUtils.ConnectionType
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}
199
200class CSR extends XSModule
201    with HasCSRConst
202{
203
204  val io = IO(new CSRIO)
205
206  io.cfOut := io.cfIn
207
208  val (valid, src1, src2, func) =
209    (io.in.valid, io.in.bits.src(0), io.in.bits.uop.ctrl.imm, io.in.bits.ext.get)
210
211  // CSR define
212
213  class Priv extends Bundle {
214    val m = Output(Bool())
215    val h = Output(Bool())
216    val s = Output(Bool())
217    val u = Output(Bool())
218  }
219
220  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
221
222  class MstatusStruct extends Bundle {
223    val sd = Output(UInt(1.W))
224
225    val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null
226    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
227    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
228    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
229
230    val tsr = Output(UInt(1.W))
231    val tw = Output(UInt(1.W))
232    val tvm = Output(UInt(1.W))
233    val mxr = Output(UInt(1.W))
234    val sum = Output(UInt(1.W))
235    val mprv = Output(UInt(1.W))
236    val xs = Output(UInt(2.W))
237    val fs = Output(UInt(2.W))
238    val mpp = Output(UInt(2.W))
239    val hpp = Output(UInt(2.W))
240    val spp = Output(UInt(1.W))
241    val pie = new Priv
242    val ie = new Priv
243    assert(this.getWidth == XLEN)
244  }
245
246  class SatpStruct extends Bundle {
247    val mode = UInt(4.W)
248    val asid = UInt(16.W)
249    val ppn  = UInt(44.W)
250  }
251
252  class Interrupt extends Bundle {
253    val e = new Priv
254    val t = new Priv
255    val s = new Priv
256  }
257
258  // Machine-Level CSRs
259
260  val mtvec = RegInit(UInt(XLEN.W), 0.U)
261  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
262  val mcause = RegInit(UInt(XLEN.W), 0.U)
263  val mtval = RegInit(UInt(XLEN.W), 0.U)
264  val mepc = Reg(UInt(XLEN.W))
265
266  val mie = RegInit(0.U(XLEN.W))
267  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
268  val mipReg  = RegInit(0.U.asTypeOf(new Interrupt).asUInt)
269  val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1)
270  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
271
272  def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt()
273  def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt()
274  var extList = List('a', 's', 'i', 'u')
275  if(HasMExtension){ extList = extList :+ 'm'}
276  if(HasCExtension){ extList = extList :+ 'c'}
277  if(HasFPU){ extList = extList ++ List('f', 'd')}
278  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
279  val misa = RegInit(UInt(XLEN.W), misaInitVal)
280  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
281  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
282
283  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
284  val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
285  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
286  val mhartid = RegInit(UInt(XLEN.W), 0.U) // the hardware thread running the code
287  val mstatus = RegInit(UInt(XLEN.W), "h00001800".U)
288  // val mstatus = RegInit(UInt(XLEN.W), "h8000c0100".U)
289  // mstatus Value Table
290  // | sd   |
291  // | pad1 |
292  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
293  // | uxl  | hardlinked to 00
294  // | pad0 |
295  // | tsr  |
296  // | tw   |
297  // | tvm  |
298  // | mxr  |
299  // | sum  |
300  // | mprv |
301  // | xs   | 00 |
302  // | fs   | 00 |
303  // | mpp  | 00 |
304  // | hpp  | 00 |
305  // | spp  | 0 |
306  // | pie  | 0000 | pie.h is used as UBE
307  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
308  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
309  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
310    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
311    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
312    mstatusNew
313  }
314
315  val mstatusMask = (~ZeroExt((
316    GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) |
317    GenMask(37) | // MBE
318    GenMask(36) | // SBE
319    GenMask(6)    // UBE
320  ), 64)).asUInt()
321
322  val medeleg = RegInit(UInt(XLEN.W), 0.U)
323  val mideleg = RegInit(UInt(XLEN.W), 0.U)
324  val mscratch = RegInit(UInt(XLEN.W), 0.U)
325
326  val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U)
327  val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U)
328  val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U)
329  val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U)
330  val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U)
331  val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U)
332  val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U)
333  val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U)
334
335  // Superviser-Level CSRs
336
337  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
338  val sstatusWmask = "hc6122".U
339  // Sstatus Write Mask
340  // -------------------------------------------------------
341  //    19           9   5     2
342  // 0  1100 0000 0001 0010 0010
343  // 0  c    0    1    2    2
344  // -------------------------------------------------------
345  val sstatusRmask = sstatusWmask | "h8000000300018000".U
346  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
347  val stvec = RegInit(UInt(XLEN.W), 0.U)
348  // val sie = RegInit(0.U(XLEN.W))
349  val sieMask = "h222".U & mideleg
350  val sipMask  = "h222".U & mideleg
351  val satp = RegInit(0.U(XLEN.W))
352  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
353  val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0
354  // val satp = RegInit(UInt(XLEN.W), 0.U)
355  val sepc = RegInit(UInt(XLEN.W), 0.U)
356  val scause = RegInit(UInt(XLEN.W), 0.U)
357  val stval = Reg(UInt(XLEN.W))
358  val sscratch = RegInit(UInt(XLEN.W), 0.U)
359  val scounteren = RegInit(UInt(XLEN.W), 0.U)
360
361  val tlbBundle = Wire(new TlbCsrBundle)
362  tlbBundle.satp := satp.asTypeOf(new SatpStruct)
363  BoringUtils.addSource(tlbBundle, "TLBCSRIO")
364
365  // User-Level CSRs
366  val uepc = Reg(UInt(XLEN.W))
367
368  // fcsr
369  class FcsrStruct extends Bundle{
370    val reserved = UInt((XLEN-3-5).W)
371    val frm = UInt(3.W)
372    val fflags = UInt(5.W)
373    assert(this.getWidth == XLEN)
374  }
375  val fcsr = RegInit(0.U(XLEN.W))
376  // set mstatus->sd and mstatus->fs when true
377  val csrw_dirty_fp_state = WireInit(false.B)
378
379  def frm_wfn(wdata: UInt): UInt = {
380    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
381    csrw_dirty_fp_state := true.B
382    fcsrOld.frm := wdata(2,0)
383    fcsrOld.asUInt()
384  }
385  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
386
387  def fflags_wfn(wdata: UInt): UInt = {
388    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
389    csrw_dirty_fp_state := true.B
390    fcsrOld.fflags := wdata(4,0)
391    fcsrOld.asUInt()
392  }
393  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
394
395  def fcsr_wfn(wdata: UInt): UInt = {
396    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
397    csrw_dirty_fp_state := true.B
398    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
399  }
400
401  val fcsrMapping = Map(
402    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn, rfn = fflags_rfn),
403    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
404    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
405  )
406
407  // Atom LR/SC Control Bits
408//  val setLr = WireInit(Bool(), false.B)
409//  val setLrVal = WireInit(Bool(), false.B)
410//  val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check
411//  val lr = RegInit(Bool(), false.B)
412//  val lrAddr = RegInit(UInt(AddrBits.W), 0.U)
413//  BoringUtils.addSink(setLr, "set_lr")
414//  BoringUtils.addSink(setLrVal, "set_lr_val")
415//  BoringUtils.addSink(setLrAddr, "set_lr_addr")
416//  BoringUtils.addSource(lr, "lr")
417//  BoringUtils.addSource(lrAddr, "lr_addr")
418//
419//  when(setLr){
420//    lr := setLrVal
421//    lrAddr := setLrAddr
422//  }
423
424  // Hart Priviledge Mode
425  val priviledgeMode = RegInit(UInt(2.W), ModeM)
426
427  // perfcnt
428  val hasPerfCnt = !env.FPGAPlatform
429  val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3
430  val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
431  val perfCntsLoMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb00 + i, perfCnts(i)))
432  val perfCntsHiMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32)))
433
434  // CSR reg map
435  val mapping = Map(
436
437    // User Trap Setup
438    // MaskedRegMap(Ustatus, ustatus),
439    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
440    // MaskedRegMap(Utvec, utvec),
441
442    // User Trap Handling
443    // MaskedRegMap(Uscratch, uscratch),
444    // MaskedRegMap(Uepc, uepc),
445    // MaskedRegMap(Ucause, ucause),
446    // MaskedRegMap(Utval, utval),
447    // MaskedRegMap(Uip, uip),
448
449    // User Counter/Timers
450    // MaskedRegMap(Cycle, cycle),
451    // MaskedRegMap(Time, time),
452    // MaskedRegMap(Instret, instret),
453
454    // Supervisor Trap Setup
455    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
456
457    // MaskedRegMap(Sedeleg, Sedeleg),
458    // MaskedRegMap(Sideleg, Sideleg),
459    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
460    MaskedRegMap(Stvec, stvec),
461    MaskedRegMap(Scounteren, scounteren),
462
463    // Supervisor Trap Handling
464    MaskedRegMap(Sscratch, sscratch),
465    MaskedRegMap(Sepc, sepc),
466    MaskedRegMap(Scause, scause),
467    MaskedRegMap(Stval, stval),
468    MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask),
469
470    // Supervisor Protection and Translation
471    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
472
473    // Machine Information Registers
474    MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable),
475    MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable),
476    MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable),
477    MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable),
478
479    // Machine Trap Setup
480    // MaskedRegMap(Mstatus, mstatus, "hffffffffffffffee".U, (x=>{printf("mstatus write: %x time: %d\n", x, GTimer()); x})),
481    MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask),
482    MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable
483    MaskedRegMap(Medeleg, medeleg, "hf3ff".U),
484    MaskedRegMap(Mideleg, mideleg, "h222".U),
485    MaskedRegMap(Mie, mie),
486    MaskedRegMap(Mtvec, mtvec),
487    MaskedRegMap(Mcounteren, mcounteren),
488
489    // Machine Trap Handling
490    MaskedRegMap(Mscratch, mscratch),
491    MaskedRegMap(Mepc, mepc),
492    MaskedRegMap(Mcause, mcause),
493    MaskedRegMap(Mtval, mtval),
494    MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable),
495
496    // Machine Memory Protection
497    MaskedRegMap(Pmpcfg0, pmpcfg0),
498    MaskedRegMap(Pmpcfg1, pmpcfg1),
499    MaskedRegMap(Pmpcfg2, pmpcfg2),
500    MaskedRegMap(Pmpcfg3, pmpcfg3),
501    MaskedRegMap(PmpaddrBase + 0, pmpaddr0),
502    MaskedRegMap(PmpaddrBase + 1, pmpaddr1),
503    MaskedRegMap(PmpaddrBase + 2, pmpaddr2),
504    MaskedRegMap(PmpaddrBase + 3, pmpaddr3)
505
506  ) ++
507    perfCntsLoMapping ++ (if (XLEN == 32) perfCntsHiMapping else Nil) ++
508    (if(HasFPU) fcsrMapping else Nil)
509
510  val addr = src2(11, 0)
511  val rdata = Wire(UInt(XLEN.W))
512  val csri = ZeroExt(io.cfIn.instr(19,15), XLEN) //unsigned imm for csri. [TODO]
513  val wdata = LookupTree(func, List(
514    CSROpType.wrt  -> src1,
515    CSROpType.set  -> (rdata | src1),
516    CSROpType.clr  -> (rdata & (~src1).asUInt()),
517    CSROpType.wrti -> csri,//TODO: csri --> src2
518    CSROpType.seti -> (rdata | csri),
519    CSROpType.clri -> (rdata & (~csri).asUInt())
520  ))
521
522  // satp wen check
523  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
524
525  // general CSR wen check
526  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
527  val permitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
528  // Writeable check is ingored.
529  // Currently, write to illegal csr addr will be ignored
530  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
531  io.out.bits.data := rdata
532  io.out.bits.uop := io.in.bits.uop
533
534  // Fix Mip/Sip write
535  val fixMapping = Map(
536    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
537    MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask)
538  )
539  val rdataDummy = Wire(UInt(XLEN.W))
540  MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata)
541
542  when(io.fpu_csr.fflags.asUInt() =/= 0.U){
543    fcsr := fflags_wfn(io.fpu_csr.fflags.asUInt())
544  }
545  // set fs and sd in mstatus
546  when(csrw_dirty_fp_state || io.fpu_csr.dirty_fs){
547    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
548    mstatusNew.fs := "b11".U
549    mstatusNew.sd := true.B
550    mstatus := mstatusNew.asUInt()
551  }
552  io.fpu_csr.frm := fcsr.asTypeOf(new FcsrStruct).frm
553
554  // CSR inst decode
555  val isEbreak = addr === privEbreak && func === CSROpType.jmp
556  val isEcall = addr === privEcall && func === CSROpType.jmp
557  val isMret = addr === privMret   && func === CSROpType.jmp
558  val isSret = addr === privSret   && func === CSROpType.jmp
559  val isUret = addr === privUret   && func === CSROpType.jmp
560
561  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func)
562  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
563
564  // Illegal priviledged operation list
565  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
566
567  // Illegal priviledged instruction check
568  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
569  val isIllegalAccess = !permitted
570  val isIllegalPrivOp = illegalSModeSret
571
572  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
573  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
574  // imem
575  // val imemPtev = true.B
576  // val imemPteu = true.B
577  // val imemPtex = true.B
578  // val imemReq = true.B
579  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
580  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
581  // assert(!hasInstrPageFault)
582
583  // dmem
584  // val dmemPtev = true.B
585  // val dmemPteu = true.B
586  // val dmemReq = true.B
587  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
588  // val dmemIsStore = true.B
589
590  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
591  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
592  // assert(!hasLoadPageFault)
593  // assert(!hasStorePageFault)
594
595  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
596  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
597  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
598  tlbBundle.priv.imode := priviledgeMode
599  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
600
601  val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid
602  val hasLoadPageFault = io.exception.bits.cf.exceptionVec(loadPageFault) && io.exception.valid
603  val hasStorePageFault = io.exception.bits.cf.exceptionVec(storePageFault) && io.exception.valid
604  val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned) && io.exception.valid
605  val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned) && io.exception.valid
606
607  // mtval write logic
608  val memExceptionAddr = SignExt(io.memExceptionVAddr, XLEN)
609  when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
610    val tval = Mux(
611      hasInstrPageFault,
612      Mux(
613        io.exception.bits.cf.crossPageIPFFix,
614        SignExt(io.exception.bits.cf.pc + 2.U, XLEN),
615        SignExt(io.exception.bits.cf.pc, XLEN)
616      ),
617      memExceptionAddr
618    )
619    when(priviledgeMode === ModeM){
620      mtval := tval
621    }.otherwise{
622      stval := tval
623    }
624  }
625
626  when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
627  {
628    mtval := memExceptionAddr
629  }
630
631  // Exception and Intr
632
633  // interrupts
634
635  val ideleg =  (mideleg & mip.asUInt)
636  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
637    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
638
639  val intrVecEnable = Wire(Vec(12, Bool()))
640  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
641  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
642  val intrBitSet = intrVec.orR()
643  io.interrupt := intrBitSet
644  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
645  val raiseIntr = intrBitSet && io.exception.valid
646  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO)
647
648  mipWire.t.m := io.mtip
649  mipWire.s.m := io.msip
650  mipWire.e.m := io.meip
651
652  // exceptions
653  val csrExceptionVec = Wire(Vec(16, Bool()))
654  csrExceptionVec.map(_ := false.B)
655  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
656  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
657  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
658  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
659  // Trigger an illegal instr exception when:
660  // * unimplemented csr is being read/written
661  // * csr access is illegal
662  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
663  csrExceptionVec(loadPageFault) := hasLoadPageFault
664  csrExceptionVec(storePageFault) := hasStorePageFault
665  val iduExceptionVec = io.cfIn.exceptionVec
666  val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
667  io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
668  io.wenFix := DontCare
669
670  val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt()
671  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
672  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
673  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
674  ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR")
675  ExcitingUtils.addSource(causeNO, "difftestCausefromCSR")
676
677  val raiseExceptionIntr = io.exception.valid
678  val retTarget = Wire(UInt(VAddrBits.W))
679  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
680  io.redirectOut := DontCare
681  io.redirectOutValid := valid && func === CSROpType.jmp && !isEcall
682  io.redirectOut.target := retTarget
683  io.flushPipe := resetSatp
684
685  XSDebug(io.redirectOutValid, "redirect to %x, pc=%x\n", io.redirectOut.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  io.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.redirectOutValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
770    io.redirectOut.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.redirectOutValid, io.redirectOut.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(mtvec, "difftestMtvec")
873    BoringUtils.addSource(stvec, "difftestStvec")
874    BoringUtils.addSource(mcause, "difftestMcause")
875    BoringUtils.addSource(scause, "difftestScause")
876    BoringUtils.addSource(satp, "difftestSatp")
877    BoringUtils.addSource(mipReg, "difftestMip")
878    BoringUtils.addSource(mie, "difftestMie")
879    BoringUtils.addSource(mscratch, "difftestMscratch")
880    BoringUtils.addSource(sscratch, "difftestSscratch")
881    BoringUtils.addSource(mideleg, "difftestMideleg")
882    BoringUtils.addSource(medeleg, "difftestMedeleg")
883  } else {
884//    BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt")
885  }
886}
887