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