1
0
rocket-chip/src/main/scala/uncore/axi4/Parameters.scala

135 lines
4.6 KiB
Scala
Raw Normal View History

// See LICENSE.SiFive for license details.
2016-10-05 02:52:15 +02:00
package uncore.axi4
import Chisel._
import config._
2016-10-05 02:52:15 +02:00
import diplomacy._
import scala.math.max
case class AXI4SlaveParameters(
address: Seq[AddressSet],
2017-03-01 09:03:01 +01:00
resources: Seq[Resource] = Nil,
2016-10-05 02:52:15 +02:00
regionType: RegionType.T = RegionType.GET_EFFECTS,
executable: Boolean = false, // processor can execute from this memory
nodePath: Seq[BaseNode] = Seq(),
supportsWrite: TransferSizes = TransferSizes.none,
supportsRead: TransferSizes = TransferSizes.none,
interleavedId: Option[Int] = None) // The device will not interleave responses (R+B)
2016-10-05 02:52:15 +02:00
{
address.foreach { a => require (a.finite) }
2017-04-25 20:09:09 +02:00
address.combinations(2).foreach { case Seq(x,y) => require (!x.overlaps(y), s"$x and $y overlap") }
2016-10-05 02:52:15 +02:00
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
val maxTransfer = max(supportsWrite.max, supportsRead.max)
val maxAddress = address.map(_.max).max
val minAlignment = address.map(_.alignment).min
2016-10-05 02:52:15 +02:00
2017-04-25 20:09:09 +02:00
// The device had better not support a transfer larger than its alignment
require (minAlignment >= maxTransfer,
s"minAlignment ($minAlignment) must be >= maxTransfer ($maxTransfer)")
2016-10-05 02:52:15 +02:00
}
case class AXI4SlavePortParameters(
2017-01-24 02:54:27 +01:00
slaves: Seq[AXI4SlaveParameters],
beatBytes: Int,
minLatency: Int = 1)
2016-10-05 02:52:15 +02:00
{
require (!slaves.isEmpty)
require (isPow2(beatBytes))
val maxTransfer = slaves.map(_.maxTransfer).max
val maxAddress = slaves.map(_.maxAddress).max
// Check the link is not pointlessly wide
2017-04-25 20:09:09 +02:00
require (maxTransfer >= beatBytes,
s"maxTransfer ($maxTransfer) should not be smaller than bus width ($beatBytes)")
2016-10-05 02:52:15 +02:00
// Check that the link can be implemented in AXI4
2017-04-25 20:09:09 +02:00
val limit = beatBytes * (1 << AXI4Parameters.lenBits)
require (maxTransfer <= limit,
s"maxTransfer ($maxTransfer) cannot be larger than $limit on a $beatBytes*8 width bus")
2016-10-05 02:52:15 +02:00
2016-10-12 07:36:40 +02:00
lazy val routingMask = AddressDecoder(slaves.map(_.address))
def findSafe(address: UInt) = Vec(slaves.map(_.address.map(_.contains(address)).reduce(_ || _)))
def findFast(address: UInt) = Vec(slaves.map(_.address.map(_.widen(~routingMask)).distinct.map(_.contains(address)).reduce(_ || _)))
2016-10-05 02:52:15 +02:00
// Require disjoint ranges for addresses
slaves.combinations(2).foreach { case Seq(x,y) =>
x.address.foreach { a => y.address.foreach { b =>
2017-04-25 20:09:09 +02:00
require (!a.overlaps(b), s"$a and $b overlap")
2016-10-05 02:52:15 +02:00
} }
}
}
case class AXI4MasterParameters(
id: IdRange = IdRange(0, 1),
aligned: Boolean = false,
maxFlight: Option[Int] = None, // None = infinite, else is a per-ID cap
nodePath: Seq[BaseNode] = Seq())
2016-10-05 02:52:15 +02:00
{
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
maxFlight.foreach { m => require (m >= 0) }
2016-10-05 02:52:15 +02:00
}
case class AXI4MasterPortParameters(
masters: Seq[AXI4MasterParameters],
userBits: Int = 0)
2016-10-05 02:52:15 +02:00
{
val endId = masters.map(_.id.end).max
require (userBits >= 0)
2016-10-05 02:52:15 +02:00
// Require disjoint ranges for ids
IdRange.overlaps(masters.map(_.id)).foreach { case (x, y) =>
require (!x.overlaps(y), s"AXI4MasterParameters.id $x and $y overlap")
}
2016-10-05 02:52:15 +02:00
}
case class AXI4BundleParameters(
addrBits: Int,
dataBits: Int,
idBits: Int,
userBits: Int)
2016-10-05 02:52:15 +02:00
{
2017-04-25 20:09:09 +02:00
require (dataBits >= 8, s"AXI4 data bits must be >= 8 (got $dataBits)")
require (addrBits >= 1, s"AXI4 addr bits must be >= 1 (got $addrBits)")
require (idBits >= 1, s"AXI4 id bits must be >= 1 (got $idBits)")
require (isPow2(dataBits), s"AXI4 data bits must be pow2 (got $dataBits)")
2016-10-05 02:52:15 +02:00
// Bring the globals into scope
val lenBits = AXI4Parameters.lenBits
val sizeBits = AXI4Parameters.sizeBits
val burstBits = AXI4Parameters.burstBits
val lockBits = AXI4Parameters.lockBits
val cacheBits = AXI4Parameters.cacheBits
val protBits = AXI4Parameters.protBits
val qosBits = AXI4Parameters.qosBits
val respBits = AXI4Parameters.respBits
def union(x: AXI4BundleParameters) =
AXI4BundleParameters(
max(addrBits, x.addrBits),
max(dataBits, x.dataBits),
max(idBits, x.idBits),
max(userBits, x.userBits))
2016-10-05 02:52:15 +02:00
}
object AXI4BundleParameters
{
val emptyBundleParams = AXI4BundleParameters(addrBits=1, dataBits=8, idBits=1, userBits=0)
2017-01-20 03:36:39 +01:00
def union(x: Seq[AXI4BundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y))
2016-10-05 02:52:15 +02:00
def apply(master: AXI4MasterPortParameters, slave: AXI4SlavePortParameters) =
new AXI4BundleParameters(
addrBits = log2Up(slave.maxAddress+1),
dataBits = slave.beatBytes * 8,
idBits = log2Up(master.endId),
userBits = master.userBits)
2016-10-05 02:52:15 +02:00
}
case class AXI4EdgeParameters(
master: AXI4MasterPortParameters,
slave: AXI4SlavePortParameters)
{
val bundle = AXI4BundleParameters(master, slave)
}