tilelink2: consider the implications of negative address mask
This commit is contained in:
parent
e437508548
commit
fa0f119f3c
@ -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]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user