1
0

Merge pull request #312 from ucb-bar/tl2-cheap-address-decode

Tl2 cheap address decode
This commit is contained in:
Wesley W. Terpstra 2016-09-17 17:37:03 -07:00 committed by GitHub
commit aa956c0108
11 changed files with 152 additions and 75 deletions

View File

@ -77,7 +77,7 @@ object GenerateGlobalAddrMap {
(if (manager.executable) AddrMapProt.X else 0), cacheable)
val multi = manager.address.size > 1
manager.address.zipWithIndex.map { case (address, i) =>
require (!address.strided) // TL1 can't do this
require (address.contiguous) // TL1 needs this
val name = manager.name + (if (multi) ".%d".format(i) else "")
AddrMapEntry(name, MemRange(address.base, address.mask+1, attr))
}

View File

@ -231,7 +231,7 @@ class TLEdgeOut(
// Transfers
def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
require (manager.anySupportAcquire)
val legal = manager.supportsAcquire(toAddress, lgSize)
val legal = manager.supportsAcquireFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.Acquire
a.param := growPermissions
@ -245,7 +245,7 @@ class TLEdgeOut(
def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt) = {
require (manager.anySupportAcquire)
val legal = manager.supportsAcquire(toAddress, lgSize)
val legal = manager.supportsAcquireFast(toAddress, lgSize)
val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.Release
c.param := shrinkPermissions
@ -260,7 +260,7 @@ class TLEdgeOut(
def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt, data: UInt) = {
require (manager.anySupportAcquire)
val legal = manager.supportsAcquire(toAddress, lgSize)
val legal = manager.supportsAcquireFast(toAddress, lgSize)
val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.ReleaseData
c.param := shrinkPermissions
@ -308,7 +308,7 @@ class TLEdgeOut(
// Accesses
def Get(fromSource: UInt, toAddress: UInt, lgSize: UInt) = {
require (manager.anySupportGet)
val legal = manager.supportsGet(toAddress, lgSize)
val legal = manager.supportsGetFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.Get
a.param := UInt(0)
@ -322,7 +322,7 @@ class TLEdgeOut(
def Put(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt) = {
require (manager.anySupportPutFull)
val legal = manager.supportsPutFull(toAddress, lgSize)
val legal = manager.supportsPutFullFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.PutFullData
a.param := UInt(0)
@ -336,7 +336,7 @@ class TLEdgeOut(
def Put(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, mask : UInt) = {
require (manager.anySupportPutPartial)
val legal = manager.supportsPutPartial(toAddress, lgSize)
val legal = manager.supportsPutPartialFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.PutPartialData
a.param := UInt(0)
@ -350,7 +350,7 @@ class TLEdgeOut(
def Arithmetic(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, atomic: UInt) = {
require (manager.anySupportArithmetic)
val legal = manager.supportsArithmetic(toAddress, lgSize)
val legal = manager.supportsArithmeticFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.ArithmeticData
a.param := atomic
@ -364,7 +364,7 @@ class TLEdgeOut(
def Logical(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, atomic: UInt) = {
require (manager.anySupportLogical)
val legal = manager.supportsLogical(toAddress, lgSize)
val legal = manager.supportsLogicalFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.LogicalData
a.param := atomic
@ -378,7 +378,7 @@ class TLEdgeOut(
def Hint(fromSource: UInt, toAddress: UInt, lgSize: UInt, param: UInt) = {
require (manager.anySupportHint)
val legal = manager.supportsHint(toAddress, lgSize)
val legal = manager.supportsHintFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.Hint
a.param := param
@ -445,7 +445,7 @@ class TLEdgeIn(
// Transfers
def Probe(fromAddress: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt) = {
require (client.anySupportProbe)
val legal = client.supportsProbe(fromAddress, lgSize)
val legal = client.supportsProbe(toSource, lgSize)
val b = Wire(new TLBundleB(bundle))
b.opcode := TLMessages.Probe
b.param := capPermissions

View File

@ -189,7 +189,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
val maxLgHints = maxHints .map(m => if (m == 0) lgMinSize else UInt(log2Ceil(m)))
// If this is infront of a single manager, these become constants
val find = manager.find(edgeIn.address(in.a.bits))
val find = manager.findFast(edgeIn.address(in.a.bits))
val maxLgArithmetic = Mux1H(find, maxLgArithmetics)
val maxLgLogical = Mux1H(find, maxLgLogicals)
val maxLgGet = Mux1H(find, maxLgGets)

View File

@ -163,10 +163,12 @@ class TLFuzzer(
edge.Hint(src, addr, size, UInt(0))
} else { (glegal, gbits) }
val legal_dest = edge.manager.containsSafe(addr)
// Pick a specific message to try to send
val a_type_sel = noiseMaker(3, inc)
val legal = MuxLookup(a_type_sel, glegal, Seq(
val legal = legal_dest && MuxLookup(a_type_sel, glegal, Seq(
UInt("b000") -> glegal,
UInt("b001") -> pflegal,
UInt("b010") -> pplegal,
@ -218,14 +220,18 @@ class ClockDivider extends BlackBox {
class TLFuzzRAM extends LazyModule
{
val model = LazyModule(new TLRAMModel)
val ram = LazyModule(new TLRAM(AddressSet(0, 0x3ff)))
val ram = LazyModule(new TLRAM(AddressSet(0x800, 0x7ff)))
val ram2 = LazyModule(new TLRAM(AddressSet(0, 0x3ff), beatBytes = 16))
val gpio = LazyModule(new RRTest1(0x400))
val xbar = LazyModule(new TLXbar)
val xbar2= LazyModule(new TLXbar)
val fuzz = LazyModule(new TLFuzzer(5000))
val cross = LazyModule(new TLAsyncCrossing)
model.node := fuzz.node
xbar.node := TLWidthWidget(TLHintHandler(model.node), 16)
xbar2.node := model.node
ram2.node := TLFragmenter(xbar2.node, 16, 256)
xbar.node := TLWidthWidget(TLHintHandler(xbar2.node), 16)
cross.node := TLFragmenter(TLBuffer(xbar.node), 4, 256)
ram.node := cross.node
gpio.node := TLFragmenter(TLBuffer(xbar.node), 4, 32)

View File

@ -45,7 +45,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
// Who wants what?
val address = edgeIn.address(in.a.bits)
val handleA = if (passthrough) !edgeOut.manager.supportsHint(address, edgeIn.size(in.a.bits)) else Bool(true)
val handleA = if (passthrough) !edgeOut.manager.supportsHintFast(address, edgeIn.size(in.a.bits)) else Bool(true)
val hintBitsAtA = handleA && in.a.bits.opcode === TLMessages.Hint
val hintWantsD = in.a.valid && hintBitsAtA
val outerWantsD = out.d.valid
@ -57,7 +57,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
assert (!hintHoldsD || hintWantsD)
in.d.valid := Mux(hintWinsD, hintWantsD, outerWantsD)
in.d.bits := Mux(hintWinsD, edgeIn.HintAck(in.a.bits, edgeOut.manager.findId(address)), out.d.bits)
in.d.bits := Mux(hintWinsD, edgeIn.HintAck(in.a.bits, edgeOut.manager.findIdStartFast(address)), out.d.bits)
out.d.ready := in.d.ready && !hintHoldsD
in.a.ready := Mux(hintBitsAtA, hintWinsD && in.d.ready, out.a.ready)

View File

@ -21,9 +21,19 @@ object IntRange
implicit def apply(end: Int): IntRange = apply(0, end)
}
case class IntSourceParameters(device: String, range: IntRange)
case class IntSourceParameters(
range: IntRange,
nodePath: Seq[IntBaseNode] = Seq())
{
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
}
case class IntSinkParameters(
nodePath: Seq[IntBaseNode] = Seq())
{
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
}
case class IntSinkPortParameters()
case class IntSourcePortParameters(sources: Seq[IntSourceParameters])
{
val num = sources.map(_.range.size).sum
@ -32,6 +42,9 @@ case class IntSourcePortParameters(sources: Seq[IntSourceParameters])
// The interrupts must perfectly cover the range
require (sources.map(_.range.end).max == num)
}
case class IntSinkPortParameters(sinks: Seq[IntSinkParameters])
case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters)
object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, IntEdge, Vec[Bool]]
@ -52,16 +65,21 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In
// Cannot use bulk connect, because the widths could differ
(bo zip bi) foreach { case (o, i) => i := o }
}
override def mixO(po: IntSourcePortParameters, node: IntBaseNode): IntSourcePortParameters =
po.copy(sources = po.sources.map { s => s.copy (nodePath = node +: s.nodePath) })
override def mixI(pi: IntSinkPortParameters, node: IntBaseNode): IntSinkPortParameters =
pi.copy(sinks = pi.sinks.map { s => s.copy (nodePath = node +: s.nodePath) })
}
case class IntIdentityNode() extends IdentityNode(IntImp)
case class IntOutputNode() extends OutputNode(IntImp)
case class IntInputNode() extends InputNode(IntImp)
case class IntSourceNode(device: String, num: Int) extends SourceNode(IntImp)(
IntSourcePortParameters(Seq(IntSourceParameters(device, num))),
(if (num == 0) 0 else 1) to 1)
case class IntSinkNode() extends SinkNode(IntImp)(IntSinkPortParameters())
case class IntSourceNode(num: Int) extends SourceNode(IntImp)(
IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1)
case class IntSinkNode() extends SinkNode(IntImp)(
IntSinkPortParameters(Seq(IntSinkParameters())))
case class IntAdapterNode(
sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters,
@ -75,7 +93,7 @@ class IntXbar extends LazyModule
val intnode = IntAdapterNode(
numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink?
numSinkPorts = 1 to 128,
sinkFn = { _ => IntSinkPortParameters() },
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) },
sourceFn = { seq =>
IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map {
case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o)))

View File

@ -24,7 +24,7 @@ object TLMonitor
val mask = edge.full_mask(bundle)
when (bundle.opcode === TLMessages.Acquire) {
assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra)
assert (edge.manager.supportsAcquireSafe(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra)
assert (source_ok, "'A' channel Acquire carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra)
assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra)
@ -33,7 +33,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.Get) {
assert (edge.manager.supportsGet(edge.address(bundle), bundle.size), "'A' channel carries Get type unsupported by manager" + extra)
assert (edge.manager.supportsGetSafe(edge.address(bundle), bundle.size), "'A' channel carries Get type unsupported by manager" + extra)
assert (source_ok, "'A' channel Get carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Get address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'A' channel Get carries invalid param" + extra)
@ -41,7 +41,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.PutFullData) {
assert (edge.manager.supportsPutFull(edge.address(bundle), bundle.size), "'A' channel carries PutFull type unsupported by manager" + extra)
assert (edge.manager.supportsPutFullSafe(edge.address(bundle), bundle.size), "'A' channel carries PutFull type unsupported by manager" + extra)
assert (source_ok, "'A' channel PutFull carries invalid source ID" + extra)
assert (is_aligned, "'A' channel PutFull address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'A' channel PutFull carries invalid param" + extra)
@ -49,7 +49,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.PutPartialData) {
assert (edge.manager.supportsPutPartial(edge.address(bundle), bundle.size), "'A' channel carries PutPartial type unsupported by manager" + extra)
assert (edge.manager.supportsPutPartialSafe(edge.address(bundle), bundle.size), "'A' channel carries PutPartial type unsupported by manager" + extra)
assert (source_ok, "'A' channel PutPartial carries invalid source ID" + extra)
assert (is_aligned, "'A' channel PutPartial address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'A' channel PutPartial carries invalid param" + extra)
@ -57,7 +57,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.ArithmeticData) {
assert (edge.manager.supportsArithmetic(edge.address(bundle), bundle.size), "'A' channel carries Arithmetic type unsupported by manager" + extra)
assert (edge.manager.supportsArithmeticSafe(edge.address(bundle), bundle.size), "'A' channel carries Arithmetic type unsupported by manager" + extra)
assert (source_ok, "'A' channel Arithmetic carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Arithmetic address not aligned to size" + extra)
assert (TLAtomics.isArithmetic(bundle.param), "'A' channel Arithmetic carries invalid opcode param" + extra)
@ -65,7 +65,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.LogicalData) {
assert (edge.manager.supportsLogical(edge.address(bundle), bundle.size), "'A' channel carries Logical type unsupported by manager" + extra)
assert (edge.manager.supportsLogicalSafe(edge.address(bundle), bundle.size), "'A' channel carries Logical type unsupported by manager" + extra)
assert (source_ok, "'A' channel Logical carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Logical address not aligned to size" + extra)
assert (TLAtomics.isLogical(bundle.param), "'A' channel Logical carries invalid opcode param" + extra)
@ -73,7 +73,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.Hint) {
assert (edge.manager.supportsHint(edge.address(bundle), bundle.size), "'A' channel carries Hint type unsupported by manager" + extra)
assert (edge.manager.supportsHintSafe(edge.address(bundle), bundle.size), "'A' channel carries Hint type unsupported by manager" + extra)
assert (source_ok, "'A' channel Hint carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Hint address not aligned to size" + extra)
assert (bundle.mask === mask, "'A' channel Hint contains invalid mask" + extra)
@ -84,7 +84,7 @@ object TLMonitor
assert (TLMessages.isB(bundle.opcode), "'B' channel has invalid opcode" + extra)
// Reuse these subexpressions to save some firrtl lines
val address_ok = edge.manager.contains(bundle.source)
val address_ok = edge.manager.containsSafe(edge.address(bundle))
val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size)
val mask = edge.full_mask(bundle)
@ -150,7 +150,7 @@ object TLMonitor
val source_ok = edge.client.contains(bundle.source)
val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size) && edge.isLoAligned(bundle.addr_lo, bundle.size)
val address_ok = edge.manager.contains(bundle.source)
val address_ok = edge.manager.containsSafe(edge.address(bundle))
when (bundle.opcode === TLMessages.ProbeAck) {
assert (address_ok, "'C' channel ProbeAck carries unmanaged address" + extra)
@ -171,7 +171,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.Release) {
assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'C' channel carries Release type unsupported by manager" + extra)
assert (edge.manager.supportsAcquireSafe(edge.address(bundle), bundle.size), "'C' channel carries Release type unsupported by manager" + extra)
assert (source_ok, "'C' channel Release carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel Release smaller than a beat" + extra)
assert (is_aligned, "'C' channel Release address not aligned to size" + extra)
@ -180,7 +180,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.ReleaseData) {
assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra)
assert (edge.manager.supportsAcquireSafe(edge.address(bundle), bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra)
assert (source_ok, "'C' channel ReleaseData carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ReleaseData smaller than a beat" + extra)
assert (is_aligned, "'C' channel ReleaseData address not aligned to size" + extra)

View File

@ -82,26 +82,29 @@ 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 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 +112,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 +139,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,12 +154,13 @@ 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 =>
require (!a.strided) // Config String does not support this
require (a.contiguous) // Config String is not so flexible
" addr 0x%x;\n size 0x%x;\n".format(a.base, a.mask+1)
}
val footer = "}\n"
@ -158,7 +169,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)
})
}
@ -198,41 +209,59 @@ case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes
val anySupportPutPartial = managers.map(!_.supportsPutPartial.none).reduce(_ || _)
val anySupportHint = managers.map(!_.supportsHint.none) .reduce(_ || _)
// Which bits suffice to distinguish between all managers
lazy val routingMask = AddressDecoder(managers.map(_.address))
// 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)))
def findId(address: UInt) = Mux1H(find(address), managers.map(m => UInt(m.sinkId.start)))
def findIdStartSafe(address: UInt) = Mux1H(findSafe(address), managers.map(m => UInt(m.sinkId.start)))
def findIdStartFast(address: UInt) = Mux1H(findFast(address), managers.map(m => UInt(m.sinkId.start)))
def findIdEndSafe(address: UInt) = Mux1H(findSafe(address), managers.map(m => UInt(m.sinkId.end)))
def findIdEndFast(address: UInt) = Mux1H(findFast(address), managers.map(m => UInt(m.sinkId.end)))
// The safe version will check the entire address
def findSafe(address: UInt) = Vec(managers.map(_.address.map(_.contains(address)).reduce(_ || _)))
// The fast version assumes the address is valid
def findFast(address: UInt) = Vec(managers.map(_.address.map(_.widen(~routingMask)).distinct.map(_.contains(address)).reduce(_ || _)))
// 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)))
def findFifoIdSafe(address: UInt) = Mux1H(findSafe(address), managers.map(m => UInt(m.fifoId.map(_+1).getOrElse(0))))
def findFifoIdFast(address: UInt) = Mux1H(findFast(address), managers.map(m => UInt(m.fifoId.map(_+1).getOrElse(0))))
def hasFifoIdSafe(address: UInt) = Mux1H(findSafe(address), managers.map(m => Bool(m.fifoId.isDefined)))
def hasFifoIdFast(address: UInt) = Mux1H(findFast(address), managers.map(m => Bool(m.fifoId.isDefined)))
lazy val addressMask = AddressDecoder(managers.map(_.address))
// !!! need a cheaper version of find, where we assume a valid address match exists
// Does this Port manage this ID/address?
def contains(address: UInt) = find(address).reduce(_ || _)
def containsSafe(address: UInt) = findSafe(address).reduce(_ || _)
// containsFast would be useless; it could always be true
def containsById(id: UInt) = findById(id).reduce(_ || _)
private def safety_helper(member: TLManagerParameters => TransferSizes)(address: UInt, lgSize: UInt) = {
private def safety_helper(member: TLManagerParameters => TransferSizes, select: UInt => Vec[Bool])(address: UInt, lgSize: UInt) = {
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)))
Mux1H(select(address), managers.map(member(_).containsLg(lgSize)))
}
}
// Check for support of a given operation at a specific address
val supportsAcquire = safety_helper(_.supportsAcquire) _
val supportsArithmetic = safety_helper(_.supportsArithmetic) _
val supportsLogical = safety_helper(_.supportsLogical) _
val supportsGet = safety_helper(_.supportsGet) _
val supportsPutFull = safety_helper(_.supportsPutFull) _
val supportsPutPartial = safety_helper(_.supportsPutPartial) _
val supportsHint = safety_helper(_.supportsHint) _
val supportsAcquireSafe = safety_helper(_.supportsAcquire, findSafe) _
val supportsArithmeticSafe = safety_helper(_.supportsArithmetic, findSafe) _
val supportsLogicalSafe = safety_helper(_.supportsLogical, findSafe) _
val supportsGetSafe = safety_helper(_.supportsGet, findSafe) _
val supportsPutFullSafe = safety_helper(_.supportsPutFull, findSafe) _
val supportsPutPartialSafe = safety_helper(_.supportsPutPartial, findSafe) _
val supportsHintSafe = safety_helper(_.supportsHint, findSafe) _
val supportsAcquireFast = safety_helper(_.supportsAcquire, findFast) _
val supportsArithmeticFast = safety_helper(_.supportsArithmetic, findFast) _
val supportsLogicalFast = safety_helper(_.supportsLogical, findFast) _
val supportsGetFast = safety_helper(_.supportsGet, findFast) _
val supportsPutFullFast = safety_helper(_.supportsPutFull, findFast) _
val supportsPutPartialFast = safety_helper(_.supportsPutPartial, findFast) _
val supportsHintFast = safety_helper(_.supportsHint, findFast) _
}
case class TLClientParameters(
@ -256,6 +285,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]) {

View File

@ -119,7 +119,7 @@ class TLRAMModel extends LazyModule
val a_addr_hi = a.addr_hi | (a_beats1 & ~a_counter1)
val a_base = edge.address(a)
val a_mask = edge.mask(a_base, a_size)
val a_fifo = edge.manager.hasFifoId(a_base)
val a_fifo = edge.manager.hasFifoIdFast(a_base)
// Grab the concurrency state we need
val a_inc_bytes = inc_bytes.map(_.read(a_addr_hi))
@ -203,7 +203,7 @@ class TLRAMModel extends LazyModule
val d_base = d_flight.base
val d_addr_hi = d_base >> shift | (d_beats1 & ~d_counter1)
val d_mask = edge.mask(d_base, d_size)
val d_fifo = edge.manager.hasFifoId(d_flight.base)
val d_fifo = edge.manager.hasFifoIdFast(d_flight.base)
// Grab the concurrency state we need
val d_inc_bytes = inc_bytes.map(_.read(d_addr_hi))
@ -222,7 +222,8 @@ class TLRAMModel extends LazyModule
// Check the response is correct
assert (d_size === d_flight.size)
assert (edge.manager.findId(d_flight.base) === d.sink)
assert (edge.manager.findIdStartFast(d_flight.base) <= d.sink)
assert (edge.manager.findIdEndFast (d_flight.base) > d.sink)
// addr_lo is allowed to differ
when (d_flight.opcode === TLMessages.Hint) {

View File

@ -12,7 +12,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB
supportsPutFull = TransferSizes(1, beatBytes),
fifoId = Some(0))) // requests are handled in order
{
require (!address.strided)
require (address.contiguous)
// Calling this method causes the matching TL2 bundle to be
// configured to route all requests to the listed RegFields.
@ -75,7 +75,7 @@ object TLRegisterNode
abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Option[Int], beatBytes: Int, undefZero: Boolean) extends LazyModule
{
val node = TLRegisterNode(address, concurrency, beatBytes, undefZero)
val intnode = IntSourceNode(name + s" @ ${address.base}", interrupts)
val intnode = IntSourceNode(interrupts)
}
case class TLRegBundleArg(interrupts: Vec[Vec[Bool]], in: Vec[TLBundle])

View File

@ -75,6 +75,23 @@ class TLXbar(policy: (Vec[Bool], Bool) => Seq[Bool] = TLXbar.lowestIndex) extend
val inputIdRanges = mapInputIds(node.edgesIn.map(_.client))
val outputIdRanges = mapOutputIds(node.edgesOut.map(_.manager))
// Find a good mask for address decoding
val port_addrs = node.edgesOut.map(_.manager.managers.map(_.address).flatten)
val routingMask = AddressDecoder(port_addrs)
val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct)
val outputPorts = route_addrs.map(seq => (addr: UInt) => seq.map(_.contains(addr)).reduce(_ || _))
// Print the mapping
if (false) {
println("Xbar mapping:")
route_addrs.foreach { p =>
print(" ")
p.foreach { a => print(s" ${a}") }
println("")
}
println("--")
}
// We need an intermediate size of bundle with the widest possible identifiers
val wide_bundle = io.in(0).params.union(io.out(0).params)
@ -145,11 +162,15 @@ class TLXbar(policy: (Vec[Bool], Bool) => Seq[Bool] = TLXbar.lowestIndex) extend
in(i).e.ready := Mux1C(grantedEIO(i), out.map(_.e.ready))
}
val requestAIO = Vec(in.map { i => Vec(node.edgesOut.map { o => i.a.valid && o.manager.contains(o.address(i.a.bits)) }) })
val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.b.valid && i .contains(o.b.bits.source) }) })
val requestCIO = Vec(in.map { i => Vec(node.edgesOut.map { o => i.c.valid && o.manager.contains(o.address(i.c.bits)) }) })
val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.d.valid && i .contains(o.d.bits.source) }) })
val requestEIO = Vec(in.map { i => Vec(outputIdRanges.map { o => i.e.valid && o .contains(i.e.bits.sink) }) })
val addressA = (in zip node.edgesIn) map { case (i, e) => (i.a.valid, e.address(i.a.bits)) }
val addressC = (in zip node.edgesIn) map { case (i, e) => (i.c.valid, e.address(i.c.bits)) }
val requestAIO = Vec(addressA.map { i => Vec(outputPorts.map { o => i._1 && o(i._2) }) })
val requestCIO = Vec(addressC.map { i => Vec(outputPorts.map { o => i._1 && o(i._2) }) })
val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.b.valid && i.contains(o.b.bits.source) }) })
val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.d.valid && i.contains(o.d.bits.source) }) })
val requestEIO = Vec(in.map { i => Vec(outputIdRanges.map { o => i.e.valid && o.contains(i.e.bits.sink) }) })
val beatsA = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats(i.a.bits) })
val beatsB = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats(o.b.bits) })