-
Notifications
You must be signed in to change notification settings - Fork 415
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 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, aUsing main patched with #9474, I run into the following:
# firtool Foo.fir -output-final-mlir - -o /dev/null | domaintool - --module Foo --domain ClockDomain,A,10 --assign 0
<stdin>:1:1: error: unknown class name @Bar_Class
module {
^The final MLIR is:
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<innerSym@sym>})
hw.module @Foo(in %a : i1 {hw.exportPort = #hw<innerSym@sym>}) {
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.frozenpath>) -> !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<!om.frozenpath>) -> (domainInfo_out: !om.class.type<@ClockDomain>, associations_out: !om.list<!om.frozenpath>) {
om.class.fields %domainInfo_in, %associations_in : !om.class.type<@ClockDomain>, !om.list<!om.frozenpath>
}
}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:
- The evaluator needs to be lazier. There's no actual need to evaluate
Bar_Classhere as it can't affect the outputs ofFoo_Class. Bar_Classneeds 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.