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:
parent
888e1c0b8a
commit
446e9625af
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue