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