#60 Got the new data cache design passing all tests and running linux
This commit is contained in:
parent
fd4da77084
commit
8be40e637b
|
@ -33,6 +33,7 @@ case class ExceptionCause() extends Bundle{
|
|||
|
||||
trait ExceptionService{
|
||||
def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause]
|
||||
def isExceptionPending() : Bool
|
||||
}
|
||||
|
||||
trait PrivilegeService{
|
||||
|
|
|
@ -96,45 +96,45 @@ object LinuxGen {
|
|||
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,
|
||||
cmdForkOnSecondStage = false,
|
||||
cmdForkPersistence = false,
|
||||
prediction = NONE,
|
||||
historyRamSizeLog2 = 10,
|
||||
catchAccessFault = true,
|
||||
compressedGen = true,
|
||||
busLatencyMin = 1,
|
||||
injectorStage = true,
|
||||
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
|
||||
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
|
||||
// new IBusCachedPlugin(
|
||||
// new IBusSimplePlugin(
|
||||
// resetVector = 0x80000000l,
|
||||
// compressedGen = true,
|
||||
// cmdForkOnSecondStage = false,
|
||||
// cmdForkPersistence = false,
|
||||
// prediction = NONE,
|
||||
// injectorStage = true,
|
||||
// config = InstructionCacheConfig(
|
||||
// cacheSize = 4096,
|
||||
// bytePerLine = 32,
|
||||
// wayCount = 1,
|
||||
// addressWidth = 32,
|
||||
// cpuDataWidth = 32,
|
||||
// memDataWidth = 32,
|
||||
// catchIllegalAccess = true,
|
||||
// historyRamSizeLog2 = 10,
|
||||
// catchAccessFault = true,
|
||||
// asyncTagMemory = false,
|
||||
// twoCycleRam = false,
|
||||
// twoCycleCache = true
|
||||
// )
|
||||
// ),
|
||||
// memoryTranslatorPortConfig = MmuPortConfig(
|
||||
// compressedGen = true,
|
||||
// busLatencyMin = 1,
|
||||
// injectorStage = true,
|
||||
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
// portTlbSize = 4
|
||||
// )
|
||||
// ),
|
||||
|
||||
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
|
||||
new IBusCachedPlugin(
|
||||
resetVector = 0x80000000l,
|
||||
compressedGen = true,
|
||||
prediction = NONE,
|
||||
injectorStage = true,
|
||||
config = InstructionCacheConfig(
|
||||
cacheSize = 4096,
|
||||
bytePerLine = 32,
|
||||
wayCount = 1,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
twoCycleCache = true
|
||||
// )
|
||||
),
|
||||
memoryTranslatorPortConfig = MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
|
||||
// new DBusSimplePlugin(
|
||||
// catchAddressMisaligned = true,
|
||||
|
@ -156,17 +156,16 @@ object LinuxGen {
|
|||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
atomicEntriesCount = 2
|
||||
)
|
||||
// ),
|
||||
// memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MmuPortConfig(
|
||||
// portTlbSize = 4
|
||||
atomicEntriesCount = 1
|
||||
// )
|
||||
),
|
||||
new StaticMemoryTranslatorPlugin(
|
||||
ioRange = _(31 downto 28) === 0xF
|
||||
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
// new StaticMemoryTranslatorPlugin(
|
||||
// ioRange = _(31 downto 28) === 0xF
|
||||
// ),
|
||||
// new MemoryTranslatorPlugin(
|
||||
// tlbSize = 32,
|
||||
// virtualRange = _(31 downto 28) === 0xC,
|
||||
|
@ -238,12 +237,12 @@ object LinuxGen {
|
|||
new YamlPlugin("cpu0.yaml")
|
||||
)
|
||||
)
|
||||
// if(withMmu) config.plugins += new MmuPlugin(
|
||||
// virtualRange = a => True,
|
||||
// // virtualRange = x => x(31 downto 24) =/= 0x81, //TODO It fix the DTB kernel access (workaround)
|
||||
// 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
|
||||
// )
|
||||
if(withMmu) config.plugins += new MmuPlugin(
|
||||
virtualRange = a => True,
|
||||
// virtualRange = x => x(31 downto 24) =/= 0x81, //TODO It fix the DTB kernel access (workaround)
|
||||
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
|
||||
)
|
||||
config
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ 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,
|
||||
wayCount : Int,
|
||||
|
@ -71,13 +73,12 @@ object DataCacheCpuExecute{
|
|||
|
||||
case class DataCacheCpuExecute(p : DataCacheConfig) extends Bundle with IMasterSlave{
|
||||
val isValid = Bool
|
||||
val isStuck = Bool
|
||||
val address = UInt(p.addressWidth bit)
|
||||
// val haltIt = Bool
|
||||
val args = DataCacheCpuExecuteArgs(p)
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, args, address)
|
||||
out(isValid, args, address)
|
||||
// in(haltIt)
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +112,7 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
|
|||
val isStuck = Bool
|
||||
val isUser = Bool
|
||||
val haltIt = Bool
|
||||
val isWrite = Bool
|
||||
val data = Bits(p.cpuDataWidth bit)
|
||||
val address = UInt(p.addressWidth bit)
|
||||
val mmuException, unalignedAccess , accessError = Bool
|
||||
|
@ -120,7 +122,7 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
|
|||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid,isStuck,isUser, address)
|
||||
in(haltIt, data, mmuException, unalignedAccess, accessError)
|
||||
in(haltIt, data, mmuException, unalignedAccess, accessError, isWrite)
|
||||
outWithNull(clearAtomicEntries)
|
||||
}
|
||||
}
|
||||
|
@ -354,8 +356,8 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
val data = Mem(Bits(wordWidth bit), wayWordCount)
|
||||
|
||||
//Reads
|
||||
val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.execute.isStuck)
|
||||
val dataReadRsp = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.execute.isStuck)
|
||||
val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.memory.isStuck)
|
||||
val dataReadRsp = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.memory.isStuck)
|
||||
|
||||
//Writes
|
||||
when(tagsWriteCmd.valid && tagsWriteCmd.way(i)){
|
||||
|
@ -380,7 +382,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
dataWriteCmd.valid := False
|
||||
dataWriteCmd.payload.assignDontCare()
|
||||
|
||||
when(io.cpu.execute.isValid && !io.cpu.execute.isStuck){
|
||||
when(io.cpu.execute.isValid && !io.cpu.memory.isStuck){
|
||||
tagsReadCmd.valid := True
|
||||
dataReadCmd.valid := True
|
||||
tagsReadCmd.payload := io.cpu.execute.address(lineRange)
|
||||
|
@ -460,7 +462,6 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
val atomic = genAtomic generate new Area{
|
||||
case class AtomicEntry() extends Bundle{
|
||||
val valid = Bool()
|
||||
val size = UInt(2 bits)
|
||||
val address = UInt(addressWidth bits)
|
||||
|
||||
def init: this.type ={
|
||||
|
@ -470,10 +471,9 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
}
|
||||
val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount)
|
||||
val entriesAllocCounter = Counter(atomicEntriesCount)
|
||||
val entriesHit = entries.map(e => e.valid && e.size === request.size && e.address === io.cpu.writeBack.address).orR
|
||||
val entriesHit = entries.map(e => e.valid && e.address === io.cpu.writeBack.address).orR
|
||||
when(io.cpu.writeBack.isValid && request.isAtomic && !request.wr){
|
||||
entries(entriesAllocCounter).valid := True
|
||||
entries(entriesAllocCounter).size := request.size //TODO remove size stuff
|
||||
entries(entriesAllocCounter).address := io.cpu.writeBack.address
|
||||
when(!io.cpu.writeBack.isStuck){
|
||||
entriesAllocCounter.increment()
|
||||
|
@ -486,11 +486,11 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
val memCmdSent = RegInit(False) setWhen (io.mem.cmd.ready) clearWhen (!io.cpu.writeBack.isStuck)
|
||||
|
||||
io.cpu.redo := mmuRsp.refilling
|
||||
io.cpu.redo := False
|
||||
io.cpu.writeBack.accessError := False
|
||||
io.cpu.writeBack.mmuException := io.cpu.writeBack.isValid && (if(catchIllegal) mmuRsp.exception || (!mmuRsp.allowWrite && request.wr) || (!mmuRsp.allowRead && !request.wr) || (!mmuRsp.allowUser && io.cpu.writeBack.isUser) else False)
|
||||
io.cpu.writeBack.unalignedAccess := io.cpu.writeBack.isValid && (if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False)
|
||||
|
||||
io.cpu.writeBack.isWrite := request.wr
|
||||
|
||||
when(io.cpu.writeBack.isValid) {
|
||||
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
|
||||
|
@ -503,6 +503,11 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
io.mem.cmd.data := request.data
|
||||
io.mem.cmd.length := 0
|
||||
io.mem.cmd.last := True
|
||||
|
||||
if(genAtomic) when(request.isAtomic && !atomic.entriesHit){
|
||||
io.mem.cmd.valid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
} otherwise {
|
||||
when(waysHit || request.wr) { //Do not require a cache refill ?
|
||||
//Data cache update
|
||||
|
@ -524,6 +529,12 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
//On write to read colisions
|
||||
io.cpu.redo := !request.wr && (colisions & waysHits) =/= 0
|
||||
|
||||
if(genAtomic) when(request.isAtomic && !atomic.entriesHit){
|
||||
io.mem.cmd.valid := False
|
||||
dataWriteCmd.valid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
} otherwise { //Do refill
|
||||
|
||||
//Emit cmd
|
||||
|
@ -554,6 +565,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
loaderValid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
io.cpu.redo setWhen(io.cpu.writeBack.isValid && mmuRsp.refilling)
|
||||
|
||||
assert(!(io.cpu.writeBack.isValid && !io.cpu.writeBack.haltIt && io.cpu.writeBack.isStuck), "writeBack stuck by another plugin is not allowed")
|
||||
|
||||
|
@ -561,9 +573,6 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
when(request.isAtomic && request.wr){
|
||||
io.cpu.writeBack.data := (!atomic.entriesHit).asBits.resized
|
||||
}
|
||||
when(request.isAtomic && !atomic.entriesHit){
|
||||
io.mem.cmd.mask := 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -285,6 +285,9 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
interface
|
||||
}
|
||||
|
||||
var exceptionPending : Bool = null
|
||||
override def isExceptionPending(): Bool = exceptionPending
|
||||
|
||||
var jumpInterface : Flow[UInt] = null
|
||||
var timerInterrupt, externalInterrupt, softwareInterrupt : Bool = null
|
||||
var externalInterruptS : Bool = null
|
||||
|
@ -378,7 +381,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
jumpInterface.valid := False
|
||||
jumpInterface.payload.assignDontCare()
|
||||
|
||||
|
||||
exceptionPending = False
|
||||
timerInterrupt = in Bool() setName("timerInterrupt")
|
||||
externalInterrupt = in Bool() setName("externalInterrupt")
|
||||
softwareInterrupt = in Bool() setName("softwareInterrupt")
|
||||
|
@ -677,7 +680,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
else
|
||||
exceptionValidsRegs(stageId) := False
|
||||
}
|
||||
if(stage != stages.last) when(stage.arbitration.isFlushed){
|
||||
when(stage.arbitration.isFlushed){
|
||||
exceptionValids(stageId) := False
|
||||
}
|
||||
}
|
||||
|
@ -688,6 +691,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
//Avoid the PC register of the last stage to change durring an exception handleing (Used to fill Xepc)
|
||||
stages.last.dontSample.getOrElseUpdate(PC, ArrayBuffer[Bool]()) += exceptionValids.last
|
||||
exceptionPending setWhen(exceptionValidsRegs.orR)
|
||||
} else null
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
|
|||
|
||||
class DBusCachedPlugin(config : DataCacheConfig,
|
||||
memoryTranslatorPortConfig : Any = null,
|
||||
csrInfo : Boolean = false) extends Plugin[VexRiscv]{
|
||||
csrInfo : Boolean = false) extends Plugin[VexRiscv] with DBusAccessService {
|
||||
import config._
|
||||
var dBus : DataCacheMemBus = null
|
||||
var mmuBus : MemoryTranslatorBus = null
|
||||
|
@ -28,11 +28,19 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
var privilegeService : PrivilegeService = null
|
||||
var redoBranch : Flow[UInt] = null
|
||||
|
||||
@dontName var dBusAccess : DBusAccess = null
|
||||
override def newDBusAccess(): DBusAccess = {
|
||||
assert(dBusAccess == null)
|
||||
dBusAccess = DBusAccess()
|
||||
dBusAccess
|
||||
}
|
||||
|
||||
object MEMORY_ENABLE extends Stageable(Bool)
|
||||
object MEMORY_MANAGMENT extends Stageable(Bool)
|
||||
object MEMORY_WR extends Stageable(Bool)
|
||||
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
||||
object MEMORY_ATOMIC extends Stageable(Bool)
|
||||
object IS_DBUS_SHARING extends Stageable(Bool())
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
|
@ -44,8 +52,9 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
MEMORY_ENABLE -> True,
|
||||
RS1_USE -> True
|
||||
) ++ (if (catchSomething) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
|
||||
RS1_USE -> True,
|
||||
IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB
|
||||
)
|
||||
|
||||
val loadActions = stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
|
@ -143,7 +152,6 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
|
||||
val size = input(INSTRUCTION)(13 downto 12).asUInt
|
||||
cache.io.cpu.execute.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.execute.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.execute.address := input(SRC_ADD).asUInt
|
||||
cache.io.cpu.execute.args.wr := input(MEMORY_WR)
|
||||
cache.io.cpu.execute.args.data := size.mux(
|
||||
|
@ -194,7 +202,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
redoBranch.payload := input(PC)
|
||||
arbitration.flushAll setWhen(redoBranch.valid)
|
||||
|
||||
when(cache.io.cpu.writeBack.isValid) {
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE)) {
|
||||
if (catchAccessError) when(cache.io.cpu.writeBack.accessError) {
|
||||
exceptionBus.valid := True
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(7) | U(5)).resized
|
||||
|
@ -235,6 +243,45 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
}
|
||||
}
|
||||
|
||||
//Share access to the dBus (used by self refilled MMU)
|
||||
val dBusSharing = (dBusAccess != null) generate pipeline plug new Area{
|
||||
dBusAccess.cmd.ready := False
|
||||
val forceDatapath = False
|
||||
when(dBusAccess.cmd.valid){
|
||||
decode.arbitration.haltByOther := True
|
||||
when(!stagesFromExecute.map(_.arbitration.isValid).orR && !pipeline.service(classOf[ExceptionService]).isExceptionPending()){
|
||||
when(!cache.io.cpu.redo) {
|
||||
cache.io.cpu.execute.isValid := True
|
||||
dBusAccess.cmd.ready := !execute.arbitration.isStuck
|
||||
}
|
||||
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 := True //TODO Cached and redo management
|
||||
if(genAtomic) cache.io.cpu.execute.args.isAtomic := False
|
||||
cache.io.cpu.execute.address := dBusAccess.cmd.address //Will only be 12 muxes
|
||||
forceDatapath := True
|
||||
}
|
||||
}
|
||||
execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire
|
||||
|
||||
|
||||
mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING))
|
||||
cache.io.cpu.memory.isValid 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.writeBack.haltIt
|
||||
dBusAccess.rsp.data := cache.io.cpu.writeBack.data
|
||||
dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError
|
||||
|
||||
component.addPrePopTask{() =>
|
||||
when(forceDatapath){
|
||||
execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits
|
||||
}
|
||||
memory.input(IS_DBUS_SHARING) init(False)
|
||||
writeBack.input(IS_DBUS_SHARING) init(False)
|
||||
}
|
||||
}
|
||||
|
||||
if(csrInfo){
|
||||
val csr = service(classOf[CsrPlugin])
|
||||
csr.r(0xCC0, 0 -> U(cacheSize/wayCount), 20 -> U(bytePerLine))
|
||||
|
|
|
@ -21,6 +21,8 @@ class HaltOnExceptionPlugin() extends Plugin[VexRiscv] with ExceptionService {
|
|||
exceptionPortsInfos += ExceptionPortInfo(interface,stage,priority)
|
||||
interface
|
||||
}
|
||||
override def isExceptionPending(): Bool = False
|
||||
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
|
|
|
@ -1316,6 +1316,16 @@ public:
|
|||
if(isDBusCheckedRegion(addr)){
|
||||
CpuRef::MemWrite w;
|
||||
w.address = addr;
|
||||
while((mask & 1) == 0){
|
||||
mask >>= 1;
|
||||
w.address++;
|
||||
w.data >>= 8;
|
||||
}
|
||||
switch(mask){
|
||||
case 1: size = 0; break;
|
||||
case 3: size = min(1u, size); break;
|
||||
case 15: size = min(2u, size); break;
|
||||
}
|
||||
w.size = 1 << size;
|
||||
switch(size){
|
||||
case 0: w.data = *data & 0xFF; break;
|
||||
|
@ -3446,6 +3456,7 @@ int main(int argc, char **argv, char **env) {
|
|||
// redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
|
||||
// return 0;
|
||||
|
||||
redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
|
||||
|
||||
for(int idx = 0;idx < 1;idx++){
|
||||
|
||||
|
|
Loading…
Reference in New Issue