tilelink2: consider the implications of negative address mask
This commit is contained in:
		@@ -82,26 +82,31 @@ case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet]
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  // Forbid misaligned base address (and empty sets)
 | 
					  // Forbid misaligned base address (and empty sets)
 | 
				
			||||||
  require ((base & mask) == 0)
 | 
					  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: BigInt) = ((x ^ base) & ~mask) == 0
 | 
				
			||||||
  def contains(x: UInt) = ~(~(x ^ UInt(base)) | UInt(mask)) === UInt(0)
 | 
					  def contains(x: UInt) = ((x ^ UInt(base)).zext() & SInt(~mask)) === SInt(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // overlap iff bitwise: both care (~mask0 & ~mask1) => both equal (base0=base1)
 | 
					  // overlap iff bitwise: both care (~mask0 & ~mask1) => both equal (base0=base1)
 | 
				
			||||||
  def overlaps(x: AddressSet) = (~(mask | x.mask) & (base ^ x.base)) == 0
 | 
					  def overlaps(x: AddressSet) = (~(mask | x.mask) & (base ^ x.base)) == 0
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // contains iff bitwise: x.mask => mask && contains(x.base)
 | 
					  // contains iff bitwise: x.mask => mask && contains(x.base)
 | 
				
			||||||
  def contains(x: AddressSet) = ((x.mask | (base ^ x.base)) & ~mask) == 0
 | 
					  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
 | 
					  // The number of bytes to which the manager must be aligned
 | 
				
			||||||
  def strided = alignment1 != mask
 | 
					  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
 | 
					  // Widen the match function to ignore all bits in imask
 | 
				
			||||||
  def widen(imask: BigInt) = AddressSet(base & ~imask, mask | 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) = {
 | 
					  def compare(x: AddressSet) = {
 | 
				
			||||||
    val primary   = (this.base - x.base).signum // smallest address first
 | 
					    val primary   = (this.base - x.base).signum // smallest address first
 | 
				
			||||||
    val secondary = (x.mask - this.mask).signum // largest mask 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
 | 
					  // 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(
 | 
					case class TLManagerParameters(
 | 
				
			||||||
@@ -130,6 +141,7 @@ case class TLManagerParameters(
 | 
				
			|||||||
  fifoId:             Option[Int]   = None,
 | 
					  fifoId:             Option[Int]   = None,
 | 
				
			||||||
  customDTS:          Option[String]= None)
 | 
					  customDTS:          Option[String]= None)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  address.foreach { a => require (a.finite) }
 | 
				
			||||||
  address.combinations(2).foreach({ case Seq(x,y) =>
 | 
					  address.combinations(2).foreach({ case Seq(x,y) =>
 | 
				
			||||||
    require (!x.overlaps(y))
 | 
					    require (!x.overlaps(y))
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@@ -144,8 +156,9 @@ case class TLManagerParameters(
 | 
				
			|||||||
    supportsPutFull.max,
 | 
					    supportsPutFull.max,
 | 
				
			||||||
    supportsPutPartial.max).max
 | 
					    supportsPutPartial.max).max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Generate the config string (in future device tree)
 | 
					  // Generate the config string (in future device tree)
 | 
				
			||||||
  lazy val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
 | 
					 | 
				
			||||||
  lazy val dts = customDTS.getOrElse {
 | 
					  lazy val dts = customDTS.getOrElse {
 | 
				
			||||||
    val header = s"${name} {\n"
 | 
					    val header = s"${name} {\n"
 | 
				
			||||||
    val middle = address.map { a =>
 | 
					    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
 | 
					  // The device had better not support a transfer larger than it's alignment
 | 
				
			||||||
  address.foreach({ case a =>
 | 
					  address.foreach({ case a =>
 | 
				
			||||||
    require (a.alignment1 >= maxTransfer-1)
 | 
					    require (a.alignment >= maxTransfer)
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -256,6 +269,8 @@ case class TLClientParameters(
 | 
				
			|||||||
    supportsGet.max,
 | 
					    supportsGet.max,
 | 
				
			||||||
    supportsPutFull.max,
 | 
					    supportsPutFull.max,
 | 
				
			||||||
    supportsPutPartial.max).max
 | 
					    supportsPutPartial.max).max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
case class TLClientPortParameters(clients: Seq[TLClientParameters]) {
 | 
					case class TLClientPortParameters(clients: Seq[TLClientParameters]) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user