Skip to content

[LLHD] Add coroutine, call_coroutine, return ops#10068

Merged
fabianschuiki merged 2 commits intomainfrom
fschuiki/llhd-coroutines
Mar 27, 2026
Merged

[LLHD] Add coroutine, call_coroutine, return ops#10068
fabianschuiki merged 2 commits intomainfrom
fschuiki/llhd-coroutines

Conversation

@fabianschuiki
Copy link
Copy Markdown
Contributor

Add llhd.coroutine, llhd.call_coroutine, and llhd.return ops to represent suspendable subroutines (SystemVerilog tasks) in the LLHD dialect. Coroutines are IsolatedFromAbove function-like ops that can contain llhd.wait and llhd.halt, just like processes. Calling a coroutine suspends the caller until the coroutine returns.

Update the parent constraints on llhd.wait and llhd.halt to also allow llhd.coroutine as a parent.

@fabianschuiki
Copy link
Copy Markdown
Contributor Author

Results of circt-tests run for 85a7160 compared to results for 1252379:

sv-tests

Changes in emitted diagnostics:

  • 0 total change
  • -7 error: 'llhd.halt' op expects parent op to be one of 'llhd.process, llhd.final'
  • -7 error: 'llhd.wait' op expects parent op 'llhd.process'
  • +7 error: 'llhd.halt' op expects parent op to be one of 'llhd.process, llhd.final, llhd.coroutine'
  • +7 error: 'llhd.wait' op expects parent op to be one of 'llhd.process, llhd.coroutine'

Comment on lines +800 to +807
/// Verify the type attribute of this coroutine.
mlir::LogicalResult verifyType() {
auto type = getFunctionTypeAttr().getValue();
if (!llvm::isa<mlir::FunctionType>(type))
return emitOpError("requires '") << getFunctionTypeAttrName() <<
"' attribute of function type";
return mlir::success();
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this already verified by ODS?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh good point, that should already be covered by ODS!

Copy link
Copy Markdown
Member

@uenoku uenoku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks straightforward definition for function like operations, LGTM.
One datapoint is CIR is representing coroutine an attribute on cir.func op(https://github.com/llvm/llvm-project/blob/a2d84b5d8d9c3ae3a07c4f47cd1b6b8f64be1b41/clang/include/clang/CIR/Dialect/IR/CIROps.td#L3610-L3611). Though I think creating an new operation seems more reasonable here.

@fabianschuiki
Copy link
Copy Markdown
Contributor Author

An attribute would definitely also be a valid option! For that we'd have to create a custom moore.func and llhd.func, such that the attribute could actually be a property of the op. I fear that simply adding a discardable attr onto func.func is going to be too brittle 🤔

fabianschuiki and others added 2 commits March 27, 2026 15:51
When a task reads a module-scope signal in an event control expression
like `@(posedge clk)`, the signal must be captured as an extra argument
to the task function. Previously, `convertTimingControl` set the
`rvalueReadCallback` to null to prevent event control reads from
polluting implicit `@*` sensitivity lists. This also suppressed the
function capture callback, causing the signal to be used across region
boundaries without being plumbed as an argument.

Replace the callback nulling with an `isInsideTimingControl` flag. The
implicit event callback checks this flag before recording reads, while
function capture callbacks (which don't check it) continue to work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add `llhd.coroutine`, `llhd.call_coroutine`, and `llhd.return` ops to
represent suspendable subroutines (SystemVerilog tasks) in the LLHD
dialect. Coroutines are `IsolatedFromAbove` function-like ops that can
contain `llhd.wait` and `llhd.halt`, just like processes. Calling a
coroutine suspends the caller until the coroutine returns.

Update the parent constraints on `llhd.wait` and `llhd.halt` to also
allow `llhd.coroutine` as a parent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@fabianschuiki fabianschuiki force-pushed the fschuiki/fix-signal-capture branch from 1252379 to 2cfee4e Compare March 27, 2026 22:52
@fabianschuiki fabianschuiki force-pushed the fschuiki/llhd-coroutines branch from 85a7160 to d676ea7 Compare March 27, 2026 22:52
@uenoku
Copy link
Copy Markdown
Member

uenoku commented Mar 27, 2026

Yeah I think if it had llhd.func it might make sense, but it still feels a bit brittle that you can only use llhd.wait in llhd.func when that specific attribute exists.

Base automatically changed from fschuiki/fix-signal-capture to main March 27, 2026 23:08
@fabianschuiki fabianschuiki merged commit 5df8c85 into main Mar 27, 2026
8 checks passed
@fabianschuiki fabianschuiki deleted the fschuiki/llhd-coroutines branch March 27, 2026 23:13
@fabianschuiki
Copy link
Copy Markdown
Contributor Author

Results of circt-tests run for d676ea7 compared to results for 2cfee4e:

sv-tests

Changes in emitted diagnostics:

  • 0 total change
  • -7 error: 'llhd.halt' op expects parent op to be one of 'llhd.process, llhd.final'
  • -7 error: 'llhd.wait' op expects parent op 'llhd.process'
  • +7 error: 'llhd.halt' op expects parent op to be one of 'llhd.process, llhd.final, llhd.coroutine'
  • +7 error: 'llhd.wait' op expects parent op to be one of 'llhd.process, llhd.coroutine'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants