1
0
rocket-chip/uncore/src/main/scala/tilelink.scala

641 lines
22 KiB
Scala
Raw Normal View History

2014-09-13 00:31:38 +02:00
// See LICENSE for license details.
2012-10-16 23:26:33 +02:00
package uncore
import Chisel._
import scala.math.max
2015-03-10 00:34:59 +01:00
import scala.reflect.ClassTag
2012-10-16 23:26:33 +02:00
2014-12-30 07:55:58 +01:00
// Parameters exposed to the top-level design, set based on
// external requirements or design space exploration
//
case object TLId extends Field[String] // Unique name per network
2015-03-01 02:02:13 +01:00
case object TLCoherencePolicy extends Field[CoherencePolicy]
case object TLBlockAddrBits extends Field[Int]
2014-12-30 07:55:58 +01:00
case object TLManagerXactIdBits extends Field[Int]
case object TLClientXactIdBits extends Field[Int]
case object TLDataBits extends Field[Int]
2014-12-07 11:57:44 +01:00
case object TLDataBeats extends Field[Int]
2015-03-01 02:02:13 +01:00
case object TLNetworkIsOrderedP2P extends Field[Boolean]
abstract trait TileLinkParameters extends UsesParameters {
2015-03-01 02:02:13 +01:00
val tlBlockAddrBits = params(TLBlockAddrBits)
val tlClientXactIdBits = params(TLClientXactIdBits)
2014-12-30 07:55:58 +01:00
val tlManagerXactIdBits = params(TLManagerXactIdBits)
val tlDataBits = params(TLDataBits)
2014-12-07 11:57:44 +01:00
val tlDataBeats = params(TLDataBeats)
2015-03-01 02:02:13 +01:00
val tlCoh = params(TLCoherencePolicy)
val tlWriteMaskBits = if(tlDataBits/8 < 1) 1 else tlDataBits/8
val tlBeatAddrBits = log2Up(tlDataBeats)
val tlByteAddrBits = log2Up(tlWriteMaskBits)
2015-03-01 02:02:13 +01:00
val tlMemoryOpcodeBits = M_SZ
val tlMemoryOperandSizeBits = MT_SZ
val tlAcquireTypeBits = max(log2Up(Acquire.nBuiltInTypes),
tlCoh.acquireTypeWidth)
val tlAcquireUnionBits = max(tlWriteMaskBits,
(tlByteAddrBits +
2015-03-01 02:02:13 +01:00
tlMemoryOperandSizeBits +
tlMemoryOpcodeBits)) + 1
val tlGrantTypeBits = max(log2Up(Grant.nBuiltInTypes),
tlCoh.grantTypeWidth) + 1
val tlNetworkPreservesPointToPointOrdering = params(TLNetworkIsOrderedP2P)
2015-03-17 07:41:56 +01:00
val amoAluOperandBits = params(AmoAluOperandBits)
2012-10-16 23:26:33 +02:00
}
abstract class TLBundle extends Bundle with TileLinkParameters
abstract class TLModule extends Module with TileLinkParameters
2014-12-30 07:55:58 +01:00
// Directionality of message channel
// Used to hook up logical network ports to physical network ports
trait TileLinkChannel extends TLBundle
trait ClientToManagerChannel extends TileLinkChannel
trait ManagerToClientChannel extends TileLinkChannel
trait ClientToClientChannel extends TileLinkChannel // Unused for now
// Common signals that are used in multiple channels.
// These traits are useful for type parameterization.
//
trait HasCacheBlockAddress extends TLBundle {
val addr_block = UInt(width = tlBlockAddrBits)
2015-03-01 02:02:13 +01:00
def conflicts(that: HasCacheBlockAddress) = this.addr_block === that.addr_block
def conflicts(addr: UInt) = this.addr_block === addr
}
trait HasTileLinkBeatId extends TLBundle {
val addr_beat = UInt(width = tlBeatAddrBits)
}
trait HasClientTransactionId extends TLBundle {
val client_xact_id = Bits(width = tlClientXactIdBits)
2012-10-16 23:26:33 +02:00
}
2014-12-30 07:55:58 +01:00
trait HasManagerTransactionId extends TLBundle {
val manager_xact_id = Bits(width = tlManagerXactIdBits)
2012-10-16 23:26:33 +02:00
}
2015-03-01 02:02:13 +01:00
trait HasTileLinkData extends HasTileLinkBeatId {
val data = UInt(width = tlDataBits)
2015-03-01 02:02:13 +01:00
def hasData(dummy: Int = 0): Bool
def hasMultibeatData(dummy: Int = 0): Bool
2012-10-16 23:26:33 +02:00
}
2014-12-30 07:55:58 +01:00
// Actual TileLink channel bundle definitions
2014-12-30 07:55:58 +01:00
class Acquire extends ClientToManagerChannel
with HasCacheBlockAddress
with HasClientTransactionId
with HasTileLinkData {
// Actual bundle fields
2015-03-01 02:02:13 +01:00
val is_builtin_type = Bool()
val a_type = UInt(width = tlAcquireTypeBits)
val union = Bits(width = tlAcquireUnionBits)
2015-02-02 10:02:06 +01:00
// Utility funcs for accessing subblock union
2015-03-01 02:02:13 +01:00
val opCodeOff = 1
val opSizeOff = tlMemoryOpcodeBits + opCodeOff
val addrByteOff = tlMemoryOperandSizeBits + opSizeOff
val addrByteMSB = tlByteAddrBits + addrByteOff
def allocate(dummy: Int = 0) = union(0)
2015-03-12 07:24:58 +01:00
def op_code(dummy: Int = 0) = Mux(isBuiltInType() &&
(a_type === Acquire.putType || a_type === Acquire.putBlockType),
M_XWR, union(opSizeOff-1, opCodeOff))
2015-03-01 02:02:13 +01:00
def op_size(dummy: Int = 0) = union(addrByteOff-1, opSizeOff)
def addr_byte(dummy: Int = 0) = union(addrByteMSB-1, addrByteOff)
2015-03-17 07:41:56 +01:00
private def amo_offset(dummy: Int = 0) = addr_byte()(tlByteAddrBits-1, log2Up(amoAluOperandBits/8))
def amo_shift_bits(dummy: Int = 0) = UInt(amoAluOperandBits)*amo_offset()
def wmask(dummy: Int = 0) =
Mux(isBuiltInType(Acquire.putAtomicType),
2015-03-17 12:58:54 +01:00
FillInterleaved(amoAluOperandBits/8, UIntToOH(amo_offset())),
2015-03-17 07:41:56 +01:00
Mux(isBuiltInType(Acquire.putBlockType) || isBuiltInType(Acquire.putType),
2015-03-17 12:58:54 +01:00
union(tlWriteMaskBits, 1),
UInt(0, width = tlWriteMaskBits)))
def full_wmask(dummy: Int = 0) = FillInterleaved(8, wmask())
2015-03-17 07:41:56 +01:00
2015-03-01 02:02:13 +01:00
def addr(dummy: Int = 0) = Cat(this.addr_block, this.addr_beat, this.addr_byte())
// Other helper funcs
2015-03-17 07:41:56 +01:00
def is(t: UInt) = a_type === t //TODO: make this more opaque; def ===?
2015-03-01 02:02:13 +01:00
def isBuiltInType(dummy: Int = 0): Bool = is_builtin_type
2015-03-17 07:41:56 +01:00
def isBuiltInType(t: UInt): Bool = is_builtin_type && a_type === t
2015-03-01 02:02:13 +01:00
def isSubBlockType(dummy: Int = 0): Bool = isBuiltInType() && Acquire.typesOnSubBlocks.contains(a_type)
2015-03-11 22:28:17 +01:00
def isPrefetch(dummy: Int = 0): Bool = isBuiltInType() && is(Acquire.prefetchType)
2015-03-01 02:02:13 +01:00
// Assumes no custom types have data
def hasData(dummy: Int = 0): Bool = isBuiltInType() && Acquire.typesWithData.contains(a_type)
2015-03-01 02:02:13 +01:00
def hasMultibeatData(dummy: Int = 0): Bool = Bool(tlDataBeats > 1) && isBuiltInType() &&
Acquire.typesWithMultibeatData.contains(a_type)
2015-03-17 08:24:59 +01:00
def requiresSelfProbe(dummy: Int = 0) = Bool(false)
2015-03-01 02:02:13 +01:00
def getBuiltInGrantType(dummy: Int = 0): UInt = {
2015-03-12 01:32:06 +01:00
MuxLookup(this.a_type, Grant.putAckType, Array(
Acquire.getType -> Grant.getDataBeatType,
Acquire.getBlockType -> Grant.getDataBlockType,
Acquire.putType -> Grant.putAckType,
Acquire.putBlockType -> Grant.putAckType,
Acquire.putAtomicType -> Grant.getDataBeatType,
Acquire.prefetchType -> Grant.prefetchAckType))
}
}
object Acquire {
2015-03-01 02:02:13 +01:00
val nBuiltInTypes = 5
//TODO: Use Enum
2015-03-01 02:02:13 +01:00
def getType = UInt("b000")
def getBlockType = UInt("b001")
def putType = UInt("b010")
def putBlockType = UInt("b011")
def putAtomicType = UInt("b100")
2015-03-11 22:28:17 +01:00
def prefetchType = UInt("b101")
2015-03-01 02:02:13 +01:00
def typesWithData = Vec(putType, putBlockType, putAtomicType)
def typesWithMultibeatData = Vec(putBlockType)
def typesOnSubBlocks = Vec(putType, getType, putAtomicType)
def fullWriteMask = SInt(-1, width = new Acquire().tlWriteMaskBits).toUInt
// Most generic constructor
def apply(
2015-03-01 02:02:13 +01:00
is_builtin_type: Bool,
a_type: Bits,
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt = UInt(0),
data: UInt = UInt(0),
2015-03-01 02:02:13 +01:00
union: UInt = UInt(0)): Acquire = {
2013-01-22 02:17:26 +01:00
val acq = new Acquire
2015-03-01 02:02:13 +01:00
acq.is_builtin_type := is_builtin_type
2013-01-22 02:17:26 +01:00
acq.a_type := a_type
acq.client_xact_id := client_xact_id
acq.addr_block := addr_block
acq.addr_beat := addr_beat
acq.data := data
2015-03-01 02:02:13 +01:00
acq.union := union
acq
}
// Copy constructor
def apply(a: Acquire): Acquire = {
2014-01-21 21:20:55 +01:00
val acq = new Acquire
acq := a
acq
}
2012-10-16 23:26:33 +02:00
}
// Asks for a single TileLink beat of data
2015-03-01 02:02:13 +01:00
object Get {
def apply(
2015-03-11 22:28:17 +01:00
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt,
alloc: Bool = Bool(true)): Acquire = {
Acquire(
2015-03-01 02:02:13 +01:00
is_builtin_type = Bool(true),
a_type = Acquire.getType,
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = addr_beat,
2015-03-01 02:02:13 +01:00
union = Cat(M_XRD, alloc))
}
}
// Asks for an entire cache block of data
2015-03-01 02:02:13 +01:00
object GetBlock {
def apply(
2015-03-11 22:28:17 +01:00
client_xact_id: UInt = UInt(0),
addr_block: UInt,
alloc: Bool = Bool(true)): Acquire = {
Acquire(
2015-03-01 02:02:13 +01:00
is_builtin_type = Bool(true),
a_type = Acquire.getBlockType,
client_xact_id = client_xact_id,
addr_block = addr_block,
2015-03-01 02:02:13 +01:00
union = Cat(M_XRD, alloc))
}
}
2012-10-16 23:26:33 +02:00
2015-03-11 22:28:17 +01:00
// Prefetch a cache block into the next level of the memory hierarchy
// with read permissions
object GetPrefetch {
def apply(
client_xact_id: UInt,
addr_block: UInt): Acquire = {
Acquire(
is_builtin_type = Bool(true),
a_type = Acquire.prefetchType,
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = UInt(0),
union = Cat(M_XRD, Bool(true)))
}
}
2015-03-01 02:02:13 +01:00
// Writes up to a single TileLink beat of data, using mask
object Put {
def apply(
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt,
data: UInt,
2015-03-17 07:41:56 +01:00
wmask: UInt = Acquire.fullWriteMask): Acquire = {
Acquire(
2015-03-01 02:02:13 +01:00
is_builtin_type = Bool(true),
a_type = Acquire.putType,
addr_block = addr_block,
addr_beat = addr_beat,
client_xact_id = client_xact_id,
data = data,
2015-03-17 07:41:56 +01:00
union = Cat(wmask, Bool(true)))
}
}
2015-03-01 02:02:13 +01:00
// Writes an entire cache block of data
object PutBlock {
def apply(
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt,
data: UInt,
2015-03-17 07:41:56 +01:00
wmask: UInt): Acquire = {
2015-03-01 02:02:13 +01:00
Acquire(
is_builtin_type = Bool(true),
a_type = Acquire.putBlockType,
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = addr_beat,
data = data,
2015-03-17 07:41:56 +01:00
union = Cat(wmask, (wmask != Acquire.fullWriteMask)))
2015-03-01 02:02:13 +01:00
}
def apply(
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt,
data: UInt,
alloc: Bool = Bool(true)): Acquire = {
Acquire(
2015-03-01 02:02:13 +01:00
is_builtin_type = Bool(true),
a_type = Acquire.putBlockType,
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = addr_beat,
data = data,
2015-03-01 02:02:13 +01:00
union = Cat(Acquire.fullWriteMask, alloc))
}
}
2015-03-01 02:02:13 +01:00
// Performs an atomic operation in the outer memory
object PutAtomic {
def apply(
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt,
addr_byte: UInt,
atomic_opcode: UInt,
operand_size: UInt,
data: UInt): Acquire = {
Acquire(
2015-03-01 02:02:13 +01:00
is_builtin_type = Bool(true),
a_type = Acquire.putAtomicType,
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = addr_beat,
data = data,
2015-03-01 02:02:13 +01:00
union = Cat(addr_byte, operand_size, atomic_opcode, Bool(true)))
}
}
2015-03-11 22:28:17 +01:00
// Prefetch a cache block into the next level of the memory hierarchy
// with write permissions
object PutPrefetch {
def apply(
client_xact_id: UInt,
addr_block: UInt): Acquire = {
Acquire(
is_builtin_type = Bool(true),
a_type = Acquire.prefetchType,
client_xact_id = client_xact_id,
addr_block = addr_block,
addr_beat = UInt(0),
union = Cat(M_XWR, Bool(true)))
}
}
2014-12-30 07:55:58 +01:00
class Probe extends ManagerToClientChannel
with HasCacheBlockAddress {
2015-03-01 02:02:13 +01:00
val p_type = UInt(width = tlCoh.probeTypeWidth)
2014-12-30 07:55:58 +01:00
def is(t: UInt) = p_type === t
}
object Probe {
def apply(p_type: UInt, addr_block: UInt) = {
2014-01-21 21:20:55 +01:00
val prb = new Probe
prb.p_type := p_type
prb.addr_block := addr_block
2014-01-21 21:20:55 +01:00
prb
}
}
2014-12-30 07:55:58 +01:00
class Release extends ClientToManagerChannel
with HasCacheBlockAddress
2014-12-30 07:55:58 +01:00
with HasClientTransactionId
with HasTileLinkData {
2015-03-01 02:02:13 +01:00
val r_type = UInt(width = tlCoh.releaseTypeWidth)
val voluntary = Bool()
// Helper funcs
2014-12-30 07:55:58 +01:00
def is(t: UInt) = r_type === t
2015-03-01 02:02:13 +01:00
def hasData(dummy: Int = 0) = tlCoh.releaseTypesWithData.contains(r_type)
2015-02-02 10:02:06 +01:00
//TODO: Assumes all releases write back full cache blocks:
2015-03-01 02:02:13 +01:00
def hasMultibeatData(dummy: Int = 0) = Bool(tlDataBeats > 1) && tlCoh.releaseTypesWithData.contains(r_type)
def isVoluntary(dummy: Int = 0) = voluntary
2015-03-01 02:02:13 +01:00
def requiresAck(dummy: Int = 0) = !Bool(tlNetworkPreservesPointToPointOrdering)
2012-10-16 23:26:33 +02:00
}
object Release {
def apply(
voluntary: Bool,
r_type: UInt,
client_xact_id: UInt,
addr_block: UInt,
addr_beat: UInt = UInt(0),
data: UInt = UInt(0)): Release = {
2014-01-21 21:20:55 +01:00
val rel = new Release
rel.r_type := r_type
rel.client_xact_id := client_xact_id
rel.addr_block := addr_block
rel.addr_beat := addr_beat
rel.data := data
rel.voluntary := voluntary
2014-01-21 21:20:55 +01:00
rel
}
}
2014-12-30 07:55:58 +01:00
class Grant extends ManagerToClientChannel
with HasTileLinkData
with HasClientTransactionId
2014-12-30 07:55:58 +01:00
with HasManagerTransactionId {
2015-03-01 02:02:13 +01:00
val is_builtin_type = Bool()
val g_type = UInt(width = tlGrantTypeBits)
// Helper funcs
2015-03-01 02:02:13 +01:00
def isBuiltInType(dummy: Int = 0): Bool = is_builtin_type
def is(t: UInt):Bool = g_type === t
def hasData(dummy: Int = 0): Bool = Mux(isBuiltInType(),
Grant.typesWithData.contains(g_type),
2015-03-01 02:02:13 +01:00
tlCoh.grantTypesWithData.contains(g_type))
def hasMultibeatData(dummy: Int = 0): Bool =
2015-03-01 02:02:13 +01:00
Bool(tlDataBeats > 1) && Mux(isBuiltInType(),
Grant.typesWithMultibeatData.contains(g_type),
2015-03-01 02:02:13 +01:00
tlCoh.grantTypesWithData.contains(g_type))
def isVoluntary(dummy: Int = 0): Bool = isBuiltInType() && (g_type === Grant.voluntaryAckType)
def requiresAck(dummy: Int = 0): Bool = !Bool(tlNetworkPreservesPointToPointOrdering) && !isVoluntary()
def makeFinish(dummy: Int = 0): Finish = {
2015-03-01 02:02:13 +01:00
val f = Bundle(new Finish, { case TLManagerXactIdBits => tlManagerXactIdBits })
f.manager_xact_id := this.manager_xact_id
f
}
}
object Grant {
2015-03-12 01:32:06 +01:00
val nBuiltInTypes = 5
def voluntaryAckType = UInt("b000")
def putAckType = UInt("b001")
def prefetchAckType = UInt("b011")
def getDataBeatType = UInt("b100")
def getDataBlockType = UInt("b101")
def typesWithData = Vec(getDataBlockType, getDataBeatType)
def typesWithMultibeatData= Vec(getDataBlockType)
def apply(
2015-03-01 02:02:13 +01:00
is_builtin_type: Bool,
g_type: UInt,
client_xact_id: UInt,
manager_xact_id: UInt,
addr_beat: UInt = UInt(0),
data: UInt = UInt(0)): Grant = {
val gnt = new Grant
2015-03-01 02:02:13 +01:00
gnt.is_builtin_type := is_builtin_type
gnt.g_type := g_type
gnt.client_xact_id := client_xact_id
2014-12-30 07:55:58 +01:00
gnt.manager_xact_id := manager_xact_id
gnt.addr_beat := addr_beat
gnt.data := data
gnt
}
2012-10-16 23:26:33 +02:00
}
2014-12-30 07:55:58 +01:00
class Finish extends ClientToManagerChannel with HasManagerTransactionId
2012-10-16 23:26:33 +02:00
2014-12-30 07:55:58 +01:00
// Complete IO definitions for two types of TileLink clients
2015-03-01 02:02:13 +01:00
class UncachedTileLinkIO extends TLBundle {
val acquire = new DecoupledIO(new LogicalNetworkIO(new Acquire))
2014-01-21 21:20:55 +01:00
val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
val finish = new DecoupledIO(new LogicalNetworkIO(new Finish))
}
2014-10-03 01:47:35 +02:00
class TileLinkIO extends UncachedTileLinkIO {
2014-01-21 21:20:55 +01:00
val probe = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip
val release = new DecoupledIO(new LogicalNetworkIO(new Release))
2012-10-16 23:26:33 +02:00
}
2014-12-30 07:55:58 +01:00
// Converts UncachedTileLinkIO to regular TileLinkIO by pinning
// probe.ready and release.valid low
class TileLinkIOWrapper extends TLModule {
val io = new Bundle {
val in = new UncachedTileLinkIO().flip
val out = new TileLinkIO
}
io.out.acquire <> io.in.acquire
io.out.grant <> io.in.grant
io.out.finish <> io.in.finish
2015-03-13 00:33:35 +01:00
io.out.probe.ready := Bool(true)
io.out.release.valid := Bool(false)
}
object TileLinkIOWrapper {
2015-03-01 02:02:13 +01:00
def apply(utl: UncachedTileLinkIO, p: Parameters): TileLinkIO = {
val conv = Module(new TileLinkIOWrapper)(p)
conv.io.in <> utl
conv.io.out
}
def apply(utl: UncachedTileLinkIO): TileLinkIO = {
val conv = Module(new TileLinkIOWrapper)
2015-02-02 10:02:06 +01:00
conv.io.in <> utl
conv.io.out
}
2015-03-01 02:02:13 +01:00
def apply(tl: TileLinkIO) = tl
}
2015-03-10 00:34:59 +01:00
// This version of TileLinkIO does not contain network headers for packets
// that originate in the Clients (i.e. Acquire and Release). These headers
// are provided in the top-level that instantiates the clients and network.
// By eliding the header subbundles within the clients we can enable
// hierarchical P&R while minimizing unconnected port errors in GDS.
class HeaderlessUncachedTileLinkIO extends TLBundle {
val acquire = new DecoupledIO(new Acquire)
val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
val finish = new DecoupledIO(new LogicalNetworkIO(new Finish))
}
class HeaderlessTileLinkIO extends HeaderlessUncachedTileLinkIO {
val probe = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip
val release = new DecoupledIO(new Release)
}
class HeaderlessTileLinkIOWrapper extends TLModule {
val io = new Bundle {
val in = new HeaderlessUncachedTileLinkIO().flip
val out = new HeaderlessTileLinkIO
}
io.out.acquire <> io.in.acquire
io.out.grant <> io.in.grant
io.out.finish <> io.in.finish
2015-03-13 00:33:35 +01:00
io.out.probe.ready := Bool(true)
2015-03-10 00:34:59 +01:00
io.out.release.valid := Bool(false)
}
object HeaderlessTileLinkIOWrapper {
def apply(utl: HeaderlessUncachedTileLinkIO): HeaderlessTileLinkIO = {
val conv = Module(new HeaderlessTileLinkIOWrapper)
conv.io.in <> utl
conv.io.out
}
}
abstract trait HasArbiterTypes {
val arbN: Int
2014-12-30 07:55:58 +01:00
type ManagerSourcedWithId = ManagerToClientChannel with HasClientTransactionId
type ClientSourcedWithId = ClientToManagerChannel with HasClientTransactionId
type ClientSourcedWithIdAndData = ClientToManagerChannel with
HasClientTransactionId with
HasTileLinkData
}
2015-03-10 00:34:59 +01:00
// Utility functions for constructing TileLinkIO arbiters
abstract class TileLinkArbiterLike(val arbN: Int) extends TLModule
with HasArbiterTypes {
2014-01-21 21:20:55 +01:00
2014-12-30 07:55:58 +01:00
// These are filled in depending on whether the arbiter mucks with the
// client ids and then needs to revert them on the way back
2014-01-21 21:20:55 +01:00
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int): Bits
2014-12-30 07:55:58 +01:00
def managerSourcedClientXactId(in: ManagerSourcedWithId): Bits
def arbIdx(in: ManagerSourcedWithId): UInt
2014-01-21 21:20:55 +01:00
2015-03-10 00:34:59 +01:00
def hookupClientSource[M <: ClientSourcedWithIdAndData : ClassTag]
(clts: Seq[DecoupledIO[LogicalNetworkIO[M]]],
mngr: DecoupledIO[LogicalNetworkIO[M]]) {
def hasData(m: LogicalNetworkIO[M]) = m.payload.hasMultibeatData()
2015-03-10 00:34:59 +01:00
val arb = Module(new LockingRRArbiter(mngr.bits.clone, arbN, params(TLDataBeats), Some(hasData _)))
clts.zipWithIndex.zip(arb.io.in).map{ case ((req, id), arb) => {
arb.valid := req.valid
arb.bits := req.bits
arb.bits.payload.client_xact_id := clientSourcedClientXactId(req.bits.payload, id)
req.ready := arb.ready
2014-01-21 21:20:55 +01:00
}}
2015-03-10 00:34:59 +01:00
arb.io.out <> mngr
}
def hookupClientSourceHeaderless[M <: ClientSourcedWithIdAndData : ClassTag]
(clts: Seq[DecoupledIO[M]],
mngr: DecoupledIO[M]) {
def hasData(m: M) = m.hasMultibeatData()
val arb = Module(new LockingRRArbiter(mngr.bits.clone, arbN, params(TLDataBeats), Some(hasData _)))
clts.zipWithIndex.zip(arb.io.in).map{ case ((req, id), arb) => {
arb.valid := req.valid
arb.bits := req.bits
arb.bits.client_xact_id := clientSourcedClientXactId(req.bits, id)
req.ready := arb.ready
}}
arb.io.out <> mngr
2014-01-21 21:20:55 +01:00
}
2015-03-10 00:34:59 +01:00
def hookupFinish[M <: LogicalNetworkIO[Finish] : ClassTag]
(clts: Seq[DecoupledIO[M]],
mngr: DecoupledIO[M]) {
val arb = Module(new RRArbiter(mngr.bits.clone, arbN))
arb.io.in zip clts map { case (arb, req) => arb <> req }
arb.io.out <> mngr
}
def hookupManagerSourceWithId[M <: ManagerSourcedWithId]
(clts: Seq[DecoupledIO[LogicalNetworkIO[M]]],
mngr: DecoupledIO[LogicalNetworkIO[M]]) {
mngr.ready := Bool(false)
2014-01-21 21:20:55 +01:00
for (i <- 0 until arbN) {
2015-03-10 00:34:59 +01:00
clts(i).valid := Bool(false)
when (arbIdx(mngr.bits.payload) === UInt(i)) {
clts(i).valid := mngr.valid
mngr.ready := clts(i).ready
2014-01-21 21:20:55 +01:00
}
2015-03-10 00:34:59 +01:00
clts(i).bits := mngr.bits
clts(i).bits.payload.client_xact_id :=
managerSourcedClientXactId(mngr.bits.payload)
2014-01-21 21:20:55 +01:00
}
}
2015-03-10 00:34:59 +01:00
def hookupManagerSourceBroadcast[M <: ManagerToClientChannel]
(clts: Seq[DecoupledIO[LogicalNetworkIO[M]]],
mngr: DecoupledIO[LogicalNetworkIO[M]]) {
clts.map{ _.valid := mngr.valid }
clts.map{ _.bits := mngr.bits }
2015-03-12 17:33:56 +01:00
mngr.ready := clts.map(_.ready).reduce(_&&_)
2015-03-10 00:34:59 +01:00
}
2014-01-21 21:20:55 +01:00
}
abstract class UncachedTileLinkIOArbiter(n: Int)
extends TileLinkArbiterLike(n) {
val io = new Bundle {
2013-08-12 19:36:44 +02:00
val in = Vec.fill(n){new UncachedTileLinkIO}.flip
val out = new UncachedTileLinkIO
}
2014-01-21 21:20:55 +01:00
hookupClientSource(io.in.map(_.acquire), io.out.acquire)
2015-03-10 00:34:59 +01:00
hookupFinish(io.in.map(_.finish), io.out.finish)
hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant)
2014-01-21 21:20:55 +01:00
}
abstract class TileLinkIOArbiter(n: Int) extends TileLinkArbiterLike(n) {
2014-01-21 21:20:55 +01:00
val io = new Bundle {
val in = Vec.fill(n){new TileLinkIO}.flip
val out = new TileLinkIO
}
2014-01-21 21:20:55 +01:00
hookupClientSource(io.in.map(_.acquire), io.out.acquire)
hookupClientSource(io.in.map(_.release), io.out.release)
2015-03-10 00:34:59 +01:00
hookupFinish(io.in.map(_.finish), io.out.finish)
hookupManagerSourceBroadcast(io.in.map(_.probe), io.out.probe)
hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant)
}
2014-01-21 21:20:55 +01:00
2014-12-30 07:55:58 +01:00
// Appends the port index of the arbiter to the client_xact_id
abstract trait AppendsArbiterId extends HasArbiterTypes {
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) =
2014-01-21 21:20:55 +01:00
Cat(in.client_xact_id, UInt(id, log2Up(arbN)))
def managerSourcedClientXactId(in: ManagerSourcedWithId) =
2014-01-21 21:20:55 +01:00
in.client_xact_id >> UInt(log2Up(arbN))
def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id(log2Up(arbN)-1,0).toUInt
2014-01-21 21:20:55 +01:00
}
2014-12-30 07:55:58 +01:00
// Uses the client_xact_id as is (assumes it has been set to port index)
abstract trait PassesId extends HasArbiterTypes {
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = in.client_xact_id
def managerSourcedClientXactId(in: ManagerSourcedWithId) = in.client_xact_id
def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id
2014-01-21 21:20:55 +01:00
}
2014-12-30 07:55:58 +01:00
// Overwrites some default client_xact_id with the port idx
abstract trait UsesNewId extends HasArbiterTypes {
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = UInt(id, log2Up(arbN))
def managerSourcedClientXactId(in: ManagerSourcedWithId) = UInt(0)
def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id
2014-01-21 21:20:55 +01:00
}
2014-12-30 07:55:58 +01:00
// Mix-in id generation traits to make concrete arbiter classes
class UncachedTileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends UncachedTileLinkIOArbiter(n) with AppendsArbiterId
class UncachedTileLinkIOArbiterThatPassesId(val n: Int) extends UncachedTileLinkIOArbiter(n) with PassesId
class UncachedTileLinkIOArbiterThatUsesNewId(val n: Int) extends UncachedTileLinkIOArbiter(n) with UsesNewId
class TileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends TileLinkIOArbiter(n) with AppendsArbiterId
class TileLinkIOArbiterThatPassesId(val n: Int) extends TileLinkIOArbiter(n) with PassesId
class TileLinkIOArbiterThatUsesNewId(val n: Int) extends TileLinkIOArbiter(n) with UsesNewId