llvm / circt

Circuit IR Compilers and Tools
https://circt.org
Other
1.67k stars 298 forks source link

[FIRRTL] GCT Taps and Dedup #3495

Closed seldridge closed 1 year ago

seldridge commented 2 years ago

This is the Grand Central (GCT) Taps variant of #3494. GCT Taps does not work on a deduplicated design. We need to fix this with a better representation for XMRs that works with dedup. Dedup and annotations do not work if the annotations describe XMRs.

Consider:

circuit Top :
  module Bar :
    input clock : Clock
    input reset : Reset

    wire w : UInt<1>
    w <= UInt<1>("h0")

  extmodule DataTap_1 :
    output _0 : UInt<1>
    defname = DataTap_1

  module Foo :
    input clock : Clock
    input reset : Reset

    inst bar of Bar
    bar.clock <= clock
    bar.reset <= reset
    wire w : UInt<1>
    inst DataTap_1 of DataTap_1
    DataTap_1._0 is invalid
    w <= DataTap_1._0

  module Bar_1 :
    input clock : Clock
    input reset : Reset

    wire w : UInt<1>
    w <= UInt<1>("h0")

  extmodule DataTap_1_0 :
    output _0 : UInt<1>
    defname = DataTap_1

  module Foo_1 :
    input clock : Clock
    input reset : Reset

    inst bar of Bar_1
    bar.clock <= clock
    bar.reset <= reset
    wire w : UInt<1>
    inst DataTap_1 of DataTap_1_0
    DataTap_1._0 is invalid
    w <= DataTap_1._0

  module Top :
    input clock : Clock
    input reset : UInt<1>

    inst foo1 of Foo
    foo1.clock <= clock
    foo1.reset <= reset
    inst foo2 of Foo_1
    foo2.clock <= clock
    foo2.reset <= reset
[
  {
    "class":"sifive.enterprise.grandcentral.DataTapsAnnotation",
    "blackBox":"~Top|DataTap_1",
    "keys":[
      {
        "class":"sifive.enterprise.grandcentral.ReferenceDataTapKey",
        "source":"~Top|Top/foo1:Foo/bar:Bar>w",
        "portName":"~Top|DataTap_1>_0"
      }
    ]
  },
  {
    "class":"sifive.enterprise.grandcentral.DataTapsAnnotation",
    "blackBox":"~Top|DataTap_1_0",
    "keys":[
      {
        "class":"sifive.enterprise.grandcentral.ReferenceDataTapKey",
        "source":"~Top|Top/foo2:Foo_1/bar:Bar_1>w",
        "portName":"~Top|DataTap_1_0>_0"
      }
    ]
  },
  {
    "class":"sifive.enterprise.grandcentral.ExtractGrandCentralAnnotation",
    "directory":"builds/gct-tests/DedupTap/firrtl/gct",
    "filename":"builds/gct-tests/DedupTap/firrtl/bindings.sv"
  },
  {
    "class":"sifive.enterprise.firrtl.TestBenchDirAnnotation",
    "dirname":"builds/gct-tests/DedupTap/firrtl/verilog/testbench"
  }
]

Currently this will crash after GCT Taps (firtool Foo.fir -annotation-file Foo.anno.json -dedup -firrtl-grand-central):

firrtl/Top.fir:36:10: error: 'firrtl.hierpath' op instance path is incorrect. Expected module: "DataTap_1_impl_1" instead found: "DataTap_1"
  module Foo_1 :
         ^
firrtl/Top.fir:36:10: note: see current operation: "firrtl.hierpath"() {namepath = [#hw.innerNameRef<@Top::@foo2>, #hw.innerNameRef<@Foo::@DataTap_1>, @DataTap_1], sym_name = "nla_4"} : () -> ()
firrtl/Top.fir:13:10: error: 'firrtl.hierpath' op instance path is incorrect. Expected module: "DataTap_1_impl_1" instead found: "DataTap_1"
  module Foo :
         ^
firrtl/Top.fir:13:10: note: see current operation: "firrtl.hierpath"() {namepath = [#hw.innerNameRef<@Top::@foo1>, #hw.innerNameRef<@Foo::@DataTap_1>, @DataTap_1], sym_name = "nla_3"} : () -> ()
dtzSiFive commented 1 year ago

Think this is good to close, with RefTypes and such! :tada: (please re-open if missed anything)

Modifying the original example to use the newer format and things look good:

circuit Top : %[[
  {
    "class":"sifive.enterprise.grandcentral.DataTapsAnnotation",
    "blackBox":"~Top|DataTap_1",
    "keys":[
      {
        "class":"sifive.enterprise.grandcentral.ReferenceDataTapKey",
        "source":"~Top|Top/foo1:Foo/bar:Bar>w",
        "sink":"~Top|Foo>w"
      }
    ]
  },
  {
    "class":"sifive.enterprise.grandcentral.DataTapsAnnotation",
    "blackBox":"~Top|DataTap_1_0",
    "keys":[
      {
        "class":"sifive.enterprise.grandcentral.ReferenceDataTapKey",
        "source":"~Top|Top/foo2:Foo_1/bar:Bar_1>w",
        "sink":"~Top|Foo_1>w"
      }
    ]
  },
  {
    "class":"sifive.enterprise.grandcentral.ExtractGrandCentralAnnotation",
    "directory":"builds/gct-tests/DedupTap/firrtl/gct",
    "filename":"builds/gct-tests/DedupTap/firrtl/bindings.sv"
  },
  {
    "class":"sifive.enterprise.firrtl.TestBenchDirAnnotation",
    "dirname":"builds/gct-tests/DedupTap/firrtl/verilog/testbench"
  }
]]
  module Bar :
    input clock : Clock
    input reset : Reset

    wire w : UInt<1>
    w <= UInt<1>("h0")

  extmodule DataTap_1 :
    input _0 : UInt<1>
    defname = DataTap_1

  module Foo :
    input clock : Clock
    input reset : Reset

    inst bar of Bar
    bar.clock <= clock
    bar.reset <= reset
    wire w : UInt<1>
    inst DataTap_1 of DataTap_1
    DataTap_1._0 <= w

  module Bar_1 :
    input clock : Clock
    input reset : Reset

    wire w : UInt<1>
    w <= UInt<1>("h0")

  extmodule DataTap_1_0 :
    input _0 : UInt<1>
    defname = DataTap_1

  module Foo_1 :
    input clock : Clock
    input reset : Reset

    inst bar of Bar_1
    bar.clock <= clock
    bar.reset <= reset
    wire w : UInt<1>
    inst DataTap_1 of DataTap_1_0
    DataTap_1._0 <= w

  module Top :
    input clock : Clock
    input reset : UInt<1>

    inst foo1 of Foo
    foo1.clock <= clock
    foo1.reset <= reset
    inst foo2 of Foo_1
    foo2.clock <= clock
    foo2.reset <= reset

Running with firtool -dedup produces:

// Generated by CIRCT 1.48.0g20230728_e59e3cf
// external module DataTap_1

module Foo();
  DataTap_1 DataTap_1 (
    ._0 (1'h0)
  );
endmodule

module Top(
  input clock,
        reset
);

  Foo foo1 ();
  Foo foo2 ();
endmodule