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