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.
|
* Created by spinalvm on 21.03.17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
trait CsrAccess
|
trait CsrAccess{
|
||||||
|
def canWrite : Boolean = false
|
||||||
|
def canRead : Boolean = false
|
||||||
|
}
|
||||||
object CsrAccess {
|
object CsrAccess {
|
||||||
object WRITE_ONLY extends CsrAccess
|
object WRITE_ONLY extends CsrAccess{
|
||||||
object READ_ONLY extends CsrAccess
|
override def canWrite : Boolean = true
|
||||||
object READ_WRITE extends CsrAccess
|
}
|
||||||
|
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
|
object NONE extends CsrAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int)
|
case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int)
|
||||||
case class MachineCsrConfig(
|
case class MachineCsrConfig(
|
||||||
|
catchIllegalAccess : Boolean,
|
||||||
mvendorid : BigInt,
|
mvendorid : BigInt,
|
||||||
marchid : BigInt,
|
marchid : BigInt,
|
||||||
mimpid : BigInt,
|
mimpid : BigInt,
|
||||||
|
@ -36,9 +47,12 @@ case class MachineCsrConfig(
|
||||||
mbadaddrAccess : CsrAccess,
|
mbadaddrAccess : CsrAccess,
|
||||||
mcycleAccess : CsrAccess,
|
mcycleAccess : CsrAccess,
|
||||||
minstretAccess : CsrAccess,
|
minstretAccess : CsrAccess,
|
||||||
|
ucycleAccess : CsrAccess,
|
||||||
wfiGen : Boolean,
|
wfiGen : Boolean,
|
||||||
ecallGen : Boolean
|
ecallGen : Boolean
|
||||||
)
|
){
|
||||||
|
assert(!ucycleAccess.canWrite)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case class CsrWrite(that : Data, bitOffset : Int)
|
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 timerInterrupt : Bool = null
|
||||||
var externalInterrupt : Bool = null
|
var externalInterrupt : Bool = null
|
||||||
var privilege : Bits = null
|
var privilege : Bits = null
|
||||||
|
var selfException : Flow[ExceptionCause] = null
|
||||||
|
|
||||||
object EnvCtrlEnum extends SpinalEnum(binarySequential){
|
object EnvCtrlEnum extends SpinalEnum(binarySequential){
|
||||||
val NONE, EBREAK, MRET= newElement()
|
val NONE, EBREAK, MRET= newElement()
|
||||||
|
@ -144,6 +159,9 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
|
||||||
externalInterrupt = in Bool() setName("externalInterrupt")
|
externalInterrupt = in Bool() setName("externalInterrupt")
|
||||||
|
|
||||||
privilege = RegInit(B"11")
|
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(mimpid != null) READ_ONLY(CSR.MIMPID , U(mimpid ))
|
||||||
if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid ))
|
if(mhartid != null) READ_ONLY(CSR.MHARTID , U(mhartid ))
|
||||||
|
|
||||||
|
//Machine CSR
|
||||||
misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
|
misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
|
||||||
READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
|
READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
|
||||||
READ_WRITE(CSR.MIP, 3 -> mip.MSIP)
|
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.MINSTRET, minstret(31 downto 0))
|
||||||
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
|
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
|
||||||
|
|
||||||
|
//User CSR
|
||||||
|
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Manage counters
|
//Manage counters
|
||||||
|
@ -350,30 +372,46 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
|
||||||
execute plug new Area {
|
execute plug new Area {
|
||||||
import execute._
|
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 imm = IMM(input(INSTRUCTION))
|
||||||
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
|
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
|
||||||
val readData = B(0, 32 bits)
|
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(
|
val writeData = input(INSTRUCTION)(13).mux(
|
||||||
False -> writeSrc,
|
False -> writeSrc,
|
||||||
True -> Mux(input(INSTRUCTION)(12), memory.input(REGFILE_WRITE_DATA) & ~writeSrc, memory.input(REGFILE_WRITE_DATA) | 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)
|
val writeOpcode = (!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|
||||||
(!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|
|
||||||
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 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))
|
arbitration.haltIt setWhen(writeInstruction && !readDataRegValid)
|
||||||
val writeEnable = writeInstruction && !memory.arbitration.isValid && readDataRegValid
|
val writeEnable = writeInstruction && !arbitration.isStuckByOthers && !arbitration.removeIt && readDataRegValid
|
||||||
assert(!(arbitration.removeIt && writeEnable),"Can't remove CSR instruction when write occure")
|
|
||||||
|
|
||||||
when(arbitration.isValid && input(IS_CSR)) {
|
when(arbitration.isValid && input(IS_CSR)) {
|
||||||
output(REGFILE_WRITE_DATA) := readData
|
output(REGFILE_WRITE_DATA) := readData
|
||||||
}
|
}
|
||||||
|
|
||||||
//Translation of the csrMapping into real logic
|
//Translation of the csrMapping into real logic
|
||||||
switch(input(INSTRUCTION)(csrRange)) {
|
val csrAddress = input(INSTRUCTION)(csrRange)
|
||||||
|
switch(csrAddress) {
|
||||||
for ((address, jobs) <- csrMapping.mapping) {
|
for ((address, jobs) <- csrMapping.mapping) {
|
||||||
is(address) {
|
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) {
|
when(writeEnable) {
|
||||||
for (element <- jobs) element match {
|
for (element <- jobs) element match {
|
||||||
case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits))
|
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 MINSTRET = 0xB02 // MRW Machine instructions-retired counter.
|
||||||
def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
|
def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
|
||||||
def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, 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(
|
val csrConfigAll = MachineCsrConfig(
|
||||||
|
catchIllegalAccess = true,
|
||||||
mvendorid = 11,
|
mvendorid = 11,
|
||||||
marchid = 22,
|
marchid = 22,
|
||||||
mimpid = 33,
|
mimpid = 33,
|
||||||
|
@ -55,10 +56,12 @@ object TopLevel {
|
||||||
mcycleAccess = CsrAccess.READ_WRITE,
|
mcycleAccess = CsrAccess.READ_WRITE,
|
||||||
minstretAccess = CsrAccess.READ_WRITE,
|
minstretAccess = CsrAccess.READ_WRITE,
|
||||||
ecallGen = true,
|
ecallGen = true,
|
||||||
wfiGen = true
|
wfiGen = true,
|
||||||
|
ucycleAccess = CsrAccess.READ_ONLY
|
||||||
)
|
)
|
||||||
|
|
||||||
val csrConfigSmall = MachineCsrConfig(
|
val csrConfigSmall = MachineCsrConfig(
|
||||||
|
catchIllegalAccess = false,
|
||||||
mvendorid = null,
|
mvendorid = null,
|
||||||
marchid = null,
|
marchid = null,
|
||||||
mimpid = null,
|
mimpid = null,
|
||||||
|
@ -74,10 +77,12 @@ object TopLevel {
|
||||||
mcycleAccess = CsrAccess.NONE,
|
mcycleAccess = CsrAccess.NONE,
|
||||||
minstretAccess = CsrAccess.NONE,
|
minstretAccess = CsrAccess.NONE,
|
||||||
ecallGen = false,
|
ecallGen = false,
|
||||||
wfiGen = false
|
wfiGen = false,
|
||||||
|
ucycleAccess = CsrAccess.NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
val csrConfigSmallest = MachineCsrConfig(
|
val csrConfigSmallest = MachineCsrConfig(
|
||||||
|
catchIllegalAccess = false,
|
||||||
mvendorid = null,
|
mvendorid = null,
|
||||||
marchid = null,
|
marchid = null,
|
||||||
mimpid = null,
|
mimpid = null,
|
||||||
|
@ -93,7 +98,8 @@ object TopLevel {
|
||||||
mcycleAccess = CsrAccess.NONE,
|
mcycleAccess = CsrAccess.NONE,
|
||||||
minstretAccess = CsrAccess.NONE,
|
minstretAccess = CsrAccess.NONE,
|
||||||
ecallGen = false,
|
ecallGen = false,
|
||||||
wfiGen = false
|
wfiGen = false,
|
||||||
|
ucycleAccess = CsrAccess.NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
val configFull = VexRiscvConfig(
|
val configFull = VexRiscvConfig(
|
||||||
|
@ -239,74 +245,63 @@ object TopLevel {
|
||||||
val configTest = VexRiscvConfig(
|
val configTest = VexRiscvConfig(
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(0x00000000l, true),
|
new PcManagerSimplePlugin(0x00000000l, true),
|
||||||
// new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
// interfaceKeepData = true,
|
interfaceKeepData = true,
|
||||||
// catchAccessFault = false
|
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 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(
|
new DBusSimplePlugin(
|
||||||
// catchAddressMisaligned = false,
|
catchAddressMisaligned = true,
|
||||||
// catchAccessFault = false
|
catchAccessFault = true
|
||||||
// ),
|
),
|
||||||
// new DBusCachedPlugin(
|
// new DBusCachedPlugin(
|
||||||
// config = new DataCacheConfig(
|
// config = new DataCacheConfig(
|
||||||
// cacheSize = 2048,
|
// cacheSize = 4096,
|
||||||
// bytePerLine = 32,
|
// bytePerLine = 32,
|
||||||
// wayCount = 1,
|
// wayCount = 1,
|
||||||
// addressWidth = 32,
|
// addressWidth = 32,
|
||||||
// cpuDataWidth = 32,
|
// cpuDataWidth = 32,
|
||||||
// memDataWidth = 32,
|
// memDataWidth = 32,
|
||||||
// catchAccessFault = false
|
// catchAccessError = true,
|
||||||
|
// catchIllegal = true,
|
||||||
|
// catchUnaligned = true,
|
||||||
|
// catchMemoryTranslationMiss = true,
|
||||||
|
// tagSizeShift = 2
|
||||||
|
// ),
|
||||||
|
// askMemoryTranslation = true,
|
||||||
|
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||||
|
// portTlbSize = 6
|
||||||
// )
|
// )
|
||||||
// ),
|
// ),
|
||||||
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(
|
// new MemoryTranslatorPlugin(
|
||||||
tlbSize = 32,
|
// tlbSize = 32,
|
||||||
virtualRange = _(31 downto 28) === 0xC,
|
// virtualRange = _(31 downto 28) === 0xC,
|
||||||
ioRange = _(31 downto 28) === 0xF
|
// ioRange = _(31 downto 28) === 0xF
|
||||||
),
|
// ),
|
||||||
new CsrPlugin(csrConfigSmall),
|
new CsrPlugin(csrConfigSmall),
|
||||||
new DecoderSimplePlugin(
|
new DecoderSimplePlugin(
|
||||||
catchIllegalInstruction = false
|
catchIllegalInstruction = true
|
||||||
),
|
),
|
||||||
new RegFilePlugin(
|
new RegFilePlugin(
|
||||||
regFileReadyKind = Plugin.SYNC,
|
regFileReadyKind = Plugin.SYNC,
|
||||||
|
@ -334,7 +329,7 @@ object TopLevel {
|
||||||
// new MachineCsr(csrConfig),
|
// new MachineCsr(csrConfig),
|
||||||
new BranchPlugin(
|
new BranchPlugin(
|
||||||
earlyBranch = false,
|
earlyBranch = false,
|
||||||
catchAddressMisaligned = false,
|
catchAddressMisaligned = true,
|
||||||
prediction = NONE
|
prediction = NONE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,7 @@ TRACE_START=0
|
||||||
CSR=yes
|
CSR=yes
|
||||||
MMU=yes
|
MMU=yes
|
||||||
DHRYSTONE=yes
|
DHRYSTONE=yes
|
||||||
FREE_RTOS=yes
|
FREE_RTOS=no
|
||||||
REDO=10
|
REDO=10
|
||||||
REF=no
|
REF=no
|
||||||
TRACE_WITH_TIME=no
|
TRACE_WITH_TIME=no
|
||||||
|
|
Loading…
Reference in New Issue