Symbiotic EDA Suite
www.symbioticeda.com
Symbiotic EDA Suite www.symbioticeda.com Symbiotic EDA We build - - PowerPoint PPT Presentation
Symbiotic EDA Suite www.symbioticeda.com Symbiotic EDA We build Open Source EDA Tools And offer commercial versions of those tools with additional functionality and support Symbiotic EDA Suite We specialize in Formal
www.symbioticeda.com
– And offer commercial versions of those tools with additional
functionality and support → Symbiotic EDA Suite
– Formal Verification Tools, with focus on Assertion Based Verification
(ABV) using SAT- and SMT-solvers
– Custom FPGA Implementation Tools (Synthesis, Place-and-route,
Timing analysis, Bit-stream generation)
– Verilog Std. 1995, 2000, 2005 – SystemVerilog Std. 2005, 2009, 2012 – VHDL Std. 1987, 1993, 2000, 2008 – SystemVerilog Assertions (SVA)
– Bounded Model Check (BMC) – Complete proof with k-induction – Automatic complete proof with PDR/IC3 – Formal cover / reachability analysis – Verification of liveness properties – Formal Equivalence Check – Reactive Synthesis
– SMT-based BMC and k-Induction Engine
– AIGER-based model checkers
– Direct SAT solving
– BTOR2 model checkers
– Proof that the finished design is functionally correct – Exhaustive proofs at the end of the design process – Adds extra NRE cost at end of project – Only attractive for most critical designs
– Exhaustive proofs only where it’s easy
– Reduce development and verification time
– Requires access to formal tools for design engineers and verification engineers – Attractive for all types of designs
Formal first
Cost of (fixing) a bug Time Development Verification / Testing Production Traditional use-case for formal Number of new bugs found Most formal tools are priced and advertised for the traditional use case.
module hello ( input wire clock, input wire reset,
); initial dout = 0; always @(posedge clock) begin if (reset) dout <= 0; else dout <= dout + 1; end always @* begin assume (dout != 10); assert (dout != 15); end endmodule [options] mode prove depth 10 [engines] smtbmc z3 [script] read -sv hello.sv prep -top hello [files] hello.sv
hello.sv hello.sby
SBY 17:08:46 [hello] Removing direcory 'hello'. SBY 17:08:46 [hello] Copy 'hello.sv' to 'hello/src/hello.sv'. SBY 17:08:46 [hello] engine_0: smtbmc z3 SBY 17:08:46 [hello] base: starting process "cd hello/src; yosys -ql ../model/design.log ../model/design.ys" SBY 17:08:46 [hello] base: VERIFIC-WARNING [VERI-1209] hello.sv:12: expression size 5 truncated to fit in target size 4 SBY 17:08:46 [hello] base: finished (returncode=0) SBY 17:08:46 [hello] smt2: starting process "cd hello/model; yosys -ql design_smt2.log design_smt2.ys" SBY 17:08:46 [hello] smt2: finished (returncode=0) SBY 17:08:46 [hello] engine_0.basecase: starting process "cd hello; yosys-smtbmc -s z3 --presat --noprogress -t 10
model/design_smt2.smt2" SBY 17:08:46 [hello] engine_0.induction: starting process "cd hello; yosys-smtbmc -s z3 --presat -i --noprogress -t 10 --append 0 --dump-vcd engine_0/trace_induct.vcd --dump-vlogtb engine_0/trace_induct_tb.v --dump-smtc engine_0/trace_induct.smtc model/design_smt2.smt2" SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Solver: z3 SBY 17:08:46 [hello] engine_0.induction: ## 0:00:00 Solver: z3 SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assumptions in step 0.. SBY 17:08:46 [hello] engine_0.induction: ## 0:00:00 Trying induction in step 10.. ..... SBY 17:08:46 [hello] engine_0.induction: ## 0:00:00 Trying induction in step 5.. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assumptions in step 1.. SBY 17:08:46 [hello] engine_0.induction: ## 0:00:00 Temporal induction successful. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assertions in step 1.. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assumptions in step 2.. SBY 17:08:46 [hello] engine_0.induction: ## 0:00:00 Status: PASSED SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assertions in step 2.. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assumptions in step 3.. ..... SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assertions in step 7.. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assumptions in step 8.. SBY 17:08:46 [hello] engine_0.induction: finished (returncode=0) SBY 17:08:46 [hello] engine_0: Status returned by engine for induction: PASS SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assertions in step 8.. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assumptions in step 9.. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Checking assertions in step 9.. SBY 17:08:46 [hello] engine_0.basecase: ## 0:00:00 Status: PASSED SBY 17:08:46 [hello] engine_0.basecase: finished (returncode=0) SBY 17:08:46 [hello] engine_0: Status returned by engine for basecase: PASS SBY 17:08:46 [hello] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0) SBY 17:08:46 [hello] summary: Elapsed process time [H:MM:SS (secs)]: 0:00:00 (0) SBY 17:08:46 [hello] summary: engine_0 (smtbmc z3) returned PASS for induction SBY 17:08:46 [hello] summary: engine_0 (smtbmc z3) returned PASS for basecase SBY 17:08:46 [hello] summary: successful proof by k-induction. SBY 17:08:46 [hello] DONE (PASS, rc=0)
sby -f hello.sby
module counter ( input clock, input reset, input up, input down,
); always @(posedge clock) begin if (reset) cnt <= 0; else if (up) cnt <= cnt + 8'd 1; else if (down) cnt <= cnt - 8'd 1; end endmodule [options] mode prove depth 10 [engines] smtbmc z3 [script] read -sv counter.sv read -sv counter_sva.sv prep -top counter [files] counter.sv counter_sva.sv
counter.sv counter.sby
module counter_sva ( input clock, input reset, input up, input down, input [7:0] cnt ); default clocking @(posedge clock); endclocking default disable iff (reset); // we have an outside guarantee that down and up can't be both active assume property (down |-> !up); // some simple properties assert property (up |=> cnt == $past(cnt) + 8'd 1); assert property (up [*2] |=> cnt == $past(cnt, 2) + 8'd 2); assert property (up ##1 up |=> cnt == $past(cnt, 2) + 8'd 2); // some more properties assert property (up ##1 down |=> cnt == $past(cnt, 2)); assert property (down |=> cnt == $past(cnt) - 8'd 1); property down_n(n); down [*n] |=> cnt == $past(cnt, n) - n; endproperty assert property (down_n(8'd 3)); assert property (down_n(8'd 5)); endmodule bind counter counter_sva sva_prop_inst (.*);
counter_sva.sv
module memory ( input clk, we, input [31:0] addr, input [7:0] wdata,
); reg [7:0] bank_0 [0:2**30-1]; reg [7:0] bank_1 [0:2**30-1]; reg [7:0] bank_2 [0:2**30-1]; reg [7:0] bank_3 [0:2**30-1]; always @(posedge clk) begin case (addr[1:0]) 2'b 00: begin rdata <= bank_0[addr >> 2]; if (we) bank_0[addr >> 2] <= wdata; end 2'b 01: begin rdata <= bank_1[addr >> 2]; if (we) bank_1[addr >> 2] <= wdata; end 2'b 10: begin rdata <= bank_2[addr >> 1]; // <- BUG if (we) bank_2[addr >> 2] <= wdata; end 2'b 11: begin rdata <= bank_3[addr >> 2]; if (we) bank_3[addr >> 2] <= wdata; end endcase end endmodule
module memcheck ( input clk, we, input [31:0] addr, input [7:0] wdata,
); memory uut ( .clk (clk ), .we (we ), .addr (addr ), .wdata(wdata), .rdata(rdata) ); checker monitor; rand const reg [31:0] monitor_addr; rand const reg [7:0] monitor_data; assert property ( @(posedge clk) (we && addr == monitor_addr && wdata == monitor_data) ##1 (!we || addr != monitor_addr) [*] ##1 (addr == monitor_addr) |=> rdata == monitor_data ); endchecker endmodule
memcheck.sby
sby -f memcheck.sby SBY 18:22:58 [memcheck] Removing direcory 'memcheck'. SBY 18:22:58 [memcheck] Copy 'memcheck.sv' to 'memcheck/src/memcheck.sv'. SBY 18:22:58 [memcheck] Copy 'memcheck_mem.sv' to 'memcheck/src/memcheck_mem.sv'. SBY 18:22:58 [memcheck] engine_0: smtbmc z3 SBY 18:22:58 [memcheck] base: starting process "cd memcheck/src; yosys -ql … SBY 18:22:58 [memcheck] base: finished (returncode=0) SBY 18:22:58 [memcheck] smt2: starting process "cd memcheck/model; yosys -ql … SBY 18:22:58 [memcheck] smt2: finished (returncode=0) SBY 18:22:58 [memcheck] engine_0: starting process "cd memcheck; yosys-smtbmc … SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Solver: z3 SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assumptions in step 0.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assertions in step 0.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assumptions in step 1.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assertions in step 1.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assumptions in step 2.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assertions in step 2.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assumptions in step 3.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Checking assertions in step 3.. SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 BMC failed! SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Assert failed in memcheck: memcheck.sv:25 SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Writing trace to VCD file: engine_0/trace.vcd SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Writing trace to Verilog testbench: engine_0/trace_tb.v SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Writing trace to constraints file: engine_0/trace.smtc SBY 18:22:58 [memcheck] engine_0: ## 0:00:00 Status: FAILED (!) SBY 18:22:58 [memcheck] engine_0: finished (returncode=1) SBY 18:22:58 [memcheck] engine_0: Status returned by engine: FAIL SBY 18:22:58 [memcheck] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0) SBY 18:22:58 [memcheck] summary: Elapsed process time [H:MM:SS (secs)]: 0:00:00 (0) SBY 18:22:58 [memcheck] summary: engine_0 (smtbmc z3) returned FAIL SBY 18:22:58 [memcheck] summary: counterexample trace: memcheck/engine_0/trace.vcd SBY 18:22:58 [memcheck] DONE (FAIL, rc=0)
module multiclk(input clk, output [3:0] counter_a, counter_b); reg [3:0] counter_a = 0; reg [3:0] counter_b = 0; always @(posedge clk) counter_a <= counter_a + 1; always @(posedge clk) counter_b[0] <= !counter_b[0]; always @(negedge counter_b[0]) counter_b[1] <= !counter_b[1]; always @(negedge counter_b[1]) counter_b[2] <= !counter_b[2]; always @(negedge counter_b[2]) counter_b[3] <= !counter_b[3]; always @* assert (counter_a == counter_b); endmodule
multiclk.sby
module setreset(input clk, input set, rst, d, output q1, q2); reg q1 = 0; always @(posedge clk, posedge set, posedge rst) if (rst) q1 <= 0; else if (set) q1 <= 1; else q1 <= d; reg q2_s = 0, q2_r = 0, q2_l; wire q2 = q2_l ? q2_s : q2_r; always @(posedge clk, posedge set) if (set) q2_s <= 1; else q2_s <= d; always @(posedge clk, posedge rst) if (rst) q2_r <= 0; else q2_r <= d; always @* begin if (rst) q2_l <= 0; else if (set) q2_l <= 1; always @* assert (q1 == q2); endmodule
setreset.sby
Verilog Design Verilog Asserts Yosys SMT-LIB2 Code Constraints File Yosys-SMTBMC PASS / FAIL VCD File Verilog Testbench Constraints File
Trace / counterexample formats
SMT-LIB2 Solver
Verilog Design Verilog Asserts Yosys AIGER Model Checker (e.g. pdr, avy) AIGER witness SMT-LIB code Yosys-SMTBMC Counter Example SMT-LIB2 Solver
unoptimized word-level representation, good for creating human readable counter examples
Yosys-SMTBMC is only used here as a post- processor, turning the AIGER witness into a useful human readable counter example (e.g. VCD). PASS/FAIL
RISC-V Processor Cores against the RISC-V ISA spec.
VexRiscv, PicoRV32) using SymbiYosys.
verifiable using riscv-formal.
isa-sim (aka Spike), the official C++ reference simulator.
MIT Model” and upcoming official RISC-V formal spec written in Haskell.
– All new features go into Symbiotic EDA Suite – Instantly available to all existing customers – No “optional features” with extra license cost
– Standard bus interfaces (AXI, Wishbone, Avalon, …) – Library of example projects to use as starting point for verification tasks
– QMC-Fuzzer: A tool to produce a universal quality metrics for test
methodologies, utilizing formal method and fuzzing techniques.
Dedicated cloud instances with Symbiotic EDA Suite pre-installed, rent by the hour
Run on any machine, pay license fees by the hour (100 hours per month included in base package), premium user support, needs Internet access
Unlimited runtime on up to 20 nodes (nodes can be changed at any time), plus 200 hours floating licenses per month, premium user support
Premium and developer support for the open source stack. Includes support for Yosys C++ API, Yosys Python API, and Yosys-SMTIO Python API.
Unlimited number of nodes and premium and developer support.
– 20 node locked licenses – 200 hours floating (use on any node) – Premium Support
– Self-service for managing node locked licenses
(for example during switch-over periods when making changes to infrastructure)
– Monitoring and management of floating licenses
www.symbioticeda.com
module fib ( input clk, pause, start, input [3:0] n,
); reg [3:0] count; reg [9:0] q; initial begin done = 0; busy = 0; end always @(posedge clk) begin done <= 0; if (!pause) begin if (!busy) begin if (start) busy <= 1; count <= 0; q <= 1; f <= 0; end else begin q <= f; f <= f + q; count <= count + 1; if (count == n) begin busy <= 0; done <= 1; end end end end `ifdef FORMAL always @(posedge clk) begin if (busy) begin assume (!start); assume ($stable(n)); end if (done) begin case ($past(n)) 0: assert (f == 1); 1: assert (f == 1); 2: assert (f == 2); 3: assert (f == 3); 4: assert (f == 5); 5: assert (f == 8); endcase cover (f == 13); cover (f == 144); cover ($past(n) == 15); end assume property (s_eventually !pause); if (start && !pause) assert property (s_eventually done); end `endif endmodule
[options] mode prove [engines] abc pdr [script] read_verilog -formal fib.sv prep -top fib [files] fib.sv fib_prove.sby [options] mode live [engines] aiger suprove [script] read_verilog -formal fib.sv prep -top fib [files] fib.sv fib_live.sby [options] mode cover append 10 [engines] smtbmc yices [script] read_verilog -formal fib.sv prep -top fib [files] fib.sv fib_cover.sby
Prove safety properties in fib.v using IC3 (pdr). Prove liveness properties in fib.v. This assumes that safety properties are already proven. Create a trace for each cover statement in the design (and check asserts for that trace). Add 10 additional time steps after the cover statement has been reached.
module parcase (input clk, A, B, C, D, E, BUG, output reg Y); always @(posedge clk) begin Y <= 0; if (A != B || BUG) begin (* parallel_case *) case (C) A: Y <= D; B: Y <= E; endcase end end endmodule
[script] read_verilog -formal parcase.v prep -top parcase assertpmux $ sby -f parcase.sby … … Assert failed in parcase: parcase.v:6 … SBY [parcase] DONE (FAIL)
reachable states (implicit) assertions (explicit) unreachable non- bad states. many of those usually implies a difficult proof.
In steps 1 .. k-1: UNSAT → next step SAT → FAIL In step k: UNSAT → PASS SAT → FAIL
1 2 3 k-1 1 1 1 2 2 3
Step 1: Step 2: Step 3: Step 4: Step k: BMC proves that no bad state is reachable within k cycles.
k-1 k k-2 k-3 k-1 k k-2 k-3 k-1 k k-2 k-1 k k
Step 1: Step 2: Step 3: Step 4: Step k+1: In steps 1 .. k: SAT → next step UNSAT → PASS In step k+1: SAT → UNKNOWN UNSAT → PASS k-induction proves that a sequence of k non-bad states is always followed by another non-bad state. The k used for induction must be ≤ the k used in BMC for a valid complete proof.
– Behaves like an additional primary input
– Behaves like an additional primary input that is latched in the
– For improved SV compatibility (only valid SV in checker …
– Find a trace so that assumptions are satisfied for all possible
sequences of values in cmd. Only one of those values needs to violate an assertion for a CEX.
– Find a trace so that assumptions are satisfied for all possible
constant values in cmd. Only one of those values needs to violate an assertion for a CEX.
module primegen; (* anyconst *) wire [31:0] prime; (* allconst *) wire [15:0] factor; always @* begin if (1 < factor && factor < prime) assume((prime % factor) != 0); assume(prime > 1000000000); cover(1); end endmodule Z3 after 35 seconds: 2359012091
module primes; parameter [8:0] gap = 500; (* anyconst *) wire [8:0] prime1; wire [9:0] prime2 = prime1 + gap; (* allconst *) wire [4:0] factor; always @* begin if (1 < factor && factor < prime1) assume((prime1 % factor) != 0); if (1 < factor && factor < prime2) assume((prime2 % factor) != 0); assume(1 < prime1); cover(1); end endmodule Z3 after 2 seconds: 173 and 673