SAT and SMT in One Lesson
Learn the one question a SAT solver answers, why UNSAT is the good news, and what an SMT solver adds for datapaths.
- Lesson
- F2.2
- Time
- 15 min
- Runs on
- SymbiYosys
- Check
- 4 questions
A formal run on a 32-bit datapath was killed after a weekend, and the engineer decided the design was too big for formal. The task had used a bit-level engine. The same property on a word-level SMT solver came back before lunch.
One Question
- Decide
No clause forces anything yet, so the solver guesses a = 1.
- Propagate
(¬a ∨ c) now needs c = 1, and (¬c ∨ d) then needs d = 1. No guessing: unit propagation.
- Conflict and learn
(¬a ∨ ¬d) is false. Tracing the implications back shows the guess a = 1 caused it, so the solver adds the clause (¬a). That conflict can never be explored again.
- Backjump and finish
(¬a) forces a = 0. Then (a ∨ b) gives b = 1, which gives c = 1 and d = 1. Every clause holds: SAT, and this assignment is the model.
Read the diagram as text
- Decide a = 1: a guess, level 1
- Propagate c = 1, d = 1: from (¬a ∨ c), then (¬c ∨ d)
- Conflict: (¬a ∨ ¬d) is false
- Learn (¬a): a = 1 always leads here
- Backjump: a = 0: forced by the learned clause
- Model: a=0 b=1 c=1 d=1: every clause true: SAT
- Decide a = 1 → Propagate c = 1, d = 1
- Propagate c = 1, d = 1 → Conflict
- Conflict → Learn (¬a)
- Learn (¬a) → Backjump: a = 0
- Backjump: a = 0 → Model: a=0 b=1 c=1 d=1: b, c, d follow
Add a sixth clause (¬b ∨ ¬d) and the same steps end in a conflict with no guess left to undo: UNSAT. Drawn by hand, not measured.
A SAT solver answers one question: is there a 0/1 assignment that makes every clause true? SAT means yes, and here it is: the model. UNSAT means no such assignment exists.
Modern solvers (CDCL) decide, propagate, hit a conflict, learn a clause that forbids it, and jump back. DPLL (1962) had the decide-propagate-backtrack loop; GRASP (1999) added clause learning; Chaff (2001) made propagation cheap.
Every BMC Query Is This Question
smtbmc log for a failing seq3 run (F2.3). One query per step; the last one was satisfiable.Checking assumptions in step 0..
Checking assertions in step 0..
Checking assumptions in step 1..
Checking assertions in step 1..
Checking assumptions in step 2..
Checking assertions in step 2..
Checking assumptions in step 3..
Checking assertions in step 3..
Checking assumptions in step 4..
Checking assertions in step 4..
BMC failed!
Assert failed in seq3: design.sv:12.35-12.47 (_witness_.check_design_sv_12_assert_16)
Status: failedEach query asks: is there an input sequence of length k that reaches a bad state? A satisfiable answer is a counterexample, and its model is the trace. An unsatisfiable answer says no failure exists at that step. In formal, UNSAT is the good news.
Words and Gates
mul_sa at depth W + 4, which covers one full multiplication. Whole-task time with SBY on this machine.- smtbmc yices
- smtbmc boolector
- smtbmc z3
- abc bmc3
Read the plot as a table
| Operand width | smtbmc yices | smtbmc boolector | smtbmc z3 | abc bmc3 |
|---|---|---|---|---|
| 4 | 189 ms | 189 ms | 205 ms | 176 ms |
| 4.5 | 256.8 ms | 246.3 ms | 338 ms | 280.3 ms |
| 5 | 324.5 ms | 303.5 ms | 471 ms | 384.5 ms |
| 5.5 | 392.3 ms | 360.8 ms | 604 ms | 488.7 ms |
| 6 | 460 ms | 418 ms | 737 ms | 593 ms |
| 6.5 | 1.293 s | 703.5 ms | 1.794 s | 1.445 s |
| 7 | 2.127 s | 989 ms | 2.852 s | 2.297 s |
| 7.5 | 6.319 s | 2.285 s | 9.634 s | 10.75 s |
| 8 | 10.51 s | 3.582 s | 16.42 s | 19.2 s |
Measured once per point. Single runs on one machine are not a ranking.
| W | smtbmc yices | smtbmc boolector | smtbmc bitwuzla | smtbmc z3 | abc bmc3 |
|---|---|---|---|---|---|
| 4 | 0.2 s | 0.2 s | 0.2 s | 0.2 s | 0.2 s |
| 6 | 0.5 s | 0.4 s | 0.4 s | 0.7 s | 0.6 s |
| 7 | 2.1 s | 1.0 s | 0.9 s | 2.9 s | 2.3 s |
| 8 | 10.5 s | 3.6 s | 9.8 s | 16.4 s | 19.2 s |
Measured, PASS everywhere. At W = 8 the fastest was smtbmc boolector (3.6 s) and the slowest abc bmc3 (19.2 s).
An SMT solver is SAT plus theories. The bit-vector theory knows that a + b is an addition, rewrites x + 0 to x, and turns words into gates only when it must. smtbmc writes SMT-LIB2 with bit-vectors and arrays; abc works on the AIGER, where everything is already gates.
Multiplication is hard for every engine: here each extra bit multiplies the time by two to eight. The four SMT solvers differ in rewriting and in their SAT core, by design. On control logic a bit-level engine often wins; F4.7 measures that habit across engines.
Same Verdict, Different Time
| mul_sa, W = 6, depth 10 | Engine | Measured result | Time |
|---|---|---|---|
| correct | smtbmc yices | PASS | 0.8 s |
| correct | smtbmc boolector | PASS | 0.7 s |
| bug: wrong multiplier bit | smtbmc yices | FAIL at step 9 | 0.5 s |
| bug: wrong multiplier bit | smtbmc boolector | FAIL at step 9 | 0.5 s |
| bug: wrong multiplier bit | abc bmc3 | FAIL at step 9 | 0.3 s |
The first four through the lab runner, the last with SBY directly. The failing step does not depend on the engine.
The rule in concurrent SVA
assert property (@(posedge clk) disable iff (rst)
done |-> p == a_q * b_q);
When done, the product equals the operands captured at start.
What the engine runs
reg [5:0] a_q=0, b_q=0;
always @(posedge clk) if (!rst && start && !busy) begin a_q <= a; b_q <= b; end
always @(posedge clk) if (!rst && done) assert(p == a_q * b_q);
Two modelling flops hold the operands.
Asked in Interviews
| Question | Answer |
|---|---|
| What is SAT, and why is UNSAT the good news? | The question whether some assignment makes a formula true. An UNSAT BMC query means no counterexample of that length exists. |
| SAT or SMT: what does bit-vector reasoning buy? | Word-level structure, rewriting and smaller formulas on datapaths. Bit-level engines often win on control logic and have IC3. |
| Name a SAT algorithm. | DPLL; CDCL with clause learning (GRASP, Chaff). |
Try It
The lab runs the 6-bit multiplier in bmc mode at depth 10 with smtbmc yices. Measured: PASS in 0.8 s.
Change the solver
Switch the engine to Boolector, Bitwuzla and Z3 in turn. The verdict stays; read the times.
Plant the bug
Change
mplier[0]tomplier[1]and run two solvers. Both report the same step.Count the queries
Open the SBY log: one "Checking assertions in step" line per step, each one a solver call.
design.sv
props.sv
Use assert property (@(posedge clk) ...);. Leave blank for immediate assertions in the design.
Inputs are free unless constrained. Run to find a counterexample or check a proof.
Model: one positive-edge clock, binary data. Sampled history requires declaration-initialized variables; primary-input history is unsupported.
SBY summary and log
Check Yourself
Remember
- A SAT solver finds an assignment that makes every clause true, or proves none exists.
- In BMC, SAT is a counterexample and UNSAT is the good news.
- CDCL solvers learn a clause from each conflict.
- SMT keeps words and arithmetic; bit-level engines see only gates. The verdict is the same, the time is not.