DataCache plugin now support all exceptions
This commit is contained in:
parent
5ba8ab7947
commit
ca1bc9cf69
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue