213 lines
8.8 KiB
Scala
213 lines
8.8 KiB
Scala
// See LICENSE for license details.
|
|
|
|
package rocket
|
|
|
|
import Chisel._
|
|
import Node._
|
|
|
|
object DecodeLogic
|
|
{
|
|
def term(b: Bits) = {
|
|
val lit = b.litOf
|
|
if (lit.isZ) {
|
|
var (bits, mask, swidth) = Literal.parseLit(lit.toString)
|
|
new Term(BigInt(bits, 2), BigInt(2).pow(lit.getWidth)-(BigInt(mask, 2)+1))
|
|
} else {
|
|
new Term(lit.value)
|
|
}
|
|
}
|
|
def logic(addr: UInt, addrWidth: Int, cache: scala.collection.mutable.Map[Term,Bool], terms: Seq[Term]) = {
|
|
terms.map { t =>
|
|
cache.getOrElseUpdate(t, (if (t.mask == 0) addr else addr & Bits(BigInt(2).pow(addrWidth)-(t.mask+1), addrWidth)) === Bits(t.value, addrWidth))
|
|
}.foldLeft(Bool(false))(_||_)
|
|
}
|
|
def apply[T <: Bits](addr: UInt, default: T, mapping: Iterable[(UInt, T)]): T = {
|
|
val cache = caches.getOrElseUpdate(addr, collection.mutable.Map[Term,Bool]())
|
|
val dterm = term(default)
|
|
val (keys, values) = mapping.unzip
|
|
val addrWidth = keys.map(_.getWidth).max
|
|
val terms = keys.toList.map(k => term(k))
|
|
val termvalues = terms zip values.toList.map(term(_))
|
|
|
|
for (t <- keys.zip(terms).tails; if !t.isEmpty)
|
|
for (u <- t.tail)
|
|
assert(!t.head._2.intersects(u._2), "DecodeLogic: keys " + t.head + " and " + u + " overlap")
|
|
|
|
val result = (0 until default.litOf.getWidth.max(values.map(_.litOf.getWidth).max)).map({ case (i: Int) =>
|
|
val mint = termvalues.filter { case (k,t) => ((t.mask >> i) & 1) == 0 && ((t.value >> i) & 1) == 1 }.map(_._1)
|
|
val maxt = termvalues.filter { case (k,t) => ((t.mask >> i) & 1) == 0 && ((t.value >> i) & 1) == 0 }.map(_._1)
|
|
val dc = termvalues.filter { case (k,t) => ((t.mask >> i) & 1) == 1 }.map(_._1)
|
|
|
|
if (((dterm.mask >> i) & 1) != 0) {
|
|
logic(addr, addrWidth, cache, SimplifyDC(mint, maxt, addrWidth)).toBits
|
|
} else {
|
|
val defbit = (dterm.value.toInt >> i) & 1
|
|
val t = if (defbit == 0) mint else maxt
|
|
val bit = logic(addr, addrWidth, cache, Simplify(t, dc, addrWidth)).toBits
|
|
if (defbit == 0) bit else ~bit
|
|
}
|
|
}).reverse.reduceRight(Cat(_,_))
|
|
default.fromBits(result)
|
|
}
|
|
def apply[T <: Bits](addr: UInt, default: Iterable[T], mappingIn: Iterable[(UInt, Iterable[T])]): Iterable[T] = {
|
|
val mapping = collection.mutable.ArrayBuffer.fill(default.size)(collection.mutable.ArrayBuffer[(UInt, T)]())
|
|
for ((key, values) <- mappingIn)
|
|
for ((value, i) <- values zipWithIndex)
|
|
mapping(i) += key -> value
|
|
for ((thisDefault, thisMapping) <- default zip mapping)
|
|
yield apply(addr, thisDefault, thisMapping)
|
|
}
|
|
def apply(addr: UInt, trues: Iterable[UInt], falses: Iterable[UInt]): Bool =
|
|
apply(addr, Bool.DC, trues.map(_ -> Bool(true)) ++ falses.map(_ -> Bool(false)))
|
|
def apply(addr: UInt, tru: UInt, fals: UInt): Bool =
|
|
apply(addr, Seq(tru), Seq(fals))
|
|
private val caches = collection.mutable.Map[UInt,collection.mutable.Map[Term,Bool]]()
|
|
}
|
|
|
|
class Term(val value: BigInt, val mask: BigInt = 0)
|
|
{
|
|
var prime = true
|
|
|
|
def covers(x: Term) = ((value ^ x.value) &~ mask | x.mask &~ mask) == 0
|
|
def intersects(x: Term) = ((value ^ x.value) &~ mask &~ x.mask) == 0
|
|
override def equals(that: Any) = that match {
|
|
case x: Term => x.value == value && x.mask == mask
|
|
case _ => false
|
|
}
|
|
override def hashCode = value.toInt
|
|
def < (that: Term) = value < that.value || value == that.value && mask < that.mask
|
|
def similar(x: Term) = {
|
|
val diff = value - x.value
|
|
mask == x.mask && value > x.value && (diff & diff-1) == 0
|
|
}
|
|
def merge(x: Term) = {
|
|
prime = false
|
|
x.prime = false
|
|
val bit = value - x.value
|
|
new Term(value &~ bit, mask | bit)
|
|
}
|
|
|
|
override def toString = value.toString(16) + "-" + mask.toString(16) + (if (prime) "p" else "")
|
|
}
|
|
|
|
object Simplify
|
|
{
|
|
def getPrimeImplicants(implicants: Seq[Term], bits: Int) = {
|
|
var prime = List[Term]()
|
|
implicants.foreach(_.prime = true)
|
|
val cols = (0 to bits).map(b => implicants.filter(b == _.mask.bitCount))
|
|
val table = cols.map(c => (0 to bits).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount):_*)))
|
|
for (i <- 0 to bits) {
|
|
for (j <- 0 until bits-i)
|
|
table(i)(j).foreach(a => table(i+1)(j) ++= table(i)(j+1).filter(_.similar(a)).map(_.merge(a)))
|
|
for (r <- table(i))
|
|
for (p <- r; if p.prime)
|
|
prime = p :: prime
|
|
}
|
|
prime.sortWith(_<_)
|
|
}
|
|
def getEssentialPrimeImplicants(prime: Seq[Term], minterms: Seq[Term]): (Seq[Term],Seq[Term],Seq[Term]) = {
|
|
for (i <- 0 until prime.size) {
|
|
val icover = minterms.filter(prime(i) covers _)
|
|
for (j <- 0 until prime.size) {
|
|
val jcover = minterms.filter(prime(j) covers _)
|
|
if (icover.size > jcover.size && jcover.forall(prime(i) covers _))
|
|
return getEssentialPrimeImplicants(prime.filter(_ != prime(j)), minterms)
|
|
}
|
|
}
|
|
|
|
val essentiallyCovered = minterms.filter(t => prime.count(_ covers t) == 1)
|
|
val essential = prime.filter(p => essentiallyCovered.exists(p covers _))
|
|
val nonessential = prime.filterNot(essential contains _)
|
|
val uncovered = minterms.filterNot(t => essential.exists(_ covers t))
|
|
if (essential.isEmpty || uncovered.isEmpty)
|
|
(essential, nonessential, uncovered)
|
|
else {
|
|
val (a, b, c) = getEssentialPrimeImplicants(nonessential, uncovered)
|
|
(essential ++ a, b, c)
|
|
}
|
|
}
|
|
def getCost(cover: Seq[Term], bits: Int) = cover.map(bits - _.mask.bitCount).sum
|
|
def cheaper(a: List[Term], b: List[Term], bits: Int) = {
|
|
val ca = getCost(a, bits)
|
|
val cb = getCost(b, bits)
|
|
def listLess(a: List[Term], b: List[Term]): Boolean = !b.isEmpty && (a.isEmpty || a.head < b.head || a.head == b.head && listLess(a.tail, b.tail))
|
|
ca < cb || ca == cb && listLess(a.sortWith(_<_), b.sortWith(_<_))
|
|
}
|
|
def getCover(implicants: Seq[Term], minterms: Seq[Term], bits: Int) = {
|
|
if (minterms.nonEmpty) {
|
|
val cover = minterms.map(m => implicants.filter(_.covers(m)).map(i => collection.mutable.Set(i)))
|
|
val all = cover.reduceLeft((c0, c1) => c0.map(a => c1.map(_ ++ a)).reduceLeft(_++_))
|
|
all.map(_.toList).reduceLeft((a, b) => if (cheaper(a, b, bits)) a else b)
|
|
} else
|
|
Seq[Term]()
|
|
}
|
|
def stringify(s: Seq[Term], bits: Int) = s.map(t => (0 until bits).map(i => if ((t.mask & (1 << i)) != 0) "x" else ((t.value >> i) & 1).toString).reduceLeft(_+_).reverse).reduceLeft(_+" + "+_)
|
|
|
|
def apply(minterms: Seq[Term], dontcares: Seq[Term], bits: Int) = {
|
|
val prime = getPrimeImplicants(minterms ++ dontcares, bits)
|
|
minterms.foreach(t => assert(prime.exists(_.covers(t))))
|
|
val (eprime, prime2, uncovered) = getEssentialPrimeImplicants(prime, minterms)
|
|
val cover = eprime ++ getCover(prime2, uncovered, bits)
|
|
minterms.foreach(t => assert(cover.exists(_.covers(t)))) // sanity check
|
|
cover
|
|
}
|
|
}
|
|
|
|
object SimplifyDC
|
|
{
|
|
def getImplicitDC(maxterms: Seq[Term], term: Term, bits: Int, above: Boolean): Term = {
|
|
for (i <- 0 until bits) {
|
|
var t: Term = null
|
|
if (above && ((term.value | term.mask) & (BigInt(1) << i)) == 0)
|
|
t = new Term(term.value | (BigInt(1) << i), term.mask)
|
|
else if (!above && (term.value & (BigInt(1) << i)) != 0)
|
|
t = new Term(term.value & ~(BigInt(1) << i), term.mask)
|
|
if (t != null && !maxterms.exists(_.intersects(t)))
|
|
return t
|
|
}
|
|
null
|
|
}
|
|
def getPrimeImplicants(minterms: Seq[Term], maxterms: Seq[Term], bits: Int) = {
|
|
var prime = List[Term]()
|
|
minterms.foreach(_.prime = true)
|
|
var mint = minterms.map(t => new Term(t.value, t.mask))
|
|
val cols = (0 to bits).map(b => mint.filter(b == _.mask.bitCount))
|
|
val table = cols.map(c => (0 to bits).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount):_*)))
|
|
|
|
for (i <- 0 to bits) {
|
|
for (j <- 0 until bits-i) {
|
|
table(i)(j).foreach(a => table(i+1)(j) ++= table(i)(j+1).filter(_ similar a).map(_ merge a))
|
|
}
|
|
for (j <- 0 until bits-i) {
|
|
for (a <- table(i)(j).filter(_.prime)) {
|
|
val dc = getImplicitDC(maxterms, a, bits, true)
|
|
if (dc != null)
|
|
table(i+1)(j) += dc merge a
|
|
}
|
|
for (a <- table(i)(j+1).filter(_.prime)) {
|
|
val dc = getImplicitDC(maxterms, a, bits, false)
|
|
if (dc != null)
|
|
table(i+1)(j) += a merge dc
|
|
}
|
|
}
|
|
for (r <- table(i))
|
|
for (p <- r; if p.prime)
|
|
prime = p :: prime
|
|
}
|
|
prime.sortWith(_<_)
|
|
}
|
|
|
|
def verify(cover: Seq[Term], minterms: Seq[Term], maxterms: Seq[Term]) = {
|
|
assert(minterms.forall(t => cover.exists(_ covers t)))
|
|
assert(maxterms.forall(t => !cover.exists(_ intersects t)))
|
|
}
|
|
def apply(minterms: Seq[Term], maxterms: Seq[Term], bits: Int) = {
|
|
val prime = getPrimeImplicants(minterms, maxterms, bits)
|
|
val (eprime, prime2, uncovered) = Simplify.getEssentialPrimeImplicants(prime, minterms)
|
|
val cover = eprime ++ Simplify.getCover(prime2, uncovered, bits)
|
|
verify(cover, minterms, maxterms)
|
|
cover
|
|
}
|
|
}
|