diplomacy: add AddressRange conversion to/from AddressSet
This commit is contained in:
		@@ -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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user