diplomacy: improve PMA circuit QoR
This commit is contained in:
@ -57,7 +57,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
// Don't overprovision the CAM
|
||||
val camSize = min(domainsNeedingHelp.size, concurrency)
|
||||
// Compact the fifoIds to only those we care about
|
||||
val camFifoIds = managers.map(m => UInt(m.fifoId.map(id => max(0, domainsNeedingHelp.indexOf(id))).getOrElse(0)))
|
||||
def camFifoId(m: TLManagerParameters) = m.fifoId.map(id => max(0, domainsNeedingHelp.indexOf(id))).getOrElse(0)
|
||||
|
||||
// CAM entry state machine
|
||||
val FREE = UInt(0) // unused waiting on Atomic from A
|
||||
@ -65,11 +65,6 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
val AMO = UInt(2) // AccessDataAck sent up D waiting for A availability
|
||||
val ACK = UInt(1) // Put sent down A waiting for PutAck from D
|
||||
|
||||
def helper(select: Seq[Bool], x: Seq[TransferSizes], lgSize: UInt) =
|
||||
if (!passthrough) Bool(false) else
|
||||
if (x.map(_ == x(0)).reduce(_ && _)) x(0).containsLg(lgSize) else
|
||||
Mux1H(select, x.map(_.containsLg(lgSize)))
|
||||
|
||||
val params = TLAtomicAutomata.CAMParams(out.a.bits.params, domainsNeedingHelp.size)
|
||||
// Do we need to do anything at all?
|
||||
if (camSize > 0) {
|
||||
@ -85,10 +80,10 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
val cam_dmatch = cam_s.map(e => e.state =/= FREE) // D should inspect these entries
|
||||
|
||||
// Can the manager already handle this message?
|
||||
val a_address = edgeIn.address(in.a.bits)
|
||||
val a_size = edgeIn.size(in.a.bits)
|
||||
val a_select = edgeOut.manager.findFast(edgeIn.address(in.a.bits))
|
||||
val a_canLogical = helper(a_select, managers.map(_.supportsLogical), a_size)
|
||||
val a_canArithmetic = helper(a_select, managers.map(_.supportsArithmetic), a_size)
|
||||
val a_canLogical = Bool(passthrough) && edgeOut.manager.supportsLogicalFast (a_address, a_size)
|
||||
val a_canArithmetic = Bool(passthrough) && edgeOut.manager.supportsArithmeticFast(a_address, a_size)
|
||||
val a_isLogical = in.a.bits.opcode === TLMessages.LogicalData
|
||||
val a_isArithmetic = in.a.bits.opcode === TLMessages.ArithmeticData
|
||||
val a_isSupported = Mux(a_isLogical, a_canLogical, Mux(a_isArithmetic, a_canArithmetic, Bool(true)))
|
||||
@ -103,7 +98,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
val a_d = a_cam_d.data
|
||||
|
||||
// Does the A request conflict with an inflight AMO?
|
||||
val a_fifoId = Mux1H(a_select, camFifoIds)
|
||||
val a_fifoId = edgeOut.manager.fastProperty(a_address, camFifoId _, (i:Int) => UInt(i))
|
||||
val a_cam_busy = (cam_abusy zip cam_a.map(_.fifoId === a_fifoId)) map { case (a,b) => a&&b } reduce (_||_)
|
||||
|
||||
// (Where) are we are allocating in the CAM?
|
||||
|
@ -101,20 +101,30 @@ case class TLManagerPortParameters(
|
||||
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)))
|
||||
|
||||
// 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(_ || _)))
|
||||
// The fast version assumes the address is valid (you probably want fastProperty instead of this function)
|
||||
def findFast(address: UInt) = {
|
||||
val routingMask = AddressDecoder(managers.map(_.address))
|
||||
Vec(managers.map(_.address.map(_.widen(~routingMask)).distinct.map(_.contains(address)).reduce(_ || _)))
|
||||
}
|
||||
|
||||
// Compute the simplest AddressSets that decide a key
|
||||
def fastPropertyGroup[K](p: TLManagerParameters => K): Map[K, Seq[AddressSet]] = {
|
||||
val groups = managers.map(m => (p(m), m.address)).groupBy(_._1).mapValues(_.flatMap(_._2))
|
||||
val reductionMask = AddressDecoder(groups.values.toList)
|
||||
groups.mapValues(seq => AddressSet.unify(seq.map(_.widen(~reductionMask)).distinct))
|
||||
}
|
||||
// Select a property
|
||||
def fastProperty[K, D <: Data](address: UInt, p: TLManagerParameters => K, d: K => D): D =
|
||||
Mux1H(fastPropertyGroup(p).map { case (v, a) => (a.map(_.contains(address)).reduce(_||_), d(v)) })
|
||||
|
||||
// Note: returns the actual fifoId + 1 or 0 if None
|
||||
def findFifoIdFast(address: UInt) = Mux1H(findFast(address), managers.map(m => UInt(m.fifoId.map(_+1).getOrElse(0))))
|
||||
def hasFifoIdFast(address: UInt) = Mux1H(findFast(address), managers.map(m => Bool(m.fifoId.isDefined)))
|
||||
def findFifoIdFast(address: UInt) = fastProperty(address, _.fifoId.map(_+1).getOrElse(0), (i:Int) => UInt(i))
|
||||
def hasFifoIdFast(address: UInt) = fastProperty(address, _.fifoId.isDefined, (b:Boolean) => Bool(b))
|
||||
|
||||
// Does this Port manage this ID/address?
|
||||
def containsSafe(address: UInt) = findSafe(address).reduce(_ || _)
|
||||
|
Reference in New Issue
Block a user