llvm / llvm/circt

[firtool] New blackbox/external-module behavior in firtool-1.137.0

Open
#9,302 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
2.2k
Forks
524
Avg merge
3d 2h
Merged PRs (30d)
46

Description

After updating from firtool-1.136.0 to firtool-1.137.0, I observed two changes in behavior to how external modules are handled, and I wasn't sure if they were intentional.

# Setup

Let's say I have this project structure:

```
./
├── bb-a/
│ └── Bar.sv
├── bb-b/
│ ├── Bar.sv
│ └── Baz.sv
└── Foo.fir
```

With these files:

```
$ cat bb-a/Bar.sv
// bb-a/Bar.sv
module Bar;
endmodule
$ cat bb-b/Bar.sv
// bb-b/Bar.sv
module Bar;
$ cat bb-b/Baz.sv
// bb-b/Baz.sv
module Baz;
endmodule
endmodule
$ cat Foo.fir
FIRRTL version 6.0.0
circuit Foo :%[[
{
"class":"firrtl.transforms.BlackBoxPathAnno",
"target":"~|Bar",
"path":"bb-a/Bar.sv"
},
{
"class":"firrtl.transforms.BlackBoxPathAnno",
"target":"~|Baz",
"path":"bb-b/Baz.sv"
},
{
"class":"firrtl.transforms.BlackBoxPathAnno",
"target":"~|Baz",
"path":"bb-b/Bar.sv"
}
]]
layer Verification, bind, "verification" :
layer Assert, bind, "verification/assert" :
layer Temporal, inline :
layer Assume, bind, "verification/assume" :
layer Temporal, inline :
layer Cover, bind, "verification/cover" :
layer Temporal, inline :

extmodule Bar :
defname = Bar

extmodule Baz :
defname = Baz

public module Foo :
input clock : Clock
input reset : UInt<1>

inst bar of Bar
inst baz of Baz
```

So, I've got a duplicate definition of the SystemVerilog `Bar` module in both sub-directories, and I've included `bb-a/Bar.sv` as the definition of the `Bar` FIRRTL module, and I've added `bb-b/Bar.sv` as a file for the `Baz` FIRRTL module, even those it's not going to be useful in the circuit definition.

# Strict handling of duplicate module definitions

When I run this with firtool-1.136.0, it compiles, and I get this result:

```
$ ./firtool-1.136.0 -default-layer-specialization=enable Foo.fir
// Generated by CIRCT firtool-1.136.0
module Foo(
input clock,
reset
);

Bar bar ();
Baz baz ();
endmodule

// ----- 8< ----- FILE "./Bar.sv" ----- 8< -----

// Generated by CIRCT firtool-1.136.0
// bb-a/Bar.sv
module Bar;
endmodule
// ----- 8< ----- FILE "./Baz.sv" ----- 8< -----

// Generated by CIRCT firtool-1.136.0
// bb-b/Baz.sv
module Baz;
endmodule
```

But with firtool-1.137.0, the build fails:

```
$ ./firtool-1.137.0 -default-layer-specialization=enable Foo.fir
Foo.fir:30:3: error: redefinition of symbol named 'Bar.sv'
extmodule Baz :
^
Foo.fir:30:3: note: see current operation:
"emit.file"() <{file_name = "./Bar.sv", sym_name = "Bar.sv"}> ({
"emit.verbatim"() <{text = "// bb-a/Bar.sv\0Amodule Bar;\0Aendmodule\0A"}> : () -> ()
}) {output_file = #hw.output_file<"./Bar.sv">} : () -> ()
Foo.fir:27:3: note: see existing symbol definition here
extmodule Bar :
^
```

Now, this isn't necessarily a bad change, but is this an expected change in behavior? Or a weird edge-case I'm hitting? Is this a change that we should communicate to users?

# New unprocessed-annotation warning

If we run this same example with the `-warn-on-unprocessed-annotations` flag, there's no warning in firtool-1.136.0:

```
$ ./firtool-1.136.0 -default-layer-specialization=enable -warn-on-unprocessed-annotations Foo.fir
... same output as above
```

But with firtool-1.137.0:

```
$ ./firtool-1.137.0 -default-layer-specialization=enable -warn-on-unprocessed-annotations Foo.fir
Foo.fir:27:3: warning: unprocessed annotation:'circt.VerbatimBlackBoxAnno' still remaining after LowerToHW
extmodule Bar :
^
... same error output as above
```

And if I update the project to remove `bb-b/Bar.sv`, and remove that annotation from `Foo.fir`, I still get the warning with a successful result:

```
$ ./firtool-1.137.0 -default-layer-specialization=enable -warn-on-unprocessed-annotations Foo.fir
Foo.fir:22:3: warning: unprocessed annotation:'circt.VerbatimBlackBoxAnno' still remaining after LowerToHW
extmodule Bar :
^
// Generated by CIRCT firtool-1.137.0
module Foo(
input clock,
reset
);

Bar bar ();
Baz baz ();
endmodule

// ----- 8< ----- FILE "./Bar.sv" ----- 8< -----

// Generated by CIRCT firtool-1.137.0
// bb-a/Bar.sv
module Bar;
endmodule

// ----- 8< ----- FILE "./Baz.sv" ----- 8< -----

// Generated by CIRCT firtool-1.137.0
// bb-b/Baz.sv
module Baz;
endmodule
```

Is that warning expected?

# Reproduction

Here's a folder containing those files, if you want to reproduce the same results:

[blackbox-errors.tar.gz](https://github.com/user-attachments/files/23941654/blackbox-errors.tar.gz)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the blackbox-errors.tar.gz reproduction and run Foo.fir through firtool-1.136.0 and firtool-1.137.0 using -default-layer-specialization=enable and -warn-on-unprocessed-annotations. Compare duplicate external-module handling and the circt.VerbatimBlackBoxAnno warning. Done means determining whether both behavior changes are intentional and identifying the expected user-facing outcome.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.