1
0
Fork 0

tilelink2: refactor address into addr_hi on ABC and addr_lo on CD

We need addr_lo in order to properly convert widths.
As part of the refactoring, move all methods out of the Bundles
This commit is contained in:
Wesley W. Terpstra 2016-09-06 23:46:44 -07:00
parent aae4230627
commit d2421654c4
14 changed files with 378 additions and 314 deletions

View File

@ -100,151 +100,72 @@ object TLAtomics
def isLogical(x: UInt) = x <= SWAP
}
class Bogus
object Bogus
{
def apply() = new Bogus
}
sealed trait TLChannel
sealed trait TLDataChannel extends TLChannel
sealed trait TLAddrChannel extends TLDataChannel
object ChannelType {
sealed trait T
case object A extends T
case object B extends T
case object C extends T
case object D extends T
case object E extends T
val cases = Seq(A, B, C, D, E)
}
trait HasTLOpcode
{
// The data field in this message has value
def hasData(x: Bogus = Bogus()): Bool
// This message requires a response
def hasFollowUp(x: Bogus = Bogus()): Bool
// What channel type is this?
def channelType(x: Bogus = Bogus()): ChannelType.T
// The size field of the opcode
def size(x: Bogus = Bogus()): UInt
}
trait HasTLData extends HasTLOpcode
{
def data(x: Bogus = Bogus()): UInt
def mask(x: Bogus = Bogus()): UInt
}
class TLBundleA(params: TLBundleParameters)
extends TLBundleBase(params)
with HasTLData
final class TLBundleA(params: TLBundleParameters)
extends TLBundleBase(params) with TLAddrChannel
{
// fixed fields during multibeat:
val opcode = UInt(width = 3)
val param = UInt(width = 3) // amo_opcode || perms || hint
val size = UInt(width = params.sizeBits)
val source = UInt(width = params.sourceBits) // from
val address = UInt(width = params.addressBits) // to
val source = UInt(width = params.sourceBits) // from
val addr_hi = UInt(width = params.addrHiBits) // to
// variable fields during multibeat:
val mask = UInt(width = params.dataBits/8)
val data = UInt(width = params.dataBits)
def hasData(x: Bogus = Bogus()) = !opcode(2)
// opcode === TLMessages.PutFullData ||
// opcode === TLMessages.PutPartialData ||
// opcode === TLMessages.ArithmeticData ||
// opcode === TLMessages.LogicalData
def hasFollowUp(x: Bogus = Bogus()) = Bool(true)
def channelType(x: Bogus = Bogus()) = ChannelType.A
def size(x: Bogus = Bogus()) = size
def data(x: Bogus = Bogus()) = data
def mask(x: Bogus = Bogus()) = mask
}
class TLBundleB(params: TLBundleParameters)
extends TLBundleBase(params)
with HasTLData
final class TLBundleB(params: TLBundleParameters)
extends TLBundleBase(params) with TLAddrChannel
{
// fixed fields during multibeat:
val opcode = UInt(width = 3)
val param = UInt(width = 3)
val size = UInt(width = params.sizeBits)
val source = UInt(width = params.sourceBits) // to
val address = UInt(width = params.addressBits) // from
val source = UInt(width = params.sourceBits) // to
val addr_hi = UInt(width = params.addrHiBits) // from
// variable fields during multibeat:
val mask = UInt(width = params.dataBits/8)
val data = UInt(width = params.dataBits)
def hasData(x: Bogus = Bogus()) = !opcode(2)
def hasFollowUp(x: Bogus = Bogus()) = Bool(true)
def channelType(x: Bogus = Bogus()) = ChannelType.B
def size(x: Bogus = Bogus()) = size
def data(x: Bogus = Bogus()) = data
def mask(x: Bogus = Bogus()) = mask
}
class TLBundleC(params: TLBundleParameters)
extends TLBundleBase(params)
with HasTLData
final class TLBundleC(params: TLBundleParameters)
extends TLBundleBase(params) with TLAddrChannel
{
// fixed fields during multibeat:
val opcode = UInt(width = 3)
val param = UInt(width = 3)
val size = UInt(width = params.sizeBits)
val source = UInt(width = params.sourceBits) // from
val address = UInt(width = params.addressBits) // to
val source = UInt(width = params.sourceBits) // from
val addr_hi = UInt(width = params.addrHiBits) // to
val addr_lo = UInt(width = params.addrLoBits) // instead of mask
// variable fields during multibeat:
val data = UInt(width = params.dataBits)
val error = Bool() // AccessAck[Data]
def hasData(x: Bogus = Bogus()) = opcode(0)
// opcode === TLMessages.AccessAckData ||
// opcode === TLMessages.ProbeAckData ||
// opcode === TLMessages.ReleaseData
def hasFollowUp(x: Bogus = Bogus()) = opcode(2) && opcode(1)
// opcode === TLMessages.Release ||
// opcode === TLMessages.ReleaseData
def channelType(x: Bogus = Bogus()) = ChannelType.C
def size(x: Bogus = Bogus()) = size
def data(x: Bogus = Bogus()) = data
def mask(x: Bogus = Bogus()) = SInt(-1, width = params.dataBits/8).asUInt
}
class TLBundleD(params: TLBundleParameters)
extends TLBundleBase(params)
with HasTLData
final class TLBundleD(params: TLBundleParameters)
extends TLBundleBase(params) with TLDataChannel
{
// fixed fields during multibeat:
val opcode = UInt(width = 3)
val param = UInt(width = 2)
val size = UInt(width = params.sizeBits)
val source = UInt(width = params.sourceBits) // to
val sink = UInt(width = params.sinkBits) // from
val opcode = UInt(width = 3)
val param = UInt(width = 2)
val size = UInt(width = params.sizeBits)
val source = UInt(width = params.sourceBits) // to
val sink = UInt(width = params.sinkBits) // from
val addr_lo = UInt(width = params.addrLoBits) // instead of mask
// variable fields during multibeat:
val data = UInt(width = params.dataBits)
val error = Bool() // AccessAck[Data], Grant[Data]
def hasData(x: Bogus = Bogus()) = opcode(0)
// opcode === TLMessages.AccessAckData ||
// opcode === TLMessages.GrantData
def hasFollowUp(x: Bogus = Bogus()) = opcode(2) && !opcode(1)
// opcode === TLMessages.Grant ||
// opcode === TLMessages.GrantData
def channelType(x: Bogus = Bogus()) = ChannelType.D
def size(x: Bogus = Bogus()) = size
def data(x: Bogus = Bogus()) = data
def mask(x: Bogus = Bogus()) = SInt(-1, width = params.dataBits/8).asUInt
val data = UInt(width = params.dataBits)
val error = Bool() // AccessAck[Data], Grant[Data]
}
class TLBundleE(params: TLBundleParameters)
extends TLBundleBase(params)
with HasTLOpcode
final class TLBundleE(params: TLBundleParameters)
extends TLBundleBase(params) with TLChannel
{
val sink = UInt(width = params.sourceBits) // to
def hasData(x: Bogus = Bogus()) = Bool(false)
def hasFollowUp(x: Bogus = Bogus()) = Bool(false)
def channelType(x: Bogus = Bogus()) = ChannelType.E
def size(x: Bogus = Bogus()) = UInt(log2Up(params.dataBits/8))
}
class TLBundle(params: TLBundleParameters) extends TLBundleBase(params)

View File

@ -10,14 +10,22 @@ class TLEdge(
manager: TLManagerPortParameters)
extends TLEdgeParameters(client, manager)
{
def isAligned(address: UInt, lgSize: UInt) =
def isHiAligned(addr_hi: UInt, lgSize: UInt): Bool = {
if (maxLgSize == 0) Bool(true) else {
val mask = ~(SInt(-1, width=maxLgSize).asUInt << lgSize)(maxLgSize-1, 0)
(address & mask) === UInt(0)
val mask = UIntToOH1(lgSize, maxLgSize) >> log2Ceil(manager.beatBytes)
(addr_hi & mask) === UInt(0)
}
}
def isLoAligned(addr_lo: UInt, lgSize: UInt): Bool = {
if (maxLgSize == 0) Bool(true) else {
val mask = UIntToOH1(lgSize, maxLgSize)
(addr_lo & mask) === UInt(0)
}
}
// This gets used everywhere, so make the smallest circuit possible ...
def fullMask(address: UInt, lgSize: UInt) = {
def mask(addr_lo: UInt, lgSize: UInt): UInt = {
val lgBytes = log2Ceil(manager.beatBytes)
val sizeOH = UIntToOH(lgSize, lgBytes)
def helper(i: Int): Seq[(Bool, Bool)] = {
@ -26,7 +34,7 @@ class TLEdge(
} else {
val sub = helper(i-1)
val size = sizeOH(lgBytes - i)
val bit = address(lgBytes - i)
val bit = addr_lo(lgBytes - i)
val nbit = !bit
Seq.tabulate (1 << i) { j =>
val (sub_acc, sub_eq) = sub(j/2)
@ -39,8 +47,8 @@ class TLEdge(
Cat(helper(lgBytes).map(_._1).reverse)
}
def lowAddress(mask: UInt) = {
// Almost OHToUInt, but any bit in low => use low address
def addr_lo(mask: UInt): UInt = {
// Almost OHToUInt, but bits set => bits not set
def helper(mask: UInt, width: Int): UInt = {
if (width <= 1) {
UInt(0)
@ -56,9 +64,9 @@ class TLEdge(
helper(mask, bundle.dataBits/8)
}
def staticHasData(bundle: HasTLOpcode): Option[Boolean] = {
bundle.channelType() match {
case ChannelType.A => {
def staticHasData(bundle: TLChannel): Option[Boolean] = {
bundle match {
case _:TLBundleA => {
// Do there exist A messages with Data?
val aDataYes = manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportPutFull || manager.anySupportPutPartial
// Do there exist A messages without Data?
@ -66,7 +74,7 @@ class TLEdge(
// Statically optimize the case where hasData is a constant
if (!aDataYes) Some(false) else if (!aDataNo) Some(true) else None
}
case ChannelType.B => {
case _:TLBundleB => {
// Do there exist B messages with Data?
val bDataYes = client.anySupportArithmetic || client.anySupportLogical || client.anySupportPutFull || client.anySupportPutPartial
// Do there exist B messages without Data?
@ -74,34 +82,119 @@ class TLEdge(
// Statically optimize the case where hasData is a constant
if (!bDataYes) Some(false) else if (!bDataNo) Some(true) else None
}
case ChannelType.C => {
case _:TLBundleC => {
// Do there eixst C messages with Data?
val cDataYes = client.anySupportGet || client.anySupportArithmetic || client.anySupportLogical || client.anySupportProbe
// Do there exist C messages without Data?
val cDataNo = client.anySupportPutFull || client.anySupportPutPartial || client.anySupportHint || client.anySupportProbe
if (!cDataYes) Some(false) else if (!cDataNo) Some(true) else None
}
case ChannelType.D => {
case _:TLBundleD => {
// Do there eixst D messages with Data?
val dDataYes = manager.anySupportGet || manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportAcquire
// Do there exist D messages without Data?
val dDataNo = manager.anySupportPutFull || manager.anySupportPutPartial || manager.anySupportHint || manager.anySupportAcquire
if (!dDataYes) Some(false) else if (!dDataNo) Some(true) else None
}
case ChannelType.E => Some(false)
case _:TLBundleE => Some(false)
}
}
def hasData(bundle: HasTLOpcode): Bool =
staticHasData(bundle).map(Bool(_)).getOrElse(bundle.hasData())
def hasFollowUp(x: TLChannel): Bool = {
x match {
case a: TLBundleA => Bool(true)
case b: TLBundleB => Bool(true)
case c: TLBundleC => c.opcode(2) && c.opcode(1)
// opcode === TLMessages.Release ||
// opcode === TLMessages.ReleaseData
case d: TLBundleD => d.opcode(2) && !d.opcode(1)
// opcode === TLMessages.Grant ||
// opcode === TLMessages.GrantData
case e: TLBundleE => Bool(false)
}
}
def numBeats(bundle: HasTLOpcode) = {
val hasData = this.hasData(bundle)
val size = bundle.size()
val cutoff = log2Ceil(manager.beatBytes)
val small = if (manager.maxTransfer <= manager.beatBytes) Bool(true) else size <= UInt(cutoff)
val decode = UIntToOH(size, maxLgSize+1) >> cutoff
Mux(!hasData || small, UInt(1), decode)
def hasData(x: TLChannel): Bool = {
val opdata = x match {
case a: TLBundleA => !a.opcode(2)
// opcode === TLMessages.PutFullData ||
// opcode === TLMessages.PutPartialData ||
// opcode === TLMessages.ArithmeticData ||
// opcode === TLMessages.LogicalData
case b: TLBundleB => !b.opcode(2)
// opcode === TLMessages.PutFullData ||
// opcode === TLMessages.PutPartialData ||
// opcode === TLMessages.ArithmeticData ||
// opcode === TLMessages.LogicalData
case c: TLBundleC => c.opcode(0)
// opcode === TLMessages.AccessAckData ||
// opcode === TLMessages.ProbeAckData ||
// opcode === TLMessages.ReleaseData
case d: TLBundleD => d.opcode(0)
// opcode === TLMessages.AccessAckData ||
// opcode === TLMessages.GrantData
case e: TLBundleE => Bool(false)
}
staticHasData(x).map(Bool(_)).getOrElse(opdata)
}
def size(x: TLDataChannel): UInt = {
x match {
case a: TLBundleA => a.size
case b: TLBundleB => b.size
case c: TLBundleC => c.size
case d: TLBundleD => d.size
}
}
def data(x: TLDataChannel): UInt = {
x match {
case a: TLBundleA => a.data
case b: TLBundleB => b.data
case c: TLBundleC => c.data
case d: TLBundleD => d.data
}
}
def mask(x: TLDataChannel): UInt = {
x match {
case a: TLBundleA => a.mask
case b: TLBundleB => b.mask
case c: TLBundleC => mask(c.addr_lo, c.size)
case d: TLBundleD => mask(d.addr_lo, d.size)
}
}
def addr_lo(x: TLDataChannel): UInt = {
x match {
case a: TLBundleA => addr_lo(a.mask)
case b: TLBundleB => addr_lo(b.mask)
case c: TLBundleC => c.addr_lo
case d: TLBundleD => d.addr_lo
}
}
def address(x: TLAddrChannel): UInt = {
val hi = x match {
case a: TLBundleA => a.addr_hi
case b: TLBundleB => b.addr_hi
case c: TLBundleC => c.addr_hi
}
if (manager.beatBytes == 1) hi else Cat(hi, addr_lo(x))
}
def numBeats(x: TLChannel): UInt = {
x match {
case _: TLBundleE => UInt(1)
case bundle: TLDataChannel => {
val hasData = this.hasData(bundle)
val size = this.size(bundle)
val cutoff = log2Ceil(manager.beatBytes)
val small = if (manager.maxTransfer <= manager.beatBytes) Bool(true) else size <= UInt(cutoff)
val decode = UIntToOH(size, maxLgSize+1) >> cutoff
Mux(!hasData || small, UInt(1), decode)
}
}
}
}
@ -119,7 +212,7 @@ class TLEdgeOut(
a.param := growPermissions
a.size := lgSize
a.source := fromSource
a.address := toAddress
a.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
a.mask := SInt(-1).asUInt
a.data := UInt(0)
(legal, a)
@ -133,7 +226,8 @@ class TLEdgeOut(
c.param := shrinkPermissions
c.size := lgSize
c.source := fromSource
c.address := toAddress
c.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
c.addr_lo := toAddress
c.data := UInt(0)
c.error := Bool(false)
(legal, c)
@ -147,31 +241,34 @@ class TLEdgeOut(
c.param := shrinkPermissions
c.size := lgSize
c.source := fromSource
c.address := toAddress
c.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
c.addr_lo := toAddress
c.data := data
c.error := Bool(false)
(legal, c)
}
def ProbeAck(toAddress: UInt, lgSize: UInt, reportPermissions: UInt) = {
def ProbeAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, reportPermissions: UInt) = {
val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.ProbeAck
c.param := reportPermissions
c.size := lgSize
c.source := UInt(0)
c.address := toAddress
c.source := fromSource
c.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
c.addr_lo := toAddress
c.data := UInt(0)
c.error := Bool(false)
c
}
def ProbeAck(toAddress: UInt, lgSize: UInt, reportPermissions: UInt, data: UInt) = {
def ProbeAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, reportPermissions: UInt, data: UInt) = {
val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.ProbeAckData
c.param := reportPermissions
c.size := lgSize
c.source := UInt(0)
c.address := toAddress
c.source := fromSource
c.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
c.addr_lo := toAddress
c.data := data
c.error := Bool(false)
c
@ -192,8 +289,8 @@ class TLEdgeOut(
a.param := UInt(0)
a.size := lgSize
a.source := fromSource
a.address := toAddress
a.mask := fullMask(toAddress, lgSize)
a.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
a.mask := mask(toAddress, lgSize)
a.data := UInt(0)
(legal, a)
}
@ -206,8 +303,8 @@ class TLEdgeOut(
a.param := UInt(0)
a.size := lgSize
a.source := fromSource
a.address := toAddress
a.mask := fullMask(toAddress, lgSize)
a.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
a.mask := mask(toAddress, lgSize)
a.data := data
(legal, a)
}
@ -220,7 +317,7 @@ class TLEdgeOut(
a.param := UInt(0)
a.size := lgSize
a.source := fromSource
a.address := toAddress
a.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
a.mask := mask
a.data := data
(legal, a)
@ -234,8 +331,8 @@ class TLEdgeOut(
a.param := atomic
a.size := lgSize
a.source := fromSource
a.address := toAddress
a.mask := fullMask(toAddress, lgSize)
a.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
a.mask := mask(toAddress, lgSize)
a.data := data
(legal, a)
}
@ -248,8 +345,8 @@ class TLEdgeOut(
a.param := atomic
a.size := lgSize
a.source := fromSource
a.address := toAddress
a.mask := fullMask(toAddress, lgSize)
a.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
a.mask := mask(toAddress, lgSize)
a.data := data
(legal, a)
}
@ -262,45 +359,53 @@ class TLEdgeOut(
a.param := param
a.size := lgSize
a.source := fromSource
a.address := toAddress
a.mask := fullMask(toAddress, lgSize)
a.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
a.mask := mask(toAddress, lgSize)
a.data := UInt(0)
(legal, a)
}
def AccessAck(toAddress: UInt, lgSize: UInt): TLBundleC = AccessAck(toAddress, lgSize, Bool(false))
def AccessAck(toAddress: UInt, lgSize: UInt, error: Bool) = {
def AccessAck(b: TLBundleB): TLBundleC = AccessAck(b.source, address(b), b.size)
def AccessAck(b: TLBundleB, error: Bool): TLBundleC = AccessAck(b.source, address(b), b.size, error)
def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt): TLBundleC = AccessAck(fromSource, toAddress, lgSize, Bool(false))
def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, error: Bool) = {
val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.AccessAck
c.param := UInt(0)
c.size := lgSize
c.source := UInt(0)
c.address := toAddress
c.source := fromSource
c.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
c.addr_lo := toAddress
c.data := UInt(0)
c.error := error
c
}
def AccessAck(toAddress: UInt, lgSize: UInt, data: UInt): TLBundleC = AccessAck(toAddress, lgSize, data, Bool(false))
def AccessAck(toAddress: UInt, lgSize: UInt, data: UInt, error: Bool) = {
def AccessAck(b: TLBundleB, data: UInt): TLBundleC = AccessAck(b.source, address(b), b.size, data)
def AccessAck(b: TLBundleB, data: UInt, error: Bool): TLBundleC = AccessAck(b.source, address(b), b.size, data, error)
def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt): TLBundleC = AccessAck(fromSource, toAddress, lgSize, data, Bool(false))
def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, error: Bool) = {
val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.AccessAckData
c.param := UInt(0)
c.size := lgSize
c.source := UInt(0)
c.address := toAddress
c.source := fromSource
c.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
c.addr_lo := toAddress
c.data := data
c.error := error
c
}
def HintAck(toAddress: UInt, lgSize: UInt) = {
def HintAck(b: TLBundleB): TLBundleC = HintAck(b.source, address(b), b.size)
def HintAck(fromSource: UInt, toAddress: UInt, lgSize: UInt) = {
val c = Wire(new TLBundleC(bundle))
c.opcode := TLMessages.HintAck
c.param := UInt(0)
c.size := lgSize
c.source := UInt(0)
c.address := toAddress
c.source := fromSource
c.addr_hi := toAddress >> log2Ceil(manager.beatBytes)
c.addr_lo := toAddress
c.data := UInt(0)
c.error := Bool(false)
c
@ -321,47 +426,50 @@ class TLEdgeIn(
b.param := capPermissions
b.size := lgSize
b.source := toSource
b.address := fromAddress
b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes)
b.mask := SInt(-1).asUInt
b.data := UInt(0)
(legal, b)
}
def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt): TLBundleD = Grant(fromSink, toSource, lgSize, capPermissions, Bool(false))
def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, error: Bool) = {
def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt): TLBundleD = Grant(fromAddress, fromSink, toSource, lgSize, capPermissions, Bool(false))
def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, error: Bool) = {
val d = Wire(new TLBundleD(bundle))
d.opcode := TLMessages.Grant
d.param := capPermissions
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.data := UInt(0)
d.error := error
d.opcode := TLMessages.Grant
d.param := capPermissions
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.addr_lo := fromAddress
d.data := UInt(0)
d.error := error
d
}
def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt): TLBundleD = Grant(fromSink, toSource, lgSize, capPermissions, data, Bool(false))
def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt, error: Bool) = {
def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt): TLBundleD = Grant(fromAddress, fromSink, toSource, lgSize, capPermissions, data, Bool(false))
def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt, error: Bool) = {
val d = Wire(new TLBundleD(bundle))
d.opcode := TLMessages.GrantData
d.param := capPermissions
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.data := data
d.error := error
d.opcode := TLMessages.GrantData
d.param := capPermissions
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.addr_lo := fromAddress
d.data := data
d.error := error
d
}
def ReleaseAck(toSource: UInt, lgSize: UInt) = {
def ReleaseAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt) = {
val d = Wire(new TLBundleD(bundle))
d.opcode := TLMessages.ReleaseAck
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := UInt(0)
d.data := UInt(0)
d.error := Bool(false)
d.opcode := TLMessages.ReleaseAck
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.addr_lo := fromAddress
d.data := UInt(0)
d.error := Bool(false)
d
}
@ -374,8 +482,8 @@ class TLEdgeIn(
b.param := UInt(0)
b.size := lgSize
b.source := toSource
b.address := fromAddress
b.mask := fullMask(fromAddress, lgSize)
b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes)
b.mask := mask(fromAddress, lgSize)
b.data := UInt(0)
(legal, b)
}
@ -388,8 +496,8 @@ class TLEdgeIn(
b.param := UInt(0)
b.size := lgSize
b.source := toSource
b.address := fromAddress
b.mask := fullMask(fromAddress, lgSize)
b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes)
b.mask := mask(fromAddress, lgSize)
b.data := data
(legal, b)
}
@ -402,7 +510,7 @@ class TLEdgeIn(
b.param := UInt(0)
b.size := lgSize
b.source := toSource
b.address := fromAddress
b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes)
b.mask := mask
b.data := data
(legal, b)
@ -416,8 +524,8 @@ class TLEdgeIn(
b.param := atomic
b.size := lgSize
b.source := toSource
b.address := fromAddress
b.mask := fullMask(fromAddress, lgSize)
b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes)
b.mask := mask(fromAddress, lgSize)
b.data := data
(legal, b)
}
@ -430,8 +538,8 @@ class TLEdgeIn(
b.param := atomic
b.size := lgSize
b.source := toSource
b.address := fromAddress
b.mask := fullMask(fromAddress, lgSize)
b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes)
b.mask := mask(fromAddress, lgSize)
b.data := data
(legal, b)
}
@ -444,47 +552,55 @@ class TLEdgeIn(
b.param := param
b.size := lgSize
b.source := toSource
b.address := fromAddress
b.mask := fullMask(fromAddress, lgSize)
b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes)
b.mask := mask(fromAddress, lgSize)
b.data := UInt(0)
(legal, b)
}
def AccessAck(toSource: UInt, lgSize: UInt): TLBundleD = AccessAck(toSource, lgSize, Bool(false))
def AccessAck(toSource: UInt, lgSize: UInt, error: Bool) = {
def AccessAck(a: TLBundleA, fromSink: UInt): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size)
def AccessAck(a: TLBundleA, fromSink: UInt, error: Bool): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size, error)
def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt): TLBundleD = AccessAck(fromAddress, fromSink, toSource, lgSize, Bool(false))
def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, error: Bool) = {
val d = Wire(new TLBundleD(bundle))
d.opcode := TLMessages.AccessAck
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := UInt(0)
d.data := UInt(0)
d.error := error
d.opcode := TLMessages.AccessAck
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.addr_lo := fromAddress
d.data := UInt(0)
d.error := error
d
}
def AccessAck(toSource: UInt, lgSize: UInt, data: UInt): TLBundleD = AccessAck(toSource, lgSize, data, Bool(false))
def AccessAck(toSource: UInt, lgSize: UInt, data: UInt, error: Bool) = {
def AccessAck(a: TLBundleA, fromSink: UInt, data: UInt): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size, data)
def AccessAck(a: TLBundleA, fromSink: UInt, data: UInt, error: Bool): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size, data, error)
def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, data: UInt): TLBundleD = AccessAck(fromAddress, fromSink, toSource, lgSize, data, Bool(false))
def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, data: UInt, error: Bool) = {
val d = Wire(new TLBundleD(bundle))
d.opcode := TLMessages.AccessAckData
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := UInt(0)
d.data := data
d.error := error
d.opcode := TLMessages.AccessAckData
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.addr_lo := fromAddress
d.data := data
d.error := error
d
}
def HintAck(toSource: UInt, lgSize: UInt) = {
def HintAck(a: TLBundleA, sink: UInt = UInt(0)): TLBundleD = HintAck(address(a), sink, a.source, a.size)
def HintAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt) = {
val d = Wire(new TLBundleD(bundle))
d.opcode := TLMessages.HintAck
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := UInt(0)
d.data := UInt(0)
d.error := Bool(false)
d.opcode := TLMessages.HintAck
d.param := UInt(0)
d.size := lgSize
d.source := toSource
d.sink := fromSink
d.addr_lo := fromAddress
d.data := UInt(0)
d.error := Bool(false)
d
}
}

View File

@ -57,7 +57,9 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
}
// All managers must share a common FIFO domain (responses might end up interleaved)
val manager = node.edgesOut(0).manager
val edgeOut = node.edgesOut(0)
val edgeIn = node.edgesIn(0)
val manager = edgeOut.manager
val managers = manager.managers
val beatBytes = manager.beatBytes
val fifoId = managers(0).fifoId
@ -137,9 +139,6 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
val counterBits = log2Up(maxSize/beatBytes)
val maxDownSize = if (alwaysMin) minSize else manager.maxTransfer
def OH1ToUInt(x: UInt) = OHToUInt((x << 1 | UInt(1)) ^ x)
def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0)
// First, handle the return path
val acknum = RegInit(UInt(0, width = counterBits))
val dOrig = Reg(UInt())
@ -147,7 +146,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
val dFirst = acknum === UInt(0)
val dsizeOH = UIntToOH (out.d.bits.size, log2Ceil(maxDownSize)+1)
val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Ceil(maxDownSize))
val dHasData = node.edgesOut(0).hasData(out.d.bits)
val dHasData = edgeOut.hasData(out.d.bits)
// calculate new acknum
val acknum_fragment = dFragnum << log2Ceil(minSize/beatBytes)
@ -189,7 +188,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
val maxLgHints = maxHints .map(m => if (m == 0) lgMinSize else UInt(log2Ceil(m)))
// If this is infront of a single manager, these become constants
val find = manager.find(in.a.bits.address)
val find = manager.find(edgeIn.address(in.a.bits))
val maxLgArithmetic = Mux1H(find, maxLgArithmetics)
val maxLgLogical = Mux1H(find, maxLgLogicals)
val maxLgGet = Mux1H(find, maxLgGets)
@ -225,7 +224,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
out.a.valid := in.a.valid
in.a.ready := out.a.ready && !delay
out.a.bits := in.a.bits
out.a.bits.address := in.a.bits.address | (~aFragnum << log2Ceil(minSize) & aOrigOH1)
out.a.bits.addr_hi := in.a.bits.addr_hi | (~aFragnum << log2Ceil(minSize/beatBytes) & aOrigOH1 >> log2Ceil(beatBytes))
out.a.bits.source := Cat(in.a.bits.source, aFragnum)
out.a.bits.size := aFrag

View File

@ -28,13 +28,13 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
require (!supportClients || bce)
if (supportManagers) {
val handleA = if (passthrough) !edgeOut.manager.supportsHint(in.a.bits.address) else Bool(true)
val handleA = if (passthrough) !edgeOut.manager.supportsHint(edgeIn.address(in.a.bits)) else Bool(true)
val bypassD = handleA && in.a.bits.opcode === TLMessages.Hint
// Prioritize existing D traffic over HintAck
in.d.valid := out.d.valid || (bypassD && in.a.valid)
out.d.ready := in.d.ready
in.d.bits := Mux(out.d.valid, out.d.bits, edgeIn.HintAck(in.a.bits.source, in.a.bits.size))
in.d.bits := Mux(out.d.valid, out.d.bits, edgeIn.HintAck(in.a.bits))
in.a.ready := Mux(bypassD, in.d.ready && !out.d.valid, out.a.ready)
out.a.valid := in.a.valid && !bypassD
@ -56,7 +56,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
// Prioritize existing C traffic over HintAck
out.c.valid := in.c.valid || (bypassC && in.b.valid)
in.c.ready := out.c.ready
out.c.bits := Mux(in.c.valid, in.c.bits, edgeOut.HintAck(out.b.bits.address, out.b.bits.size))
out.c.bits := Mux(in.c.valid, in.c.bits, edgeOut.HintAck(out.b.bits))
out.b.ready := Mux(bypassC, out.c.ready && !in.c.valid, in.b.ready)
in.b.valid := out.b.valid && !bypassC

View File

@ -50,7 +50,7 @@ object LazyModule
}
}
abstract class LazyModuleImp(val outer: LazyModule) extends Module
abstract class LazyModuleImp(outer: LazyModule) extends Module
{
// .module had better not be accessed while LazyModules are still being built!
require (LazyModule.stack.isEmpty)

View File

@ -104,14 +104,14 @@ class TLLegacy(implicit val p: Parameters) extends LazyModule with HasTileLinkPa
// Get rid of some unneeded muxes
out.a.bits.source := source
out.a.bits.data := data
out.a.bits.address := ~(~address | addressMask)
out.a.bits.addr_hi := ~(~address | addressMask) >> log2Ceil(tlDataBytes)
// TL legacy does not support bus errors
assert (!out.d.bits.error)
// Recreate the beat address counter
val beatCounter = RegInit(UInt(0, width = tlBeatAddrBits))
when (out.d.fire() && out.d.bits.hasData() && out.d.bits.size === block) {
when (out.d.fire() && edge.hasData(out.d.bits) && out.d.bits.size === block) {
beatCounter := beatCounter + UInt(1)
}

View File

@ -19,20 +19,20 @@ object TLMonitor
// Reuse these subexpressions to save some firrtl lines
val source_ok = edge.client.contains(bundle.source)
val is_aligned = edge.isAligned(bundle.address, bundle.size)
val mask = edge.fullMask(bundle.address | edge.lowAddress(bundle.mask), bundle.size)
val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size)
val mask = edge.mask(edge.addr_lo(bundle.mask), bundle.size)
when (bundle.opcode === TLMessages.Acquire) {
assert (edge.manager.supportsAcquire(bundle.address, bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra)
assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra)
assert (source_ok, "'A' channel Acquire carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra)
assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra)
assert (TLPermissions.isGrow(bundle.param), "'A' channel Acquire carries invalid grow param" + extra)
assert (bundle.mask === SInt(-1).asUInt, "'A' channel Acquire contains invalid mask" + extra)
assert (~bundle.mask === UInt(0), "'A' channel Acquire contains invalid mask" + extra)
}
when (bundle.opcode === TLMessages.Get) {
assert (edge.manager.supportsGet(bundle.address, bundle.size), "'A' channel carries Get type unsupported by manager" + extra)
assert (edge.manager.supportsGet(edge.address(bundle), bundle.size), "'A' channel carries Get type unsupported by manager" + extra)
assert (source_ok, "'A' channel Get carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Get address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'A' channel Get carries invalid param" + extra)
@ -40,7 +40,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.PutFullData) {
assert (edge.manager.supportsPutFull(bundle.address, bundle.size), "'A' channel carries PutFull type unsupported by manager" + extra)
assert (edge.manager.supportsPutFull(edge.address(bundle), bundle.size), "'A' channel carries PutFull type unsupported by manager" + extra)
assert (source_ok, "'A' channel PutFull carries invalid source ID" + extra)
assert (is_aligned, "'A' channel PutFull address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'A' channel PutFull carries invalid param" + extra)
@ -48,7 +48,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.PutPartialData) {
assert (edge.manager.supportsPutPartial(bundle.address, bundle.size), "'A' channel carries PutPartial type unsupported by manager" + extra)
assert (edge.manager.supportsPutPartial(edge.address(bundle), bundle.size), "'A' channel carries PutPartial type unsupported by manager" + extra)
assert (source_ok, "'A' channel PutPartial carries invalid source ID" + extra)
assert (is_aligned, "'A' channel PutPartial address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'A' channel PutPartial carries invalid param" + extra)
@ -57,7 +57,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.ArithmeticData) {
assert (edge.manager.supportsArithmetic(bundle.address, bundle.size), "'A' channel carries Arithmetic type unsupported by manager" + extra)
assert (edge.manager.supportsArithmetic(edge.address(bundle), bundle.size), "'A' channel carries Arithmetic type unsupported by manager" + extra)
assert (source_ok, "'A' channel Arithmetic carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Arithmetic address not aligned to size" + extra)
assert (TLAtomics.isArithmetic(bundle.param), "'A' channel Arithmetic carries invalid opcode param" + extra)
@ -65,7 +65,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.LogicalData) {
assert (edge.manager.supportsLogical(bundle.address, bundle.size), "'A' channel carries Logical type unsupported by manager" + extra)
assert (edge.manager.supportsLogical(edge.address(bundle), bundle.size), "'A' channel carries Logical type unsupported by manager" + extra)
assert (source_ok, "'A' channel Logical carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Logical address not aligned to size" + extra)
assert (TLAtomics.isLogical(bundle.param), "'A' channel Logical carries invalid opcode param" + extra)
@ -73,7 +73,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.Hint) {
assert (edge.manager.supportsHint(bundle.address), "'A' channel carries Hint type unsupported by manager" + extra)
assert (edge.manager.supportsHint(edge.address(bundle)), "'A' channel carries Hint type unsupported by manager" + extra)
assert (source_ok, "'A' channel Hint carries invalid source ID" + extra)
assert (is_aligned, "'A' channel Hint address not aligned to size" + extra)
assert (bundle.mask === mask, "'A' channel Hint contains invalid mask" + extra)
@ -85,8 +85,8 @@ object TLMonitor
// Reuse these subexpressions to save some firrtl lines
val address_ok = edge.manager.contains(bundle.source)
val is_aligned = edge.isAligned(bundle.address, bundle.size)
val mask = edge.fullMask(bundle.address | edge.lowAddress(bundle.mask), bundle.size)
val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size)
val mask = edge.mask(edge.addr_lo(bundle.mask), bundle.size)
when (bundle.opcode === TLMessages.Probe) {
assert (edge.client.supportsProbe(bundle.source, bundle.size), "'B' channel carries Probe type unsupported by client" + extra)
@ -94,7 +94,7 @@ object TLMonitor
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'B' channel Probe smaller than a beat" + extra)
assert (is_aligned, "'B' channel Probe address not aligned to size" + extra)
assert (TLPermissions.isCap(bundle.param), "'B' channel Probe carries invalid cap param" + extra)
assert (bundle.mask === SInt(-1).asUInt, "'B' channel Probe contains invalid mask" + extra)
assert (~bundle.mask === UInt(0).asUInt, "'B' channel Probe contains invalid mask" + extra)
}
when (bundle.opcode === TLMessages.Get) {
@ -150,12 +150,12 @@ object TLMonitor
assert (TLMessages.isC(bundle.opcode), "'C' channel has invalid opcode" + extra)
val source_ok = edge.client.contains(bundle.source)
val is_aligned = edge.isAligned(bundle.address, bundle.size)
val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size) && edge.isLoAligned(bundle.addr_lo, bundle.size)
val address_ok = edge.manager.contains(bundle.source)
when (bundle.opcode === TLMessages.ProbeAck) {
assert (address_ok, "'C' channel ProbeAck carries unmanaged address" + extra)
// source is ignored
assert (source_ok, "'C' channel ProbeAck carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ProbeAck smaller than a beat" + extra)
assert (is_aligned, "'C' channel ProbeAck address not aligned to size" + extra)
assert (TLPermissions.isReport(bundle.param), "'C' channel ProbeAck carries invalid report param" + extra)
@ -164,7 +164,7 @@ object TLMonitor
when (bundle.opcode === TLMessages.ProbeAckData) {
assert (address_ok, "'C' channel ProbeAckData carries unmanaged address" + extra)
// source is ignored
assert (source_ok, "'C' channel ProbeAckData carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ProbeAckData smaller than a beat" + extra)
assert (is_aligned, "'C' channel ProbeAckData address not aligned to size" + extra)
assert (TLPermissions.isReport(bundle.param), "'C' channel ProbeAckData carries invalid report param" + extra)
@ -172,7 +172,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.Release) {
assert (edge.manager.supportsAcquire(bundle.address, bundle.size), "'C' channel carries Release type unsupported by manager" + extra)
assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'C' channel carries Release type unsupported by manager" + extra)
assert (source_ok, "'C' channel Release carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel Release smaller than a beat" + extra)
assert (is_aligned, "'C' channel Release address not aligned to size" + extra)
@ -181,7 +181,7 @@ object TLMonitor
}
when (bundle.opcode === TLMessages.ReleaseData) {
assert (edge.manager.supportsAcquire(bundle.address, bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra)
assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra)
assert (source_ok, "'C' channel ReleaseData carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ReleaseData smaller than a beat" + extra)
assert (is_aligned, "'C' channel ReleaseData address not aligned to size" + extra)
@ -191,21 +191,21 @@ object TLMonitor
when (bundle.opcode === TLMessages.AccessAck) {
assert (address_ok, "'C' channel AccessAck carries unmanaged address" + extra)
// source is ignored
assert (source_ok, "'C' channel AccessAck carries invalid source ID" + extra)
assert (is_aligned, "'C' channel AccessAck address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'C' channel AccessAck carries invalid param" + extra)
}
when (bundle.opcode === TLMessages.AccessAckData) {
assert (address_ok, "'C' channel AccessAckData carries unmanaged address" + extra)
// source is ignored
assert (source_ok, "'C' channel AccessAckData carries invalid source ID" + extra)
assert (is_aligned, "'C' channel AccessAckData address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'C' channel AccessAckData carries invalid param" + extra)
}
when (bundle.opcode === TLMessages.HintAck) {
assert (address_ok, "'C' channel HintAck carries unmanaged address" + extra)
// source is ignored
assert (source_ok, "'C' channel HintAck carries invalid source ID" + extra)
assert (is_aligned, "'C' channel HintAck address not aligned to size" + extra)
assert (bundle.param === UInt(0), "'C' channel HintAck carries invalid param" + extra)
assert (!bundle.error, "'C' channel HintAck carries an error" + extra)
@ -216,11 +216,13 @@ object TLMonitor
assert (TLMessages.isD(bundle.opcode), "'D' channel has invalid opcode" + extra)
val source_ok = edge.client.contains(bundle.source)
val is_aligned = edge.isLoAligned(bundle.addr_lo, bundle.size)
val sink_ok = edge.manager.containsById(bundle.sink)
when (bundle.opcode === TLMessages.ReleaseAck) {
assert (source_ok, "'D' channel ReleaseAck carries invalid source ID" + extra)
// sink is ignored
assert (is_aligned, "'D' channel ReleaseAck address not aligned to size" + extra)
assert (sink_ok, "'D' channel ReleaseAck carries invalid sink ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'D' channel ReleaseAck smaller than a beat" + extra)
assert (bundle.param === UInt(0), "'D' channel ReleaseeAck carries invalid param" + extra)
assert (!bundle.error, "'D' channel ReleaseAck carries an error" + extra)
@ -228,6 +230,7 @@ object TLMonitor
when (bundle.opcode === TLMessages.Grant) {
assert (source_ok, "'D' channel Grant carries invalid source ID" + extra)
assert (is_aligned, "'D' channel Grant address not aligned to size" + extra)
assert (sink_ok, "'D' channel Grant carries invalid sink ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'D' channel Grant smaller than a beat" + extra)
assert (TLPermissions.isCap(bundle.param), "'D' channel Grant carries invalid cap param" + extra)
@ -235,6 +238,7 @@ object TLMonitor
when (bundle.opcode === TLMessages.GrantData) {
assert (source_ok, "'D' channel GrantData carries invalid source ID" + extra)
assert (is_aligned, "'D' channel GrantData address not aligned to size" + extra)
assert (sink_ok, "'D' channel GrantData carries invalid sink ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'D' channel GrantData smaller than a beat" + extra)
assert (TLPermissions.isCap(bundle.param), "'D' channel GrantData carries invalid cap param" + extra)
@ -242,21 +246,24 @@ object TLMonitor
when (bundle.opcode === TLMessages.AccessAck) {
assert (source_ok, "'D' channel AccessAck carries invalid source ID" + extra)
// sink is ignored
assert (is_aligned, "'D' channel AccessAck address not aligned to size" + extra)
assert (sink_ok, "'D' channel AccessAck carries invalid sink ID" + extra)
// size is ignored
assert (bundle.param === UInt(0), "'D' channel AccessAck carries invalid param" + extra)
}
when (bundle.opcode === TLMessages.AccessAckData) {
assert (source_ok, "'D' channel AccessAckData carries invalid source ID" + extra)
// sink is ignored
assert (is_aligned, "'D' channel AccessAckData address not aligned to size" + extra)
assert (sink_ok, "'D' channel AccessAckData carries invalid sink ID" + extra)
// size is ignored
assert (bundle.param === UInt(0), "'D' channel AccessAckData carries invalid param" + extra)
}
when (bundle.opcode === TLMessages.HintAck) {
assert (source_ok, "'D' channel HintAck carries invalid source ID" + extra)
// sink is ignored
assert (is_aligned, "'D' channel HintAck address not aligned to size" + extra)
assert (sink_ok, "'D' channel HintAck carries invalid sink ID" + extra)
// size is ignored
assert (bundle.param === UInt(0), "'D' channel HintAck carries invalid param" + extra)
assert (!bundle.error, "'D' channel HintAck carries an error" + extra)
@ -281,13 +288,13 @@ object TLMonitor
val param = Reg(UInt())
val size = Reg(UInt())
val source = Reg(UInt())
val address = Reg(UInt())
val addr_hi = Reg(UInt())
when (a.valid && counter =/= UInt(0)) {
assert (a.bits.opcode === opcode, "'A' channel opcode changed within multibeat operation" + extra)
assert (a.bits.param === param, "'A' channel param changed within multibeat operation" + extra)
assert (a.bits.size === size, "'A' channel size changed within multibeat operation" + extra)
assert (a.bits.source === source, "'A' channel source changed within multibeat operation" + extra)
assert (a.bits.address=== address,"'A' channel address changed with multibeat operation" + extra)
assert (a.bits.addr_hi=== addr_hi,"'A' channel addr_hi changed with multibeat operation" + extra)
}
when (a.fire()) {
counter := counter - UInt(1)
@ -297,7 +304,7 @@ object TLMonitor
param := a.bits.param
size := a.bits.size
source := a.bits.source
address := a.bits.address
addr_hi := a.bits.addr_hi
}
}
}
@ -308,13 +315,13 @@ object TLMonitor
val param = Reg(UInt())
val size = Reg(UInt())
val source = Reg(UInt())
val address = Reg(UInt())
val addr_hi = Reg(UInt())
when (b.valid && counter =/= UInt(0)) {
assert (b.bits.opcode === opcode, "'B' channel opcode changed within multibeat operation" + extra)
assert (b.bits.param === param, "'B' channel param changed within multibeat operation" + extra)
assert (b.bits.size === size, "'B' channel size changed within multibeat operation" + extra)
assert (b.bits.source === source, "'B' channel source changed within multibeat operation" + extra)
assert (b.bits.address=== address,"'B' channel address changed with multibeat operation" + extra)
assert (b.bits.addr_hi=== addr_hi,"'B' channel addr_hi changed with multibeat operation" + extra)
}
when (b.fire()) {
counter := counter - UInt(1)
@ -324,7 +331,7 @@ object TLMonitor
param := b.bits.param
size := b.bits.size
source := b.bits.source
address := b.bits.address
addr_hi := b.bits.addr_hi
}
}
}
@ -335,13 +342,15 @@ object TLMonitor
val param = Reg(UInt())
val size = Reg(UInt())
val source = Reg(UInt())
val address = Reg(UInt())
val addr_hi = Reg(UInt())
val addr_lo = Reg(UInt())
when (c.valid && counter =/= UInt(0)) {
assert (c.bits.opcode === opcode, "'C' channel opcode changed within multibeat operation" + extra)
assert (c.bits.param === param, "'C' channel param changed within multibeat operation" + extra)
assert (c.bits.size === size, "'C' channel size changed within multibeat operation" + extra)
assert (c.bits.source === source, "'C' channel source changed within multibeat operation" + extra)
assert (c.bits.address=== address,"'C' channel address changed with multibeat operation" + extra)
assert (c.bits.addr_hi=== addr_hi,"'C' channel addr_hi changed with multibeat operation" + extra)
assert (c.bits.addr_lo=== addr_lo,"'C' channel addr_lo changed with multibeat operation" + extra)
}
when (c.fire()) {
counter := counter - UInt(1)
@ -351,7 +360,8 @@ object TLMonitor
param := c.bits.param
size := c.bits.size
source := c.bits.source
address := c.bits.address
addr_hi := c.bits.addr_hi
addr_lo := c.bits.addr_lo
}
}
}
@ -363,12 +373,14 @@ object TLMonitor
val size = Reg(UInt())
val source = Reg(UInt())
val sink = Reg(UInt())
val addr_lo = Reg(UInt())
when (d.valid && counter =/= UInt(0)) {
assert (d.bits.opcode === opcode, "'D' channel opcode changed within multibeat operation" + extra)
assert (d.bits.param === param, "'D' channel param changed within multibeat operation" + extra)
assert (d.bits.size === size, "'D' channel size changed within multibeat operation" + extra)
assert (d.bits.source === source, "'D' channel source changed within multibeat operation" + extra)
assert (d.bits.sink === sink, "'D' channel sink changed with multibeat operation" + extra)
assert (d.bits.addr_lo=== addr_lo,"'C' channel addr_lo changed with multibeat operation" + extra)
}
when (d.fire()) {
counter := counter - UInt(1)
@ -379,6 +391,7 @@ object TLMonitor
size := d.bits.size
source := d.bits.source
sink := d.bits.sink
addr_lo := d.bits.addr_lo
}
}
}

View File

@ -19,25 +19,25 @@ class TLNarrower(innerBeatBytes: Int) extends LazyModule
val out = node.bundleOut
}
val edge = node.edgesOut(0)
val outerBeatBytes = edge.manager.beatBytes
val edgeOut = node.edgesOut(0)
val edgeIn = node.edgesIn(0)
val outerBeatBytes = edgeOut.manager.beatBytes
require (outerBeatBytes < innerBeatBytes)
val ratio = innerBeatBytes / outerBeatBytes
val bce = edge.manager.anySupportAcquire && edge.client.anySupportProbe
val bce = edgeOut.manager.anySupportAcquire && edgeIn.client.anySupportProbe
def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0)
def trailingZeros(x: Int) = if (x > 0) Some(log2Ceil(x & -x)) else None
def split(in: HasTLData, fire: Bool): (Bool, UInt, UInt) = {
val dataSlices = Vec.tabulate (ratio) { i => in.data()((i+1)*outerBeatBytes*8-1, i*outerBeatBytes*8) }
val maskSlices = Vec.tabulate (ratio) { i => in.mask()((i+1)*outerBeatBytes -1, i*outerBeatBytes) }
def split(edge: TLEdge, in: TLDataChannel, fire: Bool): (Bool, UInt, UInt) = {
val dataSlices = Vec.tabulate (ratio) { i => edge.data(in)((i+1)*outerBeatBytes*8-1, i*outerBeatBytes*8) }
val maskSlices = Vec.tabulate (ratio) { i => edge.mask(in)((i+1)*outerBeatBytes -1, i*outerBeatBytes) }
val filter = Reg(UInt(width = ratio), init = SInt(-1, width = ratio).asUInt)
val mask = maskSlices.map(_.orR)
val hasData = edge.hasData(in)
// decoded_size = 1111 (for smallest), 0101, 0001 (for largest)
val sizeOH1 = UIntToOH1(in.size(), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes)
val sizeOH1 = UIntToOH1(edge.size(in), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes)
val decoded_size = Seq.tabulate(ratio) { i => trailingZeros(i).map(!sizeOH1(_)).getOrElse(Bool(true)) }
val first = filter(ratio-1)
@ -56,12 +56,12 @@ class TLNarrower(innerBeatBytes: Int) extends LazyModule
}
}
def merge(in: HasTLData, fire: Bool): (Bool, UInt) = {
def merge(edge: TLEdge, in: TLDataChannel, fire: Bool): (Bool, UInt) = {
val count = RegInit(UInt(0, width = log2Ceil(ratio)))
val rdata = Reg(UInt(width = (ratio-1)*outerBeatBytes*8))
val data = Cat(in.data(), rdata)
val data = Cat(edge.data(in), rdata)
val first = count === UInt(0)
val limit = UIntToOH1(in.size(), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes)
val limit = UIntToOH1(edge.size(in), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes)
val last = count === limit || !edge.hasData(in)
when (fire) {
@ -82,21 +82,22 @@ class TLNarrower(innerBeatBytes: Int) extends LazyModule
if (edge.staticHasData(in) == Some(false)) {
(Bool(true), UInt(0))
} else {
(last, mux(in.size()))
(last, mux(edge.size(in)))
}
}
val in = io.in(0)
val out = io.out(0)
val (alast, adata, amask) = split(in.a.bits, out.a.fire())
val (alast, adata, amask) = split(edgeIn, in.a.bits, out.a.fire())
in.a.ready := out.a.ready && alast
out.a.valid := in.a.valid
out.a.bits := in.a.bits
out.a.bits.addr_hi := Cat(in.a.bits.addr_hi, edgeIn.addr_lo(in.a.bits) >> log2Ceil(outerBeatBytes))
out.a.bits.data := adata
out.a.bits.mask := amask
val (dlast, ddata) = merge(out.d.bits, out.d.fire())
val (dlast, ddata) = merge(edgeOut, out.d.bits, out.d.fire())
out.d.ready := in.d.ready || !dlast
in.d.valid := out.d.valid && dlast
in.d.bits := out.d.bits

View File

@ -286,23 +286,25 @@ case class TLClientPortParameters(clients: Seq[TLClientParameters]) {
}
case class TLBundleParameters(
addressBits: Int,
dataBits: Int,
sourceBits: Int,
sinkBits: Int,
sizeBits: Int)
addrHiBits: Int,
dataBits: Int,
sourceBits: Int,
sinkBits: Int,
sizeBits: Int)
{
// Chisel has issues with 0-width wires
require (addressBits >= 1)
require (dataBits >= 1)
require (addrHiBits >= 1)
require (dataBits >= 8)
require (sourceBits >= 1)
require (sinkBits >= 1)
require (sizeBits >= 1)
require (isPow2(dataBits))
val addrLoBits = log2Up(dataBits/8)
def union(x: TLBundleParameters) =
TLBundleParameters(
max(addressBits, x.addressBits),
max(addrHiBits, x.addrHiBits),
max(dataBits, x.dataBits),
max(sourceBits, x.sourceBits),
max(sinkBits, x.sinkBits),
@ -320,7 +322,7 @@ case class TLEdgeParameters(
require (maxTransfer >= manager.beatBytes)
val bundle = TLBundleParameters(
addressBits = log2Up(manager.maxAddress + 1),
addrHiBits = log2Up(manager.maxAddress + 1) - log2Up(manager.beatBytes),
dataBits = manager.beatBytes * 8,
sourceBits = log2Up(client.endSourceId),
sinkBits = log2Up(manager.endSinkId),

View File

@ -20,14 +20,20 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB
val a = bundleIn(0).a
val d = bundleIn(0).d
val edge = edgesIn(0)
val params = RegMapperParams(log2Up(address.mask+1), beatBytes, edge.bundle.sourceBits + edge.bundle.sizeBits)
// Please forgive me ...
val baseEnd = 0
val (sizeEnd, sizeOff) = (edge.bundle.sizeBits + baseEnd, baseEnd)
val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd)
val (addrLoEnd, addrLoOff) = (log2Ceil(beatBytes) + sourceEnd, sourceEnd)
val params = RegMapperParams(log2Up(address.mask+1), beatBytes, addrLoEnd)
val in = Wire(Decoupled(new RegMapperInput(params)))
in.bits.read := a.bits.opcode === TLMessages.Get
in.bits.index := a.bits.address >> log2Ceil(beatBytes)
in.bits.index := a.bits.addr_hi
in.bits.data := a.bits.data
in.bits.mask := a.bits.mask
in.bits.extra := Cat(a.bits.source, a.bits.size)
in.bits.extra := Cat(edge.addr_lo(a.bits), a.bits.source, a.bits.size)
// Invoke the register map builder
val (endIndex, out) = RegMapper(beatBytes, concurrency, in, mapping:_*)
@ -41,8 +47,13 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB
d.valid := out.valid
out.ready := d.ready
val sizeBits = edge.bundle.sizeBits
d.bits := edge.AccessAck(out.bits.extra >> sizeBits, out.bits.extra(sizeBits-1, 0))
// We must restore the size and addr_lo to enable width adapters to work
d.bits := edge.AccessAck(
fromAddress = out.bits.extra(addrLoEnd-1, addrLoOff),
fromSink = UInt(0), // our unique sink id
toSource = out.bits.extra(sourceEnd-1, sourceOff),
lgSize = out.bits.extra(sizeEnd-1, sizeOff))
// avoid a Mux on the data bus by manually overriding two fields
d.bits.data := out.bits.data
d.bits.opcode := Mux(out.bits.read, TLMessages.AccessAckData, TLMessages.AccessAck)

View File

@ -24,10 +24,10 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)
val mask = bigBits(address.mask - (beatBytes-1))
val mask = bigBits(address.mask >> log2Ceil(beatBytes))
val in = io.in(0)
val addrBits = (mask zip in.a.bits.address.toBools).filter(_._1).map(_._2)
val addrBits = (mask zip in.a.bits.addr_hi.toBools).filter(_._1).map(_._2)
val memAddress = Cat(addrBits.reverse)
val mem = SeqMem(1 << addrBits.size, Vec(beatBytes, Bits(width = 8)))
@ -35,6 +35,7 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule
val d_read = Reg(Bool())
val d_size = Reg(UInt())
val d_source = Reg(UInt())
val d_addr = Reg(UInt())
val d_data = Wire(UInt())
// Flow control
@ -43,7 +44,8 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule
in.d.valid := d_full
in.a.ready := in.d.ready || !d_full
in.d.bits := node.edgesIn(0).AccessAck(d_source, d_size)
val edge = node.edgesIn(0)
in.d.bits := edge.AccessAck(d_addr, UInt(0), d_source, d_size)
// avoid data-bus Mux
in.d.bits.data := d_data
in.d.bits.opcode := Mux(d_read, TLMessages.AccessAckData, TLMessages.AccessAck)
@ -56,6 +58,7 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule
d_read := read
d_size := in.a.bits.size
d_source := in.a.bits.source
d_addr := edge.addr_lo(in.a.bits)
when (read) {
rdata := mem.read(memAddress)
} .otherwise {

View File

@ -23,10 +23,6 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
require (eo.asInstanceOf[TLEdgeParameters] == ei.asInstanceOf[TLEdgeParameters])
TLMonitor.legalize(bo, eo, bi, ei)
bi <> bo
val mask = UInt(ei.manager.beatBytes - 1)
bi.a.bits.address := ~(mask | ~bo.a.bits.address)
bo.b.bits.address := ~(mask | ~bi.b.bits.address)
bi.c.bits.address := ~(mask | ~bo.c.bits.address)
}
}

View File

@ -145,11 +145,11 @@ class TLXbar(policy: (Vec[Bool], Bool) => Seq[Bool] = TLXbar.lowestIndex) extend
in(i).e.ready := Mux1C(grantedEIO(i), out.map(_.e.ready))
}
val requestAIO = Vec(in.map { i => Vec(node.edgesOut.map { o => i.a.valid && o.manager.contains(i.a.bits.address) }) })
val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.b.valid && i .contains(o.b.bits.source) }) })
val requestCIO = Vec(in.map { i => Vec(node.edgesOut.map { o => i.c.valid && o.manager.contains(i.c.bits.address) }) })
val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.d.valid && i .contains(o.d.bits.source) }) })
val requestEIO = Vec(in.map { i => Vec(outputIdRanges.map { o => i.e.valid && o .contains(i.e.bits.sink) }) })
val requestAIO = Vec(in.map { i => Vec(node.edgesOut.map { o => i.a.valid && o.manager.contains(o.address(i.a.bits)) }) })
val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.b.valid && i .contains(o.b.bits.source) }) })
val requestCIO = Vec(in.map { i => Vec(node.edgesOut.map { o => i.c.valid && o.manager.contains(o.address(i.c.bits)) }) })
val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map { i => o.d.valid && i .contains(o.d.bits.source) }) })
val requestEIO = Vec(in.map { i => Vec(outputIdRanges.map { o => i.e.valid && o .contains(i.e.bits.sink) }) })
val beatsA = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats(i.a.bits) })
val beatsB = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats(o.b.bits) })

View File

@ -5,4 +5,6 @@ import Chisel._
package object tilelink2
{
type TLBaseNode = BaseNode[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle]
def OH1ToUInt(x: UInt) = OHToUInt((x << 1 | UInt(1)) ^ x)
def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0)
}