Smaller and faster single stage instruction cache
Add fast two stage instruction cache Remove useless address == 0 checks in the HazardPlugin
This commit is contained in:
parent
c83a157c64
commit
024e14ae58
|
@ -128,7 +128,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
|
||||
}
|
||||
|
||||
if(catchAddressMisaligned) {
|
||||
if(catchAddressMisaligned) { //TODO conflict with instruction cache two stage
|
||||
branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0
|
||||
branchExceptionPort.code := 0
|
||||
branchExceptionPort.badAddr := jumpInterface.payload
|
||||
|
@ -180,7 +180,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
}
|
||||
|
||||
if(catchAddressMisaligned) {
|
||||
predictionExceptionPort.valid := input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0
|
||||
predictionExceptionPort.valid := input(INSTRUCTION_READY) && input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0
|
||||
predictionExceptionPort.code := 0
|
||||
predictionExceptionPort.badAddr := predictionJumpInterface.payload
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
}
|
||||
|
||||
if(catchAddressMisaligned) {
|
||||
branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0
|
||||
branchExceptionPort.valid := input(INSTRUCTION_READY) && arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0
|
||||
branchExceptionPort.code := 0
|
||||
branchExceptionPort.badAddr := jumpInterface.payload
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean) extends Plugin[VexR
|
|||
|
||||
|
||||
if(catchIllegalInstruction){
|
||||
decodeExceptionPort.valid := arbitration.isValid && arbitration.haltIt && !input(LEGAL_INSTRUCTION) //HalitIt to alow decoder stage to wait valid data from 2 stages cache cache
|
||||
decodeExceptionPort.valid := arbitration.isValid && arbitration.haltIt && input(INSTRUCTION_READY) && !input(LEGAL_INSTRUCTION) //HalitIt to alow decoder stage to wait valid data from 2 stages cache cache
|
||||
decodeExceptionPort.code := 2
|
||||
decodeExceptionPort.badAddr.assignDontCare()
|
||||
}
|
||||
|
|
|
@ -82,11 +82,13 @@ class HazardSimplePlugin(bypassExecute : Boolean,
|
|||
trackHazardWithStage(execute ,bypassExecute ,BYPASSABLE_EXECUTE_STAGE)
|
||||
|
||||
|
||||
when(decode.input(INSTRUCTION)(rs1Range) === 0 || (if(pessimisticUseSrc) False else !decode.input(REG1_USE))){
|
||||
src0Hazard := False
|
||||
}
|
||||
when(decode.input(INSTRUCTION)(rs2Range) === 0 || (if(pessimisticUseSrc) False else !decode.input(REG2_USE))){
|
||||
src1Hazard := False
|
||||
if(!pessimisticUseSrc) {
|
||||
when(!decode.input(REG1_USE)) {
|
||||
src0Hazard := False
|
||||
}
|
||||
when(!decode.input(REG2_USE)) {
|
||||
src1Hazard := False
|
||||
}
|
||||
}
|
||||
|
||||
when(decode.arbitration.isValid && (src0Hazard || src1Hazard)){
|
||||
|
|
|
@ -61,6 +61,7 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv]
|
|||
fetch.arbitration.haltIt setWhen (cache.io.cpu.fetch.haltIt)
|
||||
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
|
||||
}
|
||||
|
||||
cache.io.flush.cmd.valid := False
|
||||
|
@ -72,11 +73,13 @@ class IBusCachedPlugin(config : InstructionCacheConfig) extends Plugin[VexRiscv]
|
|||
cache.io.cpu.decode.address := decode.input(PC)
|
||||
decode.insert(INSTRUCTION) := cache.io.cpu.decode.data
|
||||
decode.insert(INSTRUCTION_ANTICIPATED) := cache.io.cpu.decode.dataAnticipated
|
||||
decode.insert(INSTRUCTION_READY) := !cache.io.cpu.decode.haltIt
|
||||
}
|
||||
|
||||
|
||||
if(catchAccessFault){
|
||||
if(!twoStageLogic) fetch.insert(IBUS_ACCESS_ERROR) := cache.io.cpu.fetch.error
|
||||
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
|
||||
|
@ -105,7 +108,7 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
|
|||
val isStuck = Bool
|
||||
val isStuckByOthers = if(!p.twoStageLogic) Bool else null
|
||||
val address = UInt(p.addressWidth bit)
|
||||
val data = Bits(32 bit) //If twoStageLogic == true, this signal is acurate only when there is the cache doesn't stall decode (Used for Sync regfile)
|
||||
val data = if(!p.twoStageLogic) Bits(32 bit) else null
|
||||
val error = if(!p.twoStageLogic && p.catchAccessFault) Bool else null
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
|
@ -209,13 +212,26 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val lineRange = tagRange.low-1 downto log2Up(bytePerLine)
|
||||
val wordRange = log2Up(bytePerLine)-1 downto log2Up(bytePerWord)
|
||||
val tagLineRange = tagRange.high downto lineRange.low
|
||||
val lineWordRange = lineRange.high downto wordRange.low
|
||||
|
||||
class LineInfo extends Bundle{
|
||||
val valid = Bool
|
||||
val loading = Bool
|
||||
val error = if(catchAccessFault) Bool else null
|
||||
val address = UInt(tagRange.length bit)
|
||||
}
|
||||
|
||||
class LineInfoWithHit extends LineInfo{
|
||||
val hit = Bool
|
||||
}
|
||||
|
||||
def LineInfoWithHit(lineInfo : LineInfo, testTag : UInt) = {
|
||||
val ret = new LineInfoWithHit()
|
||||
ret.assignSomeByName(lineInfo)
|
||||
ret.hit := lineInfo.valid && lineInfo.address === testTag
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
val ways = Array.fill(wayCount)(new Area{
|
||||
val tags = Mem(new LineInfo(),wayLineCount)
|
||||
|
@ -232,7 +248,6 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
|
||||
|
||||
|
||||
|
||||
val flushCounter = Reg(UInt(log2Up(wayLineCount) + 1 bit)) init(0)
|
||||
when(!flushCounter.msb){
|
||||
io.cpu.prefetch.haltIt := True
|
||||
|
@ -260,10 +275,6 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
|
||||
val request = requestIn.stage()
|
||||
|
||||
val lineInfoWrite = new LineInfo()
|
||||
lineInfoWrite.valid := flushCounter.msb
|
||||
lineInfoWrite.address := request.addr(tagRange)
|
||||
if(catchAccessFault) lineInfoWrite.error := loadingWithError
|
||||
|
||||
//Send memory requests
|
||||
val memCmdSended = RegInit(False) setWhen(io.mem.cmd.fire)
|
||||
|
@ -279,10 +290,10 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val loadedWordsReadable = RegNext(loadedWords)
|
||||
loadedWordsNext := loadedWords
|
||||
|
||||
val waysWritePort = ways(0).datas.writePort //Not multi ways
|
||||
waysWritePort.valid := io.mem.rsp.valid
|
||||
waysWritePort.address := request.addr(lineRange) @@ wordIndex
|
||||
waysWritePort.data := io.mem.rsp.data
|
||||
val waysDatasWritePort = ways(0).datas.writePort //Not multi ways
|
||||
waysDatasWritePort.valid := io.mem.rsp.valid
|
||||
waysDatasWritePort.address := request.addr(lineRange) @@ wordIndex
|
||||
waysDatasWritePort.data := io.mem.rsp.data
|
||||
when(io.mem.rsp.valid){
|
||||
wordIndex := wordIndex + 1
|
||||
loadedWordsNext(wordIndex) := True
|
||||
|
@ -297,11 +308,14 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
}
|
||||
request.ready := readyDelay === 1
|
||||
|
||||
val waysTagsWritePort = ways(0).tags.writePort //not multi way
|
||||
waysTagsWritePort.valid := io.mem.rsp.valid || !flushCounter.msb
|
||||
waysTagsWritePort.address := Mux(flushCounter.msb,request.addr(lineRange),flushCounter(flushCounter.high-1 downto 0))
|
||||
waysTagsWritePort.data.valid := flushCounter.msb
|
||||
waysTagsWritePort.data.address := request.addr(tagRange)
|
||||
waysTagsWritePort.data.loading := !memRspLast
|
||||
if(catchAccessFault) waysTagsWritePort.data.error := loadingWithError
|
||||
|
||||
when((request.valid && memRspLast) || !flushCounter.msb){
|
||||
val tagsAddress = Mux(flushCounter.msb,request.addr(lineRange),flushCounter(flushCounter.high-1 downto 0))
|
||||
ways(0).tags(tagsAddress) := lineInfoWrite //TODO
|
||||
}
|
||||
|
||||
when(requestIn.ready){
|
||||
memCmdSended := False
|
||||
|
@ -321,9 +335,9 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val waysRead = for(way <- ways) yield new Area{
|
||||
val readAddress = Mux(io.cpu.fetch.isStuck,io.cpu.fetch.address,io.cpu.prefetch.address) //TODO FMAX
|
||||
val tag = if(asyncTagMemory)
|
||||
way.tags.readAsync(io.cpu.fetch.address(lineRange))
|
||||
way.tags.readAsync(io.cpu.fetch.address(lineRange),writeFirst)
|
||||
else
|
||||
way.tags.readSync(readAddress(lineRange))
|
||||
way.tags.readSync(readAddress(lineRange),readUnderWrite = readFirst)
|
||||
|
||||
val data = way.datas.readSync(readAddress(lineRange.high downto wordRange.low))
|
||||
waysHitWord := data //Not applicable to multi way
|
||||
|
@ -332,102 +346,128 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
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
|
||||
}
|
||||
// when(lineLoader.request.valid && lineLoader.request.addr(lineRange) === io.cpu.fetch.address(lineRange)){
|
||||
// waysHitValid := False //Not applicable to multi way
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
val loaderHitValid = lineLoader.request.valid && lineLoader.request.addr(tagLineRange) === io.cpu.fetch.address(tagLineRange)
|
||||
val loaderHitReady = lineLoader.loadedWordsReadable(io.cpu.fetch.address(wordRange))
|
||||
val hit = waysHitValid && !(waysRead(0).tag.loading && !(if(asyncTagMemory) lineLoader.loadedWords else RegNext(lineLoader.loadedWords))(io.cpu.fetch.address(wordRange)))
|
||||
io.cpu.fetch.haltIt := io.cpu.fetch.isValid && !hit
|
||||
io.cpu.fetch.data := waysHitWord
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
// 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{
|
||||
|
||||
val waysHitValid = False
|
||||
val waysHitError = Bool.assignDontCare()
|
||||
val waysHitWord = Bits(wordWidth bit)
|
||||
//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
|
||||
// val overrideValid = RegInit(False) clearWhen(readValid) setWhen(hit)
|
||||
// val overrideValue = RegNextWhen(writeData,hit)
|
||||
// overrideValid ? overrideValue | readData
|
||||
// }
|
||||
|
||||
val waysRead = for(way <- ways) yield new Area{
|
||||
//shot readValid path
|
||||
def writeFirstMemWrap[T <: Data](readValid : Bool, readLastAddress : UInt, readData : 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 | readData
|
||||
}
|
||||
|
||||
//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, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) = {
|
||||
val preWrite = (writeValid && sampleAddress === writeAddress)
|
||||
val postWrite = (writeValid && sampleLastAddress === writeAddress)
|
||||
val bypass = (!sample || preWrite) ? writeData | readData
|
||||
val regEn = sample || postWrite
|
||||
val reg = RegNextWhen(bypass,regEn)
|
||||
(reg,bypass,regEn,preWrite,postWrite)
|
||||
}
|
||||
// def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) = {
|
||||
// val bypass = (!sample || (writeValid && sampleAddress === writeAddress)) ? writeData | readData
|
||||
// val regEn = sample || (writeValid && sampleLastAddress === writeAddress)
|
||||
// val reg = RegNextWhen(bypass,regEn)
|
||||
// (reg,bypass,regEn,False,False)
|
||||
// }
|
||||
require(wayCount == 1)
|
||||
val memRead = new Area{
|
||||
val way = ways(0)
|
||||
val tag = if(asyncTagMemory)
|
||||
way.tags.readAsync(io.cpu.fetch.address(lineRange))
|
||||
way.tags.readAsync(io.cpu.fetch.address(lineRange),writeFirst)
|
||||
else
|
||||
way.tags.readSync(io.cpu.prefetch.address(lineRange),enable = !io.cpu.fetch.isStuck)
|
||||
writeFirstMemWrap(
|
||||
readValid = !io.cpu.fetch.isStuck,
|
||||
// readAddress = io.cpu.prefetch.address(lineRange),
|
||||
readLastAddress = io.cpu.fetch.address(lineRange),
|
||||
readData = way.tags.readSync(io.cpu.prefetch.address(lineRange),enable = !io.cpu.fetch.isStuck),
|
||||
writeValid = lineLoader.waysTagsWritePort.valid,
|
||||
writeAddress = lineLoader.waysTagsWritePort.address,
|
||||
writeData = lineLoader.waysTagsWritePort.data
|
||||
)
|
||||
|
||||
val data = way.datas.readSync(io.cpu.prefetch.address(lineRange.high downto wordRange.low),enable = !io.cpu.fetch.isStuck)
|
||||
waysHitWord := data //Not applicable to multi way
|
||||
when(tag.valid && tag.address === io.cpu.fetch.address(tagRange)) {
|
||||
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
|
||||
}
|
||||
val data = writeFirstMemWrap(
|
||||
readValid = !io.cpu.fetch.isStuck,
|
||||
// readAddress = io.cpu.prefetch.address(lineWordRange),
|
||||
readLastAddress = io.cpu.fetch.address(lineWordRange),
|
||||
readData = way.datas.readSync(io.cpu.prefetch.address(lineWordRange),enable = !io.cpu.fetch.isStuck),
|
||||
writeValid = lineLoader.waysDatasWritePort.valid,
|
||||
writeAddress = lineLoader.waysDatasWritePort.address,
|
||||
writeData = lineLoader.waysDatasWritePort.data
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
val tag = writeFirstRegWrap(
|
||||
sample = !io.cpu.decode.isStuck,
|
||||
sampleAddress = io.cpu.fetch.address(lineRange),
|
||||
sampleLastAddress = io.cpu.decode.address(lineRange),
|
||||
readData = LineInfoWithHit(memRead.tag,io.cpu.fetch.address(tagRange)),
|
||||
writeValid = lineLoader.waysTagsWritePort.valid,
|
||||
writeAddress = lineLoader.waysTagsWritePort.address,
|
||||
writeData = LineInfoWithHit(lineLoader.waysTagsWritePort.data,io.cpu.fetch.address(tagRange)) //TODO wrong address src
|
||||
)._1
|
||||
|
||||
val loadedWord = new Area{
|
||||
val valid = RegNext(lineLoader.waysWritePort.valid)
|
||||
val address = RegNext(lineLoader.request.addr(tagLineRange) @@ lineLoader.wordIndex @@ U"00")
|
||||
val data = RegNext(lineLoader.waysWritePort.data)
|
||||
val wasLoaded = RegNext(lineLoader.loadedWords)
|
||||
}
|
||||
val (data,dataRegIn,dataRegEn,dataPreWrite,dataPostWrite) = writeFirstRegWrap(
|
||||
sample = !io.cpu.decode.isStuck,
|
||||
sampleAddress = io.cpu.fetch.address(lineWordRange),
|
||||
sampleLastAddress = io.cpu.decode.address(lineWordRange),
|
||||
readData = memRead.data,
|
||||
writeValid = lineLoader.waysDatasWritePort.valid,
|
||||
writeAddress = lineLoader.waysDatasWritePort.address,
|
||||
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)))
|
||||
|
||||
val fetchInstructionValid = Bool
|
||||
val fetchInstructionValue = Bits(32 bits)
|
||||
val fetchInstructionValidReg = Reg(Bool)
|
||||
val fetchInstructionValueReg = Reg(Bits(32 bits))
|
||||
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
|
||||
|
||||
when(fetchInstructionValidReg){
|
||||
fetchInstructionValid := True
|
||||
fetchInstructionValue := fetchInstructionValueReg
|
||||
}.elsewhen(loadedWord.valid && (loadedWord.address >> 2) === (io.cpu.fetch.address >> 2)){
|
||||
fetchInstructionValid := True
|
||||
fetchInstructionValue := loadedWord.data
|
||||
} otherwise{
|
||||
fetchInstructionValid := waysHitValid || (loadedWord.address(tagLineRange) === io.cpu.fetch.address(tagLineRange) && loadedWord.wasLoaded(io.cpu.fetch.address(wordRange)))
|
||||
fetchInstructionValue := waysHitWord //Not multi way (wasloaded)
|
||||
}
|
||||
|
||||
|
||||
when(io.cpu.fetch.isStuck){
|
||||
fetchInstructionValidReg := fetchInstructionValid
|
||||
fetchInstructionValueReg := fetchInstructionValue
|
||||
} otherwise {
|
||||
fetchInstructionValidReg := False
|
||||
}
|
||||
|
||||
io.cpu.fetch.data := fetchInstructionValue
|
||||
|
||||
|
||||
val decodeInstructionValid = Reg(Bool)
|
||||
val decodeInstructionReg = Reg(Bits(32 bits))
|
||||
val decodeInstructionRegIn = (!io.cpu.decode.isStuck) ? fetchInstructionValue | loadedWord.data
|
||||
|
||||
io.cpu.decode.dataAnticipated := decodeInstructionReg
|
||||
when(!io.cpu.decode.isStuck){
|
||||
decodeInstructionValid := fetchInstructionValid
|
||||
decodeInstructionReg := decodeInstructionRegIn
|
||||
io.cpu.decode.dataAnticipated := decodeInstructionRegIn
|
||||
}.elsewhen(loadedWord.valid && (loadedWord.address >> 2) === (io.cpu.decode.address >> 2)){
|
||||
decodeInstructionValid := True
|
||||
decodeInstructionReg := decodeInstructionRegIn
|
||||
io.cpu.decode.dataAnticipated := decodeInstructionRegIn
|
||||
}
|
||||
|
||||
io.cpu.decode.haltIt := io.cpu.decode.isValid && !decodeInstructionValid
|
||||
io.cpu.decode.data := decodeInstructionReg
|
||||
|
||||
|
||||
lineLoader.requestIn.valid := io.cpu.decode.isValid && !decodeInstructionValid
|
||||
lineLoader.requestIn.valid := io.cpu.decode.isValid && !hit //TODO avoid duplicated request
|
||||
lineLoader.requestIn.addr := io.cpu.decode.address
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean)
|
|||
fetch.insert(IBUS_ACCESS_ERROR) := iBus.rsp.error
|
||||
fetch.arbitration.haltIt setWhen(fetch.arbitration.isValid && !iBus.rsp.ready)
|
||||
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION))
|
||||
decode.insert(INSTRUCTION_READY) := True
|
||||
|
||||
if(catchAccessFault){
|
||||
decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR)
|
||||
|
|
|
@ -79,22 +79,24 @@ object TopLevel {
|
|||
|
||||
configFull.plugins ++= List(
|
||||
new PcManagerSimplePlugin(0x00000000l, false),
|
||||
new IBusSimplePlugin(
|
||||
interfaceKeepData = true,
|
||||
catchAccessFault = true
|
||||
),
|
||||
// new IBusCachedPlugin(
|
||||
// config = InstructionCacheConfig(
|
||||
// cacheSize =4096,
|
||||
// bytePerLine =32,
|
||||
// wayCount = 1,
|
||||
// wrappedMemAccess = true,
|
||||
// addressWidth = 32,
|
||||
// cpuDataWidth = 32,
|
||||
// memDataWidth = 32,
|
||||
// catchAccessFault = true
|
||||
// )
|
||||
// new IBusSimplePlugin(
|
||||
// interfaceKeepData = true,
|
||||
// catchAccessFault = true
|
||||
// ),
|
||||
new IBusCachedPlugin(
|
||||
config = InstructionCacheConfig(
|
||||
cacheSize = 4096,
|
||||
bytePerLine =32,
|
||||
wayCount = 1,
|
||||
wrappedMemAccess = true,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchAccessFault = true,
|
||||
asyncTagMemory = false,
|
||||
twoStageLogic = true
|
||||
)
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = true,
|
||||
catchAccessFault = true
|
||||
|
@ -269,9 +271,9 @@ object TopLevel {
|
|||
)
|
||||
)
|
||||
|
||||
// val toplevel = new VexRiscv(configFull)
|
||||
val toplevel = new VexRiscv(configFull)
|
||||
// val toplevel = new VexRiscv(configLight)
|
||||
val toplevel = new VexRiscv(configTest)
|
||||
// val toplevel = new VexRiscv(configTest)
|
||||
toplevel.decode.input(toplevel.config.INSTRUCTION).addAttribute(Verilator.public)
|
||||
toplevel.decode.input(toplevel.config.PC).addAttribute(Verilator.public)
|
||||
toplevel.decode.arbitration.isValid.addAttribute(Verilator.public)
|
||||
|
|
|
@ -19,6 +19,7 @@ case class VexRiscvConfig(pcWidth : Int){
|
|||
object PC extends Stageable(UInt(pcWidth bits))
|
||||
object PC_CALC_WITHOUT_JUMP extends Stageable(UInt(pcWidth bits))
|
||||
object INSTRUCTION extends Stageable(Bits(32 bits))
|
||||
object INSTRUCTION_READY extends Stageable(Bool)
|
||||
object INSTRUCTION_ANTICIPATED extends Stageable(Bits(32 bits))
|
||||
object LEGAL_INSTRUCTION extends Stageable(Bool)
|
||||
object REGFILE_WRITE_VALID extends Stageable(Bool)
|
||||
|
|
|
@ -1,52 +1,66 @@
|
|||
[*]
|
||||
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
|
||||
[*] Sun Apr 9 09:10:08 2017
|
||||
[*] Wed Apr 12 17:13:59 2017
|
||||
[*]
|
||||
[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/rv32ui-p-addi.vcd"
|
||||
[dumpfile_mtime] "Sun Apr 9 09:08:48 2017"
|
||||
[dumpfile_size] 136439
|
||||
[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/dhrystoneO3.vcd"
|
||||
[dumpfile_mtime] "Wed Apr 12 17:05:50 2017"
|
||||
[dumpfile_size] 476292557
|
||||
[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/fail.gtkw"
|
||||
[timestart] 274
|
||||
[timestart] 602234
|
||||
[size] 1776 953
|
||||
[pos] -775 -353
|
||||
*-2.774728 284 -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] -775 -1
|
||||
*-3.626630 602285 -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] 201
|
||||
[signals_width] 453
|
||||
[signals_width] 518
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 279
|
||||
@800200
|
||||
-prefetch
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_prefetch_haltIt
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_prefetch_address[31:0]
|
||||
@1000200
|
||||
-prefetch
|
||||
@800200
|
||||
-fetch
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isValid
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isStuck
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_prefetch_haltIt
|
||||
@800200
|
||||
-Fetch
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_fetch_address[31:0]
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_fetch_data[31:0]
|
||||
@1000200
|
||||
-fetch
|
||||
@800200
|
||||
-decode
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_isValid
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_haltIt
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_isStuck
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isStuck
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_fetch_isValid
|
||||
@1000200
|
||||
-Fetch
|
||||
@800200
|
||||
-Decode
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_address[31:0]
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_data[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_haltIt
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_isStuck
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_isValid
|
||||
@1000200
|
||||
-decode
|
||||
-Decode
|
||||
@800200
|
||||
-ibus
|
||||
-Task
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.task_memRead_data[31:0]
|
||||
TOP.VexRiscv.instructionCache_1.task_memRead_tag_address[19:0]
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.task_memRead_tag_valid
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.task_tag_address[19:0]
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.task_tag_valid
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.task_dataRegIn[31:0]
|
||||
TOP.VexRiscv.instructionCache_1.task_data[31:0]
|
||||
@29
|
||||
TOP.VexRiscv.instructionCache_1.task_cacheHit
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.task_hit
|
||||
TOP.VexRiscv.instructionCache_1.task_loaderHit
|
||||
@1000200
|
||||
-Task
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.io_mem_cmd_payload_address[31:0]
|
||||
@28
|
||||
|
@ -56,32 +70,16 @@ TOP.VexRiscv.instructionCache_1.io_mem_cmd_valid
|
|||
TOP.VexRiscv.instructionCache_1.io_mem_rsp_payload_data[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.io_mem_rsp_valid
|
||||
@1000200
|
||||
-ibus
|
||||
@28
|
||||
TOP.VexRiscv.instructionCache_1.clk
|
||||
@22
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_fetch_data[31:0]
|
||||
TOP.VexRiscv.decode_RegFilePlugin_srcInstruction[31:0]
|
||||
TOP.VexRiscv.instructionCache_1.io_cpu_decode_data[31:0]
|
||||
@29
|
||||
TOP.VexRiscv.decode_arbitration_isValid
|
||||
TOP.VexRiscv.instructionCache_1.lineLoader_waysDatasWritePort_payload_address[9:0]
|
||||
TOP.VexRiscv.instructionCache_1.lineLoader_waysDatasWritePort_payload_data[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.decode_arbitration_isStuck
|
||||
TOP.VexRiscv.instructionCache_1.lineLoader_waysDatasWritePort_valid
|
||||
TOP.VexRiscv.clk
|
||||
@22
|
||||
TOP.VexRiscv.decode_PC[31:0]
|
||||
TOP.VexRiscv.decode_REG1[31:0]
|
||||
TOP.VexRiscv.decode_REG2[31:0]
|
||||
TOP.VexRiscv.instructionCache_1.lineLoader_request_payload_addr[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.decode_REG1_USE
|
||||
TOP.VexRiscv.decode_REG2_USE
|
||||
TOP.VexRiscv.decode_arbitration_isValid
|
||||
TOP.VexRiscv.decode_arbitration_isStuck
|
||||
@22
|
||||
TOP.VexRiscv.decode_RegFilePlugin_regFileReadAddress1[4:0]
|
||||
TOP.VexRiscv.decode_RegFilePlugin_regFileReadAddress2[4:0]
|
||||
TOP.VexRiscv.decode_RegFilePlugin_rs1Data[31:0]
|
||||
TOP.VexRiscv.decode_RegFilePlugin_rs2Data[31:0]
|
||||
TOP.VexRiscv.decode_RegFilePlugin_srcInstruction[31:0]
|
||||
TOP.VexRiscv.instructionCache_1.lineLoader_request_ready
|
||||
TOP.VexRiscv.instructionCache_1.lineLoader_request_valid
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
||||
|
|
|
@ -681,11 +681,12 @@ public:
|
|||
#endif
|
||||
class Dhrystone : public Workspace{
|
||||
public:
|
||||
|
||||
Dhrystone(string name,bool iStall, bool dStall) : Workspace(name) {
|
||||
string hexName;
|
||||
Dhrystone(string name,string hexName,bool iStall, bool dStall) : Workspace(name) {
|
||||
setIStall(iStall);
|
||||
setDStall(dStall);
|
||||
loadHex("../../resources/hex/" + name + ".hex");
|
||||
loadHex("../../resources/hex/" + hexName + ".hex");
|
||||
this->hexName = hexName;
|
||||
}
|
||||
|
||||
virtual void checks(){
|
||||
|
@ -693,7 +694,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void pass(){
|
||||
FILE *refFile = fopen((name + ".logRef").c_str(), "r");
|
||||
FILE *refFile = fopen((hexName + ".logRef").c_str(), "r");
|
||||
fseek(refFile, 0, SEEK_END);
|
||||
uint32_t refSize = ftell(refFile);
|
||||
fseek(refFile, 0, SEEK_SET);
|
||||
|
@ -828,10 +829,10 @@ int main(int argc, char **argv, char **env) {
|
|||
#ifdef DHRYSTONE
|
||||
// Dhrystone("dhrystoneO3",false,false).run(0.05e6);
|
||||
|
||||
Dhrystone("dhrystoneO3",true,true).run(1.1e6);
|
||||
Dhrystone("dhrystoneO3M",true,true).run(1.5e6);
|
||||
Dhrystone("dhrystoneO3",false,false).run(1.5e6);
|
||||
Dhrystone("dhrystoneO3M",false,false).run(1.2e6);
|
||||
Dhrystone("dhrystoneO3_Stall","dhrystoneO3",true,true).run(1.1e6);
|
||||
Dhrystone("dhrystoneO3M_Stall","dhrystoneO3M",true,true).run(1.5e6);
|
||||
Dhrystone("dhrystoneO3","dhrystoneO3",false,false).run(1.5e6);
|
||||
Dhrystone("dhrystoneO3M","dhrystoneO3M",false,false).run(1.2e6);
|
||||
|
||||
// Dhrystone("dhrystoneO3ML",false,false).run(8e6);
|
||||
// Dhrystone("dhrystoneO3MLL",false,false).run(80e6);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
IBUS=IBUS_SIMPLE
|
||||
IBUS=IBUS_CACHED
|
||||
DBUS=DBUS_SIMPLE
|
||||
TRACE=no
|
||||
TRACE_START=0
|
||||
|
|
Loading…
Reference in New Issue