diff --git a/src/main/scala/uncore/tilelink2/AddressDecoder.scala b/src/main/scala/uncore/tilelink2/AddressDecoder.scala index adddc8a5..ea7cacac 100644 --- a/src/main/scala/uncore/tilelink2/AddressDecoder.scala +++ b/src/main/scala/uncore/tilelink2/AddressDecoder.scala @@ -28,11 +28,22 @@ object AddressDecoder require (!a.overlaps(b)) // it must be possible to disambiguate ports! } } } + val maxBits = log2Ceil(ports.map(_.map(_.max).max).max + 1) val bits = (0 until maxBits).map(BigInt(1) << _).toSeq val selected = recurse(Seq(ports.map(_.sorted).sorted(portOrder)), bits) - selected.reduceLeft(_ | _) - // port validation via mask expansion + val output = selected.reduceLeft(_ | _) + + // Modify the AddressSets to allow the new wider match functions + val widePorts = ports.map { _.map { _.widen(~output) } } + // Verify that it remains possible to disambiguate all ports + widePorts.combinations(2).foreach { case Seq(x, y) => + x.foreach { a => y.foreach { b => + require (!a.overlaps(b)) + } } + } + + output } // A simpler version that works for a Seq[Int] diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 6423db3c..7c49e792 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -98,6 +98,9 @@ case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet] // A strided slave serves discontiguous ranges def strided = alignment1 != mask + // Widen the match function to ignore all bits in imask + def widen(imask: BigInt) = AddressSet(base & ~imask, mask | imask) + // AddressSets have one natural Ordering (the containment order) def compare(x: AddressSet) = { val primary = (this.base - x.base).signum // smallest address first