1
0

standardizing sbt build conventions

This commit is contained in:
Henry Cook
2013-08-15 15:57:16 -07:00
parent 17d404b325
commit 3763cd0004
11 changed files with 20 additions and 0 deletions

View File

@ -0,0 +1,955 @@
package uncore
import Chisel._
abstract trait CoherenceAgentRole
abstract trait ClientCoherenceAgent extends CoherenceAgentRole
abstract trait MasterCoherenceAgent extends CoherenceAgentRole
abstract class CoherencePolicy {
def nClientStates: Int
def nMasterStates: Int
def nAcquireTypes: Int
def nProbeTypes: Int
def nReleaseTypes: Int
def nGrantTypes: Int
def clientStateWidth = log2Up(nClientStates)
def masterStateWidth = log2Up(nMasterStates)
def acquireTypeWidth = log2Up(nAcquireTypes)
def probeTypeWidth = log2Up(nProbeTypes)
def releaseTypeWidth = log2Up(nReleaseTypes)
def grantTypeWidth = log2Up(nGrantTypes)
def isHit (cmd: UInt, state: UInt): Bool
def isValid (state: UInt): Bool
def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire): Bool
def needsTransactionOnCacheControl(cmd: UInt, state: UInt): Bool
def needsWriteback (state: UInt): Bool
def newStateOnHit(cmd: UInt, state: UInt): UInt
def newStateOnCacheControl(cmd: UInt): UInt
def newStateOnWriteback(): UInt
def newStateOnFlush(): UInt
def newStateOnGrant(incoming: Grant, outstanding: Acquire): UInt
def newStateOnProbe(incoming: Probe, state: UInt): Bits
def getAcquireTypeOnPrimaryMiss(cmd: UInt, state: UInt): UInt
def getAcquireTypeOnSecondaryMiss(cmd: UInt, state: UInt, outstanding: Acquire): UInt
def getProbeType(a_type: UInt, global_state: UInt): UInt
def getReleaseTypeOnCacheControl(cmd: UInt): Bits
def getReleaseTypeOnVoluntaryWriteback(): Bits
def getReleaseTypeOnProbe(incoming: Probe, state: UInt): Bits
def getGrantType(a_type: UInt, count: UInt): Bits
def getGrantType(rel: Release, count: UInt): Bits
def messageHasData (rel: SourcedMessage): Bool
def messageUpdatesDataArray (reply: Grant): Bool
def messageIsUncached(acq: Acquire): Bool
def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool
def isVoluntary(rel: Release): Bool
def isVoluntary(gnt: Grant): Bool
def needsOuterRead(a_type: UInt, global_state: UInt): Bool
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool
def needsAckReply(a_type: UInt, global_state: UInt): Bool
def needsSelfProbe(acq: Acquire): Bool
def requiresAck(grant: Grant): Bool
def requiresAck(release: Release): Bool
def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool
def uSIntListContains(list: List[UInt], elem: UInt): Bool = list.map(elem === _).reduceLeft(_||_)
}
trait UncachedTransactions {
def getUncachedReadAcquireType: Bits
def getUncachedWriteAcquireType: Bits
def getUncachedReadWordAcquireType: Bits
def getUncachedWriteWordAcquireType: Bits
def getUncachedAtomicAcquireType: Bits
def isUncachedReadTransaction(acq: Acquire): Bool
}
abstract class CoherencePolicyWithUncached extends CoherencePolicy with UncachedTransactions
abstract class IncoherentPolicy extends CoherencePolicy {
// UNIMPLEMENTED
def newStateOnProbe(incoming: Probe, state: UInt): Bits = state
def getReleaseTypeOnProbe(incoming: Probe, state: UInt): Bits = Bits(0)
def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = Bool(false)
def getGrantType(a_type: UInt, count: UInt): Bits = Bits(0)
def getGrantType(rel: Release, count: UInt): Bits = Bits(0)
def getProbeType(a_type: UInt, global_state: UInt): UInt = UInt(0)
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = Bool(false)
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = Bool(false)
def needsAckReply(a_type: UInt, global_state: UInt): Bool = Bool(false)
def needsSelfProbe(acq: Acquire) = Bool(false)
def requiresAck(grant: Grant) = Bool(true)
def requiresAck(release: Release) = Bool(false)
def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = Bool(false)
}
class ThreeStateIncoherence extends IncoherentPolicy {
def nClientStates = 3
def nMasterStates = 0
def nAcquireTypes = 3
def nProbeTypes = 0
def nReleaseTypes = 2
def nGrantTypes = 3
val tileInvalid :: tileClean :: tileDirty :: Nil = Enum(nClientStates){ UInt() }
val acquireReadClean :: acquireReadDirty :: acquireWriteback :: Nil = Enum(nAcquireTypes){ UInt() }
val releaseVoluntaryInvalidateData :: releaseInvalidateAck :: Nil = Enum(nReleaseTypes){ UInt() }
val grantVoluntaryAck :: grantData :: grantAck :: Nil = Enum(nGrantTypes){ UInt() }
val uncachedAcquireTypeList = List()
val hasDataAcquireTypeList = List(acquireWriteback)
val hasDataReleaseTypeList = List(acquireWriteback)
val hasDataGrantTypeList = List(grantData)
def isHit ( cmd: UInt, state: UInt): Bool = (state === tileClean || state === tileDirty)
def isValid (state: UInt): Bool = state != tileInvalid
def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire) = Bool(false)
def needsTransactionOnCacheControl(cmd: UInt, state: UInt): Bool = state === tileDirty
def needsWriteback (state: UInt): Bool = state === tileDirty
def newState(cmd: UInt, state: UInt): UInt = {
Mux(isWrite(cmd), tileDirty, Mux(isRead(cmd), Mux(state === tileDirty, tileDirty, tileClean), state))
}
def newStateOnHit(cmd: UInt, state: UInt): UInt = newState(cmd, state)
def newStateOnCacheControl(cmd: UInt) = tileInvalid //TODO
def newStateOnWriteback() = tileInvalid
def newStateOnFlush() = tileInvalid
def newStateOnGrant(incoming: Grant, outstanding: Acquire) = {
MuxLookup(incoming.g_type, tileInvalid, Array(
grantData -> Mux(outstanding.a_type === acquireReadDirty, tileDirty, tileClean),
grantAck -> tileInvalid
))
}
def isVoluntary(rel: Release) = rel.r_type === releaseVoluntaryInvalidateData
def isVoluntary(gnt: Grant) = gnt.g_type === grantVoluntaryAck
def getAcquireTypeOnPrimaryMiss(cmd: UInt, state: UInt): UInt = {
Mux(isWriteIntent(cmd), acquireReadDirty, acquireReadClean)
}
def getAcquireTypeOnSecondaryMiss(cmd: UInt, state: UInt, outstanding: Acquire): UInt = {
Mux(isWriteIntent(cmd), acquireReadDirty, outstanding.a_type)
}
def getReleaseTypeOnCacheControl(cmd: UInt): Bits = releaseVoluntaryInvalidateData // TODO
def getReleaseTypeOnVoluntaryWriteback(): Bits = releaseVoluntaryInvalidateData
def messageHasData( msg: SourcedMessage ) = msg match {
case acq: Acquire => uSIntListContains(hasDataAcquireTypeList, acq.a_type)
case grant: Grant => uSIntListContains(hasDataGrantTypeList, grant.g_type)
case rel: Release => Bool(false)
case _ => Bool(false)
}
def messageUpdatesDataArray (reply: Grant) = (reply.g_type === grantData)
def messageIsUncached(acq: Acquire): Bool = uSIntListContains(uncachedAcquireTypeList, acq.a_type)
}
class MICoherence extends CoherencePolicyWithUncached {
def nClientStates = 2
def nMasterStates = 2
def nAcquireTypes = 6
def nProbeTypes = 2
def nReleaseTypes = 5
def nGrantTypes = 7
val tileInvalid :: tileValid :: Nil = Enum(nClientStates){ UInt() }
val globalInvalid :: globalValid :: Nil = Enum(nMasterStates){ UInt() }
val acquireReadExclusive :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: Nil = Enum(nAcquireTypes){ UInt() }
val probeInvalidate :: probeCopy :: Nil = Enum(nProbeTypes){ UInt() }
val releaseVoluntaryInvalidateData :: releaseInvalidateData :: releaseCopyData :: releaseInvalidateAck :: releaseCopyAck :: Nil = Enum(nReleaseTypes){ UInt() }
val grantVoluntaryAck :: grantReadExclusive :: grantReadUncached :: grantWriteUncached :: grantReadWordUncached :: grantWriteWordUncached :: grantAtomicUncached :: Nil = Enum(nGrantTypes){ UInt() }
val uncachedAcquireTypeList = List(acquireReadUncached, acquireWriteUncached, acquireReadWordUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataAcquireTypeList = List(acquireWriteUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataReleaseTypeList = List(releaseVoluntaryInvalidateData, releaseInvalidateData, releaseCopyData)
val hasDataGrantTypeList = List(grantReadExclusive, grantReadUncached, grantReadWordUncached, grantAtomicUncached)
def isHit (cmd: UInt, state: UInt): Bool = state != tileInvalid
def isValid (state: UInt): Bool = state != tileInvalid
def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire): Bool = (outstanding.a_type != acquireReadExclusive)
def needsTransactionOnCacheControl(cmd: UInt, state: UInt): Bool = {
MuxLookup(cmd, (state === tileValid), Array(
M_INV -> (state === tileValid),
M_CLN -> (state === tileValid)
))
}
def needsWriteback (state: UInt): Bool = {
needsTransactionOnCacheControl(M_INV, state)
}
def newStateOnHit(cmd: UInt, state: UInt): UInt = state
def newStateOnCacheControl(cmd: UInt) = {
MuxLookup(cmd, tileInvalid, Array(
M_INV -> tileInvalid,
M_CLN -> tileValid
))
}
def newStateOnWriteback() = newStateOnCacheControl(M_INV)
def newStateOnFlush() = newStateOnCacheControl(M_INV)
def newStateOnGrant(incoming: Grant, outstanding: Acquire): UInt = {
MuxLookup(incoming.g_type, tileInvalid, Array(
grantReadExclusive -> tileValid,
grantReadUncached -> tileInvalid,
grantWriteUncached -> tileInvalid,
grantReadWordUncached -> tileInvalid,
grantWriteWordUncached -> tileInvalid,
grantAtomicUncached -> tileInvalid
))
}
def newStateOnProbe(incoming: Probe, state: UInt): Bits = {
MuxLookup(incoming.p_type, state, Array(
probeInvalidate -> tileInvalid,
probeCopy -> state
))
}
def getUncachedReadAcquireType = acquireReadUncached
def getUncachedWriteAcquireType = acquireWriteUncached
def getUncachedReadWordAcquireType = acquireReadWordUncached
def getUncachedWriteWordAcquireType = acquireWriteWordUncached
def getUncachedAtomicAcquireType = acquireAtomicUncached
def isUncachedReadTransaction(acq: Acquire) = acq.a_type === acquireReadUncached
def isVoluntary(rel: Release) = rel.r_type === releaseVoluntaryInvalidateData
def isVoluntary(gnt: Grant) = gnt.g_type === grantVoluntaryAck
def getAcquireTypeOnPrimaryMiss(cmd: UInt, state: UInt): UInt = acquireReadExclusive
def getAcquireTypeOnSecondaryMiss(cmd: UInt, state: UInt, outstanding: Acquire): UInt = acquireReadExclusive
def getReleaseTypeOnCacheControl(cmd: UInt): Bits = releaseVoluntaryInvalidateData // TODO
def getReleaseTypeOnVoluntaryWriteback(): Bits = getReleaseTypeOnCacheControl(M_INV)
def getReleaseTypeOnProbe(incoming: Probe, state: UInt): Bits = {
val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array(
probeInvalidate -> releaseInvalidateData,
probeCopy -> releaseCopyData
))
val without_data = MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> releaseInvalidateAck,
probeCopy -> releaseCopyAck
))
Mux(needsWriteback(state), with_data, without_data)
}
def messageHasData(msg: SourcedMessage) = msg match {
case acq: Acquire => uSIntListContains(hasDataAcquireTypeList, acq.a_type)
case grant: Grant => uSIntListContains(hasDataGrantTypeList, grant.g_type)
case rel: Release => uSIntListContains(hasDataReleaseTypeList, rel.r_type)
case _ => Bool(false)
}
def messageUpdatesDataArray (reply: Grant): Bool = {
(reply.g_type === grantReadExclusive)
}
def messageIsUncached(acq: Acquire): Bool = uSIntListContains(uncachedAcquireTypeList, acq.a_type)
def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2)
def getGrantType(a_type: UInt, count: UInt): Bits = {
MuxLookup(a_type, grantReadUncached, Array(
acquireReadExclusive -> grantReadExclusive,
acquireReadUncached -> grantReadUncached,
acquireWriteUncached -> grantWriteUncached,
acquireReadWordUncached -> grantReadWordUncached,
acquireWriteWordUncached -> grantWriteWordUncached,
acquireAtomicUncached -> grantAtomicUncached
))
}
def getGrantType(rel: Release, count: UInt): Bits = {
MuxLookup(rel.r_type, grantReadUncached, Array(
releaseVoluntaryInvalidateData -> grantVoluntaryAck
))
}
def getProbeType(a_type: UInt, global_state: UInt): UInt = {
MuxLookup(a_type, probeCopy, Array(
acquireReadExclusive -> probeInvalidate,
acquireReadUncached -> probeCopy,
acquireWriteUncached -> probeInvalidate,
acquireReadWordUncached -> probeCopy,
acquireWriteWordUncached -> probeInvalidate,
acquireAtomicUncached -> probeInvalidate
))
}
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = {
(a_type != acquireWriteUncached)
}
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def needsAckReply(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def requiresAck(grant: Grant) = grant.g_type != grantVoluntaryAck
def requiresAck(release: Release) = Bool(false)
def needsSelfProbe(acq: Acquire) = Bool(false)
def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData)
}
class MEICoherence extends CoherencePolicyWithUncached {
def nClientStates = 3
def nMasterStates = 2
def nAcquireTypes = 7
def nProbeTypes = 3
def nReleaseTypes = 7
def nGrantTypes = 8
val tileInvalid :: tileExclusiveClean :: tileExclusiveDirty :: Nil = Enum(nClientStates){ UInt() }
val globalInvalid :: globalExclusiveClean :: Nil = Enum(nMasterStates){ UInt() }
val acquireReadExclusiveClean :: acquireReadExclusiveDirty :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: Nil = Enum(nAcquireTypes){ UInt() }
val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(nProbeTypes){ UInt() }
val releaseVoluntaryInvalidateData :: releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(nReleaseTypes){ UInt() }
val grantVoluntaryAck :: grantReadExclusive :: grantReadUncached :: grantWriteUncached :: grantReadExclusiveAck :: grantReadWordUncached :: grantWriteWordUncached :: grantAtomicUncached :: Nil = Enum(nGrantTypes){ UInt() }
val uncachedAcquireTypeList = List(acquireReadUncached, acquireWriteUncached, acquireReadWordUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataAcquireTypeList = List(acquireWriteUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataReleaseTypeList = List(releaseVoluntaryInvalidateData, releaseInvalidateData, releaseDowngradeData, releaseCopyData)
val hasDataGrantTypeList = List(grantReadExclusive, grantReadUncached, grantReadWordUncached, grantAtomicUncached)
def isHit (cmd: UInt, state: UInt): Bool = state != tileInvalid
def isValid (state: UInt): Bool = state != tileInvalid
def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire): Bool = {
(isRead(cmd) && messageIsUncached(outstanding)) ||
(isWriteIntent(cmd) && (outstanding.a_type != acquireReadExclusiveDirty))
}
def needsTransactionOnCacheControl(cmd: UInt, state: UInt): Bool = {
MuxLookup(cmd, (state === tileExclusiveDirty), Array(
M_INV -> (state === tileExclusiveDirty),
M_CLN -> (state === tileExclusiveDirty)
))
}
def needsWriteback (state: UInt): Bool = {
needsTransactionOnCacheControl(M_INV, state)
}
def newStateOnHit(cmd: UInt, state: UInt): UInt = {
Mux(isWrite(cmd), tileExclusiveDirty, state)
}
def newStateOnCacheControl(cmd: UInt) = {
MuxLookup(cmd, tileInvalid, Array(
M_INV -> tileInvalid,
M_CLN -> tileExclusiveClean
))
}
def newStateOnWriteback() = newStateOnCacheControl(M_INV)
def newStateOnFlush() = newStateOnCacheControl(M_INV)
def newStateOnGrant(incoming: Grant, outstanding: Acquire): UInt = {
MuxLookup(incoming.g_type, tileInvalid, Array(
grantReadExclusive -> Mux(outstanding.a_type === acquireReadExclusiveDirty, tileExclusiveDirty, tileExclusiveClean),
grantReadExclusiveAck -> tileExclusiveDirty,
grantReadUncached -> tileInvalid,
grantWriteUncached -> tileInvalid,
grantReadWordUncached -> tileInvalid,
grantWriteWordUncached -> tileInvalid,
grantAtomicUncached -> tileInvalid
))
}
def newStateOnProbe(incoming: Probe, state: UInt): Bits = {
MuxLookup(incoming.p_type, state, Array(
probeInvalidate -> tileInvalid,
probeDowngrade -> tileExclusiveClean,
probeCopy -> state
))
}
def getUncachedReadAcquireType = acquireReadUncached
def getUncachedWriteAcquireType = acquireWriteUncached
def getUncachedReadWordAcquireType = acquireReadWordUncached
def getUncachedWriteWordAcquireType = acquireWriteWordUncached
def getUncachedAtomicAcquireType = acquireAtomicUncached
def isUncachedReadTransaction(acq: Acquire) = acq.a_type === acquireReadUncached
def isVoluntary(rel: Release) = rel.r_type === releaseVoluntaryInvalidateData
def isVoluntary(gnt: Grant) = gnt.g_type === grantVoluntaryAck
def getAcquireTypeOnPrimaryMiss(cmd: UInt, state: UInt): UInt = {
Mux(isWriteIntent(cmd), acquireReadExclusiveDirty, acquireReadExclusiveClean)
}
def getAcquireTypeOnSecondaryMiss(cmd: UInt, state: UInt, outstanding: Acquire): UInt = {
Mux(isWriteIntent(cmd), acquireReadExclusiveDirty, outstanding.a_type)
}
def getReleaseTypeOnCacheControl(cmd: UInt): Bits = releaseVoluntaryInvalidateData // TODO
def getReleaseTypeOnVoluntaryWriteback(): Bits = getReleaseTypeOnCacheControl(M_INV)
def getReleaseTypeOnProbe(incoming: Probe, state: UInt): Bits = {
val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array(
probeInvalidate -> releaseInvalidateData,
probeDowngrade -> releaseDowngradeData,
probeCopy -> releaseCopyData
))
val without_data = MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> releaseInvalidateAck,
probeDowngrade -> releaseDowngradeAck,
probeCopy -> releaseCopyAck
))
Mux(needsWriteback(state), with_data, without_data)
}
def messageHasData(msg: SourcedMessage) = msg match {
case acq: Acquire => uSIntListContains(hasDataAcquireTypeList, acq.a_type)
case grant: Grant => uSIntListContains(hasDataGrantTypeList, grant.g_type)
case rel: Release => uSIntListContains(hasDataReleaseTypeList, rel.r_type)
case _ => Bool(false)
}
def messageUpdatesDataArray (reply: Grant): Bool = {
(reply.g_type === grantReadExclusive)
}
def messageIsUncached(acq: Acquire): Bool = uSIntListContains(uncachedAcquireTypeList, acq.a_type)
def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2)
def getGrantType(a_type: UInt, count: UInt): Bits = {
MuxLookup(a_type, grantReadUncached, Array(
acquireReadExclusiveClean -> grantReadExclusive,
acquireReadExclusiveDirty -> grantReadExclusive,
acquireReadUncached -> grantReadUncached,
acquireWriteUncached -> grantWriteUncached,
acquireReadWordUncached -> grantReadWordUncached,
acquireWriteWordUncached -> grantWriteWordUncached,
acquireAtomicUncached -> grantAtomicUncached
))
}
def getGrantType(rel: Release, count: UInt): Bits = {
MuxLookup(rel.r_type, grantReadUncached, Array(
releaseVoluntaryInvalidateData -> grantVoluntaryAck
))
}
def getProbeType(a_type: UInt, global_state: UInt): UInt = {
MuxLookup(a_type, probeCopy, Array(
acquireReadExclusiveClean -> probeInvalidate,
acquireReadExclusiveDirty -> probeInvalidate,
acquireReadUncached -> probeCopy,
acquireWriteUncached -> probeInvalidate,
acquireReadWordUncached -> probeCopy,
acquireWriteWordUncached -> probeInvalidate,
acquireAtomicUncached -> probeInvalidate
))
}
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = {
(a_type != acquireWriteUncached)
}
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def needsAckReply(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def requiresAck(grant: Grant) = grant.g_type != grantVoluntaryAck
def requiresAck(release: Release) = Bool(false)
def needsSelfProbe(acq: Acquire) = Bool(false)
def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData)
}
class MSICoherence extends CoherencePolicyWithUncached {
def nClientStates = 3
def nMasterStates = 3
def nAcquireTypes = 7
def nProbeTypes = 3
def nReleaseTypes = 7
def nGrantTypes = 9
val tileInvalid :: tileShared :: tileExclusiveDirty :: Nil = Enum(nClientStates){ UInt() }
val globalInvalid :: globalShared :: globalExclusive :: Nil = Enum(nMasterStates){ UInt() }
val acquireReadShared :: acquireReadExclusive :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: Nil = Enum(nAcquireTypes){ UInt() }
val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(nProbeTypes){ UInt() }
val releaseVoluntaryInvalidateData :: releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(nReleaseTypes){ UInt() }
val grantVoluntaryAck :: grantReadShared :: grantReadExclusive :: grantReadUncached :: grantWriteUncached :: grantReadExclusiveAck :: grantReadWordUncached :: grantWriteWordUncached :: grantAtomicUncached :: Nil = Enum(nGrantTypes){ UInt() }
val uncachedAcquireTypeList = List(acquireReadUncached, acquireWriteUncached, acquireReadWordUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataAcquireTypeList = List(acquireWriteUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataReleaseTypeList = List(releaseVoluntaryInvalidateData, releaseInvalidateData, releaseDowngradeData, releaseCopyData)
val hasDataGrantTypeList = List(grantReadShared, grantReadExclusive, grantReadUncached, grantReadWordUncached, grantAtomicUncached)
def isHit (cmd: UInt, state: UInt): Bool = {
Mux(isWriteIntent(cmd), (state === tileExclusiveDirty),
(state === tileShared || state === tileExclusiveDirty))
}
def isValid (state: UInt): Bool = {
state != tileInvalid
}
def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire): Bool = {
(isRead(cmd) && messageIsUncached(outstanding)) ||
(isWriteIntent(cmd) && (outstanding.a_type != acquireReadExclusive))
}
def needsTransactionOnCacheControl(cmd: UInt, state: UInt): Bool = {
MuxLookup(cmd, (state === tileExclusiveDirty), Array(
M_INV -> (state === tileExclusiveDirty),
M_CLN -> (state === tileExclusiveDirty)
))
}
def needsWriteback (state: UInt): Bool = {
needsTransactionOnCacheControl(M_INV, state)
}
def newStateOnHit(cmd: UInt, state: UInt): UInt = {
Mux(isWrite(cmd), tileExclusiveDirty, state)
}
def newStateOnCacheControl(cmd: UInt) = {
MuxLookup(cmd, tileInvalid, Array(
M_INV -> tileInvalid,
M_CLN -> tileShared
))
}
def newStateOnWriteback() = newStateOnCacheControl(M_INV)
def newStateOnFlush() = newStateOnCacheControl(M_INV)
def newStateOnGrant(incoming: Grant, outstanding: Acquire): UInt = {
MuxLookup(incoming.g_type, tileInvalid, Array(
grantReadShared -> tileShared,
grantReadExclusive -> tileExclusiveDirty,
grantReadExclusiveAck -> tileExclusiveDirty,
grantReadUncached -> tileInvalid,
grantWriteUncached -> tileInvalid,
grantReadWordUncached -> tileInvalid,
grantWriteWordUncached -> tileInvalid,
grantAtomicUncached -> tileInvalid
))
}
def newStateOnProbe(incoming: Probe, state: UInt): Bits = {
MuxLookup(incoming.p_type, state, Array(
probeInvalidate -> tileInvalid,
probeDowngrade -> tileShared,
probeCopy -> state
))
}
def getUncachedReadAcquireType = acquireReadUncached
def getUncachedWriteAcquireType = acquireWriteUncached
def getUncachedReadWordAcquireType = acquireReadWordUncached
def getUncachedWriteWordAcquireType = acquireWriteWordUncached
def getUncachedAtomicAcquireType = acquireAtomicUncached
def isUncachedReadTransaction(acq: Acquire) = acq.a_type === acquireReadUncached
def isVoluntary(rel: Release) = rel.r_type === releaseVoluntaryInvalidateData
def isVoluntary(gnt: Grant) = gnt.g_type === grantVoluntaryAck
def getAcquireTypeOnPrimaryMiss(cmd: UInt, state: UInt): UInt = {
Mux(isWriteIntent(cmd), acquireReadExclusive, acquireReadShared)
}
def getAcquireTypeOnSecondaryMiss(cmd: UInt, state: UInt, outstanding: Acquire): UInt = {
Mux(isWriteIntent(cmd), acquireReadExclusive, outstanding.a_type)
}
def getReleaseTypeOnCacheControl(cmd: UInt): Bits = releaseVoluntaryInvalidateData // TODO
def getReleaseTypeOnVoluntaryWriteback(): Bits = getReleaseTypeOnCacheControl(M_INV)
def getReleaseTypeOnProbe(incoming: Probe, state: UInt): Bits = {
val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array(
probeInvalidate -> releaseInvalidateData,
probeDowngrade -> releaseDowngradeData,
probeCopy -> releaseCopyData
))
val without_data = MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> releaseInvalidateAck,
probeDowngrade -> releaseDowngradeAck,
probeCopy -> releaseCopyAck
))
Mux(needsWriteback(state), with_data, without_data)
}
def messageHasData(msg: SourcedMessage) = msg match {
case acq: Acquire => uSIntListContains(hasDataAcquireTypeList, acq.a_type)
case grant: Grant => uSIntListContains(hasDataGrantTypeList, grant.g_type)
case rel: Release => uSIntListContains(hasDataReleaseTypeList, rel.r_type)
case _ => Bool(false)
}
def messageUpdatesDataArray (reply: Grant): Bool = {
(reply.g_type === grantReadShared || reply.g_type === grantReadExclusive)
}
def messageIsUncached(acq: Acquire): Bool = uSIntListContains(uncachedAcquireTypeList, acq.a_type)
def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2)
def getGrantType(a_type: UInt, count: UInt): Bits = {
MuxLookup(a_type, grantReadUncached, Array(
acquireReadShared -> Mux(count > UInt(0), grantReadShared, grantReadExclusive),
acquireReadExclusive -> grantReadExclusive,
acquireReadUncached -> grantReadUncached,
acquireWriteUncached -> grantWriteUncached,
acquireReadWordUncached -> grantReadWordUncached,
acquireWriteWordUncached -> grantWriteWordUncached,
acquireAtomicUncached -> grantAtomicUncached
))
}
def getGrantType(rel: Release, count: UInt): Bits = {
MuxLookup(rel.r_type, grantReadUncached, Array(
releaseVoluntaryInvalidateData -> grantVoluntaryAck
))
}
def getProbeType(a_type: UInt, global_state: UInt): UInt = {
MuxLookup(a_type, probeCopy, Array(
acquireReadShared -> probeDowngrade,
acquireReadExclusive -> probeInvalidate,
acquireReadUncached -> probeCopy,
acquireWriteUncached -> probeInvalidate
))
}
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = {
(a_type != acquireWriteUncached)
}
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def needsAckReply(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def requiresAck(grant: Grant) = grant.g_type != grantVoluntaryAck
def requiresAck(release: Release) = Bool(false)
def needsSelfProbe(acq: Acquire) = Bool(false)
def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData)
}
class MESICoherence extends CoherencePolicyWithUncached {
def nClientStates = 4
def nMasterStates = 3
def nAcquireTypes = 7
def nProbeTypes = 3
def nReleaseTypes = 7
def nGrantTypes = 9
val tileInvalid :: tileShared :: tileExclusiveClean :: tileExclusiveDirty :: Nil = Enum(nClientStates){ UInt() }
val globalInvalid :: globalShared :: globalExclusiveClean :: Nil = Enum(nMasterStates){ UInt() }
val acquireReadShared :: acquireReadExclusive :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: Nil = Enum(nAcquireTypes){ UInt() }
val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(nProbeTypes){ UInt() }
val releaseVoluntaryInvalidateData :: releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(nReleaseTypes){ UInt() }
val grantVoluntaryAck :: grantReadShared :: grantReadExclusive :: grantReadUncached :: grantWriteUncached :: grantReadExclusiveAck :: grantReadWordUncached :: grantWriteWordUncached :: grantAtomicUncached :: Nil = Enum(nGrantTypes){ UInt() }
val uncachedAcquireTypeList = List(acquireReadUncached, acquireWriteUncached, acquireReadWordUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataAcquireTypeList = List(acquireWriteUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataReleaseTypeList = List(releaseVoluntaryInvalidateData, releaseInvalidateData, releaseDowngradeData, releaseCopyData)
val hasDataGrantTypeList = List(grantReadShared, grantReadExclusive, grantReadUncached, grantReadWordUncached, grantAtomicUncached)
def isHit (cmd: UInt, state: UInt): Bool = {
Mux(isWriteIntent(cmd), (state === tileExclusiveClean || state === tileExclusiveDirty),
(state === tileShared || state === tileExclusiveClean || state === tileExclusiveDirty))
}
def isValid (state: UInt): Bool = {
state != tileInvalid
}
def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire): Bool = {
(isRead(cmd) && messageIsUncached(outstanding)) ||
(isWriteIntent(cmd) && (outstanding.a_type != acquireReadExclusive))
}
def needsTransactionOnCacheControl(cmd: UInt, state: UInt): Bool = {
MuxLookup(cmd, (state === tileExclusiveDirty), Array(
M_INV -> (state === tileExclusiveDirty),
M_CLN -> (state === tileExclusiveDirty)
))
}
def needsWriteback (state: UInt): Bool = {
needsTransactionOnCacheControl(M_INV, state)
}
def newStateOnHit(cmd: UInt, state: UInt): UInt = {
Mux(isWrite(cmd), tileExclusiveDirty, state)
}
def newStateOnCacheControl(cmd: UInt) = {
MuxLookup(cmd, tileInvalid, Array(
M_INV -> tileInvalid,
M_CLN -> tileShared
))
}
def newStateOnWriteback() = newStateOnCacheControl(M_INV)
def newStateOnFlush() = newStateOnCacheControl(M_INV)
def newStateOnGrant(incoming: Grant, outstanding: Acquire): UInt = {
MuxLookup(incoming.g_type, tileInvalid, Array(
grantReadShared -> tileShared,
grantReadExclusive -> Mux(outstanding.a_type === acquireReadExclusive, tileExclusiveDirty, tileExclusiveClean),
grantReadExclusiveAck -> tileExclusiveDirty,
grantReadUncached -> tileInvalid,
grantWriteUncached -> tileInvalid,
grantReadWordUncached -> tileInvalid,
grantWriteWordUncached -> tileInvalid,
grantAtomicUncached -> tileInvalid
))
}
def newStateOnProbe(incoming: Probe, state: UInt): Bits = {
MuxLookup(incoming.p_type, state, Array(
probeInvalidate -> tileInvalid,
probeDowngrade -> tileShared,
probeCopy -> state
))
}
def getUncachedReadAcquireType = acquireReadUncached
def getUncachedWriteAcquireType = acquireWriteUncached
def getUncachedReadWordAcquireType = acquireReadWordUncached
def getUncachedWriteWordAcquireType = acquireWriteWordUncached
def getUncachedAtomicAcquireType = acquireAtomicUncached
def isUncachedReadTransaction(acq: Acquire) = acq.a_type === acquireReadUncached
def isVoluntary(rel: Release) = rel.r_type === releaseVoluntaryInvalidateData
def isVoluntary(gnt: Grant) = gnt.g_type === grantVoluntaryAck
def getAcquireTypeOnPrimaryMiss(cmd: UInt, state: UInt): UInt = {
Mux(isWriteIntent(cmd), acquireReadExclusive, acquireReadShared)
}
def getAcquireTypeOnSecondaryMiss(cmd: UInt, state: UInt, outstanding: Acquire): UInt = {
Mux(isWriteIntent(cmd), acquireReadExclusive, outstanding.a_type)
}
def getReleaseTypeOnCacheControl(cmd: UInt): Bits = releaseVoluntaryInvalidateData // TODO
def getReleaseTypeOnVoluntaryWriteback(): Bits = getReleaseTypeOnCacheControl(M_INV)
def getReleaseTypeOnProbe(incoming: Probe, state: UInt): Bits = {
val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array(
probeInvalidate -> releaseInvalidateData,
probeDowngrade -> releaseDowngradeData,
probeCopy -> releaseCopyData
))
val without_data = MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> releaseInvalidateAck,
probeDowngrade -> releaseDowngradeAck,
probeCopy -> releaseCopyAck
))
Mux(needsWriteback(state), with_data, without_data)
}
def messageHasData(msg: SourcedMessage) = msg match {
case acq: Acquire => uSIntListContains(hasDataAcquireTypeList, acq.a_type)
case grant: Grant => uSIntListContains(hasDataGrantTypeList, grant.g_type)
case rel: Release => uSIntListContains(hasDataReleaseTypeList, rel.r_type)
case _ => Bool(false)
}
def messageUpdatesDataArray (reply: Grant): Bool = {
(reply.g_type === grantReadShared || reply.g_type === grantReadExclusive)
}
def messageIsUncached(acq: Acquire): Bool = uSIntListContains(uncachedAcquireTypeList, acq.a_type)
def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2)
def getGrantType(a_type: UInt, count: UInt): Bits = {
MuxLookup(a_type, grantReadUncached, Array(
acquireReadShared -> Mux(count > UInt(0), grantReadShared, grantReadExclusive),
acquireReadExclusive -> grantReadExclusive,
acquireReadUncached -> grantReadUncached,
acquireWriteUncached -> grantWriteUncached,
acquireReadWordUncached -> grantReadWordUncached,
acquireWriteWordUncached -> grantWriteWordUncached,
acquireAtomicUncached -> grantAtomicUncached
))
}
def getGrantType(rel: Release, count: UInt): Bits = {
MuxLookup(rel.r_type, grantReadUncached, Array(
releaseVoluntaryInvalidateData -> grantVoluntaryAck
))
}
def getProbeType(a_type: UInt, global_state: UInt): UInt = {
MuxLookup(a_type, probeCopy, Array(
acquireReadShared -> probeDowngrade,
acquireReadExclusive -> probeInvalidate,
acquireReadUncached -> probeCopy,
acquireWriteUncached -> probeInvalidate,
acquireReadWordUncached -> probeCopy,
acquireWriteWordUncached -> probeInvalidate,
acquireAtomicUncached -> probeInvalidate
))
}
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = {
(a_type != acquireWriteUncached)
}
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def needsAckReply(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached)
}
def requiresAck(grant: Grant) = grant.g_type != grantVoluntaryAck
def requiresAck(release: Release) = Bool(false)
def needsSelfProbe(acq: Acquire) = Bool(false)
def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData)
}
class MigratoryCoherence extends CoherencePolicyWithUncached {
def nClientStates = 7
def nMasterStates = 0
def nAcquireTypes = 8
def nProbeTypes = 4
def nReleaseTypes = 11
def nGrantTypes = 9
val tileInvalid :: tileShared :: tileExclusiveClean :: tileExclusiveDirty :: tileSharedByTwo :: tileMigratoryClean :: tileMigratoryDirty :: Nil = Enum(nClientStates){ UInt() }
val acquireReadShared :: acquireReadExclusive :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: acquireInvalidateOthers :: Nil = Enum(nAcquireTypes){ UInt() }
val probeInvalidate :: probeDowngrade :: probeCopy :: probeInvalidateOthers :: Nil = Enum(nProbeTypes){ UInt() }
val releaseVoluntaryInvalidateData :: releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: releaseDowngradeDataMigratory :: releaseDowngradeAckHasCopy :: releaseInvalidateDataMigratory :: releaseInvalidateAckMigratory :: Nil = Enum(nReleaseTypes){ UInt() }
val grantVoluntaryAck :: grantReadShared :: grantReadExclusive :: grantReadUncached :: grantWriteUncached :: grantReadExclusiveAck :: grantReadWordUncached :: grantWriteWordUncached :: grantAtomicUncached :: grantReadMigratory :: Nil = Enum(nGrantTypes){ UInt() }
val uncachedAcquireTypeList = List(acquireReadUncached, acquireWriteUncached, acquireReadWordUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataAcquireTypeList = List(acquireWriteUncached, acquireWriteWordUncached, acquireAtomicUncached)
val hasDataGrantTypeList = List(grantReadShared, grantReadExclusive, grantReadUncached, grantReadMigratory, grantReadWordUncached, grantAtomicUncached)
val hasDataReleaseTypeList = List(releaseVoluntaryInvalidateData, releaseInvalidateData, releaseDowngradeData, releaseCopyData, releaseInvalidateDataMigratory, releaseDowngradeDataMigratory)
def isHit (cmd: UInt, state: UInt): Bool = {
Mux(isWriteIntent(cmd), uSIntListContains(List(tileExclusiveClean, tileExclusiveDirty, tileMigratoryClean, tileMigratoryDirty), state), (state != tileInvalid))
}
def isValid (state: UInt): Bool = {
state != tileInvalid
}
def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire): Bool = {
(isRead(cmd) && messageIsUncached(outstanding)) ||
(isWriteIntent(cmd) && (outstanding.a_type != acquireReadExclusive && outstanding.a_type != acquireInvalidateOthers))
}
def needsTransactionOnCacheControl(cmd: UInt, state: UInt): Bool = {
MuxLookup(cmd, (state === tileExclusiveDirty), Array(
M_INV -> uSIntListContains(List(tileExclusiveDirty,tileMigratoryDirty),state),
M_CLN -> uSIntListContains(List(tileExclusiveDirty,tileMigratoryDirty),state)
))
}
def needsWriteback (state: UInt): Bool = {
needsTransactionOnCacheControl(M_INV, state)
}
def newStateOnHit(cmd: UInt, state: UInt): UInt = {
Mux(isWrite(cmd), MuxLookup(state, tileExclusiveDirty, Array(
tileExclusiveClean -> tileExclusiveDirty,
tileMigratoryClean -> tileMigratoryDirty)), state)
}
def newStateOnCacheControl(cmd: UInt) = {
MuxLookup(cmd, tileInvalid, Array(
M_INV -> tileInvalid,
M_CLN -> tileShared
))
}
def newStateOnWriteback() = newStateOnCacheControl(M_INV)
def newStateOnFlush() = newStateOnCacheControl(M_INV)
def newStateOnGrant(incoming: Grant, outstanding: Acquire): UInt = {
MuxLookup(incoming.g_type, tileInvalid, Array(
grantReadShared -> tileShared,
grantReadExclusive -> MuxLookup(outstanding.a_type, tileExclusiveDirty, Array(
acquireReadExclusive -> tileExclusiveDirty,
acquireReadShared -> tileExclusiveClean)),
grantReadExclusiveAck -> tileExclusiveDirty,
grantReadUncached -> tileInvalid,
grantWriteUncached -> tileInvalid,
grantReadWordUncached -> tileInvalid,
grantWriteWordUncached -> tileInvalid,
grantAtomicUncached -> tileInvalid,
grantReadMigratory -> MuxLookup(outstanding.a_type, tileMigratoryDirty, Array(
acquireInvalidateOthers -> tileMigratoryDirty,
acquireReadExclusive -> tileMigratoryDirty,
acquireReadShared -> tileMigratoryClean))
))
}
def newStateOnProbe(incoming: Probe, state: UInt): Bits = {
MuxLookup(incoming.p_type, state, Array(
probeInvalidate -> tileInvalid,
probeInvalidateOthers -> tileInvalid,
probeCopy -> state,
probeDowngrade -> MuxLookup(state, tileShared, Array(
tileExclusiveClean -> tileSharedByTwo,
tileExclusiveDirty -> tileSharedByTwo,
tileSharedByTwo -> tileShared,
tileMigratoryClean -> tileSharedByTwo,
tileMigratoryDirty -> tileInvalid))
))
}
def getUncachedReadAcquireType = acquireReadUncached
def getUncachedWriteAcquireType = acquireWriteUncached
def getUncachedReadWordAcquireType = acquireReadWordUncached
def getUncachedWriteWordAcquireType = acquireWriteWordUncached
def getUncachedAtomicAcquireType = acquireAtomicUncached
def isUncachedReadTransaction(acq: Acquire) = acq.a_type === acquireReadUncached
def isVoluntary(rel: Release) = rel.r_type === releaseVoluntaryInvalidateData
def isVoluntary(gnt: Grant) = gnt.g_type === grantVoluntaryAck
def getAcquireTypeOnPrimaryMiss(cmd: UInt, state: UInt): UInt = {
Mux(isWriteIntent(cmd), Mux(state === tileInvalid, acquireReadExclusive, acquireInvalidateOthers), acquireReadShared)
}
def getAcquireTypeOnSecondaryMiss(cmd: UInt, state: UInt, outstanding: Acquire): UInt = {
Mux(isWriteIntent(cmd), Mux(state === tileInvalid, acquireReadExclusive, acquireInvalidateOthers), outstanding.a_type)
}
def getReleaseTypeOnCacheControl(cmd: UInt): Bits = releaseVoluntaryInvalidateData // TODO
def getReleaseTypeOnVoluntaryWriteback(): Bits = getReleaseTypeOnCacheControl(M_INV)
def getReleaseTypeOnProbe(incoming: Probe, state: UInt): Bits = {
val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array(
probeInvalidate -> Mux(uSIntListContains(List(tileExclusiveDirty, tileMigratoryDirty), state),
releaseInvalidateDataMigratory, releaseInvalidateData),
probeDowngrade -> Mux(state === tileMigratoryDirty, releaseDowngradeDataMigratory, releaseDowngradeData),
probeCopy -> releaseCopyData
))
val without_data = MuxLookup(incoming.p_type, releaseInvalidateAck, Array(
probeInvalidate -> Mux(tileExclusiveClean === state, releaseInvalidateAckMigratory, releaseInvalidateAck),
probeInvalidateOthers -> Mux(state === tileSharedByTwo, releaseInvalidateAckMigratory, releaseInvalidateAck),
probeDowngrade -> Mux(state != tileInvalid, releaseDowngradeAckHasCopy, releaseDowngradeAck),
probeCopy -> releaseCopyAck
))
Mux(needsWriteback(state), with_data, without_data)
}
def messageHasData(msg: SourcedMessage) = msg match {
case acq: Acquire => uSIntListContains(hasDataAcquireTypeList, acq.a_type)
case grant: Grant => uSIntListContains(hasDataGrantTypeList, grant.g_type)
case rel: Release => uSIntListContains(hasDataReleaseTypeList, rel.r_type)
case _ => Bool(false)
}
def messageUpdatesDataArray (reply: Grant): Bool = {
uSIntListContains(List(grantReadShared, grantReadExclusive, grantReadMigratory), reply.g_type)
}
def messageIsUncached(acq: Acquire): Bool = uSIntListContains(uncachedAcquireTypeList, acq.a_type)
def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2)
def getGrantType(a_type: UInt, count: UInt): Bits = {
MuxLookup(a_type, grantReadUncached, Array(
acquireReadShared -> Mux(count > UInt(0), grantReadShared, grantReadExclusive), //TODO: what is count? Depend on release.p_type???
acquireReadExclusive -> grantReadExclusive,
acquireReadUncached -> grantReadUncached,
acquireWriteUncached -> grantWriteUncached,
acquireReadWordUncached -> grantReadWordUncached,
acquireWriteWordUncached -> grantWriteWordUncached,
acquireAtomicUncached -> grantAtomicUncached,
acquireInvalidateOthers -> grantReadExclusiveAck //TODO: add this to MESI?
))
}
def getGrantType(rel: Release, count: UInt): Bits = {
MuxLookup(rel.r_type, grantReadUncached, Array(
releaseVoluntaryInvalidateData -> grantVoluntaryAck
))
}
def getProbeType(a_type: UInt, global_state: UInt): UInt = {
MuxLookup(a_type, probeCopy, Array(
acquireReadShared -> probeDowngrade,
acquireReadExclusive -> probeInvalidate,
acquireReadUncached -> probeCopy,
acquireWriteUncached -> probeInvalidate,
acquireReadWordUncached -> probeCopy,
acquireWriteWordUncached -> probeInvalidate,
acquireAtomicUncached -> probeInvalidate,
acquireInvalidateOthers -> probeInvalidateOthers
))
}
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = {
(a_type != acquireWriteUncached && a_type != acquireInvalidateOthers)
}
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached || a_type === acquireWriteWordUncached || a_type === acquireAtomicUncached)
}
def needsAckReply(a_type: UInt, global_state: UInt): Bool = {
(a_type === acquireWriteUncached || a_type === acquireWriteWordUncached ||a_type === acquireInvalidateOthers)
}
def requiresAck(grant: Grant) = grant.g_type != grantVoluntaryAck
def requiresAck(release: Release) = Bool(false)
def needsSelfProbe(acq: Acquire) = Bool(false)
def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData)
}

View File

@ -0,0 +1,75 @@
package uncore
package constants
import Chisel._
import scala.math.max
object MemoryOpConstants extends MemoryOpConstants
trait MemoryOpConstants {
val MT_X = Bits("b???", 3);
val MT_B = Bits("b000", 3);
val MT_H = Bits("b001", 3);
val MT_W = Bits("b010", 3);
val MT_D = Bits("b011", 3);
val MT_BU = Bits("b100", 3);
val MT_HU = Bits("b101", 3);
val MT_WU = Bits("b110", 3);
val M_SZ = 5
val M_X = Bits("b?????");
val M_XRD = Bits("b00000"); // int load
val M_XWR = Bits("b00001"); // int store
val M_PFR = Bits("b00010"); // prefetch with intent to read
val M_PFW = Bits("b00011"); // prefetch with intent to write
val M_FENCE = Bits("b00101"); // memory fence
val M_XLR = Bits("b00110");
val M_XSC = Bits("b00111");
val M_XA_ADD = Bits("b01000");
val M_XA_SWAP = Bits("b01001");
val M_XA_AND = Bits("b01010");
val M_XA_OR = Bits("b01011");
val M_XA_MIN = Bits("b01100");
val M_XA_MAX = Bits("b01101");
val M_XA_MINU = Bits("b01110");
val M_XA_MAXU = Bits("b01111");
val M_INV = Bits("b10000"); // write back and invalidate line
val M_CLN = Bits("b10001"); // write back line
def isAMO(cmd: Bits) = cmd(3)
def isPrefetch(cmd: Bits) = cmd === M_PFR || cmd === M_PFW
def isRead(cmd: Bits) = cmd === M_XRD || cmd === M_XLR || isAMO(cmd)
def isWrite(cmd: Bits) = cmd === M_XWR || cmd === M_XSC || isAMO(cmd)
def isWriteIntent(cmd: Bits) = isWrite(cmd) || cmd === M_PFW || cmd === M_XLR
}
object AddressConstants extends AddressConstants
trait AddressConstants {
val PADDR_BITS = 32
val VADDR_BITS = 43;
val PGIDX_BITS = 13;
val PPN_BITS = PADDR_BITS-PGIDX_BITS;
val VPN_BITS = VADDR_BITS-PGIDX_BITS;
val ASID_BITS = 7;
val PERM_BITS = 6;
}
trait CacheConstants {
val CACHE_DATA_SIZE_IN_BYTES = 1 << 6
val OFFSET_BITS = log2Up(CACHE_DATA_SIZE_IN_BYTES)
}
trait TileLinkSizeConstants {
val ACQUIRE_WRITE_MASK_BITS = 6
val ACQUIRE_SUBWORD_ADDR_BITS = 3
val ACQUIRE_ATOMIC_OP_BITS = 4
}
trait MemoryInterfaceConstants extends
CacheConstants with
AddressConstants
{
val MEM_TAG_BITS = 5
val MEM_DATA_BITS = 128
val REFILL_CYCLES = CACHE_DATA_SIZE_IN_BYTES*8/MEM_DATA_BITS
val MEM_ADDR_BITS = PADDR_BITS - OFFSET_BITS
}

View File

@ -0,0 +1,539 @@
package uncore
import Chisel._
class BigMem[T <: Data](n: Int, preLatency: Int, postLatency: Int, leaf: Mem[UInt])(gen: => T) extends Module
{
class Inputs extends Bundle {
val addr = UInt(INPUT, log2Up(n))
val rw = Bool(INPUT)
val wdata = gen.asInput
val wmask = gen.asInput
override def clone = new Inputs().asInstanceOf[this.type]
}
val io = new Bundle {
val in = Valid(new Inputs).flip
val rdata = gen.asOutput
}
val data = gen
val colMux = if (2*data.width <= leaf.data.width && n > leaf.n) 1 << math.floor(math.log(leaf.data.width/data.width)/math.log(2)).toInt else 1
val nWide = if (data.width > leaf.data.width) 1+(data.width-1)/leaf.data.width else 1
val nDeep = if (n > colMux*leaf.n) 1+(n-1)/(colMux*leaf.n) else 1
if (nDeep > 1 || colMux > 1)
require(isPow2(n) && isPow2(leaf.n))
val rdataDeep = Vec.fill(nDeep){Bits()}
val rdataSel = Vec.fill(nDeep){Bool()}
for (i <- 0 until nDeep) {
val in = Pipe(io.in.valid && (if (nDeep == 1) Bool(true) else UInt(i) === io.in.bits.addr(log2Up(n)-1, log2Up(n/nDeep))), io.in.bits, preLatency)
val idx = in.bits.addr(log2Up(n/nDeep/colMux)-1, 0)
val wdata = in.bits.wdata.toBits
val wmask = in.bits.wmask.toBits
val ren = in.valid && !in.bits.rw
val reg_ren = Reg(next=ren)
val rdata = Vec.fill(nWide){Bits()}
val r = Pipe(ren, in.bits.addr, postLatency)
for (j <- 0 until nWide) {
val mem = leaf.clone
var dout: Bits = null
val ridx = if (postLatency > 0) Reg(Bits()) else null
var wmask0 = Fill(colMux, wmask(math.min(wmask.getWidth, leaf.data.width*(j+1))-1, leaf.data.width*j))
if (colMux > 1)
wmask0 = wmask0 & FillInterleaved(gen.width, UIntToOH(in.bits.addr(log2Up(n/nDeep)-1, log2Up(n/nDeep/colMux)), log2Up(colMux)))
val wdata0 = Fill(colMux, wdata(math.min(wdata.getWidth, leaf.data.width*(j+1))-1, leaf.data.width*j))
when (in.valid) {
when (in.bits.rw) { mem.write(idx, wdata0, wmask0) }
.otherwise { if (postLatency > 0) ridx := idx }
}
if (postLatency == 0) {
dout = mem(idx)
} else if (postLatency == 1) {
dout = mem(ridx)
} else
dout = Pipe(reg_ren, mem(ridx), postLatency-1).bits
rdata(j) := dout
}
val rdataWide = rdata.reduceLeft((x, y) => Cat(y, x))
var colMuxOut = rdataWide
if (colMux > 1) {
val colMuxIn = Vec((0 until colMux).map(k => rdataWide(gen.width*(k+1)-1, gen.width*k)))
colMuxOut = colMuxIn(r.bits(log2Up(n/nDeep)-1, log2Up(n/nDeep/colMux)))
}
rdataDeep(i) := colMuxOut
rdataSel(i) := r.valid
}
io.rdata := Mux1H(rdataSel, rdataDeep)
}
class LLCDataReq(ways: Int) extends MemReqCmd
{
val way = UInt(width = log2Up(ways))
val isWriteback = Bool()
override def clone = new LLCDataReq(ways).asInstanceOf[this.type]
}
class LLCTagReq(ways: Int) extends HasMemAddr
{
val way = UInt(width = log2Up(ways))
override def clone = new LLCTagReq(ways).asInstanceOf[this.type]
}
class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int) extends Module
{
val io = new Bundle {
val cpu = Decoupled(new MemReqCmd).flip
val repl_way = UInt(INPUT, log2Up(ways))
val repl_dirty = Bool(INPUT)
val repl_tag = UInt(INPUT, MEM_ADDR_BITS - log2Up(sets))
val data = Decoupled(new LLCDataReq(ways))
val tag = Decoupled(new LLCTagReq(ways))
val mem = new ioMemPipe
val mem_resp_set = UInt(OUTPUT, log2Up(sets))
val mem_resp_way = UInt(OUTPUT, log2Up(ways))
}
class MSHR extends Bundle {
val addr = UInt(width = PADDR_BITS - OFFSET_BITS)
val way = UInt(width = log2Up(ways))
val tag = io.cpu.bits.tag.clone
val refilled = Bool()
val refillCount = UInt(width = log2Up(REFILL_CYCLES))
val requested = Bool()
val old_dirty = Bool()
val old_tag = UInt(width = MEM_ADDR_BITS - log2Up(sets))
val wb_busy = Bool()
override def clone = new MSHR().asInstanceOf[this.type]
}
val valid = Vec.fill(outstanding){Reg(init=Bool(false))}
val validBits = valid.toBits
val freeId = PriorityEncoder(~validBits)
val mshr = Vec.fill(outstanding){Reg(new MSHR)}
when (io.cpu.valid && io.cpu.ready) {
valid(freeId) := Bool(true)
mshr(freeId).addr := io.cpu.bits.addr
mshr(freeId).tag := io.cpu.bits.tag
mshr(freeId).way := io.repl_way
mshr(freeId).old_dirty := io.repl_dirty
mshr(freeId).old_tag := io.repl_tag
mshr(freeId).wb_busy := Bool(false)
mshr(freeId).requested := Bool(false)
mshr(freeId).refillCount := UInt(0)
mshr(freeId).refilled := Bool(false)
}
val requests = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && !mshr(i).old_dirty && !mshr(i).wb_busy && !mshr(i).requested):_*)
val request = requests.orR && io.data.ready // allow in-flight hits to drain
val requestId = PriorityEncoder(requests)
when (io.mem.req_cmd.valid && io.mem.req_cmd.ready) { mshr(requestId).requested := Bool(true) }
val refillId = io.mem.resp.bits.tag(log2Up(outstanding)-1, 0)
val refillCount = mshr(refillId).refillCount
when (io.mem.resp.valid) {
mshr(refillId).refillCount := refillCount + UInt(1)
when (refillCount === UInt(REFILL_CYCLES-1)) { mshr(refillId).refilled := Bool(true) }
}
val replays = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && mshr(i).refilled):_*)
val replay = replays.orR
val replayId = PriorityEncoder(replays)
when (replay && io.data.ready && io.tag.ready) { valid(replayId) := Bool(false) }
val writebacks = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && mshr(i).old_dirty):_*)
val writeback = writebacks.orR
val writebackId = PriorityEncoder(writebacks)
when (writeback && io.data.ready && !replay) {
mshr(writebackId).old_dirty := Bool(false)
mshr(writebackId).wb_busy := Bool(true)
}
mshr.foreach(m => when (m.wb_busy && io.data.ready) { m.wb_busy := Bool(false) })
val conflicts = Cat(Bits(0), (0 until outstanding).map(i => valid(i) && io.cpu.bits.addr(log2Up(sets)-1, 0) === mshr(i).addr(log2Up(sets)-1, 0)):_*)
io.cpu.ready := !conflicts.orR && !validBits.andR
io.data.valid := writeback
io.data.bits.rw := Bool(false)
io.data.bits.tag := mshr(replayId).tag
io.data.bits.isWriteback := Bool(true)
io.data.bits.addr := Cat(mshr(writebackId).old_tag, mshr(writebackId).addr(log2Up(sets)-1, 0)).toUInt
io.data.bits.way := mshr(writebackId).way
when (replay) {
io.data.valid := io.tag.ready
io.data.bits.isWriteback := Bool(false)
io.data.bits.addr := mshr(replayId).addr
io.data.bits.way := mshr(replayId).way
}
io.tag.valid := replay && io.data.ready
io.tag.bits.addr := io.data.bits.addr
io.tag.bits.way := io.data.bits.way
io.mem.req_cmd.valid := request
io.mem.req_cmd.bits.rw := Bool(false)
io.mem.req_cmd.bits.addr := mshr(requestId).addr
io.mem.req_cmd.bits.tag := requestId
io.mem_resp_set := mshr(refillId).addr
io.mem_resp_way := mshr(refillId).way
}
class LLCWriteback(requestors: Int) extends Module
{
val io = new Bundle {
val req = Vec.fill(requestors){Decoupled(UInt(width = MEM_ADDR_BITS)).flip }
val data = Vec.fill(requestors){Decoupled(new MemData).flip }
val mem = new ioMemPipe
}
val valid = Reg(init=Bool(false))
val who = Reg(UInt())
val addr = Reg(UInt())
val cmd_sent = Reg(Bool())
val data_sent = Reg(Bool())
val count = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
var anyReq = Bool(false)
for (i <- 0 until requestors) {
io.req(i).ready := !valid && !anyReq
io.data(i).ready := valid && who === UInt(i) && io.mem.req_data.ready
anyReq = anyReq || io.req(i).valid
}
val nextWho = PriorityEncoder(io.req.map(_.valid))
when (!valid && io.req.map(_.valid).reduceLeft(_||_)) {
valid := Bool(true)
cmd_sent := Bool(false)
data_sent := Bool(false)
who := nextWho
addr := io.req(nextWho).bits
}
when (io.mem.req_data.valid && io.mem.req_data.ready) {
count := count + UInt(1)
when (count === UInt(REFILL_CYCLES-1)) {
data_sent := Bool(true)
when (cmd_sent) { valid := Bool(false) }
}
}
when (io.mem.req_cmd.valid && io.mem.req_cmd.ready) { cmd_sent := Bool(true) }
when (valid && cmd_sent && data_sent) { valid := Bool(false) }
io.mem.req_cmd.valid := valid && !cmd_sent
io.mem.req_cmd.bits.addr := addr
io.mem.req_cmd.bits.rw := Bool(true)
io.mem.req_data.valid := valid && !data_sent && io.data(who).valid
io.mem.req_data.bits := io.data(who).bits
}
class LLCData(latency: Int, sets: Int, ways: Int, leaf: Mem[UInt]) extends Module
{
val io = new Bundle {
val req = Decoupled(new LLCDataReq(ways)).flip
val req_data = Decoupled(new MemData).flip
val writeback = Decoupled(UInt(width = MEM_ADDR_BITS))
val writeback_data = Decoupled(new MemData)
val resp = Decoupled(new MemResp)
val mem_resp = Valid(new MemResp).flip
val mem_resp_set = UInt(INPUT, log2Up(sets))
val mem_resp_way = UInt(INPUT, log2Up(ways))
}
val data = Module(new BigMem(sets*ways*REFILL_CYCLES, 1, latency-1, leaf)(Bits(width = MEM_DATA_BITS)))
class QEntry extends MemResp {
val isWriteback = Bool()
override def clone = new QEntry().asInstanceOf[this.type]
}
val q = Module(new Queue(new QEntry, latency+2))
val qReady = q.io.count <= UInt(q.entries-latency-1)
val valid = Reg(init=Bool(false))
val req = Reg(io.req.bits.clone)
val count = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
val refillCount = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
when (data.io.in.valid && !io.mem_resp.valid) {
count := count + UInt(1)
when (valid && count === UInt(REFILL_CYCLES-1)) { valid := Bool(false) }
}
when (io.req.valid && io.req.ready) { valid := Bool(true); req := io.req.bits }
when (io.mem_resp.valid) { refillCount := refillCount + UInt(1) }
data.io.in.valid := io.req.valid && io.req.ready && Mux(io.req.bits.rw, io.req_data.valid, qReady)
data.io.in.bits.addr := Cat(io.req.bits.way, io.req.bits.addr(log2Up(sets)-1, 0), count).toUInt
data.io.in.bits.rw := io.req.bits.rw
data.io.in.bits.wdata := io.req_data.bits.data
data.io.in.bits.wmask := SInt(-1, io.req_data.bits.data.width)
when (valid) {
data.io.in.valid := Mux(req.rw, io.req_data.valid, qReady)
data.io.in.bits.addr := Cat(req.way, req.addr(log2Up(sets)-1, 0), count).toUInt
data.io.in.bits.rw := req.rw
}
when (io.mem_resp.valid) {
data.io.in.valid := Bool(true)
data.io.in.bits.addr := Cat(io.mem_resp_way, io.mem_resp_set, refillCount).toUInt
data.io.in.bits.rw := Bool(true)
data.io.in.bits.wdata := io.mem_resp.bits.data
}
val tagPipe = Pipe(data.io.in.valid && !data.io.in.bits.rw, Mux(valid, req.tag, io.req.bits.tag), latency)
q.io.enq.valid := tagPipe.valid
q.io.enq.bits.tag := tagPipe.bits
q.io.enq.bits.isWriteback := Pipe(Mux(valid, req.isWriteback, io.req.bits.isWriteback), Bool(false), latency).valid
q.io.enq.bits.data := data.io.rdata
io.req.ready := !valid && Mux(io.req.bits.isWriteback, io.writeback.ready, Bool(true))
io.req_data.ready := !io.mem_resp.valid && Mux(valid, req.rw, io.req.valid && io.req.bits.rw)
io.writeback.valid := io.req.valid && io.req.ready && io.req.bits.isWriteback
io.writeback.bits := io.req.bits.addr
q.io.deq.ready := Mux(q.io.deq.bits.isWriteback, io.writeback_data.ready, io.resp.ready)
io.resp.valid := q.io.deq.valid && !q.io.deq.bits.isWriteback
io.resp.bits := q.io.deq.bits
io.writeback_data.valid := q.io.deq.valid && q.io.deq.bits.isWriteback
io.writeback_data.bits := q.io.deq.bits
}
class MemReqArb(n: Int) extends Module // UNTESTED
{
val io = new Bundle {
val cpu = Vec.fill(n){new ioMem().flip}
val mem = new ioMem
}
val lock = Reg(init=Bool(false))
val locker = Reg(UInt())
val arb = Module(new RRArbiter(new MemReqCmd, n))
val respWho = io.mem.resp.bits.tag(log2Up(n)-1,0)
val respTag = io.mem.resp.bits.tag >> UInt(log2Up(n))
for (i <- 0 until n) {
val me = UInt(i, log2Up(n))
arb.io.in(i).valid := io.cpu(i).req_cmd.valid
arb.io.in(i).bits := io.cpu(i).req_cmd.bits
arb.io.in(i).bits.tag := Cat(io.cpu(i).req_cmd.bits.tag, me)
io.cpu(i).req_cmd.ready := arb.io.in(i).ready
io.cpu(i).req_data.ready := Bool(false)
val getLock = io.cpu(i).req_cmd.fire() && io.cpu(i).req_cmd.bits.rw && !lock
val haveLock = lock && locker === me
when (getLock) {
lock := Bool(true)
locker := UInt(i)
}
when (getLock || haveLock) {
io.cpu(i).req_data.ready := io.mem.req_data.ready
io.mem.req_data.valid := Bool(true)
io.mem.req_data.bits := io.cpu(i).req_data.bits
}
io.cpu(i).resp.valid := io.mem.resp.valid && respWho === me
io.cpu(i).resp.bits := io.mem.resp.bits
io.cpu(i).resp.bits.tag := respTag
}
io.mem.resp.ready := io.cpu(respWho).resp.ready
val unlock = Counter(io.mem.req_data.fire(), REFILL_CYCLES)._2
when (unlock) { lock := Bool(false) }
}
class DRAMSideLLC(sets: Int, ways: Int, outstanding: Int, tagLeaf: Mem[UInt], dataLeaf: Mem[UInt]) extends Module
{
val io = new Bundle {
val cpu = new ioMem().flip
val mem = new ioMemPipe
}
val tagWidth = MEM_ADDR_BITS - log2Up(sets)
val metaWidth = tagWidth + 2 // valid + dirty
val memCmdArb = Module(new Arbiter(new MemReqCmd, 2))
val dataArb = Module(new Arbiter(new LLCDataReq(ways), 2))
val mshr = Module(new LLCMSHRFile(sets, ways, outstanding))
val tags = Module(new BigMem(sets, 0, 1, tagLeaf)(Bits(width = metaWidth*ways)))
val data = Module(new LLCData(4, sets, ways, dataLeaf))
val writeback = Module(new LLCWriteback(2))
val initCount = Reg(init=UInt(0, log2Up(sets+1)))
val initialize = !initCount(log2Up(sets))
when (initialize) { initCount := initCount + UInt(1) }
val replay_s2 = Reg(init=Bool(false))
val s2_valid = Reg(init=Bool(false))
val s2 = Reg(new MemReqCmd)
val s3_rdy = Bool()
val replay_s2_rdy = Bool()
val s1_valid = Reg(next = io.cpu.req_cmd.fire() || replay_s2 && replay_s2_rdy, init = Bool(false))
val s1 = Reg(new MemReqCmd)
when (io.cpu.req_cmd.fire()) { s1 := io.cpu.req_cmd.bits }
when (replay_s2 && replay_s2_rdy) { s1 := s2 }
s2_valid := s1_valid
replay_s2 := s2_valid && !s3_rdy || replay_s2 && !replay_s2_rdy
val s2_tags = Vec.fill(ways){Reg(Bits(width = metaWidth))}
when (s1_valid) {
s2 := s1
for (i <- 0 until ways)
s2_tags(i) := tags.io.rdata(metaWidth*(i+1)-1, metaWidth*i)
}
val s2_hits = s2_tags.map(t => t(tagWidth) && s2.addr(s2.addr.width-1, s2.addr.width-tagWidth) === t(tagWidth-1, 0))
val s2_hit_way = OHToUInt(s2_hits)
val s2_hit = s2_hits.reduceLeft(_||_)
val s2_hit_dirty = s2_tags(s2_hit_way)(tagWidth+1)
val repl_way = LFSR16(s2_valid)(log2Up(ways)-1, 0)
val repl_tag = s2_tags(repl_way).toUInt
val setDirty = s2_valid && s2.rw && s2_hit && !s2_hit_dirty
val tag_we = initialize || setDirty || mshr.io.tag.fire()
val tag_waddr = Mux(initialize, initCount, Mux(setDirty, s2.addr, mshr.io.tag.bits.addr))
val tag_wdata = Cat(setDirty, !initialize, Mux(setDirty, s2.addr, mshr.io.tag.bits.addr)(mshr.io.tag.bits.addr.width-1, mshr.io.tag.bits.addr.width-tagWidth))
val tag_wmask = Mux(initialize, SInt(-1, ways), UIntToOH(Mux(setDirty, s2_hit_way, mshr.io.tag.bits.way)))
tags.io.in.valid := io.cpu.req_cmd.fire() || replay_s2 && replay_s2_rdy || tag_we
tags.io.in.bits.addr := Mux(tag_we, tag_waddr, Mux(replay_s2, s2.addr, io.cpu.req_cmd.bits.addr)(log2Up(sets)-1,0))
tags.io.in.bits.rw := tag_we
tags.io.in.bits.wdata := Fill(ways, tag_wdata)
tags.io.in.bits.wmask := FillInterleaved(metaWidth, tag_wmask)
mshr.io.cpu.valid := s2_valid && !s2_hit && !s2.rw
mshr.io.cpu.bits := s2
mshr.io.repl_way := repl_way
mshr.io.repl_dirty := repl_tag(tagWidth+1, tagWidth).andR
mshr.io.repl_tag := repl_tag
mshr.io.mem.resp := io.mem.resp
mshr.io.tag.ready := !s1_valid && !s2_valid
data.io.req <> dataArb.io.out
data.io.mem_resp := io.mem.resp
data.io.mem_resp_set := mshr.io.mem_resp_set
data.io.mem_resp_way := mshr.io.mem_resp_way
data.io.req_data.bits := io.cpu.req_data.bits
data.io.req_data.valid := io.cpu.req_data.valid
writeback.io.req(0) <> data.io.writeback
writeback.io.data(0) <> data.io.writeback_data
writeback.io.req(1).valid := s2_valid && !s2_hit && s2.rw && mshr.io.cpu.ready
writeback.io.req(1).bits := s2.addr
writeback.io.data(1).valid := io.cpu.req_data.valid
writeback.io.data(1).bits := io.cpu.req_data.bits
memCmdArb.io.in(0) <> mshr.io.mem.req_cmd
memCmdArb.io.in(1) <> writeback.io.mem.req_cmd
dataArb.io.in(0) <> mshr.io.data
dataArb.io.in(1).valid := s2_valid && s2_hit && mshr.io.cpu.ready
dataArb.io.in(1).bits := s2
dataArb.io.in(1).bits.way := s2_hit_way
dataArb.io.in(1).bits.isWriteback := Bool(false)
s3_rdy := mshr.io.cpu.ready && Mux(s2_hit, dataArb.io.in(1).ready, !s2.rw || writeback.io.req(1).ready)
replay_s2_rdy := s3_rdy && !tag_we
io.cpu.resp <> data.io.resp
io.cpu.req_cmd.ready := !s1_valid && !s2_valid && !replay_s2 && !tag_we
io.cpu.req_data.ready := writeback.io.data(1).ready || data.io.req_data.ready
io.mem.req_cmd <> memCmdArb.io.out
io.mem.req_data <> writeback.io.mem.req_data
}
class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module
{
val io = new QueueIO(data, entries)
require(isPow2(entries) && entries > 1)
val do_flow = Bool()
val do_enq = io.enq.fire() && !do_flow
val do_deq = io.deq.fire() && !do_flow
val maybe_full = Reg(init=Bool(false))
val enq_ptr = Counter(do_enq, entries)._1
val deq_ptr = Counter(do_deq, entries)._1
when (do_enq != do_deq) { maybe_full := do_enq }
val ptr_match = enq_ptr === deq_ptr
val empty = ptr_match && !maybe_full
val full = ptr_match && maybe_full
val atLeastTwo = full || enq_ptr - deq_ptr >= UInt(2)
do_flow := empty && io.deq.ready
val ram = Mem(data, entries, seqRead = true)
val ram_addr = Reg(Bits())
val ram_out_valid = Reg(Bool())
ram_out_valid := Bool(false)
when (do_enq) { ram(enq_ptr) := io.enq.bits.toBits }
when (io.deq.ready && (atLeastTwo || !io.deq.valid && !empty)) {
ram_out_valid := Bool(true)
ram_addr := Mux(io.deq.valid, deq_ptr + UInt(1), deq_ptr)
}
io.deq.valid := Mux(empty, io.enq.valid, ram_out_valid)
io.enq.ready := !full
io.deq.bits := Mux(empty, io.enq.bits, ram(ram_addr))
}
class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module
{
val io = new QueueIO(data, entries)
val fq = Module(new HellaFlowQueue(entries)(data))
io.enq <> fq.io.enq
io.deq <> Queue(fq.io.deq, 1, pipe = true)
}
object HellaQueue
{
def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = {
val q = Module((new HellaQueue(entries)) { enq.bits.clone })
q.io.enq.valid := enq.valid // not using <> so that override is allowed
q.io.enq.bits := enq.bits
enq.ready := q.io.enq.ready
q.io.deq
}
}
class DRAMSideLLCNull(numRequests: Int, refillCycles: Int) extends Module
{
val io = new Bundle {
val cpu = new ioMem().flip
val mem = new ioMemPipe
}
val numEntries = numRequests * refillCycles
val size = log2Down(numEntries) + 1
val inc = Bool()
val dec = Bool()
val count = Reg(init=UInt(numEntries, size))
val watermark = count >= UInt(refillCycles)
when (inc && !dec) {
count := count + UInt(1)
}
when (!inc && dec) {
count := count - UInt(refillCycles)
}
when (inc && dec) {
count := count - UInt(refillCycles-1)
}
val cmdq_mask = io.cpu.req_cmd.bits.rw || watermark
io.mem.req_cmd.valid := io.cpu.req_cmd.valid && cmdq_mask
io.cpu.req_cmd.ready := io.mem.req_cmd.ready && cmdq_mask
io.mem.req_cmd.bits := io.cpu.req_cmd.bits
io.mem.req_data <> io.cpu.req_data
val resp_dataq = Module((new HellaQueue(numEntries)) { new MemResp })
resp_dataq.io.enq <> io.mem.resp
io.cpu.resp <> resp_dataq.io.deq
inc := resp_dataq.io.deq.fire()
dec := io.mem.req_cmd.fire() && !io.mem.req_cmd.bits.rw
}

View File

@ -0,0 +1,187 @@
package uncore
import Chisel._
import scala.math._
trait HasMemData extends Bundle {
val data = Bits(width = MEM_DATA_BITS)
}
trait HasMemAddr extends Bundle {
val addr = UInt(width = MEM_ADDR_BITS)
}
trait HasMemTag extends Bundle {
val tag = UInt(width = MEM_TAG_BITS)
}
class MemReqCmd extends HasMemAddr with HasMemTag {
val rw = Bool()
}
class MemResp extends HasMemData with HasMemTag
class MemData extends HasMemData
class ioMem extends Bundle {
val req_cmd = Decoupled(new MemReqCmd)
val req_data = Decoupled(new MemData)
val resp = Decoupled(new MemResp).flip
}
class ioMemPipe extends Bundle {
val req_cmd = Decoupled(new MemReqCmd)
val req_data = Decoupled(new MemData)
val resp = Valid(new MemResp).flip
}
class ioMemSerialized(w: Int) extends Bundle
{
val req = Decoupled(Bits(width = w))
val resp = Valid(Bits(width = w)).flip
}
class MemSerdes(w: Int) extends Module
{
val io = new Bundle {
val wide = new ioMem().flip
val narrow = new ioMemSerialized(w)
}
val abits = io.wide.req_cmd.bits.toBits.getWidth
val dbits = io.wide.req_data.bits.toBits.getWidth
val rbits = io.wide.resp.bits.getWidth
val out_buf = Reg(Bits())
val in_buf = Reg(Bits())
val s_idle :: s_read_addr :: s_write_addr :: s_write_idle :: s_write_data :: Nil = Enum(5) { UInt() }
val state = Reg(init=s_idle)
val send_cnt = Reg(init=UInt(0, log2Up((max(abits, dbits)+w-1)/w)))
val data_send_cnt = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
val adone = io.narrow.req.ready && send_cnt === UInt((abits-1)/w)
val ddone = io.narrow.req.ready && send_cnt === UInt((dbits-1)/w)
when (io.narrow.req.valid && io.narrow.req.ready) {
send_cnt := send_cnt + UInt(1)
out_buf := out_buf >> UInt(w)
}
when (io.wide.req_cmd.valid && io.wide.req_cmd.ready) {
out_buf := io.wide.req_cmd.bits.toBits
}
when (io.wide.req_data.valid && io.wide.req_data.ready) {
out_buf := io.wide.req_data.bits.toBits
}
io.wide.req_cmd.ready := state === s_idle
io.wide.req_data.ready := state === s_write_idle
io.narrow.req.valid := state === s_read_addr || state === s_write_addr || state === s_write_data
io.narrow.req.bits := out_buf
when (state === s_idle && io.wide.req_cmd.valid) {
state := Mux(io.wide.req_cmd.bits.rw, s_write_addr, s_read_addr)
}
when (state === s_read_addr && adone) {
state := s_idle
send_cnt := UInt(0)
}
when (state === s_write_addr && adone) {
state := s_write_idle
send_cnt := UInt(0)
}
when (state === s_write_idle && io.wide.req_data.valid) {
state := s_write_data
}
when (state === s_write_data && ddone) {
data_send_cnt := data_send_cnt + UInt(1)
state := Mux(data_send_cnt === UInt(REFILL_CYCLES-1), s_idle, s_write_idle)
send_cnt := UInt(0)
}
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
val data_recv_cnt = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
val resp_val = Reg(init=Bool(false))
resp_val := Bool(false)
when (io.narrow.resp.valid) {
recv_cnt := recv_cnt + UInt(1)
when (recv_cnt === UInt((rbits-1)/w)) {
recv_cnt := UInt(0)
data_recv_cnt := data_recv_cnt + UInt(1)
resp_val := Bool(true)
}
in_buf := Cat(io.narrow.resp.bits, in_buf((rbits+w-1)/w*w-1,w))
}
io.wide.resp.valid := resp_val
io.wide.resp.bits.tag := in_buf(io.wide.resp.bits.tag.width-1,0)
io.wide.resp.bits.data := in_buf >> UInt(io.wide.resp.bits.tag.width)
}
class MemDesserIO(w: Int) extends Bundle {
val narrow = new ioMemSerialized(w).flip
val wide = new ioMem
}
class MemDesser(w: Int) extends Module // test rig side
{
val io = new MemDesserIO(w)
val abits = io.wide.req_cmd.bits.toBits.getWidth
val dbits = io.wide.req_data.bits.toBits.getWidth
val rbits = io.wide.resp.bits.getWidth
require(dbits >= abits && rbits >= dbits)
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
val data_recv_cnt = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
val adone = io.narrow.req.valid && recv_cnt === UInt((abits-1)/w)
val ddone = io.narrow.req.valid && recv_cnt === UInt((dbits-1)/w)
val rdone = io.narrow.resp.valid && recv_cnt === UInt((rbits-1)/w)
val s_cmd_recv :: s_cmd :: s_data_recv :: s_data :: s_reply :: Nil = Enum(5) { UInt() }
val state = Reg(init=s_cmd_recv)
val in_buf = Reg(Bits())
when (io.narrow.req.valid && io.narrow.req.ready || io.narrow.resp.valid) {
recv_cnt := recv_cnt + UInt(1)
in_buf := Cat(io.narrow.req.bits, in_buf((rbits+w-1)/w*w-1,w))
}
io.narrow.req.ready := state === s_cmd_recv || state === s_data_recv
when (state === s_cmd_recv && adone) {
state := s_cmd
recv_cnt := UInt(0)
}
when (state === s_cmd && io.wide.req_cmd.ready) {
state := Mux(io.wide.req_cmd.bits.rw, s_data_recv, s_reply)
}
when (state === s_data_recv && ddone) {
state := s_data
recv_cnt := UInt(0)
}
when (state === s_data && io.wide.req_data.ready) {
state := s_data_recv
when (data_recv_cnt === UInt(REFILL_CYCLES-1)) {
state := s_cmd_recv
}
data_recv_cnt := data_recv_cnt + UInt(1)
}
when (rdone) { // state === s_reply
when (data_recv_cnt === UInt(REFILL_CYCLES-1)) {
state := s_cmd_recv
}
recv_cnt := UInt(0)
data_recv_cnt := data_recv_cnt + UInt(1)
}
val req_cmd = in_buf >> UInt(((rbits+w-1)/w - (abits+w-1)/w)*w)
io.wide.req_cmd.valid := state === s_cmd
io.wide.req_cmd.bits := io.wide.req_cmd.bits.fromBits(req_cmd)
io.wide.req_data.valid := state === s_data
io.wide.req_data.bits.data := in_buf >> UInt(((rbits+w-1)/w - (dbits+w-1)/w)*w)
val dataq = Module(new Queue(new MemResp, REFILL_CYCLES))
dataq.io.enq <> io.wide.resp
dataq.io.deq.ready := recv_cnt === UInt((rbits-1)/w)
io.narrow.resp.valid := dataq.io.deq.valid
io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w))
}

View File

@ -0,0 +1,175 @@
package uncore
import Chisel._
import scala.collection.mutable.Stack
class PairedDataIO[M <: Data, D <: Data]()(m: => M, d: => D) extends Bundle {
val meta = Decoupled(m)
val data = Decoupled(d)
override def clone = { new PairedDataIO()(m,d).asInstanceOf[this.type] }
}
class PairedArbiterIO[M <: Data, D <: Data](n: Int)(m: => M, d: => D) extends Bundle {
val in = Vec.fill(n){new PairedDataIO()(m,d)}.flip
val out = new PairedDataIO()(m,d)
val meta_chosen = Bits(OUTPUT, log2Up(n))
val data_chosen = Bits(OUTPUT, log2Up(n))
override def clone = { new PairedArbiterIO(n)(m,d).asInstanceOf[this.type] }
}
class PairedLockingRRArbiter[M <: Data, D <: Data](n: Int, count: Int, needsLock: Option[M => Bool] = None)(meta: => M, data: => D) extends Module {
require(isPow2(count))
val io = new PairedArbiterIO(n)(meta,data)
val locked = if(count > 1) Reg(init=Bool(false)) else Bool(false)
val lockIdx = if(count > 1) Reg(init=UInt(n-1)) else UInt(n-1)
val grant = List.fill(n)(Bool())
val meta_chosen = Bits(width = log2Up(n))
val chosen_meta_has_data = needsLock.map(_(io.in(meta_chosen).meta.bits)).getOrElse(Bool(true))
val valid_meta_has_data = io.in(meta_chosen).meta.valid && chosen_meta_has_data
val grant_chosen_meta = !(locked && chosen_meta_has_data)
(0 until n).map(i => io.in(i).meta.ready := grant(i) && grant_chosen_meta && io.out.meta.ready)
(0 until n).map(i => io.in(i).data.ready := Mux(locked, lockIdx === UInt(i), grant(i) && valid_meta_has_data) && io.out.data.ready)
io.out.meta.valid := io.in(meta_chosen).meta.valid && grant_chosen_meta
io.out.data.valid := Mux(locked, io.in(lockIdx).data.valid, io.in(meta_chosen).data.valid && valid_meta_has_data)
io.out.meta.bits := io.in(meta_chosen).meta.bits
io.out.data.bits := Mux(locked, io.in(lockIdx).data.bits, io.in(meta_chosen).data.bits)
io.meta_chosen := meta_chosen
io.data_chosen := Mux(locked, lockIdx, meta_chosen)
if(count > 1){
val cnt = Reg(init=UInt(0, width = log2Up(count)))
val cnt_next = cnt + UInt(1)
when(io.out.data.fire()){
cnt := cnt_next
when(cnt_next === UInt(0)) {
locked := Bool(false)
}
}
when(io.out.meta.fire()) {
when(needsLock.map(_(io.out.meta.bits)).getOrElse(Bool(true))) {
when(!locked) {
locked := Bool(true)
lockIdx := Vec(io.in.map{in => in.meta.fire()}).indexWhere{i: Bool => i}
}
}
}
}
val last_grant = Reg(init=Bits(0, log2Up(n)))
val ctrl = ArbiterCtrl((0 until n).map(i => io.in(i).meta.valid && UInt(i) > last_grant) ++ io.in.map(_.meta.valid))
(0 until n).map(i => grant(i) := ctrl(i) && UInt(i) > last_grant || ctrl(i + n))
var choose = Bits(n-1)
for (i <- n-2 to 0 by -1)
choose = Mux(io.in(i).meta.valid, Bits(i), choose)
for (i <- n-1 to 1 by -1)
choose = Mux(io.in(i).meta.valid && UInt(i) > last_grant, Bits(i), choose)
meta_chosen := choose
when (io.out.meta.fire()) { last_grant := meta_chosen }
}
class PairedCrossbar[M <: Data, D <: Data](count: Int, needsLock: Option[PhysicalNetworkIO[M] => Bool] = None)(meta: => M, data: => D)(implicit conf: PhysicalNetworkConfiguration) extends PhysicalNetwork(conf) {
val io = new Bundle {
val in = Vec.fill(conf.nEndpoints){new PairedDataIO()(new PhysicalNetworkIO()(meta),new PhysicalNetworkIO()(data))}.flip
val out = Vec.fill(conf.nEndpoints){new PairedDataIO()(new PhysicalNetworkIO()(meta),new PhysicalNetworkIO()(data))}
}
val metaRdyVecs = List.fill(conf.nEndpoints)(Vec.fill(conf.nEndpoints){Bool()})
val dataRdyVecs = List.fill(conf.nEndpoints)(Vec.fill(conf.nEndpoints){Bool()})
val rdyVecs = metaRdyVecs zip dataRdyVecs
io.out.zip(rdyVecs).zipWithIndex.map{ case ((out, rdys), i) => {
val rrarb = Module(new PairedLockingRRArbiter(conf.nEndpoints, count, needsLock)(io.in(0).meta.bits.clone, io.in(0).data.bits.clone))
rrarb.io.in zip io.in zip rdys._1 zip rdys._2 map { case (((arb, in), meta_rdy), data_rdy) => {
arb.meta.valid := in.meta.valid && (in.meta.bits.header.dst === UInt(i))
arb.meta.bits := in.meta.bits
meta_rdy := arb.meta.ready && (in.meta.bits.header.dst === UInt(i))
arb.data.valid := in.data.valid && (in.data.bits.header.dst === UInt(i))
arb.data.bits := in.data.bits
data_rdy := arb.data.ready && (in.data.bits.header.dst === UInt(i))
}}
out <> rrarb.io.out
}}
for(i <- 0 until conf.nEndpoints) {
io.in(i).meta.ready := rdyVecs.map(r => r._1(i)).reduceLeft(_||_)
io.in(i).data.ready := rdyVecs.map(r => r._2(i)).reduceLeft(_||_)
}
}
case class PhysicalNetworkConfiguration(nEndpoints: Int, idBits: Int)
class PhysicalHeader(implicit conf: PhysicalNetworkConfiguration) extends Bundle {
val src = UInt(width = conf.idBits)
val dst = UInt(width = conf.idBits)
}
class PhysicalNetworkIO[T <: Data]()(data: => T)(implicit conf: PhysicalNetworkConfiguration) extends Bundle {
val header = (new PhysicalHeader)
val payload = data
override def clone = { new PhysicalNetworkIO()(data).asInstanceOf[this.type] }
}
abstract class PhysicalNetwork(conf: PhysicalNetworkConfiguration) extends Module
class BasicCrossbar[T <: Data](count: Int = 1)(data: => T)(implicit conf: PhysicalNetworkConfiguration) extends PhysicalNetwork(conf) {
val io = new Bundle {
val in = Vec.fill(conf.nEndpoints){Decoupled((new PhysicalNetworkIO){data})}.flip
val out = Vec.fill(conf.nEndpoints){Decoupled((new PhysicalNetworkIO){data})}
}
val rdyVecs = List.fill(conf.nEndpoints)(Vec.fill(conf.nEndpoints)(Bool()))
io.out.zip(rdyVecs).zipWithIndex.map{ case ((out, rdys), i) => {
val rrarb = Module(new LockingRRArbiter(io.in(0).bits, conf.nEndpoints, count))
(rrarb.io.in, io.in, rdys).zipped.map{ case (arb, in, rdy) => {
arb.valid := in.valid && (in.bits.header.dst === UInt(i))
arb.bits := in.bits
rdy := arb.ready && (in.bits.header.dst === UInt(i))
}}
out <> rrarb.io.out
}}
for(i <- 0 until conf.nEndpoints) {
io.in(i).ready := rdyVecs.map(r => r(i)).reduceLeft(_||_)
}
}
case class LogicalNetworkConfiguration(nEndpoints: Int, idBits: Int, nMasters: Int, nClients: Int)
abstract class LogicalNetwork[TileLinkType <: Bundle](endpoints: Seq[CoherenceAgentRole])(implicit conf: LogicalNetworkConfiguration) extends Module {
override val io: Vec[TileLinkType]
val physicalNetworks: Seq[PhysicalNetwork]
require(endpoints.length == conf.nEndpoints)
}
class LogicalHeader(implicit conf: LogicalNetworkConfiguration) extends Bundle {
val src = UInt(width = conf.idBits)
val dst = UInt(width = conf.idBits)
}
object FIFOedLogicalNetworkIOWrapper {
def apply[T <: Data](in: DecoupledIO[T], src: UInt = UInt(0), dst: UInt = UInt(0))(implicit conf: LogicalNetworkConfiguration) = {
val out = Decoupled((new LogicalNetworkIO){in.bits.clone}).asDirectionless
out.valid := in.valid
out.bits.payload := in.bits
out.bits.header.dst := dst
out.bits.header.src := src
in.ready := out.ready
out
}
}
object FIFOedLogicalNetworkIOUnwrapper {
def apply[T <: Data](in: DecoupledIO[LogicalNetworkIO[T]])(implicit conf: LogicalNetworkConfiguration) = {
val out = Decoupled(in.bits.payload.clone).asDirectionless
out.valid := in.valid
out.bits := in.bits.payload
in.ready := out.ready
out
}
}
class LogicalNetworkIO[T <: Data]()(data: => T)(implicit conf: LogicalNetworkConfiguration) extends Bundle {
val header = new LogicalHeader
val payload = data
override def clone = { new LogicalNetworkIO()(data).asInstanceOf[this.type] }
}

View File

@ -0,0 +1,7 @@
package object uncore extends
uncore.constants.MemoryOpConstants with
uncore.constants.TileLinkSizeConstants with
uncore.constants.MemoryInterfaceConstants
{
implicit def toOption[A](a: A) = Option(a)
}

View File

@ -0,0 +1,68 @@
package uncore
import Chisel._
class SlowIO[T <: Data](val divisor_max: Int)(data: => T) extends Module
{
val io = new Bundle {
val out_fast = Decoupled(data).flip
val out_slow = Decoupled(data)
val in_fast = Decoupled(data)
val in_slow = Decoupled(data).flip
val clk_slow = Bool(OUTPUT)
val set_divisor = Valid(Bits(width = 32)).flip
val divisor = Bits(OUTPUT, 32)
}
require(divisor_max >= 8 && divisor_max <= 65536 && isPow2(divisor_max))
val divisor = Reg(init=UInt(divisor_max-1))
val d_shadow = Reg(init=UInt(divisor_max-1))
val hold = Reg(init=UInt(divisor_max/4-1))
val h_shadow = Reg(init=UInt(divisor_max/4-1))
when (io.set_divisor.valid) {
d_shadow := io.set_divisor.bits(log2Up(divisor_max)-1, 0).toUInt
h_shadow := io.set_divisor.bits(log2Up(divisor_max)-1+16, 16).toUInt
}
io.divisor := hold << UInt(16) | divisor
val count = Reg{UInt(width = log2Up(divisor_max))}
val myclock = Reg{Bool()}
count := count + UInt(1)
val rising = count === (divisor >> UInt(1))
val falling = count === divisor
val held = count === (divisor >> UInt(1)) + hold
when (falling) {
divisor := d_shadow
hold := h_shadow
count := UInt(0)
myclock := Bool(false)
}
when (rising) {
myclock := Bool(true)
}
val in_slow_rdy = Reg(init=Bool(false))
val out_slow_val = Reg(init=Bool(false))
val out_slow_bits = Reg(data)
val fromhost_q = Module(new Queue(data,1))
fromhost_q.io.enq.valid := rising && (io.in_slow.valid && in_slow_rdy || reset)
fromhost_q.io.enq.bits := io.in_slow.bits
fromhost_q.io.deq <> io.in_fast
val tohost_q = Module(new Queue(data,1))
tohost_q.io.enq <> io.out_fast
tohost_q.io.deq.ready := rising && io.out_slow.ready && out_slow_val
when (held) {
in_slow_rdy := fromhost_q.io.enq.ready
out_slow_val := tohost_q.io.deq.valid
out_slow_bits := Mux(reset, fromhost_q.io.deq.bits, tohost_q.io.deq.bits)
}
io.in_slow.ready := in_slow_rdy
io.out_slow.valid := out_slow_val
io.out_slow.bits := out_slow_bits
io.clk_slow := myclock
}

View File

@ -0,0 +1,176 @@
package uncore
import Chisel._
case class TileLinkConfiguration(co: CoherencePolicyWithUncached, ln: LogicalNetworkConfiguration, masterXactIdBits: Int, clientXactIdBits: Int, dataBits: Int)
abstract trait TileLinkSubBundle extends Bundle {
implicit val conf: TileLinkConfiguration
override def clone = this.getClass.getConstructors.head.newInstance(conf).asInstanceOf[this.type]
}
trait HasPhysicalAddress extends TileLinkSubBundle {
val addr = UInt(width = PADDR_BITS - OFFSET_BITS)
}
trait HasClientTransactionId extends TileLinkSubBundle {
val client_xact_id = Bits(width = conf.clientXactIdBits)
}
trait HasMasterTransactionId extends TileLinkSubBundle {
val master_xact_id = Bits(width = conf.masterXactIdBits)
}
trait HasTileLinkData extends TileLinkSubBundle {
val data = Bits(width = conf.dataBits)
}
trait SourcedMessage extends Bundle
trait ClientSourcedMessage extends SourcedMessage
trait MasterSourcedMessage extends SourcedMessage
object Acquire
{
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
val acq = new Acquire
acq.a_type := a_type
acq.addr := addr
acq.client_xact_id := client_xact_id
acq.write_mask := Bits(0)
acq.subword_addr := Bits(0)
acq.atomic_opcode := Bits(0)
acq
}
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt, write_mask: Bits)(implicit conf: TileLinkConfiguration): Acquire = {
val acq = apply(a_type, addr, client_xact_id)
acq.write_mask := write_mask
acq
}
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt, subword_addr: UInt, atomic_opcode: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
val acq = apply(a_type, addr, client_xact_id)
acq.subword_addr := subword_addr
acq.atomic_opcode := atomic_opcode
acq
}
}
class Acquire(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasPhysicalAddress with HasClientTransactionId {
val a_type = Bits(width = conf.co.acquireTypeWidth)
val write_mask = Bits(width = ACQUIRE_WRITE_MASK_BITS)
val subword_addr = Bits(width = ACQUIRE_SUBWORD_ADDR_BITS)
val atomic_opcode = Bits(width = ACQUIRE_ATOMIC_OP_BITS)
}
class AcquireData(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasTileLinkData
class Probe(implicit val conf: TileLinkConfiguration) extends MasterSourcedMessage with HasPhysicalAddress with HasMasterTransactionId {
val p_type = Bits(width = conf.co.probeTypeWidth)
}
object Release
{
def apply(r_type: Bits, addr: UInt, client_xact_id: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
val rel = new Release
rel.r_type := r_type
rel.addr := addr
rel.client_xact_id := client_xact_id
rel.master_xact_id := master_xact_id
rel
}
}
class Release(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasPhysicalAddress with HasClientTransactionId with HasMasterTransactionId {
val r_type = Bits(width = conf.co.releaseTypeWidth)
}
class ReleaseData(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasTileLinkData
class Grant(implicit val conf: TileLinkConfiguration) extends MasterSourcedMessage with HasTileLinkData with HasClientTransactionId with HasMasterTransactionId {
val g_type = Bits(width = conf.co.grantTypeWidth)
}
class GrantAck(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasMasterTransactionId
trait DirectionalIO
trait ClientSourcedIO extends DirectionalIO
trait MasterSourcedIO extends DirectionalIO
class ClientSourcedFIFOIO[T <: Data]()(data: => T) extends DecoupledIO(data) with ClientSourcedIO {
override def clone = { new ClientSourcedFIFOIO()(data).asInstanceOf[this.type] }
}
class ClientSourcedDataIO[M <: Data, D <: Data]()(meta: => M, data: => D) extends PairedDataIO()(meta,data) with ClientSourcedIO {
override def clone = { new ClientSourcedDataIO()(meta,data).asInstanceOf[this.type] }
}
class MasterSourcedFIFOIO[T <: Data]()(data: => T) extends DecoupledIO(data) with MasterSourcedIO {
flip()
override def clone = { new MasterSourcedFIFOIO()(data).asInstanceOf[this.type] }
}
class MasterSourcedDataIO[M <: Data, D <: Data]()(meta: => M, data: => D) extends PairedDataIO()(meta,data) with MasterSourcedIO {
flip()
override def clone = { new MasterSourcedDataIO()(meta,data).asInstanceOf[this.type] }
}
class UncachedTileLinkIO(implicit conf: TileLinkConfiguration) extends Bundle {
implicit val ln = conf.ln
val acquire = new ClientSourcedDataIO()(new LogicalNetworkIO()(new Acquire), new LogicalNetworkIO()(new AcquireData))
val grant = new MasterSourcedFIFOIO()(new LogicalNetworkIO()(new Grant))
val grant_ack = new ClientSourcedFIFOIO()(new LogicalNetworkIO()(new GrantAck))
override def clone = { new UncachedTileLinkIO().asInstanceOf[this.type] }
}
class TileLinkIO(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIO()(conf) {
val probe = new MasterSourcedFIFOIO()(new LogicalNetworkIO()(new Probe))
val release = new ClientSourcedDataIO()(new LogicalNetworkIO()(new Release), new LogicalNetworkIO()(new ReleaseData))
override def clone = { new TileLinkIO().asInstanceOf[this.type] }
}
abstract class UncachedTileLinkIOArbiter(n: Int)(implicit conf: TileLinkConfiguration) extends Module {
def acquireClientXactId(in: Acquire, id: Int): Bits
def grantClientXactId(in: Grant): Bits
def arbIdx(in: Grant): UInt
implicit val (ln, co) = (conf.ln, conf.co)
val io = new Bundle {
val in = Vec.fill(n){new UncachedTileLinkIO}.flip
val out = new UncachedTileLinkIO
}
def acqHasData(acq: LogicalNetworkIO[Acquire]) = co.messageHasData(acq.payload)
val acq_arb = Module(new PairedLockingRRArbiter(n, REFILL_CYCLES, acqHasData _)((new LogicalNetworkIO){new Acquire},(new LogicalNetworkIO){new AcquireData}))
io.out.acquire <> acq_arb.io.out
io.in.map(_.acquire).zipWithIndex.zip(acq_arb.io.in).map{ case ((req,id), arb) => {
arb.data <> req.data
arb.meta.valid := req.meta.valid
arb.meta.bits := req.meta.bits
arb.meta.bits.payload.client_xact_id := acquireClientXactId(req.meta.bits.payload, id)
req.meta.ready := arb.meta.ready
}}
val grant_ack_arb = Module(new RRArbiter((new LogicalNetworkIO){new GrantAck},n))
io.out.grant_ack <> grant_ack_arb.io.out
grant_ack_arb.io.in zip io.in map { case (arb, req) => arb <> req.grant_ack }
io.out.grant.ready := Bool(false)
for (i <- 0 until n) {
io.in(i).grant.valid := Bool(false)
when (arbIdx(io.out.grant.bits.payload) === UInt(i)) {
io.in(i).grant.valid := io.out.grant.valid
io.out.grant.ready := io.in(i).grant.ready
}
io.in(i).grant.bits := io.out.grant.bits
io.in(i).grant.bits.payload.client_xact_id := grantClientXactId(io.out.grant.bits.payload)
}
}
class UncachedTileLinkIOArbiterThatAppendsArbiterId(n: Int)(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIOArbiter(n)(conf) {
def acquireClientXactId(in: Acquire, id: Int) = Cat(in.client_xact_id, UInt(id, log2Up(n)))
def grantClientXactId(in: Grant) = in.client_xact_id >> UInt(log2Up(n))
def arbIdx(in: Grant) = in.client_xact_id(log2Up(n)-1,0).toUInt
}
class UncachedTileLinkIOArbiterThatPassesId(n: Int)(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIOArbiter(n)(conf) {
def acquireClientXactId(in: Acquire, id: Int) = in.client_xact_id
def grantClientXactId(in: Grant) = in.client_xact_id
def arbIdx(in: Grant): UInt = in.client_xact_id
}
class UncachedTileLinkIOArbiterThatUsesNewId(n: Int)(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIOArbiter(n)(conf) {
def acquireClientXactId(in: Acquire, id: Int) = UInt(id, log2Up(n))
def grantClientXactId(in: Grant) = UInt(0) // DNC
def arbIdx(in: Grant) = in.client_xact_id
}

View File

@ -0,0 +1,331 @@
package uncore
import Chisel._
abstract class CoherenceAgent(implicit conf: TileLinkConfiguration) extends Module with MasterCoherenceAgent {
val io = new Bundle {
val client = (new TileLinkIO).flip
val master = new UncachedTileLinkIO
val incoherent = Vec.fill(conf.ln.nClients){Bool()}.asInput
}
}
case class L2CoherenceAgentConfiguration(tl: TileLinkConfiguration, nReleaseTransactions: Int, nAcquireTransactions: Int)
class L2CoherenceAgent(bankId: Int)(implicit conf: L2CoherenceAgentConfiguration) extends CoherenceAgent()(conf.tl)
{
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
// Create SHRs for outstanding transactions
val nTrackers = conf.nReleaseTransactions + conf.nAcquireTransactions
val trackerList = (0 until conf.nReleaseTransactions).map(id => Module(new VoluntaryReleaseTracker(id, bankId))) ++
(conf.nReleaseTransactions until nTrackers).map(id => Module(new AcquireTracker(id, bankId)))
// Propagate incoherence flags
trackerList.map(_.io.tile_incoherent := io.incoherent.toBits)
// Handle acquire transaction initiation
val acquire = io.client.acquire
val any_acquire_conflict = trackerList.map(_.io.has_acquire_conflict).reduce(_||_)
val block_acquires = any_acquire_conflict
val alloc_arb = Module(new Arbiter(Bool(), trackerList.size))
for( i <- 0 until trackerList.size ) {
val t = trackerList(i).io.client
alloc_arb.io.in(i).valid := t.acquire.meta.ready
t.acquire.meta.bits := acquire.meta.bits
t.acquire.meta.valid := alloc_arb.io.in(i).ready
t.acquire.data.bits := acquire.data.bits
t.acquire.data.valid := acquire.data.valid
}
acquire.meta.ready := trackerList.map(_.io.client.acquire.meta.ready).reduce(_||_) && !block_acquires
acquire.data.ready := trackerList.map(_.io.client.acquire.data.ready).reduce(_||_)
alloc_arb.io.out.ready := acquire.meta.valid && !block_acquires
// Handle probe request generation
val probe_arb = Module(new Arbiter((new LogicalNetworkIO){ new Probe }, trackerList.size))
io.client.probe <> probe_arb.io.out
probe_arb.io.in zip trackerList map { case (arb, t) => arb <> t.io.client.probe }
// Handle releases, which might be voluntary and might have data
val release = io.client.release
val voluntary = co.isVoluntary(release.meta.bits.payload)
val any_release_conflict = trackerList.tail.map(_.io.has_release_conflict).reduce(_||_)
val block_releases = Bool(false)
val conflict_idx = Vec(trackerList.map(_.io.has_release_conflict)).lastIndexWhere{b: Bool => b}
//val release_idx = Mux(voluntary, Mux(any_release_conflict, conflict_idx, UInt(0)), release.bits.payload.master_xact_id) // TODO: Add merging logic to allow allocated AcquireTracker to handle conflicts, send all necessary grants, use first sufficient response
val release_idx = Mux(voluntary, UInt(0), release.meta.bits.payload.master_xact_id)
for( i <- 0 until trackerList.size ) {
val t = trackerList(i).io.client
t.release.meta.bits := release.meta.bits
t.release.meta.valid := release.meta.valid && (release_idx === UInt(i)) && !block_releases
t.release.data.bits := release.data.bits
t.release.data.valid := release.data.valid
}
release.meta.ready := Vec(trackerList.map(_.io.client.release.meta.ready)).read(release_idx) && !block_releases
release.data.ready := trackerList.map(_.io.client.release.data.ready).reduce(_||_)
// Reply to initial requestor
val grant_arb = Module(new Arbiter((new LogicalNetworkIO){ new Grant }, trackerList.size))
io.client.grant <> grant_arb.io.out
grant_arb.io.in zip trackerList map { case (arb, t) => arb <> t.io.client.grant }
// Free finished transactions
val ack = io.client.grant_ack
trackerList.map(_.io.client.grant_ack.valid := ack.valid)
trackerList.map(_.io.client.grant_ack.bits := ack.bits)
ack.ready := Bool(true)
// Create an arbiter for the one memory port
val outer_arb = Module(new UncachedTileLinkIOArbiterThatPassesId(trackerList.size))
outer_arb.io.in zip trackerList map { case(arb, t) => arb <> t.io.master }
io.master <> outer_arb.io.out
}
abstract class XactTracker()(implicit conf: L2CoherenceAgentConfiguration) extends Module with OuterRequestGenerator {
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
val io = new Bundle {
val client = (new TileLinkIO).flip
val master = new UncachedTileLinkIO
val tile_incoherent = Bits(INPUT, ln.nClients)
val has_acquire_conflict = Bool(OUTPUT)
val has_release_conflict = Bool(OUTPUT)
}
}
class VoluntaryReleaseTracker(trackerId: Int, bankId: Int)(implicit conf: L2CoherenceAgentConfiguration) extends XactTracker()(conf) {
val s_idle :: s_mem :: s_ack :: s_busy :: Nil = Enum(4){ UInt() }
val state = Reg(init=s_idle)
val xact = Reg{ new Release }
val init_client_id_ = Reg(init=UInt(0, width = log2Up(ln.nClients)))
val release_data_needs_write = Reg(init=Bool(false))
val mem_cmd_sent = Reg(init=Bool(false))
val cmd_to_write = Acquire(co.getUncachedWriteAcquireType, xact.addr, UInt(trackerId))
io.has_acquire_conflict := Bool(false)
io.has_release_conflict := co.isCoherenceConflict(xact.addr, io.client.release.meta.bits.payload.addr) && (state != s_idle)
io.master.grant.ready := Bool(false)
io.master.acquire.meta.valid := Bool(false)
io.master.acquire.meta.bits.payload := cmd_to_write
//TODO io.master.acquire.bits.header.dst
io.master.acquire.meta.bits.header.src := UInt(bankId)
io.master.acquire.data.valid := Bool(false)
io.master.acquire.data.bits.payload.data := UInt(0)
//TODO io.master.acquire_data.bits.header.dst
io.master.acquire.data.bits.header.src := UInt(bankId)
io.client.acquire.meta.ready := Bool(false)
io.client.acquire.data.ready := Bool(false)
io.client.probe.valid := Bool(false)
io.client.release.meta.ready := Bool(false)
io.client.release.data.ready := Bool(false) // DNC
io.client.grant.valid := Bool(false)
io.client.grant.bits.payload.g_type := co.getGrantType(xact, UInt(0))
io.client.grant.bits.payload.client_xact_id := xact.client_xact_id
io.client.grant.bits.payload.master_xact_id := UInt(trackerId)
io.client.grant.bits.payload.data := UInt(0)
io.client.grant.bits.header.dst := init_client_id_
io.client.grant.bits.header.src := UInt(bankId)
io.client.grant_ack.valid := Bool(false)
switch (state) {
is(s_idle) {
io.client.release.meta.ready := Bool(true)
when( io.client.release.meta.valid ) {
xact := io.client.release.meta.bits.payload
init_client_id_ := io.client.release.meta.bits.header.src
release_data_needs_write := co.messageHasData(io.client.release.meta.bits.payload)
mem_cnt := UInt(0)
mem_cmd_sent := Bool(false)
state := s_mem
}
}
is(s_mem) {
when (release_data_needs_write) {
doOuterReqWrite(io.master.acquire,
io.client.release.data,
cmd_to_write,
release_data_needs_write,
mem_cmd_sent,
init_client_id_)
} . otherwise { state := s_ack }
}
is(s_ack) {
io.client.grant.valid := Bool(true)
when(io.client.grant.ready) { state := s_idle }
}
}
}
class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CoherenceAgentConfiguration) extends XactTracker()(conf) {
val s_idle :: s_ack :: s_mem :: s_probe :: s_busy :: Nil = Enum(5){ UInt() }
val state = Reg(init=s_idle)
val xact = Reg{ new Acquire }
val init_client_id_ = Reg(init=UInt(0, width = log2Up(ln.nClients)))
val release_data_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
//TODO: Will need id reg for merged release xacts
val init_sharer_cnt_ = Reg(init=UInt(0, width = log2Up(ln.nClients)))
val grant_type = co.getGrantType(xact.a_type, init_sharer_cnt_)
val release_count = if (ln.nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(ln.nClients)))
val probe_flags = Reg(init=Bits(0, width = ln.nClients))
val curr_p_id = PriorityEncoder(probe_flags)
val x_needs_read = Reg(init=Bool(false))
val acquire_data_needs_write = Reg(init=Bool(false))
val release_data_needs_write = Reg(init=Bool(false))
val cmd_to_write = Acquire(co.getUncachedWriteAcquireType, xact.addr, UInt(trackerId))
val cmd_to_read = Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId))
val a_w_mem_cmd_sent = Reg(init=Bool(false))
val r_w_mem_cmd_sent = Reg(init=Bool(false))
val probe_initial_flags = Bits(width = ln.nClients)
probe_initial_flags := Bits(0)
if (ln.nClients > 1) {
// issue self-probes for uncached read xacts to facilitate I$ coherence
val probe_self = Bool(true) //co.needsSelfProbe(io.client.acquire.bits.payload)
val myflag = Mux(probe_self, Bits(0), UIntToOH(io.client.acquire.meta.bits.header.src(log2Up(ln.nClients)-1,0)))
probe_initial_flags := ~(io.tile_incoherent | myflag)
}
io.has_acquire_conflict := co.isCoherenceConflict(xact.addr, io.client.acquire.meta.bits.payload.addr) && (state != s_idle)
io.has_release_conflict := co.isCoherenceConflict(xact.addr, io.client.release.meta.bits.payload.addr) && (state != s_idle)
io.master.acquire.meta.valid := Bool(false)
io.master.acquire.meta.bits.payload := Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId))
io.master.acquire.meta.bits.header.src := UInt(bankId)
io.master.acquire.data.valid := Bool(false)
io.master.acquire.data.bits.payload.data := UInt(0)
io.master.acquire.data.bits.header.src := UInt(bankId)
io.client.probe.valid := Bool(false)
io.client.probe.bits.payload.p_type := co.getProbeType(xact.a_type, UInt(0))
io.client.probe.bits.payload.master_xact_id := UInt(trackerId)
io.client.probe.bits.payload.addr := xact.addr
io.client.probe.bits.header.dst := UInt(0)
io.client.probe.bits.header.src := UInt(bankId)
io.client.grant.bits.payload.data := io.master.grant.bits.payload.data
io.client.grant.bits.payload.g_type := grant_type
io.client.grant.bits.payload.client_xact_id := xact.client_xact_id
io.client.grant.bits.payload.master_xact_id := UInt(trackerId)
io.client.grant.bits.header.dst := init_client_id_
io.client.grant.bits.header.src := UInt(bankId)
io.client.grant.valid := (io.master.grant.valid && (UInt(trackerId) === io.master.grant.bits.payload.client_xact_id))
io.client.acquire.meta.ready := Bool(false)
io.client.acquire.data.ready := Bool(false)
io.client.release.meta.ready := Bool(false)
io.client.release.data.ready := Bool(false)
io.master.grant.ready := io.client.grant.ready
io.client.grant_ack.valid := Bool(false)
switch (state) {
is(s_idle) {
io.client.acquire.meta.ready := Bool(true)
when( io.client.acquire.meta.valid ) {
xact := io.client.acquire.meta.bits.payload
init_client_id_ := io.client.acquire.meta.bits.header.src
init_sharer_cnt_ := UInt(ln.nClients) // TODO: Broadcast only
acquire_data_needs_write := co.messageHasData(io.client.acquire.meta.bits.payload)
x_needs_read := co.needsOuterRead(io.client.acquire.meta.bits.payload.a_type, UInt(0))
probe_flags := probe_initial_flags
mem_cnt := UInt(0)
r_w_mem_cmd_sent := Bool(false)
a_w_mem_cmd_sent := Bool(false)
if(ln.nClients > 1) {
release_count := PopCount(probe_initial_flags)
state := Mux(probe_initial_flags.orR, s_probe, s_mem)
} else state := s_mem
}
}
is(s_probe) {
when(probe_flags.orR) {
io.client.probe.valid := Bool(true)
io.client.probe.bits.header.dst := curr_p_id
}
when(io.client.probe.ready) {
probe_flags := probe_flags & ~(UIntToOH(curr_p_id))
}
io.client.release.meta.ready := Bool(true)
when(io.client.release.meta.valid) {
if(ln.nClients > 1) release_count := release_count - UInt(1)
when(release_count === UInt(1)) {
state := s_mem
}
when( co.messageHasData(io.client.release.meta.bits.payload)) {
release_data_needs_write := Bool(true)
release_data_client_id := io.client.release.meta.bits.header.src
}
}
when (release_data_needs_write) {
doOuterReqWrite(io.master.acquire,
io.client.release.data,
cmd_to_write,
release_data_needs_write,
r_w_mem_cmd_sent,
release_data_client_id)
}
}
is(s_mem) {
when (release_data_needs_write) {
doOuterReqWrite(io.master.acquire,
io.client.release.data,
cmd_to_write,
release_data_needs_write,
r_w_mem_cmd_sent,
release_data_client_id)
} . elsewhen(acquire_data_needs_write) {
doOuterReqWrite(io.master.acquire,
io.client.acquire.data,
cmd_to_write,
acquire_data_needs_write,
a_w_mem_cmd_sent,
init_client_id_)
} . elsewhen (x_needs_read) {
doOuterReqRead(io.master.acquire, cmd_to_read, x_needs_read)
} . otherwise {
state := Mux(co.needsAckReply(xact.a_type, UInt(0)), s_ack,
Mux(co.requiresAck(io.client.grant.bits.payload), s_busy, s_idle))
}
}
is(s_ack) {
io.client.grant.valid := Bool(true)
when(io.client.grant.ready) { state := Mux(co.requiresAck(io.client.grant.bits.payload), s_busy, s_idle) }
}
is(s_busy) { // Nothing left to do but wait for transaction to complete
when (io.client.grant_ack.valid && io.client.grant_ack.bits.payload.master_xact_id === UInt(trackerId)) {
state := s_idle
}
}
}
}
abstract trait OuterRequestGenerator {
val mem_cnt = Reg(init=UInt(0, width = log2Up(REFILL_CYCLES)))
val mem_cnt_next = mem_cnt + UInt(1)
def doOuterReqWrite[T <: HasTileLinkData](master_acq: PairedDataIO[LogicalNetworkIO[Acquire],LogicalNetworkIO[AcquireData]], client_data: DecoupledIO[LogicalNetworkIO[T]], cmd: Acquire, trigger: Bool, cmd_sent: Bool, desired_client_data_src_id: UInt) {
val do_write = client_data.valid && (client_data.bits.header.src === desired_client_data_src_id)
master_acq.meta.bits.payload := cmd
master_acq.data.bits.payload := client_data.bits.payload
when(master_acq.meta.fire()) {
cmd_sent := Bool(true)
}
when (do_write) {
master_acq.meta.valid := !cmd_sent
when (master_acq.meta.ready || cmd_sent) {
master_acq.data.valid := client_data.valid
when(master_acq.data.ready) {
client_data.ready:= Bool(true)
mem_cnt := mem_cnt_next
when(mem_cnt === UInt(REFILL_CYCLES-1)) {
trigger := Bool(false)
}
}
}
}
}
def doOuterReqRead(master_acq: PairedDataIO[LogicalNetworkIO[Acquire],LogicalNetworkIO[AcquireData]], cmd: Acquire, trigger: Bool) {
master_acq.meta.valid := Bool(true)
master_acq.meta.bits.payload := cmd
when(master_acq.meta.ready) {
trigger := Bool(false)
}
}
}