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