[circt-bmc] handle 'verif.formal' / 'verif.contract' op in module#10772
[circt-bmc] handle 'verif.formal' / 'verif.contract' op in module#10772Clo91eaf wants to merge 3 commits into
Conversation
|
@TaoBi22 wdyt? In this way we can handle the |
|
Thanks for looking into this @Clo91eaf! I wonder if it would make sense to make this hw.module input technique a new lowering strategy in LowerSymbolicValues rather than creating a new pass - WDYT? |
|
That's really make sense! I will try this new lowering strategy! |
29ecaf5 to
7eea901
Compare
| auto result = module.walk([&](SymbolicValueOp op) -> WalkResult { | ||
| if (!op->getParentOfType<HWModuleOp>()) | ||
| return op.emitError() | ||
| << "cannot lower symbolic value to HW module input outside of an " |
There was a problem hiding this comment.
nit:
| << "cannot lower symbolic value to HW module input outside of an " | |
| << "cannot lower symbolic value to hw.module input outside of an " |
|
|
||
| if (referencedModules.contains(hwModule.getModuleNameAttr())) { | ||
| hwModule.emitError() | ||
| << "cannot lower symbolic values in instantiated module '" |
There was a problem hiding this comment.
nit: can we clarify that this is only the case for this particular lowering strategy?
| @@ -0,0 +1,22 @@ | |||
| // RUN: circt-opt %s --verif-lower-symbolic-values=mode=hw-input --split-input-file --verify-diagnostics | FileCheck %s | |||
There was a problem hiding this comment.
Could these be moved into the existing test files for this pass?
| @@ -0,0 +1,22 @@ | |||
| // RUN: circt-opt %s --verif-lower-symbolic-values=mode=hw-input --split-input-file --verify-diagnostics | FileCheck %s | |||
|
|
|||
| // CHECK-LABEL: hw.module @M(in %symbolic_value : i8, out y : i8) | |||
There was a problem hiding this comment.
Can these be regex rather than hardcoded names?
|
|
||
| // CHECK-NOT: verif.symbolic_value | ||
| // CHECK-LABEL: func.func @Callee( | ||
| // CHECK-SAME: %arg0: !smt.bv<8>, %arg1: !smt.bv<8> |
| // CHECK-NOT: verif.symbolic_value | ||
| // CHECK-LABEL: func.func @Callee( | ||
| // CHECK-SAME: %arg0: !smt.bv<8>, %arg1: !smt.bv<8> | ||
| // CHECK: smt.assert |
There was a problem hiding this comment.
maybe check what we're asserting too?
7eea901 to
da63082
Compare
| hw.output %0 : i8 | ||
| } | ||
|
|
||
| // expected-error @+1 {{cannot lower symbolic values in instantiated module}} |
There was a problem hiding this comment.
nit: can we include the full error message?
| auto result = module.walk([&](SymbolicValueOp op) -> WalkResult { | ||
| if (!op->getParentOfType<HWModuleOp>()) | ||
| return op.emitError() | ||
| << "cannot lower symbolic value to hw.module input outside of an " |
There was a problem hiding this comment.
I think this is missing a test
This fixes
circt-bmconverif.contractlowering results.circt-bmcalready supportsverif.formal: its pipeline runsverif-lower-tests, which lowers a selected formal test into anhw.modulebefore BMC lowering. The issue is specific to the IR shape produced bylower-contracts.lower-contractsemits a generatedverif.formalproof op, but also keeps the originalhw.modulein the surroundingbuiltin.modulewith the contract applied to it. In that apply-mode module, contract results are replaced byverif.symbolic_value, and contract ensures becomeverif.assume.When invoking
circt-bmc --module <generated-formal>, the intended target is only the generatedverif.formal. However, the BMC pipeline runs over the wholebuiltin.module, so unrelated top-level tests and modules may still be processed. This patch detects when--moduleresolves to averif.formal, keeps that formal and its top-level symbol dependencies, and removes unrelated top-levelhw.module,verif.formal, andverif.simulationops before running the existing BMC pipeline.This also handles generated formals that depend on callee contract abstractions. After contract lowering, a caller proof may instantiate a callee whose contract has been applied as an abstraction. During BMC lowering,
hw-flatten-modulesinlines that callee abstraction into the selected target, which can leaveverif.symbolic_valueops constrained byverif.assumeinside the flattened module. The patch materializes those symbolic values as additional module inputs after flattening, preserving their nondeterministic semantics in a form the BMC pipeline can lower.For example:
would be lowered after
--lower-contractstoHere the
@Caller_CheckContract_0is depending the@Calleeand thehw-flatten-modulespass will flatten the@Calleein the@Caller_CheckContract_0toSo that the
@Calleecan become an abstract module rather than a specified implement during the formal verification solving. But this can not be processed bycirct-bmcbecauseAnd this pr move it to the input so we can see the symbolic value of the children module as the symbolic value of the parent module.
Testing
This PR adds regression coverage that starts from real
verif.contractIR, runs--lower-contracts, and then invokescirct-bmcon the generatedverif.formal, including a caller/callee case where the selected proof depends on an applied callee contract abstraction.Assisted-by: Codex:GPT-5.5