#60 Got the new data cache design passing all tests and running linux

This commit is contained in:
Charles Papon 2019-04-02 23:44:53 +02:00
parent fd4da77084
commit 8be40e637b
7 changed files with 143 additions and 70 deletions

View File

@ -33,6 +33,7 @@ case class ExceptionCause() extends Bundle{
trait ExceptionService{ trait ExceptionService{
def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause] def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause]
def isExceptionPending() : Bool
} }
trait PrivilegeService{ trait PrivilegeService{

View File

@ -96,45 +96,45 @@ object LinuxGen {
new DummyFencePlugin(), //TODO should be removed for design with caches new DummyFencePlugin(), //TODO should be removed for design with caches
//Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config //Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config
new IBusSimplePlugin( // new IBusSimplePlugin(
resetVector = 0x80000000l,
cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE,
historyRamSizeLog2 = 10,
catchAccessFault = true,
compressedGen = true,
busLatencyMin = 1,
injectorStage = true,
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
portTlbSize = 4
)
),
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
// new IBusCachedPlugin(
// resetVector = 0x80000000l, // resetVector = 0x80000000l,
// compressedGen = true, // cmdForkOnSecondStage = false,
// cmdForkPersistence = false,
// prediction = NONE, // prediction = NONE,
// injectorStage = true, // historyRamSizeLog2 = 10,
// config = InstructionCacheConfig(
// cacheSize = 4096,
// bytePerLine = 32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchIllegalAccess = true,
// catchAccessFault = true, // catchAccessFault = true,
// asyncTagMemory = false, // compressedGen = true,
// twoCycleRam = false, // busLatencyMin = 1,
// twoCycleCache = true // injectorStage = true,
// ) // memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
// ),
// memoryTranslatorPortConfig = MmuPortConfig(
// portTlbSize = 4 // portTlbSize = 4
// ) // )
// ), // ),
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
new IBusCachedPlugin(
resetVector = 0x80000000l,
compressedGen = true,
prediction = NONE,
injectorStage = true,
config = InstructionCacheConfig(
cacheSize = 4096,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = true,
catchAccessFault = true,
asyncTagMemory = false,
twoCycleRam = false,
twoCycleCache = true
// )
),
memoryTranslatorPortConfig = MmuPortConfig(
portTlbSize = 4
)
),
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))), // ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
// new DBusSimplePlugin( // new DBusSimplePlugin(
// catchAddressMisaligned = true, // catchAddressMisaligned = true,
@ -156,17 +156,16 @@ object LinuxGen {
catchAccessError = true, catchAccessError = true,
catchIllegal = true, catchIllegal = true,
catchUnaligned = true, catchUnaligned = true,
atomicEntriesCount = 2 atomicEntriesCount = 1
)
// ),
// memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MmuPortConfig(
// portTlbSize = 4
// ) // )
), ),
new StaticMemoryTranslatorPlugin( memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
ioRange = _(31 downto 28) === 0xF portTlbSize = 4
)
), ),
// new StaticMemoryTranslatorPlugin(
// ioRange = _(31 downto 28) === 0xF
// ),
// new MemoryTranslatorPlugin( // new MemoryTranslatorPlugin(
// tlbSize = 32, // tlbSize = 32,
// virtualRange = _(31 downto 28) === 0xC, // virtualRange = _(31 downto 28) === 0xC,
@ -238,12 +237,12 @@ object LinuxGen {
new YamlPlugin("cpu0.yaml") new YamlPlugin("cpu0.yaml")
) )
) )
// if(withMmu) config.plugins += new MmuPlugin( if(withMmu) config.plugins += new MmuPlugin(
// virtualRange = a => True, virtualRange = a => True,
// // virtualRange = x => x(31 downto 24) =/= 0x81, //TODO It fix the DTB kernel access (workaround) // 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), 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 allowUserIo = true
// ) )
config config
} }

View File

@ -8,6 +8,8 @@ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import spinal.lib.bus.simple._ import spinal.lib.bus.simple._
//TODO flush
case class DataCacheConfig(cacheSize : Int, case class DataCacheConfig(cacheSize : Int,
bytePerLine : Int, bytePerLine : Int,
wayCount : Int, wayCount : Int,
@ -71,13 +73,12 @@ object DataCacheCpuExecute{
case class DataCacheCpuExecute(p : DataCacheConfig) extends Bundle with IMasterSlave{ case class DataCacheCpuExecute(p : DataCacheConfig) extends Bundle with IMasterSlave{
val isValid = Bool val isValid = Bool
val isStuck = Bool
val address = UInt(p.addressWidth bit) val address = UInt(p.addressWidth bit)
// val haltIt = Bool // val haltIt = Bool
val args = DataCacheCpuExecuteArgs(p) val args = DataCacheCpuExecuteArgs(p)
override def asMaster(): Unit = { override def asMaster(): Unit = {
out(isValid, isStuck, args, address) out(isValid, args, address)
// in(haltIt) // in(haltIt)
} }
} }
@ -111,6 +112,7 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
val isStuck = Bool val isStuck = Bool
val isUser = Bool val isUser = Bool
val haltIt = Bool val haltIt = Bool
val isWrite = Bool
val data = Bits(p.cpuDataWidth bit) val data = Bits(p.cpuDataWidth bit)
val address = UInt(p.addressWidth bit) val address = UInt(p.addressWidth bit)
val mmuException, unalignedAccess , accessError = Bool val mmuException, unalignedAccess , accessError = Bool
@ -120,7 +122,7 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
override def asMaster(): Unit = { override def asMaster(): Unit = {
out(isValid,isStuck,isUser, address) out(isValid,isStuck,isUser, address)
in(haltIt, data, mmuException, unalignedAccess, accessError) in(haltIt, data, mmuException, unalignedAccess, accessError, isWrite)
outWithNull(clearAtomicEntries) outWithNull(clearAtomicEntries)
} }
} }
@ -354,8 +356,8 @@ class DataCache(p : DataCacheConfig) extends Component{
val data = Mem(Bits(wordWidth bit), wayWordCount) val data = Mem(Bits(wordWidth bit), wayWordCount)
//Reads //Reads
val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.execute.isStuck) val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.memory.isStuck)
val dataReadRsp = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.execute.isStuck) val dataReadRsp = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.memory.isStuck)
//Writes //Writes
when(tagsWriteCmd.valid && tagsWriteCmd.way(i)){ when(tagsWriteCmd.valid && tagsWriteCmd.way(i)){
@ -380,7 +382,7 @@ class DataCache(p : DataCacheConfig) extends Component{
dataWriteCmd.valid := False dataWriteCmd.valid := False
dataWriteCmd.payload.assignDontCare() dataWriteCmd.payload.assignDontCare()
when(io.cpu.execute.isValid && !io.cpu.execute.isStuck){ when(io.cpu.execute.isValid && !io.cpu.memory.isStuck){
tagsReadCmd.valid := True tagsReadCmd.valid := True
dataReadCmd.valid := True dataReadCmd.valid := True
tagsReadCmd.payload := io.cpu.execute.address(lineRange) tagsReadCmd.payload := io.cpu.execute.address(lineRange)
@ -460,7 +462,6 @@ class DataCache(p : DataCacheConfig) extends Component{
val atomic = genAtomic generate new Area{ val atomic = genAtomic generate new Area{
case class AtomicEntry() extends Bundle{ case class AtomicEntry() extends Bundle{
val valid = Bool() val valid = Bool()
val size = UInt(2 bits)
val address = UInt(addressWidth bits) val address = UInt(addressWidth bits)
def init: this.type ={ def init: this.type ={
@ -470,10 +471,9 @@ class DataCache(p : DataCacheConfig) extends Component{
} }
val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount) val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount)
val entriesAllocCounter = Counter(atomicEntriesCount) val entriesAllocCounter = Counter(atomicEntriesCount)
val entriesHit = entries.map(e => e.valid && e.size === request.size && e.address === io.cpu.writeBack.address).orR val entriesHit = entries.map(e => e.valid && e.address === io.cpu.writeBack.address).orR
when(io.cpu.writeBack.isValid && request.isAtomic && !request.wr){ when(io.cpu.writeBack.isValid && request.isAtomic && !request.wr){
entries(entriesAllocCounter).valid := True entries(entriesAllocCounter).valid := True
entries(entriesAllocCounter).size := request.size //TODO remove size stuff
entries(entriesAllocCounter).address := io.cpu.writeBack.address entries(entriesAllocCounter).address := io.cpu.writeBack.address
when(!io.cpu.writeBack.isStuck){ when(!io.cpu.writeBack.isStuck){
entriesAllocCounter.increment() entriesAllocCounter.increment()
@ -486,11 +486,11 @@ class DataCache(p : DataCacheConfig) extends Component{
val memCmdSent = RegInit(False) setWhen (io.mem.cmd.ready) clearWhen (!io.cpu.writeBack.isStuck) val memCmdSent = RegInit(False) setWhen (io.mem.cmd.ready) clearWhen (!io.cpu.writeBack.isStuck)
io.cpu.redo := mmuRsp.refilling io.cpu.redo := False
io.cpu.writeBack.accessError := False io.cpu.writeBack.accessError := False
io.cpu.writeBack.mmuException := io.cpu.writeBack.isValid && (if(catchIllegal) mmuRsp.exception || (!mmuRsp.allowWrite && request.wr) || (!mmuRsp.allowRead && !request.wr) || (!mmuRsp.allowUser && io.cpu.writeBack.isUser) else False) io.cpu.writeBack.mmuException := io.cpu.writeBack.isValid && (if(catchIllegal) mmuRsp.exception || (!mmuRsp.allowWrite && request.wr) || (!mmuRsp.allowRead && !request.wr) || (!mmuRsp.allowUser && io.cpu.writeBack.isUser) else False)
io.cpu.writeBack.unalignedAccess := io.cpu.writeBack.isValid && (if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False) io.cpu.writeBack.unalignedAccess := io.cpu.writeBack.isValid && (if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False)
io.cpu.writeBack.isWrite := request.wr
when(io.cpu.writeBack.isValid) { when(io.cpu.writeBack.isValid) {
when(request.forceUncachedAccess || mmuRsp.isIoAccess) { when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
@ -503,6 +503,11 @@ class DataCache(p : DataCacheConfig) extends Component{
io.mem.cmd.data := request.data io.mem.cmd.data := request.data
io.mem.cmd.length := 0 io.mem.cmd.length := 0
io.mem.cmd.last := True io.mem.cmd.last := True
if(genAtomic) when(request.isAtomic && !atomic.entriesHit){
io.mem.cmd.valid := False
io.cpu.writeBack.haltIt := False
}
} otherwise { } otherwise {
when(waysHit || request.wr) { //Do not require a cache refill ? when(waysHit || request.wr) { //Do not require a cache refill ?
//Data cache update //Data cache update
@ -524,6 +529,12 @@ class DataCache(p : DataCacheConfig) extends Component{
//On write to read colisions //On write to read colisions
io.cpu.redo := !request.wr && (colisions & waysHits) =/= 0 io.cpu.redo := !request.wr && (colisions & waysHits) =/= 0
if(genAtomic) when(request.isAtomic && !atomic.entriesHit){
io.mem.cmd.valid := False
dataWriteCmd.valid := False
io.cpu.writeBack.haltIt := False
}
} otherwise { //Do refill } otherwise { //Do refill
//Emit cmd //Emit cmd
@ -554,6 +565,7 @@ class DataCache(p : DataCacheConfig) extends Component{
loaderValid := False loaderValid := False
io.cpu.writeBack.haltIt := 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") assert(!(io.cpu.writeBack.isValid && !io.cpu.writeBack.haltIt && io.cpu.writeBack.isStuck), "writeBack stuck by another plugin is not allowed")
@ -561,9 +573,6 @@ class DataCache(p : DataCacheConfig) extends Component{
when(request.isAtomic && request.wr){ when(request.isAtomic && request.wr){
io.cpu.writeBack.data := (!atomic.entriesHit).asBits.resized io.cpu.writeBack.data := (!atomic.entriesHit).asBits.resized
} }
when(request.isAtomic && !atomic.entriesHit){
io.mem.cmd.mask := 0
}
} }
} }

View File

@ -285,6 +285,9 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
interface interface
} }
var exceptionPending : Bool = null
override def isExceptionPending(): Bool = exceptionPending
var jumpInterface : Flow[UInt] = null var jumpInterface : Flow[UInt] = null
var timerInterrupt, externalInterrupt, softwareInterrupt : Bool = null var timerInterrupt, externalInterrupt, softwareInterrupt : Bool = null
var externalInterruptS : Bool = null var externalInterruptS : Bool = null
@ -378,7 +381,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
jumpInterface.valid := False jumpInterface.valid := False
jumpInterface.payload.assignDontCare() jumpInterface.payload.assignDontCare()
exceptionPending = False
timerInterrupt = in Bool() setName("timerInterrupt") timerInterrupt = in Bool() setName("timerInterrupt")
externalInterrupt = in Bool() setName("externalInterrupt") externalInterrupt = in Bool() setName("externalInterrupt")
softwareInterrupt = in Bool() setName("softwareInterrupt") softwareInterrupt = in Bool() setName("softwareInterrupt")
@ -677,7 +680,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
else else
exceptionValidsRegs(stageId) := False exceptionValidsRegs(stageId) := False
} }
if(stage != stages.last) when(stage.arbitration.isFlushed){ when(stage.arbitration.isFlushed){
exceptionValids(stageId) := False exceptionValids(stageId) := False
} }
} }
@ -688,6 +691,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
//Avoid the PC register of the last stage to change durring an exception handleing (Used to fill Xepc) //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 stages.last.dontSample.getOrElseUpdate(PC, ArrayBuffer[Bool]()) += exceptionValids.last
exceptionPending setWhen(exceptionValidsRegs.orR)
} else null } else null

View File

@ -20,7 +20,7 @@ class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
class DBusCachedPlugin(config : DataCacheConfig, class DBusCachedPlugin(config : DataCacheConfig,
memoryTranslatorPortConfig : Any = null, memoryTranslatorPortConfig : Any = null,
csrInfo : Boolean = false) extends Plugin[VexRiscv]{ csrInfo : Boolean = false) extends Plugin[VexRiscv] with DBusAccessService {
import config._ import config._
var dBus : DataCacheMemBus = null var dBus : DataCacheMemBus = null
var mmuBus : MemoryTranslatorBus = null var mmuBus : MemoryTranslatorBus = null
@ -28,11 +28,19 @@ class DBusCachedPlugin(config : DataCacheConfig,
var privilegeService : PrivilegeService = null var privilegeService : PrivilegeService = null
var redoBranch : Flow[UInt] = 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_ENABLE extends Stageable(Bool)
object MEMORY_MANAGMENT extends Stageable(Bool) object MEMORY_MANAGMENT extends Stageable(Bool)
object MEMORY_WR extends Stageable(Bool) object MEMORY_WR extends Stageable(Bool)
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits)) object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
object MEMORY_ATOMIC extends Stageable(Bool) object MEMORY_ATOMIC extends Stageable(Bool)
object IS_DBUS_SHARING extends Stageable(Bool())
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
import Riscv._ import Riscv._
@ -44,8 +52,9 @@ class DBusCachedPlugin(config : DataCacheConfig,
SRC1_CTRL -> Src1CtrlEnum.RS, SRC1_CTRL -> Src1CtrlEnum.RS,
SRC_USE_SUB_LESS -> False, SRC_USE_SUB_LESS -> False,
MEMORY_ENABLE -> True, MEMORY_ENABLE -> True,
RS1_USE -> True RS1_USE -> True,
) ++ (if (catchSomething) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB
)
val loadActions = stdActions ++ List( val loadActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMI, SRC2_CTRL -> Src2CtrlEnum.IMI,
@ -143,7 +152,6 @@ class DBusCachedPlugin(config : DataCacheConfig,
val size = input(INSTRUCTION)(13 downto 12).asUInt val size = input(INSTRUCTION)(13 downto 12).asUInt
cache.io.cpu.execute.isValid := arbitration.isValid && input(MEMORY_ENABLE) 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.address := input(SRC_ADD).asUInt
cache.io.cpu.execute.args.wr := input(MEMORY_WR) cache.io.cpu.execute.args.wr := input(MEMORY_WR)
cache.io.cpu.execute.args.data := size.mux( cache.io.cpu.execute.args.data := size.mux(
@ -194,7 +202,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
redoBranch.payload := input(PC) redoBranch.payload := input(PC)
arbitration.flushAll setWhen(redoBranch.valid) arbitration.flushAll setWhen(redoBranch.valid)
when(cache.io.cpu.writeBack.isValid) { when(arbitration.isValid && input(MEMORY_ENABLE)) {
if (catchAccessError) when(cache.io.cpu.writeBack.accessError) { if (catchAccessError) when(cache.io.cpu.writeBack.accessError) {
exceptionBus.valid := True exceptionBus.valid := True
exceptionBus.code := (input(MEMORY_WR) ? U(7) | U(5)).resized exceptionBus.code := (input(MEMORY_WR) ? U(7) | U(5)).resized
@ -235,6 +243,45 @@ class DBusCachedPlugin(config : DataCacheConfig,
} }
} }
//Share access to the dBus (used by self refilled MMU)
val dBusSharing = (dBusAccess != null) generate pipeline plug new Area{
dBusAccess.cmd.ready := False
val forceDatapath = False
when(dBusAccess.cmd.valid){
decode.arbitration.haltByOther := True
when(!stagesFromExecute.map(_.arbitration.isValid).orR && !pipeline.service(classOf[ExceptionService]).isExceptionPending()){
when(!cache.io.cpu.redo) {
cache.io.cpu.execute.isValid := True
dBusAccess.cmd.ready := !execute.arbitration.isStuck
}
cache.io.cpu.execute.args.wr := dBusAccess.cmd.write
cache.io.cpu.execute.args.data := dBusAccess.cmd.data
cache.io.cpu.execute.args.size := dBusAccess.cmd.size
cache.io.cpu.execute.args.forceUncachedAccess := True //TODO Cached and redo management
if(genAtomic) cache.io.cpu.execute.args.isAtomic := False
cache.io.cpu.execute.address := dBusAccess.cmd.address //Will only be 12 muxes
forceDatapath := True
}
}
execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire
mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.memory.isValid setWhen(memory.input(IS_DBUS_SHARING))
cache.io.cpu.writeBack.isValid setWhen(writeBack.input(IS_DBUS_SHARING))
dBusAccess.rsp.valid := writeBack.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && !cache.io.cpu.writeBack.haltIt
dBusAccess.rsp.data := cache.io.cpu.writeBack.data
dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError
component.addPrePopTask{() =>
when(forceDatapath){
execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits
}
memory.input(IS_DBUS_SHARING) init(False)
writeBack.input(IS_DBUS_SHARING) init(False)
}
}
if(csrInfo){ if(csrInfo){
val csr = service(classOf[CsrPlugin]) val csr = service(classOf[CsrPlugin])
csr.r(0xCC0, 0 -> U(cacheSize/wayCount), 20 -> U(bytePerLine)) csr.r(0xCC0, 0 -> U(cacheSize/wayCount), 20 -> U(bytePerLine))

View File

@ -21,6 +21,8 @@ class HaltOnExceptionPlugin() extends Plugin[VexRiscv] with ExceptionService {
exceptionPortsInfos += ExceptionPortInfo(interface,stage,priority) exceptionPortsInfos += ExceptionPortInfo(interface,stage,priority)
interface interface
} }
override def isExceptionPending(): Bool = False
override def build(pipeline: VexRiscv): Unit = { override def build(pipeline: VexRiscv): Unit = {
import pipeline._ import pipeline._

View File

@ -1316,6 +1316,16 @@ public:
if(isDBusCheckedRegion(addr)){ if(isDBusCheckedRegion(addr)){
CpuRef::MemWrite w; CpuRef::MemWrite w;
w.address = addr; 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; w.size = 1 << size;
switch(size){ switch(size){
case 0: w.data = *data & 0xFF; break; case 0: w.data = *data & 0xFF; break;
@ -3446,6 +3456,7 @@ int main(int argc, char **argv, char **env) {
// redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3);); // redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
// return 0; // return 0;
redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
for(int idx = 0;idx < 1;idx++){ for(int idx = 0;idx < 1;idx++){