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

798 lines
29 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 rocket
import collection.mutable.LinkedHashMap
2012-10-08 05:15:54 +02:00
import Chisel._
2015-03-14 10:49:07 +01:00
import Instructions._
import config._
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
import tile._
import uncore.devices._
import util._
import Chisel.ImplicitConversions._
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)
// TODO: debugint is not in the Debug Spec v13
2016-06-02 01:57:10 +02:00
val debugint = Bool()
val zero1 = UInt(width=2)
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 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()
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 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 maxPMPs = 16
}
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))
}
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 HasRocketCoreParameters {
val interrupts = new TileInterrupts().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 = 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)
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))
2016-01-14 22:57:45 +01:00
val custom_mrw_csrs = Vec(nCustomMrwCsrs, UInt(INPUT, xLen))
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)
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)
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
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)
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 }
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, 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(40, 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)
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
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))
2017-04-22 03:01:32 +02:00
val (anyInterrupt, whichInterrupt) = chooseInterrupt(Seq(s_interrupts, m_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
// debug interrupts are only masked by being in debug mode
when (Bool(usingDebug) && reg_dcsr.debugint && !reg_debug) {
io.interrupt := true
io.interrupt_cause := UInt(interruptMSB) + CSR.debugIntCause
2016-06-02 01:57:10 +02:00
}
2015-03-14 10:49:07 +01: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.mcycle -> reg_cycle,
CSRs.minstret -> reg_instret,
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,
CSRs.dpc -> reg_dpc.asUInt,
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
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.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
}
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
}
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)
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))
require(!read_mapping.contains(addr), "custom MRW CSR address " + i + " is already in use")
read_mapping += addr -> io.custom_mrw_csrs(i)
}
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)
private def decodeAny(m: LinkedHashMap[Int,Bits]): Bool = m.map { case(k: Int, _: Bits) => io.decode.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.decode.fp_illegal := io.status.fs === 0 || !reg_misa('f'-'a')
io.decode.rocc_illegal := io.status.xs === 0 || !reg_misa('x'-'a')
io.decode.read_illegal := reg_mstatus.prv < io.decode.csr(9,8) ||
!decodeAny(read_mapping) ||
io.decode.csr === CSRs.sptbr && !allow_sfence_vma ||
(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)) ||
Bool(usingDebug) && decodeAny(debug_csrs) && !reg_debug ||
Bool(usingFPU) && decodeAny(fp_csrs) && io.decode.fp_illegal
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)
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 ||
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,
Mux[UInt](insn_break, Causes.breakpoint, io.cause))
2016-03-03 08:29:58 +01:00
val cause_lsbs = cause(log2Up(xLen)-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 notDebugTVec = {
val base = Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec)
val baseAlign = 2
val interruptAlign = log2Ceil(new MIP().getWidth)
2017-04-11 03:40:49 +02:00
val interruptOffset = cause(interruptAlign-1, 0) << baseAlign
val interruptVec = Cat(base >> (interruptAlign + baseAlign), interruptOffset)
Mux(base(0) && cause(cause.getWidth-1), 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) { reg_wfi := true }
when (pending_interrupts.orR || exception) { 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))
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 write_badaddr = cause isOneOf (Causes.illegal_instruction, Causes.breakpoint,
Causes.misaligned_load, Causes.misaligned_store, Causes.misaligned_fetch,
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)
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) {
reg_sepc := formEPC(epc)
2016-03-03 08:29:58 +01:00
reg_scause := cause
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 {
reg_mepc := formEPC(epc)
2016-03-03 08:29:58 +01:00
reg_mcause := cause
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
}
}
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
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')
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 & ~UInt(2, mtvecWidth) }
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)
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
}
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) {
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) }
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) }
}
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
}
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
reg_dcsr.debugint := io.interrupts.debug
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-04-22 03:01:32 +02:00
def chooseInterrupt(masks: Seq[UInt]) = {
// we can't simply choose the highest-numbered interrupt, because timer
// interrupts are in the wrong place in mip.
val timerMask = UInt(0xF0, xLen)
val masked = masks.map(m => Cat(m.padTo(xLen) & ~timerMask, m.padTo(xLen) & timerMask))
(masks.map(_.orR).reduce(_||_), Log2(masked.asUInt)(log2Ceil(xLen)-1, 0))
}
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')).reduce(_|_)
}