Skip to content

[circt-verilog][arcilator] arcilator fails to lower llhd.constant_time generated from simple SV delay (#1) #9467

@m2kar

Description

@m2kar

Title

[circt-verilog][arcilator] arcilator fails to lower llhd.constant_time generated from simple SV delay (#1)

Summary

I ran into a failure in the arcilator flow with a minimal SystemVerilog module using a single #1 delay. The same design runs under Verilator, but arcilator reports llhd.constant_time as illegal during conversion to arcs and stops. I did a preliminary source-level analysis (below) and would like to discuss with maintainers whether this behavior is expected or should be treated as a bug.

Details

The SV design is intentionally minimal and only uses an initial block with a
single #1 delay. There are no clocks, resets, or inputs. The only signals are
two outputs (q and ok) to indicate observable state and a success message.

Behavior:

  • At time 0, both q and ok are set to 0.
  • After #1, q is set to 1, ok is set to 1, and a $display message is
    printed.

Observed issue:

  • circt-verilog --ir-hw converts the #1 delay into llhd.constant_time.
  • The arcilator pipeline then fails when lowering to arcs, reporting that
    llhd.constant_time is illegal and the conversion fails.
  • The same SV code runs successfully under Verilator, so the issue appears
    specific to the arcilator lowering path.

Reproduction

arcilator

Create top.sv:

module top(output logic q, output logic ok);
  initial begin
    q = 1'b0;
    ok = 1'b0;
    #1 q = 1'b1;
    ok = 1'b1;
    $display("OK: arcilator run completed");
  end
endmodule

Run:

circt-verilog --ir-hw top.sv -o top.mlir
arcilator top.mlir --state-file=top.json | opt -O3 --strip-debug -S | llc -O3 --filetype=obj -o top.o
cc top.o -o top
./top

verilator

Use the same top.sv content as above.

Run:

verilator -Wall --cc top.sv --exe sim_main.cpp
make -C obj_dir -f Vtop.mk Vtop
./obj_dir/Vtop

Actual Result (arcilator)

top.mlir:4:10: error: failed to legalize operation 'llhd.constant_time' that was explicitly marked illegal
    %0 = llhd.constant_time <1000000fs, 0d, 0e>
         ^
top.mlir:1:1: error: conversion to arcs failed
module {
^

Expected Result

The minimal delay should either:

  • be supported by arcilator, or
  • be lowered to something legal for arcs without failing.

Question:

How to solve this problem and simulate this sv problem?

Analysis of Failure Cause

Based on the current sources, my preliminary analysis is that the failure stems from a missing legalization pattern in the ConvertToArcs pass:

  • llhd.constant_time is a valid LLHD op produced by circt-verilog --ir-hw for #1 delays.
  • The arcilator pipeline runs ConvertToArcs, which marks the entire LLHD dialect illegal and only provides conversions for llhd.combinational and llhd.yield.

void ConvertToArcsPass::runOnOperation() {
// Setup the type conversion.
TypeConverter converter;
// Define legal types.
converter.addConversion([](Type type) -> std::optional<Type> {
if (isa<llhd::LLHDDialect>(type.getDialect()))
return std::nullopt;
return type;
});
// Gather the conversion patterns.
ConversionPatternSet patterns(&getContext(), converter);
patterns.add<llhd::CombinationalOp>(convert);
patterns.add<llhd::YieldOp>(convert);
// Setup the legal ops. (Sort alphabetically.)
ConversionTarget target(getContext());
target.addIllegalDialect<llhd::LLHDDialect>();

  • As a result, llhd.constant_time remains illegal with no rewrite available, and the dialect conversion reports a legalization failure.

Environment

  • OS: Linux 5.15.0-164-generic
  • CIRCT: firtool-1.139.0
  • LLVM: 22.0.0git
  • Verilator: 5.022 2024-02-24 (rev v5.020-157-g2b4852048)
  • Git commit: 2e2f477

Notes

The failure appears at the llhd.constant_time op introduced during circt-verilog --ir-hw, before arcilator lowers to arcs.

Relevant Source References

  • llhd.constant_time is a core LLHD op that materializes a time constant. It is defined as llhd.constant_time in the LLHD value ops definition file. See include/circt/Dialect/LLHD/IR/LLHDValueOps.td.
  • The ConvertToArcs pass marks the entire LLHD dialect as illegal and only provides conversion patterns for llhd.combinational and llhd.yield. This means any other LLHD ops (including llhd.constant_time) remain illegal and will trigger a legalization failure. See lib/Conversion/ConvertToArcs/ConvertToArcs.cpp.
  • The arcilator pipeline explicitly runs ConvertToArcs as part of its arc conversion pipeline. See lib/Tools/arcilator/pipelines.cpp.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions