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