Skip to content

[FIRRTL] Dedup: accidentally processes modules before referenced classes #9700

@youngar

Description

@youngar
firrtl.circuit "Top" {
  firrtl.module @Top() {
    firrtl.instance foo @Foo()
    firrtl.instance bar @Bar()
  }

  firrtl.module private @Foo() {
    %w = firrtl.wire : !firrtl.class<@Spam()>
  }
  firrtl.module private @Bar() {
    %w = firrtl.wire : !firrtl.class<@Eggs()>
  }

  firrtl.class @Spam() {}
  firrtl.class @Eggs() {}
}

Running bin/circt-opt --firrtl-dedup dedup.mlir --debug-only=firrtl-dedup --mlir-disable-threading gives, with an extra printf in referred module remapping, gives:

===- Dedup circuit "Top" ----------------------------------------------------===

Found 5 modules
Computing module information
- Hash af840e70c3ea306c15884599064c0c8327f8c7f7b2a4c77b5d07495fd317fa85 for "Foo"
- Hash af840e70c3ea306c15884599064c0c8327f8c7f7b2a4c77b5d07495fd317fa85 for "Bar"
- Hash 68df36fc78303189fb153e739d3b1646133652308976e53e12d57107e421f5aa for "Top"
- Hash 27acbd3d013a60709d80df46557bfb174c0ac9eeac2e74887f6137d8ac43b62b for "Spam"
- Hash 27acbd3d013a60709d80df46557bfb174c0ac9eeac2e74887f6137d8ac43b62b for "Eggs"
Update modules
referred module: "Spam"
renamed to module: <<NULL ATTRIBUTE>>
- No match for "Foo"
referred module: "Eggs"
renamed to module: <<NULL ATTRIBUTE>>
- Replace "Bar" with "Foo"
referred module: "Bar"
renamed to module: "Foo"
referred module: "Foo"
renamed to module: "Foo"
- No match for "Top"
- No match for "Spam"
- Cannot dedup "Eggs" with "Spam" because both are public
Update annotations
- Updating 2 symbol-sensitive ops in "Top"
- Updating 1 symbol-sensitive ops in "Foo"
module {
  firrtl.circuit "Top" {
    firrtl.module @Top() {
      firrtl.instance foo @Foo()
      firrtl.instance bar @Foo()
    }
    firrtl.module private @Foo() {
      %w = firrtl.wire : !firrtl.class<@Spam()>
    }
    firrtl.class @Spam() {
    }
    firrtl.class @Eggs() {
    }
  }
}

Since Spam and Eggs did not deduplicate, due to both being public, Foo and Bar should not have deduplicated.

When hashing a module, if the hasher sees a class type, it records the class in its list of "referred modules".  Dedup depends on visiting the modules in post-order, so we can remap a module's "referred modules" (children modules) and successfully deduplicate parent modules when the children modules have deduped.  I don't think the instance graph takes into account a (e.g.) port of class type to consider that class as a child module.  The end result is that when we look this class up in the dedupMap before it has been processed, we get a null attribute, and since null == null we can deduplicate things we shouldn't.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FIRRTLInvolving the `firrtl` dialect

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions