1
0

Metadata docs and api cleanup

This commit is contained in:
Henry Cook 2015-04-20 16:32:09 -07:00
parent f66a9fd7a6
commit 4c7969b2b3
3 changed files with 160 additions and 45 deletions

View File

@ -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()),

View File

@ -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,9 +282,13 @@ 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)})
@ -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]

View File

@ -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
*/