mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-04-24 05:57:07 -04:00
Merge branch 'linuxDev' into linux
This commit is contained in:
commit
ffafc27104
43 changed files with 1167 additions and 915 deletions
|
@ -21,7 +21,7 @@ trait Pipeline {
|
|||
|
||||
def service[T](clazz : Class[T]) = {
|
||||
val filtered = plugins.filter(o => clazz.isAssignableFrom(o.getClass))
|
||||
assert(filtered.length == 1)
|
||||
assert(filtered.length == 1, s"??? ${clazz.getName}")
|
||||
filtered.head.asInstanceOf[T]
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
@ -68,7 +69,7 @@ case class MemoryTranslatorCmd() extends Bundle{
|
|||
case class MemoryTranslatorRsp() extends Bundle{
|
||||
val physicalAddress = UInt(32 bits)
|
||||
val isIoAccess = Bool
|
||||
val allowRead, allowWrite, allowExecute, allowUser = Bool
|
||||
val allowRead, allowWrite, allowExecute = Bool
|
||||
val exception = Bool
|
||||
val refilling = Bool
|
||||
}
|
||||
|
|
|
@ -81,8 +81,7 @@ object TestsWorkspace {
|
|||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
atomicEntriesCount = 2
|
||||
withLrSc = true
|
||||
),
|
||||
// memoryTranslatorPortConfig = null
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -88,8 +88,7 @@ object BrieyConfig{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -27,7 +27,7 @@ object GenFull extends App{
|
|||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
),
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
memoryTranslatorPortConfig = MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
|
@ -41,15 +41,13 @@ object GenFull extends App{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
memoryTranslatorPortConfig = MmuPortConfig(
|
||||
portTlbSize = 6
|
||||
)
|
||||
),
|
||||
new MemoryTranslatorPlugin(
|
||||
tlbSize = 32,
|
||||
new MmuPlugin(
|
||||
virtualRange = _(31 downto 28) === 0xC,
|
||||
ioRange = _(31 downto 28) === 0xF
|
||||
),
|
||||
|
|
|
@ -42,8 +42,7 @@ object GenFullNoMmu extends App{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
)
|
||||
),
|
||||
new StaticMemoryTranslatorPlugin(
|
||||
|
|
|
@ -43,8 +43,7 @@ object GenFullNoMmuMaxPerf extends App{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = false
|
||||
catchUnaligned = true
|
||||
)
|
||||
),
|
||||
new StaticMemoryTranslatorPlugin(
|
||||
|
|
|
@ -40,13 +40,13 @@ cd VexRiscv
|
|||
Run regressions =>
|
||||
sbt "runMain vexriscv.demo.LinuxGen -r"
|
||||
cd src/test/cpp/regression
|
||||
make run IBUS=CACHED DBUS=SIMPLE DEBUG_PLUGIN=no 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 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=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
|
||||
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
|
||||
|
||||
Run linux with QEMU (Require the machime mode emulator compiled in QEMU mode)
|
||||
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
|
||||
|
@ -88,13 +88,10 @@ https://github.com/riscv/riscv-qemu/wiki#build-and-install
|
|||
*/
|
||||
|
||||
|
||||
//TODO have to check, look like supervisor can't get interrupt if the machine mod didn't delegated it, have to check exactly
|
||||
object LinuxGen {
|
||||
def configFull(litex : Boolean, withMmu : Boolean) = {
|
||||
val config = VexRiscvConfig(
|
||||
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
|
||||
// new IBusSimplePlugin(
|
||||
// resetVector = 0x80000000l,
|
||||
|
@ -118,7 +115,7 @@ object LinuxGen {
|
|||
prediction = NONE,
|
||||
injectorStage = true,
|
||||
config = InstructionCacheConfig(
|
||||
cacheSize = 4096,
|
||||
cacheSize = 4096*1,
|
||||
bytePerLine = 32,
|
||||
wayCount = 1,
|
||||
addressWidth = 32,
|
||||
|
@ -129,43 +126,44 @@ object LinuxGen {
|
|||
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,
|
||||
catchAccessFault = true,
|
||||
earlyInjection = false,
|
||||
atomicEntriesCount = 1,
|
||||
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
// new DBusCachedPlugin(
|
||||
// config = new DataCacheConfig(
|
||||
// cacheSize = 4096,
|
||||
// bytePerLine = 32,
|
||||
// wayCount = 1,
|
||||
// addressWidth = 32,
|
||||
// cpuDataWidth = 32,
|
||||
// memDataWidth = 32,
|
||||
// catchAccessError = true,
|
||||
// catchIllegal = true,
|
||||
// catchUnaligned = true,
|
||||
// catchMemoryTranslationMiss = true,
|
||||
// atomicEntriesCount = 2
|
||||
// ),
|
||||
// // memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
// portTlbSize = 6
|
||||
// )
|
||||
// ),
|
||||
// new StaticMemoryTranslatorPlugin(
|
||||
// ioRange = _(31 downto 28) === 0xF
|
||||
// ),
|
||||
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
|
||||
// new DBusSimplePlugin(
|
||||
// catchAddressMisaligned = true,
|
||||
// catchAccessFault = true,
|
||||
// earlyInjection = false,
|
||||
// withLrSc = true,
|
||||
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
// portTlbSize = 4
|
||||
// )
|
||||
// ),
|
||||
new DBusCachedPlugin(
|
||||
dBusCmdMasterPipe = true,
|
||||
dBusCmdSlavePipe = true,
|
||||
dBusRspSlavePipe = true,
|
||||
config = new DataCacheConfig(
|
||||
cacheSize = 4096*1,
|
||||
bytePerLine = 32,
|
||||
wayCount = 1,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
withLrSc = true
|
||||
// )
|
||||
),
|
||||
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
|
||||
// new MemoryTranslatorPlugin(
|
||||
// tlbSize = 32,
|
||||
// virtualRange = _(31 downto 28) === 0xC,
|
||||
|
@ -183,7 +181,7 @@ object LinuxGen {
|
|||
new SrcPlugin(
|
||||
separatedAddSub = false
|
||||
),
|
||||
new FullBarrelShifterPlugin(earlyInjection = true),
|
||||
new FullBarrelShifterPlugin(earlyInjection = false),
|
||||
// new LightShifterPlugin,
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = true,
|
||||
|
@ -204,7 +202,7 @@ object LinuxGen {
|
|||
divUnrollFactor = 1
|
||||
),
|
||||
// new DivPlugin,
|
||||
new CsrPlugin(CsrPluginConfig.linux(0x80000020l)),
|
||||
new CsrPlugin(CsrPluginConfig.linux(0x80000020l).copy(ebreakGen = false)),
|
||||
// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
|
||||
// CsrPluginConfig(
|
||||
// catchIllegalAccess = false,
|
||||
|
@ -228,21 +226,22 @@ 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,
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = true,
|
||||
fenceiGenAsAJump = true
|
||||
fenceiGenAsAJump = false
|
||||
),
|
||||
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
|
||||
)
|
||||
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)
|
||||
) else {
|
||||
config.plugins += new StaticMemoryTranslatorPlugin(
|
||||
ioRange = _(31 downto 28) === 0xF
|
||||
)
|
||||
}
|
||||
config
|
||||
}
|
||||
|
||||
|
@ -265,7 +264,7 @@ object LinuxGen {
|
|||
// }
|
||||
// }
|
||||
|
||||
SpinalConfig(mergeAsyncProcess = true).generateVerilog {
|
||||
SpinalConfig(mergeAsyncProcess = true, anonymSignalPrefix = "zz").generateVerilog {
|
||||
|
||||
|
||||
val toplevel = new VexRiscv(configFull(
|
||||
|
@ -375,14 +374,13 @@ object LinuxSyntesisBench extends App{
|
|||
// val rtls = List(fullNoMmu)
|
||||
|
||||
val targets = XilinxStdTargets(
|
||||
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
)/* ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
||||
) ++ IcestormStdTargets().take(1)*/
|
||||
vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin"
|
||||
) ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin",
|
||||
quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin"
|
||||
) ++ IcestormStdTargets().take(1)
|
||||
|
||||
|
||||
Bench(rtls, targets, "/eda/tmp")
|
||||
Bench(rtls, targets, "/media/miaou/HD/linux/tmp")
|
||||
}
|
||||
|
||||
object LinuxSim extends App{
|
||||
|
|
|
@ -107,25 +107,14 @@ object VexRiscvSynthesisBench {
|
|||
// val rtls = List(fullNoMmu)
|
||||
|
||||
val targets = XilinxStdTargets(
|
||||
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin"
|
||||
) ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
||||
quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin",
|
||||
quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin"
|
||||
) ++ IcestormStdTargets().take(1)
|
||||
|
||||
|
||||
// val targets = XilinxStdTargets(
|
||||
// vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
// )
|
||||
|
||||
// val targets = AlteraStdTargets(
|
||||
// quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||
// quartusCycloneVPath = null
|
||||
// )
|
||||
|
||||
|
||||
// val targets = IcestormStdTargets()
|
||||
Bench(rtls, targets, "/eda/tmp")
|
||||
Bench(rtls, targets, "/media/miaou/HD/linux/tmp")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,8 +66,7 @@ object VexRiscvAvalonForSim{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -63,8 +63,7 @@ object VexRiscvAvalonWithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -64,8 +64,7 @@ object VexRiscvAxi4WithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -62,8 +62,7 @@ object VexRiscvCachedWishboneForSim{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -8,24 +8,25 @@ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
|||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||
import spinal.lib.bus.simple._
|
||||
|
||||
case class DataCacheConfig( cacheSize : Int,
|
||||
bytePerLine : Int,
|
||||
wayCount : Int,
|
||||
addressWidth : Int,
|
||||
cpuDataWidth : Int,
|
||||
memDataWidth : Int,
|
||||
catchAccessError : Boolean,
|
||||
catchIllegal : Boolean,
|
||||
catchUnaligned : Boolean,
|
||||
catchMemoryTranslationMiss : Boolean,
|
||||
clearTagsAfterReset : Boolean = true,
|
||||
waysHitRetime : Boolean = true,
|
||||
tagSizeShift : Int = 0, //Used to force infering ram
|
||||
atomicEntriesCount : Int = 0){
|
||||
|
||||
case class DataCacheConfig(cacheSize : Int,
|
||||
bytePerLine : Int,
|
||||
wayCount : Int,
|
||||
addressWidth : Int,
|
||||
cpuDataWidth : Int,
|
||||
memDataWidth : Int,
|
||||
catchAccessError : Boolean,
|
||||
catchIllegal : Boolean,
|
||||
catchUnaligned : Boolean,
|
||||
earlyWaysHits : Boolean = true,
|
||||
earlyDataMux : Boolean = false,
|
||||
tagSizeShift : Int = 0, //Used to force infering ram
|
||||
withLrSc : Boolean = false){
|
||||
|
||||
assert(!(earlyDataMux && !earlyWaysHits))
|
||||
def burstSize = bytePerLine*8/memDataWidth
|
||||
val burstLength = bytePerLine/(memDataWidth/8)
|
||||
def catchSomething = catchUnaligned || catchMemoryTranslationMiss || catchIllegal || catchAccessError
|
||||
def genAtomic = atomicEntriesCount != 0
|
||||
def catchSomething = catchUnaligned || catchIllegal || catchAccessError
|
||||
|
||||
def getAxi4SharedConfig() = Axi4Config(
|
||||
addressWidth = addressWidth,
|
||||
|
@ -64,108 +65,29 @@ case class DataCacheConfig( cacheSize : Int,
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
object Bypasser{
|
||||
|
||||
//shot readValid path
|
||||
def writeFirstMemWrap[T <: Data](readValid : Bool, readLastAddress : UInt, readLastData : T,writeValid : Bool, writeAddress : UInt, writeData : T) : T = {
|
||||
val writeSample = readValid || (writeValid && writeAddress === readLastAddress)
|
||||
val writeValidReg = RegNextWhen(writeValid,writeSample)
|
||||
val writeAddressReg = RegNextWhen(writeAddress,writeSample)
|
||||
val writeDataReg = RegNextWhen(writeData,writeSample)
|
||||
(writeValidReg && writeAddressReg === readLastAddress) ? writeDataReg | readLastData
|
||||
}
|
||||
|
||||
|
||||
//short readValid path
|
||||
def writeFirstMemWrap(readValid : Bool, readLastAddress : UInt, readLastData : Bits,writeValid : Bool, writeAddress : UInt, writeData : Bits,writeMask : Bits) : Bits = {
|
||||
val writeHit = writeValid && writeAddress === readLastAddress
|
||||
val writeSample = readValid || writeHit
|
||||
val writeValidReg = RegNextWhen(writeValid,writeSample)
|
||||
val writeAddressReg = RegNextWhen(writeAddress,writeSample)
|
||||
val writeDataReg = Reg(writeData)
|
||||
val writeMaskReg = Reg(Bits(widthOf(writeData)/8 bits))
|
||||
val writeDataRegBytes = writeDataReg.subdivideIn(8 bits)
|
||||
val writeDataBytes = writeData.subdivideIn(8 bits)
|
||||
val ret = cloneOf(readLastData)
|
||||
val retBytes = ret.subdivideIn(8 bits)
|
||||
val readLastDataBytes = readLastData.subdivideIn(8 bits)
|
||||
val writeRegHit = writeValidReg && writeAddressReg === readLastAddress
|
||||
for(b <- writeMask.range){
|
||||
when(writeHit && writeMask(b)){
|
||||
writeMaskReg(b) := True
|
||||
}
|
||||
when(readValid) {
|
||||
writeMaskReg(b) := writeMask(b)
|
||||
}
|
||||
when(readValid || (writeHit && writeMask(b))){
|
||||
writeDataRegBytes(b) := writeDataBytes(b)
|
||||
}
|
||||
|
||||
retBytes(b) := (writeRegHit && writeMaskReg(b)) ? writeDataRegBytes(b) | readLastDataBytes(b)
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
//Long sample path
|
||||
// def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,lastAddress : UInt, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) : (T,T) = {
|
||||
// val hit = writeValid && (sample ? sampleAddress | lastAddress) === writeAddress
|
||||
// val bypass = hit ? writeData | readData
|
||||
// val reg = RegNextWhen(bypass,sample || hit)
|
||||
// (reg,bypass)
|
||||
// }
|
||||
|
||||
//Short sample path
|
||||
def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, sampleData : T, writeValid : Bool, writeAddress : UInt, writeData : T) = {
|
||||
val bypass = (!sample || (writeValid && sampleAddress === writeAddress)) ? writeData | sampleData
|
||||
val regEn = sample || (writeValid && sampleLastAddress === writeAddress)
|
||||
val reg = RegNextWhen(bypass,regEn)
|
||||
reg
|
||||
}
|
||||
|
||||
def writeFirstRegWrap(sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, sampleData : Bits, writeValid : Bool, writeAddress : UInt, writeData : Bits,writeMask : Bits) = {
|
||||
val byteCount = widthOf(writeMask)
|
||||
val sampleWriteHit = writeValid && sampleAddress === writeAddress
|
||||
val sampleLastHit = writeValid && sampleLastAddress === writeAddress
|
||||
val regBytes = Vec(Bits(8 bits),byteCount)
|
||||
for(b <- writeMask.range){
|
||||
val bypass = Mux(!sample || (sampleWriteHit && writeMask(b)), writeData(b*8, 8 bits), sampleData(b*8, 8 bits))
|
||||
val regEn = sample || (sampleLastHit && writeMask(b))
|
||||
regBytes(b) := RegNextWhen(bypass,regEn)
|
||||
}
|
||||
regBytes.asBits
|
||||
}
|
||||
}
|
||||
|
||||
object DataCacheCpuCmdKind extends SpinalEnum{
|
||||
val MEMORY,MANAGMENT = newElement()
|
||||
}
|
||||
|
||||
object DataCacheCpuExecute{
|
||||
implicit def implArgs(that : DataCacheCpuExecute) = that.args
|
||||
}
|
||||
|
||||
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)
|
||||
out(isValid, args, address)
|
||||
// in(haltIt)
|
||||
}
|
||||
}
|
||||
|
||||
case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
|
||||
val kind = DataCacheCpuCmdKind()
|
||||
val wr = Bool
|
||||
val address = UInt(p.addressWidth bit)
|
||||
//val address = UInt(p.addressWidth bit) Given on the side, as it's also part of the main pipeline
|
||||
val data = Bits(p.cpuDataWidth bit)
|
||||
val size = UInt(2 bits)
|
||||
val forceUncachedAccess = Bool
|
||||
val clean, invalidate, way = Bool
|
||||
val isAtomic = ifGen(p.genAtomic){Bool}
|
||||
val isAtomic = ifGen(p.withLrSc){Bool}
|
||||
// val all = Bool //Address should be zero when "all" is used
|
||||
}
|
||||
|
||||
|
@ -173,12 +95,11 @@ case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSl
|
|||
val isValid = Bool
|
||||
val isStuck = Bool
|
||||
val isRemoved = Bool
|
||||
val haltIt = Bool
|
||||
val address = UInt(p.addressWidth bit)
|
||||
val mmuBus = MemoryTranslatorBus()
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, isRemoved)
|
||||
in(haltIt)
|
||||
out(isValid, isStuck, isRemoved, address)
|
||||
slave(mmuBus)
|
||||
}
|
||||
}
|
||||
|
@ -189,15 +110,17 @@ 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 mmuMiss, illegalAccess, unalignedAccess , accessError = Bool
|
||||
val badAddr = UInt(32 bits)
|
||||
val clearAtomicEntries = ifGen(p.genAtomic) {Bool}
|
||||
val address = UInt(p.addressWidth bit)
|
||||
val mmuException, unalignedAccess , accessError = Bool
|
||||
val clearAtomicEntries = ifGen(p.withLrSc) {Bool}
|
||||
|
||||
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid,isStuck,isUser)
|
||||
in(haltIt, data, mmuMiss,illegalAccess , unalignedAccess, accessError, badAddr)
|
||||
out(isValid,isStuck,isUser, address)
|
||||
in(haltIt, data, mmuException, unalignedAccess, accessError, isWrite)
|
||||
outWithNull(clearAtomicEntries)
|
||||
}
|
||||
}
|
||||
|
@ -207,10 +130,15 @@ case class DataCacheCpuBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
|||
val memory = DataCacheCpuMemory(p)
|
||||
val writeBack = DataCacheCpuWriteBack(p)
|
||||
|
||||
val redo = Bool()
|
||||
val flush = Event
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
master(execute)
|
||||
master(memory)
|
||||
master(writeBack)
|
||||
master(flush)
|
||||
in(redo)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,8 +298,6 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
|||
|
||||
class DataCache(p : DataCacheConfig) extends Component{
|
||||
import p._
|
||||
import DataCacheCpuCmdKind._
|
||||
assert(wayCount == 1)
|
||||
assert(cpuDataWidth == memDataWidth)
|
||||
|
||||
val io = new Bundle{
|
||||
|
@ -379,6 +305,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
val mem = master(DataCacheMemBus(p))
|
||||
// val flushDone = out Bool //It pulse at the same time than the manager.request.fire
|
||||
}
|
||||
|
||||
val haltCpu = False
|
||||
val lineWidth = bytePerLine*8
|
||||
val lineCount = cacheSize/bytePerLine
|
||||
|
@ -397,14 +324,13 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
|
||||
class LineInfo() extends Bundle{
|
||||
val used = Bool
|
||||
val dirty = Bool
|
||||
val valid, error = Bool()
|
||||
val address = UInt(tagRange.length bit)
|
||||
}
|
||||
|
||||
val tagsReadCmd = Flow(UInt(log2Up(wayLineCount) bits))
|
||||
val tagsWriteCmd = Flow(new Bundle{
|
||||
// val way = UInt(log2Up(wayCount) bits)
|
||||
val way = Bits(wayCount bits)
|
||||
val address = UInt(log2Up(wayLineCount) bits)
|
||||
val data = new LineInfo()
|
||||
})
|
||||
|
@ -413,13 +339,39 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
val dataReadCmd = Flow(UInt(log2Up(wayWordCount) bits))
|
||||
val dataWriteCmd = Flow(new Bundle{
|
||||
// val way = UInt(log2Up(wayCount) bits)
|
||||
val way = Bits(wayCount bits)
|
||||
val address = UInt(log2Up(wayWordCount) bits)
|
||||
val data = Bits(wordWidth bits)
|
||||
val mask = Bits(wordWidth/8 bits)
|
||||
})
|
||||
|
||||
|
||||
|
||||
io.mem.cmd.valid := False
|
||||
io.mem.cmd.payload.assignDontCare()
|
||||
|
||||
val ways = for(i <- 0 until wayCount) yield new Area{
|
||||
val tags = Mem(new LineInfo(), wayLineCount)
|
||||
val data = Mem(Bits(wordWidth bit), wayWordCount)
|
||||
|
||||
//Reads
|
||||
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)){
|
||||
tags(tagsWriteCmd.address) := tagsWriteCmd.data
|
||||
}
|
||||
when(dataWriteCmd.valid && dataWriteCmd.way(i)){
|
||||
data.write(
|
||||
address = dataWriteCmd.address,
|
||||
data = dataWriteCmd.data,
|
||||
mask = dataWriteCmd.mask
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tagsReadCmd.valid := False
|
||||
tagsReadCmd.payload.assignDontCare()
|
||||
dataReadCmd.valid := False
|
||||
|
@ -428,233 +380,94 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
tagsWriteCmd.payload.assignDontCare()
|
||||
dataWriteCmd.valid := False
|
||||
dataWriteCmd.payload.assignDontCare()
|
||||
io.mem.cmd.valid := False
|
||||
io.mem.cmd.payload.assignDontCare()
|
||||
|
||||
|
||||
val way = new Area{
|
||||
val tags = Mem(new LineInfo(),wayLineCount)
|
||||
val data = Mem(Bits(wordWidth bit),wayWordCount)
|
||||
|
||||
when(tagsWriteCmd.valid){
|
||||
tags(tagsWriteCmd.address) := tagsWriteCmd.data
|
||||
}
|
||||
when(dataWriteCmd.valid){
|
||||
data.write(
|
||||
address = dataWriteCmd.address,
|
||||
data = dataWriteCmd.data,
|
||||
mask = dataWriteCmd.mask
|
||||
)
|
||||
}
|
||||
|
||||
val tagReadRspOneAddress = RegNextWhen(tagsReadCmd.payload, tagsReadCmd.valid)
|
||||
val tagReadRspOne = Bypasser.writeFirstMemWrap(
|
||||
readValid = tagsReadCmd.valid,
|
||||
readLastAddress = tagReadRspOneAddress,
|
||||
readLastData = tags.readSync(tagsReadCmd.payload,enable = tagsReadCmd.valid),
|
||||
writeValid = tagsWriteCmd.valid,
|
||||
writeAddress = tagsWriteCmd.address,
|
||||
writeData = tagsWriteCmd.data
|
||||
)
|
||||
|
||||
val dataReadRspOneKeepAddress = False
|
||||
val dataReadRspOneAddress = RegNextWhen(dataReadCmd.payload, dataReadCmd.valid && !dataReadRspOneKeepAddress)
|
||||
val dataReadRspOneWithoutBypass = data.readSync(dataReadCmd.payload,enable = dataReadCmd.valid)
|
||||
val dataReadRspOne = Bypasser.writeFirstMemWrap(
|
||||
readValid = dataReadCmd.valid,
|
||||
readLastAddress = dataReadRspOneAddress,
|
||||
readLastData = dataReadRspOneWithoutBypass,
|
||||
writeValid = dataWriteCmd.valid,
|
||||
writeAddress = dataWriteCmd.address,
|
||||
writeData = dataWriteCmd.data,
|
||||
writeMask = dataWriteCmd.mask
|
||||
)
|
||||
|
||||
val tagReadRspTwoEnable = !io.cpu.writeBack.isStuck
|
||||
val tagReadRspTwoRegIn = (tagsWriteCmd.valid && tagsWriteCmd.address === tagReadRspOneAddress) ? tagsWriteCmd.data | tagReadRspOne
|
||||
val tagReadRspTwo = RegNextWhen(tagReadRspTwoRegIn ,tagReadRspTwoEnable)
|
||||
|
||||
|
||||
val dataReadRspTwoEnable = !io.cpu.writeBack.isStuck
|
||||
val dataReadRspTwo = Bypasser.writeFirstRegWrap(
|
||||
sample = dataReadRspTwoEnable,
|
||||
sampleAddress = dataReadRspOneAddress,
|
||||
sampleLastAddress = RegNextWhen(dataReadRspOneAddress, dataReadRspTwoEnable),
|
||||
sampleData = dataReadRspOne,
|
||||
writeValid = dataWriteCmd.valid,
|
||||
writeAddress = dataWriteCmd.address,
|
||||
writeData = dataWriteCmd.data,
|
||||
writeMask = dataWriteCmd.mask
|
||||
)
|
||||
}
|
||||
|
||||
when(io.cpu.execute.isValid && !io.cpu.execute.isStuck){
|
||||
tagsReadCmd.valid := True
|
||||
when(io.cpu.execute.isValid && !io.cpu.memory.isStuck){
|
||||
tagsReadCmd.valid := True
|
||||
dataReadCmd.valid := True
|
||||
tagsReadCmd.payload := io.cpu.execute.address(lineRange)
|
||||
|
||||
dataReadCmd.valid := True
|
||||
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) //TODO FMAX maybe critical path could be default
|
||||
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low)
|
||||
}
|
||||
|
||||
|
||||
val cpuMemoryStageNeedReadData = Bool()
|
||||
|
||||
val victim = new Area{
|
||||
val requestIn = Stream(cloneable(new Bundle{
|
||||
// val way = UInt(log2Up(wayCount) bits)
|
||||
val address = UInt(p.addressWidth bits)
|
||||
}))
|
||||
requestIn.valid := False
|
||||
requestIn.payload.assignDontCare()
|
||||
|
||||
val request = requestIn.halfPipe()
|
||||
request.ready := False
|
||||
|
||||
val buffer = Mem(Bits(p.memDataWidth bits),memTransactionPerLine << tagSizeShift) // WARNING << tagSizeShift could resolve cyclone II issue, //.add(new AttributeString("ramstyle","M4K"))
|
||||
|
||||
//Send line read commands to fill the buffer
|
||||
val readLineCmdCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
|
||||
val dataReadCmdOccure = False
|
||||
val dataReadRestored = RegInit(False)
|
||||
when(request.valid){
|
||||
when(!readLineCmdCounter.msb) {
|
||||
readLineCmdCounter := readLineCmdCounter + 1
|
||||
//dataReadCmd := request.address(lineRange.high downto wordRange.low) Done in the manager
|
||||
dataReadCmdOccure := True
|
||||
dataReadCmd.valid := True
|
||||
dataReadCmd.payload := request.address(lineRange) @@ readLineCmdCounter(readLineCmdCounter.high - 1 downto 0)
|
||||
way.dataReadRspOneKeepAddress := True
|
||||
} otherwise {
|
||||
when(!dataReadRestored && cpuMemoryStageNeedReadData) {
|
||||
dataReadCmd.valid := True
|
||||
dataReadCmd.payload := way.dataReadRspOneAddress //Restore stage one readed value
|
||||
}
|
||||
dataReadRestored := True
|
||||
}
|
||||
}
|
||||
|
||||
dataReadRestored clearWhen(request.ready)
|
||||
io.cpu.memory.haltIt := cpuMemoryStageNeedReadData && request.valid && !dataReadRestored
|
||||
|
||||
//Fill the buffer with line read responses
|
||||
val readLineRspCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
|
||||
when(Delay(dataReadCmdOccure,1, init=False)){
|
||||
buffer(readLineRspCounter.resized) := way.dataReadRspOneWithoutBypass
|
||||
readLineRspCounter := readLineRspCounter + 1
|
||||
}
|
||||
|
||||
//Send buffer read commands
|
||||
val bufferReadCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
|
||||
val bufferReadStream = Stream(buffer.addressType)
|
||||
bufferReadStream.valid := readLineRspCounter > bufferReadCounter
|
||||
bufferReadStream.payload := bufferReadCounter.resized
|
||||
when(bufferReadStream.fire){
|
||||
bufferReadCounter := bufferReadCounter + 1
|
||||
}
|
||||
val bufferReaded = buffer.streamReadSync(bufferReadStream).stage
|
||||
bufferReaded.ready := False
|
||||
|
||||
//Send memory writes from bufffer read responses
|
||||
val bufferReadedCounter = Reg(UInt(log2Up(memTransactionPerLine) bits)) init(0)
|
||||
val memCmdAlreadyUsed = False
|
||||
when(bufferReaded.valid) {
|
||||
io.mem.cmd.valid := True
|
||||
io.mem.cmd.wr := True
|
||||
io.mem.cmd.address := request.address(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
|
||||
io.mem.cmd.length := p.burstLength-1
|
||||
io.mem.cmd.data := bufferReaded.payload
|
||||
io.mem.cmd.mask := (1<<(wordWidth/8))-1
|
||||
io.mem.cmd.last := bufferReadedCounter === bufferReadedCounter.maxValue
|
||||
|
||||
when(!memCmdAlreadyUsed && io.mem.cmd.ready){
|
||||
bufferReaded.ready := True
|
||||
bufferReadedCounter := bufferReadedCounter + 1
|
||||
when(bufferReadedCounter === bufferReadedCounter.maxValue){
|
||||
request.ready := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val counter = Counter(memTransactionPerLine)
|
||||
when(request.ready){
|
||||
readLineCmdCounter.msb := False
|
||||
readLineRspCounter.msb := False
|
||||
bufferReadCounter.msb := False
|
||||
def collisionProcess(readAddress : UInt, readMask : Bits): Bits ={
|
||||
val ret = Bits(wayCount bits)
|
||||
for(i <- 0 until wayCount){
|
||||
ret(i) := dataWriteCmd.valid && dataWriteCmd.way(i) && dataWriteCmd.address === readAddress && (readMask & dataWriteCmd.mask) =/= 0
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
val stageA = new Area{
|
||||
val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck)
|
||||
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid && request.kind === MEMORY //TODO filter request kind
|
||||
io.cpu.memory.mmuBus.cmd.virtualAddress := request.address
|
||||
io.cpu.memory.mmuBus.cmd.bypassTranslation := request.way
|
||||
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
|
||||
cpuMemoryStageNeedReadData := io.cpu.memory.isValid && request.kind === MEMORY && !request.wr
|
||||
}
|
||||
|
||||
val stageB = new Area {
|
||||
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
|
||||
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck)
|
||||
val waysHit = if(waysHitRetime)
|
||||
RegNextWhen(way.tagReadRspTwoRegIn.used && io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming
|
||||
else
|
||||
way.tagReadRspTwo.used && mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwo.address
|
||||
|
||||
|
||||
//Loader interface
|
||||
val loaderValid = False
|
||||
val loaderReady = False
|
||||
val loadingDone = RegNext(loaderValid && loaderReady) init(False) //one cycle pulse
|
||||
|
||||
//delayedXX are used to relax logic timings in flush and evict modes
|
||||
val delayedIsStuck = RegNext(io.cpu.writeBack.isStuck)
|
||||
val delayedWaysHitValid = RegNext(waysHit)
|
||||
|
||||
val victimNotSent = RegInit(False) clearWhen(victim.requestIn.ready) setWhen(!io.cpu.memory.isStuck)
|
||||
val loadingNotDone = RegInit(False) clearWhen(loaderReady) setWhen(!io.cpu.memory.isStuck)
|
||||
|
||||
val writeMask = request.size.mux (
|
||||
val stage0 = new Area{
|
||||
val mask = io.cpu.execute.size.mux (
|
||||
U(0) -> B"0001",
|
||||
U(1) -> B"0011",
|
||||
default -> B"1111"
|
||||
) |<< mmuRsp.physicalAddress(1 downto 0)
|
||||
) |<< io.cpu.execute.address(1 downto 0)
|
||||
val colisions = collisionProcess(io.cpu.execute.address(lineRange.high downto wordRange.low), mask)
|
||||
}
|
||||
|
||||
val stageA = new Area{
|
||||
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.memory.isStuck)
|
||||
val request = stagePipe(io.cpu.execute.args)
|
||||
val mask = stagePipe(stage0.mask)
|
||||
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid
|
||||
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
|
||||
|
||||
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))
|
||||
val colisions = stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) //Assume the writeback stage will never be unstall memory acces while memory stage is stalled
|
||||
}
|
||||
|
||||
val stageB = new Area {
|
||||
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.writeBack.isStuck)
|
||||
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
|
||||
val mmuRspFreeze = False
|
||||
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze)
|
||||
val tagsReadRsp = ways.map(w => stagePipe(w.tagsReadRsp))
|
||||
val dataReadRsp = !earlyDataMux generate ways.map(w => stagePipe(w.dataReadRsp))
|
||||
val waysHits = if(earlyWaysHits) stagePipe(B(stageA.wayHits)) else B(tagsReadRsp.map(tag => mmuRsp.physicalAddress(tagRange) === tag.address && tag.valid).asBits())
|
||||
val waysHit = waysHits.orR
|
||||
val dataMux = if(earlyDataMux) stagePipe(stageA.dataMux) else MuxOH(waysHits, dataReadRsp)
|
||||
val mask = stagePipe(stageA.mask)
|
||||
val colisions = stagePipe(stageA.colisions)
|
||||
|
||||
//Loader interface
|
||||
val loaderValid = False
|
||||
|
||||
|
||||
val hadMemRspErrorReg = RegInit(False)
|
||||
val hadMemRspError = (io.mem.rsp.valid && io.mem.rsp.error) || hadMemRspErrorReg
|
||||
hadMemRspErrorReg := hadMemRspError && io.cpu.writeBack.haltIt
|
||||
|
||||
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
|
||||
io.cpu.writeBack.mmuMiss := False
|
||||
io.cpu.writeBack.illegalAccess := False
|
||||
io.cpu.writeBack.unalignedAccess := False
|
||||
io.cpu.writeBack.accessError := (if(catchAccessError) hadMemRspError && !io.cpu.writeBack.haltIt else False)
|
||||
io.cpu.writeBack.badAddr := request.address
|
||||
|
||||
//Evict the cache after reset logics
|
||||
val bootEvicts = if(clearTagsAfterReset) new Area {
|
||||
val flusher = new Area {
|
||||
val valid = RegInit(True)
|
||||
mmuRsp.physicalAddress init (0)
|
||||
when(valid) {
|
||||
tagsWriteCmd.valid := valid
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := False
|
||||
when(mmuRsp.physicalAddress(lineRange) =/= lineCount - 1) {
|
||||
tagsWriteCmd.way.setAll()
|
||||
tagsWriteCmd.data.valid := False
|
||||
io.cpu.writeBack.haltIt := True
|
||||
when(mmuRsp.physicalAddress(lineRange) =/= wayLineCount - 1) {
|
||||
mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
|
||||
io.cpu.writeBack.haltIt := True
|
||||
} otherwise {
|
||||
valid := False
|
||||
}
|
||||
}
|
||||
|
||||
io.cpu.flush.ready := False
|
||||
when(io.cpu.flush.valid && !io.cpu.execute.isValid && !io.cpu.memory.isValid && !io.cpu.writeBack.isValid && !io.cpu.redo){
|
||||
io.cpu.flush.ready := True
|
||||
mmuRsp.physicalAddress.getDrivingReg(lineRange) := 0
|
||||
valid := True
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val atomic = if(genAtomic) new Area{
|
||||
val atomic = withLrSc 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 ={
|
||||
|
@ -662,142 +475,143 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
this
|
||||
}
|
||||
}
|
||||
val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount)
|
||||
val entriesAllocCounter = Counter(atomicEntriesCount)
|
||||
val entriesHit = entries.map(e => e.valid && e.size === request.size && e.address === request.address).orR
|
||||
when(io.cpu.writeBack.isValid && request.isAtomic && !request.wr){
|
||||
entries(entriesAllocCounter).valid := True
|
||||
entries(entriesAllocCounter).size := request.size
|
||||
entries(entriesAllocCounter).address := request.address
|
||||
when(!io.cpu.writeBack.isStuck){
|
||||
entriesAllocCounter.increment()
|
||||
}
|
||||
val reserved = RegInit(False)
|
||||
when(io.cpu.writeBack.isValid && !io.cpu.writeBack.isStuck && !io.cpu.redo && request.isAtomic && !request.wr){
|
||||
reserved := True
|
||||
}
|
||||
when(io.cpu.writeBack.clearAtomicEntries){
|
||||
entries.foreach(_.valid := False)
|
||||
reserved := False
|
||||
}
|
||||
}
|
||||
|
||||
when(request.isAtomic && ! entriesHit){
|
||||
writeMask := 0
|
||||
}
|
||||
} else null
|
||||
val memCmdSent = RegInit(False) setWhen (io.mem.cmd.ready) clearWhen (!io.cpu.writeBack.isStuck)
|
||||
|
||||
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) 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) {
|
||||
if (catchMemoryTranslationMiss) {
|
||||
io.cpu.writeBack.mmuMiss := ??? //TODO mmuRsp.miss
|
||||
}
|
||||
switch(request.kind) {
|
||||
is(MANAGMENT) {
|
||||
when(delayedIsStuck && ???){ //TODO!mmuRsp.miss) {
|
||||
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
|
||||
io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready))
|
||||
victim.requestIn.valid := request.clean && way.tagReadRspTwo.dirty
|
||||
tagsWriteCmd.valid := victim.requestIn.ready
|
||||
} otherwise{
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
}
|
||||
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
|
||||
io.cpu.writeBack.haltIt.clearWhen(request.wr ? io.mem.cmd.ready | io.mem.rsp.valid)
|
||||
|
||||
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := !request.invalidate
|
||||
tagsWriteCmd.data.dirty := !request.clean
|
||||
io.mem.cmd.valid := !memCmdSent
|
||||
io.mem.cmd.wr := request.wr
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
|
||||
io.mem.cmd.mask := mask
|
||||
io.mem.cmd.data := request.data
|
||||
io.mem.cmd.length := 0
|
||||
io.mem.cmd.last := True
|
||||
|
||||
if(withLrSc) when(request.isAtomic && !atomic.reserved){
|
||||
io.mem.cmd.valid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
is(MEMORY) {
|
||||
val illegal = if(catchIllegal) (request.wr && !mmuRsp.allowWrite) || (!request.wr && !mmuRsp.allowRead) || (io.cpu.writeBack.isUser && !mmuRsp.allowUser) else False
|
||||
val unaligned = 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.illegalAccess := illegal
|
||||
io.cpu.writeBack.unalignedAccess := unaligned
|
||||
when((Bool(!catchMemoryTranslationMiss) || ???) && !illegal && !unaligned) { //TODO !mmuRsp.miss
|
||||
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
|
||||
val memCmdSent = RegInit(False)
|
||||
when(!victim.request.valid) {
|
||||
//Avoid mixing memory request while victim is pending
|
||||
io.mem.cmd.wr := request.wr
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
|
||||
io.mem.cmd.mask := writeMask
|
||||
io.mem.cmd.data := request.data
|
||||
io.mem.cmd.length := 0
|
||||
io.mem.cmd.last := True
|
||||
} otherwise {
|
||||
when(waysHit || request.wr) { //Do not require a cache refill ?
|
||||
//Data cache update
|
||||
dataWriteCmd.valid setWhen(request.wr && waysHit)
|
||||
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
|
||||
dataWriteCmd.data := request.data
|
||||
dataWriteCmd.mask := mask
|
||||
dataWriteCmd.way := waysHits
|
||||
|
||||
when(!memCmdSent) {
|
||||
io.mem.cmd.valid := True
|
||||
memCmdSent setWhen (io.mem.cmd.ready)
|
||||
}
|
||||
//Write through
|
||||
io.mem.cmd.valid setWhen(request.wr)
|
||||
io.mem.cmd.wr := True
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
|
||||
io.mem.cmd.mask := mask
|
||||
io.mem.cmd.data := request.data
|
||||
io.mem.cmd.length := 0
|
||||
io.mem.cmd.last := True
|
||||
io.cpu.writeBack.haltIt clearWhen(!request.wr || io.mem.cmd.ready)
|
||||
|
||||
io.cpu.writeBack.haltIt.clearWhen(memCmdSent && (io.mem.rsp.fire || request.wr)) //Cut mem.cmd.ready path but insert one cycle stall when write
|
||||
}
|
||||
memCmdSent clearWhen (!io.cpu.writeBack.isStuck)
|
||||
} otherwise {
|
||||
when(waysHit || !loadingNotDone) {
|
||||
io.cpu.writeBack.haltIt := False
|
||||
dataWriteCmd.valid := request.wr
|
||||
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
|
||||
dataWriteCmd.data := request.data
|
||||
dataWriteCmd.mask := writeMask
|
||||
//On write to read colisions
|
||||
io.cpu.redo := !request.wr && (colisions & waysHits) =/= 0
|
||||
|
||||
tagsWriteCmd.valid := (!loadingNotDone) || request.wr
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := True
|
||||
tagsWriteCmd.data.dirty := request.wr
|
||||
tagsWriteCmd.data.address := mmuRsp.physicalAddress(tagRange)
|
||||
} otherwise {
|
||||
val victimRequired = way.tagReadRspTwo.used && way.tagReadRspTwo.dirty
|
||||
loaderValid := loadingNotDone && !(victimNotSent && victim.request.isStall) //Additional condition used to be sure of that all previous victim are written into the RAM
|
||||
victim.requestIn.valid := victimRequired && victimNotSent
|
||||
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
|
||||
}
|
||||
}
|
||||
if(withLrSc) when(request.isAtomic && !atomic.reserved){
|
||||
io.mem.cmd.valid := False
|
||||
dataWriteCmd.valid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
} otherwise { //Do refill
|
||||
|
||||
//Emit cmd
|
||||
io.mem.cmd.valid setWhen(!memCmdSent)
|
||||
io.mem.cmd.wr := False
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
|
||||
io.mem.cmd.length := p.burstLength-1
|
||||
io.mem.cmd.last := True
|
||||
|
||||
loaderValid setWhen(io.mem.cmd.ready)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(request.forceUncachedAccess || 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 {
|
||||
io.cpu.writeBack.data := dataMux
|
||||
if(catchAccessError) io.cpu.writeBack.accessError := (waysHits & B(tagsReadRsp.map(_.error))) =/= 0
|
||||
}
|
||||
|
||||
//remove side effects on exceptions
|
||||
when(mmuRsp.refilling || io.cpu.writeBack.accessError || io.cpu.writeBack.mmuException || io.cpu.writeBack.unalignedAccess){
|
||||
io.mem.cmd.valid := False
|
||||
tagsWriteCmd.valid := False
|
||||
dataWriteCmd.valid := False
|
||||
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")
|
||||
io.cpu.writeBack.data := (request.forceUncachedAccess || mmuRsp.isIoAccess) ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
|
||||
if(genAtomic){
|
||||
|
||||
if(withLrSc){
|
||||
when(request.isAtomic && request.wr){
|
||||
io.cpu.writeBack.data := (!atomic.entriesHit).asBits.resized
|
||||
io.cpu.writeBack.data := (!atomic.reserved).asBits.resized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//The whole life of a loading task, the corresponding manager request is present
|
||||
val loader = new Area{
|
||||
val valid = RegNext(stageB.loaderValid) init(False)
|
||||
val valid = RegInit(False) setWhen(stageB.loaderValid)
|
||||
val baseAddress = stageB.mmuRsp.physicalAddress
|
||||
|
||||
val memCmdSent = RegInit(False)
|
||||
when(valid && !memCmdSent) {
|
||||
io.mem.cmd.valid := True
|
||||
io.mem.cmd.wr := False
|
||||
io.mem.cmd.address := baseAddress(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
|
||||
io.mem.cmd.length := p.burstLength-1
|
||||
io.mem.cmd.last := True
|
||||
}
|
||||
|
||||
when(valid && io.mem.cmd.ready){
|
||||
memCmdSent := True
|
||||
}
|
||||
|
||||
when(valid && !memCmdSent) {
|
||||
victim.memCmdAlreadyUsed := True
|
||||
}
|
||||
|
||||
val counter = Counter(memTransactionPerLine)
|
||||
val waysAllocator = Reg(Bits(wayCount bits)) init(1)
|
||||
val error = RegInit(False)
|
||||
|
||||
when(valid && io.mem.rsp.valid){
|
||||
dataWriteCmd.valid := True
|
||||
dataWriteCmd.address := baseAddress(lineRange) @@ counter
|
||||
dataWriteCmd.data := io.mem.rsp.data
|
||||
dataWriteCmd.mask := (1<<(wordWidth/8))-1
|
||||
dataWriteCmd.mask.setAll()
|
||||
dataWriteCmd.way := waysAllocator
|
||||
error := error | io.mem.rsp.error
|
||||
counter.increment()
|
||||
}
|
||||
|
||||
|
||||
when(counter.willOverflow){
|
||||
memCmdSent := False
|
||||
valid := False
|
||||
stageB.loaderReady := True
|
||||
|
||||
//Update tags
|
||||
tagsWriteCmd.valid := True
|
||||
tagsWriteCmd.address := baseAddress(lineRange)
|
||||
tagsWriteCmd.data.valid := True
|
||||
tagsWriteCmd.data.address := baseAddress(tagRange)
|
||||
tagsWriteCmd.data.error := error || io.mem.rsp.error
|
||||
tagsWriteCmd.way := waysAllocator
|
||||
|
||||
waysAllocator := (waysAllocator ## waysAllocator.msb).resized
|
||||
|
||||
error := False
|
||||
}
|
||||
|
||||
io.cpu.redo setWhen(valid)
|
||||
stageB.mmuRspFreeze setWhen(stageB.loaderValid || valid)
|
||||
}
|
||||
}
|
|
@ -249,7 +249,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
import p._
|
||||
assert(cpuDataWidth == memDataWidth, "Need testing")
|
||||
val io = new Bundle{
|
||||
val flush = slave(InstructionCacheFlushBus())
|
||||
val flush = in Bool()
|
||||
val cpu = slave(InstructionCacheCpuBus(p))
|
||||
val mem = master(InstructionCacheMemBus(p))
|
||||
}
|
||||
|
@ -300,15 +300,16 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val valid = RegInit(False) clearWhen(fire)
|
||||
val address = Reg(UInt(addressWidth bits))
|
||||
val hadError = RegInit(False) clearWhen(fire)
|
||||
val flushPending = RegInit(True)
|
||||
|
||||
when(io.cpu.fill.valid){
|
||||
valid := True
|
||||
address := io.cpu.fill.payload
|
||||
}
|
||||
|
||||
io.cpu.prefetch.haltIt setWhen(valid)
|
||||
io.cpu.prefetch.haltIt setWhen(valid || flushPending)
|
||||
|
||||
val flushCounter = Reg(UInt(log2Up(wayLineCount) + 1 bit)) init(if(preResetFlush) wayLineCount else 0)
|
||||
val flushCounter = Reg(UInt(log2Up(wayLineCount) + 1 bit))
|
||||
when(!flushCounter.msb){
|
||||
io.cpu.prefetch.haltIt := True
|
||||
flushCounter := flushCounter + 1
|
||||
|
@ -316,17 +317,16 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
when(!RegNext(flushCounter.msb)){
|
||||
io.cpu.prefetch.haltIt := True
|
||||
}
|
||||
val flushFromInterface = RegInit(False)
|
||||
io.flush.cmd.ready := !(valid || io.cpu.fetch.isValid) //io.cpu.fetch.isValid will avoid bug on first cycle miss
|
||||
when(io.flush.cmd.valid){
|
||||
|
||||
when(io.flush){
|
||||
io.cpu.prefetch.haltIt := True
|
||||
when(io.flush.cmd.ready){
|
||||
flushCounter := 0
|
||||
flushFromInterface := True
|
||||
}
|
||||
flushPending := True
|
||||
}
|
||||
|
||||
io.flush.rsp := flushCounter.msb.rise && flushFromInterface
|
||||
when(flushPending && !(valid || io.cpu.fetch.isValid) ){
|
||||
flushCounter := 0
|
||||
flushPending := False
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -411,7 +411,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
io.cpu.fetch.cacheMiss := !hit.valid
|
||||
io.cpu.fetch.error := hit.error
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -441,7 +441,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
io.cpu.decode.cacheMiss := !hit.valid
|
||||
io.cpu.decode.error := hit.error
|
||||
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)
|
||||
io.cpu.decode.physicalAddress := mmuRsp.physicalAddress
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -311,21 +314,17 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
val csrMapping = new CsrMapping()
|
||||
|
||||
//Interruption and exception data model
|
||||
case class Delegator(var enable : Bool, privilege : Int)
|
||||
case class InterruptSpec(var cond : Bool, id : Int, privilege : Int, delegators : List[Delegator])
|
||||
case class ExceptionSpec(id : Int, delegators : List[Delegator])
|
||||
var interruptSpecs = ArrayBuffer[InterruptSpec]()
|
||||
var exceptionSpecs = ArrayBuffer[ExceptionSpec]()
|
||||
|
||||
|
||||
case class InterruptSource(var cond : Bool, id : Int)
|
||||
case class InterruptPrivilege(privilege : Int){
|
||||
var privilegeCond : Bool = null
|
||||
val sources = ArrayBuffer[InterruptSource]()
|
||||
def addInterrupt(cond : Bool, id : Int, privilege : Int, delegators : List[Delegator]): Unit = {
|
||||
interruptSpecs += InterruptSpec(cond, id, privilege, delegators)
|
||||
}
|
||||
|
||||
def getInterruptPrivilege(privilege : Int) = customInterrupts.getOrElseUpdate(privilege, InterruptPrivilege(privilege))
|
||||
var customInterrupts = mutable.LinkedHashMap[Int, InterruptPrivilege]()
|
||||
def addInterrupt(cond : Bool, id : Int, privilege : Int): Unit = {
|
||||
getInterruptPrivilege(privilege).sources += InterruptSource(cond, id)
|
||||
}
|
||||
def createInterrupt(id : Int, privilege : Int) : Bool = { val ret = Bool(); addInterrupt(ret, id, privilege); ret}
|
||||
|
||||
override def r(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r(csrAddress, bitOffset, that)
|
||||
override def w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.w(csrAddress, bitOffset, that)
|
||||
override def r2w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r2w(csrAddress, bitOffset, that)
|
||||
|
@ -378,7 +377,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")
|
||||
|
@ -396,10 +395,10 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
allowInterrupts = True
|
||||
allowException = True
|
||||
|
||||
for (privilege <- customInterrupts.values;
|
||||
source <- privilege.sources){
|
||||
source.cond = source.cond.pull()
|
||||
}
|
||||
for (i <- interruptSpecs) i.cond = i.cond.pull()
|
||||
|
||||
|
||||
pipeline.update(MPP, UInt(2 bits))
|
||||
}
|
||||
|
||||
def inhibateInterrupts() : Unit = allowInterrupts := False
|
||||
|
@ -467,9 +466,13 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val minstret = Reg(UInt(64 bits)) randBoot()
|
||||
|
||||
|
||||
|
||||
val medeleg = Reg(Bits(32 bits)) init(0)
|
||||
val mideleg = Reg(Bits(32 bits)) init(0)
|
||||
val medeleg = supervisorGen generate new Area {
|
||||
val IAM, IAF, II, LAM, LAF, SAM, SAF, EU, ES, IPF, LPF, SPF = RegInit(False)
|
||||
val mapping = mutable.HashMap(0 -> IAM, 1 -> IAF, 2 -> II, 4 -> LAM, 5 -> LAF, 6 -> SAM, 7 -> SAF, 8 -> EU, 9 -> ES, 12 -> IPF, 13 -> LPF, 15 -> SPF)
|
||||
}
|
||||
val mideleg = supervisorGen generate new Area {
|
||||
val ST, SE, SS = RegInit(False)
|
||||
}
|
||||
|
||||
if(mvendorid != null) READ_ONLY(CSR.MVENDORID, U(mvendorid))
|
||||
if(marchid != null) READ_ONLY(CSR.MARCHID , U(marchid ))
|
||||
|
@ -493,14 +496,16 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
minstretAccess(CSR.MINSTRET, minstret(31 downto 0))
|
||||
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
|
||||
|
||||
medelegAccess(CSR.MEDELEG, medeleg)
|
||||
midelegAccess(CSR.MIDELEG, mideleg)
|
||||
if(supervisorGen) {
|
||||
for((id, enable) <- medeleg.mapping) medelegAccess(CSR.MEDELEG, id -> enable)
|
||||
midelegAccess(CSR.MIDELEG, 9 -> mideleg.SE, 5 -> mideleg.ST, 1 -> mideleg.SS)
|
||||
}
|
||||
|
||||
//User CSR
|
||||
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
|
||||
ucycleAccess(CSR.UCYCLEH, mcycle(63 downto 32))
|
||||
|
||||
pipeline.update(MPP, mstatus.MPP)
|
||||
pipeline(MPP) := mstatus.MPP
|
||||
}
|
||||
|
||||
val supervisorCsr = ifGen(supervisorGen) {
|
||||
|
@ -574,58 +579,16 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
|
||||
if(supervisorGen) {
|
||||
getInterruptPrivilege(1).privilegeCond = (sstatus.SIE && privilege === "01") || privilege === "00"
|
||||
getInterruptPrivilege(1).sources ++= List(
|
||||
InterruptSource(sip.STIP && sie.STIE, 5),
|
||||
InterruptSource(sip.SSIP && sie.SSIE, 1),
|
||||
InterruptSource(sip.SEIP_OR && sie.SEIE, 9)
|
||||
)
|
||||
addInterrupt(sip.STIP && sie.STIE, id = 5, privilege = 1, delegators = List(Delegator(mideleg.ST, 3)))
|
||||
addInterrupt(sip.SSIP && sie.SSIE, id = 1, privilege = 1, delegators = List(Delegator(mideleg.SS, 3)))
|
||||
addInterrupt(sip.SEIP_OR && sie.SEIE, id = 9, privilege = 1, delegators = List(Delegator(mideleg.SE, 3)))
|
||||
|
||||
for((id, enable) <- medeleg.mapping) exceptionSpecs += ExceptionSpec(id, List(Delegator(enable, 3)))
|
||||
}
|
||||
|
||||
getInterruptPrivilege(3).privilegeCond = mstatus.MIE || privilege =/= "11"
|
||||
getInterruptPrivilege(3).sources ++= List(
|
||||
InterruptSource(mip.MTIP && mie.MTIE, 7),
|
||||
InterruptSource(mip.MSIP && mie.MSIE, 3),
|
||||
InterruptSource(mip.MEIP && mie.MEIE, 11)
|
||||
)
|
||||
|
||||
case class DelegatorModel(value : Bits, source : Int, target : Int)
|
||||
// def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
|
||||
// val filtredDelegators = delegators.filter(_.target >= lowerBound)
|
||||
// val ret = U(lowerBound, 2 bits)
|
||||
// for(d <- filtredDelegators){
|
||||
// when(!d.value(id)){
|
||||
// ret := d.source
|
||||
// }
|
||||
// }
|
||||
// ret
|
||||
// }
|
||||
|
||||
def solveDelegators(delegators : Seq[DelegatorModel], id : UInt, lowerBound : UInt): UInt = {
|
||||
if(delegators.isEmpty) return U"11"
|
||||
val ret = U(delegators.last.target, 2 bits)
|
||||
for(d <- delegators){
|
||||
when(!d.value(id) || d.target < lowerBound){
|
||||
ret := d.source
|
||||
}
|
||||
}
|
||||
ret
|
||||
// val ret = U"11"
|
||||
// var continue = True
|
||||
// for(d <- delegators){
|
||||
// continue = continue && d.value(id)
|
||||
// when(continue){
|
||||
// ret := d.source
|
||||
// }
|
||||
// }
|
||||
// ret.max(lowerBound)
|
||||
}
|
||||
|
||||
val interruptDelegators = ArrayBuffer[DelegatorModel]()
|
||||
if(midelegAccess.canWrite) interruptDelegators += DelegatorModel(mideleg,3, 1)
|
||||
|
||||
val exceptionDelegators = ArrayBuffer[DelegatorModel]()
|
||||
if(medelegAccess.canWrite) exceptionDelegators += DelegatorModel(medeleg,3, 1)
|
||||
addInterrupt(mip.MTIP && mie.MTIE, id = 7, privilege = 3, delegators = Nil)
|
||||
addInterrupt(mip.MSIP && mie.MSIE, id = 3, privilege = 3, delegators = Nil)
|
||||
addInterrupt(mip.MEIP && mie.MEIE, id = 11, privilege = 3, delegators = Nil)
|
||||
|
||||
|
||||
val mepcCaptureStage = if(exceptionPortsInfos.nonEmpty) lastStage else decode
|
||||
|
@ -637,7 +600,27 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val exceptionValids = Vec(stages.map(s => Bool().setPartialName(s.getName())))
|
||||
val exceptionValidsRegs = Vec(stages.map(s => Reg(Bool).init(False).setPartialName(s.getName()))).allowUnsetRegToAvoidLatch
|
||||
val exceptionContext = Reg(ExceptionCause())
|
||||
val exceptionTargetPrivilege = solveDelegators(exceptionDelegators, exceptionContext.code, privilege)
|
||||
val exceptionTargetPrivilegeUncapped = U"11"
|
||||
|
||||
switch(exceptionContext.code){
|
||||
for(s <- exceptionSpecs){
|
||||
is(s.id){
|
||||
var exceptionPrivilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||
while(exceptionPrivilegs.length != 1){
|
||||
val p = exceptionPrivilegs.head
|
||||
if (exceptionPrivilegs.tail.forall(e => s.delegators.exists(_.privilege == e))) {
|
||||
val delegUpOn = s.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
|
||||
val delegDownOff = !s.delegators.filter(_.privilege <= p).map(_.enable).orR
|
||||
when(delegUpOn && delegDownOff) {
|
||||
exceptionTargetPrivilegeUncapped := p
|
||||
}
|
||||
}
|
||||
exceptionPrivilegs = exceptionPrivilegs.tail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val exceptionTargetPrivilege = privilege.max(exceptionTargetPrivilegeUncapped)
|
||||
|
||||
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
|
||||
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
|
||||
|
@ -677,7 +660,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 +671,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
|
||||
|
||||
|
||||
|
@ -697,32 +681,27 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
//Process interrupt request, code and privilege
|
||||
val interrupt = False
|
||||
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
||||
val interruptDelegatorHit = interruptDelegators.map(d => (d -> False)).toMap
|
||||
for(model <- customInterrupts.values.toSeq.sortBy(_.privilege)){
|
||||
when(model.privilegeCond){
|
||||
when(model.sources.map(_.cond).orR){
|
||||
interrupt := True
|
||||
}
|
||||
for(source <- model.sources){
|
||||
when(source.cond){
|
||||
interruptCode := source.id
|
||||
for(interruptDelegator <- interruptDelegators){
|
||||
interruptDelegatorHit(interruptDelegator) := (if(interruptDelegator.target < model.privilege){
|
||||
False
|
||||
} else {
|
||||
interruptDelegator.value(source.id)
|
||||
})
|
||||
}
|
||||
var interruptPrivilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||
val interruptTargetPrivilege = UInt(2 bits).assignDontCare()
|
||||
val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]()
|
||||
if(supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01")
|
||||
privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11")
|
||||
while(interruptPrivilegs.nonEmpty){
|
||||
val p = interruptPrivilegs.head
|
||||
when(privilegeAllowInterrupts(p)){
|
||||
for(i <- interruptSpecs
|
||||
if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode
|
||||
if interruptPrivilegs.tail.forall(e => i.delegators.exists(_.privilege == e))){ // EX : Supervisor timer need to have machine mode delegator
|
||||
val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
|
||||
val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR
|
||||
when(i.cond && delegUpOn && delegDownOff){
|
||||
interrupt := True
|
||||
interruptCode := i.id
|
||||
interruptTargetPrivilege := p
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val interruptTargetPrivilege = U(if(interruptDelegators.isEmpty) 3 else interruptDelegators.last.target, 2 bits)
|
||||
for(interruptDelegator <- interruptDelegators){
|
||||
when(!interruptDelegatorHit(interruptDelegator)){
|
||||
interruptTargetPrivilege := interruptDelegator.source
|
||||
}
|
||||
interruptPrivilegs = interruptPrivilegs.tail
|
||||
}
|
||||
|
||||
interrupt.clearWhen(!allowInterrupts)
|
||||
|
@ -807,7 +786,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
import lastStage._
|
||||
|
||||
//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()
|
||||
jumpInterface.valid := True
|
||||
beforeLastStage.arbitration.flushAll := True
|
||||
|
@ -879,7 +858,6 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
//Manage MRET / SRET instructions
|
||||
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
||||
//TODO check MPP value too
|
||||
when(input(INSTRUCTION)(29 downto 28).asUInt > privilege) {
|
||||
illegalInstruction := True
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import spinal.lib._
|
|||
import spinal.lib.bus.amba4.axi.Axi4
|
||||
|
||||
|
||||
class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : Any = null) extends DBusCachedPlugin(config, memoryTranslatorPortConfig){
|
||||
class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : Any = null) extends DBusCachedPlugin(config, memoryTranslatorPortConfig) {
|
||||
var dAxi : Axi4 = null
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -20,18 +20,34 @@ class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
|
|||
|
||||
class DBusCachedPlugin(config : DataCacheConfig,
|
||||
memoryTranslatorPortConfig : Any = null,
|
||||
csrInfo : Boolean = false) extends Plugin[VexRiscv]{
|
||||
dBusCmdMasterPipe : Boolean = false,
|
||||
dBusCmdSlavePipe : Boolean = false,
|
||||
dBusRspSlavePipe : Boolean = false,
|
||||
csrInfo : Boolean = false) extends Plugin[VexRiscv] with DBusAccessService {
|
||||
import config._
|
||||
|
||||
assert(isPow2(cacheSize))
|
||||
assert(!(memoryTranslatorPortConfig != null && config.cacheSize/config.wayCount > 4096), "When the D$ is used with MMU, each way can't be bigger than a page (4096 bytes)")
|
||||
|
||||
var dBus : DataCacheMemBus = null
|
||||
var mmuBus : MemoryTranslatorBus = null
|
||||
var exceptionBus : Flow[ExceptionCause] = null
|
||||
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._
|
||||
|
@ -43,23 +59,22 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
MEMORY_ENABLE -> True,
|
||||
RS1_USE -> True
|
||||
) ++ (if (catchUnaligned) 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,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
MEMORY_WR -> False,
|
||||
MEMORY_MANAGMENT -> False
|
||||
MEMORY_WR -> False
|
||||
) ++ (if(catchSomething) List(HAS_SIDE_EFFECT -> True) else Nil)
|
||||
|
||||
val storeActions = stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMS,
|
||||
RS2_USE -> True,
|
||||
MEMORY_WR -> True,
|
||||
MEMORY_MANAGMENT -> False
|
||||
MEMORY_WR -> True
|
||||
)
|
||||
|
||||
decoderService.addDefault(MEMORY_ENABLE, False)
|
||||
|
@ -68,20 +83,21 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
List(SB, SH, SW).map(_ -> storeActions)
|
||||
)
|
||||
|
||||
if(genAtomic){
|
||||
if(withLrSc){
|
||||
List(LB, LH, LW, LBU, LHU, LWU, SB, SH, SW).foreach(e =>
|
||||
decoderService.add(e, Seq(MEMORY_ATOMIC -> False))
|
||||
)
|
||||
decoderService.add(
|
||||
key = LR,
|
||||
values = loadActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
SRC_ADD_ZERO -> True,
|
||||
MEMORY_ATOMIC -> True
|
||||
)
|
||||
)
|
||||
decoderService.add(
|
||||
key = SC,
|
||||
values = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC_ADD_ZERO -> True,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
|
@ -91,13 +107,16 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
}
|
||||
|
||||
def MANAGEMENT = M"-------00000-----101-----0001111"
|
||||
decoderService.add(MANAGEMENT, stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
RS2_USE -> True,
|
||||
|
||||
decoderService.addDefault(MEMORY_MANAGMENT, False)
|
||||
decoderService.add(MANAGEMENT, List(
|
||||
MEMORY_MANAGMENT -> True
|
||||
))
|
||||
|
||||
decoderService.add(FENCE, Nil)
|
||||
|
||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
|
||||
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.writeBack)
|
||||
|
||||
if(catchSomething)
|
||||
exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack)
|
||||
|
@ -105,25 +124,25 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
if(pipeline.serviceExist(classOf[PrivilegeService]))
|
||||
privilegeService = pipeline.service(classOf[PrivilegeService])
|
||||
|
||||
if(pipeline.serviceExist(classOf[ReportService])){
|
||||
val report = pipeline.service(classOf[ReportService])
|
||||
report.add("dBus" -> {
|
||||
val e = new BusReport()
|
||||
val c = new CacheReport()
|
||||
e.kind = "cached"
|
||||
e.flushInstructions.add(0x13 | (1 << 7)) ////ADDI x1, x0, 0
|
||||
for(idx <- 0 until cacheSize by bytePerLine){
|
||||
e.flushInstructions.add(0x7000500F + (1 << 15)) //Clean invalid data cache way x1
|
||||
e.flushInstructions.add(0x13 + (1 << 7) + (1 << 15) + (bytePerLine << 20)) //ADDI x1, x1, 32
|
||||
}
|
||||
|
||||
e.info = c
|
||||
c.size = cacheSize
|
||||
c.bytePerLine = bytePerLine
|
||||
|
||||
e
|
||||
})
|
||||
}
|
||||
// if(pipeline.serviceExist(classOf[ReportService])){
|
||||
// val report = pipeline.service(classOf[ReportService])
|
||||
// report.add("dBus" -> {
|
||||
// val e = new BusReport()
|
||||
// val c = new CacheReport()
|
||||
// e.kind = "cached"
|
||||
// e.flushInstructions.add(0x13 | (1 << 7)) ////ADDI x1, x0, 0
|
||||
// for(idx <- 0 until cacheSize by bytePerLine){
|
||||
// e.flushInstructions.add(0x7000500F + (1 << 15)) //Clean invalid data cache way x1
|
||||
// e.flushInstructions.add(0x13 + (1 << 7) + (1 << 15) + (bytePerLine << 20)) //ADDI x1, x1, 32
|
||||
// }
|
||||
//
|
||||
// e.info = c
|
||||
// c.size = cacheSize
|
||||
// c.bytePerLine = bytePerLine
|
||||
//
|
||||
// e
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -133,36 +152,45 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
dBus = master(DataCacheMemBus(this.config)).setName("dBus")
|
||||
|
||||
val cache = new DataCache(this.config)
|
||||
cache.io.mem <> dBus
|
||||
|
||||
//Interconnect the plugin dBus with the cache dBus with some optional pipelining
|
||||
def optionPipe[T](cond : Boolean, on : T)(f : T => T) : T = if(cond) f(on) else on
|
||||
def cmdBuf = optionPipe(dBusCmdSlavePipe, cache.io.mem.cmd)(_.s2mPipe())
|
||||
dBus.cmd << optionPipe(dBusCmdMasterPipe, cmdBuf)(_.m2sPipe())
|
||||
cache.io.mem.rsp << optionPipe(dBusRspSlavePipe,dBus.rsp)(_.m2sPipe())
|
||||
|
||||
|
||||
|
||||
execute plug new Area {
|
||||
import execute._
|
||||
|
||||
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.address := input(SRC_ADD).asUInt
|
||||
cache.io.cpu.execute.args.data := size.mux(
|
||||
U(0) -> input(RS2)( 7 downto 0) ## input(RS2)( 7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0),
|
||||
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
|
||||
default -> input(RS2)(31 downto 0)
|
||||
)
|
||||
cache.io.cpu.execute.args.size := size
|
||||
cache.io.cpu.execute.args.forceUncachedAccess := False
|
||||
cache.io.cpu.execute.args.kind := input(MEMORY_MANAGMENT) ? DataCacheCpuCmdKind.MANAGMENT | DataCacheCpuCmdKind.MEMORY
|
||||
cache.io.cpu.execute.args.clean := input(INSTRUCTION)(28)
|
||||
cache.io.cpu.execute.args.invalidate := input(INSTRUCTION)(29)
|
||||
cache.io.cpu.execute.args.way := input(INSTRUCTION)(30)
|
||||
if(genAtomic) {
|
||||
cache.io.cpu.execute.args.forceUncachedAccess := False
|
||||
|
||||
cache.io.cpu.flush.valid := arbitration.isValid && input(MEMORY_MANAGMENT)
|
||||
arbitration.haltItself setWhen(cache.io.cpu.flush.isStall)
|
||||
|
||||
if(withLrSc) {
|
||||
cache.io.cpu.execute.args.isAtomic := False
|
||||
when(input(MEMORY_ATOMIC)){
|
||||
cache.io.cpu.execute.args.isAtomic := True
|
||||
cache.io.cpu.execute.args.address := input(SRC1).asUInt
|
||||
}
|
||||
}
|
||||
|
||||
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.args.address(1 downto 0)
|
||||
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.address(1 downto 0)
|
||||
|
||||
when(cache.io.cpu.redo && arbitration.isValid && input(MEMORY_ENABLE)){
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
|
||||
memory plug new Area{
|
||||
|
@ -170,10 +198,9 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.memory.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.memory.isRemoved := arbitration.removeIt
|
||||
arbitration.haltItself setWhen(cache.io.cpu.memory.haltIt)
|
||||
cache.io.cpu.memory.address := U(input(REGFILE_WRITE_DATA))
|
||||
|
||||
cache.io.cpu.memory.mmuBus <> mmuBus
|
||||
arbitration.haltItself setWhen (mmuBus.cmd.isValid && ???) //TODO !mmuBus.rsp.hit && !mmuBus.rsp.miss
|
||||
}
|
||||
|
||||
writeBack plug new Area{
|
||||
|
@ -181,20 +208,36 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser() else False)
|
||||
if(genAtomic) cache.io.cpu.writeBack.clearAtomicEntries := service(classOf[IContextSwitching]).isContextSwitching
|
||||
cache.io.cpu.writeBack.address := U(input(REGFILE_WRITE_DATA))
|
||||
if(withLrSc) cache.io.cpu.writeBack.clearAtomicEntries := service(classOf[IContextSwitching]).isContextSwitching
|
||||
|
||||
if(catchSomething) {
|
||||
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
|
||||
exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr
|
||||
exceptionBus.valid := False //cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
|
||||
exceptionBus.badAddr := U(input(REGFILE_WRITE_DATA))
|
||||
exceptionBus.code.assignDontCare()
|
||||
when(cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError){
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(7) | U(5)).resized
|
||||
}
|
||||
when(cache.io.cpu.writeBack.unalignedAccess){
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(6) | U(4)).resized
|
||||
}
|
||||
when(cache.io.cpu.writeBack.mmuMiss){
|
||||
exceptionBus.code := 13
|
||||
|
||||
redoBranch.valid := False
|
||||
redoBranch.payload := input(PC)
|
||||
arbitration.flushAll setWhen(redoBranch.valid)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if (catchUnaligned) when(cache.io.cpu.writeBack.unalignedAccess) {
|
||||
exceptionBus.valid := True
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(6) | U(4)).resized
|
||||
}
|
||||
when (cache.io.cpu.writeBack.mmuException) {
|
||||
exceptionBus.valid := True
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(15) | U(13)).resized
|
||||
}
|
||||
when(cache.io.cpu.redo) {
|
||||
redoBranch.valid := True
|
||||
exceptionBus.valid := False
|
||||
}
|
||||
}
|
||||
}
|
||||
arbitration.haltItself.setWhen(cache.io.cpu.writeBack.haltIt)
|
||||
|
@ -218,6 +261,48 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
}
|
||||
}
|
||||
|
||||
//Share access to the dBus (used by self refilled MMU)
|
||||
if(dBusAccess != null) 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 := False
|
||||
if(withLrSc) 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.redo || !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
|
||||
dBusAccess.rsp.redo := cache.io.cpu.redo
|
||||
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)
|
||||
when(dBusAccess.rsp.valid){
|
||||
writeBack.input(IS_DBUS_SHARING).getDrivingReg := False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(csrInfo){
|
||||
val csr = service(classOf[CsrPlugin])
|
||||
csr.r(0xCC0, 0 -> U(cacheSize/wayCount), 20 -> U(bytePerLine))
|
||||
|
|
|
@ -205,12 +205,11 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
earlyInjection : Boolean = false, /*, idempotentRegions : (UInt) => Bool = (x) => False*/
|
||||
emitCmdInMemoryStage : Boolean = false,
|
||||
onlyLoadWords : Boolean = false,
|
||||
atomicEntriesCount : Int = 0,
|
||||
withLrSc : Boolean = false,
|
||||
memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] with DBusAccessService {
|
||||
|
||||
var dBus : DBusSimpleBus = null
|
||||
assert(!(emitCmdInMemoryStage && earlyInjection))
|
||||
def genAtomic = atomicEntriesCount != 0
|
||||
object MEMORY_ENABLE extends Stageable(Bool)
|
||||
object MEMORY_READ_DATA extends Stageable(Bits(32 bits))
|
||||
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
||||
|
@ -269,7 +268,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
)
|
||||
|
||||
|
||||
if(genAtomic){
|
||||
if(withLrSc){
|
||||
List(LB, LH, LW, LBU, LHU, LWU, SB, SH, SW).foreach(e =>
|
||||
decoderService.add(e, Seq(MEMORY_ATOMIC -> False))
|
||||
)
|
||||
|
@ -280,7 +279,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
MEMORY_ATOMIC -> True
|
||||
)
|
||||
)
|
||||
//TODO probably the cached implemention of SC is bugy (address calculation)
|
||||
|
||||
decoderService.add(
|
||||
key = SC,
|
||||
values = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
|
@ -293,6 +292,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
)
|
||||
}
|
||||
|
||||
decoderService.add(FENCE, Nil)
|
||||
|
||||
rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
|
||||
if(catchSomething) {
|
||||
|
@ -362,7 +362,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
dBus.cmd.address := mmuBus.rsp.physicalAddress
|
||||
|
||||
//do not emit memory request if MMU refilling
|
||||
insert(MMU_FAULT) := input(MMU_RSP).exception || (!input(MMU_RSP).allowWrite && input(MEMORY_STORE)) || (!input(MMU_RSP).allowRead && !input(MEMORY_STORE)) || (!input(MMU_RSP).allowUser && privilegeService.isUser())
|
||||
insert(MMU_FAULT) := input(MMU_RSP).exception || (!input(MMU_RSP).allowWrite && input(MEMORY_STORE)) || (!input(MMU_RSP).allowRead && !input(MEMORY_STORE))
|
||||
skipCmd.setWhen(input(MMU_FAULT) || input(MMU_RSP).refilling)
|
||||
|
||||
insert(MMU_RSP) := mmuBus.rsp
|
||||
|
@ -373,29 +373,14 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
}
|
||||
|
||||
|
||||
val atomic = genAtomic generate new Area{
|
||||
val address = input(SRC_ADD).asUInt
|
||||
case class AtomicEntry() extends Bundle{
|
||||
val valid = Bool()
|
||||
val address = UInt(32 bits)
|
||||
|
||||
def init: this.type ={
|
||||
valid init(False)
|
||||
this
|
||||
}
|
||||
}
|
||||
val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount)
|
||||
val entriesAllocCounter = Counter(atomicEntriesCount)
|
||||
insert(ATOMIC_HIT) := entries.map(e => e.valid && e.address === address).orR
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE) && input(MEMORY_ATOMIC) && !input(MEMORY_STORE)){
|
||||
entries(entriesAllocCounter).valid := True
|
||||
entries(entriesAllocCounter).address := address
|
||||
when(!arbitration.isStuck){
|
||||
entriesAllocCounter.increment()
|
||||
}
|
||||
val atomic = withLrSc generate new Area{
|
||||
val reserved = RegInit(False)
|
||||
insert(ATOMIC_HIT) := reserved
|
||||
when(arbitration.isFiring && input(MEMORY_ENABLE) && input(MEMORY_ATOMIC) && !input(MEMORY_STORE)){
|
||||
reserved := True
|
||||
}
|
||||
when(service(classOf[IContextSwitching]).isContextSwitching){
|
||||
entries.foreach(_.valid := False)
|
||||
reserved := False
|
||||
}
|
||||
|
||||
when(input(MEMORY_STORE) && input(MEMORY_ATOMIC) && !input(ATOMIC_HIT)){
|
||||
|
@ -476,7 +461,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE)) {
|
||||
output(REGFILE_WRITE_DATA) := (if(!onlyLoadWords) rspFormated else input(MEMORY_READ_DATA))
|
||||
if(genAtomic){
|
||||
if(withLrSc){
|
||||
when(input(MEMORY_ATOMIC) && input(MEMORY_STORE)){
|
||||
output(REGFILE_WRITE_DATA) := (!input(ATOMIC_HIT)).asBits.resized
|
||||
}
|
||||
|
@ -497,6 +482,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
dBusAccess.rsp.valid := False
|
||||
dBusAccess.rsp.data := dBus.rsp.data
|
||||
dBusAccess.rsp.error := dBus.rsp.error
|
||||
dBusAccess.rsp.redo := False
|
||||
|
||||
switch(state){
|
||||
is(0){
|
||||
|
|
|
@ -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._
|
||||
|
|
|
@ -47,6 +47,10 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
injectorStage = (!config.twoCycleCache && !withoutInjectorStage) || injectorStage){
|
||||
import config._
|
||||
|
||||
assert(isPow2(cacheSize))
|
||||
assert(!(memoryTranslatorPortConfig != null && config.cacheSize/config.wayCount > 4096), "When the I$ is used with MMU, each way can't be bigger than a page (4096 bytes)")
|
||||
|
||||
|
||||
assert(!(withoutInjectorStage && injectorStage))
|
||||
|
||||
var iBus : InstructionCacheMemBus = null
|
||||
|
@ -74,8 +78,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
|
||||
super.setup(pipeline)
|
||||
|
||||
//def MANAGEMENT = M"-----------------100-----0001111"
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.addDefault(FLUSH_ALL, False)
|
||||
decoderService.add(FENCE_I, List(
|
||||
|
@ -203,7 +205,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
if (catchSomething) {
|
||||
decodeExceptionPort.valid := False
|
||||
decodeExceptionPort.code.assignDontCare()
|
||||
decodeExceptionPort.badAddr := cacheRsp.pc
|
||||
decodeExceptionPort.badAddr := cacheRsp.pc(31 downto 2) @@ "00"
|
||||
|
||||
if(catchIllegalAccess) when(cacheRsp.isValid && cacheRsp.mmuException && !issueDetected) {
|
||||
issueDetected \= True
|
||||
|
@ -216,9 +218,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
decodeExceptionPort.code := 1
|
||||
}
|
||||
decodeExceptionPort.valid clearWhen(fetcherHalt)
|
||||
}
|
||||
|
||||
decodeExceptionPort.valid clearWhen(fetcherHalt)
|
||||
|
||||
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
|
||||
iBusRsp.output.valid := cacheRspArbitration.output.valid
|
||||
|
@ -234,25 +236,13 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowUser := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := 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
|
||||
flushStage plug new Area {
|
||||
import flushStage._
|
||||
|
||||
cache.io.flush.cmd.valid := False
|
||||
when(arbitration.isValid && input(FLUSH_ALL)) {
|
||||
cache.io.flush.cmd.valid := True
|
||||
|
||||
when(!cache.io.flush.cmd.ready) {
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
}
|
||||
val flushStage = decode
|
||||
cache.io.flush := flushStage.arbitration.isValid && flushStage.input(FLUSH_ALL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import spinal.lib.bus.amba4.axi._
|
|||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||
import spinal.lib.bus.simple._
|
||||
import vexriscv.Riscv.{FENCE, FENCE_I}
|
||||
|
||||
|
||||
case class IBusSimpleCmd() extends Bundle{
|
||||
|
@ -192,6 +193,9 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
super.setup(pipeline)
|
||||
iBus = master(IBusSimpleBus(false)).setName("iBus")
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.add(FENCE_I, Nil)
|
||||
|
||||
if(catchSomething) {
|
||||
decodeExceptionPort = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.decode,1)
|
||||
}
|
||||
|
@ -317,7 +321,7 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
}
|
||||
if(memoryTranslatorPortConfig != null) {
|
||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||
when(stages.last.input.valid && !mmu.joinCtx.refilling && (mmu.joinCtx.exception || !mmu.joinCtx.allowExecute || (!mmu.joinCtx.allowUser && privilegeService.isUser()))){
|
||||
when(stages.last.input.valid && !mmu.joinCtx.refilling && (mmu.joinCtx.exception || !mmu.joinCtx.allowExecute)){
|
||||
decodeExceptionPort.code := 12
|
||||
exceptionDetected := True
|
||||
}
|
||||
|
|
|
@ -112,7 +112,6 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
|||
port.bus.rsp.allowRead := cacheLine.allowRead
|
||||
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
||||
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
||||
port.bus.rsp.allowUser := cacheLine.allowUser
|
||||
???
|
||||
// port.bus.rsp.hit := cacheHit
|
||||
// port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss)
|
||||
|
@ -121,7 +120,6 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
|||
port.bus.rsp.allowRead := True
|
||||
port.bus.rsp.allowWrite := True
|
||||
port.bus.rsp.allowExecute := True
|
||||
port.bus.rsp.allowUser := True
|
||||
???
|
||||
// port.bus.rsp.hit := True
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ case class DBusAccessCmd() extends Bundle {
|
|||
case class DBusAccessRsp() extends Bundle {
|
||||
val data = Bits(32 bits)
|
||||
val error = Bool()
|
||||
val redo = Bool()
|
||||
}
|
||||
|
||||
case class DBusAccess() extends Bundle {
|
||||
|
@ -37,17 +38,16 @@ case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConf
|
|||
|
||||
case class MmuPortConfig(portTlbSize : Int)
|
||||
|
||||
class MmuPlugin(virtualRange : UInt => Bool,
|
||||
ioRange : UInt => Bool,
|
||||
allowUserIo : Boolean,
|
||||
allowMachineModeMmu : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||
class MmuPlugin(ioRange : UInt => Bool,
|
||||
virtualRange : UInt => Bool = address => True,
|
||||
// allowUserIo : Boolean = false,
|
||||
enableMmuInMachineMode : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||
|
||||
var dBusAccess : DBusAccess = null
|
||||
val portsInfo = ArrayBuffer[MmuPort]()
|
||||
|
||||
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 /*,exceptionBus*/)
|
||||
val port = MmuPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MmuPortConfig], portsInfo.length)
|
||||
portsInfo += port
|
||||
port.bus
|
||||
}
|
||||
|
@ -95,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)
|
||||
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 {
|
||||
|
@ -108,7 +108,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||
val entryToReplace = Counter(port.args.portTlbSize)
|
||||
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())
|
||||
when(privilegeService.isMachine()) {
|
||||
if (port.priority == MmuPort.PRIORITY_DATA) {
|
||||
|
@ -124,15 +124,13 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
port.bus.rsp.allowRead := cacheLine.allowRead || csr.status.mxr && cacheLine.allowExecute
|
||||
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
||||
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
||||
port.bus.rsp.allowUser := cacheLine.allowUser
|
||||
port.bus.rsp.exception := cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum)
|
||||
port.bus.rsp.exception := cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum || !cacheLine.allowUser && privilegeService.isUser())
|
||||
port.bus.rsp.refilling := !cacheHit
|
||||
} otherwise {
|
||||
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
|
||||
port.bus.rsp.allowRead := True
|
||||
port.bus.rsp.allowWrite := True
|
||||
port.bus.rsp.allowExecute := True
|
||||
port.bus.rsp.allowUser := Bool(allowUserIo)
|
||||
port.bus.rsp.exception := False
|
||||
port.bus.rsp.refilling := False
|
||||
}
|
||||
|
@ -161,7 +159,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
val leaf = pte.R || pte.X
|
||||
}
|
||||
|
||||
val pteBuffer = RegNextWhen(dBusRsp.pte, dBusAccess.rsp.valid)
|
||||
val pteBuffer = RegNextWhen(dBusRsp.pte, dBusAccess.rsp.valid && !dBusAccess.rsp.redo)
|
||||
|
||||
dBusAccess.cmd.valid := False
|
||||
dBusAccess.cmd.write := False
|
||||
|
@ -190,10 +188,12 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
}
|
||||
is(State.L1_RSP){
|
||||
when(dBusAccess.rsp.valid){
|
||||
state := State.L0_CMD
|
||||
when(dBusRsp.leaf || dBusRsp.exception){
|
||||
state := State.IDLE
|
||||
} otherwise {
|
||||
state := State.L0_CMD
|
||||
}
|
||||
when(dBusAccess.rsp.redo){
|
||||
state := State.L1_CMD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,11 +207,14 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
is(State.L0_RSP){
|
||||
when(dBusAccess.rsp.valid) {
|
||||
state := State.IDLE
|
||||
when(dBusAccess.rsp.redo){
|
||||
state := State.L0_CMD
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(dBusAccess.rsp.valid && (dBusRsp.leaf || dBusRsp.exception)){
|
||||
when(dBusAccess.rsp.valid && !dBusAccess.rsp.redo && (dBusRsp.leaf || dBusRsp.exception)){
|
||||
for(port <- ports){
|
||||
when(portId === port.id) {
|
||||
port.entryToReplace.increment()
|
||||
|
|
|
@ -31,11 +31,9 @@ class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRis
|
|||
port.bus.rsp.allowRead := True
|
||||
port.bus.rsp.allowWrite := True
|
||||
port.bus.rsp.allowExecute := True
|
||||
port.bus.rsp.allowUser := True
|
||||
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
|
||||
???
|
||||
// port.bus.rsp.miss := False
|
||||
// port.bus.rsp.hit := True
|
||||
port.bus.rsp.exception := False
|
||||
port.bus.rsp.refilling := False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
src/test/cpp/raw/dcache/.gitignore
vendored
Normal file
4
src/test/cpp/raw/dcache/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
79
src/test/cpp/raw/dcache/build/dcache.asm
Normal file
79
src/test/cpp/raw/dcache/build/dcache.asm
Normal file
|
@ -0,0 +1,79 @@
|
|||
|
||||
build/dcache.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .crt_section:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00000097 auipc ra,0x0
|
||||
80000004: 0b808093 addi ra,ra,184 # 800000b8 <fail>
|
||||
80000008: 30509073 csrw mtvec,ra
|
||||
|
||||
8000000c <test1>:
|
||||
8000000c: 00100e13 li t3,1
|
||||
80000010: 00100093 li ra,1
|
||||
80000014: 00300113 li sp,3
|
||||
80000018: 00208093 addi ra,ra,2
|
||||
8000001c: 08209e63 bne ra,sp,800000b8 <fail>
|
||||
|
||||
80000020 <test2>:
|
||||
80000020: 00200e13 li t3,2
|
||||
80000024: f56700b7 lui ra,0xf5670
|
||||
80000028: 900ff137 lui sp,0x900ff
|
||||
8000002c: 40000313 li t1,1024
|
||||
|
||||
80000030 <test2_repeat>:
|
||||
80000030: 00100193 li gp,1
|
||||
80000034: 00200293 li t0,2
|
||||
80000038: 006303b3 add t2,t1,t1
|
||||
8000003c: 007181b3 add gp,gp,t2
|
||||
80000040: 007282b3 add t0,t0,t2
|
||||
80000044: 00312023 sw gp,0(sp) # 900ff000 <pass+0x100fef3c>
|
||||
80000048: 0000a023 sw zero,0(ra) # f5670000 <pass+0x7566ff3c>
|
||||
8000004c: 00012203 lw tp,0(sp)
|
||||
80000050: 06429463 bne t0,tp,800000b8 <fail>
|
||||
80000054: ffc30313 addi t1,t1,-4
|
||||
80000058: 01008093 addi ra,ra,16
|
||||
8000005c: 01010113 addi sp,sp,16
|
||||
80000060: 0000500f 0x500f
|
||||
80000064: fc0316e3 bnez t1,80000030 <test2_repeat>
|
||||
|
||||
80000068 <test3>:
|
||||
80000068: 00300e13 li t3,3
|
||||
8000006c: f56700b7 lui ra,0xf5670
|
||||
80000070: 900ff137 lui sp,0x900ff
|
||||
80000074: 40000313 li t1,1024
|
||||
|
||||
80000078 <test3_repeat>:
|
||||
80000078: 00200193 li gp,2
|
||||
8000007c: 00300293 li t0,3
|
||||
80000080: 006303b3 add t2,t1,t1
|
||||
80000084: 007181b3 add gp,gp,t2
|
||||
80000088: 007282b3 add t0,t0,t2
|
||||
8000008c: 00012203 lw tp,0(sp) # 900ff000 <pass+0x100fef3c>
|
||||
80000090: 00312023 sw gp,0(sp)
|
||||
80000094: 0000a023 sw zero,0(ra) # f5670000 <pass+0x7566ff3c>
|
||||
80000098: 0000500f 0x500f
|
||||
8000009c: 00012203 lw tp,0(sp)
|
||||
800000a0: 00429c63 bne t0,tp,800000b8 <fail>
|
||||
800000a4: ffc30313 addi t1,t1,-4
|
||||
800000a8: 01008093 addi ra,ra,16
|
||||
800000ac: 01010113 addi sp,sp,16
|
||||
800000b0: fc0314e3 bnez t1,80000078 <test3_repeat>
|
||||
800000b4: 0100006f j 800000c4 <pass>
|
||||
|
||||
800000b8 <fail>:
|
||||
800000b8: f0100137 lui sp,0xf0100
|
||||
800000bc: f2410113 addi sp,sp,-220 # f00fff24 <pass+0x700ffe60>
|
||||
800000c0: 01c12023 sw t3,0(sp)
|
||||
|
||||
800000c4 <pass>:
|
||||
800000c4: f0100137 lui sp,0xf0100
|
||||
800000c8: f2010113 addi sp,sp,-224 # f00fff20 <pass+0x700ffe5c>
|
||||
800000cc: 00012023 sw zero,0(sp)
|
||||
800000d0: 00000013 nop
|
||||
800000d4: 00000013 nop
|
||||
800000d8: 00000013 nop
|
||||
800000dc: 00000013 nop
|
||||
800000e0: 00000013 nop
|
||||
800000e4: 00000013 nop
|
17
src/test/cpp/raw/dcache/build/dcache.hex
Normal file
17
src/test/cpp/raw/dcache/build/dcache.hex
Normal file
|
@ -0,0 +1,17 @@
|
|||
:0200000480007A
|
||||
:10000000970000009380800B73905030130E100007
|
||||
:10001000930010001301300093802000639E20089D
|
||||
:10002000130E2000B70067F537F10F90130300405F
|
||||
:100030009301100093022000B3036300B3817100A9
|
||||
:10004000B38272002320310023A0000003220100AC
|
||||
:10005000639442061303C3FF93800001130101015F
|
||||
:100060000F500000E31603FC130E3000B70067F5D5
|
||||
:1000700037F10F90130300409301200093023000EA
|
||||
:10008000B3036300B3817100B382720003220100E5
|
||||
:100090002320310023A000000F50000003220100A4
|
||||
:1000A000639C42001303C3FF93800001130101010D
|
||||
:1000B000E31403FC6F000001370110F0130141F25B
|
||||
:1000C0002320C101370110F0130101F223200100A8
|
||||
:1000D00013000000130000001300000013000000D4
|
||||
:0800E0001300000013000000F2
|
||||
:00000001FF
|
3
src/test/cpp/raw/dcache/makefile
Normal file
3
src/test/cpp/raw/dcache/makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
PROJ_NAME=dcache
|
||||
|
||||
include ../common/asm.mk
|
75
src/test/cpp/raw/dcache/src/crt.S
Normal file
75
src/test/cpp/raw/dcache/src/crt.S
Normal file
|
@ -0,0 +1,75 @@
|
|||
.globl _star
|
||||
#define TEST_ID x28
|
||||
|
||||
_start:
|
||||
la x1, fail
|
||||
csrw mtvec, x1
|
||||
|
||||
test1: //Dummy test
|
||||
li TEST_ID, 1
|
||||
li x1, 1
|
||||
li x2, 3
|
||||
addi x1, x1, 2
|
||||
bne x1, x2, fail
|
||||
|
||||
test2: //No invalidate, without load => new one
|
||||
li TEST_ID, 2
|
||||
li x1, 0xF5670000
|
||||
li x2, 0x900FF000
|
||||
li x6, 4096/4
|
||||
test2_repeat:
|
||||
la x3, 1
|
||||
la x5, 2
|
||||
add x7, x6, x6
|
||||
add x3, x3, x7
|
||||
add x5, x5, x7
|
||||
sw x3, 0(x2)
|
||||
sw x0, 0(x1)
|
||||
lw x4, 0(x2)
|
||||
bne x5,x4, fail
|
||||
addi x6, x6, -4
|
||||
addi x1, x1, 16
|
||||
addi x2, x2, 16
|
||||
.word 0x000500F // dcache flush
|
||||
bnez x6, test2_repeat
|
||||
|
||||
test3: //with invalidate, with preload
|
||||
li TEST_ID, 3
|
||||
li x1, 0xF5670000
|
||||
li x2, 0x900FF000
|
||||
li x6, 4096/4
|
||||
test3_repeat:
|
||||
la x3, 2
|
||||
la x5, 3
|
||||
add x7, x6, x6
|
||||
add x3, x3, x7
|
||||
add x5, x5, x7
|
||||
lw x4, 0(x2)
|
||||
sw x3, 0(x2)
|
||||
sw x0, 0(x1)
|
||||
.word 0x000500F // dcache flush
|
||||
lw x4, 0(x2)
|
||||
bne x5,x4, fail
|
||||
addi x6, x6, -4
|
||||
addi x1, x1, 16
|
||||
addi x2, x2, 16
|
||||
bnez x6, test3_repeat
|
||||
|
||||
|
||||
|
||||
j pass
|
||||
|
||||
fail:
|
||||
li x2, 0xF00FFF24
|
||||
sw TEST_ID, 0(x2)
|
||||
|
||||
pass:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
16
src/test/cpp/raw/dcache/src/ld
Normal file
16
src/test/cpp/raw/dcache/src/ld
Normal file
|
@ -0,0 +1,16 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY {
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.crt_section :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*crt.o(.text)
|
||||
} > onChipRam
|
||||
|
||||
}
|
|
@ -7,14 +7,14 @@ Disassembly of section .crt_section:
|
|||
80000000 <_start>:
|
||||
80000000: 00100e93 li t4,1
|
||||
80000004: 00000097 auipc ra,0x0
|
||||
80000008: 68408093 addi ra,ra,1668 # 80000688 <mtrap>
|
||||
80000008: 6fc08093 addi ra,ra,1788 # 80000700 <mtrap>
|
||||
8000000c: 30509073 csrw mtvec,ra
|
||||
80000010: 00000097 auipc ra,0x0
|
||||
80000014: 6b008093 addi ra,ra,1712 # 800006c0 <strap>
|
||||
80000014: 72808093 addi ra,ra,1832 # 80000738 <strap>
|
||||
80000018: 10509073 csrw stvec,ra
|
||||
8000001c: f00110b7 lui ra,0xf0011
|
||||
80000020: 00000113 li sp,0
|
||||
80000024: 0020a023 sw sp,0(ra) # f0011000 <strap+0x70010940>
|
||||
80000024: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
|
||||
80000028 <test1>:
|
||||
80000028: 00100e13 li t3,1
|
||||
|
@ -33,18 +33,18 @@ Disassembly of section .crt_section:
|
|||
80000054: 01408093 addi ra,ra,20 # 80000064 <test2+0x2c>
|
||||
80000058: 34109073 csrw mepc,ra
|
||||
8000005c: 30200073 mret
|
||||
80000060: 6100006f j 80000670 <fail>
|
||||
80000060: 6880006f j 800006e8 <fail>
|
||||
80000064: 00000f17 auipc t5,0x0
|
||||
80000068: 024f0f13 addi t5,t5,36 # 80000088 <test4>
|
||||
8000006c: 00000073 ecall
|
||||
80000070: 6000006f j 80000670 <fail>
|
||||
80000070: 6780006f j 800006e8 <fail>
|
||||
|
||||
80000074 <test3>:
|
||||
80000074: 00300e13 li t3,3
|
||||
80000078: 00000f17 auipc t5,0x0
|
||||
8000007c: 010f0f13 addi t5,t5,16 # 80000088 <test4>
|
||||
80000080: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000084: 5ec0006f j 80000670 <fail>
|
||||
80000084: 6640006f j 800006e8 <fail>
|
||||
|
||||
80000088 <test4>:
|
||||
80000088: 00400e13 li t3,4
|
||||
|
@ -58,11 +58,11 @@ Disassembly of section .crt_section:
|
|||
800000a8: 01408093 addi ra,ra,20 # 800000b8 <test4+0x30>
|
||||
800000ac: 34109073 csrw mepc,ra
|
||||
800000b0: 30200073 mret
|
||||
800000b4: 5bc0006f j 80000670 <fail>
|
||||
800000b4: 6340006f j 800006e8 <fail>
|
||||
800000b8: 00000f17 auipc t5,0x0
|
||||
800000bc: 010f0f13 addi t5,t5,16 # 800000c8 <test5>
|
||||
800000c0: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
800000c4: 5ac0006f j 80000670 <fail>
|
||||
800000c4: 6240006f j 800006e8 <fail>
|
||||
|
||||
800000c8 <test5>:
|
||||
800000c8: 00500e13 li t3,5
|
||||
|
@ -75,11 +75,11 @@ Disassembly of section .crt_section:
|
|||
800000e4: 01408093 addi ra,ra,20 # 800000f4 <test5+0x2c>
|
||||
800000e8: 34109073 csrw mepc,ra
|
||||
800000ec: 30200073 mret
|
||||
800000f0: 5800006f j 80000670 <fail>
|
||||
800000f0: 5f80006f j 800006e8 <fail>
|
||||
800000f4: 00000f17 auipc t5,0x0
|
||||
800000f8: 010f0f13 addi t5,t5,16 # 80000104 <test6>
|
||||
800000fc: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000100: 5700006f j 80000670 <fail>
|
||||
80000100: 5e80006f j 800006e8 <fail>
|
||||
|
||||
80000104 <test6>:
|
||||
80000104: 00600e13 li t3,6
|
||||
|
@ -91,7 +91,7 @@ Disassembly of section .crt_section:
|
|||
80000114: 00000f17 auipc t5,0x0
|
||||
80000118: 010f0f13 addi t5,t5,16 # 80000124 <test8>
|
||||
8000011c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000120: 5500006f j 80000670 <fail>
|
||||
80000120: 5c80006f j 800006e8 <fail>
|
||||
|
||||
80000124 <test8>:
|
||||
80000124: 00800e13 li t3,8
|
||||
|
@ -107,9 +107,9 @@ Disassembly of section .crt_section:
|
|||
8000014c: 01408093 addi ra,ra,20 # 8000015c <test8+0x38>
|
||||
80000150: 34109073 csrw mepc,ra
|
||||
80000154: 30200073 mret
|
||||
80000158: 5180006f j 80000670 <fail>
|
||||
80000158: 5900006f j 800006e8 <fail>
|
||||
8000015c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000160: 5100006f j 80000670 <fail>
|
||||
80000160: 5880006f j 800006e8 <fail>
|
||||
|
||||
80000164 <test9>:
|
||||
80000164: 00900e13 li t3,9
|
||||
|
@ -124,9 +124,9 @@ Disassembly of section .crt_section:
|
|||
80000188: 01408093 addi ra,ra,20 # 80000198 <test9+0x34>
|
||||
8000018c: 34109073 csrw mepc,ra
|
||||
80000190: 30200073 mret
|
||||
80000194: 4dc0006f j 80000670 <fail>
|
||||
80000194: 5540006f j 800006e8 <fail>
|
||||
80000198: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
8000019c: 4d40006f j 80000670 <fail>
|
||||
8000019c: 54c0006f j 800006e8 <fail>
|
||||
|
||||
800001a0 <test10>:
|
||||
800001a0: 00a00e13 li t3,10
|
||||
|
@ -134,7 +134,7 @@ Disassembly of section .crt_section:
|
|||
800001a8: 03cf0f13 addi t5,t5,60 # 800001e0 <test11>
|
||||
800001ac: f00110b7 lui ra,0xf0011
|
||||
800001b0: 00000113 li sp,0
|
||||
800001b4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x70010940>
|
||||
800001b4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800001b8: 00800093 li ra,8
|
||||
800001bc: 30009073 csrw mstatus,ra
|
||||
800001c0: 000010b7 lui ra,0x1
|
||||
|
@ -142,9 +142,9 @@ Disassembly of section .crt_section:
|
|||
800001c8: 30409073 csrw mie,ra
|
||||
800001cc: f00110b7 lui ra,0xf0011
|
||||
800001d0: 00100113 li sp,1
|
||||
800001d4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x70010940>
|
||||
800001d4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800001d8: 10500073 wfi
|
||||
800001dc: 4940006f j 80000670 <fail>
|
||||
800001dc: 50c0006f j 800006e8 <fail>
|
||||
|
||||
800001e0 <test11>:
|
||||
800001e0: 00b00e13 li t3,11
|
||||
|
@ -152,7 +152,7 @@ Disassembly of section .crt_section:
|
|||
800001e8: 068f0f13 addi t5,t5,104 # 8000024c <test12>
|
||||
800001ec: f00110b7 lui ra,0xf0011
|
||||
800001f0: 00000113 li sp,0
|
||||
800001f4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x70010940>
|
||||
800001f4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800001f8: 00800093 li ra,8
|
||||
800001fc: 30009073 csrw mstatus,ra
|
||||
80000200: 000010b7 lui ra,0x1
|
||||
|
@ -168,12 +168,12 @@ Disassembly of section .crt_section:
|
|||
80000228: 01408093 addi ra,ra,20 # 80000238 <test11+0x58>
|
||||
8000022c: 34109073 csrw mepc,ra
|
||||
80000230: 30200073 mret
|
||||
80000234: 43c0006f j 80000670 <fail>
|
||||
80000234: 4b40006f j 800006e8 <fail>
|
||||
80000238: f00110b7 lui ra,0xf0011
|
||||
8000023c: 00100113 li sp,1
|
||||
80000240: 0020a023 sw sp,0(ra) # f0011000 <strap+0x70010940>
|
||||
80000240: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
80000244: 10500073 wfi
|
||||
80000248: 4280006f j 80000670 <fail>
|
||||
80000248: 4a00006f j 800006e8 <fail>
|
||||
|
||||
8000024c <test12>:
|
||||
8000024c: 00c00e13 li t3,12
|
||||
|
@ -181,7 +181,7 @@ Disassembly of section .crt_section:
|
|||
80000254: 064f0f13 addi t5,t5,100 # 800002b4 <test14>
|
||||
80000258: f00110b7 lui ra,0xf0011
|
||||
8000025c: 00000113 li sp,0
|
||||
80000260: 0020a023 sw sp,0(ra) # f0011000 <strap+0x70010940>
|
||||
80000260: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
80000264: 00800093 li ra,8
|
||||
80000268: 30009073 csrw mstatus,ra
|
||||
8000026c: 000010b7 lui ra,0x1
|
||||
|
@ -196,12 +196,12 @@ Disassembly of section .crt_section:
|
|||
80000290: 01408093 addi ra,ra,20 # 800002a0 <test12+0x54>
|
||||
80000294: 34109073 csrw mepc,ra
|
||||
80000298: 30200073 mret
|
||||
8000029c: 3d40006f j 80000670 <fail>
|
||||
8000029c: 44c0006f j 800006e8 <fail>
|
||||
800002a0: f00110b7 lui ra,0xf0011
|
||||
800002a4: 00100113 li sp,1
|
||||
800002a8: 0020a023 sw sp,0(ra) # f0011000 <strap+0x70010940>
|
||||
800002a8: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800002ac: 10500073 wfi
|
||||
800002b0: 3c00006f j 80000670 <fail>
|
||||
800002b0: 4380006f j 800006e8 <fail>
|
||||
|
||||
800002b4 <test14>:
|
||||
800002b4: 00200093 li ra,2
|
||||
|
@ -211,7 +211,7 @@ Disassembly of section .crt_section:
|
|||
800002c4: 040f0f13 addi t5,t5,64 # 80000300 <test15>
|
||||
800002c8: f00120b7 lui ra,0xf0012
|
||||
800002cc: 00000113 li sp,0
|
||||
800002d0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
800002d0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800002d4: 00200093 li ra,2
|
||||
800002d8: 30009073 csrw mstatus,ra
|
||||
800002dc: 20000093 li ra,512
|
||||
|
@ -219,7 +219,7 @@ Disassembly of section .crt_section:
|
|||
800002e4: 00000e93 li t4,0
|
||||
800002e8: f00120b7 lui ra,0xf0012
|
||||
800002ec: 00100113 li sp,1
|
||||
800002f0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
800002f0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800002f4: 06400093 li ra,100
|
||||
800002f8: fff08093 addi ra,ra,-1
|
||||
800002fc: fe104ee3 bgtz ra,800002f8 <test14+0x44>
|
||||
|
@ -230,7 +230,7 @@ Disassembly of section .crt_section:
|
|||
80000308: 068f0f13 addi t5,t5,104 # 8000036c <test16>
|
||||
8000030c: f00120b7 lui ra,0xf0012
|
||||
80000310: 00000113 li sp,0
|
||||
80000314: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
80000314: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000318: 00200093 li ra,2
|
||||
8000031c: 30009073 csrw mstatus,ra
|
||||
80000320: 20000093 li ra,512
|
||||
|
@ -245,13 +245,13 @@ Disassembly of section .crt_section:
|
|||
80000344: 01408093 addi ra,ra,20 # 80000354 <test15+0x54>
|
||||
80000348: 34109073 csrw mepc,ra
|
||||
8000034c: 30200073 mret
|
||||
80000350: 3200006f j 80000670 <fail>
|
||||
80000350: 3980006f j 800006e8 <fail>
|
||||
80000354: 00100e93 li t4,1
|
||||
80000358: f00120b7 lui ra,0xf0012
|
||||
8000035c: 00100113 li sp,1
|
||||
80000360: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
80000360: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000364: 10500073 wfi
|
||||
80000368: 3080006f j 80000670 <fail>
|
||||
80000368: 3800006f j 800006e8 <fail>
|
||||
|
||||
8000036c <test16>:
|
||||
8000036c: 01000e13 li t3,16
|
||||
|
@ -259,7 +259,7 @@ Disassembly of section .crt_section:
|
|||
80000374: 060f0f13 addi t5,t5,96 # 800003d0 <test17>
|
||||
80000378: f00120b7 lui ra,0xf0012
|
||||
8000037c: 00000113 li sp,0
|
||||
80000380: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
80000380: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000384: 00200093 li ra,2
|
||||
80000388: 30009073 csrw mstatus,ra
|
||||
8000038c: 20000093 li ra,512
|
||||
|
@ -273,12 +273,12 @@ Disassembly of section .crt_section:
|
|||
800003ac: 01408093 addi ra,ra,20 # 800003bc <test16+0x50>
|
||||
800003b0: 34109073 csrw mepc,ra
|
||||
800003b4: 30200073 mret
|
||||
800003b8: 2b80006f j 80000670 <fail>
|
||||
800003b8: 3300006f j 800006e8 <fail>
|
||||
800003bc: f00120b7 lui ra,0xf0012
|
||||
800003c0: 00100113 li sp,1
|
||||
800003c4: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
800003c4: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800003c8: 10500073 wfi
|
||||
800003cc: 2a40006f j 80000670 <fail>
|
||||
800003cc: 31c0006f j 800006e8 <fail>
|
||||
|
||||
800003d0 <test17>:
|
||||
800003d0: 01100e13 li t3,17
|
||||
|
@ -288,7 +288,7 @@ Disassembly of section .crt_section:
|
|||
800003e0: 040f0f13 addi t5,t5,64 # 8000041c <test18>
|
||||
800003e4: f00120b7 lui ra,0xf0012
|
||||
800003e8: 00000113 li sp,0
|
||||
800003ec: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
800003ec: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800003f0: 00200093 li ra,2
|
||||
800003f4: 30009073 csrw mstatus,ra
|
||||
800003f8: 20000093 li ra,512
|
||||
|
@ -296,7 +296,7 @@ Disassembly of section .crt_section:
|
|||
80000400: 00000e93 li t4,0
|
||||
80000404: f00120b7 lui ra,0xf0012
|
||||
80000408: 00100113 li sp,1
|
||||
8000040c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
8000040c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000410: 06400093 li ra,100
|
||||
80000414: fff08093 addi ra,ra,-1
|
||||
80000418: fe104ee3 bgtz ra,80000414 <test17+0x44>
|
||||
|
@ -307,7 +307,7 @@ Disassembly of section .crt_section:
|
|||
80000424: 068f0f13 addi t5,t5,104 # 80000488 <test19>
|
||||
80000428: f00120b7 lui ra,0xf0012
|
||||
8000042c: 00000113 li sp,0
|
||||
80000430: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
80000430: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000434: 00200093 li ra,2
|
||||
80000438: 30009073 csrw mstatus,ra
|
||||
8000043c: 20000093 li ra,512
|
||||
|
@ -322,13 +322,13 @@ Disassembly of section .crt_section:
|
|||
80000460: 01408093 addi ra,ra,20 # 80000470 <test18+0x54>
|
||||
80000464: 34109073 csrw mepc,ra
|
||||
80000468: 30200073 mret
|
||||
8000046c: 2040006f j 80000670 <fail>
|
||||
8000046c: 27c0006f j 800006e8 <fail>
|
||||
80000470: 00100e93 li t4,1
|
||||
80000474: f00120b7 lui ra,0xf0012
|
||||
80000478: 00100113 li sp,1
|
||||
8000047c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
8000047c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000480: 10500073 wfi
|
||||
80000484: 1ec0006f j 80000670 <fail>
|
||||
80000484: 2640006f j 800006e8 <fail>
|
||||
|
||||
80000488 <test19>:
|
||||
80000488: 01300e13 li t3,19
|
||||
|
@ -336,7 +336,7 @@ Disassembly of section .crt_section:
|
|||
80000490: 060f0f13 addi t5,t5,96 # 800004ec <test20>
|
||||
80000494: f00120b7 lui ra,0xf0012
|
||||
80000498: 00000113 li sp,0
|
||||
8000049c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
8000049c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800004a0: 00200093 li ra,2
|
||||
800004a4: 30009073 csrw mstatus,ra
|
||||
800004a8: 20000093 li ra,512
|
||||
|
@ -350,17 +350,17 @@ Disassembly of section .crt_section:
|
|||
800004c8: 01408093 addi ra,ra,20 # 800004d8 <test19+0x50>
|
||||
800004cc: 34109073 csrw mepc,ra
|
||||
800004d0: 30200073 mret
|
||||
800004d4: 19c0006f j 80000670 <fail>
|
||||
800004d4: 2140006f j 800006e8 <fail>
|
||||
800004d8: f00120b7 lui ra,0xf0012
|
||||
800004dc: 00100113 li sp,1
|
||||
800004e0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
800004e0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800004e4: 10500073 wfi
|
||||
800004e8: 1880006f j 80000670 <fail>
|
||||
800004e8: 2000006f j 800006e8 <fail>
|
||||
|
||||
800004ec <test20>:
|
||||
800004ec: f00120b7 lui ra,0xf0012
|
||||
800004f0: 00000113 li sp,0
|
||||
800004f4: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
800004f4: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800004f8: 01400e13 li t3,20
|
||||
800004fc: 00000f17 auipc t5,0x0
|
||||
80000500: 030f0f13 addi t5,t5,48 # 8000052c <test21>
|
||||
|
@ -395,12 +395,12 @@ Disassembly of section .crt_section:
|
|||
8000056c: 01408093 addi ra,ra,20 # 8000057c <test21+0x50>
|
||||
80000570: 34109073 csrw mepc,ra
|
||||
80000574: 30200073 mret
|
||||
80000578: 0f80006f j 80000670 <fail>
|
||||
80000578: 1700006f j 800006e8 <fail>
|
||||
8000057c: 00100e93 li t4,1
|
||||
80000580: 20000093 li ra,512
|
||||
80000584: 1440a073 csrs sip,ra
|
||||
80000588: 10500073 wfi
|
||||
8000058c: 0e40006f j 80000670 <fail>
|
||||
8000058c: 15c0006f j 800006e8 <fail>
|
||||
|
||||
80000590 <test22>:
|
||||
80000590: 01600e13 li t3,22
|
||||
|
@ -423,81 +423,119 @@ Disassembly of section .crt_section:
|
|||
800005d4: 01408093 addi ra,ra,20 # 800005e4 <test22+0x54>
|
||||
800005d8: 34109073 csrw mepc,ra
|
||||
800005dc: 30200073 mret
|
||||
800005e0: 0900006f j 80000670 <fail>
|
||||
800005e0: 1080006f j 800006e8 <fail>
|
||||
800005e4: 10500073 wfi
|
||||
800005e8: 0880006f j 80000670 <fail>
|
||||
800005e8: 1000006f j 800006e8 <fail>
|
||||
|
||||
800005ec <test23>:
|
||||
800005ec: 01700e13 li t3,23
|
||||
800005f0: 00000e93 li t4,0
|
||||
800005f4: f00120b7 lui ra,0xf0012
|
||||
800005f8: 00000113 li sp,0
|
||||
800005fc: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
800005fc: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000600: 20000093 li ra,512
|
||||
80000604: 1440b073 csrc sip,ra
|
||||
80000608: 344021f3 csrr gp,mip
|
||||
8000060c: f00120b7 lui ra,0xf0012
|
||||
80000610: 00100113 li sp,1
|
||||
80000614: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
80000614: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000618: 20000093 li ra,512
|
||||
8000061c: 1440b073 csrc sip,ra
|
||||
80000620: 344021f3 csrr gp,mip
|
||||
80000624: f00120b7 lui ra,0xf0012
|
||||
80000628: 00000113 li sp,0
|
||||
8000062c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
8000062c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000630: 20000093 li ra,512
|
||||
80000634: 1440b073 csrc sip,ra
|
||||
80000638: 344021f3 csrr gp,mip
|
||||
8000063c: f00120b7 lui ra,0xf0012
|
||||
80000640: 00000113 li sp,0
|
||||
80000644: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
80000644: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000648: 20000093 li ra,512
|
||||
8000064c: 1440a073 csrs sip,ra
|
||||
80000650: 344021f3 csrr gp,mip
|
||||
80000654: f00120b7 lui ra,0xf0012
|
||||
80000658: 00100113 li sp,1
|
||||
8000065c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x70011940>
|
||||
8000065c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000660: 20000093 li ra,512
|
||||
80000664: 1440a073 csrs sip,ra
|
||||
80000668: 344021f3 csrr gp,mip
|
||||
8000066c: 0100006f j 8000067c <pass>
|
||||
8000066c: f00120b7 lui ra,0xf0012
|
||||
80000670: 00000113 li sp,0
|
||||
80000674: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
|
||||
80000670 <fail>:
|
||||
80000670: f0100137 lui sp,0xf0100
|
||||
80000674: f2410113 addi sp,sp,-220 # f00fff24 <strap+0x700ff864>
|
||||
80000678: 01c12023 sw t3,0(sp)
|
||||
|
||||
8000067c <pass>:
|
||||
8000067c: f0100137 lui sp,0xf0100
|
||||
80000680: f2010113 addi sp,sp,-224 # f00fff20 <strap+0x700ff860>
|
||||
80000684: 00012023 sw zero,0(sp)
|
||||
|
||||
80000688 <mtrap>:
|
||||
80000688: fe0e84e3 beqz t4,80000670 <fail>
|
||||
8000068c: 342020f3 csrr ra,mcause
|
||||
80000690: 341020f3 csrr ra,mepc
|
||||
80000694: 300020f3 csrr ra,mstatus
|
||||
80000698: 343020f3 csrr ra,mbadaddr
|
||||
8000069c: 08000093 li ra,128
|
||||
800006a0: 3000b073 csrc mstatus,ra
|
||||
800006a4: 00200093 li ra,2
|
||||
800006a8: fc1e8ae3 beq t4,ra,8000067c <pass>
|
||||
800006ac: 000020b7 lui ra,0x2
|
||||
800006b0: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
800006b4: 3000a073 csrs mstatus,ra
|
||||
800006b8: 341f1073 csrw mepc,t5
|
||||
80000678 <test24>:
|
||||
80000678: 01800e13 li t3,24
|
||||
8000067c: 00200093 li ra,2
|
||||
80000680: 3040a073 csrs mie,ra
|
||||
80000684: 3440a073 csrs mip,ra
|
||||
80000688: 3000a073 csrs mstatus,ra
|
||||
8000068c: 00100e93 li t4,1
|
||||
80000690: 00000f17 auipc t5,0x0
|
||||
80000694: 03cf0f13 addi t5,t5,60 # 800006cc <test25>
|
||||
80000698: 000020b7 lui ra,0x2
|
||||
8000069c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
800006a0: 00001137 lui sp,0x1
|
||||
800006a4: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
800006a8: 3000b073 csrc mstatus,ra
|
||||
800006ac: 30012073 csrs mstatus,sp
|
||||
800006b0: 00000097 auipc ra,0x0
|
||||
800006b4: 01408093 addi ra,ra,20 # 800006c4 <test24_s>
|
||||
800006b8: 34109073 csrw mepc,ra
|
||||
800006bc: 30200073 mret
|
||||
800006c0: 0280006f j 800006e8 <fail>
|
||||
|
||||
800006c0 <strap>:
|
||||
800006c0: fa0e88e3 beqz t4,80000670 <fail>
|
||||
800006c4: 142020f3 csrr ra,scause
|
||||
800006c8: 141020f3 csrr ra,sepc
|
||||
800006cc: 100020f3 csrr ra,sstatus
|
||||
800006d0: 143020f3 csrr ra,sbadaddr
|
||||
800006d4: 00000073 ecall
|
||||
800006d8: 00000013 nop
|
||||
800006dc: 00000013 nop
|
||||
800006e0: 00000013 nop
|
||||
800006e4: 00000013 nop
|
||||
800006e8: 00000013 nop
|
||||
800006ec: 00000013 nop
|
||||
800006c4 <test24_s>:
|
||||
800006c4: 10500073 wfi
|
||||
800006c8: 0200006f j 800006e8 <fail>
|
||||
|
||||
800006cc <test25>:
|
||||
800006cc: 01900e13 li t3,25
|
||||
800006d0: 00000f17 auipc t5,0x0
|
||||
800006d4: 014f0f13 addi t5,t5,20 # 800006e4 <test26>
|
||||
800006d8: 30046073 csrsi mstatus,8
|
||||
800006dc: 10500073 wfi
|
||||
800006e0: 0080006f j 800006e8 <fail>
|
||||
|
||||
800006e4 <test26>:
|
||||
800006e4: 0100006f j 800006f4 <pass>
|
||||
|
||||
800006e8 <fail>:
|
||||
800006e8: f0100137 lui sp,0xf0100
|
||||
800006ec: f2410113 addi sp,sp,-220 # f00fff24 <strap+0x700ff7ec>
|
||||
800006f0: 01c12023 sw t3,0(sp)
|
||||
|
||||
800006f4 <pass>:
|
||||
800006f4: f0100137 lui sp,0xf0100
|
||||
800006f8: f2010113 addi sp,sp,-224 # f00fff20 <strap+0x700ff7e8>
|
||||
800006fc: 00012023 sw zero,0(sp)
|
||||
|
||||
80000700 <mtrap>:
|
||||
80000700: fe0e84e3 beqz t4,800006e8 <fail>
|
||||
80000704: 342020f3 csrr ra,mcause
|
||||
80000708: 341020f3 csrr ra,mepc
|
||||
8000070c: 300020f3 csrr ra,mstatus
|
||||
80000710: 343020f3 csrr ra,mtval
|
||||
80000714: 08000093 li ra,128
|
||||
80000718: 3000b073 csrc mstatus,ra
|
||||
8000071c: 00200093 li ra,2
|
||||
80000720: fc1e8ae3 beq t4,ra,800006f4 <pass>
|
||||
80000724: 000020b7 lui ra,0x2
|
||||
80000728: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
8000072c: 3000a073 csrs mstatus,ra
|
||||
80000730: 341f1073 csrw mepc,t5
|
||||
80000734: 30200073 mret
|
||||
|
||||
80000738 <strap>:
|
||||
80000738: fa0e88e3 beqz t4,800006e8 <fail>
|
||||
8000073c: 142020f3 csrr ra,scause
|
||||
80000740: 141020f3 csrr ra,sepc
|
||||
80000744: 100020f3 csrr ra,sstatus
|
||||
80000748: 143020f3 csrr ra,stval
|
||||
8000074c: 00000073 ecall
|
||||
80000750: 00000013 nop
|
||||
80000754: 00000013 nop
|
||||
80000758: 00000013 nop
|
||||
8000075c: 00000013 nop
|
||||
80000760: 00000013 nop
|
||||
80000764: 00000013 nop
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
:0200000480007A
|
||||
:10000000930E10009700000093804068739050306A
|
||||
:10001000970000009380006B73905010B71001F0B0
|
||||
:10000000930E1000970000009380C06F73905030E3
|
||||
:10001000970000009380807273905010B71001F029
|
||||
:100020001301000023A02000130E1000170F000082
|
||||
:10003000130FCF0073000000130E2000B720000044
|
||||
:10004000938000801301000073B0003073200130F2
|
||||
:1000500097000000938040017390103473002030AB
|
||||
:100060006F000061170F0000130F4F0273000000B4
|
||||
:100070006F000060130E3000170F0000130F0F0108
|
||||
:10008000832010006F00C05E130E4000B7200000F8
|
||||
:100060006F008068170F0000130F4F02730000002D
|
||||
:100070006F008067130E3000170F0000130F0F0181
|
||||
:10008000832010006F004066130E4000B720000070
|
||||
:1000900093800080371100001301018073B000309D
|
||||
:1000A000732001309700000093804001739010345A
|
||||
:1000B000730020306F00C05B170F0000130F0F019B
|
||||
:1000C000832010006F00C05A130E5000B7200000AC
|
||||
:1000B000730020306F004063170F0000130F0F0113
|
||||
:1000C000832010006F004062130E5000B720000024
|
||||
:1000D000938000801301000073B000307320013062
|
||||
:1000E000970000009380400173901034730020301B
|
||||
:1000F0006F000058170F0000130F0F01832010002E
|
||||
:100100006F000057130E60009300000173902030C1
|
||||
:1000F0006F00805F170F0000130F0F0183201000A7
|
||||
:100100006F00805E130E600093000001739020303A
|
||||
:10011000130E7000170F0000130F0F018320100043
|
||||
:100120006F000055130E8000170F0000130FCF0350
|
||||
:100120006F00805C130E8000170F0000130FCF03C9
|
||||
:10013000B720000093800080371100001301018078
|
||||
:1001400073B00030732001309700000093804001AD
|
||||
:1001500073901034730020306F00805183201000A2
|
||||
:100160006F000051130E9000170F0000130F8F0344
|
||||
:1001500073901034730020306F000059832010001A
|
||||
:100160006F008058130E9000170F0000130F8F03BD
|
||||
:10017000B7200000938000801301000073B00030AE
|
||||
:100180007320013097000000938040017390103479
|
||||
:10019000730020306F00C04D832010006F00404D71
|
||||
:10019000730020306F004055832010006F00C05462
|
||||
:1001A000130EA000170F0000130FCF03B71001F0BC
|
||||
:1001B0001301000023A02000930080007390003002
|
||||
:1001C000B71000009380008073904030B71001F0AA
|
||||
:1001D0001301100023A02000730050106F0040494D
|
||||
:1001D0001301100023A02000730050106F00C050C6
|
||||
:1001E000130EB000170F0000130F8F06B71001F0A9
|
||||
:1001F0001301000023A020009300800073900030C2
|
||||
:10020000B71000009380008073904030B72000004A
|
||||
:1002100093800080371100001301018073B000301B
|
||||
:1002200073200130970000009380400173901034D8
|
||||
:10023000730020306F00C043B71001F013011000AD
|
||||
:1002400023A02000730050106F008042130EC000E6
|
||||
:10023000730020306F00404BB71001F01301100025
|
||||
:1002400023A02000730050106F00004A130EC0005E
|
||||
:10025000170F0000130F4F06B71001F01301000035
|
||||
:1002600023A020009300800073900030B71000009E
|
||||
:100270009380008073904030B7200000938000800E
|
||||
:100280001301000073B000307320013097000000AC
|
||||
:100290009380400173901034730020306F00403D14
|
||||
:100290009380400173901034730020306F00C0448D
|
||||
:1002A000B71001F01301100023A0200073005010BC
|
||||
:1002B0006F00003C9300200073900010130EE000CC
|
||||
:1002B0006F0080439300200073900010130EE00045
|
||||
:1002C000170F0000130F0F04B72001F013010000F7
|
||||
:1002D00023A02000930020007390003093000020A2
|
||||
:1002E00073904030930E0000B72001F0130110000E
|
||||
|
@ -52,14 +52,14 @@
|
|||
:100320009300002073904030B7200000938000803D
|
||||
:10033000371100001301018073B0003073200130C9
|
||||
:1003400097000000938040017390103473002030B8
|
||||
:100350006F000032930E1000B72001F0130110005F
|
||||
:1003600023A02000730050106F008030130E000196
|
||||
:100350006F008039930E1000B72001F013011000D8
|
||||
:1003600023A02000730050106F000038130E00010E
|
||||
:10037000170F0000130F0F06B72001F01301000044
|
||||
:1003800023A02000930020007390003093000020F1
|
||||
:1003900073904030B720000093800080130100006C
|
||||
:1003A00073B000307320013097000000938040014B
|
||||
:1003B00073901034730020306F00802BB72001F051
|
||||
:1003C0001301100023A02000730050106F00402A7A
|
||||
:1003B00073901034730020306F000033B72001F0C9
|
||||
:1003C0001301100023A02000730050106F00C031F3
|
||||
:1003D000130E10019300002073903030170F0000AF
|
||||
:1003E000130F0F04B72001F01301000023A0200019
|
||||
:1003F00093002000739000309300002073904030F1
|
||||
|
@ -69,15 +69,15 @@
|
|||
:1004300023A0200093002000739000309300002040
|
||||
:1004400073904030B7200000938000803711000087
|
||||
:100450001301018073B00030732001309700000059
|
||||
:100460009380400173901034730020306F0040205F
|
||||
:100460009380400173901034730020306F00C027D8
|
||||
:10047000930E1000B72001F01301100023A02000FC
|
||||
:10048000730050106F00C01E130E3001170F0000D4
|
||||
:10048000730050106F004026130E3001170F00004C
|
||||
:10049000130F0F06B72001F01301000023A0200066
|
||||
:1004A0009300200073900030930000207390403040
|
||||
:1004B000B7200000938000801301000073B000306B
|
||||
:1004C0007320013097000000938040017390103436
|
||||
:1004D000730020306F00C019B72001F01301100025
|
||||
:1004E00023A02000730050106F008018B72001F087
|
||||
:1004D000730020306F004021B72001F0130110009D
|
||||
:1004E00023A02000730050106F000020B72001F0FF
|
||||
:1004F0001301000023A02000130E4001170F00007D
|
||||
:10050000130F0F039300200073900030930000201E
|
||||
:1005100073904030930E00009300002073A04014AD
|
||||
|
@ -86,14 +86,14 @@
|
|||
:10054000930020007390003093000020739040309F
|
||||
:10055000B720000093800080371100001301018054
|
||||
:1005600073B0003073200130970000009380400189
|
||||
:1005700073901034730020306F00800F930E1000C2
|
||||
:100580009300002073A04014730050106F00400EC1
|
||||
:1005700073901034730020306F000017930E10003A
|
||||
:100580009300002073A04014730050106F00C0153A
|
||||
:10059000130E6001170F0000130F8F05930000204A
|
||||
:1005A00073B040149300200073900030930000203B
|
||||
:1005B000739040309300002073A04014B7200000D7
|
||||
:1005C000938000801301000073B00030732001306D
|
||||
:1005D0009700000093804001739010347300203026
|
||||
:1005E0006F000009730050106F008008130E700137
|
||||
:1005E0006F008010730050106F000010130E700128
|
||||
:1005F000930E0000B72001F01301000023A020009B
|
||||
:100600009300002073B04014F3214034B72001F070
|
||||
:100610001301100023A020009300002073B04014A9
|
||||
|
@ -101,14 +101,22 @@
|
|||
:100630009300002073B04014F3214034B72001F040
|
||||
:100640001301000023A020009300002073A0401499
|
||||
:10065000F3214034B72001F01301100023A0200043
|
||||
:100660009300002073A04014F32140346F00000178
|
||||
:10067000370110F0130141F22320C101370110F0BE
|
||||
:10068000130101F223200100E3840EFEF320203445
|
||||
:10069000F3201034F3200030F320303493000008AE
|
||||
:1006A00073B0003093002000E38A1EFCB7200000E6
|
||||
:1006B0009380008073A0003073101F3473002030CB
|
||||
:1006C000E3880EFAF3202014F3201014F320001016
|
||||
:1006D000F32030147300000013000000130000002A
|
||||
:1006E00013000000130000001300000013000000BE
|
||||
:100660009300002073A04014F3214034B72001F020
|
||||
:100670001301000023A02000130E8001930020002E
|
||||
:1006800073A0403073A0403473A00030930E10006C
|
||||
:10069000170F0000130FCF03B720000093800080D6
|
||||
:1006A000371100001301018073B000307320013056
|
||||
:1006B0009700000093804001739010347300203045
|
||||
:1006C0006F008002730050106F000002130E900143
|
||||
:1006D000170F0000130F4F017360043073005010A8
|
||||
:1006E0006F0080006F000001370110F0130141F22C
|
||||
:1006F0002320C101370110F0130101F22320010072
|
||||
:10070000E3840EFEF3202034F3201034F320003075
|
||||
:10071000F32030349300000873B0003093002000C1
|
||||
:10072000E38A1EFCB72000009380008073A0003095
|
||||
:1007300073101F3473002030E3880EFAF320201466
|
||||
:10074000F3201014F3200010F32030147300000085
|
||||
:10075000130000001300000013000000130000004D
|
||||
:0807600013000000130000006B
|
||||
:040000058000000077
|
||||
:00000001FF
|
||||
|
|
|
@ -310,7 +310,32 @@ test23: //Test software and hardware setting inettrupt
|
|||
csrs sip, x1
|
||||
csrr x3, mip
|
||||
|
||||
externalInterruptS(0)
|
||||
|
||||
test24: //test supervisor software interrupt
|
||||
li TEST_ID, 24
|
||||
li x1, 2
|
||||
csrs mie, x1
|
||||
csrs mip, x1
|
||||
csrs mstatus, x1
|
||||
|
||||
li TRAP_OK, 1
|
||||
la TRAP_RET, test25
|
||||
setPriv(1)
|
||||
test24_s:
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
test25: //test undelegated supervisor interrupt in machine mode (continue test24)
|
||||
li TEST_ID, 25
|
||||
la TRAP_RET, test26
|
||||
csrsi mstatus, 1 << 3 //mie
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
test26:
|
||||
|
||||
j pass
|
||||
|
||||
|
|
4
src/test/cpp/raw/icache/.gitignore
vendored
Normal file
4
src/test/cpp/raw/icache/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
53
src/test/cpp/raw/icache/build/icache.asm
Normal file
53
src/test/cpp/raw/icache/build/icache.asm
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
build/icache.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .crt_section:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00000097 auipc ra,0x0
|
||||
80000004: 05408093 addi ra,ra,84 # 80000054 <fail>
|
||||
80000008: 30509073 csrw mtvec,ra
|
||||
|
||||
8000000c <test1>:
|
||||
8000000c: 00100e13 li t3,1
|
||||
80000010: 00100093 li ra,1
|
||||
80000014: 00300113 li sp,3
|
||||
80000018: 00208093 addi ra,ra,2
|
||||
8000001c: 02209c63 bne ra,sp,80000054 <fail>
|
||||
|
||||
80000020 <test2>:
|
||||
80000020: 00200e13 li t3,2
|
||||
80000024: 01300093 li ra,19
|
||||
80000028: 00000117 auipc sp,0x0
|
||||
8000002c: 02410113 addi sp,sp,36 # 8000004c <test2_trigger>
|
||||
80000030: 0100006f j 80000040 <test2_aligned>
|
||||
80000034: 00000013 nop
|
||||
80000038: 00000013 nop
|
||||
8000003c: 00000013 nop
|
||||
|
||||
80000040 <test2_aligned>:
|
||||
80000040: 00112023 sw ra,0(sp)
|
||||
80000044: 0000100f fence.i
|
||||
80000048: 0040006f j 8000004c <test2_trigger>
|
||||
|
||||
8000004c <test2_trigger>:
|
||||
8000004c: 0080006f j 80000054 <fail>
|
||||
80000050: 0100006f j 80000060 <pass>
|
||||
|
||||
80000054 <fail>:
|
||||
80000054: f0100137 lui sp,0xf0100
|
||||
80000058: f2410113 addi sp,sp,-220 # f00fff24 <pass+0x700ffec4>
|
||||
8000005c: 01c12023 sw t3,0(sp)
|
||||
|
||||
80000060 <pass>:
|
||||
80000060: f0100137 lui sp,0xf0100
|
||||
80000064: f2010113 addi sp,sp,-224 # f00fff20 <pass+0x700ffec0>
|
||||
80000068: 00012023 sw zero,0(sp)
|
||||
8000006c: 00000013 nop
|
||||
80000070: 00000013 nop
|
||||
80000074: 00000013 nop
|
||||
80000078: 00000013 nop
|
||||
8000007c: 00000013 nop
|
||||
80000080: 00000013 nop
|
||||
...
|
11
src/test/cpp/raw/icache/build/icache.hex
Normal file
11
src/test/cpp/raw/icache/build/icache.hex
Normal file
|
@ -0,0 +1,11 @@
|
|||
:0200000480007A
|
||||
:10000000970000009380400573905030130E10004D
|
||||
:10001000930010001301300093802000639C2002A5
|
||||
:10002000130E20009300300117010000130141025C
|
||||
:100030006F00000113000000130000001300000017
|
||||
:10004000232011000F1000006F0040006F0080009F
|
||||
:100050006F000001370110F0130141F22320C101AC
|
||||
:10006000370110F0130101F22320010013000000FA
|
||||
:100070001300000013000000130000001300000034
|
||||
:10008000130000000000000000000000000000005D
|
||||
:00000001FF
|
3
src/test/cpp/raw/icache/makefile
Normal file
3
src/test/cpp/raw/icache/makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
PROJ_NAME=icache
|
||||
|
||||
include ../common/asm.mk
|
44
src/test/cpp/raw/icache/src/crt.S
Normal file
44
src/test/cpp/raw/icache/src/crt.S
Normal file
|
@ -0,0 +1,44 @@
|
|||
.globl _star
|
||||
#define TEST_ID x28
|
||||
|
||||
_start:
|
||||
la x1, fail
|
||||
csrw mtvec, x1
|
||||
|
||||
test1: //Dummy test
|
||||
li TEST_ID, 1
|
||||
li x1, 1
|
||||
li x2, 3
|
||||
addi x1, x1, 2
|
||||
bne x1, x2, fail
|
||||
|
||||
test2:
|
||||
li TEST_ID, 2
|
||||
li x1, 0x13 //nop
|
||||
la x2, test2_trigger
|
||||
j test2_aligned
|
||||
.align(4)
|
||||
test2_aligned:
|
||||
sw x1, 0(x2)
|
||||
fence.i
|
||||
j test2_trigger
|
||||
test2_trigger:
|
||||
j fail
|
||||
|
||||
|
||||
j pass
|
||||
|
||||
fail:
|
||||
li x2, 0xF00FFF24
|
||||
sw TEST_ID, 0(x2)
|
||||
|
||||
pass:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
16
src/test/cpp/raw/icache/src/ld
Normal file
16
src/test/cpp/raw/icache/src/ld
Normal file
|
@ -0,0 +1,16 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY {
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.crt_section :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*crt.o(.text)
|
||||
} > onChipRam
|
||||
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
[*]
|
||||
[*] GTKWave Analyzer v3.3.100 (w)1999-2019 BSI
|
||||
[*] Sat Mar 30 09:33:33 2019
|
||||
[*] Mon Apr 1 21:53:07 2019
|
||||
[*]
|
||||
[dumpfile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/linux.vcd"
|
||||
[dumpfile_mtime] "Sat Mar 30 09:16:30 2019"
|
||||
[dumpfile_size] 249834424
|
||||
[dumpfile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/rv32ui-p-lw.vcd"
|
||||
[dumpfile_mtime] "Mon Apr 1 21:52:20 2019"
|
||||
[dumpfile_size] 1974526
|
||||
[savefile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/fail.gtkw"
|
||||
[timestart] 106663042
|
||||
[timestart] 348
|
||||
[size] 1920 1030
|
||||
[pos] -458 -215
|
||||
*-5.000000 106541900 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[pos] -1 -1
|
||||
*-2.000000 357 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] TOP.
|
||||
[treeopen] TOP.VexRiscv.
|
||||
[sst_width] 287
|
||||
[signals_width] 465
|
||||
[signals_width] 563
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 279
|
||||
@28
|
||||
|
@ -21,43 +21,37 @@ TOP.VexRiscv.writeBack_arbitration_isFiring
|
|||
@22
|
||||
TOP.VexRiscv.writeBack_PC[31:0]
|
||||
TOP.VexRiscv.writeBack_INSTRUCTION[31:0]
|
||||
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0]
|
||||
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.CsrPlugin_exception
|
||||
TOP.VexRiscv.CsrPlugin_privilege[1:0]
|
||||
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_valid
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_ready
|
||||
@22
|
||||
TOP.VexRiscv.CsrPlugin_scause_exceptionCode[3:0]
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_address[31:0]
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_data[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.CsrPlugin_scause_interrupt
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_last
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_length[2:0]
|
||||
@22
|
||||
TOP.VexRiscv.IBusSimplePlugin_jump_pcLoad_payload[31:0]
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_mask[3:0]
|
||||
@28
|
||||
TOP.VexRiscv.IBusSimplePlugin_jump_pcLoad_valid
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_wr
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_rsp_valid
|
||||
@22
|
||||
TOP.VexRiscv.CsrPlugin_mepc[31:0]
|
||||
TOP.VexRiscv.CsrPlugin_sepc[31:0]
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_rsp_payload_data[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.decode_IS_RVC
|
||||
@24
|
||||
TOP.VexRiscv.CsrPlugin_mcycle[63:0]
|
||||
@28
|
||||
TOP.VexRiscv.decode_IS_RVC
|
||||
TOP.VexRiscv.decode_arbitration_isValid
|
||||
@22
|
||||
TOP.VexRiscv.RegFilePlugin_regFile(10)[31:0]
|
||||
@28
|
||||
TOP.dBus_cmd_valid
|
||||
TOP.dBus_cmd_ready
|
||||
@22
|
||||
TOP.dBus_cmd_payload_address[31:0]
|
||||
@28
|
||||
TOP.dBus_cmd_payload_wr
|
||||
@29
|
||||
TOP.dBus_cmd_payload_size[1:0]
|
||||
@22
|
||||
TOP.dBus_cmd_payload_data[31:0]
|
||||
TOP.dBus_rsp_data[31:0]
|
||||
@28
|
||||
TOP.dBus_rsp_error
|
||||
TOP.dBus_rsp_ready
|
||||
[color] 1
|
||||
TOP.VexRiscv.dataCache_1_.io_mem_rsp_payload_error
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
|
|
@ -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;
|
||||
|
@ -1666,6 +1676,15 @@ public:
|
|||
case 0xF00FFF48u: mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data;break;
|
||||
case 0xF00FFF4Cu: mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); break;
|
||||
}
|
||||
if((addr & 0xFFFFF000) == 0xF5670000){
|
||||
uint32_t t = 0x900FF000 | (addr & 0xFFF);
|
||||
uint32_t old = (*mem.get(t + 3) << 24) | (*mem.get(t + 2) << 16) | (*mem.get(t + 1) << 8) | (*mem.get(t + 0) << 0);
|
||||
old++;
|
||||
*mem.get(t + 0) = old & 0xFF; old >>= 8;
|
||||
*mem.get(t + 1) = old & 0xFF; old >>= 8;
|
||||
*mem.get(t + 2) = old & 0xFF; old >>= 8;
|
||||
*mem.get(t + 3) = old & 0xFF; old >>= 8;
|
||||
}
|
||||
}else{
|
||||
switch(addr){
|
||||
case 0xF00FFF10u:
|
||||
|
@ -3446,6 +3465,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;
|
||||
|
||||
|
||||
for(int idx = 0;idx < 1;idx++){
|
||||
|
||||
#if defined(DEBUG_PLUGIN_EXTERNAL) || defined(RUN_HEX)
|
||||
|
@ -3548,6 +3568,13 @@ int main(int argc, char **argv, char **env) {
|
|||
// redo(REDO,TestX28("mmu",mmuRef, sizeof(mmuRef)/4).noInstructionReadCheck()->run(4e4);)
|
||||
// #endif
|
||||
|
||||
#ifdef IBUS_CACHED
|
||||
redo(REDO,WorkspaceRegression("icache").withRiscvRef()->loadHex("../raw/icache/build/icache.hex")->bootAt(0x80000000u)->run(50e3););
|
||||
#endif
|
||||
#ifdef DBUS_CACHED
|
||||
redo(REDO,WorkspaceRegression("dcache").loadHex("../raw/dcache/build/dcache.hex")->bootAt(0x80000000u)->run(500e3););
|
||||
#endif
|
||||
|
||||
#ifdef MMU
|
||||
redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
|
||||
#endif
|
||||
|
|
|
@ -92,7 +92,7 @@ class DhrystoneBench extends FunSuite{
|
|||
getDmips(
|
||||
name = "GenFull",
|
||||
gen = GenFull.main(null),
|
||||
testCmd = "make clean run REDO=10 CSR=no"
|
||||
testCmd = "make clean run REDO=10 CSR=no MMU=no"
|
||||
)
|
||||
|
||||
test("final_report") {
|
||||
|
|
|
@ -366,8 +366,7 @@ class DBusDimension extends VexRiscvDimension("DBus") {
|
|||
catchAccessError = catchAll,
|
||||
catchIllegal = catchAll,
|
||||
catchUnaligned = catchAll,
|
||||
catchMemoryTranslationMiss = catchAll,
|
||||
atomicEntriesCount = 0
|
||||
withLrSc = false
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue