tilelink2: first cut at parameterization
This commit is contained in:
parent
59a2e6a4dc
commit
7328b55abd
41
uncore/src/main/scala/tilelink2/Bases.scala
Normal file
41
uncore/src/main/scala/tilelink2/Bases.scala
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.tilelink2
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
import chisel3.internal.sourceinfo.SourceInfo
|
||||||
|
|
||||||
|
abstract class TLFactory
|
||||||
|
{
|
||||||
|
private val bindings = ListBuffer[(TLBaseNode, Int, TLBaseNode, Int, SourceInfo)]()
|
||||||
|
|
||||||
|
def tl(manager: TLBaseNode, client: TLBaseNode)(implicit sourceInfo: SourceInfo) = {
|
||||||
|
val (i, j) = manager.edge(client)
|
||||||
|
bindings += ((manager, i, client, j, sourceInfo))
|
||||||
|
}
|
||||||
|
|
||||||
|
def module: TLModule
|
||||||
|
|
||||||
|
protected[tilelink2] def instantiate() = {
|
||||||
|
// Find all TLFactory members of self
|
||||||
|
for (m <- getClass.getMethods) {
|
||||||
|
if (m.getParameterTypes.isEmpty &&
|
||||||
|
!java.lang.reflect.Modifier.isStatic(m.getModifiers) &&
|
||||||
|
!(m.getName contains '$') &&
|
||||||
|
classOf[TLFactory].isAssignableFrom(m.getReturnType)) {
|
||||||
|
// ... and force their lazy module members to exist
|
||||||
|
m.invoke(this).asInstanceOf[TLFactory].module
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bindings.foreach { case (x, i, y, j, s) =>
|
||||||
|
x.bundleIn(i).<>(y.bundleOut(j))(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TLModule(factory: TLFactory) extends Module
|
||||||
|
{
|
||||||
|
override def desiredName = factory.getClass.getName.split('.').last
|
||||||
|
factory.instantiate()
|
||||||
|
}
|
77
uncore/src/main/scala/tilelink2/Bundles.scala
Normal file
77
uncore/src/main/scala/tilelink2/Bundles.scala
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.tilelink2
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
abstract class TLBundleBase(val params: TLBundleParameters) extends Bundle
|
||||||
|
{
|
||||||
|
override def cloneType = {
|
||||||
|
try {
|
||||||
|
this.getClass.getConstructors.head.newInstance(params).asInstanceOf[this.type]
|
||||||
|
} catch {
|
||||||
|
case e: java.lang.IllegalArgumentException =>
|
||||||
|
throwException("Unable to use TLBundleBase.cloneType on " +
|
||||||
|
this.getClass + ", probably because " + this.getClass +
|
||||||
|
"() takes more than one argument. Consider overriding " +
|
||||||
|
"cloneType() on " + this.getClass, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLBundleA(params: TLBundleParameters) extends TLBundleBase(params)
|
||||||
|
{
|
||||||
|
val opcode = UInt(width = 3)
|
||||||
|
val param = UInt(width = 3) // amo_opcode || perms(req)
|
||||||
|
val size = UInt(width = params.sizeBits)
|
||||||
|
val source = UInt(width = params.sourceBits) // from
|
||||||
|
val address = UInt(width = params.addressBits) // to
|
||||||
|
val wmask = UInt(width = params.dataBits/8)
|
||||||
|
val data = UInt(width = params.dataBits)
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLBundleB(params: TLBundleParameters) extends TLBundleBase(params)
|
||||||
|
{
|
||||||
|
val opcode = UInt(width = 3)
|
||||||
|
val param = UInt(width = 3) // amo_opcode || perms(req)
|
||||||
|
val size = UInt(width = params.sizeBits)
|
||||||
|
val source = UInt(width = params.sourceBits) // to
|
||||||
|
val address = UInt(width = params.addressBits) // from
|
||||||
|
val wmask = UInt(width = params.dataBits/8)
|
||||||
|
val data = UInt(width = params.dataBits)
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLBundleC(params: TLBundleParameters) extends TLBundleBase(params)
|
||||||
|
{
|
||||||
|
val opcode = UInt(width = 3)
|
||||||
|
val param = UInt(width = 3) // perms(from=>to)
|
||||||
|
val size = UInt(width = params.sizeBits)
|
||||||
|
val address = UInt(width = params.addressBits) // to
|
||||||
|
val data = UInt(width = params.dataBits)
|
||||||
|
val error = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLBundleD(params: TLBundleParameters) extends TLBundleBase(params)
|
||||||
|
{
|
||||||
|
val opcode = UInt(width = 3)
|
||||||
|
val param = UInt(width = 3) // perms(to)
|
||||||
|
val size = UInt(width = params.sizeBits)
|
||||||
|
val source = UInt(width = params.sourceBits) // to
|
||||||
|
val sink = UInt(width = params.sinkBits) // from
|
||||||
|
val data = UInt(width = params.dataBits)
|
||||||
|
val error = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLBundleE(params: TLBundleParameters) extends TLBundleBase(params)
|
||||||
|
{
|
||||||
|
val sink = UInt(width = params.sourceBits) // to
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLBundle(params: TLBundleParameters) extends TLBundleBase(params)
|
||||||
|
{
|
||||||
|
val a = Decoupled(new TLBundleA(params))
|
||||||
|
val b = Decoupled(new TLBundleB(params)).flip
|
||||||
|
val c = Decoupled(new TLBundleC(params))
|
||||||
|
val d = Decoupled(new TLBundleD(params)).flip
|
||||||
|
val e = Decoupled(new TLBundleE(params))
|
||||||
|
}
|
121
uncore/src/main/scala/tilelink2/Nodes.scala
Normal file
121
uncore/src/main/scala/tilelink2/Nodes.scala
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.tilelink2
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
|
class TLBaseNode(
|
||||||
|
private val clientFn: Option[Seq[TLClientPortParameters] => TLClientPortParameters],
|
||||||
|
private val managerFn: Option[Seq[TLManagerPortParameters] => TLManagerPortParameters],
|
||||||
|
private val numClientPorts: Range.Inclusive,
|
||||||
|
private val numManagerPorts: Range.Inclusive)
|
||||||
|
{
|
||||||
|
// At least 0 ports must be supported
|
||||||
|
require (!numClientPorts.isEmpty)
|
||||||
|
require (!numManagerPorts.isEmpty)
|
||||||
|
require (numClientPorts.start >= 0)
|
||||||
|
require (numManagerPorts.start >= 0)
|
||||||
|
|
||||||
|
val noClients = numClientPorts.size == 1 && numClientPorts.contains(0)
|
||||||
|
val noManagers = numManagerPorts.size == 1 && numManagerPorts.contains(0)
|
||||||
|
|
||||||
|
require (noClients || clientFn.isDefined)
|
||||||
|
require (noManagers || managerFn.isDefined)
|
||||||
|
|
||||||
|
private val accClientPorts = ListBuffer[TLBaseNode]()
|
||||||
|
private val accManagerPorts = ListBuffer[TLBaseNode]()
|
||||||
|
private var clientRealized = false
|
||||||
|
private var managerRealized = false
|
||||||
|
|
||||||
|
protected[tilelink2] def edge(x: TLBaseNode) = {
|
||||||
|
require (!noManagers)
|
||||||
|
require (!managerRealized)
|
||||||
|
require (!x.noClients)
|
||||||
|
require (!x.clientRealized)
|
||||||
|
val i = accManagerPorts.size
|
||||||
|
val j = x.accClientPorts.size
|
||||||
|
accManagerPorts += x
|
||||||
|
x.accClientPorts += this
|
||||||
|
(i, j)
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy val clientPorts = { clientRealized = true; require (numClientPorts.contains(accClientPorts.size)); accClientPorts.result() }
|
||||||
|
private lazy val managerPorts = { managerRealized = true; require (numManagerPorts.contains(accManagerPorts.size)); accManagerPorts.result() }
|
||||||
|
private lazy val clientParams : Option[TLClientPortParameters] = clientFn.map(_(managerPorts.map(_.clientParams.get)))
|
||||||
|
private lazy val managerParams : Option[TLManagerPortParameters] = managerFn.map(_(clientPorts.map(_.managerParams.get)))
|
||||||
|
|
||||||
|
lazy val edgesOut = clientPorts.map { n => new TLEdgeOut(clientParams.get, n.managerParams.get) }
|
||||||
|
lazy val edgesIn = managerPorts.map { n => new TLEdgeIn (n.clientParams.get, managerParams.get) }
|
||||||
|
|
||||||
|
lazy val bundleOut = Vec(edgesOut.size, new TLBundle(edgesOut.map(_.bundle).reduce(_.union(_))))
|
||||||
|
lazy val bundleIn = Vec(edgesIn .size, new TLBundle(edgesIn .map(_.bundle).reduce(_.union(_)))).flip
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLClientNode(
|
||||||
|
params: TLClientParameters,
|
||||||
|
numPorts: Range.Inclusive = 1 to 1) extends TLBaseNode(
|
||||||
|
clientFn = Some {case Seq() => TLClientPortParameters(Seq(params))},
|
||||||
|
managerFn = None,
|
||||||
|
numClientPorts = numPorts,
|
||||||
|
numManagerPorts = 0 to 0)
|
||||||
|
{
|
||||||
|
require(numPorts.end >= 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
object TLClientNode
|
||||||
|
{
|
||||||
|
def apply(
|
||||||
|
params: TLClientParameters,
|
||||||
|
numPorts: Range.Inclusive = 1 to 1) = new TLClientNode(params, numPorts)
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLManagerNode(
|
||||||
|
beatBytes: Int,
|
||||||
|
params: TLManagerParameters,
|
||||||
|
numPorts: Range.Inclusive = 1 to 1) extends TLBaseNode(
|
||||||
|
clientFn = None,
|
||||||
|
managerFn = Some {case Seq() => TLManagerPortParameters(Seq(params), beatBytes)},
|
||||||
|
numClientPorts = 0 to 0,
|
||||||
|
numManagerPorts = numPorts)
|
||||||
|
{
|
||||||
|
require(numPorts.end >= 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
object TLManagerNode
|
||||||
|
{
|
||||||
|
def apply(
|
||||||
|
beatBytes: Int,
|
||||||
|
params: TLManagerParameters,
|
||||||
|
numPorts: Range.Inclusive = 1 to 1) = new TLManagerNode(beatBytes, params, numPorts)
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLAdapterNode(
|
||||||
|
clientFn: Seq[TLClientPortParameters] => TLClientPortParameters,
|
||||||
|
managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters,
|
||||||
|
numClientPorts: Range.Inclusive = 1 to 1,
|
||||||
|
numManagerPorts: Range.Inclusive = 1 to 1) extends TLBaseNode(
|
||||||
|
clientFn = Some(clientFn),
|
||||||
|
managerFn = Some(managerFn),
|
||||||
|
numClientPorts = numClientPorts,
|
||||||
|
numManagerPorts = numManagerPorts)
|
||||||
|
|
||||||
|
object TLAdapterNode
|
||||||
|
{
|
||||||
|
def apply(
|
||||||
|
clientFn: Seq[TLClientPortParameters] => TLClientPortParameters,
|
||||||
|
managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters,
|
||||||
|
numClientPorts: Range.Inclusive = 1 to 1,
|
||||||
|
numManagerPorts: Range.Inclusive = 1 to 1) = new TLAdapterNode(clientFn, managerFn, numClientPorts, numManagerPorts)
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLIDNode extends TLBaseNode(
|
||||||
|
clientFn = Some({case Seq(x) => x}),
|
||||||
|
managerFn = Some({case Seq(x) => x}),
|
||||||
|
numClientPorts = 1 to 1,
|
||||||
|
numManagerPorts = 1 to 1)
|
||||||
|
|
||||||
|
object TLIDNode
|
||||||
|
{
|
||||||
|
def apply() = new TLIDNode()
|
||||||
|
}
|
51
uncore/src/main/scala/tilelink2/Operations.scala
Normal file
51
uncore/src/main/scala/tilelink2/Operations.scala
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.tilelink2
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
class TLEdgeOut(
|
||||||
|
client: TLClientPortParameters,
|
||||||
|
manager: TLManagerPortParameters)
|
||||||
|
extends TLEdgeParameters(client, manager)
|
||||||
|
{
|
||||||
|
// Transfers
|
||||||
|
def Acquire(x: Int) = () // A
|
||||||
|
def Release(x: Int) = () // C
|
||||||
|
def ReleaseData(x: Int) = () // C
|
||||||
|
def ProbeAck(x: Int) = () // C
|
||||||
|
def ProbeDataAck(x: Int) = () // C
|
||||||
|
def GrantAck(x: Int) = () // E
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
def Get(x: Int) = () // A
|
||||||
|
def Put(x: Int) = () // A
|
||||||
|
def Atomic(x: Int) = () // A
|
||||||
|
def AccessAck(x: Int) = () // C
|
||||||
|
def AccessDataAck(x: Int) = () // C
|
||||||
|
|
||||||
|
def Hint(x: Int) = () // A
|
||||||
|
def HintAck(x: Int) = () // C
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLEdgeIn(
|
||||||
|
client: TLClientPortParameters,
|
||||||
|
manager: TLManagerPortParameters)
|
||||||
|
extends TLEdgeParameters(client, manager)
|
||||||
|
{
|
||||||
|
// Transfers
|
||||||
|
def Probe(x: Int) = () // B
|
||||||
|
def Grant(x: Int) = () // D
|
||||||
|
def GrantData(x: Int) = () // D
|
||||||
|
def ReleaseAck(x: Int) = () // D
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
def Get(x: Int) = () // B
|
||||||
|
def Put(x: Int) = () // B
|
||||||
|
def Atomic(x: Int) = () // B
|
||||||
|
def AccessAck(x: Int) = () // D
|
||||||
|
def AccessDataAck(x: Int) = () // D
|
||||||
|
|
||||||
|
def Hint(x: Int) = () // B
|
||||||
|
def HintAck(x: Int) = () // D
|
||||||
|
}
|
205
uncore/src/main/scala/tilelink2/Parameters.scala
Normal file
205
uncore/src/main/scala/tilelink2/Parameters.scala
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.tilelink2
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import scala.math.max
|
||||||
|
|
||||||
|
/** Options for memory regions */
|
||||||
|
object RegionType {
|
||||||
|
sealed trait T
|
||||||
|
case object CACHED extends T
|
||||||
|
case object TRACKED extends T
|
||||||
|
case object UNCACHED extends T
|
||||||
|
case object UNCACHEABLE extends T
|
||||||
|
val cases = Seq(CACHED, TRACKED, UNCACHED, UNCACHEABLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A non-empty half-open range; [start, end)
|
||||||
|
case class IdRange(start: Int, end: Int)
|
||||||
|
{
|
||||||
|
require (start >= 0)
|
||||||
|
require (end >= 0)
|
||||||
|
require (start < end) // not empty
|
||||||
|
|
||||||
|
// This is a strict partial ordering
|
||||||
|
def <(x: IdRange) = end <= x.start
|
||||||
|
def >(x: IdRange) = x < this
|
||||||
|
|
||||||
|
def overlaps(x: IdRange) = start < x.end && x.start < end
|
||||||
|
def contains(x: IdRange) = start <= x.start && x.end <= end
|
||||||
|
// contains => overlaps (because empty is forbidden)
|
||||||
|
|
||||||
|
def contains(x: Int) = start <= x && x < end
|
||||||
|
def contains(x: UInt) = UInt(start) <= x && x < UInt(end) // !!! special-case =
|
||||||
|
|
||||||
|
def shift(x: Int) = IdRange(start+x, end+x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An potentially empty inclusive range of 2-powers [min, max]
|
||||||
|
case class TransferSizes(min: Int, max: Int)
|
||||||
|
{
|
||||||
|
def this(x: Int) = this(x, x)
|
||||||
|
|
||||||
|
require (min <= max)
|
||||||
|
require (min != 0 || max == 0)
|
||||||
|
require (max == 0 || isPow2(max))
|
||||||
|
require (min == 0 || isPow2(min))
|
||||||
|
|
||||||
|
def none = min == 0
|
||||||
|
def contains(x: Int) = isPow2(x) && min <= x && x <= max
|
||||||
|
def containsLg(x: Int) = contains(1 << x)
|
||||||
|
def containsLg(x: UInt) = if (none) Bool(false) else { UInt(log2Ceil(min)) <= x && x <= UInt(log2Ceil(max)) } // !!! special-case =
|
||||||
|
|
||||||
|
def contains(x: TransferSizes) = x.none || (min <= x.min && x.max <= max)
|
||||||
|
|
||||||
|
def intersect(x: TransferSizes) =
|
||||||
|
if (x.max < min || min < x.max) TransferSizes.none
|
||||||
|
else TransferSizes(scala.math.max(min, x.min), scala.math.min(max, x.max))
|
||||||
|
}
|
||||||
|
|
||||||
|
object TransferSizes {
|
||||||
|
def apply(x: Int) = new TransferSizes(x)
|
||||||
|
val none = new TransferSizes(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddressSets specify the mask of bits consumed by the manager
|
||||||
|
// The base address used by the crossbar for routing
|
||||||
|
case class AddressSet(mask: BigInt, base: Option[BigInt] = None)
|
||||||
|
{
|
||||||
|
// Forbid empty sets
|
||||||
|
require (base == None || (base.get & mask) == 0)
|
||||||
|
|
||||||
|
def contains(x: BigInt) = ((x ^ base.get) & ~mask) == 0
|
||||||
|
def contains(x: UInt) = ((x ^ UInt(base.get)) & UInt(~mask)) === UInt(0)
|
||||||
|
|
||||||
|
// overlap iff bitwise: both care (~mask0 & ~mask1) => both equal (base0=base1)
|
||||||
|
// if base = None, it will be auto-assigned and thus not overlap anything
|
||||||
|
def overlaps(x: AddressSet) = (base, x.base) match {
|
||||||
|
case (Some(tbase), Some(xbase)) => (~(mask | x.mask) & (tbase ^ xbase)) == 0
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
// contains iff bitwise: x.mask => mask && contains(x.base)
|
||||||
|
def contains(x: AddressSet) = ((x.mask | (base.get ^ x.base.get)) & ~mask) == 0
|
||||||
|
// 1 less than the number of bytes to which the manager should be aligned
|
||||||
|
def alignment1 = ((mask + 1) & ~mask) - 1
|
||||||
|
def max = base.get | mask
|
||||||
|
}
|
||||||
|
|
||||||
|
case class TLManagerParameters(
|
||||||
|
address: Seq[AddressSet],
|
||||||
|
sinkId: IdRange = IdRange(0, 1),
|
||||||
|
regionType: RegionType.T = RegionType.UNCACHEABLE,
|
||||||
|
// Supports both Acquire+Release of these sizes
|
||||||
|
supportsAcquire: TransferSizes = TransferSizes.none,
|
||||||
|
supportsAtomic: TransferSizes = TransferSizes.none,
|
||||||
|
supportsGet: TransferSizes = TransferSizes.none,
|
||||||
|
supportsPutFull: TransferSizes = TransferSizes.none,
|
||||||
|
supportsPutPartial: TransferSizes = TransferSizes.none,
|
||||||
|
supportsHints: Boolean = false,
|
||||||
|
// If fifoId=Some, all messages sent to the same fifoId are delivered in FIFO order
|
||||||
|
fifoId: Option[Int] = None)
|
||||||
|
{
|
||||||
|
address.combinations(2).foreach({ case Seq(x,y) =>
|
||||||
|
require (!x.overlaps(y))
|
||||||
|
})
|
||||||
|
address.foreach({ case a =>
|
||||||
|
require (supportsAcquire.none || a.alignment1 >= supportsAcquire.max-1)
|
||||||
|
})
|
||||||
|
|
||||||
|
val maxTransfer = List(
|
||||||
|
supportsAcquire.max,
|
||||||
|
supportsAtomic.max,
|
||||||
|
supportsGet.max,
|
||||||
|
supportsPutFull.max,
|
||||||
|
supportsPutPartial.max).max
|
||||||
|
}
|
||||||
|
|
||||||
|
case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes: Int)
|
||||||
|
{
|
||||||
|
require (isPow2(beatBytes))
|
||||||
|
|
||||||
|
// Require disjoint ranges for Ids and addresses
|
||||||
|
managers.combinations(2).foreach({ case Seq(x,y) =>
|
||||||
|
require (!x.sinkId.overlaps(y.sinkId))
|
||||||
|
x.address.foreach({ a => y.address.foreach({ b =>
|
||||||
|
require (!a.overlaps(b))
|
||||||
|
})})
|
||||||
|
})
|
||||||
|
|
||||||
|
def endSinkId = managers.map(_.sinkId.end).max
|
||||||
|
def maxAddress = managers.map(_.address.map(_.max).max).max
|
||||||
|
def maxGet = managers.map(_.supportsGet.max).max
|
||||||
|
def maxTransfer = managers.map(_.maxTransfer).max
|
||||||
|
|
||||||
|
// These return Option[TLSinkParameters] for your convenience
|
||||||
|
def findById(x: Int) = managers.find(_.sinkId.contains(x))
|
||||||
|
def findByAddress(x: BigInt) = managers.find(_.address.exists(_.contains(x)))
|
||||||
|
|
||||||
|
//def buildCacheInfo(): UInt => Chilse(RegionType) // UInt = address, not sink_id
|
||||||
|
//def buildAtomicInfo(): UInt => Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
case class TLClientParameters(
|
||||||
|
sourceId: IdRange = IdRange(0,1),
|
||||||
|
// Supports both Probe+Grant of these sizes
|
||||||
|
supportsProbe: TransferSizes = TransferSizes.none,
|
||||||
|
supportsAtomics: TransferSizes = TransferSizes.none,
|
||||||
|
supportsGet: TransferSizes = TransferSizes.none,
|
||||||
|
supportsPutFull: TransferSizes = TransferSizes.none,
|
||||||
|
supportsPutPartial: TransferSizes = TransferSizes.none,
|
||||||
|
supportsHints: Boolean = false)
|
||||||
|
{
|
||||||
|
val maxTransfer = List(
|
||||||
|
supportsProbe.max,
|
||||||
|
supportsAtomics.max,
|
||||||
|
supportsGet.max,
|
||||||
|
supportsPutFull.max,
|
||||||
|
supportsPutPartial.max).max
|
||||||
|
}
|
||||||
|
|
||||||
|
case class TLClientPortParameters(clients: Seq[TLClientParameters]) {
|
||||||
|
def endSourceId = clients.map(_.sourceId.end).max
|
||||||
|
def maxTransfer = clients.map(_.maxTransfer).max
|
||||||
|
// def nSources: Int = sourceView.map(_.sourceIds.count).sum
|
||||||
|
// def nCaches: Int = sourceView.map(s => if(s.supportsProbe) 1 else 0).sum
|
||||||
|
//def makeSourceToCache() = ...
|
||||||
|
//def makeCacheToStartSource() = ...
|
||||||
|
}
|
||||||
|
|
||||||
|
case class TLBundleParameters(
|
||||||
|
addressBits: Int,
|
||||||
|
dataBits: Int,
|
||||||
|
sourceBits: Int,
|
||||||
|
sinkBits: Int,
|
||||||
|
sizeBits: Int)
|
||||||
|
{
|
||||||
|
// Chisel has issues with 0-width wires
|
||||||
|
require (addressBits >= 1)
|
||||||
|
require (dataBits >= 1)
|
||||||
|
require (sourceBits >= 1)
|
||||||
|
require (sinkBits >= 1)
|
||||||
|
require (sizeBits >= 1)
|
||||||
|
require (isPow2(dataBits))
|
||||||
|
|
||||||
|
def union(x: TLBundleParameters) =
|
||||||
|
TLBundleParameters(
|
||||||
|
max(addressBits, x.addressBits),
|
||||||
|
max(dataBits, x.dataBits),
|
||||||
|
max(sourceBits, x.sourceBits),
|
||||||
|
max(sinkBits, x.sinkBits),
|
||||||
|
max(sizeBits, x.sizeBits))
|
||||||
|
}
|
||||||
|
|
||||||
|
case class TLEdgeParameters(
|
||||||
|
client: TLClientPortParameters,
|
||||||
|
manager: TLManagerPortParameters)
|
||||||
|
{
|
||||||
|
val bundle = TLBundleParameters(
|
||||||
|
addressBits = log2Up(manager.maxAddress + 1) - log2Up(manager.beatBytes),
|
||||||
|
dataBits = manager.beatBytes * 8,
|
||||||
|
sourceBits = log2Up(client.endSourceId),
|
||||||
|
sinkBits = log2Up(manager.endSinkId),
|
||||||
|
sizeBits = log2Up(log2Up(max(client.maxTransfer, manager.maxTransfer))+1))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user