diff --git a/rocket/src/main/scala/consts.scala b/rocket/src/main/scala/consts.scala index fda38fc2..74386c12 100644 --- a/rocket/src/main/scala/consts.scala +++ b/rocket/src/main/scala/consts.scala @@ -46,10 +46,4 @@ trait ScalarOpConstants { val DW_32 = N val DW_64 = Y val DW_XPR = Y - - val SZ_PRV = 2 - val PRV_U = 0 - val PRV_S = 1 - val PRV_H = 2 - val PRV_M = 3 } diff --git a/rocket/src/main/scala/csr.scala b/rocket/src/main/scala/csr.scala index 62f81ff7..eb99d7be 100644 --- a/rocket/src/main/scala/csr.scala +++ b/rocket/src/main/scala/csr.scala @@ -10,40 +10,37 @@ import uncore._ import scala.math._ class MStatus extends Bundle { + val prv = UInt(width = PRV.SZ) // not truly part of mstatus, but convenient val sd = Bool() - val zero2 = UInt(width = 31) - val sd_rv32 = UInt(width = 1) - val zero1 = UInt(width = 9) + val zero3 = UInt(width = 31) + val sd_rv32 = Bool() + val zero2 = UInt(width = 2) val vm = UInt(width = 5) + val zero1 = UInt(width = 5) + val pum = Bool() val mprv = Bool() val xs = UInt(width = 2) val fs = UInt(width = 2) - val prv3 = UInt(width = 2) - val ie3 = Bool() - val prv2 = UInt(width = 2) - val ie2 = Bool() - val prv1 = UInt(width = 2) - val ie1 = Bool() - val prv = UInt(width = 2) - val ie = Bool() -} - -class SStatus extends Bundle { - val sd = Bool() - val zero4 = UInt(width = 31) - val sd_rv32 = UInt(width = 1) - val zero3 = UInt(width = 14) - val mprv = Bool() - val xs = UInt(width = 2) - val fs = UInt(width = 2) - val zero2 = UInt(width = 7) - val ps = Bool() - val pie = Bool() - val zero1 = UInt(width = 2) - val ie = Bool() + val mpp = UInt(width = 2) + val hpp = UInt(width = 2) + val spp = UInt(width = 1) + val mpie = Bool() + val hpie = Bool() + val spie = Bool() + val upie = Bool() + val mie = Bool() + val hie = Bool() + val sie = Bool() + val uie = Bool() } class MIP extends Bundle { + val host = Bool() + val rocc = Bool() + val mdip = Bool() + val hdip = Bool() + val sdip = Bool() + val udip = Bool() val mtip = Bool() val htip = Bool() val stip = Bool() @@ -54,6 +51,15 @@ class MIP extends Bundle { val usip = Bool() } +object PRV +{ + val SZ = 2 + val U = 0 + val S = 1 + val H = 2 + val M = 3 +} + object CSR { // commands @@ -82,6 +88,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle { val csr_xcpt = Bool(OUTPUT) val eret = Bool(OUTPUT) + val prv = UInt(OUTPUT, PRV.SZ) val status = new MStatus().asOutput val ptbr = UInt(OUTPUT, paddrBits) val evec = UInt(OUTPUT, vaddrBitsExtended) @@ -104,13 +111,44 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) { val io = new CSRFileIO - val reg_mstatus = Reg(new MStatus) - val reg_mie = Reg(init=new MIP().fromBits(0)) + val reset_mstatus = Wire(init=new MStatus().fromBits(0)) + reset_mstatus.mpp := PRV.M + reset_mstatus.prv := PRV.M + val reg_mstatus = Reg(init=reset_mstatus) + + val (supported_interrupts, delegable_interrupts) = { + val sup = Wire(init=new MIP().fromBits(0)) + sup.ssip := Bool(p(UseVM)) + sup.msip := true + sup.stip := Bool(p(UseVM)) + sup.mtip := true + sup.rocc := usingRoCC + sup.host := true + + val del = Wire(init=sup) + del.msip := false + del.mtip := false + del.mdip := false + + (sup.toBits, del.toBits) + } + val delegable_exceptions = UInt(Seq( + Causes.misaligned_fetch, + Causes.fault_fetch, + Causes.breakpoint, + Causes.fault_load, + Causes.fault_store, + Causes.user_ecall).map(1 << _).sum) + + val reg_mie = Reg(init=UInt(0, xLen)) + val reg_mideleg = Reg(init=UInt(0, xLen)) + val reg_medeleg = Reg(init=UInt(0, xLen)) val reg_mip = Reg(init=new MIP().fromBits(0)) val reg_mepc = Reg(UInt(width = vaddrBitsExtended)) val reg_mcause = Reg(Bits(width = xLen)) val reg_mbadaddr = Reg(UInt(width = vaddrBitsExtended)) val reg_mscratch = Reg(Bits(width = xLen)) + val reg_mtvec = Reg(init=UInt(p(MtvecInit), paddrBits min xLen)) val reg_sepc = Reg(UInt(width = vaddrBitsExtended)) val reg_scause = Reg(Bits(width = xLen)) @@ -118,7 +156,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val reg_sscratch = Reg(Bits(width = xLen)) val reg_stvec = Reg(UInt(width = vaddrBits)) val reg_mtimecmp = Reg(Bits(width = xLen)) - val reg_sptbr = Reg(UInt(width = paddrBits)) + val reg_sptbr = Reg(UInt(width = ppnBits)) val reg_wfi = Reg(init=Bool(false)) val reg_tohost = Reg(init=Bits(0, xLen)) @@ -126,31 +164,22 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) val reg_stats = Reg(init=Bool(false)) val reg_time = Reg(UInt(width = xLen)) val reg_instret = WideCounter(xLen, io.retire) - val reg_cycle = if (enableCommitLog) { reg_instret } else { WideCounter(xLen) } + val reg_cycle: UInt = if (enableCommitLog) { reg_instret } else { WideCounter(xLen) } val reg_uarch_counters = io.uarch_counters.map(WideCounter(xLen, _)) val reg_fflags = Reg(UInt(width = 5)) val reg_frm = Reg(UInt(width = 3)) - val irq_rocc = Bool(usingRoCC) && io.rocc.interrupt + val mip = Wire(init=reg_mip) + mip.host := (reg_fromhost =/= 0) + mip.rocc := io.rocc.interrupt + val read_mip = mip.toBits & supported_interrupts - io.interrupt_cause := 0 - io.interrupt := io.interrupt_cause(xLen-1) - val some_interrupt_pending = Wire(init=Bool(false)) - def checkInterrupt(max_priv: UInt, cond: Bool, num: Int) = { - when (cond && (reg_mstatus.prv < max_priv || reg_mstatus.prv === max_priv && reg_mstatus.ie)) { - io.interrupt_cause := UInt((BigInt(1) << (xLen-1)) + num) - } - when (cond && reg_mstatus.prv <= max_priv) { - some_interrupt_pending := true - } - } - - checkInterrupt(PRV_S, reg_mie.ssip && reg_mip.ssip, 0) - checkInterrupt(PRV_M, reg_mie.msip && reg_mip.msip, 0) - checkInterrupt(PRV_S, reg_mie.stip && reg_mip.stip, 1) - checkInterrupt(PRV_M, reg_mie.mtip && reg_mip.mtip, 1) - checkInterrupt(PRV_M, reg_fromhost =/= 0, 2) - checkInterrupt(PRV_M, irq_rocc, 3) + val pending_interrupts = read_mip & reg_mie + val m_interrupts = Mux(reg_mstatus.prv < PRV.M || (reg_mstatus.prv === PRV.M && reg_mstatus.mie), pending_interrupts & ~reg_mideleg, UInt(0)) + val s_interrupts = Mux(reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie), pending_interrupts & reg_mideleg, UInt(0)) + val all_interrupts = m_interrupts | s_interrupts + io.interrupt := all_interrupts.orR + io.interrupt_cause := (io.interrupt << (xLen-1)) + PriorityEncoder(all_interrupts) val system_insn = io.rw.cmd === CSR.I val cpu_ren = io.rw.cmd =/= CSR.N && !system_insn @@ -175,38 +204,34 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) io.host.debug_stats_csr := reg_stats // direct export up the hierarchy - val read_time = if (usingPerfCounters) reg_time else (reg_cycle: UInt) - val read_mstatus = io.status.toBits val isa_string = "IMA" + (if (usingVM) "S" else "") + - (if (usingFPU) "FD" else "") + + (if (usingFPU) "FDG" else "") + (if (usingRoCC) "X" else "") - val cpuid = ((if (xLen == 32) BigInt(0) else BigInt(2)) << (xLen-2)) | + val isa = ((if (xLen == 32) BigInt(0) else BigInt(2)) << (xLen-2)) | isa_string.map(x => 1 << (x - 'A')).reduce(_|_) - val impid = 1 - val reg_mtvec = Reg(init = UInt(mtvecInit, xLen)) + val read_mstatus = io.status.toBits()(xLen-1,0) val read_mapping = collection.mutable.LinkedHashMap[Int,Bits]( - CSRs.fflags -> (if (usingFPU) reg_fflags else UInt(0)), - CSRs.frm -> (if (usingFPU) reg_frm else UInt(0)), - CSRs.fcsr -> (if (usingFPU) Cat(reg_frm, reg_fflags) else UInt(0)), - CSRs.cycle -> reg_cycle, - CSRs.cyclew -> reg_cycle, - CSRs.time -> read_time, - CSRs.timew -> read_time, - CSRs.stime -> read_time, - CSRs.stimew -> read_time, - CSRs.mtime -> read_time, - CSRs.mcpuid -> UInt(cpuid), - CSRs.mimpid -> UInt(impid), + CSRs.mimpid -> UInt(0), + CSRs.marchid -> UInt(0), + CSRs.mvendorid -> UInt(0), + CSRs.mtime -> reg_time, + CSRs.mcycle -> reg_cycle, + CSRs.minstret -> reg_instret, + CSRs.mucounteren -> UInt(0), + CSRs.mutime_delta -> UInt(0), + CSRs.mucycle_delta -> UInt(0), + CSRs.muinstret_delta -> UInt(0), + CSRs.misa -> UInt(isa), CSRs.mstatus -> read_mstatus, - CSRs.mtdeleg -> UInt(0), - CSRs.mreset -> UInt(0), CSRs.mtvec -> reg_mtvec, - CSRs.miobase -> UInt(p(junctions.MMIOBase)), - CSRs.mipi -> UInt(0), - CSRs.mip -> reg_mip.toBits, - CSRs.mie -> reg_mie.toBits, + CSRs.mcfgaddr -> UInt(p(junctions.MMIOBase)), + CSRs.mipi -> reg_mip.msip, + CSRs.mip -> read_mip, + CSRs.mie -> reg_mie, + CSRs.mideleg -> reg_mideleg, + CSRs.medeleg -> reg_medeleg, CSRs.mscratch -> reg_mscratch, CSRs.mepc -> reg_mepc.sextTo(xLen), CSRs.mbadaddr -> reg_mbadaddr.sextTo(xLen), @@ -217,30 +242,26 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) CSRs.mtohost -> reg_tohost, CSRs.mfromhost -> reg_fromhost) - if (usingPerfCounters) { - read_mapping += CSRs.instret -> reg_instret - read_mapping += CSRs.instretw -> reg_instret - - for (i <- 0 until reg_uarch_counters.size) - read_mapping += (CSRs.uarch0 + i) -> reg_uarch_counters(i) + if (usingFPU) { + read_mapping += CSRs.fflags -> reg_fflags + read_mapping += CSRs.frm -> reg_frm + read_mapping += CSRs.fcsr -> Cat(reg_frm, reg_fflags) } if (usingVM) { - val read_sstatus = Wire(init=new SStatus().fromBits(read_mstatus)) - read_sstatus.zero1 := 0 - read_sstatus.zero2 := 0 - read_sstatus.zero3 := 0 - read_sstatus.zero4 := 0 + val read_sie = reg_mie & reg_mideleg + val read_sip = read_mip & reg_mideleg + val read_sstatus = Wire(init=io.status) + read_sstatus.vm := 0 + read_sstatus.mprv := 0 + read_sstatus.mpp := 0 + read_sstatus.hpp := 0 + read_sstatus.mpie := 0 + read_sstatus.hpie := 0 + read_sstatus.mie := 0 + read_sstatus.hie := 0 - val read_sip = Wire(init=new MIP().fromBits(0)) - read_sip.ssip := reg_mip.ssip - read_sip.stip := reg_mip.stip - - val read_sie = Wire(init=new MIP().fromBits(0)) - read_sie.ssip := reg_mie.ssip - read_sie.stip := reg_mie.stip - - read_mapping += CSRs.sstatus -> read_sstatus.toBits + read_mapping += CSRs.sstatus -> (read_sstatus.toBits())(xLen-1,0) read_mapping += CSRs.sip -> read_sip.toBits read_mapping += CSRs.sie -> read_sie.toBits read_mapping += CSRs.sscratch -> reg_sscratch @@ -250,10 +271,15 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) read_mapping += CSRs.sasid -> UInt(0) read_mapping += CSRs.sepc -> reg_sepc.sextTo(xLen) read_mapping += CSRs.stvec -> reg_stvec.sextTo(xLen) + read_mapping += CSRs.mscounteren -> UInt(0) + read_mapping += CSRs.mstime_delta -> UInt(0) + read_mapping += CSRs.mscycle_delta -> UInt(0) + read_mapping += CSRs.msinstret_delta -> UInt(0) } for (i <- 0 until nCustomMrwCsrs) { - val addr = CSRs.mrwbase + i + val addr = 0xff0 + i + require(addr < (1 << CSR.ADDRSZ)) require(!read_mapping.contains(addr), "custom MRW CSR address " + i + " is already in use") read_mapping += addr -> io.custom_mrw_csrs(i) } @@ -278,14 +304,13 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) Mux(io.rw.cmd === CSR.S, io.rw.rdata | io.rw.wdata, host_csr_bits.data))) - val opcode = io.rw.addr - val insn_call = !opcode(8) && !opcode(0) && system_insn - val insn_break = !opcode(8) && opcode(0) && system_insn - val insn_ret = opcode(8) && !opcode(1) && !opcode(0) && system_insn && priv_sufficient - val insn_sfence_vm = opcode(8) && !opcode(1) && opcode(0) && system_insn && priv_sufficient - val maybe_insn_redirect_trap = opcode(2) && system_insn - val insn_redirect_trap = maybe_insn_redirect_trap && priv_sufficient - val insn_wfi = opcode(8) && opcode(1) && !opcode(0) && system_insn && priv_sufficient + val do_system_insn = priv_sufficient && system_insn + val opcode = UInt(1) << io.rw.addr(2,0) + val insn_call = do_system_insn && opcode(0) + val insn_break = do_system_insn && opcode(1) + val insn_ret = do_system_insn && opcode(2) + val insn_sfence_vm = do_system_insn && opcode(4) + val insn_wfi = do_system_insn && opcode(5) val csr_xcpt = (cpu_wen && read_only) || (cpu_ren && (!priv_sufficient || !addr_valid || fp_csr && !io.status.fs.orR)) || @@ -293,67 +318,77 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) insn_call || insn_break when (insn_wfi) { reg_wfi := true } - when (some_interrupt_pending) { reg_wfi := false } + when (read_mip.orR) { reg_wfi := false } + val cause = + Mux(!csr_xcpt, io.cause, + Mux(insn_call, reg_mstatus.prv + Causes.user_ecall, + Mux[UInt](insn_break, Causes.breakpoint, Causes.illegal_instruction))) + val cause_lsbs = cause(log2Up(xLen)-1,0) + val can_delegate = Bool(p(UseVM)) && reg_mstatus.prv < PRV.M + val delegate = can_delegate && Mux(cause(xLen-1), reg_mideleg(cause_lsbs), reg_medeleg(cause_lsbs)) + val tvec = Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec) + val epc = Mux(can_delegate, reg_sepc, reg_mepc) io.fatc := insn_sfence_vm - io.evec := Mux(io.exception || csr_xcpt, (reg_mstatus.prv << 6) + reg_mtvec, - Mux(maybe_insn_redirect_trap, reg_stvec.sextTo(vaddrBitsExtended), - Mux(reg_mstatus.prv(1) || Bool(!p(UseVM)), reg_mepc, reg_sepc))) + io.evec := Mux(io.exception || csr_xcpt, tvec, epc) io.ptbr := reg_sptbr io.csr_xcpt := csr_xcpt - io.eret := insn_ret || insn_redirect_trap + io.eret := insn_ret io.status := reg_mstatus - io.status.fs := Fill(2, reg_mstatus.fs.orR) // either off or dirty (no clean/initial support yet) - io.status.xs := Fill(2, reg_mstatus.xs.orR) // either off or dirty (no clean/initial support yet) io.status.sd := io.status.fs.andR || io.status.xs.andR if (xLen == 32) io.status.sd_rv32 := io.status.sd when (io.exception || csr_xcpt) { - reg_mstatus.ie := false - reg_mstatus.prv := PRV_M - reg_mstatus.mprv := false - reg_mstatus.prv1 := reg_mstatus.prv - reg_mstatus.ie1 := reg_mstatus.ie - reg_mstatus.prv2 := reg_mstatus.prv1 - reg_mstatus.ie2 := reg_mstatus.ie1 - - reg_mepc := ~(~io.pc | (coreInstBytes-1)) - reg_mcause := io.cause - when (csr_xcpt) { - reg_mcause := Causes.illegal_instruction - when (insn_break) { reg_mcause := Causes.breakpoint } - when (insn_call) { reg_mcause := reg_mstatus.prv + Causes.user_ecall } - } - - reg_mbadaddr := io.pc - when (io.cause === Causes.fault_load || io.cause === Causes.misaligned_load || - io.cause === Causes.fault_store || io.cause === Causes.misaligned_store) { + val ldst_badaddr = { val (upper, lower) = Split(io.rw.wdata, vaddrBits) val sign = Mux(lower.toSInt < SInt(0), upper.andR, upper.orR) - reg_mbadaddr := Cat(sign, lower) + Cat(sign, lower) + } + val ldst = + cause === Causes.fault_load || cause === Causes.misaligned_load || + cause === Causes.fault_store || cause === Causes.misaligned_store + val badaddr = Mux(ldst, ldst_badaddr, io.pc) + val epc = ~(~io.pc | (coreInstBytes-1)) + val pie = read_mstatus(reg_mstatus.prv) + + when (delegate) { + reg_sepc := epc + reg_scause := cause + reg_sbadaddr := badaddr + reg_mstatus.spie := pie + reg_mstatus.spp := reg_mstatus.prv + reg_mstatus.sie := false + reg_mstatus.prv := PRV.S + }.otherwise { + reg_mepc := epc + reg_mcause := cause + reg_mbadaddr := badaddr + reg_mstatus.mpie := pie + reg_mstatus.mpp := reg_mstatus.prv + reg_mstatus.mie := false + reg_mstatus.prv := PRV.M } } when (insn_ret) { - reg_mstatus.ie := reg_mstatus.ie1 - reg_mstatus.prv := reg_mstatus.prv1 - reg_mstatus.prv1 := reg_mstatus.prv2 - reg_mstatus.ie1 := reg_mstatus.ie2 - reg_mstatus.prv2 := PRV_U - reg_mstatus.ie2 := true - } - - when (insn_redirect_trap) { - reg_mstatus.prv := PRV_S - reg_sbadaddr := reg_mbadaddr - reg_scause := reg_mcause - reg_sepc := reg_mepc + when (can_delegate) { + when (reg_mstatus.spp.toBool) { reg_mstatus.sie := reg_mstatus.spie } + reg_mstatus.spie := false + reg_mstatus.spp := PRV.U + reg_mstatus.prv := reg_mstatus.spp + }.otherwise { + when (reg_mstatus.mpp(1)) { reg_mstatus.mie := reg_mstatus.mpie } + when (reg_mstatus.mpp(0)) { reg_mstatus.sie := reg_mstatus.mpie } + reg_mstatus.mpie := false + reg_mstatus.mpp := PRV.U + reg_mstatus.prv := reg_mstatus.mpp + } } - assert(PopCount(insn_ret :: insn_redirect_trap :: io.exception :: csr_xcpt :: Nil) <= 1, "these conditions must be mutually exclusive") + assert(PopCount(insn_ret :: io.exception :: csr_xcpt :: Nil) <= 1, "these conditions must be mutually exclusive") - when (read_time >= reg_mtimecmp) { + when (reg_time >= reg_mtimecmp) { reg_mip.mtip := true } @@ -372,17 +407,18 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) when (wen) { when (decoded_addr(CSRs.mstatus)) { val new_mstatus = new MStatus().fromBits(wdata) - reg_mstatus.ie := new_mstatus.ie - reg_mstatus.ie1 := new_mstatus.ie1 + reg_mstatus.mie := new_mstatus.mie + reg_mstatus.mpie := new_mstatus.mpie - val supportedModes = Vec((PRV_M :: PRV_U :: (if (usingVM) List(PRV_S) else Nil)).map(UInt(_))) + val supportedModes = Vec((PRV.M :: PRV.U :: (if (usingVM) List(PRV.S) else Nil)).map(UInt(_))) if (supportedModes.size > 1) { reg_mstatus.mprv := new_mstatus.mprv - when (supportedModes contains new_mstatus.prv) { reg_mstatus.prv := new_mstatus.prv } - when (supportedModes contains new_mstatus.prv1) { reg_mstatus.prv1 := new_mstatus.prv1 } + when (supportedModes contains new_mstatus.mpp) { reg_mstatus.mpp := new_mstatus.mpp } if (supportedModes.size > 2) { - when (supportedModes contains new_mstatus.prv2) { reg_mstatus.prv2 := new_mstatus.prv2 } - reg_mstatus.ie2 := new_mstatus.ie2 + reg_mstatus.pum := new_mstatus.pum + reg_mstatus.spp := new_mstatus.spp + reg_mstatus.spie := new_mstatus.spie + reg_mstatus.sie := new_mstatus.sie } } @@ -391,8 +427,8 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) when (new_mstatus.vm === 0) { reg_mstatus.vm := 0 } when (new_mstatus.vm === vm_on) { reg_mstatus.vm := vm_on } } - if (usingVM || usingFPU) reg_mstatus.fs := new_mstatus.fs - if (usingRoCC) reg_mstatus.xs := new_mstatus.xs + if (usingVM || usingFPU) reg_mstatus.fs := Fill(2, new_mstatus.fs.orR) + if (usingRoCC) reg_mstatus.xs := Fill(2, new_mstatus.xs.orR) } when (decoded_addr(CSRs.mip)) { val new_mip = new MIP().fromBits(wdata) @@ -405,76 +441,48 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p) when (decoded_addr(CSRs.mipi)) { reg_mip.msip := wdata(0) } - when (decoded_addr(CSRs.mie)) { - val new_mie = new MIP().fromBits(wdata) - if (usingVM) { - reg_mie.ssip := new_mie.ssip - reg_mie.stip := new_mie.stip - } - reg_mie.msip := new_mie.msip - reg_mie.mtip := new_mie.mtip - } + when (decoded_addr(CSRs.mie)) { reg_mie := wdata & supported_interrupts } when (decoded_addr(CSRs.fflags)) { reg_fflags := wdata } when (decoded_addr(CSRs.frm)) { reg_frm := wdata } when (decoded_addr(CSRs.fcsr)) { reg_fflags := wdata; reg_frm := wdata >> reg_fflags.getWidth } when (decoded_addr(CSRs.mepc)) { reg_mepc := ~(~wdata | (coreInstBytes-1)) } when (decoded_addr(CSRs.mscratch)) { reg_mscratch := wdata } + if (p(MtvecWritable)) + when (decoded_addr(CSRs.mtvec)) { reg_mtvec := wdata >> 2 << 2 } when (decoded_addr(CSRs.mcause)) { reg_mcause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ } when (decoded_addr(CSRs.mbadaddr)) { reg_mbadaddr := wdata(vaddrBitsExtended-1,0) } - if (usingPerfCounters) - when (decoded_addr(CSRs.instretw)) { reg_instret := wdata } when (decoded_addr(CSRs.mtimecmp)) { reg_mtimecmp := wdata; reg_mip.mtip := false } when (decoded_addr(CSRs.mtime)) { reg_time := wdata } when (decoded_addr(CSRs.mfromhost)){ when (reg_fromhost === UInt(0) || !host_csr_req_fire) { reg_fromhost := wdata } } when (decoded_addr(CSRs.mtohost)) { when (reg_tohost === UInt(0) || host_csr_req_fire) { reg_tohost := wdata } } when (decoded_addr(CSRs.stats)) { reg_stats := wdata(0) } - when (decoded_addr(CSRs.mtvec)) { reg_mtvec := wdata & ~UInt("b11") } if (usingVM) { when (decoded_addr(CSRs.sstatus)) { - val new_sstatus = new SStatus().fromBits(wdata) - reg_mstatus.ie := new_sstatus.ie - reg_mstatus.ie1 := new_sstatus.pie - reg_mstatus.prv1 := Mux[UInt](new_sstatus.ps, PRV_S, PRV_U) - reg_mstatus.mprv := new_sstatus.mprv - reg_mstatus.fs := new_sstatus.fs // even without an FPU - if (usingRoCC) reg_mstatus.xs := new_sstatus.xs + val new_sstatus = new MStatus().fromBits(wdata) + reg_mstatus.sie := new_sstatus.sie + reg_mstatus.spie := new_sstatus.spie + reg_mstatus.spp := new_sstatus.spp + reg_mstatus.pum := new_sstatus.pum + reg_mstatus.fs := Fill(2, new_sstatus.fs.orR) // even without an FPU + if (usingRoCC) reg_mstatus.xs := Fill(2, new_sstatus.xs.orR) } when (decoded_addr(CSRs.sip)) { val new_sip = new MIP().fromBits(wdata) reg_mip.ssip := new_sip.ssip } - when (decoded_addr(CSRs.sie)) { - val new_sie = new MIP().fromBits(wdata) - reg_mie.ssip := new_sie.ssip - reg_mie.stip := new_sie.stip - } + when (decoded_addr(CSRs.sie)) { reg_mie := (reg_mie & ~reg_mideleg) | (wdata & reg_mideleg) } when (decoded_addr(CSRs.sscratch)) { reg_sscratch := wdata } - when (decoded_addr(CSRs.sptbr)) { reg_sptbr := Cat(wdata(paddrBits-1, pgIdxBits), Bits(0, pgIdxBits)) } - when (decoded_addr(CSRs.sepc)) { reg_sepc := ~(~wdata | (coreInstBytes-1)) } - when (decoded_addr(CSRs.stvec)) { reg_stvec := ~(~wdata | (coreInstBytes-1)) } + when (decoded_addr(CSRs.sptbr)) { reg_sptbr := wdata } + when (decoded_addr(CSRs.sepc)) { reg_sepc := wdata >> log2Up(coreInstBytes) << log2Up(coreInstBytes) } + when (decoded_addr(CSRs.stvec)) { reg_stvec := wdata >> 2 << 2 } + when (decoded_addr(CSRs.scause)) { reg_scause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ } + when (decoded_addr(CSRs.sbadaddr)) { reg_sbadaddr := wdata(vaddrBitsExtended-1,0) } + when (decoded_addr(CSRs.mideleg)) { reg_mideleg := wdata & delegable_interrupts } + when (decoded_addr(CSRs.medeleg)) { reg_medeleg := wdata & delegable_exceptions } } } io.rocc.csr.waddr := addr io.rocc.csr.wdata := wdata io.rocc.csr.wen := wen - - when(this.reset) { - reg_mstatus.zero1 := 0 - reg_mstatus.zero2 := 0 - reg_mstatus.ie := false - reg_mstatus.prv := PRV_M - reg_mstatus.ie1 := false - reg_mstatus.prv1 := PRV_M /* hard-wired to M when missing user mode */ - reg_mstatus.ie2 := false /* hard-wired to 0 when missing supervisor mode */ - reg_mstatus.prv2 := PRV_U /* hard-wired to 0 when missing supervisor mode */ - reg_mstatus.ie3 := false /* hard-wired to 0 when missing hypervisor mode */ - reg_mstatus.prv3 := PRV_U /* hard-wired to 0 when missing hypervisor mode */ - reg_mstatus.mprv := false - reg_mstatus.vm := 0 - reg_mstatus.fs := 0 - reg_mstatus.xs := 0 - reg_mstatus.sd_rv32 := false - reg_mstatus.sd := false - } } diff --git a/rocket/src/main/scala/frontend.scala b/rocket/src/main/scala/frontend.scala index 96e7c2ec..28cfbfa0 100644 --- a/rocket/src/main/scala/frontend.scala +++ b/rocket/src/main/scala/frontend.scala @@ -42,7 +42,7 @@ class Frontend(implicit p: Parameters) extends CoreModule()(p) with HasL1CachePa val s1_pc = ~(~s1_pc_ | (coreInstBytes-1)) // discard PC LSBS (this propagates down the pipeline) val s1_same_block = Reg(Bool()) val s2_valid = Reg(init=Bool(true)) - val s2_pc = Reg(init=UInt(startAddr)) + val s2_pc = Reg(init=UInt(p(ResetVector))) val s2_btb_resp_valid = Reg(init=Bool(false)) val s2_btb_resp_bits = Reg(btb.io.resp.bits) val s2_xcpt_if = Reg(init=Bool(false)) diff --git a/rocket/src/main/scala/idecode.scala b/rocket/src/main/scala/idecode.scala index 2464b817..d71bf32c 100644 --- a/rocket/src/main/scala/idecode.scala +++ b/rocket/src/main/scala/idecode.scala @@ -174,7 +174,6 @@ object XDecode extends DecodeConstants SCALL-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), SBREAK-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), SRET-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), - MRTS-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), WFI-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N), CSRRW-> List(Y, N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.W,N,N,N), CSRRS-> List(Y, N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.S,N,N,N), diff --git a/rocket/src/main/scala/instructions.scala b/rocket/src/main/scala/instructions.scala index 564b0f8d..d854fac8 100644 --- a/rocket/src/main/scala/instructions.scala +++ b/rocket/src/main/scala/instructions.scala @@ -94,12 +94,9 @@ object Instructions { def SC_D = BitPat("b00011????????????011?????0101111") def SCALL = BitPat("b00000000000000000000000001110011") def SBREAK = BitPat("b00000000000100000000000001110011") - def SRET = BitPat("b00010000000000000000000001110011") - def SFENCE_VM = BitPat("b000100000001?????000000001110011") - def WFI = BitPat("b00010000001000000000000001110011") - def MRTH = BitPat("b00110000011000000000000001110011") - def MRTS = BitPat("b00110000010100000000000001110011") - def HRTS = BitPat("b00100000010100000000000001110011") + def SRET = BitPat("b00010000001000000000000001110011") + def SFENCE_VM = BitPat("b000100000100?????000000001110011") + def WFI = BitPat("b00010000010100000000000001110011") def CSRRW = BitPat("b?????????????????001?????1110011") def CSRRS = BitPat("b?????????????????010?????1110011") def CSRRC = BitPat("b?????????????????011?????1110011") @@ -268,50 +265,63 @@ object CSRs { val uarch14 = 0xcce val uarch15 = 0xccf val sstatus = 0x100 - val stvec = 0x101 val sie = 0x104 + val stvec = 0x105 val sscratch = 0x140 val sepc = 0x141 + val scause = 0x142 + val sbadaddr = 0x143 val sip = 0x144 val sptbr = 0x180 val sasid = 0x181 - val cyclew = 0x900 - val timew = 0x901 - val instretw = 0x902 + val scycle = 0xd00 val stime = 0xd01 - val scause = 0xd42 - val sbadaddr = 0xd43 - val stimew = 0xa01 + val sinstret = 0xd02 val mstatus = 0x300 - val mtvec = 0x301 - val mtdeleg = 0x302 + val medeleg = 0x302 + val mideleg = 0x303 val mie = 0x304 + val mtvec = 0x305 val mtimecmp = 0x321 val mscratch = 0x340 val mepc = 0x341 val mcause = 0x342 val mbadaddr = 0x343 val mip = 0x344 - val mtime = 0x701 - val mcpuid = 0xf00 - val mimpid = 0xf01 - val mhartid = 0xf10 - val mtohost = 0x780 - val mfromhost = 0x781 - val mreset = 0x782 - val mipi = 0x783 - val miobase = 0x784 + val mipi = 0x345 + val mucounteren = 0x310 + val mscounteren = 0x311 + val mucycle_delta = 0x700 + val mutime_delta = 0x701 + val muinstret_delta = 0x702 + val mscycle_delta = 0x704 + val mstime_delta = 0x705 + val msinstret_delta = 0x706 + val mcycle = 0xf00 + val mtime = 0xf01 + val minstret = 0xf02 + val misa = 0xf10 + val mvendorid = 0xf11 + val marchid = 0xf12 + val mimpid = 0xf13 + val mcfgaddr = 0xf14 + val mhartid = 0xf15 + val mtohost = 0x7c0 + val mfromhost = 0x7c1 + val mreset = 0x7c2 val cycleh = 0xc80 val timeh = 0xc81 val instreth = 0xc82 - val cyclehw = 0x980 - val timehw = 0x981 - val instrethw = 0x982 - val stimeh = 0xd81 - val stimehw = 0xa81 val mtimecmph = 0x361 - val mtimeh = 0x741 - val mrwbase = 0x790 + val mucycle_deltah = 0x780 + val mutime_deltah = 0x781 + val muinstret_deltah = 0x782 + val mscycle_deltah = 0x784 + val mstime_deltah = 0x785 + val msinstret_deltah = 0x786 + val mcycleh = 0xf80 + val mtimeh = 0xf81 + val minstreth = 0xf82 val all = { val res = collection.mutable.ArrayBuffer[Int]() res += fflags @@ -338,39 +348,50 @@ object CSRs { res += uarch14 res += uarch15 res += sstatus - res += stvec res += sie + res += stvec res += sscratch res += sepc + res += scause + res += sbadaddr res += sip res += sptbr res += sasid - res += cyclew - res += timew - res += instretw + res += scycle res += stime - res += scause - res += sbadaddr - res += stimew + res += sinstret res += mstatus - res += mtvec - res += mtdeleg + res += medeleg + res += mideleg res += mie + res += mtvec res += mtimecmp res += mscratch res += mepc res += mcause res += mbadaddr res += mip + res += mipi + res += mucounteren + res += mscounteren + res += mucycle_delta + res += mutime_delta + res += muinstret_delta + res += mscycle_delta + res += mstime_delta + res += msinstret_delta + res += mcycle res += mtime - res += mcpuid + res += minstret + res += misa + res += mvendorid + res += marchid res += mimpid + res += mcfgaddr res += mhartid res += mtohost res += mfromhost res += mreset - res += mipi - res += miobase res.toArray } val all32 = { @@ -378,13 +399,16 @@ object CSRs { res += cycleh res += timeh res += instreth - res += cyclehw - res += timehw - res += instrethw - res += stimeh - res += stimehw res += mtimecmph + res += mucycle_deltah + res += mutime_deltah + res += muinstret_deltah + res += mscycle_deltah + res += mstime_deltah + res += msinstret_deltah + res += mcycleh res += mtimeh + res += minstreth res.toArray } } diff --git a/rocket/src/main/scala/ptw.scala b/rocket/src/main/scala/ptw.scala index a8bfa03c..6ec57d5c 100644 --- a/rocket/src/main/scala/ptw.scala +++ b/rocket/src/main/scala/ptw.scala @@ -15,7 +15,6 @@ class PTWReq(implicit p: Parameters) extends CoreBundle()(p) { } class PTWResp(implicit p: Parameters) extends CoreBundle()(p) { - val error = Bool() val pte = new PTE } @@ -27,7 +26,7 @@ class TLBPTWIO(implicit p: Parameters) extends CoreBundle()(p) { } class DatapathPTWIO(implicit p: Parameters) extends CoreBundle()(p) { - val ptbr = UInt(INPUT, paddrBits) + val ptbr = UInt(INPUT, ppnBits) val invalidate = Bool(INPUT) val status = new MStatus().asInput } @@ -59,7 +58,7 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { val dpath = new DatapathPTWIO } - val s_ready :: s_req :: s_wait :: s_set_dirty :: s_wait_dirty :: s_done :: s_error :: Nil = Enum(UInt(), 7) + val s_ready :: s_req :: s_wait :: s_set_dirty :: s_wait_dirty :: s_done :: Nil = Enum(UInt(), 6) val state = Reg(init=s_ready) val count = Reg(UInt(width = log2Up(pgLevels))) @@ -79,7 +78,7 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { when (arb.io.out.fire()) { r_req := arb.io.out.bits r_req_dest := arb.io.chosen - r_pte.ppn := io.dpath.ptbr(paddrBits-1,pgIdxBits) + r_pte.ppn := io.dpath.ptbr } val (pte_cache_hit, pte_cache_data) = { @@ -122,16 +121,12 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { io.mem.req.bits.kill := Bool(false) io.mem.req.bits.data := pte_wdata.toBits - val resp_err = state === s_error - val resp_val = state === s_done || resp_err - val r_resp_ppn = io.mem.req.bits.addr >> pgIdxBits val resp_ppn = Vec((0 until pgLevels-1).map(i => Cat(r_resp_ppn >> pgLevelBits*(pgLevels-i-1), r_req.addr(pgLevelBits*(pgLevels-i-1)-1,0))) :+ r_resp_ppn)(count) + val resp_val = state === s_done for (i <- 0 until io.requestor.size) { - val me = r_req_dest === UInt(i) - io.requestor(i).resp.valid := resp_val && me - io.requestor(i).resp.bits.error := resp_err + io.requestor(i).resp.valid := resp_val && (r_req_dest === i) io.requestor(i).resp.bits.pte := r_pte io.requestor(i).resp.bits.pte.ppn := resp_ppn io.requestor(i).invalidate := io.dpath.invalidate @@ -161,14 +156,14 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { state := s_req } when (io.mem.resp.valid) { - state := s_error + state := s_done + when (pte.leaf() && set_dirty_bit) { + state := s_set_dirty + } when (pte.table() && count < pgLevels-1) { state := s_req count := count + 1 } - when (pte.leaf()) { - state := Mux(set_dirty_bit, s_set_dirty, s_done) - } } } is (s_set_dirty) { @@ -187,8 +182,5 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { is (s_done) { state := s_ready } - is (s_error) { - state := s_ready - } } } diff --git a/rocket/src/main/scala/rocc.scala b/rocket/src/main/scala/rocc.scala index d17dde1b..eee67228 100644 --- a/rocket/src/main/scala/rocc.scala +++ b/rocket/src/main/scala/rocc.scala @@ -47,7 +47,7 @@ class RoCCInterface(implicit p: Parameters) extends CoreBundle()(p) { val resp = Decoupled(new RoCCResponse) val mem = new HellaCacheIO()(p.alterPartial({ case CacheName => "L1D" })) val busy = Bool(OUTPUT) - val s = Bool(INPUT) + val status = new MStatus().asInput val interrupt = Bool(OUTPUT) // These should be handled differently, eventually @@ -142,8 +142,7 @@ class TranslatorExample(implicit p: Parameters) extends RoCC()(p) { val req_rd = Reg(io.resp.bits.rd) val req_offset = req_addr(pgIdxBits - 1, 0) val req_vpn = req_addr(coreMaxAddrBits - 1, pgIdxBits) - val ppn = Reg(UInt(width = ppnBits)) - val error = Reg(Bool()) + val pte = Reg(new PTE) val s_idle :: s_ptw_req :: s_ptw_resp :: s_resp :: Nil = Enum(Bits(), 4) val state = Reg(init = s_idle) @@ -161,8 +160,7 @@ class TranslatorExample(implicit p: Parameters) extends RoCC()(p) { when (ptw.req.fire()) { state := s_ptw_resp } when (state === s_ptw_resp && ptw.resp.valid) { - error := ptw.resp.bits.error - ppn := ptw.resp.bits.pte.ppn + pte := ptw.resp.bits.pte state := s_resp } @@ -175,7 +173,7 @@ class TranslatorExample(implicit p: Parameters) extends RoCC()(p) { io.resp.valid := (state === s_resp) io.resp.bits.rd := req_rd - io.resp.bits.data := Mux(error, SInt(-1).toUInt, Cat(ppn, req_offset)) + io.resp.bits.data := Mux(pte.leaf(), Cat(pte.ppn, req_offset), ~UInt(0, xLen)) io.busy := (state =/= s_idle) io.interrupt := Bool(false) diff --git a/rocket/src/main/scala/rocket.scala b/rocket/src/main/scala/rocket.scala index d9657095..0eb175e5 100644 --- a/rocket/src/main/scala/rocket.scala +++ b/rocket/src/main/scala/rocket.scala @@ -22,7 +22,9 @@ case object CoreInstBits extends Field[Int] case object CoreDataBits extends Field[Int] case object CoreDCacheReqTagBits extends Field[Int] case object NCustomMRWCSRs extends Field[Int] +case object MtvecWritable extends Field[Boolean] case object MtvecInit extends Field[BigInt] +case object ResetVector extends Field[BigInt] trait HasCoreParameters extends HasAddrMapParameters { implicit val p: Parameters @@ -51,8 +53,6 @@ trait HasCoreParameters extends HasAddrMapParameters { else p(BuildRoCC).flatMap(_.csrs) val nRoccCsrs = p(RoccNCSRs) val nCores = p(HtifKey).nCores - val mtvecInit = p(MtvecInit) - val startAddr = mtvecInit + 0x100 // Print out log of committed instructions and their writeback values. // Requires post-processing due to out-of-order writebacks. @@ -539,7 +539,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) { io.rocc.cmd.valid := wb_rocc_val io.rocc.exception := wb_xcpt && csr.io.status.xs.orR - io.rocc.s := csr.io.status.prv.orR // should we just pass all of mstatus? + io.rocc.status := csr.io.status io.rocc.cmd.bits.inst := new RoCCInstruction().fromBits(wb_reg_inst) io.rocc.cmd.bits.rs1 := wb_reg_wdata io.rocc.cmd.bits.rs2 := wb_reg_rs2 diff --git a/rocket/src/main/scala/tile.scala b/rocket/src/main/scala/tile.scala index a7bfeec3..4dbda975 100644 --- a/rocket/src/main/scala/tile.scala +++ b/rocket/src/main/scala/tile.scala @@ -84,7 +84,7 @@ class RocketTile(resetSignal: Bool = null)(implicit p: Parameters) extends Tile( })) val dcIF = Module(new SimpleHellaCacheIF()(dcacheParams)) rocc.io.cmd <> cmdRouter.io.out(i) - rocc.io.s := core.io.rocc.s + rocc.io.status := core.io.rocc.status rocc.io.exception := core.io.rocc.exception rocc.io.host_id := io.host.id dcIF.io.requestor <> rocc.io.mem diff --git a/rocket/src/main/scala/tlb.scala b/rocket/src/main/scala/tlb.scala index 55e7359d..323bc5fc 100644 --- a/rocket/src/main/scala/tlb.scala +++ b/rocket/src/main/scala/tlb.scala @@ -100,7 +100,6 @@ class TLB(implicit p: Parameters) extends TLBModule()(p) { val tag_hit_addr = OHToUInt(tag_cam.io.hits) // permission bit arrays - val valid_array = Reg(Vec(entries, Bool())) // PTE is valid (not equivalent to CAM tag valid bit!) val ur_array = Reg(Vec(entries, Bool())) // user read permission val uw_array = Reg(Vec(entries, Bool())) // user write permission val ux_array = Reg(Vec(entries, Bool())) // user execute permission @@ -111,13 +110,12 @@ class TLB(implicit p: Parameters) extends TLBModule()(p) { when (io.ptw.resp.valid) { val pte = io.ptw.resp.bits.pte tag_ram(r_refill_waddr) := pte.ppn - valid_array(r_refill_waddr) := !io.ptw.resp.bits.error - ur_array(r_refill_waddr) := pte.ur() && !io.ptw.resp.bits.error - uw_array(r_refill_waddr) := pte.uw() && !io.ptw.resp.bits.error - ux_array(r_refill_waddr) := pte.ux() && !io.ptw.resp.bits.error - sr_array(r_refill_waddr) := pte.sr() && !io.ptw.resp.bits.error - sw_array(r_refill_waddr) := pte.sw() && !io.ptw.resp.bits.error - sx_array(r_refill_waddr) := pte.sx() && !io.ptw.resp.bits.error + ur_array(r_refill_waddr) := pte.ur() + uw_array(r_refill_waddr) := pte.uw() + ux_array(r_refill_waddr) := pte.ux() + sr_array(r_refill_waddr) := pte.sr() + sw_array(r_refill_waddr) := pte.sw() + sx_array(r_refill_waddr) := pte.sx() dirty_array(r_refill_waddr) := pte.d } @@ -126,14 +124,17 @@ class TLB(implicit p: Parameters) extends TLBModule()(p) { val invalid_entry = PriorityEncoder(~tag_cam.io.valid_bits) val plru = new PseudoLRU(entries) val repl_waddr = Mux(has_invalid_entry, invalid_entry, plru.replace) - - val priv = Mux(io.ptw.status.mprv && !io.req.bits.instruction, io.ptw.status.prv1, io.ptw.status.prv) - val priv_s = priv === PRV_S - val priv_uses_vm = priv <= PRV_S + + val do_mprv = io.ptw.status.prv === PRV.M && io.ptw.status.mprv && !io.req.bits.instruction + val priv = Mux(do_mprv, io.ptw.status.mpp, io.ptw.status.prv) + val priv_s = priv === PRV.S + val priv_uses_vm = priv <= PRV.S val req_xwr = Cat(!r_req.store, r_req.store, !(r_req.instruction || r_req.store)) - val r_array = Mux(priv_s, sr_array.toBits, ur_array.toBits) - val w_array = Mux(priv_s, sw_array.toBits, uw_array.toBits) + val ur_bits = ur_array.toBits + val pum_ok = ~Mux(io.ptw.status.pum, ur_bits, UInt(0)) + val r_array = Mux(priv_s, sr_array.toBits & pum_ok, ur_bits) + val w_array = Mux(priv_s, sw_array.toBits & pum_ok, uw_array.toBits) val x_array = Mux(priv_s, sx_array.toBits, ux_array.toBits) val vm_enabled = io.ptw.status.vm(3) && priv_uses_vm && !io.req.bits.passthrough @@ -160,10 +161,10 @@ class TLB(implicit p: Parameters) extends TLBModule()(p) { io.resp.ppn := Mux(vm_enabled, Mux1H(tag_cam.io.hits, tag_ram), io.req.bits.vpn(ppnBits-1,0)) io.resp.hit_idx := tag_cam.io.hits - // clear invalid entries on access, or all entries on a TLB flush - tag_cam.io.clear := io.ptw.invalidate || io.req.fire() - tag_cam.io.clear_mask := ~valid_array.toBits | (tag_cam.io.hits & ~tag_hits) - when (io.ptw.invalidate) { tag_cam.io.clear_mask := ~UInt(0, entries) } + // clear entries on a TLB flush. + // TODO: selective flushing. careful with superpage mappings (flush it all) + tag_cam.io.clear := io.ptw.invalidate + tag_cam.io.clear_mask := ~UInt(0, entries) io.ptw.req.valid := state === s_request io.ptw.req.bits.addr := r_refill_tag