- Know Verilog and One Other Programming Language
- Verilog required b/c it's the input language that our tools transform into a file format SMT solvers can use
- Watch Lectures 0-7 of Hehner's A Practical Theory of Programming Course
- Sit on it for a few days to a week (you'll prob be confused)
- Up to and including Quantifiers should be fine
- You may wish to do some the textbook problems
- Familiarity w/ Lisp syntax
- Read slides #25 to the end of this slide deck
- You may want to take a quick look at the z3 Guide.
yosys
,yosys-smtbmc
, andz3
installed
- You will begin to recognize the terminology used in Wikipedia articles
on logic ("predicate", "statements assumed to be true", "theory")
- Term "theory" is thrown around a lot
- APToP looks kinda like a logic one would use for SMT.
- What are BitVectors/Uninterpreted Functions/Arrays?
What next? This describes what I did to learn more, including missteps.
- SAT is "given a set of boolean expressions and variables, can I make
all the expressions true by using specific values for all the variables?"
- For example,
(x AND y) OR z
is a boolean expression consisting ofAND
andOR
operators.
- For example,
- SMT is SAT on steroids. We have extra entities besides boolean variables/expressions we can manipulate, and associated "rules" for manipulation called theories. The expressions that need to be true can also use these new entities.
When I discuss theories, I mean the mathematical definition
of theory. Personally, for our purposes I think it's just easier to informally see a theory
described, at which point you can extrapolate for how to define a theory
for another object. So let me just give an example of a theory (Boolean Logic).
Note that this is reiterating parts of Hehner's first lecture using English instead
of symbols. The purpose of watching Lectures 0-7 is to get a feel for how to define theories,
manipulate expressions, and recognize statements about entities that remain logically
true
no matter how you manipulate these entities.
- Boolean variables can take on one of two values-
true
orfalse
. - Boolean logic has its own way to manipulate- change/create- boolean types (operators):
AND
,OR
,NOT
,NAND
,NOR
,XOR
,XNOR
are prob familiar.- There are extra manipulations you can define:
x EQ y
:true
ifx
equalsy
, otherwisefalse
x IMPLIES y
: Ifx
istrue
,y
must betrue
for the whole expression to betrue
. Ifx
is false,x IMPLIES y
istrue
;y
's value is irrelevant.x IMPLIED_BY y
: Ify
istrue
,x
must betrue
for the whole expression to betrue
. Ify
is false,x IMPLIED_BY y
istrue
;x
's value is irrelevant.IF x THEN y ELSE z
: Use the value ofy
ifx
istrue
, otherwise use the value ofz
(x
,y
, andz
are booleans or an expression that returns a boolean)
- We can chain operators together to create expressions.
Other entities, such as Lists, have their own sets of operators and
"rules" for manipulation that make a theory. Not all operators are compatible
w/ each other (for example, we can't OR
a bool and a list), but we can
define operators/"rules" that return other entities. For instance, the answer
to the question "Are two lists are equal to each other?" is either yes
or no
,
or true
or false
- a bool! List equality could thus be defined as taking
two Lists and returning a bool.
- We create some statements that define new rules for how our variables can be manipulated based on the existing theories.
- We create a number of statements that we assume are
true
, and want to know whether these statements are in facttrue
for some set of input variables in #1, when we allow manipulations of variables based on the theories and statements in #1. We call these assertions. - The SMT solver runs an algorithm to figure out whether, by setting all
input variables to values, we can make all statements in #2
true
.
- If we find a set of inputs which make all of our assertions true,
the SMT solver returns
SAT
. Otherwise the solver returnsUNSAT
.
- Some functions are left for the SMT solver to "fill in".
All we do is specify the input and output. For instance, I can create
L1 MysteryOp L2
function/operator, which takes two lists and returns a bool. It's up to the SMT solver to determine whatMysteryOp
actually does based on List Theory, but it better take in two Lists and output a bool!- These are known as Uninterpreted Functions. Like Lists, integers, and booleans, they also have a theory associated with them.
- Some (many?) variables in expressions will also have some of their values left unspecified.
- Both Uninterpreted Functions and variables whose values are unspecified become input variables to the entire system of statements. Outputs of and intermediate variables within the system of statements become subject to assertions- the statements we wish to know whether or not we can make true for at least one set of input variables.
SMTv2 is a file format that defines statements that SMT solvers understand and can be used to create scripts for systems that you want to prove meet/do not meet certain conditions.
A contrived example using the scripting capabilities of the SMTv2 interchange format is shown on the z3 guide, which I reproduce here:
(declare-const a Int)
(declare-fun f (Int Bool) Int)
(assert (> a 10))
(assert (< (f a true) 100))
(check-sat)
(get-model)
Let's walk through each line:
(declare-const a Int)
: This declares a constanta
of typeInt
, for integer. Like bools and Lists, integers have their own separate theory!a
can now be used later for any purpose we feel like; we know it's an integer, but we don't know which integer (could be0
,1
,999
).(declare-fun f (Int Bool) Int)
: This creates an Uninterpreted Function.f
is a function take takes in an integer and bool, and returns an int. I have no idea what expressions make up this function right now, but I know that the expressions that make up the function will leave an integer and bool "free" for input and return an integer as output.
(declare-const a Int)
is shorthand for(declare-fun a () Int)
. This makes sense to me, as if you're not inputting anything, but getting an output, what's the point of doing anything except just returning the output immediately?
(assert (> a 10))
: Our first assertion. We need our constanta
to be greater than 10 for this statement to be true.(assert (< (f a true) 100))
: Our second assertion. We need our functionf
, given the inputa
(samea
as defined in #1) and atrue
boolean input value, to return an integer less than100
for this statement to betrue
.(check-sat)
: Find an example, if one exists, ofa
andf
that makes the assertions defined in #3 and #4 true.(get-model)
: IfSAT
, z3 will tell me "how did z3 definea
andf
to make the assertions true"?
If we run the code snippet by trying z3
online, we find that the entire
system of statements is SAT
. The SMT solver for me chose the following
inputs/model:
sat
(model
(define-fun a () Int 11)
(define-fun f ((x!1 Int) (x!2 Bool)) Int
(ite (and (= x!1 11) (= x!2 true)) 0 0))
)
define-fun
actually specifies how a function should behave by defining
expressions while leaving the inputs x!1
and x!2
as free variables
(i.e. "any value valid for an integer and bool"). ite
is
"if then else", analogous to "if-else statements" in most programming
languages.
Instead of using Bunches, Sets, Strings, and Lists, as described
in APToP, we use BitVectors, Arrays, and Uninterpreted Functions for z3
Uninterpreted Function, BitVector and Array Theory is described in the z3 Guide,
so read that and we can go on to the next section!
Blatantly stolen from Clifford Wolf's examples:
module hello(input clk, input rst, output [3:0] cnt);
reg [3:0] cnt = 0;
always @(posedge clk) begin
if (rst)
cnt <= 0;
else
cnt <= cnt + 1;
end
`ifdef FORMAL
assume property (cnt != 10);
assert property (cnt != 15);
`endif
endmodule
It's a 4-bit counter! yosys
is capable of converting Verilog code into
functions and logic that an SMT solver can understand. The verilog code
defines the rules for how our inputs can be manipulated to produce
outputs.
The SMTv2 output from yosys
can be input into a SMT solver just fine.
As-is, the SMTv2 output produced by yosys
isn't enough to actually
do the types of proofs we want. All the boiler-plate is there however,
including transitioning from state n
to state n + 1
.
For Bounded Model Check (BMC) SAT
is actually the fail condition, and
provides a counterexample showing a set of inputs over time that cause
the conditions to fail
-
Forgetting
clock2dff
pass in a multi-clock design -
my_hello1
-
Sometimes you will see expressions like:
(or (|hello#3| state) (not true))
, where theor
orand
operator is unnecessary. This is a side-effect of how yosys generates SMT2 files in the backend. In other contexts,(not true)
would be an expression with variables.
[z3_guide] : http://rise4fun.com/z3/tutorialcontent/guide