mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-04-24 05:57:07 -04:00
Decoding lib cleaning
This commit is contained in:
parent
137b1ee32c
commit
5260ad5c35
7 changed files with 94 additions and 40 deletions
|
@ -53,8 +53,7 @@ object TestsWorkspace {
|
|||
asyncTagMemory = false,
|
||||
twoCycleRam = false
|
||||
),
|
||||
askMemoryTranslation = true,
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
|
|
|
@ -30,7 +30,6 @@ object GenFull extends App{
|
|||
asyncTagMemory = false,
|
||||
twoCycleRam = true
|
||||
),
|
||||
askMemoryTranslation = true,
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
|
|
|
@ -29,8 +29,7 @@ object GenSmallAndProductiveICache extends App{
|
|||
catchMemoryTranslationMiss = false,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false
|
||||
),
|
||||
askMemoryTranslation = false
|
||||
)
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = false,
|
||||
|
|
|
@ -2,6 +2,8 @@ package vexriscv.demo
|
|||
|
||||
import spinal.core._
|
||||
import spinal.lib.eda.bench._
|
||||
import vexriscv.VexRiscv
|
||||
import vexriscv.plugin.DecoderSimplePlugin
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
@ -11,7 +13,7 @@ import scala.collection.mutable.ArrayBuffer
|
|||
object VexRiscvSynthesisBench {
|
||||
def main(args: Array[String]) {
|
||||
|
||||
def wrap(that : => Component) : Component = that
|
||||
// def wrap(that : => Component) : Component = that
|
||||
// Wrap with input/output registers
|
||||
// def wrap(that : => Component) : Component = {
|
||||
// //new WrapWithReg.Wrapper(that)
|
||||
|
@ -31,6 +33,13 @@ object VexRiscvSynthesisBench {
|
|||
// c
|
||||
// }
|
||||
|
||||
// Wrap to do a decoding bench
|
||||
def wrap(that : => VexRiscv) : VexRiscv = {
|
||||
val top = that
|
||||
top.service(classOf[DecoderSimplePlugin]).bench(top)
|
||||
top
|
||||
}
|
||||
|
||||
val smallestNoCsr = new Rtl {
|
||||
override def getName(): String = "VexRiscv smallest no CSR"
|
||||
override def getRtlPath(): String = "VexRiscvSmallestNoCsr.v"
|
||||
|
@ -84,9 +93,12 @@ object VexRiscvSynthesisBench {
|
|||
SpinalVerilog(wrap(GenFull.cpu()).setDefinitionName(getRtlPath().split("\\.").head))
|
||||
}
|
||||
|
||||
|
||||
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||
// val rtls = List(noCacheNoMmuMaxPerf, fullNoMmuMaxPerf)
|
||||
val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||
val rtls = List(smallAndProductive, full)
|
||||
|
||||
|
||||
val targets = XilinxStdTargets(
|
||||
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
|
|
|
@ -4,12 +4,14 @@ import vexriscv._
|
|||
import spinal.core._
|
||||
import spinal.core.internals.Literal
|
||||
import spinal.lib._
|
||||
import vexriscv.demo.GenFull
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
||||
case class Masked(value : BigInt,care : BigInt){
|
||||
assert((value & ~care) == 0)
|
||||
var isPrime = true
|
||||
|
||||
def < (that: Masked) = value < that.value || value == that.value && ~care < ~that.care
|
||||
|
@ -23,13 +25,15 @@ case class Masked(value : BigInt,care : BigInt){
|
|||
this
|
||||
}
|
||||
|
||||
def merge(x: Masked) = {
|
||||
def mergeOneBitDifSmaller(x: Masked) = {
|
||||
val bit = value - x.value
|
||||
val ret = new Masked(value &~ bit, care & ~bit)
|
||||
// ret.isPrime = isPrime || x.isPrime
|
||||
isPrime = false
|
||||
x.isPrime = false
|
||||
val bit = value - x.value
|
||||
new Masked(value &~ bit, care & ~bit)
|
||||
ret
|
||||
}
|
||||
def similar(x: Masked) = {
|
||||
def isSimilarOneBitDifSmaller(x: Masked) = {
|
||||
val diff = value - x.value
|
||||
care == x.care && value > x.value && (diff & diff - 1) == 0
|
||||
}
|
||||
|
@ -123,7 +127,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean, forceLegalInstructi
|
|||
// 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.getPrimeImplicants(spec.unzip._1.toSeq, 32))
|
||||
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
|
||||
|
@ -145,7 +149,11 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean, forceLegalInstructi
|
|||
def bench(toplevel : VexRiscv): Unit ={
|
||||
toplevel.rework{
|
||||
import toplevel.config._
|
||||
toplevel.getAllIo.toList.foreach(_.asDirectionLess())
|
||||
toplevel.getAllIo.foreach{io =>
|
||||
if(io.isInput) io.assignDontCare()
|
||||
io.asDirectionLess()
|
||||
}
|
||||
toplevel.decode.input(INSTRUCTION).removeAssignments()
|
||||
toplevel.decode.input(INSTRUCTION) := Delay((in Bits(32 bits)).setName("instruction"),2)
|
||||
val stageables = encodings.flatMap(_._2.map(_._1)).toSet
|
||||
stageables.foreach(e => out(RegNext(RegNext(toplevel.decode.insert(e)).setName(e.getName()))))
|
||||
|
@ -155,12 +163,19 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean, forceLegalInstructi
|
|||
}
|
||||
}
|
||||
|
||||
object DecodingBench extends App{
|
||||
SpinalVerilog{
|
||||
val top = GenFull.cpu()
|
||||
top.service(classOf[DecoderSimplePlugin]).bench(top)
|
||||
top
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object Symplify{
|
||||
val cache = mutable.HashMap[Bits,mutable.HashMap[Masked,Bool]]()
|
||||
def getCache(addr : Bits) = cache.getOrElseUpdate(addr,mutable.HashMap[Masked,Bool]())
|
||||
|
||||
|
||||
//Generate terms logic for the given input
|
||||
def logicOf(input : Bits,terms : Seq[Masked]) = terms.map(t => getCache(input).getOrElseUpdate(t,t === input)).asBits.orR
|
||||
|
||||
|
@ -170,7 +185,7 @@ object Symplify{
|
|||
(for(bitId <- 0 until resultWidth) yield{
|
||||
val trueTerm = mapping.filter { case (k,t) => (t.care.testBit(bitId) && t.value.testBit(bitId))}.map(_._1)
|
||||
val falseTerm = mapping.filter { case (k,t) => (t.care.testBit(bitId) && !t.value.testBit(bitId))}.map(_._1)
|
||||
val symplifiedTerms = SymplifyBit.getPrimeImplicants(trueTerm.toSeq, falseTerm.toSeq, addrWidth)
|
||||
val symplifiedTerms = SymplifyBit.getPrimeImplicantsByTrueAndFalse(trueTerm.toSeq, falseTerm.toSeq, addrWidth)
|
||||
logicOf(input, symplifiedTerms)
|
||||
}).asBits
|
||||
}
|
||||
|
@ -196,28 +211,31 @@ object SymplifyBit{
|
|||
}
|
||||
|
||||
//Return primes implicants for the trueTerms, falseTerms spec. Default value is don't care
|
||||
def getPrimeImplicants(trueTerms: Seq[Masked],falseTerms: Seq[Masked],inputWidth : Int): Seq[Masked] = {
|
||||
def getPrimeImplicantsByTrueAndFalse(trueTerms: Seq[Masked], falseTerms: Seq[Masked], inputWidth : Int): Seq[Masked] = {
|
||||
val primes = ArrayBuffer[Masked]()
|
||||
trueTerms.foreach(_.isPrime = true)
|
||||
falseTerms.foreach(_.isPrime = true)
|
||||
val trueTermByCareCount = (inputWidth to 0 by -1).map(b => trueTerms.filter(b == _.care.bitCount))
|
||||
//table[Vector[HashSet[Masked]]](careCount)(bitSetCount)
|
||||
val table = trueTermByCareCount.map(c => (0 to inputWidth).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount): _*)))
|
||||
for (i <- 0 to inputWidth) {
|
||||
//Expends explicit terms
|
||||
for (j <- 0 until inputWidth - i){
|
||||
for(term <- table(i)(j)){
|
||||
table(i+1)(j) ++= table(i)(j+1).filter(_.similar(term)).map(_.merge(term))
|
||||
table(i+1)(j) ++= table(i)(j+1).withFilter(_.isSimilarOneBitDifSmaller(term)).map(_.mergeOneBitDifSmaller(term))
|
||||
}
|
||||
}
|
||||
//Expends implicit don't care terms
|
||||
for (j <- 0 until inputWidth-i) {
|
||||
for (a <- table(i)(j).filter(_.isPrime)) {
|
||||
val dc = genImplicitDontCare(falseTerms, a, inputWidth, true)
|
||||
for (prime <- table(i)(j).withFilter(_.isPrime)) {
|
||||
val dc = genImplicitDontCare(falseTerms, prime, inputWidth, true)
|
||||
if (dc != null)
|
||||
table(i+1)(j) += dc merge a
|
||||
table(i+1)(j) += dc mergeOneBitDifSmaller prime
|
||||
}
|
||||
for (a <- table(i)(j+1).filter(_.isPrime)) {
|
||||
val dc = genImplicitDontCare(falseTerms, a, inputWidth, false)
|
||||
for (prime <- table(i)(j+1).withFilter(_.isPrime)) {
|
||||
val dc = genImplicitDontCare(falseTerms, prime, inputWidth, false)
|
||||
if (dc != null)
|
||||
table(i+1)(j) += a merge dc
|
||||
table(i+1)(j) += prime mergeOneBitDifSmaller dc
|
||||
}
|
||||
}
|
||||
for (r <- table(i))
|
||||
|
@ -226,6 +244,14 @@ object SymplifyBit{
|
|||
}
|
||||
|
||||
verify(primes, trueTerms, falseTerms)
|
||||
for(prime <- primes){
|
||||
try{
|
||||
verify(primes.filterNot(_ == prime), trueTerms, falseTerms)
|
||||
assert(false)
|
||||
} catch {
|
||||
case _ : Throwable =>
|
||||
}
|
||||
}
|
||||
primes
|
||||
}
|
||||
|
||||
|
@ -235,16 +261,20 @@ object SymplifyBit{
|
|||
require(falseTerms.forall(falseTerm => !terms.exists(_ covers falseTerm)))
|
||||
}
|
||||
|
||||
//Return primes implicants for the trueTerms, default value is False
|
||||
def getPrimeImplicants(trueTerms: Seq[Masked],inputWidth : Int): Seq[Masked] = {
|
||||
// Return primes implicants for the trueTerms, default value is False.
|
||||
// You can insert don't care values by adding non-prime implicants in the trueTerms
|
||||
// Will simplify the trueTerms from the most constrained ones to the least constrained ones
|
||||
def getPrimeImplicantsByTrueAndDontCare(trueTerms: Seq[Masked],dontCareTerms: Seq[Masked], inputWidth : Int): Seq[Masked] = {
|
||||
val primes = ArrayBuffer[Masked]()
|
||||
trueTerms.foreach(_.isPrime = true)
|
||||
val trueTermByCareCount = (inputWidth to 0 by -1).map(b => trueTerms.filter(b == _.care.bitCount))
|
||||
val table = trueTermByCareCount.map(c => (0 to inputWidth).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount): _*)))
|
||||
dontCareTerms.foreach(_.isPrime = false)
|
||||
val termsByCareCount = (inputWidth to 0 by -1).map(b => (trueTerms ++ dontCareTerms).filter(b == _.care.bitCount))
|
||||
//table[Vector[HashSet[Masked]]](careCount)(bitSetCount)
|
||||
val table = termsByCareCount.map(c => (0 to inputWidth).map(b => collection.mutable.Set(c.filter(m => b == m.value.bitCount): _*)))
|
||||
for (i <- 0 to inputWidth) {
|
||||
for (j <- 0 until inputWidth - i){
|
||||
for(term <- table(i)(j)){
|
||||
table(i+1)(j) ++= table(i)(j+1).filter(_.similar(term)).map(_.merge(term))
|
||||
table(i+1)(j) ++= table(i)(j+1).withFilter(_.isSimilarOneBitDifSmaller(term)).map(_.mergeOneBitDifSmaller(term))
|
||||
}
|
||||
}
|
||||
for (r <- table(i))
|
||||
|
@ -255,13 +285,29 @@ object SymplifyBit{
|
|||
}
|
||||
|
||||
def main(args: Array[String]) {
|
||||
val default = Masked(0,0xF)
|
||||
val primeImplicants = List(4,8,10,11,12,15).map(v => Masked(v,0xF))
|
||||
val dcImplicants = List(9,14).map(v => Masked(v,0xF).setPrime(false))
|
||||
val reducedPrimeImplicants = getPrimeImplicants(primeImplicants ++ dcImplicants,4)
|
||||
println("UUT")
|
||||
println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n"))
|
||||
println("REF")
|
||||
println("-100\n10--\n1--0\n1-1-")
|
||||
{
|
||||
// val default = Masked(0, 0xF)
|
||||
// val primeImplicants = List(4, 8, 10, 11, 12, 15).map(v => Masked(v, 0xF))
|
||||
// val dcImplicants = List(9, 14).map(v => Masked(v, 0xF).setPrime(false))
|
||||
// val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4)
|
||||
// println("UUT")
|
||||
// println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n"))
|
||||
// println("REF")
|
||||
// println("-100\n10--\n1--0\n1-1-")
|
||||
}
|
||||
|
||||
{
|
||||
val primeImplicants = List(0).map(v => Masked(v, 0xF))
|
||||
val dcImplicants = (1 to 15).map(v => Masked(v, 0xF))
|
||||
val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4)
|
||||
println("UUT")
|
||||
println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n"))
|
||||
}
|
||||
// {
|
||||
// val trueTerms = List(0, 15).map(v => Masked(v, 0xF))
|
||||
// val falseTerms = List(3).map(v => Masked(v, 0xF))
|
||||
// val primes = getPrimeImplicants(trueTerms, falseTerms, 4)
|
||||
// println(primes.map(_.toString(4)).mkString("\n"))
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import spinal.core._
|
|||
import spinal.lib._
|
||||
|
||||
|
||||
class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : Boolean = false, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
|
||||
class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
|
||||
import config._
|
||||
|
||||
var iBus : InstructionCacheMemBus = null
|
||||
|
@ -39,7 +39,7 @@ class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : B
|
|||
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
|
||||
}
|
||||
|
||||
if(askMemoryTranslation)
|
||||
if(pipeline.serviceExist(classOf[MemoryTranslator]))
|
||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig)
|
||||
|
||||
if(pipeline.serviceExist(classOf[PrivilegeService]))
|
||||
|
|
|
@ -23,8 +23,7 @@ object PlayGen extends App{
|
|||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
preResetFlush = false
|
||||
),
|
||||
askMemoryTranslation = false
|
||||
)
|
||||
),
|
||||
new FormalPlugin,
|
||||
new HaltOnExceptionPlugin,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue