Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion 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, requireIsHardware, BaseModule, ChiselAnnotation, ChiselMultiAnnotation}
import chisel3.properties.Property
import chisel3.reflect.DataMirror
import firrtl.transforms.DontTouchAnnotation
import firrtl.annotations.Annotation

/** 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 @@ -46,4 +47,18 @@ object dontTouch {
data
}

/** Mark a module so that its ports will not get optimized away.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this already do the right thing w.r.t. property ports and probe ports?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed in dev, we're fine to add this API but we should direct users to Public and Probe here in the API docs depending on the use case.

*
* @param module whose ports shouldl not get optimized away
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param module whose ports shouldl not get optimized away
* @param module whose ports should not get optimized away

*/
def modulePorts(module: BaseModule): BaseModule = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need an implicit SourceInfo here for DataMirror.fullModulePorts, that's why compilation is failing (incremental compile often hides this particular problem, that you can't materialize source locators in chisel core).


annotate(new ChiselMultiAnnotation {
def toFirrtl: Seq[Annotation] = (DataMirror.fullModulePorts(module).map {
case (_, data) => DontTouchAnnotation(data.toNamed)
})
Comment on lines +57 to +59
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fullModulePorts is returns every Aggregate and Element so this will result in dontTouching things multiple times. Can we instead maybe just use .modulePorts and call dontTouch.apply above (which does the recursion and only marks Elements)?

})
module
}

}
62 changes: 62 additions & 0 deletions src/test/scala/chiselTests/DontTouchSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,66 @@ class DontTouchSpec extends ChiselFlatSpec with Utils {
// Ensure can compile the result.
compile(new HasProbesAndProperties())
}

"dontTouch.modulePorts" should "mark all ports of a module" in {
class ModuleWithPorts extends Module {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a test for a Module with property and/or Probe ports? Im unclear if those are expected to be annotated, or there is supposed to be an error, or...?

val io = IO(new Bundle {
val a = Output(UInt(32.W))
val b = Input(new Bundle {
val x = Bool()
val y = new Bundle {
val foo = UInt(4.W)
}
})
})
io.a := DontCare
}
class DummyWrapper extends Module {
val dut = Module(new ModuleWithPorts)
dontTouch.modulePorts(dut)
}

val (_, annos) = getFirrtlAndAnnos(new DummyWrapper)
(annos should contain).allOf(
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>clock".rt),
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>reset".rt),
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>io".rt),
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>io.b".rt),
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>io.b.y".rt),
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>io.b.y.foo".rt),
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>io.b.x".rt),
DontTouchAnnotation("~DummyWrapper|ModuleWithPorts>io.a".rt)
)
}

"dontTouch.modulePorts" should "mark bored ports" in {
class ModuleToBore extends Module {
val io = IO(new Bundle {
val a = Output(UInt(32.W))
val b = Input(Bool())
})
io.a := DontCare

val boreMe = Wire(UInt(4.W))
boreMe := DontCare
}
class BoreModule extends Module {
val boreOut = IO(Output(UInt(4.W)))
val dut = Module(new ModuleToBore)

boreOut := chisel3.util.experimental.BoringUtils.bore(dut.boreMe)
dontTouch.modulePorts(dut)
}

val (_, annos) = getFirrtlAndAnnos(new BoreModule)
(annos should contain).allOf(
DontTouchAnnotation("~BoreModule|ModuleToBore>clock".rt),
DontTouchAnnotation("~BoreModule|ModuleToBore>reset".rt),
DontTouchAnnotation("~BoreModule|ModuleToBore>io".rt),
DontTouchAnnotation("~BoreModule|ModuleToBore>io.b".rt),
DontTouchAnnotation("~BoreModule|ModuleToBore>io.a".rt),
DontTouchAnnotation("~BoreModule|BoreModule>dut.boreOut_bore".rt)
)
}

}