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