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