def test_btor_get_non_bool_value(self): with Solver(name="btor") as s: x = Symbol("x", BVType(16)) s.add_assertion(Equals(x, BV(1, 16))) self.assertTrue(s.solve()) self.assertEqual(s.get_value(Equals(x, BV(1, 16))), TRUE()) self.assertEqual(s.get_value(BVAdd(x, BV(1, 16))), BV(2, 16))
def overlaps(i,j): """ Returns True if two instructions i,j overlap in their encoding. TODO: Add operand constraints into the solver formula. """ if(i.pseudo or j.pseudo): return False ILEN=32 instr = Symbol("instr" , BVType(width=ILEN)) imask = Symbol("imask" , BVType(width=ILEN)) imatch = Symbol("imatch" , BVType(width=ILEN)) jmask = Symbol("jmask" , BVType(width=ILEN)) jmatch = Symbol("jmatch" , BVType(width=ILEN)) domains = And([ EQ(imask , BV(i.mask() ,width=ILEN)), EQ(imatch, BV(i.match(),width=ILEN)), EQ(jmask , BV(j.mask() ,width=ILEN)), EQ(jmatch, BV(j.match(),width=ILEN)) ]) problem = And([ EQ(instr & imask, imatch), EQ(instr & jmask, jmatch) ]) formula = And(domains, problem) return is_sat(formula)
def Orr(in_, out): # INVAR: (in = 0) -> (out = 0) & (in != 0) -> (out = 1) vars_ = [in_, out] comment = "Orr (in, out) = (%s, %s)" % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) if (in_.symbol_type() == BOOL) and (out.symbol_type() == BOOL): invar = EqualsOrIff(in_, out) else: if out.symbol_type() == BOOL: out0 = Not(out) out1 = out else: out0 = EqualsOrIff(out, BV(0, 1)) out1 = EqualsOrIff(out, BV(1, 1)) true_res = Implies( EqualsOrIff(in_, BV(0, in_.symbol_type().width)), out0) false_res = Implies( Not(EqualsOrIff(in_, BV(0, in_.symbol_type().width))), out1) invar = And(true_res, false_res) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def Mux(in0, in1, sel, out): # if Modules.functional # INVAR: out' = Ite(sel = 0, in0, in1) # else # INVAR: ((sel = 0) -> (out = in0)) & ((sel = 1) -> (out = in1)) vars_ = [in0, in1, sel, out] comment = "Mux (in0, in1, sel, out) = (%s, %s, %s, %s)" % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) if sel.symbol_type() == BOOL: sel0 = Not(sel) sel1 = sel else: sel0 = EqualsOrIff(sel, BV(0, 1)) sel1 = EqualsOrIff(sel, BV(1, 1)) if Modules.functional: invar = And(EqualsOrIff(out, Ite(sel0, in0, in1))) else: invar = And(Implies(sel0, EqualsOrIff(in0, out)), Implies(sel1, EqualsOrIff(in1, out))) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def Neq(in0, in1, out): # INVAR: (((in0 != in1) -> (out = #b1)) & ((in0 == in1) -> (out = #b0))) vars_ = [in0, in1, out] comment = "Eq (in0, in1, out) = (%s, %s, %s)" % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) # TODO: Create functional encoding if Modules.functional: if out.symbol_type() == BOOL: invar = EqualsOrIff(out, Not(EqualsOrIff(in0, in1))) else: invar = EqualsOrIff(out, BVNot(BVComp(in0, in1))) else: eq = EqualsOrIff(in0, in1) if out.symbol_type() == BOOL: out0 = Not(out) out1 = out else: out0 = EqualsOrIff(out, BV(0, 1)) out1 = EqualsOrIff(out, BV(1, 1)) invar = And(Implies(Not(eq), out1), Implies(eq, out0)) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def resize_bvs(self, formula): """ Resize the bitvector variables wrt to the maximum domain size """ subs_map = {} for (fvar, max_value) in self.fvars_maxval.iteritems(): old_enc_var = self.fvars2encvars.lookup_a(fvar) bv_size = self.get_size(max_value+1) new_enc_var = FreshSymbol(BVType(bv_size)) self.fvars2encvars.add(fvar, new_enc_var) val2val = self.fvars2values[fvar] for i in range(max_value + 1): old_value = BV(i, SymbolicGrounding.MAX_BV) new_value = BV(i, bv_size) fval = val2val.lookup_b(old_value) val2val.add(fval, new_value) old_f = Equals(old_enc_var, old_value) new_f = Equals(new_enc_var, new_value) subs_map[old_f] = new_f formula = substitute(formula, subs_map) return formula
def make_bv(val, typ): if isinstance(val, int): val = BV(val, typ.width) else: val = simplify(val) assert val.get_type() == typ return val
def Clock(clk): # INIT: clk = 0 # TRANS: clk' = !clk comment = "Clock (clk) = (" + clk.symbol_name() + ")" if clk.symbol_type() == BOOL: clk0 = Not(clk) clk1 = clk else: clk0 = EqualsOrIff(clk, BV(0, 1)) clk1 = EqualsOrIff(clk, BV(1, 1)) init = clk0 invar = TRUE() if False: trans = EqualsOrIff(clk0, TS.to_next(clk1)) else: # Implementation that leverages on the boolean propagation trans1 = Implies(clk0, TS.to_next(clk1)) trans2 = Implies(clk1, TS.to_next(clk0)) trans = And(trans1, trans2) if Modules.abstract_clock: invar = clk0 init = TRUE() trans = TRUE() ts = TS(comment) ts.vars, ts.state_vars = set([clk]), set([clk]) ts.set_behavior(init, trans, invar) return ts
def Negedge(self, x): if get_type(x).is_bool_type(): if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return Not(x) return And(x, Not(TS.to_next(x))) if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return EqualsOrIff(x, BV(0,1)) return And(BV2B(x), EqualsOrIff(TS.to_next(x), BV(0,1)))
def Posedge(self, x): if get_type(x).is_bool_type(): if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return x return And(Not(x), TS.to_next(x)) if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return EqualsOrIff(x, BV(1,1)) return And(EqualsOrIff(x, BV(0,1)), BV2B(TS.to_next(x)))
def MemAcc(self, left, right): ltype = left.get_type() assert ltype.is_array_type() if right.is_constant() and right.get_type().is_int_type(): right = BV(right.constant_value(), ltype.index_type.width) return Select(left, right)
def __recombine_constants(self, first, second, zeros, ones): inds_z0 = [] inds_o0 = [] inds_z1 = [] inds_o1 = [] if zeros is not None: zeros.sort() inds_z0 = [i[0] for i in zeros if i[0] is not None] inds_z1 = [i[1] for i in zeros if i[1] is not None] if ones is not None: ones.sort() inds_o0 = [i[0] for i in ones if i[0] is not None] inds_o1 = [i[1] for i in ones if i[1] is not None] c_inds0 = list(set(inds_z0 + inds_o0)) c_inds1 = list(set(inds_z1 + inds_o1)) if (len(c_inds0) > 1) and (len(c_inds1) == 0): min_1 = min(c_inds0) max_1 = max(c_inds0) if len(c_inds0) == ((max_1 - min_1) + 1): inds_z = [(i, 0) for i in inds_z0] inds_o = [(i, 1) for i in inds_o0] inds = inds_z + inds_o inds.sort() inds.reverse() value = [str(v[1]) for v in inds] bvval = bin_to_dec("".join(value)) bvlen = len(c_inds0) new_second = BV(bvval, bvlen) return (first, new_second, ((min_1, max_1), (0, bvlen - 1))) return (first, second, None) # Bit Constant e.g. var[0] = 0, var[1] = 0, ... if (second.is_symbol()): return (first, second, None) if (len(inds_1) > 1) and (len(inds_2) == 0): min_1 = min(inds_1) max_1 = max(inds_1) if len(inds_1) == ((max_1 - min_1) + 1): val = second.constant_value() bvlen = len(inds_1) bvval = val if val == 0 else (2**bvlen) - 1 new_second = BV(bvval, bvlen) return (first, new_second, ((min_1, max_1), (0, bvlen - 1))) return (first, second, None)
def scan_const5_f(scan_var_5): if 16 not in og_design_free_vars: og_design_free_vars[16] = Symbol("x_max_og_design", BVType(16)) x16 = og_design_free_vars[16] x76 = BV(1, 16) x77 = BVSubExtend(x16, x76) x78 = BVEqualsExtend(scan_var_5, x77) x79 = BV(0, 16) x80 = BV(1, 16) x81 = BVAddExtend(scan_var_5, x80) x82 = IteExtend(x78, x79, x81) return x82
def scan_const10_f(scan_var_10): if 16 not in op_design_free_vars: op_design_free_vars[16] = Symbol("x_max_op_design", BVType(16)) x16 = op_design_free_vars[16] x40 = BV(1, 16) x41 = BVSubExtend(x16, x40) x42 = BVEqualsExtend(scan_var_10, x41) x43 = BV(0, 16) x44 = BV(1, 16) x45 = BVAddExtend(scan_var_10, x44) x46 = IteExtend(x42, x43, x45) return x46
def Andr(in_, out): # INVAR: (in = 2**width - 1) -> (out = 1) & (in != 2**width - 1) -> (out = 0) vars_ = [in_, out] comment = "Andr (in, out) = (%s, %s)"%(tuple([x.symbol_name() for x in vars_])) Logger.log(comment, 3) width = in_.symbol_type().width eq_all_ones = EqualsOrIff(in_, BV(2**width - 1,width)) true_res = Implies(eq_all_ones, EqualsOrIff(out, BV(1,1))) false_res = Implies(Not(eq_all_ones), EqualsOrIff(out, BV(0,1))) invar = And(true_res, false_res) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def test_complex_types(self): with self.assertRaises(PysmtTypeError): # Not(Store(Array<Real,BV8>(8d_0), 1.0, 8d_5) = # Store(Array<Int,BV8>(8d_0), 1, 8d_5)) Not( Equals(Store(Array(REAL, BV(0, 8)), Real(1), BV(5, 8)), Store(Array(INT, BV(0, 8)), Int(1), BV(5, 8)))) nested_a = Symbol("a_arb_aii", ArrayType(ArrayType(REAL, BV8), ARRAY_INT_INT)) with self.assertRaises(PysmtTypeError): # This is wrong, because the first elemnt of Array must be a Type Equals(nested_a, Array(Array(REAL, BV(0, 8)), Array(INT, Int(7))))
def scan_const7_f(scan_var_7): x53 = scan_const5 if 16 not in og_design_free_vars: og_design_free_vars[16] = Symbol("x_max_og_design", BVType(16)) x16 = og_design_free_vars[16] x54 = BV(1, 16) x55 = BVSubExtend(x16, x54) x56 = BVEqualsExtend(x53, x55) x57 = BV(0, 16) if 18 not in og_design_free_vars: og_design_free_vars[18] = Symbol("x_stride_og_design", BVType(16)) x18 = og_design_free_vars[18] x58 = BVAddExtend(scan_var_7, x18) x59 = IteExtend(x56, x57, x58) return x59
def mem_access(addr, locations, width_idx, idx=0): first_loc = min(2**width_idx, len(locations)) - 1 ite_chain = locations[first_loc] for i in reversed(range(0, first_loc)): location = BV(i, width_idx) ite_chain = Ite(EqualsOrIff(addr, location), locations[i], ite_chain) return ite_chain
def main(): # example = counter(4) # bmcind = BMCInduction(example[0]) # pdr = PDR(example[0]) # for prop in example[1]: # bmcind.check_property(prop) # pdr.check_property(prop) # print("") from pysmt.typing import BVType x = Symbol("x", BVType(4)) xprime = next_var(x) y = Symbol("y", BVType(4)) yprime = next_var(y) var = [x, y] nvar = [xprime, yprime] init = x.Equals(0) & y.Equals(1) print(init) trans = xprime.Equals(x.Equals(15).Ite(BV( 15, 4), x + 1)) & yprime.Equals(x + y.BVULT(y).Ite(y, x + y)) print(trans) prop = y.BVUGT(0) print(prop) system = TransitionSystem(var, init, trans) bmcind = BMCInduction(system) pdr = PDR(system) pdr.check_property(prop) bmcind.check_property(prop) print("")
def test_normalization(self): from pysmt.environment import Environment env2 = Environment() mgr2 = env2.formula_manager ty = ArrayType(BOOL, REAL) x = FreshSymbol(ty) fty = FunctionType(BOOL, (ty, )) f = FreshSymbol(fty) g = Function(f, (x, )) self.assertIsNotNone(g) self.assertNotIn(g, mgr2) g2 = mgr2.normalize(g) self.assertIn(g2, mgr2) # Since the types are from two different environments, they # should be different. x2 = g2.arg(0) ty2 = x2.symbol_type() self.assertFalse(ty2 is ty, ty) fname = g2.function_name() fty2 = fname.symbol_type() self.assertFalse(fty2 is fty, fty) # Test ArrayValue h = Array(BVType(4), BV(0, 4)) h2 = mgr2.normalize(h) self.assertEqual(h.array_value_index_type(), h2.array_value_index_type()) self.assertFalse(h.array_value_index_type() is \ h2.array_value_index_type())
def get_domain_formula(self): """ Returns the formula that encodes the domains of each variable in the encoding. Note: the size of the BV is not enough. """ domain = TRUE_PYSMT() for (fvar, max_value) in self.fvars_maxval.iteritems(): enc_var = self.fvars2encvars.lookup_a(fvar) bv_size = self.get_size(max_value+1) # WARNING: must use the unsigned comparison of bitvectors lb = BVUGE(enc_var, BV(self.init_val, bv_size)) ub = BVULE(enc_var, BV(max_value, bv_size)) domain = And(domain, And(ub,lb)) return domain
def get_sts(self, params): if len(params) != len(self.interface.split()): Logger.error("Invalid parameters for clock behavior \"%s\"" % (self.name)) clk = params[0] valuepar = params[1] if (not type(clk) == FNode) or (not clk.is_symbol()): Logger.error("Clock symbol \"%s\" not found" % (str(clk))) if (type(valuepar) == FNode) and (valuepar.is_bv_constant()): value = valuepar.constant_value() else: try: value = int(valuepar) except: Logger.error( "Clock value should be an integer number instead of \"%s\"" % valuepar) init = [] invar = [] trans = [] vars = set([]) if clk.symbol_type().is_bv_type(): pos_clk = EqualsOrIff(clk, BV(1, 1)) neg_clk = EqualsOrIff(clk, BV(0, 1)) else: pos_clk = clk neg_clk = Not(clk) if value == 1: invar.append(pos_clk) else: invar.append(neg_clk) ts = TS("Clock Behavior") ts.vars, ts.init, ts.invar, ts.trans = vars, And(init), And( invar), And(trans) Logger.log( "Adding clock behavior \"%s(%s)\"" % (self.name, ", ".join([str(p) for p in params])), 1) return ts
def get_behavior(self, input_var, output_var): vartype = get_type(output_var) if vartype.is_bool_type(): return FALSE() assert vartype.is_bv_type() return BV(0, vartype.width)
def test_btor_bitwidth_bug_in_shift(self): # (384, 384, 9) # (x69 >> 1_384) s = Solver(name="btor") x69 = Symbol("x69", BVType(384)) # BVLShr f = BVLShr(x69, BV(1, 384)) c = s.converter.convert(f) self.assertIsNotNone(c) # BVLShl f = BVLShl(x69, BV(1, 384)) c = s.converter.convert(f) self.assertIsNotNone(c) # BVAShr f = BVAShr(x69, BV(1, 384)) c = s.converter.convert(f) self.assertIsNotNone(c)
def Const(out, value): if value is None: return None if out.symbol_type() == BOOL: const = TRUE() if value == 1 else FALSE() else: const = BV(value, out.symbol_type().width) return (out, const)
def get_behavior(self, input_var, output_var): vartype = get_type(output_var) if vartype.is_bool_type(): return TRUE() assert vartype.is_bv_type() width = vartype.width return BV((2**width)-1, width)
def all_binary(self): for l in self.all_bv_numbers(): for r in self.all_bv_numbers(): for op in self.bin_operators: try: self.check(op(l, r)) except AssertionError: if op in [BVUDiv, BVSDiv] and r == BV(0, r.bv_width()): print("Warning: Division value mismatch.") print(l, op, r)
def Dec2BV(self, left, right): if right.is_int_constant(): size = right.constant_value() else: size = get_type(right).width if not left.is_int_constant(): Logger.error("Left argument of dec2bv should be a number") return BV(left.constant_value(), size)
def test_parse_bvx_var(self): """bvX is a valid identifier.""" smtlib_input = """ (declare-fun bv1 () (_ BitVec 8)) (assert (bvult (_ bv0 8) (bvmul (bvadd bv1 (_ bv1 8)) (_ bv5 8)))) (check-sat)""" parser = SmtLibParser() buffer_ = cStringIO(smtlib_input) script = parser.get_script(buffer_) # Check Parsed result iscript = iter(script) cmd = next(iscript) self.assertEqual(cmd.name, DECLARE_FUN) bv1 = cmd.args[0] self.assertEqual(bv1.symbol_type().width, 8) cmd = next(iscript) parsed_f = cmd.args[0] target_f = BVULT(BV(0, 8), BVMul(BVAdd(bv1, BV(1, 8)), BV(5, 8))) self.assertEqual(parsed_f, target_f)
def generate_constraint_for_input_partition(input_partition): formula = None for var_name in input_partition: sym_array = Symbol(var_name, ArrayType(BV32, BV8)) sym_var = BVConcat( Select(sym_array, BV(3, 32)), BVConcat( Select(sym_array, BV(2, 32)), BVConcat(Select(sym_array, BV(1, 32)), Select(sym_array, BV(0, 32))))) constant_info = input_partition[var_name] upper_bound = int(constant_info['upper-bound']) lower_bound = int(constant_info['lower-bound']) sub_formula = And(BVSGE(SBV(upper_bound, 32), sym_var), BVSLE(SBV(lower_bound, 32), sym_var)) if formula is None: formula = sub_formula else: formula = And(formula, sub_formula) return formula