2016-08-19 20:08:35 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
package uncore.tilelink2
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import scala.math.max
|
|
|
|
|
|
|
|
/** Options for memory regions */
|
|
|
|
object RegionType {
|
|
|
|
sealed trait T
|
|
|
|
case object CACHED extends T
|
|
|
|
case object TRACKED extends T
|
|
|
|
case object UNCACHED extends T
|
2016-08-25 01:07:45 +02:00
|
|
|
case object PUT_EFFECTS extends T
|
|
|
|
case object GET_EFFECTS extends T // GET_EFFECTS => PUT_EFFECTS
|
|
|
|
val cases = Seq(CACHED, TRACKED, UNCACHED, PUT_EFFECTS, GET_EFFECTS)
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// A non-empty half-open range; [start, end)
|
|
|
|
case class IdRange(start: Int, end: Int)
|
|
|
|
{
|
|
|
|
require (start >= 0)
|
|
|
|
require (start < end) // not empty
|
|
|
|
|
|
|
|
// This is a strict partial ordering
|
|
|
|
def <(x: IdRange) = end <= x.start
|
|
|
|
def >(x: IdRange) = x < this
|
|
|
|
|
|
|
|
def overlaps(x: IdRange) = start < x.end && x.start < end
|
|
|
|
def contains(x: IdRange) = start <= x.start && x.end <= end
|
|
|
|
// contains => overlaps (because empty is forbidden)
|
|
|
|
|
|
|
|
def contains(x: Int) = start <= x && x < end
|
2016-08-24 01:23:35 +02:00
|
|
|
def contains(x: UInt) =
|
|
|
|
if (start+1 == end) { UInt(start) === x }
|
2016-09-05 02:48:45 +02:00
|
|
|
else if (isPow2(end-start) && ((end | start) & (end-start-1)) == 0)
|
|
|
|
{ ~(~(UInt(start) ^ x) | UInt(end-start-1)) === UInt(0) }
|
2016-08-24 01:23:35 +02:00
|
|
|
else { UInt(start) <= x && x < UInt(end) }
|
2016-08-19 20:08:35 +02:00
|
|
|
|
|
|
|
def shift(x: Int) = IdRange(start+x, end+x)
|
2016-08-24 22:50:32 +02:00
|
|
|
def size = end - start
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
2016-08-20 05:28:58 +02:00
|
|
|
// An potentially empty inclusive range of 2-powers [min, max] (in bytes)
|
2016-08-19 20:08:35 +02:00
|
|
|
case class TransferSizes(min: Int, max: Int)
|
|
|
|
{
|
|
|
|
def this(x: Int) = this(x, x)
|
|
|
|
|
|
|
|
require (min <= max)
|
2016-09-01 20:12:59 +02:00
|
|
|
require (min >= 0 && max >= 0)
|
2016-08-19 20:08:35 +02:00
|
|
|
require (max == 0 || isPow2(max))
|
|
|
|
require (min == 0 || isPow2(min))
|
2016-09-06 07:10:28 +02:00
|
|
|
require (max == 0 || min != 0) // 0 is forbidden unless (0,0)
|
2016-08-19 20:08:35 +02:00
|
|
|
|
|
|
|
def none = min == 0
|
|
|
|
def contains(x: Int) = isPow2(x) && min <= x && x <= max
|
|
|
|
def containsLg(x: Int) = contains(1 << x)
|
2016-08-24 01:23:35 +02:00
|
|
|
def containsLg(x: UInt) =
|
|
|
|
if (none) Bool(false)
|
|
|
|
else if (min == max) { UInt(log2Ceil(min)) === x }
|
|
|
|
else { UInt(log2Ceil(min)) <= x && x <= UInt(log2Ceil(max)) }
|
2016-08-19 20:08:35 +02:00
|
|
|
|
|
|
|
def contains(x: TransferSizes) = x.none || (min <= x.min && x.max <= max)
|
|
|
|
|
|
|
|
def intersect(x: TransferSizes) =
|
2016-09-15 03:08:49 +02:00
|
|
|
if (x.max < min || max < x.min) TransferSizes.none
|
2016-08-19 20:08:35 +02:00
|
|
|
else TransferSizes(scala.math.max(min, x.min), scala.math.min(max, x.max))
|
|
|
|
}
|
|
|
|
|
|
|
|
object TransferSizes {
|
|
|
|
def apply(x: Int) = new TransferSizes(x)
|
|
|
|
val none = new TransferSizes(0)
|
2016-08-19 22:47:18 +02:00
|
|
|
|
|
|
|
implicit def asBool(x: TransferSizes) = !x.none
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
2016-08-31 23:49:18 +02:00
|
|
|
// 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, ...
|
2016-09-15 23:47:44 +02:00
|
|
|
case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet]
|
2016-08-19 20:08:35 +02:00
|
|
|
{
|
2016-08-26 23:13:54 +02:00
|
|
|
// Forbid misaligned base address (and empty sets)
|
2016-08-31 23:49:18 +02:00
|
|
|
require ((base & mask) == 0)
|
2016-08-19 20:08:35 +02:00
|
|
|
|
2016-09-05 02:48:45 +02:00
|
|
|
def contains(x: BigInt) = ~(~(x ^ base) | mask) == 0
|
|
|
|
def contains(x: UInt) = ~(~(x ^ UInt(base)) | UInt(mask)) === UInt(0)
|
2016-08-19 20:08:35 +02:00
|
|
|
|
|
|
|
// overlap iff bitwise: both care (~mask0 & ~mask1) => both equal (base0=base1)
|
2016-08-31 23:49:18 +02:00
|
|
|
def overlaps(x: AddressSet) = (~(mask | x.mask) & (base ^ x.base)) == 0
|
2016-08-19 20:08:35 +02:00
|
|
|
|
|
|
|
// contains iff bitwise: x.mask => mask && contains(x.base)
|
2016-08-31 23:49:18 +02:00
|
|
|
def contains(x: AddressSet) = ((x.mask | (base ^ x.base)) & ~mask) == 0
|
2016-08-19 20:08:35 +02:00
|
|
|
// 1 less than the number of bytes to which the manager should be aligned
|
|
|
|
def alignment1 = ((mask + 1) & ~mask) - 1
|
2016-08-31 23:49:18 +02:00
|
|
|
def max = base | mask
|
2016-08-26 23:13:54 +02:00
|
|
|
|
2016-08-31 23:49:18 +02:00
|
|
|
// A strided slave serves discontiguous ranges
|
2016-08-26 23:13:54 +02:00
|
|
|
def strided = alignment1 != mask
|
2016-09-15 23:47:44 +02:00
|
|
|
|
2016-09-16 09:49:05 +02:00
|
|
|
// Widen the match function to ignore all bits in imask
|
|
|
|
def widen(imask: BigInt) = AddressSet(base & ~imask, mask | imask)
|
|
|
|
|
2016-09-15 23:47:44 +02:00
|
|
|
// AddressSets have one natural Ordering (the containment order)
|
|
|
|
def compare(x: AddressSet) = {
|
|
|
|
val primary = (this.base - x.base).signum // smallest address first
|
|
|
|
val secondary = (x.mask - this.mask).signum // largest mask first
|
|
|
|
if (primary != 0) primary else secondary
|
|
|
|
}
|
|
|
|
|
|
|
|
// We always want to see things in hex
|
|
|
|
override def toString() = "AddressSet(0x%x, 0x%x)".format(base, mask)
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case class TLManagerParameters(
|
|
|
|
address: Seq[AddressSet],
|
2016-09-15 03:08:49 +02:00
|
|
|
sinkId: IdRange = IdRange(0, 1),
|
|
|
|
regionType: RegionType.T = RegionType.GET_EFFECTS,
|
|
|
|
executable: Boolean = false, // processor can execute from this memory
|
|
|
|
nodePath: Seq[TLBaseNode] = Seq(),
|
2016-08-19 22:47:18 +02:00
|
|
|
// Supports both Acquire+Release+Finish of these sizes
|
2016-08-19 20:08:35 +02:00
|
|
|
supportsAcquire: TransferSizes = TransferSizes.none,
|
2016-08-20 03:39:21 +02:00
|
|
|
supportsArithmetic: TransferSizes = TransferSizes.none,
|
|
|
|
supportsLogical: TransferSizes = TransferSizes.none,
|
2016-08-19 20:08:35 +02:00
|
|
|
supportsGet: TransferSizes = TransferSizes.none,
|
|
|
|
supportsPutFull: TransferSizes = TransferSizes.none,
|
|
|
|
supportsPutPartial: TransferSizes = TransferSizes.none,
|
2016-09-13 02:15:28 +02:00
|
|
|
supportsHint: TransferSizes = TransferSizes.none,
|
2016-08-26 23:13:54 +02:00
|
|
|
// If fifoId=Some, all accesses sent to the same fifoId are executed and ACK'd in FIFO order
|
2016-09-17 02:26:14 +02:00
|
|
|
fifoId: Option[Int] = None,
|
|
|
|
customDTS: Option[String]= None)
|
2016-08-19 20:08:35 +02:00
|
|
|
{
|
|
|
|
address.combinations(2).foreach({ case Seq(x,y) =>
|
|
|
|
require (!x.overlaps(y))
|
|
|
|
})
|
2016-09-10 05:56:48 +02:00
|
|
|
require (supportsPutFull.contains(supportsPutPartial))
|
2016-08-19 20:08:35 +02:00
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
// Largest support transfer of all types
|
2016-08-19 20:08:35 +02:00
|
|
|
val maxTransfer = List(
|
|
|
|
supportsAcquire.max,
|
2016-08-20 03:39:21 +02:00
|
|
|
supportsArithmetic.max,
|
|
|
|
supportsLogical.max,
|
2016-08-19 20:08:35 +02:00
|
|
|
supportsGet.max,
|
|
|
|
supportsPutFull.max,
|
|
|
|
supportsPutPartial.max).max
|
2016-09-06 04:45:16 +02:00
|
|
|
|
2016-09-17 02:26:14 +02:00
|
|
|
// 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 =>
|
|
|
|
require (!a.strided) // Config String does not support this
|
|
|
|
" addr 0x%x;\n size 0x%x;\n".format(a.base, a.mask+1)
|
|
|
|
}
|
|
|
|
val footer = "}\n"
|
|
|
|
header + middle.reduce(_ + _) + footer
|
|
|
|
}
|
|
|
|
|
2016-09-06 04:45:16 +02:00
|
|
|
// The device had better not support a transfer larger than it's alignment
|
|
|
|
address.foreach({ case a =>
|
|
|
|
require (a.alignment1 >= maxTransfer-1)
|
|
|
|
})
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes: Int)
|
|
|
|
{
|
2016-08-31 01:02:46 +02:00
|
|
|
require (!managers.isEmpty)
|
2016-08-19 20:08:35 +02:00
|
|
|
require (isPow2(beatBytes))
|
|
|
|
|
|
|
|
// Require disjoint ranges for Ids and addresses
|
|
|
|
managers.combinations(2).foreach({ case Seq(x,y) =>
|
|
|
|
require (!x.sinkId.overlaps(y.sinkId))
|
|
|
|
x.address.foreach({ a => y.address.foreach({ b =>
|
|
|
|
require (!a.overlaps(b))
|
|
|
|
})})
|
|
|
|
})
|
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
// Bounds on required sizes
|
2016-08-19 20:08:35 +02:00
|
|
|
def endSinkId = managers.map(_.sinkId.end).max
|
|
|
|
def maxAddress = managers.map(_.address.map(_.max).max).max
|
|
|
|
def maxTransfer = managers.map(_.maxTransfer).max
|
2016-08-19 22:47:18 +02:00
|
|
|
|
|
|
|
// Operation sizes supported by all outward Managers
|
|
|
|
val allSupportAcquire = managers.map(_.supportsAcquire) .reduce(_ intersect _)
|
2016-08-20 03:39:21 +02:00
|
|
|
val allSupportArithmetic = managers.map(_.supportsArithmetic).reduce(_ intersect _)
|
|
|
|
val allSupportLogical = managers.map(_.supportsLogical) .reduce(_ intersect _)
|
2016-08-19 22:47:18 +02:00
|
|
|
val allSupportGet = managers.map(_.supportsGet) .reduce(_ intersect _)
|
|
|
|
val allSupportPutFull = managers.map(_.supportsPutFull) .reduce(_ intersect _)
|
|
|
|
val allSupportPutPartial = managers.map(_.supportsPutPartial).reduce(_ intersect _)
|
2016-09-13 02:15:28 +02:00
|
|
|
val allSupportHint = managers.map(_.supportsHint) .reduce(_ intersect _)
|
2016-08-19 22:47:18 +02:00
|
|
|
|
2016-08-22 22:28:52 +02:00
|
|
|
// Operation supported by at least one outward Managers
|
|
|
|
val anySupportAcquire = managers.map(!_.supportsAcquire.none) .reduce(_ || _)
|
|
|
|
val anySupportArithmetic = managers.map(!_.supportsArithmetic.none).reduce(_ || _)
|
|
|
|
val anySupportLogical = managers.map(!_.supportsLogical.none) .reduce(_ || _)
|
|
|
|
val anySupportGet = managers.map(!_.supportsGet.none) .reduce(_ || _)
|
|
|
|
val anySupportPutFull = managers.map(!_.supportsPutFull.none) .reduce(_ || _)
|
|
|
|
val anySupportPutPartial = managers.map(!_.supportsPutPartial.none).reduce(_ || _)
|
2016-09-13 02:15:28 +02:00
|
|
|
val anySupportHint = managers.map(!_.supportsHint.none) .reduce(_ || _)
|
2016-08-22 22:28:52 +02:00
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
// These return Option[TLManagerParameters] for your convenience
|
|
|
|
def find(address: BigInt) = managers.find(_.address.exists(_.contains(address)))
|
|
|
|
def findById(id: Int) = managers.find(_.sinkId.contains(id))
|
|
|
|
|
|
|
|
// Synthesizable lookup methods
|
|
|
|
def find(address: UInt) = Vec(managers.map(_.address.map(_.contains(address)).reduce(_ || _)))
|
|
|
|
def findById(id: UInt) = Vec(managers.map(_.sinkId.contains(id)))
|
2016-09-13 02:26:40 +02:00
|
|
|
def findId(address: UInt) = Mux1H(find(address), managers.map(m => UInt(m.sinkId.start)))
|
2016-09-01 20:12:59 +02:00
|
|
|
|
2016-09-14 00:44:36 +02:00
|
|
|
// Note: returns the actual fifoId + 1 or 0 if None
|
|
|
|
def findFifoId(address: UInt) = Mux1H(find(address), managers.map(m => UInt(m.fifoId.map(_+1).getOrElse(0))))
|
|
|
|
def hasFifoId(address: UInt) = Mux1H(find(address), managers.map(m => Bool(m.fifoId.isDefined)))
|
|
|
|
|
2016-09-15 23:47:44 +02:00
|
|
|
lazy val addressMask = AddressDecoder(managers.map(_.address))
|
2016-09-01 20:12:59 +02:00
|
|
|
// !!! need a cheaper version of find, where we assume a valid address match exists
|
2016-08-19 22:47:18 +02:00
|
|
|
|
|
|
|
// Does this Port manage this ID/address?
|
|
|
|
def contains(address: UInt) = find(address).reduce(_ || _)
|
|
|
|
def containsById(id: UInt) = findById(id).reduce(_ || _)
|
2016-09-13 02:26:40 +02:00
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
private def safety_helper(member: TLManagerParameters => TransferSizes)(address: UInt, lgSize: UInt) = {
|
2016-08-31 01:02:46 +02:00
|
|
|
val allSame = managers.map(member(_) == member(managers(0))).reduce(_ && _)
|
|
|
|
if (allSame) member(managers(0)).containsLg(lgSize) else {
|
|
|
|
Mux1H(find(address), managers.map(member(_).containsLg(lgSize)))
|
|
|
|
}
|
2016-08-19 22:47:18 +02:00
|
|
|
}
|
2016-08-19 20:08:35 +02:00
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
// Check for support of a given operation at a specific address
|
|
|
|
val supportsAcquire = safety_helper(_.supportsAcquire) _
|
2016-08-20 03:39:21 +02:00
|
|
|
val supportsArithmetic = safety_helper(_.supportsArithmetic) _
|
|
|
|
val supportsLogical = safety_helper(_.supportsLogical) _
|
2016-08-19 22:47:18 +02:00
|
|
|
val supportsGet = safety_helper(_.supportsGet) _
|
|
|
|
val supportsPutFull = safety_helper(_.supportsPutFull) _
|
|
|
|
val supportsPutPartial = safety_helper(_.supportsPutPartial) _
|
2016-09-13 02:15:28 +02:00
|
|
|
val supportsHint = safety_helper(_.supportsHint) _
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case class TLClientParameters(
|
2016-09-15 03:08:49 +02:00
|
|
|
sourceId: IdRange = IdRange(0,1),
|
|
|
|
nodePath: Seq[TLBaseNode] = Seq(),
|
2016-08-19 20:08:35 +02:00
|
|
|
// Supports both Probe+Grant of these sizes
|
|
|
|
supportsProbe: TransferSizes = TransferSizes.none,
|
2016-08-20 03:39:21 +02:00
|
|
|
supportsArithmetic: TransferSizes = TransferSizes.none,
|
|
|
|
supportsLogical: TransferSizes = TransferSizes.none,
|
2016-08-19 20:08:35 +02:00
|
|
|
supportsGet: TransferSizes = TransferSizes.none,
|
|
|
|
supportsPutFull: TransferSizes = TransferSizes.none,
|
|
|
|
supportsPutPartial: TransferSizes = TransferSizes.none,
|
2016-09-13 02:15:28 +02:00
|
|
|
supportsHint: TransferSizes = TransferSizes.none)
|
2016-08-19 20:08:35 +02:00
|
|
|
{
|
2016-09-10 05:56:48 +02:00
|
|
|
require (supportsPutFull.contains(supportsPutPartial))
|
|
|
|
|
2016-08-19 20:08:35 +02:00
|
|
|
val maxTransfer = List(
|
|
|
|
supportsProbe.max,
|
2016-08-20 03:39:21 +02:00
|
|
|
supportsArithmetic.max,
|
|
|
|
supportsLogical.max,
|
2016-08-19 20:08:35 +02:00
|
|
|
supportsGet.max,
|
|
|
|
supportsPutFull.max,
|
|
|
|
supportsPutPartial.max).max
|
|
|
|
}
|
|
|
|
|
|
|
|
case class TLClientPortParameters(clients: Seq[TLClientParameters]) {
|
2016-08-31 01:02:46 +02:00
|
|
|
require (!clients.isEmpty)
|
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
// Require disjoint ranges for Ids
|
|
|
|
clients.combinations(2).foreach({ case Seq(x,y) =>
|
|
|
|
require (!x.sourceId.overlaps(y.sourceId))
|
|
|
|
})
|
|
|
|
|
|
|
|
// Bounds on required sizes
|
2016-08-19 20:08:35 +02:00
|
|
|
def endSourceId = clients.map(_.sourceId.end).max
|
|
|
|
def maxTransfer = clients.map(_.maxTransfer).max
|
2016-08-19 22:47:18 +02:00
|
|
|
|
|
|
|
// Operation sizes supported by all inward Clients
|
|
|
|
val allSupportProbe = clients.map(_.supportsProbe) .reduce(_ intersect _)
|
2016-08-20 03:39:21 +02:00
|
|
|
val allSupportArithmetic = clients.map(_.supportsArithmetic).reduce(_ intersect _)
|
|
|
|
val allSupportLogical = clients.map(_.supportsLogical) .reduce(_ intersect _)
|
2016-08-19 22:47:18 +02:00
|
|
|
val allSupportGet = clients.map(_.supportsGet) .reduce(_ intersect _)
|
|
|
|
val allSupportPutFull = clients.map(_.supportsPutFull) .reduce(_ intersect _)
|
|
|
|
val allSupportPutPartial = clients.map(_.supportsPutPartial).reduce(_ intersect _)
|
2016-09-13 02:15:28 +02:00
|
|
|
val allSupportHint = clients.map(_.supportsHint) .reduce(_ intersect _)
|
2016-08-19 22:47:18 +02:00
|
|
|
|
2016-08-22 22:28:52 +02:00
|
|
|
// Operation is supported by at least one client
|
|
|
|
val anySupportProbe = clients.map(!_.supportsProbe.none) .reduce(_ || _)
|
|
|
|
val anySupportArithmetic = clients.map(!_.supportsArithmetic.none).reduce(_ || _)
|
|
|
|
val anySupportLogical = clients.map(!_.supportsLogical.none) .reduce(_ || _)
|
|
|
|
val anySupportGet = clients.map(!_.supportsGet.none) .reduce(_ || _)
|
|
|
|
val anySupportPutFull = clients.map(!_.supportsPutFull.none) .reduce(_ || _)
|
|
|
|
val anySupportPutPartial = clients.map(!_.supportsPutPartial.none).reduce(_ || _)
|
2016-09-13 02:15:28 +02:00
|
|
|
val anySupportHint = clients.map(!_.supportsHint.none) .reduce(_ || _)
|
2016-08-22 22:28:52 +02:00
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
// These return Option[TLClientParameters] for your convenience
|
|
|
|
def find(id: Int) = clients.find(_.sourceId.contains(id))
|
2016-09-13 02:26:40 +02:00
|
|
|
|
2016-08-19 22:47:18 +02:00
|
|
|
// Synthesizable lookup methods
|
|
|
|
def find(id: UInt) = Vec(clients.map(_.sourceId.contains(id)))
|
|
|
|
def contains(id: UInt) = find(id).reduce(_ || _)
|
2016-09-13 02:26:40 +02:00
|
|
|
|
2016-08-23 00:37:30 +02:00
|
|
|
private def safety_helper(member: TLClientParameters => TransferSizes)(id: UInt, lgSize: UInt) = {
|
2016-08-31 01:02:46 +02:00
|
|
|
val allSame = clients.map(member(_) == member(clients(0))).reduce(_ && _)
|
|
|
|
if (allSame) member(clients(0)).containsLg(lgSize) else {
|
|
|
|
Mux1H(find(id), clients.map(member(_).containsLg(lgSize)))
|
|
|
|
}
|
2016-08-19 22:47:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check for support of a given operation at a specific id
|
|
|
|
val supportsProbe = safety_helper(_.supportsProbe) _
|
2016-08-20 03:39:21 +02:00
|
|
|
val supportsArithmetic = safety_helper(_.supportsArithmetic) _
|
|
|
|
val supportsLogical = safety_helper(_.supportsLogical) _
|
2016-08-19 22:47:18 +02:00
|
|
|
val supportsGet = safety_helper(_.supportsGet) _
|
|
|
|
val supportsPutFull = safety_helper(_.supportsPutFull) _
|
|
|
|
val supportsPutPartial = safety_helper(_.supportsPutPartial) _
|
2016-09-13 02:15:28 +02:00
|
|
|
val supportsHint = safety_helper(_.supportsHint) _
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case class TLBundleParameters(
|
2016-09-07 08:46:44 +02:00
|
|
|
addrHiBits: Int,
|
|
|
|
dataBits: Int,
|
|
|
|
sourceBits: Int,
|
|
|
|
sinkBits: Int,
|
|
|
|
sizeBits: Int)
|
2016-08-19 20:08:35 +02:00
|
|
|
{
|
|
|
|
// Chisel has issues with 0-width wires
|
2016-09-07 08:46:44 +02:00
|
|
|
require (addrHiBits >= 1)
|
|
|
|
require (dataBits >= 8)
|
2016-08-19 20:08:35 +02:00
|
|
|
require (sourceBits >= 1)
|
|
|
|
require (sinkBits >= 1)
|
|
|
|
require (sizeBits >= 1)
|
|
|
|
require (isPow2(dataBits))
|
2016-09-07 08:46:44 +02:00
|
|
|
|
|
|
|
val addrLoBits = log2Up(dataBits/8)
|
|
|
|
|
2016-08-19 20:08:35 +02:00
|
|
|
def union(x: TLBundleParameters) =
|
|
|
|
TLBundleParameters(
|
2016-09-07 08:46:44 +02:00
|
|
|
max(addrHiBits, x.addrHiBits),
|
2016-08-19 20:08:35 +02:00
|
|
|
max(dataBits, x.dataBits),
|
|
|
|
max(sourceBits, x.sourceBits),
|
|
|
|
max(sinkBits, x.sinkBits),
|
|
|
|
max(sizeBits, x.sizeBits))
|
|
|
|
}
|
|
|
|
|
|
|
|
case class TLEdgeParameters(
|
|
|
|
client: TLClientPortParameters,
|
|
|
|
manager: TLManagerPortParameters)
|
|
|
|
{
|
2016-08-20 05:28:58 +02:00
|
|
|
val maxTransfer = max(client.maxTransfer, manager.maxTransfer)
|
|
|
|
val maxLgSize = log2Up(maxTransfer)
|
|
|
|
|
2016-08-22 22:18:01 +02:00
|
|
|
// Sanity check the link...
|
|
|
|
require (maxTransfer >= manager.beatBytes)
|
|
|
|
|
2016-08-19 20:08:35 +02:00
|
|
|
val bundle = TLBundleParameters(
|
2016-09-10 10:22:12 +02:00
|
|
|
addrHiBits = log2Up(manager.maxAddress + 1) - log2Ceil(manager.beatBytes),
|
2016-08-19 20:08:35 +02:00
|
|
|
dataBits = manager.beatBytes * 8,
|
|
|
|
sourceBits = log2Up(client.endSourceId),
|
|
|
|
sinkBits = log2Up(manager.endSinkId),
|
2016-08-20 05:28:58 +02:00
|
|
|
sizeBits = log2Up(maxLgSize+1))
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|