931 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Scala
		
	
	
	
	
	
			
		
		
	
	
			931 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Scala
		
	
	
	
	
	
// See LICENSE for license details.
 | 
						|
 | 
						|
package uncore
 | 
						|
import Chisel._
 | 
						|
import scala.math.max
 | 
						|
import scala.reflect._
 | 
						|
import scala.reflect.runtime.universe._
 | 
						|
 | 
						|
// 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
 | 
						|
case object TLCoherencePolicy extends Field[CoherencePolicy]
 | 
						|
case object TLBlockAddrBits extends Field[Int]
 | 
						|
case object TLMaxClientXacts extends Field[Int]
 | 
						|
case object TLMaxClientPorts extends Field[Int]
 | 
						|
case object TLMaxManagerXacts extends Field[Int]
 | 
						|
case object TLDataBits extends Field[Int]
 | 
						|
case object TLDataBeats extends Field[Int]
 | 
						|
case object TLNetworkIsOrderedP2P extends Field[Boolean]
 | 
						|
 | 
						|
abstract trait TileLinkParameters extends UsesParameters {
 | 
						|
  val tlBlockAddrBits = params(TLBlockAddrBits)
 | 
						|
  val tlMaxClientXacts = params(TLMaxClientXacts)
 | 
						|
  val tlMaxClientPorts = params(TLMaxClientPorts)
 | 
						|
  val tlMaxManagerXacts = params(TLMaxManagerXacts)
 | 
						|
  val tlClientXactIdBits = log2Up(tlMaxClientXacts*tlMaxClientPorts)
 | 
						|
  val tlManagerXactIdBits = log2Up(tlMaxManagerXacts)
 | 
						|
  val tlDataBits = params(TLDataBits)
 | 
						|
  val tlDataBytes = tlDataBits/8
 | 
						|
  val tlDataBeats = params(TLDataBeats)
 | 
						|
  val tlCoh = params(TLCoherencePolicy)
 | 
						|
  val tlWriteMaskBits = if(tlDataBits/8 < 1) 1 else tlDataBits/8
 | 
						|
  val tlBeatAddrBits = log2Up(tlDataBeats)
 | 
						|
  val tlByteAddrBits = log2Up(tlWriteMaskBits)
 | 
						|
  val tlMemoryOpcodeBits = M_SZ
 | 
						|
  val tlMemoryOperandSizeBits = MT_SZ
 | 
						|
  val tlAcquireTypeBits = max(log2Up(Acquire.nBuiltInTypes), 
 | 
						|
                              tlCoh.acquireTypeWidth)
 | 
						|
  val tlAcquireUnionBits = max(tlWriteMaskBits,
 | 
						|
                                 (tlByteAddrBits +
 | 
						|
                                   tlMemoryOperandSizeBits +
 | 
						|
                                   tlMemoryOpcodeBits)) + 1
 | 
						|
  val tlGrantTypeBits = max(log2Up(Grant.nBuiltInTypes), 
 | 
						|
                              tlCoh.grantTypeWidth) + 1
 | 
						|
  val tlNetworkPreservesPointToPointOrdering = params(TLNetworkIsOrderedP2P)
 | 
						|
  val amoAluOperandBits = params(AmoAluOperandBits)
 | 
						|
}
 | 
						|
 | 
						|
abstract class TLBundle extends Bundle with TileLinkParameters {
 | 
						|
}
 | 
						|
abstract class TLModule extends Module with TileLinkParameters
 | 
						|
 | 
						|
// Directionality of message channel
 | 
						|
// Used to hook up logical network ports to physical network ports
 | 
						|
trait TileLinkChannel extends TLBundle {
 | 
						|
  def hasData(dummy: Int = 0): Bool
 | 
						|
  def hasMultibeatData(dummy: Int = 0): Bool
 | 
						|
}
 | 
						|
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)
 | 
						|
 | 
						|
  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)
 | 
						|
}
 | 
						|
 | 
						|
trait HasManagerTransactionId extends TLBundle {
 | 
						|
  val manager_xact_id = Bits(width = tlManagerXactIdBits)
 | 
						|
}
 | 
						|
 | 
						|
trait HasTileLinkData extends HasTileLinkBeatId {
 | 
						|
  val data = UInt(width = tlDataBits)
 | 
						|
 | 
						|
  def hasData(dummy: Int = 0): Bool
 | 
						|
  def hasMultibeatData(dummy: Int = 0): Bool
 | 
						|
}
 | 
						|
 | 
						|
// Actual TileLink channel bundle definitions
 | 
						|
 | 
						|
class Acquire extends ClientToManagerChannel 
 | 
						|
    with HasCacheBlockAddress 
 | 
						|
    with HasClientTransactionId 
 | 
						|
    with HasTileLinkData {
 | 
						|
  // Actual bundle fields
 | 
						|
  val is_builtin_type = Bool()
 | 
						|
  val a_type = UInt(width = tlAcquireTypeBits)
 | 
						|
  val union = Bits(width = tlAcquireUnionBits)
 | 
						|
 | 
						|
  // Utility funcs for accessing subblock union
 | 
						|
  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(isBuiltInType(Acquire.putType) || isBuiltInType(Acquire.putBlockType),
 | 
						|
    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)
 | 
						|
  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), 
 | 
						|
      FillInterleaved(amoAluOperandBits/8, UIntToOH(amo_offset())),
 | 
						|
      Mux(isBuiltInType(Acquire.putBlockType) || isBuiltInType(Acquire.putType),
 | 
						|
        union(tlWriteMaskBits, 1),
 | 
						|
        UInt(0, width = tlWriteMaskBits)))
 | 
						|
  def full_wmask(dummy: Int = 0) = FillInterleaved(8, wmask())
 | 
						|
 | 
						|
  def addr(dummy: Int = 0) = Cat(this.addr_block, this.addr_beat, this.addr_byte())
 | 
						|
 | 
						|
  // Other helper funcs
 | 
						|
  def is(t: UInt) = a_type === t //TODO: make this more opaque; def ===?
 | 
						|
 | 
						|
  def isBuiltInType(dummy: Int = 0): Bool = is_builtin_type
 | 
						|
  def isBuiltInType(t: UInt): Bool = is_builtin_type && a_type === t 
 | 
						|
 | 
						|
  def isSubBlockType(dummy: Int = 0): Bool = isBuiltInType() && Acquire.typesOnSubBlocks.contains(a_type) 
 | 
						|
 | 
						|
  def isPrefetch(dummy: Int = 0): Bool = isBuiltInType() && is(Acquire.prefetchType) 
 | 
						|
 | 
						|
  // Assumes no custom types have data
 | 
						|
  def hasData(dummy: Int = 0): Bool = isBuiltInType() && Acquire.typesWithData.contains(a_type)
 | 
						|
 | 
						|
  def hasMultibeatData(dummy: Int = 0): Bool = Bool(tlDataBeats > 1) && isBuiltInType() &&
 | 
						|
                                           Acquire.typesWithMultibeatData.contains(a_type)
 | 
						|
 | 
						|
  def requiresSelfProbe(dummy: Int = 0) = Bool(false)
 | 
						|
 | 
						|
  def getBuiltInGrantType(dummy: Int = 0): UInt = {
 | 
						|
    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 {
 | 
						|
  val nBuiltInTypes = 5
 | 
						|
  //TODO: Use Enum
 | 
						|
  def getType       = UInt("b000")
 | 
						|
  def getBlockType  = UInt("b001")
 | 
						|
  def putType       = UInt("b010")
 | 
						|
  def putBlockType  = UInt("b011")
 | 
						|
  def putAtomicType = UInt("b100")
 | 
						|
  def prefetchType = UInt("b101")
 | 
						|
  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(
 | 
						|
      is_builtin_type: Bool,
 | 
						|
      a_type: Bits,
 | 
						|
      client_xact_id: UInt,
 | 
						|
      addr_block: UInt,
 | 
						|
      addr_beat: UInt = UInt(0),
 | 
						|
      data: UInt = UInt(0),
 | 
						|
      union: UInt = UInt(0)): Acquire = {
 | 
						|
    val acq = new Acquire
 | 
						|
    acq.is_builtin_type := is_builtin_type
 | 
						|
    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
 | 
						|
    acq.union := union
 | 
						|
    acq
 | 
						|
  }
 | 
						|
  // Copy constructor
 | 
						|
  def apply(a: Acquire): Acquire = {
 | 
						|
    val acq = new Acquire
 | 
						|
    acq := a
 | 
						|
    acq
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Asks for a single TileLink beat of data
 | 
						|
object Get {
 | 
						|
  def apply(
 | 
						|
      client_xact_id: UInt,
 | 
						|
      addr_block: UInt,
 | 
						|
      addr_beat: UInt,
 | 
						|
      alloc: Bool = Bool(true)): Acquire = {
 | 
						|
    Acquire(
 | 
						|
      is_builtin_type = Bool(true),
 | 
						|
      a_type = Acquire.getType,
 | 
						|
      client_xact_id = client_xact_id,
 | 
						|
      addr_block = addr_block,
 | 
						|
      addr_beat = addr_beat,
 | 
						|
      union = Cat(M_XRD, alloc))
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Asks for an entire cache block of data
 | 
						|
object GetBlock {
 | 
						|
  def apply(
 | 
						|
      client_xact_id: UInt = UInt(0),
 | 
						|
      addr_block: UInt,
 | 
						|
      alloc: Bool = Bool(true)): Acquire = {
 | 
						|
    Acquire(
 | 
						|
      is_builtin_type = Bool(true),
 | 
						|
      a_type = Acquire.getBlockType,
 | 
						|
      client_xact_id = client_xact_id, 
 | 
						|
      addr_block = addr_block,
 | 
						|
      union = Cat(M_XRD, alloc))
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// 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)))
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// 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,
 | 
						|
      wmask: UInt = Acquire.fullWriteMask): Acquire = {
 | 
						|
    Acquire(
 | 
						|
      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,
 | 
						|
      union = Cat(wmask, Bool(true)))
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Writes an entire cache block of data
 | 
						|
object PutBlock {
 | 
						|
  def apply(
 | 
						|
      client_xact_id: UInt,
 | 
						|
      addr_block: UInt,
 | 
						|
      addr_beat: UInt,
 | 
						|
      data: UInt,
 | 
						|
      wmask: 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(wmask, (wmask != Acquire.fullWriteMask)))
 | 
						|
  }
 | 
						|
  def apply(
 | 
						|
      client_xact_id: UInt,
 | 
						|
      addr_block: UInt,
 | 
						|
      addr_beat: UInt,
 | 
						|
      data: UInt,
 | 
						|
      alloc: Bool = Bool(true)): 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(Acquire.fullWriteMask, alloc))
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// 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(
 | 
						|
      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,
 | 
						|
      union = Cat(addr_byte, operand_size, atomic_opcode, Bool(true)))
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// 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)))
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class Probe extends ManagerToClientChannel 
 | 
						|
    with HasCacheBlockAddress {
 | 
						|
  val p_type = UInt(width = tlCoh.probeTypeWidth)
 | 
						|
 | 
						|
  def is(t: UInt) = p_type === t
 | 
						|
  def hasData(dummy: Int = 0) = Bool(false)
 | 
						|
  def hasMultibeatData(dummy: Int = 0) = Bool(false)
 | 
						|
}
 | 
						|
 | 
						|
object Probe {
 | 
						|
  def apply(p_type: UInt, addr_block: UInt) = {
 | 
						|
    val prb = new Probe
 | 
						|
    prb.p_type := p_type
 | 
						|
    prb.addr_block := addr_block
 | 
						|
    prb
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class Release extends ClientToManagerChannel 
 | 
						|
    with HasCacheBlockAddress 
 | 
						|
    with HasClientTransactionId 
 | 
						|
    with HasTileLinkData {
 | 
						|
  val r_type = UInt(width = tlCoh.releaseTypeWidth)
 | 
						|
  val voluntary = Bool()
 | 
						|
 | 
						|
  // Helper funcs
 | 
						|
  def is(t: UInt) = r_type === t
 | 
						|
  def hasData(dummy: Int = 0) = tlCoh.releaseTypesWithData.contains(r_type)
 | 
						|
  //TODO: Assumes all releases write back full cache blocks:
 | 
						|
  def hasMultibeatData(dummy: Int = 0) = Bool(tlDataBeats > 1) && tlCoh.releaseTypesWithData.contains(r_type)
 | 
						|
  def isVoluntary(dummy: Int = 0) = voluntary
 | 
						|
  def requiresAck(dummy: Int = 0) = !Bool(tlNetworkPreservesPointToPointOrdering)
 | 
						|
}
 | 
						|
 | 
						|
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 = {
 | 
						|
    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
 | 
						|
    rel
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class Grant extends ManagerToClientChannel 
 | 
						|
    with HasTileLinkData 
 | 
						|
    with HasClientTransactionId 
 | 
						|
    with HasManagerTransactionId {
 | 
						|
  val is_builtin_type = Bool()
 | 
						|
  val g_type = UInt(width = tlGrantTypeBits)
 | 
						|
 | 
						|
  // Helper funcs
 | 
						|
  def isBuiltInType(dummy: Int = 0): Bool = is_builtin_type
 | 
						|
  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))
 | 
						|
  def hasMultibeatData(dummy: Int = 0): Bool = 
 | 
						|
    Bool(tlDataBeats > 1) && Mux(isBuiltInType(),
 | 
						|
                               Grant.typesWithMultibeatData.contains(g_type),
 | 
						|
                               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 = {
 | 
						|
    val f = Bundle(new Finish, { case TLMaxManagerXacts => tlMaxManagerXacts })
 | 
						|
    f.manager_xact_id := this.manager_xact_id
 | 
						|
    f
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
object Grant {
 | 
						|
  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(
 | 
						|
      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
 | 
						|
    gnt.is_builtin_type := is_builtin_type
 | 
						|
    gnt.g_type := g_type
 | 
						|
    gnt.client_xact_id := client_xact_id
 | 
						|
    gnt.manager_xact_id := manager_xact_id
 | 
						|
    gnt.addr_beat := addr_beat
 | 
						|
    gnt.data := data
 | 
						|
    gnt
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class Finish extends ClientToManagerChannel with HasManagerTransactionId {
 | 
						|
  def hasData(dummy: Int = 0) = Bool(false)
 | 
						|
  def hasMultibeatData(dummy: Int = 0) = Bool(false)
 | 
						|
}
 | 
						|
 | 
						|
// Complete IO definitions for two types of TileLink clients 
 | 
						|
class UncachedTileLinkIO extends TLBundle {
 | 
						|
  val acquire   = new DecoupledIO(new LogicalNetworkIO(new Acquire))
 | 
						|
  val grant     = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
 | 
						|
  val finish = new DecoupledIO(new LogicalNetworkIO(new Finish))
 | 
						|
}
 | 
						|
 | 
						|
class TileLinkIO extends UncachedTileLinkIO {
 | 
						|
  val probe     = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip
 | 
						|
  val release   = new DecoupledIO(new LogicalNetworkIO(new Release))
 | 
						|
}
 | 
						|
 | 
						|
// 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
 | 
						|
  io.out.probe.ready := Bool(true)
 | 
						|
  io.out.release.valid := Bool(false)
 | 
						|
}
 | 
						|
 | 
						|
// 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.
 | 
						|
// Secondly, this version of the interface elides Finish messages, with the
 | 
						|
// assumption that a FinishUnit has been coupled to the TileLinkIO port
 | 
						|
// to deal with acking received Grants.
 | 
						|
class HeaderlessUncachedTileLinkIO extends TLBundle {
 | 
						|
  val acquire   = new DecoupledIO(new Acquire)
 | 
						|
  val grant     = new DecoupledIO(new Grant).flip
 | 
						|
}
 | 
						|
 | 
						|
class HeaderlessTileLinkIO extends HeaderlessUncachedTileLinkIO {
 | 
						|
  val probe     = new DecoupledIO(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.probe.ready := Bool(true)
 | 
						|
  io.out.release.valid := Bool(false)
 | 
						|
}
 | 
						|
 | 
						|
object TileLinkIOWrapper {
 | 
						|
  def apply(utl: HeaderlessUncachedTileLinkIO, p: Parameters): HeaderlessTileLinkIO = {
 | 
						|
    val conv = Module(new HeaderlessTileLinkIOWrapper)(p)
 | 
						|
    conv.io.in <> utl
 | 
						|
    conv.io.out
 | 
						|
  }
 | 
						|
  def apply(utl: HeaderlessUncachedTileLinkIO): HeaderlessTileLinkIO = {
 | 
						|
    val conv = Module(new HeaderlessTileLinkIOWrapper)
 | 
						|
    conv.io.in <> utl
 | 
						|
    conv.io.out
 | 
						|
  }
 | 
						|
  def apply(tl: HeaderlessTileLinkIO): HeaderlessTileLinkIO = tl
 | 
						|
  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)
 | 
						|
    conv.io.in <> utl
 | 
						|
    conv.io.out
 | 
						|
  }
 | 
						|
  def apply(tl: TileLinkIO): TileLinkIO = tl
 | 
						|
}
 | 
						|
 | 
						|
trait HasDataBeatCounters {
 | 
						|
  type HasBeat = TileLinkChannel with HasTileLinkBeatId
 | 
						|
  type HasClientId = TileLinkChannel with HasClientTransactionId
 | 
						|
  type LNAcquire = LogicalNetworkIO[Acquire]
 | 
						|
  type LNRelease = LogicalNetworkIO[Release]
 | 
						|
  type LNGrant = LogicalNetworkIO[Grant]
 | 
						|
 | 
						|
  def connectDataBeatCounter[S <: TileLinkChannel : ClassTag](inc: Bool, data: S, beat: UInt) = {
 | 
						|
    val multi = data.hasMultibeatData()
 | 
						|
    val (multi_cnt, multi_done) = Counter(inc && multi, data.tlDataBeats)
 | 
						|
    val cnt = Mux(multi, multi_cnt, beat)
 | 
						|
    val done = Mux(multi, multi_done, inc)
 | 
						|
    (cnt, done)
 | 
						|
  }
 | 
						|
 | 
						|
  def connectOutgoingDataBeatCounter[T <: Data : TypeTag](
 | 
						|
      in: DecoupledIO[T], 
 | 
						|
      beat: UInt = UInt(0)): (UInt, Bool) = {
 | 
						|
    in.bits match {
 | 
						|
      case p: TileLinkChannel if typeTag[T].tpe <:< typeTag[TileLinkChannel].tpe =>
 | 
						|
        connectDataBeatCounter(in.fire(), p, beat)
 | 
						|
      case ln: LNGrant if typeTag[T].tpe <:< typeTag[LNGrant].tpe =>
 | 
						|
        connectDataBeatCounter(in.fire(), ln.payload, beat)
 | 
						|
      case _ => { require(false, "Don't know how to connect a beat counter to " + typeTag[T].tpe); (UInt(0), Bool(false))}
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  def connectIncomingDataBeatCounters[T <: HasClientId : ClassTag](
 | 
						|
      in: DecoupledIO[LogicalNetworkIO[T]],
 | 
						|
      entries: Int): Vec[Bool] = {
 | 
						|
    val id = in.bits.payload.client_xact_id
 | 
						|
    Vec((0 until entries).map { i =>
 | 
						|
      connectDataBeatCounter(in.fire() && id === UInt(i), in.bits.payload, UInt(0))._2 
 | 
						|
    })
 | 
						|
  }
 | 
						|
 | 
						|
  def connectIncomingDataBeatCounter[T <: Data : TypeTag](in: DecoupledIO[T]): Bool = {
 | 
						|
    in.bits match {
 | 
						|
      case p: TileLinkChannel if typeTag[T].tpe <:< typeTag[TileLinkChannel].tpe =>
 | 
						|
        connectDataBeatCounter(in.fire(), p, UInt(0))._2
 | 
						|
      case ln: LNAcquire if typeTag[T].tpe =:= typeTag[LNAcquire].tpe =>
 | 
						|
        connectDataBeatCounter(in.fire(), ln.payload, UInt(0))._2
 | 
						|
      case ln: LNRelease if typeTag[T].tpe =:= typeTag[LNRelease].tpe =>
 | 
						|
        connectDataBeatCounter(in.fire(), ln.payload, UInt(0))._2
 | 
						|
      case ln: LNGrant if typeTag[T].tpe =:= typeTag[LNGrant].tpe =>
 | 
						|
        connectDataBeatCounter(in.fire(), ln.payload, UInt(0))._2
 | 
						|
      case _ => { require(false, "Don't know how to connect a beat counter to " +  typeTag[T].tpe); Bool(false)}
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  def connectHeaderlessTwoWayBeatCounter[ T <: TileLinkChannel : ClassTag, S <: TileLinkChannel : ClassTag](
 | 
						|
      max: Int,
 | 
						|
      up: DecoupledIO[T],
 | 
						|
      down: DecoupledIO[S],
 | 
						|
      beat: UInt): (Bool, UInt, Bool, UInt, Bool) = {
 | 
						|
    val cnt = Reg(init = UInt(0, width = log2Up(max+1)))
 | 
						|
    val (up_idx, do_inc) = connectDataBeatCounter(up.fire(), up.bits, beat)
 | 
						|
    val (down_idx, do_dec) = connectDataBeatCounter(down.fire(), down.bits, beat)
 | 
						|
    cnt := Mux(do_dec,
 | 
						|
            Mux(do_inc, cnt, cnt - UInt(1)),
 | 
						|
            Mux(do_inc, cnt + UInt(1), cnt))
 | 
						|
    (cnt > UInt(0), up_idx, do_inc, down_idx, do_dec)
 | 
						|
  }
 | 
						|
 | 
						|
  def connectTwoWayBeatCounter[ T <: TileLinkChannel : ClassTag, S <: TileLinkChannel : ClassTag](
 | 
						|
      max: Int,
 | 
						|
      up: DecoupledIO[LogicalNetworkIO[T]],
 | 
						|
      down: DecoupledIO[LogicalNetworkIO[S]],
 | 
						|
      inc: T => Bool = (t: T) => Bool(true),
 | 
						|
      dec: S => Bool = (s: S) => Bool(true)): (Bool, UInt, Bool, UInt, Bool) = {
 | 
						|
    val cnt = Reg(init = UInt(0, width = log2Up(max+1)))
 | 
						|
    val (up_idx, up_done) = connectDataBeatCounter(up.fire(), up.bits.payload, UInt(0))
 | 
						|
    val (down_idx, down_done) = connectDataBeatCounter(down.fire(), down.bits.payload, UInt(0))
 | 
						|
    val do_inc = up_done && inc(up.bits.payload)
 | 
						|
    val do_dec = down_done && dec(down.bits.payload)
 | 
						|
    cnt := Mux(do_dec,
 | 
						|
            Mux(do_inc, cnt, cnt - UInt(1)),
 | 
						|
            Mux(do_inc, cnt + UInt(1), cnt))
 | 
						|
    (cnt > UInt(0), up_idx, up_done, down_idx, down_done)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class FinishQueueEntry extends TLBundle {
 | 
						|
    val fin = new Finish
 | 
						|
    val dst = UInt(width = log2Up(params(LNEndpoints)))
 | 
						|
}
 | 
						|
 | 
						|
class FinishQueue(entries: Int) extends Queue(new FinishQueueEntry, entries)
 | 
						|
 | 
						|
class FinishUnit(srcId: Int = 0) extends TLModule 
 | 
						|
    with HasDataBeatCounters {
 | 
						|
  val io = new Bundle {
 | 
						|
    val grant = Decoupled(new LogicalNetworkIO(new Grant)).flip
 | 
						|
    val refill = Decoupled(new Grant)
 | 
						|
    val finish = Decoupled(new LogicalNetworkIO(new Finish))
 | 
						|
    val ready = Bool(OUTPUT)
 | 
						|
    val grant_done = Bool(OUTPUT)
 | 
						|
    val pending_finish = Bool(OUTPUT)
 | 
						|
  }
 | 
						|
 | 
						|
  val entries = 1 << tlClientXactIdBits
 | 
						|
  val g = io.grant.bits.payload
 | 
						|
  assert(g.client_xact_id <= UInt(entries), "No grant beat counter provisioned, only " + entries)
 | 
						|
 | 
						|
  val done = connectIncomingDataBeatCounters(io.grant, entries).reduce(_||_)
 | 
						|
  val q = Module(new FinishQueue(entries))
 | 
						|
 | 
						|
  q.io.enq.valid := io.grant.valid && g.requiresAck() && (!g.hasMultibeatData() || done)
 | 
						|
  q.io.enq.bits.fin := g.makeFinish()
 | 
						|
  q.io.enq.bits.dst := io.grant.bits.header.src
 | 
						|
 | 
						|
  io.finish.bits.header.src := UInt(srcId)
 | 
						|
  io.finish.bits.header.dst := q.io.deq.bits.dst
 | 
						|
  io.finish.bits.payload := q.io.deq.bits.fin
 | 
						|
  io.finish.valid := q.io.deq.valid
 | 
						|
  q.io.deq.ready := io.finish.ready
 | 
						|
 | 
						|
  io.refill.valid := io.grant.valid
 | 
						|
  io.refill.bits := io.grant.bits.payload
 | 
						|
  io.grant.ready := (q.io.enq.ready || !g.requiresAck()) && (io.refill.ready || !g.hasData())
 | 
						|
 | 
						|
  io.ready := q.io.enq.ready
 | 
						|
  io.grant_done := done
 | 
						|
  io.pending_finish := q.io.deq.valid
 | 
						|
}
 | 
						|
 | 
						|
object TileLinkHeaderOverwriter {
 | 
						|
  def apply[T <: ClientToManagerChannel](
 | 
						|
      in: DecoupledIO[LogicalNetworkIO[T]],
 | 
						|
      clientId: Int,
 | 
						|
      passThrough: Boolean): DecoupledIO[LogicalNetworkIO[T]] = {
 | 
						|
    val out = in.clone.asDirectionless
 | 
						|
    out.bits.payload := in.bits.payload
 | 
						|
    out.bits.header.src := UInt(clientId)
 | 
						|
    out.bits.header.dst := (if(passThrough) in.bits.header.dst else UInt(0))
 | 
						|
    out.valid := in.valid
 | 
						|
    in.ready := out.ready
 | 
						|
    out
 | 
						|
  }
 | 
						|
 | 
						|
  def apply[T <: ClientToManagerChannel with HasCacheBlockAddress](
 | 
						|
      in: DecoupledIO[LogicalNetworkIO[T]],
 | 
						|
      clientId: Int,
 | 
						|
      nBanks: Int,
 | 
						|
      addrConvert: UInt => UInt): DecoupledIO[LogicalNetworkIO[T]] = {
 | 
						|
    val out: DecoupledIO[LogicalNetworkIO[T]] = apply(in, clientId, false)
 | 
						|
    out.bits.header.dst := addrConvert(in.bits.payload.addr_block)
 | 
						|
    out
 | 
						|
  }
 | 
						|
 | 
						|
  def apply[T <: ClientToManagerChannel with HasCacheBlockAddress : ClassTag](
 | 
						|
      in: DecoupledIO[T],
 | 
						|
      clientId: Int,
 | 
						|
      addrConvert: UInt => UInt): DecoupledIO[LogicalNetworkIO[T]] = {
 | 
						|
    val out = new DecoupledIO(new LogicalNetworkIO(in.bits.clone)).asDirectionless
 | 
						|
    out.bits.payload := in.bits
 | 
						|
    out.bits.header.src := UInt(clientId)
 | 
						|
    out.bits.header.dst := addrConvert(in.bits.addr_block)
 | 
						|
    out.valid := in.valid
 | 
						|
    in.ready := out.ready
 | 
						|
    out
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class TileLinkNetworkPort(clientId: Int, addrConvert: UInt => UInt) extends TLModule {
 | 
						|
  val io = new Bundle {
 | 
						|
    val client = new HeaderlessTileLinkIO().flip
 | 
						|
    val network = new TileLinkIO
 | 
						|
  }
 | 
						|
 | 
						|
  val finisher = Module(new FinishUnit(clientId))
 | 
						|
  finisher.io.grant <> io.network.grant
 | 
						|
  io.network.finish <> finisher.io.finish
 | 
						|
 | 
						|
  val acq_with_header = TileLinkHeaderOverwriter(io.client.acquire, clientId, addrConvert)
 | 
						|
  val rel_with_header = TileLinkHeaderOverwriter(io.client.release, clientId, addrConvert)
 | 
						|
  val prb_without_header = DecoupledLogicalNetworkIOUnwrapper(io.network.probe)
 | 
						|
  val gnt_without_header = finisher.io.refill
 | 
						|
 | 
						|
  io.network.acquire.bits := acq_with_header.bits
 | 
						|
  io.network.acquire.valid := acq_with_header.valid && finisher.io.ready
 | 
						|
  acq_with_header.ready := io.network.acquire.ready && finisher.io.ready
 | 
						|
  io.network.release <> rel_with_header
 | 
						|
  io.client.probe <> prb_without_header
 | 
						|
  io.client.grant <> gnt_without_header
 | 
						|
}
 | 
						|
 | 
						|
object TileLinkNetworkPort {
 | 
						|
  def apply[T <: Data](
 | 
						|
      client: HeaderlessTileLinkIO,
 | 
						|
      clientId: Int = 0,
 | 
						|
      addrConvert: UInt => UInt = u => UInt(0))(implicit p: Parameters): TileLinkIO = {
 | 
						|
    val port = Module(new TileLinkNetworkPort(clientId, addrConvert))(p)
 | 
						|
    port.io.client <> client
 | 
						|
    port.io.network
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class TileLinkEnqueuer(depths: (Int, Int, Int, Int, Int)) extends Module {
 | 
						|
  val io = new Bundle {
 | 
						|
    val client = new TileLinkIO().flip
 | 
						|
    val manager = new TileLinkIO
 | 
						|
  }
 | 
						|
  io.manager.acquire <> (if(depths._1 > 0) Queue(io.client.acquire, depths._1) else io.client.acquire)
 | 
						|
  io.client.probe    <> (if(depths._2 > 0) Queue(io.manager.probe, depths._2) else io.manager.probe)
 | 
						|
  io.manager.release <> (if(depths._3 > 0) Queue(io.client.release, depths._3) else io.client.release)
 | 
						|
  io.client.grant    <> (if(depths._4 > 0) Queue(io.manager.grant, depths._4) else io.manager.grant)
 | 
						|
  io.manager.finish  <> (if(depths._5 > 0) Queue(io.client.finish, depths._5) else io.client.finish)
 | 
						|
}
 | 
						|
 | 
						|
object TileLinkEnqueuer {
 | 
						|
  def apply(in: TileLinkIO, depths: (Int, Int, Int, Int, Int))(p: Parameters): TileLinkIO = {
 | 
						|
    val t = Module(new TileLinkEnqueuer(depths))(p)
 | 
						|
    t.io.client <> in
 | 
						|
    t.io.manager
 | 
						|
  }
 | 
						|
  def apply(in: TileLinkIO, depth: Int)(p: Parameters): TileLinkIO = {
 | 
						|
    apply(in, (depth, depth, depth, depth, depth))(p)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
abstract trait HasArbiterTypes {
 | 
						|
  type ManagerSourcedWithId = ManagerToClientChannel with HasClientTransactionId
 | 
						|
  type ClientSourcedWithId = ClientToManagerChannel with HasClientTransactionId
 | 
						|
  type ClientSourcedWithIdAndData = ClientToManagerChannel with 
 | 
						|
                                      HasClientTransactionId with 
 | 
						|
                                      HasTileLinkData
 | 
						|
}
 | 
						|
 | 
						|
// Utility functions for constructing TileLinkIO arbiters
 | 
						|
trait TileLinkArbiterLike extends HasArbiterTypes with TileLinkParameters{
 | 
						|
  val arbN: Int
 | 
						|
  // These are filled in depending on whether the arbiter mucks with the 
 | 
						|
  // client ids and then needs to revert them on the way back
 | 
						|
  def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int): Bits
 | 
						|
  def managerSourcedClientXactId(in: ManagerSourcedWithId): Bits
 | 
						|
  def arbIdx(in: ManagerSourcedWithId): UInt
 | 
						|
 | 
						|
  def hookupClientSource[M <: ClientSourcedWithIdAndData : ClassTag](
 | 
						|
      clts: Seq[DecoupledIO[LogicalNetworkIO[M]]],
 | 
						|
      mngr: DecoupledIO[LogicalNetworkIO[M]]) {
 | 
						|
    def hasData(m: LogicalNetworkIO[M]) = m.payload.hasMultibeatData()
 | 
						|
    val arb = Module(new LockingRRArbiter(mngr.bits.clone, arbN, 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
 | 
						|
    }}
 | 
						|
    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, 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
 | 
						|
  }
 | 
						|
 | 
						|
  def hookupManagerSourceWithHeader[M <: ManagerToClientChannel](
 | 
						|
      clts: Seq[DecoupledIO[LogicalNetworkIO[M]]], 
 | 
						|
      mngr: DecoupledIO[LogicalNetworkIO[M]]) {
 | 
						|
    mngr.ready := Bool(false)
 | 
						|
    for (i <- 0 until arbN) {
 | 
						|
      clts(i).valid := Bool(false)
 | 
						|
      when (mngr.bits.header.dst === UInt(i)) {
 | 
						|
        clts(i).valid := mngr.valid
 | 
						|
        mngr.ready := clts(i).ready
 | 
						|
      }
 | 
						|
      clts(i).bits := mngr.bits
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  def hookupManagerSourceWithId[M <: ManagerSourcedWithId](
 | 
						|
      clts: Seq[DecoupledIO[LogicalNetworkIO[M]]], 
 | 
						|
      mngr: DecoupledIO[LogicalNetworkIO[M]]) {
 | 
						|
    mngr.ready := Bool(false)
 | 
						|
    for (i <- 0 until arbN) {
 | 
						|
      clts(i).valid := Bool(false)
 | 
						|
      when (arbIdx(mngr.bits.payload) === UInt(i)) {
 | 
						|
        clts(i).valid := mngr.valid
 | 
						|
        mngr.ready := clts(i).ready
 | 
						|
      }
 | 
						|
      clts(i).bits := mngr.bits
 | 
						|
      clts(i).bits.payload.client_xact_id := managerSourcedClientXactId(mngr.bits.payload)
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  def hookupManagerSourceHeaderlessWithId[M <: ManagerSourcedWithId](
 | 
						|
      clts: Seq[DecoupledIO[M]], 
 | 
						|
      mngr: DecoupledIO[M]) {
 | 
						|
    mngr.ready := Bool(false)
 | 
						|
    for (i <- 0 until arbN) {
 | 
						|
      clts(i).valid := Bool(false)
 | 
						|
      when (arbIdx(mngr.bits) === UInt(i)) {
 | 
						|
        clts(i).valid := mngr.valid
 | 
						|
        mngr.ready := clts(i).ready
 | 
						|
      }
 | 
						|
      clts(i).bits := mngr.bits
 | 
						|
      clts(i).bits.client_xact_id := managerSourcedClientXactId(mngr.bits)
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  def hookupManagerSourceBroadcast[M <: Data](
 | 
						|
      clts: Seq[DecoupledIO[M]], 
 | 
						|
      mngr: DecoupledIO[M]) {
 | 
						|
    clts.map{ _.valid := mngr.valid }
 | 
						|
    clts.map{ _.bits := mngr.bits }
 | 
						|
    mngr.ready := clts.map(_.ready).reduce(_&&_)
 | 
						|
  }
 | 
						|
 | 
						|
  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
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
abstract class UncachedTileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike {
 | 
						|
  val io = new Bundle {
 | 
						|
    val in = Vec.fill(arbN){new UncachedTileLinkIO}.flip
 | 
						|
    val out = new UncachedTileLinkIO
 | 
						|
  }
 | 
						|
  hookupClientSource(io.in.map(_.acquire), io.out.acquire)
 | 
						|
  hookupFinish(io.in.map(_.finish), io.out.finish)
 | 
						|
  hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant)
 | 
						|
}
 | 
						|
 | 
						|
abstract class TileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike {
 | 
						|
  val io = new Bundle {
 | 
						|
    val in = Vec.fill(arbN){new TileLinkIO}.flip
 | 
						|
    val out = new TileLinkIO
 | 
						|
  }
 | 
						|
  hookupClientSource(io.in.map(_.acquire), io.out.acquire)
 | 
						|
  hookupClientSource(io.in.map(_.release), io.out.release)
 | 
						|
  hookupFinish(io.in.map(_.finish), io.out.finish)
 | 
						|
  hookupManagerSourceBroadcast(io.in.map(_.probe), io.out.probe)
 | 
						|
  hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant)
 | 
						|
}
 | 
						|
 | 
						|
class HeaderlessUncachedTileLinkIOArbiter(val arbN: Int) extends Module
 | 
						|
    with TileLinkArbiterLike
 | 
						|
    with AppendsArbiterId {
 | 
						|
  val io = new Bundle {
 | 
						|
    val in = Vec.fill(arbN){new HeaderlessUncachedTileLinkIO}.flip
 | 
						|
    val out = new HeaderlessUncachedTileLinkIO
 | 
						|
  }
 | 
						|
  hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire)
 | 
						|
  hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant)
 | 
						|
}
 | 
						|
 | 
						|
class HeaderlessTileLinkIOArbiter(val arbN: Int) extends Module
 | 
						|
    with TileLinkArbiterLike
 | 
						|
    with AppendsArbiterId {
 | 
						|
  val io = new Bundle {
 | 
						|
    val in = Vec.fill(arbN){new HeaderlessTileLinkIO}.flip
 | 
						|
    val out = new HeaderlessTileLinkIO
 | 
						|
  }
 | 
						|
  hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire)
 | 
						|
  hookupClientSourceHeaderless(io.in.map(_.release), io.out.release)
 | 
						|
  hookupManagerSourceBroadcast(io.in.map(_.probe), io.out.probe)
 | 
						|
  hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant)
 | 
						|
}
 | 
						|
 | 
						|
// Appends the port index of the arbiter to the client_xact_id
 | 
						|
trait AppendsArbiterId extends TileLinkArbiterLike {
 | 
						|
  def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) =
 | 
						|
    Cat(in.client_xact_id, UInt(id, log2Up(arbN)))
 | 
						|
  def managerSourcedClientXactId(in: ManagerSourcedWithId) = 
 | 
						|
    in.client_xact_id >> UInt(log2Up(arbN))
 | 
						|
  def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id(log2Up(arbN)-1,0).toUInt
 | 
						|
}
 | 
						|
 | 
						|
// Uses the client_xact_id as is (assumes it has been set to port index)
 | 
						|
trait PassesId extends TileLinkArbiterLike {
 | 
						|
  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
 | 
						|
}
 | 
						|
 | 
						|
// Overwrites some default client_xact_id with the port idx
 | 
						|
trait UsesNewId extends TileLinkArbiterLike {
 | 
						|
  def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = UInt(id, log2Up(arbN))
 | 
						|
  def managerSourcedClientXactId(in: ManagerSourcedWithId) = UInt(0)
 | 
						|
  def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id
 | 
						|
}
 | 
						|
 | 
						|
// 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
 |