Fix granularity control
This commit is contained in:
parent
6471014131
commit
4a2dc0ff5f
|
@ -344,13 +344,13 @@ case class CsrDuringWrite(doThat :() => Unit)
|
|||
case class CsrDuringRead(doThat :() => Unit)
|
||||
case class CsrDuring(doThat :() => Unit)
|
||||
case class CsrOnRead(doThat : () => Unit)
|
||||
case class CsrAllow()
|
||||
|
||||
|
||||
case class CsrMapping() extends CsrInterface{
|
||||
case class CsrMapping() extends Area with CsrInterface {
|
||||
val mapping = mutable.LinkedHashMap[Int,ArrayBuffer[Any]]()
|
||||
val always = ArrayBuffer[Any]()
|
||||
val readDataSignal, readDataInit, writeDataSignal = Bits(32 bits)
|
||||
val allowCsrSignal = False
|
||||
val hazardFree = Bool()
|
||||
|
||||
readDataSignal := readDataInit
|
||||
|
@ -364,11 +364,11 @@ case class CsrMapping() extends CsrInterface{
|
|||
override def during(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrDuring(() => body))
|
||||
override def onRead(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrOnRead(() => {body}))
|
||||
override def duringAny(): Bool = ???
|
||||
override def duringAnyWrite(body: => Unit) : Unit = always += CsrDuringRead(() => body)
|
||||
override def duringAnyRead(body: => Unit) : Unit = always += CsrDuringWrite(() => body)
|
||||
override def duringAnyRead(body: => Unit) : Unit = always += CsrDuringRead(() => body)
|
||||
override def duringAnyWrite(body: => Unit) : Unit = always += CsrDuringWrite(() => body)
|
||||
override def readData() = readDataSignal
|
||||
override def writeData() = writeDataSignal
|
||||
override def allow(csrAddress: Int): Unit = addMappingAt(csrAddress, CsrAllow())
|
||||
override def allowCsr() = allowCsrSignal := True
|
||||
override def isHazardFree() = hazardFree
|
||||
}
|
||||
|
||||
|
@ -386,9 +386,9 @@ trait CsrInterface{
|
|||
r(csrAddress,bitOffset,that)
|
||||
w(csrAddress,bitOffset,that)
|
||||
}
|
||||
def allow(csrAddress: Int): Unit
|
||||
def duringAnyWrite(body: => Unit) : Unit //Called all the durration of a Csr write instruction in the execute stage
|
||||
def duringAnyRead(body: => Unit) : Unit //same than above for read
|
||||
def duringAnyRead(body: => Unit) : Unit //Called all the durration of a Csr write instruction in the execute stage
|
||||
def duringAnyWrite(body: => Unit) : Unit //same than above for read
|
||||
def allowCsr() : Unit //In case your csr do not use the regular API with csrAddress but is implemented using "side channels", you can call that if the current csr is implemented
|
||||
def isHazardFree() : Bool // You should not have any side effect nor use readData() until this return True
|
||||
|
||||
def r2w(csrAddress : Int, bitOffset : Int,that : Data): Unit
|
||||
|
@ -515,9 +515,9 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
override def duringRead(csrAddress: Int)(body: => Unit): Unit = csrMapping.duringRead(csrAddress)(body)
|
||||
override def during(csrAddress: Int)(body: => Unit): Unit = csrMapping.during(csrAddress)(body)
|
||||
override def duringAny(): Bool = pipeline.execute.arbitration.isValid && pipeline.execute.input(IS_CSR)
|
||||
override def duringAnyWrite(body: => Unit) = csrMapping.duringAnyWrite(body)
|
||||
override def duringAnyRead(body: => Unit) = csrMapping.duringAnyRead(body)
|
||||
override def allow(csrAddress: Int): Unit = csrMapping.allow(csrAddress)
|
||||
override def duringAnyWrite(body: => Unit) = csrMapping.duringAnyWrite(body)
|
||||
override def allowCsr() = csrMapping.allowCsr()
|
||||
override def readData() = csrMapping.readData()
|
||||
override def writeData() = csrMapping.writeData()
|
||||
override def isHazardFree() = csrMapping.isHazardFree()
|
||||
|
@ -1147,8 +1147,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
val readEnable = readInstruction && !arbitration.isStuck
|
||||
csrMapping.hazardFree := !blockedBySideEffects
|
||||
|
||||
val READDATASIGNAL = csrMapping.readDataSignal
|
||||
|
||||
val readToWriteData = CombInit(readData)
|
||||
writeData := (if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux(
|
||||
False -> writeSrc,
|
||||
|
@ -1183,7 +1181,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
} else {
|
||||
if (withWrite) illegalAccess.clearWhen(input(CSR_WRITE_OPCODE))
|
||||
if (withRead) illegalAccess.clearWhen(input(CSR_READ_OPCODE))
|
||||
if (jobs.exists(j => j.isInstanceOf[CsrAllow])) illegalAccess := False
|
||||
}
|
||||
|
||||
|
||||
|
@ -1269,6 +1266,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
case element : CsrDuringRead => when(readInstruction){element.doThat()}
|
||||
}
|
||||
|
||||
illegalAccess clearWhen(csrMapping.allowCsrSignal)
|
||||
|
||||
when(privilege < csrAddress(9 downto 8).asUInt){
|
||||
illegalAccess := True
|
||||
readInstruction := False
|
||||
|
|
|
@ -11,7 +11,6 @@ import vexriscv.plugin.MemoryTranslatorPort.{_}
|
|||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.fsm._
|
||||
import javax.net.ssl.TrustManager
|
||||
|
||||
/* Each 32-bit pmpcfg# register contains four 8-bit configuration sections.
|
||||
* These section numbers contain flags which apply to regions defined by the
|
||||
|
@ -79,15 +78,15 @@ trait Pmp {
|
|||
def lBit = 7
|
||||
}
|
||||
|
||||
class PmpSetter(grain : Int) extends Component with Pmp {
|
||||
class PmpSetter(cutoff : Int) extends Component with Pmp {
|
||||
val io = new Bundle {
|
||||
val addr = in UInt(xlen bits)
|
||||
val base, mask = out UInt(xlen - grain bits)
|
||||
val base, mask = out UInt(xlen - cutoff bits)
|
||||
}
|
||||
|
||||
val ones = io.addr & ~(io.addr + 1)
|
||||
io.base := io.addr(xlen - 1 - grain downto 0) ^ ones(xlen - 1 - grain downto 0)
|
||||
io.mask := ~ones(xlen - grain downto 1)
|
||||
io.base := io.addr(xlen - 3 downto cutoff - 2) ^ ones(xlen - 3 downto cutoff - 2)
|
||||
io.mask := ~ones(xlen - 2 downto cutoff - 1)
|
||||
}
|
||||
|
||||
case class ProtectedMemoryTranslatorPort(bus : MemoryTranslatorBus)
|
||||
|
@ -98,7 +97,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend
|
|||
|
||||
var setter : PmpSetter = null
|
||||
var dPort, iPort : ProtectedMemoryTranslatorPort = null
|
||||
val grain = log2Up(granularity) - 1
|
||||
val cutoff = log2Up(granularity) - 1
|
||||
|
||||
override def newTranslationPort(priority : Int, args : Any): MemoryTranslatorBus = {
|
||||
val port = ProtectedMemoryTranslatorPort(MemoryTranslatorBus(new MemoryTranslatorBusParameter(0, 0)))
|
||||
|
@ -110,7 +109,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend
|
|||
}
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
setter = new PmpSetter(grain)
|
||||
setter = new PmpSetter(cutoff)
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -123,7 +122,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend
|
|||
|
||||
val pmpaddr = Mem(UInt(xlen bits), regions)
|
||||
val pmpcfg = Vector.fill(regions)(Reg(Bits(8 bits)) init(0))
|
||||
val base, mask = Vector.fill(regions)(Reg(UInt(xlen - grain bits)))
|
||||
val base, mask = Vector.fill(regions)(Reg(UInt(xlen - cutoff bits)))
|
||||
|
||||
// object PMPCFG extends Stageable(Bool)
|
||||
// object PMPADDR extends Stageable(Bool)
|
||||
|
@ -313,7 +312,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend
|
|||
dPort.bus.rsp.allowExecute := False
|
||||
dPort.bus.busy := False
|
||||
|
||||
val hits = getHits(address(31 downto grain))
|
||||
val hits = getHits(address(31 downto cutoff))
|
||||
|
||||
when(~hits.orR) {
|
||||
dPort.bus.rsp.allowRead := privilegeService.isMachine()
|
||||
|
@ -335,7 +334,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend
|
|||
iPort.bus.rsp.allowWrite := False
|
||||
iPort.bus.busy := False
|
||||
|
||||
val hits = getHits(address(31 downto grain))
|
||||
val hits = getHits(address(31 downto cutoff))
|
||||
|
||||
when(~hits.orR) {
|
||||
iPort.bus.rsp.allowExecute := privilegeService.isMachine()
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
#define TRAP_RETURN x30
|
||||
#define TRAP_EXIT x9
|
||||
|
||||
#define PMPCFG0 0x07120000
|
||||
#define PMPCFG0_ 0x07920808
|
||||
#define PMPCFG0 0x071a0000
|
||||
#define PMPCFG0_ 0x079a0808
|
||||
#define PMPCFG1 0x191f0304
|
||||
#define PMPCFG2 0x000f090a
|
||||
#define PMPCFG3 0x0f1e1900
|
||||
#define PMPCFG3 0x1c1e1900
|
||||
|
||||
#define PMPADDR0 0x20000000 // OFF (test0) -> TOR (test1) -> OFF (test2)
|
||||
#define PMPADDR1 0xffffffff // OFF (test0) -> TOR (test1) -> OFF (test2)
|
||||
#define PMPADDR2 0x20002000 // NA4 W
|
||||
#define PMPADDR2 0x20200000 // NAPOT W
|
||||
#define PMPADDR3 0x20003fff // OFF RWX -> 0x00000000 OFF RWX (test2)
|
||||
#define PMPADDR4 0x20003fff // OFF X
|
||||
#define PMPADDR5 0x20003fff // OFF RW
|
||||
|
@ -29,7 +29,7 @@
|
|||
#define PMPADDR12 0x00000000 // OFF
|
||||
#define PMPADDR13 0x00000000 // NAPOT R
|
||||
#define PMPADDR14 0x00000000 // NAPOT WX
|
||||
#define PMPADDR15 0x00000000 // TOR RWX
|
||||
#define PMPADDR15 0x000001ff // NAPOT X
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
@ -71,6 +71,8 @@ test0:
|
|||
csrw pmpcfg1, x5
|
||||
li x5, PMPCFG2
|
||||
csrw pmpcfg2, x5
|
||||
csrr x6, pmpcfg2
|
||||
bne x5, x6, fail
|
||||
li x5, PMPCFG3
|
||||
csrw pmpcfg3, x5
|
||||
li x5, PMPADDR0
|
||||
|
@ -125,11 +127,11 @@ test1:
|
|||
csrw pmpcfg0, x5 // lock region 2
|
||||
csrr x6, pmpcfg0
|
||||
bne x5, x6, fail
|
||||
li x1, 0x80008000
|
||||
li x1, 0x80800000
|
||||
li x2, 0xdeadbeef
|
||||
sw x2, 0x0(x1) // should be OK (write 0x80008000)
|
||||
sw x2, 0x0(x1) // should be OK (write 0x80800000)
|
||||
la TRAP_RETURN, test2
|
||||
lw x3, 0x0(x1) // should fault (read 0x80008000)
|
||||
lw x3, 0x0(x1) // should fault (read 0x80800000)
|
||||
j fail
|
||||
|
||||
// "unlock" region 2, attempt read/write from machine mode
|
||||
|
@ -140,21 +142,17 @@ test2:
|
|||
csrw pmpcfg0, x5 // "unlock" region 2
|
||||
csrr x6, pmpcfg0
|
||||
beq x5, x6, fail
|
||||
li x5, PMPADDR3
|
||||
csrwi pmpaddr3, 0x0
|
||||
csrr x6, pmpaddr3
|
||||
bnez x6, fail
|
||||
beq x5, x6, fail
|
||||
li x5, PMPADDR2
|
||||
bnez x6, fail
|
||||
csrwi pmpaddr2, 0x0
|
||||
csrr x6, pmpaddr2
|
||||
beqz x6, fail
|
||||
bne x5, x6, fail
|
||||
li x1, 0x80008000
|
||||
beqz x6, fail
|
||||
li x1, 0x80800000
|
||||
li x2, 0xdeadbeef
|
||||
sw x2, 0x0(x1) // should still be OK (write 0x80008000)
|
||||
sw x2, 0x0(x1) // should still be OK (write 0x80800000)
|
||||
la TRAP_RETURN, test3
|
||||
lw x3, 0x0(x1) // should still fault (read 0x80008000)
|
||||
lw x3, 0x0(x1) // should still fault (read 0x80800000)
|
||||
j fail
|
||||
|
||||
// verify masked CSR read/write operations
|
||||
|
@ -178,12 +176,12 @@ test3:
|
|||
li x5, 0x00ff00ff
|
||||
csrc pmpcfg0, x5
|
||||
csrr x6, pmpcfg0
|
||||
li x5, 0x07920000
|
||||
li x5, 0x079a0000
|
||||
bne x5, x6, fail
|
||||
li x5, 0x00ff0707
|
||||
csrs pmpcfg0, x5
|
||||
csrr x6, pmpcfg0
|
||||
li x5, 0x07920707
|
||||
li x5, 0x079a0707
|
||||
bne x5, x6, fail
|
||||
|
||||
// jump into user mode
|
||||
|
@ -192,6 +190,7 @@ test4:
|
|||
la TRAP_RETURN, fail
|
||||
la x2, test5
|
||||
csrw mepc, x2
|
||||
# j pass
|
||||
mret
|
||||
|
||||
// attempt to read/write region 2 from user mode
|
||||
|
@ -199,10 +198,10 @@ test5:
|
|||
li TEST_ID, 5
|
||||
la TRAP_RETURN, fail
|
||||
li x2, 0xdeadbeef
|
||||
li x1, 0x80008000
|
||||
sw x2, 0x0(x1) // should be OK (write 0x80008000)
|
||||
li x1, 0x80800000
|
||||
sw x2, 0x0(x1) // should be OK (write 0x80800000)
|
||||
la TRAP_RETURN, test6
|
||||
lw x3, 0x0(x1) // should fault (read 0x80008000)
|
||||
lw x3, 0x0(x1) // should fault (read 0x80800000)
|
||||
j fail
|
||||
|
||||
// attempt to read/write other regions from user mode
|
||||
|
|
Loading…
Reference in New Issue