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