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