Metadata docs and api cleanup
This commit is contained in:
parent
f66a9fd7a6
commit
4c7969b2b3
@ -338,10 +338,6 @@ class L2DataArray(delay: Int) extends L2HellaCacheModule {
|
||||
io.write.ready := Bool(true)
|
||||
}
|
||||
|
||||
class L2SecondaryMissInfo extends TLBundle
|
||||
with HasTileLinkBeatId
|
||||
with HasClientTransactionId
|
||||
|
||||
class L2HellaCacheBank extends HierarchicalCoherenceAgent
|
||||
with L2HellaCacheParameters {
|
||||
require(isPow2(nSets))
|
||||
@ -617,10 +613,7 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
|
||||
val pending_coh = Reg{ xact_old_meta.coh.clone }
|
||||
|
||||
// Secondary miss queue
|
||||
val ignt_q = Module(new Queue(new L2SecondaryMissInfo, nSecondaryMisses))(innerTLParams)
|
||||
ignt_q.io.enq.bits.client_xact_id := io.iacq().client_xact_id
|
||||
ignt_q.io.enq.bits.addr_beat := io.iacq().addr_beat
|
||||
// TODO add ignt.dst <- iacq.src
|
||||
val ignt_q = Module(new Queue(new SecondaryMissInfo, nSecondaryMisses))(innerTLParams)
|
||||
|
||||
// State holding progress made on processing this transaction
|
||||
val iacq_data_done = connectIncomingDataBeatCounter(io.inner.acquire)
|
||||
@ -741,6 +734,12 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
|
||||
can_merge_iacq_put ||
|
||||
can_merge_iacq_get
|
||||
|
||||
// Enqueue secondary miss information
|
||||
ignt_q.io.enq.valid := iacq_data_done
|
||||
ignt_q.io.enq.bits.client_xact_id := io.iacq().client_xact_id
|
||||
ignt_q.io.enq.bits.addr_beat := io.iacq().addr_beat
|
||||
// TODO add ignt.dst <- iacq.src
|
||||
|
||||
// Track whether any beats are missing from a PutBlock
|
||||
pending_puts := (pending_puts & dropPendingBitWhenBeatHasData(io.inner.acquire))
|
||||
|
||||
@ -792,22 +791,20 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
|
||||
addPendingBitWhenBeatHasData(io.inner.release) |
|
||||
addPendingBitWhenBeatHasData(io.outer.grant) |
|
||||
addPendingBitInternal(io.data.resp)
|
||||
ignt_q.io.enq.valid := iacq_data_done
|
||||
ignt_q.io.deq.ready := ignt_data_done
|
||||
// Make the Grant message using the data stored in the secondary miss queue
|
||||
io.inner.grant.valid := state === s_busy &&
|
||||
ignt_q.io.deq.valid &&
|
||||
(!io.ignt().hasData() ||
|
||||
pending_ignt_data(ignt_data_idx))
|
||||
// Make the Grant message using the data stored in the secondary miss queue
|
||||
io.inner.grant.bits := pending_coh.inner.makeGrant(
|
||||
dst = xact.client_id, // TODO: ignt_q.io.deq.bits.src
|
||||
acq = xact,
|
||||
client_xact_id = ignt_q.io.deq.bits.client_xact_id,
|
||||
pri = xact,
|
||||
sec = ignt_q.io.deq.bits,
|
||||
manager_xact_id = UInt(trackerId),
|
||||
addr_beat = ignt_data_idx,
|
||||
data = Mux(xact.is(Acquire.putAtomicType),
|
||||
amo_result,
|
||||
data_buffer(ignt_data_idx)))
|
||||
io.inner.grant.bits.addr_beat := ignt_data_idx // override based on outgoing counter
|
||||
|
||||
val pending_coh_on_ignt = HierarchicalMetadata(
|
||||
pending_coh.inner.onGrant(io.ignt()),
|
||||
|
@ -3,7 +3,7 @@
|
||||
package uncore
|
||||
import Chisel._
|
||||
|
||||
// Classes to represent coherence information in clients and managers
|
||||
/** Base class to represent coherence information in clients and managers */
|
||||
abstract class CoherenceMetadata extends Bundle {
|
||||
val co = params(TLCoherencePolicy)
|
||||
val id = params(TLId)
|
||||
@ -15,21 +15,35 @@ abstract class CoherenceMetadata extends Bundle {
|
||||
* memory operations or [[uncore.Probe]] messages.
|
||||
*/
|
||||
class ClientMetadata extends CoherenceMetadata {
|
||||
/** Actual state information stored in this bundle */
|
||||
val state = UInt(width = co.clientStateWidth)
|
||||
|
||||
/** Metadata equality */
|
||||
def ===(rhs: ClientMetadata): Bool = this.state === rhs.state
|
||||
def !=(rhs: ClientMetadata): Bool = !this.===(rhs)
|
||||
|
||||
/** Is the block's data present in this cache */
|
||||
def isValid(dummy: Int = 0): Bool = co.isValid(this)
|
||||
def isHit(cmd: UInt): Bool = co.isHit(cmd, this)
|
||||
def isMiss(cmd: UInt): Bool = !co.isHit(cmd, this)
|
||||
def requiresAcquireOnSecondaryMiss(first_cmd: UInt, second_cmd: UInt): Bool =
|
||||
co.requiresAcquireOnSecondaryMiss(first_cmd, second_cmd, this)
|
||||
def requiresReleaseOnCacheControl(cmd: UInt): Bool =
|
||||
co.requiresReleaseOnCacheControl(cmd: UInt, this)
|
||||
/** Does this cache have permissions on this block sufficient to perform op */
|
||||
def isHit(op_code: UInt): Bool = co.isHit(op_code, this)
|
||||
/** Does this cache lack permissions on this block sufficient to perform op */
|
||||
def isMiss(op_code: UInt): Bool = !co.isHit(op_code, this)
|
||||
/** Does a secondary miss on the block require another Acquire message */
|
||||
def requiresAcquireOnSecondaryMiss(first_op: UInt, second_op: UInt): Bool =
|
||||
co.requiresAcquireOnSecondaryMiss(first_op, second_op, this)
|
||||
/** Does op require a Release to be made to outer memory */
|
||||
def requiresReleaseOnCacheControl(op_code: UInt): Bool =
|
||||
co.requiresReleaseOnCacheControl(op_code: UInt, this)
|
||||
/** Does an eviction require a Release to be made to outer memory */
|
||||
def requiresVoluntaryWriteback(dummy: Int = 0): Bool =
|
||||
co.requiresReleaseOnCacheControl(M_FLUSH, this)
|
||||
|
||||
/** Constructs an Acquire message based on this metdata and a memory operation
|
||||
*
|
||||
* @param client_xact_id client's transaction id
|
||||
* @param addr_block address of the cache block
|
||||
* @param op_code a memory operation from [[uncore.MemoryOpConstants]]
|
||||
*/
|
||||
def makeAcquire(
|
||||
client_xact_id: UInt,
|
||||
addr_block: UInt,
|
||||
@ -43,6 +57,13 @@ class ClientMetadata extends CoherenceMetadata {
|
||||
{ case TLId => id })
|
||||
}
|
||||
|
||||
/** Constructs a Release message based on this metadata on an eviction
|
||||
*
|
||||
* @param client_xact_id client's transaction id
|
||||
* @param addr_block address of the cache block
|
||||
* @param addr_beat sub-block address (which beat)
|
||||
* @param data data being written back
|
||||
*/
|
||||
def makeVoluntaryWriteback(
|
||||
client_xact_id: UInt,
|
||||
addr_block: UInt,
|
||||
@ -57,6 +78,12 @@ class ClientMetadata extends CoherenceMetadata {
|
||||
data = data), { case TLId => id })
|
||||
}
|
||||
|
||||
/** Constructs a Release message based on this metadata and a [[uncore.Probe]]
|
||||
*
|
||||
* @param the incoming [[uncore.Probe]]
|
||||
* @param addr_beat sub-block address (which beat)
|
||||
* @param data data being released
|
||||
*/
|
||||
def makeRelease(
|
||||
prb: Probe,
|
||||
addr_beat: UInt = UInt(0),
|
||||
@ -70,16 +97,37 @@ class ClientMetadata extends CoherenceMetadata {
|
||||
data = data), { case TLId => id })
|
||||
}
|
||||
|
||||
/** New metadata after receiving a [[uncore.Grant]]
|
||||
*
|
||||
* @param incoming the incoming [[uncore.Grant]]
|
||||
* @param pending the mem op that triggered this transaction
|
||||
*/
|
||||
def onGrant(incoming: Grant, pending: UInt): ClientMetadata =
|
||||
Bundle(co.clientMetadataOnGrant(incoming, pending, this), { case TLId => id })
|
||||
|
||||
/** New metadata after receiving a [[uncore.Probe]]
|
||||
*
|
||||
* @param incoming the incoming [[uncore.Probe]]
|
||||
*/
|
||||
def onProbe(incoming: Probe): ClientMetadata =
|
||||
Bundle(co.clientMetadataOnProbe(incoming, this), { case TLId => id })
|
||||
def onHit(cmd: UInt): ClientMetadata =
|
||||
Bundle(co.clientMetadataOnHit(cmd, this), { case TLId => id })
|
||||
def onCacheControl(cmd: UInt): ClientMetadata =
|
||||
Bundle(co.clientMetadataOnCacheControl(cmd, this), { case TLId => id })
|
||||
|
||||
/** New metadata after a op_code hits this block
|
||||
*
|
||||
* @param op_code a memory operation from [[uncore.MemoryOpConstants]]
|
||||
*/
|
||||
def onHit(op_code: UInt): ClientMetadata =
|
||||
Bundle(co.clientMetadataOnHit(op_code, this), { case TLId => id })
|
||||
|
||||
/** New metadata after receiving a [[uncore.Probe]]
|
||||
*
|
||||
* @param op_code a memory operation from [[uncore.MemoryOpConstants]]
|
||||
*/
|
||||
def onCacheControl(op_code: UInt): ClientMetadata =
|
||||
Bundle(co.clientMetadataOnCacheControl(op_code, this), { case TLId => id })
|
||||
}
|
||||
|
||||
/** Factories for ClientMetadata, including on reset */
|
||||
object ClientMetadata {
|
||||
def apply(state: UInt) = {
|
||||
val meta = new ClientMetadata
|
||||
@ -89,33 +137,64 @@ object ClientMetadata {
|
||||
def onReset = new ClientMetadata().co.clientMetadataOnReset
|
||||
}
|
||||
|
||||
/* The ManagerMetadata stores manager-side information about the status
|
||||
of a cache block, including whether it has any known sharers. Its
|
||||
API can be used to create Probe and Grant TileLink messages.
|
||||
*/
|
||||
/** Stores manager-side information about the status
|
||||
* of a cache block, including whether it has any known sharers.
|
||||
*
|
||||
* Its API can be used to create [[uncore.Probe]] and [[uncore.Grant]] messages.
|
||||
*/
|
||||
class ManagerMetadata extends CoherenceMetadata {
|
||||
// Currently no coherence policies assume manager-side state information
|
||||
// val state = UInt(width = co.masterStateWidth) TODO: Fix 0-width wires in Chisel
|
||||
|
||||
/** The directory information for this block */
|
||||
val sharers = UInt(width = co.dir.width)
|
||||
|
||||
/** Metadata equality */
|
||||
def ===(rhs: ManagerMetadata): Bool = //this.state === rhs.state && TODO: Fix 0-width wires in Chisel
|
||||
this.sharers === rhs.sharers
|
||||
def !=(rhs: ManagerMetadata): Bool = !this.===(rhs)
|
||||
def full(dummy: Int = 0) = co.dir.full(this.sharers)
|
||||
|
||||
/** Converts the directory info into an N-hot sharer bitvector (i.e. full representation) */
|
||||
def full(dummy: Int = 0): UInt = co.dir.full(this.sharers)
|
||||
|
||||
/** Does this [[uncore.Acquire]] require [[uncore.Probes]] to be sent */
|
||||
def requiresProbes(acq: Acquire): Bool = co.requiresProbes(acq, this)
|
||||
def requiresProbes(cmd: UInt): Bool = co.requiresProbes(cmd, this)
|
||||
/** Does this memory op require [[uncore.Probes]] to be sent */
|
||||
def requiresProbes(op_code: UInt): Bool = co.requiresProbes(op_code, this)
|
||||
/** Does an eviction require [[uncore.Probes]] to be sent */
|
||||
def requiresProbesOnVoluntaryWriteback(dummy: Int = 0): Bool =
|
||||
co.requiresProbes(M_FLUSH, this)
|
||||
|
||||
def makeProbe(dst: UInt, cmd: UInt, addr_block: UInt): ProbeToDst =
|
||||
Bundle(Probe(dst, co.getProbeType(cmd, this), addr_block), { case TLId => id })
|
||||
|
||||
/** Construct an appropriate [[uncore.ProbeToDst]] for a given [[uncore.Acquire]]
|
||||
*
|
||||
* @param dst Destination client id for this Probe
|
||||
* @param acq Acquire message triggering this Probe
|
||||
*/
|
||||
def makeProbe(dst: UInt, acq: Acquire): ProbeToDst =
|
||||
Bundle(Probe(dst, co.getProbeType(acq, this), acq.addr_block), { case TLId => id })
|
||||
|
||||
/** Construct an appropriate [[uncore.ProbeToDst]] for a given mem op
|
||||
*
|
||||
* @param dst Destination client id for this Probe
|
||||
* @param op_code memory operation triggering this Probe
|
||||
* @param addr_block address of the cache block being probed
|
||||
*/
|
||||
def makeProbe(dst: UInt, op_code: UInt, addr_block: UInt): ProbeToDst =
|
||||
Bundle(Probe(dst, co.getProbeType(op_code, this), addr_block), { case TLId => id })
|
||||
|
||||
/** Construct an appropriate [[uncore.ProbeToDst]] for an eviction
|
||||
*
|
||||
* @param dst Destination client id for this Probe
|
||||
* @param addr_block address of the cache block being probed prior to eviction
|
||||
*/
|
||||
def makeProbeForVoluntaryWriteback(dst: UInt, addr_block: UInt): ProbeToDst =
|
||||
makeProbe(dst, M_FLUSH, addr_block)
|
||||
|
||||
/** Construct an appropriate [[uncore.GrantToDst]] to acknowledge an [[uncore.Release]]
|
||||
*
|
||||
* @param rel Release message being acknowledged by this Grant
|
||||
* @param manager_xact_id manager's transaction id
|
||||
*/
|
||||
def makeGrant(rel: ReleaseFromSrc, manager_xact_id: UInt): GrantToDst = {
|
||||
Bundle(Grant(
|
||||
dst = rel.client_id,
|
||||
@ -125,6 +204,15 @@ class ManagerMetadata extends CoherenceMetadata {
|
||||
manager_xact_id = manager_xact_id), { case TLId => id })
|
||||
}
|
||||
|
||||
/** Construct an appropriate [[uncore.GrantToDst]] to respond to an [[uncore.Acquire]]
|
||||
*
|
||||
* May contain single or multiple beats of data, or just be a permissions upgrade.
|
||||
*
|
||||
* @param acq Acquire message being responded to by this Grant
|
||||
* @param manager_xact_id manager's transaction id
|
||||
* @param addr_beat beat id of the data
|
||||
* @param data data being refilled to the original requestor
|
||||
*/
|
||||
def makeGrant(
|
||||
acq: AcquireFromSrc,
|
||||
manager_xact_id: UInt,
|
||||
@ -142,26 +230,42 @@ class ManagerMetadata extends CoherenceMetadata {
|
||||
data = data), { case TLId => id })
|
||||
}
|
||||
|
||||
/** Construct an [[uncore.GrantToDst]] to respond to an [[uncore.Acquire]] with some overrides
|
||||
*
|
||||
* Used to respond to secondary misses merged into this transaction.
|
||||
* May contain single or multiple beats of data.
|
||||
*
|
||||
* @param pri Primary miss's Acquire message, used to get g_type and dst
|
||||
* @param sec Secondary miss info, used to get beat and client_xact_id
|
||||
* @param manager_xact_id manager's transaction id
|
||||
* @param data data being refilled to the original requestor
|
||||
*/
|
||||
def makeGrant(
|
||||
dst: UInt,
|
||||
acq: AcquireFromSrc,
|
||||
client_xact_id: UInt,
|
||||
pri: AcquireFromSrc,
|
||||
sec: SecondaryMissInfo,
|
||||
manager_xact_id: UInt,
|
||||
addr_beat: UInt,
|
||||
data: UInt): GrantToDst = {
|
||||
val g = makeGrant(acq, manager_xact_id, addr_beat, data)
|
||||
g.client_id := dst
|
||||
g.client_xact_id := client_xact_id
|
||||
val g = makeGrant(pri, manager_xact_id, sec.addr_beat, data)
|
||||
g.client_xact_id := sec.client_xact_id
|
||||
g
|
||||
}
|
||||
|
||||
/** New metadata after receiving a [[uncore.ReleaseFromSrc]]
|
||||
*
|
||||
* @param incoming the incoming [[uncore.ReleaseFromSrc]]
|
||||
*/
|
||||
def onRelease(incoming: ReleaseFromSrc): ManagerMetadata =
|
||||
Bundle(co.managerMetadataOnRelease(incoming, incoming.client_id, this), { case TLId => id })
|
||||
|
||||
/** New metadata after sending a [[uncore.GrantToDst]]
|
||||
*
|
||||
* @param outgoing the outgoing [[uncore.GrantToDst]]
|
||||
*/
|
||||
def onGrant(outgoing: GrantToDst): ManagerMetadata =
|
||||
Bundle(co.managerMetadataOnGrant(outgoing, outgoing.client_id, this), { case TLId => id })
|
||||
}
|
||||
|
||||
/** Factories for ManagerMetadata, including on reset */
|
||||
object ManagerMetadata {
|
||||
def apply(sharers: UInt, state: UInt = UInt(width = 0)) = {
|
||||
val meta = new ManagerMetadata
|
||||
@ -178,10 +282,14 @@ object ManagerMetadata {
|
||||
def onReset = new ManagerMetadata().co.managerMetadataOnReset
|
||||
}
|
||||
|
||||
/* HierarchicalMetadata is used in a cache in a multi-level memory hierarchy
|
||||
that is a Manager with respect to some inner caches and a Client with
|
||||
respect to some outer cache.
|
||||
*/
|
||||
/** HierarchicalMetadata is used in a cache in a multi-level memory hierarchy
|
||||
* that is a manager with respect to some inner caches and a client with
|
||||
* respect to some outer cache.
|
||||
*
|
||||
* This class makes use of two different sets of TileLink parameters, which are
|
||||
* applied by contextually mapping [[uncore.TLId]] to one of
|
||||
* [[uncore.InnerTLId]] or [[uncore.OuterTLId]].
|
||||
*/
|
||||
class HierarchicalMetadata extends CoherenceMetadata {
|
||||
val inner: ManagerMetadata = Bundle(new ManagerMetadata, {case TLId => params(InnerTLId)})
|
||||
val outer: ClientMetadata = Bundle(new ClientMetadata, {case TLId => params(OuterTLId)})
|
||||
@ -190,6 +298,7 @@ class HierarchicalMetadata extends CoherenceMetadata {
|
||||
def !=(rhs: HierarchicalMetadata): Bool = !this.===(rhs)
|
||||
}
|
||||
|
||||
/** Factories for HierarchicalMetadata, including on reset */
|
||||
object HierarchicalMetadata {
|
||||
def apply(inner: ManagerMetadata, outer: ClientMetadata): HierarchicalMetadata = {
|
||||
val m = new HierarchicalMetadata
|
||||
@ -200,5 +309,7 @@ object HierarchicalMetadata {
|
||||
def onReset: HierarchicalMetadata = apply(ManagerMetadata.onReset, ClientMetadata.onReset)
|
||||
}
|
||||
|
||||
/** Identifies the TLId of the inner network in a hierarchical cache controller */
|
||||
case object InnerTLId extends Field[String]
|
||||
/** Identifies the TLId of the outer network in a hierarchical cache controller */
|
||||
case object OuterTLId extends Field[String]
|
||||
|
@ -785,6 +785,13 @@ class ClientTileLinkIOWrapper extends TLModule {
|
||||
io.out.release.valid := Bool(false)
|
||||
}
|
||||
|
||||
/** Used to track metadata for transactions where multiple secondary misses have been merged
|
||||
* and handled by a single transaction tracker.
|
||||
*/
|
||||
class SecondaryMissInfo extends TLBundle // TODO: add a_type to merge e.g. Get+GetBlocks, and/or HasClientId
|
||||
with HasTileLinkBeatId
|
||||
with HasClientTransactionId
|
||||
|
||||
/** A helper module that automatically issues [[uncore.Finish]] messages in repsonse
|
||||
* to [[uncore.Grant]] that it receives from a manager and forwards to a client
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user