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 Verification Tools, with focus on Assertion Based Verification (ABV) using SAT- and SMT-solvers ● Business model → SW Licenses and support – Custom FPGA Implementation Tools (Synthesis, Place-and-route, Timing analysis, Bit-stream generation) ● Business model → Custom tool development
Symbiotic EDA Suite Formal Verification Features ● Supported Engines / Solvers ● HDL Support (Yosys++) – SMT-based BMC and k-Induction Engine – Verilog Std. 1995, 2000, 2005 ● Z3 – SystemVerilog Std. 2005, 2009, 2012 ● Boolector – VHDL Std. 1987, 1993, 2000, 2008 ● Yices2 – SystemVerilog Assertions (SVA) ● CVC4 ● Immediate assert / assume / cover ● Every SMT2 solver supported (BV recommended) ● Concurrent assert / assume / cover ● Comprehensive SVA properties support – AIGER-based model checkers ● Safety, liveness, and cover properties ● ABC ● Super Prove ● Types of Formal Methods (SymbiYosys) ● Avy ● aigbmc – Bounded Model Check (BMC) – Complete proof with k-induction – Direct SAT solving – Automatic complete proof with PDR/IC3 ● Minisat – Formal cover / reachability analysis ● Penelope – Verification of liveness properties ● (simple API for adding others) – Formal Equivalence Check – BTOR2 model checkers – Reactive Synthesis ● Boolector
Formal ABV Methodologies Traditional use vs. “Formal first” ● Traditional use of formal ABV – 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 Symbiotic EDA Suite – Only attractive for most critical designs is suitable for both ● “Formal first” methodology methodologies! – Exhaustive proofs only where it’s easy ● BMC and/or deep restricted BMC otherwise ● No need to cover entire functional spec for added value ● Reuse properties for common interfaces (AXI, Whishbone, etc.) – Reduce development and verification time ● Formal methods find obscure corner-cases easily ● Formal ABV usually produces very short counter-example traces ● Ad-hoc cover statements can often replace simple ad-hoc test-benches during development – Requires access to formal tools for design engineers and verification engineers – Attractive for all types of designs
“Formal first” vs. traditional use of formal methods Cost of (fixing) a bug Traditional use-case for formal Most formal tools are priced and advertised for the traditional use case. Number of new bugs found Formal first Time Development Verification / Testing Production
Hello World hello.sv hello.sby module hello ( [options] input wire clock, mode prove input wire reset, depth 10 output reg [3:0] dout ); [engines] initial dout = 0; smtbmc z3 always @(posedge clock) begin [script] if (reset) read -sv hello.sv dout <= 0; prep -top hello else dout <= dout + 1; [files] end hello.sv always @* begin assume (dout != 10); assert (dout != 15); end endmodule
sby -f 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 --append 0 --dump-vcd engine_0/trace.vcd --dump-vlogtb engine_0/trace_tb.v --dump-smtc engine_0/trace.smtc 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)
Hello World (SVA) counter.sv counter.sby module counter ( [options] input clock, mode prove input reset, depth 10 input up, input down, [engines] output reg [7:0] cnt smtbmc z3 ); always @(posedge clock) begin [script] if (reset) read -sv counter.sv cnt <= 0; read -sv counter_sva.sv else if (up) prep -top counter cnt <= cnt + 8'd 1; else if (down) [files] cnt <= cnt - 8'd 1; counter.sv end counter_sva.sv endmodule
counter_sva.sv 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 (.*);
module memory ( memcheck.sv input clk, we, input [31:0] addr, input [7:0] wdata, output reg [7:0] rdata ); 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, memcheck.sv input [31:0] addr, input [7:0] wdata, output [7:0] rdata ); memcheck.sby memory uut ( [options] .clk (clk ), .we (we ), mode bmc .addr (addr ), expect fail .wdata(wdata), .rdata(rdata) depth 10 ); ... 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
Recommend
More recommend