Skip to content

[Seq] LowerSeqToSV Creating Illegal IR #8941

@seldridge

Description

@seldridge

After doing some more experiments with use of inline layers, I hit an issue with LowerSeqToSV producing invalid IR. Consider the following:

sv.macro.decl @C
hw.hierpath private @A [@Foo::@clock]
hw.hierpath private @B [@Foo::@reset]
hw.module private @Bar() {
  %c1_i10 = hw.constant 1 : i10
  %c0_i10 = hw.constant 0 : i10
  %0 = sv.xmr.ref @B : !hw.inout<i1>
  %1 = sv.read_inout %0 : !hw.inout<i1>
  %2 = seq.to_clock %1
  %3 = sv.xmr.ref @A : !hw.inout<i1>
  %4 = sv.read_inout %3 : !hw.inout<i1>
  sv.ifdef @C {
    %count = seq.firreg %5 clock %2 reset async %4, %c0_i10 : i10
    %5 = comb.add bin %count, %c1_i10 : i10
  }
  hw.output
}
hw.module.extern @Foo(
  in %clock : !seq.clock {hw.exportPort = #hw<innerSym@clock>},
  in %reset : i1 {hw.exportPort = #hw<innerSym@reset>}
)

Compile this creates illegal IR:

$ circt-opt Foo.mlir --pass-pipeline='builtin.module(lower-seq-to-sv)'
reduced.0.mlir:13:14: error: operand #0 does not dominate this use
    %count = seq.firreg %5 clock %2 reset async %4, %c0_i10 : i10
             ^
reduced.0.mlir:13:14: note: see current operation: "sv.bpassign"(%17, %4) : (!hw.inout<i10>, i10) -> ()
reduced.0.mlir:13:14: note: operand defined here (op is neither in a parent nor in a child region)

The final MLIR is:

#loc = loc("reduced.0.mlir":19:6)
#loc1 = loc("reduced.0.mlir":20:6)
"builtin.module"() ({
  "sv.macro.decl"() <{sym_name = "SYNTHESIS"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "VERILATOR"}> : () -> ()
  "emit.fragment"() <{sym_name = "RANDOM_INIT_FRAGMENT"}> ({
    "sv.verbatim"() <{format_string = "// Standard header to adapt well known macros for register randomization.", symbols = []}> : () -> ()
    "sv.verbatim"() <{format_string = "\0A// RANDOM may be set to an expression that produces a 32-bit random unsigned value.", symbols = []}> : () -> ()
    "sv.ifdef"() <{cond = #sv<macro.ident @RANDOM>}> ({
    ^bb0:
    }, {
      "sv.macro.def"() <{format_string = "$random", macroName = @RANDOM, symbols = []}> : () -> ()
    }) : () -> ()
    "sv.verbatim"() <{format_string = "\0A// Users can define INIT_RANDOM as general code that gets injected into the\0A// initializer block for modules with registers.", symbols = []}> : () -> ()
    "sv.ifdef"() <{cond = #sv<macro.ident @INIT_RANDOM>}> ({
    ^bb0:
    }, {
      "sv.macro.def"() <{format_string = "", macroName = @INIT_RANDOM, symbols = []}> : () -> ()
    }) : () -> ()
    "sv.verbatim"() <{format_string = "\0A// If using random initialization, you can also define RANDOMIZE_DELAY to\0A// customize the delay used, otherwise 0.002 is used.", symbols = []}> : () -> ()
    "sv.ifdef"() <{cond = #sv<macro.ident @RANDOMIZE_DELAY>}> ({
    ^bb0:
    }, {
      "sv.macro.def"() <{format_string = "0.002", macroName = @RANDOMIZE_DELAY, symbols = []}> : () -> ()
    }) : () -> ()
    "sv.verbatim"() <{format_string = "\0A// Define INIT_RANDOM_PROLOG_ for use in our modules below.", symbols = []}> : () -> ()
    "sv.ifdef"() <{cond = #sv<macro.ident @INIT_RANDOM_PROLOG_>}> ({
    ^bb0:
    }, {
      "sv.ifdef"() <{cond = #sv<macro.ident @RANDOMIZE>}> ({
        "sv.ifdef"() <{cond = #sv<macro.ident @VERILATOR>}> ({
          "sv.macro.def"() <{format_string = "`INIT_RANDOM", macroName = @INIT_RANDOM_PROLOG_, symbols = []}> : () -> ()
        }, {
          "sv.macro.def"() <{format_string = "`INIT_RANDOM #`RANDOMIZE_DELAY begin end", macroName = @INIT_RANDOM_PROLOG_, symbols = []}> : () -> ()
        }) : () -> ()
      }, {
        "sv.macro.def"() <{format_string = "", macroName = @INIT_RANDOM_PROLOG_, symbols = []}> : () -> ()
      }) : () -> ()
    }) : () -> ()
  }) : () -> ()
  "emit.fragment"() <{sym_name = "RANDOM_INIT_REG_FRAGMENT"}> ({
    "sv.verbatim"() <{format_string = "\0A// Include register initializers in init blocks unless synthesis is set", symbols = []}> : () -> ()
    "sv.ifdef"() <{cond = #sv<macro.ident @RANDOMIZE>}> ({
    ^bb0:
    }, {
      "sv.ifdef"() <{cond = #sv<macro.ident @RANDOMIZE_REG_INIT>}> ({
        "sv.macro.def"() <{format_string = "", macroName = @RANDOMIZE, symbols = []}> : () -> ()
      }, {
      }) : () -> ()
    }) : () -> ()
    "sv.ifdef"() <{cond = #sv<macro.ident @SYNTHESIS>}> ({
    ^bb0:
    }, {
      "sv.ifdef"() <{cond = #sv<macro.ident @ENABLE_INITIAL_REG_>}> ({
      ^bb0:
      }, {
        "sv.macro.def"() <{format_string = "", macroName = @ENABLE_INITIAL_REG_, symbols = []}> : () -> ()
      }) : () -> ()
    }) : () -> ()
    "sv.verbatim"() <{format_string = "", symbols = []}> : () -> ()
  }) : () -> ()
  "sv.macro.decl"() <{sym_name = "ENABLE_INITIAL_REG_"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "ENABLE_INITIAL_MEM_"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "FIRRTL_BEFORE_INITIAL"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "FIRRTL_AFTER_INITIAL"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "RANDOMIZE_REG_INIT"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "RANDOMIZE"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "RANDOMIZE_DELAY"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "RANDOM"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "INIT_RANDOM"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "INIT_RANDOM_PROLOG_"}> : () -> ()
  "sv.macro.decl"() <{sym_name = "C"}> : () -> ()
  "hw.hierpath"() <{namepath = [#hw.innerNameRef<@Foo::@clock>], sym_name = "A"}> {sym_visibility = "private"} : () -> ()
  "hw.hierpath"() <{namepath = [#hw.innerNameRef<@Foo::@reset>], sym_name = "B"}> {sym_visibility = "private"} : () -> ()
  "hw.hierpath"() <{namepath = [#hw.innerNameRef<@Bar::@count>], sym_name = "Bar_count"}> : () -> ()
  "hw.module"() <{module_type = !hw.modty<>, parameters = [], sym_name = "Bar"}> ({
    %0 = "hw.constant"() <{value = 0 : i0}> : () -> i0
    %1 = "hw.constant"() <{value = true}> : () -> i1
    %2 = "hw.constant"() <{value = false}> : () -> i1
    %3 = "hw.constant"() <{value = 1 : i10}> : () -> i10
    %4 = "hw.constant"() <{value = 0 : i10}> : () -> i10
    %5 = "sv.xmr.ref"() <{ref = @B, verbatimSuffix = ""}> : () -> !hw.inout<i1>
    %6 = "sv.read_inout"(%5) : (!hw.inout<i1>) -> i1
    %7 = "sv.xmr.ref"() <{ref = @A, verbatimSuffix = ""}> : () -> !hw.inout<i1>
    %8 = "sv.read_inout"(%7) : (!hw.inout<i1>) -> i1
    "sv.ifdef"() <{cond = #sv<macro.ident @C>}> ({
      %17 = "sv.reg"() <{inner_sym = #hw<innerSym@count>, name = "count"}> : () -> !hw.inout<i10>
      %18 = "sv.read_inout"(%17) : (!hw.inout<i10>) -> i10
      %19 = "comb.add"(%18, %3) <{twoState}> : (i10, i10) -> i10
      "sv.always"(%6, %8) <{events = [0 : i32, 0 : i32]}> ({
        "sv.if"(%8) ({
          "sv.passign"(%17, %4) : (!hw.inout<i10>, i10) -> ()
        }, {
          "sv.passign"(%17, %19) : (!hw.inout<i10>, i10) -> ()
        }) : (i1) -> ()
      }) : (i1, i1) -> ()
    }, {
    }) : () -> ()
    "sv.ifdef"() <{cond = #sv<macro.ident @ENABLE_INITIAL_REG_>}> ({
      "sv.ordered"() ({
        "sv.ifdef"() <{cond = #sv<macro.ident @FIRRTL_BEFORE_INITIAL>}> ({
          "sv.verbatim"() <{format_string = "`FIRRTL_BEFORE_INITIAL", symbols = []}> : () -> ()
        }, {
        }) : () -> ()
        "sv.initial"() ({
          "sv.ifdef.procedural"() <{cond = #sv<macro.ident @INIT_RANDOM_PROLOG_>}> ({
            "sv.verbatim"() <{format_string = "`INIT_RANDOM_PROLOG_", symbols = []}> : () -> ()
          }, {
          }) : () -> ()
          "sv.ifdef.procedural"() <{cond = #sv<macro.ident @RANDOMIZE_REG_INIT>}> ({
            %9 = "sv.logic"() <{name = "_RANDOM"}> : () -> !hw.inout<uarray<1xi32>>
            "sv.for"(%2, %1, %1) <{inductionVarName = "i"}> ({
            ^bb0(%arg0: i1):
              %14 = "sv.macro.ref.expr.se"() <{macroName = @RANDOM}> : () -> i32
              %15 = "comb.extract"(%arg0) <{lowBit = 0 : i32}> : (i1) -> i0
              %16 = "sv.array_index_inout"(%9, %15) : (!hw.inout<uarray<1xi32>>, i0) -> !hw.inout<i32>
              "sv.bpassign"(%16, %14) : (!hw.inout<i32>, i32) -> ()
            }) : (i1, i1, i1) -> ()
            %10 = "sv.array_index_inout"(%9, %0) : (!hw.inout<uarray<1xi32>>, i0) -> !hw.inout<i32>
            "sv.ifdef.procedural"() <{cond = #sv<macro.ident @C>}> ({
              %11 = "sv.xmr.ref"() <{ref = @Bar_count, verbatimSuffix = ""}> : () -> !hw.inout<i10>
              %12 = "sv.read_inout"(%10) : (!hw.inout<i32>) -> i32
              %13 = "comb.extract"(%12) <{lowBit = 0 : i32}> : (i32) -> i10
              "sv.bpassign"(%11, %13) : (!hw.inout<i10>, i10) -> ()
            }, {
            }) : () -> ()
          }, {
          }) : () -> ()
          "sv.if"(%8) ({
            "sv.bpassign"(%17, %4) : (!hw.inout<i10>, i10) -> ()
          }, {
          }) : (i1) -> ()
        }) : () -> ()
        "sv.ifdef"() <{cond = #sv<macro.ident @FIRRTL_AFTER_INITIAL>}> ({
          "sv.verbatim"() <{format_string = "`FIRRTL_AFTER_INITIAL", symbols = []}> : () -> ()
        }, {
        }) : () -> ()
      }) : () -> ()
    }, {
    }) : () -> ()
    "hw.output"() : () -> ()
  }) {emit.fragments = [@RANDOM_INIT_REG_FRAGMENT, @RANDOM_INIT_FRAGMENT], sym_visibility = "private"} : () -> ()
  "hw.module.extern"() <{module_type = !hw.modty<input clock : i1, input reset : i1>, parameters = [], per_port_attrs = [{hw.exportPort = #hw<innerSym@clock>}, {hw.exportPort = #hw<innerSym@reset>}], port_locs = [#loc, #loc1], sym_name = "Foo"}> ({
  }) : () -> ()
}) : () -> ()

Metadata

Metadata

Assignees

Labels

SeqInvolving the `seq` dialect

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions