From d2421654c408b758fffb9f87d3ee0bf026e41796 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 6 Sep 2016 23:46:44 -0700 Subject: [PATCH] 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 --- src/main/scala/uncore/tilelink2/Bundles.scala | 135 ++----- src/main/scala/uncore/tilelink2/Edges.scala | 352 ++++++++++++------ .../scala/uncore/tilelink2/Fragmenter.scala | 13 +- .../scala/uncore/tilelink2/HintHandler.scala | 6 +- .../scala/uncore/tilelink2/LazyModule.scala | 2 +- src/main/scala/uncore/tilelink2/Legacy.scala | 4 +- src/main/scala/uncore/tilelink2/Monitor.scala | 81 ++-- .../scala/uncore/tilelink2/Narrower.scala | 29 +- .../scala/uncore/tilelink2/Parameters.scala | 22 +- .../uncore/tilelink2/RegisterRouter.scala | 23 +- src/main/scala/uncore/tilelink2/SRAM.scala | 9 +- src/main/scala/uncore/tilelink2/TLNodes.scala | 4 - src/main/scala/uncore/tilelink2/Xbar.scala | 10 +- src/main/scala/uncore/tilelink2/package.scala | 2 + 14 files changed, 378 insertions(+), 314 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/Bundles.scala b/src/main/scala/uncore/tilelink2/Bundles.scala index 0c0a95e4..e071c466 100644 --- a/src/main/scala/uncore/tilelink2/Bundles.scala +++ b/src/main/scala/uncore/tilelink2/Bundles.scala @@ -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) diff --git a/src/main/scala/uncore/tilelink2/Edges.scala b/src/main/scala/uncore/tilelink2/Edges.scala index 7b65cabf..75053b88 100644 --- a/src/main/scala/uncore/tilelink2/Edges.scala +++ b/src/main/scala/uncore/tilelink2/Edges.scala @@ -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 } } diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index cec91c59..6364f72a 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -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 diff --git a/src/main/scala/uncore/tilelink2/HintHandler.scala b/src/main/scala/uncore/tilelink2/HintHandler.scala index 1ae934d0..0222991e 100644 --- a/src/main/scala/uncore/tilelink2/HintHandler.scala +++ b/src/main/scala/uncore/tilelink2/HintHandler.scala @@ -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 diff --git a/src/main/scala/uncore/tilelink2/LazyModule.scala b/src/main/scala/uncore/tilelink2/LazyModule.scala index 83386f30..8504e711 100644 --- a/src/main/scala/uncore/tilelink2/LazyModule.scala +++ b/src/main/scala/uncore/tilelink2/LazyModule.scala @@ -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) diff --git a/src/main/scala/uncore/tilelink2/Legacy.scala b/src/main/scala/uncore/tilelink2/Legacy.scala index 91041169..d21503cb 100644 --- a/src/main/scala/uncore/tilelink2/Legacy.scala +++ b/src/main/scala/uncore/tilelink2/Legacy.scala @@ -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) } diff --git a/src/main/scala/uncore/tilelink2/Monitor.scala b/src/main/scala/uncore/tilelink2/Monitor.scala index 8f974a8a..a74a6c20 100644 --- a/src/main/scala/uncore/tilelink2/Monitor.scala +++ b/src/main/scala/uncore/tilelink2/Monitor.scala @@ -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 } } } diff --git a/src/main/scala/uncore/tilelink2/Narrower.scala b/src/main/scala/uncore/tilelink2/Narrower.scala index 4f0401c3..599386d9 100644 --- a/src/main/scala/uncore/tilelink2/Narrower.scala +++ b/src/main/scala/uncore/tilelink2/Narrower.scala @@ -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 diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 0fb438ab..355fdb3a 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -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), diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/uncore/tilelink2/RegisterRouter.scala index e39788e4..e455efda 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouter.scala @@ -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) diff --git a/src/main/scala/uncore/tilelink2/SRAM.scala b/src/main/scala/uncore/tilelink2/SRAM.scala index 28639223..07d107df 100644 --- a/src/main/scala/uncore/tilelink2/SRAM.scala +++ b/src/main/scala/uncore/tilelink2/SRAM.scala @@ -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 { diff --git a/src/main/scala/uncore/tilelink2/TLNodes.scala b/src/main/scala/uncore/tilelink2/TLNodes.scala index f9685a0a..88a27042 100644 --- a/src/main/scala/uncore/tilelink2/TLNodes.scala +++ b/src/main/scala/uncore/tilelink2/TLNodes.scala @@ -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) } } diff --git a/src/main/scala/uncore/tilelink2/Xbar.scala b/src/main/scala/uncore/tilelink2/Xbar.scala index e37e3134..9302ea10 100644 --- a/src/main/scala/uncore/tilelink2/Xbar.scala +++ b/src/main/scala/uncore/tilelink2/Xbar.scala @@ -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) }) diff --git a/src/main/scala/uncore/tilelink2/package.scala b/src/main/scala/uncore/tilelink2/package.scala index 501fdccb..621fc288 100644 --- a/src/main/scala/uncore/tilelink2/package.scala +++ b/src/main/scala/uncore/tilelink2/package.scala @@ -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) }