Skip to content

[SV] Add sv.macro_instance operation#9900

Draft
uenoku wants to merge 1 commit intollvm:mainfrom
uenoku:dev/hidetou/macro-instance
Draft

[SV] Add sv.macro_instance operation#9900
uenoku wants to merge 1 commit intollvm:mainfrom
uenoku:dev/hidetou/macro-instance

Conversation

@uenoku
Copy link
Member

@uenoku uenoku commented Mar 10, 2026

The PR is still draft and tests are missing.

This commit introduces a new sv.macro_instance operation to the SV dialect, which allows instantiating a module where the actual module to instantiate is determined by a macro at elaboration time.

 %c = sv.macro_instance "foo" @Macro [@A, @B] (a: %a: i1, b: %b: i4) -> (c: i5)
`Macro foo (
   .a(a),
   .b(b),
   .c(c)
 );

The operation takes:

  • An instance name
  • A macro name (referencing an sv.macro.decl)
  • A list of candidate module names
  • Input and output ports matching the candidate modules

When exported to Verilog, it emits a macro-based module instantiation where the macro name is used as the module name.

Alternative representation considered was sv.macro.module which associates a macro with Module side, instead of with instances. This was not used because it doesn't compose well with the concept of candidate modules names and existing InstanceGraph:

hw.module public @A(in %a: i1, in %b: i1, out: c) 
hw.module @B(in %a: i1, in %b: i1, out: c) noescape
sv.macro.module @Module  macro @MacroName (in %a: i1, in %b: i1, out: c)

Also we can in fact do the same thing with existing hw.module.extern by embedding macro into its verilog name attribute, however I didn't like we have to embed macro into verilog name, and also I wanted to create edges from instances to modules in InstanceGraph

AI-assisted-by Sonnet 4.5

This commit introduces a new sv.macro_instance operation to the SV dialect,
which allows instantiating a module where the actual module to instantiate
is determined by a macro at elaboration time.

The operation takes:
- An instance name
- A macro name (referencing an sv.macro.decl)
- A list of candidate module names
- Input and output ports matching the candidate modules

When exported to Verilog, it emits a macro-based module instantiation where
the macro name is used as the module name.
Comment on lines +2961 to +2966
do {
FlatSymbolRefAttr moduleName;
if (parser.parseAttribute(moduleName))
return failure();
moduleNames.push_back(moduleName);
} while (succeeded(parser.parseOptionalComma()));
Copy link
Member Author

Choose a reason for hiding this comment

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

Manually parsing array feels not right.

Copy link
Member

@seldridge seldridge left a comment

Choose a reason for hiding this comment

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

I really like this. It makes sense to be in the SV dialect (and not HW). Additionally, I agree that there isn't any benefit in the added indirection of the macro module op.

Couple of other observations:

  1. The restriction on requiring at least one candidate instantiation seems reasonable. However, this would then mean that the canonical way to make this user-provided is to have an external module as the lone instantiation. It feels perhaps cleaner to allow for no candidate modules to be provided. However, this would be redundant with the always allowed external module case. tl;dr: I think the candidates being non-empty makes sense.
  2. Could the PR include an example of an external module so that the case of (1) could be shown, too?

@uenoku
Copy link
Member Author

uenoku commented Mar 11, 2026

However, this would then mean that the canonical way to make this user-provided is to have an external module as the lone instantiation. It feels perhaps cleaner to allow for no candidate modules to be provided

Yes, that's the intended use case. However, I think treating empty candidates as truly 'open' makes a lot of sense. One of the reasons I made this mandatory was that there are a few places (e.g., ExportVerilog uses this to get the exact port order) where the instance graph node expects non-empty referred modules. I think I can work around this (verilog doesn't care about port orders anyway).

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