2016-11-28 01:16:37 +01:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
// See LICENSE.Berkeley for license details.
|
2014-09-13 03:06:41 +02:00
|
|
|
|
2012-02-26 02:09:26 +01:00
|
|
|
package rocket
|
2011-10-26 08:02:47 +02:00
|
|
|
|
2012-10-08 05:15:54 +02:00
|
|
|
import Chisel._
|
2015-03-14 10:49:07 +01:00
|
|
|
import Instructions._
|
2016-11-18 23:05:14 +01:00
|
|
|
import config._
|
2016-06-28 22:15:39 +02:00
|
|
|
import uncore.devices._
|
2016-09-28 06:27:07 +02:00
|
|
|
import util._
|
2016-09-29 01:10:32 +02:00
|
|
|
import Chisel.ImplicitConversions._
|
2011-10-26 08:02:47 +02:00
|
|
|
|
2015-03-14 10:49:07 +01:00
|
|
|
class MStatus extends Bundle {
|
2016-09-12 21:00:04 +02:00
|
|
|
// not truly part of mstatus, but convenient
|
|
|
|
val debug = Bool()
|
|
|
|
val isa = UInt(width = 32)
|
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
val prv = UInt(width = PRV.SZ) // not truly part of mstatus, but convenient
|
2015-03-14 10:49:07 +01:00
|
|
|
val sd = Bool()
|
2016-03-03 08:29:58 +01:00
|
|
|
val zero3 = UInt(width = 31)
|
|
|
|
val sd_rv32 = Bool()
|
|
|
|
val zero2 = UInt(width = 2)
|
2015-05-19 03:23:58 +02:00
|
|
|
val vm = UInt(width = 5)
|
2016-07-06 04:19:49 +02:00
|
|
|
val zero1 = UInt(width = 4)
|
|
|
|
val mxr = Bool()
|
2016-03-03 08:29:58 +01:00
|
|
|
val pum = Bool()
|
2015-05-19 03:23:58 +02:00
|
|
|
val mprv = Bool()
|
2015-03-14 10:49:07 +01:00
|
|
|
val xs = UInt(width = 2)
|
|
|
|
val fs = UInt(width = 2)
|
2016-03-03 08:29:58 +01:00
|
|
|
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()
|
2015-05-19 03:23:58 +02:00
|
|
|
}
|
|
|
|
|
2016-06-02 01:57:10 +02:00
|
|
|
class DCSR extends Bundle {
|
|
|
|
val xdebugver = UInt(width = 2)
|
|
|
|
val ndreset = Bool()
|
|
|
|
val fullreset = Bool()
|
2016-08-26 08:07:34 +02:00
|
|
|
val zero3 = UInt(width = 12)
|
2016-06-02 01:57:10 +02:00
|
|
|
val ebreakm = Bool()
|
|
|
|
val ebreakh = Bool()
|
|
|
|
val ebreaks = Bool()
|
|
|
|
val ebreaku = Bool()
|
|
|
|
val zero2 = Bool()
|
|
|
|
val stopcycle = Bool()
|
|
|
|
val stoptime = Bool()
|
|
|
|
val cause = UInt(width = 3)
|
|
|
|
val debugint = Bool()
|
|
|
|
val zero1 = Bool()
|
|
|
|
val halt = Bool()
|
|
|
|
val step = Bool()
|
|
|
|
val prv = UInt(width = PRV.SZ)
|
|
|
|
}
|
|
|
|
|
2016-09-14 01:25:31 +02:00
|
|
|
class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) {
|
|
|
|
val debug = Bool()
|
|
|
|
val mtip = Bool()
|
|
|
|
val msip = Bool()
|
|
|
|
val meip = Bool()
|
|
|
|
val seip = usingVM.option(Bool())
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:23:58 +02:00
|
|
|
class MIP extends Bundle {
|
2016-03-03 08:29:58 +01:00
|
|
|
val rocc = Bool()
|
2016-05-02 23:40:52 +02:00
|
|
|
val meip = Bool()
|
|
|
|
val heip = Bool()
|
|
|
|
val seip = Bool()
|
|
|
|
val ueip = Bool()
|
2015-05-19 03:23:58 +02:00
|
|
|
val mtip = Bool()
|
|
|
|
val htip = Bool()
|
|
|
|
val stip = Bool()
|
|
|
|
val utip = Bool()
|
|
|
|
val msip = Bool()
|
|
|
|
val hsip = Bool()
|
|
|
|
val ssip = Bool()
|
|
|
|
val usip = Bool()
|
2012-11-27 10:28:06 +01:00
|
|
|
}
|
|
|
|
|
2016-06-18 03:29:05 +02:00
|
|
|
class PTBR(implicit p: Parameters) extends CoreBundle()(p) {
|
|
|
|
require(maxPAddrBits - pgIdxBits + asIdBits <= xLen)
|
|
|
|
val asid = UInt(width = asIdBits)
|
|
|
|
val ppn = UInt(width = maxPAddrBits - pgIdxBits)
|
|
|
|
}
|
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
object PRV
|
|
|
|
{
|
|
|
|
val SZ = 2
|
|
|
|
val U = 0
|
|
|
|
val S = 1
|
|
|
|
val H = 2
|
|
|
|
val M = 3
|
|
|
|
}
|
|
|
|
|
2013-11-25 13:35:15 +01:00
|
|
|
object CSR
|
2011-10-26 08:02:47 +02:00
|
|
|
{
|
2012-11-27 10:28:06 +01:00
|
|
|
// commands
|
2015-03-14 10:49:07 +01:00
|
|
|
val SZ = 3
|
2017-01-31 22:54:02 +01:00
|
|
|
def X = BitPat.dontCare(SZ)
|
|
|
|
def N = UInt(0,SZ)
|
|
|
|
def W = UInt(1,SZ)
|
|
|
|
def S = UInt(2,SZ)
|
|
|
|
def C = UInt(3,SZ)
|
|
|
|
def I = UInt(4,SZ)
|
|
|
|
def R = UInt(5,SZ)
|
2015-10-06 06:48:05 +02:00
|
|
|
|
|
|
|
val ADDRSZ = 12
|
2017-01-31 23:45:11 +01:00
|
|
|
def debugIntCause = new MIP().getWidth
|
|
|
|
def debugTriggerCause = {
|
2016-08-26 08:07:34 +02:00
|
|
|
require(debugIntCause >= Causes.all.max)
|
|
|
|
debugIntCause
|
|
|
|
}
|
2016-08-27 05:27:27 +02:00
|
|
|
|
|
|
|
val firstCtr = CSRs.cycle
|
|
|
|
val firstHPM = 3
|
|
|
|
val firstHPC = CSRs.cycle + firstHPM
|
|
|
|
val firstHPE = CSRs.mucounteren + firstHPM
|
|
|
|
val firstMHPC = CSRs.mcycle + firstHPM
|
|
|
|
val nHPM = 29
|
|
|
|
val nCtr = firstHPM + nHPM
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|
|
|
|
|
2015-10-06 06:48:05 +02:00
|
|
|
class CSRFileIO(implicit p: Parameters) extends CoreBundle {
|
2016-09-14 01:25:31 +02:00
|
|
|
val interrupts = new TileInterrupts().asInput
|
|
|
|
val hartid = UInt(INPUT, xLen)
|
2014-05-10 04:26:43 +02:00
|
|
|
val rw = new Bundle {
|
2015-10-06 06:48:05 +02:00
|
|
|
val addr = UInt(INPUT, CSR.ADDRSZ)
|
2014-05-10 04:26:43 +02:00
|
|
|
val cmd = Bits(INPUT, CSR.SZ)
|
2015-02-02 05:04:13 +01:00
|
|
|
val rdata = Bits(OUTPUT, xLen)
|
|
|
|
val wdata = Bits(INPUT, xLen)
|
2014-05-10 04:26:43 +02:00
|
|
|
}
|
|
|
|
|
2015-05-19 03:23:58 +02:00
|
|
|
val csr_stall = Bool(OUTPUT)
|
2015-03-14 10:49:07 +01:00
|
|
|
val csr_xcpt = Bool(OUTPUT)
|
2015-03-17 08:14:32 +01:00
|
|
|
val eret = Bool(OUTPUT)
|
2016-06-16 01:21:24 +02:00
|
|
|
val singleStep = Bool(OUTPUT)
|
2015-03-14 10:49:07 +01:00
|
|
|
|
|
|
|
val status = new MStatus().asOutput
|
2016-06-18 03:29:05 +02:00
|
|
|
val ptbr = new PTBR().asOutput
|
2015-05-19 03:23:58 +02:00
|
|
|
val evec = UInt(OUTPUT, vaddrBitsExtended)
|
2014-05-10 04:26:43 +02:00
|
|
|
val exception = Bool(INPUT)
|
2015-02-02 05:04:13 +01:00
|
|
|
val retire = UInt(INPUT, log2Up(1+retireWidth))
|
2016-01-14 22:57:45 +01:00
|
|
|
val custom_mrw_csrs = Vec(nCustomMrwCsrs, UInt(INPUT, xLen))
|
2015-02-02 05:04:13 +01:00
|
|
|
val cause = UInt(INPUT, xLen)
|
2015-05-19 03:23:58 +02:00
|
|
|
val pc = UInt(INPUT, vaddrBitsExtended)
|
2016-06-09 21:33:43 +02:00
|
|
|
val badaddr = UInt(INPUT, vaddrBitsExtended)
|
2014-05-10 04:26:43 +02:00
|
|
|
val fatc = Bool(OUTPUT)
|
2015-02-02 05:04:13 +01:00
|
|
|
val time = UInt(OUTPUT, xLen)
|
2014-05-10 04:26:43 +02:00
|
|
|
val fcsr_rm = Bits(OUTPUT, FPConstants.RM_SZ)
|
|
|
|
val fcsr_flags = Valid(Bits(width = FPConstants.FLAGS_SZ)).flip
|
2017-01-17 03:24:08 +01:00
|
|
|
val rocc_interrupt = Bool(INPUT)
|
2015-03-14 10:49:07 +01:00
|
|
|
val interrupt = Bool(OUTPUT)
|
|
|
|
val interrupt_cause = UInt(OUTPUT, xLen)
|
2016-08-26 08:07:34 +02:00
|
|
|
val bp = Vec(nBreakpoints, new BP).asOutput
|
2016-08-27 05:27:27 +02:00
|
|
|
val events = Vec(nPerfEvents, Bool()).asInput
|
2014-05-10 04:26:43 +02:00
|
|
|
}
|
|
|
|
|
2015-10-06 06:48:05 +02:00
|
|
|
class CSRFile(implicit p: Parameters) extends CoreModule()(p)
|
2011-10-26 08:02:47 +02:00
|
|
|
{
|
2014-05-10 04:26:43 +02:00
|
|
|
val io = new CSRFileIO
|
2015-05-19 03:23:58 +02:00
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
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)
|
|
|
|
|
2016-08-18 00:02:27 +02:00
|
|
|
val new_prv = Wire(init = reg_mstatus.prv)
|
|
|
|
reg_mstatus.prv := legalizePrivilege(new_prv)
|
|
|
|
|
2016-06-02 01:57:10 +02:00
|
|
|
val reset_dcsr = Wire(init=new DCSR().fromBits(0))
|
|
|
|
reset_dcsr.xdebugver := 1
|
|
|
|
reset_dcsr.prv := PRV.M
|
|
|
|
val reg_dcsr = Reg(init=reset_dcsr)
|
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
val (supported_interrupts, delegable_interrupts) = {
|
|
|
|
val sup = Wire(init=new MIP().fromBits(0))
|
2016-08-26 08:07:34 +02:00
|
|
|
sup.ssip := Bool(usingVM)
|
2016-03-03 08:29:58 +01:00
|
|
|
sup.msip := true
|
2016-08-26 08:07:34 +02:00
|
|
|
sup.stip := Bool(usingVM)
|
2016-03-03 08:29:58 +01:00
|
|
|
sup.mtip := true
|
2016-05-02 23:40:52 +02:00
|
|
|
sup.meip := true
|
2016-08-26 08:07:34 +02:00
|
|
|
sup.seip := Bool(usingVM)
|
2016-03-03 08:29:58 +01:00
|
|
|
sup.rocc := usingRoCC
|
|
|
|
|
|
|
|
val del = Wire(init=sup)
|
|
|
|
del.msip := false
|
|
|
|
del.mtip := false
|
2016-05-02 23:40:52 +02:00
|
|
|
del.meip := false
|
2016-03-03 08:29:58 +01:00
|
|
|
|
2016-08-01 02:13:52 +02:00
|
|
|
(sup.asUInt, del.asUInt)
|
2016-03-03 08:29:58 +01:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
|
2016-06-16 01:21:24 +02:00
|
|
|
val exception = io.exception || io.csr_xcpt
|
2016-06-02 01:57:10 +02:00
|
|
|
val reg_debug = Reg(init=Bool(false))
|
|
|
|
val reg_dpc = Reg(UInt(width = vaddrBitsExtended))
|
|
|
|
val reg_dscratch = Reg(UInt(width = xLen))
|
|
|
|
|
2016-06-16 01:21:24 +02:00
|
|
|
val reg_singleStepped = Reg(Bool())
|
|
|
|
when (io.retire(0) || exception) { reg_singleStepped := true }
|
|
|
|
when (!io.singleStep) { reg_singleStepped := false }
|
|
|
|
assert(!io.singleStep || io.retire <= UInt(1))
|
|
|
|
assert(!reg_singleStepped || io.retire === UInt(0))
|
|
|
|
|
2016-08-26 08:07:34 +02:00
|
|
|
val reg_tselect = Reg(UInt(width = log2Up(nBreakpoints)))
|
|
|
|
val reg_bp = Reg(Vec(1 << log2Up(nBreakpoints), new BP))
|
2016-06-09 05:19:52 +02:00
|
|
|
|
2016-08-27 05:27:27 +02:00
|
|
|
val reg_mie = Reg(UInt(width = xLen))
|
|
|
|
val reg_mideleg = Reg(UInt(width = xLen))
|
|
|
|
val reg_medeleg = Reg(UInt(width = xLen))
|
2016-05-03 00:18:41 +02:00
|
|
|
val reg_mip = Reg(new MIP)
|
2015-05-19 03:23:58 +02:00
|
|
|
val reg_mepc = Reg(UInt(width = vaddrBitsExtended))
|
2015-03-14 10:49:07 +01:00
|
|
|
val reg_mcause = Reg(Bits(width = xLen))
|
2015-05-19 03:23:58 +02:00
|
|
|
val reg_mbadaddr = Reg(UInt(width = vaddrBitsExtended))
|
2015-03-14 10:49:07 +01:00
|
|
|
val reg_mscratch = Reg(Bits(width = xLen))
|
Allow reset vector to be set dynamically
A chip's power-up sequence, or awake-from-sleep sequence, may wish to
set the reset PC based upon dynamic properties, e.g., the settings of
external pins. Support this by passing the reset vector to the Coreplex.
ExampleTop simply hard-wires the reset vector, as was the case before.
Additionally, allow MTVEC to *not* be reset. In most cases, including
riscv-tests, pk, and bbl, overriding MTVEC is one of the first things
that the boot sequence does. So the reset value is superfluous.
2016-09-20 01:45:57 +02:00
|
|
|
val mtvecWidth = paddrBits min xLen
|
|
|
|
val reg_mtvec = p(MtvecInit) match {
|
|
|
|
case Some(addr) => Reg(init=UInt(addr, mtvecWidth))
|
|
|
|
case None => Reg(UInt(width = mtvecWidth))
|
|
|
|
}
|
2016-08-27 05:27:27 +02:00
|
|
|
val reg_mucounteren = Reg(UInt(width = 32))
|
|
|
|
val reg_mscounteren = Reg(UInt(width = 32))
|
|
|
|
val delegable_counters = (BigInt(1) << (nPerfCounters + CSR.firstHPM)) - 1
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2015-05-19 03:23:58 +02:00
|
|
|
val reg_sepc = Reg(UInt(width = vaddrBitsExtended))
|
2015-03-14 10:49:07 +01:00
|
|
|
val reg_scause = Reg(Bits(width = xLen))
|
2015-05-19 03:23:58 +02:00
|
|
|
val reg_sbadaddr = Reg(UInt(width = vaddrBitsExtended))
|
2015-03-14 10:49:07 +01:00
|
|
|
val reg_sscratch = Reg(Bits(width = xLen))
|
2015-05-19 03:23:58 +02:00
|
|
|
val reg_stvec = Reg(UInt(width = vaddrBits))
|
2016-06-18 03:29:05 +02:00
|
|
|
val reg_sptbr = Reg(new PTBR)
|
2015-05-19 03:23:58 +02:00
|
|
|
val reg_wfi = Reg(init=Bool(false))
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2013-11-25 13:35:15 +01:00
|
|
|
val reg_fflags = Reg(UInt(width = 5))
|
|
|
|
val reg_frm = Reg(UInt(width = 3))
|
2012-11-27 10:28:06 +01:00
|
|
|
|
2016-03-11 02:32:00 +01:00
|
|
|
val reg_instret = WideCounter(64, io.retire)
|
2016-08-27 05:27:27 +02:00
|
|
|
val reg_cycle = if (enableCommitLog) reg_instret else WideCounter(64)
|
|
|
|
val reg_hpmevent = Seq.fill(nPerfCounters)(if (nPerfEvents > 1) Reg(UInt(width = log2Ceil(nPerfEvents))) else UInt(0))
|
|
|
|
val reg_hpmcounter = reg_hpmevent.map(e => WideCounter(64, ((UInt(0) +: io.events): Seq[UInt])(e)))
|
2016-03-11 02:32:00 +01:00
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
val mip = Wire(init=reg_mip)
|
2017-01-17 03:24:08 +01:00
|
|
|
mip.rocc := io.rocc_interrupt
|
2016-08-01 02:13:52 +02:00
|
|
|
val read_mip = mip.asUInt & supported_interrupts
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
val pending_interrupts = read_mip & reg_mie
|
2016-06-02 01:57:10 +02:00
|
|
|
val m_interrupts = Mux(!reg_debug && (reg_mstatus.prv < PRV.M || (reg_mstatus.prv === PRV.M && reg_mstatus.mie)), pending_interrupts & ~reg_mideleg, UInt(0))
|
|
|
|
val s_interrupts = Mux(!reg_debug && (reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie)), pending_interrupts & reg_mideleg, UInt(0))
|
2016-03-03 08:29:58 +01:00
|
|
|
val all_interrupts = m_interrupts | s_interrupts
|
2016-06-02 01:57:10 +02:00
|
|
|
val interruptMSB = BigInt(1) << (xLen-1)
|
2016-09-29 01:10:32 +02:00
|
|
|
val interruptCause = UInt(interruptMSB) + PriorityEncoder(all_interrupts)
|
2016-06-23 02:17:52 +02:00
|
|
|
io.interrupt := all_interrupts.orR && !io.singleStep || reg_singleStepped
|
2016-06-02 01:57:10 +02:00
|
|
|
io.interrupt_cause := interruptCause
|
2016-08-26 08:07:34 +02:00
|
|
|
io.bp := reg_bp take nBreakpoints
|
2016-06-02 01:57:10 +02:00
|
|
|
|
|
|
|
// debug interrupts are only masked by being in debug mode
|
|
|
|
when (Bool(usingDebug) && reg_dcsr.debugint && !reg_debug) {
|
|
|
|
io.interrupt := true
|
2016-09-29 01:10:32 +02:00
|
|
|
io.interrupt_cause := UInt(interruptMSB) + CSR.debugIntCause
|
2016-06-02 01:57:10 +02:00
|
|
|
}
|
2015-03-14 10:49:07 +01:00
|
|
|
|
|
|
|
val system_insn = io.rw.cmd === CSR.I
|
2016-01-14 22:57:45 +01:00
|
|
|
val cpu_ren = io.rw.cmd =/= CSR.N && !system_insn
|
2016-08-27 05:27:27 +02:00
|
|
|
val cpu_wen = cpu_ren && io.rw.cmd =/= CSR.R
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2016-09-12 21:00:04 +02:00
|
|
|
val isaMaskString =
|
2016-09-07 08:53:12 +02:00
|
|
|
(if (usingMulDiv) "M" else "") +
|
|
|
|
(if (usingAtomics) "A" else "") +
|
|
|
|
(if (usingFPU) "F" else "") +
|
|
|
|
(if (usingFPU && xLen > 32) "D" else "") +
|
2016-09-12 21:00:04 +02:00
|
|
|
(if (usingCompressed) "C" else "") +
|
2015-10-06 06:48:05 +02:00
|
|
|
(if (usingRoCC) "X" else "")
|
2016-09-12 21:00:04 +02:00
|
|
|
val isaString = "I" + isaMaskString +
|
|
|
|
(if (usingVM) "S" else "") +
|
|
|
|
(if (usingUser) "U" else "")
|
|
|
|
val isaMax = (BigInt(log2Ceil(xLen) - 4) << (xLen-2)) | isaStringToMask(isaString)
|
|
|
|
val reg_misa = Reg(init=UInt(isaMax))
|
2016-08-01 02:13:52 +02:00
|
|
|
val read_mstatus = io.status.asUInt()(xLen-1,0)
|
2015-03-25 03:32:45 +01:00
|
|
|
|
|
|
|
val read_mapping = collection.mutable.LinkedHashMap[Int,Bits](
|
2016-08-26 08:07:34 +02:00
|
|
|
CSRs.tselect -> reg_tselect,
|
|
|
|
CSRs.tdata1 -> reg_bp(reg_tselect).control.asUInt,
|
|
|
|
CSRs.tdata2 -> reg_bp(reg_tselect).address.sextTo(xLen),
|
2016-03-03 08:29:58 +01:00
|
|
|
CSRs.mimpid -> UInt(0),
|
|
|
|
CSRs.marchid -> UInt(0),
|
|
|
|
CSRs.mvendorid -> UInt(0),
|
|
|
|
CSRs.mcycle -> reg_cycle,
|
|
|
|
CSRs.minstret -> reg_instret,
|
2016-09-12 21:00:04 +02:00
|
|
|
CSRs.misa -> reg_misa,
|
2015-03-25 03:32:45 +01:00
|
|
|
CSRs.mstatus -> read_mstatus,
|
2016-01-29 20:32:59 +01:00
|
|
|
CSRs.mtvec -> reg_mtvec,
|
2016-03-03 08:29:58 +01:00
|
|
|
CSRs.mip -> read_mip,
|
|
|
|
CSRs.mie -> reg_mie,
|
|
|
|
CSRs.mideleg -> reg_mideleg,
|
|
|
|
CSRs.medeleg -> reg_medeleg,
|
2015-03-25 03:32:45 +01:00
|
|
|
CSRs.mscratch -> reg_mscratch,
|
2015-05-19 03:23:58 +02:00
|
|
|
CSRs.mepc -> reg_mepc.sextTo(xLen),
|
|
|
|
CSRs.mbadaddr -> reg_mbadaddr.sextTo(xLen),
|
2015-03-25 03:32:45 +01:00
|
|
|
CSRs.mcause -> reg_mcause,
|
2016-09-14 01:25:31 +02:00
|
|
|
CSRs.mhartid -> io.hartid)
|
2015-03-25 03:32:45 +01:00
|
|
|
|
2016-08-27 05:27:27 +02:00
|
|
|
val debug_csrs = collection.immutable.ListMap(
|
2016-08-26 08:07:34 +02:00
|
|
|
CSRs.dcsr -> reg_dcsr.asUInt,
|
|
|
|
CSRs.dpc -> reg_dpc.asUInt,
|
2016-08-27 05:27:27 +02:00
|
|
|
CSRs.dscratch -> reg_dscratch.asUInt)
|
|
|
|
|
|
|
|
val fp_csrs = collection.immutable.ListMap(
|
|
|
|
CSRs.fflags -> reg_fflags,
|
|
|
|
CSRs.frm -> reg_frm,
|
|
|
|
CSRs.fcsr -> Cat(reg_frm, reg_fflags))
|
2016-08-26 08:07:34 +02:00
|
|
|
|
|
|
|
if (usingDebug)
|
|
|
|
read_mapping ++= debug_csrs
|
2016-06-02 01:57:10 +02:00
|
|
|
|
2016-08-27 05:27:27 +02:00
|
|
|
if (usingFPU)
|
|
|
|
read_mapping ++= fp_csrs
|
|
|
|
|
|
|
|
for (((e, c), i) <- (reg_hpmevent.padTo(CSR.nHPM, UInt(0))
|
|
|
|
zip reg_hpmcounter.map(x => x: UInt).padTo(CSR.nHPM, UInt(0))) zipWithIndex) {
|
|
|
|
read_mapping += (i + CSR.firstHPE) -> e // mhpmeventN
|
|
|
|
read_mapping += (i + CSR.firstMHPC) -> c // mhpmcounterN
|
|
|
|
if (usingUser) read_mapping += (i + CSR.firstHPC) -> c // hpmcounterN
|
2015-09-28 22:55:23 +02:00
|
|
|
}
|
|
|
|
|
2015-10-06 06:48:05 +02:00
|
|
|
if (usingVM) {
|
2016-03-03 08:29:58 +01:00
|
|
|
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
|
|
|
|
|
2016-08-01 02:13:52 +02:00
|
|
|
read_mapping += CSRs.sstatus -> (read_sstatus.asUInt())(xLen-1,0)
|
|
|
|
read_mapping += CSRs.sip -> read_sip.asUInt
|
|
|
|
read_mapping += CSRs.sie -> read_sie.asUInt
|
2015-03-25 03:32:45 +01:00
|
|
|
read_mapping += CSRs.sscratch -> reg_sscratch
|
|
|
|
read_mapping += CSRs.scause -> reg_scause
|
2015-05-19 03:23:58 +02:00
|
|
|
read_mapping += CSRs.sbadaddr -> reg_sbadaddr.sextTo(xLen)
|
2016-08-01 02:13:52 +02:00
|
|
|
read_mapping += CSRs.sptbr -> reg_sptbr.asUInt
|
2015-05-19 03:23:58 +02:00
|
|
|
read_mapping += CSRs.sepc -> reg_sepc.sextTo(xLen)
|
|
|
|
read_mapping += CSRs.stvec -> reg_stvec.sextTo(xLen)
|
2016-08-27 05:27:27 +02:00
|
|
|
read_mapping += CSRs.mscounteren -> reg_mscounteren
|
|
|
|
}
|
|
|
|
|
|
|
|
if (usingUser) {
|
|
|
|
read_mapping += CSRs.mucounteren -> reg_mucounteren
|
|
|
|
read_mapping += CSRs.cycle -> reg_cycle
|
|
|
|
read_mapping += CSRs.instret -> reg_instret
|
2015-03-25 03:32:45 +01:00
|
|
|
}
|
|
|
|
|
2016-03-11 02:32:00 +01:00
|
|
|
if (xLen == 32) {
|
|
|
|
read_mapping += CSRs.mcycleh -> (reg_cycle >> 32)
|
|
|
|
read_mapping += CSRs.minstreth -> (reg_instret >> 32)
|
2016-08-27 05:27:27 +02:00
|
|
|
if (usingUser) {
|
|
|
|
read_mapping += CSRs.cycleh -> (reg_cycle >> 32)
|
|
|
|
read_mapping += CSRs.instreth -> (reg_instret >> 32)
|
2016-03-11 02:32:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-06 06:48:05 +02:00
|
|
|
for (i <- 0 until nCustomMrwCsrs) {
|
2016-03-03 08:29:58 +01:00
|
|
|
val addr = 0xff0 + i
|
|
|
|
require(addr < (1 << CSR.ADDRSZ))
|
2015-03-25 07:48:47 +01:00
|
|
|
require(!read_mapping.contains(addr), "custom MRW CSR address " + i + " is already in use")
|
|
|
|
read_mapping += addr -> io.custom_mrw_csrs(i)
|
|
|
|
}
|
|
|
|
|
2016-05-02 23:40:52 +02:00
|
|
|
val decoded_addr = read_mapping map { case (k, v) => k -> (io.rw.addr === k) }
|
2015-03-14 10:49:07 +01:00
|
|
|
val addr_valid = decoded_addr.values.reduce(_||_)
|
2016-08-27 05:27:27 +02:00
|
|
|
val fp_csr = if (usingFPU) decoded_addr.filterKeys(fp_csrs contains _ ).values reduce(_||_) else Bool(false)
|
|
|
|
val hpm_csr = if (usingUser) io.rw.addr >= CSR.firstCtr && io.rw.addr < CSR.firstCtr + CSR.nCtr else Bool(false)
|
|
|
|
val hpm_en = reg_debug || reg_mstatus.prv === PRV.M ||
|
|
|
|
(reg_mstatus.prv === PRV.S && reg_mscounteren(io.rw.addr(log2Ceil(CSR.nCtr)-1, 0))) ||
|
|
|
|
(reg_mstatus.prv === PRV.U && reg_mucounteren(io.rw.addr(log2Ceil(CSR.nCtr)-1, 0)))
|
2016-08-26 08:07:34 +02:00
|
|
|
val csr_addr_priv = io.rw.addr(9,8)
|
|
|
|
|
|
|
|
val debug_csr_mask = 0x090 // only debug CSRs have address bits 7 and 4 set
|
|
|
|
require((read_mapping -- debug_csrs.keys).keys.forall(x => (x & debug_csr_mask) != debug_csr_mask))
|
|
|
|
require(debug_csrs.keys.forall(x => (x & debug_csr_mask) == debug_csr_mask))
|
|
|
|
val csr_debug = Bool(usingDebug) && (io.rw.addr & debug_csr_mask) === debug_csr_mask
|
|
|
|
val priv_sufficient = reg_debug || (!csr_debug && reg_mstatus.prv >= csr_addr_priv)
|
2015-03-14 10:49:07 +01:00
|
|
|
val read_only = io.rw.addr(11,10).andR
|
2016-08-27 05:27:27 +02:00
|
|
|
val wen = cpu_wen && priv_sufficient && !read_only
|
2016-06-11 04:55:58 +02:00
|
|
|
|
2016-08-19 18:46:43 +02:00
|
|
|
val wdata = (Mux(io.rw.cmd.isOneOf(CSR.S, CSR.C), io.rw.rdata, UInt(0)) |
|
2016-06-11 04:55:58 +02:00
|
|
|
Mux(io.rw.cmd =/= CSR.C, io.rw.wdata, UInt(0))) &
|
|
|
|
~Mux(io.rw.cmd === CSR.C, io.rw.wdata, UInt(0))
|
2012-02-12 02:20:33 +01:00
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
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)
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2016-06-16 01:21:24 +02:00
|
|
|
io.csr_xcpt := (cpu_wen && read_only) ||
|
2016-09-12 21:00:04 +02:00
|
|
|
(cpu_ren && (!priv_sufficient || !addr_valid || (hpm_csr && !hpm_en) || (fp_csr && !(io.status.fs.orR && reg_misa('f'-'a'))))) ||
|
2015-03-14 10:49:07 +01:00
|
|
|
(system_insn && !priv_sufficient) ||
|
|
|
|
insn_call || insn_break
|
|
|
|
|
2015-05-19 03:23:58 +02:00
|
|
|
when (insn_wfi) { reg_wfi := true }
|
2016-07-08 00:30:43 +02:00
|
|
|
when (pending_interrupts.orR) { reg_wfi := false }
|
2016-03-03 08:29:58 +01:00
|
|
|
|
|
|
|
val cause =
|
2016-06-16 01:21:24 +02:00
|
|
|
Mux(!io.csr_xcpt, io.cause,
|
2016-03-03 08:29:58 +01:00
|
|
|
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)
|
2016-08-26 08:07:34 +02:00
|
|
|
val causeIsDebugInt = cause(xLen-1) && cause_lsbs === CSR.debugIntCause
|
|
|
|
val causeIsDebugTrigger = !cause(xLen-1) && cause_lsbs === CSR.debugTriggerCause
|
|
|
|
val causeIsDebugBreak = !cause(xLen-1) && insn_break && Cat(reg_dcsr.ebreakm, reg_dcsr.ebreakh, reg_dcsr.ebreaks, reg_dcsr.ebreaku)(reg_mstatus.prv)
|
|
|
|
val trapToDebug = Bool(usingDebug) && (reg_singleStepped || causeIsDebugInt || causeIsDebugTrigger || causeIsDebugBreak || reg_debug)
|
|
|
|
val delegate = Bool(usingVM) && reg_mstatus.prv < PRV.M && Mux(cause(xLen-1), reg_mideleg(cause_lsbs), reg_medeleg(cause_lsbs))
|
2016-06-07 05:57:22 +02:00
|
|
|
val debugTVec = Mux(reg_debug, UInt(0x808), UInt(0x800))
|
|
|
|
val tvec = Mux(trapToDebug, debugTVec, Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec))
|
2016-08-26 08:07:34 +02:00
|
|
|
val epc = Mux(csr_debug, reg_dpc, Mux(Bool(usingVM) && !csr_addr_priv(1), reg_sepc, reg_mepc))
|
2015-03-14 10:49:07 +01:00
|
|
|
io.fatc := insn_sfence_vm
|
2016-06-16 01:21:24 +02:00
|
|
|
io.evec := Mux(exception, tvec, epc)
|
2015-03-14 10:49:07 +01:00
|
|
|
io.ptbr := reg_sptbr
|
2016-03-03 08:29:58 +01:00
|
|
|
io.eret := insn_ret
|
2016-06-16 01:21:24 +02:00
|
|
|
io.singleStep := reg_dcsr.step && !reg_debug
|
2015-03-14 10:49:07 +01:00
|
|
|
io.status := reg_mstatus
|
2015-08-01 00:42:10 +02:00
|
|
|
io.status.sd := io.status.fs.andR || io.status.xs.andR
|
2016-06-02 01:57:10 +02:00
|
|
|
io.status.debug := reg_debug
|
2016-09-12 21:00:04 +02:00
|
|
|
io.status.isa := reg_misa
|
2015-03-25 07:48:47 +01:00
|
|
|
if (xLen == 32)
|
|
|
|
io.status.sd_rv32 := io.status.sd
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2016-06-16 01:21:24 +02:00
|
|
|
when (exception) {
|
2016-03-03 08:29:58 +01:00
|
|
|
val epc = ~(~io.pc | (coreInstBytes-1))
|
|
|
|
val pie = read_mstatus(reg_mstatus.prv)
|
|
|
|
|
2016-07-30 00:18:39 +02:00
|
|
|
val write_badaddr = cause isOneOf (Causes.breakpoint,
|
|
|
|
Causes.misaligned_load, Causes.misaligned_store, Causes.misaligned_fetch,
|
|
|
|
Causes.fault_load, Causes.fault_store, Causes.fault_fetch)
|
|
|
|
|
2016-06-02 01:57:10 +02:00
|
|
|
when (trapToDebug) {
|
|
|
|
reg_debug := true
|
|
|
|
reg_dpc := epc
|
2016-08-26 08:07:34 +02:00
|
|
|
reg_dcsr.cause := Mux(reg_singleStepped, 4, Mux(causeIsDebugInt, 3, Mux[UInt](causeIsDebugTrigger, 2, 1)))
|
2016-08-18 00:02:27 +02:00
|
|
|
reg_dcsr.prv := trimPrivilege(reg_mstatus.prv)
|
2016-06-02 01:57:10 +02:00
|
|
|
}.elsewhen (delegate) {
|
2016-09-12 21:00:04 +02:00
|
|
|
reg_sepc := formEPC(epc)
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_scause := cause
|
2016-07-30 00:18:39 +02:00
|
|
|
when (write_badaddr) { reg_sbadaddr := io.badaddr }
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_mstatus.spie := pie
|
|
|
|
reg_mstatus.spp := reg_mstatus.prv
|
|
|
|
reg_mstatus.sie := false
|
2016-08-18 00:02:27 +02:00
|
|
|
new_prv := PRV.S
|
2016-03-03 08:29:58 +01:00
|
|
|
}.otherwise {
|
2016-09-12 21:00:04 +02:00
|
|
|
reg_mepc := formEPC(epc)
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_mcause := cause
|
2016-07-30 00:18:39 +02:00
|
|
|
when (write_badaddr) { reg_mbadaddr := io.badaddr }
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_mstatus.mpie := pie
|
2016-08-18 00:02:27 +02:00
|
|
|
reg_mstatus.mpp := trimPrivilege(reg_mstatus.prv)
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_mstatus.mie := false
|
2016-08-18 00:02:27 +02:00
|
|
|
new_prv := PRV.M
|
2015-03-14 10:49:07 +01:00
|
|
|
}
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|
2016-08-18 00:02:27 +02:00
|
|
|
|
2015-03-14 10:49:07 +01:00
|
|
|
when (insn_ret) {
|
2016-08-26 08:07:34 +02:00
|
|
|
when (Bool(usingVM) && !csr_addr_priv(1)) {
|
2016-03-03 08:29:58 +01:00
|
|
|
when (reg_mstatus.spp.toBool) { reg_mstatus.sie := reg_mstatus.spie }
|
|
|
|
reg_mstatus.spie := false
|
|
|
|
reg_mstatus.spp := PRV.U
|
2016-08-18 00:02:27 +02:00
|
|
|
new_prv := reg_mstatus.spp
|
2016-06-02 01:57:10 +02:00
|
|
|
}.elsewhen (csr_debug) {
|
2016-08-18 00:02:27 +02:00
|
|
|
new_prv := reg_dcsr.prv
|
2016-06-02 01:57:10 +02:00
|
|
|
reg_debug := false
|
2016-03-03 08:29:58 +01:00
|
|
|
}.otherwise {
|
|
|
|
when (reg_mstatus.mpp(1)) { reg_mstatus.mie := reg_mstatus.mpie }
|
2016-05-26 00:37:32 +02:00
|
|
|
.elsewhen (Bool(usingVM) && reg_mstatus.mpp(0)) { reg_mstatus.sie := reg_mstatus.mpie }
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_mstatus.mpie := false
|
2016-08-18 00:02:27 +02:00
|
|
|
reg_mstatus.mpp := legalizePrivilege(PRV.U)
|
|
|
|
new_prv := reg_mstatus.mpp
|
2016-03-03 08:29:58 +01:00
|
|
|
}
|
2015-03-14 10:49:07 +01:00
|
|
|
}
|
|
|
|
|
2016-06-16 01:21:24 +02:00
|
|
|
assert(PopCount(insn_ret :: io.exception :: io.csr_xcpt :: Nil) <= 1, "these conditions must be mutually exclusive")
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2015-07-06 01:38:49 +02:00
|
|
|
io.time := reg_cycle
|
2015-05-19 03:23:58 +02:00
|
|
|
io.csr_stall := reg_wfi
|
2012-08-04 04:00:34 +02:00
|
|
|
|
2014-03-16 01:31:48 +01:00
|
|
|
io.rw.rdata := Mux1H(for ((k, v) <- read_mapping) yield decoded_addr(k) -> v)
|
2013-11-25 13:35:15 +01:00
|
|
|
|
|
|
|
io.fcsr_rm := reg_frm
|
|
|
|
when (io.fcsr_flags.valid) {
|
|
|
|
reg_fflags := reg_fflags | io.fcsr_flags.bits
|
|
|
|
}
|
2011-11-13 09:27:57 +01:00
|
|
|
|
2012-02-20 08:15:45 +01:00
|
|
|
when (wen) {
|
2015-03-14 10:49:07 +01:00
|
|
|
when (decoded_addr(CSRs.mstatus)) {
|
|
|
|
val new_mstatus = new MStatus().fromBits(wdata)
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_mstatus.mie := new_mstatus.mie
|
|
|
|
reg_mstatus.mpie := new_mstatus.mpie
|
2015-03-25 03:32:45 +01:00
|
|
|
|
2016-08-18 00:02:27 +02:00
|
|
|
if (usingUser) {
|
2015-05-19 03:23:58 +02:00
|
|
|
reg_mstatus.mprv := new_mstatus.mprv
|
2016-08-18 00:02:27 +02:00
|
|
|
reg_mstatus.mpp := trimPrivilege(new_mstatus.mpp)
|
|
|
|
if (usingVM) {
|
2016-07-06 04:19:49 +02:00
|
|
|
reg_mstatus.mxr := new_mstatus.mxr
|
2016-03-03 08:29:58 +01:00
|
|
|
reg_mstatus.pum := new_mstatus.pum
|
|
|
|
reg_mstatus.spp := new_mstatus.spp
|
|
|
|
reg_mstatus.spie := new_mstatus.spie
|
|
|
|
reg_mstatus.sie := new_mstatus.sie
|
2015-03-25 03:32:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-06 06:48:05 +02:00
|
|
|
if (usingVM) {
|
2016-03-30 20:01:53 +02:00
|
|
|
require(if (xLen == 32) pgLevels == 2 else pgLevels > 2 && pgLevels < 6)
|
|
|
|
val vm_on = 6 + pgLevels // TODO Sv48 support should imply Sv39 support
|
2015-05-19 03:23:58 +02:00
|
|
|
when (new_mstatus.vm === 0) { reg_mstatus.vm := 0 }
|
|
|
|
when (new_mstatus.vm === vm_on) { reg_mstatus.vm := vm_on }
|
|
|
|
}
|
2016-03-03 08:29:58 +01:00
|
|
|
if (usingVM || usingFPU) reg_mstatus.fs := Fill(2, new_mstatus.fs.orR)
|
|
|
|
if (usingRoCC) reg_mstatus.xs := Fill(2, new_mstatus.xs.orR)
|
2015-03-14 10:49:07 +01:00
|
|
|
}
|
2016-09-12 21:00:04 +02:00
|
|
|
when (decoded_addr(CSRs.misa)) {
|
|
|
|
val mask = UInt(isaStringToMask(isaMaskString))
|
|
|
|
val f = wdata('f' - 'a')
|
|
|
|
reg_misa := ~(~wdata | (!f << ('d' - 'a'))) & mask | reg_misa & ~mask
|
|
|
|
}
|
2015-05-19 03:23:58 +02:00
|
|
|
when (decoded_addr(CSRs.mip)) {
|
|
|
|
val new_mip = new MIP().fromBits(wdata)
|
2015-10-06 06:48:05 +02:00
|
|
|
if (usingVM) {
|
2015-05-19 03:23:58 +02:00
|
|
|
reg_mip.ssip := new_mip.ssip
|
2015-07-06 01:38:49 +02:00
|
|
|
reg_mip.stip := new_mip.stip
|
|
|
|
}
|
2015-11-17 06:51:43 +01:00
|
|
|
}
|
2016-03-03 08:29:58 +01:00
|
|
|
when (decoded_addr(CSRs.mie)) { reg_mie := wdata & supported_interrupts }
|
2016-09-12 21:00:04 +02:00
|
|
|
when (decoded_addr(CSRs.mepc)) { reg_mepc := formEPC(wdata) }
|
2015-03-14 10:49:07 +01:00
|
|
|
when (decoded_addr(CSRs.mscratch)) { reg_mscratch := wdata }
|
2016-03-03 08:29:58 +01:00
|
|
|
if (p(MtvecWritable))
|
|
|
|
when (decoded_addr(CSRs.mtvec)) { reg_mtvec := wdata >> 2 << 2 }
|
2015-03-14 10:49:07 +01:00
|
|
|
when (decoded_addr(CSRs.mcause)) { reg_mcause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ }
|
2015-05-19 03:23:58 +02:00
|
|
|
when (decoded_addr(CSRs.mbadaddr)) { reg_mbadaddr := wdata(vaddrBitsExtended-1,0) }
|
2016-08-27 05:27:27 +02:00
|
|
|
|
|
|
|
for (((e, c), i) <- (reg_hpmevent zip reg_hpmcounter) zipWithIndex) {
|
|
|
|
writeCounter(i + CSR.firstMHPC, c, wdata)
|
|
|
|
if (nPerfEvents > 1)
|
|
|
|
when (decoded_addr(i + CSR.firstHPE)) { e := wdata }
|
|
|
|
}
|
|
|
|
writeCounter(CSRs.mcycle, reg_cycle, wdata)
|
|
|
|
writeCounter(CSRs.minstret, reg_instret, wdata)
|
|
|
|
|
2016-03-11 02:30:56 +01:00
|
|
|
if (usingFPU) {
|
|
|
|
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 }
|
|
|
|
}
|
2016-06-02 01:57:10 +02:00
|
|
|
if (usingDebug) {
|
|
|
|
when (decoded_addr(CSRs.dcsr)) {
|
|
|
|
val new_dcsr = new DCSR().fromBits(wdata)
|
2016-06-09 21:29:26 +02:00
|
|
|
reg_dcsr.halt := new_dcsr.halt
|
2016-06-16 01:21:24 +02:00
|
|
|
reg_dcsr.step := new_dcsr.step
|
2016-06-02 01:57:10 +02:00
|
|
|
reg_dcsr.ebreakm := new_dcsr.ebreakm
|
|
|
|
if (usingVM) reg_dcsr.ebreaks := new_dcsr.ebreaks
|
|
|
|
if (usingUser) reg_dcsr.ebreaku := new_dcsr.ebreaku
|
2016-08-18 00:02:27 +02:00
|
|
|
if (usingUser) reg_dcsr.prv := trimPrivilege(new_dcsr.prv)
|
2016-06-02 01:57:10 +02:00
|
|
|
}
|
|
|
|
when (decoded_addr(CSRs.dpc)) { reg_dpc := ~(~wdata | (coreInstBytes-1)) }
|
|
|
|
when (decoded_addr(CSRs.dscratch)) { reg_dscratch := wdata }
|
|
|
|
}
|
2015-10-06 06:48:05 +02:00
|
|
|
if (usingVM) {
|
2015-03-25 03:32:45 +01:00
|
|
|
when (decoded_addr(CSRs.sstatus)) {
|
2016-03-03 08:29:58 +01:00
|
|
|
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)
|
2015-03-25 03:32:45 +01:00
|
|
|
}
|
2015-05-19 03:23:58 +02:00
|
|
|
when (decoded_addr(CSRs.sip)) {
|
|
|
|
val new_sip = new MIP().fromBits(wdata)
|
|
|
|
reg_mip.ssip := new_sip.ssip
|
|
|
|
}
|
2016-03-03 08:29:58 +01:00
|
|
|
when (decoded_addr(CSRs.sie)) { reg_mie := (reg_mie & ~reg_mideleg) | (wdata & reg_mideleg) }
|
2015-03-25 03:32:45 +01:00
|
|
|
when (decoded_addr(CSRs.sscratch)) { reg_sscratch := wdata }
|
2016-06-18 03:29:05 +02:00
|
|
|
when (decoded_addr(CSRs.sptbr)) { reg_sptbr.ppn := wdata(ppnBits-1,0) }
|
2016-09-12 21:00:04 +02:00
|
|
|
when (decoded_addr(CSRs.sepc)) { reg_sepc := formEPC(wdata) }
|
2016-03-03 08:29:58 +01:00
|
|
|
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 }
|
2016-09-29 01:10:32 +02:00
|
|
|
when (decoded_addr(CSRs.mscounteren)) { reg_mscounteren := wdata & UInt(delegable_counters) }
|
2016-08-27 05:27:27 +02:00
|
|
|
}
|
|
|
|
if (usingUser) {
|
2016-09-29 01:10:32 +02:00
|
|
|
when (decoded_addr(CSRs.mucounteren)) { reg_mucounteren := wdata & UInt(delegable_counters) }
|
2015-03-25 03:32:45 +01:00
|
|
|
}
|
2016-08-26 08:07:34 +02:00
|
|
|
if (nBreakpoints > 0) {
|
|
|
|
when (decoded_addr(CSRs.tselect)) { reg_tselect := wdata }
|
2016-06-11 04:55:58 +02:00
|
|
|
|
2016-08-26 08:07:34 +02:00
|
|
|
val bp = reg_bp(reg_tselect)
|
|
|
|
when (!bp.control.dmode || reg_debug) {
|
|
|
|
when (decoded_addr(CSRs.tdata1)) {
|
2016-06-11 04:55:58 +02:00
|
|
|
val newBPC = new BPControl().fromBits(wdata)
|
2016-08-26 08:07:34 +02:00
|
|
|
val dMode = newBPC.dmode && reg_debug
|
|
|
|
bp.control := newBPC
|
|
|
|
bp.control.dmode := dMode
|
|
|
|
bp.control.action := dMode && newBPC.action
|
2016-06-11 04:55:58 +02:00
|
|
|
}
|
2016-08-26 08:07:34 +02:00
|
|
|
when (decoded_addr(CSRs.tdata2)) { bp.address := wdata }
|
2016-06-09 05:19:52 +02:00
|
|
|
}
|
|
|
|
}
|
2012-02-12 02:20:33 +01:00
|
|
|
}
|
|
|
|
|
2016-10-05 07:28:56 +02:00
|
|
|
reg_mip <> io.interrupts
|
2016-09-14 01:25:31 +02:00
|
|
|
reg_dcsr.debugint := io.interrupts.debug
|
2016-05-02 23:40:52 +02:00
|
|
|
|
2016-10-05 07:23:20 +02:00
|
|
|
if (!usingVM) {
|
|
|
|
reg_mideleg := 0
|
|
|
|
reg_medeleg := 0
|
|
|
|
reg_mscounteren := 0
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!usingUser) {
|
|
|
|
reg_mucounteren := 0
|
|
|
|
}
|
|
|
|
|
2016-06-18 03:29:05 +02:00
|
|
|
reg_sptbr.asid := 0
|
2016-08-26 08:07:34 +02:00
|
|
|
if (nBreakpoints <= 1) reg_tselect := 0
|
|
|
|
if (nBreakpoints >= 1)
|
|
|
|
reg_bp(nBreakpoints-1).control.chain := false
|
2016-06-11 04:55:58 +02:00
|
|
|
for (bpc <- reg_bp map {_.control}) {
|
2016-08-26 08:07:34 +02:00
|
|
|
bpc.ttype := bpc.tType
|
|
|
|
bpc.maskmax := bpc.maskMax
|
2016-06-10 04:07:10 +02:00
|
|
|
bpc.reserved := 0
|
2016-08-26 08:07:34 +02:00
|
|
|
bpc.zero := 0
|
2016-06-09 05:19:52 +02:00
|
|
|
bpc.h := false
|
|
|
|
if (!usingVM) bpc.s := false
|
|
|
|
if (!usingUser) bpc.u := false
|
|
|
|
if (!usingVM && !usingUser) bpc.m := true
|
|
|
|
when (reset) {
|
2016-08-26 08:07:34 +02:00
|
|
|
bpc.action := false
|
|
|
|
bpc.dmode := false
|
2016-06-09 05:19:52 +02:00
|
|
|
bpc.r := false
|
|
|
|
bpc.w := false
|
|
|
|
bpc.x := false
|
|
|
|
}
|
|
|
|
}
|
2016-08-26 08:07:34 +02:00
|
|
|
for (bp <- reg_bp drop nBreakpoints)
|
2016-06-11 04:55:58 +02:00
|
|
|
bp := new BP().fromBits(0)
|
2016-08-18 00:02:27 +02:00
|
|
|
|
|
|
|
def legalizePrivilege(priv: UInt): UInt =
|
|
|
|
if (usingVM) Mux(priv === PRV.H, PRV.U, priv)
|
|
|
|
else if (usingUser) Fill(2, priv(0))
|
|
|
|
else PRV.M
|
|
|
|
|
|
|
|
def trimPrivilege(priv: UInt): UInt =
|
|
|
|
if (usingVM) priv
|
|
|
|
else legalizePrivilege(priv)
|
2016-08-27 05:27:27 +02:00
|
|
|
|
|
|
|
def writeCounter(lo: Int, ctr: WideCounter, wdata: UInt) = {
|
|
|
|
if (xLen == 32) {
|
|
|
|
val hi = lo + CSRs.mcycleh - CSRs.mcycle
|
|
|
|
when (decoded_addr(lo)) { ctr := Cat(ctr(63, 32), wdata) }
|
|
|
|
when (decoded_addr(hi)) { ctr := Cat(wdata, ctr(31, 0)) }
|
|
|
|
} else {
|
|
|
|
when (decoded_addr(lo)) { ctr := wdata }
|
|
|
|
}
|
|
|
|
}
|
2016-09-12 21:00:04 +02:00
|
|
|
def formEPC(x: UInt) = ~(~x | Cat(!reg_misa('c'-'a'), UInt(1)))
|
|
|
|
def isaStringToMask(s: String) = s.map(x => 1 << (x - 'A')).reduce(_|_)
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|