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) io.write.ready := Bool(true)
} }
class L2SecondaryMissInfo extends TLBundle
with HasTileLinkBeatId
with HasClientTransactionId
class L2HellaCacheBank extends HierarchicalCoherenceAgent class L2HellaCacheBank extends HierarchicalCoherenceAgent
with L2HellaCacheParameters { with L2HellaCacheParameters {
require(isPow2(nSets)) require(isPow2(nSets))
@ -617,10 +613,7 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
val pending_coh = Reg{ xact_old_meta.coh.clone } val pending_coh = Reg{ xact_old_meta.coh.clone }
// Secondary miss queue // Secondary miss queue
val ignt_q = Module(new Queue(new L2SecondaryMissInfo, nSecondaryMisses))(innerTLParams) val ignt_q = Module(new Queue(new SecondaryMissInfo, 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
// State holding progress made on processing this transaction // State holding progress made on processing this transaction
val iacq_data_done = connectIncomingDataBeatCounter(io.inner.acquire) 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_put ||
can_merge_iacq_get 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 // Track whether any beats are missing from a PutBlock
pending_puts := (pending_puts & dropPendingBitWhenBeatHasData(io.inner.acquire)) pending_puts := (pending_puts & dropPendingBitWhenBeatHasData(io.inner.acquire))
@ -792,22 +791,20 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
addPendingBitWhenBeatHasData(io.inner.release) | addPendingBitWhenBeatHasData(io.inner.release) |
addPendingBitWhenBeatHasData(io.outer.grant) | addPendingBitWhenBeatHasData(io.outer.grant) |
addPendingBitInternal(io.data.resp) addPendingBitInternal(io.data.resp)
ignt_q.io.enq.valid := iacq_data_done
ignt_q.io.deq.ready := ignt_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 && io.inner.grant.valid := state === s_busy &&
ignt_q.io.deq.valid && ignt_q.io.deq.valid &&
(!io.ignt().hasData() || (!io.ignt().hasData() ||
pending_ignt_data(ignt_data_idx)) 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( io.inner.grant.bits := pending_coh.inner.makeGrant(
dst = xact.client_id, // TODO: ignt_q.io.deq.bits.src pri = xact,
acq = xact, sec = ignt_q.io.deq.bits,
client_xact_id = ignt_q.io.deq.bits.client_xact_id,
manager_xact_id = UInt(trackerId), manager_xact_id = UInt(trackerId),
addr_beat = ignt_data_idx,
data = Mux(xact.is(Acquire.putAtomicType), data = Mux(xact.is(Acquire.putAtomicType),
amo_result, amo_result,
data_buffer(ignt_data_idx))) 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( val pending_coh_on_ignt = HierarchicalMetadata(
pending_coh.inner.onGrant(io.ignt()), pending_coh.inner.onGrant(io.ignt()),

View File

@ -3,7 +3,7 @@
package uncore package uncore
import Chisel._ 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 { abstract class CoherenceMetadata extends Bundle {
val co = params(TLCoherencePolicy) val co = params(TLCoherencePolicy)
val id = params(TLId) val id = params(TLId)
@ -15,21 +15,35 @@ abstract class CoherenceMetadata extends Bundle {
* memory operations or [[uncore.Probe]] messages. * memory operations or [[uncore.Probe]] messages.
*/ */
class ClientMetadata extends CoherenceMetadata { class ClientMetadata extends CoherenceMetadata {
/** Actual state information stored in this bundle */
val state = UInt(width = co.clientStateWidth) val state = UInt(width = co.clientStateWidth)
/** Metadata equality */
def ===(rhs: ClientMetadata): Bool = this.state === rhs.state def ===(rhs: ClientMetadata): Bool = this.state === rhs.state
def !=(rhs: ClientMetadata): Bool = !this.===(rhs) 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 isValid(dummy: Int = 0): Bool = co.isValid(this)
def isHit(cmd: UInt): Bool = co.isHit(cmd, this) /** Does this cache have permissions on this block sufficient to perform op */
def isMiss(cmd: UInt): Bool = !co.isHit(cmd, this) def isHit(op_code: UInt): Bool = co.isHit(op_code, this)
def requiresAcquireOnSecondaryMiss(first_cmd: UInt, second_cmd: UInt): Bool = /** Does this cache lack permissions on this block sufficient to perform op */
co.requiresAcquireOnSecondaryMiss(first_cmd, second_cmd, this) def isMiss(op_code: UInt): Bool = !co.isHit(op_code, this)
def requiresReleaseOnCacheControl(cmd: UInt): Bool = /** Does a secondary miss on the block require another Acquire message */
co.requiresReleaseOnCacheControl(cmd: UInt, this) 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 = def requiresVoluntaryWriteback(dummy: Int = 0): Bool =
co.requiresReleaseOnCacheControl(M_FLUSH, this) 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( def makeAcquire(
client_xact_id: UInt, client_xact_id: UInt,
addr_block: UInt, addr_block: UInt,
@ -43,6 +57,13 @@ class ClientMetadata extends CoherenceMetadata {
{ case TLId => id }) { 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( def makeVoluntaryWriteback(
client_xact_id: UInt, client_xact_id: UInt,
addr_block: UInt, addr_block: UInt,
@ -57,6 +78,12 @@ class ClientMetadata extends CoherenceMetadata {
data = data), { case TLId => id }) 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( def makeRelease(
prb: Probe, prb: Probe,
addr_beat: UInt = UInt(0), addr_beat: UInt = UInt(0),
@ -70,16 +97,37 @@ class ClientMetadata extends CoherenceMetadata {
data = data), { case TLId => id }) 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 = def onGrant(incoming: Grant, pending: UInt): ClientMetadata =
Bundle(co.clientMetadataOnGrant(incoming, pending, this), { case TLId => id }) 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 = def onProbe(incoming: Probe): ClientMetadata =
Bundle(co.clientMetadataOnProbe(incoming, this), { case TLId => id }) Bundle(co.clientMetadataOnProbe(incoming, this), { case TLId => id })
def onHit(cmd: UInt): ClientMetadata =
Bundle(co.clientMetadataOnHit(cmd, this), { case TLId => id }) /** New metadata after a op_code hits this block
def onCacheControl(cmd: UInt): ClientMetadata = *
Bundle(co.clientMetadataOnCacheControl(cmd, this), { case TLId => id }) * @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 { object ClientMetadata {
def apply(state: UInt) = { def apply(state: UInt) = {
val meta = new ClientMetadata val meta = new ClientMetadata
@ -89,33 +137,64 @@ object ClientMetadata {
def onReset = new ClientMetadata().co.clientMetadataOnReset def onReset = new ClientMetadata().co.clientMetadataOnReset
} }
/* The ManagerMetadata stores manager-side information about the status /** Stores manager-side information about the status
of a cache block, including whether it has any known sharers. Its * of a cache block, including whether it has any known sharers.
API can be used to create Probe and Grant TileLink messages. *
*/ * Its API can be used to create [[uncore.Probe]] and [[uncore.Grant]] messages.
*/
class ManagerMetadata extends CoherenceMetadata { 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 // 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) val sharers = UInt(width = co.dir.width)
/** Metadata equality */
def ===(rhs: ManagerMetadata): Bool = //this.state === rhs.state && TODO: Fix 0-width wires in Chisel def ===(rhs: ManagerMetadata): Bool = //this.state === rhs.state && TODO: Fix 0-width wires in Chisel
this.sharers === rhs.sharers this.sharers === rhs.sharers
def !=(rhs: ManagerMetadata): Bool = !this.===(rhs) 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(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 = def requiresProbesOnVoluntaryWriteback(dummy: Int = 0): Bool =
co.requiresProbes(M_FLUSH, this) co.requiresProbes(M_FLUSH, this)
def makeProbe(dst: UInt, cmd: UInt, addr_block: UInt): ProbeToDst = /** Construct an appropriate [[uncore.ProbeToDst]] for a given [[uncore.Acquire]]
Bundle(Probe(dst, co.getProbeType(cmd, this), addr_block), { case TLId => id }) *
* @param dst Destination client id for this Probe
* @param acq Acquire message triggering this Probe
*/
def makeProbe(dst: UInt, acq: Acquire): ProbeToDst = def makeProbe(dst: UInt, acq: Acquire): ProbeToDst =
Bundle(Probe(dst, co.getProbeType(acq, this), acq.addr_block), { case TLId => id }) 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 = def makeProbeForVoluntaryWriteback(dst: UInt, addr_block: UInt): ProbeToDst =
makeProbe(dst, M_FLUSH, addr_block) 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 = { def makeGrant(rel: ReleaseFromSrc, manager_xact_id: UInt): GrantToDst = {
Bundle(Grant( Bundle(Grant(
dst = rel.client_id, dst = rel.client_id,
@ -125,6 +204,15 @@ class ManagerMetadata extends CoherenceMetadata {
manager_xact_id = manager_xact_id), { case TLId => id }) 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( def makeGrant(
acq: AcquireFromSrc, acq: AcquireFromSrc,
manager_xact_id: UInt, manager_xact_id: UInt,
@ -142,26 +230,42 @@ class ManagerMetadata extends CoherenceMetadata {
data = data), { case TLId => id }) 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( def makeGrant(
dst: UInt, pri: AcquireFromSrc,
acq: AcquireFromSrc, sec: SecondaryMissInfo,
client_xact_id: UInt,
manager_xact_id: UInt, manager_xact_id: UInt,
addr_beat: UInt,
data: UInt): GrantToDst = { data: UInt): GrantToDst = {
val g = makeGrant(acq, manager_xact_id, addr_beat, data) val g = makeGrant(pri, manager_xact_id, sec.addr_beat, data)
g.client_id := dst g.client_xact_id := sec.client_xact_id
g.client_xact_id := client_xact_id
g g
} }
/** New metadata after receiving a [[uncore.ReleaseFromSrc]]
*
* @param incoming the incoming [[uncore.ReleaseFromSrc]]
*/
def onRelease(incoming: ReleaseFromSrc): ManagerMetadata = def onRelease(incoming: ReleaseFromSrc): ManagerMetadata =
Bundle(co.managerMetadataOnRelease(incoming, incoming.client_id, this), { case TLId => id }) 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 = def onGrant(outgoing: GrantToDst): ManagerMetadata =
Bundle(co.managerMetadataOnGrant(outgoing, outgoing.client_id, this), { case TLId => id }) Bundle(co.managerMetadataOnGrant(outgoing, outgoing.client_id, this), { case TLId => id })
} }
/** Factories for ManagerMetadata, including on reset */
object ManagerMetadata { object ManagerMetadata {
def apply(sharers: UInt, state: UInt = UInt(width = 0)) = { def apply(sharers: UInt, state: UInt = UInt(width = 0)) = {
val meta = new ManagerMetadata val meta = new ManagerMetadata
@ -178,10 +282,14 @@ object ManagerMetadata {
def onReset = new ManagerMetadata().co.managerMetadataOnReset def onReset = new ManagerMetadata().co.managerMetadataOnReset
} }
/* HierarchicalMetadata is used in a cache in a multi-level memory hierarchy /** 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 * that is a manager with respect to some inner caches and a client with
respect to some outer cache. * 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 { class HierarchicalMetadata extends CoherenceMetadata {
val inner: ManagerMetadata = Bundle(new ManagerMetadata, {case TLId => params(InnerTLId)}) val inner: ManagerMetadata = Bundle(new ManagerMetadata, {case TLId => params(InnerTLId)})
val outer: ClientMetadata = Bundle(new ClientMetadata, {case TLId => params(OuterTLId)}) val outer: ClientMetadata = Bundle(new ClientMetadata, {case TLId => params(OuterTLId)})
@ -190,6 +298,7 @@ class HierarchicalMetadata extends CoherenceMetadata {
def !=(rhs: HierarchicalMetadata): Bool = !this.===(rhs) def !=(rhs: HierarchicalMetadata): Bool = !this.===(rhs)
} }
/** Factories for HierarchicalMetadata, including on reset */
object HierarchicalMetadata { object HierarchicalMetadata {
def apply(inner: ManagerMetadata, outer: ClientMetadata): HierarchicalMetadata = { def apply(inner: ManagerMetadata, outer: ClientMetadata): HierarchicalMetadata = {
val m = new HierarchicalMetadata val m = new HierarchicalMetadata
@ -200,5 +309,7 @@ object HierarchicalMetadata {
def onReset: HierarchicalMetadata = apply(ManagerMetadata.onReset, ClientMetadata.onReset) 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] case object InnerTLId extends Field[String]
/** Identifies the TLId of the outer network in a hierarchical cache controller */
case object OuterTLId extends Field[String] case object OuterTLId extends Field[String]

View File

@ -785,6 +785,13 @@ class ClientTileLinkIOWrapper extends TLModule {
io.out.release.valid := Bool(false) 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 /** 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 * to [[uncore.Grant]] that it receives from a manager and forwards to a client
*/ */