xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision a1fd7de4103f2448006f7bd974fd59cb9c6e7c7b)
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  // Branch control
600  val retTarget = Wire(UInt(VAddrBits.W))
601  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
602  csrio.redirectOut.valid := valid && func === CSROpType.jmp && !isEcall
603  csrio.redirectOut.bits := retTarget
604  flushPipe := resetSatp
605  XSDebug(csrio.redirectOut.valid, "redirect to %x, pc=%x\n", csrio.redirectOut.bits, cfIn.pc)
606
607  retTarget := DontCare
608  // val illegalEret = TODO
609
610  when (valid && isMret) {
611    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
612    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
613    mstatusNew.ie.m := mstatusOld.pie.m
614    priviledgeMode := mstatusOld.mpp
615    mstatusNew.pie.m := true.B
616    mstatusNew.mpp := ModeU
617    mstatusNew.mprv := 0.U
618    mstatus := mstatusNew.asUInt
619//    lr := false.B
620    retTarget := mepc(VAddrBits-1, 0)
621  }
622
623  when (valid && isSret && !illegalSModeSret) {
624    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
625    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
626    mstatusNew.ie.s := mstatusOld.pie.s
627    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
628    mstatusNew.pie.s := true.B
629    mstatusNew.spp := ModeU
630    mstatus := mstatusNew.asUInt
631    mstatusNew.mprv := 0.U
632    // lr := false.B
633    retTarget := sepc(VAddrBits-1, 0)
634  }
635
636  when (valid && isUret) {
637    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
638    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
639    // mstatusNew.mpp.m := ModeU //TODO: add mode U
640    mstatusNew.ie.u := mstatusOld.pie.u
641    priviledgeMode := ModeU
642    mstatusNew.pie.u := true.B
643    mstatus := mstatusNew.asUInt
644    retTarget := uepc(VAddrBits-1, 0)
645  }
646
647  XSDebug(csrio.redirectOut.valid,
648    "Rediret %x isSret:%d retTarget:%x sepc:%x cfInpc:%x valid:%d\n",
649    csrio.redirectOut.bits, isSret, retTarget, sepc, cfIn.pc, valid
650  )
651
652  io.in.ready := true.B
653  io.out.valid := valid
654
655  /**
656    * Exception and Intr
657    */
658  val ideleg =  (mideleg & mip.asUInt)
659  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
660    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
661
662  // send interrupt information to ROQ
663  val intrVecEnable = Wire(Vec(12, Bool()))
664  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
665  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
666  val intrBitSet = intrVec.orR()
667  csrio.interrupt := intrBitSet
668  mipWire.t.m := csrio.externalInterrupt.mtip
669  mipWire.s.m := csrio.externalInterrupt.msip
670  mipWire.e.m := csrio.externalInterrupt.meip
671
672  // interrupts
673  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
674  val raiseIntr = csrio.exception.valid && csrio.isInterrupt
675  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.cf.pc, intrNO)
676
677  // exceptions
678  val raiseException = csrio.exception.valid && !csrio.isInterrupt
679  val hasInstrPageFault = csrio.exception.bits.cf.exceptionVec(instrPageFault) && raiseException
680  val hasLoadPageFault = csrio.exception.bits.cf.exceptionVec(loadPageFault) && raiseException
681  val hasStorePageFault = csrio.exception.bits.cf.exceptionVec(storePageFault) && raiseException
682  val hasStoreAddrMisaligned = csrio.exception.bits.cf.exceptionVec(storeAddrMisaligned) && raiseException
683  val hasLoadAddrMisaligned = csrio.exception.bits.cf.exceptionVec(loadAddrMisaligned) && raiseException
684
685  val csrExceptionVec = Wire(Vec(16, Bool()))
686  csrExceptionVec.map(_ := false.B)
687  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
688  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
689  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
690  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
691  // Trigger an illegal instr exception when:
692  // * unimplemented csr is being read/written
693  // * csr access is illegal
694  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
695  csrExceptionVec(loadPageFault) := hasLoadPageFault
696  csrExceptionVec(storePageFault) := hasStorePageFault
697  val iduExceptionVec = cfIn.exceptionVec
698  val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
699  cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
700
701  val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec.asUInt()
702  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
703  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
704  // if (!env.FPGAPlatform) {
705    val id = debugId()
706    val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
707    ExcitingUtils.addSource(difftestIntrNO, s"difftestIntrNOfromCSR$id")
708    ExcitingUtils.addSource(causeNO, s"difftestCausefromCSR$id")
709  // }
710
711  val raiseExceptionIntr = csrio.exception.valid
712  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
713    csrio.exception.bits.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
714  )
715  XSDebug(raiseExceptionIntr,
716    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
717    csrio.exception.bits.cf.pc,
718    mstatus,
719    mideleg,
720    medeleg,
721    priviledgeMode
722  )
723
724  // mtval write logic
725  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
726  when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
727    val tval = Mux(
728      hasInstrPageFault,
729      Mux(
730        csrio.exception.bits.cf.crossPageIPFFix,
731        SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN),
732        SignExt(csrio.exception.bits.cf.pc, XLEN)
733      ),
734      memExceptionAddr
735    )
736    when(priviledgeMode === ModeM){
737      mtval := tval
738    }.otherwise{
739      stval := tval
740    }
741  }
742
743  when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
744  {
745    mtval := memExceptionAddr
746  }
747
748  val deleg = Mux(raiseIntr, mideleg , medeleg)
749  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
750  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
751  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
752  csrio.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
753
754  when (raiseExceptionIntr) {
755    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
756    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
757
758    when (delegS) {
759      scause := causeNO
760      sepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
761      mstatusNew.spp := priviledgeMode
762      mstatusNew.pie.s := mstatusOld.ie.s
763      mstatusNew.ie.s := false.B
764      priviledgeMode := ModeS
765      when(tvalWen){stval := 0.U}
766      // trapTarget := stvec(VAddrBits-1. 0)
767    }.otherwise {
768      mcause := causeNO
769      mepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
770      mstatusNew.mpp := priviledgeMode
771      mstatusNew.pie.m := mstatusOld.ie.m
772      mstatusNew.ie.m := false.B
773      priviledgeMode := ModeM
774      when(tvalWen){mtval := 0.U}
775      // trapTarget := mtvec(VAddrBits-1. 0)
776    }
777
778    mstatus := mstatusNew.asUInt
779  }
780
781  XSDebug(raiseExceptionIntr && delegS,
782    "Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n",
783    csrio.redirectOut.valid, csrio.redirectOut.bits, raiseExceptionIntr,
784    isSret, sepc, delegS, deleg
785  )
786  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
787
788
789  /**
790    * Performance counters
791    */
792  val perfCntList = Map(
793//    "Mcycle"      -> (0xb00, "perfCntCondMcycle"     ),
794//    "Minstret"    -> (0xb02, "perfCntCondMinstret"   ),
795    "MbpInstr"    -> (0xb03, "perfCntCondMbpInstr"   ),
796    "MbpRight"    -> (0xb04, "perfCntCondMbpRight"   ),
797    "MbpWrong"    -> (0xb05, "perfCntCondMbpWrong"   ),
798    "MbpBRight"   -> (0xb06, "perfCntCondMbpBRight"   ),
799    "MbpBWrong"   -> (0xb07, "perfCntCondMbpBWrong"   ),
800    "MbpJRight"   -> (0xb08, "perfCntCondMbpJRight"   ),
801    "MbpJWrong"   -> (0xb09, "perfCntCondMbpJWrong"   ),
802    "MbpIRight"   -> (0xb0a, "perfCntCondMbpIRight"   ),
803    "MbpIWrong"   -> (0xb0b, "perfCntCondMbpIWrong"   ),
804    "MbpRRight"   -> (0xb0c, "perfCntCondMbpRRight"   ),
805    "MbpRWrong"   -> (0xb0d, "perfCntCondMbpRWrong"   ),
806    "RoqWalk"     -> (0xb0f, "perfCntCondRoqWalk"     ),
807    "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0"     ),
808    "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1"     ),
809    "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2"     ),
810    "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3"     ),
811    "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0"    ),
812    "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1"    ),
813    "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2"    ),
814    "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3"    ),
815    "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0"     ),
816    "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0"    ),
817    "PtwReqCnt"   -> (0xb25, "perfCntPtwReqCnt"       ),
818    "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt"     ),
819    "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit"     ),
820    "ICacheReq"   -> (0xb28, "perfCntIcacheReqCnt"     ),
821    "ICacheMiss"   -> (0xb29, "perfCntIcacheMissCnt"     )//,
822    // "FetchFromICache" -> (0xb2a, "CntFetchFromICache"),
823    // "FetchFromLoopBuffer" -> (0xb2b, "CntFetchFromLoopBuffer"),
824    // "ExitLoop1" -> (0xb2c, "CntExitLoop1"),
825    // "ExitLoop2" -> (0xb2d, "CntExitLoop2"),
826    // "ExitLoop3" -> (0xb2e, "CntExitLoop3")
827//    "Custom1"     -> (0xb1b, "Custom1"             ),
828//    "Custom2"     -> (0xb1c, "Custom2"             ),
829//    "Custom3"     -> (0xb1d, "Custom3"             ),
830//    "Custom4"     -> (0xb1e, "Custom4"             ),
831//    "Custom5"     -> (0xb1f, "Custom5"             ),
832//    "Custom6"     -> (0xb20, "Custom6"             ),
833//    "Custom7"     -> (0xb21, "Custom7"             ),
834//    "Custom8"     -> (0xb22, "Custom8"             ),
835//    "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
836  )
837  val perfCntCond = List.fill(0x80)(WireInit(false.B))
838  (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
839
840//  ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf)
841  perfCntList.foreach {
842    case (_, (address, boringId)) =>
843      if(hasPerfCnt){
844        ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
845      }
846//      if (!hasPerfCnt) {
847//        // do not enable perfcnts except for Mcycle and Minstret
848//        if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) {
849//          perfCntCond(address & 0x7f) := false.B
850//        }
851//      }
852  }
853
854  val xstrap = WireInit(false.B)
855  if(!env.FPGAPlatform && EnableBPU){
856    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
857  }
858  def readWithScala(addr: Int): UInt = mapping(addr)._1
859
860  if (!env.FPGAPlatform) {
861
862    // display all perfcnt when nooptrap is executed
863    when (xstrap) {
864      printf("======== PerfCnt =========\n")
865      perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) =>
866        printf("%d <- " + str + "\n", readWithScala(address))
867      }
868    }
869
870    ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug)
871    ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug)
872    ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug)
873    ExcitingUtils.addSource(mepc, "difftestMepc", Debug)
874    ExcitingUtils.addSource(sepc, "difftestSepc", Debug)
875    ExcitingUtils.addSource(mtval, "difftestMtval", Debug)
876    ExcitingUtils.addSource(stval, "difftestStval", Debug)
877    ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug)
878    ExcitingUtils.addSource(stvec, "difftestStvec", Debug)
879    ExcitingUtils.addSource(mcause, "difftestMcause", Debug)
880    ExcitingUtils.addSource(scause, "difftestScause", Debug)
881    ExcitingUtils.addSource(satp, "difftestSatp", Debug)
882    ExcitingUtils.addSource(mipReg, "difftestMip", Debug)
883    ExcitingUtils.addSource(mie, "difftestMie", Debug)
884    ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug)
885    ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug)
886    ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug)
887    ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug)
888  } else {
889  }
890}
891