xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision 2dcdc8fb62c839600b26c2e2f5d9c50f4817314e)
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
19trait HasCSRConst {
20  // User Trap Setup
21  val Ustatus       = 0x000
22  val Uie           = 0x004
23  val Utvec         = 0x005
24
25  // User Trap Handling
26  val Uscratch      = 0x040
27  val Uepc          = 0x041
28  val Ucause        = 0x042
29  val Utval         = 0x043
30  val Uip           = 0x044
31
32  // User Floating-Point CSRs (not implemented)
33  val Fflags        = 0x001
34  val Frm           = 0x002
35  val Fcsr          = 0x003
36
37  // User Counter/Timers
38  val Cycle         = 0xC00
39  val Time          = 0xC01
40  val Instret       = 0xC02
41
42  // Supervisor Trap Setup
43  val Sstatus       = 0x100
44  val Sedeleg       = 0x102
45  val Sideleg       = 0x103
46  val Sie           = 0x104
47  val Stvec         = 0x105
48  val Scounteren    = 0x106
49
50  // Supervisor Trap Handling
51  val Sscratch      = 0x140
52  val Sepc          = 0x141
53  val Scause        = 0x142
54  val Stval         = 0x143
55  val Sip           = 0x144
56
57  // Supervisor Protection and Translation
58  val Satp          = 0x180
59
60  // Machine Information Registers
61  val Mvendorid     = 0xF11
62  val Marchid       = 0xF12
63  val Mimpid        = 0xF13
64  val Mhartid       = 0xF14
65
66  // Machine Trap Setup
67  val Mstatus       = 0x300
68  val Misa          = 0x301
69  val Medeleg       = 0x302
70  val Mideleg       = 0x303
71  val Mie           = 0x304
72  val Mtvec         = 0x305
73  val Mcounteren    = 0x306
74
75  // Machine Trap Handling
76  val Mscratch      = 0x340
77  val Mepc          = 0x341
78  val Mcause        = 0x342
79  val Mtval         = 0x343
80  val Mip           = 0x344
81
82  // Machine Memory Protection
83  // TBD
84  val Pmpcfg0       = 0x3A0
85  val Pmpcfg1       = 0x3A1
86  val Pmpcfg2       = 0x3A2
87  val Pmpcfg3       = 0x3A3
88  val PmpaddrBase   = 0x3B0
89
90  // Machine Counter/Timers
91  // Currently, we uses perfcnt csr set instead of standard Machine Counter/Timers
92  // 0xB80 - 0x89F are also used as perfcnt csr
93
94  // Machine Counter Setup (not implemented)
95  // Debug/Trace Registers (shared with Debug Mode) (not implemented)
96  // Debug Mode Registers (not implemented)
97
98  def privEcall  = 0x000.U
99  def privEbreak = 0x001.U
100  def privMret   = 0x302.U
101  def privSret   = 0x102.U
102  def privUret   = 0x002.U
103
104  def ModeM     = 0x3.U
105  def ModeH     = 0x2.U
106  def ModeS     = 0x1.U
107  def ModeU     = 0x0.U
108
109  def IRQ_UEIP  = 0
110  def IRQ_SEIP  = 1
111  def IRQ_MEIP  = 3
112
113  def IRQ_UTIP  = 4
114  def IRQ_STIP  = 5
115  def IRQ_MTIP  = 7
116
117  def IRQ_USIP  = 8
118  def IRQ_SSIP  = 9
119  def IRQ_MSIP  = 11
120
121  val IntPriority = Seq(
122    IRQ_MEIP, IRQ_MSIP, IRQ_MTIP,
123    IRQ_SEIP, IRQ_SSIP, IRQ_STIP,
124    IRQ_UEIP, IRQ_USIP, IRQ_UTIP
125  )
126
127  def csrAccessPermissionCheck(addr: UInt, wen: Bool, mode: UInt): Bool = {
128    val readOnly = addr(11,10) === "b11".U
129    val lowestAccessPrivilegeLevel = addr(9,8)
130    mode >= lowestAccessPrivilegeLevel && !(wen && readOnly)
131  }
132}
133
134trait HasExceptionNO {
135  def instrAddrMisaligned = 0
136  def instrAccessFault    = 1
137  def illegalInstr        = 2
138  def breakPoint          = 3
139  def loadAddrMisaligned  = 4
140  def loadAccessFault     = 5
141  def storeAddrMisaligned = 6
142  def storeAccessFault    = 7
143  def ecallU              = 8
144  def ecallS              = 9
145  def ecallM              = 11
146  def instrPageFault      = 12
147  def loadPageFault       = 13
148  def storePageFault      = 15
149
150  val ExcPriority = Seq(
151      breakPoint, // TODO: different BP has different priority
152      instrPageFault,
153      instrAccessFault,
154      illegalInstr,
155      instrAddrMisaligned,
156      ecallM, ecallS, ecallU,
157      storePageFault,
158      loadPageFault,
159      storeAccessFault,
160      loadAccessFault,
161      storeAddrMisaligned,
162      loadAddrMisaligned
163  )
164}
165
166class FpuCsrIO extends XSBundle {
167  val fflags = Output(Valid(UInt(5.W)))
168  val isIllegal = Output(Bool())
169  val dirty_fs = Output(Bool())
170  val frm = Input(UInt(3.W))
171}
172
173
174class PerfCounterIO extends XSBundle {
175  val value = Input(UInt(XLEN.W))
176}
177
178class CSR extends FunctionUnit with HasCSRConst
179{
180  val csrio = IO(new Bundle {
181    // output (for func === CSROpType.jmp)
182    val redirectOut = ValidIO(UInt(VAddrBits.W))
183    val perf = Vec(NumPerfCounters, new PerfCounterIO)
184    // to FPU
185    val fpu = Flipped(new FpuCsrIO)
186    // from rob
187    val exception = Flipped(ValidIO(new MicroOp))
188    val isInterrupt = Input(Bool())
189    // to ROB
190    val trapTarget = Output(UInt(VAddrBits.W))
191    val interrupt = Output(Bool())
192    // from LSQ
193    val memExceptionVAddr = Input(UInt(VAddrBits.W))
194    // from outside cpu,externalInterrupt
195    val externalInterrupt = new ExternalInterruptIO
196    // TLB
197    val tlb = Output(new TlbCsrBundle)
198  })
199
200  val cfIn = io.in.bits.uop.cf
201  val cfOut = Wire(new CtrlFlow)
202  cfOut := cfIn
203  val flushPipe = Wire(Bool())
204
205  val (valid, src1, src2, func) = (
206    io.in.valid,
207    io.in.bits.src(0),
208    io.in.bits.uop.ctrl.imm,
209    io.in.bits.uop.ctrl.fuOpType
210  )
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  csrio.tlb := 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(update: Boolean)(wdata: UInt): UInt = {
389    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
390    val fcsrNew = WireInit(fcsrOld)
391    csrw_dirty_fp_state := true.B
392    if(update){
393      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
394    } else {
395      fcsrNew.fflags := wdata(4,0)
396    }
397    fcsrNew.asUInt()
398  }
399  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
400
401  def fcsr_wfn(wdata: UInt): UInt = {
402    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
403    csrw_dirty_fp_state := true.B
404    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
405  }
406
407  val fcsrMapping = Map(
408    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
409    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
410    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
411  )
412
413  // Atom LR/SC Control Bits
414//  val setLr = WireInit(Bool(), false.B)
415//  val setLrVal = WireInit(Bool(), false.B)
416//  val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check
417//  val lr = RegInit(Bool(), false.B)
418//  val lrAddr = RegInit(UInt(AddrBits.W), 0.U)
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  println(s"CSR: hasPerfCnt:${hasPerfCnt}")
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(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  io.out.bits.uop.cf := cfOut
535  io.out.bits.uop.ctrl.flushPipe := flushPipe
536
537  // Fix Mip/Sip write
538  val fixMapping = Map(
539    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
540    MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask)
541  )
542  val rdataDummy = Wire(UInt(XLEN.W))
543  MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata)
544
545  when(csrio.fpu.fflags.valid){
546    fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits)
547  }
548  // set fs and sd in mstatus
549  when(csrw_dirty_fp_state || csrio.fpu.dirty_fs){
550    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
551    mstatusNew.fs := "b11".U
552    mstatusNew.sd := true.B
553    mstatus := mstatusNew.asUInt()
554  }
555  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
556
557  // CSR inst decode
558  val isEbreak = addr === privEbreak && func === CSROpType.jmp
559  val isEcall = addr === privEcall && func === CSROpType.jmp
560  val isMret = addr === privMret   && func === CSROpType.jmp
561  val isSret = addr === privSret   && func === CSROpType.jmp
562  val isUret = addr === privUret   && func === CSROpType.jmp
563
564  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func)
565  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
566
567  // Illegal priviledged operation list
568  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
569
570  // Illegal priviledged instruction check
571  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
572  val isIllegalAccess = !permitted
573  val isIllegalPrivOp = illegalSModeSret
574
575  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
576  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
577  // imem
578  // val imemPtev = true.B
579  // val imemPteu = true.B
580  // val imemPtex = true.B
581  // val imemReq = true.B
582  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
583  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
584  // assert(!hasInstrPageFault)
585
586  // dmem
587  // val dmemPtev = true.B
588  // val dmemPteu = true.B
589  // val dmemReq = true.B
590  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
591  // val dmemIsStore = true.B
592
593  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
594  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
595  // assert(!hasLoadPageFault)
596  // assert(!hasStorePageFault)
597
598  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
599  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
600  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
601  tlbBundle.priv.imode := priviledgeMode
602  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
603
604  // Branch control
605  val retTarget = Wire(UInt(VAddrBits.W))
606  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
607  csrio.redirectOut.valid := valid && func === CSROpType.jmp && !isEcall
608  csrio.redirectOut.bits := retTarget
609  flushPipe := resetSatp
610  XSDebug(csrio.redirectOut.valid, "redirect to %x, pc=%x\n", csrio.redirectOut.bits, cfIn.pc)
611
612  retTarget := DontCare
613  // val illegalEret = TODO
614
615  when (valid && isMret) {
616    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
617    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
618    mstatusNew.ie.m := mstatusOld.pie.m
619    priviledgeMode := mstatusOld.mpp
620    mstatusNew.pie.m := true.B
621    mstatusNew.mpp := ModeU
622    mstatusNew.mprv := 0.U
623    mstatus := mstatusNew.asUInt
624//    lr := false.B
625    retTarget := mepc(VAddrBits-1, 0)
626  }
627
628  when (valid && isSret && !illegalSModeSret) {
629    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
630    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
631    mstatusNew.ie.s := mstatusOld.pie.s
632    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
633    mstatusNew.pie.s := true.B
634    mstatusNew.spp := ModeU
635    mstatus := mstatusNew.asUInt
636    mstatusNew.mprv := 0.U
637    // lr := false.B
638    retTarget := sepc(VAddrBits-1, 0)
639  }
640
641  when (valid && isUret) {
642    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
643    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
644    // mstatusNew.mpp.m := ModeU //TODO: add mode U
645    mstatusNew.ie.u := mstatusOld.pie.u
646    priviledgeMode := ModeU
647    mstatusNew.pie.u := true.B
648    mstatus := mstatusNew.asUInt
649    retTarget := uepc(VAddrBits-1, 0)
650  }
651
652  XSDebug(csrio.redirectOut.valid,
653    "Rediret %x isSret:%d retTarget:%x sepc:%x cfInpc:%x valid:%d\n",
654    csrio.redirectOut.bits, isSret, retTarget, sepc, cfIn.pc, valid
655  )
656
657  io.in.ready := true.B
658  io.out.valid := valid
659
660  /**
661    * Exception and Intr
662    */
663  val ideleg =  (mideleg & mip.asUInt)
664  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
665    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
666
667  // send interrupt information to ROQ
668  val intrVecEnable = Wire(Vec(12, Bool()))
669  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
670  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
671  val intrBitSet = intrVec.orR()
672  csrio.interrupt := intrBitSet
673  mipWire.t.m := csrio.externalInterrupt.mtip
674  mipWire.s.m := csrio.externalInterrupt.msip
675  mipWire.e.m := csrio.externalInterrupt.meip
676
677  // interrupts
678  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
679  val raiseIntr = csrio.exception.valid && csrio.isInterrupt
680  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.cf.pc, intrNO)
681
682  // exceptions
683  val raiseException = csrio.exception.valid && !csrio.isInterrupt
684  val hasInstrPageFault = csrio.exception.bits.cf.exceptionVec(instrPageFault) && raiseException
685  val hasLoadPageFault = csrio.exception.bits.cf.exceptionVec(loadPageFault) && raiseException
686  val hasStorePageFault = csrio.exception.bits.cf.exceptionVec(storePageFault) && raiseException
687  val hasStoreAddrMisaligned = csrio.exception.bits.cf.exceptionVec(storeAddrMisaligned) && raiseException
688  val hasLoadAddrMisaligned = csrio.exception.bits.cf.exceptionVec(loadAddrMisaligned) && raiseException
689
690  val csrExceptionVec = Wire(Vec(16, Bool()))
691  csrExceptionVec.map(_ := false.B)
692  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
693  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
694  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
695  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
696  // Trigger an illegal instr exception when:
697  // * unimplemented csr is being read/written
698  // * csr access is illegal
699  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
700  csrExceptionVec(loadPageFault) := hasLoadPageFault
701  csrExceptionVec(storePageFault) := hasStorePageFault
702  val iduExceptionVec = cfIn.exceptionVec
703  val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
704  cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
705
706  val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec.asUInt()
707  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
708  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
709  // if (!env.FPGAPlatform) {
710    val id = debugId()
711    val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
712    ExcitingUtils.addSource(difftestIntrNO, s"difftestIntrNOfromCSR$id")
713    ExcitingUtils.addSource(causeNO, s"difftestCausefromCSR$id")
714  // }
715
716  val raiseExceptionIntr = csrio.exception.valid
717  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
718    csrio.exception.bits.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
719  )
720  XSDebug(raiseExceptionIntr,
721    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
722    csrio.exception.bits.cf.pc,
723    mstatus,
724    mideleg,
725    medeleg,
726    priviledgeMode
727  )
728
729  // mtval write logic
730  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
731  when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
732    val tval = Mux(
733      hasInstrPageFault,
734      Mux(
735        csrio.exception.bits.cf.crossPageIPFFix,
736        SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN),
737        SignExt(csrio.exception.bits.cf.pc, XLEN)
738      ),
739      memExceptionAddr
740    )
741    when(priviledgeMode === ModeM){
742      mtval := tval
743    }.otherwise{
744      stval := tval
745    }
746  }
747
748  when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
749  {
750    mtval := memExceptionAddr
751  }
752
753  val deleg = Mux(raiseIntr, mideleg , medeleg)
754  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
755  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
756  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
757  csrio.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
758
759  when (raiseExceptionIntr) {
760    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
761    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
762
763    when (delegS) {
764      scause := causeNO
765      sepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
766      mstatusNew.spp := priviledgeMode
767      mstatusNew.pie.s := mstatusOld.ie.s
768      mstatusNew.ie.s := false.B
769      priviledgeMode := ModeS
770      when(tvalWen){stval := 0.U}
771      // trapTarget := stvec(VAddrBits-1. 0)
772    }.otherwise {
773      mcause := causeNO
774      mepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
775      mstatusNew.mpp := priviledgeMode
776      mstatusNew.pie.m := mstatusOld.ie.m
777      mstatusNew.ie.m := false.B
778      priviledgeMode := ModeM
779      when(tvalWen){mtval := 0.U}
780      // trapTarget := mtvec(VAddrBits-1. 0)
781    }
782
783    mstatus := mstatusNew.asUInt
784  }
785
786  XSDebug(raiseExceptionIntr && delegS,
787    "Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n",
788    csrio.redirectOut.valid, csrio.redirectOut.bits, raiseExceptionIntr,
789    isSret, sepc, delegS, deleg
790  )
791  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
792
793
794  /**
795    * Performance counters
796    */
797  val perfCntList = Map(
798//    "Mcycle"      -> (0xb00, "perfCntCondMcycle"     ),
799//    "Minstret"    -> (0xb02, "perfCntCondMinstret"   ),
800    "MbpInstr"    -> (0xb03, "perfCntCondMbpInstr"   ),
801    "MbpRight"    -> (0xb04, "perfCntCondMbpRight"   ),
802    "MbpWrong"    -> (0xb05, "perfCntCondMbpWrong"   ),
803    "MbpBRight"   -> (0xb06, "perfCntCondMbpBRight"   ),
804    "MbpBWrong"   -> (0xb07, "perfCntCondMbpBWrong"   ),
805    "MbpJRight"   -> (0xb08, "perfCntCondMbpJRight"   ),
806    "MbpJWrong"   -> (0xb09, "perfCntCondMbpJWrong"   ),
807    "MbpIRight"   -> (0xb0a, "perfCntCondMbpIRight"   ),
808    "MbpIWrong"   -> (0xb0b, "perfCntCondMbpIWrong"   ),
809    "MbpRRight"   -> (0xb0c, "perfCntCondMbpRRight"   ),
810    "MbpRWrong"   -> (0xb0d, "perfCntCondMbpRWrong"   ),
811    "RoqWalk"     -> (0xb0f, "perfCntCondRoqWalk"     ),
812    "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0"     ),
813    "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1"     ),
814    "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2"     ),
815    "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3"     ),
816    "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0"    ),
817    "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1"    ),
818    "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2"    ),
819    "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3"    ),
820    "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0"     ),
821    "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0"    ),
822    "PtwReqCnt"   -> (0xb25, "perfCntPtwReqCnt"       ),
823    "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt"     ),
824    "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit"     ),
825    "ICacheReq"   -> (0xb28, "perfCntIcacheReqCnt"     ),
826    "ICacheMiss"   -> (0xb29, "perfCntIcacheMissCnt"     )//,
827    // "FetchFromICache" -> (0xb2a, "CntFetchFromICache"),
828    // "FetchFromLoopBuffer" -> (0xb2b, "CntFetchFromLoopBuffer"),
829    // "ExitLoop1" -> (0xb2c, "CntExitLoop1"),
830    // "ExitLoop2" -> (0xb2d, "CntExitLoop2"),
831    // "ExitLoop3" -> (0xb2e, "CntExitLoop3")
832//    "Custom1"     -> (0xb1b, "Custom1"             ),
833//    "Custom2"     -> (0xb1c, "Custom2"             ),
834//    "Custom3"     -> (0xb1d, "Custom3"             ),
835//    "Custom4"     -> (0xb1e, "Custom4"             ),
836//    "Custom5"     -> (0xb1f, "Custom5"             ),
837//    "Custom6"     -> (0xb20, "Custom6"             ),
838//    "Custom7"     -> (0xb21, "Custom7"             ),
839//    "Custom8"     -> (0xb22, "Custom8"             ),
840//    "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
841  )
842  val perfCntCond = List.fill(0x80)(WireInit(false.B))
843  (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
844
845//  ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf)
846  perfCntList.foreach {
847    case (_, (address, boringId)) =>
848      if(hasPerfCnt){
849        ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
850      }
851//      if (!hasPerfCnt) {
852//        // do not enable perfcnts except for Mcycle and Minstret
853//        if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) {
854//          perfCntCond(address & 0x7f) := false.B
855//        }
856//      }
857  }
858
859  val xstrap = WireInit(false.B)
860  if(!env.FPGAPlatform && EnableBPU){
861    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
862  }
863  def readWithScala(addr: Int): UInt = mapping(addr)._1
864
865  if (!env.FPGAPlatform) {
866
867    // display all perfcnt when nooptrap is executed
868    when (xstrap) {
869      printf("======== PerfCnt =========\n")
870      perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) =>
871        printf("%d <- " + str + "\n", readWithScala(address))
872      }
873    }
874
875    ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug)
876    ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug)
877    ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug)
878    ExcitingUtils.addSource(mepc, "difftestMepc", Debug)
879    ExcitingUtils.addSource(sepc, "difftestSepc", Debug)
880    ExcitingUtils.addSource(mtval, "difftestMtval", Debug)
881    ExcitingUtils.addSource(stval, "difftestStval", Debug)
882    ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug)
883    ExcitingUtils.addSource(stvec, "difftestStvec", Debug)
884    ExcitingUtils.addSource(mcause, "difftestMcause", Debug)
885    ExcitingUtils.addSource(scause, "difftestScause", Debug)
886    ExcitingUtils.addSource(satp, "difftestSatp", Debug)
887    ExcitingUtils.addSource(mipReg, "difftestMip", Debug)
888    ExcitingUtils.addSource(mie, "difftestMie", Debug)
889    ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug)
890    ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug)
891    ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug)
892    ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug)
893  } else {
894  }
895}
896