mmu working for instruction and data bus (both tested)

This commit is contained in:
Charles Papon 2017-05-03 18:42:54 +02:00
parent c647ef8bb6
commit 534a4c3494
5 changed files with 70 additions and 41 deletions

View File

@ -13,28 +13,36 @@ case class InstructionCacheConfig( cacheSize : Int,
cpuDataWidth : Int,
memDataWidth : Int,
catchAccessFault : Boolean,
catchMemoryTranslationMiss : Boolean,
asyncTagMemory : Boolean,
twoStageLogic : Boolean){
def burstSize = bytePerLine*8/memDataWidth
def catchSomething = catchAccessFault || catchMemoryTranslationMiss
}
class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv] {
class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : Boolean = false, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
import config._
var iBus : InstructionCacheMemBus = null
assert(twoStageLogic || !askMemoryTranslation)
var iBus : InstructionCacheMemBus = null
var mmuBus : MemoryTranslatorBus = null
var decodeExceptionPort : Flow[ExceptionCause] = null
object IBUS_ACCESS_ERROR extends Stageable(Bool)
var decodeExceptionPort : Flow[ExceptionCause] = null
override def setup(pipeline: VexRiscv): Unit = {
pipeline.unremovableStages += pipeline.prefetch
if(catchAccessFault) {
if(catchSomething) {
val exceptionService = pipeline.service(classOf[ExceptionService])
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
}
if(askMemoryTranslation != null)
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig)
}
override def build(pipeline: VexRiscv): Unit = {
@ -62,6 +70,15 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv]
fetch.insert(INSTRUCTION) := cache.io.cpu.fetch.data
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION))
decode.insert(INSTRUCTION_READY) := True
}else {
if (mmuBus != null) {
cache.io.cpu.fetch.mmuBus <> mmuBus
} else {
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress
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.flush.cmd.valid := False
@ -77,12 +94,17 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv]
}
if(catchAccessFault){
if(!twoStageLogic) fetch.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.fetch.error
if( twoStageLogic) decode.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.decode.error
if(catchSomething){
if(catchAccessFault) {
if (!twoStageLogic) fetch.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.fetch.error
if (twoStageLogic) decode.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.decode.error
}
decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR)
decodeExceptionPort.code := 1
val accessFault = if(catchAccessFault) decode.input(IBUS_ACCESS_ERROR) else False
val mmuMiss = if(catchMemoryTranslationMiss) cache.io.cpu.decode.mmuMiss else False
decodeExceptionPort.valid := decode.arbitration.isValid && (accessFault || mmuMiss)
decodeExceptionPort.code := mmuMiss ? U(14) | 1
decodeExceptionPort.badAddr := decode.input(PC)
}
}
@ -110,11 +132,13 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
val address = UInt(p.addressWidth bit)
val data = if(!p.twoStageLogic) Bits(32 bit) else null
val error = if(!p.twoStageLogic && p.catchAccessFault) Bool else null
val mmuBus = if(p.twoStageLogic) MemoryTranslatorBus() else null
override def asMaster(): Unit = {
out(isValid, isStuck, address)
outWithNull(isStuckByOthers)
inWithNull(error,data,haltIt)
slaveWithNull(mmuBus)
}
}
@ -127,11 +151,12 @@ case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle
val data = Bits(32 bit)
val dataAnticipated = Bits(32 bits)
val error = if(p.catchAccessFault) Bool else null
val mmuMiss = if(p.catchMemoryTranslationMiss) Bool else null
override def asMaster(): Unit = {
out(isValid, isStuck, address)
in(haltIt, data, dataAnticipated)
if(p.catchAccessFault) in(error)
inWithNull(error,mmuMiss)
}
}
@ -345,10 +370,6 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
waysHitValid := True
if(catchAccessFault) waysHitError := tag.error
}
// when(lineLoader.request.valid && lineLoader.request.addr(lineRange) === io.cpu.fetch.address(lineRange)){
// waysHitValid := False //Not applicable to multi way
// }
}
@ -358,18 +379,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
if(catchAccessFault) io.cpu.fetch.error := waysRead(0).tag.error
lineLoader.requestIn.valid := io.cpu.fetch.isValid && !hit //TODO avoid duplicated request
lineLoader.requestIn.addr := io.cpu.fetch.address
// val loaderHitValid = lineLoader.request.valid && lineLoader.request.addr(tagLineRange) === io.cpu.fetch.address(tagLineRange)
// val loaderHitReady = lineLoader.loadedWordsReadable(io.cpu.fetch.address(wordRange))
//
//
// io.cpu.fetch.haltIt := io.cpu.fetch.isValid && !(waysHitValid || (loaderHitValid && loaderHitReady))
// io.cpu.fetch.data := waysHitWord //TODO
// if(catchAccessFault) io.cpu.fetch.error := (waysHitValid && waysHitError) || (loaderHitValid && loaderHitReady && lineLoader.loadingWithErrorReg)
// lineLoader.requestIn.valid := io.cpu.fetch.isValid && !io.cpu.fetch.isStuckByOthers && !waysHitValid
// lineLoader.requestIn.addr := io.cpu.fetch.address
} else new Area{
//Long readValidPath
// def writeFirstMemWrap[T <: Data](readValid : Bool, readAddress : UInt, lastAddress : UInt, readData : T,writeValid : Bool, writeAddress : UInt, writeData : T) : T = {
// val hit = writeValid && (readValid ? readAddress | lastAddress) === writeAddress
@ -458,17 +468,22 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
writeData = lineLoader.waysDatasWritePort.data
)
val hit = tag.valid && tag.address === io.cpu.decode.address(tagRange) && !(tag.loading && !lineLoader.loadedWords(io.cpu.decode.address(wordRange)))
// val hit = tag.hit && !(tag.loading && !lineLoader.loadedWords(io.cpu.decode.address(wordRange)))
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.address
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.hit && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange)))
io.cpu.decode.haltIt := io.cpu.decode.isValid && !hit //TODO PERF not halit it when removed, Should probably be applyed in many other places
io.cpu.decode.data := data
// io.cpu.decode.dataAnticipated := dataRegEn ? dataRegIn | data
io.cpu.decode.dataAnticipated := io.cpu.decode.isStuck ? Mux(dataPostWrite,lineLoader.waysDatasWritePort.data,data) | Mux(dataPreWrite,lineLoader.waysDatasWritePort.data,memRead.data)
if(catchAccessFault) io.cpu.decode.error := tag.error
if(catchMemoryTranslationMiss) io.cpu.decode.mmuMiss := mmuRsp.miss
lineLoader.requestIn.valid := io.cpu.decode.isValid && !hit //TODO avoid duplicated request
lineLoader.requestIn.addr := io.cpu.decode.address
lineLoader.requestIn.valid := io.cpu.decode.isValid && !hit && !mmuRsp.miss//TODO avoid duplicated request
lineLoader.requestIn.addr := mmuRsp.physicalAddress
}
io.flush.cmd.ready := !(lineLoader.request.valid || io.cpu.fetch.isValid)

View File

@ -236,8 +236,13 @@ object TopLevel {
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessFault = false,
catchMemoryTranslationMiss = true,
asyncTagMemory = false,
twoStageLogic = true
),
askMemoryTranslation = true,
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 4
)
),

View File

@ -160,6 +160,7 @@ public:
VerilatedVcdC* tfp;
#endif
bool withInstructionReadCheck = true;
void setIStall(bool enable) { iStall = enable; }
void setDStall(bool enable) { dStall = enable; }
@ -269,6 +270,7 @@ public:
virtual void pass(){ throw success();}
virtual void fail(){ throw std::exception();}
virtual void fillSimELements();
Workspace* noInstructionReadCheck(){withInstructionReadCheck = false; return this;}
void dump(int i){
#ifdef TRACE
if(i/2 >= TRACE_START) tfp->dump(i);
@ -348,11 +350,13 @@ public:
for(SimElement* simElement : simElements) simElement->preCycle();
if(top->VexRiscv->decode_arbitration_isValid && !top->VexRiscv->decode_arbitration_haltIt){
uint32_t expectedData;
bool dummy;
iBusAccess(top->VexRiscv->decode_PC, &expectedData, &dummy);
assertEq(top->VexRiscv->decode_INSTRUCTION,expectedData);
if(withInstructionReadCheck){
if(top->VexRiscv->decode_arbitration_isValid && !top->VexRiscv->decode_arbitration_haltIt){
uint32_t expectedData;
bool dummy;
iBusAccess(top->VexRiscv->decode_PC, &expectedData, &dummy);
assertEq(top->VexRiscv->decode_INSTRUCTION,expectedData);
}
}
checks();
@ -832,8 +836,10 @@ int main(int argc, char **argv, char **env) {
#endif
#ifdef MMU
uint32_t mmuRef[] = {1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5,
13, 0xC4000000,0x33333333, 6};
redo(REDO,TestX28("mmu",mmuRef, sizeof(mmuRef)/4).run(4e3);)
13, 0xC4000000,0x33333333, 6,7,
1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5,
13, 0xC4000000,0x33333333, 6,7};
redo(REDO,TestX28("mmu",mmuRef, sizeof(mmuRef)/4).noInstructionReadCheck()->run(4e3);)
#endif
#endif

View File

@ -1,12 +1,12 @@
IBUS=IBUS_CACHED
DBUS=DBUS_CACHED
TRACE=yes
TRACE=no
TRACE_START=0
CSR=no
MMU=yes
DHRYSTONE=yes
FREE_RTOS=no
REDO=1
REDO=10
REF=no
TRACE_WITH_TIME=no
REF_TIME=no

View File

@ -2,7 +2,7 @@
:100010001300000013000000130000001300000094
:10002000732E2034732E3034B74E0C00370F01F08E
:10003000930F40002B800E002B90EF0173002030B7
:10004000130E1000130300021303F3FF2B10030021
:10004000130E10001303F0011303F3FF2B10030032
:10005000E31C03FE130E200037020C00B70201F070
:10006000130300002B0002002B10530037120C006A
:10007000B70201F0130310002B0002002B105300F5
@ -16,8 +16,11 @@
:1000F00023A0D31003AE0310032E041003AE04108C
:10010000130E4000032E02002320E30003AE020082
:10011000032E0200130E5000032E0500130E600084
:100120001300000013000000130000001300000083
:0401300013000000B8
:10012000130E700037620C00B70200F01303F001E9
:100130002B0002002B1053001300000013000000DE
:10014000130000001300000013000000370200C677
:1001500067000200130000001300000013000000FD
:08016000130000001300000071
:020000044000BA
:1000000013050000678000006FF09FFF13050000DC
:1000100067800000130500006780000013050000E2