1
0

Vec considered harmful; use isOneOf instead (#64)

Vec is heavyweight and really should only be used for I/O and
dynamic indexing.  A recurring pattern in uncore is

    Vec(const1, const2, const3) contains x

which is nice but has a deleterious effect on simulation copilation
and execution time.  This patch proposes an alternative:

    x isOneOf (const1, const2, const3)
    x isOneOf seqOfThings

I think it's also more idiomatic.

This is just a prototype; I'm not wed to the name or implementation.
This commit is contained in:
Andrew Waterman 2016-07-07 19:25:57 -07:00 committed by GitHub
parent 16a6b11081
commit 70b677ecda
6 changed files with 73 additions and 57 deletions

View File

@ -0,0 +1,11 @@
package uncore
import Chisel._
package object Util {
implicit class UIntIsOneOf(val x: UInt) extends AnyVal {
def isOneOf(s: Seq[UInt]): Bool = s.map(x === _).reduce(_||_)
def isOneOf(u1: UInt, u2: UInt*): Bool = isOneOf(u1 +: u2.toSeq)
}
}

View File

@ -6,6 +6,7 @@ import Chisel._
import uncore.coherence._
import uncore.tilelink._
import uncore.constants._
import uncore.Util._
import cde.Parameters
class L2BroadcastHub(implicit p: Parameters) extends HierarchicalCoherenceAgent()(p) {
@ -155,7 +156,7 @@ class BufferedBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters)
// and/or write back dirty data, and may be unexpected voluntary releases
def irel_can_merge = io.irel().conflicts(xact_addr_block) &&
io.irel().isVoluntary() &&
!Vec(s_idle, s_meta_write).contains(state) &&
!state.isOneOf(s_idle, s_meta_write) &&
!all_pending_done &&
!io.outer.grant.fire() &&
!io.inner.grant.fire() &&

View File

@ -9,6 +9,7 @@ import uncore.util.AMOALU
import uncore.coherence._
import uncore.tilelink._
import uncore.constants._
import uncore.Util._
import cde.{Parameters, Field}
case object CacheName extends Field[String]
@ -807,7 +808,7 @@ class CacheAcquireTracker(trackerId: Int)(implicit p: Parameters)
// Setup IOs used for routing in the parent
val before_wb_alloc = Vec(s_meta_read, s_meta_resp, s_wb_req).contains(state)
val before_wb_alloc = state isOneOf (s_meta_read, s_meta_resp, s_wb_req)
routeInParent(
iacqMatches = inSameSet(_, xact_addr_block),
@ -899,7 +900,7 @@ class CacheAcquireTracker(trackerId: Int)(implicit p: Parameters)
def irel_can_merge = io.irel().conflicts(xact_addr_block) &&
io.irel().isVoluntary() &&
!Vec(s_idle, s_meta_read, s_meta_resp, s_meta_write).contains(state) &&
!state.isOneOf(s_idle, s_meta_read, s_meta_resp, s_meta_write) &&
!all_pending_done &&
!io.outer.grant.fire() &&
!io.inner.grant.fire() &&

View File

@ -6,6 +6,7 @@ import Chisel._
import uncore.coherence._
import uncore.tilelink._
import uncore.util._
import uncore.Util._
import cde.{Field, Parameters}
import scala.math.max
@ -275,7 +276,7 @@ trait AcceptsVoluntaryReleases extends HasVoluntaryReleaseMetadataBuffer {
}
}
io.inner.grant.valid := Vec(s_wb_req, s_wb_resp, s_inner_probe, s_busy).contains(state) &&
io.inner.grant.valid := state.isOneOf(s_wb_req, s_wb_resp, s_inner_probe, s_busy) &&
vol_ignt_counter.pending &&
!(pending_irel_data.orR || block_vol_ignt)

View File

@ -5,6 +5,7 @@ package uncore.coherence
import Chisel._
import uncore.tilelink._
import uncore.constants._
import uncore.Util._
/** The entire CoherencePolicy API consists of the following three traits:
* HasCustomTileLinkMessageTypes, used to define custom messages
@ -32,8 +33,8 @@ trait HasCustomTileLinkMessageTypes {
def grantTypeWidth = log2Up(nGrantTypes)
val acquireTypesWithData = Nil // Only built-in Acquire types have data for now
def releaseTypesWithData: Vec[UInt]
def grantTypesWithData: Vec[UInt]
def releaseTypesWithData: Seq[UInt]
def grantTypesWithData: Seq[UInt]
}
/** This API contains all functions required for client coherence agents.
@ -47,16 +48,16 @@ trait HasClientSideCoherencePolicy {
// Client coherence states and their permissions
val nClientStates: Int
def clientStateWidth = log2Ceil(nClientStates)
def clientStatesWithReadPermission: Vec[UInt]
def clientStatesWithWritePermission: Vec[UInt]
def clientStatesWithDirtyData: Vec[UInt]
def clientStatesWithReadPermission: Seq[UInt]
def clientStatesWithWritePermission: Seq[UInt]
def clientStatesWithDirtyData: Seq[UInt]
// Transaction initiation logic
def isValid(meta: ClientMetadata): Bool
def isHit(cmd: UInt, meta: ClientMetadata): Bool = {
Mux(isWriteIntent(cmd),
clientStatesWithWritePermission.contains(meta.state),
clientStatesWithReadPermission.contains(meta.state))
meta.state isOneOf clientStatesWithWritePermission,
meta.state isOneOf clientStatesWithReadPermission)
}
//TODO: Assumes all states with write permissions also have read permissions
def requiresAcquireOnSecondaryMiss(
@ -68,7 +69,7 @@ trait HasClientSideCoherencePolicy {
//TODO: Assumes all cache ctrl ops writeback dirty data, and
// doesn't issue transaction when e.g. downgrading Exclusive to Shared:
def requiresReleaseOnCacheControl(cmd: UInt, meta: ClientMetadata): Bool =
clientStatesWithDirtyData.contains(meta.state)
meta.state isOneOf clientStatesWithDirtyData
// Determine which custom message type to use
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt
@ -131,23 +132,23 @@ class MICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
val releaseInvalidateData :: releaseCopyData :: releaseInvalidateAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantExclusive :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Vec(releaseInvalidateData, releaseCopyData)
def grantTypesWithData = Vec(grantExclusive)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseCopyData)
def grantTypesWithData = Seq(grantExclusive)
// Client states and functions
val nClientStates = 2
val clientInvalid :: clientValid :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Vec(clientValid)
def clientStatesWithWritePermission = Vec(clientValid)
def clientStatesWithDirtyData = Vec(clientValid)
def clientStatesWithReadPermission = Seq(clientValid)
def clientStatesWithWritePermission = Seq(clientValid)
def clientStatesWithDirtyData = Seq(clientValid)
def isValid (meta: ClientMetadata): Bool = meta.state =/= clientInvalid
def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt = acquireExclusive
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = clientStatesWithDirtyData.contains(meta.state)
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseCopyData, releaseCopyAck),
@ -222,16 +223,16 @@ class MEICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantExclusive :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Vec(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Vec(grantExclusive)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Seq(grantExclusive)
// Client states and functions
val nClientStates = 3
val clientInvalid :: clientExclusiveClean :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Vec(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithWritePermission = Vec(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithDirtyData = Vec(clientExclusiveDirty)
def clientStatesWithReadPermission = Seq(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty)
def isValid (meta: ClientMetadata) = meta.state =/= clientInvalid
@ -239,7 +240,7 @@ class MEICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
Mux(isWriteIntent(cmd), acquireExclusiveDirty, acquireExclusiveClean)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = clientStatesWithDirtyData.contains(meta.state)
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
@ -324,16 +325,16 @@ class MSICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantShared :: grantExclusive :: grantExclusiveAck :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Vec(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Vec(grantShared, grantExclusive)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Seq(grantShared, grantExclusive)
// Client states and functions
val nClientStates = 3
val clientInvalid :: clientShared :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Vec(clientShared, clientExclusiveDirty)
def clientStatesWithWritePermission = Vec(clientExclusiveDirty)
def clientStatesWithDirtyData = Vec(clientExclusiveDirty)
def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty)
def isValid(meta: ClientMetadata): Bool = meta.state =/= clientInvalid
@ -341,7 +342,7 @@ class MSICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
Mux(isWriteIntent(cmd), acquireExclusive, acquireShared)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = clientStatesWithDirtyData.contains(meta.state)
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
@ -361,7 +362,7 @@ class MSICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
ClientMetadata(
MuxLookup(cmd, meta.state, Array(
M_FLUSH -> clientInvalid,
M_PRODUCE -> Mux(clientStatesWithWritePermission.contains(meta.state),
M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission,
clientShared, meta.state))))(meta.p)
def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) =
@ -442,16 +443,16 @@ class MESICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes)
val grantShared :: grantExclusive :: grantExclusiveAck :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Vec(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Vec(grantShared, grantExclusive)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData)
def grantTypesWithData = Seq(grantShared, grantExclusive)
// Client states and functions
val nClientStates = 4
val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Vec(clientShared, clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithWritePermission = Vec(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithDirtyData = Vec(clientExclusiveDirty)
def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty)
def isValid(meta: ClientMetadata): Bool = meta.state =/= clientInvalid
@ -459,7 +460,7 @@ class MESICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
Mux(isWriteIntent(cmd), acquireExclusive, acquireShared)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = clientStatesWithDirtyData.contains(meta.state)
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
@ -479,7 +480,7 @@ class MESICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) {
ClientMetadata(
MuxLookup(cmd, meta.state, Array(
M_FLUSH -> clientInvalid,
M_PRODUCE -> Mux(clientStatesWithWritePermission.contains(meta.state),
M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission,
clientShared, meta.state),
M_CLEAN -> Mux(meta.state === clientExclusiveDirty,
clientExclusiveClean, meta.state))))(meta.p)
@ -558,16 +559,16 @@ class MigratoryCoherence(dir: DirectoryRepresentation) extends CoherencePolicy(d
val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: releaseDowngradeDataMigratory :: releaseDowngradeAckHasCopy :: releaseInvalidateDataMigratory :: releaseInvalidateAckMigratory :: Nil = Enum(UInt(), nReleaseTypes)
val grantShared :: grantExclusive :: grantExclusiveAck :: grantReadMigratory :: Nil = Enum(UInt(), nGrantTypes)
def releaseTypesWithData = Vec(releaseInvalidateData, releaseDowngradeData, releaseCopyData, releaseInvalidateDataMigratory, releaseDowngradeDataMigratory)
def grantTypesWithData = Vec(grantShared, grantExclusive, grantReadMigratory)
def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData, releaseInvalidateDataMigratory, releaseDowngradeDataMigratory)
def grantTypesWithData = Seq(grantShared, grantExclusive, grantReadMigratory)
// Client states and functions
val nClientStates = 7
val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: clientSharedByTwo :: clientMigratoryClean :: clientMigratoryDirty :: Nil = Enum(UInt(), nClientStates)
def clientStatesWithReadPermission = Vec(clientShared, clientExclusiveClean, clientExclusiveDirty, clientSharedByTwo, clientMigratoryClean, clientMigratoryDirty)
def clientStatesWithWritePermission = Vec(clientExclusiveClean, clientExclusiveDirty, clientMigratoryClean, clientMigratoryDirty)
def clientStatesWithDirtyData = Vec(clientExclusiveDirty, clientMigratoryDirty)
def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveClean, clientExclusiveDirty, clientSharedByTwo, clientMigratoryClean, clientMigratoryDirty)
def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty, clientMigratoryClean, clientMigratoryDirty)
def clientStatesWithDirtyData = Seq(clientExclusiveDirty, clientMigratoryDirty)
def isValid (meta: ClientMetadata): Bool = meta.state =/= clientInvalid
@ -577,7 +578,7 @@ class MigratoryCoherence(dir: DirectoryRepresentation) extends CoherencePolicy(d
acquireShared)
def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = {
val dirty = clientStatesWithDirtyData.contains(meta.state)
val dirty = meta.state isOneOf clientStatesWithDirtyData
MuxLookup(cmd, releaseCopyAck, Array(
M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck),
M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck),
@ -585,9 +586,9 @@ class MigratoryCoherence(dir: DirectoryRepresentation) extends CoherencePolicy(d
}
def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt = {
val dirty = clientStatesWithDirtyData.contains(meta.state)
val dirty = meta.state isOneOf clientStatesWithDirtyData
val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array(
probeInvalidate -> Mux(Vec(clientExclusiveDirty, clientMigratoryDirty).contains(meta.state),
probeInvalidate -> Mux(meta.state isOneOf (clientExclusiveDirty, clientMigratoryDirty),
releaseInvalidateDataMigratory, releaseInvalidateData),
probeDowngrade -> Mux(meta.state === clientMigratoryDirty,
releaseDowngradeDataMigratory, releaseDowngradeData),
@ -614,7 +615,7 @@ class MigratoryCoherence(dir: DirectoryRepresentation) extends CoherencePolicy(d
ClientMetadata(
MuxLookup(cmd, meta.state, Array(
M_FLUSH -> clientInvalid,
M_PRODUCE -> Mux(clientStatesWithWritePermission.contains(meta.state),
M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission,
clientShared, meta.state),
M_CLEAN -> MuxLookup(meta.state, meta.state, Array(
clientExclusiveDirty -> clientExclusiveClean,

View File

@ -4,6 +4,7 @@ package uncore.tilelink
import Chisel._
import junctions._
import uncore.coherence.CoherencePolicy
import uncore.Util._
import scala.math.max
import uncore.constants._
import cde.{Parameters, Field}
@ -211,7 +212,7 @@ trait HasAcquireType extends HasTileLinkParameters {
def isBuiltInType(t: UInt): Bool = is_builtin_type && a_type === t
/** Does this message refer to subblock operands using info in the Acquire.union subbundle */
def isSubBlockType(dummy: Int = 0): Bool = isBuiltInType() && Acquire.typesOnSubBlocks.contains(a_type)
def isSubBlockType(dummy: Int = 0): Bool = isBuiltInType() && a_type.isOneOf(Acquire.typesOnSubBlocks)
/** Is this message a built-in prefetch message */
def isPrefetch(dummy: Int = 0): Bool = isBuiltInType() &&
@ -224,11 +225,11 @@ trait HasAcquireType extends HasTileLinkParameters {
def isGet(dummy: Int = 0): Bool = isBuiltInType() && (is(Acquire.getType) || is(Acquire.getBlockType))
/** Does this message contain data? Assumes that no custom message types have data. */
def hasData(dummy: Int = 0): Bool = isBuiltInType() && Acquire.typesWithData.contains(a_type)
def hasData(dummy: Int = 0): Bool = isBuiltInType() && a_type.isOneOf(Acquire.typesWithData)
/** Does this message contain multiple beats of data? Assumes that no custom message types have data. */
def hasMultibeatData(dummy: Int = 0): Bool = Bool(tlDataBeats > 1) && isBuiltInType() &&
Acquire.typesWithMultibeatData.contains(a_type)
a_type.isOneOf(Acquire.typesWithMultibeatData)
/** Mapping between each built-in Acquire type and a built-in Grant type. */
def getBuiltInGrantType(dummy: Int = 0): UInt = Acquire.getBuiltInGrantType(this.a_type)
@ -251,9 +252,9 @@ trait HasReleaseType extends HasTileLinkParameters with MightBeVoluntary {
val r_type = UInt(width = tlCoh.releaseTypeWidth)
def is(t: UInt) = r_type === t
def hasData(dummy: Int = 0) = tlCoh.releaseTypesWithData.contains(r_type)
def hasData(dummy: Int = 0) = r_type.isOneOf(tlCoh.releaseTypesWithData)
def hasMultibeatData(dummy: Int = 0) = Bool(tlDataBeats > 1) &&
tlCoh.releaseTypesWithData.contains(r_type)
r_type.isOneOf(tlCoh.releaseTypesWithData)
def isVoluntary(dummy: Int = 0) = voluntary
def requiresAck(dummy: Int = 0) = !Bool(tlNetworkPreservesPointToPointOrdering)
}
@ -267,12 +268,12 @@ trait HasGrantType extends HasTileLinkParameters with MightBeVoluntary {
def isBuiltInType(t: UInt): Bool = is_builtin_type && g_type === t
def is(t: UInt):Bool = g_type === t
def hasData(dummy: Int = 0): Bool = Mux(isBuiltInType(),
Grant.typesWithData.contains(g_type),
tlCoh.grantTypesWithData.contains(g_type))
g_type.isOneOf(Grant.typesWithData),
g_type.isOneOf(tlCoh.grantTypesWithData))
def hasMultibeatData(dummy: Int = 0): Bool =
Bool(tlDataBeats > 1) && Mux(isBuiltInType(),
Grant.typesWithMultibeatData.contains(g_type),
tlCoh.grantTypesWithData.contains(g_type))
g_type.isOneOf(Grant.typesWithMultibeatData),
g_type.isOneOf(tlCoh.grantTypesWithData))
def isVoluntary(dummy: Int = 0): Bool = isBuiltInType() && (g_type === Grant.voluntaryAckType)
def requiresAck(dummy: Int = 0): Bool = !Bool(tlNetworkPreservesPointToPointOrdering) && !isVoluntary()
}
@ -296,7 +297,7 @@ class AcquireMetadata(implicit p: Parameters) extends ClientToManagerChannel
/** Complete physical address for block, beat or operand */
def full_addr(dummy: Int = 0) =
Cat(this.addr_block, this.addr_beat,
Mux(isBuiltInType() && Acquire.typesWithAddrByte.contains(this.a_type),
Mux(isBuiltInType() && this.a_type.isOneOf(Acquire.typesWithAddrByte),
this.addr_byte(), UInt(0, tlByteAddrBits)))
}