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