From d7f6c18c0ab5513ce3ee2c0a6f92e8d89ca6addd Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Wed, 10 Apr 2019 00:35:15 +0200 Subject: [PATCH] Fix DebugPlugin -> force machine mode, force uncached memory load --- src/main/scala/vexriscv/Pipeline.scala | 6 +-- src/main/scala/vexriscv/Services.scala | 3 ++ src/main/scala/vexriscv/Stage.scala | 1 - src/main/scala/vexriscv/VexRiscv.scala | 1 + src/main/scala/vexriscv/demo/Linux.scala | 44 ++++++++++++++++--- src/main/scala/vexriscv/ip/DataCache.scala | 8 ++-- .../scala/vexriscv/plugin/CsrPlugin.scala | 15 +++++-- .../vexriscv/plugin/DBusCachedPlugin.scala | 5 ++- .../scala/vexriscv/plugin/DebugPlugin.scala | 22 ++++++---- src/test/cpp/regression/main.cpp | 30 ++++++++----- 10 files changed, 94 insertions(+), 41 deletions(-) diff --git a/src/main/scala/vexriscv/Pipeline.scala b/src/main/scala/vexriscv/Pipeline.scala index cde5ae8..14fe071 100644 --- a/src/main/scala/vexriscv/Pipeline.scala +++ b/src/main/scala/vexriscv/Pipeline.scala @@ -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]) diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index 0e04127..26ecf84 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -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 } diff --git a/src/main/scala/vexriscv/Stage.scala b/src/main/scala/vexriscv/Stage.scala index 504b0d3..e293f49 100644 --- a/src/main/scala/vexriscv/Stage.scala +++ b/src/main/scala/vexriscv/Stage.scala @@ -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 diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index c0da1d4..be5505f 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -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)) diff --git a/src/main/scala/vexriscv/demo/Linux.scala b/src/main/scala/vexriscv/demo/Linux.scala index 31e9198..09ed514 100644 --- a/src/main/scala/vexriscv/demo/Linux.scala +++ b/src/main/scala/vexriscv/demo/Linux.scala @@ -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) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 5726cdd..04c84be 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -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 { diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 377b95b..751106a 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -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 } } diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 8b8d807..b48386c 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -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 diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 4915eea..454d352 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -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 } }} } diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index 8e1c146..78f15a3 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -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