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._
|
2017-02-09 22:59:09 +01:00
|
|
|
import tile._
|
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()
|
2017-02-27 23:27:19 +01:00
|
|
|
val zero2 = UInt(width = 27)
|
|
|
|
val sxl = UInt(width = 2)
|
|
|
|
val uxl = UInt(width = 2)
|
2016-03-03 08:29:58 +01:00
|
|
|
val sd_rv32 = Bool()
|
2017-02-27 23:27:19 +01:00
|
|
|
val zero1 = UInt(width = 9)
|
|
|
|
val tw = Bool()
|
|
|
|
val tvm = Bool()
|
2016-07-06 04:19:49 +02:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
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) {
|
2017-02-27 23:27:19 +01:00
|
|
|
def pgLevelsToMode(i: Int) = (xLen, i) match {
|
|
|
|
case (32, 2) => 1
|
|
|
|
case (64, x) if x >= 3 && x <= 6 => x + 5
|
|
|
|
}
|
|
|
|
val (modeBits, maxASIdBits) = xLen match {
|
|
|
|
case 32 => (1, 9)
|
|
|
|
case 64 => (4, 16)
|
|
|
|
}
|
|
|
|
require(modeBits + maxASIdBits + maxPAddrBits - pgIdxBits == xLen)
|
|
|
|
|
|
|
|
val mode = UInt(width = modeBits)
|
|
|
|
val asid = UInt(width = maxASIdBits)
|
2016-06-18 03:29:05 +02:00
|
|
|
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
|
2017-02-27 23:27:19 +01:00
|
|
|
val firstHPC = CSRs.hpmcounter3
|
|
|
|
val firstHPE = CSRs.mhpmevent3
|
|
|
|
val firstMHPC = CSRs.mhpmcounter3
|
2016-08-27 05:27:27 +02:00
|
|
|
val firstHPM = 3
|
2017-02-27 23:27:19 +01:00
|
|
|
val nCtr = 32
|
|
|
|
val nHPM = nCtr - firstHPM
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|
|
|
|
|
2017-02-09 22:59:09 +01:00
|
|
|
class CSRFileIO(implicit p: Parameters) extends CoreBundle
|
|
|
|
with HasRocketCoreParameters {
|
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)
|
2017-02-09 22:59:09 +01:00
|
|
|
with HasRocketCoreParameters {
|
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))
|
2017-02-27 23:27:19 +01:00
|
|
|
val effective_prv = Cat(reg_debug, reg_mstatus.prv)
|
2016-06-02 01:57:10 +02:00
|
|
|
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
|
2017-02-09 22:59:09 +01:00
|
|
|
val reg_mtvec = mtvecInit match {
|
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
|
|
|
case Some(addr) => Reg(init=UInt(addr, mtvecWidth))
|
|
|
|
case None => Reg(UInt(width = mtvecWidth))
|
|
|
|
}
|
2017-02-27 23:27:19 +01:00
|
|
|
val reg_mcounteren = Reg(UInt(width = 32))
|
|
|
|
val reg_scounteren = Reg(UInt(width = 32))
|
2016-08-27 05:27:27 +02:00
|
|
|
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
|
2017-02-27 23:27:19 +01:00
|
|
|
val m_interrupts = Mux(reg_mstatus.prv <= PRV.S || (reg_mstatus.prv === PRV.M && reg_mstatus.mie), pending_interrupts & ~reg_mideleg, UInt(0))
|
|
|
|
val s_interrupts = Mux(m_interrupts === 0 && (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)
|
2017-02-27 23:27:19 +01:00
|
|
|
io.interrupt := all_interrupts.orR && !reg_debug && !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.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)
|
2017-02-27 23:27:19 +01:00
|
|
|
read_mapping += CSRs.scounteren -> reg_scounteren
|
2016-08-27 05:27:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (usingUser) {
|
2017-02-27 23:27:19 +01:00
|
|
|
read_mapping += CSRs.mcounteren -> reg_mcounteren
|
2016-08-27 05:27:27 +02:00
|
|
|
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)
|
2017-02-27 23:27:19 +01:00
|
|
|
val hpm_en = effective_prv > PRV.S || (reg_mcounteren & Mux((!usingVM).B || reg_mstatus.prv === PRV.S, delegable_counters.U, reg_scounteren))(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
|
|
|
|
2017-02-27 23:27:19 +01:00
|
|
|
val wdata = (Mux(io.rw.cmd.isOneOf(CSR.S, CSR.C), io.rw.rdata, UInt(0)) | io.rw.wdata) &
|
2016-06-11 04:55:58 +02:00
|
|
|
~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)
|
2017-02-27 23:27:19 +01:00
|
|
|
val insn_rs2 = io.rw.addr(5)
|
|
|
|
val insn_call = do_system_insn && !insn_rs2 && opcode(0)
|
2016-03-03 08:29:58 +01:00
|
|
|
val insn_break = do_system_insn && opcode(1)
|
|
|
|
val insn_ret = do_system_insn && opcode(2)
|
2017-02-27 23:27:19 +01:00
|
|
|
val allow_wfi = effective_prv > PRV.S || !reg_mstatus.tw
|
|
|
|
val want_wfi = do_system_insn && opcode(5)
|
|
|
|
val insn_wfi = want_wfi && allow_wfi
|
|
|
|
val allow_sfence_vma = effective_prv > PRV.S || !reg_mstatus.tvm
|
|
|
|
val want_sfence_vma = do_system_insn && insn_rs2
|
|
|
|
val insn_sfence_vma = want_sfence_vma && allow_sfence_vma
|
|
|
|
val allow_fcsr = io.status.fs.orR && reg_misa('f'-'a')
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2016-06-16 01:21:24 +02:00
|
|
|
io.csr_xcpt := (cpu_wen && read_only) ||
|
2017-02-27 23:27:19 +01:00
|
|
|
(cpu_ren &&
|
|
|
|
(!priv_sufficient ||
|
|
|
|
!addr_valid ||
|
|
|
|
(if (usingVM) decoded_addr(CSRs.sptbr) && !allow_sfence_vma else false.B) ||
|
|
|
|
(hpm_csr && !hpm_en) ||
|
|
|
|
(fp_csr && !allow_fcsr))) ||
|
2015-03-14 10:49:07 +01:00
|
|
|
(system_insn && !priv_sufficient) ||
|
2017-02-27 23:27:19 +01:00
|
|
|
insn_call || insn_break ||
|
|
|
|
want_wfi && !allow_wfi ||
|
|
|
|
want_sfence_vma && !allow_sfence_vma
|
2015-03-14 10:49:07 +01:00
|
|
|
|
2015-05-19 03:23:58 +02:00
|
|
|
when (insn_wfi) { reg_wfi := true }
|
2017-02-27 23:27:19 +01:00
|
|
|
when (pending_interrupts.orR || exception) { 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)
|
2017-02-27 23:27:19 +01:00
|
|
|
val delegate = Bool(usingVM) && reg_mstatus.prv <= PRV.S && 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))
|
2017-02-27 23:27:19 +01:00
|
|
|
io.fatc := insn_sfence_vma
|
|
|
|
io.evec := Mux(insn_ret, epc, tvec)
|
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
|
2017-02-27 23:27:19 +01:00
|
|
|
io.status.uxl := (if (usingUser) log2Ceil(xLen) - 4 else 0)
|
|
|
|
io.status.sxl := (if (usingVM) log2Ceil(xLen) - 4 else 0)
|
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 }
|
2017-02-02 07:40:01 +01:00
|
|
|
reg_mstatus.spie := true
|
2016-03-03 08:29:58 +01:00
|
|
|
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 }
|
2017-02-02 07:40:01 +01:00
|
|
|
reg_mstatus.mpie := true
|
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)
|
2017-02-27 23:27:19 +01:00
|
|
|
reg_mstatus.mxr := new_mstatus.mxr
|
2016-08-18 00:02:27 +02:00
|
|
|
if (usingVM) {
|
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
|
2017-02-27 23:27:19 +01:00
|
|
|
reg_mstatus.tw := new_mstatus.tw
|
|
|
|
reg_mstatus.tvm := new_mstatus.tvm
|
2015-03-25 03:32:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 }
|
2017-02-09 22:59:09 +01:00
|
|
|
if (mtvecWritable)
|
2016-03-03 08:29:58 +01:00
|
|
|
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)
|
|
|
|
|
2017-02-27 23:27:19 +01:00
|
|
|
if (usingFPU) when (allow_fcsr) {
|
2016-03-11 02:30:56 +01:00
|
|
|
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
|
|
|
|
}
|
2017-02-27 23:27:19 +01:00
|
|
|
when (decoded_addr(CSRs.sptbr) && allow_sfence_vma) {
|
|
|
|
val new_sptbr = new PTBR().fromBits(wdata)
|
|
|
|
val valid_mode = new_sptbr.pgLevelsToMode(pgLevels)
|
|
|
|
when (new_sptbr.mode === 0) { reg_sptbr.mode := 0 }
|
|
|
|
when (new_sptbr.mode === valid_mode) { reg_sptbr.mode := valid_mode }
|
|
|
|
when (new_sptbr.mode === 0 || new_sptbr.mode === valid_mode) {
|
|
|
|
reg_sptbr.ppn := new_sptbr.ppn(ppnBits-1,0)
|
|
|
|
if (asIdBits > 0) reg_sptbr.asid := new_sptbr.asid(asIdBits-1,0)
|
|
|
|
}
|
|
|
|
}
|
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-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 }
|
2017-02-27 23:27:19 +01:00
|
|
|
when (decoded_addr(CSRs.scounteren)) { reg_scounteren := wdata & UInt(delegable_counters) }
|
2016-08-27 05:27:27 +02:00
|
|
|
}
|
|
|
|
if (usingUser) {
|
2017-02-27 23:27:19 +01:00
|
|
|
when (decoded_addr(CSRs.mcounteren)) { reg_mcounteren := 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
|
2017-02-27 23:27:19 +01:00
|
|
|
reg_scounteren := 0
|
2016-10-05 07:23:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!usingUser) {
|
2017-02-27 23:27:19 +01:00
|
|
|
reg_mcounteren := 0
|
2016-10-05 07:23:20 +02:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|