Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Verif] Add format_verilog_string, print operations #5616

Merged
merged 3 commits into from
Jul 20, 2023

Conversation

mortbopet
Copy link
Contributor

@mortbopet mortbopet commented Jul 18, 2023

#5577, #5575 - relatively small changes, so decided to just do both of these in one go.

Re. the lowering; verif.printf lowers directly to a sv.fwrite outputting to stdout via. inspection of its source operand (which is expected to be a verif.fstr). The source fstr is not deleted in the process (there may be other users). However, i marked verif.fstr as Pure meaning that it'll get removed if canonicalize is run after lower-verif-to-sv and there are no more users.
It's expected that verif.printf will reside inside something that eventually lowers to a procedural SV region, if one is going the SV route. I'd imagine that most users will embed verif.printf inside hw.triggered regions.

#5577, #5575

Re. the lowering; `verif.printf` lowers directly to a `sv.fwrite` via. inspection of its source operand (which is expected to be a `verif.fstr`). The source `fstr` is `not` deleted in the process (there may be other users). However, i marked `verif.fstr` as `Pure` meaning that it'll get removed if `canonicalize` is run after `lower-verif-to-sv` and there are no more users of the result.
It's expected that `verif.printf` will reside inside *something* that eventually lowers to a procedural SV region, if one is going the SV route. I'd imagine that most users will embed `verif.printf` inside `hw.triggered` regions.
include/circt/Dialect/Verif/VerifOps.td Outdated Show resolved Hide resolved
Comment on lines 65 to 71
def PrintfOp : VerifOp<"printf", []> {
let summary = "Prints a formatted message.";
let arguments = (ins HWStringType:$formattedString);
let assemblyFormat = [{
$formattedString attr-dict
}];
}
Copy link
Contributor

@fabianschuiki fabianschuiki Jul 18, 2023

Choose a reason for hiding this comment

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

I think I would just call this PrintOp and verif.print, without the "f". This operation doesn't really do any formatting, it just prints a string. The formatting happens with the above op. It would be cool if the formatting didn't leak into the printing op!

We could argue that this being emitted as sv.fwrite is just an optimized lowering that's able to lower PrintOp(FormatStringOp(...)) directly. But we could also just lower the FormatStringOp into a fully interpolated SV string first, and then do an unformatted print afterwards.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed. reserve printf for when we have file handles or something.

Comment on lines 42 to 46
auto fstrOp = dyn_cast_or_null<FormatStringOp>(
op.getFormattedString().getDefiningOp());
if (!fstrOp)
return op->emitOpError()
<< "expected FormatStringOp as the source of the formatted string";
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like a good starting point! In the future we might have something like hw.constant_string which we could accept here as well. Or instead, absorbing FormatStringOp could be an optimized lowering and the default simple lowering would just be the !hw.string being passed into the sv::FWriteOp as is.

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 -- hw.string should be converted to a sv string (in export verilog) and the default lowering for fmtstring should be $*format to make this more composable.

Copy link
Contributor

@teqdruid teqdruid left a comment

Choose a reason for hiding this comment

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

lgtm % comments. thanks!

include/circt/Dialect/Verif/VerifOps.td Outdated Show resolved Hide resolved
lib/Conversion/VerifToSV/CMakeLists.txt Outdated Show resolved Hide resolved
Comment on lines 42 to 46
auto fstrOp = dyn_cast_or_null<FormatStringOp>(
op.getFormattedString().getDefiningOp());
if (!fstrOp)
return op->emitOpError()
<< "expected FormatStringOp as the source of the formatted string";
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 -- hw.string should be converted to a sv string (in export verilog) and the default lowering for fmtstring should be $*format to make this more composable.

Copy link
Contributor

@darthscsi darthscsi left a comment

Choose a reason for hiding this comment

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

LGTM modulo op naming

let summary = "Creates a formatted string.";
let description = [{
Creates a formatted string suitable for printing via the `verif.printf` op.
The formatting syntax is (for now) expected to be identical to verilog
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps be explicit in the name? FormatVerilogStringOp and format_verilog? If verilog is leaking in, lets be clear about it and then when we define an independent format string, it can have it's own op rather than having to convert all the users of this one.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed. Since printf accepts a hw.string, it shouldn't be a problem to add something else later.

Comment on lines 65 to 71
def PrintfOp : VerifOp<"printf", []> {
let summary = "Prints a formatted message.";
let arguments = (ins HWStringType:$formattedString);
let assemblyFormat = [{
$formattedString attr-dict
}];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed. reserve printf for when we have file handles or something.

ConversionTarget target(context);
RewritePatternSet patterns(&context);

target.addIllegalOp<PrintfOp>();
Copy link
Contributor

Choose a reason for hiding this comment

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

FormatStringOp can be lowered to $sformat to cover everything.

@mortbopet
Copy link
Contributor Author

Thank you for the review - updated the format string op to be called verif.format_verilog_string, and verif.print.

I'd like to do this the "right" way - that is, emit verif.format_verilog_string through $sformat(...). However, that requires me to implement string in system verilog, as well as modify fwrite to take a reference to such a SVInOutString-like type, and a whole other can of worms.

So I'll mark that as future work and go with this for now.

@mortbopet mortbopet changed the title [Verif] Add fstr, printf operations [Verif] Add format_verilog_string, print operations Jul 20, 2023
@mortbopet mortbopet merged commit 2b14a00 into main Jul 20, 2023
5 checks passed
@darthscsi darthscsi deleted the dev/mpetersen/verif_str branch June 4, 2024 14:50
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.

None yet

4 participants