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

707 lines
25 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
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)
2016-03-03 08:29:58 +01:00
val prv = UInt(width = PRV.SZ) // not truly part of mstatus, but convenient
2015-03-14 10:49:07 +01:00
val sd = Bool()
2017-02-27 23:27:19 +01:00
val zero2 = UInt(width = 27)
val sxl = UInt(width = 2)
val uxl = UInt(width = 2)
2016-03-03 08:29:58 +01:00
val sd_rv32 = Bool()
2017-02-27 23:27:19 +01:00
val zero1 = UInt(width = 9)
val tw = Bool()
val tvm = Bool()
2016-07-06 04:19:49 +02:00
val mxr = Bool()
2016-03-03 08:29:58 +01:00
val pum = Bool()
2015-05-19 03:23:58 +02:00
val mprv = Bool()
2015-03-14 10:49:07 +01:00
val xs = UInt(width = 2)
val fs = UInt(width = 2)
2016-03-03 08:29:58 +01:00
val mpp = UInt(width = 2)
val hpp = UInt(width = 2)
val spp = UInt(width = 1)
val mpie = Bool()
val hpie = Bool()
val spie = Bool()
val upie = Bool()
val mie = Bool()
val hie = Bool()
val sie = Bool()
val uie = Bool()
2015-05-19 03:23:58 +02:00
}
2016-06-02 01:57:10 +02:00
class DCSR extends Bundle {
val xdebugver = UInt(width = 2)
val ndreset = Bool()
val fullreset = Bool()
val zero3 = UInt(width = 12)
2016-06-02 01:57:10 +02:00
val ebreakm = Bool()
val ebreakh = Bool()
val ebreaks = Bool()
val ebreaku = Bool()
val zero2 = Bool()
val stopcycle = Bool()
val stoptime = Bool()
val cause = UInt(width = 3)
val debugint = Bool()
val zero1 = Bool()
val halt = Bool()
val step = Bool()
val prv = UInt(width = PRV.SZ)
}
2015-05-19 03:23:58 +02:00
class MIP extends Bundle {
2016-03-03 08:29:58 +01:00
val rocc = Bool()
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 = new MIP().getWidth
def debugTriggerCause = {
require(debugIntCause >= Causes.all.max)
debugIntCause
}
2016-08-27 05:27:27 +02:00
val firstCtr = CSRs.cycle
2017-02-27 23:27:19 +01:00
val firstHPC = CSRs.hpmcounter3
val firstHPE = CSRs.mhpmevent3
val firstMHPC = CSRs.mhpmcounter3
2016-08-27 05:27:27 +02:00
val firstHPM = 3
2017-02-27 23:27:19 +01:00
val nCtr = 32
val nHPM = nCtr - firstHPM
}
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, 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)
val rdata = Bits(OUTPUT, xLen)
val wdata = Bits(INPUT, xLen)
2014-05-10 04:26:43 +02:00
}
2015-05-19 03:23:58 +02:00
val csr_stall = Bool(OUTPUT)
2015-03-14 10:49:07 +01:00
val csr_xcpt = Bool(OUTPUT)
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)
2014-05-10 04:26:43 +02:00
val fatc = Bool(OUTPUT)
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
2016-08-27 05:27:27 +02:00
val events = Vec(nPerfEvents, Bool()).asInput
2014-05-10 04:26:43 +02:00
}
2015-10-06 06:48:05 +02:00
class CSRFile(implicit p: Parameters) extends CoreModule()(p)
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(init=new MIP().fromBits(0))
sup.ssip := Bool(usingVM)
2016-03-03 08:29:58 +01:00
sup.msip := true
sup.stip := Bool(usingVM)
2016-03-03 08:29:58 +01:00
sup.mtip := true
sup.meip := true
sup.seip := Bool(usingVM)
2016-03-03 08:29:58 +01:00
sup.rocc := usingRoCC
val del = Wire(init=sup)
del.msip := false
del.mtip := false
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.fault_fetch,
Causes.breakpoint,
Causes.fault_load,
Causes.fault_store,
Causes.user_ecall).map(1 << _).sum)
2016-06-16 01:21:24 +02:00
val exception = io.exception || io.csr_xcpt
2016-06-02 01:57:10 +02:00
val reg_debug = Reg(init=Bool(false))
2017-02-27 23:27:19 +01:00
val effective_prv = Cat(reg_debug, reg_mstatus.prv)
2016-06-02 01:57:10 +02:00
val reg_dpc = Reg(UInt(width = vaddrBitsExtended))
val reg_dscratch = Reg(UInt(width = xLen))
2016-06-16 01:21:24 +02:00
val reg_singleStepped = Reg(Bool())
when (io.retire(0) || exception) { reg_singleStepped := true }
when (!io.singleStep) { reg_singleStepped := false }
assert(!io.singleStep || io.retire <= UInt(1))
assert(!reg_singleStepped || io.retire === UInt(0))
val reg_tselect = Reg(UInt(width = log2Up(nBreakpoints)))
val reg_bp = Reg(Vec(1 << log2Up(nBreakpoints), new BP))
2016-06-09 05:19:52 +02:00
2016-08-27 05:27:27 +02:00
val reg_mie = Reg(UInt(width = xLen))
val reg_mideleg = Reg(UInt(width = xLen))
val reg_medeleg = Reg(UInt(width = xLen))
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)
val reg_hpmevent = Seq.fill(nPerfCounters)(if (nPerfEvents > 1) Reg(UInt(width = log2Ceil(nPerfEvents))) else UInt(0))
val reg_hpmcounter = reg_hpmevent.map(e => WideCounter(64, ((UInt(0) +: io.events): Seq[UInt])(e)))
2016-03-11 02:32:00 +01:00
2016-03-03 08:29:58 +01:00
val mip = Wire(init=reg_mip)
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))
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)
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
io.bp := reg_bp take nBreakpoints
2016-06-02 01:57:10 +02:00
// debug interrupts are only masked by being in debug mode
when (Bool(usingDebug) && reg_dcsr.debugint && !reg_debug) {
io.interrupt := true
io.interrupt_cause := UInt(interruptMSB) + CSR.debugIntCause
2016-06-02 01:57:10 +02:00
}
2015-03-14 10:49:07 +01:00
val system_insn = io.rw.cmd === CSR.I
2016-01-14 22:57:45 +01:00
val cpu_ren = io.rw.cmd =/= CSR.N && !system_insn
2016-08-27 05:27:27 +02:00
val cpu_wen = cpu_ren && io.rw.cmd =/= CSR.R
2015-03-14 10:49:07 +01:00
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 = collection.mutable.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.mideleg -> reg_mideleg,
CSRs.medeleg -> reg_medeleg,
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)
2016-08-27 05:27:27 +02:00
val debug_csrs = collection.immutable.ListMap(
CSRs.dcsr -> reg_dcsr.asUInt,
CSRs.dpc -> reg_dpc.asUInt,
2016-08-27 05:27:27 +02:00
CSRs.dscratch -> reg_dscratch.asUInt)
val fp_csrs = collection.immutable.ListMap(
CSRs.fflags -> reg_fflags,
CSRs.frm -> reg_frm,
CSRs.fcsr -> Cat(reg_frm, reg_fflags))
if (usingDebug)
read_mapping ++= debug_csrs
2016-06-02 01:57:10 +02:00
2016-08-27 05:27:27 +02:00
if (usingFPU)
read_mapping ++= fp_csrs
for (((e, c), i) <- (reg_hpmevent.padTo(CSR.nHPM, UInt(0))
zip reg_hpmcounter.map(x => x: UInt).padTo(CSR.nHPM, UInt(0))) zipWithIndex) {
read_mapping += (i + CSR.firstHPE) -> e // mhpmeventN
read_mapping += (i + CSR.firstMHPC) -> c // mhpmcounterN
if (usingUser) read_mapping += (i + CSR.firstHPC) -> c // hpmcounterN
2015-09-28 22:55:23 +02:00
}
2015-10-06 06:48:05 +02:00
if (usingVM) {
2016-03-03 08:29:58 +01:00
val read_sie = reg_mie & reg_mideleg
val read_sip = read_mip & reg_mideleg
val read_sstatus = Wire(init=io.status)
read_sstatus.mprv := 0
read_sstatus.mpp := 0
read_sstatus.hpp := 0
read_sstatus.mpie := 0
read_sstatus.hpie := 0
read_sstatus.mie := 0
read_sstatus.hie := 0
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
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
}
}
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) }
2015-03-14 10:49:07 +01:00
val addr_valid = decoded_addr.values.reduce(_||_)
2016-08-27 05:27:27 +02:00
val fp_csr = if (usingFPU) decoded_addr.filterKeys(fp_csrs contains _ ).values reduce(_||_) else Bool(false)
val hpm_csr = if (usingUser) io.rw.addr >= CSR.firstCtr && io.rw.addr < CSR.firstCtr + CSR.nCtr else Bool(false)
2017-02-27 23:27:19 +01:00
val hpm_en = effective_prv > PRV.S || (reg_mcounteren & Mux((!usingVM).B || reg_mstatus.prv === PRV.S, delegable_counters.U, reg_scounteren))(io.rw.addr(log2Ceil(CSR.nCtr)-1, 0))
val csr_addr_priv = io.rw.addr(9,8)
val debug_csr_mask = 0x090 // only debug CSRs have address bits 7 and 4 set
require((read_mapping -- debug_csrs.keys).keys.forall(x => (x & debug_csr_mask) != debug_csr_mask))
require(debug_csrs.keys.forall(x => (x & debug_csr_mask) == debug_csr_mask))
val csr_debug = Bool(usingDebug) && (io.rw.addr & debug_csr_mask) === debug_csr_mask
val priv_sufficient = reg_debug || (!csr_debug && reg_mstatus.prv >= csr_addr_priv)
2015-03-14 10:49:07 +01:00
val read_only = io.rw.addr(11,10).andR
2016-08-27 05:27:27 +02:00
val wen = cpu_wen && priv_sufficient && !read_only
2017-02-27 23:27:19 +01:00
val wdata = (Mux(io.rw.cmd.isOneOf(CSR.S, CSR.C), io.rw.rdata, UInt(0)) | io.rw.wdata) &
~Mux(io.rw.cmd === CSR.C, io.rw.wdata, UInt(0))
2012-02-12 02:20:33 +01:00
2016-03-03 08:29:58 +01:00
val do_system_insn = priv_sufficient && system_insn
val opcode = UInt(1) << io.rw.addr(2,0)
2017-02-27 23:27:19 +01:00
val insn_rs2 = io.rw.addr(5)
val insn_call = do_system_insn && !insn_rs2 && opcode(0)
2016-03-03 08:29:58 +01:00
val insn_break = do_system_insn && opcode(1)
val insn_ret = do_system_insn && opcode(2)
2017-02-27 23:27:19 +01:00
val allow_wfi = effective_prv > PRV.S || !reg_mstatus.tw
val want_wfi = do_system_insn && opcode(5)
val insn_wfi = want_wfi && allow_wfi
val allow_sfence_vma = effective_prv > PRV.S || !reg_mstatus.tvm
val want_sfence_vma = do_system_insn && insn_rs2
val insn_sfence_vma = want_sfence_vma && allow_sfence_vma
val allow_fcsr = io.status.fs.orR && reg_misa('f'-'a')
2015-03-14 10:49:07 +01:00
2016-06-16 01:21:24 +02:00
io.csr_xcpt := (cpu_wen && read_only) ||
2017-02-27 23:27:19 +01:00
(cpu_ren &&
(!priv_sufficient ||
!addr_valid ||
(if (usingVM) decoded_addr(CSRs.sptbr) && !allow_sfence_vma else false.B) ||
(hpm_csr && !hpm_en) ||
(fp_csr && !allow_fcsr))) ||
2015-03-14 10:49:07 +01:00
(system_insn && !priv_sufficient) ||
2017-02-27 23:27:19 +01:00
insn_call || insn_break ||
want_wfi && !allow_wfi ||
want_sfence_vma && !allow_sfence_vma
2015-03-14 10:49:07 +01:00
2015-05-19 03:23:58 +02:00
when (insn_wfi) { reg_wfi := true }
2017-02-27 23:27:19 +01:00
when (pending_interrupts.orR || exception) { reg_wfi := false }
2016-03-03 08:29:58 +01:00
val cause =
2016-06-16 01:21:24 +02:00
Mux(!io.csr_xcpt, io.cause,
2016-03-03 08:29:58 +01:00
Mux(insn_call, reg_mstatus.prv + Causes.user_ecall,
Mux[UInt](insn_break, Causes.breakpoint, Causes.illegal_instruction)))
val cause_lsbs = cause(log2Up(xLen)-1,0)
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))
val debugTVec = Mux(reg_debug, UInt(0x808), UInt(0x800))
val tvec = Mux(trapToDebug, debugTVec, Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec))
val epc = Mux(csr_debug, reg_dpc, Mux(Bool(usingVM) && !csr_addr_priv(1), reg_sepc, reg_mepc))
2017-02-27 23:27:19 +01:00
io.fatc := insn_sfence_vma
io.evec := Mux(insn_ret, epc, tvec)
2015-03-14 10:49:07 +01:00
io.ptbr := reg_sptbr
2016-03-03 08:29:58 +01:00
io.eret := insn_ret
2016-06-16 01:21:24 +02:00
io.singleStep := reg_dcsr.step && !reg_debug
2015-03-14 10:49:07 +01:00
io.status := reg_mstatus
2015-08-01 00:42:10 +02:00
io.status.sd := io.status.fs.andR || io.status.xs.andR
2016-06-02 01:57:10 +02:00
io.status.debug := reg_debug
io.status.isa := reg_misa
2017-02-27 23:27:19 +01:00
io.status.uxl := (if (usingUser) log2Ceil(xLen) - 4 else 0)
io.status.sxl := (if (usingVM) log2Ceil(xLen) - 4 else 0)
if (xLen == 32)
io.status.sd_rv32 := io.status.sd
2015-03-14 10:49:07 +01:00
2016-06-16 01:21:24 +02:00
when (exception) {
2016-03-03 08:29:58 +01:00
val epc = ~(~io.pc | (coreInstBytes-1))
val pie = read_mstatus(reg_mstatus.prv)
val write_badaddr = cause isOneOf (Causes.breakpoint,
Causes.misaligned_load, Causes.misaligned_store, Causes.misaligned_fetch,
Causes.fault_load, Causes.fault_store, Causes.fault_fetch)
2016-06-02 01:57:10 +02:00
when (trapToDebug) {
reg_debug := true
reg_dpc := epc
reg_dcsr.cause := Mux(reg_singleStepped, 4, Mux(causeIsDebugInt, 3, Mux[UInt](causeIsDebugTrigger, 2, 1)))
reg_dcsr.prv := trimPrivilege(reg_mstatus.prv)
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
when (write_badaddr) { reg_sbadaddr := io.badaddr }
2016-03-03 08:29:58 +01:00
reg_mstatus.spie := pie
reg_mstatus.spp := reg_mstatus.prv
reg_mstatus.sie := false
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
when (write_badaddr) { reg_mbadaddr := io.badaddr }
2016-03-03 08:29:58 +01:00
reg_mstatus.mpie := pie
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) && !csr_addr_priv(1)) {
2016-03-03 08:29:58 +01:00
when (reg_mstatus.spp.toBool) { reg_mstatus.sie := reg_mstatus.spie }
reg_mstatus.spie := true
2016-03-03 08:29:58 +01:00
reg_mstatus.spp := PRV.U
new_prv := reg_mstatus.spp
2016-06-02 01:57:10 +02:00
}.elsewhen (csr_debug) {
new_prv := reg_dcsr.prv
2016-06-02 01:57:10 +02:00
reg_debug := false
2016-03-03 08:29:58 +01:00
}.otherwise {
when (reg_mstatus.mpp(1)) { reg_mstatus.mie := reg_mstatus.mpie }
.elsewhen (Bool(usingVM) && reg_mstatus.mpp(0)) { reg_mstatus.sie := reg_mstatus.mpie }
reg_mstatus.mpie := true
reg_mstatus.mpp := legalizePrivilege(PRV.U)
new_prv := reg_mstatus.mpp
2016-03-03 08:29:58 +01:00
}
2015-03-14 10:49:07 +01:00
}
2016-06-16 01:21:24 +02:00
assert(PopCount(insn_ret :: io.exception :: io.csr_xcpt :: Nil) <= 1, "these conditions must be mutually exclusive")
2015-03-14 10:49:07 +01:00
2015-07-06 01:38:49 +02:00
io.time := reg_cycle
2015-05-19 03:23:58 +02:00
io.csr_stall := reg_wfi
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 (wen) {
2015-03-14 10:49:07 +01:00
when (decoded_addr(CSRs.mstatus)) {
val new_mstatus = new MStatus().fromBits(wdata)
2016-03-03 08:29:58 +01:00
reg_mstatus.mie := new_mstatus.mie
reg_mstatus.mpie := new_mstatus.mpie
if (usingUser) {
2015-05-19 03:23:58 +02:00
reg_mstatus.mprv := new_mstatus.mprv
reg_mstatus.mpp := trimPrivilege(new_mstatus.mpp)
2017-02-27 23:27:19 +01:00
reg_mstatus.mxr := new_mstatus.mxr
if (usingVM) {
2016-03-03 08:29:58 +01:00
reg_mstatus.pum := new_mstatus.pum
reg_mstatus.spp := new_mstatus.spp
reg_mstatus.spie := new_mstatus.spie
reg_mstatus.sie := new_mstatus.sie
2017-02-27 23:27:19 +01:00
reg_mstatus.tw := new_mstatus.tw
reg_mstatus.tvm := new_mstatus.tvm
}
}
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))
val f = wdata('f' - 'a')
reg_misa := ~(~wdata | (!f << ('d' - 'a'))) & mask | reg_misa & ~mask
}
2015-05-19 03:23:58 +02:00
when (decoded_addr(CSRs.mip)) {
val new_mip = new MIP().fromBits(wdata)
2015-10-06 06:48:05 +02:00
if (usingVM) {
2015-05-19 03:23:58 +02:00
reg_mip.ssip := new_mip.ssip
2015-07-06 01:38:49 +02:00
reg_mip.stip := new_mip.stip
}
}
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)
2016-03-03 08:29:58 +01:00
when (decoded_addr(CSRs.mtvec)) { reg_mtvec := wdata >> 2 << 2 }
2015-03-14 10:49:07 +01:00
when (decoded_addr(CSRs.mcause)) { reg_mcause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ }
2015-05-19 03:23:58 +02:00
when (decoded_addr(CSRs.mbadaddr)) { reg_mbadaddr := wdata(vaddrBitsExtended-1,0) }
2016-08-27 05:27:27 +02:00
for (((e, c), i) <- (reg_hpmevent zip reg_hpmcounter) zipWithIndex) {
writeCounter(i + CSR.firstMHPC, c, wdata)
if (nPerfEvents > 1)
when (decoded_addr(i + CSR.firstHPE)) { e := wdata }
}
writeCounter(CSRs.mcycle, reg_cycle, wdata)
writeCounter(CSRs.minstret, reg_instret, wdata)
2017-02-27 23:27:19 +01:00
if (usingFPU) when (allow_fcsr) {
2016-03-11 02:30:56 +01:00
when (decoded_addr(CSRs.fflags)) { reg_fflags := wdata }
when (decoded_addr(CSRs.frm)) { reg_frm := wdata }
when (decoded_addr(CSRs.fcsr)) { reg_fflags := wdata; reg_frm := wdata >> reg_fflags.getWidth }
}
2016-06-02 01:57:10 +02:00
if (usingDebug) {
when (decoded_addr(CSRs.dcsr)) {
val new_dcsr = new DCSR().fromBits(wdata)
2016-06-09 21:29:26 +02:00
reg_dcsr.halt := new_dcsr.halt
2016-06-16 01:21:24 +02:00
reg_dcsr.step := new_dcsr.step
2016-06-02 01:57:10 +02:00
reg_dcsr.ebreakm := new_dcsr.ebreakm
if (usingVM) reg_dcsr.ebreaks := new_dcsr.ebreaks
if (usingUser) reg_dcsr.ebreaku := new_dcsr.ebreaku
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
reg_mstatus.pum := new_sstatus.pum
reg_mstatus.fs := Fill(2, new_sstatus.fs.orR) // even without an FPU
if (usingRoCC) reg_mstatus.xs := Fill(2, new_sstatus.xs.orR)
}
2015-05-19 03:23:58 +02:00
when (decoded_addr(CSRs.sip)) {
val new_sip = new MIP().fromBits(wdata)
reg_mip.ssip := new_sip.ssip
}
2017-02-27 23:27:19 +01:00
when (decoded_addr(CSRs.sptbr) && allow_sfence_vma) {
val new_sptbr = new PTBR().fromBits(wdata)
val valid_mode = new_sptbr.pgLevelsToMode(pgLevels)
when (new_sptbr.mode === 0) { reg_sptbr.mode := 0 }
when (new_sptbr.mode === valid_mode) { reg_sptbr.mode := valid_mode }
when (new_sptbr.mode === 0 || new_sptbr.mode === valid_mode) {
reg_sptbr.ppn := new_sptbr.ppn(ppnBits-1,0)
if (asIdBits > 0) reg_sptbr.asid := new_sptbr.asid(asIdBits-1,0)
}
}
2016-03-03 08:29:58 +01:00
when (decoded_addr(CSRs.sie)) { reg_mie := (reg_mie & ~reg_mideleg) | (wdata & reg_mideleg) }
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
}
}
2012-02-12 02:20:33 +01:00
}
reg_mip <> io.interrupts
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)
def legalizePrivilege(priv: UInt): UInt =
if (usingVM) Mux(priv === PRV.H, PRV.U, priv)
else if (usingUser) Fill(2, priv(0))
else PRV.M
def trimPrivilege(priv: UInt): UInt =
if (usingVM) priv
else legalizePrivilege(priv)
2016-08-27 05:27:27 +02:00
def writeCounter(lo: Int, ctr: WideCounter, wdata: UInt) = {
if (xLen == 32) {
val hi = lo + CSRs.mcycleh - CSRs.mcycle
when (decoded_addr(lo)) { ctr := Cat(ctr(63, 32), wdata) }
when (decoded_addr(hi)) { ctr := Cat(wdata, ctr(31, 0)) }
} else {
when (decoded_addr(lo)) { ctr := wdata }
}
}
def formEPC(x: UInt) = ~(~x | Cat(!reg_misa('c'-'a'), UInt(1)))
def isaStringToMask(s: String) = s.map(x => 1 << (x - 'A')).reduce(_|_)
}