Skip to content

[Sim][SimToSv] DPI-C Semantic preserving sim.func.dpi and sim.func.dpi.call#9977

Merged
uenoku merged 7 commits intollvm:mainfrom
pscabot:dev/pscabot/sim_dpi_call
Apr 3, 2026
Merged

[Sim][SimToSv] DPI-C Semantic preserving sim.func.dpi and sim.func.dpi.call#9977
uenoku merged 7 commits intollvm:mainfrom
pscabot:dev/pscabot/sim_dpi_call

Conversation

@pscabot
Copy link
Copy Markdown
Contributor

@pscabot pscabot commented Mar 19, 2026

Introduce DPIDirection enum (Input, Output, InOut, Return, Ref) and
DPIFunctionType, a first-class MLIR type that bundles port name, type,
and direction. DPIFuncOp now stores DPIFunctionType + FunctionType
instead of hw::ModuleType + per_argument_attrs.

  • SimTypes: DPIArgumentstruct, DPIFunctionTypeStorage with cached index
    arrays. Shared helpers (stringifyDPIDirectionKeyword,
    parseDPIDirectionKeyword, isCallOperandDir) and
    DPIModuleType::verify() for reuse by downstream dialects.
  • SimOps: DPIFuncOp parser/printer with keyword syntax
    (input/output/inout/return/ref). Verifier adds sim-specific
    checks (ref→llvm.ptr, function_type consistency).
  • LowerDPIFunc: Iterates DPIFunctionType ports directly.
  • FIRRTL LowerDPI: Builds DPIModuleType; dedup keyed on
    {StringAttr, DPIModuleType}.
  • SimDPI.md: Elaborates design choices for the new semantics.

AI-Assisted-by: GitHub Copilot CLI with GPT-5.4 and Claude Opus 4.6

This is the first of a 2 PR series introducing full sematic preserving DPI calls from SystemVerilog through Moore to Sim.

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.

The proposal makes sense to me. Thank you for working on this! One high-level comment is can you consider introducing a type for dpi function that correctly capture sim.func.explicitly_returned and byref as more structured way instead of putting on operations? I admit I'm the one that abused ModuleType but would be fantastic if we can use this opportunity to clean up.

@pscabot
Copy link
Copy Markdown
Contributor Author

pscabot commented Mar 19, 2026

The proposal makes sense to me. Thank you for working on this! One high-level comment is can you consider introducing a type for dpi function that correctly capture sim.func.explicitly_returned and byref as more structured way instead of putting on operations? I admit I'm the one that abused ModuleType but would be fantastic if we can use this opportunity to clean up.

So, departing from the ModuleType is certainly an option. I considered it but it seemed a bit too invasive. I will try to do it.

@uenoku
Copy link
Copy Markdown
Member

uenoku commented Mar 19, 2026

Thanks, that would be really great!

@pscabot pscabot force-pushed the dev/pscabot/sim_dpi_call branch from 71e2b6e to c85d35e Compare March 23, 2026 12:40
Introduce DPIDirection enum (Input, Output, InOut, Return, Ref) and
DPIModuleType, a first-class MLIR type that bundles port name, type,
and direction. DPIFuncOp now stores DPIModuleType + FunctionType
instead of hw::ModuleType + per_argument_attrs.

- SimTypes: DPIPort struct, DPIModuleTypeStorage with cached index
  arrays. Shared helpers (stringifyDPIDirectionKeyword,
  parseDPIDirectionKeyword, isCallOperandDir) and
  DPIModuleType::verify() for reuse by downstream dialects.
- SimOps: DPIFuncOp parser/printer with keyword syntax
  (input/output/inout/return/ref). Verifier adds sim-specific
  checks (ref→llvm.ptr, function_type consistency).
- LowerDPIFunc: Iterates DPIModuleType ports directly.
- SimToSV: Uses getHWModuleType() at conversion boundary.
- FIRRTL LowerDPI: Builds DPIModuleType; dedup keyed on
  {StringAttr, DPIModuleType}.
- SimDPI.md: Elaborates design choices for the new semantics.
@pscabot pscabot force-pushed the dev/pscabot/sim_dpi_call branch from c85d35e to 269f033 Compare March 23, 2026 13:18
@pscabot pscabot requested a review from uenoku March 23, 2026 13:33
@pscabot
Copy link
Copy Markdown
Contributor Author

pscabot commented Mar 24, 2026

Thanks, that would be really great!

OK. So it is done. Indeed more invasive but the semantics are much better

@pscabot
Copy link
Copy Markdown
Contributor Author

pscabot commented Mar 30, 2026

Thanks, that would be really great!

@uenoku Hi, are you planning to review this PR? Is there anything else I should do? Is there anyone else I should contact somehow? I hope I am not being too bold, just noticed there wasn't any movement :-). Thanks _/||\_

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.

Generally looks good to me. Sorry for delay.

Comment thread integration_test/arcilator/JIT/dpi.mlir Outdated
Comment thread include/circt/Dialect/Sim/SimTypes.td Outdated
KeyTy getAsKey() const { return ports; }

llvm::ArrayRef<DPIPort> getPorts() const { return ports; }

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.

Could you consider store mlir::FunctionType in the storage?

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.

I will try

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.

DPIPort contains information about the direction and semantics of the arguments/ports. If we simply use FunctionType as storage we will not have this information which is integral to this change. Or maybe I misunderstood your meaning?

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.

Ah I meant to simply store mlir::FunctionType in DPIFunctionTypeStorage, instead of storing in DPIFuncOp since it a bit weird that DPIFuncOp takes two types

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.

Done

Comment thread include/circt/Dialect/Sim/SimTypes.td Outdated
Comment on lines +215 to +217
auto it = state.dpiFuncDeclMapping.find(op.getCalleeAttr().getAttr());
if (it != state.dpiFuncDeclMapping.end())
op.setCallee(it->second.getSymNameAttr());
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.

What was the reason for this behavior change?

Copy link
Copy Markdown
Contributor Author

@pscabot pscabot Apr 2, 2026

Choose a reason for hiding this comment

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

My bad. There is no "real" need for this change, and it is actually a bad change as it is implemented now. I wanted to avoid an undefined behavior in case of malformed IR (which should actually be caught before) but ended up silently masking the error. I will emit an explicit failure

sim.func.dpi @add_mlir(in %a : i32, in %b : i32, out c : i32) attributes {verilogName = "add_mlir_impl"}
sim.func.dpi @mul_shared(input %a : i32, input %b : i32, output c : i32)
sim.func.dpi @add_mlir(input %a : i32, input %b : i32, output c : i32) attributes {verilogName = "add_mlir_impl"}
func.func @add_mlir_impl(%arg0: i32, %arg1: i32, %arg2: !llvm.ptr) {
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.

Not blocking, but does JIT work with inout already?

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.

As far as I can tell ARC goes through LowerDPIFunc so it should be supported. Should we add a test for it here? If it doesn't work, whould it be fixed as part of this PR?

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.

No I was just curios! Thank you for checking!

Comment thread lib/Dialect/Sim/SimTypes.cpp
Comment thread test/Dialect/Sim/lower-dpi-errors.mlir Outdated
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.

LGTM, thanks!

@uenoku uenoku merged commit 1696571 into llvm:main Apr 3, 2026
7 of 8 checks passed
joaovam pushed a commit to joaovam/circt that referenced this pull request Apr 10, 2026
…i.call (llvm#9977)

Introduce DPIDirection enum (Input, Output, InOut, Return, Ref) and
DPIFunctionType, a first-class MLIR type that bundles port name, type,
and direction. DPIFuncOp now stores DPIFunctionType + FunctionType
instead of hw::ModuleType + per_argument_attrs.

- SimTypes: DPIArgumentstruct, DPIFunctionTypeStorage with cached index
  arrays. Shared helpers (stringifyDPIDirectionKeyword,
  parseDPIDirectionKeyword, isCallOperandDir) and
  DPIModuleType::verify() for reuse by downstream dialects.
- SimOps: DPIFuncOp parser/printer with keyword syntax
  (input/output/inout/return/ref). Verifier adds sim-specific
  checks (ref→llvm.ptr, function_type consistency).
- LowerDPIFunc: Iterates DPIFunctionType ports directly.
- FIRRTL LowerDPI: Builds DPIModuleType; dedup keyed on
  {StringAttr, DPIModuleType}.
- SimDPI.md: Elaborates design choices for the new semantics.

AI-Assisted-by: GitHub Copilot CLI with GPT-5.4 and Claude Opus 4.6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants