[FIRRTL][InferResets] Disallow external modules on InstanceChoice?
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 524
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Description
When an instance choice was used for normal module and external module,
InferReset with FullAsyncResetTransform adds a reset port to only normal ports.
I don't consider this is a bug of InferResets since this is fundamentally not fixable, and I think for predicability we should simply ban external modules on InstanceChoice and let users to create a wrapper module for that.
```scala
FIRRTL version 5.1.0
circuit test :%[[
{ "class":"circt.FullResetAnnotation",
"target":"~test|test>reset",
"resetType":"async" }]]
option Platform:
FPGA
extmodule Foo:
input clock : Clock
input a: UInt<1>
output b: UInt<1>
module Bar:
input clock : Clock
input a: UInt<1>
output b: UInt<1>
reg r: UInt<1>, clock
connect r, a
connect b, r
public module test :
input clock : Clock
input reset : AsyncReset
input in : UInt<1>
output out : UInt<1>
instchoice proc of Bar, Platform:
FPGA => Foo
connect proc.a, in
connect proc.clock, clock
connect out, proc.b
```
```
bar.fir:30:5: error: 'firrtl.instance_choice' op has a wrong number of results; expected 3 but got 4
instchoice proc of Bar, Platform:
^
bar.fir:30:5: note: see current operation: %0:4 = "firrtl.instance_choice"() <{annotations = [], caseNames = [@Platform::@FPGA], domainInfo = [[], [], [], []], layers = [], moduleNames = [@Bar, @Foo], name = "proc", nameKind = #firrtl, portAnnotations = [[], [], [], []], portDirections = array, portNames = ["reset", "clock", "a", "b"]}> : () -> (!firrtl.asyncreset, !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>)
bar.fir:12:3: note: original module declared here
extmodule Foo:
^
// -----// IR Dump After InferResets Failed (firrtl-infer-resets) //----- //
"firrtl.circuit"() <{annotations = [], name = "test"}> ({
"firrtl.option"() <{sym_name = "Platform"}> ({
"firrtl.option_case"() <{sym_name = "FPGA"}> : () -> ()
}) : () -> ()
"firrtl.extmodule"() <{annotations = [], convention = #firrtl, domainInfo = [[], [], []], externalRequirements = [], knownLayers = [], layers = [], parameters = [], portAnnotations = [[], [], []], portDirections = array, portLocations = [loc("bar.fir":13:11), loc("bar.fir":14:11), loc("bar.fir":15:12)], portNames = ["clock", "a", "b"], portSymbols = [], portTypes = [!firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>], sym_name = "Foo"}> ({
}) {sym_visibility = "private"} : () -> ()
"firrtl.module"() <{annotations = [{class = "circt.FullResetAnnotation"}], convention = #firrtl, domainInfo = [], layers = [], portAnnotations = [], portDirections = array, portLocations = [loc("bar.fir":27:11), loc("bar.fir":18:11), loc("bar.fir":19:11), loc("bar.fir":20:12)], portNames = ["reset", "clock", "a", "b"], portSymbols = [], portTypes = [!firrtl.asyncreset, !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>], sym_name = "Bar"}> ({
^bb0(%arg4: !firrtl.asyncreset, %arg5: !firrtl.clock, %arg6: !firrtl.uint<1>, %arg7: !firrtl.uint<1>):
%1 = "firrtl.constant"() <{value = 0 : ui1}> : () -> !firrtl.const.uint<1>
%2 = "firrtl.regreset"(%arg5, %arg4, %1) <{annotations = [], name = "r", nameKind = #firrtl}> : (!firrtl.clock, !firrtl.asyncreset, !firrtl.const.uint<1>) -> !firrtl.uint<1>
"firrtl.matchingconnect"(%2, %arg6) : (!firrtl.uint<1>, !firrtl.uint<1>) -> ()
"firrtl.matchingconnect"(%arg7, %2) : (!firrtl.uint<1>, !firrtl.uint<1>) -> ()
}) {sym_visibility = "private"} : () -> ()
"firrtl.module"() <{annotations = [{class = "circt.FullResetAnnotation"}], convention = #firrtl, domainInfo = [[], [], [], []], layers = [], portAnnotations = [[], [{class = "circt.FullResetAnnotation", resetType = "async"}], [], []], portDirections = array, portLocations = [loc("bar.fir":26:11), loc("bar.fir":27:11), loc("bar.fir":28:11), loc("bar.fir":29:12)], portNames = ["clock", "reset", "in", "out"], portSymbols = [], portTypes = [!firrtl.clock, !firrtl.asyncreset, !firrtl.uint<1>, !firrtl.uint<1>], sym_name = "test"}> ({
^bb0(%arg0: !firrtl.clock, %arg1: !firrtl.asyncreset, %arg2: !firrtl.uint<1>, %arg3: !firrtl.uint<1>):
%0:4 = "firrtl.instance_choice"() <{annotations = [], caseNames = [@Platform::@FPGA], domainInfo = [[], [], [], []], layers = [], moduleNames = [@Bar, @Foo], name = "proc", nameKind = #firrtl, portAnnotations = [[], [], [], []], portDirections = array, portNames = ["reset", "clock", "a", "b"]}> : () -> (!firrtl.asyncreset, !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>)
"firrtl.matchingconnect"(%0#0, %arg1) : (!firrtl.asyncreset, !firrtl.asyncreset) -> ()
"firrtl.matchingconnect"(%0#2, %arg2) : (!firrtl.uint<1>, !firrtl.uint<1>) -> ()
"firrtl.matchingconnect"(%0#1, %arg0) : (!firrtl.clock, !firrtl.clock) -> ()
"firrtl.matchingconnect"(%arg3, %0#3) : (!firrtl.uint<1>, !firrtl.uint<1>) -> ()
}) : () -> ()
}) : () -> ()
uenoku@pop-os ~/d/circt (dev/hidetou/rewrite-db) [1]>
```
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the supplied FIRRTL example and read how InferResets handles the InstanceChoice containing Bar and external module Foo. The change is complete when InstanceChoice rejects external modules predictably and the example fails with that restriction rather than a port-count mismatch.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100