1
0
Fork 0

tilelink2: AddressSet always has an assigned base address

The consensus seems to be that TileLink should not be assigning
addresses dynamically. The reasons:

1. We can come up with another scheme for assigning addresses that is
   independent of TileLink.  This decoupling is good, because it would
   allow us to use the same mechanism for different buses in the SoC.

2. The informational flow of addresses is more likely to naturally follow
   the module hierarchy than the TileLike bus topology. Thus, it seems
   better to pass address parameterization using Module constructors.

3. Addresses are still checked by TileLink, so using a Module-centric
   flow for addresses will not pose a correctness concern.

4. An address need only be provided to a slave on its construction and
   TileLink parameterization spreads this globally. Thus, the burden to
   manually assign an address is low.
This commit is contained in:
Wesley W. Terpstra 2016-08-31 14:49:18 -07:00
parent ae2bc4da21
commit 9cd2991fb3
3 changed files with 15 additions and 17 deletions

View File

@ -4,7 +4,7 @@ package uncore.tilelink2
import Chisel._
case class GPIOParams(num: Int, address: Option[BigInt] = None)
case class GPIOParams(num: Int, address: BigInt)
trait GPIOBundle
{

View File

@ -75,30 +75,28 @@ object TransferSizes {
implicit def asBool(x: TransferSizes) = !x.none
}
// AddressSets specify the mask of bits consumed by the manager
// The base address used by the crossbar for routing
case class AddressSet(mask: BigInt, base: Option[BigInt] = None)
// AddressSets specify the address space managed by the manager
// Base is the base address, and mask are the bits consumed by the manager
// e.g: base=0x200, mask=0xff describes a device managing 0x200-0x2ff
// e.g: base=0x1000, mask=0xf0f decribes a device managing 0x1000-0x100f, 0x1100-0x110f, ...
case class AddressSet(base: BigInt, mask: BigInt)
{
// Forbid misaligned base address (and empty sets)
require (base == None || (base.get & mask) == 0)
require ((base & mask) == 0)
def contains(x: BigInt) = ((x ^ base.get) & ~mask) == 0
def contains(x: UInt) = ((x ^ UInt(base.get)) & ~UInt(mask)) === UInt(0)
def contains(x: BigInt) = ((x ^ base) & ~mask) == 0
def contains(x: UInt) = ((x ^ UInt(base)) & ~UInt(mask)) === UInt(0)
// overlap iff bitwise: both care (~mask0 & ~mask1) => both equal (base0=base1)
// if base = None, it will be auto-assigned and thus not overlap anything
def overlaps(x: AddressSet) = (base, x.base) match {
case (Some(tbase), Some(xbase)) => (~(mask | x.mask) & (tbase ^ xbase)) == 0
case _ => false
}
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.get ^ x.base.get)) & ~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.get | mask
def max = base | mask
// A strided slave has serves discontiguous ranges
// A strided slave serves discontiguous ranges
def strided = alignment1 != mask
}

View File

@ -74,10 +74,10 @@ class TLRegModule[P, B <: Bundle](val params: P, bundleBuilder: => B, router: TL
}
class TLRegisterRouter[B <: Bundle, M <: LazyModuleImp]
(address: Option[BigInt] = None, size: BigInt = 4096, concurrency: Option[Int] = None, beatBytes: Int = 4)
(base: BigInt, size: BigInt = 4096, concurrency: Option[Int] = None, beatBytes: Int = 4)
(bundleBuilder: Vec[TLBundle] => B)
(moduleBuilder: (=> B, TLRegisterRouterBase) => M)
extends TLRegisterRouterBase(AddressSet(size-1, address), concurrency, beatBytes)
extends TLRegisterRouterBase(AddressSet(base, size-1), concurrency, beatBytes)
{
require (size % 4096 == 0) // devices should be 4K aligned
require (isPow2(size))