#60 Got instruction cache running linux :D
This commit is contained in:
parent
1dff9aff8a
commit
bc0af02c97
|
@ -56,7 +56,6 @@ object TestsWorkspace {
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -65,7 +65,6 @@ object BrieyConfig{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -23,7 +23,6 @@ object GenFull extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -27,7 +27,6 @@ object GenFullNoMmu extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -28,7 +28,6 @@ object GenFullNoMmuMaxPerf extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = false,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -26,7 +26,6 @@ object GenSmallAndProductiveICache extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = false,
|
||||
catchAccessFault = false,
|
||||
catchMemoryTranslationMiss = false,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -40,13 +40,13 @@ cd VexRiscv
|
|||
Run regressions =>
|
||||
sbt "runMain vexriscv.demo.LinuxGen -r"
|
||||
cd src/test/cpp/regression
|
||||
make run DBUS=SIMPLE IBUS=SIMPLE DHRYSTONE=yes SUPERVISOR=yes CSR=yes COMPRESSED=yes REDO=10 TRACE=no
|
||||
make run IBUS=CACHED DBUS=SIMPLE DEBUG_PLUGIN=no DHRYSTONE=yes SUPERVISOR=yes CSR=yes COMPRESSED=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 DBUS=SIMPLE IBUS=SIMPLE 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=SIMPLE DEBUG_PLUGIN=no 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
|
||||
|
||||
Run linux with QEMU (Require the machime mode emulator compiled in QEMU mode)
|
||||
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
|
||||
|
@ -94,43 +94,46 @@ object LinuxGen {
|
|||
val config = VexRiscvConfig(
|
||||
plugins = List(
|
||||
new DummyFencePlugin(), //TODO should be removed for design with caches
|
||||
new IBusSimplePlugin(
|
||||
|
||||
//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(
|
||||
resetVector = 0x80000000l,
|
||||
cmdForkOnSecondStage = false,
|
||||
cmdForkPersistence = false,
|
||||
prediction = NONE,
|
||||
historyRamSizeLog2 = 10,
|
||||
catchAccessFault = true,
|
||||
compressedGen = true,
|
||||
busLatencyMin = 1,
|
||||
prediction = NONE,
|
||||
injectorStage = true,
|
||||
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
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
|
||||
)
|
||||
),
|
||||
// new IBusCachedPlugin(
|
||||
// resetVector = 0x80000000l,
|
||||
// compressedGen = false,
|
||||
// prediction = NONE,
|
||||
// injectorStage = true,
|
||||
// config = InstructionCacheConfig(
|
||||
// cacheSize = 4096,
|
||||
// bytePerLine = 32,
|
||||
// wayCount = 1,
|
||||
// addressWidth = 32,
|
||||
// cpuDataWidth = 32,
|
||||
// memDataWidth = 32,
|
||||
// catchIllegalAccess = true,
|
||||
// catchAccessFault = true,
|
||||
// catchMemoryTranslationMiss = true,
|
||||
// asyncTagMemory = false,
|
||||
// twoCycleRam = false,
|
||||
// twoCycleCache = true
|
||||
// ),
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
// portTlbSize = 4
|
||||
// )
|
||||
// ),
|
||||
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = true,
|
||||
|
@ -225,7 +228,7 @@ object LinuxGen {
|
|||
// wfiGenAsNop = true,
|
||||
// ucycleAccess = CsrAccess.NONE
|
||||
// )),
|
||||
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
|
||||
// new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
|
||||
new BranchPlugin(
|
||||
earlyBranch = true,
|
||||
catchAddressMisaligned = true,
|
||||
|
|
|
@ -48,7 +48,6 @@ object VexRiscvAvalonForSim{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true
|
||||
)
|
||||
|
|
|
@ -44,7 +44,6 @@ object VexRiscvAvalonWithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -45,7 +45,6 @@ object VexRiscvAxi4WithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
|
|
@ -44,7 +44,6 @@ object VexRiscvCachedWishboneForSim{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true
|
||||
)
|
||||
|
|
|
@ -17,7 +17,6 @@ case class InstructionCacheConfig( cacheSize : Int,
|
|||
memDataWidth : Int,
|
||||
catchIllegalAccess : Boolean,
|
||||
catchAccessFault : Boolean,
|
||||
catchMemoryTranslationMiss : Boolean,
|
||||
asyncTagMemory : Boolean,
|
||||
twoCycleCache : Boolean = true,
|
||||
twoCycleRam : Boolean = false,
|
||||
|
@ -26,7 +25,7 @@ case class InstructionCacheConfig( cacheSize : Int,
|
|||
assert(!(twoCycleRam && !twoCycleCache))
|
||||
|
||||
def burstSize = bytePerLine*8/memDataWidth
|
||||
def catchSomething = catchAccessFault || catchMemoryTranslationMiss || catchIllegalAccess
|
||||
def catchSomething = catchAccessFault || catchIllegalAccess
|
||||
|
||||
def getAxi4Config() = Axi4Config(
|
||||
addressWidth = addressWidth,
|
||||
|
@ -86,7 +85,7 @@ trait InstructionCacheCommons{
|
|||
val pc : UInt
|
||||
val physicalAddress : UInt
|
||||
val data : Bits
|
||||
val cacheMiss, error, mmuMiss, illegalAccess, isUser : Bool
|
||||
val cacheMiss, error, mmuRefilling, mmuException, isUser : Bool
|
||||
}
|
||||
|
||||
case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons {
|
||||
|
@ -99,11 +98,11 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
|
|||
val dataBypass = Bits(p.cpuDataWidth bits)
|
||||
val mmuBus = MemoryTranslatorBus()
|
||||
val physicalAddress = UInt(p.addressWidth bits)
|
||||
val cacheMiss, error, mmuMiss, illegalAccess,isUser = ifGen(!p.twoCycleCache)(Bool)
|
||||
val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(!p.twoCycleCache)(Bool)
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, isRemoved, pc)
|
||||
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss,physicalAddress)
|
||||
inWithNull(error,mmuRefilling,mmuException,data, cacheMiss,physicalAddress)
|
||||
outWithNull(isUser, dataBypass, dataBypassValid)
|
||||
slaveWithNull(mmuBus)
|
||||
}
|
||||
|
@ -116,12 +115,12 @@ case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle
|
|||
val pc = UInt(p.addressWidth bits)
|
||||
val physicalAddress = UInt(p.addressWidth bits)
|
||||
val data = Bits(p.cpuDataWidth bits)
|
||||
val cacheMiss, error, mmuMiss, illegalAccess, isUser = ifGen(p.twoCycleCache)(Bool)
|
||||
val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(p.twoCycleCache)(Bool)
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, pc)
|
||||
outWithNull(isUser)
|
||||
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss, physicalAddress)
|
||||
inWithNull(error, mmuRefilling, mmuException,data, cacheMiss, physicalAddress)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,8 +410,8 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
|
||||
io.cpu.fetch.cacheMiss := !hit.valid
|
||||
io.cpu.fetch.error := hit.error
|
||||
io.cpu.fetch.mmuMiss := ??? //TODO mmuRsp.miss
|
||||
io.cpu.fetch.illegalAccess := !mmuRsp.allowExecute || (io.cpu.fetch.isUser && !mmuRsp.allowUser)
|
||||
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 ?
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -441,8 +440,8 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
|
||||
io.cpu.decode.cacheMiss := !hit.valid
|
||||
io.cpu.decode.error := hit.error
|
||||
io.cpu.decode.mmuMiss := ??? //TODO mmuRsp.miss
|
||||
io.cpu.decode.illegalAccess := !mmuRsp.allowExecute || (io.cpu.decode.isUser && !mmuRsp.allowUser)
|
||||
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.physicalAddress := mmuRsp.physicalAddress
|
||||
})
|
||||
}
|
||||
|
|
|
@ -807,7 +807,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
import lastStage._
|
||||
|
||||
//Manage MRET / SRET instructions
|
||||
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
||||
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { //TODO do not allow user mode already implemented somewhere else ?
|
||||
fetcher.haltIt()
|
||||
jumpInterface.valid := True
|
||||
beforeLastStage.arbitration.flushAll := True
|
||||
|
|
|
@ -74,11 +74,11 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
|
||||
super.setup(pipeline)
|
||||
|
||||
def MANAGEMENT = M"-----------------100-----0001111"
|
||||
//def MANAGEMENT = M"-----------------100-----0001111"
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.addDefault(FLUSH_ALL, False)
|
||||
decoderService.add(MANAGEMENT, List(
|
||||
decoderService.add(FENCE_I, List(
|
||||
FLUSH_ALL -> True
|
||||
))
|
||||
|
||||
|
@ -101,7 +101,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
val e = new BusReport()
|
||||
val c = new CacheReport()
|
||||
e.kind = "cached"
|
||||
e.flushInstructions.add(0x400F) //invalid instruction cache
|
||||
e.flushInstructions.add(0x100F) //FENCE.I
|
||||
e.flushInstructions.add(0x13)
|
||||
e.flushInstructions.add(0x13)
|
||||
e.flushInstructions.add(0x13)
|
||||
|
@ -187,7 +187,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
val cacheRspArbitration = stages(if (twoCycleCache) 2 else 1)
|
||||
var issueDetected = False
|
||||
val redoFetch = False //RegNext(False) init(False)
|
||||
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected) {
|
||||
when(cacheRsp.isValid && (cacheRsp.cacheMiss || cacheRsp.mmuRefilling) && !issueDetected) {
|
||||
issueDetected \= True
|
||||
redoFetch := iBusRsp.readyForError
|
||||
}
|
||||
|
@ -201,19 +201,25 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
|
||||
|
||||
if (catchSomething) {
|
||||
val accessFault = if (catchAccessFault) cacheRsp.error else False
|
||||
val mmuMiss = if (catchMemoryTranslationMiss) cacheRsp.mmuMiss else False
|
||||
val illegalAccess = if (catchIllegalAccess) cacheRsp.illegalAccess else False
|
||||
|
||||
decodeExceptionPort.valid := False
|
||||
decodeExceptionPort.code := mmuMiss ? U(14) | 1
|
||||
decodeExceptionPort.code.assignDontCare()
|
||||
decodeExceptionPort.badAddr := cacheRsp.pc
|
||||
when(cacheRsp.isValid && (accessFault || mmuMiss || illegalAccess) && !issueDetected) {
|
||||
|
||||
if(catchIllegalAccess) when(cacheRsp.isValid && cacheRsp.mmuException && !issueDetected) {
|
||||
issueDetected \= True
|
||||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
decodeExceptionPort.code := 12
|
||||
}
|
||||
|
||||
if(catchAccessFault) when(cacheRsp.isValid && cacheRsp.error && !issueDetected) {
|
||||
issueDetected \= True
|
||||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
decodeExceptionPort.code := 1
|
||||
}
|
||||
}
|
||||
|
||||
decodeExceptionPort.valid clearWhen(fetcherHalt)
|
||||
|
||||
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
|
||||
iBusRsp.output.valid := cacheRspArbitration.output.valid
|
||||
cacheRspArbitration.output.ready := iBusRsp.output.ready
|
||||
|
@ -223,7 +229,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
|
||||
if (mmuBus != null) {
|
||||
cache.io.cpu.fetch.mmuBus <> mmuBus
|
||||
(if (twoCycleCache) stages(1).halt else rsp.iBusRspOutputHalt) setWhen (mmuBus.cmd.isValid && ???) //TODO !mmuBus.rsp.hit && !mmuBus.rsp.miss
|
||||
} else {
|
||||
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
|
||||
|
@ -231,9 +236,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowUser := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False
|
||||
??? //TODO
|
||||
// cache.io.cpu.fetch.mmuBus.rsp.miss := False
|
||||
// cache.io.cpu.fetch.mmuBus.rsp.hit := False
|
||||
cache.io.cpu.fetch.mmuBus.rsp.exception := False
|
||||
cache.io.cpu.fetch.mmuBus.rsp.refilling := False
|
||||
}
|
||||
|
||||
val flushStage = if(memory != null) memory else execute
|
||||
|
|
|
@ -232,6 +232,7 @@ class success : public std::exception { };
|
|||
class RiscvGolden {
|
||||
public:
|
||||
int32_t pc, lastPc;
|
||||
uint32_t lastInstruction;
|
||||
int32_t regs[32];
|
||||
|
||||
uint32_t mscratch, sscratch;
|
||||
|
@ -706,6 +707,7 @@ public:
|
|||
return;
|
||||
}
|
||||
}
|
||||
lastInstruction = i;
|
||||
currentInstruction = i;
|
||||
if ((i & 0x3) == 0x3) {
|
||||
//32 bit
|
||||
|
@ -1584,7 +1586,11 @@ public:
|
|||
staticMutex.unlock();
|
||||
} catch (const std::exception& e) {
|
||||
staticMutex.lock();
|
||||
cout << "FAIL " << name << " at PC=" << hex << setw(8) << top->VexRiscv->writeBack_PC << dec << endl; //<< " seed : " << seed <<
|
||||
|
||||
cout << "FAIL " << name << " at PC=" << hex << setw(8) << top->VexRiscv->writeBack_PC << dec; //<< " seed : " << seed <<
|
||||
if(riscvRefEnable) cout << hex << " REF PC=" << riscvRef.lastPc << " REF I=" << riscvRef.lastInstruction << dec;
|
||||
cout << endl;
|
||||
|
||||
cycles += instanceCycles;
|
||||
staticMutex.unlock();
|
||||
failed = true;
|
||||
|
|
|
@ -27,7 +27,7 @@ REDO?=10
|
|||
REF=no
|
||||
TRACE_WITH_TIME=no
|
||||
REF_TIME=no
|
||||
THREAD_COUNT?=4
|
||||
THREAD_COUNT?=$(shell nproc)
|
||||
MTIME_INSTR_FACTOR?=no
|
||||
COMPRESSED?=no
|
||||
SUPERVISOR?=no
|
||||
|
|
|
@ -315,7 +315,6 @@ class IBusDimension extends VexRiscvDimension("IBus") {
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = catchAll,
|
||||
catchAccessFault = catchAll,
|
||||
catchMemoryTranslationMiss = catchAll,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = twoCycleRam,
|
||||
twoCycleCache = twoCycleCache
|
||||
|
|
Loading…
Reference in New Issue