Skip to content
STIMSMITH

Counterexample Generation

Concept WIKI v3 · 8/1/2026

Counterexample generation is the activity of turning the satisfiable result of checking a negated property into a concrete artifact that witnesses how the property can be violated. In the UCLID5 setting, an SMT solver's satisfying assignment is converted into a counterexample that diagnoses design, modeling, or specification problems. In directed micro-architectural test generation and ADL-driven functional test generation for microprocessors, the same mechanism is repurposed so that counterexamples become concrete test programs (instruction sequences), built by decomposing properties across partitioned modules and merging the partial counterexamples back together. In stochastic and theorem-proving contexts, the notion is extended to collections of violating paths with sufficient probability and to example-driven diagnosis of failed conjectures.

Definition

Counterexample generation is the activity of turning the satisfiable result of checking a negated property into a concrete artifact that witnesses how the property can be violated. The cited evidence describes several distinct settings in which this notion appears.

In the UCLID5 setting, the workflow checks a verification condition by asking an SMT solver to satisfy the negation of the desired property; when the solver returns that the formula is satisfiable, it supplies concrete values for all data elements in the formula, including uninterpreted functions, and UCLID5 uses those values to construct a counterexample: a sequence of actions that could occur in the model and violate a verification condition. [counterexample-generation-from-satisfiability]

In the directed micro-architectural test generation setting, the negated version of a desired property together with the processor model is applied to a model checker, which automatically produces a counterexample that contains a sequence of instructions (a test program) leading from an initial state to a failure state. [mtv06-test-generation-from-counterexample]

In the ADL-driven functional test program generation setting using SMV, designers write properties by hand specifying the negation of the behavior they want to validate; the SMV model checker then produces a counterexample in the form of an instruction sequence, which is converted into a complete test (instruction sequence plus expected results) by a cycle-accurate structural simulator generated from the Architecture Description Language (ADL) specification. [adl-smv-counterexample]

Role in a UCLID5 Verification Flow

Given a model and verification script, UCLID5 generates verification conditions as formulas in logics that support the theories used by the model. These formulas are typically negations of the properties the user wants to verify, and UCLID5 invokes an SMT solver to analyze them. [verification-condition-generation]

The solver can return three outcomes:

  • Unsatisfiable: because the checked formula is typically the negation of the property, unsatisfiability indicates that the desired verification condition holds.
  • Satisfiable: the solver provides concrete satisfying values, which typically implies that some verification condition failed; these values are used for counterexample generation.
  • Indeterminate: the solver cannot find a satisfying solution but also cannot prove unsatisfiability, which typically indicates that the model is too complex or needs reasoning beyond what the solver can provide. [solver-outcomes]

Diagnostic Meaning

A generated counterexample is not automatically proof of a design bug alone. In the cited UCLID5 setting, counterexamples are important indications of one of three situations: a true error in the design, an inaccurate or overly abstract model, or an improperly expressed verification condition. [counterexample-diagnostics]

Interaction with Abstraction

The UCLID5 evidence emphasizes that formal models involve choices about data types and abstraction level. A general rule stated for the UCLID5 modeling context is to use the most abstract model that still captures the properties required for correctness. Counterexamples can therefore serve as feedback not only about the implementation being modeled, but also about whether the abstraction is too coarse or otherwise inaccurate. [model-abstraction]

Example Context from the Evidence

The cited UCLID5 report applies this workflow to formal verification of pipelined Y86-64 microprocessors, using the Z3 SMT solver (UCLID5 version 0.9.5 and Z3 version 4.5.0). [uclid5-z3-context]

Counterexample Generation as ADL-Driven Functional Test Generation (SMV)

In the cited ADL-driven approach, the designer starts by specifying the microprocessor architecture in an Architecture Description Language (ADL); the processor model is generated automatically from this ADL specification and described in the SMV language. The verification engineer writes properties by hand in SMV (specifically, the negation of the property that should hold). The SMV model checker is applied to the model with these negated properties and produces a counterexample in the form of an instruction sequence that activates the targeted behavior. Each counterexample is then combined with the expected results produced by a cycle-accurate structural simulator (also generated automatically from the ADL specification) to yield a complete functional test. Coverage reports from the simulator drive the addition of new properties when coverage is insufficient. [adl-smv-overview]

Two concrete examples from this setting illustrate the workflow:

  • A property hazard: assert G(ID._stall = 0); is used to generate a counterexample that stalls the decode unit via a read-after-write hazard. The property is negated and applied to the SMV model; the SMV model checker returns an instruction sequence (NOP, ADD R3,R1,R2, ADD R4,R3,R2) that exercises the stall at cycle 4. The reported run time was 1.3 seconds on a 359 MHz Sun UltraSPARC-II with 2048M RAM. [adl-smv-stall-example]
  • A property init: assert G((cycle = 8) -> X((DIV.Ain != 2) | (DIV.Bin != 3))); is added to drive a previously uncovered path in the division unit by initializing internal registers Ain and Bin to values 2 and 3 at clock cycle 9. The model checker produces a counterexample (NOPs followed by MOVI R4,#2; MOVI R5,#3; DIV R0,R4,R5) in 75.4 seconds on the same platform. [adl-smv-div-example]

The cited approach explicitly states that it pursues this direction because functional verification consumes a significant portion of the microprocessor design cycle, and model checking offers an opportunity to reduce validation cost. Future work identified in this report includes applying the resulting tests to the RTL description of the processor, automatic coverage estimation, and automatic generation of properties from the ADL specification. The authors also note that they are investigating the use of SAT-based bounded model checkers to generate functional test programs. [adl-smv-summary]

Counterexample Generation as Directed Test Generation (e500 Pipeline)

In the directed micro-architectural test generation work on the e500 superscalar processor (Power Architecture Technology), counterexample generation is repurposed as test-program generation. The processor model is partitioned into multiple modules based on functional units (e.g., reservation stations, issue, decode, GIQ, rename buffer), because verifying the whole model as a single unit is infeasible due to state explosion during model checking. [mtv06-model-partitioning]

Properties expressed in Linear Temporal Logic (LTL) using operators G, F, X, U combined with Boolean connectives ∧, ∨, ¬, → are generated from pipeline interactions and negated so that a counterexample represents an interaction fault. A common pattern is F(p1 ∧ p2 ∧ … ∧ pn), expressing that activities pi over n modules must become true at some time step. [mtv06-ltl-properties]

Naively checking the negated property against the whole model is unsuitable because of state explosion. To counter this, the cited approach decomposes properties across modules and uses decompositional model checking, in which sub-properties are applied to appropriate modules and partial counterexamples are merged to construct a final test program. [mtv06-decompositional-mc]

Property Decomposition for Counterexample Generation

Simple decompositions enabled by the Boolean structure of properties include:

  • G(p ∧ q) = G(p) ∧ G(q)
  • F(p ∨ q) = F(p) ∨ F(q)
  • X(p ∨ q) = X(p) ∨ X(q)
  • X(p ∧ q) = X(p) ∧ X(p)

Some combinations are not decomposable at all, for example F(p ∧ q) = F(p) ∧ F(q) and G(p ∨ q) = G(p) ∨ G(q). Other combinations such as pUq, F(p → F(q)), or F(p → G(q)) are decomposable in principle but the decomposition is not beneficial compared to traditional model checking. [mtv06-decomposition-rules]

Introducing an explicit clock (time step) variable clk and a specific time step ts into the property enables additional decompositions that are useful for counterexample generation. Although the left- and right-hand sides of these decompositions are not logically equivalent, they produce functionally equivalent counterexamples. An example is:

G((clk = ts) ∨ (p ∨ q)) ≈ G((clk = ts) ∨ p) ∨ G((clk = ts) ∨ q) [mtv06-clock-based-decomposition]

Merging Partial Counterexamples

A key challenge is integrating partial counterexamples generated for partitioned modules, because the relationships among decomposed modules and sub-properties are not generally preserved at the whole-design level. The cited approach proposes clock-based integration of partial counterexamples: when two sub-properties are applied at the same clock cycle (clk = ts) to two modules sharing a parent module, the two generated counterexamples are merged into the output property of the parent module, which is then used to generate counterexamples at the previous clock cycle (clk = ts − 1). [mtv06-merge-partial-cxes]

In the e500 pipeline, for instance, four reservation station (RS) modules share the Issue stage as a parent module; counterexamples generated from multiple RS modules at cycle k are merged into the output property of the Issue stage at cycle k, and the negated version of that property is applied to the model checker together with the Issue module to generate a counterexample at cycle k − 1 that produces the output properties of Decode, GIQ, and Rename buffer. Merging continues until the primary input instruction sequence is obtained. [mtv06-merge-example]

Produced Test Programs

The approach was applied to a set of interaction faults and corner cases, producing concrete test programs of the following kinds, with associated test code lengths:

Test case Description Test code length
1 Instruction dual issue 15
2 Renaming src1 operand 12
3 Read operand from forwarding path (RAW) 9
4 Reservation station reads operand from forwarding path (RAW) 7
5 Read operand from renaming reg. (RAW) 10
6 Read operand from GPR (RAW) 11

[mtv06-test-cases]

CITATIONS

17 sources
17 citations
[1] Counterexample generation converts the satisfiable result of a negated property check into a concrete witnessing artifact (UCLID5: a sequence of model actions; ADL/SMV and directed micro-architectural test generation: an instruction sequence that becomes a test program). Formal Verification of Pipelined Y86-64 Microprocessors with UCLID5
[2] In UCLID5, when the SMT solver returns satisfiable, it provides concrete values for all data elements (including uninterpreted functions) and UCLID5 uses them to generate a counterexample: a sequence of actions that could occur in the model and violate a verification condition. Formal Verification of Pipelined Y86-64 Microprocessors with UCLID5
[3] UCLID5-generated counterexamples are diagnostic signals indicating a true design error, an inaccurate or overly abstract model, or an improperly expressed verification condition. Formal Verification of Pipelined Y86-64 Microprocessors with UCLID5
[4] UCLID5 invokes an SMT solver on the negation of the properties to verify; the solver can return unsatisfiable (desired verification condition holds), satisfiable (typically implies a verification condition failed; values used for counterexample generation), or indeterminate (model is too complex or requires reasoning beyond the solver). Formal Verification of Pipelined Y86-64 Microprocessors with UCLID5
[5] Counterexample generation supports feedback on abstraction choices: as a general rule, the most abstract model that still captures the relevant correctness properties should be used, and counterexamples can reveal whether the abstraction is too coarse or inaccurate. Formal Verification of Pipelined Y86-64 Microprocessors with UCLID5
[6] In the directed micro-architectural test generation setting, the negated version of a desired property together with the processor model is applied to the model checker, which automatically produces a counterexample containing a sequence of instructions (a test program) from an initial state to a failure state; a naive whole-model approach is unsuitable due to state explosion. Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[7] The e500 processor model is partitioned into multiple modules based on functional units (reservation stations, issue, decode, GIQ, rename buffer) because verifying the entire model as a single unit is infeasible due to state explosion during model checking. Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[8] Pipeline interactions are expressed as LTL properties using temporal operators G, F, X, U and Boolean connectives ∧, ∨, ¬, →; a common pattern is F(p1 ∧ p2 ∧ … ∧ pn), expressing that activities pi over n modules must become true at some time step, and the negation is used so that the counterexample represents an interaction fault. Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[9] Boolean decompositions useful for counterexample generation include G(p ∧ q) = G(p) ∧ G(q), F(p ∨ q) = F(p) ∨ F(q), X(p ∨ q) = X(p) ∨ X(q), and X(p ∧ q) = X(p) ∧ X(p); non-decomposable combinations include F(p ∧ q) = F(p) ∧ F(q) and G(p ∨ q) = G(p) ∨ G(q); combinations such as pUq, F(p → F(q)), or F(p → G(q)) are decomposable in principle but not beneficial compared to traditional model checking. Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[10] Introducing a clock (time step) variable clk and a specific time step ts enables additional decompositions useful for counterexample generation; the sides are not logically equivalent but produce functionally equivalent counterexamples, e.g., G((clk = ts) ∨ (p ∨ q)) ≈ G((clk = ts) ∨ p) ∨ G((clk = ts) ∨ q). Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[11] Partial counterexamples generated for partitioned modules are integrated using clock-based integration: when two sub-properties are applied at the same clock cycle (clk = ts) to two modules sharing a parent module, the two counterexamples are merged into the output property of the parent module and used to generate counterexamples at clk = ts − 1; merging continues until the primary input instruction sequence is obtained. Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[12] In the e500 pipeline, four reservation station (RS) modules share the Issue stage as a parent module; counterexamples from multiple RS modules at cycle k are merged into the output property of the Issue stage, and the negated version of that property is applied with the Issue module to produce a counterexample at cycle k − 1 covering Decode, GIQ, and Rename buffer. Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[13] The directed micro-architectural test generation approach produced concrete test programs for interaction faults and corner cases, with associated test code lengths: instruction dual issue (15), renaming src1 operand (12), read operand from forwarding path RAW (9), reservation station reads operand from forwarding path RAW (7), read operand from renaming reg. RAW (10), read operand from GPR RAW (11). Directed Micro-architectural Test Generation for an Industrial Processor: A Case Study
[14] In the ADL/SMV approach, the processor model is generated from the ADL specification and described in SMV; properties are written by hand as the negation of the desired behavior and applied with the SMV model checker to generate counterexamples (instruction sequences), which are combined with expected results from a cycle-accurate structural simulator (also generated from the ADL) to produce complete functional tests. Architecture Description Language driven Functional Test Program Generation for Microprocessors using SMV
[15] Applying the negated hazard property G(ID._stall = 0) to the SMV model of the DLX pipeline produces a counterexample in the form of an instruction sequence (NOP, ADD R3,R1,R2, ADD R4,R3,R2) that stalls the decode unit at cycle 4; SMV takes 1.3 seconds on a 359 MHz Sun UltraSPARC-II with 2048M RAM. Architecture Description Language driven Functional Test Program Generation for Microprocessors using SMV
[16] Adding the property init: assert G((cycle = 8) -> X((DIV.Ain != 2) | (DIV.Bin != 3))) generates a counterexample (MOVI R4,#2; MOVI R5,#3; DIV R0,R4,R5) that initializes the DIV unit internal registers Ain and Bin at clock cycle 9, exercising a previously uncovered path; SMV takes 75.4 seconds on a 359 MHz Sun UltraSPARC-II with 2048M RAM. Architecture Description Language driven Functional Test Program Generation for Microprocessors using SMV
[17] The ADL/SMV report frames functional verification as a significant cost driver in microprocessor design and pursues model checking as a way to reduce validation cost; future work includes applying tests to RTL, automatic coverage estimation, automatic generation of properties from the ADL specification, and investigating SAT-based bounded model checking for generating functional test programs. Architecture Description Language driven Functional Test Program Generation for Microprocessors using SMV

VERSION HISTORY

v3 · 8/1/2026 · minimax/minimax-m3 (current)
v2 · 7/3/2026 · minimax/minimax-m3
v1 · 5/26/2026 · gpt-5.5