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._
|
2014-11-12 02:36:55 +01:00
|
|
|
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]
|
2014-08-08 21:21:57 +02:00
|
|
|
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]
|
2014-08-08 21:21:57 +02:00
|
|
|
|
2014-11-12 02:36:55 +01:00
|
|
|
abstract trait TileLinkParameters extends UsesParameters {
|
2015-03-01 02:02:13 +01:00
|
|
|
val tlBlockAddrBits = params(TLBlockAddrBits)
|
2014-11-12 02:36:55 +01:00
|
|
|
val tlClientXactIdBits = params(TLClientXactIdBits)
|
2014-12-30 07:55:58 +01:00
|
|
|
val tlManagerXactIdBits = params(TLManagerXactIdBits)
|
2014-11-12 02:36:55 +01:00
|
|
|
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)
|
2015-02-02 04:57:53 +01:00
|
|
|
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,
|
2015-02-02 04:57:53 +01:00
|
|
|
(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)
|
2012-10-16 23:26:33 +02:00
|
|
|
}
|
|
|
|
|
2014-12-07 12:02:20 +01:00
|
|
|
abstract class TLBundle extends Bundle with TileLinkParameters
|
|
|
|
abstract class TLModule extends Module with TileLinkParameters
|
2014-11-12 02:36:55 +01:00
|
|
|
|
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.
|
|
|
|
//
|
2015-02-02 04:57:53 +01:00
|
|
|
trait HasCacheBlockAddress extends TLBundle {
|
|
|
|
val addr_block = UInt(width = tlBlockAddrBits)
|
2015-02-06 22:20:44 +01:00
|
|
|
|
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
|
2015-02-02 04:57:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
trait HasTileLinkBeatId extends TLBundle {
|
|
|
|
val addr_beat = UInt(width = tlBeatAddrBits)
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2014-11-12 02:36:55 +01:00
|
|
|
val data = UInt(width = tlDataBits)
|
2015-03-01 02:02:13 +01:00
|
|
|
|
2015-02-02 04:57:53 +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
|
2013-03-20 22:10:16 +01:00
|
|
|
|
2014-12-30 07:55:58 +01:00
|
|
|
class Acquire extends ClientToManagerChannel
|
2015-02-02 04:57:53 +01:00
|
|
|
with HasCacheBlockAddress
|
2014-11-12 02:36:55 +01:00
|
|
|
with HasClientTransactionId
|
|
|
|
with HasTileLinkData {
|
2015-02-02 04:57:53 +01:00
|
|
|
// 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 04:57:53 +01:00
|
|
|
|
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)
|
|
|
|
def op_code(dummy: Int = 0) = Mux(hasData(), M_XWR, union(opSizeOff-1, opCodeOff))
|
|
|
|
def op_size(dummy: Int = 0) = union(addrByteOff-1, opSizeOff)
|
|
|
|
def addr_byte(dummy: Int = 0) = union(addrByteMSB-1, addrByteOff)
|
|
|
|
def write_mask(dummy: Int = 0) = union(tlWriteMaskBits, 1)
|
|
|
|
def addr(dummy: Int = 0) = Cat(this.addr_block, this.addr_beat, this.addr_byte())
|
2015-02-02 04:57:53 +01:00
|
|
|
|
|
|
|
// Other helper funcs
|
2014-11-13 01:25:25 +01:00
|
|
|
def is(t: UInt) = a_type === t
|
2015-02-02 04:57:53 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
def isBuiltInType(dummy: Int = 0): Bool = is_builtin_type
|
2015-02-02 04:57:53 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
def isSubBlockType(dummy: Int = 0): Bool = isBuiltInType() && Acquire.typesOnSubBlocks.contains(a_type)
|
2015-02-02 04:57:53 +01:00
|
|
|
|
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-02-02 04:57:53 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
def hasMultibeatData(dummy: Int = 0): Bool = Bool(tlDataBeats > 1) && isBuiltInType() &&
|
|
|
|
Acquire.typesWithMultibeatData.contains(a_type)
|
2015-02-02 04:57:53 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
//TODO: This function is a hack to support Rocket icache snooping Rocket nbdcache:
|
|
|
|
def requiresSelfProbe(dummy: Int = 0) = isBuiltInType() && a_type === Acquire.getBlockType
|
|
|
|
|
|
|
|
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))
|
2015-02-02 04:57:53 +01:00
|
|
|
}
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
object Acquire {
|
2015-03-01 02:02:13 +01:00
|
|
|
val nBuiltInTypes = 5
|
2015-02-02 04:57:53 +01:00
|
|
|
//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)
|
2015-02-02 04:57:53 +01:00
|
|
|
|
|
|
|
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,
|
2015-02-02 04:57:53 +01:00
|
|
|
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
|
2015-02-02 04:57:53 +01:00
|
|
|
acq.addr_block := addr_block
|
|
|
|
acq.addr_beat := addr_beat
|
2014-03-29 18:53:49 +01:00
|
|
|
acq.data := data
|
2015-03-01 02:02:13 +01:00
|
|
|
acq.union := union
|
2014-03-29 18:53:49 +01:00
|
|
|
acq
|
|
|
|
}
|
2015-02-02 04:57:53 +01:00
|
|
|
// Copy constructor
|
2014-08-08 21:21:57 +02:00
|
|
|
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
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2015-02-02 04:57:53 +01:00
|
|
|
// Asks for a single TileLink beat of data
|
2015-03-01 02:02:13 +01:00
|
|
|
object Get {
|
2015-02-02 04:57:53 +01:00
|
|
|
def apply(
|
2015-03-11 22:28:17 +01:00
|
|
|
client_xact_id: UInt,
|
|
|
|
addr_block: UInt,
|
|
|
|
addr_beat: UInt,
|
2015-02-02 04:57:53 +01:00
|
|
|
alloc: Bool = Bool(true)): Acquire = {
|
|
|
|
Acquire(
|
2015-03-01 02:02:13 +01:00
|
|
|
is_builtin_type = Bool(true),
|
|
|
|
a_type = Acquire.getType,
|
2015-02-02 04:57:53 +01:00
|
|
|
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))
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
2015-02-02 04:57:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Asks for an entire cache block of data
|
2015-03-01 02:02:13 +01:00
|
|
|
object GetBlock {
|
2015-02-02 04:57:53 +01:00
|
|
|
def apply(
|
2015-03-11 22:28:17 +01:00
|
|
|
client_xact_id: UInt = UInt(0),
|
|
|
|
addr_block: UInt,
|
2015-02-02 04:57:53 +01:00
|
|
|
alloc: Bool = Bool(true)): Acquire = {
|
|
|
|
Acquire(
|
2015-03-01 02:02:13 +01:00
|
|
|
is_builtin_type = Bool(true),
|
|
|
|
a_type = Acquire.getBlockType,
|
2015-02-02 04:57:53 +01:00
|
|
|
client_xact_id = client_xact_id,
|
|
|
|
addr_block = addr_block,
|
2015-03-01 02:02:13 +01:00
|
|
|
union = Cat(M_XRD, alloc))
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
2013-08-02 23:55:06 +02:00
|
|
|
}
|
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 {
|
2015-02-02 04:57:53 +01:00
|
|
|
def apply(
|
|
|
|
client_xact_id: UInt,
|
|
|
|
addr_block: UInt,
|
|
|
|
addr_beat: UInt,
|
|
|
|
data: UInt,
|
2015-03-01 02:02:13 +01:00
|
|
|
write_mask: UInt = Acquire.fullWriteMask): Acquire = {
|
2015-02-02 04:57:53 +01:00
|
|
|
Acquire(
|
2015-03-01 02:02:13 +01:00
|
|
|
is_builtin_type = Bool(true),
|
|
|
|
a_type = Acquire.putType,
|
2015-02-02 04:57:53 +01:00
|
|
|
addr_block = addr_block,
|
|
|
|
addr_beat = addr_beat,
|
|
|
|
client_xact_id = client_xact_id,
|
|
|
|
data = data,
|
2015-03-01 02:02:13 +01:00
|
|
|
union = Cat(write_mask, Bool(true)))
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
2015-02-02 04:57:53 +01:00
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
write_mask: UInt): Acquire = {
|
|
|
|
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,
|
|
|
|
union = Cat(write_mask, (write_mask != Acquire.fullWriteMask)))
|
|
|
|
}
|
2015-02-02 04:57:53 +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,
|
2015-02-02 04:57:53 +01:00
|
|
|
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))
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
// Performs an atomic operation in the outer memory
|
|
|
|
object PutAtomic {
|
2015-02-02 04:57:53 +01:00
|
|
|
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,
|
2015-02-02 04:57:53 +01:00
|
|
|
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)))
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-05 23:21:38 +01:00
|
|
|
|
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
|
2015-02-02 04:57:53 +01:00
|
|
|
with HasCacheBlockAddress {
|
2015-03-01 02:02:13 +01:00
|
|
|
val p_type = UInt(width = tlCoh.probeTypeWidth)
|
2015-02-02 04:57:53 +01:00
|
|
|
|
2014-12-30 07:55:58 +01:00
|
|
|
def is(t: UInt) = p_type === t
|
|
|
|
}
|
|
|
|
|
2014-11-05 23:21:38 +01:00
|
|
|
object Probe {
|
2015-02-02 04:57:53 +01:00
|
|
|
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
|
2015-02-02 04:57:53 +01:00
|
|
|
prb.addr_block := addr_block
|
2014-01-21 21:20:55 +01:00
|
|
|
prb
|
|
|
|
}
|
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2014-12-30 07:55:58 +01:00
|
|
|
class Release extends ClientToManagerChannel
|
2015-02-02 04:57:53 +01:00
|
|
|
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)
|
2015-02-02 04:57:53 +01:00
|
|
|
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)
|
2015-02-02 04:57:53 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-11-05 23:21:38 +01:00
|
|
|
object Release {
|
2015-02-02 04:57:53 +01:00
|
|
|
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
|
2014-11-05 23:21:38 +01:00
|
|
|
rel.client_xact_id := client_xact_id
|
2015-02-02 04:57:53 +01:00
|
|
|
rel.addr_block := addr_block
|
|
|
|
rel.addr_beat := addr_beat
|
2014-03-29 18:53:49 +01:00
|
|
|
rel.data := data
|
2015-02-02 04:57:53 +01:00
|
|
|
rel.voluntary := voluntary
|
2014-01-21 21:20:55 +01:00
|
|
|
rel
|
|
|
|
}
|
2013-01-29 01:39:45 +01:00
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2014-12-30 07:55:58 +01:00
|
|
|
class Grant extends ManagerToClientChannel
|
2014-11-12 02:36:55 +01:00
|
|
|
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)
|
2015-02-02 04:57:53 +01:00
|
|
|
|
|
|
|
// 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(),
|
2015-02-02 04:57:53 +01:00
|
|
|
Grant.typesWithData.contains(g_type),
|
2015-03-01 02:02:13 +01:00
|
|
|
tlCoh.grantTypesWithData.contains(g_type))
|
2015-02-02 04:57:53 +01:00
|
|
|
def hasMultibeatData(dummy: Int = 0): Bool =
|
2015-03-01 02:02:13 +01:00
|
|
|
Bool(tlDataBeats > 1) && Mux(isBuiltInType(),
|
2015-02-02 04:57:53 +01:00
|
|
|
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()
|
2015-02-02 04:57:53 +01:00
|
|
|
def makeFinish(dummy: Int = 0): Finish = {
|
2015-03-01 02:02:13 +01:00
|
|
|
val f = Bundle(new Finish, { case TLManagerXactIdBits => tlManagerXactIdBits })
|
2015-02-02 04:57:53 +01:00
|
|
|
f.manager_xact_id := this.manager_xact_id
|
|
|
|
f
|
|
|
|
}
|
2014-11-12 02:36:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2015-02-02 04:57:53 +01:00
|
|
|
|
|
|
|
def apply(
|
2015-03-01 02:02:13 +01:00
|
|
|
is_builtin_type: Bool,
|
2015-02-02 04:57:53 +01:00
|
|
|
g_type: UInt,
|
|
|
|
client_xact_id: UInt,
|
|
|
|
manager_xact_id: UInt,
|
|
|
|
addr_beat: UInt = UInt(0),
|
|
|
|
data: UInt = UInt(0)): Grant = {
|
2014-03-29 18:53:49 +01:00
|
|
|
val gnt = new Grant
|
2015-03-01 02:02:13 +01:00
|
|
|
gnt.is_builtin_type := is_builtin_type
|
2014-03-29 18:53:49 +01:00
|
|
|
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
|
2015-02-02 04:57:53 +01:00
|
|
|
gnt.addr_beat := addr_beat
|
2014-03-29 18:53:49 +01:00
|
|
|
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 {
|
2014-03-29 18:53:49 +01:00
|
|
|
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
|
2014-04-27 00:17:05 +02:00
|
|
|
val finish = new DecoupledIO(new LogicalNetworkIO(new Finish))
|
2013-03-20 22:10:16 +01:00
|
|
|
}
|
|
|
|
|
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
|
2014-03-29 18:53:49 +01:00
|
|
|
val release = new DecoupledIO(new LogicalNetworkIO(new Release))
|
2012-10-16 23:26:33 +02:00
|
|
|
}
|
2013-03-20 22:10:16 +01:00
|
|
|
|
2014-12-30 07:55:58 +01:00
|
|
|
// Converts UncachedTileLinkIO to regular TileLinkIO by pinning
|
|
|
|
// probe.ready and release.valid low
|
2014-12-12 21:07:04 +01:00
|
|
|
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
|
|
|
|
io.out.probe.ready := Bool(false)
|
|
|
|
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 = {
|
2014-12-12 21:07:04 +01:00
|
|
|
val conv = Module(new TileLinkIOWrapper)
|
2015-02-02 10:02:06 +01:00
|
|
|
conv.io.in <> utl
|
2014-12-12 21:07:04 +01:00
|
|
|
conv.io.out
|
|
|
|
}
|
2015-03-01 02:02:13 +01:00
|
|
|
def apply(tl: TileLinkIO) = tl
|
2014-12-12 21:07:04 +01:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
io.out.probe.ready := Bool(false)
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-02 04:57:53 +01:00
|
|
|
abstract trait HasArbiterTypes {
|
|
|
|
val arbN: Int
|
2014-12-30 07:55:58 +01:00
|
|
|
type ManagerSourcedWithId = ManagerToClientChannel with HasClientTransactionId
|
2015-02-02 04:57:53 +01:00
|
|
|
type ClientSourcedWithId = ClientToManagerChannel with HasClientTransactionId
|
|
|
|
type ClientSourcedWithIdAndData = ClientToManagerChannel with
|
|
|
|
HasClientTransactionId with
|
|
|
|
HasTileLinkData
|
|
|
|
}
|
2015-03-10 00:34:59 +01:00
|
|
|
|
2015-02-02 04:57:53 +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]]) {
|
2015-02-02 04:57:53 +01:00
|
|
|
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) => {
|
2014-03-29 18:53:49 +01:00
|
|
|
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 }
|
|
|
|
mngr.ready := clts.map(_.ready).reduce(_||_)
|
|
|
|
}
|
2014-01-21 21:20:55 +01:00
|
|
|
}
|
|
|
|
|
2014-08-08 21:21:57 +02:00
|
|
|
abstract class UncachedTileLinkIOArbiter(n: Int)
|
|
|
|
extends TileLinkArbiterLike(n) {
|
2013-03-20 22:10:16 +01:00
|
|
|
val io = new Bundle {
|
2013-08-12 19:36:44 +02:00
|
|
|
val in = Vec.fill(n){new UncachedTileLinkIO}.flip
|
2013-03-20 22:10:16 +01:00
|
|
|
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
|
|
|
}
|
2013-03-20 22:10:16 +01:00
|
|
|
|
2014-08-08 21:21:57 +02: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
|
2013-07-10 00:37:42 +02:00
|
|
|
}
|
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)
|
2013-07-10 00:37:42 +02:00
|
|
|
}
|
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
|
2015-02-02 04:57:53 +01:00
|
|
|
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)))
|
2015-02-02 04:57:53 +01:00
|
|
|
def managerSourcedClientXactId(in: ManagerSourcedWithId) =
|
2014-01-21 21:20:55 +01:00
|
|
|
in.client_xact_id >> UInt(log2Up(arbN))
|
2015-02-02 04:57:53 +01:00
|
|
|
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)
|
2015-02-02 04:57:53 +01:00
|
|
|
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
|
2015-02-02 04:57:53 +01:00
|
|
|
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
|
2014-08-08 21:21:57 +02:00
|
|
|
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
|