tilelink2: differentiate fast/safe address lookup cases
This commit is contained in:
parent
b4baae4214
commit
b11839f5a1
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -209,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(
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user