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