#60 Got the new instruction cache design passing the standard regressions

This commit is contained in:
Charles Papon 2019-04-02 00:26:53 +02:00
parent bc0af02c97
commit fd4da77084
17 changed files with 353 additions and 546 deletions

View File

@ -21,7 +21,7 @@ trait Pipeline {
def service[T](clazz : Class[T]) = {
val filtered = plugins.filter(o => clazz.isAssignableFrom(o.getClass))
assert(filtered.length == 1)
assert(filtered.length == 1, s"??? ${clazz.getName}")
filtered.head.asInstanceOf[T]
}

View File

@ -81,7 +81,6 @@ object TestsWorkspace {
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true,
atomicEntriesCount = 2
),
// memoryTranslatorPortConfig = null

View File

@ -88,8 +88,7 @@ object BrieyConfig{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchUnaligned = true
),
memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(

View File

@ -41,8 +41,7 @@ object GenFull extends App{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchUnaligned = true
),
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 6

View File

@ -42,8 +42,7 @@ object GenFullNoMmu extends App{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchUnaligned = true
)
),
new StaticMemoryTranslatorPlugin(

View File

@ -43,8 +43,7 @@ object GenFullNoMmuMaxPerf extends App{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = false
catchUnaligned = true
)
),
new StaticMemoryTranslatorPlugin(

View File

@ -96,76 +96,77 @@ object LinuxGen {
new DummyFencePlugin(), //TODO should be removed for design with caches
//Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config
// new IBusSimplePlugin(
// resetVector = 0x80000000l,
// cmdForkOnSecondStage = false,
// cmdForkPersistence = false,
// prediction = NONE,
// historyRamSizeLog2 = 10,
// catchAccessFault = true,
// compressedGen = true,
// busLatencyMin = 1,
// injectorStage = true,
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
// portTlbSize = 4
// )
// ),
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
new IBusCachedPlugin(
new IBusSimplePlugin(
resetVector = 0x80000000l,
compressedGen = true,
cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE,
injectorStage = true,
config = InstructionCacheConfig(
cacheSize = 4096,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = true,
catchAccessFault = true,
asyncTagMemory = false,
twoCycleRam = false,
twoCycleCache = true
),
memoryTranslatorPortConfig = MmuPortConfig(
portTlbSize = 4
)
),
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
new DBusSimplePlugin(
catchAddressMisaligned = true,
historyRamSizeLog2 = 10,
catchAccessFault = true,
earlyInjection = false,
atomicEntriesCount = 1,
compressedGen = true,
busLatencyMin = 1,
injectorStage = true,
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
portTlbSize = 4
)
),
// new DBusCachedPlugin(
// config = new DataCacheConfig(
// cacheSize = 4096,
// bytePerLine = 32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchAccessError = true,
// catchIllegal = true,
// catchUnaligned = true,
// catchMemoryTranslationMiss = true,
// atomicEntriesCount = 2
// ),
// // memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 6
// )
// ),
// new StaticMemoryTranslatorPlugin(
// ioRange = _(31 downto 28) === 0xF
// ),
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
// new IBusCachedPlugin(
// resetVector = 0x80000000l,
// compressedGen = true,
// prediction = NONE,
// injectorStage = true,
// config = InstructionCacheConfig(
// cacheSize = 4096,
// bytePerLine = 32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchIllegalAccess = true,
// catchAccessFault = true,
// asyncTagMemory = false,
// twoCycleRam = false,
// twoCycleCache = true
// )
// ),
// memoryTranslatorPortConfig = MmuPortConfig(
// portTlbSize = 4
// )
// ),
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
// new DBusSimplePlugin(
// catchAddressMisaligned = true,
// catchAccessFault = true,
// earlyInjection = false,
// atomicEntriesCount = 1,
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
// portTlbSize = 4
// )
// ),
new DBusCachedPlugin(
config = new DataCacheConfig(
cacheSize = 4096,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
atomicEntriesCount = 2
)
// ),
// memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MmuPortConfig(
// portTlbSize = 4
// )
),
new StaticMemoryTranslatorPlugin(
ioRange = _(31 downto 28) === 0xF
),
// new MemoryTranslatorPlugin(
// tlbSize = 32,
// virtualRange = _(31 downto 28) === 0xC,
@ -237,12 +238,12 @@ object LinuxGen {
new YamlPlugin("cpu0.yaml")
)
)
if(withMmu) config.plugins += new MmuPlugin(
virtualRange = a => True,
// virtualRange = x => x(31 downto 24) =/= 0x81, //TODO It fix the DTB kernel access (workaround)
ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE || x(31 downto 28) === 0xF else x(31 downto 28) === 0xF),
allowUserIo = true
)
// if(withMmu) config.plugins += new MmuPlugin(
// virtualRange = a => True,
// // virtualRange = x => x(31 downto 24) =/= 0x81, //TODO It fix the DTB kernel access (workaround)
// ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE || x(31 downto 28) === 0xF else x(31 downto 28) === 0xF),
// allowUserIo = true
// )
config
}
@ -265,7 +266,7 @@ object LinuxGen {
// }
// }
SpinalConfig(mergeAsyncProcess = true).generateVerilog {
SpinalConfig(mergeAsyncProcess = true, anonymSignalPrefix = "zz").generateVerilog {
val toplevel = new VexRiscv(configFull(

View File

@ -66,8 +66,7 @@ object VexRiscvAvalonForSim{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchUnaligned = true
),
memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(

View File

@ -63,8 +63,7 @@ object VexRiscvAvalonWithIntegratedJtag{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchUnaligned = true
),
memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(

View File

@ -64,8 +64,7 @@ object VexRiscvAxi4WithIntegratedJtag{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchUnaligned = true
),
memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(

View File

@ -62,8 +62,7 @@ object VexRiscvCachedWishboneForSim{
memDataWidth = 32,
catchAccessError = true,
catchIllegal = true,
catchUnaligned = true,
catchMemoryTranslationMiss = true
catchUnaligned = true
),
memoryTranslatorPortConfig = null
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(

View File

@ -8,23 +8,24 @@ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
import spinal.lib.bus.simple._
case class DataCacheConfig( cacheSize : Int,
bytePerLine : Int,
wayCount : Int,
addressWidth : Int,
cpuDataWidth : Int,
memDataWidth : Int,
catchAccessError : Boolean,
catchIllegal : Boolean,
catchUnaligned : Boolean,
catchMemoryTranslationMiss : Boolean,
clearTagsAfterReset : Boolean = true,
waysHitRetime : Boolean = true,
tagSizeShift : Int = 0, //Used to force infering ram
atomicEntriesCount : Int = 0){
case class DataCacheConfig(cacheSize : Int,
bytePerLine : Int,
wayCount : Int,
addressWidth : Int,
cpuDataWidth : Int,
memDataWidth : Int,
catchAccessError : Boolean,
catchIllegal : Boolean,
catchUnaligned : Boolean,
earlyWaysHits : Boolean = true,
earlyDataMux : Boolean = false,
tagSizeShift : Int = 0, //Used to force infering ram
atomicEntriesCount : Int = 0){
assert(!(earlyDataMux && !earlyWaysHits))
def burstSize = bytePerLine*8/memDataWidth
val burstLength = bytePerLine/(memDataWidth/8)
def catchSomething = catchUnaligned || catchMemoryTranslationMiss || catchIllegal || catchAccessError
def catchSomething = catchUnaligned || catchIllegal || catchAccessError
def genAtomic = atomicEntriesCount != 0
def getAxi4SharedConfig() = Axi4Config(
@ -64,83 +65,6 @@ case class DataCacheConfig( cacheSize : Int,
)
}
object Bypasser{
//shot readValid path
def writeFirstMemWrap[T <: Data](readValid : Bool, readLastAddress : UInt, readLastData : T,writeValid : Bool, writeAddress : UInt, writeData : T) : T = {
val writeSample = readValid || (writeValid && writeAddress === readLastAddress)
val writeValidReg = RegNextWhen(writeValid,writeSample)
val writeAddressReg = RegNextWhen(writeAddress,writeSample)
val writeDataReg = RegNextWhen(writeData,writeSample)
(writeValidReg && writeAddressReg === readLastAddress) ? writeDataReg | readLastData
}
//short readValid path
def writeFirstMemWrap(readValid : Bool, readLastAddress : UInt, readLastData : Bits,writeValid : Bool, writeAddress : UInt, writeData : Bits,writeMask : Bits) : Bits = {
val writeHit = writeValid && writeAddress === readLastAddress
val writeSample = readValid || writeHit
val writeValidReg = RegNextWhen(writeValid,writeSample)
val writeAddressReg = RegNextWhen(writeAddress,writeSample)
val writeDataReg = Reg(writeData)
val writeMaskReg = Reg(Bits(widthOf(writeData)/8 bits))
val writeDataRegBytes = writeDataReg.subdivideIn(8 bits)
val writeDataBytes = writeData.subdivideIn(8 bits)
val ret = cloneOf(readLastData)
val retBytes = ret.subdivideIn(8 bits)
val readLastDataBytes = readLastData.subdivideIn(8 bits)
val writeRegHit = writeValidReg && writeAddressReg === readLastAddress
for(b <- writeMask.range){
when(writeHit && writeMask(b)){
writeMaskReg(b) := True
}
when(readValid) {
writeMaskReg(b) := writeMask(b)
}
when(readValid || (writeHit && writeMask(b))){
writeDataRegBytes(b) := writeDataBytes(b)
}
retBytes(b) := (writeRegHit && writeMaskReg(b)) ? writeDataRegBytes(b) | readLastDataBytes(b)
}
ret
}
//Long sample path
// def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,lastAddress : UInt, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) : (T,T) = {
// val hit = writeValid && (sample ? sampleAddress | lastAddress) === writeAddress
// val bypass = hit ? writeData | readData
// val reg = RegNextWhen(bypass,sample || hit)
// (reg,bypass)
// }
//Short sample path
def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, sampleData : T, writeValid : Bool, writeAddress : UInt, writeData : T) = {
val bypass = (!sample || (writeValid && sampleAddress === writeAddress)) ? writeData | sampleData
val regEn = sample || (writeValid && sampleLastAddress === writeAddress)
val reg = RegNextWhen(bypass,regEn)
reg
}
def writeFirstRegWrap(sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, sampleData : Bits, writeValid : Bool, writeAddress : UInt, writeData : Bits,writeMask : Bits) = {
val byteCount = widthOf(writeMask)
val sampleWriteHit = writeValid && sampleAddress === writeAddress
val sampleLastHit = writeValid && sampleLastAddress === writeAddress
val regBytes = Vec(Bits(8 bits),byteCount)
for(b <- writeMask.range){
val bypass = Mux(!sample || (sampleWriteHit && writeMask(b)), writeData(b*8, 8 bits), sampleData(b*8, 8 bits))
val regEn = sample || (sampleLastHit && writeMask(b))
regBytes(b) := RegNextWhen(bypass,regEn)
}
regBytes.asBits
}
}
object DataCacheCpuCmdKind extends SpinalEnum{
val MEMORY,MANAGMENT = newElement()
}
object DataCacheCpuExecute{
implicit def implArgs(that : DataCacheCpuExecute) = that.args
}
@ -148,23 +72,22 @@ object DataCacheCpuExecute{
case class DataCacheCpuExecute(p : DataCacheConfig) extends Bundle with IMasterSlave{
val isValid = Bool
val isStuck = Bool
val address = UInt(p.addressWidth bit)
// val haltIt = Bool
val args = DataCacheCpuExecuteArgs(p)
override def asMaster(): Unit = {
out(isValid, isStuck, args)
out(isValid, isStuck, args, address)
// in(haltIt)
}
}
case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
val kind = DataCacheCpuCmdKind()
val wr = Bool
val address = UInt(p.addressWidth bit)
//val address = UInt(p.addressWidth bit) Given on the side, as it's also part of the main pipeline
val data = Bits(p.cpuDataWidth bit)
val size = UInt(2 bits)
val forceUncachedAccess = Bool
val clean, invalidate, way = Bool
val isAtomic = ifGen(p.genAtomic){Bool}
// val all = Bool //Address should be zero when "all" is used
}
@ -173,12 +96,11 @@ case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSl
val isValid = Bool
val isStuck = Bool
val isRemoved = Bool
val haltIt = Bool
val address = UInt(p.addressWidth bit)
val mmuBus = MemoryTranslatorBus()
override def asMaster(): Unit = {
out(isValid, isStuck, isRemoved)
in(haltIt)
out(isValid, isStuck, isRemoved, address)
slave(mmuBus)
}
}
@ -190,14 +112,15 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
val isUser = Bool
val haltIt = Bool
val data = Bits(p.cpuDataWidth bit)
val mmuMiss, illegalAccess, unalignedAccess , accessError = Bool
val badAddr = UInt(32 bits)
val address = UInt(p.addressWidth bit)
val mmuException, unalignedAccess , accessError = Bool
val clearAtomicEntries = ifGen(p.genAtomic) {Bool}
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
override def asMaster(): Unit = {
out(isValid,isStuck,isUser)
in(haltIt, data, mmuMiss,illegalAccess , unalignedAccess, accessError, badAddr)
out(isValid,isStuck,isUser, address)
in(haltIt, data, mmuException, unalignedAccess, accessError)
outWithNull(clearAtomicEntries)
}
}
@ -207,10 +130,13 @@ case class DataCacheCpuBus(p : DataCacheConfig) extends Bundle with IMasterSlave
val memory = DataCacheCpuMemory(p)
val writeBack = DataCacheCpuWriteBack(p)
val redo = Bool()
override def asMaster(): Unit = {
master(execute)
master(memory)
master(writeBack)
in(redo)
}
}
@ -370,7 +296,6 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
class DataCache(p : DataCacheConfig) extends Component{
import p._
import DataCacheCpuCmdKind._
assert(wayCount == 1)
assert(cpuDataWidth == memDataWidth)
@ -379,6 +304,7 @@ class DataCache(p : DataCacheConfig) extends Component{
val mem = master(DataCacheMemBus(p))
// val flushDone = out Bool //It pulse at the same time than the manager.request.fire
}
val haltCpu = False
val lineWidth = bytePerLine*8
val lineCount = cacheSize/bytePerLine
@ -397,14 +323,13 @@ class DataCache(p : DataCacheConfig) extends Component{
class LineInfo() extends Bundle{
val used = Bool
val dirty = Bool
val valid, error = Bool()
val address = UInt(tagRange.length bit)
}
val tagsReadCmd = Flow(UInt(log2Up(wayLineCount) bits))
val tagsWriteCmd = Flow(new Bundle{
// val way = UInt(log2Up(wayCount) bits)
val way = Bits(wayCount bits)
val address = UInt(log2Up(wayLineCount) bits)
val data = new LineInfo()
})
@ -413,13 +338,39 @@ class DataCache(p : DataCacheConfig) extends Component{
val dataReadCmd = Flow(UInt(log2Up(wayWordCount) bits))
val dataWriteCmd = Flow(new Bundle{
// val way = UInt(log2Up(wayCount) bits)
val way = Bits(wayCount bits)
val address = UInt(log2Up(wayWordCount) bits)
val data = Bits(wordWidth bits)
val mask = Bits(wordWidth/8 bits)
})
io.mem.cmd.valid := False
io.mem.cmd.payload.assignDontCare()
val ways = for(i <- 0 until wayCount) yield new Area{
val tags = Mem(new LineInfo(), wayLineCount)
val data = Mem(Bits(wordWidth bit), wayWordCount)
//Reads
val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.execute.isStuck)
val dataReadRsp = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.execute.isStuck)
//Writes
when(tagsWriteCmd.valid && tagsWriteCmd.way(i)){
tags(tagsWriteCmd.address) := tagsWriteCmd.data
}
when(dataWriteCmd.valid && dataWriteCmd.way(i)){
data.write(
address = dataWriteCmd.address,
data = dataWriteCmd.data,
mask = dataWriteCmd.mask
)
}
}
tagsReadCmd.valid := False
tagsReadCmd.payload.assignDontCare()
dataReadCmd.valid := False
@ -428,219 +379,74 @@ class DataCache(p : DataCacheConfig) extends Component{
tagsWriteCmd.payload.assignDontCare()
dataWriteCmd.valid := False
dataWriteCmd.payload.assignDontCare()
io.mem.cmd.valid := False
io.mem.cmd.payload.assignDontCare()
val way = new Area{
val tags = Mem(new LineInfo(),wayLineCount)
val data = Mem(Bits(wordWidth bit),wayWordCount)
when(tagsWriteCmd.valid){
tags(tagsWriteCmd.address) := tagsWriteCmd.data
}
when(dataWriteCmd.valid){
data.write(
address = dataWriteCmd.address,
data = dataWriteCmd.data,
mask = dataWriteCmd.mask
)
}
val tagReadRspOneAddress = RegNextWhen(tagsReadCmd.payload, tagsReadCmd.valid)
val tagReadRspOne = Bypasser.writeFirstMemWrap(
readValid = tagsReadCmd.valid,
readLastAddress = tagReadRspOneAddress,
readLastData = tags.readSync(tagsReadCmd.payload,enable = tagsReadCmd.valid),
writeValid = tagsWriteCmd.valid,
writeAddress = tagsWriteCmd.address,
writeData = tagsWriteCmd.data
)
val dataReadRspOneKeepAddress = False
val dataReadRspOneAddress = RegNextWhen(dataReadCmd.payload, dataReadCmd.valid && !dataReadRspOneKeepAddress)
val dataReadRspOneWithoutBypass = data.readSync(dataReadCmd.payload,enable = dataReadCmd.valid)
val dataReadRspOne = Bypasser.writeFirstMemWrap(
readValid = dataReadCmd.valid,
readLastAddress = dataReadRspOneAddress,
readLastData = dataReadRspOneWithoutBypass,
writeValid = dataWriteCmd.valid,
writeAddress = dataWriteCmd.address,
writeData = dataWriteCmd.data,
writeMask = dataWriteCmd.mask
)
val tagReadRspTwoEnable = !io.cpu.writeBack.isStuck
val tagReadRspTwoRegIn = (tagsWriteCmd.valid && tagsWriteCmd.address === tagReadRspOneAddress) ? tagsWriteCmd.data | tagReadRspOne
val tagReadRspTwo = RegNextWhen(tagReadRspTwoRegIn ,tagReadRspTwoEnable)
val dataReadRspTwoEnable = !io.cpu.writeBack.isStuck
val dataReadRspTwo = Bypasser.writeFirstRegWrap(
sample = dataReadRspTwoEnable,
sampleAddress = dataReadRspOneAddress,
sampleLastAddress = RegNextWhen(dataReadRspOneAddress, dataReadRspTwoEnable),
sampleData = dataReadRspOne,
writeValid = dataWriteCmd.valid,
writeAddress = dataWriteCmd.address,
writeData = dataWriteCmd.data,
writeMask = dataWriteCmd.mask
)
}
when(io.cpu.execute.isValid && !io.cpu.execute.isStuck){
tagsReadCmd.valid := True
tagsReadCmd.valid := True
dataReadCmd.valid := True
tagsReadCmd.payload := io.cpu.execute.address(lineRange)
dataReadCmd.valid := True
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) //TODO FMAX maybe critical path could be default
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low)
}
val cpuMemoryStageNeedReadData = Bool()
val victim = new Area{
val requestIn = Stream(cloneable(new Bundle{
// val way = UInt(log2Up(wayCount) bits)
val address = UInt(p.addressWidth bits)
}))
requestIn.valid := False
requestIn.payload.assignDontCare()
val request = requestIn.halfPipe()
request.ready := False
val buffer = Mem(Bits(p.memDataWidth bits),memTransactionPerLine << tagSizeShift) // WARNING << tagSizeShift could resolve cyclone II issue, //.add(new AttributeString("ramstyle","M4K"))
//Send line read commands to fill the buffer
val readLineCmdCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
val dataReadCmdOccure = False
val dataReadRestored = RegInit(False)
when(request.valid){
when(!readLineCmdCounter.msb) {
readLineCmdCounter := readLineCmdCounter + 1
//dataReadCmd := request.address(lineRange.high downto wordRange.low) Done in the manager
dataReadCmdOccure := True
dataReadCmd.valid := True
dataReadCmd.payload := request.address(lineRange) @@ readLineCmdCounter(readLineCmdCounter.high - 1 downto 0)
way.dataReadRspOneKeepAddress := True
} otherwise {
when(!dataReadRestored && cpuMemoryStageNeedReadData) {
dataReadCmd.valid := True
dataReadCmd.payload := way.dataReadRspOneAddress //Restore stage one readed value
}
dataReadRestored := True
}
}
dataReadRestored clearWhen(request.ready)
io.cpu.memory.haltIt := cpuMemoryStageNeedReadData && request.valid && !dataReadRestored
//Fill the buffer with line read responses
val readLineRspCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
when(Delay(dataReadCmdOccure,1, init=False)){
buffer(readLineRspCounter.resized) := way.dataReadRspOneWithoutBypass
readLineRspCounter := readLineRspCounter + 1
}
//Send buffer read commands
val bufferReadCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
val bufferReadStream = Stream(buffer.addressType)
bufferReadStream.valid := readLineRspCounter > bufferReadCounter
bufferReadStream.payload := bufferReadCounter.resized
when(bufferReadStream.fire){
bufferReadCounter := bufferReadCounter + 1
}
val bufferReaded = buffer.streamReadSync(bufferReadStream).stage
bufferReaded.ready := False
//Send memory writes from bufffer read responses
val bufferReadedCounter = Reg(UInt(log2Up(memTransactionPerLine) bits)) init(0)
val memCmdAlreadyUsed = False
when(bufferReaded.valid) {
io.mem.cmd.valid := True
io.mem.cmd.wr := True
io.mem.cmd.address := request.address(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
io.mem.cmd.length := p.burstLength-1
io.mem.cmd.data := bufferReaded.payload
io.mem.cmd.mask := (1<<(wordWidth/8))-1
io.mem.cmd.last := bufferReadedCounter === bufferReadedCounter.maxValue
when(!memCmdAlreadyUsed && io.mem.cmd.ready){
bufferReaded.ready := True
bufferReadedCounter := bufferReadedCounter + 1
when(bufferReadedCounter === bufferReadedCounter.maxValue){
request.ready := True
}
}
}
val counter = Counter(memTransactionPerLine)
when(request.ready){
readLineCmdCounter.msb := False
readLineRspCounter.msb := False
bufferReadCounter.msb := False
def collisionProcess(readAddress : UInt, readMask : Bits): Bits ={
val ret = Bits(wayCount bits)
for(i <- 0 until wayCount){
ret(i) := dataWriteCmd.valid && dataWriteCmd.way(i) && dataWriteCmd.address === readAddress && (readMask & dataWriteCmd.mask) =/= 0
}
ret
}
val stageA = new Area{
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.bypassTranslation := request.way
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
cpuMemoryStageNeedReadData := io.cpu.memory.isValid && request.kind === MEMORY && !request.wr
}
val stageB = new Area {
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck)
val waysHit = if(waysHitRetime)
RegNextWhen(way.tagReadRspTwoRegIn.used && io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming
else
way.tagReadRspTwo.used && mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwo.address
//Loader interface
val loaderValid = False
val loaderReady = False
val loadingDone = RegNext(loaderValid && loaderReady) init(False) //one cycle pulse
//delayedXX are used to relax logic timings in flush and evict modes
val delayedIsStuck = RegNext(io.cpu.writeBack.isStuck)
val delayedWaysHitValid = RegNext(waysHit)
val victimNotSent = RegInit(False) clearWhen(victim.requestIn.ready) setWhen(!io.cpu.memory.isStuck)
val loadingNotDone = RegInit(False) clearWhen(loaderReady) setWhen(!io.cpu.memory.isStuck)
val writeMask = request.size.mux (
val stage0 = new Area{
val mask = io.cpu.execute.size.mux (
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) |<< mmuRsp.physicalAddress(1 downto 0)
) |<< io.cpu.execute.address(1 downto 0)
val colisions = collisionProcess(io.cpu.execute.address(lineRange.high downto wordRange.low), mask)
}
val stageA = new Area{
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.memory.isStuck)
val request = stagePipe(io.cpu.execute.args)
val mask = stagePipe(stage0.mask)
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid
io.cpu.memory.mmuBus.cmd.virtualAddress := io.cpu.memory.address
io.cpu.memory.mmuBus.cmd.bypassTranslation := False
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
val wayHits = earlyWaysHits generate ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid))
val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp))
val colisions = stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) //Assume the writeback stage will never be unstall memory acces while memory stage is stalled
}
val stageB = new Area {
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.writeBack.isStuck)
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
val mmuRspFreeze = False
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze)
val tagsReadRsp = ways.map(w => stagePipe(w.tagsReadRsp))
val dataReadRsp = !earlyDataMux generate ways.map(w => stagePipe(w.dataReadRsp))
val waysHits = if(earlyWaysHits) stagePipe(B(stageA.wayHits)) else B(tagsReadRsp.map(tag => mmuRsp.physicalAddress(tagRange) === tag.address && tag.valid).asBits())
val waysHit = waysHits.orR
val dataMux = if(earlyDataMux) stagePipe(stageA.dataMux) else MuxOH(waysHits, dataReadRsp)
val mask = stagePipe(stageA.mask)
val colisions = stagePipe(stageA.colisions)
//Loader interface
val loaderValid = False
val hadMemRspErrorReg = RegInit(False)
val hadMemRspError = (io.mem.rsp.valid && io.mem.rsp.error) || hadMemRspErrorReg
hadMemRspErrorReg := hadMemRspError && io.cpu.writeBack.haltIt
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) hadMemRspError && !io.cpu.writeBack.haltIt else False)
io.cpu.writeBack.badAddr := request.address
//Evict the cache after reset logics
val bootEvicts = if(clearTagsAfterReset) new Area {
val flusher = new Area {
val valid = RegInit(True)
mmuRsp.physicalAddress init (0)
when(valid) {
tagsWriteCmd.valid := valid
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := False
tagsWriteCmd.way.setAll()
tagsWriteCmd.data.valid := False
when(mmuRsp.physicalAddress(lineRange) =/= lineCount - 1) {
mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
io.cpu.writeBack.haltIt := True
@ -651,7 +457,7 @@ class DataCache(p : DataCacheConfig) extends Component{
}
val atomic = if(genAtomic) new Area{
val atomic = genAtomic generate new Area{
case class AtomicEntry() extends Bundle{
val valid = Bool()
val size = UInt(2 bits)
@ -664,11 +470,11 @@ class DataCache(p : DataCacheConfig) extends Component{
}
val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount)
val entriesAllocCounter = Counter(atomicEntriesCount)
val entriesHit = entries.map(e => e.valid && e.size === request.size && e.address === request.address).orR
val entriesHit = entries.map(e => e.valid && e.size === request.size && e.address === io.cpu.writeBack.address).orR
when(io.cpu.writeBack.isValid && request.isAtomic && !request.wr){
entries(entriesAllocCounter).valid := True
entries(entriesAllocCounter).size := request.size
entries(entriesAllocCounter).address := request.address
entries(entriesAllocCounter).size := request.size //TODO remove size stuff
entries(entriesAllocCounter).address := io.cpu.writeBack.address
when(!io.cpu.writeBack.isStuck){
entriesAllocCounter.increment()
}
@ -676,128 +482,127 @@ class DataCache(p : DataCacheConfig) extends Component{
when(io.cpu.writeBack.clearAtomicEntries){
entries.foreach(_.valid := False)
}
}
val memCmdSent = RegInit(False) setWhen (io.mem.cmd.ready) clearWhen (!io.cpu.writeBack.isStuck)
io.cpu.redo := mmuRsp.refilling
io.cpu.writeBack.accessError := False
io.cpu.writeBack.mmuException := io.cpu.writeBack.isValid && (if(catchIllegal) mmuRsp.exception || (!mmuRsp.allowWrite && request.wr) || (!mmuRsp.allowRead && !request.wr) || (!mmuRsp.allowUser && io.cpu.writeBack.isUser) else False)
io.cpu.writeBack.unalignedAccess := io.cpu.writeBack.isValid && (if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False)
when(request.isAtomic && ! entriesHit){
writeMask := 0
}
} else null
when(io.cpu.writeBack.isValid) {
if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := ??? //TODO mmuRsp.miss
}
switch(request.kind) {
is(MANAGMENT) {
when(delayedIsStuck && ???){ //TODO!mmuRsp.miss) {
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready))
victim.requestIn.valid := request.clean && way.tagReadRspTwo.dirty
tagsWriteCmd.valid := victim.requestIn.ready
} otherwise{
io.cpu.writeBack.haltIt := False
}
}
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
io.cpu.writeBack.haltIt.clearWhen(request.wr ? io.mem.cmd.ready | io.mem.rsp.valid)
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
}
is(MEMORY) {
val illegal = if(catchIllegal) (request.wr && !mmuRsp.allowWrite) || (!request.wr && !mmuRsp.allowRead) || (io.cpu.writeBack.isUser && !mmuRsp.allowUser) else False
val unaligned = if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False
io.cpu.writeBack.illegalAccess := illegal
io.cpu.writeBack.unalignedAccess := unaligned
when((Bool(!catchMemoryTranslationMiss) || ???) && !illegal && !unaligned) { //TODO !mmuRsp.miss
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
val memCmdSent = RegInit(False)
when(!victim.request.valid) {
//Avoid mixing memory request while victim is pending
io.mem.cmd.wr := request.wr
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
io.mem.cmd.mask := writeMask
io.mem.cmd.data := request.data
io.mem.cmd.length := 0
io.mem.cmd.last := True
io.mem.cmd.valid := !memCmdSent
io.mem.cmd.wr := request.wr
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
io.mem.cmd.mask := mask
io.mem.cmd.data := request.data
io.mem.cmd.length := 0
io.mem.cmd.last := True
} otherwise {
when(waysHit || request.wr) { //Do not require a cache refill ?
//Data cache update
dataWriteCmd.valid setWhen(request.wr && waysHit)
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
dataWriteCmd.data := request.data
dataWriteCmd.mask := mask
dataWriteCmd.way := waysHits
when(!memCmdSent) {
io.mem.cmd.valid := True
memCmdSent setWhen (io.mem.cmd.ready)
}
//Write through
io.mem.cmd.valid setWhen(request.wr)
io.mem.cmd.wr := True
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
io.mem.cmd.mask := mask
io.mem.cmd.data := request.data
io.mem.cmd.length := 0
io.mem.cmd.last := True
io.cpu.writeBack.haltIt clearWhen(!request.wr || io.mem.cmd.ready)
io.cpu.writeBack.haltIt.clearWhen(memCmdSent && (io.mem.rsp.fire || request.wr)) //Cut mem.cmd.ready path but insert one cycle stall when write
}
memCmdSent clearWhen (!io.cpu.writeBack.isStuck)
} otherwise {
when(waysHit || !loadingNotDone) {
io.cpu.writeBack.haltIt := False
dataWriteCmd.valid := request.wr
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
dataWriteCmd.data := request.data
dataWriteCmd.mask := writeMask
//On write to read colisions
io.cpu.redo := !request.wr && (colisions & waysHits) =/= 0
} otherwise { //Do refill
tagsWriteCmd.valid := (!loadingNotDone) || request.wr
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := True
tagsWriteCmd.data.dirty := request.wr
tagsWriteCmd.data.address := mmuRsp.physicalAddress(tagRange)
} otherwise {
val victimRequired = way.tagReadRspTwo.used && way.tagReadRspTwo.dirty
loaderValid := loadingNotDone && !(victimNotSent && victim.request.isStall) //Additional condition used to be sure of that all previous victim are written into the RAM
victim.requestIn.valid := victimRequired && victimNotSent
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
}
}
}
//Emit cmd
io.mem.cmd.valid setWhen(!memCmdSent)
io.mem.cmd.wr := False
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
io.mem.cmd.length := p.burstLength-1
io.mem.cmd.last := True
loaderValid setWhen(io.mem.cmd.ready)
}
}
}
when(request.forceUncachedAccess || mmuRsp.isIoAccess){
io.cpu.writeBack.data := io.mem.rsp.data
if(catchAccessError) io.cpu.writeBack.accessError := io.mem.rsp.valid && io.mem.rsp.error
} otherwise {
io.cpu.writeBack.data := dataMux
if(catchAccessError) io.cpu.writeBack.accessError := (waysHits & B(tagsReadRsp.map(_.error))) =/= 0
}
//remove side effects on exceptions
when(mmuRsp.refilling || io.cpu.writeBack.accessError || io.cpu.writeBack.mmuException || io.cpu.writeBack.unalignedAccess){
io.mem.cmd.valid := False
tagsWriteCmd.valid := False
dataWriteCmd.valid := False
loaderValid := False
io.cpu.writeBack.haltIt := False
}
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.forceUncachedAccess || mmuRsp.isIoAccess) ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
if(genAtomic){
when(request.isAtomic && request.wr){
io.cpu.writeBack.data := (!atomic.entriesHit).asBits.resized
}
when(request.isAtomic && !atomic.entriesHit){
io.mem.cmd.mask := 0
}
}
}
//The whole life of a loading task, the corresponding manager request is present
val loader = new Area{
val valid = RegNext(stageB.loaderValid) init(False)
val valid = RegInit(False) setWhen(stageB.loaderValid)
val baseAddress = stageB.mmuRsp.physicalAddress
val memCmdSent = RegInit(False)
when(valid && !memCmdSent) {
io.mem.cmd.valid := True
io.mem.cmd.wr := False
io.mem.cmd.address := baseAddress(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
io.mem.cmd.length := p.burstLength-1
io.mem.cmd.last := True
}
when(valid && io.mem.cmd.ready){
memCmdSent := True
}
when(valid && !memCmdSent) {
victim.memCmdAlreadyUsed := True
}
val counter = Counter(memTransactionPerLine)
val waysAllocator = Reg(Bits(wayCount bits)) init(1)
val error = RegInit(False)
when(valid && io.mem.rsp.valid){
dataWriteCmd.valid := True
dataWriteCmd.address := baseAddress(lineRange) @@ counter
dataWriteCmd.data := io.mem.rsp.data
dataWriteCmd.mask := (1<<(wordWidth/8))-1
dataWriteCmd.mask.setAll()
dataWriteCmd.way := waysAllocator
error := error | io.mem.rsp.error
counter.increment()
}
when(counter.willOverflow){
memCmdSent := False
valid := False
stageB.loaderReady := True
//Update tags
tagsWriteCmd.valid := True
tagsWriteCmd.address := baseAddress(lineRange)
tagsWriteCmd.data.valid := True
tagsWriteCmd.data.address := baseAddress(tagRange)
tagsWriteCmd.data.error := error || io.mem.rsp.error
tagsWriteCmd.way := waysAllocator
waysAllocator := (waysAllocator ## waysAllocator.msb).resized
error := False
}
io.cpu.redo setWhen(valid)
stageB.mmuRspFreeze setWhen(stageB.loaderValid || valid)
}
}

View File

@ -26,6 +26,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
var mmuBus : MemoryTranslatorBus = null
var exceptionBus : Flow[ExceptionCause] = null
var privilegeService : PrivilegeService = null
var redoBranch : Flow[UInt] = null
object MEMORY_ENABLE extends Stageable(Bool)
object MEMORY_MANAGMENT extends Stageable(Bool)
@ -44,7 +45,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
SRC_USE_SUB_LESS -> False,
MEMORY_ENABLE -> True,
RS1_USE -> True
) ++ (if (catchUnaligned) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
) ++ (if (catchSomething) 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,
@ -75,13 +76,14 @@ class DBusCachedPlugin(config : DataCacheConfig,
decoderService.add(
key = LR,
values = loadActions.filter(_._1 != SRC2_CTRL) ++ Seq(
SRC2_CTRL -> Src2CtrlEnum.RS,
SRC_ADD_ZERO -> True,
MEMORY_ATOMIC -> True
)
)
decoderService.add(
key = SC,
values = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
SRC_ADD_ZERO -> True,
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> False,
@ -98,6 +100,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
))
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.writeBack)
if(catchSomething)
exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack)
@ -141,8 +144,8 @@ class DBusCachedPlugin(config : DataCacheConfig,
val size = input(INSTRUCTION)(13 downto 12).asUInt
cache.io.cpu.execute.isValid := arbitration.isValid && input(MEMORY_ENABLE)
cache.io.cpu.execute.isStuck := arbitration.isStuck
cache.io.cpu.execute.address := input(SRC_ADD).asUInt
cache.io.cpu.execute.args.wr := input(MEMORY_WR)
cache.io.cpu.execute.args.address := input(SRC_ADD).asUInt
cache.io.cpu.execute.args.data := size.mux(
U(0) -> input(RS2)( 7 downto 0) ## input(RS2)( 7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0),
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
@ -150,19 +153,18 @@ class DBusCachedPlugin(config : DataCacheConfig,
)
cache.io.cpu.execute.args.size := size
cache.io.cpu.execute.args.forceUncachedAccess := False
cache.io.cpu.execute.args.kind := input(MEMORY_MANAGMENT) ? DataCacheCpuCmdKind.MANAGMENT | DataCacheCpuCmdKind.MEMORY
cache.io.cpu.execute.args.clean := input(INSTRUCTION)(28)
cache.io.cpu.execute.args.invalidate := input(INSTRUCTION)(29)
cache.io.cpu.execute.args.way := input(INSTRUCTION)(30)
if(genAtomic) {
cache.io.cpu.execute.args.isAtomic := False
when(input(MEMORY_ATOMIC)){
cache.io.cpu.execute.args.isAtomic := True
cache.io.cpu.execute.args.address := input(SRC1).asUInt
}
}
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.args.address(1 downto 0)
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.address(1 downto 0)
when(cache.io.cpu.redo && arbitration.isValid && input(MEMORY_ENABLE)){
arbitration.haltItself := True
}
}
memory plug new Area{
@ -170,10 +172,9 @@ class DBusCachedPlugin(config : DataCacheConfig,
cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE)
cache.io.cpu.memory.isStuck := arbitration.isStuck
cache.io.cpu.memory.isRemoved := arbitration.removeIt
arbitration.haltItself setWhen(cache.io.cpu.memory.haltIt)
cache.io.cpu.memory.address := U(input(REGFILE_WRITE_DATA))
cache.io.cpu.memory.mmuBus <> mmuBus
arbitration.haltItself setWhen (mmuBus.cmd.isValid && ???) //TODO !mmuBus.rsp.hit && !mmuBus.rsp.miss
}
writeBack plug new Area{
@ -181,20 +182,36 @@ class DBusCachedPlugin(config : DataCacheConfig,
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser() else False)
cache.io.cpu.writeBack.address := U(input(REGFILE_WRITE_DATA))
if(genAtomic) cache.io.cpu.writeBack.clearAtomicEntries := service(classOf[IContextSwitching]).isContextSwitching
if(catchSomething) {
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr
exceptionBus.valid := False //cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
exceptionBus.badAddr := U(input(REGFILE_WRITE_DATA))
exceptionBus.code.assignDontCare()
when(cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError){
exceptionBus.code := (input(MEMORY_WR) ? U(7) | U(5)).resized
}
when(cache.io.cpu.writeBack.unalignedAccess){
exceptionBus.code := (input(MEMORY_WR) ? U(6) | U(4)).resized
}
when(cache.io.cpu.writeBack.mmuMiss){
exceptionBus.code := 13
redoBranch.valid := False
redoBranch.payload := input(PC)
arbitration.flushAll setWhen(redoBranch.valid)
when(cache.io.cpu.writeBack.isValid) {
if (catchAccessError) when(cache.io.cpu.writeBack.accessError) {
exceptionBus.valid := True
exceptionBus.code := (input(MEMORY_WR) ? U(7) | U(5)).resized
}
if (catchUnaligned) when(cache.io.cpu.writeBack.unalignedAccess) {
exceptionBus.valid := True
exceptionBus.code := (input(MEMORY_WR) ? U(6) | U(4)).resized
}
when (cache.io.cpu.writeBack.mmuException) {
exceptionBus.valid := True
exceptionBus.code := (input(MEMORY_WR) ? U(15) | U(13)).resized
}
when(cache.io.cpu.redo) {
redoBranch.valid := True
exceptionBus.valid := False
}
}
}
arbitration.haltItself.setWhen(cache.io.cpu.writeBack.haltIt)

View File

@ -33,9 +33,8 @@ class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRis
port.bus.rsp.allowExecute := True
port.bus.rsp.allowUser := True
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
???
// port.bus.rsp.miss := False
// port.bus.rsp.hit := True
port.bus.rsp.exception := False
port.bus.rsp.refilling := False
}
}
}

View File

@ -1,19 +1,19 @@
[*]
[*] GTKWave Analyzer v3.3.100 (w)1999-2019 BSI
[*] Sat Mar 30 09:33:33 2019
[*] Mon Apr 1 21:53:07 2019
[*]
[dumpfile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/linux.vcd"
[dumpfile_mtime] "Sat Mar 30 09:16:30 2019"
[dumpfile_size] 249834424
[dumpfile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/rv32ui-p-lw.vcd"
[dumpfile_mtime] "Mon Apr 1 21:52:20 2019"
[dumpfile_size] 1974526
[savefile] "/home/miaou/pro/VexRiscv/src/test/cpp/regression/fail.gtkw"
[timestart] 106663042
[timestart] 348
[size] 1920 1030
[pos] -458 -215
*-5.000000 106541900 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[pos] -1 -1
*-2.000000 357 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] TOP.
[treeopen] TOP.VexRiscv.
[sst_width] 287
[signals_width] 465
[signals_width] 563
[sst_expanded] 1
[sst_vpaned_height] 279
@28
@ -21,43 +21,37 @@ TOP.VexRiscv.writeBack_arbitration_isFiring
@22
TOP.VexRiscv.writeBack_PC[31:0]
TOP.VexRiscv.writeBack_INSTRUCTION[31:0]
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_address[4:0]
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_payload_data[31:0]
@28
TOP.VexRiscv.CsrPlugin_exception
TOP.VexRiscv.CsrPlugin_privilege[1:0]
TOP.VexRiscv.writeBack_RegFilePlugin_regFileWrite_valid
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_valid
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_ready
@22
TOP.VexRiscv.CsrPlugin_scause_exceptionCode[3:0]
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_address[31:0]
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_data[31:0]
@28
TOP.VexRiscv.CsrPlugin_scause_interrupt
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_last
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_length[2:0]
@22
TOP.VexRiscv.IBusSimplePlugin_jump_pcLoad_payload[31:0]
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_mask[3:0]
@28
TOP.VexRiscv.IBusSimplePlugin_jump_pcLoad_valid
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_cmd_payload_wr
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_rsp_valid
@22
TOP.VexRiscv.CsrPlugin_mepc[31:0]
TOP.VexRiscv.CsrPlugin_sepc[31:0]
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_rsp_payload_data[31:0]
@28
TOP.VexRiscv.decode_IS_RVC
@24
TOP.VexRiscv.CsrPlugin_mcycle[63:0]
@28
TOP.VexRiscv.decode_IS_RVC
TOP.VexRiscv.decode_arbitration_isValid
@22
TOP.VexRiscv.RegFilePlugin_regFile(10)[31:0]
@28
TOP.dBus_cmd_valid
TOP.dBus_cmd_ready
@22
TOP.dBus_cmd_payload_address[31:0]
@28
TOP.dBus_cmd_payload_wr
@29
TOP.dBus_cmd_payload_size[1:0]
@22
TOP.dBus_cmd_payload_data[31:0]
TOP.dBus_rsp_data[31:0]
@28
TOP.dBus_rsp_error
TOP.dBus_rsp_ready
[color] 1
TOP.VexRiscv.dataCache_1_.io_mem_rsp_payload_error
[pattern_trace] 1
[pattern_trace] 0

View File

@ -3446,6 +3446,7 @@ int main(int argc, char **argv, char **env) {
// redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
// return 0;
for(int idx = 0;idx < 1;idx++){
#if defined(DEBUG_PLUGIN_EXTERNAL) || defined(RUN_HEX)

View File

@ -366,7 +366,6 @@ class DBusDimension extends VexRiscvDimension("DBus") {
catchAccessError = catchAll,
catchIllegal = catchAll,
catchUnaligned = catchAll,
catchMemoryTranslationMiss = catchAll,
atomicEntriesCount = 0
),
memoryTranslatorPortConfig = null