Add tightly coupled interface to the i$

This commit is contained in:
Dolu1990 2019-01-21 23:46:18 +01:00
parent 8f1b4cc8e5
commit f4598fbd0a
8 changed files with 301 additions and 161 deletions

View File

@ -30,6 +30,13 @@ trait Pipeline {
filtered.length != 0 filtered.length != 0
} }
def serviceElse[T](clazz : Class[T], default : => T) : T = {
if(!serviceExist(clazz)) return default
val filtered = plugins.filter(o => clazz.isAssignableFrom(o.getClass))
assert(filtered.length == 1)
filtered.head.asInstanceOf[T]
}
def update[T](that : PipelineConfig[T], value : T) : Unit = configs(that) = value def update[T](that : PipelineConfig[T], value : T) : Unit = configs(that) = value
def apply[T](that : PipelineConfig[T]) : T = configs(that).asInstanceOf[T] def apply[T](that : PipelineConfig[T]) : T = configs(that).asInstanceOf[T]

View File

@ -39,6 +39,10 @@ trait PrivilegeService{
def isUser(stage : Stage) : Bool def isUser(stage : Stage) : Bool
} }
case class PrivilegeServiceDefault() extends PrivilegeService{
override def isUser(stage: Stage): Bool = False
}
trait InterruptionInhibitor{ trait InterruptionInhibitor{
def inhibateInterrupts() : Unit def inhibateInterrupts() : Unit
} }

View File

@ -28,20 +28,20 @@ import spinal.lib.eda.altera.{InterruptReceiverTag, ResetEmitterTag}
object TestsWorkspace { object TestsWorkspace {
def main(args: Array[String]) { def main(args: Array[String]) {
SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_").generateVerilog { def configFull = {
val configFull = VexRiscvConfig( val config = VexRiscvConfig(
plugins = List( plugins = List(
// new IBusSimplePlugin( // new IBusSimplePlugin(
// resetVector = 0x80000000l, // resetVector = 0x80000000l,
// cmdForkOnSecondStage = false, // cmdForkOnSecondStage = false,
// cmdForkPersistence = false, // cmdForkPersistence = false,
// prediction = NONE, // prediction = NONE,
// historyRamSizeLog2 = 10, // historyRamSizeLog2 = 10,
// catchAccessFault = false, // catchAccessFault = false,
// compressedGen = false, // compressedGen = false,
// busLatencyMin = 1, // busLatencyMin = 1,
// injectorStage = true // injectorStage = true
// ), // ),
new IBusCachedPlugin( new IBusCachedPlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
compressedGen = false, compressedGen = false,
@ -65,11 +65,12 @@ object TestsWorkspace {
portTlbSize = 4 portTlbSize = 4
) )
), ),
// new DBusSimplePlugin( // ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
// catchAddressMisaligned = true, // new DBusSimplePlugin(
// catchAccessFault = false, // catchAddressMisaligned = true,
// earlyInjection = false // catchAccessFault = false,
// ), // earlyInjection = false
// ),
new DBusCachedPlugin( new DBusCachedPlugin(
config = new DataCacheConfig( config = new DataCacheConfig(
cacheSize = 4096, cacheSize = 4096,
@ -84,21 +85,21 @@ object TestsWorkspace {
catchMemoryTranslationMiss = true, catchMemoryTranslationMiss = true,
atomicEntriesCount = 2 atomicEntriesCount = 2
), ),
// memoryTranslatorPortConfig = null // memoryTranslatorPortConfig = null
memoryTranslatorPortConfig = MemoryTranslatorPortConfig( memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 6 portTlbSize = 6
) )
), ),
// new StaticMemoryTranslatorPlugin( // new StaticMemoryTranslatorPlugin(
// ioRange = _(31 downto 28) === 0xF // ioRange = _(31 downto 28) === 0xF
// ), // ),
new MemoryTranslatorPlugin( new MemoryTranslatorPlugin(
tlbSize = 32, tlbSize = 32,
virtualRange = _(31 downto 28) === 0xC, virtualRange = _(31 downto 28) === 0xC,
ioRange = _(31 downto 28) === 0xF ioRange = _(31 downto 28) === 0xF
), ),
new DecoderSimplePlugin( new DecoderSimplePlugin(
catchIllegalInstruction = false catchIllegalInstruction = true
), ),
new RegFilePlugin( new RegFilePlugin(
regFileReadyKind = plugin.ASYNC, regFileReadyKind = plugin.ASYNC,
@ -128,31 +129,31 @@ object TestsWorkspace {
mulUnrollFactor = 32, mulUnrollFactor = 32,
divUnrollFactor = 1 divUnrollFactor = 1
), ),
// new DivPlugin, // new DivPlugin,
new CsrPlugin(CsrPluginConfig.all(0x80000020l)), new CsrPlugin(CsrPluginConfig.all(0x80000020l)),
// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/* // new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
// CsrPluginConfig( // CsrPluginConfig(
// catchIllegalAccess = false, // catchIllegalAccess = false,
// mvendorid = null, // mvendorid = null,
// marchid = null, // marchid = null,
// mimpid = null, // mimpid = null,
// mhartid = null, // mhartid = null,
// misaExtensionsInit = 0, // misaExtensionsInit = 0,
// misaAccess = CsrAccess.READ_ONLY, // misaAccess = CsrAccess.READ_ONLY,
// mtvecAccess = CsrAccess.WRITE_ONLY, // mtvecAccess = CsrAccess.WRITE_ONLY,
// mtvecInit = 0x80000020l, // mtvecInit = 0x80000020l,
// mepcAccess = CsrAccess.READ_WRITE, // mepcAccess = CsrAccess.READ_WRITE,
// mscratchGen = true, // mscratchGen = true,
// mcauseAccess = CsrAccess.READ_ONLY, // mcauseAccess = CsrAccess.READ_ONLY,
// mbadaddrAccess = CsrAccess.READ_ONLY, // mbadaddrAccess = CsrAccess.READ_ONLY,
// mcycleAccess = CsrAccess.NONE, // mcycleAccess = CsrAccess.NONE,
// minstretAccess = CsrAccess.NONE, // minstretAccess = CsrAccess.NONE,
// ecallGen = true, // ecallGen = true,
// ebreakGen = true, // ebreakGen = true,
// wfiGenAsWait = false, // wfiGenAsWait = false,
// wfiGenAsNop = true, // wfiGenAsNop = true,
// ucycleAccess = CsrAccess.NONE // ucycleAccess = CsrAccess.NONE
// )), // )),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin( new BranchPlugin(
earlyBranch = true, earlyBranch = true,
@ -162,8 +163,28 @@ object TestsWorkspace {
new YamlPlugin("cpu0.yaml") new YamlPlugin("cpu0.yaml")
) )
) )
config
}
// import spinal.core.sim._
// SimConfig.withConfig(SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_")).allOptimisation.compile(new VexRiscv(configFull)).doSimUntilVoid{ dut =>
// dut.clockDomain.forkStimulus(10)
// dut.clockDomain.forkSimSpeedPrinter(4)
// var iBus : InstructionCacheMemBus = null
//
// dut.plugins.foreach{
// case plugin: IBusCachedPlugin => iBus = plugin.iBus
// case _ =>
// }
// dut.clockDomain.onSamplings{
//// iBus.cmd.ready.randomize()
// iBus.rsp.data #= 0x13
// }
// }
SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_").generateVerilog {
val toplevel = new VexRiscv(configFull) val toplevel = new VexRiscv(configFull)
// val toplevel = new VexRiscv(configLight) // val toplevel = new VexRiscv(configLight)

View File

@ -86,15 +86,17 @@ trait InstructionCacheCommons{
val pc : UInt val pc : UInt
val physicalAddress : UInt val physicalAddress : UInt
val data : Bits val data : Bits
val cacheMiss, error, mmuMiss, illegalAccess,isUser : Bool val cacheMiss, error, mmuMiss, illegalAccess, isUser : Bool
} }
case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons { case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons {
val isValid = Bool val isValid = Bool()
val isStuck = Bool val isStuck = Bool()
val isRemoved = Bool val isRemoved = Bool()
val pc = UInt(p.addressWidth bits) val pc = UInt(p.addressWidth bits)
val data = Bits(p.cpuDataWidth bits) val data = Bits(p.cpuDataWidth bits)
val dataBypassValid = Bool()
val dataBypass = Bits(p.cpuDataWidth bits)
val mmuBus = MemoryTranslatorBus() val mmuBus = MemoryTranslatorBus()
val physicalAddress = UInt(p.addressWidth bits) val physicalAddress = UInt(p.addressWidth bits)
val cacheMiss, error, mmuMiss, illegalAccess,isUser = ifGen(!p.twoCycleCache)(Bool) val cacheMiss, error, mmuMiss, illegalAccess,isUser = ifGen(!p.twoCycleCache)(Bool)
@ -102,7 +104,7 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
override def asMaster(): Unit = { override def asMaster(): Unit = {
out(isValid, isStuck, isRemoved, pc) out(isValid, isStuck, isRemoved, pc)
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss,physicalAddress) inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss,physicalAddress)
outWithNull(isUser) outWithNull(isUser, dataBypass, dataBypassValid)
slaveWithNull(mmuBus) slaveWithNull(mmuBus)
} }
} }
@ -381,21 +383,21 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
} }
val hit = if(!twoCycleRam) new Area{ val hit = (!twoCycleRam) generate new Area{
val hits = read.waysValues.map(way => way.tag.valid && way.tag.address === io.cpu.fetch.mmuBus.rsp.physicalAddress(tagRange)) val hits = read.waysValues.map(way => way.tag.valid && way.tag.address === io.cpu.fetch.mmuBus.rsp.physicalAddress(tagRange))
val valid = Cat(hits).orR val valid = Cat(hits).orR
val id = OHToUInt(hits) val id = OHToUInt(hits)
val error = read.waysValues.map(_.tag.error).read(id) val error = read.waysValues.map(_.tag.error).read(id)
val data = read.waysValues.map(_.data).read(id) val data = read.waysValues.map(_.data).read(id)
val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange)) val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange))
io.cpu.fetch.data := word io.cpu.fetch.data := (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | word)
if(twoCycleCache){ if(twoCycleCache){
io.cpu.decode.data := RegNextWhen(io.cpu.fetch.data,!io.cpu.decode.isStuck) io.cpu.decode.data := RegNextWhen(io.cpu.fetch.data,!io.cpu.decode.isStuck)
} }
} else null }
if(twoCycleRam && wayCount == 1){ if(twoCycleRam && wayCount == 1){
io.cpu.fetch.data := read.waysValues.head.data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange)) io.cpu.fetch.data := (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | read.waysValues.head.data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange)))
} }
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
@ -405,7 +407,6 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress
val resolution = ifGen(!twoCycleCache)( new Area{ val resolution = ifGen(!twoCycleCache)( new Area{
// def stage[T <: Data](that : T) = RegNextWhen(that,!io.cpu.decode.isStuck)
val mmuRsp = io.cpu.fetch.mmuBus.rsp val mmuRsp = io.cpu.fetch.mmuBus.rsp
io.cpu.fetch.cacheMiss := !hit.valid io.cpu.fetch.cacheMiss := !hit.valid
@ -432,17 +433,13 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
val error = tags(id).error val error = tags(id).error
val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id) val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id)
val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange)) val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange))
when(stage(io.cpu.fetch.dataBypassValid)){
word := stage(io.cpu.fetch.dataBypass)
}
io.cpu.decode.data := word io.cpu.decode.data := word
} }
io.cpu.decode.cacheMiss := !hit.valid io.cpu.decode.cacheMiss := !hit.valid
// when( io.cpu.decode.isValid && io.cpu.decode.cacheMiss){
// io.cpu.prefetch.haltIt := True
// lineLoader.valid := True
// lineLoader.address := mmuRsp.physicalAddress //Could be optimise if mmu not used
// }
// when(io.cpu)
io.cpu.decode.error := hit.error io.cpu.decode.error := hit.error
io.cpu.decode.mmuMiss := mmuRsp.miss io.cpu.decode.mmuMiss := mmuRsp.miss
io.cpu.decode.illegalAccess := !mmuRsp.allowExecute || (io.cpu.decode.isUser && !mmuRsp.allowUser) io.cpu.decode.illegalAccess := !mmuRsp.allowExecute || (io.cpu.decode.isUser && !mmuRsp.allowUser)

View File

@ -5,10 +5,26 @@ import vexriscv.ip._
import spinal.core._ import spinal.core._
import spinal.lib._ import spinal.lib._
import scala.collection.mutable.ArrayBuffer
//class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] { //class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
// var iBus : InstructionCacheMemBus = null // var iBus : InstructionCacheMemBus = null
// override def build(pipeline: VexRiscv): Unit = ??? // override def build(pipeline: VexRiscv): Unit = ???
//} //}
case class TightlyCoupledBus() extends Bundle with IMasterSlave {
val enable = Bool()
val address = UInt(32 bits)
val data = Bits(32 bits)
override def asMaster(): Unit = {
out(enable, address)
in(data)
}
}
case class TightlyCoupledPortParameter(name : String, hit : UInt => Bool)
case class TightlyCoupledPort(p : TightlyCoupledPortParameter, var bus : TightlyCoupledBus)
class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
relaxedPcCalculation : Boolean = false, relaxedPcCalculation : Boolean = false,
prediction : BranchPrediction = NONE, prediction : BranchPrediction = NONE,
@ -36,6 +52,15 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
var privilegeService : PrivilegeService = null var privilegeService : PrivilegeService = null
var redoBranch : Flow[UInt] = null var redoBranch : Flow[UInt] = null
var decodeExceptionPort : Flow[ExceptionCause] = null var decodeExceptionPort : Flow[ExceptionCause] = null
val tightlyCoupledPorts = ArrayBuffer[TightlyCoupledPort]()
def newTightlyCoupledPort(p : TightlyCoupledPortParameter) = {
val port = TightlyCoupledPort(p, null)
tightlyCoupledPorts += port
this
}
object FLUSH_ALL extends Stageable(Bool) object FLUSH_ALL extends Stageable(Bool)
object IBUS_ACCESS_ERROR extends Stageable(Bool) object IBUS_ACCESS_ERROR extends Stageable(Bool)
@ -66,8 +91,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
if(pipeline.serviceExist(classOf[MemoryTranslator])) if(pipeline.serviceExist(classOf[MemoryTranslator]))
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_INSTRUCTION, memoryTranslatorPortConfig) mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_INSTRUCTION, memoryTranslatorPortConfig)
if(pipeline.serviceExist(classOf[PrivilegeService])) privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
privilegeService = pipeline.service(classOf[PrivilegeService])
if(pipeline.serviceExist(classOf[ReportService])){ if(pipeline.serviceExist(classOf[ReportService])){
val report = pipeline.service(classOf[ReportService]) val report = pipeline.service(classOf[ReportService])
@ -98,21 +122,106 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
val cache = new InstructionCache(IBusCachedPlugin.this.config) val cache = new InstructionCache(IBusCachedPlugin.this.config)
iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus") iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus")
iBus <> cache.io.mem iBus <> cache.io.mem
iBus.cmd.address.allowOverride := cache.io.mem.cmd.address // - debugAddressOffset iBus.cmd.address.allowOverride := cache.io.mem.cmd.address
val stageOffset = if(relaxedPcCalculation) 1 else 0 val stageOffset = if(relaxedPcCalculation) 1 else 0
def stages = iBusRsp.stages.drop(stageOffset) def stages = iBusRsp.stages.drop(stageOffset)
tightlyCoupledPorts.foreach(p => p.bus = master(TightlyCoupledBus()).setName(p.p.name))
val s0 = new Area {
//address decoding
val tightlyCoupledHits = Vec(tightlyCoupledPorts.map(_.p.hit(stages(0).input.payload)))
val tightlyCoupledHit = tightlyCoupledHits.orR
for((port, hit) <- (tightlyCoupledPorts, tightlyCoupledHits).zipped){
port.bus.enable := stages(0).input.fire && hit
port.bus.address := stages(0).input.payload(31 downto 2) @@ U"00"
}
//Connect prefetch cache side //Connect prefetch cache side
cache.io.cpu.prefetch.isValid := stages(0).input.valid cache.io.cpu.prefetch.isValid := stages(0).input.valid && !tightlyCoupledHit
cache.io.cpu.prefetch.pc := stages(0).input.payload cache.io.cpu.prefetch.pc := stages(0).input.payload
stages(0).halt setWhen(cache.io.cpu.prefetch.haltIt) stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt)
cache.io.cpu.fetch.isRemoved := flush cache.io.cpu.fetch.isRemoved := flush
}
val s1 = new Area {
val tightlyCoupledHits = RegNextWhen(s0.tightlyCoupledHits, stages(1).input.ready)
val tightlyCoupledHit = RegNextWhen(s0.tightlyCoupledHit, stages(1).input.ready)
cache.io.cpu.fetch.dataBypassValid := tightlyCoupledHit
cache.io.cpu.fetch.dataBypass := (if(tightlyCoupledPorts.isEmpty) B(0) else MuxOH(tightlyCoupledHits, tightlyCoupledPorts.map(e => CombInit(e.bus.data))))
//Connect fetch cache side
cache.io.cpu.fetch.isValid := stages(1).input.valid && !tightlyCoupledHit
cache.io.cpu.fetch.isStuck := !stages(1).input.ready
cache.io.cpu.fetch.pc := stages(1).input.payload
if (!twoCycleCache) {
cache.io.cpu.fetch.isUser := privilegeService.isUser(decode)
}
}
val s2 = twoCycleCache generate new Area {
val tightlyCoupledHit = RegNextWhen(s1.tightlyCoupledHit, stages(2).input.ready)
cache.io.cpu.decode.isValid := stages(2).input.valid && !tightlyCoupledHit
cache.io.cpu.decode.isStuck := !stages(2).input.ready
cache.io.cpu.decode.pc := stages(2).input.payload
cache.io.cpu.decode.isUser := privilegeService.isUser(decode)
if ((!twoCycleRam || wayCount == 1) && !compressedGen && !injectorStage) {
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), cache.io.cpu.fetch.data)
}
}
val rsp = new Area {
val iBusRspOutputHalt = False val iBusRspOutputHalt = False
val cacheRsp = if (twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch
val cacheRspArbitration = stages(if (twoCycleCache) 2 else 1)
var issueDetected = False
val redoFetch = False //RegNext(False) init(False)
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected) {
issueDetected \= True
redoFetch := iBusRsp.readyForError
}
//Refill / redo
assert(decodePcGen == compressedGen)
cache.io.cpu.fill.valid := redoFetch
cache.io.cpu.fill.payload := cacheRsp.physicalAddress
redoBranch.valid := redoFetch
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
if (catchSomething) {
val accessFault = if (catchAccessFault) cacheRsp.error else False
val mmuMiss = if (catchMemoryTranslationMiss) cacheRsp.mmuMiss else False
val illegalAccess = if (catchIllegalAccess) cacheRsp.illegalAccess else False
decodeExceptionPort.valid := False
decodeExceptionPort.code := mmuMiss ? U(14) | 1
decodeExceptionPort.badAddr := cacheRsp.pc
when(cacheRsp.isValid && (accessFault || mmuMiss || illegalAccess) && !issueDetected) {
issueDetected \= True
decodeExceptionPort.valid := iBusRsp.readyForError
}
}
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
iBusRsp.output.valid := cacheRspArbitration.output.valid
cacheRspArbitration.output.ready := iBusRsp.output.ready
iBusRsp.output.rsp.inst := cacheRsp.data
iBusRsp.output.pc := cacheRspArbitration.output.payload
}
if (mmuBus != null) { if (mmuBus != null) {
cache.io.cpu.fetch.mmuBus <> mmuBus cache.io.cpu.fetch.mmuBus <> mmuBus
(if(twoCycleCache) stages(1).halt else iBusRspOutputHalt) setWhen(mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss) (if (twoCycleCache) stages(1).halt else rsp.iBusRspOutputHalt) setWhen (mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss)
} else { } else {
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress 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.allowExecute := True
@ -124,64 +233,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
cache.io.cpu.fetch.mmuBus.rsp.hit := False cache.io.cpu.fetch.mmuBus.rsp.hit := False
} }
//Connect fetch cache side
cache.io.cpu.fetch.isValid := stages(1).input.valid
cache.io.cpu.fetch.isStuck := !stages(1).input.ready
cache.io.cpu.fetch.pc := stages(1).input.payload
if(twoCycleCache){
cache.io.cpu.decode.isValid := stages(2).input.valid
cache.io.cpu.decode.isStuck := !stages(2).input.ready
cache.io.cpu.decode.pc := stages(2).input.payload
cache.io.cpu.decode.isUser := (if (privilegeService != null) privilegeService.isUser(decode) else False)
if((!twoCycleRam || wayCount == 1) && !compressedGen && !injectorStage){
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), cache.io.cpu.fetch.data)
}
} else {
cache.io.cpu.fetch.isUser := (if (privilegeService != null) privilegeService.isUser(decode) else False)
}
// val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss
val cacheRsp = if(twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch
val cacheRspArbitration = stages(if(twoCycleCache) 2 else 1)
var issueDetected = False
val redoFetch = False //RegNext(False) init(False)
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected){
issueDetected \= True
redoFetch := iBusRsp.readyForError
}
assert(decodePcGen == compressedGen)
cache.io.cpu.fill.valid := redoFetch
redoBranch.valid := redoFetch
redoBranch.payload := (if(decodePcGen) decode.input(PC) else cacheRsp.pc)
cache.io.cpu.fill.payload := cacheRsp.physicalAddress
if(catchSomething){
val accessFault = if (catchAccessFault) cacheRsp.error else False
val mmuMiss = if (catchMemoryTranslationMiss) cacheRsp.mmuMiss else False
val illegalAccess = if (catchIllegalAccess) cacheRsp.illegalAccess else False
decodeExceptionPort.valid := False
decodeExceptionPort.code := mmuMiss ? U(14) | 1
decodeExceptionPort.badAddr := cacheRsp.pc
when(cacheRsp.isValid && (accessFault || mmuMiss || illegalAccess) && !issueDetected){
issueDetected \= True
decodeExceptionPort.valid := iBusRsp.readyForError
}
}
cacheRspArbitration.halt setWhen(issueDetected || iBusRspOutputHalt)
iBusRsp.output.arbitrationFrom(cacheRspArbitration.output)
iBusRsp.output.rsp.inst := cacheRsp.data
iBusRsp.output.pc := cacheRspArbitration.output.payload
val flushStage = if(memory != null) memory else execute val flushStage = if(memory != null) memory else execute
flushStage plug new Area { flushStage plug new Area {
import flushStage._ import flushStage._

View File

@ -1192,6 +1192,43 @@ public:
}; };
#endif #endif
#ifdef IBUS_TC
class IBusTc : public SimElement{
public:
uint32_t nextData;
Workspace *ws;
VVexRiscv* top;
IBusTc(Workspace* ws){
this->ws = ws;
this->top = ws->top;
}
virtual void onReset(){
}
virtual void preCycle(){
if (top->iBusTc_enable) {
if((top->iBusTc_address & 0x70000000) != 0 || (top->iBusTc_address & 0x20) == 0){
printf("IBusTc access out of range\n");
ws->fail();
}
bool error_next;
ws->iBusAccess(top->iBusTc_address, &nextData,&error_next);
}
}
virtual void postCycle(){
top->iBusTc_data = nextData;
}
};
#endif
#ifdef IBUS_SIMPLE_AVALON #ifdef IBUS_SIMPLE_AVALON
struct IBusSimpleAvalonRsp{ struct IBusSimpleAvalonRsp{
@ -1274,6 +1311,12 @@ public:
bool error; bool error;
top->iBus_rsp_valid = 0; top->iBus_rsp_valid = 0;
if(pendingCount != 0 && (!ws->iStall || VL_RANDOM_I(7) < 100)){ if(pendingCount != 0 && (!ws->iStall || VL_RANDOM_I(7) < 100)){
#ifdef IBUS_TC
if((address & 0x70000000) == 0 && (address & 0x20) != 0){
printf("IBUS_CACHED access out of range\n");
ws->fail();
}
#endif
ws->iBusAccess(address,&top->iBus_rsp_payload_data,&error); ws->iBusAccess(address,&top->iBus_rsp_payload_data,&error);
top->iBus_rsp_payload_error = error; top->iBus_rsp_payload_error = error;
pendingCount--; pendingCount--;
@ -1960,6 +2003,11 @@ void Workspace::fillSimELements(){
#if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE) #if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
simElements.push_back(new IBusCachedWishbone(this)); simElements.push_back(new IBusCachedWishbone(this));
#endif #endif
#ifdef IBUS_TC
simElements.push_back(new IBusTc(this));
#endif
#ifdef DBUS_SIMPLE #ifdef DBUS_SIMPLE
simElements.push_back(new DBusSimple(this)); simElements.push_back(new DBusSimple(this));
#endif #endif

View File

@ -1,6 +1,7 @@
DEBUG?=no DEBUG?=no
IBUS?=CACHED IBUS?=CACHED
IBUS_TC?=no
DBUS?=CACHED DBUS?=CACHED
TRACE?=no TRACE?=no
TRACE_ACCESS?=no TRACE_ACCESS?=no
@ -42,7 +43,7 @@ ADDCFLAGS += -CFLAGS -DTHREAD_COUNT=${THREAD_COUNT}
ifeq ($(DEBUG),yes) ifeq ($(DEBUG),yes)
ADDCFLAGS += -CFLAGS -O0 -CFLAGS -g ADDCFLAGS += -CFLAGS -O0 -CFLAGS -g
else else
ADDCFLAGS += -CFLAGS -O3 ADDCFLAGS += -CFLAGS -O3 -O3
endif endif
@ -58,6 +59,11 @@ ifneq ($(RUN_HEX),no)
ADDCFLAGS += -CFLAGS -DRUN_HEX='\"$(RUN_HEX)\"' ADDCFLAGS += -CFLAGS -DRUN_HEX='\"$(RUN_HEX)\"'
endif endif
ifeq ($(IBUS_TC),yes)
ADDCFLAGS += -CFLAGS -DIBUS_TC=yes
endif
ifeq ($(COMPRESSED),yes) ifeq ($(COMPRESSED),yes)
ADDCFLAGS += -CFLAGS -DCOMPRESSED ADDCFLAGS += -CFLAGS -DCOMPRESSED
endif endif

View File

@ -284,6 +284,8 @@ class IBusDimension extends VexRiscvDimension("IBus") {
} }
} else { } else {
val compressed = r.nextBoolean() val compressed = r.nextBoolean()
val tighlyCoupled = r.nextBoolean()
// val tighlyCoupled = false
val prediction = random(r, List(NONE, STATIC, DYNAMIC, DYNAMIC_TARGET)) val prediction = random(r, List(NONE, STATIC, DYNAMIC, DYNAMIC_TARGET))
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
val relaxedPcCalculation, twoCycleCache, injectorStage = r.nextBoolean() val relaxedPcCalculation, twoCycleCache, injectorStage = r.nextBoolean()
@ -295,9 +297,10 @@ class IBusDimension extends VexRiscvDimension("IBus") {
wayCount = 1 << r.nextInt(3) wayCount = 1 << r.nextInt(3)
}while(cacheSize/wayCount < 512) }while(cacheSize/wayCount < 512)
new VexRiscvPosition("Cached" + (if(twoCycleCache) "2cc" else "") + (if(injectorStage) "Injstage" else "") + (if(twoCycleRam) "2cr" else "") + "S" + cacheSize + "W" + wayCount + (if(relaxedPcCalculation) "Relax" else "") + (if(compressed) "Rvc" else "") + prediction.getClass.getTypeName().replace("$","")) with InstructionAnticipatedPosition{ new VexRiscvPosition("Cached" + (if(twoCycleCache) "2cc" else "") + (if(injectorStage) "Injstage" else "") + (if(twoCycleRam) "2cr" else "") + "S" + cacheSize + "W" + wayCount + (if(relaxedPcCalculation) "Relax" else "") + (if(compressed) "Rvc" else "") + prediction.getClass.getTypeName().replace("$","")+ (if(tighlyCoupled)"Tc" else "")) with InstructionAnticipatedPosition{
override def testParam = "IBUS=CACHED" + (if(compressed) " COMPRESSED=yes" else "") override def testParam = "IBUS=CACHED" + (if(compressed) " COMPRESSED=yes" else "") + (if(tighlyCoupled)" IBUS_TC=yes" else "")
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new IBusCachedPlugin( override def applyOn(config: VexRiscvConfig): Unit = {
val p = new IBusCachedPlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
compressedGen = compressed, compressedGen = compressed,
prediction = prediction, prediction = prediction,
@ -318,6 +321,9 @@ class IBusDimension extends VexRiscvDimension("IBus") {
twoCycleCache = twoCycleCache twoCycleCache = twoCycleCache
) )
) )
if(tighlyCoupled) p.newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5)))
config.plugins += p
}
override def instructionAnticipatedOk() = !twoCycleCache || ((!twoCycleRam || wayCount == 1) && !compressed) override def instructionAnticipatedOk() = !twoCycleCache || ((!twoCycleRam || wayCount == 1) && !compressed)
} }
} }
@ -523,8 +529,8 @@ class TestIndividualFeatures extends FunSuite {
// val testId = Some(mutable.HashSet[Int](0,28,45,93)) // val testId = Some(mutable.HashSet[Int](0,28,45,93))
// val testId = Some(mutable.HashSet[Int](5)) // val testId = Some(mutable.HashSet[Int](31))
// val seed = -2089952013329208578l // val seed = -7716775349351274630l