From bf399cc927ceb158a7fc72b89078164488b50b91 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Fri, 26 Mar 2021 10:12:03 +0100 Subject: [PATCH 01/14] Initial commit of optimized PMP plugin --- .../scala/vexriscv/plugin/CsrPlugin.scala | 50 ++- .../scala/vexriscv/plugin/PmpPlugin.scala | 367 +++++++++++------- src/test/cpp/raw/pmp/build/pmp.asm | 243 +++++++----- src/test/cpp/raw/pmp/build/pmp.elf | Bin 5480 -> 5680 bytes src/test/cpp/raw/pmp/build/pmp.hex | 68 ++-- src/test/cpp/raw/pmp/build/pmp.map | 24 +- src/test/cpp/raw/pmp/src/crt.S | 89 +++-- 7 files changed, 521 insertions(+), 320 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index c980fa8..7f4c774 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -32,6 +32,14 @@ object CsrAccess { object NONE extends CsrAccess } +object CsrPlugin { + object IS_CSR extends Stageable(Bool) + object CSR_WRITE_OPCODE extends Stageable(Bool) + object CSR_READ_OPCODE extends Stageable(Bool) + object IS_PMP_CFG extends Stageable(Bool) + object IS_PMP_ADDR extends Stageable(Bool) +} + case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int) case class CsrPluginConfig( catchIllegalAccess : Boolean, @@ -399,6 +407,7 @@ trait IWake{ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface with IWake{ import config._ import CsrAccess._ + import CsrPlugin._ assert(!(wfiGenAsNop && wfiGenAsWait)) @@ -440,9 +449,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } object ENV_CTRL extends Stageable(EnvCtrlEnum()) - object IS_CSR extends Stageable(Bool) - object CSR_WRITE_OPCODE extends Stageable(Bool) - object CSR_READ_OPCODE extends Stageable(Bool) object PIPELINED_CSR_READ extends Stageable(Bits(32 bits)) var allowInterrupts : Bool = null @@ -1029,9 +1035,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep || (input(INSTRUCTION)(14 downto 13) === B"11" && imm.z === 0) ) insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000" + + if (pipeline.serviceExist(classOf[PmpPlugin])) { + insert(IS_PMP_CFG) := input(INSTRUCTION)(31 downto 24) === 0x3a + insert(IS_PMP_ADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b + } } - execute plug new Area{ import execute._ //Manage WFI instructions @@ -1103,25 +1113,27 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc) ) - when(arbitration.isValid && input(IS_CSR)) { - if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData - arbitration.haltItself setWhen(blockedBySideEffects) - } - if(pipelineCsrRead){ - insert(PIPELINED_CSR_READ) := readData - when(memory.arbitration.isValid && memory.input(IS_CSR)) { - memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ) + val csrAddress = input(INSTRUCTION)(csrRange) + val pmpAccess = if (pipeline.serviceExist(classOf[PmpPlugin])) { + input(IS_PMP_CFG) | input(IS_PMP_ADDR) + } else False + + when (~pmpAccess) { + when(arbitration.isValid && input(IS_CSR)) { + if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData + arbitration.haltItself setWhen(blockedBySideEffects) } + if(pipelineCsrRead){ + insert(PIPELINED_CSR_READ) := readData + when(memory.arbitration.isValid && memory.input(IS_CSR)) { + memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ) + } + } + }.elsewhen(arbitration.isValid && input(IS_CSR)) { + illegalAccess := False } -// -// Component.current.rework{ -// when(arbitration.isFiring && input(IS_CSR)) { -// memory.input(REGFILE_WRITE_DATA).getDrivingReg := readData -// } -// } //Translation of the csrMapping into real logic - val csrAddress = input(INSTRUCTION)(csrRange) Component.current.afterElaboration{ def doJobs(jobs : ArrayBuffer[Any]): Unit ={ val withWrite = jobs.exists(j => j.isInstanceOf[CsrWrite] || j.isInstanceOf[CsrOnWrite] || j.isInstanceOf[CsrDuringWrite]) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index e6cb396..357d5b8 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samuel Lindemer + * Copyright (c) 2021 Samuel Lindemer * * SPDX-License-Identifier: MIT */ @@ -7,9 +7,11 @@ package vexriscv.plugin import vexriscv.{VexRiscv, _} +import vexriscv.plugin.CsrPlugin.{_} +import vexriscv.plugin.MemoryTranslatorPort.{_} import spinal.core._ import spinal.lib._ -import scala.collection.mutable.ArrayBuffer +import spinal.lib.fsm._ /* Each 32-bit pmpcfg# register contains four 8-bit configuration sections. * These section numbers contain flags which apply to regions defined by the @@ -63,104 +65,70 @@ import scala.collection.mutable.ArrayBuffer * register defines a 4-byte wide region. */ -case class PmpRegister(previous : PmpRegister) extends Area { - +trait Pmp { def OFF = 0 def TOR = 1 def NA4 = 2 def NAPOT = 3 - val state = new Area { - val r, w, x = Reg(Bool) - val l = RegInit(False) - val a = Reg(UInt(2 bits)) init(0) - val addr = Reg(UInt(32 bits)) + def xlen = 32 + def rBit = 0 + def wBit = 1 + def xBit = 2 + def aBits = 4 downto 3 + def lBit = 7 +} + +class PmpSetter() extends Component with Pmp { + val io = new Bundle { + val a = in Bits(2 bits) + val addr = in UInt(xlen bits) + val prevHi = in UInt(30 bits) + val boundLo, boundHi = out UInt(30 bits) } - // CSR writes connect to these signals rather than the internal state - // registers. This makes locking and WARL possible. - val csr = new Area { - val r, w, x = Bool - val l = Bool - val a = UInt(2 bits) - val addr = UInt(32 bits) - } + val shifted = io.addr(29 downto 0) + io.boundLo := shifted + io.boundHi := shifted - // Last valid assignment wins; nothing happens if a user-initiated write did - // not occur on this clock cycle. - csr.r := state.r - csr.w := state.w - csr.x := state.x - csr.l := state.l - csr.a := state.a - csr.addr := state.addr - - // Computed PMP region bounds - val region = new Area { - val valid, locked = Bool - val start, end = UInt(32 bits) - } - - when(~state.l) { - state.r := csr.r - state.w := csr.w - state.x := csr.x - state.l := csr.l - state.a := csr.a - state.addr := csr.addr - - if (csr.l == True & csr.a == TOR) { - previous.state.l := True + switch (io.a) { + is (TOR) { + io.boundLo := io.prevHi } - } - - val shifted = state.addr |<< 2 - val mask = state.addr & ~(state.addr + 1) - val masked = (state.addr & ~mask) |<< 2 - - // PMP changes take effect two clock cycles after the initial CSR write (i.e., - // settings propagate from csr -> state -> region). - region.locked := state.l - region.valid := True - - switch(csr.a) { - is(TOR) { - if (previous == null) region.start := 0 - else region.start := previous.region.end - region.end := shifted + is (NA4) { + io.boundHi := shifted + 1 } - is(NA4) { - region.start := shifted - region.end := shifted + 4 - } - is(NAPOT) { - region.start := masked - region.end := masked + ((mask + 1) |<< 3) - } - default { - region.start := 0 - region.end := shifted - region.valid := False + is (NAPOT) { + val mask = io.addr & ~(io.addr + 1) + val boundLo = (io.addr ^ mask)(29 downto 0) + io.boundLo := boundLo + io.boundHi := boundLo + ((mask + 1) |<< 3)(29 downto 0) } } } case class ProtectedMemoryTranslatorPort(bus : MemoryTranslatorBus) -class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator { - - // Each pmpcfg# CSR configures four regions. - assert((regions % 4) == 0) - - val pmps = ArrayBuffer[PmpRegister]() - val portsInfo = ArrayBuffer[ProtectedMemoryTranslatorPort]() +class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator with Pmp { + assert(regions % 4 == 0) + assert(regions <= 16) + var setter : PmpSetter = null + var dPort, iPort : ProtectedMemoryTranslatorPort = null + override def newTranslationPort(priority : Int, args : Any): MemoryTranslatorBus = { val port = ProtectedMemoryTranslatorPort(MemoryTranslatorBus(new MemoryTranslatorBusParameter(0, 0))) - portsInfo += port + priority match { + case PRIORITY_INSTRUCTION => iPort = port + case PRIORITY_DATA => dPort = port + } port.bus } + override def setup(pipeline: VexRiscv): Unit = { + setter = new PmpSetter() + } + override def build(pipeline: VexRiscv): Unit = { import pipeline.config._ import pipeline._ @@ -169,78 +137,201 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] val csrService = pipeline.service(classOf[CsrInterface]) val privilegeService = pipeline.service(classOf[PrivilegeService]) - val core = pipeline plug new Area { + val pmpaddr = Mem(UInt(xlen bits), regions) + val pmpcfg = Reg(Bits(8 * regions bits)) init(0) + val boundLo, boundHi = Mem(UInt(30 bits), regions) + val cfgRegion = pmpcfg.subdivideIn(8 bits) + val cfgRegister = pmpcfg.subdivideIn(xlen bits) + val lockMask = Reg(Bits(4 bits)) init(B"4'0") - // Instantiate pmpaddr0 ... pmpaddr# CSRs. - for (i <- 0 until regions) { - if (i == 0) { - pmps += PmpRegister(null) - } else { - pmps += PmpRegister(pmps.last) + execute plug new Area { + import execute._ + + val csrAddress = input(INSTRUCTION)(csrRange) + val accessAddr = input(IS_PMP_ADDR) + val accessCfg = input(IS_PMP_CFG) + val pmpWrite = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) & (accessAddr | accessCfg) + val pmpRead = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) & (accessAddr | accessCfg) + val pmpIndex = csrAddress(log2Up(regions) - 1 downto 0).asUInt + val pmpSelect = pmpIndex(log2Up(regions) - 3 downto 0) + + val readAddr = pmpaddr.readAsync(pmpIndex).asBits + val readCfg = cfgRegister(pmpSelect) + val readToWrite = Mux(accessCfg, readCfg, readAddr) + val writeSrc = input(SRC1) + val writeData = input(INSTRUCTION)(13).mux( + False -> writeSrc, + True -> Mux( + input(INSTRUCTION)(12), + readToWrite & ~writeSrc, + readToWrite | writeSrc + ) + ) + + val writer = new Area { + when (accessCfg) { + when (pmpRead) { + output(REGFILE_WRITE_DATA).assignFromBits(readCfg) + } + when (pmpWrite) { + switch(pmpSelect) { + for (i <- 0 until (regions / 4)) { + is(i) { + for (j <- Range(0, xlen, 8)) { + val bitRange = j + xlen * i + lBit downto j + xlen * i + val overwrite = writeData.subdivideIn(8 bits)(j / 8) + val locked = cfgRegister(i).subdivideIn(8 bits)(j / 8)(lBit) + lockMask(j / 8) := locked + when (~locked) { + pmpcfg(bitRange).assignFromBits(overwrite) + if (j != 0 || i != 0) { + when (overwrite(lBit) & overwrite(aBits) === TOR) { + pmpcfg(j + xlen * i - 1) := True + } + } + } + } + } + } + } + } + }.elsewhen (accessAddr) { + when (pmpRead) { + output(REGFILE_WRITE_DATA) := readAddr + } } - csrService.r(0x3b0 + i, pmps(i).state.addr) - csrService.w(0x3b0 + i, pmps(i).csr.addr) + val locked = cfgRegion(pmpIndex)(lBit) + pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & pmpWrite & accessAddr) } - // Instantiate pmpcfg0 ... pmpcfg# CSRs. - for (i <- 0 until (regions / 4)) { - csrService.r(0x3a0 + i, - 31 -> pmps((i * 4) + 3).state.l, 23 -> pmps((i * 4) + 2).state.l, - 15 -> pmps((i * 4) + 1).state.l, 7 -> pmps((i * 4) ).state.l, - 27 -> pmps((i * 4) + 3).state.a, 26 -> pmps((i * 4) + 3).state.x, - 25 -> pmps((i * 4) + 3).state.w, 24 -> pmps((i * 4) + 3).state.r, - 19 -> pmps((i * 4) + 2).state.a, 18 -> pmps((i * 4) + 2).state.x, - 17 -> pmps((i * 4) + 2).state.w, 16 -> pmps((i * 4) + 2).state.r, - 11 -> pmps((i * 4) + 1).state.a, 10 -> pmps((i * 4) + 1).state.x, - 9 -> pmps((i * 4) + 1).state.w, 8 -> pmps((i * 4) + 1).state.r, - 3 -> pmps((i * 4) ).state.a, 2 -> pmps((i * 4) ).state.x, - 1 -> pmps((i * 4) ).state.w, 0 -> pmps((i * 4) ).state.r - ) - csrService.w(0x3a0 + i, - 31 -> pmps((i * 4) + 3).csr.l, 23 -> pmps((i * 4) + 2).csr.l, - 15 -> pmps((i * 4) + 1).csr.l, 7 -> pmps((i * 4) ).csr.l, - 27 -> pmps((i * 4) + 3).csr.a, 26 -> pmps((i * 4) + 3).csr.x, - 25 -> pmps((i * 4) + 3).csr.w, 24 -> pmps((i * 4) + 3).csr.r, - 19 -> pmps((i * 4) + 2).csr.a, 18 -> pmps((i * 4) + 2).csr.x, - 17 -> pmps((i * 4) + 2).csr.w, 16 -> pmps((i * 4) + 2).csr.r, - 11 -> pmps((i * 4) + 1).csr.a, 10 -> pmps((i * 4) + 1).csr.x, - 9 -> pmps((i * 4) + 1).csr.w, 8 -> pmps((i * 4) + 1).csr.r, - 3 -> pmps((i * 4) ).csr.a, 2 -> pmps((i * 4) ).csr.x, - 1 -> pmps((i * 4) ).csr.w, 0 -> pmps((i * 4) ).csr.r - ) - } + val controller = new StateMachine { + val counter = Reg(UInt(log2Up(regions) bits)) init(0) + val enable = RegInit(False) - // Connect memory ports to PMP logic. - val ports = for ((port, portId) <- portsInfo.zipWithIndex) yield new Area { + val stateIdle : State = new State with EntryPoint { + onEntry { + lockMask := B"4'x0" + enable := False + counter := 0 + } + onExit { + enable := True + arbitration.haltItself := True + } + whenIsActive { + when (pmpWrite) { + when (accessCfg) { + goto(stateCfg) + }.elsewhen (accessAddr) { + goto(stateAddr) + } + } + } + } - val address = port.bus.cmd(0).virtualAddress - port.bus.rsp.physicalAddress := address + val stateCfg : State = new State { + onEntry (counter := pmpIndex(log2Up(regions) - 3 downto 0) @@ U"2'00") + whenIsActive { + counter := counter + 1 + when (counter(1 downto 0) === 3) { + goto(stateIdle) + } otherwise { + arbitration.haltItself := True + } + } + } - // Only the first matching PMP region applies. - val hits = pmps.map(pmp => pmp.region.valid & - pmp.region.start <= address & - pmp.region.end > address & - (pmp.region.locked | ~privilegeService.isMachine())) + val stateAddr : State = new State { + onEntry (counter := pmpIndex) + whenIsActive { + counter := counter + 1 + when (counter === (pmpIndex + 1) | counter === 0) { + goto(stateIdle) + } otherwise { + arbitration.haltItself := True + } + } + } - // M-mode has full access by default, others have none. - when(CountOne(hits) === 0) { - port.bus.rsp.allowRead := privilegeService.isMachine() - port.bus.rsp.allowWrite := privilegeService.isMachine() - port.bus.rsp.allowExecute := privilegeService.isMachine() + when (accessCfg) { + setter.io.a := writeData.subdivideIn(8 bits)(counter(1 downto 0))(aBits) + setter.io.addr := pmpaddr(counter) } otherwise { - port.bus.rsp.allowRead := MuxOH(OHMasking.first(hits), pmps.map(_.state.r)) - port.bus.rsp.allowWrite := MuxOH(OHMasking.first(hits), pmps.map(_.state.w)) - port.bus.rsp.allowExecute := MuxOH(OHMasking.first(hits), pmps.map(_.state.x)) + setter.io.a := cfgRegion(counter)(aBits) + when (counter === pmpIndex) { + setter.io.addr := writeData.asUInt + } otherwise { + setter.io.addr := pmpaddr(counter) + } } + + when (counter === 0) { + setter.io.prevHi := 0 + } otherwise { + setter.io.prevHi := boundHi(counter - 1) + } + + when (enable & + ((accessCfg & ~lockMask(counter(1 downto 0))) | + (accessAddr & ~cfgRegion(counter)(lBit)))) { + boundLo(counter) := setter.io.boundLo + boundHi(counter) := setter.io.boundHi + } + } + } - port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress) - port.bus.rsp.isPaging := False - port.bus.rsp.exception := False - port.bus.rsp.refilling := False - port.bus.busy := False + pipeline plug new Area { + def getHits(address : UInt) = { + (0 until regions).map(i => + address >= boundLo(U(i, log2Up(regions) bits)) & + address < boundHi(U(i, log2Up(regions) bits)) & + (cfgRegion(i)(lBit) | ~privilegeService.isMachine()) & + cfgRegion(i)(aBits) =/= 0 + ) + } + val dGuard = new Area { + val address = dPort.bus.cmd(0).virtualAddress + dPort.bus.rsp.physicalAddress := address + dPort.bus.rsp.isIoAccess := ioRange(address) + dPort.bus.rsp.isPaging := False + dPort.bus.rsp.exception := False + dPort.bus.rsp.refilling := False + dPort.bus.rsp.allowExecute := False + dPort.bus.busy := False + + val hits = getHits(address(31 downto 2)) + + when(~hits.orR) { + dPort.bus.rsp.allowRead := privilegeService.isMachine() + dPort.bus.rsp.allowWrite := privilegeService.isMachine() + } otherwise { + val oneHot = OHMasking.first(hits) + dPort.bus.rsp.allowRead := MuxOH(oneHot, cfgRegion.map(cfg => cfg(rBit))) + dPort.bus.rsp.allowWrite := MuxOH(oneHot, cfgRegion.map(cfg => cfg(wBit))) + } + } + + val iGuard = new Area { + val address = iPort.bus.cmd(0).virtualAddress + iPort.bus.rsp.physicalAddress := address + iPort.bus.rsp.isIoAccess := ioRange(address) + iPort.bus.rsp.isPaging := False + iPort.bus.rsp.exception := False + iPort.bus.rsp.refilling := False + iPort.bus.rsp.allowRead := False + iPort.bus.rsp.allowWrite := False + iPort.bus.busy := False + + val hits = getHits(address(31 downto 2)) + + when(~hits.orR) { + iPort.bus.rsp.allowExecute := privilegeService.isMachine() + } otherwise { + val oneHot = OHMasking.first(hits) + iPort.bus.rsp.allowExecute := MuxOH(oneHot, cfgRegion.map(cfg => cfg(xBit))) + } } } } -} - +} \ No newline at end of file diff --git a/src/test/cpp/raw/pmp/build/pmp.asm b/src/test/cpp/raw/pmp/build/pmp.asm index 4508ee6..c1fa1b7 100644 --- a/src/test/cpp/raw/pmp/build/pmp.asm +++ b/src/test/cpp/raw/pmp/build/pmp.asm @@ -17,26 +17,26 @@ Disassembly of section .crt_section: 80000018 : 80000018: 00000e13 li t3,0 8000001c: 00000f17 auipc t5,0x0 -80000020: 27cf0f13 addi t5,t5,636 # 80000298 +80000020: 330f0f13 addi t5,t5,816 # 8000034c 80000024: 800000b7 lui ra,0x80000 80000028: 80008237 lui tp,0x80008 8000002c: deadc137 lui sp,0xdeadc -80000030: eef10113 addi sp,sp,-273 # deadbeef -80000034: 0020a023 sw sp,0(ra) # 80000000 -80000038: 00222023 sw sp,0(tp) # 80008000 +80000030: eef10113 addi sp,sp,-273 # deadbeef +80000034: 0020a023 sw sp,0(ra) # 80000000 +80000038: 00222023 sw sp,0(tp) # 80008000 8000003c: 0000a183 lw gp,0(ra) -80000040: 24311c63 bne sp,gp,80000298 +80000040: 30311663 bne sp,gp,8000034c 80000044: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000048: 24311863 bne sp,gp,80000298 +80000048: 30311263 bne sp,gp,8000034c 8000004c: 071202b7 lui t0,0x7120 80000050: 3a029073 csrw pmpcfg0,t0 80000054: 3a002373 csrr t1,pmpcfg0 -80000058: 24629063 bne t0,t1,80000298 +80000058: 2e629a63 bne t0,t1,8000034c 8000005c: 191f02b7 lui t0,0x191f0 80000060: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc> 80000064: 3a129073 csrw pmpcfg1,t0 -80000068: 000f02b7 lui t0,0xf0 -8000006c: 50628293 addi t0,t0,1286 # f0506 <_start-0x7ff0fafa> +80000068: 000f12b7 lui t0,0xf1 +8000006c: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> 80000070: 3a229073 csrw pmpcfg2,t0 80000074: 0f1e22b7 lui t0,0xf1e2 80000078: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> @@ -44,7 +44,7 @@ Disassembly of section .crt_section: 80000080: 200002b7 lui t0,0x20000 80000084: 3b029073 csrw pmpaddr0,t0 80000088: 3b002373 csrr t1,pmpaddr0 -8000008c: 20629663 bne t0,t1,80000298 +8000008c: 2c629063 bne t0,t1,8000034c 80000090: fff00293 li t0,-1 80000094: 3b129073 csrw pmpaddr1,t0 80000098: 200022b7 lui t0,0x20002 @@ -85,119 +85,166 @@ Disassembly of section .crt_section: 80000124: 0020a023 sw sp,0(ra) 80000128: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> 8000012c: 0000a183 lw gp,0(ra) -80000130: 16311463 bne sp,gp,80000298 +80000130: 20311e63 bne sp,gp,8000034c 80000134: 00000193 li gp,0 80000138: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -8000013c: 14311e63 bne sp,gp,80000298 +8000013c: 20311863 bne sp,gp,8000034c 80000140 : 80000140: 00100e13 li t3,1 80000144: 00000f17 auipc t5,0x0 -80000148: 154f0f13 addi t5,t5,340 # 80000298 +80000148: 208f0f13 addi t5,t5,520 # 8000034c 8000014c: 079212b7 lui t0,0x7921 80000150: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8> 80000154: 3a029073 csrw pmpcfg0,t0 80000158: 3a002373 csrr t1,pmpcfg0 -8000015c: 12629e63 bne t0,t1,80000298 +8000015c: 1e629863 bne t0,t1,8000034c 80000160: 800080b7 lui ra,0x80008 80000164: deadc137 lui sp,0xdeadc -80000168: eef10113 addi sp,sp,-273 # deadbeef -8000016c: 0020a023 sw sp,0(ra) # 80008000 +80000168: eef10113 addi sp,sp,-273 # deadbeef +8000016c: 0020a023 sw sp,0(ra) # 80008000 80000170: 00000f17 auipc t5,0x0 80000174: 010f0f13 addi t5,t5,16 # 80000180 80000178: 0000a183 lw gp,0(ra) -8000017c: 11c0006f j 80000298 +8000017c: 1d00006f j 8000034c 80000180 : 80000180: 00200e13 li t3,2 80000184: 00000f17 auipc t5,0x0 -80000188: 114f0f13 addi t5,t5,276 # 80000298 +80000188: 1c8f0f13 addi t5,t5,456 # 8000034c 8000018c: 071202b7 lui t0,0x7120 80000190: 3a029073 csrw pmpcfg0,t0 80000194: 3a002373 csrr t1,pmpcfg0 -80000198: 3b205073 csrwi pmpaddr2,0 -8000019c: 3b202373 csrr t1,pmpaddr2 -800001a0: 0e030c63 beqz t1,80000298 -800001a4: 0e628a63 beq t0,t1,80000298 -800001a8: 800080b7 lui ra,0x80008 -800001ac: deadc137 lui sp,0xdeadc -800001b0: eef10113 addi sp,sp,-273 # deadbeef -800001b4: 0020a023 sw sp,0(ra) # 80008000 -800001b8: 00000f17 auipc t5,0x0 -800001bc: 010f0f13 addi t5,t5,16 # 800001c8 -800001c0: 0000a183 lw gp,0(ra) -800001c4: 0d40006f j 80000298 +80000198: 1a628a63 beq t0,t1,8000034c +8000019c: 200042b7 lui t0,0x20004 +800001a0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800001a4: 3b305073 csrwi pmpaddr3,0 +800001a8: 3b302373 csrr t1,pmpaddr3 +800001ac: 1a031063 bnez t1,8000034c +800001b0: 18628e63 beq t0,t1,8000034c +800001b4: 200022b7 lui t0,0x20002 +800001b8: 3b205073 csrwi pmpaddr2,0 +800001bc: 3b202373 csrr t1,pmpaddr2 +800001c0: 18030663 beqz t1,8000034c +800001c4: 18629463 bne t0,t1,8000034c +800001c8: 800080b7 lui ra,0x80008 +800001cc: deadc137 lui sp,0xdeadc +800001d0: eef10113 addi sp,sp,-273 # deadbeef +800001d4: 0020a023 sw sp,0(ra) # 80008000 +800001d8: 00000f17 auipc t5,0x0 +800001dc: 010f0f13 addi t5,t5,16 # 800001e8 +800001e0: 0000a183 lw gp,0(ra) +800001e4: 1680006f j 8000034c -800001c8 : -800001c8: 00300e13 li t3,3 -800001cc: 00000f17 auipc t5,0x0 -800001d0: 0ccf0f13 addi t5,t5,204 # 80000298 -800001d4: 00000117 auipc sp,0x0 -800001d8: 01010113 addi sp,sp,16 # 800001e4 -800001dc: 34111073 csrw mepc,sp -800001e0: 30200073 mret +800001e8 : +800001e8: 00300e13 li t3,3 +800001ec: 00000f17 auipc t5,0x0 +800001f0: 160f0f13 addi t5,t5,352 # 8000034c +800001f4: 00ff02b7 lui t0,0xff0 +800001f8: 3b32a073 csrs pmpaddr3,t0 +800001fc: 3b302373 csrr t1,pmpaddr3 +80000200: 14629663 bne t0,t1,8000034c +80000204: 0ff00293 li t0,255 +80000208: 3b32a073 csrs pmpaddr3,t0 +8000020c: 3b302373 csrr t1,pmpaddr3 +80000210: 00ff02b7 lui t0,0xff0 +80000214: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000218: 12629a63 bne t0,t1,8000034c +8000021c: 00ff02b7 lui t0,0xff0 +80000220: 3b32b073 csrc pmpaddr3,t0 +80000224: 3b302373 csrr t1,pmpaddr3 +80000228: 0ff00293 li t0,255 +8000022c: 12629063 bne t0,t1,8000034c +80000230: 00ff02b7 lui t0,0xff0 +80000234: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000238: 3a02b073 csrc pmpcfg0,t0 +8000023c: 3a002373 csrr t1,pmpcfg0 +80000240: 079202b7 lui t0,0x7920 +80000244: 10629463 bne t0,t1,8000034c +80000248: 00ff02b7 lui t0,0xff0 +8000024c: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> +80000250: 3a02a073 csrs pmpcfg0,t0 +80000254: 3a002373 csrr t1,pmpcfg0 +80000258: 079202b7 lui t0,0x7920 +8000025c: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9> +80000260: 0e629663 bne t0,t1,8000034c -800001e4 : -800001e4: 00400e13 li t3,4 -800001e8: 00000f17 auipc t5,0x0 -800001ec: 0b0f0f13 addi t5,t5,176 # 80000298 -800001f0: deadc137 lui sp,0xdeadc -800001f4: eef10113 addi sp,sp,-273 # deadbeef -800001f8: 800080b7 lui ra,0x80008 -800001fc: 0020a023 sw sp,0(ra) # 80008000 -80000200: 00000f17 auipc t5,0x0 -80000204: 010f0f13 addi t5,t5,16 # 80000210 -80000208: 0000a183 lw gp,0(ra) -8000020c: 08c0006f j 80000298 - -80000210 : -80000210: 00500e13 li t3,5 -80000214: deadc137 lui sp,0xdeadc -80000218: eef10113 addi sp,sp,-273 # deadbeef -8000021c: 800000b7 lui ra,0x80000 -80000220: 0020a023 sw sp,0(ra) # 80000000 -80000224: 0000a183 lw gp,0(ra) -80000228: 06311863 bne sp,gp,80000298 - -8000022c : -8000022c: 00600e13 li t3,6 -80000230: 800100b7 lui ra,0x80010 -80000234: 0000a183 lw gp,0(ra) # 80010000 -80000238: 00000f17 auipc t5,0x0 -8000023c: 06cf0f13 addi t5,t5,108 # 800002a4 -80000240: 0030a023 sw gp,0(ra) -80000244: 0540006f j 80000298 - -80000248 : -80000248: 00700e13 li t3,7 -8000024c: 00000f17 auipc t5,0x0 -80000250: 04cf0f13 addi t5,t5,76 # 80000298 -80000254: deadc137 lui sp,0xdeadc -80000258: eef10113 addi sp,sp,-273 # deadbeef -8000025c: 800300b7 lui ra,0x80030 -80000260: ff808093 addi ra,ra,-8 # 8002fff8 -80000264: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000264 : +80000264: 00400e13 li t3,4 80000268: 00000f17 auipc t5,0x0 -8000026c: fa8f0f13 addi t5,t5,-88 # 80000210 -80000270: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000274: 0240006f j 80000298 +8000026c: 0e4f0f13 addi t5,t5,228 # 8000034c +80000270: 00000117 auipc sp,0x0 +80000274: 01010113 addi sp,sp,16 # 80000280 +80000278: 34111073 csrw mepc,sp +8000027c: 30200073 mret -80000278 : -80000278: 00800e13 li t3,8 -8000027c: 800400b7 lui ra,0x80040 -80000280: ff808093 addi ra,ra,-8 # 8003fff8 -80000284: 0000a183 lw gp,0(ra) -80000288: 00000f17 auipc t5,0x0 -8000028c: 01cf0f13 addi t5,t5,28 # 800002a4 -80000290: 0030a023 sw gp,0(ra) -80000294: 0040006f j 80000298 +80000280 : +80000280: 00500e13 li t3,5 +80000284: 00000f17 auipc t5,0x0 +80000288: 0c8f0f13 addi t5,t5,200 # 8000034c +8000028c: deadc137 lui sp,0xdeadc +80000290: eef10113 addi sp,sp,-273 # deadbeef +80000294: 800080b7 lui ra,0x80008 +80000298: 0020a023 sw sp,0(ra) # 80008000 +8000029c: 00000f17 auipc t5,0x0 +800002a0: 010f0f13 addi t5,t5,16 # 800002ac +800002a4: 0000a183 lw gp,0(ra) +800002a8: 0a40006f j 8000034c -80000298 : -80000298: f0100137 lui sp,0xf0100 -8000029c: f2410113 addi sp,sp,-220 # f00fff24 -800002a0: 01c12023 sw t3,0(sp) +800002ac : +800002ac: 00600e13 li t3,6 +800002b0: 00000f17 auipc t5,0x0 +800002b4: 09cf0f13 addi t5,t5,156 # 8000034c +800002b8: deadc137 lui sp,0xdeadc +800002bc: eef10113 addi sp,sp,-273 # deadbeef +800002c0: 800000b7 lui ra,0x80000 +800002c4: 0020a023 sw sp,0(ra) # 80000000 +800002c8: 0000a183 lw gp,0(ra) +800002cc: 08311063 bne sp,gp,8000034c -800002a4 : -800002a4: f0100137 lui sp,0xf0100 -800002a8: f2010113 addi sp,sp,-224 # f00fff20 -800002ac: 00012023 sw zero,0(sp) +800002d0 : +800002d0: 00700e13 li t3,7 +800002d4: 00000f17 auipc t5,0x0 +800002d8: 078f0f13 addi t5,t5,120 # 8000034c +800002dc: 800400b7 lui ra,0x80040 +800002e0: 0000a183 lw gp,0(ra) # 80040000 +800002e4: 00000f17 auipc t5,0x0 +800002e8: 074f0f13 addi t5,t5,116 # 80000358 +800002ec: 0030a023 sw gp,0(ra) +800002f0: 05c0006f j 8000034c + +800002f4 : +800002f4: 00800e13 li t3,8 +800002f8: 00000f17 auipc t5,0x0 +800002fc: 054f0f13 addi t5,t5,84 # 8000034c +80000300: deadc137 lui sp,0xdeadc +80000304: eef10113 addi sp,sp,-273 # deadbeef +80000308: 800300b7 lui ra,0x80030 +8000030c: ff808093 addi ra,ra,-8 # 8002fff8 +80000310: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000314: 00000f17 auipc t5,0x0 +80000318: 010f0f13 addi t5,t5,16 # 80000324 +8000031c: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +80000320: 02c0006f j 8000034c + +80000324 : +80000324: 00900e13 li t3,9 +80000328: 00000f17 auipc t5,0x0 +8000032c: 024f0f13 addi t5,t5,36 # 8000034c +80000330: 800400b7 lui ra,0x80040 +80000334: ff808093 addi ra,ra,-8 # 8003fff8 +80000338: 0000a183 lw gp,0(ra) +8000033c: 00000f17 auipc t5,0x0 +80000340: 01cf0f13 addi t5,t5,28 # 80000358 +80000344: 0030a023 sw gp,0(ra) +80000348: 0040006f j 8000034c + +8000034c : +8000034c: f0100137 lui sp,0xf0100 +80000350: f2410113 addi sp,sp,-220 # f00fff24 +80000354: 01c12023 sw t3,0(sp) + +80000358 : +80000358: f0100137 lui sp,0xf0100 +8000035c: f2010113 addi sp,sp,-224 # f00fff20 +80000360: 00012023 sw zero,0(sp) diff --git a/src/test/cpp/raw/pmp/build/pmp.elf b/src/test/cpp/raw/pmp/build/pmp.elf index b844a20189743c473a3eeb6c94fa6b6976f7932d..68e30ea6a9ba2d543a6c80014c5854c5ee1aca40 100755 GIT binary patch delta 844 zcmY*XF>ljA6n;K84IpZ}J|}Sl4M&VXLM1q9Q6Ujh)PbQO5+;~XYloo|R<7!VRLk8M z!0n+5F`$$gq_E%>egUwtz)B}n5PNuz<0hQs(|zCj-n)12^Wo+GLdZxnw_7excVvK$ z{C@SDdRJYH0Q}_uzfbReQ0ezCtH;1%W!O0YaPw7r=R5&dui6pOvpghqZb99BBQgNqt0k%Xjv>gAn&LQyrB!^HKGgLSU954#gp1?6pG+Vkds)0jOY*uN z?~Qp8bUk<9QRpS5Il8>16mS$&k|eIpE^%NsRodx0Pm3e$wRwsvYa{CO$<&S5o!F6~ z8(Q@QRlGDU8^M$x^T||OS*vHmWB8b%il1_saUIzgzCVbaP4uc1JA-;cl@JQqp*1Zc zp6J)iIRNNxaCZwNq#@JYTC8o=9~9s-uyG^?6;Z3=3C}Yx7$cL zK+4}<`=s3*p2+~B#hCovo6nN{`0ni4;MiT*-UkRydehsdIRq_lI^)KuN_bB>&vMpI@5~T^M6W$9Gnz@VQ*(FF1abbC2FLh^U5)!5qb} z6<#3L`Tu;6c(%fQ;#U>EOnkM%*NL|(e4Cgo%7ae*?f@W~H}r5-DcHEDHWrI`5r3H> z-nUGia(rlY>!|_I!Pk~^_5;mydfO2?fj+PpbsCS5*T_rzLb~tbPs?d7n*jN}OQX$& F{Q=jbd`tiU diff --git a/src/test/cpp/raw/pmp/build/pmp.hex b/src/test/cpp/raw/pmp/build/pmp.hex index 8197935..5dc92f6 100644 --- a/src/test/cpp/raw/pmp/build/pmp.hex +++ b/src/test/cpp/raw/pmp/build/pmp.hex @@ -1,13 +1,13 @@ :0200000480007A :100000009700000093800001739050306F00C00093 :1000100073101F3473002030130E0000170F000000 -:10002000130FCF27B70000803782008037C1ADDEC5 +:10002000130F0F33B70000803782008037C1ADDE79 :100030001301F1EE23A020002320220083A1000061 -:10004000631C31248321020063183124B702120794 -:100050007390023A7323003A63906224B7021F1927 -:10006000938242307390123AB7020F00938262502B +:10004000631631308321020063123130B702120788 +:100050007390023A7323003A639A622EB7021F1913 +:10006000938242307390123AB7120F009382A2909B :100070007390223AB7221E0F938202907390323A05 -:10008000B70200207390023B7323003B639662200B +:10008000B70200207390023B7323003B6390622C05 :100090009302F0FF7390123BB72200207390223B33 :1000A000B74200209382F2FF7390323BB7420020A8 :1000B0009382F2FF7390423BB74200209382F2FF9B @@ -18,29 +18,41 @@ :100100007390C23B930200007390D23B93020000B5 :100110007390E23B930200007390F23B3701C10001 :100120001301E1FE23A020002320220083A1000070 -:10013000631431169301000083210200631E311401 -:10014000130E1000170F0000130F4F15B712920770 -:10015000938282807390023A7323003A639E621204 +:10013000631E3120930100008321020063183120E7 +:10014000130E1000170F0000130F8F20B712920725 +:10015000938282807390023A7323003A6398621EFE :10016000B780008037C1ADDE1301F1EE23A020007F -:10017000170F0000130F0F0183A100006F00C011C3 -:10018000130E2000170F0000130F4F11B7021207B4 -:100190007390023A7323003A7350203B7323203B41 -:1001A000630C030E638A620EB780008037C1ADDE38 -:1001B0001301F1EE23A02000170F0000130F0F0111 -:1001C00083A100006F00400D130E3000170F0000D8 -:1001D000130FCF0C1701000013010101731011342C -:1001E00073002030130E4000170F0000130F0F0B89 -:1001F00037C1ADDE1301F1EEB780008023A02000EF -:10020000170F0000130F0F0183A100006F00C0083B -:10021000130E500037C1ADDE1301F1EEB7000080C0 -:1002200023A0200083A1000063183106130E600094 -:10023000B700018083A10000170F0000130FCF0645 -:1002400023A030006F004005130E7000170F000050 -:10025000130FCF0437C1ADDE1301F1EEB7000380F9 -:10026000938080FF23202200170F0000130F8FFAC6 -:10027000832102006F004002130E8000B70004804B -:10028000938080FF83A10000170F0000130FCF01A0 -:1002900023A030006F004000370110F0130141F23D -:1002A0002320C101370110F0130101F223200100C6 +:10017000170F0000130F0F0183A100006F00001D77 +:10018000130E2000170F0000130F8F1CB702120769 +:100190007390023A7323003A638A621AB7420020CE +:1001A0009382F2FF7350303B7323303B6310031A8A +:1001B000638E6218B72200207350203B7323203BCC +:1001C0006306031863946218B780008037C1ADDE00 +:1001D0001301F1EE23A02000170F0000130F0F01F1 +:1001E00083A100006F008016130E3000170F00006F +:1001F000130F0F16B702FF0073A0323B7323303B7F +:10020000639662149302F00F73A0323B7323303B6A +:10021000B702FF009382F20F639A6212B702FF00E7 +:1002200073B0323B7323303B9302F00F6390621242 +:10023000B702FF009382F20F73B0023A7323003AC1 +:10024000B702920763946210B702FF009382727044 +:1002500073A0023A7323003AB70292079382727036 +:100260006396620E130E4000170F0000130F4F0E1F +:1002700017010000130101017310113473002030C5 +:10028000130E5000170F0000130F8F0C37C1ADDE97 +:100290001301F1EEB780008023A02000170F0000AB +:1002A000130F0F0183A100006F00400A130E6000BE +:1002B000170F0000130FCF0937C1ADDE1301F1EEA8 +:1002C000B700008023A0200083A100006310310844 +:1002D000130E7000170F0000130F8F07B700048074 +:1002E00083A10000170F0000130F4F0723A0300059 +:1002F0006F00C005130E8000170F0000130F4F058D +:1003000037C1ADDE1301F1EEB7000380938080FFAB +:1003100023202200170F0000130F0F01832102007A +:100320006F00C002130E9000170F0000130F4F0252 +:10033000B7000480938080FF83A10000170F0000A6 +:10034000130FCF0123A030006F004000370110F0E1 +:10035000130141F22320C101370110F0130101F212 +:040360002320010055 :040000058000000077 :00000001FF diff --git a/src/test/cpp/raw/pmp/build/pmp.map b/src/test/cpp/raw/pmp/build/pmp.map index 2a01820..f2e88d8 100644 --- a/src/test/cpp/raw/pmp/build/pmp.map +++ b/src/test/cpp/raw/pmp/build/pmp.map @@ -8,28 +8,28 @@ onChipRam 0x0000000080000000 0x0000000000020000 w !xr Linker script and memory map LOAD build/src/crt.o -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a START GROUP -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/lib/libc.a -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/lib/libgloss.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libc.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libgloss.a END GROUP -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a -.crt_section 0x0000000080000000 0x2b0 +.crt_section 0x0000000080000000 0x364 0x0000000080000000 . = ALIGN (0x4) *crt.o(.text) - .text 0x0000000080000000 0x2b0 build/src/crt.o + .text 0x0000000080000000 0x364 build/src/crt.o 0x0000000080000000 _start 0x0000000080000010 trap OUTPUT(build/pmp.elf elf32-littleriscv) -.data 0x00000000800002b0 0x0 - .data 0x00000000800002b0 0x0 build/src/crt.o +.data 0x0000000080000364 0x0 + .data 0x0000000080000364 0x0 build/src/crt.o -.bss 0x00000000800002b0 0x0 - .bss 0x00000000800002b0 0x0 build/src/crt.o +.bss 0x0000000080000364 0x0 + .bss 0x0000000080000364 0x0 build/src/crt.o .riscv.attributes - 0x0000000000000000 0x1e + 0x0000000000000000 0x1a .riscv.attributes - 0x0000000000000000 0x1e build/src/crt.o + 0x0000000000000000 0x1a build/src/crt.o diff --git a/src/test/cpp/raw/pmp/src/crt.S b/src/test/cpp/raw/pmp/src/crt.S index 76ee02f..089500a 100644 --- a/src/test/cpp/raw/pmp/src/crt.S +++ b/src/test/cpp/raw/pmp/src/crt.S @@ -8,15 +8,15 @@ #define TRAP_RA x30 #define PMPCFG0 0x07120000 -#define PMPCFG0_ 0x07920808 // locked +#define PMPCFG0_ 0x07920808 #define PMPCFG1 0x191f0304 -#define PMPCFG2 0x000f0506 +#define PMPCFG2 0x000f090a #define PMPCFG3 0x0f1e1900 -#define PMPADDR0 0x20000000 // OFF -#define PMPADDR1 0xffffffff // OFF +#define PMPADDR0 0x20000000 // OFF (test0) -> TOR (test1) -> OFF (test2) +#define PMPADDR1 0xffffffff // OFF (test0) -> TOR (test1) -> OFF (test2) #define PMPADDR2 0x20002000 // NA4 W -#define PMPADDR3 0x20003fff // OFF RWX +#define PMPADDR3 0x20003fff // OFF RWX -> 0x00000000 OFF RWX (test2) #define PMPADDR4 0x20003fff // OFF X #define PMPADDR5 0x20003fff // OFF RW #define PMPADDR6 0x20001fff // NAPOT RWX @@ -132,10 +132,17 @@ test2: li x5, PMPCFG0 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 csrwi pmpaddr2, 0x0 csrr x6, pmpaddr2 - beqz x6, fail - beq x5, x6, fail + beqz x6, fail + bne x5, x6, fail li x1, 0x80008000 li x2, 0xdeadbeef sw x2, 0x0(x1) // should still be OK (write 0x80008000) @@ -143,54 +150,86 @@ test2: lw x3, 0x0(x1) // should still fault (read 0x80008000) j fail -// jump into user mode +// verify masked CSR read/write operations test3: li TEST_ID, 3 la TRAP_RA, fail - la x2, test4 + li x5, 0x00ff0000 + csrs pmpaddr3, x5 + csrr x6, pmpaddr3 + bne x5, x6, fail + li x5, 0x000000ff + csrs pmpaddr3, x5 + csrr x6, pmpaddr3 + li x5, 0x00ff00ff + bne x5, x6, fail + li x5, 0x00ff0000 + csrc pmpaddr3, x5 + csrr x6, pmpaddr3 + li x5, 0x000000ff + bne x5, x6, fail + li x5, 0x00ff00ff + csrc pmpcfg0, x5 + csrr x6, pmpcfg0 + li x5, 0x07920000 + bne x5, x6, fail + li x5, 0x00ff0707 + csrs pmpcfg0, x5 + csrr x6, pmpcfg0 + li x5, 0x07920707 + bne x5, x6, fail + +// jump into user mode +test4: + li TEST_ID, 4 + la TRAP_RA, fail + la x2, test5 csrw mepc, x2 mret // attempt to read/write region 2 from user mode -test4: - li TEST_ID, 4 +test5: + li TEST_ID, 5 la TRAP_RA, fail li x2, 0xdeadbeef li x1, 0x80008000 sw x2, 0x0(x1) // should be OK (write 0x80008000) - la TRAP_RA, test5 + la TRAP_RA, test6 lw x3, 0x0(x1) // should fault (read 0x80008000) j fail // attempt to read/write other regions from user mode -test5: - li TEST_ID, 5 +test6: + li TEST_ID, 6 + la TRAP_RA, fail li x2, 0xdeadbeef li x1, 0x80000000 sw x2, 0x0(x1) lw x3, 0x0(x1) bne x2, x3, fail // should be OK (read/write 0x80000000) -test6: - li TEST_ID, 6 - li x1, 0x80010000 - lw x3, 0x0(x1) // should be OK (read 0x80010000) - la TRAP_RA, pass - sw x3, 0x0(x1) // should fault (write 0x80010000) - j fail - test7: li TEST_ID, 7 + la TRAP_RA, fail + li x1, 0x80040000 + lw x3, 0x0(x1) // should be OK (read 0x80040000) + la TRAP_RA, pass + sw x3, 0x0(x1) // should fault (write 0x80040000) + j fail + +test8: + li TEST_ID, 8 la TRAP_RA, fail li x2, 0xdeadbeef li x1, 0x8002fff8 sw x2, 0x0(x4) // should be OK (write 0x8002fff8) - la TRAP_RA, test5 + la TRAP_RA, test9 lw x3, 0x0(x4) // should fault (read 0x8002fff8) j fail -test8: - li TEST_ID, 8 +test9: + li TEST_ID, 9 + la TRAP_RA, fail li x1, 0x8003fff8 lw x3, 0x0(x1) // should be OK (read 0x8003fff8) la TRAP_RA, pass From b41db0af93ee80fb7eb2891f450e5d74334c0db4 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Mon, 12 Apr 2021 09:58:49 +0200 Subject: [PATCH 02/14] Prevent PMP access from U-mode, fix tests --- .../scala/vexriscv/plugin/PmpPlugin.scala | 5 +- src/test/cpp/raw/pmp/build/pmp.asm | 494 ++++++++++-------- src/test/cpp/raw/pmp/build/pmp.elf | Bin 5680 -> 5952 bytes src/test/cpp/raw/pmp/build/pmp.hex | 118 +++-- src/test/cpp/raw/pmp/build/pmp.map | 14 +- src/test/cpp/raw/pmp/src/crt.S | 104 +++- 6 files changed, 417 insertions(+), 318 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index 357d5b8..7f120da 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -150,8 +150,9 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] val csrAddress = input(INSTRUCTION)(csrRange) val accessAddr = input(IS_PMP_ADDR) val accessCfg = input(IS_PMP_CFG) - val pmpWrite = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) & (accessAddr | accessCfg) - val pmpRead = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) & (accessAddr | accessCfg) + val accessAny = (accessAddr | accessCfg) & privilegeService.isMachine() + val pmpWrite = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) & accessAny + val pmpRead = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) & accessAny val pmpIndex = csrAddress(log2Up(regions) - 1 downto 0).asUInt val pmpSelect = pmpIndex(log2Up(regions) - 3 downto 0) diff --git a/src/test/cpp/raw/pmp/build/pmp.asm b/src/test/cpp/raw/pmp/build/pmp.asm index c1fa1b7..ef3f280 100644 --- a/src/test/cpp/raw/pmp/build/pmp.asm +++ b/src/test/cpp/raw/pmp/build/pmp.asm @@ -5,246 +5,290 @@ build/pmp.elf: file format elf32-littleriscv Disassembly of section .crt_section: 80000000 <_start>: -80000000: 00000097 auipc ra,0x0 -80000004: 01008093 addi ra,ra,16 # 80000010 -80000008: 30509073 csrw mtvec,ra -8000000c: 00c0006f j 80000018 +80000000: 00000493 li s1,0 +80000004: 00000097 auipc ra,0x0 +80000008: 01008093 addi ra,ra,16 # 80000014 +8000000c: 30509073 csrw mtvec,ra +80000010: 0140006f j 80000024 -80000010 : -80000010: 341f1073 csrw mepc,t5 -80000014: 30200073 mret +80000014 : +80000014: 341f1073 csrw mepc,t5 +80000018: 00049463 bnez s1,80000020 +8000001c: 30200073 mret -80000018 : -80000018: 00000e13 li t3,0 -8000001c: 00000f17 auipc t5,0x0 -80000020: 330f0f13 addi t5,t5,816 # 8000034c -80000024: 800000b7 lui ra,0x80000 -80000028: 80008237 lui tp,0x80008 -8000002c: deadc137 lui sp,0xdeadc -80000030: eef10113 addi sp,sp,-273 # deadbeef -80000034: 0020a023 sw sp,0(ra) # 80000000 -80000038: 00222023 sw sp,0(tp) # 80008000 -8000003c: 0000a183 lw gp,0(ra) -80000040: 30311663 bne sp,gp,8000034c -80000044: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000048: 30311263 bne sp,gp,8000034c -8000004c: 071202b7 lui t0,0x7120 -80000050: 3a029073 csrw pmpcfg0,t0 -80000054: 3a002373 csrr t1,pmpcfg0 -80000058: 2e629a63 bne t0,t1,8000034c -8000005c: 191f02b7 lui t0,0x191f0 -80000060: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc> -80000064: 3a129073 csrw pmpcfg1,t0 -80000068: 000f12b7 lui t0,0xf1 -8000006c: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> -80000070: 3a229073 csrw pmpcfg2,t0 -80000074: 0f1e22b7 lui t0,0xf1e2 -80000078: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> -8000007c: 3a329073 csrw pmpcfg3,t0 -80000080: 200002b7 lui t0,0x20000 -80000084: 3b029073 csrw pmpaddr0,t0 -80000088: 3b002373 csrr t1,pmpaddr0 -8000008c: 2c629063 bne t0,t1,8000034c -80000090: fff00293 li t0,-1 -80000094: 3b129073 csrw pmpaddr1,t0 -80000098: 200022b7 lui t0,0x20002 -8000009c: 3b229073 csrw pmpaddr2,t0 -800000a0: 200042b7 lui t0,0x20004 -800000a4: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000a8: 3b329073 csrw pmpaddr3,t0 +80000020 : +80000020: 000f0067 jr t5 + +80000024 : +80000024: 00000e13 li t3,0 +80000028: 00000f17 auipc t5,0x0 +8000002c: 3a4f0f13 addi t5,t5,932 # 800003cc +80000030: 800000b7 lui ra,0x80000 +80000034: 80008237 lui tp,0x80008 +80000038: deadc137 lui sp,0xdeadc +8000003c: eef10113 addi sp,sp,-273 # deadbeef +80000040: 0020a023 sw sp,0(ra) # 80000000 +80000044: 00222023 sw sp,0(tp) # 80008000 +80000048: 0000a183 lw gp,0(ra) +8000004c: 38311063 bne sp,gp,800003cc +80000050: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +80000054: 36311c63 bne sp,gp,800003cc +80000058: 071202b7 lui t0,0x7120 +8000005c: 3a029073 csrw pmpcfg0,t0 +80000060: 3a002373 csrr t1,pmpcfg0 +80000064: 36629463 bne t0,t1,800003cc +80000068: 191f02b7 lui t0,0x191f0 +8000006c: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc> +80000070: 3a129073 csrw pmpcfg1,t0 +80000074: 000f12b7 lui t0,0xf1 +80000078: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> +8000007c: 3a229073 csrw pmpcfg2,t0 +80000080: 0f1e22b7 lui t0,0xf1e2 +80000084: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> +80000088: 3a329073 csrw pmpcfg3,t0 +8000008c: 200002b7 lui t0,0x20000 +80000090: 3b029073 csrw pmpaddr0,t0 +80000094: 3b002373 csrr t1,pmpaddr0 +80000098: 32629a63 bne t0,t1,800003cc +8000009c: fff00293 li t0,-1 +800000a0: 3b129073 csrw pmpaddr1,t0 +800000a4: 200022b7 lui t0,0x20002 +800000a8: 3b229073 csrw pmpaddr2,t0 800000ac: 200042b7 lui t0,0x20004 800000b0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000b4: 3b429073 csrw pmpaddr4,t0 +800000b4: 3b329073 csrw pmpaddr3,t0 800000b8: 200042b7 lui t0,0x20004 800000bc: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000c0: 3b529073 csrw pmpaddr5,t0 -800000c4: 200022b7 lui t0,0x20002 -800000c8: fff28293 addi t0,t0,-1 # 20001fff <_start-0x5fffe001> -800000cc: 3b629073 csrw pmpaddr6,t0 -800000d0: 200062b7 lui t0,0x20006 -800000d4: fff28293 addi t0,t0,-1 # 20005fff <_start-0x5fffa001> -800000d8: 3b729073 csrw pmpaddr7,t0 -800000dc: 2000c2b7 lui t0,0x2000c -800000e0: 3b829073 csrw pmpaddr8,t0 -800000e4: 2000d2b7 lui t0,0x2000d -800000e8: 3b929073 csrw pmpaddr9,t0 -800000ec: fff00293 li t0,-1 -800000f0: 3ba29073 csrw pmpaddr10,t0 -800000f4: 00000293 li t0,0 -800000f8: 3bb29073 csrw pmpaddr11,t0 -800000fc: 00000293 li t0,0 -80000100: 3bc29073 csrw pmpaddr12,t0 -80000104: 00000293 li t0,0 -80000108: 3bd29073 csrw pmpaddr13,t0 -8000010c: 00000293 li t0,0 -80000110: 3be29073 csrw pmpaddr14,t0 -80000114: 00000293 li t0,0 -80000118: 3bf29073 csrw pmpaddr15,t0 -8000011c: 00c10137 lui sp,0xc10 -80000120: fee10113 addi sp,sp,-18 # c0ffee <_start-0x7f3f0012> -80000124: 0020a023 sw sp,0(ra) -80000128: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> -8000012c: 0000a183 lw gp,0(ra) -80000130: 20311e63 bne sp,gp,8000034c -80000134: 00000193 li gp,0 -80000138: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -8000013c: 20311863 bne sp,gp,8000034c +800000c0: 3b429073 csrw pmpaddr4,t0 +800000c4: 200042b7 lui t0,0x20004 +800000c8: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800000cc: 3b529073 csrw pmpaddr5,t0 +800000d0: 200022b7 lui t0,0x20002 +800000d4: fff28293 addi t0,t0,-1 # 20001fff <_start-0x5fffe001> +800000d8: 3b629073 csrw pmpaddr6,t0 +800000dc: 200062b7 lui t0,0x20006 +800000e0: fff28293 addi t0,t0,-1 # 20005fff <_start-0x5fffa001> +800000e4: 3b729073 csrw pmpaddr7,t0 +800000e8: 200d02b7 lui t0,0x200d0 +800000ec: 3b829073 csrw pmpaddr8,t0 +800000f0: 200e02b7 lui t0,0x200e0 +800000f4: 3b929073 csrw pmpaddr9,t0 +800000f8: fff00293 li t0,-1 +800000fc: 3ba29073 csrw pmpaddr10,t0 +80000100: 00000293 li t0,0 +80000104: 3bb29073 csrw pmpaddr11,t0 +80000108: 00000293 li t0,0 +8000010c: 3bc29073 csrw pmpaddr12,t0 +80000110: 00000293 li t0,0 +80000114: 3bd29073 csrw pmpaddr13,t0 +80000118: 00000293 li t0,0 +8000011c: 3be29073 csrw pmpaddr14,t0 +80000120: 00000293 li t0,0 +80000124: 3bf29073 csrw pmpaddr15,t0 +80000128: 00c10137 lui sp,0xc10 +8000012c: fee10113 addi sp,sp,-18 # c0ffee <_start-0x7f3f0012> +80000130: 0020a023 sw sp,0(ra) +80000134: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000138: 0000a183 lw gp,0(ra) +8000013c: 28311863 bne sp,gp,800003cc +80000140: 00000193 li gp,0 +80000144: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +80000148: 28311263 bne sp,gp,800003cc -80000140 : -80000140: 00100e13 li t3,1 -80000144: 00000f17 auipc t5,0x0 -80000148: 208f0f13 addi t5,t5,520 # 8000034c -8000014c: 079212b7 lui t0,0x7921 -80000150: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8> -80000154: 3a029073 csrw pmpcfg0,t0 -80000158: 3a002373 csrr t1,pmpcfg0 -8000015c: 1e629863 bne t0,t1,8000034c -80000160: 800080b7 lui ra,0x80008 -80000164: deadc137 lui sp,0xdeadc -80000168: eef10113 addi sp,sp,-273 # deadbeef -8000016c: 0020a023 sw sp,0(ra) # 80008000 -80000170: 00000f17 auipc t5,0x0 -80000174: 010f0f13 addi t5,t5,16 # 80000180 -80000178: 0000a183 lw gp,0(ra) -8000017c: 1d00006f j 8000034c +8000014c : +8000014c: 00100e13 li t3,1 +80000150: 00000f17 auipc t5,0x0 +80000154: 27cf0f13 addi t5,t5,636 # 800003cc +80000158: 079212b7 lui t0,0x7921 +8000015c: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8> +80000160: 3a029073 csrw pmpcfg0,t0 +80000164: 3a002373 csrr t1,pmpcfg0 +80000168: 26629263 bne t0,t1,800003cc +8000016c: 800080b7 lui ra,0x80008 +80000170: deadc137 lui sp,0xdeadc +80000174: eef10113 addi sp,sp,-273 # deadbeef +80000178: 0020a023 sw sp,0(ra) # 80008000 +8000017c: 00000f17 auipc t5,0x0 +80000180: 010f0f13 addi t5,t5,16 # 8000018c +80000184: 0000a183 lw gp,0(ra) +80000188: 2440006f j 800003cc -80000180 : -80000180: 00200e13 li t3,2 -80000184: 00000f17 auipc t5,0x0 -80000188: 1c8f0f13 addi t5,t5,456 # 8000034c -8000018c: 071202b7 lui t0,0x7120 -80000190: 3a029073 csrw pmpcfg0,t0 -80000194: 3a002373 csrr t1,pmpcfg0 -80000198: 1a628a63 beq t0,t1,8000034c -8000019c: 200042b7 lui t0,0x20004 -800001a0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800001a4: 3b305073 csrwi pmpaddr3,0 -800001a8: 3b302373 csrr t1,pmpaddr3 -800001ac: 1a031063 bnez t1,8000034c -800001b0: 18628e63 beq t0,t1,8000034c -800001b4: 200022b7 lui t0,0x20002 -800001b8: 3b205073 csrwi pmpaddr2,0 -800001bc: 3b202373 csrr t1,pmpaddr2 -800001c0: 18030663 beqz t1,8000034c -800001c4: 18629463 bne t0,t1,8000034c -800001c8: 800080b7 lui ra,0x80008 -800001cc: deadc137 lui sp,0xdeadc -800001d0: eef10113 addi sp,sp,-273 # deadbeef -800001d4: 0020a023 sw sp,0(ra) # 80008000 -800001d8: 00000f17 auipc t5,0x0 -800001dc: 010f0f13 addi t5,t5,16 # 800001e8 -800001e0: 0000a183 lw gp,0(ra) -800001e4: 1680006f j 8000034c +8000018c : +8000018c: 00200e13 li t3,2 +80000190: 00000f17 auipc t5,0x0 +80000194: 23cf0f13 addi t5,t5,572 # 800003cc +80000198: 071202b7 lui t0,0x7120 +8000019c: 3a029073 csrw pmpcfg0,t0 +800001a0: 3a002373 csrr t1,pmpcfg0 +800001a4: 22628463 beq t0,t1,800003cc +800001a8: 200042b7 lui t0,0x20004 +800001ac: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800001b0: 3b305073 csrwi pmpaddr3,0 +800001b4: 3b302373 csrr t1,pmpaddr3 +800001b8: 20031a63 bnez t1,800003cc +800001bc: 20628863 beq t0,t1,800003cc +800001c0: 200022b7 lui t0,0x20002 +800001c4: 3b205073 csrwi pmpaddr2,0 +800001c8: 3b202373 csrr t1,pmpaddr2 +800001cc: 20030063 beqz t1,800003cc +800001d0: 1e629e63 bne t0,t1,800003cc +800001d4: 800080b7 lui ra,0x80008 +800001d8: deadc137 lui sp,0xdeadc +800001dc: eef10113 addi sp,sp,-273 # deadbeef +800001e0: 0020a023 sw sp,0(ra) # 80008000 +800001e4: 00000f17 auipc t5,0x0 +800001e8: 010f0f13 addi t5,t5,16 # 800001f4 +800001ec: 0000a183 lw gp,0(ra) +800001f0: 1dc0006f j 800003cc -800001e8 : -800001e8: 00300e13 li t3,3 -800001ec: 00000f17 auipc t5,0x0 -800001f0: 160f0f13 addi t5,t5,352 # 8000034c -800001f4: 00ff02b7 lui t0,0xff0 -800001f8: 3b32a073 csrs pmpaddr3,t0 -800001fc: 3b302373 csrr t1,pmpaddr3 -80000200: 14629663 bne t0,t1,8000034c -80000204: 0ff00293 li t0,255 -80000208: 3b32a073 csrs pmpaddr3,t0 -8000020c: 3b302373 csrr t1,pmpaddr3 -80000210: 00ff02b7 lui t0,0xff0 -80000214: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> -80000218: 12629a63 bne t0,t1,8000034c +800001f4 : +800001f4: 00300e13 li t3,3 +800001f8: 00000f17 auipc t5,0x0 +800001fc: 1d4f0f13 addi t5,t5,468 # 800003cc +80000200: 00ff02b7 lui t0,0xff0 +80000204: 3b32a073 csrs pmpaddr3,t0 +80000208: 3b302373 csrr t1,pmpaddr3 +8000020c: 1c629063 bne t0,t1,800003cc +80000210: 0ff00293 li t0,255 +80000214: 3b32a073 csrs pmpaddr3,t0 +80000218: 3b302373 csrr t1,pmpaddr3 8000021c: 00ff02b7 lui t0,0xff0 -80000220: 3b32b073 csrc pmpaddr3,t0 -80000224: 3b302373 csrr t1,pmpaddr3 -80000228: 0ff00293 li t0,255 -8000022c: 12629063 bne t0,t1,8000034c -80000230: 00ff02b7 lui t0,0xff0 -80000234: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> -80000238: 3a02b073 csrc pmpcfg0,t0 -8000023c: 3a002373 csrr t1,pmpcfg0 -80000240: 079202b7 lui t0,0x7920 -80000244: 10629463 bne t0,t1,8000034c -80000248: 00ff02b7 lui t0,0xff0 -8000024c: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> -80000250: 3a02a073 csrs pmpcfg0,t0 -80000254: 3a002373 csrr t1,pmpcfg0 -80000258: 079202b7 lui t0,0x7920 -8000025c: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9> -80000260: 0e629663 bne t0,t1,8000034c +80000220: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000224: 1a629463 bne t0,t1,800003cc +80000228: 00ff02b7 lui t0,0xff0 +8000022c: 3b32b073 csrc pmpaddr3,t0 +80000230: 3b302373 csrr t1,pmpaddr3 +80000234: 0ff00293 li t0,255 +80000238: 18629a63 bne t0,t1,800003cc +8000023c: 00ff02b7 lui t0,0xff0 +80000240: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000244: 3a02b073 csrc pmpcfg0,t0 +80000248: 3a002373 csrr t1,pmpcfg0 +8000024c: 079202b7 lui t0,0x7920 +80000250: 16629e63 bne t0,t1,800003cc +80000254: 00ff02b7 lui t0,0xff0 +80000258: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> +8000025c: 3a02a073 csrs pmpcfg0,t0 +80000260: 3a002373 csrr t1,pmpcfg0 +80000264: 079202b7 lui t0,0x7920 +80000268: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9> +8000026c: 16629063 bne t0,t1,800003cc -80000264 : -80000264: 00400e13 li t3,4 -80000268: 00000f17 auipc t5,0x0 -8000026c: 0e4f0f13 addi t5,t5,228 # 8000034c -80000270: 00000117 auipc sp,0x0 -80000274: 01010113 addi sp,sp,16 # 80000280 -80000278: 34111073 csrw mepc,sp -8000027c: 30200073 mret +80000270 : +80000270: 00400e13 li t3,4 +80000274: 00000f17 auipc t5,0x0 +80000278: 158f0f13 addi t5,t5,344 # 800003cc +8000027c: 00000117 auipc sp,0x0 +80000280: 01010113 addi sp,sp,16 # 8000028c +80000284: 34111073 csrw mepc,sp +80000288: 30200073 mret -80000280 : -80000280: 00500e13 li t3,5 -80000284: 00000f17 auipc t5,0x0 -80000288: 0c8f0f13 addi t5,t5,200 # 8000034c -8000028c: deadc137 lui sp,0xdeadc -80000290: eef10113 addi sp,sp,-273 # deadbeef -80000294: 800080b7 lui ra,0x80008 -80000298: 0020a023 sw sp,0(ra) # 80008000 -8000029c: 00000f17 auipc t5,0x0 -800002a0: 010f0f13 addi t5,t5,16 # 800002ac -800002a4: 0000a183 lw gp,0(ra) -800002a8: 0a40006f j 8000034c +8000028c : +8000028c: 00500e13 li t3,5 +80000290: 00000f17 auipc t5,0x0 +80000294: 13cf0f13 addi t5,t5,316 # 800003cc +80000298: deadc137 lui sp,0xdeadc +8000029c: eef10113 addi sp,sp,-273 # deadbeef +800002a0: 800080b7 lui ra,0x80008 +800002a4: 0020a023 sw sp,0(ra) # 80008000 +800002a8: 00000f17 auipc t5,0x0 +800002ac: 010f0f13 addi t5,t5,16 # 800002b8 +800002b0: 0000a183 lw gp,0(ra) +800002b4: 1180006f j 800003cc -800002ac : -800002ac: 00600e13 li t3,6 -800002b0: 00000f17 auipc t5,0x0 -800002b4: 09cf0f13 addi t5,t5,156 # 8000034c -800002b8: deadc137 lui sp,0xdeadc -800002bc: eef10113 addi sp,sp,-273 # deadbeef -800002c0: 800000b7 lui ra,0x80000 -800002c4: 0020a023 sw sp,0(ra) # 80000000 -800002c8: 0000a183 lw gp,0(ra) -800002cc: 08311063 bne sp,gp,8000034c +800002b8 : +800002b8: 00600e13 li t3,6 +800002bc: 00000f17 auipc t5,0x0 +800002c0: 110f0f13 addi t5,t5,272 # 800003cc +800002c4: deadc137 lui sp,0xdeadc +800002c8: eef10113 addi sp,sp,-273 # deadbeef +800002cc: 800000b7 lui ra,0x80000 +800002d0: 0020a023 sw sp,0(ra) # 80000000 +800002d4: 0000a183 lw gp,0(ra) +800002d8: 0e311a63 bne sp,gp,800003cc -800002d0 : -800002d0: 00700e13 li t3,7 -800002d4: 00000f17 auipc t5,0x0 -800002d8: 078f0f13 addi t5,t5,120 # 8000034c -800002dc: 800400b7 lui ra,0x80040 -800002e0: 0000a183 lw gp,0(ra) # 80040000 -800002e4: 00000f17 auipc t5,0x0 -800002e8: 074f0f13 addi t5,t5,116 # 80000358 -800002ec: 0030a023 sw gp,0(ra) -800002f0: 05c0006f j 8000034c +800002dc : +800002dc: 00700e13 li t3,7 +800002e0: 00000f17 auipc t5,0x0 +800002e4: 0ecf0f13 addi t5,t5,236 # 800003cc +800002e8: 800400b7 lui ra,0x80040 +800002ec: 0000a183 lw gp,0(ra) # 80040000 +800002f0: 00000f17 auipc t5,0x0 +800002f4: 010f0f13 addi t5,t5,16 # 80000300 +800002f8: 0030a023 sw gp,0(ra) +800002fc: 0d00006f j 800003cc -800002f4 : -800002f4: 00800e13 li t3,8 -800002f8: 00000f17 auipc t5,0x0 -800002fc: 054f0f13 addi t5,t5,84 # 8000034c -80000300: deadc137 lui sp,0xdeadc -80000304: eef10113 addi sp,sp,-273 # deadbeef -80000308: 800300b7 lui ra,0x80030 -8000030c: ff808093 addi ra,ra,-8 # 8002fff8 -80000310: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> -80000314: 00000f17 auipc t5,0x0 -80000318: 010f0f13 addi t5,t5,16 # 80000324 -8000031c: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000320: 02c0006f j 8000034c +80000300 : +80000300: 00800e13 li t3,8 +80000304: 00000f17 auipc t5,0x0 +80000308: 0c8f0f13 addi t5,t5,200 # 800003cc +8000030c: deadc137 lui sp,0xdeadc +80000310: eef10113 addi sp,sp,-273 # deadbeef +80000314: 803400b7 lui ra,0x80340 +80000318: ff808093 addi ra,ra,-8 # 8033fff8 +8000031c: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000320: 00000f17 auipc t5,0x0 +80000324: 010f0f13 addi t5,t5,16 # 80000330 +80000328: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +8000032c: 0a00006f j 800003cc -80000324 : -80000324: 00900e13 li t3,9 -80000328: 00000f17 auipc t5,0x0 -8000032c: 024f0f13 addi t5,t5,36 # 8000034c -80000330: 800400b7 lui ra,0x80040 -80000334: ff808093 addi ra,ra,-8 # 8003fff8 -80000338: 0000a183 lw gp,0(ra) -8000033c: 00000f17 auipc t5,0x0 -80000340: 01cf0f13 addi t5,t5,28 # 80000358 -80000344: 0030a023 sw gp,0(ra) -80000348: 0040006f j 8000034c +80000330 : +80000330: 00900e13 li t3,9 +80000334: 00000f17 auipc t5,0x0 +80000338: 098f0f13 addi t5,t5,152 # 800003cc +8000033c: 803800b7 lui ra,0x80380 +80000340: ff808093 addi ra,ra,-8 # 8037fff8 +80000344: 0000a183 lw gp,0(ra) +80000348: 00000f17 auipc t5,0x0 +8000034c: 010f0f13 addi t5,t5,16 # 80000358 +80000350: 0030a023 sw gp,0(ra) +80000354: 0780006f j 800003cc -8000034c : -8000034c: f0100137 lui sp,0xf0100 -80000350: f2410113 addi sp,sp,-220 # f00fff24 -80000354: 01c12023 sw t3,0(sp) +80000358 : +80000358: 00a00e13 li t3,10 +8000035c: 00000f17 auipc t5,0x0 +80000360: 014f0f13 addi t5,t5,20 # 80000370 +80000364: 00100493 li s1,1 +80000368: 3a305073 csrwi pmpcfg3,0 +8000036c: 0600006f j 800003cc -80000358 : -80000358: f0100137 lui sp,0xf0100 -8000035c: f2010113 addi sp,sp,-224 # f00fff20 -80000360: 00012023 sw zero,0(sp) +80000370 : +80000370: 00a00e13 li t3,10 +80000374: 0f1e22b7 lui t0,0xf1e2 +80000378: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> +8000037c: 3a302373 csrr t1,pmpcfg3 +80000380: 04629663 bne t0,t1,800003cc + +80000384 : +80000384: 00b00e13 li t3,11 +80000388: 00000f17 auipc t5,0x0 +8000038c: 044f0f13 addi t5,t5,68 # 800003cc +80000390: 00000493 li s1,0 +80000394: 00000117 auipc sp,0x0 +80000398: 01010113 addi sp,sp,16 # 800003a4 +8000039c: 34111073 csrw mepc,sp +800003a0: 30200073 mret + +800003a4 : +800003a4: 00b00e13 li t3,11 +800003a8: 00000f17 auipc t5,0x0 +800003ac: 014f0f13 addi t5,t5,20 # 800003bc +800003b0: 00100493 li s1,1 +800003b4: 3ba05073 csrwi pmpaddr10,0 +800003b8: 0140006f j 800003cc + +800003bc : +800003bc: 00b00e13 li t3,11 +800003c0: fff00293 li t0,-1 +800003c4: 3ba02373 csrr t1,pmpaddr10 +800003c8: 00628863 beq t0,t1,800003d8 + +800003cc : +800003cc: f0100137 lui sp,0xf0100 +800003d0: f2410113 addi sp,sp,-220 # f00fff24 +800003d4: 01c12023 sw t3,0(sp) + +800003d8 : +800003d8: f0100137 lui sp,0xf0100 +800003dc: f2010113 addi sp,sp,-224 # f00fff20 +800003e0: 00012023 sw zero,0(sp) diff --git a/src/test/cpp/raw/pmp/build/pmp.elf b/src/test/cpp/raw/pmp/build/pmp.elf index 68e30ea6a9ba2d543a6c80014c5854c5ee1aca40..26fc85b43a89acc7708191e30981cd7f5b88847c 100755 GIT binary patch literal 5952 zcmeHLPiP!f9R9t@CZS?yH~UP|#{QY^mYRd4v)i?aJ0NXP4^rsjq4XfcooUpCXqI`? zq98bIb5IaEWU7J(S&LU8co`2KjAudcEVR z-ZyU+_PzJQl@}Rfq?-5$j(AK(jp7|GR@F*I$lwHh#20VB9hm%q*7k?idHyK zI8ZoHI8ZoHI8ZoHI8ZoHI8ZoHI8ZoHIPgDlATAMof@g_CVj}9;+jNPE%ITJOw?u+0 z`*kW4H;ER@M7(^po#6le>HydNm%niK@b~)AqPkV1+n*D8mB!lbGX{Al8W$6zIx8Zh zE$Y>`TSV1%QY}+FxEG12)=p}t%JINJzu8Uslod>rpLuz`koVGcNX(6q`co3!!aKZ{Js~t3*5Yv z&3$Kn5#DheK8ea)OYSvpcJ%tW-d}Pp((_5L!Z~ifs=2w57JE}_rJvqX!{laP*E16; zg_75G>O&iz(@}1Q8F%OLah+BehvA{z*IF;%G4zjdGt&Aa39TvJqjkesZVofuRTh^j zBsz8*_s>XvwCC$~+xyrpadS^=OY(bs)R)nCR%__U?^NEW_HljaU@y=rt32TB@8~N$Is6Ln^&Gwd+|S`H;GG-}fWOG$cY(jj;T_|8=G(U0(!06+frmh#ioiERBWmEjEWakTvc&R#b;G)*xf9< zX>Me=p|MB(t`M{#g03H^iHTOkJ8uSE7di0L{D$t~DL2HX7xcE@q7}8NR=Ppp_uQL! za=FU?)}Dln;hIV1p*%O1XUMvhvd%Ix=)UIfbD|{;kYx?oWX4bVxJi>i$~y80TV_l_ dM{wn)p>Uq)BXGLudU9Xqb@M3F)*@uB`x`f|h-Lr) delta 881 zcmY+Dzi-n(6vvUx1a^=ZkchZ~goIQp z-H@QBhe}m3q&rCIM|h#47ZvtqbeE6Zn9Y4DvEA5Jd)b+ ztK#8_>N3nxm5s}0|LgX`uf$h?iSF+KZ#fNaJB@%SmEe_c#uj#NF^sWBa7;0SH@=z3 zRYQZS&UhFjmIuIl=hLm*{)`}cX=T^fhw*+I7xGUnh|(Cg(s(}|HkP-FC`*!B(S6+E zy)2$^uJiUfy(e62bS5%;CIF1!E9VHZDIIx*D%4t&a&9PplY6N9#c$ZB%5lsp+ z;X^4E_QYrUY~92I;gdj8lJP9ECuM9QhdDlr{5{7tD=QS*6#DQOGAHIOd1{W x)G(yBcxl+^_l+~>LJGj}!A=Y%vULg>f0`rf&ESQJLfJNz5 Date: Mon, 12 Apr 2021 10:14:10 +0200 Subject: [PATCH 03/14] Update README.md --- README.md | 102 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index eec2dd0..79e66c9 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ - [CPU generation](#cpu-generation) - [Regression tests](#regression-tests) - [Interactive debug of the simulated CPU via GDB OpenOCD and Verilator](#interactive-debug-of-the-simulated-cpu-via-gdb-openocd-and-verilator) -- [Using Eclipse to run and debug the software](#using-Eclipse-to-run-and-debug-the-software) - * [By using gnu-mcu-eclipse](#by-using-gnu-mcu-eclipse) - * [By using Zylin plugin (old)](#by-using-zylin-plugin-old) +- [Using Eclipse to run and debug the software](#using-eclipse-to-run-and-debug-the-software) + - [By using gnu-mcu-eclipse](#by-using-gnu-mcu-eclipse) + - [By using Zylin plugin (old)](#by-using-zylin-plugin-old) - [Briey SoC](#briey-soc) - [Murax SoC](#murax-soc) - [Running Linux](#running-linux) @@ -19,7 +19,32 @@ - [Adding a new CSR via the plugin system](#adding-a-new-csr-via-the-plugin-system) - [CPU clock and resets](#cpu-clock-and-resets) - [VexRiscv Architecture](#vexriscv-architecture) - * [Plugins](#plugins) + - [Plugins](#plugins) + - [IBusSimplePlugin](#ibussimpleplugin) + - [IBusCachedPlugin](#ibuscachedplugin) + - [DecoderSimplePlugin](#decodersimpleplugin) + - [RegFilePlugin](#regfileplugin) + - [HazardSimplePlugin](#hazardsimpleplugin) + - [SrcPlugin](#srcplugin) + - [IntAluPlugin](#intaluplugin) + - [LightShifterPlugin](#lightshifterplugin) + - [FullBarrelShifterPlugin](#fullbarrelshifterplugin) + - [BranchPlugin](#branchplugin) + - [Prediction NONE](#prediction-none) + - [Prediction STATIC](#prediction-static) + - [Prediction DYNAMIC](#prediction-dynamic) + - [Prediction DYNAMIC_TARGET](#prediction-dynamic_target) + - [DBusSimplePlugin](#dbussimpleplugin) + - [DBusCachedPlugin](#dbuscachedplugin) + - [MulPlugin](#mulplugin) + - [DivPlugin](#divplugin) + - [MulDivIterativePlugin](#muldiviterativeplugin) + - [CsrPlugin](#csrplugin) + - [StaticMemoryTranslatorPlugin](#staticmemorytranslatorplugin) + - [MmuPlugin](#mmuplugin) + - [PmpPlugin](#pmpplugin) + - [DebugPlugin](#debugplugin) + - [YamlPlugin](#yamlplugin) @@ -672,26 +697,51 @@ and everything else, including the program counter is added into the CPU via plu This chapter describes the currently implemented plugins. -- [IBusSimplePlugin](#ibussimpleplugin) -- [IBusCachedPlugin](#ibuscachedplugin) -- [DecoderSimplePlugin](#decodersimpleplugin) -- [RegFilePlugin](#regfileplugin) -- [HazardSimplePlugin](#hazardsimpleplugin) -- [SrcPlugin](#srcplugin) -- [IntAluPlugin](#intaluplugin) -- [LightShifterPlugin](#lightshifterplugin) -- [FullBarrelShifterPlugin](#fullbarrelshifterplugin) -- [BranchPlugin](#branchplugin) -- [DBusSimplePlugin](#dbussimpleplugin) -- [DBusCachedPlugin](#dbuscachedplugin) -- [MulPlugin](#mulplugin) -- [DivPlugin](#divplugin) -- [MulDivIterativePlugin](#muldiviterativeplugin) -- [CsrPlugin](#csrplugin) -- [StaticMemoryTranslatorPlugin](#staticmemorytranslatorplugin) -- [MemoryTranslatorPlugin](#memorytranslatorplugin) -- [DebugPlugin](#debugplugin) -- [YamlPlugin](#yamlplugin) +- [Index](#index) +- [Description](#description) +- [Area usage and maximal frequency](#area-usage-and-maximal-frequency) +- [Dependencies](#dependencies) +- [CPU generation](#cpu-generation) +- [Regression tests](#regression-tests) +- [Interactive debug of the simulated CPU via GDB OpenOCD and Verilator](#interactive-debug-of-the-simulated-cpu-via-gdb-openocd-and-verilator) +- [Using Eclipse to run and debug the software](#using-eclipse-to-run-and-debug-the-software) + - [By using gnu-mcu-eclipse](#by-using-gnu-mcu-eclipse) + - [By using Zylin plugin (old)](#by-using-zylin-plugin-old) +- [Briey SoC](#briey-soc) +- [Murax SoC](#murax-soc) +- [Running Linux](#running-linux) +- [Build the RISC-V GCC](#build-the-risc-v-gcc) +- [CPU parametrization and instantiation example](#cpu-parametrization-and-instantiation-example) +- [Add a custom instruction to the CPU via the plugin system](#add-a-custom-instruction-to-the-cpu-via-the-plugin-system) +- [Adding a new CSR via the plugin system](#adding-a-new-csr-via-the-plugin-system) +- [CPU clock and resets](#cpu-clock-and-resets) +- [VexRiscv Architecture](#vexriscv-architecture) + - [Plugins](#plugins) + - [IBusSimplePlugin](#ibussimpleplugin) + - [IBusCachedPlugin](#ibuscachedplugin) + - [DecoderSimplePlugin](#decodersimpleplugin) + - [RegFilePlugin](#regfileplugin) + - [HazardSimplePlugin](#hazardsimpleplugin) + - [SrcPlugin](#srcplugin) + - [IntAluPlugin](#intaluplugin) + - [LightShifterPlugin](#lightshifterplugin) + - [FullBarrelShifterPlugin](#fullbarrelshifterplugin) + - [BranchPlugin](#branchplugin) + - [Prediction NONE](#prediction-none) + - [Prediction STATIC](#prediction-static) + - [Prediction DYNAMIC](#prediction-dynamic) + - [Prediction DYNAMIC_TARGET](#prediction-dynamic_target) + - [DBusSimplePlugin](#dbussimpleplugin) + - [DBusCachedPlugin](#dbuscachedplugin) + - [MulPlugin](#mulplugin) + - [DivPlugin](#divplugin) + - [MulDivIterativePlugin](#muldiviterativeplugin) + - [CsrPlugin](#csrplugin) + - [StaticMemoryTranslatorPlugin](#staticmemorytranslatorplugin) + - [MmuPlugin](#mmuplugin) + - [PmpPlugin](#pmpplugin) + - [DebugPlugin](#debugplugin) + - [YamlPlugin](#yamlplugin) #### IBusSimplePlugin @@ -1027,6 +1077,10 @@ Static memory translator plugin which allows to specify which range of the memor Hardware refilled MMU implementation. Allows other plugins such as DBusCachedPlugin/IBusCachedPlugin to instanciate memory address translation ports. Each port has a small dedicated fully associative TLB cache which is refilled automaticaly via a dbus access sharing. +#### PmpPlugin + +This is a physical memory protection (PMP) plugin which conforms to the latest RISC-V privilege specification. PMP is configured by writing two special CSRs: `pmpcfg#` and `pmpaddr#`. The former contains the permissions and addressing modes for four protection regions, and the latter contains the encoded start address for a single region. Since the actual region bounds must be computed from the values written to these registers, writing them takes a few CPU cylces: (5 for `pmpcfg#` and 2-3 for `pmpaddr#`). This delay is necessary in order to centralize all of the decoding logic into a single component. Otherwise, it would have to be duplicated for each region, even though the decoding operation happens only when PMP is reprogrammed (e.g., on some context switches). + #### DebugPlugin This plugin implements enough CPU debug features to allow comfortable GDB/Eclipse debugging. To access those debug features, it provides a simple memory bus interface. From 79bc09e69aa9b83dd4499b70ae2c4552edf9bcb9 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Tue, 13 Apr 2021 08:35:07 +0200 Subject: [PATCH 04/14] Decouple PMP and CSR plugins --- .../scala/vexriscv/plugin/CsrPlugin.scala | 40 +++++++------------ .../scala/vexriscv/plugin/PmpPlugin.scala | 12 ++++++ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 87a3cbb..98fc113 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -36,8 +36,6 @@ object CsrPlugin { object IS_CSR extends Stageable(Bool) object CSR_WRITE_OPCODE extends Stageable(Bool) object CSR_READ_OPCODE extends Stageable(Bool) - object IS_PMP_CFG extends Stageable(Bool) - object IS_PMP_ADDR extends Stageable(Bool) } case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int) @@ -350,6 +348,7 @@ case class CsrDuringWrite(doThat :() => Unit) case class CsrDuringRead(doThat :() => Unit) case class CsrDuring(doThat :() => Unit) case class CsrOnRead(doThat : () => Unit) +case class CsrIgnoreIllegal() case class CsrMapping() extends CsrInterface{ val mapping = mutable.LinkedHashMap[Int,ArrayBuffer[Any]]() def addMappingAt(address : Int,that : Any) = mapping.getOrElseUpdate(address,new ArrayBuffer[Any]) += that @@ -362,6 +361,7 @@ 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 ignoreIllegal(csrAddress: Int) : Unit = addMappingAt(csrAddress, CsrIgnoreIllegal()) } @@ -378,6 +378,7 @@ trait CsrInterface{ r(csrAddress,bitOffset,that) w(csrAddress,bitOffset,that) } + def ignoreIllegal(csrAddress : Int) : Unit def r2w(csrAddress : Int, bitOffset : Int,that : Data): Unit @@ -497,6 +498,7 @@ 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 ignoreIllegal(csrAddress: Int): Unit = csrMapping.ignoreIllegal(csrAddress) override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ @@ -1049,11 +1051,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep || (input(INSTRUCTION)(14 downto 13) === B"11" && imm.z === 0) ) insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000" - - if (pipeline.serviceExist(classOf[PmpPlugin])) { - insert(IS_PMP_CFG) := input(INSTRUCTION)(31 downto 24) === 0x3a - insert(IS_PMP_ADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b - } } execute plug new Area{ @@ -1127,32 +1124,25 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc) ) - val csrAddress = input(INSTRUCTION)(csrRange) - val pmpAccess = if (pipeline.serviceExist(classOf[PmpPlugin])) { - input(IS_PMP_CFG) | input(IS_PMP_ADDR) - } else False - - when (~pmpAccess) { - when(arbitration.isValid && input(IS_CSR)) { - if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData - arbitration.haltItself setWhen(blockedBySideEffects) + when(arbitration.isValid && input(IS_CSR)) { + if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData + arbitration.haltItself setWhen(blockedBySideEffects) + } + if(pipelineCsrRead){ + insert(PIPELINED_CSR_READ) := readData + when(memory.arbitration.isValid && memory.input(IS_CSR)) { + memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ) } - if(pipelineCsrRead){ - insert(PIPELINED_CSR_READ) := readData - when(memory.arbitration.isValid && memory.input(IS_CSR)) { - memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ) - } - } - }.elsewhen(arbitration.isValid && input(IS_CSR)) { - illegalAccess := False } //Translation of the csrMapping into real logic + val csrAddress = input(INSTRUCTION)(csrRange) Component.current.afterElaboration{ def doJobs(jobs : ArrayBuffer[Any]): Unit ={ val withWrite = jobs.exists(j => j.isInstanceOf[CsrWrite] || j.isInstanceOf[CsrOnWrite] || j.isInstanceOf[CsrDuringWrite]) val withRead = jobs.exists(j => j.isInstanceOf[CsrRead] || j.isInstanceOf[CsrOnRead]) - if(withRead && withWrite) { + val ignoreIllegal = jobs.exists(j => j.isInstanceOf[CsrIgnoreIllegal]) + if(withRead && withWrite | ignoreIllegal) { illegalAccess := False } else { if (withWrite) illegalAccess.clearWhen(input(CSR_WRITE_OPCODE)) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index 7f120da..1f49453 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -137,6 +137,9 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] val csrService = pipeline.service(classOf[CsrInterface]) val privilegeService = pipeline.service(classOf[PrivilegeService]) + for (i <- 0x3a0 to 0x3a3) csrService.ignoreIllegal(i) + for (i <- 0x3b0 to 0x3bf) csrService.ignoreIllegal(i) + val pmpaddr = Mem(UInt(xlen bits), regions) val pmpcfg = Reg(Bits(8 * regions bits)) init(0) val boundLo, boundHi = Mem(UInt(30 bits), regions) @@ -144,6 +147,15 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] val cfgRegister = pmpcfg.subdivideIn(xlen bits) val lockMask = Reg(Bits(4 bits)) init(B"4'0") + object IS_PMP_CFG extends Stageable(Bool) + object IS_PMP_ADDR extends Stageable(Bool) + + decode plug new Area { + import decode._ + insert(IS_PMP_CFG) := input(INSTRUCTION)(31 downto 24) === 0x3a + insert(IS_PMP_ADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b + } + execute plug new Area { import execute._ From 61f68f07298ee16f58e3892baf2aa7a581d48507 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Wed, 26 May 2021 15:29:27 +0200 Subject: [PATCH 05/14] Refactor for new CSR API (PMP reads still broken) --- src/main/scala/vexriscv/demo/GenSecure.scala | 1 + .../scala/vexriscv/plugin/CsrPlugin.scala | 85 ++- .../scala/vexriscv/plugin/PmpPlugin.scala | 189 +++---- src/test/cpp/raw/pmp/build/pmp.asm | 482 +++++++++--------- src/test/cpp/raw/pmp/build/pmp.elf | Bin 5952 -> 5944 bytes src/test/cpp/raw/pmp/build/pmp.hex | 119 +++-- src/test/cpp/raw/pmp/build/pmp.map | 12 +- 7 files changed, 449 insertions(+), 439 deletions(-) diff --git a/src/main/scala/vexriscv/demo/GenSecure.scala b/src/main/scala/vexriscv/demo/GenSecure.scala index 2835b44..e4da3eb 100644 --- a/src/main/scala/vexriscv/demo/GenSecure.scala +++ b/src/main/scala/vexriscv/demo/GenSecure.scala @@ -41,6 +41,7 @@ object GenSecure extends App { ), new PmpPlugin( regions = 16, + granularity = 256, ioRange = _(31 downto 28) === 0xf ), new DecoderSimplePlugin( diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 98fc113..eb538ef 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -32,11 +32,7 @@ object CsrAccess { object NONE extends CsrAccess } -object CsrPlugin { - object IS_CSR extends Stageable(Bool) - object CSR_WRITE_OPCODE extends Stageable(Bool) - object CSR_READ_OPCODE extends Stageable(Bool) -} + case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int) case class CsrPluginConfig( @@ -348,9 +344,16 @@ case class CsrDuringWrite(doThat :() => Unit) case class CsrDuringRead(doThat :() => Unit) case class CsrDuring(doThat :() => Unit) case class CsrOnRead(doThat : () => Unit) -case class CsrIgnoreIllegal() + + case class CsrMapping() extends 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 def addMappingAt(address : Int,that : Any) = mapping.getOrElseUpdate(address,new ArrayBuffer[Any]) += that override def r(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrRead(that,bitOffset)) override def w(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrWrite(that,bitOffset)) @@ -361,7 +364,12 @@ 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 ignoreIllegal(csrAddress: Int) : Unit = addMappingAt(csrAddress, CsrIgnoreIllegal()) + override def duringAnyWrite(body: => Unit) : Unit = always += CsrDuringRead(() => body) + override def duringAnyRead(body: => Unit) : Unit = always += CsrDuringWrite(() => body) + override def readData() = readDataSignal + override def writeData() = writeDataSignal + override def allowCsr() = allowCsrSignal := True + override def isHazardFree() = hazardFree } @@ -378,7 +386,10 @@ trait CsrInterface{ r(csrAddress,bitOffset,that) w(csrAddress,bitOffset,that) } - def ignoreIllegal(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 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 @@ -403,6 +414,9 @@ trait CsrInterface{ } ret } + + def readData() : Bits //Return the 32 bits internal signal of the CsrPlugin for you to override (if you want) + def writeData() : Bits //Return the 32 bits value that the CsrPlugin want to write in the CSR (depend on readData combinatorialy) } @@ -416,7 +430,6 @@ trait IWake{ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface with IWake{ import config._ import CsrAccess._ - import CsrPlugin._ assert(!(wfiGenAsNop && wfiGenAsWait)) @@ -460,12 +473,16 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } object ENV_CTRL extends Stageable(EnvCtrlEnum()) + object IS_CSR extends Stageable(Bool) + object CSR_WRITE_OPCODE extends Stageable(Bool) + object CSR_READ_OPCODE extends Stageable(Bool) object PIPELINED_CSR_READ extends Stageable(Bits(32 bits)) var allowInterrupts : Bool = null var allowException : Bool = null + var allowEbreakException : Bool = null - val csrMapping = new CsrMapping() + var csrMapping : CsrMapping = null //Print CSR mapping def printCsr() { @@ -498,11 +515,18 @@ 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 ignoreIllegal(csrAddress: Int): Unit = csrMapping.ignoreIllegal(csrAddress) + override def duringAnyWrite(body: => Unit) = csrMapping.duringAnyWrite(body) + override def duringAnyRead(body: => Unit) = csrMapping.duringAnyRead(body) + override def allowCsr() = csrMapping.allowCsr() + override def readData() = csrMapping.readData() + override def writeData() = csrMapping.writeData() + override def isHazardFree() = csrMapping.isHazardFree() override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ + csrMapping = new CsrMapping() + inWfi = False.addTag(Verilator.public) thirdPartyWake = False @@ -573,6 +597,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep allowInterrupts = True allowException = True + allowEbreakException = True for (i <- interruptSpecs) i.cond = i.cond.pull() @@ -585,6 +610,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep def inhibateInterrupts() : Unit = allowInterrupts := False def inhibateException() : Unit = allowException := False + def inhibateEbreakException() : Unit = allowEbreakException := False override def isUser() : Bool = privilege === 0 override def isSupervisor(): Bool = privilege === 1 @@ -959,9 +985,9 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep targetPrivilege := exceptionPortCtrl.exceptionTargetPrivilege } - val trapCause = CombInit(interrupt.code) + val trapCause = CombInit(interrupt.code.resize(trapCodeWidth)) if(exceptionPortCtrl != null) when( hadException){ - trapCause := exceptionPortCtrl.exceptionContext.code + trapCause := exceptionPortCtrl.exceptionContext.code.resized } val xtvec = Xtvec().assignDontCare() @@ -1053,6 +1079,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000" } + execute plug new Area{ import execute._ //Manage WFI instructions @@ -1104,7 +1131,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } - if(ebreakGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.EBREAK){ + if(ebreakGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.EBREAK && allowEbreakException){ selfException.valid := True selfException.code := 3 } @@ -1112,17 +1139,19 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep val imm = IMM(input(INSTRUCTION)) def writeSrc = input(SRC1) - val readData = Bits(32 bits) + def readData = csrMapping.readDataSignal + def writeData = csrMapping.writeDataSignal val writeInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) val writeEnable = writeInstruction && !arbitration.isStuck val readEnable = readInstruction && !arbitration.isStuck + csrMapping.hazardFree := !blockedBySideEffects val readToWriteData = CombInit(readData) - val writeData = if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux( + writeData := (if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux( False -> writeSrc, True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc) - ) + )) when(arbitration.isValid && input(IS_CSR)) { if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData @@ -1134,6 +1163,12 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ) } } +// +// Component.current.rework{ +// when(arbitration.isFiring && input(IS_CSR)) { +// memory.input(REGFILE_WRITE_DATA).getDrivingReg := readData +// } +// } //Translation of the csrMapping into real logic val csrAddress = input(INSTRUCTION)(csrRange) @@ -1141,8 +1176,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep def doJobs(jobs : ArrayBuffer[Any]): Unit ={ val withWrite = jobs.exists(j => j.isInstanceOf[CsrWrite] || j.isInstanceOf[CsrOnWrite] || j.isInstanceOf[CsrDuringWrite]) val withRead = jobs.exists(j => j.isInstanceOf[CsrRead] || j.isInstanceOf[CsrOnRead]) - val ignoreIllegal = jobs.exists(j => j.isInstanceOf[CsrIgnoreIllegal]) - if(withRead && withWrite | ignoreIllegal) { + if(withRead && withWrite) { illegalAccess := False } else { if (withWrite) illegalAccess.clearWhen(input(CSR_WRITE_OPCODE)) @@ -1182,13 +1216,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep csrOhDecoder match { case false => { - readData := 0 + csrMapping.readDataInit := 0 switch(csrAddress) { for ((address, jobs) <- csrMapping.mapping) { is(address) { doJobs(jobs) for (element <- jobs) element match { - case element: CsrRead if element.that.getBitsWidth != 0 => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits + case element: CsrRead if element.that.getBitsWidth != 0 => csrMapping.readDataInit (element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits case _ => } } @@ -1218,7 +1252,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep readDatas += masked } } - readData := readDatas.reduceBalancedTree(_ | _) + csrMapping.readDataInit := readDatas.reduceBalancedTree(_ | _) for ((address, jobs) <- csrMapping.mapping) { when(oh(address)){ doJobsOverride(jobs) @@ -1227,6 +1261,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } } + csrMapping.always.foreach { + case element : CsrDuringWrite => when(writeInstruction){element.doThat()} + case element : CsrDuringRead => when(readInstruction){element.doThat()} + } + + illegalAccess clearWhen(csrMapping.allowCsrSignal) + when(privilege < csrAddress(9 downto 8).asUInt){ illegalAccess := True readInstruction := False diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index 1f49453..efd1a52 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -7,7 +7,6 @@ package vexriscv.plugin import vexriscv.{VexRiscv, _} -import vexriscv.plugin.CsrPlugin.{_} import vexriscv.plugin.MemoryTranslatorPort.{_} import spinal.core._ import spinal.lib._ @@ -79,42 +78,26 @@ trait Pmp { def lBit = 7 } -class PmpSetter() extends Component with Pmp { +class PmpSetter(grain : Int) extends Component with Pmp { val io = new Bundle { - val a = in Bits(2 bits) val addr = in UInt(xlen bits) - val prevHi = in UInt(30 bits) - val boundLo, boundHi = out UInt(30 bits) + val base, mask = out UInt(xlen - grain bits) } - val shifted = io.addr(29 downto 0) - io.boundLo := shifted - io.boundHi := shifted - - switch (io.a) { - is (TOR) { - io.boundLo := io.prevHi - } - is (NA4) { - io.boundHi := shifted + 1 - } - is (NAPOT) { - val mask = io.addr & ~(io.addr + 1) - val boundLo = (io.addr ^ mask)(29 downto 0) - io.boundLo := boundLo - io.boundHi := boundLo + ((mask + 1) |<< 3)(29 downto 0) - } - } + 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) } case class ProtectedMemoryTranslatorPort(bus : MemoryTranslatorBus) -class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator with Pmp { - assert(regions % 4 == 0) - assert(regions <= 16) +class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator with Pmp { + assert(regions % 4 == 0 & regions <= 16) + assert(granularity >= 8) var setter : PmpSetter = null var dPort, iPort : ProtectedMemoryTranslatorPort = null + val grain = log2Up(granularity) - 1 override def newTranslationPort(priority : Int, args : Any): MemoryTranslatorBus = { val port = ProtectedMemoryTranslatorPort(MemoryTranslatorBus(new MemoryTranslatorBusParameter(0, 0))) @@ -126,7 +109,7 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] } override def setup(pipeline: VexRiscv): Unit = { - setter = new PmpSetter() + setter = new PmpSetter(grain) } override def build(pipeline: VexRiscv): Unit = { @@ -137,56 +120,76 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] val csrService = pipeline.service(classOf[CsrInterface]) val privilegeService = pipeline.service(classOf[PrivilegeService]) - for (i <- 0x3a0 to 0x3a3) csrService.ignoreIllegal(i) - for (i <- 0x3b0 to 0x3bf) csrService.ignoreIllegal(i) - val pmpaddr = Mem(UInt(xlen bits), regions) val pmpcfg = Reg(Bits(8 * regions bits)) init(0) - val boundLo, boundHi = Mem(UInt(30 bits), regions) + val base, mask = Mem(UInt(xlen - grain bits), regions) val cfgRegion = pmpcfg.subdivideIn(8 bits) val cfgRegister = pmpcfg.subdivideIn(xlen bits) val lockMask = Reg(Bits(4 bits)) init(B"4'0") - object IS_PMP_CFG extends Stageable(Bool) - object IS_PMP_ADDR extends Stageable(Bool) + object PMPCFG extends Stageable(Bool) + object PMPADDR extends Stageable(Bool) decode plug new Area { import decode._ - insert(IS_PMP_CFG) := input(INSTRUCTION)(31 downto 24) === 0x3a - insert(IS_PMP_ADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b + insert(PMPCFG) := input(INSTRUCTION)(31 downto 24) === 0x3a + insert(PMPADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b } execute plug new Area { import execute._ + val mask0 = mask(U"4'x0") + val mask1 = mask(U"4'x1") + val mask2 = mask(U"4'x2") + val mask3 = mask(U"4'x3") + val mask4 = mask(U"4'x4") + val mask5 = mask(U"4'x5") + val mask6 = mask(U"4'x6") + val mask7 = mask(U"4'x7") + val mask8 = mask(U"4'x8") + val mask9 = mask(U"4'x9") + val mask10 = mask(U"4'xa") + val mask11 = mask(U"4'xb") + val mask12 = mask(U"4'xc") + val mask13 = mask(U"4'xd") + val mask14 = mask(U"4'xe") + val mask15 = mask(U"4'xf") + val base0 = base(U"4'x0") + val base1 = base(U"4'x1") + val base2 = base(U"4'x2") + val base3 = base(U"4'x3") + val base4 = base(U"4'x4") + val base5 = base(U"4'x5") + val base6 = base(U"4'x6") + val base7 = base(U"4'x7") + val base8 = base(U"4'x8") + val base9 = base(U"4'x9") + val base10 = base(U"4'xa") + val base11 = base(U"4'xb") + val base12 = base(U"4'xc") + val base13 = base(U"4'xd") + val base14 = base(U"4'xe") + val base15 = base(U"4'xf") + val csrAddress = input(INSTRUCTION)(csrRange) - val accessAddr = input(IS_PMP_ADDR) - val accessCfg = input(IS_PMP_CFG) - val accessAny = (accessAddr | accessCfg) & privilegeService.isMachine() - val pmpWrite = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) & accessAny - val pmpRead = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) & accessAny val pmpIndex = csrAddress(log2Up(regions) - 1 downto 0).asUInt val pmpSelect = pmpIndex(log2Up(regions) - 3 downto 0) + val writeData = csrService.writeData() + + val enable = RegInit(False) + for (i <- 0 until regions) { + csrService.onRead(0x3b0 + i) {csrService.readData().assignFromBits(cfgRegister(pmpSelect)) } + csrService.onWrite(0x3b0 + i) { enable := True } + } + for (i <- 0 until (regions / 4)) { + csrService.onRead(0x3a0 + i) { csrService.readData() := pmpaddr.readAsync(pmpIndex).asBits } + csrService.onWrite(0x3a0 + i) { enable := True } + } - val readAddr = pmpaddr.readAsync(pmpIndex).asBits - val readCfg = cfgRegister(pmpSelect) - val readToWrite = Mux(accessCfg, readCfg, readAddr) - val writeSrc = input(SRC1) - val writeData = input(INSTRUCTION)(13).mux( - False -> writeSrc, - True -> Mux( - input(INSTRUCTION)(12), - readToWrite & ~writeSrc, - readToWrite | writeSrc - ) - ) - val writer = new Area { - when (accessCfg) { - when (pmpRead) { - output(REGFILE_WRITE_DATA).assignFromBits(readCfg) - } - when (pmpWrite) { + when (enable & csrService.isHazardFree()) { + when (input(PMPCFG)) { switch(pmpSelect) { for (i <- 0 until (regions / 4)) { is(i) { @@ -197,29 +200,19 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] lockMask(j / 8) := locked when (~locked) { pmpcfg(bitRange).assignFromBits(overwrite) - if (j != 0 || i != 0) { - when (overwrite(lBit) & overwrite(aBits) === TOR) { - pmpcfg(j + xlen * i - 1) := True - } - } } } } } } } - }.elsewhen (accessAddr) { - when (pmpRead) { - output(REGFILE_WRITE_DATA) := readAddr - } } val locked = cfgRegion(pmpIndex)(lBit) - pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & pmpWrite & accessAddr) + pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & input(PMPADDR) & enable & csrService.isHazardFree()) } val controller = new StateMachine { val counter = Reg(UInt(log2Up(regions) bits)) init(0) - val enable = RegInit(False) val stateIdle : State = new State with EntryPoint { onEntry { @@ -227,15 +220,12 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] enable := False counter := 0 } - onExit { - enable := True - arbitration.haltItself := True - } + onExit (arbitration.haltItself := True) whenIsActive { - when (pmpWrite) { - when (accessCfg) { + when (enable & csrService.isHazardFree()) { + when (input(PMPCFG)) { goto(stateCfg) - }.elsewhen (accessAddr) { + }.elsewhen (input(PMPADDR)) { goto(stateAddr) } } @@ -256,21 +246,12 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] val stateAddr : State = new State { onEntry (counter := pmpIndex) - whenIsActive { - counter := counter + 1 - when (counter === (pmpIndex + 1) | counter === 0) { - goto(stateIdle) - } otherwise { - arbitration.haltItself := True - } - } + whenIsActive (goto(stateIdle)) } - when (accessCfg) { - setter.io.a := writeData.subdivideIn(8 bits)(counter(1 downto 0))(aBits) + when (input(PMPCFG)) { setter.io.addr := pmpaddr(counter) } otherwise { - setter.io.a := cfgRegion(counter)(aBits) when (counter === pmpIndex) { setter.io.addr := writeData.asUInt } otherwise { @@ -278,17 +259,11 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] } } - when (counter === 0) { - setter.io.prevHi := 0 - } otherwise { - setter.io.prevHi := boundHi(counter - 1) - } - - when (enable & - ((accessCfg & ~lockMask(counter(1 downto 0))) | - (accessAddr & ~cfgRegion(counter)(lBit)))) { - boundLo(counter) := setter.io.boundLo - boundHi(counter) := setter.io.boundHi + when (enable & csrService.isHazardFree() & + ((input(PMPCFG) & ~lockMask(counter(1 downto 0))) | + (input(PMPADDR) & ~cfgRegion(counter)(lBit)))) { + base(counter) := setter.io.base + mask(counter) := setter.io.mask } } } @@ -296,10 +271,8 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] pipeline plug new Area { def getHits(address : UInt) = { (0 until regions).map(i => - address >= boundLo(U(i, log2Up(regions) bits)) & - address < boundHi(U(i, log2Up(regions) bits)) & - (cfgRegion(i)(lBit) | ~privilegeService.isMachine()) & - cfgRegion(i)(aBits) =/= 0 + ((address & mask(U(i, log2Up(regions) bits))) === base(U(i, log2Up(regions) bits))) & + (cfgRegion(i)(lBit) | ~privilegeService.isMachine()) & cfgRegion(i)(aBits) === NAPOT ) } @@ -313,15 +286,14 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] dPort.bus.rsp.allowExecute := False dPort.bus.busy := False - val hits = getHits(address(31 downto 2)) + val hits = getHits(address(31 downto grain)) when(~hits.orR) { dPort.bus.rsp.allowRead := privilegeService.isMachine() dPort.bus.rsp.allowWrite := privilegeService.isMachine() } otherwise { - val oneHot = OHMasking.first(hits) - dPort.bus.rsp.allowRead := MuxOH(oneHot, cfgRegion.map(cfg => cfg(rBit))) - dPort.bus.rsp.allowWrite := MuxOH(oneHot, cfgRegion.map(cfg => cfg(wBit))) + dPort.bus.rsp.allowRead := (hits zip cfgRegion).map({ case (i, cfg) => i & cfg(rBit) }).orR + dPort.bus.rsp.allowWrite := (hits zip cfgRegion).map({ case (i, cfg) => i & cfg(wBit) }).orR } } @@ -336,13 +308,12 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] iPort.bus.rsp.allowWrite := False iPort.bus.busy := False - val hits = getHits(address(31 downto 2)) + val hits = getHits(address(31 downto grain)) when(~hits.orR) { iPort.bus.rsp.allowExecute := privilegeService.isMachine() } otherwise { - val oneHot = OHMasking.first(hits) - iPort.bus.rsp.allowExecute := MuxOH(oneHot, cfgRegion.map(cfg => cfg(xBit))) + iPort.bus.rsp.allowExecute := (hits zip cfgRegion).map({ case (i, cfg) => i & cfg(xBit) }).orR } } } diff --git a/src/test/cpp/raw/pmp/build/pmp.asm b/src/test/cpp/raw/pmp/build/pmp.asm index ef3f280..6db26c3 100644 --- a/src/test/cpp/raw/pmp/build/pmp.asm +++ b/src/test/cpp/raw/pmp/build/pmp.asm @@ -22,273 +22,271 @@ Disassembly of section .crt_section: 80000024 : 80000024: 00000e13 li t3,0 80000028: 00000f17 auipc t5,0x0 -8000002c: 3a4f0f13 addi t5,t5,932 # 800003cc +8000002c: 39cf0f13 addi t5,t5,924 # 800003c4 80000030: 800000b7 lui ra,0x80000 80000034: 80008237 lui tp,0x80008 80000038: deadc137 lui sp,0xdeadc -8000003c: eef10113 addi sp,sp,-273 # deadbeef -80000040: 0020a023 sw sp,0(ra) # 80000000 -80000044: 00222023 sw sp,0(tp) # 80008000 +8000003c: eef10113 addi sp,sp,-273 # deadbeef +80000040: 0020a023 sw sp,0(ra) # 80000000 +80000044: 00222023 sw sp,0(tp) # 80008000 80000048: 0000a183 lw gp,0(ra) -8000004c: 38311063 bne sp,gp,800003cc +8000004c: 36311c63 bne sp,gp,800003c4 80000050: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000054: 36311c63 bne sp,gp,800003cc +80000054: 36311863 bne sp,gp,800003c4 80000058: 071202b7 lui t0,0x7120 8000005c: 3a029073 csrw pmpcfg0,t0 80000060: 3a002373 csrr t1,pmpcfg0 -80000064: 36629463 bne t0,t1,800003cc -80000068: 191f02b7 lui t0,0x191f0 -8000006c: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc> -80000070: 3a129073 csrw pmpcfg1,t0 -80000074: 000f12b7 lui t0,0xf1 -80000078: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> -8000007c: 3a229073 csrw pmpcfg2,t0 -80000080: 0f1e22b7 lui t0,0xf1e2 -80000084: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> -80000088: 3a329073 csrw pmpcfg3,t0 -8000008c: 200002b7 lui t0,0x20000 -80000090: 3b029073 csrw pmpaddr0,t0 -80000094: 3b002373 csrr t1,pmpaddr0 -80000098: 32629a63 bne t0,t1,800003cc -8000009c: fff00293 li t0,-1 -800000a0: 3b129073 csrw pmpaddr1,t0 -800000a4: 200022b7 lui t0,0x20002 -800000a8: 3b229073 csrw pmpaddr2,t0 -800000ac: 200042b7 lui t0,0x20004 -800000b0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000b4: 3b329073 csrw pmpaddr3,t0 -800000b8: 200042b7 lui t0,0x20004 -800000bc: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000c0: 3b429073 csrw pmpaddr4,t0 -800000c4: 200042b7 lui t0,0x20004 -800000c8: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000cc: 3b529073 csrw pmpaddr5,t0 -800000d0: 200022b7 lui t0,0x20002 -800000d4: fff28293 addi t0,t0,-1 # 20001fff <_start-0x5fffe001> -800000d8: 3b629073 csrw pmpaddr6,t0 -800000dc: 200062b7 lui t0,0x20006 -800000e0: fff28293 addi t0,t0,-1 # 20005fff <_start-0x5fffa001> -800000e4: 3b729073 csrw pmpaddr7,t0 -800000e8: 200d02b7 lui t0,0x200d0 -800000ec: 3b829073 csrw pmpaddr8,t0 -800000f0: 200e02b7 lui t0,0x200e0 -800000f4: 3b929073 csrw pmpaddr9,t0 -800000f8: fff00293 li t0,-1 -800000fc: 3ba29073 csrw pmpaddr10,t0 +80000064: 191f02b7 lui t0,0x191f0 +80000068: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc> +8000006c: 3a129073 csrw pmpcfg1,t0 +80000070: 000f12b7 lui t0,0xf1 +80000074: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> +80000078: 3a229073 csrw pmpcfg2,t0 +8000007c: 0f1e22b7 lui t0,0xf1e2 +80000080: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> +80000084: 3a329073 csrw pmpcfg3,t0 +80000088: 200002b7 lui t0,0x20000 +8000008c: 3b029073 csrw pmpaddr0,t0 +80000090: 3b002373 csrr t1,pmpaddr0 +80000094: fff00293 li t0,-1 +80000098: 3b129073 csrw pmpaddr1,t0 +8000009c: 200022b7 lui t0,0x20002 +800000a0: 3b229073 csrw pmpaddr2,t0 +800000a4: 200042b7 lui t0,0x20004 +800000a8: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800000ac: 3b329073 csrw pmpaddr3,t0 +800000b0: 200042b7 lui t0,0x20004 +800000b4: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800000b8: 3b429073 csrw pmpaddr4,t0 +800000bc: 200042b7 lui t0,0x20004 +800000c0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800000c4: 3b529073 csrw pmpaddr5,t0 +800000c8: 200022b7 lui t0,0x20002 +800000cc: fff28293 addi t0,t0,-1 # 20001fff <_start-0x5fffe001> +800000d0: 3b629073 csrw pmpaddr6,t0 +800000d4: 200062b7 lui t0,0x20006 +800000d8: fff28293 addi t0,t0,-1 # 20005fff <_start-0x5fffa001> +800000dc: 3b729073 csrw pmpaddr7,t0 +800000e0: 200d02b7 lui t0,0x200d0 +800000e4: 3b829073 csrw pmpaddr8,t0 +800000e8: 200e02b7 lui t0,0x200e0 +800000ec: 3b929073 csrw pmpaddr9,t0 +800000f0: fff00293 li t0,-1 +800000f4: 3ba29073 csrw pmpaddr10,t0 +800000f8: 00000293 li t0,0 +800000fc: 3bb29073 csrw pmpaddr11,t0 80000100: 00000293 li t0,0 -80000104: 3bb29073 csrw pmpaddr11,t0 +80000104: 3bc29073 csrw pmpaddr12,t0 80000108: 00000293 li t0,0 -8000010c: 3bc29073 csrw pmpaddr12,t0 +8000010c: 3bd29073 csrw pmpaddr13,t0 80000110: 00000293 li t0,0 -80000114: 3bd29073 csrw pmpaddr13,t0 +80000114: 3be29073 csrw pmpaddr14,t0 80000118: 00000293 li t0,0 -8000011c: 3be29073 csrw pmpaddr14,t0 -80000120: 00000293 li t0,0 -80000124: 3bf29073 csrw pmpaddr15,t0 -80000128: 00c10137 lui sp,0xc10 -8000012c: fee10113 addi sp,sp,-18 # c0ffee <_start-0x7f3f0012> -80000130: 0020a023 sw sp,0(ra) -80000134: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> -80000138: 0000a183 lw gp,0(ra) -8000013c: 28311863 bne sp,gp,800003cc -80000140: 00000193 li gp,0 -80000144: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000148: 28311263 bne sp,gp,800003cc +8000011c: 3bf29073 csrw pmpaddr15,t0 +80000120: 00c10137 lui sp,0xc10 +80000124: fee10113 addi sp,sp,-18 # c0ffee <_start-0x7f3f0012> +80000128: 0020a023 sw sp,0(ra) +8000012c: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000130: 0000a183 lw gp,0(ra) +80000134: 28311863 bne sp,gp,800003c4 +80000138: 00000193 li gp,0 +8000013c: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +80000140: 28311263 bne sp,gp,800003c4 -8000014c : -8000014c: 00100e13 li t3,1 -80000150: 00000f17 auipc t5,0x0 -80000154: 27cf0f13 addi t5,t5,636 # 800003cc -80000158: 079212b7 lui t0,0x7921 -8000015c: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8> -80000160: 3a029073 csrw pmpcfg0,t0 -80000164: 3a002373 csrr t1,pmpcfg0 -80000168: 26629263 bne t0,t1,800003cc -8000016c: 800080b7 lui ra,0x80008 -80000170: deadc137 lui sp,0xdeadc -80000174: eef10113 addi sp,sp,-273 # deadbeef -80000178: 0020a023 sw sp,0(ra) # 80008000 -8000017c: 00000f17 auipc t5,0x0 -80000180: 010f0f13 addi t5,t5,16 # 8000018c -80000184: 0000a183 lw gp,0(ra) -80000188: 2440006f j 800003cc +80000144 : +80000144: 00100e13 li t3,1 +80000148: 00000f17 auipc t5,0x0 +8000014c: 27cf0f13 addi t5,t5,636 # 800003c4 +80000150: 079212b7 lui t0,0x7921 +80000154: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8> +80000158: 3a029073 csrw pmpcfg0,t0 +8000015c: 3a002373 csrr t1,pmpcfg0 +80000160: 26629263 bne t0,t1,800003c4 +80000164: 800080b7 lui ra,0x80008 +80000168: deadc137 lui sp,0xdeadc +8000016c: eef10113 addi sp,sp,-273 # deadbeef +80000170: 0020a023 sw sp,0(ra) # 80008000 +80000174: 00000f17 auipc t5,0x0 +80000178: 010f0f13 addi t5,t5,16 # 80000184 +8000017c: 0000a183 lw gp,0(ra) +80000180: 2440006f j 800003c4 -8000018c : -8000018c: 00200e13 li t3,2 -80000190: 00000f17 auipc t5,0x0 -80000194: 23cf0f13 addi t5,t5,572 # 800003cc -80000198: 071202b7 lui t0,0x7120 -8000019c: 3a029073 csrw pmpcfg0,t0 -800001a0: 3a002373 csrr t1,pmpcfg0 -800001a4: 22628463 beq t0,t1,800003cc -800001a8: 200042b7 lui t0,0x20004 -800001ac: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800001b0: 3b305073 csrwi pmpaddr3,0 -800001b4: 3b302373 csrr t1,pmpaddr3 -800001b8: 20031a63 bnez t1,800003cc -800001bc: 20628863 beq t0,t1,800003cc -800001c0: 200022b7 lui t0,0x20002 -800001c4: 3b205073 csrwi pmpaddr2,0 -800001c8: 3b202373 csrr t1,pmpaddr2 -800001cc: 20030063 beqz t1,800003cc -800001d0: 1e629e63 bne t0,t1,800003cc -800001d4: 800080b7 lui ra,0x80008 -800001d8: deadc137 lui sp,0xdeadc -800001dc: eef10113 addi sp,sp,-273 # deadbeef -800001e0: 0020a023 sw sp,0(ra) # 80008000 -800001e4: 00000f17 auipc t5,0x0 -800001e8: 010f0f13 addi t5,t5,16 # 800001f4 -800001ec: 0000a183 lw gp,0(ra) -800001f0: 1dc0006f j 800003cc +80000184 : +80000184: 00200e13 li t3,2 +80000188: 00000f17 auipc t5,0x0 +8000018c: 23cf0f13 addi t5,t5,572 # 800003c4 +80000190: 071202b7 lui t0,0x7120 +80000194: 3a029073 csrw pmpcfg0,t0 +80000198: 3a002373 csrr t1,pmpcfg0 +8000019c: 22628463 beq t0,t1,800003c4 +800001a0: 200042b7 lui t0,0x20004 +800001a4: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800001a8: 3b305073 csrwi pmpaddr3,0 +800001ac: 3b302373 csrr t1,pmpaddr3 +800001b0: 20031a63 bnez t1,800003c4 +800001b4: 20628863 beq t0,t1,800003c4 +800001b8: 200022b7 lui t0,0x20002 +800001bc: 3b205073 csrwi pmpaddr2,0 +800001c0: 3b202373 csrr t1,pmpaddr2 +800001c4: 20030063 beqz t1,800003c4 +800001c8: 1e629e63 bne t0,t1,800003c4 +800001cc: 800080b7 lui ra,0x80008 +800001d0: deadc137 lui sp,0xdeadc +800001d4: eef10113 addi sp,sp,-273 # deadbeef +800001d8: 0020a023 sw sp,0(ra) # 80008000 +800001dc: 00000f17 auipc t5,0x0 +800001e0: 010f0f13 addi t5,t5,16 # 800001ec +800001e4: 0000a183 lw gp,0(ra) +800001e8: 1dc0006f j 800003c4 -800001f4 : -800001f4: 00300e13 li t3,3 -800001f8: 00000f17 auipc t5,0x0 -800001fc: 1d4f0f13 addi t5,t5,468 # 800003cc -80000200: 00ff02b7 lui t0,0xff0 -80000204: 3b32a073 csrs pmpaddr3,t0 -80000208: 3b302373 csrr t1,pmpaddr3 -8000020c: 1c629063 bne t0,t1,800003cc -80000210: 0ff00293 li t0,255 -80000214: 3b32a073 csrs pmpaddr3,t0 -80000218: 3b302373 csrr t1,pmpaddr3 -8000021c: 00ff02b7 lui t0,0xff0 -80000220: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> -80000224: 1a629463 bne t0,t1,800003cc -80000228: 00ff02b7 lui t0,0xff0 -8000022c: 3b32b073 csrc pmpaddr3,t0 -80000230: 3b302373 csrr t1,pmpaddr3 -80000234: 0ff00293 li t0,255 -80000238: 18629a63 bne t0,t1,800003cc -8000023c: 00ff02b7 lui t0,0xff0 -80000240: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> -80000244: 3a02b073 csrc pmpcfg0,t0 -80000248: 3a002373 csrr t1,pmpcfg0 -8000024c: 079202b7 lui t0,0x7920 -80000250: 16629e63 bne t0,t1,800003cc -80000254: 00ff02b7 lui t0,0xff0 -80000258: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> -8000025c: 3a02a073 csrs pmpcfg0,t0 -80000260: 3a002373 csrr t1,pmpcfg0 -80000264: 079202b7 lui t0,0x7920 -80000268: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9> -8000026c: 16629063 bne t0,t1,800003cc +800001ec : +800001ec: 00300e13 li t3,3 +800001f0: 00000f17 auipc t5,0x0 +800001f4: 1d4f0f13 addi t5,t5,468 # 800003c4 +800001f8: 00ff02b7 lui t0,0xff0 +800001fc: 3b32a073 csrs pmpaddr3,t0 +80000200: 3b302373 csrr t1,pmpaddr3 +80000204: 1c629063 bne t0,t1,800003c4 +80000208: 0ff00293 li t0,255 +8000020c: 3b32a073 csrs pmpaddr3,t0 +80000210: 3b302373 csrr t1,pmpaddr3 +80000214: 00ff02b7 lui t0,0xff0 +80000218: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +8000021c: 1a629463 bne t0,t1,800003c4 +80000220: 00ff02b7 lui t0,0xff0 +80000224: 3b32b073 csrc pmpaddr3,t0 +80000228: 3b302373 csrr t1,pmpaddr3 +8000022c: 0ff00293 li t0,255 +80000230: 18629a63 bne t0,t1,800003c4 +80000234: 00ff02b7 lui t0,0xff0 +80000238: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +8000023c: 3a02b073 csrc pmpcfg0,t0 +80000240: 3a002373 csrr t1,pmpcfg0 +80000244: 079202b7 lui t0,0x7920 +80000248: 16629e63 bne t0,t1,800003c4 +8000024c: 00ff02b7 lui t0,0xff0 +80000250: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> +80000254: 3a02a073 csrs pmpcfg0,t0 +80000258: 3a002373 csrr t1,pmpcfg0 +8000025c: 079202b7 lui t0,0x7920 +80000260: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9> +80000264: 16629063 bne t0,t1,800003c4 -80000270 : -80000270: 00400e13 li t3,4 -80000274: 00000f17 auipc t5,0x0 -80000278: 158f0f13 addi t5,t5,344 # 800003cc -8000027c: 00000117 auipc sp,0x0 -80000280: 01010113 addi sp,sp,16 # 8000028c -80000284: 34111073 csrw mepc,sp -80000288: 30200073 mret +80000268 : +80000268: 00400e13 li t3,4 +8000026c: 00000f17 auipc t5,0x0 +80000270: 158f0f13 addi t5,t5,344 # 800003c4 +80000274: 00000117 auipc sp,0x0 +80000278: 01010113 addi sp,sp,16 # 80000284 +8000027c: 34111073 csrw mepc,sp +80000280: 30200073 mret -8000028c : -8000028c: 00500e13 li t3,5 -80000290: 00000f17 auipc t5,0x0 -80000294: 13cf0f13 addi t5,t5,316 # 800003cc -80000298: deadc137 lui sp,0xdeadc -8000029c: eef10113 addi sp,sp,-273 # deadbeef -800002a0: 800080b7 lui ra,0x80008 -800002a4: 0020a023 sw sp,0(ra) # 80008000 -800002a8: 00000f17 auipc t5,0x0 -800002ac: 010f0f13 addi t5,t5,16 # 800002b8 -800002b0: 0000a183 lw gp,0(ra) -800002b4: 1180006f j 800003cc +80000284 : +80000284: 00500e13 li t3,5 +80000288: 00000f17 auipc t5,0x0 +8000028c: 13cf0f13 addi t5,t5,316 # 800003c4 +80000290: deadc137 lui sp,0xdeadc +80000294: eef10113 addi sp,sp,-273 # deadbeef +80000298: 800080b7 lui ra,0x80008 +8000029c: 0020a023 sw sp,0(ra) # 80008000 +800002a0: 00000f17 auipc t5,0x0 +800002a4: 010f0f13 addi t5,t5,16 # 800002b0 +800002a8: 0000a183 lw gp,0(ra) +800002ac: 1180006f j 800003c4 -800002b8 : -800002b8: 00600e13 li t3,6 -800002bc: 00000f17 auipc t5,0x0 -800002c0: 110f0f13 addi t5,t5,272 # 800003cc -800002c4: deadc137 lui sp,0xdeadc -800002c8: eef10113 addi sp,sp,-273 # deadbeef -800002cc: 800000b7 lui ra,0x80000 -800002d0: 0020a023 sw sp,0(ra) # 80000000 -800002d4: 0000a183 lw gp,0(ra) -800002d8: 0e311a63 bne sp,gp,800003cc +800002b0 : +800002b0: 00600e13 li t3,6 +800002b4: 00000f17 auipc t5,0x0 +800002b8: 110f0f13 addi t5,t5,272 # 800003c4 +800002bc: deadc137 lui sp,0xdeadc +800002c0: eef10113 addi sp,sp,-273 # deadbeef +800002c4: 800000b7 lui ra,0x80000 +800002c8: 0020a023 sw sp,0(ra) # 80000000 +800002cc: 0000a183 lw gp,0(ra) +800002d0: 0e311a63 bne sp,gp,800003c4 -800002dc : -800002dc: 00700e13 li t3,7 -800002e0: 00000f17 auipc t5,0x0 -800002e4: 0ecf0f13 addi t5,t5,236 # 800003cc -800002e8: 800400b7 lui ra,0x80040 -800002ec: 0000a183 lw gp,0(ra) # 80040000 -800002f0: 00000f17 auipc t5,0x0 -800002f4: 010f0f13 addi t5,t5,16 # 80000300 -800002f8: 0030a023 sw gp,0(ra) -800002fc: 0d00006f j 800003cc +800002d4 : +800002d4: 00700e13 li t3,7 +800002d8: 00000f17 auipc t5,0x0 +800002dc: 0ecf0f13 addi t5,t5,236 # 800003c4 +800002e0: 800400b7 lui ra,0x80040 +800002e4: 0000a183 lw gp,0(ra) # 80040000 +800002e8: 00000f17 auipc t5,0x0 +800002ec: 010f0f13 addi t5,t5,16 # 800002f8 +800002f0: 0030a023 sw gp,0(ra) +800002f4: 0d00006f j 800003c4 -80000300 : -80000300: 00800e13 li t3,8 -80000304: 00000f17 auipc t5,0x0 -80000308: 0c8f0f13 addi t5,t5,200 # 800003cc -8000030c: deadc137 lui sp,0xdeadc -80000310: eef10113 addi sp,sp,-273 # deadbeef -80000314: 803400b7 lui ra,0x80340 -80000318: ff808093 addi ra,ra,-8 # 8033fff8 -8000031c: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> -80000320: 00000f17 auipc t5,0x0 -80000324: 010f0f13 addi t5,t5,16 # 80000330 -80000328: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -8000032c: 0a00006f j 800003cc +800002f8 : +800002f8: 00800e13 li t3,8 +800002fc: 00000f17 auipc t5,0x0 +80000300: 0c8f0f13 addi t5,t5,200 # 800003c4 +80000304: deadc137 lui sp,0xdeadc +80000308: eef10113 addi sp,sp,-273 # deadbeef +8000030c: 803400b7 lui ra,0x80340 +80000310: ff808093 addi ra,ra,-8 # 8033fff8 +80000314: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000318: 00000f17 auipc t5,0x0 +8000031c: 010f0f13 addi t5,t5,16 # 80000328 +80000320: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +80000324: 0a00006f j 800003c4 -80000330 : -80000330: 00900e13 li t3,9 -80000334: 00000f17 auipc t5,0x0 -80000338: 098f0f13 addi t5,t5,152 # 800003cc -8000033c: 803800b7 lui ra,0x80380 -80000340: ff808093 addi ra,ra,-8 # 8037fff8 -80000344: 0000a183 lw gp,0(ra) -80000348: 00000f17 auipc t5,0x0 -8000034c: 010f0f13 addi t5,t5,16 # 80000358 -80000350: 0030a023 sw gp,0(ra) -80000354: 0780006f j 800003cc +80000328 : +80000328: 00900e13 li t3,9 +8000032c: 00000f17 auipc t5,0x0 +80000330: 098f0f13 addi t5,t5,152 # 800003c4 +80000334: 803800b7 lui ra,0x80380 +80000338: ff808093 addi ra,ra,-8 # 8037fff8 +8000033c: 0000a183 lw gp,0(ra) +80000340: 00000f17 auipc t5,0x0 +80000344: 010f0f13 addi t5,t5,16 # 80000350 +80000348: 0030a023 sw gp,0(ra) +8000034c: 0780006f j 800003c4 -80000358 : -80000358: 00a00e13 li t3,10 -8000035c: 00000f17 auipc t5,0x0 -80000360: 014f0f13 addi t5,t5,20 # 80000370 -80000364: 00100493 li s1,1 -80000368: 3a305073 csrwi pmpcfg3,0 -8000036c: 0600006f j 800003cc +80000350 : +80000350: 00a00e13 li t3,10 +80000354: 00000f17 auipc t5,0x0 +80000358: 014f0f13 addi t5,t5,20 # 80000368 +8000035c: 00100493 li s1,1 +80000360: 3a305073 csrwi pmpcfg3,0 +80000364: 0600006f j 800003c4 -80000370 : -80000370: 00a00e13 li t3,10 -80000374: 0f1e22b7 lui t0,0xf1e2 -80000378: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> -8000037c: 3a302373 csrr t1,pmpcfg3 -80000380: 04629663 bne t0,t1,800003cc +80000368 : +80000368: 00a00e13 li t3,10 +8000036c: 0f1e22b7 lui t0,0xf1e2 +80000370: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> +80000374: 3a302373 csrr t1,pmpcfg3 +80000378: 04629663 bne t0,t1,800003c4 -80000384 : -80000384: 00b00e13 li t3,11 -80000388: 00000f17 auipc t5,0x0 -8000038c: 044f0f13 addi t5,t5,68 # 800003cc -80000390: 00000493 li s1,0 -80000394: 00000117 auipc sp,0x0 -80000398: 01010113 addi sp,sp,16 # 800003a4 -8000039c: 34111073 csrw mepc,sp -800003a0: 30200073 mret +8000037c : +8000037c: 00b00e13 li t3,11 +80000380: 00000f17 auipc t5,0x0 +80000384: 044f0f13 addi t5,t5,68 # 800003c4 +80000388: 00000493 li s1,0 +8000038c: 00000117 auipc sp,0x0 +80000390: 01010113 addi sp,sp,16 # 8000039c +80000394: 34111073 csrw mepc,sp +80000398: 30200073 mret -800003a4 : -800003a4: 00b00e13 li t3,11 -800003a8: 00000f17 auipc t5,0x0 -800003ac: 014f0f13 addi t5,t5,20 # 800003bc -800003b0: 00100493 li s1,1 -800003b4: 3ba05073 csrwi pmpaddr10,0 -800003b8: 0140006f j 800003cc +8000039c : +8000039c: 00b00e13 li t3,11 +800003a0: 00000f17 auipc t5,0x0 +800003a4: 014f0f13 addi t5,t5,20 # 800003b4 +800003a8: 00100493 li s1,1 +800003ac: 3ba05073 csrwi pmpaddr10,0 +800003b0: 0140006f j 800003c4 -800003bc : -800003bc: 00b00e13 li t3,11 -800003c0: fff00293 li t0,-1 -800003c4: 3ba02373 csrr t1,pmpaddr10 -800003c8: 00628863 beq t0,t1,800003d8 +800003b4 : +800003b4: 00b00e13 li t3,11 +800003b8: fff00293 li t0,-1 +800003bc: 3ba02373 csrr t1,pmpaddr10 +800003c0: 00628863 beq t0,t1,800003d0 -800003cc : -800003cc: f0100137 lui sp,0xf0100 -800003d0: f2410113 addi sp,sp,-220 # f00fff24 -800003d4: 01c12023 sw t3,0(sp) +800003c4 : +800003c4: f0100137 lui sp,0xf0100 +800003c8: f2410113 addi sp,sp,-220 # f00fff24 +800003cc: 01c12023 sw t3,0(sp) -800003d8 : -800003d8: f0100137 lui sp,0xf0100 -800003dc: f2010113 addi sp,sp,-224 # f00fff20 -800003e0: 00012023 sw zero,0(sp) +800003d0 : +800003d0: f0100137 lui sp,0xf0100 +800003d4: f2010113 addi sp,sp,-224 # f00fff20 +800003d8: 00012023 sw zero,0(sp) diff --git a/src/test/cpp/raw/pmp/build/pmp.elf b/src/test/cpp/raw/pmp/build/pmp.elf index 26fc85b43a89acc7708191e30981cd7f5b88847c..93342d09ddf7c1c79f7bc9c54acec60e475fe976 100755 GIT binary patch delta 372 zcmX@0w?l7&0;9)7MP=4I%nS^7HhMngXF6{=*+4*6T*lC>S&@k$S;Ek4JChK5@dPHT zVr2%a$r%C$o976eV6H#H%+SC928;}9K-z^7!Pf!uTafrhK>iyfz6Fqv0r_{3_yG(I^$ZM14hRD(FhJtR0QnI}{1hO+0EwRiWre3 H6~)B?(=axp diff --git a/src/test/cpp/raw/pmp/build/pmp.hex b/src/test/cpp/raw/pmp/build/pmp.hex index 0672169..2ad2696 100644 --- a/src/test/cpp/raw/pmp/build/pmp.hex +++ b/src/test/cpp/raw/pmp/build/pmp.hex @@ -1,66 +1,65 @@ :0200000480007A :10000000930400009700000093800001739050302B :100010006F00400173101F3463940400730020309C -:1000200067000F00130E0000170F0000130F4F3A68 +:1000200067000F00130E0000170F0000130FCF39E9 :10003000B70000803782008037C1ADDE1301F1EEDA -:1000400023A020002320220083A100006310313868 -:1000500083210200631C3136B70212077390023A03 -:100060007323003A63946236B7021F1993824230B9 -:100070007390123AB7120F009382A2907390223AB3 -:10008000B7221E0F938202907390323AB70200207B -:100090007390023B7323003B639A62329302F0FF3A -:1000A0007390123BB72200207390223BB74200208E -:1000B0009382F2FF7390323BB74200209382F2FFAB -:1000C0007390423BB74200209382F2FF7390523B01 -:1000D000B72200209382F2FF7390623BB762002048 -:1000E0009382F2FF7390723BB7020D207390823BB4 -:1000F000B7020E207390923B9302F0FF7390A23BE5 -:10010000930200007390B23B930200007390C23BD5 -:10011000930200007390D23B930200007390E23B85 -:10012000930200007390F23B3701C1001301E1FE1E -:1001300023A020002320220083A10000631831287F -:10014000930100008321020063123128130E100076 -:10015000170F0000130FCF27B712920793828280E8 -:100160007390023A7323003A63926226B78000804C -:1001700037C1ADDE1301F1EE23A02000170F000000 -:10018000130F0F0183A100006F004024130E200005 -:10019000170F0000130FCF23B70212077390023A14 -:1001A0007323003A63846222B74200209382F2FFF5 -:1001B0007350303B7323303B631A03206388622003 -:1001C000B72200207350203B7323203B63000320A1 -:1001D000639E621EB780008037C1ADDE1301F1EE71 -:1001E00023A02000170F0000130F0F0183A10000B0 -:1001F0006F00C01D130E3000170F0000130F4F1DAE -:10020000B702FF0073A0323B7323303B6390621C44 -:100210009302F00F73A0323B7323303BB702FF0011 -:100220009382F20F6394621AB702FF0073B0323BFD -:100230007323303B9302F00F639A6218B702FF00FA -:100240009382F20F73B0023A7323003AB702920717 -:10025000639E6216B702FF009382727073A0023A27 -:100260007323003AB702920793827270639062160A -:10027000130E4000170F0000130F8F151701000019 -:10028000130101017310113473002030130E50005C -:10029000170F0000130FCF1337C1ADDE1301F1EEBE -:1002A000B780008023A02000170F0000130F0F015C -:1002B00083A100006F008011130E6000170F000073 -:1002C000130F0F1137C1ADDE1301F1EEB70000803F -:1002D00023A0200083A10000631A310E130E7000CA -:1002E000170F0000130FCF0EB700048083A100008A -:1002F000170F0000130F0F0123A030006F00000D37 -:10030000130E8000170F0000130F8F0C37C1ADDEE6 -:100310001301F1EEB7003480938080FF2320220088 -:10032000170F0000130F0F01832102006F00000A56 -:10033000130E9000170F0000130F8F09B7003880BD -:10034000938080FF83A10000170F0000130F0F019F -:1003500023A030006F008007130EA000170F0000CD -:10036000130F4F01930410007350303A6F000006D2 -:10037000130EA000B7221E0F938202907323303A0F -:1003800063966204130EB000170F0000130F4F04A2 -:1003900093040000170100001301010173101134D0 -:1003A00073002030130EB000170F0000130F4F0121 -:1003B000930410007350A03B6F004001130EB00077 -:1003C0009302F0FF7323A03B63886200370110F0B3 -:1003D000130141F22320C101370110F0130101F292 -:0403E00023200100D5 +:1000400023A020002320220083A10000631C31365E +:100050008321020063183136B70212077390023A07 +:100060007323003AB7021F19938242307390123AF9 +:10007000B7120F009382A2907390223AB7221E0FFC +:10008000938202907390323AB70200207390023B41 +:100090007323003B9302F0FF7390123BB7220020C2 +:1000A0007390223BB74200209382F2FF7390323B61 +:1000B000B74200209382F2FF7390423BB742002088 +:1000C0009382F2FF7390523BB72200209382F2FF9B +:1000D0007390623BB76200209382F2FF7390723B91 +:1000E000B7020D207390823BB7020E207390923BB3 +:1000F0009302F0FF7390A23B930200007390B23B17 +:10010000930200007390C23B930200007390D23BB5 +:10011000930200007390E23B930200007390F23B65 +:100120003701C1001301E1FE23A02000232022009B +:1001300083A100006318312893010000832102008D +:1001400063123128130E1000170F0000130FCF2772 +:10015000B7129207938282807390023A7323003A17 +:1001600063926226B780008037C1ADDE1301F1EEE5 +:1001700023A02000170F0000130F0F0183A1000020 +:100180006F004024130E2000170F0000130FCF2321 +:10019000B70212077390023A7323003A6384622213 +:1001A000B74200209382F2FF7350303B7323303B01 +:1001B000631A032063886220B72200207350203B1B +:1001C0007323203B63000320639E621EB780008080 +:1001D00037C1ADDE1301F1EE23A02000170F0000A0 +:1001E000130F0F0183A100006F00C01D130E30001C +:1001F000170F0000130F4F1DB702FF0073A0323B13 +:100200007323303B6390621C9302F00F73A0323B68 +:100210007323303BB702FF009382F20F6394621A9C +:10022000B702FF0073B0323B7323303B9302F00FF1 +:10023000639A6218B702FF009382F20F73B0023A1A +:100240007323003AB7029207639E6216B702FF005B +:100250009382727073A0023A7323003AB702920736 +:100260009382727063906216130E4000170F0000A5 +:10027000130F8F15170100001301010173101134C2 +:1002800073002030130E5000170F0000130FCF1310 +:1002900037C1ADDE1301F1EEB780008023A020004E +:1002A000170F0000130F0F0183A100006F008011D2 +:1002B000130E6000170F0000130F0F1137C1ADDED2 +:1002C0001301F1EEB700008023A0200083A10000FD +:1002D000631A310E130E7000170F0000130FCF0EAC +:1002E000B700048083A10000170F0000130F0F0157 +:1002F00023A030006F00000D130E8000170F0000C8 +:10030000130F8F0C37C1ADDE1301F1EEB70034804F +:10031000938080FF23202200170F0000130F0F018E +:10032000832102006F00000A130E9000170F0000D7 +:10033000130F8F09B7003880938080FF83A10000DE +:10034000170F0000130F0F0123A030006F0080076C +:10035000130EA000170F0000130F4F01930410009D +:100360007350303A6F000006130EA000B7221E0F24 +:10037000938202907323303A63966204130EB000A6 +:10038000170F0000130F4F04930400001701000023 +:10039000130101017310113473002030130EB000EB +:1003A000170F0000130F4F01930410007350A03B70 +:1003B0006F004001130EB0009302F0FF7323A03BC7 +:1003C00063886200370110F0130141F22320C1015C +:0C03D000370110F0130101F2232001009E :040000058000000077 :00000001FF diff --git a/src/test/cpp/raw/pmp/build/pmp.map b/src/test/cpp/raw/pmp/build/pmp.map index 0e76f88..fd0c6b0 100644 --- a/src/test/cpp/raw/pmp/build/pmp.map +++ b/src/test/cpp/raw/pmp/build/pmp.map @@ -15,19 +15,19 @@ LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unk END GROUP LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a -.crt_section 0x0000000080000000 0x3e4 +.crt_section 0x0000000080000000 0x3dc 0x0000000080000000 . = ALIGN (0x4) *crt.o(.text) - .text 0x0000000080000000 0x3e4 build/src/crt.o + .text 0x0000000080000000 0x3dc build/src/crt.o 0x0000000080000000 _start 0x0000000080000014 trap OUTPUT(build/pmp.elf elf32-littleriscv) -.data 0x00000000800003e4 0x0 - .data 0x00000000800003e4 0x0 build/src/crt.o +.data 0x00000000800003dc 0x0 + .data 0x00000000800003dc 0x0 build/src/crt.o -.bss 0x00000000800003e4 0x0 - .bss 0x00000000800003e4 0x0 build/src/crt.o +.bss 0x00000000800003dc 0x0 + .bss 0x00000000800003dc 0x0 build/src/crt.o .riscv.attributes 0x0000000000000000 0x1a From a5f66623b7d4515c794e2c3dcf79ecfd091d6def Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Wed, 26 May 2021 16:34:51 +0200 Subject: [PATCH 06/14] Add an "allow" property to individual CSRs --- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 11 +++++------ src/main/scala/vexriscv/plugin/PmpPlugin.scala | 15 +++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index eb538ef..ab8fcb2 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -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{ 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 @@ -368,7 +368,7 @@ case class CsrMapping() extends CsrInterface{ override def duringAnyRead(body: => Unit) : Unit = always += CsrDuringWrite(() => body) override def readData() = readDataSignal override def writeData() = writeDataSignal - override def allowCsr() = allowCsrSignal := True + override def allow(csrAddress: Int): Unit = addMappingAt(csrAddress, CsrAllow()) 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 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 @@ -517,7 +517,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep 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 allowCsr() = csrMapping.allowCsr() + override def allow(csrAddress: Int): Unit = csrMapping.allow(csrAddress) override def readData() = csrMapping.readData() override def writeData() = csrMapping.writeData() override def isHazardFree() = csrMapping.isHazardFree() @@ -1181,6 +1181,7 @@ 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 } @@ -1266,8 +1267,6 @@ 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 diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index efd1a52..1e974a2 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -178,13 +178,16 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend val writeData = csrService.writeData() val enable = RegInit(False) - for (i <- 0 until regions) { - csrService.onRead(0x3b0 + i) {csrService.readData().assignFromBits(cfgRegister(pmpSelect)) } - csrService.onWrite(0x3b0 + i) { enable := True } + for (i <- 0 until regions) csrService.allow(0x3b0 + i) + for (i <- 0 until (regions / 4)) csrService.allow(0x3a0 + i) + + csrService.duringAnyRead { + when (input(PMPCFG)) { csrService.readData().assignFromBits(cfgRegister(pmpSelect)) } + when (input(PMPADDR)) { csrService.readData() := pmpaddr.readAsync(pmpIndex).asBits } } - for (i <- 0 until (regions / 4)) { - csrService.onRead(0x3a0 + i) { csrService.readData() := pmpaddr.readAsync(pmpIndex).asBits } - csrService.onWrite(0x3a0 + i) { enable := True } + + csrService.duringAnyWrite { + when (input(PMPCFG) | input(PMPADDR)) { enable := True } } val writer = new Area { From 6471014131daaf90743fb4f838ed1bff88d1789d Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Thu, 27 May 2021 14:34:51 +0200 Subject: [PATCH 07/14] Simplify pmpcfg encoding --- .../scala/vexriscv/plugin/CsrPlugin.scala | 2 + .../scala/vexriscv/plugin/PmpPlugin.scala | 144 ++++++++++-------- 2 files changed, 86 insertions(+), 60 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index ab8fcb2..471ffe3 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -1147,6 +1147,8 @@ 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, diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index 1e974a2..e10a92a 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -11,6 +11,7 @@ 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 @@ -121,20 +122,17 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend val privilegeService = pipeline.service(classOf[PrivilegeService]) val pmpaddr = Mem(UInt(xlen bits), regions) - val pmpcfg = Reg(Bits(8 * regions bits)) init(0) - val base, mask = Mem(UInt(xlen - grain bits), regions) - val cfgRegion = pmpcfg.subdivideIn(8 bits) - val cfgRegister = pmpcfg.subdivideIn(xlen bits) - val lockMask = Reg(Bits(4 bits)) init(B"4'0") + val pmpcfg = Vector.fill(regions)(Reg(Bits(8 bits)) init(0)) + val base, mask = Vector.fill(regions)(Reg(UInt(xlen - grain bits))) - object PMPCFG extends Stageable(Bool) - object PMPADDR extends Stageable(Bool) + // object PMPCFG extends Stageable(Bool) + // object PMPADDR extends Stageable(Bool) - decode plug new Area { - import decode._ - insert(PMPCFG) := input(INSTRUCTION)(31 downto 24) === 0x3a - insert(PMPADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b - } + // decode plug new Area { + // import decode._ + // insert(PMPCFG) := input(INSTRUCTION)(31 downto 24) === 0x3a + // insert(PMPADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b + // } execute plug new Area { import execute._ @@ -171,64 +169,91 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend val base13 = base(U"4'xd") val base14 = base(U"4'xe") val base15 = base(U"4'xf") + val pmpcfg0 = pmpcfg(0) + val pmpcfg1 = pmpcfg(1) + val pmpcfg2 = pmpcfg(2) + val pmpcfg3 = pmpcfg(3) + val pmpcfg4 = pmpcfg(4) + val pmpcfg5 = pmpcfg(5) + val pmpcfg6 = pmpcfg(6) + val pmpcfg7 = pmpcfg(7) + val pmpcfg8 = pmpcfg(8) + val pmpcfg9 = pmpcfg(9) + val pmpcfg10 = pmpcfg(10) + val pmpcfg11 = pmpcfg(11) + val pmpcfg12 = pmpcfg(12) + val pmpcfg13 = pmpcfg(13) + val pmpcfg14 = pmpcfg(14) + val pmpcfg15 = pmpcfg(15) val csrAddress = input(INSTRUCTION)(csrRange) val pmpIndex = csrAddress(log2Up(regions) - 1 downto 0).asUInt + val pmpIndexReg = Reg(UInt(log2Up(regions) bits)) val pmpSelect = pmpIndex(log2Up(regions) - 3 downto 0) - val writeData = csrService.writeData() - - val enable = RegInit(False) - for (i <- 0 until regions) csrService.allow(0x3b0 + i) - for (i <- 0 until (regions / 4)) csrService.allow(0x3a0 + i) + val pmpSelectReg = Reg(UInt(log2Up(regions) - 2 bits)) + val pmpAccessCfg = RegInit(False) + val pmpAccessAddr = RegInit(False) + val writeData = Reg(Bits(xlen bits)) + val pending = RegInit(False) + val hazardFree = csrService.isHazardFree() - csrService.duringAnyRead { - when (input(PMPCFG)) { csrService.readData().assignFromBits(cfgRegister(pmpSelect)) } - when (input(PMPADDR)) { csrService.readData() := pmpaddr.readAsync(pmpIndex).asBits } + def reconfigure() = { + pending := True + writeData := csrService.writeData() + pmpIndexReg := pmpIndex + pmpSelectReg := pmpSelect + pmpAccessCfg := input(INSTRUCTION)(31 downto 24) === 0x3a + pmpAccessAddr := input(INSTRUCTION)(31 downto 24) === 0x3b } - csrService.duringAnyWrite { - when (input(PMPCFG) | input(PMPADDR)) { enable := True } + for (i <- 0 until regions) { + csrService.onRead(0x3b0 + i) { + csrService.readData() := pmpaddr.readAsync(pmpIndex).asBits + } + csrService.onWrite(0x3b0 + i) { reconfigure() } + } + for (i <- 0 until (regions / 4)) { + csrService.onRead(0x3a0 + i) { + csrService.readData() := pmpcfg(i * 4 + 3) ## pmpcfg(i * 4 + 2) ## pmpcfg(i * 4 + 1) ## pmpcfg(i * 4) + } + csrService.onWrite(0x3a0 + i) { reconfigure() } } val writer = new Area { - when (enable & csrService.isHazardFree()) { - when (input(PMPCFG)) { - switch(pmpSelect) { - for (i <- 0 until (regions / 4)) { - is(i) { - for (j <- Range(0, xlen, 8)) { - val bitRange = j + xlen * i + lBit downto j + xlen * i - val overwrite = writeData.subdivideIn(8 bits)(j / 8) - val locked = cfgRegister(i).subdivideIn(8 bits)(j / 8)(lBit) - lockMask(j / 8) := locked - when (~locked) { - pmpcfg(bitRange).assignFromBits(overwrite) - } - } - } + when (pending) { + arbitration.haltItself := True + when (hazardFree & pmpAccessCfg) { + val overwrite = writeData.subdivideIn(8 bits) + for (i <- 0 until 4) { + when (~pmpcfg(pmpSelectReg @@ U(i, 2 bits))(lBit)) { + pmpcfg(pmpSelectReg @@ U(i, 2 bits)).assignFromBits(overwrite(i)) } } } } - val locked = cfgRegion(pmpIndex)(lBit) - pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & input(PMPADDR) & enable & csrService.isHazardFree()) + val locked = pmpcfg(pmpIndex)(lBit) + pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & pmpAccessAddr & pending & hazardFree) } val controller = new StateMachine { + val enable = RegInit(False) val counter = Reg(UInt(log2Up(regions) bits)) init(0) val stateIdle : State = new State with EntryPoint { onEntry { - lockMask := B"4'x0" enable := False counter := 0 } - onExit (arbitration.haltItself := True) + onExit { + enable := True + pending := False + arbitration.haltItself := True + } whenIsActive { - when (enable & csrService.isHazardFree()) { - when (input(PMPCFG)) { + when (pending & hazardFree) { + when (pmpAccessCfg) { goto(stateCfg) - }.elsewhen (input(PMPADDR)) { + }.elsewhen (pmpAccessAddr) { goto(stateAddr) } } @@ -236,7 +261,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } val stateCfg : State = new State { - onEntry (counter := pmpIndex(log2Up(regions) - 3 downto 0) @@ U"2'00") + onEntry (counter := pmpSelectReg @@ U(0, 2 bits)) whenIsActive { counter := counter + 1 when (counter(1 downto 0) === 3) { @@ -248,23 +273,17 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } val stateAddr : State = new State { - onEntry (counter := pmpIndex) + onEntry (counter := pmpIndexReg) whenIsActive (goto(stateIdle)) } - when (input(PMPCFG)) { - setter.io.addr := pmpaddr(counter) + when (pmpAccessAddr) { + setter.io.addr := writeData.asUInt } otherwise { - when (counter === pmpIndex) { - setter.io.addr := writeData.asUInt - } otherwise { - setter.io.addr := pmpaddr(counter) - } + setter.io.addr := pmpaddr.readAsync(counter) } - when (enable & csrService.isHazardFree() & - ((input(PMPCFG) & ~lockMask(counter(1 downto 0))) | - (input(PMPADDR) & ~cfgRegion(counter)(lBit)))) { + when (enable & ~pmpcfg(counter)(lBit)) { base(counter) := setter.io.base mask(counter) := setter.io.mask } @@ -272,13 +291,18 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } pipeline plug new Area { + def getHits(address : UInt) = { (0 until regions).map(i => ((address & mask(U(i, log2Up(regions) bits))) === base(U(i, log2Up(regions) bits))) & - (cfgRegion(i)(lBit) | ~privilegeService.isMachine()) & cfgRegion(i)(aBits) === NAPOT + (pmpcfg(i)(lBit) | ~privilegeService.isMachine()) & pmpcfg(i)(aBits) === NAPOT ) } + def getPermission(hits : IndexedSeq[Bool], bit : Int) = { + (hits zip pmpcfg).map({ case (i, cfg) => i & cfg(bit) }).orR + } + val dGuard = new Area { val address = dPort.bus.cmd(0).virtualAddress dPort.bus.rsp.physicalAddress := address @@ -295,8 +319,8 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend dPort.bus.rsp.allowRead := privilegeService.isMachine() dPort.bus.rsp.allowWrite := privilegeService.isMachine() } otherwise { - dPort.bus.rsp.allowRead := (hits zip cfgRegion).map({ case (i, cfg) => i & cfg(rBit) }).orR - dPort.bus.rsp.allowWrite := (hits zip cfgRegion).map({ case (i, cfg) => i & cfg(wBit) }).orR + dPort.bus.rsp.allowRead := getPermission(hits, rBit) + dPort.bus.rsp.allowWrite := getPermission(hits, wBit) } } @@ -316,7 +340,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend when(~hits.orR) { iPort.bus.rsp.allowExecute := privilegeService.isMachine() } otherwise { - iPort.bus.rsp.allowExecute := (hits zip cfgRegion).map({ case (i, cfg) => i & cfg(xBit) }).orR + iPort.bus.rsp.allowExecute := getPermission(hits, xBit) } } } From 4a2dc0ff5f69894bd6daae67ea1385e5674fa5cd Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Thu, 27 May 2021 15:50:45 +0200 Subject: [PATCH 08/14] Fix granularity control --- .../scala/vexriscv/plugin/CsrPlugin.scala | 25 ++++++----- .../scala/vexriscv/plugin/PmpPlugin.scala | 19 ++++---- src/test/cpp/raw/pmp/src/crt.S | 43 +++++++++---------- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 471ffe3..f8d944a 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -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 diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index e10a92a..e6c94ea 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -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() diff --git a/src/test/cpp/raw/pmp/src/crt.S b/src/test/cpp/raw/pmp/src/crt.S index a03e76c..3dd75ff 100644 --- a/src/test/cpp/raw/pmp/src/crt.S +++ b/src/test/cpp/raw/pmp/src/crt.S @@ -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 From 24a534acffd4dd5f1758485311437c265c049f67 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Fri, 28 May 2021 13:54:55 +0200 Subject: [PATCH 09/14] All tests passing on new PMP plugin --- src/main/scala/vexriscv/demo/GenSecure.scala | 2 +- .../scala/vexriscv/plugin/CsrPlugin.scala | 8 + .../scala/vexriscv/plugin/PmpPlugin.scala | 159 +++--- src/test/cpp/raw/pmp/build/pmp.asm | 457 ++++++++---------- src/test/cpp/raw/pmp/build/pmp.elf | Bin 5944 -> 5804 bytes src/test/cpp/raw/pmp/build/pmp.hex | 112 ++--- src/test/cpp/raw/pmp/build/pmp.map | 12 +- src/test/cpp/raw/pmp/src/crt.S | 89 ++-- .../vexriscv/TestIndividualFeatures.scala | 1 + 9 files changed, 379 insertions(+), 461 deletions(-) diff --git a/src/main/scala/vexriscv/demo/GenSecure.scala b/src/main/scala/vexriscv/demo/GenSecure.scala index e4da3eb..8b2cd55 100644 --- a/src/main/scala/vexriscv/demo/GenSecure.scala +++ b/src/main/scala/vexriscv/demo/GenSecure.scala @@ -41,7 +41,7 @@ object GenSecure extends App { ), new PmpPlugin( regions = 16, - granularity = 256, + granularity = 32, ioRange = _(31 downto 28) === 0xf ), new DecoderSimplePlugin( diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index f8d944a..9d16dd5 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -366,6 +366,8 @@ case class CsrMapping() extends Area with CsrInterface { override def duringAny(): Bool = ??? override def duringAnyRead(body: => Unit) : Unit = always += CsrDuringRead(() => body) override def duringAnyWrite(body: => Unit) : Unit = always += CsrDuringWrite(() => body) + override def onAnyRead(body: => Unit) : Unit = always += CsrOnRead(() => body) + override def onAnyWrite(body: => Unit) : Unit = always += CsrOnWrite(() => body) override def readData() = readDataSignal override def writeData() = writeDataSignal override def allowCsr() = allowCsrSignal := True @@ -388,6 +390,8 @@ trait CsrInterface{ } 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 onAnyRead(body: => Unit) : Unit + def onAnyWrite(body: => Unit) : Unit 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 @@ -517,6 +521,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep override def duringAny(): Bool = pipeline.execute.arbitration.isValid && pipeline.execute.input(IS_CSR) override def duringAnyRead(body: => Unit) = csrMapping.duringAnyRead(body) override def duringAnyWrite(body: => Unit) = csrMapping.duringAnyWrite(body) + override def onAnyRead(body: => Unit) = csrMapping.onAnyRead(body) + override def onAnyWrite(body: => Unit) = csrMapping.onAnyWrite(body) override def allowCsr() = csrMapping.allowCsr() override def readData() = csrMapping.readData() override def writeData() = csrMapping.writeData() @@ -1264,6 +1270,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep csrMapping.always.foreach { case element : CsrDuringWrite => when(writeInstruction){element.doThat()} case element : CsrDuringRead => when(readInstruction){element.doThat()} + case element : CsrOnWrite => when(writeEnable){element.doThat()} + case element : CsrOnRead => when(readEnable){element.doThat()} } illegalAccess clearWhen(csrMapping.allowCsrSignal) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index e6c94ea..f9d47ee 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -62,6 +62,10 @@ import spinal.lib.fsm._ * * NA4: This is essentially an edge case of NAPOT where the entire pmpaddr# * register defines a 4-byte wide region. + * + * N.B. THIS IMPLEMENTATION ONLY SUPPORTS NAPOT ADDRESSING. REGIONS ARE NOT + * ORDERED BY PRIORITY. A PERMISSION IS GRANTED TO AN ACCESS IF ANY MATCHING + * PMP REGION HAS THAT PERMISSION ENABLED. */ trait Pmp { @@ -124,114 +128,74 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend val pmpcfg = Vector.fill(regions)(Reg(Bits(8 bits)) init(0)) val base, mask = Vector.fill(regions)(Reg(UInt(xlen - cutoff bits))) - // object PMPCFG extends Stageable(Bool) - // object PMPADDR extends Stageable(Bool) - - // decode plug new Area { - // import decode._ - // insert(PMPCFG) := input(INSTRUCTION)(31 downto 24) === 0x3a - // insert(PMPADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b - // } + def machineMode : Bool = privilegeService.isMachine() execute plug new Area { import execute._ - val mask0 = mask(U"4'x0") - val mask1 = mask(U"4'x1") - val mask2 = mask(U"4'x2") - val mask3 = mask(U"4'x3") - val mask4 = mask(U"4'x4") - val mask5 = mask(U"4'x5") - val mask6 = mask(U"4'x6") - val mask7 = mask(U"4'x7") - val mask8 = mask(U"4'x8") - val mask9 = mask(U"4'x9") - val mask10 = mask(U"4'xa") - val mask11 = mask(U"4'xb") - val mask12 = mask(U"4'xc") - val mask13 = mask(U"4'xd") - val mask14 = mask(U"4'xe") - val mask15 = mask(U"4'xf") - val base0 = base(U"4'x0") - val base1 = base(U"4'x1") - val base2 = base(U"4'x2") - val base3 = base(U"4'x3") - val base4 = base(U"4'x4") - val base5 = base(U"4'x5") - val base6 = base(U"4'x6") - val base7 = base(U"4'x7") - val base8 = base(U"4'x8") - val base9 = base(U"4'x9") - val base10 = base(U"4'xa") - val base11 = base(U"4'xb") - val base12 = base(U"4'xc") - val base13 = base(U"4'xd") - val base14 = base(U"4'xe") - val base15 = base(U"4'xf") - val pmpcfg0 = pmpcfg(0) - val pmpcfg1 = pmpcfg(1) - val pmpcfg2 = pmpcfg(2) - val pmpcfg3 = pmpcfg(3) - val pmpcfg4 = pmpcfg(4) - val pmpcfg5 = pmpcfg(5) - val pmpcfg6 = pmpcfg(6) - val pmpcfg7 = pmpcfg(7) - val pmpcfg8 = pmpcfg(8) - val pmpcfg9 = pmpcfg(9) - val pmpcfg10 = pmpcfg(10) - val pmpcfg11 = pmpcfg(11) - val pmpcfg12 = pmpcfg(12) - val pmpcfg13 = pmpcfg(13) - val pmpcfg14 = pmpcfg(14) - val pmpcfg15 = pmpcfg(15) - - val csrAddress = input(INSTRUCTION)(csrRange) - val pmpIndex = csrAddress(log2Up(regions) - 1 downto 0).asUInt - val pmpIndexReg = Reg(UInt(log2Up(regions) bits)) - val pmpSelect = pmpIndex(log2Up(regions) - 3 downto 0) - val pmpSelectReg = Reg(UInt(log2Up(regions) - 2 bits)) - val pmpAccessCfg = RegInit(False) - val pmpAccessAddr = RegInit(False) - val writeData = Reg(Bits(xlen bits)) val pending = RegInit(False) val hazardFree = csrService.isHazardFree() - - def reconfigure() = { - pending := True - writeData := csrService.writeData() - pmpIndexReg := pmpIndex - pmpSelectReg := pmpSelect - pmpAccessCfg := input(INSTRUCTION)(31 downto 24) === 0x3a - pmpAccessAddr := input(INSTRUCTION)(31 downto 24) === 0x3b + + val csrAddress = input(INSTRUCTION)(csrRange) + val pmpNcfg = csrAddress(log2Up(regions) - 1 downto 0).asUInt + val pmpcfgN = pmpNcfg(log2Up(regions) - 3 downto 0) + val pmpcfgCsr = input(INSTRUCTION)(31 downto 24) === 0x3a + val pmpaddrCsr = input(INSTRUCTION)(31 downto 24) === 0x3b + + val pmpNcfg_ = Reg(UInt(log2Up(regions) bits)) + val pmpcfgN_ = Reg(UInt(log2Up(regions) - 2 bits)) + val pmpcfgCsr_ = RegInit(False) + val pmpaddrCsr_ = RegInit(False) + val writeData_ = Reg(Bits(xlen bits)) + + csrService.duringAnyRead { + when (machineMode) { + when (pmpcfgCsr) { + csrService.allowCsr() + csrService.readData() := + pmpcfg(pmpcfgN @@ U(3, 2 bits)) ## + pmpcfg(pmpcfgN @@ U(2, 2 bits)) ## + pmpcfg(pmpcfgN @@ U(1, 2 bits)) ## + pmpcfg(pmpcfgN @@ U(0, 2 bits)) + } + when (pmpaddrCsr) { + csrService.allowCsr() + csrService.readData() := pmpaddr.readAsync(pmpNcfg).asBits + } + } } - for (i <- 0 until regions) { - csrService.onRead(0x3b0 + i) { - csrService.readData() := pmpaddr.readAsync(pmpIndex).asBits + csrService.duringAnyWrite { + when ((pmpcfgCsr | pmpaddrCsr) & machineMode) { + csrService.allowCsr() } - csrService.onWrite(0x3b0 + i) { reconfigure() } } - for (i <- 0 until (regions / 4)) { - csrService.onRead(0x3a0 + i) { - csrService.readData() := pmpcfg(i * 4 + 3) ## pmpcfg(i * 4 + 2) ## pmpcfg(i * 4 + 1) ## pmpcfg(i * 4) + + csrService.onAnyWrite { + when ((pmpcfgCsr | pmpaddrCsr) & machineMode) { + pending := True + writeData_ := csrService.writeData() + pmpNcfg_ := pmpNcfg + pmpcfgN_ := pmpcfgN + pmpaddrCsr_ := pmpcfgCsr + pmpcfgCsr_ := pmpaddrCsr } - csrService.onWrite(0x3a0 + i) { reconfigure() } } val writer = new Area { when (pending) { arbitration.haltItself := True - when (hazardFree & pmpAccessCfg) { - val overwrite = writeData.subdivideIn(8 bits) + when (hazardFree & pmpaddrCsr_) { + val overwrite = writeData_.subdivideIn(8 bits) for (i <- 0 until 4) { - when (~pmpcfg(pmpSelectReg @@ U(i, 2 bits))(lBit)) { - pmpcfg(pmpSelectReg @@ U(i, 2 bits)).assignFromBits(overwrite(i)) + when (~pmpcfg(pmpcfgN_ @@ U(i, 2 bits))(lBit)) { + pmpcfg(pmpcfgN_ @@ U(i, 2 bits)).assignFromBits(overwrite(i)) } } } } - val locked = pmpcfg(pmpIndex)(lBit) - pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & pmpAccessAddr & pending & hazardFree) + val locked = pmpcfg(pmpNcfg_)(lBit) + pmpaddr.write(pmpNcfg_, writeData_.asUInt, ~locked & pmpcfgCsr_ & pending & hazardFree) } val controller = new StateMachine { @@ -250,9 +214,9 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } whenIsActive { when (pending & hazardFree) { - when (pmpAccessCfg) { + when (pmpaddrCsr_) { goto(stateCfg) - }.elsewhen (pmpAccessAddr) { + }.elsewhen (pmpcfgCsr_) { goto(stateAddr) } } @@ -260,7 +224,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } val stateCfg : State = new State { - onEntry (counter := pmpSelectReg @@ U(0, 2 bits)) + onEntry (counter := pmpcfgN_ @@ U(0, 2 bits)) whenIsActive { counter := counter + 1 when (counter(1 downto 0) === 3) { @@ -272,12 +236,12 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } val stateAddr : State = new State { - onEntry (counter := pmpIndexReg) + onEntry (counter := pmpNcfg_) whenIsActive (goto(stateIdle)) } - when (pmpAccessAddr) { - setter.io.addr := writeData.asUInt + when (pmpcfgCsr_) { + setter.io.addr := writeData_.asUInt } otherwise { setter.io.addr := pmpaddr.readAsync(counter) } @@ -290,11 +254,10 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } pipeline plug new Area { - def getHits(address : UInt) = { (0 until regions).map(i => ((address & mask(U(i, log2Up(regions) bits))) === base(U(i, log2Up(regions) bits))) & - (pmpcfg(i)(lBit) | ~privilegeService.isMachine()) & pmpcfg(i)(aBits) === NAPOT + (pmpcfg(i)(lBit) | ~machineMode) & (pmpcfg(i)(aBits) === NAPOT) ) } @@ -315,8 +278,8 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend val hits = getHits(address(31 downto cutoff)) when(~hits.orR) { - dPort.bus.rsp.allowRead := privilegeService.isMachine() - dPort.bus.rsp.allowWrite := privilegeService.isMachine() + dPort.bus.rsp.allowRead := machineMode + dPort.bus.rsp.allowWrite := machineMode } otherwise { dPort.bus.rsp.allowRead := getPermission(hits, rBit) dPort.bus.rsp.allowWrite := getPermission(hits, wBit) @@ -337,7 +300,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend val hits = getHits(address(31 downto cutoff)) when(~hits.orR) { - iPort.bus.rsp.allowExecute := privilegeService.isMachine() + iPort.bus.rsp.allowExecute := machineMode } otherwise { iPort.bus.rsp.allowExecute := getPermission(hits, xBit) } diff --git a/src/test/cpp/raw/pmp/build/pmp.asm b/src/test/cpp/raw/pmp/build/pmp.asm index 6db26c3..34ddcbf 100644 --- a/src/test/cpp/raw/pmp/build/pmp.asm +++ b/src/test/cpp/raw/pmp/build/pmp.asm @@ -22,271 +22,244 @@ Disassembly of section .crt_section: 80000024 : 80000024: 00000e13 li t3,0 80000028: 00000f17 auipc t5,0x0 -8000002c: 39cf0f13 addi t5,t5,924 # 800003c4 +8000002c: 340f0f13 addi t5,t5,832 # 80000368 80000030: 800000b7 lui ra,0x80000 80000034: 80008237 lui tp,0x80008 80000038: deadc137 lui sp,0xdeadc -8000003c: eef10113 addi sp,sp,-273 # deadbeef -80000040: 0020a023 sw sp,0(ra) # 80000000 -80000044: 00222023 sw sp,0(tp) # 80008000 +8000003c: eef10113 addi sp,sp,-273 # deadbeef +80000040: 0020a023 sw sp,0(ra) # 80000000 +80000044: 00222023 sw sp,0(tp) # 80008000 80000048: 0000a183 lw gp,0(ra) -8000004c: 36311c63 bne sp,gp,800003c4 +8000004c: 30311e63 bne sp,gp,80000368 80000050: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000054: 36311863 bne sp,gp,800003c4 -80000058: 071202b7 lui t0,0x7120 +80000054: 30311a63 bne sp,gp,80000368 +80000058: 071a02b7 lui t0,0x71a0 8000005c: 3a029073 csrw pmpcfg0,t0 80000060: 3a002373 csrr t1,pmpcfg0 -80000064: 191f02b7 lui t0,0x191f0 -80000068: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc> -8000006c: 3a129073 csrw pmpcfg1,t0 -80000070: 000f12b7 lui t0,0xf1 -80000074: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> -80000078: 3a229073 csrw pmpcfg2,t0 -8000007c: 0f1e22b7 lui t0,0xf1e2 -80000080: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> -80000084: 3a329073 csrw pmpcfg3,t0 -80000088: 200002b7 lui t0,0x20000 -8000008c: 3b029073 csrw pmpaddr0,t0 -80000090: 3b002373 csrr t1,pmpaddr0 -80000094: fff00293 li t0,-1 -80000098: 3b129073 csrw pmpaddr1,t0 -8000009c: 200022b7 lui t0,0x20002 -800000a0: 3b229073 csrw pmpaddr2,t0 -800000a4: 200042b7 lui t0,0x20004 -800000a8: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000ac: 3b329073 csrw pmpaddr3,t0 -800000b0: 200042b7 lui t0,0x20004 -800000b4: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000b8: 3b429073 csrw pmpaddr4,t0 -800000bc: 200042b7 lui t0,0x20004 -800000c0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800000c4: 3b529073 csrw pmpaddr5,t0 -800000c8: 200022b7 lui t0,0x20002 -800000cc: fff28293 addi t0,t0,-1 # 20001fff <_start-0x5fffe001> -800000d0: 3b629073 csrw pmpaddr6,t0 -800000d4: 200062b7 lui t0,0x20006 -800000d8: fff28293 addi t0,t0,-1 # 20005fff <_start-0x5fffa001> -800000dc: 3b729073 csrw pmpaddr7,t0 -800000e0: 200d02b7 lui t0,0x200d0 -800000e4: 3b829073 csrw pmpaddr8,t0 -800000e8: 200e02b7 lui t0,0x200e0 -800000ec: 3b929073 csrw pmpaddr9,t0 -800000f0: fff00293 li t0,-1 -800000f4: 3ba29073 csrw pmpaddr10,t0 -800000f8: 00000293 li t0,0 -800000fc: 3bb29073 csrw pmpaddr11,t0 -80000100: 00000293 li t0,0 -80000104: 3bc29073 csrw pmpaddr12,t0 +80000064: 30629263 bne t0,t1,80000368 +80000068: 1a1902b7 lui t0,0x1a190 +8000006c: 30428293 addi t0,t0,772 # 1a190304 <_start-0x65e6fcfc> +80000070: 3a129073 csrw pmpcfg1,t0 +80000074: 000f12b7 lui t0,0xf1 +80000078: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> +8000007c: 3a229073 csrw pmpcfg2,t0 +80000080: 3a202373 csrr t1,pmpcfg2 +80000084: 2e629263 bne t0,t1,80000368 +80000088: 1c1e22b7 lui t0,0x1c1e2 +8000008c: 90028293 addi t0,t0,-1792 # 1c1e1900 <_start-0x63e1e700> +80000090: 3a329073 csrw pmpcfg3,t0 +80000094: 200002b7 lui t0,0x20000 +80000098: 3b029073 csrw pmpaddr0,t0 +8000009c: 3b002373 csrr t1,pmpaddr0 +800000a0: 2c629463 bne t0,t1,80000368 +800000a4: fff00293 li t0,-1 +800000a8: 3b129073 csrw pmpaddr1,t0 +800000ac: 202002b7 lui t0,0x20200 +800000b0: 3b229073 csrw pmpaddr2,t0 +800000b4: 200042b7 lui t0,0x20004 +800000b8: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800000bc: 3b329073 csrw pmpaddr3,t0 +800000c0: 200042b7 lui t0,0x20004 +800000c4: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800000c8: 3b429073 csrw pmpaddr4,t0 +800000cc: 200042b7 lui t0,0x20004 +800000d0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800000d4: 3b529073 csrw pmpaddr5,t0 +800000d8: 230002b7 lui t0,0x23000 +800000dc: fff28293 addi t0,t0,-1 # 22ffffff <_start-0x5d000001> +800000e0: 3b629073 csrw pmpaddr6,t0 +800000e4: 220402b7 lui t0,0x22040 +800000e8: fff28293 addi t0,t0,-1 # 2203ffff <_start-0x5dfc0001> +800000ec: 3b729073 csrw pmpaddr7,t0 +800000f0: 200d02b7 lui t0,0x200d0 +800000f4: 3b829073 csrw pmpaddr8,t0 +800000f8: 200e02b7 lui t0,0x200e0 +800000fc: 3b929073 csrw pmpaddr9,t0 +80000100: fff00293 li t0,-1 +80000104: 3ba29073 csrw pmpaddr10,t0 80000108: 00000293 li t0,0 -8000010c: 3bd29073 csrw pmpaddr13,t0 +8000010c: 3bb29073 csrw pmpaddr11,t0 80000110: 00000293 li t0,0 -80000114: 3be29073 csrw pmpaddr14,t0 +80000114: 3bc29073 csrw pmpaddr12,t0 80000118: 00000293 li t0,0 -8000011c: 3bf29073 csrw pmpaddr15,t0 -80000120: 00c10137 lui sp,0xc10 -80000124: fee10113 addi sp,sp,-18 # c0ffee <_start-0x7f3f0012> -80000128: 0020a023 sw sp,0(ra) -8000012c: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> -80000130: 0000a183 lw gp,0(ra) -80000134: 28311863 bne sp,gp,800003c4 -80000138: 00000193 li gp,0 -8000013c: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000140: 28311263 bne sp,gp,800003c4 +8000011c: 3bd29073 csrw pmpaddr13,t0 +80000120: 00000293 li t0,0 +80000124: 3be29073 csrw pmpaddr14,t0 +80000128: fff00293 li t0,-1 +8000012c: 3bf29073 csrw pmpaddr15,t0 +80000130: 00c10137 lui sp,0xc10 +80000134: fee10113 addi sp,sp,-18 # c0ffee <_start-0x7f3f0012> +80000138: 0020a023 sw sp,0(ra) +8000013c: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000140: 0000a183 lw gp,0(ra) +80000144: 22311263 bne sp,gp,80000368 +80000148: 00000193 li gp,0 +8000014c: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +80000150: 20311c63 bne sp,gp,80000368 -80000144 : -80000144: 00100e13 li t3,1 -80000148: 00000f17 auipc t5,0x0 -8000014c: 27cf0f13 addi t5,t5,636 # 800003c4 -80000150: 079212b7 lui t0,0x7921 -80000154: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8> -80000158: 3a029073 csrw pmpcfg0,t0 -8000015c: 3a002373 csrr t1,pmpcfg0 -80000160: 26629263 bne t0,t1,800003c4 -80000164: 800080b7 lui ra,0x80008 -80000168: deadc137 lui sp,0xdeadc -8000016c: eef10113 addi sp,sp,-273 # deadbeef -80000170: 0020a023 sw sp,0(ra) # 80008000 -80000174: 00000f17 auipc t5,0x0 -80000178: 010f0f13 addi t5,t5,16 # 80000184 -8000017c: 0000a183 lw gp,0(ra) -80000180: 2440006f j 800003c4 +80000154 : +80000154: 00100e13 li t3,1 +80000158: 00000f17 auipc t5,0x0 +8000015c: 210f0f13 addi t5,t5,528 # 80000368 +80000160: 079a12b7 lui t0,0x79a1 +80000164: 80828293 addi t0,t0,-2040 # 79a0808 <_start-0x7865f7f8> +80000168: 3a029073 csrw pmpcfg0,t0 +8000016c: 3a002373 csrr t1,pmpcfg0 +80000170: 1e629c63 bne t0,t1,80000368 +80000174: 808000b7 lui ra,0x80800 +80000178: deadc137 lui sp,0xdeadc +8000017c: eef10113 addi sp,sp,-273 # deadbeef +80000180: 0020a023 sw sp,0(ra) # 80800000 +80000184: 00000f17 auipc t5,0x0 +80000188: 010f0f13 addi t5,t5,16 # 80000194 +8000018c: 0000a183 lw gp,0(ra) +80000190: 1d80006f j 80000368 -80000184 : -80000184: 00200e13 li t3,2 -80000188: 00000f17 auipc t5,0x0 -8000018c: 23cf0f13 addi t5,t5,572 # 800003c4 -80000190: 071202b7 lui t0,0x7120 -80000194: 3a029073 csrw pmpcfg0,t0 -80000198: 3a002373 csrr t1,pmpcfg0 -8000019c: 22628463 beq t0,t1,800003c4 -800001a0: 200042b7 lui t0,0x20004 -800001a4: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> -800001a8: 3b305073 csrwi pmpaddr3,0 -800001ac: 3b302373 csrr t1,pmpaddr3 -800001b0: 20031a63 bnez t1,800003c4 -800001b4: 20628863 beq t0,t1,800003c4 -800001b8: 200022b7 lui t0,0x20002 +80000194 : +80000194: 00200e13 li t3,2 +80000198: 00000f17 auipc t5,0x0 +8000019c: 1d0f0f13 addi t5,t5,464 # 80000368 +800001a0: 071a02b7 lui t0,0x71a0 +800001a4: 3a029073 csrw pmpcfg0,t0 +800001a8: 3a002373 csrr t1,pmpcfg0 +800001ac: 1a628e63 beq t0,t1,80000368 +800001b0: 3b305073 csrwi pmpaddr3,0 +800001b4: 3b302373 csrr t1,pmpaddr3 +800001b8: 1a031863 bnez t1,80000368 800001bc: 3b205073 csrwi pmpaddr2,0 800001c0: 3b202373 csrr t1,pmpaddr2 -800001c4: 20030063 beqz t1,800003c4 -800001c8: 1e629e63 bne t0,t1,800003c4 -800001cc: 800080b7 lui ra,0x80008 -800001d0: deadc137 lui sp,0xdeadc -800001d4: eef10113 addi sp,sp,-273 # deadbeef -800001d8: 0020a023 sw sp,0(ra) # 80008000 -800001dc: 00000f17 auipc t5,0x0 -800001e0: 010f0f13 addi t5,t5,16 # 800001ec -800001e4: 0000a183 lw gp,0(ra) -800001e8: 1dc0006f j 800003c4 +800001c4: 1a030263 beqz t1,80000368 +800001c8: 808000b7 lui ra,0x80800 +800001cc: deadc137 lui sp,0xdeadc +800001d0: eef10113 addi sp,sp,-273 # deadbeef +800001d4: 0020a023 sw sp,0(ra) # 80800000 +800001d8: 00000f17 auipc t5,0x0 +800001dc: 010f0f13 addi t5,t5,16 # 800001e8 +800001e0: 0000a183 lw gp,0(ra) +800001e4: 1840006f j 80000368 -800001ec : -800001ec: 00300e13 li t3,3 -800001f0: 00000f17 auipc t5,0x0 -800001f4: 1d4f0f13 addi t5,t5,468 # 800003c4 -800001f8: 00ff02b7 lui t0,0xff0 -800001fc: 3b32a073 csrs pmpaddr3,t0 -80000200: 3b302373 csrr t1,pmpaddr3 -80000204: 1c629063 bne t0,t1,800003c4 -80000208: 0ff00293 li t0,255 -8000020c: 3b32a073 csrs pmpaddr3,t0 -80000210: 3b302373 csrr t1,pmpaddr3 -80000214: 00ff02b7 lui t0,0xff0 -80000218: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> -8000021c: 1a629463 bne t0,t1,800003c4 -80000220: 00ff02b7 lui t0,0xff0 -80000224: 3b32b073 csrc pmpaddr3,t0 -80000228: 3b302373 csrr t1,pmpaddr3 -8000022c: 0ff00293 li t0,255 -80000230: 18629a63 bne t0,t1,800003c4 -80000234: 00ff02b7 lui t0,0xff0 -80000238: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> -8000023c: 3a02b073 csrc pmpcfg0,t0 -80000240: 3a002373 csrr t1,pmpcfg0 -80000244: 079202b7 lui t0,0x7920 -80000248: 16629e63 bne t0,t1,800003c4 -8000024c: 00ff02b7 lui t0,0xff0 -80000250: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> -80000254: 3a02a073 csrs pmpcfg0,t0 -80000258: 3a002373 csrr t1,pmpcfg0 -8000025c: 079202b7 lui t0,0x7920 -80000260: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9> -80000264: 16629063 bne t0,t1,800003c4 +800001e8 : +800001e8: 00300e13 li t3,3 +800001ec: 00000f17 auipc t5,0x0 +800001f0: 17cf0f13 addi t5,t5,380 # 80000368 +800001f4: 00ff02b7 lui t0,0xff0 +800001f8: 3b32a073 csrs pmpaddr3,t0 +800001fc: 3b302373 csrr t1,pmpaddr3 +80000200: 16629463 bne t0,t1,80000368 +80000204: 0ff00293 li t0,255 +80000208: 3b32a073 csrs pmpaddr3,t0 +8000020c: 3b302373 csrr t1,pmpaddr3 +80000210: 00ff02b7 lui t0,0xff0 +80000214: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000218: 14629863 bne t0,t1,80000368 +8000021c: 00ff02b7 lui t0,0xff0 +80000220: 3b32b073 csrc pmpaddr3,t0 +80000224: 3b302373 csrr t1,pmpaddr3 +80000228: 0ff00293 li t0,255 +8000022c: 12629e63 bne t0,t1,80000368 +80000230: 00ff02b7 lui t0,0xff0 +80000234: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000238: 3a02b073 csrc pmpcfg0,t0 +8000023c: 3a002373 csrr t1,pmpcfg0 +80000240: 079a02b7 lui t0,0x79a0 +80000244: 12629263 bne t0,t1,80000368 +80000248: 00ff02b7 lui t0,0xff0 +8000024c: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> +80000250: 3a02a073 csrs pmpcfg0,t0 +80000254: 3a002373 csrr t1,pmpcfg0 +80000258: 079a02b7 lui t0,0x79a0 +8000025c: 70728293 addi t0,t0,1799 # 79a0707 <_start-0x7865f8f9> +80000260: 10629463 bne t0,t1,80000368 -80000268 : -80000268: 00400e13 li t3,4 -8000026c: 00000f17 auipc t5,0x0 -80000270: 158f0f13 addi t5,t5,344 # 800003c4 -80000274: 00000117 auipc sp,0x0 -80000278: 01010113 addi sp,sp,16 # 80000284 -8000027c: 34111073 csrw mepc,sp -80000280: 30200073 mret +80000264 : +80000264: 00400e13 li t3,4 +80000268: 00000f17 auipc t5,0x0 +8000026c: 100f0f13 addi t5,t5,256 # 80000368 +80000270: 00000117 auipc sp,0x0 +80000274: 01010113 addi sp,sp,16 # 80000280 +80000278: 34111073 csrw mepc,sp +8000027c: 30200073 mret -80000284 : -80000284: 00500e13 li t3,5 -80000288: 00000f17 auipc t5,0x0 -8000028c: 13cf0f13 addi t5,t5,316 # 800003c4 -80000290: deadc137 lui sp,0xdeadc -80000294: eef10113 addi sp,sp,-273 # deadbeef -80000298: 800080b7 lui ra,0x80008 -8000029c: 0020a023 sw sp,0(ra) # 80008000 -800002a0: 00000f17 auipc t5,0x0 -800002a4: 010f0f13 addi t5,t5,16 # 800002b0 -800002a8: 0000a183 lw gp,0(ra) -800002ac: 1180006f j 800003c4 +80000280 : +80000280: 00500e13 li t3,5 +80000284: 00000f17 auipc t5,0x0 +80000288: 0e4f0f13 addi t5,t5,228 # 80000368 +8000028c: deadc137 lui sp,0xdeadc +80000290: eef10113 addi sp,sp,-273 # deadbeef +80000294: 808000b7 lui ra,0x80800 +80000298: 0020a023 sw sp,0(ra) # 80800000 +8000029c: 00000f17 auipc t5,0x0 +800002a0: 010f0f13 addi t5,t5,16 # 800002ac +800002a4: 0000a183 lw gp,0(ra) +800002a8: 0c00006f j 80000368 -800002b0 : -800002b0: 00600e13 li t3,6 -800002b4: 00000f17 auipc t5,0x0 -800002b8: 110f0f13 addi t5,t5,272 # 800003c4 -800002bc: deadc137 lui sp,0xdeadc -800002c0: eef10113 addi sp,sp,-273 # deadbeef -800002c4: 800000b7 lui ra,0x80000 -800002c8: 0020a023 sw sp,0(ra) # 80000000 -800002cc: 0000a183 lw gp,0(ra) -800002d0: 0e311a63 bne sp,gp,800003c4 +800002ac : +800002ac: 00600e13 li t3,6 +800002b0: 00000f17 auipc t5,0x0 +800002b4: 0b8f0f13 addi t5,t5,184 # 80000368 +800002b8: deadc137 lui sp,0xdeadc +800002bc: eef10113 addi sp,sp,-273 # deadbeef +800002c0: 880000b7 lui ra,0x88000 +800002c4: 0020a023 sw sp,0(ra) # 88000000 +800002c8: 0000a183 lw gp,0(ra) -800002d4 : -800002d4: 00700e13 li t3,7 -800002d8: 00000f17 auipc t5,0x0 -800002dc: 0ecf0f13 addi t5,t5,236 # 800003c4 -800002e0: 800400b7 lui ra,0x80040 -800002e4: 0000a183 lw gp,0(ra) # 80040000 -800002e8: 00000f17 auipc t5,0x0 -800002ec: 010f0f13 addi t5,t5,16 # 800002f8 -800002f0: 0030a023 sw gp,0(ra) -800002f4: 0d00006f j 800003c4 +800002cc : +800002cc: 00700e13 li t3,7 +800002d0: 00000f17 auipc t5,0x0 +800002d4: 098f0f13 addi t5,t5,152 # 80000368 +800002d8: 890000b7 lui ra,0x89000 +800002dc: ff008093 addi ra,ra,-16 # 88fffff0 +800002e0: 0000a183 lw gp,0(ra) +800002e4: 00000f17 auipc t5,0x0 +800002e8: 010f0f13 addi t5,t5,16 # 800002f4 +800002ec: 0030a023 sw gp,0(ra) +800002f0: 0780006f j 80000368 -800002f8 : -800002f8: 00800e13 li t3,8 -800002fc: 00000f17 auipc t5,0x0 -80000300: 0c8f0f13 addi t5,t5,200 # 800003c4 -80000304: deadc137 lui sp,0xdeadc -80000308: eef10113 addi sp,sp,-273 # deadbeef -8000030c: 803400b7 lui ra,0x80340 -80000310: ff808093 addi ra,ra,-8 # 8033fff8 -80000314: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> -80000318: 00000f17 auipc t5,0x0 -8000031c: 010f0f13 addi t5,t5,16 # 80000328 -80000320: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000324: 0a00006f j 800003c4 +800002f4 : +800002f4: 00800e13 li t3,8 +800002f8: 00000f17 auipc t5,0x0 +800002fc: 014f0f13 addi t5,t5,20 # 8000030c +80000300: 00100493 li s1,1 +80000304: 3a305073 csrwi pmpcfg3,0 +80000308: 0600006f j 80000368 -80000328 : -80000328: 00900e13 li t3,9 -8000032c: 00000f17 auipc t5,0x0 -80000330: 098f0f13 addi t5,t5,152 # 800003c4 -80000334: 803800b7 lui ra,0x80380 -80000338: ff808093 addi ra,ra,-8 # 8037fff8 -8000033c: 0000a183 lw gp,0(ra) -80000340: 00000f17 auipc t5,0x0 -80000344: 010f0f13 addi t5,t5,16 # 80000350 -80000348: 0030a023 sw gp,0(ra) -8000034c: 0780006f j 800003c4 +8000030c : +8000030c: 00800e13 li t3,8 +80000310: 1c1e22b7 lui t0,0x1c1e2 +80000314: 90028293 addi t0,t0,-1792 # 1c1e1900 <_start-0x63e1e700> +80000318: 3a302373 csrr t1,pmpcfg3 +8000031c: 04629663 bne t0,t1,80000368 -80000350 : -80000350: 00a00e13 li t3,10 -80000354: 00000f17 auipc t5,0x0 -80000358: 014f0f13 addi t5,t5,20 # 80000368 -8000035c: 00100493 li s1,1 -80000360: 3a305073 csrwi pmpcfg3,0 -80000364: 0600006f j 800003c4 +80000320 : +80000320: 00900e13 li t3,9 +80000324: 00000f17 auipc t5,0x0 +80000328: 044f0f13 addi t5,t5,68 # 80000368 +8000032c: 00000493 li s1,0 +80000330: 00000117 auipc sp,0x0 +80000334: 01010113 addi sp,sp,16 # 80000340 +80000338: 34111073 csrw mepc,sp +8000033c: 30200073 mret -80000368 : -80000368: 00a00e13 li t3,10 -8000036c: 0f1e22b7 lui t0,0xf1e2 -80000370: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> -80000374: 3a302373 csrr t1,pmpcfg3 -80000378: 04629663 bne t0,t1,800003c4 +80000340 : +80000340: 00900e13 li t3,9 +80000344: 00000f17 auipc t5,0x0 +80000348: 014f0f13 addi t5,t5,20 # 80000358 +8000034c: 00100493 li s1,1 +80000350: 3ba05073 csrwi pmpaddr10,0 +80000354: 0140006f j 80000368 -8000037c : -8000037c: 00b00e13 li t3,11 -80000380: 00000f17 auipc t5,0x0 -80000384: 044f0f13 addi t5,t5,68 # 800003c4 -80000388: 00000493 li s1,0 -8000038c: 00000117 auipc sp,0x0 -80000390: 01010113 addi sp,sp,16 # 8000039c -80000394: 34111073 csrw mepc,sp -80000398: 30200073 mret +80000358 : +80000358: 00900e13 li t3,9 +8000035c: fff00293 li t0,-1 +80000360: 3ba02373 csrr t1,pmpaddr10 +80000364: 00628863 beq t0,t1,80000374 -8000039c : -8000039c: 00b00e13 li t3,11 -800003a0: 00000f17 auipc t5,0x0 -800003a4: 014f0f13 addi t5,t5,20 # 800003b4 -800003a8: 00100493 li s1,1 -800003ac: 3ba05073 csrwi pmpaddr10,0 -800003b0: 0140006f j 800003c4 +80000368 : +80000368: f0100137 lui sp,0xf0100 +8000036c: f2410113 addi sp,sp,-220 # f00fff24 +80000370: 01c12023 sw t3,0(sp) -800003b4 : -800003b4: 00b00e13 li t3,11 -800003b8: fff00293 li t0,-1 -800003bc: 3ba02373 csrr t1,pmpaddr10 -800003c0: 00628863 beq t0,t1,800003d0 - -800003c4 : -800003c4: f0100137 lui sp,0xf0100 -800003c8: f2410113 addi sp,sp,-220 # f00fff24 -800003cc: 01c12023 sw t3,0(sp) - -800003d0 : -800003d0: f0100137 lui sp,0xf0100 -800003d4: f2010113 addi sp,sp,-224 # f00fff20 -800003d8: 00012023 sw zero,0(sp) +80000374 : +80000374: f0100137 lui sp,0xf0100 +80000378: f2010113 addi sp,sp,-224 # f00fff20 +8000037c: 00012023 sw zero,0(sp) diff --git a/src/test/cpp/raw/pmp/build/pmp.elf b/src/test/cpp/raw/pmp/build/pmp.elf index 93342d09ddf7c1c79f7bc9c54acec60e475fe976..c28d2cd523bee38e7cdf0e83e5a0a9c9325ecb76 100755 GIT binary patch delta 959 zcmY+BPiPZC6vp37QiE7`H<|ovn$&F;6r`3-DA*)mL-C>)0}6VQx@*CM(9j7YUNUSI z^rEX1L`tzy@E}yEr}f~)yU?o_y$PN~#gka#+s&p~-(hxs-}`3Xo44=gcTTxFeV=(; zE>DOUfOvcEt4h@cX=~Ax{;gvutuVRrgXVNav-? z-7@BNKR@r4XNpp2Y1QsobCUiTpt0dmU2bb9RSJf5exYQc6fet9+A=z1F*#LDRmze8 z1Z9gAohcgRQ~;)`vtDX5Ast5?w6SH)cp&6na=Io;OwmWq(tpi9vSqZ(5j*Pu<-}m|+rnE=-!ydo`DPZ91OW}lx(KqoTkzk4#6(usR z0nV?E1rGUo@M9h7;ymm2Q!CCCS9aMk;>vB7!_{N2x;J7VAP54-@q3Akc@DW3;VSaC z2rnXEr(^#aWD()B$U6}}kNh#hEr2fkjtH00Fd1p+DzYBoRpe%bZz5lbFh}l0_%!7%X`wbFp|0I;*_1Xa%3zkZK{xKbc!{Et?@i-pd-ezRsRFy2Sui2teGw bPkzo$PyEGe@5=qGkrx?&x?eC1v<2}GaMsbY literal 5944 zcmeHLPiP!f82{evCZWa5Z1&kCjr}v-Ep-nio!PEQx&zXNDk4G`51xd$^BS9l*evs= zr9#1Bn}eP@WU7LQti20Cgt;2=u87AX=vkzVm!6E@doyqMg`#-$Fc0SYzTfZt=6myg z`zDb2;FULCC4_()2K)&*idsm%Hk-|~z(&3SlQ5CZS0o={j2@K$#5EzPj2Bfg3I_@Y z3I_@Y3I_@Y3I_@Y3I_@Y3I_@Y3I_@Y{wEG3Wq?odS&|3{k2}s5TqeA7y2T!pfrIVb z01K!IFlPZ!>xWAz{=dIGz-#ZTUnqI(6F<(C5Q3pA3RNi~U(@Ue4FPe{2rDqxjK@ zS7ut`j8U_r_D|Kh5_=JzANDGmq2@b^n;B{GObV^=lP$O=HT$ZcnL;@dyy{aQI_Nn} zQ!~oB`_GO0w4x-64#as@dhr{h{wOtLr9YCwiqt*ZH=3g6FxOopNx1^NOY;3BIJh0Oq0+7>AfLJUN)bxwGhdCLu6~g{|Q;h`%q5 z=g%R&O2+s+;%yB#5&y2?6~r6HSpTxnYxpYST@AmE_-74w5I@!MTZkLl^Sq6?qv7j_ zH#EG7_^yUS#Gh;UF5+)Ayp8xr4S$3fM8Y|401#+HmP$+#rrvWzP-UXsyux_S1q?B>{2m_fhGIjr%p z8-#LUfJOfPdtukd90pn5P!&Gq8eeB&Z|f#3%0so-4a1=4-@+#syZmqC1(XrICNp^? zz88yc$7+=GqJbIdzTzKIfCU9GiymT#jDN~U<0INEdzIs0ep;{ T8mgZ-*Sc;Ro3xb(v(o(y?t_O3 diff --git a/src/test/cpp/raw/pmp/build/pmp.hex b/src/test/cpp/raw/pmp/build/pmp.hex index 2ad2696..805692b 100644 --- a/src/test/cpp/raw/pmp/build/pmp.hex +++ b/src/test/cpp/raw/pmp/build/pmp.hex @@ -1,65 +1,59 @@ :0200000480007A :10000000930400009700000093800001739050302B :100010006F00400173101F3463940400730020309C -:1000200067000F00130E0000170F0000130FCF39E9 +:1000200067000F00130E0000170F0000130F0F34AE :10003000B70000803782008037C1ADDE1301F1EEDA -:1000400023A020002320220083A10000631C31365E -:100050008321020063183136B70212077390023A07 -:100060007323003AB7021F19938242307390123AF9 -:10007000B7120F009382A2907390223AB7221E0FFC -:10008000938202907390323AB70200207390023B41 -:100090007323003B9302F0FF7390123BB7220020C2 -:1000A0007390223BB74200209382F2FF7390323B61 -:1000B000B74200209382F2FF7390423BB742002088 -:1000C0009382F2FF7390523BB72200209382F2FF9B -:1000D0007390623BB76200209382F2FF7390723B91 -:1000E000B7020D207390823BB7020E207390923BB3 -:1000F0009302F0FF7390A23B930200007390B23B17 -:10010000930200007390C23B930200007390D23BB5 -:10011000930200007390E23B930200007390F23B65 -:100120003701C1001301E1FE23A02000232022009B -:1001300083A100006318312893010000832102008D -:1001400063123128130E1000170F0000130FCF2772 -:10015000B7129207938282807390023A7323003A17 -:1001600063926226B780008037C1ADDE1301F1EEE5 -:1001700023A02000170F0000130F0F0183A1000020 -:100180006F004024130E2000170F0000130FCF2321 -:10019000B70212077390023A7323003A6384622213 -:1001A000B74200209382F2FF7350303B7323303B01 -:1001B000631A032063886220B72200207350203B1B -:1001C0007323203B63000320639E621EB780008080 -:1001D00037C1ADDE1301F1EE23A02000170F0000A0 -:1001E000130F0F0183A100006F00C01D130E30001C -:1001F000170F0000130F4F1DB702FF0073A0323B13 -:100200007323303B6390621C9302F00F73A0323B68 -:100210007323303BB702FF009382F20F6394621A9C -:10022000B702FF0073B0323B7323303B9302F00FF1 -:10023000639A6218B702FF009382F20F73B0023A1A -:100240007323003AB7029207639E6216B702FF005B -:100250009382727073A0023A7323003AB702920736 -:100260009382727063906216130E4000170F0000A5 -:10027000130F8F15170100001301010173101134C2 -:1002800073002030130E5000170F0000130FCF1310 -:1002900037C1ADDE1301F1EEB780008023A020004E -:1002A000170F0000130F0F0183A100006F008011D2 -:1002B000130E6000170F0000130F0F1137C1ADDED2 -:1002C0001301F1EEB700008023A0200083A10000FD -:1002D000631A310E130E7000170F0000130FCF0EAC -:1002E000B700048083A10000170F0000130F0F0157 -:1002F00023A030006F00000D130E8000170F0000C8 -:10030000130F8F0C37C1ADDE1301F1EEB70034804F -:10031000938080FF23202200170F0000130F0F018E -:10032000832102006F00000A130E9000170F0000D7 -:10033000130F8F09B7003880938080FF83A10000DE -:10034000170F0000130F0F0123A030006F0080076C -:10035000130EA000170F0000130F4F01930410009D -:100360007350303A6F000006130EA000B7221E0F24 -:10037000938202907323303A63966204130EB000A6 -:10038000170F0000130F4F04930400001701000023 -:10039000130101017310113473002030130EB000EB -:1003A000170F0000130F4F01930410007350A03B70 -:1003B0006F004001130EB0009302F0FF7323A03BC7 -:1003C00063886200370110F0130141F22320C1015C -:0C03D000370110F0130101F2232001009E +:1000400023A020002320220083A10000631E313062 +:1000500083210200631A3130B7021A077390023A03 +:100060007323003A63926230B702191A93824230C6 +:100070007390123AB7120F009382A2907390223AB3 +:100080007323203A6392622EB7221E1C9382029041 +:100090007390323AB70200207390023B7323003B07 +:1000A0006394622C9302F0FF7390123BB7022020FE +:1000B0007390223BB74200209382F2FF7390323B51 +:1000C000B74200209382F2FF7390423BB742002078 +:1000D0009382F2FF7390523BB70200239382F2FFA8 +:1000E0007390623BB70204229382F2FF7390723BDB +:1000F000B7020D207390823BB7020E207390923BA3 +:100100009302F0FF7390A23B930200007390B23B06 +:10011000930200007390C23B930200007390D23BA5 +:10012000930200007390E23B9302F0FF7390F23B66 +:100130003701C1001301E1FE23A02000232022008B +:1001400083A1000063123122930100008321020089 +:10015000631C3120130E1000170F0000130F0F2126 +:10016000B7129A07938282807390023A7323003AFF +:10017000639C621EB700808037C1ADDE1301F1EED3 +:1001800023A02000170F0000130F0F0183A1000010 +:100190006F00801D130E2000170F0000130F0F1D9E +:1001A000B7021A077390023A7323003A638E621AF9 +:1001B0007350303B7323303B6318031A7350203B5A +:1001C0007323203B6302031AB700808037C1ADDE82 +:1001D0001301F1EE23A02000170F0000130F0F01F1 +:1001E00083A100006F004018130E3000170F0000AD +:1001F000130FCF17B702FF0073A0323B7323303BBE +:10020000639462169302F00F73A0323B7323303B6A +:10021000B702FF009382F20F63986214B702FF00E7 +:1002200073B0323B7323303B9302F00F639E621234 +:10023000B702FF009382F20F73B0023A7323003AC1 +:10024000B7029A0763926212B702FF00938272703C +:1002500073A0023A7323003AB7029A07938272702E +:1002600063946210130E4000170F0000130F0F105D +:1002700017010000130101017310113473002030C5 +:10028000130E5000170F0000130F4F0E37C1ADDED5 +:100290001301F1EEB700808023A02000170F0000AB +:1002A000130F0F0183A100006F00000C130E6000FC +:1002B000170F0000130F8F0B37C1ADDE1301F1EEE6 +:1002C000B700008823A0200083A10000130E700057 +:1002D000170F0000130F8F09B7000089938000FFEC +:1002E00083A10000170F0000130F0F0123A030009F +:1002F0006F008007130E8000170F0000130F4F01CF +:10030000930410007350303A6F000006130E800003 +:10031000B7221E1C938202907323303A63966204C4 +:10032000130E9000170F0000130F4F0493040000EA +:100330001701000013010101731011347300203004 +:10034000130E9000170F0000130F4F0193041000BD +:100350007350A03B6F004001130E90009302F0FF1A +:100360007323A03B63886200370110F0130141F250 +:100370002320C101370110F0130101F223200100F5 :040000058000000077 :00000001FF diff --git a/src/test/cpp/raw/pmp/build/pmp.map b/src/test/cpp/raw/pmp/build/pmp.map index fd0c6b0..0a074b1 100644 --- a/src/test/cpp/raw/pmp/build/pmp.map +++ b/src/test/cpp/raw/pmp/build/pmp.map @@ -15,19 +15,19 @@ LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unk END GROUP LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a -.crt_section 0x0000000080000000 0x3dc +.crt_section 0x0000000080000000 0x380 0x0000000080000000 . = ALIGN (0x4) *crt.o(.text) - .text 0x0000000080000000 0x3dc build/src/crt.o + .text 0x0000000080000000 0x380 build/src/crt.o 0x0000000080000000 _start 0x0000000080000014 trap OUTPUT(build/pmp.elf elf32-littleriscv) -.data 0x00000000800003dc 0x0 - .data 0x00000000800003dc 0x0 build/src/crt.o +.data 0x0000000080000380 0x0 + .data 0x0000000080000380 0x0 build/src/crt.o -.bss 0x00000000800003dc 0x0 - .bss 0x00000000800003dc 0x0 build/src/crt.o +.bss 0x0000000080000380 0x0 + .bss 0x0000000080000380 0x0 build/src/crt.o .riscv.attributes 0x0000000000000000 0x1a diff --git a/src/test/cpp/raw/pmp/src/crt.S b/src/test/cpp/raw/pmp/src/crt.S index 3dd75ff..5c74beb 100644 --- a/src/test/cpp/raw/pmp/src/crt.S +++ b/src/test/cpp/raw/pmp/src/crt.S @@ -10,7 +10,7 @@ #define PMPCFG0 0x071a0000 #define PMPCFG0_ 0x079a0808 -#define PMPCFG1 0x191f0304 +#define PMPCFG1 0x1a190304 #define PMPCFG2 0x000f090a #define PMPCFG3 0x1c1e1900 @@ -20,8 +20,8 @@ #define PMPADDR3 0x20003fff // OFF RWX -> 0x00000000 OFF RWX (test2) #define PMPADDR4 0x20003fff // OFF X #define PMPADDR5 0x20003fff // OFF RW -#define PMPADDR6 0x20001fff // NAPOT RWX -#define PMPADDR7 0x20005fff // NAPOT R +#define PMPADDR6 0x22ffffff // NAPOT R +#define PMPADDR7 0x2203ffff // NAPOT W #define PMPADDR8 0x200d0000 // TOR W #define PMPADDR9 0x200e0000 // TOR R #define PMPADDR10 0xffffffff // TOR RWX @@ -29,7 +29,7 @@ #define PMPADDR12 0x00000000 // OFF #define PMPADDR13 0x00000000 // NAPOT R #define PMPADDR14 0x00000000 // NAPOT WX -#define PMPADDR15 0x000001ff // NAPOT X +#define PMPADDR15 0xffffffff // NAPOT X .global _start _start: @@ -129,9 +129,9 @@ test1: bne x5, x6, fail li x1, 0x80800000 li x2, 0xdeadbeef - sw x2, 0x0(x1) // should be OK (write 0x80800000) + sw x2, 0x0(x1) // should be OK (write region 2) la TRAP_RETURN, test2 - lw x3, 0x0(x1) // should fault (read 0x80800000) + lw x3, 0x0(x1) // should fault (read region 2) j fail // "unlock" region 2, attempt read/write from machine mode @@ -150,9 +150,9 @@ test2: beqz x6, fail li x1, 0x80800000 li x2, 0xdeadbeef - sw x2, 0x0(x1) // should still be OK (write 0x80800000) + sw x2, 0x0(x1) // should still be OK (write region 2) la TRAP_RETURN, test3 - lw x3, 0x0(x1) // should still fault (read 0x80800000) + lw x3, 0x0(x1) // should still fault (read region 2) j fail // verify masked CSR read/write operations @@ -184,99 +184,78 @@ test3: li x5, 0x079a0707 bne x5, x6, fail -// jump into user mode +// jump into U-mode test4: li TEST_ID, 4 la TRAP_RETURN, fail la x2, test5 csrw mepc, x2 - # j pass mret -// attempt to read/write region 2 from user mode +// attempt to read/write the locked region from U-mode test5: li TEST_ID, 5 la TRAP_RETURN, fail li x2, 0xdeadbeef li x1, 0x80800000 - sw x2, 0x0(x1) // should be OK (write 0x80800000) + sw x2, 0x0(x1) // should be OK (write region 2) la TRAP_RETURN, test6 - lw x3, 0x0(x1) // should fault (read 0x80800000) + lw x3, 0x0(x1) // should fault (read region 2) j fail -// attempt to read/write other regions from user mode +// attempt to read/write overlapping regions from U-mode test6: li TEST_ID, 6 - la TRAP_RETURN, fail + la TRAP_RETURN, fail li x2, 0xdeadbeef - li x1, 0x80000000 - sw x2, 0x0(x1) - lw x3, 0x0(x1) - bne x2, x3, fail // should be OK (read/write 0x80000000) + li x1, 0x88000000 + sw x2, 0x0(x1) // should be OK (write region 6/7) + lw x3, 0x0(x1) // should be OK (write region 6/7) test7: li TEST_ID, 7 la TRAP_RETURN, fail - li x1, 0x80040000 - lw x3, 0x0(x1) // should be OK (read 0x80040000) - la TRAP_RETURN, test8 - sw x3, 0x0(x1) // should fault (write 0x80040000) - j fail - -test8: - li TEST_ID, 8 - la TRAP_RETURN, fail - li x2, 0xdeadbeef - li x1, 0x8033fff8 - sw x2, 0x0(x4) // should be OK (write region 8) - la TRAP_RETURN, test9 - lw x3, 0x0(x4) // should fault (read region 8) - j fail - -test9: - li TEST_ID, 9 - la TRAP_RETURN, fail - li x1, 0x8037fff8 - lw x3, 0x0(x1) // should be OK (read region 9) - la TRAP_RETURN, test10a - sw x3, 0x0(x1) // should fault (write region 9) + li x1, 0x88fffff0 + lw x3, 0x0(x1) // should be OK (read region 6) + la TRAP_RETURN, test8a + sw x3, 0x0(x1) // should fault (write region 6) j fail // attempt to write a pmpcfg# register from U-mode -test10a: - li TEST_ID, 10 - la TRAP_RETURN, test10b +test8a: + li TEST_ID, 8 + la TRAP_RETURN, test8b li TRAP_EXIT, 0x1 csrwi pmpcfg3, 0x0 j fail // check the result from M-mode -test10b: - li TEST_ID, 10 +test8b: + li TEST_ID, 8 li x5, PMPCFG3 csrr x6, pmpcfg3 bne x5, x6, fail // jump back into U-mode -test11a: - li TEST_ID, 11 +test9a: + li TEST_ID, 9 la TRAP_RETURN, fail li TRAP_EXIT, 0x0 - la x2, test11b + la x2, test9b csrw mepc, x2 mret // attempt to write a pmpaddr# register from U-mode -test11b: - li TEST_ID, 11 - la TRAP_RETURN, test11c +test9b: + li TEST_ID, 9 + la TRAP_RETURN, test9c li TRAP_EXIT, 0x1 csrwi pmpaddr10, 0x0 j fail // check the result from M-mode -test11c: - li TEST_ID, 11 +test9c: + li TEST_ID, 9 li x5, PMPADDR10 csrr x6, pmpaddr10 beq x5, x6, pass diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 6167f71..77a4738 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -520,6 +520,7 @@ class MmuPmpDimension extends VexRiscvDimension("DBus") { override def applyOn(config: VexRiscvConfig): Unit = { config.plugins += new PmpPlugin( regions = 16, + granularity = 32, ioRange = _ (31 downto 28) === 0xF ) } From 243d0ec664671444d9c6f32a23f8c98aa950a689 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Fri, 28 May 2021 13:59:59 +0200 Subject: [PATCH 10/14] Clarify PMP section in README --- README.md | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 62dde96..895f3c2 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,35 @@ - [Adding a new CSR via the plugin system](#adding-a-new-csr-via-the-plugin-system) - [CPU clock and resets](#cpu-clock-and-resets) - [VexRiscv Architecture](#vexriscv-architecture) - * [FPU](#fpu) - * [Plugins](#plugins) + - [FPU](#fpu) + - [Plugins](#plugins) + - [IBusSimplePlugin](#ibussimpleplugin) + - [IBusCachedPlugin](#ibuscachedplugin) + - [DecoderSimplePlugin](#decodersimpleplugin) + - [RegFilePlugin](#regfileplugin) + - [HazardSimplePlugin](#hazardsimpleplugin) + - [SrcPlugin](#srcplugin) + - [IntAluPlugin](#intaluplugin) + - [LightShifterPlugin](#lightshifterplugin) + - [FullBarrelShifterPlugin](#fullbarrelshifterplugin) + - [BranchPlugin](#branchplugin) + - [Prediction NONE](#prediction-none) + - [Prediction STATIC](#prediction-static) + - [Prediction DYNAMIC](#prediction-dynamic) + - [Prediction DYNAMIC_TARGET](#prediction-dynamic_target) + - [DBusSimplePlugin](#dbussimpleplugin) + - [DBusCachedPlugin](#dbuscachedplugin) + - [MulPlugin](#mulplugin) + - [DivPlugin](#divplugin) + - [MulDivIterativePlugin](#muldiviterativeplugin) + - [CsrPlugin](#csrplugin) + - [StaticMemoryTranslatorPlugin](#staticmemorytranslatorplugin) + - [MmuPlugin](#mmuplugin) + - [PmpPlugin](#pmpplugin) + - [DebugPlugin](#debugplugin) + - [YamlPlugin](#yamlplugin) + - [FpuPlugin](#fpuplugin) + - [AesPlugin](#aesplugin) @@ -1079,7 +1106,7 @@ fully associative TLB cache which is refilled automaticaly via a dbus access sha #### PmpPlugin -This is a physical memory protection (PMP) plugin which conforms to the latest RISC-V privilege specification. PMP is configured by writing two special CSRs: `pmpcfg#` and `pmpaddr#`. The former contains the permissions and addressing modes for four protection regions, and the latter contains the encoded start address for a single region. Since the actual region bounds must be computed from the values written to these registers, writing them takes a few CPU cylces: (5 for `pmpcfg#` and 2-3 for `pmpaddr#`). This delay is necessary in order to centralize all of the decoding logic into a single component. Otherwise, it would have to be duplicated for each region, even though the decoding operation happens only when PMP is reprogrammed (e.g., on some context switches). +This is a physical memory protection (PMP) plugin which conforms to the latest RISC-V privilege specification. PMP is configured by writing two special CSRs: `pmpcfg#` and `pmpaddr#`. The former contains the permissions and addressing modes for four protection regions, and the latter contains the encoded start address for a single region. Since the actual region bounds must be computed from the values written to these registers, writing them takes a few CPU cylces. This delay is necessary in order to centralize all of the decoding logic into a single component. Otherwise, it would have to be duplicated for each region, even though the decoding operation happens only when PMP is reprogrammed (e.g., on some context switches). #### DebugPlugin From 3a4ab7ad517b483d25652e08b0c532e78084d4ed Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Fri, 28 May 2021 16:17:19 +0200 Subject: [PATCH 11/14] Un-pend PMP CSR writes on pipeline flushes --- src/main/scala/vexriscv/plugin/PmpPlugin.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index f9d47ee..34d323d 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -182,6 +182,10 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } } + when (arbitration.isFlushed) { + pending := False + } + val writer = new Area { when (pending) { arbitration.haltItself := True From 2a4ca0b249e7e72464bf88fe05c4a52f8bb5bdc3 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Wed, 2 Jun 2021 16:01:30 +0200 Subject: [PATCH 12/14] PMP CSR writes occur in execute stage --- .../scala/vexriscv/plugin/PmpPlugin.scala | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index 34d323d..36626b1 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -133,7 +133,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend execute plug new Area { import execute._ - val pending = RegInit(False) + val pending = RegInit(False) clearWhen(!arbitration.isStuck) val hazardFree = csrService.isHazardFree() val csrAddress = input(INSTRUCTION)(csrRange) @@ -168,24 +168,17 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend csrService.duringAnyWrite { when ((pmpcfgCsr | pmpaddrCsr) & machineMode) { csrService.allowCsr() + when (!pending) { + pending := True + writeData_ := csrService.writeData() + pmpNcfg_ := pmpNcfg + pmpcfgN_ := pmpcfgN + pmpaddrCsr_ := pmpcfgCsr + pmpcfgCsr_ := pmpaddrCsr + } } } - csrService.onAnyWrite { - when ((pmpcfgCsr | pmpaddrCsr) & machineMode) { - pending := True - writeData_ := csrService.writeData() - pmpNcfg_ := pmpNcfg - pmpcfgN_ := pmpcfgN - pmpaddrCsr_ := pmpcfgCsr - pmpcfgCsr_ := pmpaddrCsr - } - } - - when (arbitration.isFlushed) { - pending := False - } - val writer = new Area { when (pending) { arbitration.haltItself := True @@ -208,12 +201,12 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend val stateIdle : State = new State with EntryPoint { onEntry { + pending := False enable := False counter := 0 } onExit { enable := True - pending := False arbitration.haltItself := True } whenIsActive { From 342b06128f5a147f2b7d3784dd3a59f0ca11abe2 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Wed, 2 Jun 2021 16:39:52 +0200 Subject: [PATCH 13/14] Combine all the PMP logic into one FSM --- .../scala/vexriscv/plugin/PmpPlugin.scala | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index 36626b1..1cebfe7 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -160,7 +160,7 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } when (pmpaddrCsr) { csrService.allowCsr() - csrService.readData() := pmpaddr.readAsync(pmpNcfg).asBits + csrService.readData() := pmpaddr(pmpNcfg).asBits } } } @@ -173,28 +173,12 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend writeData_ := csrService.writeData() pmpNcfg_ := pmpNcfg pmpcfgN_ := pmpcfgN - pmpaddrCsr_ := pmpcfgCsr - pmpcfgCsr_ := pmpaddrCsr + pmpcfgCsr_ := pmpcfgCsr + pmpaddrCsr_ := pmpaddrCsr } } } - val writer = new Area { - when (pending) { - arbitration.haltItself := True - when (hazardFree & pmpaddrCsr_) { - val overwrite = writeData_.subdivideIn(8 bits) - for (i <- 0 until 4) { - when (~pmpcfg(pmpcfgN_ @@ U(i, 2 bits))(lBit)) { - pmpcfg(pmpcfgN_ @@ U(i, 2 bits)).assignFromBits(overwrite(i)) - } - } - } - } - val locked = pmpcfg(pmpNcfg_)(lBit) - pmpaddr.write(pmpNcfg_, writeData_.asUInt, ~locked & pmpcfgCsr_ & pending & hazardFree) - } - val controller = new StateMachine { val enable = RegInit(False) val counter = Reg(UInt(log2Up(regions) bits)) init(0) @@ -205,21 +189,38 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend enable := False counter := 0 } - onExit { - enable := True - arbitration.haltItself := True - } whenIsActive { - when (pending & hazardFree) { - when (pmpaddrCsr_) { - goto(stateCfg) - }.elsewhen (pmpcfgCsr_) { - goto(stateAddr) + when (pending) { + arbitration.haltItself := True + when (hazardFree) { + goto(stateWrite) } } } } + val stateWrite : State = new State { + onExit (enable := True) + whenIsActive { + arbitration.haltItself := True + when (pmpcfgCsr_) { + val overwrite = writeData_.subdivideIn(8 bits) + for (i <- 0 until 4) { + when (~pmpcfg(pmpcfgN_ @@ U(i, 2 bits))(lBit)) { + pmpcfg(pmpcfgN_ @@ U(i, 2 bits)).assignFromBits(overwrite(i)) + } + } + goto(stateCfg) + } + when (pmpaddrCsr_) { + when (~pmpcfg(pmpNcfg_)(lBit)) { + pmpaddr(pmpNcfg_) := writeData_.asUInt + } + goto(stateAddr) + } + } + } + val stateCfg : State = new State { onEntry (counter := pmpcfgN_ @@ U(0, 2 bits)) whenIsActive { @@ -237,10 +238,10 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend whenIsActive (goto(stateIdle)) } - when (pmpcfgCsr_) { + when (pmpaddrCsr_) { setter.io.addr := writeData_.asUInt } otherwise { - setter.io.addr := pmpaddr.readAsync(counter) + setter.io.addr := pmpaddr(counter) } when (enable & ~pmpcfg(counter)(lBit)) { From 156a84e76fc8e04fab3257ce0351a6c05c215c67 Mon Sep 17 00:00:00 2001 From: Samuel Lindemer Date: Thu, 3 Jun 2021 13:12:55 +0200 Subject: [PATCH 14/14] Fix PMP FSM halting logic --- .../scala/vexriscv/plugin/PmpPlugin.scala | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index 1cebfe7..7c1330b 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -133,7 +133,8 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend execute plug new Area { import execute._ - val pending = RegInit(False) clearWhen(!arbitration.isStuck) + val fsmPending = RegInit(False) clearWhen(!arbitration.isStuck) + val fsmComplete = False val hazardFree = csrService.isHazardFree() val csrAddress = input(INSTRUCTION)(csrRange) @@ -168,8 +169,9 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend csrService.duringAnyWrite { when ((pmpcfgCsr | pmpaddrCsr) & machineMode) { csrService.allowCsr() - when (!pending) { - pending := True + arbitration.haltItself := !fsmComplete + when (!fsmPending) { + fsmPending := True writeData_ := csrService.writeData() pmpNcfg_ := pmpNcfg pmpcfgN_ := pmpcfgN @@ -179,30 +181,26 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend } } - val controller = new StateMachine { - val enable = RegInit(False) - val counter = Reg(UInt(log2Up(regions) bits)) init(0) + val fsm = new StateMachine { + val fsmEnable = RegInit(False) + val fsmCounter = Reg(UInt(log2Up(regions) bits)) init(0) val stateIdle : State = new State with EntryPoint { onEntry { - pending := False - enable := False - counter := 0 + fsmPending := False + fsmEnable := False + fsmComplete := True + fsmCounter := 0 } whenIsActive { - when (pending) { - arbitration.haltItself := True - when (hazardFree) { - goto(stateWrite) - } + when (fsmPending & hazardFree) { + goto(stateWrite) } } } val stateWrite : State = new State { - onExit (enable := True) whenIsActive { - arbitration.haltItself := True when (pmpcfgCsr_) { val overwrite = writeData_.subdivideIn(8 bits) for (i <- 0 until 4) { @@ -219,34 +217,33 @@ class PmpPlugin(regions : Int, granularity : Int, ioRange : UInt => Bool) extend goto(stateAddr) } } + onExit (fsmEnable := True) } val stateCfg : State = new State { - onEntry (counter := pmpcfgN_ @@ U(0, 2 bits)) + onEntry (fsmCounter := pmpcfgN_ @@ U(0, 2 bits)) whenIsActive { - counter := counter + 1 - when (counter(1 downto 0) === 3) { + fsmCounter := fsmCounter + 1 + when (fsmCounter(1 downto 0) === 3) { goto(stateIdle) - } otherwise { - arbitration.haltItself := True } } } val stateAddr : State = new State { - onEntry (counter := pmpNcfg_) + onEntry (fsmCounter := pmpNcfg_) whenIsActive (goto(stateIdle)) } when (pmpaddrCsr_) { setter.io.addr := writeData_.asUInt } otherwise { - setter.io.addr := pmpaddr(counter) + setter.io.addr := pmpaddr(fsmCounter) } - when (enable & ~pmpcfg(counter)(lBit)) { - base(counter) := setter.io.base - mask(counter) := setter.io.mask + when (fsmEnable & ~pmpcfg(fsmCounter)(lBit)) { + base(fsmCounter) := setter.io.base + mask(fsmCounter) := setter.io.mask } } }