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(
|
new MmuPlugin(
|
||||||
virtualRange = _(31 downto 28) === 0xC,
|
virtualRange = _(31 downto 28) === 0xC,
|
||||||
ioRange = _(31 downto 28) === 0xF,
|
ioRange = _(31 downto 28) === 0xF
|
||||||
allowUserIo = false
|
|
||||||
),
|
),
|
||||||
new DecoderSimplePlugin(
|
new DecoderSimplePlugin(
|
||||||
catchIllegalInstruction = true
|
catchIllegalInstruction = true
|
||||||
|
|
|
@ -90,12 +90,11 @@ https://github.com/riscv/riscv-qemu/wiki#build-and-install
|
||||||
|
|
||||||
//TODO test dcache flush
|
//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 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 {
|
object LinuxGen {
|
||||||
def configFull(litex : Boolean, withMmu : Boolean) = {
|
def configFull(litex : Boolean, withMmu : Boolean) = {
|
||||||
val config = VexRiscvConfig(
|
val config = VexRiscvConfig(
|
||||||
plugins = List(
|
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
|
//Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config
|
||||||
// new IBusSimplePlugin(
|
// new IBusSimplePlugin(
|
||||||
// resetVector = 0x80000000l,
|
// resetVector = 0x80000000l,
|
||||||
|
@ -179,7 +178,7 @@ object LinuxGen {
|
||||||
),
|
),
|
||||||
new RegFilePlugin(
|
new RegFilePlugin(
|
||||||
regFileReadyKind = plugin.SYNC,
|
regFileReadyKind = plugin.SYNC,
|
||||||
zeroBoot = true //TODO
|
zeroBoot = true
|
||||||
),
|
),
|
||||||
new IntAluPlugin,
|
new IntAluPlugin,
|
||||||
new SrcPlugin(
|
new SrcPlugin(
|
||||||
|
@ -240,10 +239,7 @@ object LinuxGen {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if(withMmu) config.plugins += new MmuPlugin(
|
if(withMmu) config.plugins += new MmuPlugin(
|
||||||
virtualRange = a => True,
|
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)
|
||||||
// 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 ??
|
|
||||||
) else {
|
) else {
|
||||||
config.plugins += new StaticMemoryTranslatorPlugin(
|
config.plugins += new StaticMemoryTranslatorPlugin(
|
||||||
ioRange = _(31 downto 28) === 0xF
|
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.wishbone.{Wishbone, WishboneConfig}
|
||||||
import spinal.lib.bus.simple._
|
import spinal.lib.bus.simple._
|
||||||
|
|
||||||
//TODO flush
|
|
||||||
|
|
||||||
case class DataCacheConfig(cacheSize : Int,
|
case class DataCacheConfig(cacheSize : Int,
|
||||||
bytePerLine : Int,
|
bytePerLine : Int,
|
||||||
|
|
|
@ -411,7 +411,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
||||||
io.cpu.fetch.cacheMiss := !hit.valid
|
io.cpu.fetch.cacheMiss := !hit.valid
|
||||||
io.cpu.fetch.error := hit.error
|
io.cpu.fetch.error := hit.error
|
||||||
io.cpu.fetch.mmuRefilling := mmuRsp.refilling
|
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.cacheMiss := !hit.valid
|
||||||
io.cpu.decode.error := hit.error
|
io.cpu.decode.error := hit.error
|
||||||
io.cpu.decode.mmuRefilling := mmuRsp.refilling
|
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
|
io.cpu.decode.physicalAddress := mmuRsp.physicalAddress
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -813,7 +813,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
import lastStage._
|
import lastStage._
|
||||||
|
|
||||||
//Manage MRET / SRET instructions
|
//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()
|
fetcher.haltIt()
|
||||||
jumpInterface.valid := True
|
jumpInterface.valid := True
|
||||||
beforeLastStage.arbitration.flushAll := True
|
beforeLastStage.arbitration.flushAll := True
|
||||||
|
@ -885,7 +885,6 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
|
|
||||||
//Manage MRET / SRET instructions
|
//Manage MRET / SRET instructions
|
||||||
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
||||||
//TODO check MPP value too
|
|
||||||
when(input(INSTRUCTION)(29 downto 28).asUInt > privilege) {
|
when(input(INSTRUCTION)(29 downto 28).asUInt > privilege) {
|
||||||
illegalInstruction := True
|
illegalInstruction := True
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,8 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
||||||
MEMORY_MANAGMENT -> True
|
MEMORY_MANAGMENT -> True
|
||||||
))
|
))
|
||||||
|
|
||||||
|
decoderService.add(FENCE, Nil)
|
||||||
|
|
||||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
|
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
|
||||||
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.writeBack)
|
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))
|
mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING))
|
||||||
cache.io.cpu.memory.isValid 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))
|
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.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
|
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)
|
rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
|
||||||
if(catchSomething) {
|
if(catchSomething) {
|
||||||
|
|
|
@ -78,8 +78,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
||||||
|
|
||||||
super.setup(pipeline)
|
super.setup(pipeline)
|
||||||
|
|
||||||
//def MANAGEMENT = M"-----------------100-----0001111"
|
|
||||||
|
|
||||||
val decoderService = pipeline.service(classOf[DecoderService])
|
val decoderService = pipeline.service(classOf[DecoderService])
|
||||||
decoderService.addDefault(FLUSH_ALL, False)
|
decoderService.addDefault(FLUSH_ALL, False)
|
||||||
decoderService.add(FENCE_I, List(
|
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.avalon.{AvalonMM, AvalonMMConfig}
|
||||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
import spinal.lib.bus.simple._
|
import spinal.lib.bus.simple._
|
||||||
|
import vexriscv.Riscv.{FENCE, FENCE_I}
|
||||||
|
|
||||||
|
|
||||||
case class IBusSimpleCmd() extends Bundle{
|
case class IBusSimpleCmd() extends Bundle{
|
||||||
|
@ -192,6 +193,9 @@ class IBusSimplePlugin(resetVector : BigInt,
|
||||||
super.setup(pipeline)
|
super.setup(pipeline)
|
||||||
iBus = master(IBusSimpleBus(false)).setName("iBus")
|
iBus = master(IBusSimpleBus(false)).setName("iBus")
|
||||||
|
|
||||||
|
val decoderService = pipeline.service(classOf[DecoderService])
|
||||||
|
decoderService.add(FENCE_I, Nil)
|
||||||
|
|
||||||
if(catchSomething) {
|
if(catchSomething) {
|
||||||
decodeExceptionPort = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.decode,1)
|
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)
|
case class MmuPortConfig(portTlbSize : Int)
|
||||||
|
|
||||||
class MmuPlugin(virtualRange : UInt => Bool,
|
class MmuPlugin(ioRange : UInt => Bool,
|
||||||
ioRange : UInt => Bool,
|
virtualRange : UInt => Bool = address => True,
|
||||||
allowUserIo : Boolean,
|
// allowUserIo : Boolean = false,
|
||||||
allowMachineModeMmu : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
enableMmuInMachineMode : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||||
|
|
||||||
var dBusAccess : DBusAccess = null
|
var dBusAccess : DBusAccess = null
|
||||||
val portsInfo = ArrayBuffer[MmuPort]()
|
val portsInfo = ArrayBuffer[MmuPort]()
|
||||||
|
|
||||||
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
|
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)
|
||||||
val port = MmuPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MmuPortConfig], portsInfo.length /*,exceptionBus*/)
|
|
||||||
portsInfo += port
|
portsInfo += port
|
||||||
port.bus
|
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)
|
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 {
|
val core = pipeline plug new Area {
|
||||||
|
@ -109,7 +108,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
||||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||||
val entryToReplace = Counter(port.args.portTlbSize)
|
val entryToReplace = Counter(port.args.portTlbSize)
|
||||||
val requireMmuLockup = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation && csr.satp.mode
|
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())
|
requireMmuLockup clearWhen(!csr.status.mprv && privilegeService.isMachine())
|
||||||
when(privilegeService.isMachine()) {
|
when(privilegeService.isMachine()) {
|
||||||
if (port.priority == MmuPort.PRIORITY_DATA) {
|
if (port.priority == MmuPort.PRIORITY_DATA) {
|
||||||
|
@ -133,7 +132,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
||||||
port.bus.rsp.allowRead := True
|
port.bus.rsp.allowRead := True
|
||||||
port.bus.rsp.allowWrite := True
|
port.bus.rsp.allowWrite := True
|
||||||
port.bus.rsp.allowExecute := 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.exception := False
|
||||||
port.bus.rsp.refilling := False
|
port.bus.rsp.refilling := False
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue