2015-03-01 02:02:13 +01:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
package uncore
|
|
|
|
import Chisel._
|
|
|
|
|
|
|
|
// Classes to represent coherence information in clients and managers
|
|
|
|
abstract class CoherenceMetadata extends Bundle {
|
|
|
|
val co = params(TLCoherencePolicy)
|
|
|
|
val id = params(TLId)
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The ClientMetadata 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 TileLink Probes.
|
|
|
|
*/
|
|
|
|
class ClientMetadata extends CoherenceMetadata {
|
|
|
|
val state = UInt(width = co.clientStateWidth)
|
|
|
|
|
|
|
|
def ===(rhs: ClientMetadata): Bool = this.state === rhs.state
|
2015-03-24 10:06:53 +01:00
|
|
|
def !=(rhs: ClientMetadata): Bool = !this.===(rhs)
|
2015-03-01 02:02:13 +01:00
|
|
|
|
|
|
|
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)
|
|
|
|
def requiresVoluntaryWriteback(dummy: Int = 0): Bool =
|
|
|
|
co.requiresReleaseOnCacheControl(M_FLUSH, this)
|
|
|
|
|
|
|
|
def makeAcquire(
|
|
|
|
client_xact_id: UInt,
|
|
|
|
addr_block: UInt,
|
|
|
|
op_code: UInt): Acquire = {
|
|
|
|
Bundle(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))),
|
|
|
|
{ case TLId => id })
|
|
|
|
}
|
|
|
|
|
|
|
|
def makeVoluntaryWriteback(
|
|
|
|
client_xact_id: UInt,
|
|
|
|
addr_block: UInt,
|
|
|
|
addr_beat: UInt = UInt(0),
|
|
|
|
data: UInt = UInt(0)): Release = {
|
|
|
|
Bundle(Release(
|
|
|
|
voluntary = Bool(true),
|
|
|
|
r_type = co.getReleaseType(M_FLUSH, this),
|
|
|
|
client_xact_id = client_xact_id,
|
|
|
|
addr_block = addr_block,
|
|
|
|
addr_beat = addr_beat,
|
|
|
|
data = data), { case TLId => id })
|
|
|
|
}
|
|
|
|
|
|
|
|
def makeRelease(
|
|
|
|
prb: Probe,
|
|
|
|
client_xact_id: UInt,
|
|
|
|
addr_beat: UInt = UInt(0),
|
|
|
|
data: UInt = UInt(0)): Release = {
|
|
|
|
Bundle(Release(
|
|
|
|
voluntary = Bool(false),
|
|
|
|
r_type = co.getReleaseType(prb, this),
|
|
|
|
client_xact_id = client_xact_id,
|
|
|
|
addr_block = prb.addr_block,
|
|
|
|
addr_beat = addr_beat,
|
|
|
|
data = data), { case TLId => id })
|
|
|
|
}
|
|
|
|
|
|
|
|
def onGrant(incoming: Grant, pending: UInt): ClientMetadata =
|
|
|
|
Bundle(co.clientMetadataOnGrant(incoming, pending, this), { case TLId => id })
|
|
|
|
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 })
|
|
|
|
}
|
|
|
|
|
|
|
|
object ClientMetadata {
|
|
|
|
def apply(state: UInt) = {
|
|
|
|
val meta = new ClientMetadata
|
|
|
|
meta.state := state
|
|
|
|
meta
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
class ManagerMetadata extends CoherenceMetadata {
|
|
|
|
// val state = UInt(width = co.masterStateWidth) TODO: Fix 0-width wires in Chisel
|
|
|
|
val sharers = UInt(width = co.dir.width)
|
|
|
|
|
|
|
|
def ===(rhs: ManagerMetadata): Bool = //this.state === rhs.state && TODO: Fix 0-width wires in Chisel
|
|
|
|
this.sharers === rhs.sharers
|
2015-03-24 10:06:53 +01:00
|
|
|
def !=(rhs: ManagerMetadata): Bool = !this.===(rhs)
|
2015-03-01 02:02:13 +01:00
|
|
|
def full(dummy: Int = 0) = co.dir.full(this.sharers)
|
|
|
|
|
|
|
|
def requiresProbes(acq: Acquire): Bool = co.requiresProbes(acq, this)
|
|
|
|
def requiresProbes(cmd: UInt): Bool = co.requiresProbes(cmd, this)
|
|
|
|
def requiresProbesOnVoluntaryWriteback(dummy: Int = 0): Bool =
|
|
|
|
co.requiresProbes(M_FLUSH, this)
|
|
|
|
|
|
|
|
def makeProbe(cmd: UInt, addr_block: UInt): Probe =
|
|
|
|
Bundle(Probe(co.getProbeType(cmd, this), addr_block), { case TLId => id })
|
|
|
|
|
|
|
|
def makeProbe(acq: Acquire): Probe =
|
|
|
|
Bundle(Probe(co.getProbeType(acq, this), acq.addr_block), { case TLId => id })
|
|
|
|
|
|
|
|
def makeProbeForVoluntaryWriteback(addr_block: UInt): Probe =
|
|
|
|
makeProbe(M_FLUSH, addr_block)
|
|
|
|
|
|
|
|
def makeGrant(rel: Release, manager_xact_id: UInt): Grant = {
|
|
|
|
Bundle(Grant(
|
|
|
|
is_builtin_type = Bool(true),
|
|
|
|
g_type = Grant.voluntaryAckType,
|
|
|
|
client_xact_id = rel.client_xact_id,
|
|
|
|
manager_xact_id = manager_xact_id), { case TLId => id })
|
|
|
|
}
|
|
|
|
|
|
|
|
def makeGrant(
|
|
|
|
acq: Acquire,
|
|
|
|
manager_xact_id: UInt,
|
|
|
|
addr_beat: UInt = UInt(0),
|
|
|
|
data: UInt = UInt(0)): Grant = {
|
|
|
|
Bundle(Grant(
|
|
|
|
is_builtin_type = acq.isBuiltInType(),
|
|
|
|
g_type = Mux(acq.isBuiltInType(),
|
|
|
|
acq.getBuiltInGrantType(),
|
|
|
|
co.getGrantType(acq, this)),
|
|
|
|
client_xact_id = acq.client_xact_id,
|
|
|
|
manager_xact_id = manager_xact_id,
|
|
|
|
addr_beat = addr_beat,
|
|
|
|
data = data), { case TLId => id })
|
|
|
|
}
|
|
|
|
|
|
|
|
def onRelease(incoming: Release, src: UInt): ManagerMetadata =
|
|
|
|
Bundle(co.managerMetadataOnRelease(incoming, src, this), { case TLId => id })
|
|
|
|
|
|
|
|
def onGrant(outgoing: Grant, dst: UInt): ManagerMetadata =
|
|
|
|
Bundle(co.managerMetadataOnGrant(outgoing, dst, this), { case TLId => id })
|
|
|
|
}
|
|
|
|
|
|
|
|
object ManagerMetadata {
|
|
|
|
def apply(sharers: UInt, state: UInt = UInt(width = 0)) = {
|
|
|
|
val meta = new ManagerMetadata
|
|
|
|
//meta.state := state TODO: Fix 0-width wires in Chisel
|
|
|
|
meta.sharers := sharers
|
|
|
|
meta
|
|
|
|
}
|
|
|
|
def apply() = {
|
|
|
|
val meta = new ManagerMetadata
|
|
|
|
//meta.state := UInt(width = 0) TODO: Fix 0-width wires in Chisel
|
|
|
|
meta.sharers := meta.co.dir.flush
|
|
|
|
meta
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
class HierarchicalMetadata extends CoherenceMetadata {
|
|
|
|
val inner: ManagerMetadata = Bundle(new ManagerMetadata, {case TLId => params(InnerTLId)})
|
|
|
|
val outer: ClientMetadata = Bundle(new ClientMetadata, {case TLId => params(OuterTLId)})
|
|
|
|
def ===(rhs: HierarchicalMetadata): Bool =
|
|
|
|
this.inner === rhs.inner && this.outer === rhs.outer
|
2015-03-24 10:06:53 +01:00
|
|
|
def !=(rhs: HierarchicalMetadata): Bool = !this.===(rhs)
|
2015-03-01 02:02:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
object HierarchicalMetadata {
|
|
|
|
def apply(inner: ManagerMetadata, outer: ClientMetadata): HierarchicalMetadata = {
|
|
|
|
val m = new HierarchicalMetadata
|
|
|
|
m.inner := inner
|
|
|
|
m.outer := outer
|
|
|
|
m
|
|
|
|
}
|
|
|
|
def onReset: HierarchicalMetadata = apply(ManagerMetadata.onReset, ClientMetadata.onReset)
|
|
|
|
}
|
|
|
|
|
|
|
|
case object InnerTLId extends Field[String]
|
|
|
|
case object OuterTLId extends Field[String]
|