From 11b0272d917c25706cc837382abc9b2c511321d1 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 2 Sep 2016 19:55:08 -0700 Subject: [PATCH] tilelink2: create optimized hasData method on edges (statically evaluates if known) --- uncore/src/main/scala/tilelink2/Bundles.scala | 17 ++++++++ uncore/src/main/scala/tilelink2/Edges.scala | 41 ++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/uncore/src/main/scala/tilelink2/Bundles.scala b/uncore/src/main/scala/tilelink2/Bundles.scala index 88b742d7..0c0a95e4 100644 --- a/uncore/src/main/scala/tilelink2/Bundles.scala +++ b/uncore/src/main/scala/tilelink2/Bundles.scala @@ -106,12 +106,24 @@ object Bogus def apply() = new Bogus } +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 } @@ -142,6 +154,7 @@ class TLBundleA(params: TLBundleParameters) // 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 @@ -163,6 +176,7 @@ class TLBundleB(params: TLBundleParameters) 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 @@ -189,6 +203,7 @@ class TLBundleC(params: TLBundleParameters) 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 @@ -214,6 +229,7 @@ class TLBundleD(params: TLBundleParameters) 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 @@ -227,6 +243,7 @@ class TLBundleE(params: TLBundleParameters) 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)) } diff --git a/uncore/src/main/scala/tilelink2/Edges.scala b/uncore/src/main/scala/tilelink2/Edges.scala index cd1a2449..0d178560 100644 --- a/uncore/src/main/scala/tilelink2/Edges.scala +++ b/uncore/src/main/scala/tilelink2/Edges.scala @@ -39,8 +39,47 @@ class TLEdge( Cat(helper(lgBytes).map(_._1).reverse) } + def staticHasData(bundle: HasTLOpcode): Option[Boolean] = { + bundle.channelType() match { + case ChannelType.A => { + // Do there exist A messages with Data? + val aDataYes = manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportPutFull || manager.anySupportPutPartial + // Do there exist A messages without Data? + val aDataNo = manager.anySupportAcquire || manager.anySupportGet || manager.anySupportHint + // Statically optimize the case where hasData is a constant + if (!aDataYes) Some(false) else if (!aDataNo) Some(true) else None + } + case ChannelType.B => { + // Do there exist B messages with Data? + val bDataYes = client.anySupportArithmetic || client.anySupportLogical || client.anySupportPutFull || client.anySupportPutPartial + // Do there exist B messages without Data? + val bDataNo = client.anySupportProbe || client.anySupportGet || client.anySupportHint + // Statically optimize the case where hasData is a constant + if (!bDataYes) Some(false) else if (!bDataNo) Some(true) else None + } + case ChannelType.C => { + // 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 => { + // 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) + } + } + + def hasData(bundle: HasTLOpcode): Bool = + staticHasData(bundle).map(Bool(_)).getOrElse(bundle.hasData()) + def numBeats(bundle: HasTLOpcode) = { - val hasData = bundle.hasData() + val hasData = this.hasData(bundle) val size = bundle.size() val cutoff = log2Ceil(manager.beatBytes) val small = size <= UInt(cutoff)