-
Notifications
You must be signed in to change notification settings - Fork 383
[LTL][ImportVerilog] Add support for $rose, $stable, $fell #8999
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
Conversation
bd09846 to
f80e221
Compare
This commit adds support for lowering `$rose` `$stable` and `$fell` from assertion contexts into LTL.
To this end, this PR adds a new operation for look-back semantics, `ltl.PastOp`.
* **New op**
* `ltl.past`: takes a sequence and an integer delay, returning the sequence observed `$delay` cycles earlier.
* **Assertion system call lowering**
* Added `Context::convertAssertionSystemCallArity1` to map single-argument system calls into LTL constructs:
* `$rose(x)` → `x ∧ ¬past(x,1)`
* `$fell(x)` → `¬x ∧ past(x,1)`
* `$stable(x)` → `(x ∧ past(x,1)) ∨ (¬x ∧ ¬past(x,1))`
* Integrated into `convertAssertionCallExpression` to dispatch on `$rose/$fell/$stable` from the AST.
* **Conversion plumbing**
* Added entry point `convertAssertionCallExpression` to `Context`.
* Adjusted `Expressions.cpp` visitor to recognize these system calls and redirect them to the new assertion conversion path.
* **Tests**
* Extended `builtins.sv` with assertions using `$rose`, `$fell`, `$stable`.
* CHECK lines verify correct lowering into `ltl.past`, `ltl.not`, `ltl.and`, `ltl.or` sequences.
f80e221 to
41e1fed
Compare
|
I think this PR should be implemented after the #8673 is finished. Wdyt? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Only a minor comment on past on sequences.
include/circt/Dialect/LTL/LTLOps.td
Outdated
|
|
||
| def PastOp : LTLOp<"past", [Pure]> { | ||
| let arguments = (ins | ||
| LTLAnySequenceType:$input, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the semantics of ltl.past when used on a sequence instead of a boolean? Does that mean the sequence must have finished matching in the previous cycle? And how would we print an ltl.past with a sequence input back as Verilog?
If I remember correctly, the $past function in Verilog only operates on booleans. In that case it might make sense to make ltl.past operate on just i1 for now. It's always easier to start with an overconstrained op and relax later, than figuring out semantics later 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair point, I'll limit it to i1 for this PR!
@sequencer Good point, this also has the concerning quality of magically inferring what clock the Do you have an idea how we could do that clock inference in ImportVerilog? Would we apply the clock inference rules of the SV standard and search for a parent construct that has a clock, and then use that when we create the LTL ops? |
Hi, I wasn't aware of the discussion in #8673. It's clearly important & useful work, but judging from the duration from opening until now (2.5 months) I would suppose it will take some time to land. |
|
FWIW slang implements all of the clock flow and clock inference rules from the LRM in its analysis layer, e.g. https://github.com/MikePopoloski/slang/blob/6637781e9315193e6ca2cfd3128d91eb05acd41a/source/analysis/AnalyzedAssertion.cpp#L269 (and yes, the rules are arcane and messy). This is not easily exposed via a nice API at the moment, mostly because I wasn't sure how downstream consumers would like it to be presented. I'm happy to accept a proposal for how that information could be extracted and made usable by the ImportVerilog pass. |
@MikePopoloski Reusing this from Slang would be absolutely fantastic 🥳. Not having to go through all the pain of distilling out those rules again, and instead helping maintain a single implementation sounds much more reasonable. ImportVerilog simply walks the AST and conjures up IR ops along the way. It would be nice if we could either run the analysis for asserts and sampled value funcs as we encounter them, and then basically ask what the implied clock is, or if we could run the analysis once on the entire AST, and then just query that analysis for the implied clocks. Would something like that make sense? |
|
I think I'm going to land this now to not hold up subsequent work. Hope that's okay with you, @sequencer! |
Yes, the AnalysisManager runs in one pass once the AST is fully constructed. The question is how to store and query the results of the assertion analysis. |
|
Could we populate a hash map with the analysis results for each relevant AST node? Something that makes it easy to later pick up one of the asserts or sampled value function calls, and ask the analysis for the stored information associated with that. If the analysis is just visiting the AST and generating diagnostics, you could also leave the burden of storing the analysis results in a meaningful format to the user by accepting a callback function that the analysis calls whenever it has gathered some information. ImportVerilog could then supply its own callback that just stores the info in a format convenient for it. On the other hand, I could see other users of Slang be interested in this info. Having the analysis result stored in some form on the Slang side would be useful for that. |
|
I opened MikePopoloski/slang#1528 to track adding the API. I'm leaning toward a callback but we'll see how it looks when I start working on it. |
You're a legend, Mike! Let us know if we can help in any way. |
This commit adds support for lowering
$rose$stableand$fellfrom assertion contexts into LTL.To this end, this PR adds a new operation for look-back semantics,
ltl.PastOp.ltl.past: takes an integer and a delay, returning the sequence observed$delaycycles earlier.Context::convertAssertionSystemCallArity1to map single-argument system calls into LTL constructs:$rose(x)→x ∧ ¬past(x,1)$fell(x)→¬x ∧ past(x,1)$stable(x)→(x ∧ past(x,1)) ∨ (¬x ∧ ¬past(x,1))convertAssertionCallExpressionto dispatch on$rose/$fell/$stablefrom the AST.convertAssertionCallExpressiontoContext.Expressions.cppvisitor to recognize these system calls and redirect them to the new assertion conversion path.builtins.svwith assertions using$rose,$fell,$stable.ltl.past,ltl.not,ltl.and,ltl.orsequences.