1
0

diplomacy: optimize IdRange.contains (#798)

This should make an optimal circuit for a wider class of ranges.
This commit is contained in:
Wesley W. Terpstra 2017-06-15 15:56:14 -07:00 committed by GitHub
parent d316aeb275
commit 93d423d202

View File

@ -33,10 +33,20 @@ case class IdRange(start: Int, end: Int) extends Ordered[IdRange]
def contains(x: Int) = start <= x && x < end def contains(x: Int) = start <= x && x < end
def contains(x: UInt) = def contains(x: UInt) =
if (start+1 == end) { UInt(start) === x } if (size == 1) { // simple comparison
else if (isPow2(end-start) && ((end | start) & (end-start-1)) == 0) x === UInt(start)
{ ~(~(UInt(start) ^ x) | UInt(end-start-1)) === UInt(0) } } else {
else { UInt(start) <= x && x < UInt(end) } // find index of largest different bit
val largestDeltaBit = log2Floor(start ^ (end-1))
val smallestCommonBit = largestDeltaBit + 1 // may not exist in x
val uncommonMask = (1 << smallestCommonBit) - 1
val uncommonBits = (x | UInt(0, width=smallestCommonBit))(largestDeltaBit, 0)
// the prefix must match exactly (note: may shift ALL bits away)
(x >> smallestCommonBit) === UInt(start >> smallestCommonBit) &&
// firrtl constant prop range analysis can eliminate these two:
UInt(start & uncommonMask) <= uncommonBits &&
uncommonBits <= UInt((end-1) & uncommonMask)
}
def shift(x: Int) = IdRange(start+x, end+x) def shift(x: Int) = IdRange(start+x, end+x)
def size = end - start def size = end - start