CsrPlugin now catch illegal CSR access (wrong address + to low privilege level)
This commit is contained in:
parent
fe184636dd
commit
736478ff1d
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue