1
0

diplomacy: support given bits in AddressDecoder

This commit is contained in:
Wesley W. Terpstra 2017-01-22 00:58:55 -08:00 committed by Henry Cook
parent c0b6d31377
commit d4b3a0f0be

View File

@ -19,7 +19,7 @@ object AddressDecoder
// Find the minimum subset of bits needed to disambiguate port addresses. // Find the minimum subset of bits needed to disambiguate port addresses.
// ie: inspecting only the bits in the output, you can look at an address // ie: inspecting only the bits in the output, you can look at an address
// and decide to which port (outer Seq) the address belongs. // and decide to which port (outer Seq) the address belongs.
def apply(ports: Ports): BigInt = if (ports.size <= 1) 0 else { def apply(ports: Ports, givenBits: BigInt = BigInt(0)): BigInt = if (ports.size <= 1) givenBits else {
// Every port must have at least one address! // Every port must have at least one address!
ports.foreach { p => require (!p.isEmpty) } ports.foreach { p => require (!p.isEmpty) }
// Verify the user did not give us an impossible problem // Verify the user did not give us an impossible problem
@ -30,9 +30,11 @@ object AddressDecoder
} }
val maxBits = log2Ceil(ports.map(_.map(_.max).max).max + 1) val maxBits = log2Ceil(ports.map(_.map(_.max).max).max + 1)
val bits = (0 until maxBits).map(BigInt(1) << _).toSeq val (bitsToTry, bitsToTake) = (0 until maxBits).map(BigInt(1) << _).partition(b => (givenBits & b) == 0)
val selected = recurse(Seq(ports.map(_.sorted).sorted(portOrder)), bits) val partitions = Seq(ports.map(_.sorted).sorted(portOrder))
val output = selected.reduceLeft(_ | _) val givenPartitions = bitsToTake.foldLeft(partitions) { (p, b) => partitionPartitions(p, b) }
val selected = recurse(givenPartitions, bitsToTry.toSeq)
val output = selected.reduceLeft(_ | _) | givenBits
// Modify the AddressSets to allow the new wider match functions // Modify the AddressSets to allow the new wider match functions
val widePorts = ports.map { _.map { _.widen(~output) } } val widePorts = ports.map { _.map { _.widen(~output) } }
@ -103,28 +105,25 @@ object AddressDecoder
// requirement: ports have sorted addresses and are sorted lexicographically // requirement: ports have sorted addresses and are sorted lexicographically
val debug = false val debug = false
def recurse(partitions: Partitions, bits: Seq[BigInt]): Seq[BigInt] = { def recurse(partitions: Partitions, bits: Seq[BigInt]): Seq[BigInt] = {
if (debug) { if (partitions.map(_.size <= 1).reduce(_ && _)) Seq() else {
println("Partitioning:") if (debug) {
partitions.foreach { partition => println("Partitioning:")
println(" Partition:") partitions.foreach { partition =>
partition.foreach { port => println(" Partition:")
print(" ") partition.foreach { port =>
port.foreach { a => print(s" ${a}") } print(" ")
println("") port.foreach { a => print(s" ${a}") }
println("")
}
} }
} }
} val candidates = bits.map { bit =>
val candidates = bits.map { bit => val result = partitionPartitions(partitions, bit)
val result = partitionPartitions(partitions, bit) val score = bitScore(result)
val score = bitScore(result) (score, bit, result)
(score, bit, result) }
} val (bestScore, bestBit, bestPartitions) = candidates.min(Ordering.by[(Seq[Int], BigInt, Partitions), Iterable[Int]](_._1.toIterable))
val (bestScore, bestBit, bestPartitions) = candidates.min(Ordering.by[(Seq[Int], BigInt, Partitions), Iterable[Int]](_._1.toIterable)) if (debug) println("=> Selected bit 0x%x".format(bestBit))
if (debug) println("=> Selected bit 0x%x".format(bestBit))
if (bestScore(0) <= 1) {
if (debug) println("---")
Seq(bestBit)
} else {
bestBit +: recurse(bestPartitions, bits.filter(_ != bestBit)) bestBit +: recurse(bestPartitions, bits.filter(_ != bestBit))
} }
} }