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