diplomacy: add AddressRange conversion to/from AddressSet
This commit is contained in:
parent
bb70b1a3c3
commit
c01a74f4a0
@ -76,6 +76,32 @@ object TransferSizes {
|
|||||||
implicit def asBool(x: TransferSizes) = !x.none
|
implicit def asBool(x: TransferSizes) = !x.none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use AddressSet instead -- this is just for pretty printing
|
||||||
|
case class AddressRange(base: BigInt, size: BigInt) extends Ordered[AddressRange]
|
||||||
|
{
|
||||||
|
val end = base + size
|
||||||
|
|
||||||
|
require (base >= 0)
|
||||||
|
require (size > 0)
|
||||||
|
|
||||||
|
def compare(x: AddressRange) = {
|
||||||
|
val primary = (this.base - x.base).signum
|
||||||
|
val secondary = (x.size - this.size).signum
|
||||||
|
if (primary != 0) primary else secondary
|
||||||
|
}
|
||||||
|
|
||||||
|
def contains(x: AddressRange) = base <= x.base && x.end <= end
|
||||||
|
def union(x: AddressRange): Option[AddressRange] = {
|
||||||
|
if (base > x.end || x.base > end) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
val obase = if (base < x.base) base else x.base
|
||||||
|
val oend = if (end > x.end) end else x.end
|
||||||
|
Some(AddressRange(obase, oend-obase))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AddressSets specify the address space managed by the manager
|
// AddressSets specify the address space managed by the manager
|
||||||
// Base is the base address, and mask are the bits consumed by the manager
|
// Base is the base address, and mask are the bits consumed by the manager
|
||||||
// e.g: base=0x200, mask=0xff describes a device managing 0x200-0x2ff
|
// e.g: base=0x200, mask=0xff describes a device managing 0x200-0x2ff
|
||||||
@ -132,6 +158,32 @@ case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet]
|
|||||||
"AddressSet(0x%x, ~0x%x)".format(base, ~mask)
|
"AddressSet(0x%x, ~0x%x)".format(base, ~mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def toRanges = {
|
||||||
|
require (finite)
|
||||||
|
val size = alignment
|
||||||
|
val fragments = mask & ~(size-1)
|
||||||
|
val bits = bitIndexes(fragments)
|
||||||
|
(BigInt(0) until (BigInt(1) << bits.size)).map { i =>
|
||||||
|
val off = bitIndexes(i).foldLeft(base) { case (a, b) => a.setBit(bits(b)) }
|
||||||
|
AddressRange(off, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object AddressRange
|
||||||
|
{
|
||||||
|
def fromSets(seq: Seq[AddressSet]): Seq[AddressRange] = unify(seq.flatMap(_.toRanges))
|
||||||
|
def unify(seq: Seq[AddressRange]): Seq[AddressRange] = {
|
||||||
|
if (seq.isEmpty) return Nil
|
||||||
|
val ranges = seq.sorted
|
||||||
|
ranges.tail.foldLeft(Seq(ranges.head)) { case (head :: tail, x) =>
|
||||||
|
head.union(x) match {
|
||||||
|
case Some(z) => z :: tail
|
||||||
|
case None => x :: head :: tail
|
||||||
|
}
|
||||||
|
}.reverse
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object AddressSet
|
object AddressSet
|
||||||
|
@ -9,4 +9,14 @@ package object diplomacy
|
|||||||
case SourceLine(filename, line, col) => s"$prefix$filename:$line:$col$suffix"
|
case SourceLine(filename, line, col) => s"$prefix$filename:$line:$col$suffix"
|
||||||
case _ => ""
|
case _ => ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def bitIndexes(x: BigInt, tail: Seq[Int] = Nil): Seq[Int] = {
|
||||||
|
require (x >= 0)
|
||||||
|
if (x == 0) {
|
||||||
|
tail.reverse
|
||||||
|
} else {
|
||||||
|
val lowest = x.lowestSetBit
|
||||||
|
bitIndexes(x.clearBit(lowest), lowest +: tail)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user