Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
279 changes: 33 additions & 246 deletions src/main/scala/riscv/Config.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package riscv

import spinal.core._
import riscv.plugins._
import spinal.core.log2Up

sealed trait BaseIsa {
val xlen: Int
Expand All @@ -23,259 +22,47 @@ object BaseIsa {
}
}

sealed trait PrefetcherType
object PrefetcherType {
case object None extends PrefetcherType
case object SequentialInstructionPrefetcher extends PrefetcherType
}

case class PrefetcherConfig(prefetcherType: PrefetcherType) {
def create(implicit config: Config): Option[Plugin[Pipeline] with PrefetchService] = {
prefetcherType match {
case PrefetcherType.None => None
case PrefetcherType.SequentialInstructionPrefetcher =>
Some(new memory.SequentialInstructionPrefetcher)
}
}
}

case class CacheConfig(
sets: Int,
ways: Int,
prefetcher: PrefetcherConfig = PrefetcherConfig(PrefetcherType.None),
maxPrefetches: Int = 1,
delay: Int = 1
)

sealed abstract class Config(
val isa: BaseIsa,
val memBusWidth: Int,
val idWidth: Int,
val extraDbusReadDelay: Int,
val applyDelayToIBus: Boolean,
val iCaches: Seq[CacheConfig],
val dCaches: Seq[CacheConfig],
val stlSpec: Boolean,
val debug: Boolean
) {
val ibusConfig = MemBusConfig(
addressWidth = isa.xlen,
idWidth = 2,
dataWidth = memBusWidth,
readWrite = false
)

val readDbusConfig = MemBusConfig(
addressWidth = isa.xlen,
idWidth = idWidth,
dataWidth = memBusWidth,
readWrite = false
)

val dbusConfig = MemBusConfig(
addressWidth = isa.xlen,
idWidth = idWidth,
dataWidth = memBusWidth
)
class Config(val baseIsa: BaseIsa, val debug: Boolean = true, val stlSpec: Boolean = true, val memoryTagger: Boolean = false) {
def xlen = baseIsa.xlen
def numRegs = baseIsa.numRegs

override def toString: String =
s"""${getClass.getSimpleName}(
| isa=$isa,
| memBusWidth=$memBusWidth,
| idWidth=$idWidth,
| extraDbusReadDelay=$extraDbusReadDelay,
| applyDelayToIBus=$applyDelayToIBus,
| iCaches=$iCaches,
| dCaches=$dCaches,
| stlSpec=$stlSpec,
| debug=$debug
|)""".stripMargin
}

class StaticPipelineConfig(
isa: BaseIsa = BaseIsa.RV32I,
memBusWidth: Int = 128,
idWidth: Int = log2Up(4),
extraDbusReadDelay: Int = 32,
applyDelayToIBus: Boolean = false,
iCaches: Seq[CacheConfig] = Seq(
CacheConfig(
sets = 2,
ways = 2,
prefetcher = PrefetcherConfig(PrefetcherType.SequentialInstructionPrefetcher)
)
),
dCaches: Seq[CacheConfig] = Seq(CacheConfig(sets = 8, ways = 2)),
debug: Boolean = true
) extends Config(
isa = isa,
memBusWidth = memBusWidth,
idWidth = idWidth,
extraDbusReadDelay = extraDbusReadDelay,
applyDelayToIBus = applyDelayToIBus,
iCaches = iCaches,
dCaches = dCaches,
stlSpec = false,
debug = debug
)
def memBusWidth: Int = 128

class DynamicPipelineConfig(
isa: BaseIsa = BaseIsa.RV32I,
memBusWidth: Int = 128,
extraDbusReadDelay: Int = 32,
applyDelayToIBus: Boolean = false,
iCaches: Seq[CacheConfig] = Seq(
CacheConfig(
sets = 2,
ways = 2,
prefetcher = PrefetcherConfig(PrefetcherType.SequentialInstructionPrefetcher)
)
),
dCaches: Seq[CacheConfig] = Seq(CacheConfig(sets = 8, ways = 2)),
val robEntries: Int = 32,
val parallelAlus: Int = 8,
val parallelMulDivs: Int = 2,
val parallelLoads: Int = 3,
val addressBasedPsf: Boolean = true,
val addressBasedSsb: Boolean = true,
stlSpec: Boolean = true,
debug: Boolean = true
) extends Config(
isa = isa,
memBusWidth = memBusWidth,
idWidth = log2Up(parallelLoads + 1),
extraDbusReadDelay = extraDbusReadDelay,
applyDelayToIBus = applyDelayToIBus,
iCaches = iCaches,
dCaches = dCaches,
stlSpec = stlSpec,
debug = debug
) {
override def toString: String =
s"""${super.toString.dropRight(1)}
| robEntries=$robEntries,
| parallelAlus=$parallelAlus,
| parallelMulDivs=$parallelMulDivs,
| parallelLoads=$parallelLoads,
| addressBasedPsf=$addressBasedPsf,
| addressBasedSsb=$addressBasedSsb
|)""".stripMargin
}
def tagGranularity: Int = 8

object Config {
private def getIsa(isa: String): BaseIsa = {
isa match {
case "RV32I" => BaseIsa.RV32I
case "RV32E" => BaseIsa.RV32E
case "RV64I" => BaseIsa.RV64I
case other => throw new IllegalArgumentException(s"Unknown ISA: $other")
}
}
def tagBusWidth: Int = if (memoryTagger) memBusWidth / tagGranularity else 0

def apply(jsonString: String): Config = {
val jsonObject = ujson.read(jsonString)
def robEntries: Int = 32

def parseBool(jsonObject: ujson.Value, key: String, default: Boolean): Boolean = {
jsonObject.obj.get(key).map(_.bool).getOrElse(default)
}
def parallelAlus: Int = 8

def parseInt(jsonObject: ujson.Value, key: String, default: Int): Int = {
jsonObject.obj.get(key).map(_.num.toInt).getOrElse(default)
}
def parallelMulDivs: Int = 2

def parseIsa(jsonObject: ujson.Value, key: String, default: BaseIsa): BaseIsa = {
jsonObject.obj.get(key).map(_.str) match {
case Some(isa) => getIsa(isa)
case None => default
}
}
def parallelLoads: Int = 3

def parsePrefetcher(
jsonObject: ujson.Value,
key: String,
default: PrefetcherConfig
): PrefetcherConfig = {
jsonObject.obj.get(key) match {
case Some(prefetcher) =>
PrefetcherConfig(prefetcher.obj.get("prefetcherType").map(_.str) match {
case Some(prefetcherType) =>
prefetcherType match {
case "None" => PrefetcherType.None
case "SequentialInstructionPrefetcher" =>
PrefetcherType.SequentialInstructionPrefetcher
case other => throw new IllegalArgumentException(s"Unknown prefetcher: $other")
}
case None => default.prefetcherType
})
case None => default
}
}
def addressBasedPsf: Boolean = true

def parseCaches(
jsonObject: ujson.Value,
key: String,
default: CacheConfig
): Seq[CacheConfig] = {
jsonObject.obj.get(key).map(_.arr) match {
case Some(caches) => caches.map(cache => parseCache(cache, default))
case None => Seq(default)
}
}
def addressBasedSsb: Boolean = true

def parseCache(cache: ujson.Value, default: CacheConfig): CacheConfig = {
CacheConfig(
sets = parseInt(cache, "sets", default.sets),
ways = parseInt(cache, "ways", default.ways),
prefetcher = parsePrefetcher(cache, "prefetcher", default.prefetcher),
maxPrefetches = parseInt(cache, "maxPrefetches", default.maxPrefetches),
delay = parseInt(cache, "delay", default.delay)
)
}

jsonObject("pipeline").str match {
case "Static" => {
val default: StaticPipelineConfig = new StaticPipelineConfig()
new StaticPipelineConfig(
isa = parseIsa(jsonObject, "isa", default.isa),
memBusWidth = parseInt(jsonObject, "memBusWidth", default.memBusWidth),
idWidth = parseInt(jsonObject, "idWidth", default.idWidth),
extraDbusReadDelay =
parseInt(jsonObject, "extraDbusReadDelay", default.extraDbusReadDelay),
applyDelayToIBus = parseBool(jsonObject, "applyDelayToIBus", default.applyDelayToIBus),
iCaches = parseCaches(jsonObject, "iCaches", default.iCaches.head),
dCaches = parseCaches(jsonObject, "dCaches", default.dCaches.head),
debug = parseBool(jsonObject, "debug", default.debug)
)
}
case "Dynamic" => {
val default: DynamicPipelineConfig = new DynamicPipelineConfig()
new DynamicPipelineConfig(
isa = parseIsa(jsonObject, "isa", default.isa),
memBusWidth = parseInt(jsonObject, "memBusWidth", default.memBusWidth),
extraDbusReadDelay =
parseInt(jsonObject, "extraDbusReadDelay", default.extraDbusReadDelay),
applyDelayToIBus = parseBool(jsonObject, "applyDelayToIBus", default.applyDelayToIBus),
iCaches = parseCaches(jsonObject, "iCaches", default.iCaches.head),
dCaches = parseCaches(jsonObject, "dCaches", default.dCaches.head),
robEntries = parseInt(jsonObject, "robEntries", default.robEntries),
parallelAlus = parseInt(jsonObject, "parallelAlus", default.parallelAlus),
parallelMulDivs = parseInt(jsonObject, "parallelMulDivs", default.parallelMulDivs),
parallelLoads = parseInt(jsonObject, "parallelLoads", default.parallelLoads),
addressBasedPsf = parseBool(jsonObject, "addressBasedPsf", default.addressBasedPsf),
addressBasedSsb = parseBool(jsonObject, "addressBasedSsb", default.addressBasedSsb),
stlSpec = parseBool(jsonObject, "stlSpec", default.stlSpec),
debug = parseBool(jsonObject, "debug", default.debug)
)
}
case other => throw new IllegalArgumentException(s"Unknown pipeline: $other")
}
}
def ibusConfig = MemBusConfig(
addressWidth = baseIsa.xlen,
idWidth = 2,
dataWidth = memBusWidth,
readWrite = false,
tagBusWidth = tagBusWidth
)
def readDbusConfig = MemBusConfig(
addressWidth = baseIsa.xlen,
idWidth = log2Up(parallelLoads + 1),
dataWidth = memBusWidth,
readWrite = false,
tagBusWidth = tagBusWidth

def apply(pipeline: String, isa: String): Config = {
pipeline match {
case "Static" => new StaticPipelineConfig(isa = getIsa(isa))
case "Dynamic" => new DynamicPipelineConfig(isa = getIsa(isa))
case other => throw new IllegalArgumentException(s"Unknown pipeline: $other")
}
}
)
def dbusConfig = MemBusConfig(
addressWidth = baseIsa.xlen,
idWidth = log2Up(parallelLoads + 1),
dataWidth = memBusWidth,
tagBusWidth = tagBusWidth
)
}
Loading
Loading