diff options
| author | Jack Koenig | 2017-05-30 12:41:36 -0700 |
|---|---|---|
| committer | Jack Koenig | 2017-05-31 11:47:11 -0700 |
| commit | 13500bcbde86125701550cc4d2e0dc39703ec338 (patch) | |
| tree | dc64bcde03f0678f2ada44642d79a60149010cf1 | |
| parent | d359b47a461dd84937d1655803ddfae955da6a4e (diff) | |
Add dontTouch for annotating Data to not be removed
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala | 39 | ||||
| -rw-r--r-- | src/main/scala/chisel3/package.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/DontTouchSpec.scala | 62 |
3 files changed, 102 insertions, 1 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala b/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala index 015629e5..ad4050f3 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala @@ -2,7 +2,7 @@ package chisel3.core -import chisel3.internal.InstanceId +import chisel3.internal.{Builder, InstanceId} import firrtl.Transform import firrtl.annotations.{Annotation, CircuitName, ComponentName, ModuleName} @@ -28,3 +28,40 @@ case class ChiselAnnotation(component: InstanceId, transformClass: Class[_ <: Tr } } } + +/** Marks that a signal should not be removed by Chisel and Firrtl optimization passes + * + * @example {{{ + * class MyModule extends Module { + * val io = IO(new Bundle { + * val a = Input(UInt(32.W)) + * val b = Output(UInt(32.W)) + * }) + * io.b := io.a + * val dead = io.a +% 1.U // normally dead would be pruned by DCE + * dontTouch(dead) // Marking it as such will preserve it + * } + * }}} + * + * @note Calling this on Data creates an annotation that Chisel emits to a separate annotations + * file. This file must be passed to Firrtl independently of the .fir file. + * [[chisel3.Driver.execute]] will do this automatically. + */ +object dontTouch { // scalastyle:ignore object.name + /** Marks a signal to be preserved in Chisel and Firrtl + * + * @note Requires the argument to be bound to hardware + * @param data The signal to be marked + * @return Unmodified signal `data` + */ + def apply[T <: Data](data: T)(implicit compileOptions: CompileOptions): T = { + if (compileOptions.checkSynthesizable) { + Binding.checkSynthesizable(data, s"$data") + } + // TODO unify with firrtl.transforms.DontTouchAnnotation + val anno = ChiselAnnotation(data, classOf[firrtl.Transform], "DONTtouch!") + Builder.annotations += anno + data + } +} + diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index ac4e5441..1899b2ec 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -321,6 +321,8 @@ package object chisel3 { // scalastyle:ignore package.object.name val withClock = chisel3.core.withClock val withReset = chisel3.core.withReset + val dontTouch = chisel3.core.dontTouch + type BaseModule = chisel3.core.BaseModule type MultiIOModule = chisel3.core.ImplicitModule type RawModule = chisel3.core.UserModule diff --git a/src/test/scala/chiselTests/DontTouchSpec.scala b/src/test/scala/chiselTests/DontTouchSpec.scala new file mode 100644 index 00000000..6cd2c54d --- /dev/null +++ b/src/test/scala/chiselTests/DontTouchSpec.scala @@ -0,0 +1,62 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import chisel3.experimental.dontTouch +import firrtl.{FirrtlExecutionSuccess, Transform} + +class HasDeadCodeChild(withDontTouch: Boolean) extends Module { + val io = IO(new Bundle { + val a = Input(UInt(32.W)) + val b = Output(UInt(32.W)) + val c = Output(Vec(2, UInt(32.W))) + }) + io.b := io.a + if (withDontTouch) { + dontTouch(io.c) + } +} + +class HasDeadCode(withDontTouch: Boolean) extends Module { + val io = IO(new Bundle { + val a = Input(UInt(32.W)) + val b = Output(UInt(32.W)) + }) + val inst = Module(new HasDeadCodeChild(withDontTouch)) + inst.io.a := io.a + io.b := inst.io.b + val dead = Wire(init = io.a + 1.U) + if (withDontTouch) { + dontTouch(dead) + } +} + +class DontTouchSpec extends ChiselFlatSpec { + val deadSignals = List( + "io_c_0", + "io_c_1", + "dead" + ) + "Dead code" should "be removed by default" in { + val verilog = compile(new HasDeadCode(false)) + for (signal <- deadSignals) { + verilog should not include (signal) + } + } + it should "NOT be removed if marked dontTouch" in { + val verilog = compile(new HasDeadCode(true)) + for (signal <- deadSignals) { + verilog should include (signal) + } + } + "Dont touch" should "only work on bound hardware" in { + a [chisel3.core.Binding.BindingException] should be thrownBy { + compile(new Module { + val io = IO(new Bundle { }) + dontTouch(new Bundle { val a = UInt(32.W) } ) + }) + } + } +} + |
