Skip to content

Commit

Permalink
axi4: convert wcorrupt into a standard user-bits field
Browse files Browse the repository at this point in the history
  • Loading branch information
terpstra committed Mar 13, 2020
1 parent 185a1e7 commit 4cb3766
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 33 deletions.
8 changes: 4 additions & 4 deletions src/main/scala/amba/axi4/Bundles.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ abstract class AXI4BundleA(params: AXI4BundleParameters) extends AXI4BundleBase(
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 user = BundleMap(params.requestFields)
val user = BundleMap(params.requestFields.filter(_.key.isControl))
val echo = BundleMap(params.echoFields)
// val region = UInt(width = 4) // optional

Expand All @@ -46,15 +46,15 @@ class AXI4BundleW(params: AXI4BundleParameters) extends AXI4BundleBase(params)
val data = UInt(width = params.dataBits)
val strb = UInt(width = params.dataBits/8)
val last = Bool()
val corrupt = if (params.wcorrupt) Some(Bool()) else None
val user = BundleMap(params.requestFields.filter(_.key.isData))
}

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 user = BundleMap(params.responseFields)
val user = BundleMap(params.responseFields) // control and data
val echo = BundleMap(params.echoFields)
val last = Bool()
}
Expand All @@ -63,7 +63,7 @@ class AXI4BundleB(params: AXI4BundleParameters) extends AXI4BundleBase(params)
{
val id = UInt(width = params.idBits)
val resp = UInt(width = params.respBits)
val user = BundleMap(params.responseFields)
val user = BundleMap(params.responseFields.filter(_.key.isControl))
val echo = BundleMap(params.echoFields)
}

Expand Down
12 changes: 4 additions & 8 deletions src/main/scala/amba/axi4/Parameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ case class AXI4SlaveParameters(
case class AXI4SlavePortParameters(
slaves: Seq[AXI4SlaveParameters],
beatBytes: Int,
wcorrupt: Boolean = false,
minLatency: Int = 1,
responseFields: Seq[BundleFieldBase] = Nil,
requestKeys: Seq[BundleKeyBase] = Nil)
Expand Down Expand Up @@ -102,8 +101,7 @@ case class AXI4BundleParameters(
idBits: Int,
echoFields: Seq[BundleFieldBase] = Nil,
requestFields: Seq[BundleFieldBase] = Nil,
responseFields: Seq[BundleFieldBase] = Nil,
wcorrupt: Boolean = false)
responseFields: Seq[BundleFieldBase] = Nil)
{
require (dataBits >= 8, s"AXI4 data bits must be >= 8 (got $dataBits)")
require (addrBits >= 1, s"AXI4 addr bits must be >= 1 (got $addrBits)")
Expand All @@ -127,13 +125,12 @@ case class AXI4BundleParameters(
max(idBits, x.idBits),
BundleField.union(echoFields ++ x.echoFields),
BundleField.union(requestFields ++ x.requestFields),
BundleField.union(responseFields ++ x.responseFields),
wcorrupt || x.wcorrupt)
BundleField.union(responseFields ++ x.responseFields))
}

object AXI4BundleParameters
{
val emptyBundleParams = AXI4BundleParameters(addrBits=1, dataBits=8, idBits=1, echoFields=Nil, requestFields=Nil, responseFields=Nil, wcorrupt=false)
val emptyBundleParams = AXI4BundleParameters(addrBits=1, dataBits=8, idBits=1, echoFields=Nil, requestFields=Nil, responseFields=Nil)
def union(x: Seq[AXI4BundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y))

def apply(master: AXI4MasterPortParameters, slave: AXI4SlavePortParameters) =
Expand All @@ -143,8 +140,7 @@ object AXI4BundleParameters
idBits = log2Up(master.endId),
echoFields = master.echoFields,
requestFields = BundleField.accept(master.requestFields, slave.requestKeys),
responseFields = BundleField.accept(slave.responseFields, master.responseKeys),
wcorrupt = slave.wcorrupt)
responseFields = BundleField.accept(slave.responseFields, master.responseKeys))
}

case class AXI4EdgeParameters(
Expand Down
19 changes: 12 additions & 7 deletions src/main/scala/amba/axi4/SRAM.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{BusMemoryLogicalTreeNode, LogicalModuleTree, LogicalTreeNode}
import freechips.rocketchip.diplomaticobjectmodel.model.AXI4_Lite
import freechips.rocketchip.util._
import freechips.rocketchip.amba._

// Setting wcorrupt=true is not enough to enable the w.user field
// You must also list AMBACorrupt in your master's requestFields
class AXI4RAM(
address: AddressSet,
cacheable: Boolean = true,
Expand All @@ -17,7 +20,7 @@ class AXI4RAM(
beatBytes: Int = 4,
devName: Option[String] = None,
errors: Seq[AddressSet] = Nil,
wcorrupt: Boolean = false)
wcorrupt: Boolean = true)
(implicit p: Parameters) extends DiplomaticSRAM(address, beatBytes, devName)
{
val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
Expand All @@ -30,11 +33,11 @@ class AXI4RAM(
supportsWrite = TransferSizes(1, beatBytes),
interleavedId = Some(0))),
beatBytes = beatBytes,
wcorrupt = wcorrupt,
requestKeys = if (wcorrupt) Seq(AMBACorrupt) else Seq(),
minLatency = 1)))

lazy val module = new LazyModuleImp(this) {
val (in, _) = node.in(0)
val (in, edgeIn) = node.in(0)
val (mem, omSRAM, omMem) = makeSinglePortedByteWriteSeqMem(size = 1L << mask.filter(b=>b).size)

parentLogicalTreeNode.map {
Expand All @@ -49,7 +52,7 @@ class AXI4RAM(
LogicalModuleTree.add(parentLTN, sramLogicalTreeNode)
}

val corrupt = if (wcorrupt) Some(SeqMem(1 << mask.filter(b=>b).size, UInt(width=2))) else None
val corrupt = if (edgeIn.bundle.requestFields.contains(AMBACorrupt)) Some(SeqMem(1 << mask.filter(b=>b).size, UInt(width=2))) else None

val r_addr = Cat((mask zip (in.ar.bits.addr >> log2Ceil(beatBytes)).asBools).filter(_._1).map(_._2).reverse)
val w_addr = Cat((mask zip (in.aw.bits.addr >> log2Ceil(beatBytes)).asBools).filter(_._1).map(_._2).reverse)
Expand All @@ -74,7 +77,7 @@ class AXI4RAM(
val wdata = Vec.tabulate(beatBytes) { i => in.w.bits.data(8*(i+1)-1, 8*i) }
when (in.aw.fire() && w_sel0) {
mem.write(w_addr, wdata, in.w.bits.strb.asBools)
corrupt.foreach { _.write(w_addr, in.w.bits.corrupt.get.asUInt) }
corrupt.foreach { _.write(w_addr, in.w.bits.user(AMBACorrupt).asUInt) }
}

in. b.valid := w_full
Expand Down Expand Up @@ -122,7 +125,8 @@ object AXI4RAM
executable: Boolean = true,
beatBytes: Int = 4,
devName: Option[String] = None,
errors: Seq[AddressSet] = Nil)
errors: Seq[AddressSet] = Nil,
wcorrupt: Boolean = true)
(implicit p: Parameters) =
{
val axi4ram = LazyModule(new AXI4RAM(
Expand All @@ -131,7 +135,8 @@ object AXI4RAM
executable = executable,
beatBytes = beatBytes,
devName = devName,
errors = errors))
errors = errors,
wcorrupt = wcorrupt))
axi4ram.node
}
}
13 changes: 7 additions & 6 deletions src/main/scala/amba/axi4/ToTL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._

case class AXI4ToTLNode(wcorrupt: Boolean = false)(implicit valName: ValName) extends MixedAdapterNode(AXI4Imp, TLImp)(
case class AXI4ToTLNode(wcorrupt: Boolean)(implicit valName: ValName) extends MixedAdapterNode(AXI4Imp, TLImp)(
dFn = { case mp =>
mp.masters.foreach { m => require (m.maxFlight.isDefined, "AXI4 must include a transaction maximum per ID to convert to TL") }
val maxFlight = mp.masters.map(_.maxFlight.get).max
Expand Down Expand Up @@ -39,13 +39,14 @@ case class AXI4ToTLNode(wcorrupt: Boolean = false)(implicit valName: ValName) ex
supportsRead = m.supportsGet.intersect(maxXfer),
interleavedId = Some(0))}, // TL2 never interleaves D beats
beatBytes = mp.beatBytes,
wcorrupt = wcorrupt,
minLatency = mp.minLatency,
responseFields = mp.responseFields,
requestKeys = mp.requestKeys.filter(_ != AMBAProt))
requestKeys = (if (wcorrupt) Seq(AMBACorrupt) else Seq()) ++ mp.requestKeys.filter(_ != AMBAProt))
})

class AXI4ToTL(wcorrupt: Boolean = false)(implicit p: Parameters) extends LazyModule
// Setting wcorrupt true is insufficient to enable w.user.corrupt
// One must additionally provide list it in the AXI4 master's requestFields
class AXI4ToTL(wcorrupt: Boolean)(implicit p: Parameters) extends LazyModule
{
val node = AXI4ToTLNode(wcorrupt)

Expand Down Expand Up @@ -122,7 +123,7 @@ class AXI4ToTL(wcorrupt: Boolean = false)(implicit p: Parameters) extends LazyMo
in.w.ready := w_out.ready && in.aw.valid
w_out.valid := in.aw.valid && in.w.valid
w_out.bits :<= edgeOut.Put(w_id, w_addr, w_size, in.w.bits.data, in.w.bits.strb)._2
in.w.bits.corrupt.foreach { w_out.bits.corrupt := _ }
in.w.bits.user.lift(AMBACorrupt).foreach { w_out.bits.corrupt := _ }

w_out.bits.user :<= in.aw.bits.user
w_out.bits.user.lift(AMBAProt).foreach { wprot =>
Expand Down Expand Up @@ -198,7 +199,7 @@ class AXI4BundleRError(params: AXI4BundleParameters) extends AXI4BundleBase(para

object AXI4ToTL
{
def apply(wcorrupt: Boolean = false)(implicit p: Parameters) =
def apply(wcorrupt: Boolean = true)(implicit p: Parameters) =
{
val axi42tl = LazyModule(new AXI4ToTL(wcorrupt))
axi42tl.node
Expand Down
1 change: 0 additions & 1 deletion src/main/scala/amba/axi4/Xbar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class AXI4Xbar(
responseFields = BundleField.union(seq.flatMap(_.responseFields)),
requestKeys = seq.flatMap(_.requestKeys).distinct,
minLatency = seq.map(_.minLatency).min,
wcorrupt = seq.exists(_.wcorrupt),
slaves = seq.flatMap { port =>
require (port.beatBytes == seq(0).beatBytes,
s"Xbar data widths don't match: ${port.slaves.map(_.name)} has ${port.beatBytes}B vs ${seq(0).slaves.map(_.name)} has ${seq(0).beatBytes}B")
Expand Down
7 changes: 7 additions & 0 deletions src/main/scala/amba/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ package object amba {
x.fetch := false.B
}
}

// Used to convert a TileLink corrupt signal into an AMBA user bit
case object AMBACorrupt extends DataKey[Bool]("corrupt")
case class AMBACorruptField() extends BundleField(AMBACorrupt) {
def data = Output(Bool())
def default(x: Bool) { x := false.B }
}
}
15 changes: 8 additions & 7 deletions src/main/scala/tilelink/ToAXI4.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ case class TLToAXI4IdMapEntry(axi4Id: IdRange, tlId: IdRange, name: String, isCa
if (requestFifo) " [FIFO]" else "")
}

case class TLToAXI4Node(stripBits: Int = 0)(implicit valName: ValName) extends MixedAdapterNode(TLImp, AXI4Imp)(
case class TLToAXI4Node(stripBits: Int = 0, wcorrupt: Boolean = true)(implicit valName: ValName) extends MixedAdapterNode(TLImp, AXI4Imp)(
dFn = { p =>
p.clients.foreach { c =>
require (c.sourceId.start % (1 << stripBits) == 0 &&
Expand All @@ -68,7 +68,7 @@ case class TLToAXI4Node(stripBits: Int = 0)(implicit valName: ValName) extends M
}
AXI4MasterPortParameters(
masters = masters,
requestFields = p.requestFields.filter(!_.isInstanceOf[AMBAProtField]),
requestFields = (if (wcorrupt) Seq(AMBACorruptField()) else Seq()) ++ p.requestFields.filter(!_.isInstanceOf[AMBAProtField]),
echoFields = AXI4TLStateField(log2Ceil(p.endSourceId)) +: p.echoFields,
responseKeys = p.responseKeys)
},
Expand All @@ -92,9 +92,10 @@ case class TLToAXI4Node(stripBits: Int = 0)(implicit valName: ValName) extends M
requestKeys = AMBAProt +: p.requestKeys)
})

class TLToAXI4(val combinational: Boolean = true, val adapterName: Option[String] = None, val stripBits: Int = 0)(implicit p: Parameters) extends LazyModule
// wcorrupt alone is not enough; a slave must include AMBACorrupt in the slave port's requestKeys
class TLToAXI4(val combinational: Boolean = true, val adapterName: Option[String] = None, val stripBits: Int = 0, val wcorrupt: Boolean = true)(implicit p: Parameters) extends LazyModule
{
val node = TLToAXI4Node(stripBits)
val node = TLToAXI4Node(stripBits, wcorrupt)

lazy val module = new LazyModuleImp(this) {
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
Expand Down Expand Up @@ -198,7 +199,7 @@ class TLToAXI4(val combinational: Boolean = true, val adapterName: Option[String
out_w.bits.data := in.a.bits.data
out_w.bits.strb := in.a.bits.mask
out_w.bits.last := a_last
out_w.bits.corrupt.foreach { _ := in.a.bits.corrupt }
out_w.bits.user.lift(AMBACorrupt).foreach { _ := in.a.bits.corrupt }

// R and B => D arbitration
val r_holds_d = RegInit(Bool(false))
Expand Down Expand Up @@ -270,9 +271,9 @@ class TLToAXI4(val combinational: Boolean = true, val adapterName: Option[String

object TLToAXI4
{
def apply(combinational: Boolean = true, adapterName: Option[String] = None, stripBits: Int = 0)(implicit p: Parameters) =
def apply(combinational: Boolean = true, adapterName: Option[String] = None, stripBits: Int = 0, wcorrupt: Boolean = true)(implicit p: Parameters) =
{
val tl2axi4 = LazyModule(new TLToAXI4(combinational, adapterName, stripBits))
val tl2axi4 = LazyModule(new TLToAXI4(combinational, adapterName, stripBits, wcorrupt))
tl2axi4.node
}

Expand Down

0 comments on commit 4cb3766

Please sign in to comment.