1
0
Fork 0
rocket-chip/src/main/scala/rocket/CSR.scala

849 lines
31 KiB
Scala
Raw Normal View History

// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
2014-09-13 03:06:41 +02:00
package freechips.rocketchip.rocket
2012-10-08 05:15:54 +02:00
import Chisel._
import Chisel.ImplicitConversions._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.tile._
import freechips.rocketchip.util._
import freechips.rocketchip.util.property._
import scala.collection.mutable.LinkedHashMap
import Instructions._
2015-03-14 10:49:07 +01:00
class MStatus extends Bundle {
// not truly part of mstatus, but convenient
val debug = Bool()
val isa = UInt(width = 32)
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()
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-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 zero4 = UInt(width=2)
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 zero1 = UInt(width=3)
2016-06-02 01:57:10 +02:00
val step = Bool()
val prv = UInt(width = PRV.SZ)
}
class MIP(implicit p: Parameters) extends CoreBundle()(p)
with HasCoreParameters {
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()
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
{
2012-11-27 10:28:06 +01:00
// commands
2015-03-14 10:49:07 +01:00
val SZ = 3
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
def busErrorIntCause = 128
def debugIntCause = 14 // keep in sync with MIP.debug
def debugTriggerCause = {
val res = debugIntCause
require(!(Causes.all contains res))
res
}
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
val hpmWidth = 40
val maxPMPs = 16
}
2017-03-09 09:28:19 +01:00
class PerfCounterIO(implicit p: Parameters) extends CoreBundle
with HasCoreParameters {
2017-03-09 09:28:19 +01:00
val eventSel = UInt(OUTPUT, xLen)
val inc = UInt(INPUT, log2Ceil(1+retireWidth))
}
2017-09-20 07:59:28 +02:00
class TracedInstruction(implicit p: Parameters) extends CoreBundle {
val valid = Bool()
2017-09-20 23:32:41 +02:00
val iaddr = UInt(width = coreMaxAddrBits)
2017-09-20 07:59:28 +02:00
val insn = UInt(width = iLen)
val priv = UInt(width = 3)
val exception = Bool()
val interrupt = Bool()
val cause = UInt(width = log2Ceil(1 + CSR.busErrorIntCause))
2017-09-20 07:59:28 +02:00
val tval = UInt(width = coreMaxAddrBits max iLen)
}
class CSRDecodeIO extends 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)
}
Heterogeneous Tiles (#550) Fundamental new features: * Added tile package: This package is intended to hold components re-usable across different types of tile. Will be the future location of TL2-RoCC accelerators and new diplomatic versions of intra-tile interfaces. * Adopted [ModuleName]Params convention: Code base was very inconsistent about what to name case classes that provide parameters to modules. Settled on calling them [ModuleName]Params to distinguish them from config.Parameters and config.Config. So far applied mostly only to case classes defined within rocket and tile. * Defined RocketTileParams: A nested case class containing case classes for all the components of a tile (L1 caches and core). Allows all such parameters to vary per-tile. * Defined RocketCoreParams: All the parameters that can be varied per-core. * Defined L1CacheParams: A trait defining the parameters common to L1 caches, made concrete in different derived case classes. * Defined RocketTilesKey: A sequence of RocketTileParams, one for every tile to be created. * Provided HeterogeneousDualCoreConfig: An example of making a heterogeneous chip with two cores, one big and one little. * Changes to legacy code: ReplacementPolicy moved to package util. L1Metadata moved to package tile. Legacy L2 cache agent removed because it can no longer share the metadata array implementation with the L1. Legacy GroundTests on life support. Additional changes that got rolled in along the way: * rocket: Fix critical path through BTB for I$ index bits > pgIdxBits * coreplex: tiles connected via :=* * groundtest: updated to use TileParams * tilelink: cache cork requirements are relaxed to allow more cacheless masters
2017-02-09 22:59:09 +01:00
class CSRFileIO(implicit p: Parameters) extends CoreBundle
with HasCoreParameters {
val interrupts = new CoreInterrupts().asInput
val hartid = UInt(INPUT, hartIdLen)
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)
val rdata = Bits(OUTPUT, xLen)
val wdata = Bits(INPUT, xLen)
2014-05-10 04:26:43 +02:00
}
val decode = Vec(decodeWidth, new CSRDecodeIO)
2015-05-19 03:23:58 +02:00
val csr_stall = Bool(OUTPUT)
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)
val retire = UInt(INPUT, log2Up(1+retireWidth))
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)
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
val rocc_interrupt = Bool(INPUT)
2015-03-14 10:49:07 +01:00
val interrupt = Bool(OUTPUT)
val interrupt_cause = UInt(OUTPUT, xLen)
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)
2017-09-20 07:59:28 +02:00
val inst = Vec(retireWidth, UInt(width = iLen)).asInput
val trace = Vec(retireWidth, new TracedInstruction).asOutput
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)
with HasCoreParameters {
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)
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(new MIP)
sup.usip := false
sup.ssip := Bool(usingVM)
sup.hsip := false
2016-03-03 08:29:58 +01:00
sup.msip := true
sup.utip := false
sup.stip := Bool(usingVM)
sup.htip := false
2016-03-03 08:29:58 +01:00
sup.mtip := true
sup.ueip := false
sup.seip := Bool(usingVM)
sup.heip := false
sup.meip := true
2016-03-03 08:29:58 +01:00
sup.rocc := usingRoCC
sup.zero1 := false
sup.debug := false
sup.zero2 := false
sup.lip foreach { _ := true }
val supported_high_interrupts = if (io.interrupts.buserror.nonEmpty) UInt(BigInt(1) << CSR.busErrorIntCause) else 0.U
2016-03-03 08:29:58 +01:00
val del = Wire(init=sup)
del.msip := false
del.mtip := false
del.meip := false
2016-03-03 08:29:58 +01:00
(sup.asUInt | supported_high_interrupts, del.asUInt)
2016-03-03 08:29:58 +01:00
}
val delegable_exceptions = UInt(Seq(
Causes.misaligned_fetch,
Causes.fetch_page_fault,
2016-03-03 08:29:58 +01:00
Causes.breakpoint,
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())
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))
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))
val mtvecWidth = paddrBits min xLen
Heterogeneous Tiles (#550) Fundamental new features: * Added tile package: This package is intended to hold components re-usable across different types of tile. Will be the future location of TL2-RoCC accelerators and new diplomatic versions of intra-tile interfaces. * Adopted [ModuleName]Params convention: Code base was very inconsistent about what to name case classes that provide parameters to modules. Settled on calling them [ModuleName]Params to distinguish them from config.Parameters and config.Config. So far applied mostly only to case classes defined within rocket and tile. * Defined RocketTileParams: A nested case class containing case classes for all the components of a tile (L1 caches and core). Allows all such parameters to vary per-tile. * Defined RocketCoreParams: All the parameters that can be varied per-core. * Defined L1CacheParams: A trait defining the parameters common to L1 caches, made concrete in different derived case classes. * Defined RocketTilesKey: A sequence of RocketTileParams, one for every tile to be created. * Provided HeterogeneousDualCoreConfig: An example of making a heterogeneous chip with two cores, one big and one little. * Changes to legacy code: ReplacementPolicy moved to package util. L1Metadata moved to package tile. Legacy L2 cache agent removed because it can no longer share the metadata array implementation with the L1. Legacy GroundTests on life support. Additional changes that got rolled in along the way: * rocket: Fix critical path through BTB for I$ index bits > pgIdxBits * coreplex: tiles connected via :=* * groundtest: updated to use TileParams * tilelink: cache cork requirements are relaxed to allow more cacheless masters
2017-02-09 22:59:09 +01:00
val reg_mtvec = mtvecInit match {
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(CSR.hpmWidth, c.inc, reset = false))
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)
mip.lip := (io.interrupts.lip: Seq[Bool])
mip.mtip := io.interrupts.mtip
mip.msip := io.interrupts.msip
mip.meip := io.interrupts.meip
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(_) }
mip.rocc := io.rocc_interrupt
val read_mip = mip.asUInt & supported_interrupts
val high_interrupts = io.interrupts.buserror.map(_ << CSR.busErrorIntCause).getOrElse(0.U)
2015-03-14 10:49:07 +01:00
val pending_interrupts = high_interrupts | (read_mip & reg_mie)
val d_interrupts = io.interrupts.debug << CSR.debugIntCause
val m_interrupts = Mux(reg_mstatus.prv <= PRV.S || reg_mstatus.mie, ~(~pending_interrupts | reg_mideleg), UInt(0))
val s_interrupts = Mux(reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie), pending_interrupts & reg_mideleg, UInt(0))
val (anyInterrupt, whichInterrupt) = chooseInterrupt(Seq(s_interrupts, m_interrupts, d_interrupts))
2016-06-02 01:57:10 +02:00
val interruptMSB = BigInt(1) << (xLen-1)
2017-04-22 03:01:32 +02:00
val interruptCause = UInt(interruptMSB) + whichInterrupt
io.interrupt := anyInterrupt && !reg_debug && !io.singleStep || reg_singleStepped
2016-06-02 01:57:10 +02:00
io.interrupt_cause := interruptCause
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
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 "") +
(if (usingCompressed) "C" else "") +
2015-10-06 06:48:05 +02:00
(if (usingRoCC) "X" else "")
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))
val read_mstatus = io.status.asUInt()(xLen-1,0)
val read_mapping = LinkedHashMap[Int,Bits](
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.misa -> reg_misa,
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.mscratch -> reg_mscratch,
2015-05-19 03:23:58 +02:00
CSRs.mepc -> reg_mepc.sextTo(xLen),
CSRs.mbadaddr -> reg_mbadaddr.sextTo(xLen),
CSRs.mcause -> reg_mcause,
CSRs.mhartid -> io.hartid)
val debug_csrs = LinkedHashMap[Int,Bits](
CSRs.dcsr -> reg_dcsr.asUInt,
2018-01-26 21:07:33 +01:00
CSRs.dpc -> reg_dpc.sextTo(xLen),
2016-08-27 05:27:27 +02:00
CSRs.dscratch -> reg_dscratch.asUInt)
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))
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
if (coreParams.haveBasicCounters) {
read_mapping += CSRs.mcycle -> reg_cycle
read_mapping += CSRs.minstret -> reg_instret
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
if (xLen == 32) {
read_mapping += (i + CSR.firstMHPCH) -> c // mhpmcounterNh
if (usingUser) read_mapping += (i + CSR.firstHPCH) -> c // hpmcounterNh
}
}
if (usingUser) {
read_mapping += CSRs.mcounteren -> reg_mcounteren
read_mapping += CSRs.cycle -> reg_cycle
read_mapping += CSRs.instret -> reg_instret
}
2017-03-09 09:28:19 +01:00
if (xLen == 32) {
read_mapping += CSRs.mcycleh -> (reg_cycle >> 32)
read_mapping += CSRs.minstreth -> (reg_instret >> 32)
if (usingUser) {
read_mapping += CSRs.cycleh -> (reg_cycle >> 32)
read_mapping += CSRs.instreth -> (reg_instret >> 32)
}
2017-03-09 09:28:19 +01:00
}
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.uxl := io.status.uxl
2017-03-20 08:19:38 +01:00
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
read_mapping += CSRs.sstatus -> (read_sstatus.asUInt())(xLen-1,0)
read_mapping += CSRs.sip -> read_sip.asUInt
read_mapping += CSRs.sie -> read_sie.asUInt
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)
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
read_mapping += CSRs.mideleg -> reg_mideleg
read_mapping += CSRs.medeleg -> reg_medeleg
2016-08-27 05:27:27 +02:00
}
2017-03-15 09:18:39 +01:00
val pmpCfgPerCSR = xLen / new PMPConfig().getWidth
def pmpCfgIndex(i: Int) = (xLen / 32) * (i / pmpCfgPerCSR)
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
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
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)
val insn_call = system_insn && opcode(0)
val insn_break = system_insn && opcode(1)
val insn_ret = system_insn && opcode(2)
val insn_wfi = system_insn && opcode(5)
for (io_dec <- io.decode) {
def decodeAny(m: LinkedHashMap[Int,Bits]): Bool = m.map { case(k: Int, _: Bits) => io_dec.csr === k }.reduce(_||_)
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
io_dec.fp_illegal := io.status.fs === 0 || !reg_misa('f'-'a')
io_dec.rocc_illegal := io.status.xs === 0 || !reg_misa('x'-'a')
io_dec.read_illegal := reg_mstatus.prv < io_dec.csr(9,8) ||
!decodeAny(read_mapping) ||
io_dec.csr === CSRs.sptbr && !allow_sfence_vma ||
(io_dec.csr.inRange(CSR.firstCtr, CSR.firstCtr + CSR.nCtr) || io_dec.csr.inRange(CSR.firstCtrH, CSR.firstCtrH + CSR.nCtr)) && reg_mstatus.prv <= PRV.S && hpm_mask(io_dec.csr(log2Ceil(CSR.firstCtr)-1,0)) ||
Bool(usingDebug) && decodeAny(debug_csrs) && !reg_debug ||
Bool(usingFPU) && decodeAny(fp_csrs) && io_dec.fp_illegal
io_dec.write_illegal := io_dec.csr(11,10).andR
io_dec.write_flush := !(io_dec.csr >= CSRs.mscratch && io_dec.csr <= CSRs.mbadaddr || io_dec.csr >= CSRs.sscratch && io_dec.csr <= CSRs.sbadaddr)
io_dec.system_illegal := reg_mstatus.prv < io_dec.csr(9,8) ||
!io_dec.csr(5) && io_dec.csr(2) && !allow_wfi ||
!io_dec.csr(5) && io_dec.csr(1) && !allow_sret ||
io_dec.csr(5) && !allow_sfence_vma
}
2016-03-03 08:29:58 +01:00
val cause =
Mux(insn_call, reg_mstatus.prv + Causes.user_ecall,
Mux[UInt](insn_break, Causes.breakpoint, io.cause))
val cause_lsbs = cause(io.trace.head.cause.getWidth-1, 0)
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 debugTVec = Mux(reg_debug, Mux(insn_break, UInt(0x800), UInt(0x808)), UInt(0x800))
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))
val mtvecBaseAlign = 2
val mtvecInterruptAlign = log2Ceil(new MIP().getWidth)
val notDebugTVec = {
val base = Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec)
val interruptOffset = cause(mtvecInterruptAlign-1, 0) << mtvecBaseAlign
val interruptVec = Cat(base >> (mtvecInterruptAlign + mtvecBaseAlign), interruptOffset)
val doVector = base(0) && cause(cause.getWidth-1) && (cause_lsbs >> mtvecInterruptAlign) === 0
Mux(doVector, interruptVec, base)
}
val tvec = Mux(trapToDebug, debugTVec, notDebugTVec)
io.evec := tvec
2015-03-14 10:49:07 +01:00
io.ptbr := reg_sptbr
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
io.status.isa := reg_misa
io.status.uxl := (if (usingUser) log2Ceil(xLen) - 4 else 0)
io.status.sxl := (if (usingVM) log2Ceil(xLen) - 4 else 0)
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))
if (xLen == 32)
io.status.sd_rv32 := io.status.sd
2015-03-14 10:49:07 +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 && !io.singleStep && !reg_debug) { reg_wfi := true }
when (pending_interrupts.orR || exception || io.interrupts.debug) { reg_wfi := false }
assert(!reg_wfi || io.retire === UInt(0))
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))
2018-01-26 21:07:33 +01:00
val epc = formEPC(io.pc)
val write_badaddr = exception && cause.isOneOf(Causes.illegal_instruction, Causes.breakpoint,
2017-09-20 21:18:03 +02:00
Causes.misaligned_load, Causes.misaligned_store,
2017-09-20 07:59:28 +02:00
Causes.load_access, Causes.store_access, Causes.fetch_access,
Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault)
val badaddr_value = Mux(write_badaddr, io.badaddr, 0.U)
val noCause :: mCause :: hCause :: sCause :: uCause :: Nil = Enum(5)
val xcause_dest = Wire(init = noCause)
2017-09-20 07:59:28 +02:00
when (exception) {
2016-06-02 01:57:10 +02:00
when (trapToDebug) {
when (!reg_debug) {
reg_debug := true
reg_dpc := epc
reg_dcsr.cause := Mux(reg_singleStepped, 4, Mux(causeIsDebugInt, 3, Mux[UInt](causeIsDebugTrigger, 2, 1)))
reg_dcsr.prv := trimPrivilege(reg_mstatus.prv)
new_prv := PRV.M
}
2016-06-02 01:57:10 +02:00
}.elsewhen (delegate) {
2018-01-26 21:07:33 +01:00
reg_sepc := epc
2016-03-03 08:29:58 +01:00
reg_scause := cause
xcause_dest := sCause
reg_sbadaddr := badaddr_value
reg_mstatus.spie := reg_mstatus.sie
2016-03-03 08:29:58 +01:00
reg_mstatus.spp := reg_mstatus.prv
reg_mstatus.sie := false
new_prv := PRV.S
2016-03-03 08:29:58 +01:00
}.otherwise {
2018-01-26 21:07:33 +01:00
reg_mepc := epc
2016-03-03 08:29:58 +01:00
reg_mcause := cause
xcause_dest := mCause
reg_mbadaddr := badaddr_value
reg_mstatus.mpie := reg_mstatus.mie
reg_mstatus.mpp := trimPrivilege(reg_mstatus.prv)
2016-03-03 08:29:58 +01:00
reg_mstatus.mie := false
new_prv := PRV.M
2015-03-14 10:49:07 +01:00
}
}
2018-01-16 09:45:50 +01:00
for (i <- 0 until supported_interrupts.getWidth) {
val en = exception && (supported_interrupts & (BigInt(1) << i).U) =/= 0 && cause === (BigInt(1) << (xLen - 1)).U + i
val delegable = (delegable_interrupts & (BigInt(1) << i).U) =/= 0
cover(en, s"INTERRUPT_M_$i")
cover(en && delegable && delegate, s"INTERRUPT_S_$i")
}
for (i <- 0 until xLen) {
val supported_exceptions = 0x87e |
(if (usingCompressed && !coreParams.misaWritable) 0 else 1) |
(if (usingUser) 0x100 else 0) |
(if (usingVM) 0xb200 else 0)
if (((supported_exceptions >> i) & 1) != 0) {
val en = exception && cause === i
cover(en, s"EXCEPTION_M_$i")
cover(en && delegate, s"EXCEPTION_S_$i")
}
}
2015-03-14 10:49:07 +01:00
when (insn_ret) {
when (Bool(usingVM) && !io.rw.addr(9)) {
reg_mstatus.sie := reg_mstatus.spie
reg_mstatus.spie := true
2016-03-03 08:29:58 +01:00
reg_mstatus.spp := PRV.U
new_prv := reg_mstatus.spp
io.evec := reg_sepc
}.elsewhen (Bool(usingDebug) && io.rw.addr(10)) {
new_prv := reg_dcsr.prv
2016-06-02 01:57:10 +02:00
reg_debug := false
io.evec := reg_dpc
2016-03-03 08:29:58 +01:00
}.otherwise {
reg_mstatus.mie := reg_mstatus.mpie
reg_mstatus.mpie := true
reg_mstatus.mpp := legalizePrivilege(PRV.U)
new_prv := reg_mstatus.mpp
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
io.rw.rdata := Mux1H(for ((k, v) <- read_mapping) yield decoded_addr(k) -> v)
2013-11-25 13:35:15 +01:00
// cover access to register
read_mapping.foreach( {case (k, v) => {
cover(io.rw.cmd.isOneOf(CSR.W, CSR.S, CSR.C, CSR.R) && io.rw.addr===k, "CSR_access_"+k.toString, "Cover Accessing Core CSR field")
}})
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
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
if (usingUser) {
2015-05-19 03:23:58 +02:00
reg_mstatus.mprv := new_mstatus.mprv
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
}
}
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
}
when (decoded_addr(CSRs.misa)) {
val mask = UInt(isaStringToMask(isaMaskString), xLen)
val f = wdata('f' - 'a')
2017-09-21 04:16:34 +02:00
if (coreParams.misaWritable)
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
}
}
2016-03-03 08:29:58 +01:00
when (decoded_addr(CSRs.mie)) { reg_mie := wdata & supported_interrupts }
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 }
Heterogeneous Tiles (#550) Fundamental new features: * Added tile package: This package is intended to hold components re-usable across different types of tile. Will be the future location of TL2-RoCC accelerators and new diplomatic versions of intra-tile interfaces. * Adopted [ModuleName]Params convention: Code base was very inconsistent about what to name case classes that provide parameters to modules. Settled on calling them [ModuleName]Params to distinguish them from config.Parameters and config.Config. So far applied mostly only to case classes defined within rocket and tile. * Defined RocketTileParams: A nested case class containing case classes for all the components of a tile (L1 caches and core). Allows all such parameters to vary per-tile. * Defined RocketCoreParams: All the parameters that can be varied per-core. * Defined L1CacheParams: A trait defining the parameters common to L1 caches, made concrete in different derived case classes. * Defined RocketTilesKey: A sequence of RocketTileParams, one for every tile to be created. * Provided HeterogeneousDualCoreConfig: An example of making a heterogeneous chip with two cores, one big and one little. * Changes to legacy code: ReplacementPolicy moved to package util. L1Metadata moved to package tile. Legacy L2 cache agent removed because it can no longer share the metadata array implementation with the L1. Legacy GroundTests on life support. Additional changes that got rolled in along the way: * rocket: Fix critical path through BTB for I$ index bits > pgIdxBits * coreplex: tiles connected via :=* * groundtest: updated to use TileParams * tilelink: cache cork requirements are relaxed to allow more cacheless masters
2017-02-09 22:59:09 +01:00
if (mtvecWritable)
when (decoded_addr(CSRs.mtvec)) { reg_mtvec := ~(~wdata | 2.U | Mux(wdata(0), UInt(((BigInt(1) << mtvecInterruptAlign) - 1) << mtvecBaseAlign), 0.U)) }
when (decoded_addr(CSRs.mcause)) { reg_mcause := wdata & UInt((BigInt(1) << (xLen-1)) + (BigInt(1) << whichInterrupt.getWidth) - 1) }
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
}
if (coreParams.haveBasicCounters) {
writeCounter(CSRs.mcycle, reg_cycle, wdata)
writeCounter(CSRs.minstret, reg_instret, wdata)
}
2016-08-27 05:27:27 +02: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-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
if (usingUser) reg_dcsr.prv := trimPrivilege(new_dcsr.prv)
2016-06-02 01:57:10 +02:00
}
2018-01-26 21:07:33 +01:00
when (decoded_addr(CSRs.dpc)) { reg_dpc := formEPC(wdata) }
2016-06-02 01:57:10 +02:00
when (decoded_addr(CSRs.dscratch)) { reg_dscratch := wdata }
}
2015-10-06 06:48:05 +02:00
if (usingVM) {
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-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
}
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) }
when (decoded_addr(CSRs.sscratch)) { reg_sscratch := wdata }
when (decoded_addr(CSRs.sepc)) { reg_sepc := formEPC(wdata) }
when (decoded_addr(CSRs.stvec)) { reg_stvec := ~(~wdata | 2.U | Mux(wdata(0), UInt(((BigInt(1) << mtvecInterruptAlign) - 1) << mtvecBaseAlign), 0.U)) }
2016-03-03 08:29:58 +01:00
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) }
}
if (nBreakpoints > 0) {
when (decoded_addr(CSRs.tselect)) { reg_tselect := wdata }
val bp = reg_bp(reg_tselect)
when (!bp.control.dmode || reg_debug) {
when (decoded_addr(CSRs.tdata1)) {
val newBPC = new BPControl().fromBits(wdata)
val dMode = newBPC.dmode && reg_debug
bp.control := newBPC
bp.control.dmode := dMode
bp.control.action := dMode && newBPC.action
}
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)
2017-03-30 09:31:34 +02:00
when (decoded_addr(CSRs.pmpcfg0 + pmpCfgIndex(i)) && !pmp.cfgLocked) {
2017-03-15 09:18:39 +01:00
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
}
if (!usingVM) {
reg_mideleg := 0
reg_medeleg := 0
2017-02-27 23:27:19 +01:00
reg_scounteren := 0
}
if (!usingUser) {
2017-02-27 23:27:19 +01:00
reg_mcounteren := 0
}
2016-06-18 03:29:05 +02:00
reg_sptbr.asid := 0
if (nBreakpoints <= 1) reg_tselect := 0
if (nBreakpoints >= 1)
reg_bp(nBreakpoints-1).control.chain := false
for (bpc <- reg_bp map {_.control}) {
bpc.ttype := bpc.tType
bpc.maskmax := bpc.maskMax
2016-06-10 04:07:10 +02:00
bpc.reserved := 0
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) {
bpc.action := false
bpc.dmode := false
2016-06-09 05:19:52 +02:00
bpc.r := false
bpc.w := false
bpc.x := false
}
}
for (bp <- reg_bp drop nBreakpoints)
bp := new BP().fromBits(0)
2017-03-30 09:31:34 +02:00
for (pmp <- reg_pmp) {
pmp.cfg.res := 0
when (reset) {
pmp.cfg.a := 0
pmp.cfg.l := 0
2017-03-15 09:18:39 +01:00
}
}
2017-09-20 07:59:28 +02:00
for (((t, insn), i) <- (io.trace zip io.inst).zipWithIndex) {
t.exception := io.retire >= i && exception
t.valid := io.retire > i || t.exception
t.insn := insn
2017-09-20 23:32:41 +02:00
t.iaddr := io.pc
2017-09-20 07:59:28 +02:00
t.priv := Cat(reg_debug, reg_mstatus.prv)
t.cause := cause
t.interrupt := cause(xLen-1)
2017-09-20 07:59:28 +02:00
t.tval := badaddr_value
}
def chooseInterrupt(masksIn: Seq[UInt]): (Bool, UInt) = {
val nonstandard = supported_interrupts.getWidth-1 to 12 by -1
// MEI, MSI, MTI, SEI, SSI, STI, UEI, USI, UTI
val standard = Seq(11, 3, 7, 9, 1, 5, 8, 0, 4)
val priority = nonstandard ++ standard
val masks = masksIn.reverse
val any = masks.flatMap(m => priority.filter(_ < m.getWidth).map(i => m(i))).reduce(_||_)
val which = PriorityMux(masks.flatMap(m => priority.filter(_ < m.getWidth).map(i => (m(i), i.U))))
(any, which)
2017-04-22 03:01:32 +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))
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
}
}
def formEPC(x: UInt) = ~(~x | Cat(!reg_misa('c'-'a'), UInt(1)))
def isaStringToMask(s: String) = s.map(x => 1 << (x - 'A')).foldLeft(0)(_|_)
}