Skip to content

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

Open
pscabot wants to merge 4 commits intollvm:mainfrom
pscabot:dev/pscabot/sim_dpi_call
Open

[Sim][SimToSv] DPI-C Semantic preserving sim.func.dpi and sim.func.dpi.call#9977
pscabot wants to merge 4 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.

// CHECK-NEXT: d = {{0*}}6
sim.func.dpi @mul_shared(in %a : i32, in %b : i32, out c : i32)
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)
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.

nit: Could you use in/out terminology for the consistency with module?

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 could. I chose input/output etc for the same terminology as SystemVerilog. If considering this you are still sure you want to change it I will.

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.

I generally prefer consistency with HW dialect over System verilog itself. SystemVerilog uses terminology input/output for ports, but we are using in/out for hw.module.

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

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?

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?

// DPIFunctionType parser/printer
//===----------------------------------------------------------------------===//

/// Parse: !sim.dpi_functy<input "a" : i32, output "b" : i32>
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.

Please add ronud-trip test for dpi_functy


hw.module @top() {
hw.output
} No newline at end of file
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.

nit: please insert newline at the end of file

Suggested change
}
}

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