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