DataCache plugin now support all exceptions

This commit is contained in:
Charles Papon 2017-05-07 10:44:41 +02:00
parent 5ba8ab7947
commit ca1bc9cf69
6 changed files with 53 additions and 33 deletions

View File

@ -12,13 +12,15 @@ case class DataCacheConfig( cacheSize : Int,
addressWidth : Int, addressWidth : Int,
cpuDataWidth : Int, cpuDataWidth : Int,
memDataWidth : Int, memDataWidth : Int,
catchAccessFault : Boolean, catchAccessError : Boolean,
catchIllegal : Boolean,
catchUnaligned : Boolean,
catchMemoryTranslationMiss : Boolean, catchMemoryTranslationMiss : Boolean,
clearTagsAfterReset : Boolean = true,
tagSizeShift : Int = 0){ //Used to force infering ram tagSizeShift : Int = 0){ //Used to force infering ram
def burstSize = bytePerLine*8/memDataWidth def burstSize = bytePerLine*8/memDataWidth
val burstLength = bytePerLine/(memDataWidth/8) val burstLength = bytePerLine/(memDataWidth/8)
assert(catchAccessFault == false) def catchSomething = catchUnaligned || catchMemoryTranslationMiss || catchIllegal || catchAccessError
def catchSomething = catchAccessFault || catchMemoryTranslationMiss
} }
@ -43,7 +45,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
SRC_USE_SUB_LESS -> False, SRC_USE_SUB_LESS -> False,
MEMORY_ENABLE -> True, MEMORY_ENABLE -> True,
REG1_USE -> True REG1_USE -> True
) ++ (if (catchAccessFault) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage ) ++ (if (catchUnaligned) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
val loadActions = stdActions ++ List( val loadActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMI, SRC2_CTRL -> Src2CtrlEnum.IMI,
@ -99,7 +101,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
U(1) -> B"0011", U(1) -> B"0011",
default -> B"1111" default -> B"1111"
) << cache.io.cpu.execute.args.address(1 downto 0)).resized ) << cache.io.cpu.execute.args.address(1 downto 0)).resized
cache.io.cpu.execute.args.bypass := cache.io.cpu.execute.args.address(31 downto 28) === 0xF cache.io.cpu.execute.args.forceUncachedAccess := False // cache.io.cpu.execute.args.address(31 downto 28) === 0xF
cache.io.cpu.execute.args.kind := DataCacheCpuCmdKind.MEMORY cache.io.cpu.execute.args.kind := DataCacheCpuCmdKind.MEMORY
cache.io.cpu.execute.args.clean := False cache.io.cpu.execute.args.clean := False
cache.io.cpu.execute.args.invalidate := False cache.io.cpu.execute.args.invalidate := False
@ -128,9 +130,12 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
cache.io.cpu.writeBack.isStuck := arbitration.isStuck cache.io.cpu.writeBack.isStuck := arbitration.isStuck
if(catchSomething) { if(catchSomething) {
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError
exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr
exceptionBus.code := 13 exceptionBus.code := 13
when(cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.accessError){
exceptionBus.code := (input(INSTRUCTION)(5) ? U(7) | U(5)).resized
}
} }
arbitration.haltIt.setWhen(cache.io.cpu.writeBack.haltIt) arbitration.haltIt.setWhen(cache.io.cpu.writeBack.haltIt)
@ -255,7 +260,7 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
val address = UInt(p.addressWidth bit) val address = UInt(p.addressWidth bit)
val data = Bits(p.cpuDataWidth bit) val data = Bits(p.cpuDataWidth bit)
val mask = Bits(p.cpuDataWidth/8 bit) val mask = Bits(p.cpuDataWidth/8 bit)
val bypass = Bool val forceUncachedAccess = Bool
val clean, invalidate, way = Bool val clean, invalidate, way = Bool
// val all = Bool //Address should be zero when "all" is used // val all = Bool //Address should be zero when "all" is used
} }
@ -278,14 +283,13 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
val isStuck = Bool val isStuck = Bool
val haltIt = Bool val haltIt = Bool
val data = Bits(p.cpuDataWidth bit) val data = Bits(p.cpuDataWidth bit)
val mmuMiss = Bool val mmuMiss, illegalAccess, unalignedAccess , accessError = Bool
val badAddr = UInt(32 bits) val badAddr = UInt(32 bits)
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null // val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
override def asMaster(): Unit = { override def asMaster(): Unit = {
out(isValid,isStuck) out(isValid,isStuck)
in(haltIt, data, mmuMiss, badAddr) in(haltIt, data, mmuMiss,illegalAccess , unalignedAccess, accessError, badAddr)
} }
} }
@ -311,6 +315,7 @@ case class DataCacheMemCmd(p : DataCacheConfig) extends Bundle{
} }
case class DataCacheMemRsp(p : DataCacheConfig) extends Bundle{ case class DataCacheMemRsp(p : DataCacheConfig) extends Bundle{
val data = Bits(p.memDataWidth bit) val data = Bits(p.memDataWidth bit)
val error = Bool
} }
case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave{ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave{
@ -449,7 +454,7 @@ class DataCache(p : DataCacheConfig) extends Component{
tagsReadCmd.payload := io.cpu.execute.address(lineRange) tagsReadCmd.payload := io.cpu.execute.address(lineRange)
dataReadCmd.valid := True dataReadCmd.valid := True
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) //TODO FMAX mayybe critical path could be default dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) //TODO FMAX maybe critical path could be default
} }
@ -544,7 +549,7 @@ class DataCache(p : DataCacheConfig) extends Component{
val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck) 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.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.virtualAddress := request.address
io.cpu.memory.mmuBus.cmd.bypass := request.way io.cpu.memory.mmuBus.cmd.bypassTranslation := request.way
} }
val stageB = new Area { val stageB = new Area {
@ -568,10 +573,13 @@ class DataCache(p : DataCacheConfig) extends Component{
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
io.cpu.writeBack.mmuMiss := False io.cpu.writeBack.mmuMiss := False
io.cpu.writeBack.illegalAccess := False
io.cpu.writeBack.unalignedAccess := False
io.cpu.writeBack.accessError := (if(catchAccessError) io.mem.rsp.valid && io.mem.rsp.error else False)
io.cpu.writeBack.badAddr := request.address io.cpu.writeBack.badAddr := request.address
//Evict the cache after reset logics //Evict the cache after reset logics
val bootEvicts = new Area { val bootEvicts = if(clearTagsAfterReset) new Area {
val valid = RegInit(True) val valid = RegInit(True)
mmuRsp.physicalAddress init (0) mmuRsp.physicalAddress init (0)
when(valid) { when(valid) {
@ -588,11 +596,11 @@ class DataCache(p : DataCacheConfig) extends Component{
} }
when(io.cpu.writeBack.isValid) { when(io.cpu.writeBack.isValid) {
if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := mmuRsp.miss
}
switch(request.kind) { switch(request.kind) {
is(LINE) { is(LINE) {
if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := mmuRsp.miss
}
when(delayedIsStuck && !mmuRsp.miss) { when(delayedIsStuck && !mmuRsp.miss) {
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) { when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready)) io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready))
@ -604,16 +612,17 @@ class DataCache(p : DataCacheConfig) extends Component{
} }
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false) victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := !request.invalidate tagsWriteCmd.data.used := !request.invalidate
tagsWriteCmd.data.dirty := !request.clean tagsWriteCmd.data.dirty := !request.clean
} }
is(MEMORY) { is(MEMORY) {
if (catchMemoryTranslationMiss) { val illegal = if(catchIllegal) (request.wr && !mmuRsp.allowWrite) || (!request.wr && !mmuRsp.allowRead) else False
io.cpu.writeBack.mmuMiss := mmuRsp.miss val unaligned = if(catchUnaligned) ((request.mask === 0xF && mmuRsp.physicalAddress(1 downto 0) =/= 0) || ((request.mask === 0x3 || request.mask === 0xC) && mmuRsp.physicalAddress(0) =/= False)) else False
} io.cpu.writeBack.illegalAccess := illegal
when(Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) { io.cpu.writeBack.unalignedAccess := unaligned
when(request.bypass) { when((Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) && !illegal && !unaligned) {
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
val memCmdSent = RegInit(False) val memCmdSent = RegInit(False)
when(!victim.request.valid) { when(!victim.request.valid) {
//Avoid mixing memory request while victim is pending //Avoid mixing memory request while victim is pending
@ -639,7 +648,7 @@ class DataCache(p : DataCacheConfig) extends Component{
dataWriteCmd.data := request.data dataWriteCmd.data := request.data
dataWriteCmd.mask := request.mask dataWriteCmd.mask := request.mask
tagsWriteCmd.valid := !loadingNotDone || request.wr tagsWriteCmd.valid := (!loadingNotDone) || request.wr
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := True tagsWriteCmd.data.used := True
tagsWriteCmd.data.dirty := request.wr tagsWriteCmd.data.dirty := request.wr
@ -658,7 +667,7 @@ class DataCache(p : DataCacheConfig) extends Component{
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")
io.cpu.writeBack.data := request.bypass ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways io.cpu.writeBack.data := request.forceUncachedAccess ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
} }
//The whole life of a loading task, the corresponding manager request is present //The whole life of a loading task, the corresponding manager request is present

View File

@ -458,7 +458,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.address io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.address
io.cpu.fetch.mmuBus.cmd.bypass := False io.cpu.fetch.mmuBus.cmd.bypassTranslation := False
val mmuRsp = RegNextWhen(io.cpu.fetch.mmuBus.rsp,!io.cpu.decode.isStuck) val mmuRsp = RegNextWhen(io.cpu.fetch.mmuBus.rsp,!io.cpu.decode.isStuck)
val hit = tag.valid && tag.address === mmuRsp.physicalAddress(tagRange) && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange))) val hit = tag.valid && tag.address === mmuRsp.physicalAddress(tagRange) && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange)))

View File

@ -9,7 +9,9 @@ case class MemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage, args :
case class MemoryTranslatorPortConfig(portTlbSize : Int) case class MemoryTranslatorPortConfig(portTlbSize : Int)
class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator { class MemoryTranslatorPlugin(tlbSize : Int,
virtualRange : UInt => Bool,
ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator {
assert(isPow2(tlbSize)) assert(isPow2(tlbSize))
val portsInfo = ArrayBuffer[MemoryTranslatorPort]() val portsInfo = ArrayBuffer[MemoryTranslatorPort]()
@ -66,7 +68,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plu
val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12)) val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12))
val cacheHit = cacheHits.asBits.orR val cacheHit = cacheHits.asBits.orR
val cacheLine = MuxOH(cacheHits, cache) val cacheLine = MuxOH(cacheHits, cache)
val isInMmuRange = mmuRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypass val isInMmuRange = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation
val sharedMiss = RegInit(False) val sharedMiss = RegInit(False)
val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits)) val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))
@ -112,6 +114,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plu
port.bus.rsp.allowWrite := True port.bus.rsp.allowWrite := True
port.bus.rsp.allowExecute := True port.bus.rsp.allowExecute := True
} }
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
port.bus.rsp.miss := sharedMiss port.bus.rsp.miss := sharedMiss
} }
} }

View File

@ -25,10 +25,11 @@ trait ExceptionService{
case class MemoryTranslatorCmd() extends Bundle{ case class MemoryTranslatorCmd() extends Bundle{
val isValid = Bool val isValid = Bool
val virtualAddress = UInt(32 bits) val virtualAddress = UInt(32 bits)
val bypass = Bool val bypassTranslation = Bool
} }
case class MemoryTranslatorRsp() extends Bundle{ case class MemoryTranslatorRsp() extends Bundle{
val physicalAddress = UInt(32 bits) val physicalAddress = UInt(32 bits)
val isIoAccess = Bool
val allowRead, allowWrite, allowExecute = Bool val allowRead, allowWrite, allowExecute = Bool
val miss = Bool val miss = Bool
} }

View File

@ -129,7 +129,9 @@ object TopLevel {
addressWidth = 32, addressWidth = 32,
cpuDataWidth = 32, cpuDataWidth = 32,
memDataWidth = 32, memDataWidth = 32,
catchAccessFault = false, catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = false catchMemoryTranslationMiss = false
) )
), ),
@ -269,7 +271,9 @@ object TopLevel {
addressWidth = 32, addressWidth = 32,
cpuDataWidth = 32, cpuDataWidth = 32,
memDataWidth = 32, memDataWidth = 32,
catchAccessFault = false, catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true, catchMemoryTranslationMiss = true,
tagSizeShift = 2 tagSizeShift = 2
), ),
@ -281,7 +285,8 @@ object TopLevel {
new MemoryTranslatorPlugin( new MemoryTranslatorPlugin(
tlbSize = 32, tlbSize = 32,
mmuRange = _(31 downto 28) === 0xC virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF
), ),
new MachineCsr(csrConfigSmall), new MachineCsr(csrConfigSmall),
new DecoderSimplePlugin( new DecoderSimplePlugin(

View File

@ -562,12 +562,14 @@ public:
virtual void postCycle(){ virtual void postCycle(){
if(pendingCount != 0 && !wr && (!ws->dStall || VL_RANDOM_I(7) < 100)){ if(pendingCount != 0 && !wr && (!ws->dStall || VL_RANDOM_I(7) < 100)){
ws->dBusAccess(address,0,2,0,&top->dBus_rsp_payload_data,&error_next); ws->dBusAccess(address,0,2,0,&top->dBus_rsp_payload_data,&error_next);
top->dBus_rsp_payload_error = error_next;
top->dBus_rsp_valid = 1; top->dBus_rsp_valid = 1;
address += 4; address += 4;
pendingCount--; pendingCount--;
} else{ } else{
top->dBus_rsp_valid = 0; top->dBus_rsp_valid = 0;
top->dBus_rsp_payload_data = VL_RANDOM_I(32); top->dBus_rsp_payload_data = VL_RANDOM_I(32);
top->dBus_rsp_payload_error = VL_RANDOM_I(1);
} }
top->dBus_cmd_ready = (ws->dStall ? VL_RANDOM_I(7) < 100 : 1) && (pendingCount == 0 || wr); top->dBus_cmd_ready = (ws->dStall ? VL_RANDOM_I(7) < 100 : 1) && (pendingCount == 0 || wr);