xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision a9ecfa67572f9dc8d32a66b8924cfc8e21bbda0c)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.ExcitingUtils.{ConnectionType, Debug}
5import chisel3.util._
6import fpu.Fflags
7import utils._
8import xiangshan._
9import xiangshan.backend._
10import xiangshan.backend.fu.FunctionUnit._
11import utils.XSDebug
12
13trait HasCSRConst {
14  // User Trap Setup
15  val Ustatus       = 0x000
16  val Uie           = 0x004
17  val Utvec         = 0x005
18
19  // User Trap Handling
20  val Uscratch      = 0x040
21  val Uepc          = 0x041
22  val Ucause        = 0x042
23  val Utval         = 0x043
24  val Uip           = 0x044
25
26  // User Floating-Point CSRs (not implemented)
27  val Fflags        = 0x001
28  val Frm           = 0x002
29  val Fcsr          = 0x003
30
31  // User Counter/Timers
32  val Cycle         = 0xC00
33  val Time          = 0xC01
34  val Instret       = 0xC02
35
36  // Supervisor Trap Setup
37  val Sstatus       = 0x100
38  val Sedeleg       = 0x102
39  val Sideleg       = 0x103
40  val Sie           = 0x104
41  val Stvec         = 0x105
42  val Scounteren    = 0x106
43
44  // Supervisor Trap Handling
45  val Sscratch      = 0x140
46  val Sepc          = 0x141
47  val Scause        = 0x142
48  val Stval         = 0x143
49  val Sip           = 0x144
50
51  // Supervisor Protection and Translation
52  val Satp          = 0x180
53
54  // Machine Information Registers
55  val Mvendorid     = 0xF11
56  val Marchid       = 0xF12
57  val Mimpid        = 0xF13
58  val Mhartid       = 0xF14
59
60  // Machine Trap Setup
61  val Mstatus       = 0x300
62  val Misa          = 0x301
63  val Medeleg       = 0x302
64  val Mideleg       = 0x303
65  val Mie           = 0x304
66  val Mtvec         = 0x305
67  val Mcounteren    = 0x306
68
69  // Machine Trap Handling
70  val Mscratch      = 0x340
71  val Mepc          = 0x341
72  val Mcause        = 0x342
73  val Mtval         = 0x343
74  val Mip           = 0x344
75
76  // Machine Memory Protection
77  // TBD
78  val Pmpcfg0       = 0x3A0
79  val Pmpcfg1       = 0x3A1
80  val Pmpcfg2       = 0x3A2
81  val Pmpcfg3       = 0x3A3
82  val PmpaddrBase   = 0x3B0
83
84  // Machine Counter/Timers
85  // Currently, we uses perfcnt csr set instead of standard Machine Counter/Timers
86  // 0xB80 - 0x89F are also used as perfcnt csr
87
88  // Machine Counter Setup (not implemented)
89  // Debug/Trace Registers (shared with Debug Mode) (not implemented)
90  // Debug Mode Registers (not implemented)
91
92  def privEcall  = 0x000.U
93  def privEbreak = 0x001.U
94  def privMret   = 0x302.U
95  def privSret   = 0x102.U
96  def privUret   = 0x002.U
97
98  def ModeM     = 0x3.U
99  def ModeH     = 0x2.U
100  def ModeS     = 0x1.U
101  def ModeU     = 0x0.U
102
103  def IRQ_UEIP  = 0
104  def IRQ_SEIP  = 1
105  def IRQ_MEIP  = 3
106
107  def IRQ_UTIP  = 4
108  def IRQ_STIP  = 5
109  def IRQ_MTIP  = 7
110
111  def IRQ_USIP  = 8
112  def IRQ_SSIP  = 9
113  def IRQ_MSIP  = 11
114
115  val IntPriority = Seq(
116    IRQ_MEIP, IRQ_MSIP, IRQ_MTIP,
117    IRQ_SEIP, IRQ_SSIP, IRQ_STIP,
118    IRQ_UEIP, IRQ_USIP, IRQ_UTIP
119  )
120
121  def csrAccessPermissionCheck(addr: UInt, wen: Bool, mode: UInt): Bool = {
122    val readOnly = addr(11,10) === "b11".U
123    val lowestAccessPrivilegeLevel = addr(9,8)
124    mode >= lowestAccessPrivilegeLevel && !(wen && readOnly)
125  }
126}
127
128trait HasExceptionNO {
129  def instrAddrMisaligned = 0
130  def instrAccessFault    = 1
131  def illegalInstr        = 2
132  def breakPoint          = 3
133  def loadAddrMisaligned  = 4
134  def loadAccessFault     = 5
135  def storeAddrMisaligned = 6
136  def storeAccessFault    = 7
137  def ecallU              = 8
138  def ecallS              = 9
139  def ecallM              = 11
140  def instrPageFault      = 12
141  def loadPageFault       = 13
142  def storePageFault      = 15
143
144  val ExcPriority = Seq(
145      breakPoint, // TODO: different BP has different priority
146      instrPageFault,
147      instrAccessFault,
148      illegalInstr,
149      instrAddrMisaligned,
150      ecallM, ecallS, ecallU,
151      storePageFault,
152      loadPageFault,
153      storeAccessFault,
154      loadAccessFault,
155      storeAddrMisaligned,
156      loadAddrMisaligned
157  )
158}
159
160class FpuCsrIO extends XSBundle {
161  val fflags = Output(new Fflags)
162  val isIllegal = Output(Bool())
163  val dirty_fs = Output(Bool())
164  val frm = Input(UInt(3.W))
165}
166
167
168class PerfCounterIO extends XSBundle {
169  val value = Input(UInt(XLEN.W))
170}
171
172class CSRIO extends FunctionUnitIO[UInt, Null](csrCfg, len=64, extIn= FuOpType()) {
173  val cfIn = Input(new CtrlFlow)
174  val redirectOut = Output(new Redirect)
175  val redirectOutValid = Output(Bool())
176  val fpu_csr = Flipped(new FpuCsrIO)
177  val cfOut = Output(new CtrlFlow)
178  // from rob
179  val exception = Flipped(ValidIO(new MicroOp))
180  val isInterrupt = Input(Bool())
181  // for exception check
182  val instrValid = Input(Bool())
183  val flushPipe = Output(Bool())
184  // for differential testing
185//  val intrNO = Output(UInt(XLEN.W))
186  val wenFix = Output(Bool())
187
188  override def cloneType: CSRIO.this.type =
189    new CSRIO().asInstanceOf[this.type]
190
191  val perf = Vec(NumPerfCounters, new PerfCounterIO)
192  val memExceptionVAddr = Input(UInt(VAddrBits.W))
193  val trapTarget = Output(UInt(VAddrBits.W))
194  val mtip = Input(Bool())
195  val msip = Input(Bool())
196  val meip = Input(Bool())
197  val interrupt = Output(Bool())
198  val tlbCsrIO = Output(new TlbCsrBundle)
199}
200
201class CSR extends XSModule
202    with HasCSRConst
203{
204
205  val io = IO(new CSRIO)
206
207  io.cfOut := io.cfIn
208
209  val (valid, src1, src2, func) =
210    (io.in.valid, io.in.bits.src(0), io.in.bits.uop.ctrl.imm, io.in.bits.ext.get)
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  io.tlbCsrIO := 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
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(io.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
530  // Fix Mip/Sip write
531  val fixMapping = Map(
532    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
533    MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask)
534  )
535  val rdataDummy = Wire(UInt(XLEN.W))
536  MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata)
537
538  when(io.fpu_csr.fflags.asUInt() =/= 0.U){
539    fcsr := fflags_wfn(io.fpu_csr.fflags.asUInt())
540  }
541  // set fs and sd in mstatus
542  when(csrw_dirty_fp_state || io.fpu_csr.dirty_fs){
543    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
544    mstatusNew.fs := "b11".U
545    mstatusNew.sd := true.B
546    mstatus := mstatusNew.asUInt()
547  }
548  io.fpu_csr.frm := fcsr.asTypeOf(new FcsrStruct).frm
549
550  // CSR inst decode
551  val isEbreak = addr === privEbreak && func === CSROpType.jmp
552  val isEcall = addr === privEcall && func === CSROpType.jmp
553  val isMret = addr === privMret   && func === CSROpType.jmp
554  val isSret = addr === privSret   && func === CSROpType.jmp
555  val isUret = addr === privUret   && func === CSROpType.jmp
556
557  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func)
558  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
559
560  // Illegal priviledged operation list
561  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
562
563  // Illegal priviledged instruction check
564  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
565  val isIllegalAccess = !permitted
566  val isIllegalPrivOp = illegalSModeSret
567
568  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
569  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
570  // imem
571  // val imemPtev = true.B
572  // val imemPteu = true.B
573  // val imemPtex = true.B
574  // val imemReq = true.B
575  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
576  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
577  // assert(!hasInstrPageFault)
578
579  // dmem
580  // val dmemPtev = true.B
581  // val dmemPteu = true.B
582  // val dmemReq = true.B
583  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
584  // val dmemIsStore = true.B
585
586  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
587  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
588  // assert(!hasLoadPageFault)
589  // assert(!hasStorePageFault)
590
591  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
592  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
593  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
594  tlbBundle.priv.imode := priviledgeMode
595  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
596
597  val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid
598  val hasLoadPageFault = io.exception.bits.cf.exceptionVec(loadPageFault) && io.exception.valid
599  val hasStorePageFault = io.exception.bits.cf.exceptionVec(storePageFault) && io.exception.valid
600  val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned) && io.exception.valid
601  val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned) && io.exception.valid
602
603  // mtval write logic
604  val memExceptionAddr = SignExt(io.memExceptionVAddr, XLEN)
605  when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
606    val tval = Mux(
607      hasInstrPageFault,
608      Mux(
609        io.exception.bits.cf.crossPageIPFFix,
610        SignExt(io.exception.bits.cf.pc + 2.U, XLEN),
611        SignExt(io.exception.bits.cf.pc, XLEN)
612      ),
613      memExceptionAddr
614    )
615    when(priviledgeMode === ModeM){
616      mtval := tval
617    }.otherwise{
618      stval := tval
619    }
620  }
621
622  when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
623  {
624    mtval := memExceptionAddr
625  }
626
627  // Exception and Intr
628
629  // interrupts
630
631  val ideleg =  (mideleg & mip.asUInt)
632  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
633    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
634
635  val intrVecEnable = Wire(Vec(12, Bool()))
636  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
637  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
638  val intrBitSet = intrVec.orR()
639  io.interrupt := intrBitSet
640  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
641  val raiseIntr = intrBitSet && io.exception.valid && io.isInterrupt
642  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO)
643
644  mipWire.t.m := io.mtip
645  mipWire.s.m := io.msip
646  mipWire.e.m := io.meip
647
648  // exceptions
649  val csrExceptionVec = Wire(Vec(16, Bool()))
650  csrExceptionVec.map(_ := false.B)
651  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
652  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
653  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
654  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
655  // Trigger an illegal instr exception when:
656  // * unimplemented csr is being read/written
657  // * csr access is illegal
658  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
659  csrExceptionVec(loadPageFault) := hasLoadPageFault
660  csrExceptionVec(storePageFault) := hasStorePageFault
661  val iduExceptionVec = io.cfIn.exceptionVec
662  val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
663  io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
664  io.wenFix := DontCare
665
666  val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt()
667  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
668  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
669  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
670  ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR")
671  ExcitingUtils.addSource(causeNO, "difftestCausefromCSR")
672
673  val raiseExceptionIntr = io.exception.valid
674  val retTarget = Wire(UInt(VAddrBits.W))
675  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
676  io.redirectOut := DontCare
677  io.redirectOutValid := valid && func === CSROpType.jmp && !isEcall
678  io.redirectOut.target := retTarget
679  io.flushPipe := resetSatp
680
681  XSDebug(io.redirectOutValid, "redirect to %x, pc=%x\n", io.redirectOut.target, io.cfIn.pc)
682
683  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",io.exception.bits.cf.pc, intrNO, io.exception.bits.cf.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
684  XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode)
685
686  // Branch control
687
688  val deleg = Mux(raiseIntr, mideleg , medeleg)
689  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
690  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
691  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
692
693  io.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
694  retTarget := DontCare
695  // val illegalEret = TODO
696
697  when (valid && isMret) {
698    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
699    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
700    mstatusNew.ie.m := mstatusOld.pie.m
701    priviledgeMode := mstatusOld.mpp
702    mstatusNew.pie.m := true.B
703    mstatusNew.mpp := ModeU
704    mstatusNew.mprv := 0.U
705    mstatus := mstatusNew.asUInt
706//    lr := false.B
707    retTarget := mepc(VAddrBits-1, 0)
708  }
709
710  when (valid && isSret && !illegalSModeSret) {
711    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
712    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
713    mstatusNew.ie.s := mstatusOld.pie.s
714    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
715    mstatusNew.pie.s := true.B
716    mstatusNew.spp := ModeU
717    mstatus := mstatusNew.asUInt
718    mstatusNew.mprv := 0.U
719    // lr := false.B
720    retTarget := sepc(VAddrBits-1, 0)
721  }
722
723  when (valid && isUret) {
724    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
725    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
726    // mstatusNew.mpp.m := ModeU //TODO: add mode U
727    mstatusNew.ie.u := mstatusOld.pie.u
728    priviledgeMode := ModeU
729    mstatusNew.pie.u := true.B
730    mstatus := mstatusNew.asUInt
731    retTarget := uepc(VAddrBits-1, 0)
732  }
733
734  when (raiseExceptionIntr) {
735    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
736    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
737
738    when (delegS) {
739      scause := causeNO
740      sepc := SignExt(io.exception.bits.cf.pc, XLEN)
741      mstatusNew.spp := priviledgeMode
742      mstatusNew.pie.s := mstatusOld.ie.s
743      mstatusNew.ie.s := false.B
744      priviledgeMode := ModeS
745      when(tvalWen){stval := 0.U}
746      // trapTarget := stvec(VAddrBits-1. 0)
747    }.otherwise {
748      mcause := causeNO
749      mepc := SignExt(io.exception.bits.cf.pc, XLEN)
750      mstatusNew.mpp := priviledgeMode
751      mstatusNew.pie.m := mstatusOld.ie.m
752      mstatusNew.ie.m := false.B
753      priviledgeMode := ModeM
754      when(tvalWen){mtval := 0.U}
755      // trapTarget := mtvec(VAddrBits-1. 0)
756    }
757
758    mstatus := mstatusNew.asUInt
759  }
760
761  io.in.ready := true.B
762  io.out.valid := valid
763
764
765  XSDebug(io.redirectOutValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
766    io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
767  XSDebug(raiseExceptionIntr && delegS, "Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
768    io.redirectOutValid, io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
769  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc)
770
771
772  // perfcnt
773
774  val perfCntList = Map(
775//    "Mcycle"      -> (0xb00, "perfCntCondMcycle"     ),
776//    "Minstret"    -> (0xb02, "perfCntCondMinstret"   ),
777    "MbpInstr"    -> (0xb03, "perfCntCondMbpInstr"   ),
778    "MbpRight"    -> (0xb04, "perfCntCondMbpRight"   ),
779    "MbpWrong"    -> (0xb05, "perfCntCondMbpWrong"   ),
780    "MbpBRight"   -> (0xb06, "perfCntCondMbpBRight"   ),
781    "MbpBWrong"   -> (0xb07, "perfCntCondMbpBWrong"   ),
782    "MbpJRight"   -> (0xb08, "perfCntCondMbpJRight"   ),
783    "MbpJWrong"   -> (0xb09, "perfCntCondMbpJWrong"   ),
784    "MbpIRight"   -> (0xb0a, "perfCntCondMbpIRight"   ),
785    "MbpIWrong"   -> (0xb0b, "perfCntCondMbpIWrong"   ),
786    "MbpRRight"   -> (0xb0c, "perfCntCondMbpRRight"   ),
787    "MbpRWrong"   -> (0xb0d, "perfCntCondMbpRWrong"   ),
788    "DpqReplay"   -> (0xb0e, "perfCntCondDpqReplay"   ),
789    "RoqWalk"     -> (0xb0f, "perfCntCondRoqWalk"     ),
790    "RoqWaitInt"  -> (0xb10, "perfCntCondRoqWaitInt"  ),
791    "RoqWaitFp"   -> (0xb11, "perfCntCondRoqWaitFp"   ),
792    "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ),
793    "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"),
794    "Dp1Empty"    -> (0xb14, "perfCntCondDp1Empty"    ),
795    "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0"     ),
796    "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1"     ),
797    "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2"     ),
798    "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3"     ),
799    "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0"    ),
800    "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1"    ),
801    "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2"    ),
802    "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3"    ),
803    "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0"     ),
804    "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0"    ),
805    "PtwReqCnt"   -> (0xb25, "perfCntPtwReqCnt"       ),
806    "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt"     ),
807    "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit"     ),
808    "ICacheReq"   -> (0xb28, "perfCntIcacheReqCnt"     ),
809    "ICacheMiss"   -> (0xb29, "perfCntIcacheMissCnt"     )
810//    "Custom1"     -> (0xb1b, "Custom1"             ),
811//    "Custom2"     -> (0xb1c, "Custom2"             ),
812//    "Custom3"     -> (0xb1d, "Custom3"             ),
813//    "Custom4"     -> (0xb1e, "Custom4"             ),
814//    "Custom5"     -> (0xb1f, "Custom5"             ),
815//    "Custom6"     -> (0xb20, "Custom6"             ),
816//    "Custom7"     -> (0xb21, "Custom7"             ),
817//    "Custom8"     -> (0xb22, "Custom8"             ),
818//    "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
819  )
820  val perfCntCond = List.fill(0x80)(WireInit(false.B))
821  (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
822
823//  ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf)
824  perfCntList.foreach {
825    case (_, (address, boringId)) =>
826      if(hasPerfCnt){
827        ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
828      }
829//      if (!hasPerfCnt) {
830//        // do not enable perfcnts except for Mcycle and Minstret
831//        if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) {
832//          perfCntCond(address & 0x7f) := false.B
833//        }
834//      }
835  }
836
837  val xstrap = WireInit(false.B)
838  if(!env.FPGAPlatform && EnableBPU){
839    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
840  }
841  def readWithScala(addr: Int): UInt = mapping(addr)._1
842
843  if (!env.FPGAPlatform) {
844
845    // display all perfcnt when nooptrap is executed
846    when (xstrap) {
847      printf("======== PerfCnt =========\n")
848      perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) =>
849        printf("%d <- " + str + "\n", readWithScala(address))
850      }
851    }
852
853    ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug)
854    ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug)
855    ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug)
856    ExcitingUtils.addSource(mepc, "difftestMepc", Debug)
857    ExcitingUtils.addSource(sepc, "difftestSepc", Debug)
858    ExcitingUtils.addSource(mtval, "difftestMtval", Debug)
859    ExcitingUtils.addSource(stval, "difftestStval", Debug)
860    ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug)
861    ExcitingUtils.addSource(stvec, "difftestStvec", Debug)
862    ExcitingUtils.addSource(mcause, "difftestMcause", Debug)
863    ExcitingUtils.addSource(scause, "difftestScause", Debug)
864    ExcitingUtils.addSource(satp, "difftestSatp", Debug)
865    ExcitingUtils.addSource(mipReg, "difftestMip", Debug)
866    ExcitingUtils.addSource(mie, "difftestMie", Debug)
867    ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug)
868    ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug)
869    ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug)
870    ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug)
871  } else {
872  }
873}
874