1
0

reorganize moving non-submodule packages into src/main/scala

This commit is contained in:
Howard Mao
2016-08-19 10:58:56 -07:00
parent f78da0b0ea
commit 7b20609d4d
110 changed files with 3 additions and 381 deletions

View File

@ -0,0 +1,43 @@
// See LICENSE for license details.
package uncore.coherence
import Chisel._
// This class encapsulates transformations on different directory information
// storage formats
abstract class DirectoryRepresentation(val width: Int) {
def pop(prev: UInt, id: UInt): UInt
def push(prev: UInt, id: UInt): UInt
def flush: UInt
def none(s: UInt): Bool
def one(s: UInt): Bool
def count(s: UInt): UInt
def next(s: UInt): UInt
def full(s: UInt): UInt
}
abstract trait HasDirectoryRepresentation {
val dir: DirectoryRepresentation
}
class NullRepresentation(nClients: Int) extends DirectoryRepresentation(1) {
def pop(prev: UInt, id: UInt) = UInt(0)
def push(prev: UInt, id: UInt) = UInt(0)
def flush = UInt(0)
def none(s: UInt) = Bool(false)
def one(s: UInt) = Bool(false)
def count(s: UInt) = UInt(nClients)
def next(s: UInt) = UInt(0)
def full(s: UInt) = SInt(-1, width = nClients).asUInt
}
class FullRepresentation(nClients: Int) extends DirectoryRepresentation(nClients) {
def pop(prev: UInt, id: UInt) = prev & ~UIntToOH(id)
def push(prev: UInt, id: UInt) = prev | UIntToOH(id)
def flush = UInt(0, width = width)
def none(s: UInt) = s === UInt(0)
def one(s: UInt) = PopCount(s) === UInt(1)
def count(s: UInt) = PopCount(s)
def next(s: UInt) = PriorityEncoder(s)
def full(s: UInt) = s
}

View File

@ -0,0 +1,344 @@
// See LICENSE for license details.
package uncore.coherence
import Chisel._
import uncore.tilelink._
import uncore.constants._
import cde.{Parameters, Field}
/** 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]
/** Base class to represent coherence information in clients and managers */
abstract class CoherenceMetadata(implicit p: Parameters) extends TLBundle()(p) {
val co = tlCoh
}
/** Stores the client-side coherence information,
* such as permissions on the data and whether the data is dirty.
* Its API can be used to make TileLink messages in response to
* memory operations or [[uncore.Probe]] messages.
*/
class ClientMetadata(implicit p: Parameters) extends CoherenceMetadata()(p) {
/** 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)
/** 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.constants.MemoryOpConstants]]
*/
def makeAcquire(
op_code: UInt,
client_xact_id: UInt,
addr_block: UInt): Acquire = {
Acquire(
is_builtin_type = Bool(false),
a_type = co.getAcquireType(op_code, this),
client_xact_id = client_xact_id,
addr_block = addr_block,
union = Cat(op_code, Bool(true)))(p)
}
/** Constructs a Release message based on this metadata on cache control op
*
* @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 makeVoluntaryRelease(
op_code: UInt,
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt = UInt(0),
data: UInt = UInt(0)): Release =
Release(
voluntary = Bool(true),
r_type = co.getReleaseType(op_code, this),
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = addr_beat,
data = data)(p)
/** 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,
addr_beat: UInt = UInt(0),
data: UInt = UInt(0)): Release =
makeVoluntaryRelease(
op_code = M_FLUSH,
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = addr_beat,
data = data)
/** 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),
data: UInt = UInt(0)): Release =
Release(
voluntary = Bool(false),
r_type = co.getReleaseType(prb, this),
client_xact_id = UInt(0),
addr_block = prb.addr_block,
addr_beat = addr_beat,
data = data)(p)
/** 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 =
co.clientMetadataOnGrant(incoming, pending, this)
/** New metadata after receiving a [[uncore.Probe]]
*
* @param incoming the incoming [[uncore.Probe]]
*/
def onProbe(incoming: Probe): ClientMetadata =
co.clientMetadataOnProbe(incoming, this)
/** New metadata after a op_code hits this block
*
* @param op_code a memory operation from [[uncore.constants.MemoryOpConstants]]
*/
def onHit(op_code: UInt): ClientMetadata =
co.clientMetadataOnHit(op_code, this)
/** New metadata after op_code releases permissions on this block
*
* @param op_code a memory operation from [[uncore.constants.MemoryOpConstants]]
*/
def onCacheControl(op_code: UInt): ClientMetadata =
co.clientMetadataOnCacheControl(op_code, this)
}
/** Factories for ClientMetadata, including on reset */
object ClientMetadata {
def apply(state: UInt)(implicit p: Parameters) = {
val meta = Wire(new ClientMetadata)
meta.state := state
meta
}
def onReset(implicit p: Parameters) = ClientMetadata(UInt(0))(p) // TODO: assumes clientInvalid === 0
}
/** 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(implicit p: Parameters) extends CoherenceMetadata()(p) {
// 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)
/** 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.Probe Probes]] to be sent */
def requiresProbes(acq: HasAcquireType): Bool = co.requiresProbes(acq, this)
/** Does this memory op require [[uncore.Probe Probes]] to be sent */
def requiresProbes(op_code: UInt): Bool = co.requiresProbes(op_code, this)
/** Does an eviction require [[uncore.Probe Probes]] to be sent */
def requiresProbesOnVoluntaryWriteback(dummy: Int = 0): Bool =
co.requiresProbes(M_FLUSH, this)
/** 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
* @param addr_block address of the cache block being probed
*/
def makeProbe(dst: UInt, acq: HasAcquireType, addr_block: UInt): ProbeToDst =
Probe(dst, co.getProbeType(acq, this), addr_block)(p)
/** 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: AcquireMetadata): ProbeToDst =
Probe(dst, co.getProbeType(acq, this), acq.addr_block)(p)
/** 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 =
Probe(dst, co.getProbeType(op_code, this), addr_block)(p)
/** 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
*/
def makeGrant(rel: ReleaseMetadata with HasClientId): GrantToDst =
Grant(
dst = rel.client_id,
is_builtin_type = Bool(true),
g_type = Grant.voluntaryAckType,
client_xact_id = rel.client_xact_id,
manager_xact_id = UInt(0))(p)
/** 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: AcquireMetadata with HasClientId,
manager_xact_id: UInt,
addr_beat: UInt = UInt(0),
data: UInt = UInt(0)): GrantToDst =
Grant(
dst = acq.client_id,
is_builtin_type = acq.isBuiltInType(),
g_type = co.getGrantType(acq, this),
client_xact_id = acq.client_xact_id,
manager_xact_id = manager_xact_id,
addr_beat = addr_beat,
data = data)(p)
/** 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 sec Secondary miss info
* @param manager_xact_id manager's transaction id
* @param data data being refilled to the original requestor
*/
def makeGrant(
sec: SecondaryMissInfo,
manager_xact_id: UInt,
data: UInt): GrantToDst = {
Grant(
dst = sec.client_id,
is_builtin_type = sec.isBuiltInType(),
g_type = co.getGrantType(sec, this),
client_xact_id = sec.client_xact_id,
manager_xact_id = manager_xact_id,
addr_beat = sec.addr_beat,
data = data)(p)
}
/** New metadata after receiving a [[uncore.ReleaseFromSrc]]
*
* @param incoming the incoming [[uncore.ReleaseFromSrc]]
*/
def onRelease(incoming: ReleaseMetadata with HasClientId): ManagerMetadata =
co.managerMetadataOnRelease(incoming, incoming.client_id, this)
/** New metadata after sending a [[uncore.GrantToDst]]
*
* @param outgoing the outgoing [[uncore.GrantToDst]]
*/
def onGrant(outgoing: GrantMetadata with HasClientId): ManagerMetadata =
co.managerMetadataOnGrant(outgoing, outgoing.client_id, this)
}
/** Factories for ManagerMetadata, including on reset */
object ManagerMetadata {
def apply(sharers: UInt, state: UInt = UInt(width = 0))(implicit p: Parameters) = {
val meta = Wire(new ManagerMetadata)
//meta.state := state TODO: Fix 0-width wires in Chisel
meta.sharers := sharers
meta
}
def apply(implicit p: Parameters) = {
val meta = Wire(new ManagerMetadata)
//meta.state := UInt(width = 0) TODO: Fix 0-width wires in Chisel
meta.sharers := meta.co.dir.flush
meta
}
def onReset(implicit p: Parameters) = ManagerMetadata(p)
}
/** 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(implicit p: Parameters) extends CoherenceMetadata()(p) {
val inner: ManagerMetadata = new ManagerMetadata()(p.alterPartial({case TLId => p(InnerTLId)}))
val outer: ClientMetadata = new ClientMetadata()(p.alterPartial({case TLId => p(OuterTLId)}))
def ===(rhs: HierarchicalMetadata): Bool =
this.inner === rhs.inner && this.outer === rhs.outer
def =/=(rhs: HierarchicalMetadata): Bool = !this.===(rhs)
}
/** Factories for HierarchicalMetadata, including on reset */
object HierarchicalMetadata {
def apply(inner: ManagerMetadata, outer: ClientMetadata)
(implicit p: Parameters): HierarchicalMetadata = {
val m = Wire(new HierarchicalMetadata)
m.inner := inner
m.outer := outer
m
}
def onReset(implicit p: Parameters): HierarchicalMetadata =
apply(ManagerMetadata.onReset, ClientMetadata.onReset)
}

View File

@ -0,0 +1,696 @@
// See LICENSE for license details.
package uncore.coherence
import Chisel._
import uncore.tilelink._
import uncore.constants._
import uncore.util._
/** The entire CoherencePolicy API consists of the following three traits:
* HasCustomTileLinkMessageTypes, used to define custom messages
* HasClientSideCoherencePolicy, for client coherence agents
* HasManagerSideCoherencePolicy, for manager coherence agents
*/
abstract class CoherencePolicy(val dir: DirectoryRepresentation)
extends HasCustomTileLinkMessageTypes
with HasClientSideCoherencePolicy
with HasManagerSideCoherencePolicy
/** This API defines the custom, coherence-policy-defined message types,
* as opposed to the built-in ones found in tilelink.scala.
* Policies must enumerate the custom messages to be sent over each
* channel, as well as which of them have associated data.
*/
trait HasCustomTileLinkMessageTypes {
val nAcquireTypes: Int
def acquireTypeWidth = log2Up(nAcquireTypes)
val nProbeTypes: Int
def probeTypeWidth = log2Up(nProbeTypes)
val nReleaseTypes: Int
def releaseTypeWidth = log2Up(nReleaseTypes)
val nGrantTypes: Int
def grantTypeWidth = log2Up(nGrantTypes)
val acquireTypesWithData = Nil // Only built-in Acquire types have data for now
def releaseTypesWithData: Seq[UInt]
def grantTypesWithData: Seq[UInt]
}
/** This API contains all functions required for client coherence agents.
* Policies must enumerate the number of client states and define their
* permissions with respect to memory operations. Policies must fill in functions
* to control which messages are sent and how metadata is updated in response
* to coherence events. These funtions are generally called from within the
* ClientMetadata class in metadata.scala
*/
trait HasClientSideCoherencePolicy {
// Client coherence states and their permissions
val nClientStates: Int
def clientStateWidth = log2Ceil(nClientStates)
def clientStatesWithReadPermission: Seq[UInt]
def clientStatesWithWritePermission: Seq[UInt]
def clientStatesWithDirtyData: Seq[UInt]
// Transaction initiation logic
def isValid(meta: ClientMetadata): Bool
def isHit(cmd: UInt, meta: ClientMetadata): Bool = {
Mux(isWriteIntent(cmd),
meta.state isOneOf clientStatesWithWritePermission,
meta.state isOneOf clientStatesWithReadPermission)
}
//TODO: Assumes all states with write permissions also have read permissions
def requiresAcquireOnSecondaryMiss(
first_cmd: UInt,
second_cmd: UInt,
meta: ClientMetadata): Bool = {
isWriteIntent(second_cmd) && !isWriteIntent(first_cmd)
}
//TODO: Assumes all cache ctrl ops writeback dirty data, and
// doesn't issue transaction when e.g. downgrading Exclusive to Shared:
def requiresReleaseOnCacheControl(cmd: UInt, meta: ClientMetadata): Bool =
meta.state isOneOf clientStatesWithDirtyData
// Determine which custom message type to use
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt
def getReleaseType(p: HasProbeType, meta: ClientMetadata): UInt
// Mutate ClientMetadata based on messages or cmds
def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata): ClientMetadata
def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata): ClientMetadata
def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata): ClientMetadata
def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata): ClientMetadata
}
/** This API contains all functions required for manager coherence agents.
* Policies must enumerate the number of manager states. Policies must fill
* in functions to control which Probe and Grant messages are sent and how
* metadata should be updated in response to coherence events. These funtions
* are generally called from within the ManagerMetadata class in metadata.scala
*/
trait HasManagerSideCoherencePolicy extends HasDirectoryRepresentation {
val nManagerStates: Int
def masterStateWidth = log2Ceil(nManagerStates)
// Transaction probing logic
def requiresProbes(acq: HasAcquireType, meta: ManagerMetadata): Bool
def requiresProbes(cmd: UInt, meta: ManagerMetadata): Bool
// Determine which custom message type to use in response
def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt
def getProbeType(acq: HasAcquireType, meta: ManagerMetadata): UInt
def getGrantType(acq: HasAcquireType, meta: ManagerMetadata): UInt
def getExclusiveGrantType(): UInt
// Mutate ManagerMetadata based on messages or cmds
def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata): ManagerMetadata
def managerMetadataOnGrant(outgoing: HasGrantType, dst: UInt, meta: ManagerMetadata) =
ManagerMetadata(sharers=Mux(outgoing.isBuiltInType(), // Assumes all built-ins are uncached
meta.sharers,
dir.push(meta.sharers, dst)))(meta.p)
//state = meta.state) TODO: Fix 0-width wires in Chisel
}
/** The following concrete implementations of CoherencePolicy each provide the
* functionality of one particular protocol.
*/
/** A simple protocol with only two Client states.
* Data is always assumed to be dirty.
* Only a single client may ever have a copy of a block at a time.
*/
class MICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
// Message types
val nAcquireTypes = 1
val nProbeTypes = 2
val nReleaseTypes = 4
val nGrantTypes = 1
val acquireExclusive :: Nil = Enum(UInt(), nAcquireTypes)
val probeInvalidate :: probeCopy :: Nil = Enum(UInt(), nProbeTypes)
val releaseInvalidateData :: releaseCopyData :: releaseInvalidateAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantExclusive :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseCopyData)
def grantTypesWithData = Seq(grantExclusive)
// Client states and functions
val nClientStates = 2
val clientInvalid :: clientValid :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Seq(clientValid)
def clientStatesWithWritePermission = Seq(clientValid)
def clientStatesWithDirtyData = Seq(clientValid)
def isValid (meta: ClientMetadata): Bool = meta.state =/= clientInvalid
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt = acquireExclusive
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseCopyData, releaseCopyAck),
M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck)))
}
def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt =
MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> getReleaseType(M_FLUSH, meta),
probeCopy -> getReleaseType(M_FLUSH, meta)))
def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) = meta
def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(Mux(cmd === M_FLUSH, clientInvalid, meta.state))(meta.p)
def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) =
ClientMetadata(Mux(incoming.isBuiltInType(), clientInvalid, clientValid))(meta.p)
def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) =
ClientMetadata(Mux(incoming.p_type === probeInvalidate,
clientInvalid, meta.state))(meta.p)
// Manager states and functions:
val nManagerStates = 0 // We don't actually need any states for this protocol
def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) = !dir.none(meta.sharers)
def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers)
def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt =
MuxLookup(cmd, probeCopy, Array(
M_FLUSH -> probeInvalidate))
def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(),
MuxLookup(a.a_type, probeCopy, Array(
Acquire.getBlockType -> probeCopy,
Acquire.putBlockType -> probeInvalidate,
Acquire.getType -> probeCopy,
Acquire.putType -> probeInvalidate,
Acquire.getPrefetchType -> probeCopy,
Acquire.putPrefetchType -> probeInvalidate,
Acquire.putAtomicType -> probeInvalidate)),
probeInvalidate)
def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type), grantExclusive)
def getExclusiveGrantType(): UInt = grantExclusive
def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = {
val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p)
MuxCase(meta, Array(
incoming.is(releaseInvalidateData) -> popped,
incoming.is(releaseInvalidateAck) -> popped))
}
}
/** A simple protocol with only three Client states.
* Data is marked as dirty when written.
* Only a single client may ever have a copy of a block at a time.
*/
class MEICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
// Message types
val nAcquireTypes = 2
val nProbeTypes = 3
val nReleaseTypes = 6
val nGrantTypes = 1
val acquireExclusiveClean :: acquireExclusiveDirty :: Nil = Enum(UInt(), nAcquireTypes)
val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes)
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantExclusive :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Seq(grantExclusive)
// Client states and functions
val nClientStates = 3
val clientInvalid :: clientExclusiveClean :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Seq(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty)
def isValid (meta: ClientMetadata) = meta.state =/= clientInvalid
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt =
Mux(isWriteIntent(cmd), acquireExclusiveDirty, acquireExclusiveClean)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck)))
}
def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt =
MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> getReleaseType(M_FLUSH, meta),
probeDowngrade -> getReleaseType(M_FLUSH, meta),
probeCopy -> getReleaseType(M_FLUSH, meta)))
def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, meta.state))(meta.p)
def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
MuxLookup(cmd, meta.state, Array(
M_FLUSH -> clientInvalid,
M_CLEAN -> Mux(meta.state === clientExclusiveDirty, clientExclusiveClean, meta.state))))(meta.p)
def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
Mux(incoming.isBuiltInType(), clientInvalid,
Mux(isWrite(cmd), clientExclusiveDirty, clientExclusiveClean)))(meta.p)
def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) =
ClientMetadata(
MuxLookup(incoming.p_type, meta.state, Array(
probeInvalidate -> clientInvalid,
probeDowngrade -> clientInvalid,
probeCopy -> clientInvalid)))(meta.p)
// Manager states and functions:
val nManagerStates = 0 // We don't actually need any states for this protocol
def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) = !dir.none(meta.sharers)
def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers)
def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt =
MuxLookup(cmd, probeCopy, Array(
M_FLUSH -> probeInvalidate,
M_PRODUCE -> probeDowngrade))
def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(),
MuxLookup(a.a_type, probeCopy, Array(
Acquire.getBlockType -> probeCopy,
Acquire.putBlockType -> probeInvalidate,
Acquire.getType -> probeCopy,
Acquire.putType -> probeInvalidate,
Acquire.getPrefetchType -> probeCopy,
Acquire.putPrefetchType -> probeInvalidate,
Acquire.putAtomicType -> probeInvalidate)),
probeInvalidate)
def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type), grantExclusive)
def getExclusiveGrantType(): UInt = grantExclusive
def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = {
val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p)
MuxCase(meta, Array(
incoming.is(releaseInvalidateData) -> popped,
incoming.is(releaseInvalidateAck) -> popped))
}
}
/** A protocol with only three Client states.
* Data is always assumed to be dirty.
* Multiple clients may share read permissions on a block at the same time.
*/
class MSICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
// Message types
val nAcquireTypes = 2
val nProbeTypes = 3
val nReleaseTypes = 6
val nGrantTypes = 3
val acquireShared :: acquireExclusive :: Nil = Enum(UInt(), nAcquireTypes)
val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes)
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantShared :: grantExclusive :: grantExclusiveAck :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Seq(grantShared, grantExclusive)
// Client states and functions
val nClientStates = 3
val clientInvalid :: clientShared :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty)
def isValid(meta: ClientMetadata): Bool = meta.state =/= clientInvalid
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt =
Mux(isWriteIntent(cmd), acquireExclusive, acquireShared)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck)))
}
def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt =
MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> getReleaseType(M_FLUSH, meta),
probeDowngrade -> getReleaseType(M_PRODUCE, meta),
probeCopy -> getReleaseType(M_PRODUCE, meta)))
def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, meta.state))(meta.p)
def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
MuxLookup(cmd, meta.state, Array(
M_FLUSH -> clientInvalid,
M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission,
clientShared, meta.state))))(meta.p)
def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
Mux(incoming.isBuiltInType(), clientInvalid,
MuxLookup(incoming.g_type, clientInvalid, Array(
grantShared -> clientShared,
grantExclusive -> clientExclusiveDirty,
grantExclusiveAck -> clientExclusiveDirty))))(meta.p)
def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) =
ClientMetadata(
MuxLookup(incoming.p_type, meta.state, Array(
probeInvalidate -> clientInvalid,
probeDowngrade -> clientShared,
probeCopy -> clientShared)))(meta.p)
// Manager states and functions:
val nManagerStates = 0 // TODO: We could add a Shared state to avoid probing
// only a single sharer (also would need
// notification msg to track clean drops)
// Also could avoid probes on outer WBs.
def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) =
Mux(dir.none(meta.sharers), Bool(false),
Mux(dir.one(meta.sharers), Bool(true), //TODO: for now we assume it's Exclusive
Mux(a.isBuiltInType(), a.hasData(), a.a_type =/= acquireShared)))
def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers)
def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt =
MuxLookup(cmd, probeCopy, Array(
M_FLUSH -> probeInvalidate,
M_PRODUCE -> probeDowngrade))
def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(),
MuxLookup(a.a_type, probeCopy, Array(
Acquire.getBlockType -> probeCopy,
Acquire.putBlockType -> probeInvalidate,
Acquire.getType -> probeCopy,
Acquire.putType -> probeInvalidate,
Acquire.getPrefetchType -> probeCopy,
Acquire.putPrefetchType -> probeInvalidate,
Acquire.putAtomicType -> probeInvalidate)),
MuxLookup(a.a_type, probeCopy, Array(
acquireShared -> probeDowngrade,
acquireExclusive -> probeInvalidate)))
def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type),
Mux(a.a_type === acquireShared,
Mux(!dir.none(meta.sharers), grantShared, grantExclusive),
grantExclusive))
def getExclusiveGrantType(): UInt = grantExclusive
def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = {
val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p)
MuxCase(meta, Array(
incoming.is(releaseInvalidateData) -> popped,
incoming.is(releaseInvalidateAck) -> popped))
}
}
/** A protocol with four Client states.
* Data is marked as dirty when written.
* Multiple clients may share read permissions on a block at the same time.
*/
class MESICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
// Message types
val nAcquireTypes = 2
val nProbeTypes = 3
val nReleaseTypes = 6
val nGrantTypes = 3
val acquireShared :: acquireExclusive :: Nil = Enum(UInt(), nAcquireTypes)
val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes)
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantShared :: grantExclusive :: grantExclusiveAck :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Seq(grantShared, grantExclusive)
// Client states and functions
val nClientStates = 4
val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty)
def isValid(meta: ClientMetadata): Bool = meta.state =/= clientInvalid
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt =
Mux(isWriteIntent(cmd), acquireExclusive, acquireShared)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck)))
}
def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt =
MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> getReleaseType(M_FLUSH, meta),
probeDowngrade -> getReleaseType(M_PRODUCE, meta),
probeCopy -> getReleaseType(M_PRODUCE, meta)))
def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, meta.state))(meta.p)
def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
MuxLookup(cmd, meta.state, Array(
M_FLUSH -> clientInvalid,
M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission,
clientShared, meta.state),
M_CLEAN -> Mux(meta.state === clientExclusiveDirty,
clientExclusiveClean, meta.state))))(meta.p)
def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
Mux(incoming.isBuiltInType(), clientInvalid,
MuxLookup(incoming.g_type, clientInvalid, Array(
grantShared -> clientShared,
grantExclusive -> Mux(isWrite(cmd), clientExclusiveDirty, clientExclusiveClean),
grantExclusiveAck -> clientExclusiveDirty))))(meta.p)
def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) =
ClientMetadata(
MuxLookup(incoming.p_type, meta.state, Array(
probeInvalidate -> clientInvalid,
probeDowngrade -> clientShared,
probeCopy -> clientShared)))(meta.p)
// Manager states and functions:
val nManagerStates = 0 // TODO: We could add a Shared state to avoid probing
// only a single sharer (also would need
// notification msg to track clean drops)
// Also could avoid probes on outer WBs.
def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) =
Mux(dir.none(meta.sharers), Bool(false),
Mux(dir.one(meta.sharers), Bool(true), //TODO: for now we assume it's Exclusive
Mux(a.isBuiltInType(), a.hasData(), a.a_type =/= acquireShared)))
def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers)
def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt =
MuxLookup(cmd, probeCopy, Array(
M_FLUSH -> probeInvalidate,
M_PRODUCE -> probeDowngrade))
def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(),
MuxLookup(a.a_type, probeCopy, Array(
Acquire.getBlockType -> probeCopy,
Acquire.putBlockType -> probeInvalidate,
Acquire.getType -> probeCopy,
Acquire.putType -> probeInvalidate,
Acquire.getPrefetchType -> probeCopy,
Acquire.putPrefetchType -> probeInvalidate,
Acquire.putAtomicType -> probeInvalidate)),
MuxLookup(a.a_type, probeCopy, Array(
acquireShared -> probeDowngrade,
acquireExclusive -> probeInvalidate)))
def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type),
Mux(a.a_type === acquireShared,
Mux(!dir.none(meta.sharers), grantShared, grantExclusive),
grantExclusive))
def getExclusiveGrantType(): UInt = grantExclusive
def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = {
val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p)
MuxCase(meta, Array(
incoming.is(releaseInvalidateData) -> popped,
incoming.is(releaseInvalidateAck) -> popped))
}
}
class MigratoryCoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
// Message types
val nAcquireTypes = 3
val nProbeTypes = 4
val nReleaseTypes = 10
val nGrantTypes = 4
val acquireShared :: acquireExclusive :: acquireInvalidateOthers :: Nil = Enum(UInt(), nAcquireTypes)
val probeInvalidate :: probeDowngrade :: probeCopy :: probeInvalidateOthers :: Nil = Enum(UInt(), nProbeTypes)
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: releaseDowngradeDataMigratory :: releaseDowngradeAckHasCopy :: releaseInvalidateDataMigratory :: releaseInvalidateAckMigratory :: Nil = Enum(UInt(), nReleaseTypes)
val grantShared :: grantExclusive :: grantExclusiveAck :: grantReadMigratory :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData, releaseInvalidateDataMigratory, releaseDowngradeDataMigratory)
def grantTypesWithData = Seq(grantShared, grantExclusive, grantReadMigratory)
// Client states and functions
val nClientStates = 7
val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: clientSharedByTwo :: clientMigratoryClean :: clientMigratoryDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveClean, clientExclusiveDirty, clientSharedByTwo, clientMigratoryClean, clientMigratoryDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty, clientMigratoryClean, clientMigratoryDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty, clientMigratoryDirty)
def isValid (meta: ClientMetadata): Bool = meta.state =/= clientInvalid
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt =
Mux(isWriteIntent(cmd),
Mux(meta.state === clientInvalid, acquireExclusive, acquireInvalidateOthers),
acquireShared)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck)))
}
def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt = {
val dirty = meta.state isOneOf clientStatesWithDirtyData
val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array(
probeInvalidate -> Mux(meta.state isOneOf (clientExclusiveDirty, clientMigratoryDirty),
releaseInvalidateDataMigratory, releaseInvalidateData),
probeDowngrade -> Mux(meta.state === clientMigratoryDirty,
releaseDowngradeDataMigratory, releaseDowngradeData),
probeCopy -> releaseCopyData))
val without_data = MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> Mux(clientExclusiveClean === meta.state,
releaseInvalidateAckMigratory, releaseInvalidateAck),
probeInvalidateOthers -> Mux(clientSharedByTwo === meta.state,
releaseInvalidateAckMigratory, releaseInvalidateAck),
probeDowngrade -> Mux(meta.state =/= clientInvalid,
releaseDowngradeAckHasCopy, releaseDowngradeAck),
probeCopy -> Mux(meta.state =/= clientInvalid,
releaseDowngradeAckHasCopy, releaseDowngradeAck)))
Mux(dirty, with_data, without_data)
}
def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
Mux(isWrite(cmd), MuxLookup(meta.state, clientExclusiveDirty, Array(
clientExclusiveClean -> clientExclusiveDirty,
clientMigratoryClean -> clientMigratoryDirty)),
meta.state))(meta.p)
def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
MuxLookup(cmd, meta.state, Array(
M_FLUSH -> clientInvalid,
M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission,
clientShared, meta.state),
M_CLEAN -> MuxLookup(meta.state, meta.state, Array(
clientExclusiveDirty -> clientExclusiveClean,
clientMigratoryDirty -> clientMigratoryClean)))))(meta.p)
def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) =
ClientMetadata(
Mux(incoming.isBuiltInType(), clientInvalid,
MuxLookup(incoming.g_type, clientInvalid, Array(
grantShared -> clientShared,
grantExclusive -> Mux(isWrite(cmd), clientExclusiveDirty, clientExclusiveClean),
grantExclusiveAck -> clientExclusiveDirty,
grantReadMigratory -> Mux(isWrite(cmd),
clientMigratoryDirty, clientMigratoryClean)))))(meta.p)
def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) = {
val downgradeState = MuxLookup(meta.state, clientShared, Array(
clientExclusiveClean -> clientSharedByTwo,
clientExclusiveDirty -> clientSharedByTwo,
clientSharedByTwo -> clientShared,
clientMigratoryClean -> clientSharedByTwo,
clientMigratoryDirty -> clientInvalid))
ClientMetadata(
MuxLookup(incoming.p_type, meta.state, Array(
probeInvalidate -> clientInvalid,
probeInvalidateOthers -> clientInvalid,
probeDowngrade -> downgradeState,
probeCopy -> downgradeState)))(meta.p)
}
// Manager states and functions:
val nManagerStates = 0 // TODO: we could add some states to reduce the number of message types
def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) =
Mux(dir.none(meta.sharers), Bool(false),
Mux(dir.one(meta.sharers), Bool(true), //TODO: for now we assume it's Exclusive
Mux(a.isBuiltInType(), a.hasData(), a.a_type =/= acquireShared)))
def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers)
def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt =
MuxLookup(cmd, probeCopy, Array(
M_FLUSH -> probeInvalidate,
M_PRODUCE -> probeDowngrade))
def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(),
MuxLookup(a.a_type, probeCopy, Array(
Acquire.getBlockType -> probeCopy,
Acquire.putBlockType -> probeInvalidate,
Acquire.getType -> probeCopy,
Acquire.putType -> probeInvalidate,
Acquire.getPrefetchType -> probeCopy,
Acquire.putPrefetchType -> probeInvalidate,
Acquire.putAtomicType -> probeInvalidate)),
MuxLookup(a.a_type, probeCopy, Array(
acquireShared -> probeDowngrade,
acquireExclusive -> probeInvalidate,
acquireInvalidateOthers -> probeInvalidateOthers)))
def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt =
Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type),
MuxLookup(a.a_type, grantShared, Array(
acquireShared -> Mux(!dir.none(meta.sharers), grantShared, grantExclusive),
acquireExclusive -> grantExclusive,
acquireInvalidateOthers -> grantExclusiveAck))) //TODO: add this to MESI for broadcast?
def getExclusiveGrantType(): UInt = grantExclusive
def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = {
val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p)
MuxCase(meta, Array(
incoming.is(releaseInvalidateData) -> popped,
incoming.is(releaseInvalidateAck) -> popped,
incoming.is(releaseInvalidateDataMigratory) -> popped,
incoming.is(releaseInvalidateAckMigratory) -> popped))
}
}