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) (if (manager.executable) AddrMapProt.X else 0), cacheable)
val multi = manager.address.size > 1 val multi = manager.address.size > 1
manager.address.zipWithIndex.map { case (address, i) => 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 "") val name = manager.name + (if (multi) ".%d".format(i) else "")
AddrMapEntry(name, MemRange(address.base, address.mask+1, attr)) AddrMapEntry(name, MemRange(address.base, address.mask+1, attr))
} }

View File

@ -231,7 +231,7 @@ class TLEdgeOut(
// Transfers // Transfers
def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = { def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
require (manager.anySupportAcquire) require (manager.anySupportAcquire)
val legal = manager.supportsAcquire(toAddress, lgSize) val legal = manager.supportsAcquireFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle)) val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.Acquire a.opcode := TLMessages.Acquire
a.param := growPermissions a.param := growPermissions
@ -245,7 +245,7 @@ class TLEdgeOut(
def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt) = { def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt) = {
require (manager.anySupportAcquire) require (manager.anySupportAcquire)
val legal = manager.supportsAcquire(toAddress, lgSize) val legal = manager.supportsAcquireFast(toAddress, lgSize)
val c = Wire(new TLBundleC(bundle)) val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.Release c.opcode := TLMessages.Release
c.param := shrinkPermissions c.param := shrinkPermissions
@ -260,7 +260,7 @@ class TLEdgeOut(
def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt, data: UInt) = { def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt, data: UInt) = {
require (manager.anySupportAcquire) require (manager.anySupportAcquire)
val legal = manager.supportsAcquire(toAddress, lgSize) val legal = manager.supportsAcquireFast(toAddress, lgSize)
val c = Wire(new TLBundleC(bundle)) val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.ReleaseData c.opcode := TLMessages.ReleaseData
c.param := shrinkPermissions c.param := shrinkPermissions
@ -308,7 +308,7 @@ class TLEdgeOut(
// Accesses // Accesses
def Get(fromSource: UInt, toAddress: UInt, lgSize: UInt) = { def Get(fromSource: UInt, toAddress: UInt, lgSize: UInt) = {
require (manager.anySupportGet) require (manager.anySupportGet)
val legal = manager.supportsGet(toAddress, lgSize) val legal = manager.supportsGetFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle)) val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.Get a.opcode := TLMessages.Get
a.param := UInt(0) a.param := UInt(0)
@ -322,7 +322,7 @@ class TLEdgeOut(
def Put(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt) = { def Put(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt) = {
require (manager.anySupportPutFull) require (manager.anySupportPutFull)
val legal = manager.supportsPutFull(toAddress, lgSize) val legal = manager.supportsPutFullFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle)) val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.PutFullData a.opcode := TLMessages.PutFullData
a.param := UInt(0) a.param := UInt(0)
@ -336,7 +336,7 @@ class TLEdgeOut(
def Put(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, mask : UInt) = { def Put(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, mask : UInt) = {
require (manager.anySupportPutPartial) require (manager.anySupportPutPartial)
val legal = manager.supportsPutPartial(toAddress, lgSize) val legal = manager.supportsPutPartialFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle)) val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.PutPartialData a.opcode := TLMessages.PutPartialData
a.param := UInt(0) a.param := UInt(0)
@ -350,7 +350,7 @@ class TLEdgeOut(
def Arithmetic(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, atomic: UInt) = { def Arithmetic(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, atomic: UInt) = {
require (manager.anySupportArithmetic) require (manager.anySupportArithmetic)
val legal = manager.supportsArithmetic(toAddress, lgSize) val legal = manager.supportsArithmeticFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle)) val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.ArithmeticData a.opcode := TLMessages.ArithmeticData
a.param := atomic a.param := atomic
@ -364,7 +364,7 @@ class TLEdgeOut(
def Logical(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, atomic: UInt) = { def Logical(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, atomic: UInt) = {
require (manager.anySupportLogical) require (manager.anySupportLogical)
val legal = manager.supportsLogical(toAddress, lgSize) val legal = manager.supportsLogicalFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle)) val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.LogicalData a.opcode := TLMessages.LogicalData
a.param := atomic a.param := atomic
@ -378,7 +378,7 @@ class TLEdgeOut(
def Hint(fromSource: UInt, toAddress: UInt, lgSize: UInt, param: UInt) = { def Hint(fromSource: UInt, toAddress: UInt, lgSize: UInt, param: UInt) = {
require (manager.anySupportHint) require (manager.anySupportHint)
val legal = manager.supportsHint(toAddress, lgSize) val legal = manager.supportsHintFast(toAddress, lgSize)
val a = Wire(new TLBundleA(bundle)) val a = Wire(new TLBundleA(bundle))
a.opcode := TLMessages.Hint a.opcode := TLMessages.Hint
a.param := param a.param := param
@ -445,7 +445,7 @@ class TLEdgeIn(
// Transfers // Transfers
def Probe(fromAddress: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt) = { def Probe(fromAddress: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt) = {
require (client.anySupportProbe) require (client.anySupportProbe)
val legal = client.supportsProbe(fromAddress, lgSize) val legal = client.supportsProbe(toSource, lgSize)
val b = Wire(new TLBundleB(bundle)) val b = Wire(new TLBundleB(bundle))
b.opcode := TLMessages.Probe b.opcode := TLMessages.Probe
b.param := capPermissions 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))) val maxLgHints = maxHints .map(m => if (m == 0) lgMinSize else UInt(log2Ceil(m)))
// If this is infront of a single manager, these become constants // 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 maxLgArithmetic = Mux1H(find, maxLgArithmetics)
val maxLgLogical = Mux1H(find, maxLgLogicals) val maxLgLogical = Mux1H(find, maxLgLogicals)
val maxLgGet = Mux1H(find, maxLgGets) val maxLgGet = Mux1H(find, maxLgGets)

View File

@ -163,10 +163,12 @@ class TLFuzzer(
edge.Hint(src, addr, size, UInt(0)) edge.Hint(src, addr, size, UInt(0))
} else { (glegal, gbits) } } else { (glegal, gbits) }
val legal_dest = edge.manager.containsSafe(addr)
// Pick a specific message to try to send // Pick a specific message to try to send
val a_type_sel = noiseMaker(3, inc) 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("b000") -> glegal,
UInt("b001") -> pflegal, UInt("b001") -> pflegal,
UInt("b010") -> pplegal, UInt("b010") -> pplegal,
@ -218,14 +220,18 @@ class ClockDivider extends BlackBox {
class TLFuzzRAM extends LazyModule class TLFuzzRAM extends LazyModule
{ {
val model = LazyModule(new TLRAMModel) 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 gpio = LazyModule(new RRTest1(0x400))
val xbar = LazyModule(new TLXbar) val xbar = LazyModule(new TLXbar)
val xbar2= LazyModule(new TLXbar)
val fuzz = LazyModule(new TLFuzzer(5000)) val fuzz = LazyModule(new TLFuzzer(5000))
val cross = LazyModule(new TLAsyncCrossing) val cross = LazyModule(new TLAsyncCrossing)
model.node := fuzz.node 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) cross.node := TLFragmenter(TLBuffer(xbar.node), 4, 256)
ram.node := cross.node ram.node := cross.node
gpio.node := TLFragmenter(TLBuffer(xbar.node), 4, 32) 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? // Who wants what?
val address = edgeIn.address(in.a.bits) 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 hintBitsAtA = handleA && in.a.bits.opcode === TLMessages.Hint
val hintWantsD = in.a.valid && hintBitsAtA val hintWantsD = in.a.valid && hintBitsAtA
val outerWantsD = out.d.valid val outerWantsD = out.d.valid
@ -57,7 +57,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
assert (!hintHoldsD || hintWantsD) assert (!hintHoldsD || hintWantsD)
in.d.valid := Mux(hintWinsD, hintWantsD, outerWantsD) 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 out.d.ready := in.d.ready && !hintHoldsD
in.a.ready := Mux(hintBitsAtA, hintWinsD && in.d.ready, out.a.ready) 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) 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]) case class IntSourcePortParameters(sources: Seq[IntSourceParameters])
{ {
val num = sources.map(_.range.size).sum val num = sources.map(_.range.size).sum
@ -32,6 +42,9 @@ case class IntSourcePortParameters(sources: Seq[IntSourceParameters])
// The interrupts must perfectly cover the range // The interrupts must perfectly cover the range
require (sources.map(_.range.end).max == num) require (sources.map(_.range.end).max == num)
} }
case class IntSinkPortParameters(sinks: Seq[IntSinkParameters])
case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters) case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters)
object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, IntEdge, Vec[Bool]] 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 // Cannot use bulk connect, because the widths could differ
(bo zip bi) foreach { case (o, i) => i := o } (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 IntIdentityNode() extends IdentityNode(IntImp)
case class IntOutputNode() extends OutputNode(IntImp) case class IntOutputNode() extends OutputNode(IntImp)
case class IntInputNode() extends InputNode(IntImp) case class IntInputNode() extends InputNode(IntImp)
case class IntSourceNode(device: String, num: Int) extends SourceNode(IntImp)( case class IntSourceNode(num: Int) extends SourceNode(IntImp)(
IntSourcePortParameters(Seq(IntSourceParameters(device, num))), IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1)
(if (num == 0) 0 else 1) to 1) case class IntSinkNode() extends SinkNode(IntImp)(
case class IntSinkNode() extends SinkNode(IntImp)(IntSinkPortParameters()) IntSinkPortParameters(Seq(IntSinkParameters())))
case class IntAdapterNode( case class IntAdapterNode(
sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters, sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters,
@ -75,7 +93,7 @@ class IntXbar extends LazyModule
val intnode = IntAdapterNode( val intnode = IntAdapterNode(
numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink? numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink?
numSinkPorts = 1 to 128, numSinkPorts = 1 to 128,
sinkFn = { _ => IntSinkPortParameters() }, sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) },
sourceFn = { seq => sourceFn = { seq =>
IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map { IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map {
case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) 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) val mask = edge.full_mask(bundle)
when (bundle.opcode === TLMessages.Acquire) { 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 (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 (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) assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra)
@ -33,7 +33,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.Get) { 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 (source_ok, "'A' channel Get carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Get address not aligned to size" + 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) assert (bundle.param === UInt(0), "'A' channel Get carries invalid param" + extra)
@ -41,7 +41,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.PutFullData) { 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 (source_ok, "'A' channel PutFull carries invalid source ID" + extra)
assert (is_aligned, "'A' channel PutFull address not aligned to size" + 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) assert (bundle.param === UInt(0), "'A' channel PutFull carries invalid param" + extra)
@ -49,7 +49,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.PutPartialData) { 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 (source_ok, "'A' channel PutPartial carries invalid source ID" + extra)
assert (is_aligned, "'A' channel PutPartial address not aligned to size" + 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) assert (bundle.param === UInt(0), "'A' channel PutPartial carries invalid param" + extra)
@ -57,7 +57,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.ArithmeticData) { 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 (source_ok, "'A' channel Arithmetic carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Arithmetic address not aligned to size" + 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) assert (TLAtomics.isArithmetic(bundle.param), "'A' channel Arithmetic carries invalid opcode param" + extra)
@ -65,7 +65,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.LogicalData) { 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 (source_ok, "'A' channel Logical carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Logical address not aligned to size" + 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) assert (TLAtomics.isLogical(bundle.param), "'A' channel Logical carries invalid opcode param" + extra)
@ -73,7 +73,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.Hint) { 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 (source_ok, "'A' channel Hint carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Hint address not aligned to size" + extra) assert (is_aligned, "'A' channel Hint address not aligned to size" + extra)
assert (bundle.mask === mask, "'A' channel Hint contains invalid mask" + 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) assert (TLMessages.isB(bundle.opcode), "'B' channel has invalid opcode" + extra)
// Reuse these subexpressions to save some firrtl lines // 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 is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size)
val mask = edge.full_mask(bundle) val mask = edge.full_mask(bundle)
@ -150,7 +150,7 @@ object TLMonitor
val source_ok = edge.client.contains(bundle.source) 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 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) { when (bundle.opcode === TLMessages.ProbeAck) {
assert (address_ok, "'C' channel ProbeAck carries unmanaged address" + extra) assert (address_ok, "'C' channel ProbeAck carries unmanaged address" + extra)
@ -171,7 +171,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.Release) { 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 (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 (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) assert (is_aligned, "'C' channel Release address not aligned to size" + extra)
@ -180,7 +180,7 @@ object TLMonitor
} }
when (bundle.opcode === TLMessages.ReleaseData) { 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 (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 (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) 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) // 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 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 +112,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 +139,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,12 +154,13 @@ 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 =>
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) " addr 0x%x;\n size 0x%x;\n".format(a.base, a.mask+1)
} }
val footer = "}\n" val footer = "}\n"
@ -158,7 +169,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)
}) })
} }
@ -198,41 +209,59 @@ case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes
val anySupportPutPartial = managers.map(!_.supportsPutPartial.none).reduce(_ || _) val anySupportPutPartial = managers.map(!_.supportsPutPartial.none).reduce(_ || _)
val anySupportHint = managers.map(!_.supportsHint.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 // These return Option[TLManagerParameters] for your convenience
def find(address: BigInt) = managers.find(_.address.exists(_.contains(address))) def find(address: BigInt) = managers.find(_.address.exists(_.contains(address)))
def findById(id: Int) = managers.find(_.sinkId.contains(id)) def findById(id: Int) = managers.find(_.sinkId.contains(id))
// Synthesizable lookup methods // 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 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 // 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 findFifoIdSafe(address: UInt) = Mux1H(findSafe(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 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)))
lazy val addressMask = AddressDecoder(managers.map(_.address)) def hasFifoIdFast(address: UInt) = Mux1H(findFast(address), managers.map(m => Bool(m.fifoId.isDefined)))
// !!! need a cheaper version of find, where we assume a valid address match exists
// Does this Port manage this ID/address? // 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(_ || _) 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(_ && _) val allSame = managers.map(member(_) == member(managers(0))).reduce(_ && _)
if (allSame) member(managers(0)).containsLg(lgSize) else { 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 // Check for support of a given operation at a specific address
val supportsAcquire = safety_helper(_.supportsAcquire) _ val supportsAcquireSafe = safety_helper(_.supportsAcquire, findSafe) _
val supportsArithmetic = safety_helper(_.supportsArithmetic) _ val supportsArithmeticSafe = safety_helper(_.supportsArithmetic, findSafe) _
val supportsLogical = safety_helper(_.supportsLogical) _ val supportsLogicalSafe = safety_helper(_.supportsLogical, findSafe) _
val supportsGet = safety_helper(_.supportsGet) _ val supportsGetSafe = safety_helper(_.supportsGet, findSafe) _
val supportsPutFull = safety_helper(_.supportsPutFull) _ val supportsPutFullSafe = safety_helper(_.supportsPutFull, findSafe) _
val supportsPutPartial = safety_helper(_.supportsPutPartial) _ val supportsPutPartialSafe = safety_helper(_.supportsPutPartial, findSafe) _
val supportsHint = safety_helper(_.supportsHint) _ 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( case class TLClientParameters(
@ -256,6 +285,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]) {

View File

@ -119,7 +119,7 @@ class TLRAMModel extends LazyModule
val a_addr_hi = a.addr_hi | (a_beats1 & ~a_counter1) val a_addr_hi = a.addr_hi | (a_beats1 & ~a_counter1)
val a_base = edge.address(a) val a_base = edge.address(a)
val a_mask = edge.mask(a_base, a_size) 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 // Grab the concurrency state we need
val a_inc_bytes = inc_bytes.map(_.read(a_addr_hi)) 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_base = d_flight.base
val d_addr_hi = d_base >> shift | (d_beats1 & ~d_counter1) val d_addr_hi = d_base >> shift | (d_beats1 & ~d_counter1)
val d_mask = edge.mask(d_base, d_size) 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 // Grab the concurrency state we need
val d_inc_bytes = inc_bytes.map(_.read(d_addr_hi)) val d_inc_bytes = inc_bytes.map(_.read(d_addr_hi))
@ -222,7 +222,8 @@ class TLRAMModel extends LazyModule
// Check the response is correct // Check the response is correct
assert (d_size === d_flight.size) 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 // addr_lo is allowed to differ
when (d_flight.opcode === TLMessages.Hint) { 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), supportsPutFull = TransferSizes(1, beatBytes),
fifoId = Some(0))) // requests are handled in order fifoId = Some(0))) // requests are handled in order
{ {
require (!address.strided) require (address.contiguous)
// Calling this method causes the matching TL2 bundle to be // Calling this method causes the matching TL2 bundle to be
// configured to route all requests to the listed RegFields. // 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 abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Option[Int], beatBytes: Int, undefZero: Boolean) extends LazyModule
{ {
val node = TLRegisterNode(address, concurrency, beatBytes, undefZero) 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]) 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 inputIdRanges = mapInputIds(node.edgesIn.map(_.client))
val outputIdRanges = mapOutputIds(node.edgesOut.map(_.manager)) 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 // We need an intermediate size of bundle with the widest possible identifiers
val wide_bundle = io.in(0).params.union(io.out(0).params) 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)) 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 addressA = (in zip node.edgesIn) map { case (i, e) => (i.a.valid, e.address(i.a.bits)) }
val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.b.valid && i .contains(o.b.bits.source) }) }) val addressC = (in zip node.edgesIn) map { case (i, e) => (i.c.valid, e.address(i.c.bits)) }
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 requestAIO = Vec(addressA.map { i => Vec(outputPorts.map { o => i._1 && o(i._2) }) })
val requestEIO = Vec(in.map { i => Vec(outputIdRanges.map { o => i.e.valid && o .contains(i.e.bits.sink) }) }) 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 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) }) val beatsB = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats(o.b.bits) })