1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.ExcitingUtils.{ConnectionType, Debug} 5import chisel3.util._ 6import utils._ 7import xiangshan._ 8import xiangshan.backend._ 9import utils.XSDebug 10 11object debugId extends Function0[Integer] { 12 var x = 0 13 def apply(): Integer = { 14 x = x + 1 15 return x 16 } 17} 18 19trait HasCSRConst { 20 // User Trap Setup 21 val Ustatus = 0x000 22 val Uie = 0x004 23 val Utvec = 0x005 24 25 // User Trap Handling 26 val Uscratch = 0x040 27 val Uepc = 0x041 28 val Ucause = 0x042 29 val Utval = 0x043 30 val Uip = 0x044 31 32 // User Floating-Point CSRs (not implemented) 33 val Fflags = 0x001 34 val Frm = 0x002 35 val Fcsr = 0x003 36 37 // User Counter/Timers 38 val Cycle = 0xC00 39 val Time = 0xC01 40 val Instret = 0xC02 41 42 // Supervisor Trap Setup 43 val Sstatus = 0x100 44 val Sedeleg = 0x102 45 val Sideleg = 0x103 46 val Sie = 0x104 47 val Stvec = 0x105 48 val Scounteren = 0x106 49 50 // Supervisor Trap Handling 51 val Sscratch = 0x140 52 val Sepc = 0x141 53 val Scause = 0x142 54 val Stval = 0x143 55 val Sip = 0x144 56 57 // Supervisor Protection and Translation 58 val Satp = 0x180 59 60 // Machine Information Registers 61 val Mvendorid = 0xF11 62 val Marchid = 0xF12 63 val Mimpid = 0xF13 64 val Mhartid = 0xF14 65 66 // Machine Trap Setup 67 val Mstatus = 0x300 68 val Misa = 0x301 69 val Medeleg = 0x302 70 val Mideleg = 0x303 71 val Mie = 0x304 72 val Mtvec = 0x305 73 val Mcounteren = 0x306 74 75 // Machine Trap Handling 76 val Mscratch = 0x340 77 val Mepc = 0x341 78 val Mcause = 0x342 79 val Mtval = 0x343 80 val Mip = 0x344 81 82 // Machine Memory Protection 83 // TBD 84 val Pmpcfg0 = 0x3A0 85 val Pmpcfg1 = 0x3A1 86 val Pmpcfg2 = 0x3A2 87 val Pmpcfg3 = 0x3A3 88 val PmpaddrBase = 0x3B0 89 90 // Machine Counter/Timers 91 // Currently, we uses perfcnt csr set instead of standard Machine Counter/Timers 92 // 0xB80 - 0x89F are also used as perfcnt csr 93 94 // Machine Counter Setup (not implemented) 95 // Debug/Trace Registers (shared with Debug Mode) (not implemented) 96 // Debug Mode Registers (not implemented) 97 98 def privEcall = 0x000.U 99 def privEbreak = 0x001.U 100 def privMret = 0x302.U 101 def privSret = 0x102.U 102 def privUret = 0x002.U 103 104 def ModeM = 0x3.U 105 def ModeH = 0x2.U 106 def ModeS = 0x1.U 107 def ModeU = 0x0.U 108 109 def IRQ_UEIP = 0 110 def IRQ_SEIP = 1 111 def IRQ_MEIP = 3 112 113 def IRQ_UTIP = 4 114 def IRQ_STIP = 5 115 def IRQ_MTIP = 7 116 117 def IRQ_USIP = 8 118 def IRQ_SSIP = 9 119 def IRQ_MSIP = 11 120 121 val IntPriority = Seq( 122 IRQ_MEIP, IRQ_MSIP, IRQ_MTIP, 123 IRQ_SEIP, IRQ_SSIP, IRQ_STIP, 124 IRQ_UEIP, IRQ_USIP, IRQ_UTIP 125 ) 126 127 def csrAccessPermissionCheck(addr: UInt, wen: Bool, mode: UInt): Bool = { 128 val readOnly = addr(11,10) === "b11".U 129 val lowestAccessPrivilegeLevel = addr(9,8) 130 mode >= lowestAccessPrivilegeLevel && !(wen && readOnly) 131 } 132} 133 134trait HasExceptionNO { 135 def instrAddrMisaligned = 0 136 def instrAccessFault = 1 137 def illegalInstr = 2 138 def breakPoint = 3 139 def loadAddrMisaligned = 4 140 def loadAccessFault = 5 141 def storeAddrMisaligned = 6 142 def storeAccessFault = 7 143 def ecallU = 8 144 def ecallS = 9 145 def ecallM = 11 146 def instrPageFault = 12 147 def loadPageFault = 13 148 def storePageFault = 15 149 150 val ExcPriority = Seq( 151 breakPoint, // TODO: different BP has different priority 152 instrPageFault, 153 instrAccessFault, 154 illegalInstr, 155 instrAddrMisaligned, 156 ecallM, ecallS, ecallU, 157 storePageFault, 158 loadPageFault, 159 storeAccessFault, 160 loadAccessFault, 161 storeAddrMisaligned, 162 loadAddrMisaligned 163 ) 164} 165 166class FpuCsrIO extends XSBundle { 167 val fflags = Output(Valid(UInt(5.W))) 168 val isIllegal = Output(Bool()) 169 val dirty_fs = Output(Bool()) 170 val frm = Input(UInt(3.W)) 171} 172 173 174class PerfCounterIO extends XSBundle { 175 val value = Input(UInt(XLEN.W)) 176} 177 178class CSR extends FunctionUnit with HasCSRConst 179{ 180 val csrio = IO(new Bundle { 181 // output (for func === CSROpType.jmp) 182 val redirectOut = ValidIO(UInt(VAddrBits.W)) 183 val perf = Vec(NumPerfCounters, new PerfCounterIO) 184 // to FPU 185 val fpu = Flipped(new FpuCsrIO) 186 // from rob 187 val exception = Flipped(ValidIO(new MicroOp)) 188 val isInterrupt = Input(Bool()) 189 // to ROB 190 val trapTarget = Output(UInt(VAddrBits.W)) 191 val interrupt = Output(Bool()) 192 // from LSQ 193 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 194 // from outside cpu,externalInterrupt 195 val externalInterrupt = new ExternalInterruptIO 196 // TLB 197 val tlb = Output(new TlbCsrBundle) 198 }) 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 csrio.tlb := 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(update: Boolean)(wdata: UInt): UInt = { 389 val fcsrOld = fcsr.asTypeOf(new FcsrStruct) 390 val fcsrNew = WireInit(fcsrOld) 391 csrw_dirty_fp_state := true.B 392 if(update){ 393 fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags 394 } else { 395 fcsrNew.fflags := wdata(4,0) 396 } 397 fcsrNew.asUInt() 398 } 399 def fflags_rfn(rdata:UInt): UInt = rdata(4,0) 400 401 def fcsr_wfn(wdata: UInt): UInt = { 402 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 403 csrw_dirty_fp_state := true.B 404 Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags) 405 } 406 407 val fcsrMapping = Map( 408 MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn), 409 MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn), 410 MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn) 411 ) 412 413 // Atom LR/SC Control Bits 414// val setLr = WireInit(Bool(), false.B) 415// val setLrVal = WireInit(Bool(), false.B) 416// val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check 417// val lr = RegInit(Bool(), false.B) 418// val lrAddr = RegInit(UInt(AddrBits.W), 0.U) 419// 420// when(setLr){ 421// lr := setLrVal 422// lrAddr := setLrAddr 423// } 424 425 // Hart Priviledge Mode 426 val priviledgeMode = RegInit(UInt(2.W), ModeM) 427 428 // perfcnt 429 val hasPerfCnt = !env.FPGAPlatform 430 val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3 431 val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 432 val perfCntsLoMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb00 + i, perfCnts(i))) 433 val perfCntsHiMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32))) 434 println(s"CSR: hasPerfCnt:${hasPerfCnt}") 435 // CSR reg map 436 val mapping = Map( 437 438 // User Trap Setup 439 // MaskedRegMap(Ustatus, ustatus), 440 // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable), 441 // MaskedRegMap(Utvec, utvec), 442 443 // User Trap Handling 444 // MaskedRegMap(Uscratch, uscratch), 445 // MaskedRegMap(Uepc, uepc), 446 // MaskedRegMap(Ucause, ucause), 447 // MaskedRegMap(Utval, utval), 448 // MaskedRegMap(Uip, uip), 449 450 // User Counter/Timers 451 // MaskedRegMap(Cycle, cycle), 452 // MaskedRegMap(Time, time), 453 // MaskedRegMap(Instret, instret), 454 455 // Supervisor Trap Setup 456 MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask), 457 458 // MaskedRegMap(Sedeleg, Sedeleg), 459 // MaskedRegMap(Sideleg, Sideleg), 460 MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask), 461 MaskedRegMap(Stvec, stvec), 462 MaskedRegMap(Scounteren, scounteren), 463 464 // Supervisor Trap Handling 465 MaskedRegMap(Sscratch, sscratch), 466 MaskedRegMap(Sepc, sepc), 467 MaskedRegMap(Scause, scause), 468 MaskedRegMap(Stval, stval), 469 MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask), 470 471 // Supervisor Protection and Translation 472 MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask), 473 474 // Machine Information Registers 475 MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable), 476 MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable), 477 MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable), 478 MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable), 479 480 // Machine Trap Setup 481 // MaskedRegMap(Mstatus, mstatus, "hffffffffffffffee".U, (x=>{printf("mstatus write: %x time: %d\n", x, GTimer()); x})), 482 MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask), 483 MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable 484 MaskedRegMap(Medeleg, medeleg, "hf3ff".U), 485 MaskedRegMap(Mideleg, mideleg, "h222".U), 486 MaskedRegMap(Mie, mie), 487 MaskedRegMap(Mtvec, mtvec), 488 MaskedRegMap(Mcounteren, mcounteren), 489 490 // Machine Trap Handling 491 MaskedRegMap(Mscratch, mscratch), 492 MaskedRegMap(Mepc, mepc), 493 MaskedRegMap(Mcause, mcause), 494 MaskedRegMap(Mtval, mtval), 495 MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable), 496 497 // Machine Memory Protection 498 MaskedRegMap(Pmpcfg0, pmpcfg0), 499 MaskedRegMap(Pmpcfg1, pmpcfg1), 500 MaskedRegMap(Pmpcfg2, pmpcfg2), 501 MaskedRegMap(Pmpcfg3, pmpcfg3), 502 MaskedRegMap(PmpaddrBase + 0, pmpaddr0), 503 MaskedRegMap(PmpaddrBase + 1, pmpaddr1), 504 MaskedRegMap(PmpaddrBase + 2, pmpaddr2), 505 MaskedRegMap(PmpaddrBase + 3, pmpaddr3) 506 507 ) ++ 508 perfCntsLoMapping ++ (if (XLEN == 32) perfCntsHiMapping else Nil) ++ 509 (if(HasFPU) fcsrMapping else Nil) 510 511 val addr = src2(11, 0) 512 val rdata = Wire(UInt(XLEN.W)) 513 val csri = ZeroExt(cfIn.instr(19,15), XLEN) //unsigned imm for csri. [TODO] 514 val wdata = LookupTree(func, List( 515 CSROpType.wrt -> src1, 516 CSROpType.set -> (rdata | src1), 517 CSROpType.clr -> (rdata & (~src1).asUInt()), 518 CSROpType.wrti -> csri,//TODO: csri --> src2 519 CSROpType.seti -> (rdata | csri), 520 CSROpType.clri -> (rdata & (~csri).asUInt()) 521 )) 522 523 // satp wen check 524 val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U) 525 526 // general CSR wen check 527 val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode) 528 val permitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode) 529 // Writeable check is ingored. 530 // Currently, write to illegal csr addr will be ignored 531 MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata) 532 io.out.bits.data := rdata 533 io.out.bits.uop := io.in.bits.uop 534 io.out.bits.uop.cf := cfOut 535 io.out.bits.uop.ctrl.flushPipe := flushPipe 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(csrio.fpu.fflags.valid){ 546 fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits) 547 } 548 // set fs and sd in mstatus 549 when(csrw_dirty_fp_state || csrio.fpu.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 csrio.fpu.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", cfIn.pc, addr, rdata, wdata, func) 565 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", 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 // Branch control 605 val retTarget = Wire(UInt(VAddrBits.W)) 606 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 607 csrio.redirectOut.valid := valid && func === CSROpType.jmp && !isEcall 608 csrio.redirectOut.bits := retTarget 609 flushPipe := resetSatp 610 XSDebug(csrio.redirectOut.valid, "redirect to %x, pc=%x\n", csrio.redirectOut.bits, cfIn.pc) 611 612 retTarget := DontCare 613 // val illegalEret = TODO 614 615 when (valid && isMret) { 616 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 617 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 618 mstatusNew.ie.m := mstatusOld.pie.m 619 priviledgeMode := mstatusOld.mpp 620 mstatusNew.pie.m := true.B 621 mstatusNew.mpp := ModeU 622 mstatusNew.mprv := 0.U 623 mstatus := mstatusNew.asUInt 624// lr := false.B 625 retTarget := mepc(VAddrBits-1, 0) 626 } 627 628 when (valid && isSret && !illegalSModeSret) { 629 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 630 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 631 mstatusNew.ie.s := mstatusOld.pie.s 632 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 633 mstatusNew.pie.s := true.B 634 mstatusNew.spp := ModeU 635 mstatus := mstatusNew.asUInt 636 mstatusNew.mprv := 0.U 637 // lr := false.B 638 retTarget := sepc(VAddrBits-1, 0) 639 } 640 641 when (valid && isUret) { 642 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 643 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 644 // mstatusNew.mpp.m := ModeU //TODO: add mode U 645 mstatusNew.ie.u := mstatusOld.pie.u 646 priviledgeMode := ModeU 647 mstatusNew.pie.u := true.B 648 mstatus := mstatusNew.asUInt 649 retTarget := uepc(VAddrBits-1, 0) 650 } 651 652 XSDebug(csrio.redirectOut.valid, 653 "Rediret %x isSret:%d retTarget:%x sepc:%x cfInpc:%x valid:%d\n", 654 csrio.redirectOut.bits, isSret, retTarget, sepc, cfIn.pc, valid 655 ) 656 657 io.in.ready := true.B 658 io.out.valid := valid 659 660 /** 661 * Exception and Intr 662 */ 663 val ideleg = (mideleg & mip.asUInt) 664 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 665 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 666 667 // send interrupt information to ROQ 668 val intrVecEnable = Wire(Vec(12, Bool())) 669 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 670 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 671 val intrBitSet = intrVec.orR() 672 csrio.interrupt := intrBitSet 673 mipWire.t.m := csrio.externalInterrupt.mtip 674 mipWire.s.m := csrio.externalInterrupt.msip 675 mipWire.e.m := csrio.externalInterrupt.meip 676 677 // interrupts 678 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 679 val raiseIntr = csrio.exception.valid && csrio.isInterrupt 680 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.cf.pc, intrNO) 681 682 // exceptions 683 val raiseException = csrio.exception.valid && !csrio.isInterrupt 684 val hasInstrPageFault = csrio.exception.bits.cf.exceptionVec(instrPageFault) && raiseException 685 val hasLoadPageFault = csrio.exception.bits.cf.exceptionVec(loadPageFault) && raiseException 686 val hasStorePageFault = csrio.exception.bits.cf.exceptionVec(storePageFault) && raiseException 687 val hasStoreAddrMisaligned = csrio.exception.bits.cf.exceptionVec(storeAddrMisaligned) && raiseException 688 val hasLoadAddrMisaligned = csrio.exception.bits.cf.exceptionVec(loadAddrMisaligned) && raiseException 689 690 val csrExceptionVec = Wire(Vec(16, Bool())) 691 csrExceptionVec.map(_ := false.B) 692 csrExceptionVec(breakPoint) := io.in.valid && isEbreak 693 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 694 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 695 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 696 // Trigger an illegal instr exception when: 697 // * unimplemented csr is being read/written 698 // * csr access is illegal 699 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 700 csrExceptionVec(loadPageFault) := hasLoadPageFault 701 csrExceptionVec(storePageFault) := hasStorePageFault 702 val iduExceptionVec = cfIn.exceptionVec 703 val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt() 704 cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) } 705 706 val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec.asUInt() 707 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 708 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 709 // if (!env.FPGAPlatform) { 710 val id = debugId() 711 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 712 ExcitingUtils.addSource(difftestIntrNO, s"difftestIntrNOfromCSR$id") 713 ExcitingUtils.addSource(causeNO, s"difftestCausefromCSR$id") 714 // } 715 716 val raiseExceptionIntr = csrio.exception.valid 717 XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n", 718 csrio.exception.bits.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt 719 ) 720 XSDebug(raiseExceptionIntr, 721 "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", 722 csrio.exception.bits.cf.pc, 723 mstatus, 724 mideleg, 725 medeleg, 726 priviledgeMode 727 ) 728 729 // mtval write logic 730 val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN) 731 when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){ 732 val tval = Mux( 733 hasInstrPageFault, 734 Mux( 735 csrio.exception.bits.cf.crossPageIPFFix, 736 SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN), 737 SignExt(csrio.exception.bits.cf.pc, XLEN) 738 ), 739 memExceptionAddr 740 ) 741 when(priviledgeMode === ModeM){ 742 mtval := tval 743 }.otherwise{ 744 stval := tval 745 } 746 } 747 748 when(hasLoadAddrMisaligned || hasStoreAddrMisaligned) 749 { 750 mtval := memExceptionAddr 751 } 752 753 val deleg = Mux(raiseIntr, mideleg , medeleg) 754 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 755 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 756 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 757 csrio.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 758 759 when (raiseExceptionIntr) { 760 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 761 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 762 763 when (delegS) { 764 scause := causeNO 765 sepc := SignExt(csrio.exception.bits.cf.pc, XLEN) 766 mstatusNew.spp := priviledgeMode 767 mstatusNew.pie.s := mstatusOld.ie.s 768 mstatusNew.ie.s := false.B 769 priviledgeMode := ModeS 770 when(tvalWen){stval := 0.U} 771 // trapTarget := stvec(VAddrBits-1. 0) 772 }.otherwise { 773 mcause := causeNO 774 mepc := SignExt(csrio.exception.bits.cf.pc, XLEN) 775 mstatusNew.mpp := priviledgeMode 776 mstatusNew.pie.m := mstatusOld.ie.m 777 mstatusNew.ie.m := false.B 778 priviledgeMode := ModeM 779 when(tvalWen){mtval := 0.U} 780 // trapTarget := mtvec(VAddrBits-1. 0) 781 } 782 783 mstatus := mstatusNew.asUInt 784 } 785 786 XSDebug(raiseExceptionIntr && delegS, 787 "Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n", 788 csrio.redirectOut.valid, csrio.redirectOut.bits, raiseExceptionIntr, 789 isSret, sepc, delegS, deleg 790 ) 791 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc) 792 793 794 /** 795 * Performance counters 796 */ 797 val perfCntList = Map( 798// "Mcycle" -> (0xb00, "perfCntCondMcycle" ), 799// "Minstret" -> (0xb02, "perfCntCondMinstret" ), 800 "MbpInstr" -> (0xb03, "perfCntCondMbpInstr" ), 801 "MbpRight" -> (0xb04, "perfCntCondMbpRight" ), 802 "MbpWrong" -> (0xb05, "perfCntCondMbpWrong" ), 803 "MbpBRight" -> (0xb06, "perfCntCondMbpBRight" ), 804 "MbpBWrong" -> (0xb07, "perfCntCondMbpBWrong" ), 805 "MbpJRight" -> (0xb08, "perfCntCondMbpJRight" ), 806 "MbpJWrong" -> (0xb09, "perfCntCondMbpJWrong" ), 807 "MbpIRight" -> (0xb0a, "perfCntCondMbpIRight" ), 808 "MbpIWrong" -> (0xb0b, "perfCntCondMbpIWrong" ), 809 "MbpRRight" -> (0xb0c, "perfCntCondMbpRRight" ), 810 "MbpRWrong" -> (0xb0d, "perfCntCondMbpRWrong" ), 811 "RoqWalk" -> (0xb0f, "perfCntCondRoqWalk" ), 812 "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0" ), 813 "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1" ), 814 "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2" ), 815 "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3" ), 816 "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0" ), 817 "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1" ), 818 "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2" ), 819 "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3" ), 820 "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0" ), 821 "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0" ), 822 "PtwReqCnt" -> (0xb25, "perfCntPtwReqCnt" ), 823 "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt" ), 824 "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit" ), 825 "ICacheReq" -> (0xb28, "perfCntIcacheReqCnt" ), 826 "ICacheMiss" -> (0xb29, "perfCntIcacheMissCnt" )//, 827 // "FetchFromICache" -> (0xb2a, "CntFetchFromICache"), 828 // "FetchFromLoopBuffer" -> (0xb2b, "CntFetchFromLoopBuffer"), 829 // "ExitLoop1" -> (0xb2c, "CntExitLoop1"), 830 // "ExitLoop2" -> (0xb2d, "CntExitLoop2"), 831 // "ExitLoop3" -> (0xb2e, "CntExitLoop3") 832// "Custom1" -> (0xb1b, "Custom1" ), 833// "Custom2" -> (0xb1c, "Custom2" ), 834// "Custom3" -> (0xb1d, "Custom3" ), 835// "Custom4" -> (0xb1e, "Custom4" ), 836// "Custom5" -> (0xb1f, "Custom5" ), 837// "Custom6" -> (0xb20, "Custom6" ), 838// "Custom7" -> (0xb21, "Custom7" ), 839// "Custom8" -> (0xb22, "Custom8" ), 840// "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit") 841 ) 842 val perfCntCond = List.fill(0x80)(WireInit(false.B)) 843 (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 844 845// ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf) 846 perfCntList.foreach { 847 case (_, (address, boringId)) => 848 if(hasPerfCnt){ 849 ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf) 850 } 851// if (!hasPerfCnt) { 852// // do not enable perfcnts except for Mcycle and Minstret 853// if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) { 854// perfCntCond(address & 0x7f) := false.B 855// } 856// } 857 } 858 859 val xstrap = WireInit(false.B) 860 if(!env.FPGAPlatform && EnableBPU){ 861 ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug) 862 } 863 def readWithScala(addr: Int): UInt = mapping(addr)._1 864 865 if (!env.FPGAPlatform) { 866 867 // display all perfcnt when nooptrap is executed 868 when (xstrap) { 869 printf("======== PerfCnt =========\n") 870 perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) => 871 printf("%d <- " + str + "\n", readWithScala(address)) 872 } 873 } 874 875 ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug) 876 ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug) 877 ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug) 878 ExcitingUtils.addSource(mepc, "difftestMepc", Debug) 879 ExcitingUtils.addSource(sepc, "difftestSepc", Debug) 880 ExcitingUtils.addSource(mtval, "difftestMtval", Debug) 881 ExcitingUtils.addSource(stval, "difftestStval", Debug) 882 ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug) 883 ExcitingUtils.addSource(stvec, "difftestStvec", Debug) 884 ExcitingUtils.addSource(mcause, "difftestMcause", Debug) 885 ExcitingUtils.addSource(scause, "difftestScause", Debug) 886 ExcitingUtils.addSource(satp, "difftestSatp", Debug) 887 ExcitingUtils.addSource(mipReg, "difftestMip", Debug) 888 ExcitingUtils.addSource(mie, "difftestMie", Debug) 889 ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug) 890 ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug) 891 ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug) 892 ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug) 893 } else { 894 } 895} 896