The App Map
Learn what a formal app is, which apps need a hand-written rule and which generate their own, and which app catches which bug.
- Lesson
- F5.1
- Time
- 10 min
- Runs on
- SymbiYosys
- Check
- 4 questions
A team bought a formal licence and was asked to "run formal on the SoC". They opened property verification on the whole top level, wrote nothing for a month, and reported that it did not converge. The connectivity and register checkers in the same licence needed a spreadsheet each and no property at all.
Measured with smtbmc yices at depth 20: FAIL at reported step 2. F5.3 finds the same bug from one typed table row, with no property written by hand.
One Narrow Question per App
| App: the narrow question | What you give it | What it generates or finds | Built by hand in |
|---|---|---|---|
| Automatic checks: can the code reach a state it implies is impossible? | the RTL only | a cover per state; index, x and carry asserts | F5.2 |
| Connectivity: is pin A wired to pin B? | a pin table | one equality per row, a cover per condition | F5.3 |
| Registers: does each field behave as the map says? | a register map | a fixed check set per access type | F5.4 |
| X: can an unknown reach an output? | the RTL only | unknowns as free values, asserts on outputs | F5.5 |
| CDC/RDC: is each crossing synchronised, and safe to synchronise? | the clock and reset domains | a crossing list, then protocol properties | F5.6 |
| Unreachability: can this coverage bin ever be hit? | the unhit bins | assert(!bin) under prove, or a trace | F5.7 |
| Information flow: can the secret reach this pin? | a secret and its sinks | two copies with equal public inputs | F5.8 |
| Post-silicon: how could the lab symptom happen? | a symptom and the lab notes | a cover under assumptions | F5.9 |
| Equivalence: do two designs behave the same? | two designs | a miter of the two | F6 |
Commercial formal suites sell most of these rows as separate apps under their own names. Underneath, every row is assert, assume and cover around a generator.
A formal app is the three verbs (F1.3) packaged around one narrow question. Because the question is fixed, the tool can write the properties from a table, from the RTL itself or from a second design. The design can then be far larger than a hand-written proof could handle.
Each row of the map is built by hand in this module on the open engine, so you see exactly what the app generates and where it stops.
Who Writes the Rule
Read the diagram as text
- Property verification (F1 to F4): the general case: you write every rule
- Generated from a table or the RTL: automatic checks, connectivity, registers, X, unreachability
- Generated from a second design: equivalence (F6)
- A person names the rule: CDC protocol properties, information flow, post-silicon covers
- Where a team with no formal engineer starts: connectivity and registers: a spreadsheet in, a verdict out
- Generated from a table or the RTL → Property verification (F1 to F4)
- Generated from a second design → Property verification (F1 to F4)
- A person names the rule → Property verification (F1 to F4)
- Generated from a table or the RTL → Where a team with no formal engineer starts
The generated group needs no formal expertise to run, but someone still has to read every verdict against the spec.
The generated group is where a team without a formal specialist starts: connectivity and registers turn an existing spreadsheet into a verdict. The hand-written group needs someone who can state the rule: which crossing protocol, which secret and sink, which symptom.
The trace above shows the difference. Two hand-written rows found the swapped pad: FAIL at reported step 2. In F5.3 a generator writes those rows from the pin table, along with the other seventeen.
Which App Catches Which Bug
| Bug | App that catches it | Lesson |
|---|---|---|
| an FSM state that can never be entered | automatic checks (or unreachability) | F5.2 |
| a W1C bit that behaves as read-write | registers | F5.4 |
| two pad selects swapped | connectivity | F5.3 |
| an unreset flop that reaches an enable | X-propagation | F5.5 |
| a binary pointer across clock domains | CDC, protocol property | F5.6 |
| a coverage bin no test ever hits | unreachability | F5.7 |
| a key bit on a debug port | information flow | F5.8 |
| a deadlock seen once in the lab | post-silicon | F5.9 |
| a FIFO that overflows under one sequence | no app: write the property | F3.4 |
| a request that is never granted | no app: liveness | F3.7 |
The last two rows belong to no app on purpose. Most design-specific bugs still need a person to write the rule.
An app proves its generated properties and nothing else. A narrow, fixed property set means a wrong spec stays wrong, and a bug outside the question is invisible. Use the apps for what they are good at, then write the properties only you can write.
Asked in Interviews
| Question | Answer |
|---|---|
| What are formal apps, and which are "automatic"? | Packaged narrow questions. The automatic ones take a table, the RTL or a second design and generate their properties: automatic checks, connectivity, registers, unreachability, equivalence. |
| Which app would you run first on a new SoC? | Connectivity and registers: no property to write, a spreadsheet already exists, and they pay back at once. |
| Do the automatic apps prove the design correct? | No. They prove a fixed, narrow set of generated properties. |
Try It
always @(posedge clk) begin
if ($initstate) begin assume(rst); end else begin assume(!rst); end
end
reg pipe_in_q=0, rst_q=1; // last cycle's pipe_in and rst
always @(posedge clk) begin pipe_in_q <= pipe_in; rst_q <= rst; end
// generated from the connection table
always @(posedge clk) if (!rst) begin
if (pad_sel == 2'd0) assert(pad41 == gpio_o[0]);
if (pad_sel == 2'd1) assert(pad41 == uart_tx);
if (pad_sel == 2'd2) assert(pad41 == spi_mosi);
end[options]
mode bmc
depth 20
[engines]
smtbmc yices
[script]
read_verilog -formal -sv design.sv
prep -top conn_top
[files]
design.svRun it
Run as it is: FAIL at reported step 2. Which select value does the trace use?
Fix the mux
Swap the two pad41 selects back in the RTL: BMC PASS to depth 20.
Count the rows
How many rows like these would a 200-pin pad ring need? That is the case for a generator.
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 formal app is assert, assume and cover around a generator, aimed at one narrow question.
- Generated apps take a table, the RTL or a second design; hand-written ones need someone to name the rule.
- Start a new SoC with connectivity and registers: no property to write.
- An app proves its generated properties only; design-specific bugs still need your own.