llvm / llvm/circt

[CIRCT-VERILOG][ARC] arcilator fails to legalize llhd.process from always_comb with for loop

Open
#10,185 7 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
2.2k
Forks
524
Avg merge
3d 2h
Merged PRs (30d)
46

Description

## [CIRCT-VERILOG][ARC] arcilator fails to legalize llhd.process from always_comb with for loop

**Tool**: circt (CIRCT 5dc62fe)
**Severity**: Compilation Error

### Description
An `always_comb` block containing a zero-iteration for loop (`for (int i = 0; i < 0; i++);`) causes CIRCT to fail during the arcilator lowering phase. The `llhd.process` operation generated from the `always_comb` block cannot be legalized, as the LowerProcessesPass fails to convert it to `llhd.CombinationalOp`, leaving it marked as illegal when ConvertToArcs runs.

### Minimal Reproducible Example
```systemverilog
module top(output logic [3:0] out);
always_comb begin out = 4'b0;
for (int i = 0; i < 0; i++);
end endmodule
```

### Reproduction Steps
```bash
circt-verilog --ir-hw minimal_testcase.sv | arcilator
```

### Actual Output
```
circt-verilog.mlir:7:5: error: failed to legalize operation 'llhd.process' that was explicitly marked illegal: "llhd.process"() ({...}) : () -> ()
llhd.process {
^
circt-verilog.mlir:7:5: note: see current operation:
"llhd.process"() ({
"cf.br"(%2)[^bb2] : (i32) -> ()
^bb1: // pred: ^bb4
"cf.br"(%2)[^bb2] : (i32) -> ()
^bb2(%4: i32): // 3 preds: ^bb0, ^bb1, ^bb3
%5 = "comb.icmp"(%4, %1) <{predicate = 2 : i64}> : (i32, i32) -> i1
"cf.cond_br"(%5)[^bb3, ^bb4] <{operandSegmentSizes = array}> : (i1) -> ()
^bb3: // pred: ^bb2
%6 = "comb.add"(%4, %0) : (i32, i32) -> i32
"cf.br"(%6)[^bb2] : (i32) -> ()
^bb4: // pred: ^bb2
"llhd.wait"(%3)[^bb1] <{operandSegmentSizes = array}> : (i4) -> ()
}) : () -> ()
circt-verilog.mlir:1:1: error: conversion to arcs failed
module {
^
```

### Expected Output
The code should compile without error. The zero-iteration for loop is valid SystemVerilog and should not cause compilation failure.

### Cross-Tool Comparison
- **verilator**: PASS (exit_code 0, no errors)
- **iverilog**: PASS (exit_code 0, non-fatal warning only)
- **circt**: FAILS (trigger_tool)

### Root Cause (Preliminary)
The `always_comb` block is correctly lowered to `llhd::ProcessOp` by MooreToCore conversion. However, LowerProcessesPass.matchControlFlow() returns `false` for the control flow graph created by the zero-iteration for loop (where block bb2 has 3 predecessors), causing the process to remain as `llhd::ProcessOp`. When arcilator runs ConvertToArcsPass, the entire LLHD dialect is marked illegal, but only `llhd::CombinationalOp` and `llhd::YieldOp` have conversion patterns registered. The unhandled `llhd::ProcessOp` fails with "explicitly marked illegal" error.

The crash occurs at ConvertToArcs.cpp:585 where `target.addIllegalDialect()` marks the entire LLHD dialect as illegal.

### Standard Compliance Assessment
- **Classification**: tool_bug
- **IEEE References**: IEEE 1800-2017 Section 9.2.2.2 (always_comb procedure)
- **Justification**: The SystemVerilog code `always_comb begin ... for (int i = 0; i < 0; i++); ... end` is syntactically and semantically valid per IEEE 1800. The zero-iteration for loop is legal SV behavior. CIRCT should correctly process this construct without failing. The failure is in the compiler's handling of the generated IR, not in the input code itself.

Assisted-by: Claude Code:claude-opus-4-6

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the failure with `circt-verilog --ir-hw minimal_testcase.sv | arcilator`, then inspect `LowerProcessesPass.matchControlFlow()` and `ConvertToArcs.cpp` around line 585. Determine why this zero-iteration loop leaves an `llhd.process` unconverted; done means the supplied SystemVerilog example compiles successfully through arcilator without the legalization error.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.