llvm / llvm/circt

[OM][Evaluator][FIRRTL] Should we be able to evaluate ext classes if we don't use the outputs?

Open
#9,490 0 comments 0 reactions 0 assignees View on GitHub
FIRRTL OM
Dominant language
C++
Stars
2.2k
Forks
524
Avg merge
3d 2h
Merged PRs (30d)
46

Description

I've run into the following when starting to turn on domains for an internal design. The issue is I have _a lot_ of external modules, which map to external classes, but I don't have any internal domain information for them. However, I don't exactly _need_ any internal information for them.

E.g.:

``` firrtl
FIRRTL version 6.0.0
circuit Foo:
domain ClockDomain:
name: String
period: Integer

extmodule Bar:
input A: Domain of ClockDomain
input a: UInt<1> domains [A]

public module Foo:
input A: Domain of ClockDomain
input a: UInt<1> domains [A]

inst bar of Bar
domain_define bar.A = A
connect bar.a, a
```

Using `main` patched with https://github.com/llvm/circt/pull/9474, I run into the following:

``` console
# firtool Foo.fir -output-final-mlir - -o /dev/null | domaintool - --module Foo --domain ClockDomain,A,10 --assign 0
:1:1: error: unknown class name @Bar_Class
module {
^
```

The final MLIR is:

``` mlir
module {
hw.hierpath private @nla [@Foo::@sym]
hw.hierpath private @nla_0 [@Foo::@sym_0]
hw.module.extern private @Bar(in %a : i1 {hw.exportPort = #hw})
hw.module @Foo(in %a : i1 {hw.exportPort = #hw}) {
hw.instance "bar" sym @sym_0 @Bar(a: %a: i1) -> () {hw.verilogName = "bar"}
hw.output
}
om.class.extern @Bar_Class(%basepath: !om.frozenbasepath, %A: !om.class.type<@ClockDomain>) -> (A_out: !om.class.type<@ClockDomain_out>) {
}
om.class @Foo_Class(%basepath: !om.frozenbasepath, %A: !om.class.type<@ClockDomain>) -> (A_out: !om.class.type<@ClockDomain_out>) {
%0 = om.object @ClockDomain_out(%basepath, %A, %2) : (!om.frozenbasepath, !om.class.type<@ClockDomain>, !om.list) -> !om.class.type<@ClockDomain_out>
%1 = om.frozenpath_create reference %basepath "Foo>a"
%2 = om.list_create %1 : !om.frozenpath
%3 = om.frozenbasepath_create %basepath "Foo/bar"
%4 = om.object @Bar_Class(%3, %A) : (!om.frozenbasepath, !om.class.type<@ClockDomain>) -> !om.class.type<@Bar_Class>
%5 = om.object.field %4, [@A_out] : (!om.class.type<@Bar_Class>) -> !om.class.type<@ClockDomain_out>
om.class.fields %0 : !om.class.type<@ClockDomain_out>
}
om.class @ClockDomain(%basepath: !om.frozenbasepath, %name_in: !om.string, %period_in: !om.integer) -> (name_out: !om.string, period_out: !om.integer) {
om.class.fields %name_in, %period_in : !om.string, !om.integer
}
om.class @ClockDomain_out(%basepath: !om.frozenbasepath, %domainInfo_in: !om.class.type<@ClockDomain>, %associations_in: !om.list) -> (domainInfo_out: !om.class.type<@ClockDomain>, associations_out: !om.list) {
om.class.fields %domainInfo_in, %associations_in : !om.class.type<@ClockDomain>, !om.list
}
}
```

tl;dr: the evaluator tries to evaluate the class `Bar_Class`, but it can't because it's external.

There's two rough shapes of solutions here:

1. The evaluator needs to be lazier. There's no actual _need_ to evaluate `Bar_Class` here as it can't affect the outputs of `Foo_Class`.
2. `Bar_Class` needs to not be external and the domain information needs to be available for it. Or: this is illegal and the circuit needs to be linked before it can be evaluated.

This is a simpler example than what I was discussing with @dtzSiFive earlier today where `Bar` provided all domain information and `Foo` only had output domains. In that situation, there's nothing that you can do other than (2). Hence, this may be what is necessary here.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the firtool and domaintool invocation in the report, then trace the evaluator handling of the external @Bar_Class referenced from @Foo_Class. No source file or test is named; done means establishing and implementing the accepted behavior for unused external classes, with coverage for the shown FIRRTL example.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.