TopWiringTransform must run before LowerTypes
See original GitHub issueChecklist
- Did you specify the current behavior?
- Did you specify the expected behavior?
- Did you provide a code example showing the problem?
- Did you describe your environment?
- Did you specify relevant external information?
What is the current behavior?
If you try to top wire a bundle with flipped connections the TopWiringTransform
runs before LowerTypes
, then you expectedly get a bundle at the top with flipped connections. If the TopWiringTransform
runs after LowerTypes
, flippedness is lost and all top wired ports will be outputs.
With the current dependencies for TopWiringTransform
, running after LowerTypes
is a legal ordering.
What is the expected behavior?
The destruction of flippedness isn’t what the user (me) wants here. TopWiring
should run before LowerTypes
.
Steps to Reproduce
If you add a dummy transform to push TopWiring
later, you can change the direction of a top-wired port from ir.Input
to ir.Output
.
package firrtlTests.transforms
import firrtl.{
ir,
CircuitState,
DependencyAPIMigration,
Parser,
Transform
}
import firrtl.annotations.{
CircuitName,
ComponentName,
ModuleName
}
import firrtl.options.Dependency
import firrtl.passes.LowerTypes
import firrtl.testutils.FirrtlCheckers._
import firrtl.transforms.TopWiring.{
TopWiringAnnotation,
TopWiringTransform
}
import org.scalatest.flatspec.AnyFlatSpec
object Dummy extends Transform with DependencyAPIMigration {
override def prerequisites = Seq(Dependency(LowerTypes))
override def optionalPrerequisites = Nil
override def optionalPrerequisiteOf = Seq(Dependency[TopWiringTransform])
override def invalidates(a: Transform) = false
override def execute(a: CircuitState) = a
}
class TopWiringBug extends AnyFlatSpec {
"TopWiringTransform" should "preserver directionality after LowerTypes?" in {
val input =
"""|circuit Foo:
| module Foo:
| wire a: {flip b: UInt<1>}
| a is invalid
|""".stripMargin
val annos = Seq(
TopWiringAnnotation(ComponentName(s"a", ModuleName(s"Foo", CircuitName(s"Foo"))), s"t_"),
)
val compiler = new firrtl.stage.transforms.Compiler(
Seq(
Dependency[TopWiringTransform],
Dependency(LowerTypes),
Dependency(Dummy) /* Including Dummy causes this test to fail */
)
)
compiler.transform(CircuitState(Parser.parse(input), annos)) should containTree {
case ir.Port(_, "t_a_b", ir.Input, _) => true
}
}
}
Your environment
Current-ish master: 05ba1c9d52c056e33b4121ea55812ae596016ea3
External Information
None.
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (7 by maintainers)
Top Results From Across the Web
DependencyAPI - firrtl 1.5.3 - javadoc.io
A prerequisite is a transform that must run before this transform. An optional prerequisites is transform that should run before this transform if...
Read more >firrtl 1.4.4 - firrtl.Transform
All transform that must run before this transform. All transform that must run before this transform. Definition Classes: Transform → DependencyAPI; Note.
Read more >java.io.FileWriter Scala Example - ProgramCreek.com
This page shows Scala examples of java.io.FileWriter.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Indeed.
There’s one case where we’re dynamically adding a transform that invokes TopWiringTransform (using our own mechanism, not the two you gave) – so long as that transform defines the right prerequisites there will be no surprises. All of the other instances of this are part of the core compiler and are statically scheduled in a mega SeqTransform like thing – those should will likely be fine.
Thanks for the tips!
It’s to expose a port of a submodule and drive it from the outside. Roughly:
TopWiringTransform
was convenient because it could be done from the point where the module was instantiated as opposed to having to know the type of the module port and do sources/sinks for theWiringTransform
.This worked at some point, then after accumulating some custom transforms, I noticed that directions started getting stripped.