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,
cpuDataWidth : Int,
memDataWidth : Int,
catchAccessFault : Boolean,
catchAccessError : Boolean,
catchIllegal : Boolean,
catchUnaligned : Boolean,
catchMemoryTranslationMiss : Boolean,
clearTagsAfterReset : Boolean = true,
tagSizeShift : Int = 0){ //Used to force infering ram
def burstSize = bytePerLine*8/memDataWidth
val burstLength = bytePerLine/(memDataWidth/8)
assert(catchAccessFault == false)
def catchSomething = catchAccessFault || catchMemoryTranslationMiss
def catchSomething = catchUnaligned || catchMemoryTranslationMiss || catchIllegal || catchAccessError
}
@ -43,7 +45,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
SRC_USE_SUB_LESS -> False,
MEMORY_ENABLE -> 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(
SRC2_CTRL -> Src2CtrlEnum.IMI,
@ -99,7 +101,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
U(1) -> B"0011",
default -> B"1111"
) << 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.clean := 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.isStuck := arbitration.isStuck
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.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)
@ -255,7 +260,7 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
val address = UInt(p.addressWidth bit)
val data = Bits(p.cpuDataWidth bit)
val mask = Bits(p.cpuDataWidth/8 bit)
val bypass = Bool
val forceUncachedAccess = Bool
val clean, invalidate, way = Bool
// 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 haltIt = Bool
val data = Bits(p.cpuDataWidth bit)
val mmuMiss = Bool
val mmuMiss, illegalAccess, unalignedAccess , accessError = Bool
val badAddr = UInt(32 bits)
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
override def asMaster(): Unit = {
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{
val data = Bits(p.memDataWidth bit)
val error = Bool
}
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)
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)
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.bypass := request.way
io.cpu.memory.mmuBus.cmd.bypassTranslation := request.way
}
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.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
//Evict the cache after reset logics
val bootEvicts = new Area {
val bootEvicts = if(clearTagsAfterReset) new Area {
val valid = RegInit(True)
mmuRsp.physicalAddress init (0)
when(valid) {
@ -588,11 +596,11 @@ class DataCache(p : DataCacheConfig) extends Component{
}
when(io.cpu.writeBack.isValid) {
if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := mmuRsp.miss
}
switch(request.kind) {
is(LINE) {
if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := mmuRsp.miss
}
when(delayedIsStuck && !mmuRsp.miss) {
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
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)
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := !request.invalidate
tagsWriteCmd.data.dirty := !request.clean
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := !request.invalidate
tagsWriteCmd.data.dirty := !request.clean
}
is(MEMORY) {
if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := mmuRsp.miss
}
when(Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) {
when(request.bypass) {
val illegal = if(catchIllegal) (request.wr && !mmuRsp.allowWrite) || (!request.wr && !mmuRsp.allowRead) else False
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
io.cpu.writeBack.unalignedAccess := unaligned
when((Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) && !illegal && !unaligned) {
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
val memCmdSent = RegInit(False)
when(!victim.request.valid) {
//Avoid mixing memory request while victim is pending
@ -639,7 +648,7 @@ class DataCache(p : DataCacheConfig) extends Component{
dataWriteCmd.data := request.data
dataWriteCmd.mask := request.mask
tagsWriteCmd.valid := !loadingNotDone || request.wr
tagsWriteCmd.valid := (!loadingNotDone) || request.wr
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := True
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")
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

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.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 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)
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))
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 cacheHit = cacheHits.asBits.orR
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 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.allowExecute := True
}
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
port.bus.rsp.miss := sharedMiss
}
}

View File

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

View File

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

View File

@ -562,12 +562,14 @@ public:
virtual void postCycle(){
if(pendingCount != 0 && !wr && (!ws->dStall || VL_RANDOM_I(7) < 100)){
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;
address += 4;
pendingCount--;
} else{
top->dBus_rsp_valid = 0;
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);