axi4: diplomacy capable AXI4
This commit is contained in:
parent
dcb9383568
commit
b29d34038e
68
src/main/scala/uncore/axi4/Bundles.scala
Normal file
68
src/main/scala/uncore/axi4/Bundles.scala
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.axi4
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import chisel3.util.Irrevocable
|
||||||
|
import util.GenericParameterizedBundle
|
||||||
|
|
||||||
|
abstract class AXI4BundleBase(params: AXI4BundleParameters) extends GenericParameterizedBundle(params)
|
||||||
|
|
||||||
|
abstract class AXI4BundleA(params: AXI4BundleParameters) extends AXI4BundleBase(params)
|
||||||
|
{
|
||||||
|
val id = UInt(width = params.idBits)
|
||||||
|
val addr = UInt(width = params.addrBits)
|
||||||
|
val len = UInt(width = params.lenBits) // number of beats - 1
|
||||||
|
val size = UInt(width = params.sizeBits) // bytes in beat = 2^size
|
||||||
|
val burst = UInt(width = params.burstBits)
|
||||||
|
val lock = UInt(width = params.lockBits)
|
||||||
|
val cache = UInt(width = params.cacheBits)
|
||||||
|
val prot = UInt(width = params.protBits)
|
||||||
|
val qos = UInt(width = params.qosBits) // 0=no QoS, bigger = higher priority
|
||||||
|
// val region = UInt(width = 4) // optional
|
||||||
|
}
|
||||||
|
|
||||||
|
// A non-standard bundle that can be both AR and AW
|
||||||
|
class AXI4BundleARW(params: AXI4BundleParameters) extends AXI4BundleA(params)
|
||||||
|
{
|
||||||
|
val wen = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXI4BundleAW(params: AXI4BundleParameters) extends AXI4BundleA(params)
|
||||||
|
class AXI4BundleAR(params: AXI4BundleParameters) extends AXI4BundleA(params)
|
||||||
|
|
||||||
|
class AXI4BundleW(params: AXI4BundleParameters) extends AXI4BundleBase(params)
|
||||||
|
{
|
||||||
|
// id ... removed in AXI4
|
||||||
|
val data = UInt(width = params.dataBits)
|
||||||
|
val strb = UInt(width = params.dataBits/8)
|
||||||
|
val last = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXI4BundleR(params: AXI4BundleParameters) extends AXI4BundleBase(params)
|
||||||
|
{
|
||||||
|
val id = UInt(width = params.idBits)
|
||||||
|
val data = UInt(width = params.dataBits)
|
||||||
|
val resp = UInt(width = params.respBits)
|
||||||
|
val last = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXI4BundleB(params: AXI4BundleParameters) extends AXI4BundleBase(params)
|
||||||
|
{
|
||||||
|
val id = UInt(width = params.idBits)
|
||||||
|
val resp = UInt(width = params.respBits)
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXI4Bundle(params: AXI4BundleParameters) extends AXI4BundleBase(params)
|
||||||
|
{
|
||||||
|
val aw = Irrevocable(new AXI4BundleAW(params))
|
||||||
|
val w = Irrevocable(new AXI4BundleW (params))
|
||||||
|
val b = Irrevocable(new AXI4BundleB (params)).flip
|
||||||
|
val ar = Irrevocable(new AXI4BundleAR(params))
|
||||||
|
val r = Irrevocable(new AXI4BundleR (params)).flip
|
||||||
|
}
|
||||||
|
|
||||||
|
object AXI4Bundle
|
||||||
|
{
|
||||||
|
def apply(params: AXI4BundleParameters) = new AXI4Bundle(params)
|
||||||
|
}
|
47
src/main/scala/uncore/axi4/Nodes.scala
Normal file
47
src/main/scala/uncore/axi4/Nodes.scala
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.axi4
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import chisel3.internal.sourceinfo.SourceInfo
|
||||||
|
import diplomacy._
|
||||||
|
|
||||||
|
object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4EdgeParameters, AXI4Bundle]
|
||||||
|
{
|
||||||
|
def edgeO(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu)
|
||||||
|
def edgeI(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu)
|
||||||
|
def bundleO(eo: Seq[AXI4EdgeParameters]): Vec[AXI4Bundle] = {
|
||||||
|
require (!eo.isEmpty)
|
||||||
|
Vec(eo.size, AXI4Bundle(eo.map(_.bundle).reduce(_.union(_))))
|
||||||
|
}
|
||||||
|
def bundleI(ei: Seq[AXI4EdgeParameters]): Vec[AXI4Bundle] = {
|
||||||
|
require (!ei.isEmpty)
|
||||||
|
Vec(ei.size, AXI4Bundle(ei.map(_.bundle).reduce(_.union(_)))).flip
|
||||||
|
}
|
||||||
|
|
||||||
|
def colour = "#00ccff" // bluish
|
||||||
|
def connect(bo: => AXI4Bundle, bi: => AXI4Bundle, ei: => AXI4EdgeParameters)(implicit sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||||
|
(None, () => { bi <> bo })
|
||||||
|
}
|
||||||
|
|
||||||
|
override def mixO(pd: AXI4MasterPortParameters, node: OutwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4MasterPortParameters =
|
||||||
|
pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) })
|
||||||
|
override def mixI(pu: AXI4SlavePortParameters, node: InwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4SlavePortParameters =
|
||||||
|
pu.copy(slaves = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) })
|
||||||
|
}
|
||||||
|
|
||||||
|
case class AXI4IdentityNode() extends IdentityNode(AXI4Imp)
|
||||||
|
case class AXI4OutputNode() extends OutputNode(AXI4Imp)
|
||||||
|
case class AXI4InputNode() extends InputNode(AXI4Imp)
|
||||||
|
|
||||||
|
case class AXI4MasterNode(portParams: AXI4MasterPortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||||
|
extends SourceNode(AXI4Imp)(portParams, numPorts)
|
||||||
|
case class AXI4SlaveNode(portParams: AXI4SlavePortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||||
|
extends SinkNode(AXI4Imp)(portParams, numPorts)
|
||||||
|
|
||||||
|
case class AXI4AdapterNode(
|
||||||
|
clientFn: Seq[AXI4MasterPortParameters] => AXI4MasterPortParameters,
|
||||||
|
managerFn: Seq[AXI4SlavePortParameters] => AXI4SlavePortParameters,
|
||||||
|
numMasterPorts: Range.Inclusive = 1 to 1,
|
||||||
|
numSlavePorts: Range.Inclusive = 1 to 1)
|
||||||
|
extends InteriorNode(AXI4Imp)(clientFn, managerFn, numMasterPorts, numSlavePorts)
|
109
src/main/scala/uncore/axi4/Parameters.scala
Normal file
109
src/main/scala/uncore/axi4/Parameters.scala
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.axi4
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import diplomacy._
|
||||||
|
import scala.math.max
|
||||||
|
|
||||||
|
case class AXI4SlaveParameters(
|
||||||
|
address: Seq[AddressSet],
|
||||||
|
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 read responses
|
||||||
|
{
|
||||||
|
address.foreach { a => require (a.finite) }
|
||||||
|
address.combinations(2).foreach { case Seq(x,y) => require (!x.overlaps(y)) }
|
||||||
|
|
||||||
|
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
|
||||||
|
val maxTransfer = max(supportsWrite.max, supportsRead.max)
|
||||||
|
val maxAddress = address.map(_.max).max
|
||||||
|
|
||||||
|
// The device had better not support a transfer larger than it's alignment
|
||||||
|
address.foreach { case a => require (a.alignment >= maxTransfer) }
|
||||||
|
}
|
||||||
|
|
||||||
|
case class AXI4SlavePortParameters(
|
||||||
|
slaves: Seq[AXI4SlaveParameters],
|
||||||
|
beatBytes: Int)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
require (maxTransfer >= beatBytes)
|
||||||
|
// Check that the link can be implemented in AXI4
|
||||||
|
require (maxTransfer <= beatBytes * (1 << AXI4Parameters.lenBits))
|
||||||
|
|
||||||
|
// Require disjoint ranges for addresses
|
||||||
|
slaves.combinations(2).foreach { case Seq(x,y) =>
|
||||||
|
x.address.foreach { a => y.address.foreach { b =>
|
||||||
|
require (!a.overlaps(b))
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case class AXI4MasterParameters(
|
||||||
|
id: IdRange = IdRange(0, 1),
|
||||||
|
nodePath: Seq[BaseNode] = Seq())
|
||||||
|
{
|
||||||
|
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
|
||||||
|
}
|
||||||
|
|
||||||
|
case class AXI4MasterPortParameters(
|
||||||
|
masters: Seq[AXI4MasterParameters])
|
||||||
|
{
|
||||||
|
val endId = masters.map(_.id.end).max
|
||||||
|
|
||||||
|
// Require disjoint ranges for ids
|
||||||
|
masters.combinations(2).foreach { case Seq(x,y) => require (!x.id.overlaps(y.id)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
case class AXI4BundleParameters(
|
||||||
|
addrBits: Int,
|
||||||
|
dataBits: Int,
|
||||||
|
idBits: Int)
|
||||||
|
{
|
||||||
|
require (dataBits >= 8)
|
||||||
|
require (addrBits >= 1)
|
||||||
|
require (idBits >= 1)
|
||||||
|
require (isPow2(dataBits))
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
|
||||||
|
object AXI4BundleParameters
|
||||||
|
{
|
||||||
|
def apply(master: AXI4MasterPortParameters, slave: AXI4SlavePortParameters) =
|
||||||
|
new AXI4BundleParameters(
|
||||||
|
addrBits = log2Up(slave.maxAddress+1),
|
||||||
|
dataBits = slave.beatBytes * 8,
|
||||||
|
idBits = log2Up(master.endId))
|
||||||
|
}
|
||||||
|
|
||||||
|
case class AXI4EdgeParameters(
|
||||||
|
master: AXI4MasterPortParameters,
|
||||||
|
slave: AXI4SlavePortParameters)
|
||||||
|
{
|
||||||
|
val bundle = AXI4BundleParameters(master, slave)
|
||||||
|
}
|
37
src/main/scala/uncore/axi4/Protocol.scala
Normal file
37
src/main/scala/uncore/axi4/Protocol.scala
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.axi4
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import chisel3.util.{Irrevocable, IrrevocableIO}
|
||||||
|
|
||||||
|
object AXI4Parameters
|
||||||
|
{
|
||||||
|
// These are all fixed by the AXI4 standard:
|
||||||
|
val lenBits = 8
|
||||||
|
val sizeBits = 3
|
||||||
|
val burstBits = 2
|
||||||
|
val lockBits = 1
|
||||||
|
val cacheBits = 4
|
||||||
|
val protBits = 3
|
||||||
|
val qosBits = 4
|
||||||
|
val respBits = 2
|
||||||
|
|
||||||
|
val CACHE_RALLOCATE = UInt(8, width = cacheBits)
|
||||||
|
val CACHE_WALLOCATE = UInt(4, width = cacheBits)
|
||||||
|
val CACHE_MODIFIABLE = UInt(2, width = cacheBits)
|
||||||
|
val CACHE_BUFFERABLE = UInt(1, width = cacheBits)
|
||||||
|
|
||||||
|
val PROT_PRIVILEDGED = UInt(1, width = protBits)
|
||||||
|
val PROT_INSECURE = UInt(2, width = protBits)
|
||||||
|
val PROT_INSTRUCTION = UInt(4, width = protBits)
|
||||||
|
|
||||||
|
val BURST_FIXED = UInt(0, width = burstBits)
|
||||||
|
val BURST_INCR = UInt(1, width = burstBits)
|
||||||
|
val BURST_WRAP = UInt(2, width = burstBits)
|
||||||
|
|
||||||
|
val RESP_OKAY = UInt(0, width = respBits)
|
||||||
|
val RESP_EXOKAY = UInt(1, width = respBits)
|
||||||
|
val RESP_SLVERR = UInt(2, width = respBits)
|
||||||
|
val RESP_DECERR = UInt(3, width = respBits)
|
||||||
|
}
|
9
src/main/scala/uncore/axi4/package.scala
Normal file
9
src/main/scala/uncore/axi4/package.scala
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package uncore
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import diplomacy._
|
||||||
|
|
||||||
|
package object axi4
|
||||||
|
{
|
||||||
|
type AXI4OutwardNode = OutwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user