Skip to content

[ARC] arcilator fails to legalize 'llhd.process' during class instantiation lowering #10187

@m2kar

Description

@m2kar

Bug Report: arcilator fails to legalize 'llhd.process' during class instantiation lowering

Tool: CIRCT v1.144.0 (circt-verilog + arcilator)
Severity: Compilation Error

Description

CIRCT fails to compile SystemVerilog code containing class instantiation in procedural context. The circt-verilog frontend successfully parses the class declaration and generates MLIR, but the arcilator backend crashes with a legalization failure: "failed to legalize operation 'llhd.process' that was explicitly marked illegal". This is a circt compilation error where Verilator and Icarus Verilog successfully compile the same code without errors.

The root cause is that CIRCT incorrectly lowers SystemVerilog class instantiation to llhd.process operations, which Arcilator cannot convert to LLVM IR. The llhd.process dialect is designed for hardware simulation processes, not software object allocation.

Minimal Reproducible Example

module top;
  class parent;
  endclass

  initial begin
    parent p = new();
  end
endmodule

Reproduction Steps

# CIRCT fails
circt-verilog --ir-hw minimal_testcase.sv | arcilator

# Verilator succeeds
verilator --lint-only --sv minimal_testcase.sv

# Icarus Verilog succeeds
iverilog -g2012 minimal_testcase.sv

Actual Output

$ circt-verilog --ir-hw minimal_testcase.sv | arcilator
minimal_testcase.sv:6:12: warning: initializing a static variable in a procedural context requires an explicit 'static' keyword [-Wexplicit-static]
    parent p = new();
           ^
minimal_testcase.sv:2:9: remark: Class builtin functions (needed for randomization, constraints, and covergroups) are not yet supported and will be dropped during lowering.
  class parent;
        ^
<stdin>:5:5: error: failed to legalize operation 'llhd.process' that was explicitly marked illegal: "llhd.process"() ({...}) : () -> ()
    llhd.process {
    ^
<stdin>:5:5: note: see current operation: 
"llhd.process"() ({
  %1 = "func.call"(%0) <{callee = @malloc}> : (i64) -> !llvm.ptr
  "llhd.halt"() : () -> ()
}) : () -> ()
<stdin>:1:1: error: conversion to arcs failed
module {
^

Expected Output

The code should compile successfully without errors. The testcase is valid IEEE 1800-2023 SystemVerilog:

  • Class declaration is valid (IEEE 1800-2023 Section 8.2)
  • Class instantiation with new() is valid (IEEE 1800-2023 Section 8.13)
  • Procedural context (initial block) is valid (IEEE 1800-2023 Section 9.2)

Verilator and Icarus Verilog both compile this code successfully.

Cross-Tool Comparison

Tool Version Result
Verilator 5.022 Success
Icarus Verilog 13.0 (devel) Success
CIRCT v1.144.0 Failure

Consensus: Most tools handle this correctly; CIRCT has compilation issues with class instantiation due to incorrect lowering to llhd.process dialect.

Root Cause (Preliminary)

CIRCT's circt-verilog frontend lowers class instantiation to llhd.process operations, but Arcilator lacks a legalization pattern to convert llhd.process to LLVM IR. This is a fundamental architectural issue:

  1. Incomplete Class Support: CIRCT emits a remark acknowledging classes are unsupported but continues processing instead of rejecting the input with a clear error message.

  2. Missing Arcilator Pattern: Arcilator's ConvertToArcs pass marks the entire LLHD dialect as illegal but lacks conversion patterns for llhd.process operations generated by class instantiation.

  3. Dialect Design Mismatch: LLHD process constructs represent hardware simulation processes (concurrent behavior), while SystemVerilog class instantiation represents software object allocation. Using llhd.process for classes is a conceptual mismatch.

Failure Point: Arcilator (CIRCT's LLHD-to-LLVM conversion pass), legalization stage before LLVM IR generation.

Standard Compliance Assessment

Classification: Tool Bug (CIRCT Implementation Issue)

IEEE References:

  • IEEE 1800-2023 Section 8.2 (Class Declarations)
  • IEEE 1800-2023 Section 8.13 (Class Instantiation)
  • IEEE 1800-2023 Section 9.2 (Initial Procedures)

Analysis:
The testcase is fully IEEE 1800-2023 compliant. No undefined behavior or ambiguous constructs exist. CIRCT's failure to compile this code is a tool deficiency, not a standard compliance issue. The frontend generates invalid MLIR by lowering class instantiation to an incompatible dialect (llhd.process instead of LLVM dialect), and the backend lacks legalization patterns to handle the result.

Recommended Fix:

  • Short-term: Emit a clear error message in circt-verilog when encountering class instantiation instead of attempting lowering
  • Long-term: Implement proper class instantiation lowering directly to LLVM dialect (not LLHD dialect), similar to Verilator's C++ generation strategy

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions