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
|
|
|
|
2017-03-22 22:38:33 +01:00
|
|
|
import collection.mutable.LinkedHashMap
|
|
|
|
|
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)
|
|
|
|
|
2017-03-15 23:21:13 +01:00
|
|
|
val dprv = UInt(width = PRV.SZ) // effective privilege for data accesses
|
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-03-27 06:56:35 +02:00
|
|
|
val zero2 = UInt(width = 31)
|
2016-03-03 08:29:58 +01:00
|
|
|
val sd_rv32 = Bool()
|
2017-03-13 22:49:46 +01:00
|
|
|
val zero1 = UInt(width = 8)
|
|
|
|
val tsr = Bool()
|
2017-02-27 23:27:19 +01:00
|
|
|
val tw = Bool()
|
|
|
|
val tvm = Bool()
|
2016-07-06 04:19:49 +02:00
|
|
|
val mxr = Bool()
|
2017-03-20 05:38:50 +01:00
|
|
|
val sum = 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)
|
|
|
|
}
|
|
|
|
|
2017-03-24 22:49:12 +01:00
|
|
|
class MIP(implicit p: Parameters) extends CoreBundle()(p)
|
|
|
|
with HasRocketCoreParameters {
|
|
|
|
val lip = Vec(coreParams.nLocalInterrupts, Bool())
|
|
|
|
val zero2 = Bool()
|
|
|
|
val debug = Bool() // keep in sync with CSR.debugIntCause
|
|
|
|
val zero1 = Bool()
|
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-03-24 22:49:12 +01:00
|
|
|
def debugIntCause = 14 // keep in sync with MIP.debug
|
2017-01-31 23:45:11 +01:00
|
|
|
def debugTriggerCause = {
|
2017-03-24 22:49:12 +01:00
|
|
|
val res = debugIntCause
|
2017-03-27 03:18:35 +02:00
|
|
|
require(!(Causes.all contains res))
|
|
|
|
res
|
2016-08-26 08:07:34 +02:00
|
|
|
}
|
2016-08-27 05:27:27 +02:00
|
|
|
|
|
|
|
val firstCtr = CSRs.cycle
|
2017-03-09 09:28:19 +01:00
|
|
|
val firstCtrH = CSRs.cycleh
|
2017-02-27 23:27:19 +01:00
|
|
|
val firstHPC = CSRs.hpmcounter3
|
2017-03-09 09:28:19 +01:00
|
|
|
val firstHPCH = CSRs.hpmcounter3h
|
2017-02-27 23:27:19 +01:00
|
|
|
val firstHPE = CSRs.mhpmevent3
|
|
|
|
val firstMHPC = CSRs.mhpmcounter3
|
2017-03-09 09:28:19 +01:00
|
|
|
val firstMHPCH = CSRs.mhpmcounter3h
|
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
|
2017-03-30 07:20:58 +02:00
|
|
|
|
|
|
|
val maxPMPs = 16
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|
|
|
|
|
2017-03-09 09:28:19 +01:00
|
|
|
class PerfCounterIO(implicit p: Parameters) extends CoreBundle
|
|
|
|
with HasRocketCoreParameters {
|
|
|
|
val eventSel = UInt(OUTPUT, xLen)
|
|
|
|
val inc = UInt(INPUT, log2Ceil(1+retireWidth))
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-03-07 23:33:51 +01:00
|
|
|
val decode = new Bundle {
|
|
|
|
val csr = UInt(INPUT, CSR.ADDRSZ)
|
|
|
|
val fp_illegal = Bool(OUTPUT)
|
|
|
|
val rocc_illegal = Bool(OUTPUT)
|
|
|
|
val read_illegal = Bool(OUTPUT)
|
|
|
|
val write_illegal = Bool(OUTPUT)
|
|
|
|
val write_flush = Bool(OUTPUT)
|
|
|
|
val system_illegal = Bool(OUTPUT)
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:23:58 +02:00
|
|
|
val csr_stall = 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)
|
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
|
2017-03-15 09:18:39 +01:00
|
|
|
val pmp = Vec(nPMPs, new PMP).asOutput
|
2017-03-09 09:28:19 +01:00
|
|
|
val counters = Vec(nPerfCounters, new PerfCounterIO)
|
2014-05-10 04:26:43 +02:00
|
|
|
}
|
|
|
|
|
2017-03-09 09:28:19 +01:00
|
|
|
class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(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) = {
|
2017-03-24 22:49:12 +01:00
|
|
|
val sup = Wire(new MIP)
|
|
|
|
sup.usip := false
|
2016-08-26 08:07:34 +02:00
|
|
|
sup.ssip := Bool(usingVM)
|
2017-03-24 22:49:12 +01:00
|
|
|
sup.hsip := false
|
2016-03-03 08:29:58 +01:00
|
|
|
sup.msip := true
|
2017-03-24 22:49:12 +01:00
|
|
|
sup.utip := false
|
2016-08-26 08:07:34 +02:00
|
|
|
sup.stip := Bool(usingVM)
|
2017-03-24 22:49:12 +01:00
|
|
|
sup.htip := false
|
2016-03-03 08:29:58 +01:00
|
|
|
sup.mtip := true
|
2017-03-24 22:49:12 +01:00
|
|
|
sup.ueip := false
|
2016-08-26 08:07:34 +02:00
|
|
|
sup.seip := Bool(usingVM)
|
2017-03-24 22:49:12 +01:00
|
|
|
sup.heip := false
|
|
|
|
sup.meip := true
|
2016-03-03 08:29:58 +01:00
|
|
|
sup.rocc := usingRoCC
|
2017-03-24 22:49:12 +01:00
|
|
|
sup.zero1 := false
|
|
|
|
sup.debug := false
|
|
|
|
sup.zero2 := false
|
|
|
|
sup.lip foreach { _ := true }
|
2016-03-03 08:29:58 +01:00
|
|
|
|
|
|
|
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,
|
2017-03-27 03:18:35 +02:00
|
|
|
Causes.fetch_page_fault,
|
2016-03-03 08:29:58 +01:00
|
|
|
Causes.breakpoint,
|
2017-03-27 03:18:35 +02:00
|
|
|
Causes.load_page_fault,
|
|
|
|
Causes.store_page_fault,
|
2016-03-03 08:29:58 +01:00
|
|
|
Causes.user_ecall).map(1 << _).sum)
|
|
|
|
|
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())
|
|
|
|
|
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))
|
2017-03-20 13:21:50 +01:00
|
|
|
val reg_pmp = Reg(Vec(nPMPs, new PMPReg))
|
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)
|
2017-03-09 09:28:19 +01:00
|
|
|
val reg_hpmevent = io.counters.map(c => Reg(init = UInt(0, xLen)))
|
|
|
|
(io.counters zip reg_hpmevent) foreach { case (c, e) => c.eventSel := e }
|
|
|
|
val reg_hpmcounter = io.counters.map(c => WideCounter(40, c.inc, reset = false))
|
2017-03-07 23:33:51 +01:00
|
|
|
val hpm_mask = reg_mcounteren & Mux((!usingVM).B || reg_mstatus.prv === PRV.S, delegable_counters.U, reg_scounteren)
|
2016-03-11 02:32:00 +01:00
|
|
|
|
2016-03-03 08:29:58 +01:00
|
|
|
val mip = Wire(init=reg_mip)
|
2017-03-28 01:35:47 +02:00
|
|
|
// seip is the OR of reg_mip.seip and the actual line from the PLIC
|
|
|
|
io.interrupts.seip.foreach { mip.seip := reg_mip.seip || RegNext(_) }
|
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
|
2017-03-20 13:21:50 +01:00
|
|
|
io.pmp := reg_pmp.map(PMP(_))
|
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
|
|
|
|
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
|
|
|
|
2017-03-22 22:38:33 +01:00
|
|
|
val read_mapping = 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,
|
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
|
|
|
|
2017-03-22 22:38:33 +01:00
|
|
|
val debug_csrs = LinkedHashMap[Int,Bits](
|
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)
|
|
|
|
|
2017-03-22 22:38:33 +01:00
|
|
|
val fp_csrs = LinkedHashMap[Int,Bits](
|
2016-08-27 05:27:27 +02:00
|
|
|
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
|
2017-03-09 09:28:19 +01:00
|
|
|
if (xLen == 32) {
|
|
|
|
read_mapping += (i + CSR.firstMHPCH) -> c // mhpmcounterNh
|
|
|
|
if (usingUser) read_mapping += (i + CSR.firstHPCH) -> c // hpmcounterNh
|
|
|
|
}
|
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
|
2017-03-20 08:19:38 +01:00
|
|
|
val read_sstatus = Wire(init = 0.U.asTypeOf(new MStatus))
|
|
|
|
read_sstatus.sd := io.status.sd
|
|
|
|
read_sstatus.sd_rv32 := io.status.sd_rv32
|
|
|
|
read_sstatus.mxr := io.status.mxr
|
|
|
|
read_sstatus.sum := io.status.sum
|
|
|
|
read_sstatus.xs := io.status.xs
|
|
|
|
read_sstatus.fs := io.status.fs
|
|
|
|
read_sstatus.spp := io.status.spp
|
|
|
|
read_sstatus.spie := io.status.spie
|
|
|
|
read_sstatus.sie := io.status.sie
|
2016-03-03 08:29:58 +01:00
|
|
|
|
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
|
2017-03-20 13:47:35 +01:00
|
|
|
read_mapping += CSRs.mideleg -> reg_mideleg
|
|
|
|
read_mapping += CSRs.medeleg -> reg_medeleg
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-15 09:18:39 +01:00
|
|
|
val pmpCfgPerCSR = xLen / new PMPConfig().getWidth
|
|
|
|
def pmpCfgIndex(i: Int) = (xLen / 32) * (i / pmpCfgPerCSR)
|
2017-03-30 07:20:58 +02:00
|
|
|
if (reg_pmp.nonEmpty) {
|
|
|
|
require(reg_pmp.size <= CSR.maxPMPs)
|
|
|
|
val read_pmp = reg_pmp.padTo(CSR.maxPMPs, 0.U.asTypeOf(new PMP))
|
|
|
|
for (i <- 0 until read_pmp.size by pmpCfgPerCSR)
|
|
|
|
read_mapping += (CSRs.pmpcfg0 + pmpCfgIndex(i)) -> read_pmp.map(_.cfg).slice(i, i + pmpCfgPerCSR).asUInt
|
|
|
|
for ((pmp, i) <- read_pmp zipWithIndex)
|
|
|
|
read_mapping += (CSRs.pmpaddr0 + i) -> pmp.addr
|
|
|
|
}
|
2017-03-15 09:18:39 +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) }
|
2017-03-28 01:35:47 +02:00
|
|
|
val wdata = readModifyWriteCSR(io.rw.cmd, io.rw.rdata, io.rw.wdata)
|
2012-02-12 02:20:33 +01:00
|
|
|
|
2017-03-07 23:33:51 +01:00
|
|
|
val system_insn = io.rw.cmd === CSR.I
|
2016-03-03 08:29:58 +01:00
|
|
|
val opcode = UInt(1) << io.rw.addr(2,0)
|
2017-03-14 21:54:49 +01:00
|
|
|
val insn_call = system_insn && opcode(0)
|
2017-03-07 23:33:51 +01:00
|
|
|
val insn_break = system_insn && opcode(1)
|
|
|
|
val insn_ret = system_insn && opcode(2)
|
|
|
|
val insn_wfi = system_insn && opcode(5)
|
|
|
|
|
2017-03-22 22:38:33 +01:00
|
|
|
private def decodeAny(m: LinkedHashMap[Int,Bits]): Bool = m.map { case(k: Int, _: Bits) => io.decode.csr === k }.reduce(_||_)
|
2017-03-14 22:37:09 +01:00
|
|
|
val allow_wfi = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tw
|
|
|
|
val allow_sfence_vma = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tvm
|
|
|
|
val allow_sret = Bool(!usingVM) || reg_mstatus.prv > PRV.S || !reg_mstatus.tsr
|
2017-03-07 23:33:51 +01:00
|
|
|
io.decode.fp_illegal := io.status.fs === 0 || !reg_misa('f'-'a')
|
|
|
|
io.decode.rocc_illegal := io.status.xs === 0 || !reg_misa('x'-'a')
|
2017-03-14 22:37:09 +01:00
|
|
|
io.decode.read_illegal := reg_mstatus.prv < io.decode.csr(9,8) ||
|
2017-03-22 22:38:33 +01:00
|
|
|
!decodeAny(read_mapping) ||
|
2017-03-07 23:33:51 +01:00
|
|
|
io.decode.csr === CSRs.sptbr && !allow_sfence_vma ||
|
2017-03-14 22:37:09 +01:00
|
|
|
(io.decode.csr.inRange(CSR.firstCtr, CSR.firstCtr + CSR.nCtr) || io.decode.csr.inRange(CSR.firstCtrH, CSR.firstCtrH + CSR.nCtr)) && reg_mstatus.prv <= PRV.S && hpm_mask(io.decode.csr(log2Ceil(CSR.firstCtr)-1,0)) ||
|
2017-03-22 22:38:33 +01:00
|
|
|
Bool(usingDebug) && decodeAny(debug_csrs) && !reg_debug ||
|
|
|
|
Bool(usingFPU) && decodeAny(fp_csrs) && io.decode.fp_illegal
|
2017-03-07 23:33:51 +01:00
|
|
|
io.decode.write_illegal := io.decode.csr(11,10).andR
|
|
|
|
io.decode.write_flush := !(io.decode.csr >= CSRs.mscratch && io.decode.csr <= CSRs.mbadaddr || io.decode.csr >= CSRs.sscratch && io.decode.csr <= CSRs.sbadaddr)
|
2017-03-14 22:37:09 +01:00
|
|
|
io.decode.system_illegal := reg_mstatus.prv < io.decode.csr(9,8) ||
|
2017-03-13 22:49:46 +01:00
|
|
|
!io.decode.csr(5) && io.decode.csr(2) && !allow_wfi ||
|
|
|
|
!io.decode.csr(5) && io.decode.csr(1) && !allow_sret ||
|
2017-03-07 23:33:51 +01:00
|
|
|
io.decode.csr(5) && !allow_sfence_vma
|
2016-03-03 08:29:58 +01:00
|
|
|
|
|
|
|
val cause =
|
|
|
|
Mux(insn_call, reg_mstatus.prv + Causes.user_ecall,
|
2017-03-07 23:33:51 +01:00
|
|
|
Mux[UInt](insn_break, Causes.breakpoint, io.cause))
|
2016-03-03 08:29:58 +01:00
|
|
|
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))
|
2017-03-07 23:33:51 +01:00
|
|
|
io.evec := tvec
|
2015-03-14 10:49:07 +01:00
|
|
|
io.ptbr := reg_sptbr
|
2017-03-07 23:33:51 +01:00
|
|
|
io.eret := insn_call || insn_break || 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-03-23 01:18:04 +01:00
|
|
|
io.status.dprv := Reg(next = Mux(reg_mstatus.mprv && !reg_debug, reg_mstatus.mpp, reg_mstatus.prv))
|
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
|
|
|
|
2017-03-07 23:33:51 +01:00
|
|
|
val exception = insn_call || insn_break || io.exception
|
|
|
|
assert(PopCount(insn_ret :: insn_call :: insn_break :: io.exception :: Nil) <= 1, "these conditions must be mutually exclusive")
|
|
|
|
|
|
|
|
when (insn_wfi) { reg_wfi := true }
|
|
|
|
when (pending_interrupts.orR || exception) { reg_wfi := false }
|
|
|
|
assert(!reg_wfi || io.retire === UInt(0))
|
|
|
|
|
|
|
|
when (io.retire(0)) { reg_singleStepped := true }
|
|
|
|
when (!io.singleStep) { reg_singleStepped := false }
|
|
|
|
assert(!io.singleStep || io.retire <= UInt(1))
|
|
|
|
assert(!reg_singleStepped || io.retire === UInt(0))
|
|
|
|
|
2016-06-16 01:21:24 +02:00
|
|
|
when (exception) {
|
2016-03-03 08:29:58 +01:00
|
|
|
val epc = ~(~io.pc | (coreInstBytes-1))
|
|
|
|
|
2017-03-28 07:06:52 +02:00
|
|
|
val write_badaddr = cause isOneOf (Causes.illegal_instruction, Causes.breakpoint,
|
2016-07-30 00:18:39 +02:00
|
|
|
Causes.misaligned_load, Causes.misaligned_store, Causes.misaligned_fetch,
|
2017-03-27 03:18:35 +02:00
|
|
|
Causes.load_access, Causes.store_access, Causes.fetch_access,
|
2017-03-28 07:06:52 +02:00
|
|
|
Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault)
|
2016-07-30 00:18:39 +02:00
|
|
|
|
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)
|
2017-03-14 22:37:09 +01:00
|
|
|
new_prv := PRV.M
|
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 }
|
2017-03-16 20:54:08 +01:00
|
|
|
reg_mstatus.spie := reg_mstatus.sie
|
2016-03-03 08:29:58 +01:00
|
|
|
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 }
|
2017-03-16 20:54:08 +01:00
|
|
|
reg_mstatus.mpie := reg_mstatus.mie
|
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) {
|
2017-03-07 23:33:51 +01:00
|
|
|
when (Bool(usingVM) && !io.rw.addr(9)) {
|
2017-03-16 20:54:08 +01:00
|
|
|
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
|
2017-03-07 23:33:51 +01:00
|
|
|
io.evec := reg_sepc
|
|
|
|
}.elsewhen (Bool(usingDebug) && io.rw.addr(10)) {
|
2016-08-18 00:02:27 +02:00
|
|
|
new_prv := reg_dcsr.prv
|
2016-06-02 01:57:10 +02:00
|
|
|
reg_debug := false
|
2017-03-07 23:33:51 +01:00
|
|
|
io.evec := reg_dpc
|
2016-03-03 08:29:58 +01:00
|
|
|
}.otherwise {
|
2017-03-16 20:54:08 +01:00
|
|
|
reg_mstatus.mie := 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
|
2017-03-07 23:33:51 +01:00
|
|
|
io.evec := reg_mepc
|
2016-03-03 08:29:58 +01:00
|
|
|
}
|
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
|
|
|
|
2017-03-07 23:33:51 +01:00
|
|
|
when (io.rw.cmd.isOneOf(CSR.S, CSR.C, CSR.W)) {
|
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) {
|
2017-03-20 08:19:38 +01:00
|
|
|
reg_mstatus.mxr := new_mstatus.mxr
|
2017-03-20 05:38:50 +01:00
|
|
|
reg_mstatus.sum := new_mstatus.sum
|
2016-03-03 08:29:58 +01:00
|
|
|
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
|
2017-03-13 22:49:46 +01:00
|
|
|
reg_mstatus.tsr := new_mstatus.tsr
|
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)) {
|
2017-03-27 06:56:35 +02:00
|
|
|
val mask = UInt(isaStringToMask(isaMaskString), xLen)
|
2016-09-12 21:00:04 +02:00
|
|
|
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)) {
|
2017-03-28 01:35:47 +02:00
|
|
|
// MIP should be modified based on the value in reg_mip, not the value
|
|
|
|
// in read_mip, since read_mip.seip is the OR of reg_mip.seip and
|
|
|
|
// io.interrupts.seip. We don't want the value on the PLIC line to
|
|
|
|
// inadvertently be OR'd into read_mip.seip.
|
|
|
|
val new_mip = readModifyWriteCSR(io.rw.cmd, reg_mip.asUInt, io.rw.wdata).asTypeOf(new MIP)
|
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
|
2017-03-28 01:35:47 +02:00
|
|
|
reg_mip.seip := new_mip.seip
|
2015-07-06 01:38:49 +02:00
|
|
|
}
|
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)
|
2017-03-09 09:28:19 +01:00
|
|
|
when (decoded_addr(i + CSR.firstHPE)) { e := perfEventSets.maskEventSelector(wdata) }
|
2016-08-27 05:27:27 +02:00
|
|
|
}
|
|
|
|
writeCounter(CSRs.mcycle, reg_cycle, wdata)
|
|
|
|
writeCounter(CSRs.minstret, reg_instret, wdata)
|
|
|
|
|
2017-03-07 23:33:51 +01:00
|
|
|
if (usingFPU) {
|
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
|
2017-03-20 08:19:38 +01:00
|
|
|
reg_mstatus.mxr := new_sstatus.mxr
|
2017-03-20 05:38:50 +01:00
|
|
|
reg_mstatus.sum := new_sstatus.sum
|
2016-03-03 08:29:58 +01:00
|
|
|
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-03-07 23:33:51 +01:00
|
|
|
when (decoded_addr(CSRs.sptbr)) {
|
2017-02-27 23:27:19 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2017-03-24 23:55:51 +01:00
|
|
|
if (reg_pmp.nonEmpty) for (((pmp, next), i) <- (reg_pmp zip (reg_pmp.tail :+ reg_pmp.last)) zipWithIndex) {
|
2017-03-15 09:18:39 +01:00
|
|
|
require(xLen % pmp.cfg.getWidth == 0)
|
|
|
|
when (decoded_addr(CSRs.pmpcfg0 + pmpCfgIndex(i)) && !pmp.locked) {
|
|
|
|
pmp.cfg := new PMPConfig().fromBits(wdata >> ((i * pmp.cfg.getWidth) % xLen))
|
|
|
|
}
|
|
|
|
when (decoded_addr(CSRs.pmpaddr0 + i) && !pmp.addrLocked(next)) {
|
|
|
|
pmp.addr := wdata
|
|
|
|
}
|
|
|
|
}
|
2012-02-12 02:20:33 +01:00
|
|
|
}
|
|
|
|
|
2017-03-28 02:53:48 +02:00
|
|
|
reg_mip.lip := (io.interrupts.lip: Seq[Bool])
|
2017-03-28 01:35:47 +02:00
|
|
|
reg_mip.mtip := io.interrupts.mtip
|
|
|
|
reg_mip.msip := io.interrupts.msip
|
|
|
|
reg_mip.meip := io.interrupts.meip
|
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)
|
2017-03-15 09:18:39 +01:00
|
|
|
if (reg_pmp.nonEmpty) {
|
|
|
|
for (pmp <- reg_pmp) {
|
|
|
|
if (!usingUser) pmp.cfg.m := true
|
|
|
|
when (reset) { pmp.cfg.p := 0 }
|
|
|
|
}
|
|
|
|
}
|
2016-08-18 00:02:27 +02:00
|
|
|
|
2017-03-28 01:35:47 +02:00
|
|
|
def readModifyWriteCSR(cmd: UInt, rdata: UInt, wdata: UInt) =
|
|
|
|
(Mux(cmd.isOneOf(CSR.S, CSR.C), rdata, UInt(0)) | wdata) & ~Mux(cmd === CSR.C, wdata, UInt(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
|
2017-03-09 09:28:19 +01:00
|
|
|
when (decoded_addr(lo)) { ctr := Cat(ctr(ctr.getWidth-1, 32), wdata) }
|
|
|
|
when (decoded_addr(hi)) { ctr := Cat(wdata(ctr.getWidth-33, 0), ctr(31, 0)) }
|
2016-08-27 05:27:27 +02:00
|
|
|
} else {
|
2017-03-09 09:28:19 +01:00
|
|
|
when (decoded_addr(lo)) { ctr := wdata(ctr.getWidth-1, 0) }
|
2016-08-27 05:27:27 +02:00
|
|
|
}
|
|
|
|
}
|
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
|
|
|
}
|