Centralised all todo in linux.scala

Sorted out fence fence.i instruction in iBus/dBus plugins.
Fixed MMU permitions while in used mode and bypassing the MMU
This commit is contained in:
Charles Papon 2019-04-05 12:17:29 +02:00
parent 888e1c0b8a
commit 446e9625af
10 changed files with 23 additions and 25 deletions

View File

@ -49,8 +49,7 @@ object GenFull extends App{
),
new MmuPlugin(
virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF,
allowUserIo = false
ioRange = _(31 downto 28) === 0xF
),
new DecoderSimplePlugin(
catchIllegalInstruction = true

View File

@ -90,12 +90,11 @@ https://github.com/riscv/riscv-qemu/wiki#build-and-install
//TODO test dcache flush
//TODO have to check, look like supervisor can't get interrupt if the machine mod didn't delegated it, have to check exactly
//TODO IBus cached and uncached, do not allow supervisor if it's a user page ? io.cpu.fetch.mmuException
object LinuxGen {
def configFull(litex : Boolean, withMmu : Boolean) = {
val config = VexRiscvConfig(
plugins = List(
new DummyFencePlugin(), //TODO should be removed for design with caches
//Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config
// new IBusSimplePlugin(
// resetVector = 0x80000000l,
@ -179,7 +178,7 @@ object LinuxGen {
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
zeroBoot = true //TODO
zeroBoot = true
),
new IntAluPlugin,
new SrcPlugin(
@ -240,10 +239,7 @@ object LinuxGen {
)
)
if(withMmu) config.plugins += new MmuPlugin(
virtualRange = a => True,
// virtualRange = x => x(31 downto 24) =/= 0x81,
ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE || x(31 downto 28) === 0xF else x(31 downto 28) === 0xF),
allowUserIo = true //TODO ??
ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE || x(31 downto 28) === 0xF else x(31 downto 28) === 0xF)
) else {
config.plugins += new StaticMemoryTranslatorPlugin(
ioRange = _(31 downto 28) === 0xF

View File

@ -8,7 +8,6 @@ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import spinal.lib.bus.simple._
//TODO flush
case class DataCacheConfig(cacheSize : Int,
bytePerLine : Int,

View File

@ -411,7 +411,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.fetch.cacheMiss := !hit.valid
io.cpu.fetch.error := hit.error
io.cpu.fetch.mmuRefilling := mmuRsp.refilling
io.cpu.fetch.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.fetch.isUser)) //TODO Do not allow supervisor if it's a user page ?
io.cpu.fetch.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.fetch.isUser))
})
}
@ -441,7 +441,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.decode.cacheMiss := !hit.valid
io.cpu.decode.error := hit.error
io.cpu.decode.mmuRefilling := mmuRsp.refilling
io.cpu.decode.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.decode.isUser)) //TODO Do not allow supervisor if it's a user page ?
io.cpu.decode.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute || (!mmuRsp.allowUser && io.cpu.decode.isUser))
io.cpu.decode.physicalAddress := mmuRsp.physicalAddress
})
}

View File

@ -813,7 +813,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
import lastStage._
//Manage MRET / SRET instructions
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { //TODO do not allow user mode already implemented somewhere else ?
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
fetcher.haltIt()
jumpInterface.valid := True
beforeLastStage.arbitration.flushAll := True
@ -885,7 +885,6 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
//Manage MRET / SRET instructions
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
//TODO check MPP value too
when(input(INSTRUCTION)(29 downto 28).asUInt > privilege) {
illegalInstruction := True
}

View File

@ -113,6 +113,8 @@ class DBusCachedPlugin(config : DataCacheConfig,
MEMORY_MANAGMENT -> True
))
decoderService.add(FENCE, Nil)
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.writeBack)
@ -284,6 +286,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.memory.isValid setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.memory.mmuBus.rsp.allowUser setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.writeBack.isValid setWhen(writeBack.input(IS_DBUS_SHARING))
dBusAccess.rsp.valid := writeBack.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt)
dBusAccess.rsp.data := cache.io.cpu.writeBack.data

View File

@ -292,6 +292,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
)
}
decoderService.add(FENCE, Nil)
rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
if(catchSomething) {

View File

@ -78,8 +78,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
super.setup(pipeline)
//def MANAGEMENT = M"-----------------100-----0001111"
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(FLUSH_ALL, False)
decoderService.add(FENCE_I, List(

View File

@ -7,6 +7,7 @@ import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import spinal.lib.bus.simple._
import vexriscv.Riscv.{FENCE, FENCE_I}
case class IBusSimpleCmd() extends Bundle{
@ -192,6 +193,9 @@ class IBusSimplePlugin(resetVector : BigInt,
super.setup(pipeline)
iBus = master(IBusSimpleBus(false)).setName("iBus")
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.add(FENCE_I, Nil)
if(catchSomething) {
decodeExceptionPort = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.decode,1)
}

View File

@ -38,17 +38,16 @@ case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConf
case class MmuPortConfig(portTlbSize : Int)
class MmuPlugin(virtualRange : UInt => Bool,
ioRange : UInt => Bool,
allowUserIo : Boolean,
allowMachineModeMmu : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
class MmuPlugin(ioRange : UInt => Bool,
virtualRange : UInt => Bool = address => True,
// allowUserIo : Boolean = false,
enableMmuInMachineMode : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
var dBusAccess : DBusAccess = null
val portsInfo = ArrayBuffer[MmuPort]()
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
// val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage)
val port = MmuPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MmuPortConfig], portsInfo.length /*,exceptionBus*/)
val port = MmuPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MmuPortConfig], portsInfo.length)
portsInfo += port
port.bus
}
@ -96,7 +95,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
}
for(offset <- List(CSR.MSTATUS, CSR.SSTATUS)) csrService.rw(offset, 19 -> status.mxr, 18 -> status.sum, 17 -> status.mprv)
csrService.rw(CSR.SATP, 31 -> satp.mode, 0 -> satp.ppn) //TODO write only ?
csrService.rw(CSR.SATP, 31 -> satp.mode, 0 -> satp.ppn)
}
val core = pipeline plug new Area {
@ -109,7 +108,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
val entryToReplace = Counter(port.args.portTlbSize)
val requireMmuLockup = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation && csr.satp.mode
if(!allowMachineModeMmu) {
if(!enableMmuInMachineMode) {
requireMmuLockup clearWhen(!csr.status.mprv && privilegeService.isMachine())
when(privilegeService.isMachine()) {
if (port.priority == MmuPort.PRIORITY_DATA) {
@ -133,7 +132,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
port.bus.rsp.allowRead := True
port.bus.rsp.allowWrite := True
port.bus.rsp.allowExecute := True
port.bus.rsp.allowUser := Bool(allowUserIo)
port.bus.rsp.allowUser := True
port.bus.rsp.exception := False
port.bus.rsp.refilling := False
}