Skip to content

Commit

Permalink
Add requireIsAnnotatable for better errors when annotating literals
Browse files Browse the repository at this point in the history
  • Loading branch information
jackkoenig committed Apr 4, 2024
1 parent ce05462 commit fb2421c
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 4 deletions.
5 changes: 3 additions & 2 deletions core/src/main/scala/chisel3/dontTouch.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

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
import chisel3.experimental.requireIsHardware

/** Marks that a signal's leaves are an optimization barrier to Chisel and the
* FIRRTL compiler. This has the effect of guaranteeing that a signal will not
Expand Down Expand Up @@ -34,7 +35,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[_] => ()
Expand Down
14 changes: 14 additions & 0 deletions core/src/main/scala/chisel3/experimental/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/scala/chisel3/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/chisel3/util/experimental/decode/decoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions src/test/scala/chiselTests/DontTouchSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down

0 comments on commit fb2421c

Please sign in to comment.