From 4be3b6fbb5f3da183026c87d2be356bffee5da89 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Fri, 5 Apr 2024 09:05:07 -0700 Subject: [PATCH] Add requireIsAnnotatable for better errors when annotating literals (#3968) --- core/src/main/scala/chisel3/dontTouch.scala | 4 ++-- .../main/scala/chisel3/experimental/package.scala | 14 ++++++++++++++ core/src/main/scala/chisel3/package.scala | 4 ++++ .../chisel3/util/experimental/decode/decoder.scala | 4 ++-- src/test/scala/chiselTests/DontTouchSpec.scala | 8 ++++++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/chisel3/dontTouch.scala b/core/src/main/scala/chisel3/dontTouch.scala index 6e06dba977e..6c527b79964 100644 --- a/core/src/main/scala/chisel3/dontTouch.scala +++ b/core/src/main/scala/chisel3/dontTouch.scala @@ -2,7 +2,7 @@ package chisel3 -import chisel3.experimental.{annotate, requireIsHardware, ChiselAnnotation} +import chisel3.experimental.{annotate, requireIsAnnotatable, ChiselAnnotation} import chisel3.properties.Property import chisel3.reflect.DataMirror import firrtl.transforms.DontTouchAnnotation @@ -34,7 +34,7 @@ object dontTouch { * @return Unmodified signal `data` */ def apply[T <: Data](data: T): T = { - requireIsHardware(data, "Data marked dontTouch") + requireIsAnnotatable(data, "Data marked dontTouch") data match { case d if DataMirror.hasProbeTypeModifier(d) => () case _: Property[_] => () diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 755838fa5c5..075b7123881 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -62,6 +62,20 @@ package object experimental { } } + /** Require that a Data can be annotated. It must be non-literal hardware. + */ + object requireIsAnnotatable { + def apply(node: Data, msg: String = ""): Unit = { + requireIsHardware(node, msg) + if (node.isLit) { + val prefix = if (msg.nonEmpty) s"$msg " else "" + throw ExpectedAnnotatableException( + s"$prefix'$node' must not be a literal." + ) + } + } + } + /** Requires that a node is a chisel type (not hardware, "unbound") */ object requireIsChiselType { diff --git a/core/src/main/scala/chisel3/package.scala b/core/src/main/scala/chisel3/package.scala index 9485054ef49..a106167df3f 100644 --- a/core/src/main/scala/chisel3/package.scala +++ b/core/src/main/scala/chisel3/package.scala @@ -398,6 +398,10 @@ package object chisel3 { */ case class ExpectedHardwareException(message: String) extends BindingException(message) + /** A function expected annotatable hardware + */ + case class ExpectedAnnotatableException(message: String) extends BindingException(message) + /** An aggregate had a mix of specified and unspecified directionality children */ case class MixedDirectionAggregateException(message: String) extends BindingException(message) diff --git a/src/main/scala/chisel3/util/experimental/decode/decoder.scala b/src/main/scala/chisel3/util/experimental/decode/decoder.scala index 58585e90fb8..9d3faaa9272 100644 --- a/src/main/scala/chisel3/util/experimental/decode/decoder.scala +++ b/src/main/scala/chisel3/util/experimental/decode/decoder.scala @@ -3,7 +3,7 @@ package chisel3.util.experimental.decode import chisel3._ -import chisel3.experimental.{annotate, ChiselAnnotation} +import chisel3.experimental.{annotate, requireIsAnnotatable, ChiselAnnotation} import chisel3.util.{pla, BitPat} import chisel3.util.experimental.{getAnnotations, BitSet} import firrtl.annotations.Annotation @@ -30,7 +30,7 @@ object decoder extends LazyLogging { val (plaInput, plaOutput) = pla(minimizedTable.table.toSeq, BitPat(minimizedTable.default.value.U(minimizedTable.default.getWidth.W))) - assert(plaOutput.isSynthesizable, s"Using DecodeTableAnnotation on non-hardware value $plaOutput") + requireIsAnnotatable(plaOutput, "DecodeTableAnnotation target") annotate(new ChiselAnnotation { override def toFirrtl: Annotation = DecodeTableAnnotation(plaOutput.toTarget, truthTable.toString, minimizedTable.toString) diff --git a/src/test/scala/chiselTests/DontTouchSpec.scala b/src/test/scala/chiselTests/DontTouchSpec.scala index d239adafbd1..d0c73cf0620 100644 --- a/src/test/scala/chiselTests/DontTouchSpec.scala +++ b/src/test/scala/chiselTests/DontTouchSpec.scala @@ -106,6 +106,14 @@ class DontTouchSpec extends ChiselFlatSpec with Utils { }) } } + it should "not work on literals" in { + val e = the[chisel3.ExpectedAnnotatableException] thrownBy { + ChiselStage.emitCHIRRTL(new Module { + dontTouch(123.U) + }) + } + e.getMessage should include("must not be a literal") + } "fields" should "be marked don't touch by default" in { val (_, annos) = getFirrtlAndAnnos(new HasDeadCodeLeaves())