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