Skip to content

[ImportVerilog] Add queue insert/delete ops#9632

Open
Lauriethefish wants to merge 4 commits intollvm:mainfrom
Lauriethefish:queue-ins-del
Open

[ImportVerilog] Add queue insert/delete ops#9632
Lauriethefish wants to merge 4 commits intollvm:mainfrom
Lauriethefish:queue-ins-del

Conversation

@Lauriethefish
Copy link
Contributor

@Lauriethefish Lauriethefish commented Feb 7, 2026

Requires adding support for arity-3 system calls (Insert takes two parameters plus a queue), which has been done following the existing convention. Other than that, the work is roughly the same as in #9537.

The Delete method has been split into two Moore ops, one for each of its overloads:

  • If an index is supplied, QueueDeleteOp removes the element at that index.
  • If no index is supplied, QueueClearOp clears the entire queue.

Insert is implemented as QueueInsertOp.

If @Scheremo or @TaoBi22 could review when available 😃

Requires adding support for arity-3 system calls.
The `Delete` method has been split into two moore ops, one for each of its overloads:
- If an index is supplied, `QueueDeleteOp` removes the element at that index.
- If no index is supplied, `QueueClearOp` clears the entire queue.
Copy link
Contributor

@TaoBi22 TaoBi22 left a comment

Choose a reason for hiding this comment

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

This looks great! A couple of comments but they're both super minor

See IEEE 1800-2023 § 7.10.2.2 "Insert()"
}];
let arguments = (ins QueueType:$queue, TwoValuedI32:$index, UnpackedType:$item);
let results = (outs VoidType:$out);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can probably just not declare any results on these ops (I see @Scheremo used this VoidType result style on some existing queue ops though, @Scheremo is there a specific reason for that?)

Copy link
Contributor Author

@Lauriethefish Lauriethefish Feb 9, 2026

Choose a reason for hiding this comment

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

Perhaps: It makes for a more consistent style in convertSystemCallArity*. If the return type is a VoidType then it is possible to return the result of QueueDeleteOp::create directly instead of needing to have a separate line return Value();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll make a commit locally that removes all the instances of VoidType, then depending on the outcome of this conversation I'll push it to the branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This turns out to be quite an annoying one to fix: convertSystemCall emits the error unsupported system call if the result returned is a null value, and VoidType conveniently gets around this. Assuming we want to avoid a significant refactor, it might be easiest to keep VoidType.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with @TaoBi22: it would be great to have these ops not return a result 👍. Better to sort the weird SystemVerilog expression/statement stuff out during the AST-to-IR conversion. The result-less ops should work nicely from the system call conversion in Statements.cpp (see other comment) 😃

Copy link
Contributor

Choose a reason for hiding this comment

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

I publicly agree with both @TaoBi22 and @fabianschuiki, I think we can drop the VoidType return value on all queue ops 🤔

Copy link
Contributor

@fabianschuiki fabianschuiki left a comment

Choose a reason for hiding this comment

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

Hey @Lauriethefish, thanks a lot for working on this. This is a really cool addition to the Verilog frontend 🥳. Just a minor comment about op name and result type. Otherwise this looks good to me!

Comment on lines +2816 to +2822
.Case("delete",
[&]() -> Value {
if (isa<moore::QueueType>(value.getType())) {
return moore::QueueClearOp::create(builder, loc, value);
}
return {};
})
Copy link
Contributor

Choose a reason for hiding this comment

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

Out of curiosity: do you know if you can use a q.delete(...) in an expression? If I recall correctly from SV, they don't return a result, or some weird notion of a void type in SV which you can never use in an expression.

You migth be able to add support for this result-less queue ops to the Statements.cpp file instead: https://github.com/llvm/circt/blob/main/lib/Conversion/ImportVerilog/Statements.cpp#L855-L861. That way you don't have to deal with result types 😃

Comment on lines +3993 to +3995
q.delete(1);
q.delete();
q.insert(0, 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Very cool 😎

See IEEE 1800-2023 § 7.10.2.2 "Insert()"
}];
let arguments = (ins QueueType:$queue, TwoValuedI32:$index, UnpackedType:$item);
let results = (outs VoidType:$out);
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with @TaoBi22: it would be great to have these ops not return a result 👍. Better to sort the weird SystemVerilog expression/statement stuff out during the AST-to-IR conversion. The result-less ops should work nicely from the system call conversion in Statements.cpp (see other comment) 😃

}];
}

def QueueInsertOp : MooreOp<"insert", [
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you mind prefixing these ops with queue.? I think we'll have more than one insert op, one for each container type. Something like this:

Suggested change
def QueueInsertOp : MooreOp<"insert", [
def QueueInsertOp : MooreOp<"queue.insert", [

(We probably should tweak push_front and friends in the future, too.)

Copy link
Contributor

@fabianschuiki fabianschuiki left a comment

Choose a reason for hiding this comment

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

Hey @Lauriethefish, thanks a lot for working on this. This is a really cool addition to the Verilog frontend 🥳. Just a minor comment about op name and result type. Otherwise this looks good to me!

Copy link
Contributor

@Scheremo Scheremo left a comment

Choose a reason for hiding this comment

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

Just realised I never submitted this review!
Mostly LGTM. I would agree with @TaoBi22 and @fabianschuiki on outstanding action items.

See IEEE 1800-2023 § 7.10.2.2 "Insert()"
}];
let arguments = (ins QueueType:$queue, TwoValuedI32:$index, UnpackedType:$item);
let results = (outs VoidType:$out);
Copy link
Contributor

Choose a reason for hiding this comment

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

I publicly agree with both @TaoBi22 and @fabianschuiki, I think we can drop the VoidType return value on all queue ops 🤔

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.

4 participants