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 lsroqExceptionAddr = WireInit(0.U(VAddrBits.W)) 599 val atomExceptionAddr = WireInit(0.U(VAddrBits.W)) 600 val atomOverrideXtval = WireInit(false.B) 601 ExcitingUtils.addSource(io.exception.bits.lsroqIdx, "EXECPTION_LSROQIDX") 602 ExcitingUtils.addSink(lsroqExceptionAddr, "EXECPTION_VADDR") 603 ExcitingUtils.addSink(atomExceptionAddr, "ATOM_EXECPTION_VADDR") 604 ExcitingUtils.addSink(atomOverrideXtval, "ATOM_OVERRIDE_XTVAL") 605 val memExceptionAddr = Mux(atomOverrideXtval, atomExceptionAddr, lsroqExceptionAddr) 606 when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){ 607 val tval = Mux( 608 hasInstrPageFault, 609 Mux( 610 io.exception.bits.cf.crossPageIPFFix, 611 SignExt(io.exception.bits.cf.pc + 2.U, XLEN), 612 SignExt(io.exception.bits.cf.pc, XLEN) 613 ), 614 SignExt(memExceptionAddr, XLEN) 615 ) 616 when(priviledgeMode === ModeM){ 617 mtval := tval 618 }.otherwise{ 619 stval := tval 620 } 621 } 622 623 when(hasLoadAddrMisaligned || hasStoreAddrMisaligned) 624 { 625 mtval := SignExt(memExceptionAddr, XLEN) 626 } 627 628 // Exception and Intr 629 630 // interrupts 631 632 val ideleg = (mideleg & mip.asUInt) 633 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 634 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 635 636 val intrVecEnable = Wire(Vec(12, Bool())) 637 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 638 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 639 val intrBitSet = intrVec.orR() 640 ExcitingUtils.addSource(intrBitSet, "intrBitSetIDU") 641 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 642 val raiseIntr = intrBitSet && io.exception.valid 643 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO) 644 645 val mtip = WireInit(false.B) 646 val msip = WireInit(false.B) 647 val meip = WireInit(false.B) 648 ExcitingUtils.addSink(mtip, "mtip") 649 ExcitingUtils.addSink(msip, "msip") 650 ExcitingUtils.addSink(meip, "meip") 651 mipWire.t.m := mtip 652 mipWire.s.m := msip 653 mipWire.e.m := 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 trapTarget = Wire(UInt(VAddrBits.W)) 683 ExcitingUtils.addSource(trapTarget, "trapTarget") 684 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 685 io.redirect := DontCare 686 io.redirectValid := valid && func === CSROpType.jmp && !isEcall 687 io.redirect.target := retTarget 688 io.flushPipe := resetSatp 689 690 XSDebug(io.redirectValid, "redirect to %x, pc=%x\n", io.redirect.target, io.cfIn.pc) 691 692 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) 693 XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode) 694 695 // Branch control 696 697 val deleg = Mux(raiseIntr, mideleg , medeleg) 698 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 699 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 700 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 701 702 trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 703 retTarget := DontCare 704 // val illegalEret = TODO 705 706 when (valid && isMret) { 707 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 708 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 709 mstatusNew.ie.m := mstatusOld.pie.m 710 priviledgeMode := mstatusOld.mpp 711 mstatusNew.pie.m := true.B 712 mstatusNew.mpp := ModeU 713 mstatusNew.mprv := 0.U 714 mstatus := mstatusNew.asUInt 715// lr := false.B 716 retTarget := mepc(VAddrBits-1, 0) 717 } 718 719 when (valid && isSret && !illegalSModeSret) { 720 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 721 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 722 mstatusNew.ie.s := mstatusOld.pie.s 723 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 724 mstatusNew.pie.s := true.B 725 mstatusNew.spp := ModeU 726 mstatus := mstatusNew.asUInt 727 mstatusNew.mprv := 0.U 728 // lr := false.B 729 retTarget := sepc(VAddrBits-1, 0) 730 } 731 732 when (valid && isUret) { 733 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 734 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 735 // mstatusNew.mpp.m := ModeU //TODO: add mode U 736 mstatusNew.ie.u := mstatusOld.pie.u 737 priviledgeMode := ModeU 738 mstatusNew.pie.u := true.B 739 mstatus := mstatusNew.asUInt 740 retTarget := uepc(VAddrBits-1, 0) 741 } 742 743 when (raiseExceptionIntr) { 744 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 745 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 746 747 when (delegS) { 748 scause := causeNO 749 sepc := SignExt(io.exception.bits.cf.pc, XLEN) 750 mstatusNew.spp := priviledgeMode 751 mstatusNew.pie.s := mstatusOld.ie.s 752 mstatusNew.ie.s := false.B 753 priviledgeMode := ModeS 754 when(tvalWen){stval := 0.U} 755 // trapTarget := stvec(VAddrBits-1. 0) 756 }.otherwise { 757 mcause := causeNO 758 mepc := SignExt(io.exception.bits.cf.pc, XLEN) 759 mstatusNew.mpp := priviledgeMode 760 mstatusNew.pie.m := mstatusOld.ie.m 761 mstatusNew.ie.m := false.B 762 priviledgeMode := ModeM 763 when(tvalWen){mtval := 0.U} 764 // trapTarget := mtvec(VAddrBits-1. 0) 765 } 766 767 mstatus := mstatusNew.asUInt 768 } 769 770 io.in.ready := true.B 771 io.out.valid := valid 772 773 774 XSDebug(io.redirectValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", 775 io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 776 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", 777 io.redirectValid, io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 778 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc) 779 780 781 // perfcnt 782 783 val perfCntList = Map( 784// "Mcycle" -> (0xb00, "perfCntCondMcycle" ), 785// "Minstret" -> (0xb02, "perfCntCondMinstret" ), 786 "MbpInstr" -> (0xb03, "perfCntCondMbpInstr" ), 787 "MbpRight" -> (0xb04, "perfCntCondMbpRight" ), 788 "MbpWrong" -> (0xb05, "perfCntCondMbpWrong" ), 789 "MbpBRight" -> (0xb06, "perfCntCondMbpBRight" ), 790 "MbpBWrong" -> (0xb07, "perfCntCondMbpBWrong" ), 791 "MbpJRight" -> (0xb08, "perfCntCondMbpJRight" ), 792 "MbpJWrong" -> (0xb09, "perfCntCondMbpJWrong" ), 793 "MbpIRight" -> (0xb0a, "perfCntCondMbpIRight" ), 794 "MbpIWrong" -> (0xb0b, "perfCntCondMbpIWrong" ), 795 "MbpRRight" -> (0xb0c, "perfCntCondMbpRRight" ), 796 "MbpRWrong" -> (0xb0d, "perfCntCondMbpRWrong" ), 797 "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0" ), 798 "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1" ), 799 "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2" ), 800 "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3" ), 801 "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0" ), 802 "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1" ), 803 "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2" ), 804 "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3" ), 805 "PtwReqCnt" -> (0xb23, "perfCntPtwReqCnt" ), 806 "PtwCycleCnt" -> (0xb24, "perfCntPtwCycleCnt" ), 807 "PtwL2TlbHit" -> (0xb25, "perfCntPtwL2TlbHit" ), 808 "CacheLoadMiss0" -> (0xb26, "perfCntCacheLoadMiss0" ), 809 "CacheLoadMiss1" -> (0xb27, "perfCntCacheLoadMiss1" ), 810 "ITlbReqCnt0" -> (0xb28, "perfCntItlbReqCnt0" ), 811 "ITlbMissCnt0"-> (0xb29, "perfCntItlbMissCnt0" ), 812 "PtwReqCnt" -> (0xb2a, "perfCntPtwReqCnt" ), 813 "PtwCycleCnt" -> (0xb2b, "perfCntPtwCycleCnt" ), 814 "PtwL2TlbHit" -> (0xb2c, "perfCntPtwL2TlbHit" ), 815 "ICacheReq" -> (0xb2d, "perfCntIcacheReqCnt" ), 816 "ICacheMiss" -> (0xb2e, "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