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