Merge remote-tracking branch 'origin/dev'
This commit is contained in:
commit
9a61ff8347
|
@ -156,8 +156,8 @@ sudo make install
|
|||
|
||||
## CPU generation
|
||||
You can find two example CPU instances in:
|
||||
- src/main/scala/vexriscv/GenFull.scala
|
||||
- src/main/scala/vexriscv/GenSmallest.scala
|
||||
- src/main/scala/vexriscv/demo/GenFull.scala
|
||||
- src/main/scala/vexriscv/demo/GenSmallest.scala
|
||||
|
||||
To generate the corresponding RTL as a VexRiscv.v file, run the following commands in the root directory of this repository:
|
||||
|
||||
|
|
32
build.sbt
32
build.sbt
|
@ -1,25 +1,3 @@
|
|||
//name := "VexRiscv"
|
||||
//
|
||||
//organization := "com.github.spinalhdl"
|
||||
//
|
||||
//version := "1.0.0"
|
||||
//
|
||||
//scalaVersion := "2.11.6"
|
||||
//
|
||||
//EclipseKeys.withSource := true
|
||||
//
|
||||
//libraryDependencies ++= Seq(
|
||||
// "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.1",
|
||||
// "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.1",
|
||||
// "org.scalatest" % "scalatest_2.11" % "2.2.1",
|
||||
// "org.yaml" % "snakeyaml" % "1.8"
|
||||
//)
|
||||
//
|
||||
//
|
||||
//
|
||||
//addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
|
||||
//scalacOptions += "-P:continuations:enable"
|
||||
//fork := true
|
||||
|
||||
lazy val root = (project in file(".")).
|
||||
settings(
|
||||
|
@ -29,16 +7,16 @@ lazy val root = (project in file(".")).
|
|||
version := "1.0.0"
|
||||
)),
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.1",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.1",
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.2",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.2",
|
||||
"org.scalatest" % "scalatest_2.11" % "2.2.1",
|
||||
"org.yaml" % "snakeyaml" % "1.8"
|
||||
),
|
||||
name := "VexRiscv"
|
||||
)//.dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib)
|
||||
//lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "SpinalHDL-sim")
|
||||
//lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "SpinalHDL-core")
|
||||
//lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "SpinalHDL-lib")
|
||||
//lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "sim")
|
||||
//lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "core")
|
||||
//lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "lib")
|
||||
|
||||
|
||||
fork := true
|
|
@ -30,6 +30,13 @@ trait Pipeline {
|
|||
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 apply[T](that : PipelineConfig[T]) : T = configs(that).asInstanceOf[T]
|
||||
|
||||
|
|
|
@ -39,6 +39,10 @@ trait PrivilegeService{
|
|||
def isUser(stage : Stage) : Bool
|
||||
}
|
||||
|
||||
case class PrivilegeServiceDefault() extends PrivilegeService{
|
||||
override def isUser(stage: Stage): Bool = False
|
||||
}
|
||||
|
||||
trait InterruptionInhibitor{
|
||||
def inhibateInterrupts() : Unit
|
||||
}
|
||||
|
|
|
@ -28,20 +28,20 @@ import spinal.lib.eda.altera.{InterruptReceiverTag, ResetEmitterTag}
|
|||
|
||||
object TestsWorkspace {
|
||||
def main(args: Array[String]) {
|
||||
SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_").generateVerilog {
|
||||
val configFull = VexRiscvConfig(
|
||||
def configFull = {
|
||||
val config = VexRiscvConfig(
|
||||
plugins = List(
|
||||
// new IBusSimplePlugin(
|
||||
// resetVector = 0x80000000l,
|
||||
// cmdForkOnSecondStage = false,
|
||||
// cmdForkPersistence = false,
|
||||
// prediction = NONE,
|
||||
// historyRamSizeLog2 = 10,
|
||||
// catchAccessFault = false,
|
||||
// compressedGen = false,
|
||||
// busLatencyMin = 1,
|
||||
// injectorStage = true
|
||||
// ),
|
||||
// new IBusSimplePlugin(
|
||||
// resetVector = 0x80000000l,
|
||||
// cmdForkOnSecondStage = false,
|
||||
// cmdForkPersistence = false,
|
||||
// prediction = NONE,
|
||||
// historyRamSizeLog2 = 10,
|
||||
// catchAccessFault = false,
|
||||
// compressedGen = false,
|
||||
// busLatencyMin = 1,
|
||||
// injectorStage = true
|
||||
// ),
|
||||
new IBusCachedPlugin(
|
||||
resetVector = 0x80000000l,
|
||||
compressedGen = false,
|
||||
|
@ -65,11 +65,12 @@ object TestsWorkspace {
|
|||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
// new DBusSimplePlugin(
|
||||
// catchAddressMisaligned = true,
|
||||
// catchAccessFault = false,
|
||||
// earlyInjection = false
|
||||
// ),
|
||||
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
|
||||
// new DBusSimplePlugin(
|
||||
// catchAddressMisaligned = true,
|
||||
// catchAccessFault = false,
|
||||
// earlyInjection = false
|
||||
// ),
|
||||
new DBusCachedPlugin(
|
||||
config = new DataCacheConfig(
|
||||
cacheSize = 4096,
|
||||
|
@ -84,21 +85,21 @@ object TestsWorkspace {
|
|||
catchMemoryTranslationMiss = true,
|
||||
atomicEntriesCount = 2
|
||||
),
|
||||
// memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = null
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
portTlbSize = 6
|
||||
)
|
||||
),
|
||||
// new StaticMemoryTranslatorPlugin(
|
||||
// ioRange = _(31 downto 28) === 0xF
|
||||
// ),
|
||||
// new StaticMemoryTranslatorPlugin(
|
||||
// ioRange = _(31 downto 28) === 0xF
|
||||
// ),
|
||||
new MemoryTranslatorPlugin(
|
||||
tlbSize = 32,
|
||||
virtualRange = _(31 downto 28) === 0xC,
|
||||
ioRange = _(31 downto 28) === 0xF
|
||||
),
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = false
|
||||
catchIllegalInstruction = true
|
||||
),
|
||||
new RegFilePlugin(
|
||||
regFileReadyKind = plugin.ASYNC,
|
||||
|
@ -109,7 +110,7 @@ object TestsWorkspace {
|
|||
separatedAddSub = false
|
||||
),
|
||||
new FullBarrelShifterPlugin(earlyInjection = true),
|
||||
// new LightShifterPlugin,
|
||||
// new LightShifterPlugin,
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = true,
|
||||
bypassMemory = true,
|
||||
|
@ -119,8 +120,8 @@ object TestsWorkspace {
|
|||
pessimisticWriteRegFile = false,
|
||||
pessimisticAddressMatch = false
|
||||
),
|
||||
// new HazardSimplePlugin(false, true, false, true),
|
||||
// new HazardSimplePlugin(false, false, false, false),
|
||||
// new HazardSimplePlugin(false, true, false, true),
|
||||
// new HazardSimplePlugin(false, false, false, false),
|
||||
new MulPlugin,
|
||||
new MulDivIterativePlugin(
|
||||
genMul = false,
|
||||
|
@ -128,31 +129,31 @@ object TestsWorkspace {
|
|||
mulUnrollFactor = 32,
|
||||
divUnrollFactor = 1
|
||||
),
|
||||
// new DivPlugin,
|
||||
// new DivPlugin,
|
||||
new CsrPlugin(CsrPluginConfig.all(0x80000020l)),
|
||||
// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
|
||||
// CsrPluginConfig(
|
||||
// catchIllegalAccess = false,
|
||||
// mvendorid = null,
|
||||
// marchid = null,
|
||||
// mimpid = null,
|
||||
// mhartid = null,
|
||||
// misaExtensionsInit = 0,
|
||||
// misaAccess = CsrAccess.READ_ONLY,
|
||||
// mtvecAccess = CsrAccess.WRITE_ONLY,
|
||||
// mtvecInit = 0x80000020l,
|
||||
// mepcAccess = CsrAccess.READ_WRITE,
|
||||
// mscratchGen = true,
|
||||
// mcauseAccess = CsrAccess.READ_ONLY,
|
||||
// mbadaddrAccess = CsrAccess.READ_ONLY,
|
||||
// mcycleAccess = CsrAccess.NONE,
|
||||
// minstretAccess = CsrAccess.NONE,
|
||||
// ecallGen = true,
|
||||
// ebreakGen = true,
|
||||
// wfiGenAsWait = false,
|
||||
// wfiGenAsNop = true,
|
||||
// ucycleAccess = CsrAccess.NONE
|
||||
// )),
|
||||
// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
|
||||
// CsrPluginConfig(
|
||||
// catchIllegalAccess = false,
|
||||
// mvendorid = null,
|
||||
// marchid = null,
|
||||
// mimpid = null,
|
||||
// mhartid = null,
|
||||
// misaExtensionsInit = 0,
|
||||
// misaAccess = CsrAccess.READ_ONLY,
|
||||
// mtvecAccess = CsrAccess.WRITE_ONLY,
|
||||
// mtvecInit = 0x80000020l,
|
||||
// mepcAccess = CsrAccess.READ_WRITE,
|
||||
// mscratchGen = true,
|
||||
// mcauseAccess = CsrAccess.READ_ONLY,
|
||||
// mbadaddrAccess = CsrAccess.READ_ONLY,
|
||||
// mcycleAccess = CsrAccess.NONE,
|
||||
// minstretAccess = CsrAccess.NONE,
|
||||
// ecallGen = true,
|
||||
// ebreakGen = true,
|
||||
// wfiGenAsWait = false,
|
||||
// wfiGenAsNop = true,
|
||||
// ucycleAccess = CsrAccess.NONE
|
||||
// )),
|
||||
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
|
||||
new BranchPlugin(
|
||||
earlyBranch = true,
|
||||
|
@ -162,8 +163,28 @@ object TestsWorkspace {
|
|||
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(configLight)
|
||||
|
|
|
@ -258,10 +258,12 @@ class Briey(config: BrieyConfig) extends Component{
|
|||
)
|
||||
|
||||
val gpioACtrl = Apb3Gpio(
|
||||
gpioWidth = 32
|
||||
gpioWidth = 32,
|
||||
withReadSync = true
|
||||
)
|
||||
val gpioBCtrl = Apb3Gpio(
|
||||
gpioWidth = 32
|
||||
gpioWidth = 32,
|
||||
withReadSync = true
|
||||
)
|
||||
val timerCtrl = PinsecTimerCtrl()
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
|
||||
//******** APB peripherals *********
|
||||
val apbMapping = ArrayBuffer[(Apb3, SizeMapping)]()
|
||||
val gpioACtrl = Apb3Gpio(gpioWidth = gpioWidth)
|
||||
val gpioACtrl = Apb3Gpio(gpioWidth = gpioWidth, withReadSync = true)
|
||||
io.gpioA <> gpioACtrl.io.gpio
|
||||
apbMapping += gpioACtrl.io.apb -> (0x00000, 4 kB)
|
||||
|
||||
|
|
|
@ -86,15 +86,17 @@ trait InstructionCacheCommons{
|
|||
val pc : UInt
|
||||
val physicalAddress : UInt
|
||||
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 {
|
||||
val isValid = Bool
|
||||
val isStuck = Bool
|
||||
val isRemoved = Bool
|
||||
val isValid = Bool()
|
||||
val isStuck = Bool()
|
||||
val isRemoved = Bool()
|
||||
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 physicalAddress = UInt(p.addressWidth bits)
|
||||
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 = {
|
||||
out(isValid, isStuck, isRemoved, pc)
|
||||
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss,physicalAddress)
|
||||
outWithNull(isUser)
|
||||
outWithNull(isUser, dataBypass, dataBypassValid)
|
||||
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 valid = Cat(hits).orR
|
||||
val id = OHToUInt(hits)
|
||||
val error = read.waysValues.map(_.tag.error).read(id)
|
||||
val data = read.waysValues.map(_.data).read(id)
|
||||
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){
|
||||
io.cpu.decode.data := RegNextWhen(io.cpu.fetch.data,!io.cpu.decode.isStuck)
|
||||
}
|
||||
} else null
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -405,7 +407,6 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress
|
||||
|
||||
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
|
||||
|
||||
io.cpu.fetch.cacheMiss := !hit.valid
|
||||
|
@ -432,17 +433,13 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val error = tags(id).error
|
||||
val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id)
|
||||
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.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.mmuMiss := mmuRsp.miss
|
||||
io.cpu.decode.illegalAccess := !mmuRsp.allowExecute || (io.cpu.decode.isUser && !mmuRsp.allowUser)
|
||||
|
|
|
@ -271,6 +271,20 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val csrMapping = new CsrMapping()
|
||||
|
||||
|
||||
|
||||
case class InterruptSource(var cond : Bool, id : Int)
|
||||
case class InterruptPrivilege(privilege : Int){
|
||||
var privilegeCond : Bool = null
|
||||
val sources = ArrayBuffer[InterruptSource]()
|
||||
}
|
||||
|
||||
def getInterruptPrivilege(privilege : Int) = customInterrupts.getOrElseUpdate(privilege, InterruptPrivilege(privilege))
|
||||
var customInterrupts = mutable.LinkedHashMap[Int, InterruptPrivilege]()
|
||||
def addInterrupt(cond : Bool, id : Int, privilege : Int): Unit = {
|
||||
getInterruptPrivilege(privilege).sources += InterruptSource(cond, id)
|
||||
}
|
||||
def createInterrupt(id : Int, privilege : Int) : Bool = { val ret = Bool(); addInterrupt(ret, id, privilege); ret}
|
||||
|
||||
override def r(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r(csrAddress, bitOffset, that)
|
||||
override def w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.w(csrAddress, bitOffset, that)
|
||||
override def onWrite(csrAddress: Int)(body: => Unit): Unit = csrMapping.onWrite(csrAddress)(body)
|
||||
|
@ -338,6 +352,11 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
allowInterrupts = True
|
||||
allowException = True
|
||||
|
||||
for (privilege <- customInterrupts.values;
|
||||
source <- privilege.sources){
|
||||
source.cond = source.cond.pull()
|
||||
}
|
||||
}
|
||||
|
||||
def inhibateInterrupts() : Unit = allowInterrupts := False
|
||||
|
@ -500,20 +519,22 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
minstret := minstret + 1
|
||||
}
|
||||
|
||||
case class InterruptSource(cond : Bool, id : Int)
|
||||
case class InterruptPrivilege(privilege : Int, privilegeCond : Bool, sources : ArrayBuffer[InterruptSource])
|
||||
val interruptModel = ArrayBuffer[InterruptPrivilege]()
|
||||
if(supervisorGen) interruptModel += InterruptPrivilege(1, sstatus.SIE && privilege <= "01", ArrayBuffer(
|
||||
InterruptSource(sip.STIP && sie.STIE, 5),
|
||||
InterruptSource(sip.SSIP && sie.SSIE, 1),
|
||||
InterruptSource(sip.SEIP && sie.SEIE, 9)
|
||||
))
|
||||
|
||||
interruptModel += InterruptPrivilege(3, mstatus.MIE , ArrayBuffer(
|
||||
if(supervisorGen) {
|
||||
getInterruptPrivilege(1).privilegeCond = sstatus.SIE && privilege <= "01"
|
||||
getInterruptPrivilege(1).sources ++= List(
|
||||
InterruptSource(sip.STIP && sie.STIE, 5),
|
||||
InterruptSource(sip.SSIP && sie.SSIE, 1),
|
||||
InterruptSource(sip.SEIP && sie.SEIE, 9)
|
||||
)
|
||||
}
|
||||
|
||||
getInterruptPrivilege(3).privilegeCond = mstatus.MIE
|
||||
getInterruptPrivilege(3).sources ++= List(
|
||||
InterruptSource(mip.MTIP && mie.MTIE, 7),
|
||||
InterruptSource(mip.MSIP && mie.MSIE, 3),
|
||||
InterruptSource(mip.MEIP && mie.MEIE, 11)
|
||||
))
|
||||
)
|
||||
|
||||
case class DelegatorModel(value : Bits, source : Int, target : Int)
|
||||
// def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
|
||||
|
@ -621,7 +642,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val interrupt = False
|
||||
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
||||
val interruptDelegatorHit = interruptDelegators.map(d => (d -> False)).toMap
|
||||
for(model <- interruptModel){
|
||||
for(model <- customInterrupts.values.toSeq.sortBy(_.privilege)){
|
||||
when(model.privilegeCond){
|
||||
when(model.sources.map(_.cond).orR){
|
||||
interrupt := True
|
||||
|
|
|
@ -84,61 +84,79 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
|
||||
val stageables = (encodings.flatMap(_._2.map(_._1)) ++ defaults.map(_._1)).toSet.toList
|
||||
|
||||
var offset = 0
|
||||
var defaultValue, defaultCare = BigInt(0)
|
||||
val offsetOf = mutable.HashMap[Stageable[_ <: BaseType],Int]()
|
||||
val stupidDecoder = false
|
||||
if(stupidDecoder){
|
||||
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := False
|
||||
for(stageable <- stageables){
|
||||
if(defaults.contains(stageable)){
|
||||
insert(stageable).assignFrom(defaults(stageable))
|
||||
} else {
|
||||
insert(stageable).assignDontCare()
|
||||
}
|
||||
}
|
||||
for((key, tasks) <- encodings){
|
||||
when(input(INSTRUCTION) === key){
|
||||
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := True
|
||||
for((stageable, value) <- tasks){
|
||||
insert(stageable).assignFrom(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var offset = 0
|
||||
var defaultValue, defaultCare = BigInt(0)
|
||||
val offsetOf = mutable.HashMap[Stageable[_ <: BaseType], Int]()
|
||||
|
||||
//Build defaults value and field offset map
|
||||
stageables.foreach(e => {
|
||||
defaults.get(e) match {
|
||||
case Some(value) => {
|
||||
value.head.source match {
|
||||
//Build defaults value and field offset map
|
||||
stageables.foreach(e => {
|
||||
defaults.get(e) match {
|
||||
case Some(value) => {
|
||||
value.head.source match {
|
||||
case literal: EnumLiteral[_] => literal.fixEncoding(e.dataType.asInstanceOf[SpinalEnumCraft[_]].getEncoding)
|
||||
case _ =>
|
||||
}
|
||||
defaultValue += value.head.source.asInstanceOf[Literal].getValue << offset
|
||||
defaultCare += ((BigInt(1) << e.dataType.getBitsWidth) - 1) << offset
|
||||
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
offsetOf(e) = offset
|
||||
offset += e.dataType.getBitsWidth
|
||||
})
|
||||
|
||||
//Build spec
|
||||
val spec = encodings.map { case (key, values) =>
|
||||
var decodedValue = defaultValue
|
||||
var decodedCare = defaultCare
|
||||
for ((e, literal) <- values) {
|
||||
literal.head.source match {
|
||||
case literal: EnumLiteral[_] => literal.fixEncoding(e.dataType.asInstanceOf[SpinalEnumCraft[_]].getEncoding)
|
||||
case _ =>
|
||||
}
|
||||
defaultValue += value.head.source .asInstanceOf[Literal].getValue << offset
|
||||
defaultCare += ((BigInt(1) << e.dataType.getBitsWidth) - 1) << offset
|
||||
|
||||
val offset = offsetOf(e)
|
||||
decodedValue |= literal.head.source.asInstanceOf[Literal].getValue << offset
|
||||
decodedCare |= ((BigInt(1) << e.dataType.getBitsWidth) - 1) << offset
|
||||
}
|
||||
case _ =>
|
||||
(Masked(key.value, key.careAbout), Masked(decodedValue, decodedCare))
|
||||
}
|
||||
offsetOf(e) = offset
|
||||
offset += e.dataType.getBitsWidth
|
||||
})
|
||||
|
||||
//Build spec
|
||||
val spec = encodings.map { case (key, values) =>
|
||||
var decodedValue = defaultValue
|
||||
var decodedCare = defaultCare
|
||||
for((e, literal) <- values){
|
||||
literal.head.source match{
|
||||
case literal : EnumLiteral[_] => literal.fixEncoding(e.dataType.asInstanceOf[SpinalEnumCraft[_]].getEncoding)
|
||||
case _ =>
|
||||
}
|
||||
val offset = offsetOf(e)
|
||||
decodedValue |= literal.head.source.asInstanceOf[Literal].getValue << offset
|
||||
decodedCare |= ((BigInt(1) << e.dataType.getBitsWidth)-1) << offset
|
||||
}
|
||||
(Masked(key.value,key.careAbout),Masked(decodedValue,decodedCare))
|
||||
|
||||
// logic implementation
|
||||
val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits)
|
||||
decodedBits := Symplify(input(INSTRUCTION), spec, decodedBits.getWidth)
|
||||
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32))
|
||||
|
||||
|
||||
//Unpack decodedBits and insert fields in the pipeline
|
||||
offset = 0
|
||||
stageables.foreach(e => {
|
||||
insert(e).assignFromBits(decodedBits(offset, e.dataType.getBitsWidth bits))
|
||||
// insert(e).assignFromBits(RegNext(decodedBits(offset, e.dataType.getBitsWidth bits)))
|
||||
offset += e.dataType.getBitsWidth
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
// logic implementation
|
||||
val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits)
|
||||
decodedBits := Symplify(input(INSTRUCTION),spec, decodedBits.getWidth)
|
||||
if(catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32))
|
||||
|
||||
|
||||
//Unpack decodedBits and insert fields in the pipeline
|
||||
offset = 0
|
||||
stageables.foreach(e => {
|
||||
insert(e).assignFromBits(decodedBits(offset, e.dataType.getBitsWidth bits))
|
||||
// insert(e).assignFromBits(RegNext(decodedBits(offset, e.dataType.getBitsWidth bits)))
|
||||
offset += e.dataType.getBitsWidth
|
||||
})
|
||||
|
||||
|
||||
if(catchIllegalInstruction){
|
||||
decodeExceptionPort.valid := arbitration.isValid && input(INSTRUCTION_READY) && !input(LEGAL_INSTRUCTION) // ?? HalitIt to alow decoder stage to wait valid data from 2 stages cache cache ??
|
||||
decodeExceptionPort.code := 2
|
||||
|
@ -149,8 +167,8 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
def bench(toplevel : VexRiscv): Unit ={
|
||||
toplevel.rework{
|
||||
import toplevel.config._
|
||||
toplevel.getAllIo.foreach{io =>
|
||||
if(io.isInput) io.assignDontCare()
|
||||
toplevel.getAllIo.toList.foreach{io =>
|
||||
if(io.isInput) { io.assignDontCare()}
|
||||
io.setAsDirectionLess()
|
||||
}
|
||||
toplevel.decode.input(INSTRUCTION).removeAssignments()
|
||||
|
|
|
@ -5,10 +5,26 @@ import vexriscv.ip._
|
|||
import spinal.core._
|
||||
import spinal.lib._
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
//class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
|
||||
// var iBus : InstructionCacheMemBus = null
|
||||
// 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,
|
||||
relaxedPcCalculation : Boolean = false,
|
||||
prediction : BranchPrediction = NONE,
|
||||
|
@ -17,7 +33,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
keepPcPlus4 : Boolean = false,
|
||||
config : InstructionCacheConfig,
|
||||
memoryTranslatorPortConfig : Any = null,
|
||||
injectorStage : Boolean = false) extends IBusFetcherImpl(
|
||||
injectorStage : Boolean = false,
|
||||
withoutInjectorStage : Boolean = false) extends IBusFetcherImpl(
|
||||
resetVector = resetVector,
|
||||
keepPcPlus4 = keepPcPlus4,
|
||||
decodePcGen = compressedGen,
|
||||
|
@ -27,15 +44,25 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
injectorReadyCutGen = false,
|
||||
prediction = prediction,
|
||||
historyRamSizeLog2 = historyRamSizeLog2,
|
||||
injectorStage = !config.twoCycleCache || injectorStage){
|
||||
injectorStage = (!config.twoCycleCache && !withoutInjectorStage) || injectorStage){
|
||||
import config._
|
||||
|
||||
assert(!(withoutInjectorStage && injectorStage))
|
||||
|
||||
var iBus : InstructionCacheMemBus = null
|
||||
var mmuBus : MemoryTranslatorBus = null
|
||||
var privilegeService : PrivilegeService = null
|
||||
var redoBranch : Flow[UInt] = 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 IBUS_ACCESS_ERROR extends Stageable(Bool)
|
||||
|
@ -66,8 +93,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
if(pipeline.serviceExist(classOf[MemoryTranslator]))
|
||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_INSTRUCTION, memoryTranslatorPortConfig)
|
||||
|
||||
if(pipeline.serviceExist(classOf[PrivilegeService]))
|
||||
privilegeService = pipeline.service(classOf[PrivilegeService])
|
||||
privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||
|
||||
if(pipeline.serviceExist(classOf[ReportService])){
|
||||
val report = pipeline.service(classOf[ReportService])
|
||||
|
@ -98,21 +124,106 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
val cache = new InstructionCache(IBusCachedPlugin.this.config)
|
||||
iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus")
|
||||
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
|
||||
def stages = iBusRsp.stages.drop(stageOffset)
|
||||
//Connect prefetch cache side
|
||||
cache.io.cpu.prefetch.isValid := stages(0).input.valid
|
||||
cache.io.cpu.prefetch.pc := stages(0).input.payload
|
||||
stages(0).halt setWhen(cache.io.cpu.prefetch.haltIt)
|
||||
|
||||
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
|
||||
cache.io.cpu.prefetch.isValid := stages(0).input.valid && !tightlyCoupledHit
|
||||
cache.io.cpu.prefetch.pc := stages(0).input.payload
|
||||
stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt)
|
||||
|
||||
|
||||
cache.io.cpu.fetch.isRemoved := flush
|
||||
val iBusRspOutputHalt = False
|
||||
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 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) {
|
||||
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 {
|
||||
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
|
||||
|
@ -124,64 +235,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
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
|
||||
flushStage plug new Area {
|
||||
import flushStage._
|
||||
|
|
|
@ -1192,6 +1192,43 @@ public:
|
|||
};
|
||||
#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
|
||||
|
||||
struct IBusSimpleAvalonRsp{
|
||||
|
@ -1274,6 +1311,12 @@ public:
|
|||
bool error;
|
||||
top->iBus_rsp_valid = 0;
|
||||
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);
|
||||
top->iBus_rsp_payload_error = error;
|
||||
pendingCount--;
|
||||
|
@ -1960,6 +2003,11 @@ void Workspace::fillSimELements(){
|
|||
#if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
|
||||
simElements.push_back(new IBusCachedWishbone(this));
|
||||
#endif
|
||||
|
||||
#ifdef IBUS_TC
|
||||
simElements.push_back(new IBusTc(this));
|
||||
#endif
|
||||
|
||||
#ifdef DBUS_SIMPLE
|
||||
simElements.push_back(new DBusSimple(this));
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
DEBUG?=no
|
||||
|
||||
IBUS?=CACHED
|
||||
IBUS_TC?=no
|
||||
DBUS?=CACHED
|
||||
TRACE?=no
|
||||
TRACE_ACCESS?=no
|
||||
|
@ -42,7 +43,7 @@ ADDCFLAGS += -CFLAGS -DTHREAD_COUNT=${THREAD_COUNT}
|
|||
ifeq ($(DEBUG),yes)
|
||||
ADDCFLAGS += -CFLAGS -O0 -CFLAGS -g
|
||||
else
|
||||
ADDCFLAGS += -CFLAGS -O3
|
||||
ADDCFLAGS += -CFLAGS -O3 -O3
|
||||
endif
|
||||
|
||||
|
||||
|
@ -58,6 +59,11 @@ ifneq ($(RUN_HEX),no)
|
|||
ADDCFLAGS += -CFLAGS -DRUN_HEX='\"$(RUN_HEX)\"'
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(IBUS_TC),yes)
|
||||
ADDCFLAGS += -CFLAGS -DIBUS_TC=yes
|
||||
endif
|
||||
|
||||
ifeq ($(COMPRESSED),yes)
|
||||
ADDCFLAGS += -CFLAGS -DCOMPRESSED
|
||||
endif
|
||||
|
|
|
@ -284,6 +284,8 @@ class IBusDimension extends VexRiscvDimension("IBus") {
|
|||
}
|
||||
} else {
|
||||
val compressed = r.nextBoolean()
|
||||
val tighlyCoupled = r.nextBoolean()
|
||||
// val tighlyCoupled = false
|
||||
val prediction = random(r, List(NONE, STATIC, DYNAMIC, DYNAMIC_TARGET))
|
||||
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
|
||||
val relaxedPcCalculation, twoCycleCache, injectorStage = r.nextBoolean()
|
||||
|
@ -295,29 +297,33 @@ class IBusDimension extends VexRiscvDimension("IBus") {
|
|||
wayCount = 1 << r.nextInt(3)
|
||||
}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{
|
||||
override def testParam = "IBUS=CACHED" + (if(compressed) " COMPRESSED=yes" else "")
|
||||
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new IBusCachedPlugin(
|
||||
resetVector = 0x80000000l,
|
||||
compressedGen = compressed,
|
||||
prediction = prediction,
|
||||
relaxedPcCalculation = relaxedPcCalculation,
|
||||
injectorStage = injectorStage,
|
||||
config = InstructionCacheConfig(
|
||||
cacheSize = cacheSize,
|
||||
bytePerLine = 32,
|
||||
wayCount = wayCount,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchIllegalAccess = catchAll,
|
||||
catchAccessFault = catchAll,
|
||||
catchMemoryTranslationMiss = catchAll,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = twoCycleRam,
|
||||
twoCycleCache = twoCycleCache
|
||||
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 "") + (if(tighlyCoupled)" IBUS_TC=yes" else "")
|
||||
override def applyOn(config: VexRiscvConfig): Unit = {
|
||||
val p = new IBusCachedPlugin(
|
||||
resetVector = 0x80000000l,
|
||||
compressedGen = compressed,
|
||||
prediction = prediction,
|
||||
relaxedPcCalculation = relaxedPcCalculation,
|
||||
injectorStage = injectorStage,
|
||||
config = InstructionCacheConfig(
|
||||
cacheSize = cacheSize,
|
||||
bytePerLine = 32,
|
||||
wayCount = wayCount,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchIllegalAccess = catchAll,
|
||||
catchAccessFault = catchAll,
|
||||
catchMemoryTranslationMiss = catchAll,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = twoCycleRam,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -523,8 +529,8 @@ class TestIndividualFeatures extends FunSuite {
|
|||
|
||||
|
||||
// val testId = Some(mutable.HashSet[Int](0,28,45,93))
|
||||
// val testId = Some(mutable.HashSet[Int](5))
|
||||
// val seed = -2089952013329208578l
|
||||
// val testId = Some(mutable.HashSet[Int](31))
|
||||
// val seed = -7716775349351274630l
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue