CsrPlugin now catch illegal CSR access (wrong address + to low privilege level)

This commit is contained in:
Charles Papon 2017-05-09 00:40:44 +02:00
parent fe184636dd
commit 736478ff1d
4 changed files with 119 additions and 82 deletions

View File

@ -12,16 +12,27 @@ import scala.collection.mutable
* Created by spinalvm on 21.03.17.
*/
trait CsrAccess
trait CsrAccess{
def canWrite : Boolean = false
def canRead : Boolean = false
}
object CsrAccess {
object WRITE_ONLY extends CsrAccess
object READ_ONLY extends CsrAccess
object READ_WRITE extends CsrAccess
object WRITE_ONLY extends CsrAccess{
override def canWrite : Boolean = true
}
object READ_ONLY extends CsrAccess{
override def canRead : Boolean = true
}
object READ_WRITE extends CsrAccess{
override def canWrite : Boolean = true
override def canRead : Boolean = true
}
object NONE extends CsrAccess
}
case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int)
case class MachineCsrConfig(
catchIllegalAccess : Boolean,
mvendorid : BigInt,
marchid : BigInt,
mimpid : BigInt,
@ -36,9 +47,12 @@ case class MachineCsrConfig(
mbadaddrAccess : CsrAccess,
mcycleAccess : CsrAccess,
minstretAccess : CsrAccess,
ucycleAccess : CsrAccess,
wfiGen : Boolean,
ecallGen : Boolean
)
){
assert(!ucycleAccess.canWrite)
}
case class CsrWrite(that : Data, bitOffset : Int)
@ -82,6 +96,7 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
var timerInterrupt : Bool = null
var externalInterrupt : Bool = null
var privilege : Bits = null
var selfException : Flow[ExceptionCause] = null
object EnvCtrlEnum extends SpinalEnum(binarySequential){
val NONE, EBREAK, MRET= newElement()
@ -144,6 +159,9 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
externalInterrupt = in Bool() setName("externalInterrupt")
privilege = RegInit(B"11")
if(catchIllegalAccess)
selfException = newExceptionPort(pipeline.execute)
}
@ -205,6 +223,7 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
if(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid ))
if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid ))
//Machine CSR
misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
READ_WRITE(CSR.MIP, 3 -> mip.MSIP)
@ -221,6 +240,9 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
minstretAccess(CSR.MINSTRET, minstret(31 downto 0))
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
//User CSR
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
//Manage counters
@ -350,30 +372,46 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
execute plug new Area {
import execute._
val illegalAccess = True
if(catchIllegalAccess) {
selfException.valid := arbitration.isValid && input(IS_CSR) && illegalAccess
selfException.code := 2
selfException.badAddr.assignDontCare()
}
val imm = IMM(input(INSTRUCTION))
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
val readData = B(0, 32 bits)
val readDataRegValid = Reg(Bool) setWhen(arbitration.isValid) clearWhen(!arbitration.isStuck)
val readDataRegValid = Reg(Bool) setWhen(arbitration.isValid && !memory.arbitration.isStuck) clearWhen(!arbitration.isStuck)
val writeData = input(INSTRUCTION)(13).mux(
False -> writeSrc,
True -> Mux(input(INSTRUCTION)(12), memory.input(REGFILE_WRITE_DATA) & ~writeSrc, memory.input(REGFILE_WRITE_DATA) | writeSrc)
)
val writeInstruction = arbitration.isValid && input(IS_CSR)
(!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
val writeOpcode = (!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0)))
val writeInstruction = arbitration.isValid && input(IS_CSR) && writeOpcode
arbitration.haltIt setWhen(writeInstruction && (!readDataRegValid || memory.arbitration.isValid))
val writeEnable = writeInstruction && !memory.arbitration.isValid && readDataRegValid
assert(!(arbitration.removeIt && writeEnable),"Can't remove CSR instruction when write occure")
arbitration.haltIt setWhen(writeInstruction && !readDataRegValid)
val writeEnable = writeInstruction && !arbitration.isStuckByOthers && !arbitration.removeIt && readDataRegValid
when(arbitration.isValid && input(IS_CSR)) {
output(REGFILE_WRITE_DATA) := readData
}
//Translation of the csrMapping into real logic
switch(input(INSTRUCTION)(csrRange)) {
val csrAddress = input(INSTRUCTION)(csrRange)
switch(csrAddress) {
for ((address, jobs) <- csrMapping.mapping) {
is(address) {
val withWrite = jobs.exists(_.isInstanceOf[CsrWrite])
val withRead = jobs.exists(_.isInstanceOf[CsrRead])
if(withRead && withWrite) {
illegalAccess := False
} else {
if (withWrite) illegalAccess.clearWhen(writeOpcode)
if (withRead) illegalAccess.clearWhen(!writeOpcode)
}
when(writeEnable) {
for (element <- jobs) element match {
case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits))
@ -388,6 +426,7 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
}
}
}
illegalAccess setWhen(privilege.asUInt < csrAddress(9 downto 8).asUInt)
}
}
}

View File

@ -111,5 +111,8 @@ object Riscv{
def MINSTRET = 0xB02 // MRW Machine instructions-retired counter.
def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, RV32I only.
def UCYCLE = 0xC00 // UR Machine ucycle counter.
}
}

View File

@ -40,6 +40,7 @@ object TopLevel {
val csrConfigAll = MachineCsrConfig(
catchIllegalAccess = true,
mvendorid = 11,
marchid = 22,
mimpid = 33,
@ -55,10 +56,12 @@ object TopLevel {
mcycleAccess = CsrAccess.READ_WRITE,
minstretAccess = CsrAccess.READ_WRITE,
ecallGen = true,
wfiGen = true
wfiGen = true,
ucycleAccess = CsrAccess.READ_ONLY
)
val csrConfigSmall = MachineCsrConfig(
catchIllegalAccess = false,
mvendorid = null,
marchid = null,
mimpid = null,
@ -74,10 +77,12 @@ object TopLevel {
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
wfiGen = false
wfiGen = false,
ucycleAccess = CsrAccess.NONE
)
val csrConfigSmallest = MachineCsrConfig(
catchIllegalAccess = false,
mvendorid = null,
marchid = null,
mimpid = null,
@ -93,7 +98,8 @@ object TopLevel {
mcycleAccess = CsrAccess.NONE,
minstretAccess = CsrAccess.NONE,
ecallGen = false,
wfiGen = false
wfiGen = false,
ucycleAccess = CsrAccess.NONE
)
val configFull = VexRiscvConfig(
@ -239,74 +245,63 @@ object TopLevel {
val configTest = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(0x00000000l, true),
// new IBusSimplePlugin(
// interfaceKeepData = true,
// catchAccessFault = false
// ),
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 4096,
bytePerLine =32,
wayCount = 1,
wrappedMemAccess = true,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = true,
catchAccessFault = true,
catchMemoryTranslationMiss = true,
asyncTagMemory = false,
twoStageLogic = true
),
askMemoryTranslation = true,
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 4
)
new IBusSimplePlugin(
interfaceKeepData = true,
catchAccessFault = true
),
// new IBusCachedPlugin(
// config = InstructionCacheConfig(
// cacheSize = 4096,
// bytePerLine =32,
// wayCount = 1,
// wrappedMemAccess = true,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchIllegalAccess = true,
// catchAccessFault = true,
// catchMemoryTranslationMiss = true,
// asyncTagMemory = false,
// twoStageLogic = true
// ),
// askMemoryTranslation = true,
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 4
// )
// ),
// new DBusSimplePlugin(
// catchAddressMisaligned = false,
// catchAccessFault = false
// ),
// new DBusCachedPlugin(
// config = new DataCacheConfig(
// cacheSize = 2048,
// bytePerLine = 32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchAccessFault = false
// )
// ),
new DBusCachedPlugin(
config = new DataCacheConfig(
cacheSize = 4096,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true,
tagSizeShift = 2
),
askMemoryTranslation = true,
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 6
)
new DBusSimplePlugin(
catchAddressMisaligned = true,
catchAccessFault = true
),
// new DBusCachedPlugin(
// config = new DataCacheConfig(
// cacheSize = 4096,
// bytePerLine = 32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchAccessError = true,
// catchIllegal = true,
// catchUnaligned = true,
// catchMemoryTranslationMiss = true,
// tagSizeShift = 2
// ),
// askMemoryTranslation = true,
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 6
// )
// ),
new MemoryTranslatorPlugin(
tlbSize = 32,
virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF
),
// new MemoryTranslatorPlugin(
// tlbSize = 32,
// virtualRange = _(31 downto 28) === 0xC,
// ioRange = _(31 downto 28) === 0xF
// ),
new CsrPlugin(csrConfigSmall),
new DecoderSimplePlugin(
catchIllegalInstruction = false
catchIllegalInstruction = true
),
new RegFilePlugin(
regFileReadyKind = Plugin.SYNC,
@ -329,12 +324,12 @@ object TopLevel {
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
),
// new MulPlugin,
// new DivPlugin,
// new MulPlugin,
// new DivPlugin,
// new MachineCsr(csrConfig),
new BranchPlugin(
earlyBranch = false,
catchAddressMisaligned = false,
catchAddressMisaligned = true,
prediction = NONE
)
)

View File

@ -5,7 +5,7 @@ TRACE_START=0
CSR=yes
MMU=yes
DHRYSTONE=yes
FREE_RTOS=yes
FREE_RTOS=no
REDO=10
REF=no
TRACE_WITH_TIME=no