diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 61bdad72..af8343cb 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -82,26 +82,31 @@ case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet] { // Forbid misaligned base address (and empty sets) require ((base & mask) == 0) + require (base >= 0) // TL2 address widths are not fixed => negative is ambiguous + // We do allow negative mask (=> ignore all high bits) - def contains(x: BigInt) = ~(~(x ^ base) | mask) == 0 - def contains(x: UInt) = ~(~(x ^ UInt(base)) | UInt(mask)) === UInt(0) + def contains(x: BigInt) = ((x ^ base) & ~mask) == 0 + def contains(x: UInt) = ((x ^ UInt(base)).zext() & SInt(~mask)) === SInt(0) // overlap iff bitwise: both care (~mask0 & ~mask1) => both equal (base0=base1) def overlaps(x: AddressSet) = (~(mask | x.mask) & (base ^ x.base)) == 0 - // contains iff bitwise: x.mask => mask && contains(x.base) def contains(x: AddressSet) = ((x.mask | (base ^ x.base)) & ~mask) == 0 - // 1 less than the number of bytes to which the manager should be aligned - def alignment1 = ((mask + 1) & ~mask) - 1 - def max = base | mask - // A strided slave serves discontiguous ranges - def strided = alignment1 != mask + // The number of bytes to which the manager must be aligned + def alignment = ((mask + 1) & ~mask) + + // Is this a contiguous memory range + def contiguous = alignment == mask+1 + def strided = alignment != mask+1 + + def finite = mask >= 0 + def max = { require (finite); base | 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) + // AddressSets have one natural Ordering (the containment order, if contiguous) def compare(x: AddressSet) = { val primary = (this.base - x.base).signum // smallest address first val secondary = (x.mask - this.mask).signum // largest mask first @@ -109,7 +114,13 @@ case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet] } // We always want to see things in hex - override def toString() = "AddressSet(0x%x, 0x%x)".format(base, mask) + override def toString() = { + if (mask >= 0) { + "AddressSet(0x%x, 0x%x)".format(base, mask) + } else { + "AddressSet(0x%x, ~0x%x)".format(base, ~mask) + } + } } case class TLManagerParameters( @@ -130,6 +141,7 @@ case class TLManagerParameters( fifoId: Option[Int] = None, customDTS: Option[String]= None) { + address.foreach { a => require (a.finite) } address.combinations(2).foreach({ case Seq(x,y) => require (!x.overlaps(y)) }) @@ -144,8 +156,9 @@ case class TLManagerParameters( supportsPutFull.max, supportsPutPartial.max).max + val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") + // Generate the config string (in future device tree) - lazy val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") lazy val dts = customDTS.getOrElse { val header = s"${name} {\n" val middle = address.map { a => @@ -158,7 +171,7 @@ case class TLManagerParameters( // The device had better not support a transfer larger than it's alignment address.foreach({ case a => - require (a.alignment1 >= maxTransfer-1) + require (a.alignment >= maxTransfer) }) } @@ -256,6 +269,8 @@ case class TLClientParameters( supportsGet.max, supportsPutFull.max, supportsPutPartial.max).max + + val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") } case class TLClientPortParameters(clients: Seq[TLClientParameters]) {