Fix DebugPlugin -> force machine mode, force uncached memory load

This commit is contained in:
Charles Papon 2019-04-10 00:35:15 +02:00
parent 9b6b65b8b4
commit d7f6c18c0a
10 changed files with 94 additions and 41 deletions

View file

@ -14,7 +14,7 @@ trait Pipeline {
val plugins = ArrayBuffer[Plugin[T]]()
var stages = ArrayBuffer[Stage]()
var unremovableStages = mutable.Set[Stage]()
val configs = mutable.HashMap[PipelineThing[_], Any]()
val things = mutable.HashMap[PipelineThing[_], Any]()
// val services = ArrayBuffer[Any]()
def indexOf(stage : Stage) = stages.indexOf(stage)
@ -37,8 +37,8 @@ trait Pipeline {
filtered.head.asInstanceOf[T]
}
def update[T](that : PipelineThing[T], value : T) : Unit = configs(that) = value
def apply[T](that : PipelineThing[T]) : T = configs(that).asInstanceOf[T]
def update[T](that : PipelineThing[T], value : T) : Unit = things(that) = value
def apply[T](that : PipelineThing[T]) : T = things(that).asInstanceOf[T]
def build(): Unit ={
plugins.foreach(_.pipeline = this.asInstanceOf[T])

View file

@ -40,12 +40,14 @@ trait PrivilegeService{
def isUser() : Bool
def isSupervisor() : Bool
def isMachine() : Bool
def forceMachine() : Unit
}
case class PrivilegeServiceDefault() extends PrivilegeService{
override def isUser(): Bool = False
override def isSupervisor(): Bool = False
override def isMachine(): Bool = True
override def forceMachine(): Unit = {}
}
trait InterruptionInhibitor{
@ -56,6 +58,7 @@ trait ExceptionInhibitor{
def inhibateException() : Unit
}
trait RegFileService{
def readStage() : Stage
}

View file

@ -50,7 +50,6 @@ class Stage() extends Area{
val haltByOther = False //When settable, stuck the instruction, should only be set by something else than the stucked instruction
val removeIt = False //When settable, unschedule the instruction as if it was never executed (no side effect)
val flushAll = False //When settable, unschedule instructions in the current stage and all prior ones
val redoIt = False //Allow to notify that a given instruction in a pipeline is rescheduled
val isValid = Bool //Inform if a instruction is in the current stage
val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther)
val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else

View file

@ -43,6 +43,7 @@ case class VexRiscvConfig(){
object REGFILE_WRITE_DATA extends Stageable(Bits(32 bits))
object MPP extends PipelineThing[UInt]
object DEBUG_BYPASS_CACHE extends PipelineThing[Bool]
object SRC1 extends Stageable(Bits(32 bits))
object SRC2 extends Stageable(Bits(32 bits))

View file

@ -40,13 +40,13 @@ cd VexRiscv
Run regressions =>
sbt "runMain vexriscv.demo.LinuxGen -r"
cd src/test/cpp/regression
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes CSR=yes COMPRESSED=yes REDO=10 TRACE=no
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes CSR=yes COMPRESSED=yes LRSC=yes AMO=yes REDO=10 TRACE=no
Run linux in simulation (Require the machime mode emulator compiled in SIM mode) =>
sbt "runMain vexriscv.demo.LinuxGen"
cd src/test/cpp/regression
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=../../../main/c/emulator/build/emulator.bin VMLINUX=$BUILDROOT/output/images/vmlinux.bin DTB=$BUILDROOT/board/spinal/vexriscv_sim/rv32.dtb RAMDISK=$BUILDROOT/output/images/rootfs.cpio TRACE=no FLOW_INFO=no
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=yes LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=../../../main/c/emulator/build/emulator.bin VMLINUX=$BUILDROOT/output/images/Image DTB=$BUILDROOT/board/spinal/vexriscv_sim/rv32.dtb RAMDISK=$BUILDROOT/output/images/rootfs.cpio TRACE=no FLOW_INFO=no
Run linux with QEMU (Require the machime mode emulator compiled in QEMU mode)
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
@ -85,6 +85,35 @@ Generate a DTB from a DTS =>
dtc -O dtb -o rv32.dtb rv32.dts
https://github.com/riscv/riscv-qemu/wiki#build-and-install
memo :
export DATA=/home/miaou/Downloads/Binaries-master
cd src/test/cpp/regression
rm VexRiscv.v
cp $DATA/VexRiscv.v ../../../..
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=$DATA/emulator.bin VMLINUX=$DATA/vmlinux.bin DTB=$DATA/rv32.dtb RAMDISK=$DATA/rootfs.cpio TRACE=no FLOW_INFO=no
qemu-system-riscv32 -nographic -machine virt -m 1536M -device loader,file=$DATA/emulator.bin,addr=0x80000000,cpu-num=0 -device loader,file=$DATA/rv32.dtb,addr=0xC3000000 -device loader,file=$DATA/vmlinux.bin,addr=0xC0000000 -device loader,file=$DATA/rootfs.cpio,addr=0xc2000000
program ../../../main/c/emulator/build/emulator.bin 0x80000000 verify
soc.loadBin(EMULATOR, 0x80000000);
soc.loadBin(VMLINUX, 0xC0000000);
soc.loadBin(DTB, 0xC3000000);
soc.loadBin(RAMDISK, 0xC2000000);
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=yes LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes
EMULATOR=../../../main/c/emulator/build/emulator.bin
VMLINUX=/home/miaou/pro/riscv/buildrootSpinal/output/images/Image
DTB=/home/miaou/pro/riscv/buildrootSpinal/board/spinal/vexriscv_sim/rv32.dtb
RAMDISK=/home/miaou/pro/riscv/buildrootSpinal/output/images/rootfs.cpio TRACE=no FLOW_INFO=no
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=yes LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes DEBUG_PLUGIN_EXTERNAL=yes
*/
@ -97,7 +126,7 @@ object LinuxGen {
// resetVector = 0x80000000l,
// cmdForkOnSecondStage = false,
// cmdForkPersistence = false,
// prediction = NONE,
// prediction = DYNAMIC_TARGET,
// historyRamSizeLog2 = 10,
// catchAccessFault = true,
// compressedGen = true,
@ -156,7 +185,8 @@ object LinuxGen {
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
withLrSc = true
withLrSc = true,
withAmo = true
// )
),
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
@ -264,7 +294,7 @@ object LinuxGen {
// }
// }
SpinalConfig(mergeAsyncProcess = true, anonymSignalPrefix = "zz").generateVerilog {
SpinalConfig(mergeAsyncProcess = true, anonymSignalPrefix = "_zz").generateVerilog {
val toplevel = new VexRiscv(configFull(
@ -359,13 +389,13 @@ object LinuxSyntesisBench extends App{
val withoutMmu = new Rtl {
override def getName(): String = "VexRiscv Without Mmu"
override def getRtlPath(): String = "VexRiscvWithoutMmu.v"
SpinalVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = false)).setDefinitionName(getRtlPath().split("\\.").head))
SpinalConfig(inlineRom=true).generateVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = false)).setDefinitionName(getRtlPath().split("\\.").head))
}
val withMmu = new Rtl {
override def getName(): String = "VexRiscv With Mmu"
override def getRtlPath(): String = "VexRiscvWithMmu.v"
SpinalVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = true)).setDefinitionName(getRtlPath().split("\\.").head))
SpinalConfig(inlineRom=true).generateVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = true)).setDefinitionName(getRtlPath().split("\\.").head))
}
val rtls = List(withoutMmu, withMmu)

View file

@ -86,7 +86,6 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
val wr = Bool
val data = Bits(p.cpuDataWidth bit)
val size = UInt(2 bits)
val forceUncachedAccess = Bool()
val isLrsc = p.withLrSc generate Bool()
val isAmo = p.withAmo generate Bool()
val amoCtrl = p.withAmo generate new Bundle {
@ -99,11 +98,13 @@ case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSl
val isValid = Bool
val isStuck = Bool
val isRemoved = Bool
val isWrite = Bool
val address = UInt(p.addressWidth bit)
val mmuBus = MemoryTranslatorBus()
override def asMaster(): Unit = {
out(isValid, isStuck, isRemoved, address)
in(isWrite)
slave(mmuBus)
}
}
@ -414,6 +415,7 @@ class DataCache(p : DataCacheConfig) extends Component{
io.cpu.memory.mmuBus.cmd.virtualAddress := io.cpu.memory.address
io.cpu.memory.mmuBus.cmd.bypassTranslation := False
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
io.cpu.memory.isWrite := request.wr
val wayHits = earlyWaysHits generate ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid))
val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp))
@ -516,7 +518,7 @@ class DataCache(p : DataCacheConfig) extends Component{
io.mem.cmd.data := requestDataBypass
when(io.cpu.writeBack.isValid) {
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
when(mmuRsp.isIoAccess) {
io.cpu.writeBack.haltIt.clearWhen(request.wr ? io.mem.cmd.ready | io.mem.rsp.valid)
io.mem.cmd.valid := !memCmdSent
@ -576,7 +578,7 @@ class DataCache(p : DataCacheConfig) extends Component{
}
}
when(request.forceUncachedAccess || mmuRsp.isIoAccess){
when(mmuRsp.isIoAccess){
io.cpu.writeBack.data := io.mem.rsp.data
if(catchAccessError) io.cpu.writeBack.accessError := io.mem.rsp.valid && io.mem.rsp.error
} otherwise {

View file

@ -291,6 +291,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
var jumpInterface : Flow[UInt] = null
var timerInterrupt, externalInterrupt, softwareInterrupt : Bool = null
var externalInterruptS : Bool = null
var forceMachineWire : Bool = null
var privilege : UInt = null
var selfException : Flow[ExceptionCause] = null
var contextSwitching : Bool = null
@ -387,7 +388,8 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
}
contextSwitching = Bool().setName("contextSwitching")
privilege = RegInit(U"11").setName("CsrPlugin_privilege")
privilege = UInt(2 bits).setName("CsrPlugin_privilege")
forceMachineWire = False
if(catchIllegalAccess || ecallGen || ebreakGen)
selfException = newExceptionPort(pipeline.execute)
@ -407,6 +409,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
override def isUser() : Bool = privilege === 0
override def isSupervisor(): Bool = privilege === 1
override def isMachine(): Bool = privilege === 3
override def forceMachine(): Unit = forceMachineWire := True
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
@ -431,6 +434,10 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
val base = UInt(xlen-2 bits)
}
val privilegeReg = RegInit(U"11")
privilege := privilegeReg
when(forceMachineWire) { privilege := 3 }
val machineCsr = pipeline plug new Area{
//Define CSR registers
// Status => MXR, SUM, TVM, TW, TSE ?
@ -752,7 +759,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") )
beforeLastStage.arbitration.flushAll := True
privilege := targetPrivilege
privilegeReg := targetPrivilege
switch(targetPrivilege){
if(supervisorGen) is(1) {
@ -795,14 +802,14 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
mstatus.MPP := U"00"
mstatus.MIE := mstatus.MPIE
mstatus.MPIE := True
privilege := mstatus.MPP
privilegeReg := mstatus.MPP
jumpInterface.payload := mepc
}
if(supervisorGen) is(1){
sstatus.SPP := U"0"
sstatus.SIE := sstatus.SPIE
sstatus.SPIE := True
privilege := U"0" @@ sstatus.SPP
privilegeReg := U"0" @@ sstatus.SPP
jumpInterface.payload := sepc
}
}

View file

@ -150,6 +150,8 @@ class DBusCachedPlugin(config : DataCacheConfig,
if(pipeline.serviceExist(classOf[PrivilegeService]))
privilegeService = pipeline.service(classOf[PrivilegeService])
pipeline.update(DEBUG_BYPASS_CACHE, False)
}
override def build(pipeline: VexRiscv): Unit = {
@ -187,7 +189,6 @@ class DBusCachedPlugin(config : DataCacheConfig,
default -> input(RS2)(31 downto 0)
)
cache.io.cpu.execute.args.size := size
cache.io.cpu.execute.args.forceUncachedAccess := False
cache.io.cpu.flush.valid := arbitration.isValid && input(MEMORY_MANAGMENT)
@ -221,6 +222,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
cache.io.cpu.memory.address := U(input(REGFILE_WRITE_DATA))
cache.io.cpu.memory.mmuBus <> mmuBus
cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite)
}
writeBack plug new Area{
@ -298,7 +300,6 @@ class DBusCachedPlugin(config : DataCacheConfig,
cache.io.cpu.execute.args.wr := dBusAccess.cmd.write
cache.io.cpu.execute.args.data := dBusAccess.cmd.data
cache.io.cpu.execute.args.size := dBusAccess.cmd.size
cache.io.cpu.execute.args.forceUncachedAccess := False
if(withLrSc) cache.io.cpu.execute.args.isLrsc := False
if(withAmo) cache.io.cpu.execute.args.isAmo := False
cache.io.cpu.execute.address := dBusAccess.cmd.address //Will only be 12 muxes

View file

@ -141,8 +141,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
val haltIt = RegInit(False)
val stepIt = RegInit(False)
val isPipActive = RegNext(stages.map(_.arbitration.isValid).orR)
val isPipBusy = isPipActive || RegNext(isPipActive)
val isPipBusy = RegNext(stages.map(_.arbitration.isValid).orR || iBusFetcher.incoming())
val godmode = RegInit(False) setWhen(haltIt && !isPipBusy)
val haltedByBreak = RegInit(False)
val hardwareBreakpoints = Vec(Reg(new Bundle{
@ -176,6 +176,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
resetIt setWhen (io.bus.cmd.data(16)) clearWhen (io.bus.cmd.data(24))
haltIt setWhen (io.bus.cmd.data(17)) clearWhen (io.bus.cmd.data(25))
haltedByBreak clearWhen (io.bus.cmd.data(25))
godmode clearWhen(io.bus.cmd.data(25))
}
}
is(0x1) {
@ -219,10 +220,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
}
}
when(stepIt && Cat(pipeline.stages.map(_.arbitration.redoIt)).asBits.orR) {
haltIt := False
}
//Avoid having two C instruction executed in a single step
if(pipeline(RVC_GEN)){
val cleanStep = RegNext(stepIt && decode.arbitration.isFiring) init(False)
@ -236,10 +233,17 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
service(classOf[InterruptionInhibitor]).inhibateInterrupts()
}
}
if(serviceExist(classOf[ExceptionInhibitor])) {
when(haltIt) {
service(classOf[ExceptionInhibitor]).inhibateException()
when(godmode) {
pipeline.plugins.foreach{
case p : ExceptionInhibitor => p.inhibateException()
case _ =>
}
pipeline.plugins.foreach{
case p : PrivilegeService => p.forceMachine()
case _ =>
}
if(pipeline.things.contains(DEBUG_BYPASS_CACHE)) pipeline(DEBUG_BYPASS_CACHE) := True
}
}}
}

View file

@ -3489,18 +3489,24 @@ int main(int argc, char **argv, char **env) {
// }
#ifdef LINUX_SOC
LinuxSoc("linux")
.withRiscvRef()
->loadBin(EMULATOR, 0x80000000)
->loadBin(VMLINUX, 0xC0000000)
->loadBin(DTB, 0xC3000000)
->loadBin(RAMDISK, 0xC2000000)
->setIStall(true) //TODO It currently improve speed but should be removed later
->setDStall(true)
->bootAt(0x80000000)
->run(0);
// ->run((496300000l + 2000000) / 2);
// ->run(438700000l/2);
{
LinuxSoc soc("linux");
#ifndef DEBUG_PLUGIN_EXTERNAL
soc.withRiscvRef();
soc.loadBin(EMULATOR, 0x80000000);
soc.loadBin(VMLINUX, 0xC0000000);
soc.loadBin(DTB, 0xC3000000);
soc.loadBin(RAMDISK, 0xC2000000);
#endif
soc.setIStall(true); //TODO It currently improve speed but should be removed later
soc.setDStall(true);
soc.bootAt(0x80000000);
soc.run(0);
// soc.run((496300000l + 2000000) / 2);
// soc.run(438700000l/2);
return -1;
}
#endif
// #ifdef MMU