Skip to content

Commit

Permalink
Merge pull request #2335 from chipsalliance/amba-prot
Browse files Browse the repository at this point in the history
Fix various bugs related to the new user bits in TileLink
  • Loading branch information
terpstra authored Mar 14, 2020
2 parents 6f2f91a + b684c1f commit a79be8f
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/main/scala/amba/axi4/Parameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ case class AXI4BundleParameters(
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)")
echoFields.foreach { f => require (f.key.isControl, s"${f} is not a legal echo field") }

// Bring the globals into scope
val lenBits = AXI4Parameters.lenBits
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/amba/axi4/ToTL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ case class AXI4ToTLNode(wcorrupt: Boolean)(implicit valName: ValName) extends Mi
nodePath = m.nodePath,
requestFifo = true)
},
echoFields = mp.requestFields,
echoFields = mp.echoFields,
requestFields = AMBAProtField() +: mp.requestFields,
responseKeys = mp.responseKeys)
},
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/tilelink/Fragmenter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
val fullMask = UInt((BigInt(1) << beatBytes) - 1)
assert (!repeater.io.full || in_a.bits.mask === fullMask)
out.a.bits.mask := Mux(repeater.io.full, fullMask, in.a.bits.mask)
out.a.bits.user.partialAssignL(in.a.bits.user.subset(_.isData))

// Tie off unused channels
in.b.valid := Bool(false)
Expand Down
14 changes: 8 additions & 6 deletions src/main/scala/tilelink/HintHandler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import chisel3._
import chisel3.util._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.Repeater
import freechips.rocketchip.util._
import freechips.rocketchip.devices.tilelink.TLROM
import scala.math.min

Expand Down Expand Up @@ -56,11 +56,8 @@ class TLHintHandler(passthrough: Boolean = true)(implicit p: Parameters) extends
val mux = Wire(chiselTypeOf(in.a))

repeater.io.repeat := mapPP && !edgeIn.last(out.a)
repeater.io.enq <> in.a
// Work-around broken chisel3 <>
out.a.bits := mux.bits
out.a.valid := mux.valid
mux.ready := out.a.ready
repeater.io.enq :<> in.a
out.a :<> mux

// Only some signals need to be repeated
mux.bits.opcode := in.a.bits.opcode // ignored when full
Expand All @@ -72,6 +69,11 @@ class TLHintHandler(passthrough: Boolean = true)(implicit p: Parameters) extends
mux.bits.mask := in.a.bits.mask // ignored when full
mux.bits.corrupt := in.a.bits.corrupt // irrelevant when full (mask = 0)

// Hints have no data fields; use defaults for those
mux.bits.user :<= in.a.bits.user
mux.bits.user.partialAssignL(repeater.io.deq.bits.user.subset(_.isControl))
mux.bits.echo :<= repeater.io.deq.bits.echo // control only

mux.valid := repeater.io.deq.valid
repeater.io.deq.ready := mux.ready

Expand Down
21 changes: 11 additions & 10 deletions src/main/scala/tilelink/Parameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,8 @@ class TLSlavePortParameters private(
beatBytes: Int = -1,
endSinkId: Int = endSinkId,
minLatency: Int = minLatency,
responseFields: Seq[BundleFieldBase] = Nil,
requestKeys: Seq[BundleKeyBase] = Nil) =
responseFields: Seq[BundleFieldBase] = responseFields,
requestKeys: Seq[BundleKeyBase] = requestKeys) =
{
new TLSlavePortParameters(
slaves = managers,
Expand All @@ -599,8 +599,8 @@ class TLSlavePortParameters private(
beatBytes: Int = -1,
endSinkId: Int = endSinkId,
minLatency: Int = minLatency,
responseFields: Seq[BundleFieldBase] = Nil,
requestKeys: Seq[BundleKeyBase] = Nil) =
responseFields: Seq[BundleFieldBase] = responseFields,
requestKeys: Seq[BundleKeyBase] = requestKeys) =
{
v1copy(
managers,
Expand Down Expand Up @@ -944,9 +944,9 @@ class TLMasterPortParameters private(
def v1copy(
clients: Seq[TLClientParameters] = masters,
minLatency: Int = minLatency,
echoFields: Seq[BundleFieldBase] = Nil,
requestFields: Seq[BundleFieldBase] = Nil,
responseKeys: Seq[BundleKeyBase] = Nil) =
echoFields: Seq[BundleFieldBase] = echoFields,
requestFields: Seq[BundleFieldBase] = requestFields,
responseKeys: Seq[BundleKeyBase] = responseKeys) =
{
new TLMasterPortParameters(
masters = clients,
Expand All @@ -961,9 +961,9 @@ class TLMasterPortParameters private(
def copy(
clients: Seq[TLClientParameters] = masters,
minLatency: Int = minLatency,
echoFields: Seq[BundleFieldBase] = Nil,
requestFields: Seq[BundleFieldBase] = Nil,
responseKeys: Seq[BundleKeyBase] = Nil) =
echoFields: Seq[BundleFieldBase] = echoFields,
requestFields: Seq[BundleFieldBase] = requestFields,
responseKeys: Seq[BundleKeyBase] = responseKeys) =
{
v1copy(
clients,
Expand Down Expand Up @@ -1028,6 +1028,7 @@ case class TLBundleParameters(
require (sinkBits >= 1)
require (sizeBits >= 1)
require (isPow2(dataBits))
echoFields.foreach { f => require (f.key.isControl, s"${f} is not a legal echo field") }

val addrLoBits = log2Up(dataBits/8)

Expand Down
10 changes: 6 additions & 4 deletions src/main/scala/tilelink/ToAHB.scala
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,12 @@ class TLToAHB(val aFlow: Boolean = false, val supportHints: Boolean = true, val

// Set prot bits if we have extra meta-data
send.hauser.lift(AMBAProt).foreach { x =>
out.hprot(0) := !x.fetch
out.hprot(1) := x.privileged
out.hprot(2) := x.bufferable
out.hprot(3) := x.cacheable
val hprot = Wire(Vec(4, Bool()))
hprot(0) := !x.fetch
hprot(1) := x.privileged
hprot(2) := x.bufferable
hprot(3) := x.cacheable
out.hprot := Cat(hprot.reverse)
}

// We need a skidpad to capture D output:
Expand Down
8 changes: 5 additions & 3 deletions src/main/scala/tilelink/ToAPB.scala
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ class TLToAPB(val aFlow: Boolean = true)(implicit p: Parameters) extends LazyMod
out.pstrb := Mux(a_write, a.bits.mask, UInt(0))
out.pauser :<= a.bits.user
a.bits.user.lift(AMBAProt).foreach { x =>
out.pprot(0) := x.privileged
out.pprot(1) := !x.secure
out.pprot(2) := x.fetch
val pprot = Wire(Vec(3, Bool()))
pprot(0) := x.privileged
pprot(1) := !x.secure
pprot(2) := x.fetch
out.pprot := Cat(pprot.reverse)
}

a.ready := a_enable && out.pready
Expand Down
18 changes: 11 additions & 7 deletions src/main/scala/tilelink/ToAXI4.scala
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,17 @@ class TLToAXI4(val combinational: Boolean = true, val adapterName: Option[String
a_extra.size := a_size

in.a.bits.user.lift(AMBAProt).foreach { x =>
arw.prot(0) := x.privileged
arw.prot(1) := !x.secure
arw.prot(2) := x.fetch
arw.cache(0) := x.bufferable
arw.cache(1) := x.modifiable
arw.cache(2) := x.cacheable
arw.cache(3) := x.cacheable
val prot = Wire(Vec(3, Bool()))
val cache = Wire(Vec(4, Bool()))
prot(0) := x.privileged
prot(1) := !x.secure
prot(2) := x.fetch
cache(0) := x.bufferable
cache(1) := x.modifiable
cache(2) := x.cacheable
cache(3) := x.cacheable
arw.prot := Cat(prot.reverse)
arw.cache := Cat(cache.reverse)
}

val stall = sourceStall(in.a.bits.source) && a_first
Expand Down
26 changes: 26 additions & 0 deletions src/main/scala/util/BundleMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,22 @@ class BundleMap(val fields: Seq[BundleFieldBase]) extends Record with CustomBulk
}
}

// A BundleMap is best viewed as a map from BundleKey to Data
def keydata: Seq[(BundleKeyBase, Data)] = (fields zip elements) map { case (field, (_, data)) => (field.key, data) }

def apply[T <: Data](key: BundleKey[T]): T = elements(key.name).asInstanceOf[T]
def lift [T <: Data](key: BundleKey[T]): Option[T] = elements.lift(key.name).map(_.asInstanceOf[T])

def apply(key: BundleKeyBase): Data = elements(key.name)
def lift (key: BundleKeyBase): Option[Data] = elements.lift(key.name)

// Create a new BundleMap with only the selected Keys retained
def subset(fn: BundleKeyBase => Boolean): BundleMap = {
val out = Wire(BundleMap(fields.filter(x => fn(x.key))))
out :<= this
out
}

// Assign all outputs of this from either:
// outputs of that (if they exist)
// or the default value for the BundleField
Expand Down Expand Up @@ -166,6 +176,22 @@ class BundleMap(val fields: Seq[BundleFieldBase]) extends Record with CustomBulk
}
// it's ok to have excess elements in 'hx'
}

// Assign only those outputs of this which exist as outputs in that
def partialAssignL(that: BundleMap): Unit = {
val h = HashMap(that.keydata:_*)
keydata foreach { case (key, vx) =>
h.lift(key).foreach { vy => FixChisel3.descendL(vx, vy) }
}
}

// Assign only those inputs of that which exist as inputs in this
def partialAssignR(that: BundleMap): Unit = {
val h = HashMap(keydata:_*)
that.keydata foreach { case (key, vy) =>
h.lift(key).foreach { vx => FixChisel3.descendL(vx, vy) }
}
}
}

object BundleMap {
Expand Down

0 comments on commit a79be8f

Please sign in to comment.