mmu working for instruction and data bus (both tested)
This commit is contained in:
parent
c647ef8bb6
commit
534a4c3494
|
@ -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)
|
||||
|
|
|
@ -236,8 +236,13 @@ object TopLevel {
|
|||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchAccessFault = false,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoStageLogic = true
|
||||
),
|
||||
askMemoryTranslation = true,
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue