Beispiel #1
0
    def Uop(bvop, bop, in_, out):
        # INVAR: (<op> in) = out)
        vars_ = [in_, out]
        comment = ""  #(bvop.__name__ + " (in, out) = (%s, %s)")%(tuple([x.symbol_name() for x in vars_]))
        Logger.log(comment, 3)

        in_B = get_type(in_).is_bool_type()
        outB = get_type(out).is_bool_type()

        bools = (1 if in_B else 0) + (1 if outB else 0)

        if bop == None:
            if in_B:
                in_ = B2BV(in_)
            if outB:
                out = B2BV(out)
            invar = EqualsOrIff(bvop(in_), out)
        else:
            if bools == 2:
                invar = EqualsOrIff(bop(in_), out)
            elif bools == 0:
                invar = EqualsOrIff(bvop(in_), out)
            else:
                if not in_B:
                    invar = EqualsOrIff(bop(BV2B(in_)), out)
                if not outB:
                    invar = EqualsOrIff(bop(in_), BV2B(out))

        ts = TS(comment)
        ts.vars, ts.invar = get_free_variables(invar), invar
        return ts
Beispiel #2
0
    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)
Beispiel #3
0
 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)))
Beispiel #4
0
 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)))
Beispiel #5
0
    def get_behavior(self, input_var, output_var):
        vartype = get_type(input_var)
        if vartype.is_bool_type():
            return Not(input_var)

        assert vartype.is_bv_type()

        return BVNot(input_var)
Beispiel #6
0
    def walk_debug(self, formula, **kwargs):
        from pysmt.shortcuts import Equals, Iff, get_type, is_valid
        from pysmt.typing import BOOL

        if formula in self.memoization:
            return self.memoization[formula]

        args = [self.walk(s, **kwargs) for s in formula.args()]

        f = self.functions[formula.node_type()]
        res = f(formula, args=args, **kwargs)
        ltype = get_type(formula)
        rtype = get_type(res)
        test = Equals(formula, res) if ltype != BOOL else Iff(formula, res)
        assert (ltype == rtype) and is_valid(test, solver_name="z3"), \
               ("Was: %s \n Obtained: %s\n" % (str(formula), str(res)))
        return res
Beispiel #7
0
    def walk_debug(self, formula, **kwargs):
        from pysmt.shortcuts import Equals, Iff, get_type, is_valid
        from pysmt.typing import BOOL

        if formula in self.memoization:
            return self.memoization[formula]

        args = [self.walk(s, **kwargs) for s in formula.get_sons()]

        f = self.functions[formula.node_type()]
        res = f(formula, args, **kwargs)
        ltype = get_type(formula)
        rtype = get_type(res)
        test = Equals(formula, res) if ltype != BOOL else Iff(formula, res)
        assert (ltype == rtype) and is_valid(test, solver_name="z3"), \
               ("Was: %s \n Obtained: %s\n" % (str(formula), str(res)))
        return res
Beispiel #8
0
    def Bop(bvop, bop, in0, in1, out):
        # INVAR: (in0 <op> in1) = out
        vars_ = [in0, in1, out]
        comment = ""  #(bvop.__name__ + " (in0, in1, out) = (%s, %s, %s)")%(tuple([x.symbol_name() for x in vars_]))
        Logger.log(comment, 3)

        in0B = get_type(in0).is_bool_type()
        in1B = get_type(in1).is_bool_type()
        outB = get_type(out).is_bool_type()

        bools = (1 if in0B else 0) + (1 if in1B else 0) + (1 if outB else 0)

        if bop == None:
            if in0B:
                in0 = Ite(in0, BV(1, 1), BV(0, 1))
            if in1B:
                in1 = Ite(in1, BV(1, 1), BV(0, 1))
            if outB:
                out = Ite(out, BV(1, 1), BV(0, 1))

            invar = EqualsOrIff(bvop(in0, in1), out)

        else:
            if bools == 3:
                invar = EqualsOrIff(bop(in0, in1), out)
            elif bools == 0:
                invar = EqualsOrIff(bvop(in0, in1), out)
            elif bools == 1:
                if in0B:
                    invar = EqualsOrIff(bvop(B2BV(in0), in1), out)
                if in1B:
                    invar = EqualsOrIff(bvop(in0, B2BV(in1)), out)
                if outB:
                    invar = EqualsOrIff(BV2B(bvop(in0, in1)), out)
            else:
                if not in0B:
                    invar = EqualsOrIff(bop(BV2B(in0), in1), out)
                if not in1B:
                    invar = EqualsOrIff(bop(in0, BV2B(in1)), out)
                if not outB:
                    invar = EqualsOrIff(B2BV(bop(in0, in1)), out)

        ts = TS(comment)
        ts.vars, ts.invar = get_free_variables(invar), invar
        return ts
Beispiel #9
0
    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)
Beispiel #10
0
    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)
Beispiel #11
0
    def compile_sts(self, name, params):
        ts = TS()
        parsize = params[0]
        size = None

        if type(parsize) == str:
            sparser = StringParser()
            parsize = sparser.parse_formula(parsize)

        if parsize.is_constant():
            size = parsize.constant_value()

        if get_type(parsize).is_bv_type():
            size = get_type(parsize).width

        if size is None:
            Logger.error("Undefined size for symbol \"%s\"" % (params[0]))

        value = Symbol("%s.value" % name, BVType(size))
        ts.add_var(value)
        ts.trans = EqualsOrIff(value, TS.get_prime(value))

        return ts
Beispiel #12
0
    def _generalize_pattern(self, term):
        head, args = term.function_name(), term.args()
        pat_idxs = [
            i for i, a in enumerate(args) if a.is_function_application()
        ]
        if len(pat_idxs) > 1:
            args1pat = list(args)
            phs = []
            for i in pat_idxs[1:]:
                ph = FreshSymbol(get_type(args[i]), template='?splt%d')
                phs.append(ph)
                args1pat[i] = ph

            headpat = SmtLibSExpression(Function(head, args1pat))
            #print("=|>", pat_idxs, headpat, phs)

            for ph in phs:
                cases = list(self._get_cases(ph))
                if len(cases) > 1:
                    yield [
                        headpat,
                        SExpression(['potential_split', ph] + cases)
                    ]
Beispiel #13
0
def get_const(val: FNode, match: FNode = None) -> FNode:
    '''
    Returns a bit-vector constant based on the input value.

    If match is an FNode instead of None, tries to match the bit-width
    '''
    if type(val) == FNode:
        return val
    elif type(val) == int:
        if match is not None:
            if type(match) != FNode:
                Logger.error(
                    "Expecting an FNode in get_const, but got {}".format(
                        type(match)))
            match_width = get_type(match).width
            if val.bit_length() > match_width:
                Logger.error(
                    "Trying to match bit-width of {} but can't express {} in {} bits"
                    .format(match, val, match_width))
            return BV(val, match_width)
        return BV(val, DEFAULTINT)
    else:
        raise RuntimeError("Unhandled case in get_const: {}".format(type(val)))
Beispiel #14
0
    def parse_string(self, strinput):

        hts = HTS()
        ts = TS()

        nodemap = {}
        node_covered = set([])

        # list of tuples of var and cond_assign_list
        # cond_assign_list is tuples of (condition, value)
        # where everything is a pysmt FNode
        # for btor, the condition is always True
        ftrans = []

        initlist = []
        invarlist = []

        invar_props = []
        ltl_props = []

        prop_count = 0

        # clean string input, remove special characters from names
        for sc, rep in special_char_replacements.items():
            strinput = strinput.replace(sc, rep)

        def getnode(nid):
            node_covered.add(nid)
            if int(nid) < 0:
                return Ite(BV2B(nodemap[str(-int(nid))]), BV(0,1), BV(1,1))
            return nodemap[nid]

        def binary_op(bvop, bop, left, right):
            if (get_type(left) == BOOL) and (get_type(right) == BOOL):
                return bop(left, right)
            return bvop(B2BV(left), B2BV(right))

        def unary_op(bvop, bop, left):
            if (get_type(left) == BOOL):
                return bop(left)
            return bvop(left)

        for line in strinput.split(NL):
            linetok = line.split()
            if len(linetok) == 0:
                continue
            if linetok[0] == COM:
                continue

            (nid, ntype, *nids) = linetok

            if ntype == SORT:
                (stype, *attr) = nids
                if stype == BITVEC:
                    nodemap[nid] = BVType(int(attr[0]))
                    node_covered.add(nid)
                if stype == ARRAY:
                    nodemap[nid] = ArrayType(getnode(attr[0]), getnode(attr[1]))
                    node_covered.add(nid)

            if ntype == WRITE:
                nodemap[nid] = Store(*[getnode(n) for n in nids[1:4]])

            if ntype == READ:
                nodemap[nid] = Select(getnode(nids[1]), getnode(nids[2]))

            if ntype == ZERO:
                nodemap[nid] = BV(0, getnode(nids[0]).width)

            if ntype == ONE:
                nodemap[nid] = BV(1, getnode(nids[0]).width)

            if ntype == ONES:
                width = getnode(nids[0]).width
                nodemap[nid] = BV((2**width)-1, width)

            if ntype == REDOR:
                width = get_type(getnode(nids[1])).width
                zeros = BV(0, width)
                nodemap[nid] = BVNot(BVComp(getnode(nids[1]), zeros))

            if ntype == REDXOR:
                width = get_type(getnode(nids[1])).width
                nodemap[nid] = BV(0, width)
                zeros = BV(0, width)
                for yx_i in range(width):
                  tmp = BV(1 << yx_i, width)
                  tmp_2 = BVAnd(tmp, B2BV(getnode(nids[1])))
                  tmp_3 = BVZExt(B2BV(BVComp(tmp_2, zeros)), int(width - 1))
                  nodemap[nid] = BVAdd(tmp_3, nodemap[nid])
                nodemap[nid] = BVComp(BVAnd(BV(1, width), nodemap[nid]), BV(1, width))

            if ntype == REDAND:
                width = get_type(getnode(nids[1])).width
                ones = BV((2**width)-1, width)
                nodemap[nid] = BVComp(getnode(nids[1]), ones)

            if ntype == CONSTD:
                width = getnode(nids[0]).width
                nodemap[nid] = BV(int(nids[1]), width)

            if ntype == CONST:
                width = getnode(nids[0]).width
                nodemap[nid] = BV(bin_to_dec(nids[1]), width)

            if ntype == STATE:
                if len(nids) > 1:
                    nodemap[nid] = Symbol(nids[1], getnode(nids[0]))
                else:
                    nodemap[nid] = Symbol((SN%nid), getnode(nids[0]))
                ts.add_state_var(nodemap[nid])

            if ntype == INPUT:
                if len(nids) > 1:
                    nodemap[nid] = Symbol(nids[1], getnode(nids[0]))
                else:
                    nodemap[nid] = Symbol((SN%nid), getnode(nids[0]))
                ts.add_input_var(nodemap[nid])

            if ntype == OUTPUT:
                # unfortunately we need to create an extra symbol just to have the output name
                # we could be smarter about this, but then this parser can't be greedy
                original_symbol = getnode(nids[0])
                output_symbol = Symbol(nids[1], original_symbol.get_type())
                nodemap[nid] = EqualsOrIff(output_symbol, original_symbol)
                invarlist.append(nodemap[nid])
                node_covered.add(nid)
                ts.add_output_var(output_symbol)

            if ntype == AND:
                nodemap[nid] = binary_op(BVAnd, And, getnode(nids[1]), getnode(nids[2]))

            if ntype == CONCAT:
                nodemap[nid] = BVConcat(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == XOR:
                nodemap[nid] = binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2]))

            if ntype == XNOR:
                nodemap[nid] = BVNot(binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2])))

            if ntype == NAND:
                bvop = lambda x,y: BVNot(BVAnd(x, y))
                bop = lambda x,y: Not(And(x, y))
                nodemap[nid] = binary_op(bvop, bop, getnode(nids[1]), getnode(nids[2]))

            if ntype == IMPLIES:
                nodemap[nid] = BVOr(BVNot(getnode(nids[1])), getnode(nids[2]))

            if ntype == NOT:
                nodemap[nid] = unary_op(BVNot, Not, getnode(nids[1]))

            if ntype == NEG:
                nodemap[nid] = unary_op(BVNeg, Not, getnode(nids[1]))

            if ntype == UEXT:
                nodemap[nid] = BVZExt(B2BV(getnode(nids[1])), int(nids[2]))

            if ntype == SEXT:
                nodemap[nid] = BVSExt(B2BV(getnode(nids[1])), int(nids[2]))

            if ntype == OR:
                nodemap[nid] = binary_op(BVOr, Or, getnode(nids[1]), getnode(nids[2]))

            if ntype == ADD:
                nodemap[nid] = BVAdd(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SUB:
                nodemap[nid] = BVSub(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == UGT:
                nodemap[nid] = BVUGT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == UGTE:
                nodemap[nid] = BVUGE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == ULT:
                nodemap[nid] = BVULT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == ULTE:
                nodemap[nid] = BVULE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SGT:
                nodemap[nid] = BVSGT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SGTE:
                nodemap[nid] = BVSGE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SLT:
                nodemap[nid] = BVSLT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SLTE:
                nodemap[nid] = BVSLE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == EQ:
                nodemap[nid] = BVComp(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == NEQ:
                nodemap[nid] = BVNot(BVComp(getnode(nids[1]), getnode(nids[2])))

            if ntype == MUL:
                nodemap[nid] = BVMul(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SLICE:
                nodemap[nid] = BVExtract(B2BV(getnode(nids[1])), int(nids[3]), int(nids[2]))

            if ntype == SLL:
                nodemap[nid] = BVLShl(getnode(nids[1]), getnode(nids[2]))

            if ntype == SRA:
                nodemap[nid] = BVAShr(getnode(nids[1]), getnode(nids[2]))

            if ntype == SRL:
                nodemap[nid] = BVLShr(getnode(nids[1]), getnode(nids[2]))

            if ntype == ITE:
                if (get_type(getnode(nids[2])) == BOOL) or (get_type(getnode(nids[3])) == BOOL):
                    nodemap[nid] = Ite(BV2B(getnode(nids[1])), B2BV(getnode(nids[2])), B2BV(getnode(nids[3])))
                else:
                    nodemap[nid] = Ite(BV2B(getnode(nids[1])), getnode(nids[2]), getnode(nids[3]))

            if ntype == NEXT:
                if (get_type(getnode(nids[1])) == BOOL) or (get_type(getnode(nids[2])) == BOOL):
                    lval = TS.get_prime(getnode(nids[1]))
                    rval = BV2B(getnode(nids[2]))
                else:
                    lval = TS.get_prime(getnode(nids[1]))
                    rval = getnode(nids[2])

                nodemap[nid] = EqualsOrIff(lval, rval)

                ftrans.append(
                     (lval,
                     [(TRUE(), rval)])
                )

            if ntype == INIT:
                if (get_type(getnode(nids[1])) == BOOL) or (get_type(getnode(nids[2])) == BOOL):
                    nodemap[nid] = EqualsOrIff(BV2B(getnode(nids[1])), BV2B(getnode(nids[2])))
                else:
                    nodemap[nid] = EqualsOrIff(getnode(nids[1]), getnode(nids[2]))
                initlist.append(getnode(nid))

            if ntype == CONSTRAINT:
                nodemap[nid] = BV2B(getnode(nids[0]))
                invarlist.append(getnode(nid))

            if ntype == BAD:
                nodemap[nid] = getnode(nids[0])

                if ASSERTINFO in line:
                    filename_lineno = os.path.basename(nids[3])
                    assert_name = 'embedded_assertion_%s'%filename_lineno
                    description = "Embedded assertion at line {1} in {0}".format(*filename_lineno.split(COLON_REP))
                else:
                    assert_name = 'embedded_assertion_%i'%prop_count
                    description = 'Embedded assertion number %i'%prop_count
                    prop_count += 1

                # Following problem format (name, description, strformula)
                invar_props.append((assert_name, description, Not(BV2B(getnode(nid)))))

            if nid not in nodemap:
                Logger.error("Unknown node type \"%s\""%ntype)

            # get wirename if it exists
            if ntype not in {STATE, INPUT, OUTPUT, BAD}:
                # check for wirename, if it's an integer, then it's a node ref
                try:
                    a = int(nids[-1])
                except:
                    try:
                        wire = Symbol(str(nids[-1]), getnode(nids[0]))
                        invarlist.append(EqualsOrIff(wire, B2BV(nodemap[nid])))
                        ts.add_var(wire)
                    except:
                        pass

        if Logger.level(1):
            name = lambda x: str(nodemap[x]) if nodemap[x].is_symbol() else x
            uncovered = [name(x) for x in nodemap if x not in node_covered]
            uncovered.sort()
            if len(uncovered) > 0:
                Logger.warning("Unlinked nodes \"%s\""%",".join(uncovered))

        if not self.symbolic_init:
            init = simplify(And(initlist))
        else:
            init = TRUE()

        invar = simplify(And(invarlist))

        # instead of trans, we're using the ftrans format -- see below
        ts.set_behavior(init, TRUE(), invar)

        # add ftrans
        for var, cond_assign_list in ftrans:
            ts.add_func_trans(var, cond_assign_list)

        hts.add_ts(ts)

        return (hts, invar_props, ltl_props)
Beispiel #15
0
 def Ones(self, x):
     if type(x) == int:
         return BV((2**x) - 1, x)
     size = get_type(x).width
     return BV((2**size) - 1, size)
Beispiel #16
0
 def Posedge(self, x):
     if get_type(x).is_bool_type():
         return And(Not(x), TS.to_next(x))
     return And(EqualsOrIff(x, BV(0, 1)), BV2B(TS.to_next(x)))
Beispiel #17
0
 def Zero(self, x):
     if type(x) == int:
         return BV(0, x)
     size = get_type(x).width
     return BV(0, size)
Beispiel #18
0
 def Negedge(self, x):
     if get_type(x).is_bool_type():
         return And(x, Not(TS.to_next(x)))
     return And(BV2B(x), EqualsOrIff(TS.to_next(x), BV(0, 1)))
Beispiel #19
0
    def parse_string(self, strinput):

        hts = HTS()
        ts = TS()

        nodemap = {}
        node_covered = set([])

        translist = []
        initlist = []
        invarlist = []

        invar_props = []
        ltl_props = []

        def getnode(nid):
            node_covered.add(nid)
            if int(nid) < 0:
                return Ite(BV2B(nodemap[str(-int(nid))]), BV(0,1), BV(1,1))
            return nodemap[nid]

        def binary_op(bvop, bop, left, right):
            if (get_type(left) == BOOL) and (get_type(right) == BOOL):
                return bop(left, right)
            return bvop(B2BV(left), B2BV(right))

        def unary_op(bvop, bop, left):
            if (get_type(left) == BOOL):
                return bop(left)
            return bvop(left)

        for line in strinput.split(NL):
            linetok = line.split()
            if len(linetok) == 0:
                continue
            if linetok[0] == COM:
                continue

            (nid, ntype, *nids) = linetok

            if ntype == SORT:
                (stype, *attr) = nids
                if stype == BITVEC:
                    nodemap[nid] = BVType(int(attr[0]))
                    node_covered.add(nid)
                if stype == ARRAY:
                    nodemap[nid] = ArrayType(getnode(attr[0]), getnode(attr[1]))
                    node_covered.add(nid)

            if ntype == WRITE:
                nodemap[nid] = Store(*[getnode(n) for n in nids[1:4]])

            if ntype == READ:
                nodemap[nid] = Select(getnode(nids[1]), getnode(nids[2]))

            if ntype == ZERO:
                nodemap[nid] = BV(0, getnode(nids[0]).width)

            if ntype == ONE:
                nodemap[nid] = BV(1, getnode(nids[0]).width)

            if ntype == ONES:
                width = getnode(nids[0]).width
                nodemap[nid] = BV((2**width)-1, width)

            if ntype == REDOR:
                width = get_type(getnode(nids[1])).width
                zeros = BV(0, width)
                nodemap[nid] = BVNot(BVComp(getnode(nids[1]), zeros))

            if ntype == REDAND:
                width = get_type(getnode(nids[1])).width
                ones = BV((2**width)-1, width)
                nodemap[nid] = BVComp(getnode(nids[1]), ones)

            if ntype == CONSTD:
                width = getnode(nids[0]).width
                nodemap[nid] = BV(int(nids[1]), width)

            if ntype == CONST:
                width = getnode(nids[0]).width
                nodemap[nid] = BV(bin_to_dec(nids[1]), width)

            if ntype == STATE:
                if len(nids) > 1:
                    nodemap[nid] = Symbol(nids[1], getnode(nids[0]))
                else:
                    nodemap[nid] = Symbol((SN%nid), getnode(nids[0]))
                ts.add_state_var(nodemap[nid])

            if ntype == INPUT:
                if len(nids) > 1:
                    nodemap[nid] = Symbol(nids[1], getnode(nids[0]))
                else:
                    nodemap[nid] = Symbol((SN%nid), getnode(nids[0]))
                ts.add_input_var(nodemap[nid])

            if ntype == OUTPUT:
                if len(nids) > 2:
                    symbol = Symbol(nids[2], getnode(nids[0]))
                else:
                    symbol = Symbol((SN%nid), getnode(nids[0]))

                nodemap[nid] = EqualsOrIff(symbol, B2BV(getnode(nids[1])))
                invarlist.append(nodemap[nid])
                node_covered.add(nid)
                ts.add_output_var(symbol)

            if ntype == AND:
                nodemap[nid] = binary_op(BVAnd, And, getnode(nids[1]), getnode(nids[2]))

            if ntype == CONCAT:
                nodemap[nid] = BVConcat(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == XOR:
                nodemap[nid] = binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2]))

            if ntype == NAND:
                bvop = lambda x,y: BVNot(BVAnd(x, y))
                bop = lambda x,y: Not(And(x, y))
                nodemap[nid] = binary_op(bvop, bop, getnode(nids[1]), getnode(nids[2]))

            if ntype == IMPLIES:
                nodemap[nid] = BVOr(BVNot(getnode(nids[1])), getnode(nids[2]))

            if ntype == NOT:
                nodemap[nid] = unary_op(BVNot, Not, getnode(nids[1]))

            if ntype == UEXT:
                nodemap[nid] = BVZExt(B2BV(getnode(nids[1])), int(nids[2]))

            if ntype == OR:
                nodemap[nid] = binary_op(BVOr, Or, getnode(nids[1]), getnode(nids[2]))

            if ntype == ADD:
                nodemap[nid] = BVAdd(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SUB:
                nodemap[nid] = BVSub(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == UGT:
                nodemap[nid] = BVUGT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == UGTE:
                nodemap[nid] = BVUGE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == ULT:
                nodemap[nid] = BVULT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == ULTE:
                nodemap[nid] = BVULE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == EQ:
                nodemap[nid] = BVComp(getnode(nids[1]), getnode(nids[2]))

            if ntype == NE:
                nodemap[nid] = BVNot(BVComp(getnode(nids[1]), getnode(nids[2])))

            if ntype == MUL:
                nodemap[nid] = BVMul(B2BV(getnode(nids[1])), B2BV(getnode(nids[2])))

            if ntype == SLICE:
                nodemap[nid] = BVExtract(B2BV(getnode(nids[1])), int(nids[3]), int(nids[2]))

            if ntype == SLL:
                nodemap[nid] = BVLShl(getnode(nids[1]), getnode(nids[2]))

            if ntype == SRA:
                nodemap[nid] = BVAShr(getnode(nids[1]), getnode(nids[2]))

            if ntype == SRL:
                nodemap[nid] = BVLShr(getnode(nids[1]), getnode(nids[2]))

            if ntype == ITE:
                if (get_type(getnode(nids[2])) == BOOL) or (get_type(getnode(nids[3])) == BOOL):
                    nodemap[nid] = Ite(BV2B(getnode(nids[1])), BV2B(getnode(nids[2])), BV2B(getnode(nids[3])))
                else:
                    nodemap[nid] = Ite(BV2B(getnode(nids[1])), getnode(nids[2]), getnode(nids[3]))

            if ntype == NEXT:
                if (get_type(getnode(nids[1])) == BOOL) or (get_type(getnode(nids[2])) == BOOL):
                    nodemap[nid] = EqualsOrIff(BV2B(TS.get_prime(getnode(nids[1]))), BV2B(getnode(nids[2])))
                else:
                    nodemap[nid] = EqualsOrIff(TS.get_prime(getnode(nids[1])), getnode(nids[2]))
                translist.append(getnode(nid))

            if ntype == INIT:
                if (get_type(getnode(nids[1])) == BOOL) or (get_type(getnode(nids[2])) == BOOL):
                    nodemap[nid] = EqualsOrIff(BV2B(getnode(nids[1])), BV2B(getnode(nids[2])))
                else:
                    nodemap[nid] = EqualsOrIff(getnode(nids[1]), getnode(nids[2]))
                initlist.append(getnode(nid))

            if ntype == CONSTRAINT:
                nodemap[nid] = BV2B(getnode(nids[0]))
                invarlist.append(getnode(nid))

            if ntype == BAD:
                nodemap[nid] = getnode(nids[0])
                invar_props.append(Not(BV2B(getnode(nid))))

            if nid not in nodemap:
                Logger.error("Unknown node type \"%s\""%ntype)

        if Logger.level(1):
            name = lambda x: str(nodemap[x]) if nodemap[x].is_symbol() else x
            uncovered = [name(x) for x in nodemap if x not in node_covered]
            uncovered.sort()
            if len(uncovered) > 0:
                Logger.warning("Unlinked nodes \"%s\""%",".join(uncovered))

        if not self.symbolic_init:
            init = simplify(And(initlist))
        else:
            init = TRUE()
        trans = simplify(And(translist))
        invar = simplify(And(invarlist))

        ts.set_behavior(init, trans, invar)
        hts.add_ts(ts)

        return (hts, invar_props, ltl_props)
Beispiel #20
0
def B2BV(f):
    if get_type(f).is_bv_type():
        return f
    return Ite(f, BV(1,1), BV(0,1))
Beispiel #21
0
def expr_to_pysmt(context: TranslationContext,
                  expr: Expr,
                  *,
                  is_expectation: bool = False,
                  allow_infinity: bool = False) -> FNode:
    """
    Translate a pGCL expression to a pySMT formula.

    Note that substitution expressions are not allowed here (they are not
    supported in pySMT).

    You can pass in the optional `is_expectation` parameter to have all integer
    values converted to real values.

    If `allow_infinity` is `True`, then infinity expressions will be mapped
    directly to the `infinity` variable of the given
    :py:class:`TranslationContext`. Take care to appropriately constrain the
    `infinity` variable! Note that arithmetic expressions may not contain
    infinity, to prevent expressions like `infinity - infinity`.

    .. doctest::

        >>> from probably.pgcl.parser import parse_expr
        >>> from pysmt.shortcuts import Symbol
        >>> from pysmt.typing import INT

        >>> expr = parse_expr("x + 4 * 13")
        >>> context = TranslationContext({"x": Symbol("x", INT)})
        >>> expr_to_pysmt(context, expr)
        (x + (4 * 13))
    """
    if isinstance(expr, BoolLitExpr):
        return TRUE() if expr.value else FALSE()
    elif isinstance(expr, NatLitExpr):
        if is_expectation:
            return ToReal(Int(expr.value))
        else:
            return Int(expr.value)
    elif isinstance(expr, FloatLitExpr):
        if expr.is_infinite():
            if not allow_infinity:
                raise Exception(
                    f"Infinity is not allowed in this expression: {expr}")
            return context.infinity
        else:
            return Real(Fraction(expr.value))
    elif isinstance(expr, VarExpr):
        var = context.variables[expr.var]
        if is_expectation and get_type(var) == INT:
            var = ToReal(var)
        return var
    elif isinstance(expr, UnopExpr):
        operand = expr_to_pysmt(context,
                                expr.expr,
                                is_expectation=False,
                                allow_infinity=allow_infinity)
        if expr.operator == Unop.NEG:
            return Not(operand)
        elif expr.operator == Unop.IVERSON:
            return Ite(operand, Real(1), Real(0))
    elif isinstance(expr, BinopExpr):
        # `is_expectation` is disabled if we enter a non-arithmetic expression
        # (we do not convert integers to reals within a boolean expression such
        # as `x == y`, for example).
        #
        # Similarly, `allow_infinity` is disabled if we enter an arithmetic
        # expression because calculations with infinity are hard to make sense of.
        is_arith_op = expr.operator in [Binop.PLUS, Binop.MINUS, Binop.TIMES]
        is_expectation = is_expectation  # TODO: and is_arith_op
        allow_infinity = allow_infinity  # TODO: and not is_arith_op?!??!
        lhs = expr_to_pysmt(context,
                            expr.lhs,
                            is_expectation=is_expectation,
                            allow_infinity=allow_infinity)
        rhs = expr_to_pysmt(context,
                            expr.rhs,
                            is_expectation=is_expectation,
                            allow_infinity=allow_infinity)
        if expr.operator == Binop.OR:
            return Or(lhs, rhs)
        elif expr.operator == Binop.AND:
            return And(lhs, rhs)
        elif expr.operator == Binop.LEQ:
            return LE(lhs, rhs)
        elif expr.operator == Binop.LE:
            return LT(lhs, rhs)
        elif expr.operator == Binop.EQ:
            return EqualsOrIff(lhs, rhs)
        elif expr.operator == Binop.PLUS:
            return Plus(lhs, rhs)
        elif expr.operator == Binop.MINUS:
            return Ite(LE(lhs, rhs),
                       (Int(0) if get_type(lhs) == INT else Real(0)),
                       Minus(lhs, rhs))
        elif expr.operator == Binop.TIMES:
            return Times(lhs, rhs)
    elif isinstance(expr, SubstExpr):
        raise Exception("Substitution expression is not allowed here.")

    raise Exception("unreachable")
Beispiel #22
0
def BV2B(f):
    if get_type(f).is_bool_type():
        return f
    return EqualsOrIff(f, BV(1,1))
Beispiel #23
0
    def parse_string(self, strinput):

        hts = HTS()
        ts = TS()

        nodemap = {}
        node_covered = set([])

        # list of tuples of var and cond_assign_list
        # cond_assign_list is tuples of (condition, value)
        # where everything is a pysmt FNode
        # for btor, the condition is always True
        ftrans = []

        initlist = []
        invarlist = []

        invar_props = []
        ltl_props = []

        prop_count = 0

        # clean string input, remove special characters from names
        for sc, rep in special_char_replacements.items():
            strinput = strinput.replace(sc, rep)

        def getnode(nid):
            node_covered.add(nid)
            if int(nid) < 0:
                return Ite(BV2B(nodemap[str(-int(nid))]), BV(0, 1), BV(1, 1))
            return nodemap[nid]

        def binary_op(bvop, bop, left, right):
            if (get_type(left) == BOOL) and (get_type(right) == BOOL):
                return bop(left, right)
            return bvop(B2BV(left), B2BV(right))

        def unary_op(bvop, bop, left):
            if (get_type(left) == BOOL):
                return bop(left)
            return bvop(left)

        for line in strinput.split(NL):
            linetok = line.split()
            if len(linetok) == 0:
                continue
            if linetok[0] == COM:
                continue

            (nid, ntype, *nids) = linetok

            if ntype == SORT:
                (stype, *attr) = nids
                if stype == BITVEC:
                    nodemap[nid] = BVType(int(attr[0]))
                    node_covered.add(nid)
                if stype == ARRAY:
                    nodemap[nid] = ArrayType(getnode(attr[0]),
                                             getnode(attr[1]))
                    node_covered.add(nid)

            if ntype == WRITE:
                nodemap[nid] = Store(*[getnode(n) for n in nids[1:4]])

            if ntype == READ:
                nodemap[nid] = Select(getnode(nids[1]), getnode(nids[2]))

            if ntype == ZERO:
                nodemap[nid] = BV(0, getnode(nids[0]).width)

            if ntype == ONE:
                nodemap[nid] = BV(1, getnode(nids[0]).width)

            if ntype == ONES:
                width = getnode(nids[0]).width
                nodemap[nid] = BV((2**width) - 1, width)

            if ntype == REDOR:
                width = get_type(getnode(nids[1])).width
                zeros = BV(0, width)
                nodemap[nid] = BVNot(BVComp(getnode(nids[1]), zeros))

            if ntype == REDAND:
                width = get_type(getnode(nids[1])).width
                ones = BV((2**width) - 1, width)
                nodemap[nid] = BVComp(getnode(nids[1]), ones)

            if ntype == CONSTD:
                width = getnode(nids[0]).width
                nodemap[nid] = BV(int(nids[1]), width)

            if ntype == CONST:
                width = getnode(nids[0]).width
                try:
                    nodemap[nid] = BV(bin_to_dec(nids[1]), width)
                except ValueError:
                    if not all([i == 'x' or i == 'z' for i in nids[1]]):
                        raise RuntimeError(
                            "If not a valid number, only support "
                            "all don't cares or high-impedance but got {}".
                            format(nids[1]))
                    # create a fresh variable for this non-deterministic constant
                    nodemap[nid] = Symbol('const_' + nids[1], BVType(width))
                    ts.add_state_var(nodemap[nid])
                    Logger.warning(
                        "Creating a fresh symbol for unsupported X/Z constant %s"
                        % nids[1])

            if ntype == STATE:
                if len(nids) > 1:
                    nodemap[nid] = Symbol(nids[1], getnode(nids[0]))
                else:
                    nodemap[nid] = Symbol((SN % nid), getnode(nids[0]))
                ts.add_state_var(nodemap[nid])

            if ntype == INPUT:
                if len(nids) > 1:
                    nodemap[nid] = Symbol(nids[1], getnode(nids[0]))
                else:
                    nodemap[nid] = Symbol((SN % nid), getnode(nids[0]))
                ts.add_input_var(nodemap[nid])

            if ntype == OUTPUT:
                # unfortunately we need to create an extra symbol just to have the output name
                # we could be smarter about this, but then this parser can't be greedy
                original_symbol = B2BV(getnode(nids[0]))
                output_symbol = Symbol(nids[1], original_symbol.get_type())
                nodemap[nid] = EqualsOrIff(output_symbol, original_symbol)
                invarlist.append(nodemap[nid])
                node_covered.add(nid)
                ts.add_output_var(output_symbol)

            if ntype == AND:
                nodemap[nid] = binary_op(BVAnd, And, getnode(nids[1]),
                                         getnode(nids[2]))

            if ntype == CONCAT:
                nodemap[nid] = BVConcat(B2BV(getnode(nids[1])),
                                        B2BV(getnode(nids[2])))

            if ntype == XOR:
                nodemap[nid] = binary_op(BVXor, Xor, getnode(nids[1]),
                                         getnode(nids[2]))

            if ntype == XNOR:
                nodemap[nid] = BVNot(
                    binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2])))

            if ntype == NAND:
                bvop = lambda x, y: BVNot(BVAnd(x, y))
                bop = lambda x, y: Not(And(x, y))
                nodemap[nid] = binary_op(bvop, bop, getnode(nids[1]),
                                         getnode(nids[2]))

            if ntype == IMPLIES:
                nodemap[nid] = BVOr(BVNot(getnode(nids[1])), getnode(nids[2]))

            if ntype == NOT:
                nodemap[nid] = unary_op(BVNot, Not, getnode(nids[1]))

            if ntype == NEG:
                nodemap[nid] = unary_op(BVNeg, Not, getnode(nids[1]))

            if ntype == UEXT:
                nodemap[nid] = BVZExt(B2BV(getnode(nids[1])), int(nids[2]))

            if ntype == SEXT:
                nodemap[nid] = BVSExt(B2BV(getnode(nids[1])), int(nids[2]))

            if ntype == OR:
                nodemap[nid] = binary_op(BVOr, Or, getnode(nids[1]),
                                         getnode(nids[2]))

            if ntype == ADD:
                nodemap[nid] = BVAdd(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == SUB:
                nodemap[nid] = BVSub(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == UGT:
                nodemap[nid] = BVUGT(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == UGTE:
                nodemap[nid] = BVUGE(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == ULT:
                nodemap[nid] = BVULT(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == ULTE:
                nodemap[nid] = BVULE(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == SGT:
                nodemap[nid] = BVSGT(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == SGTE:
                nodemap[nid] = BVSGE(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == SLT:
                nodemap[nid] = BVSLT(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == SLTE:
                nodemap[nid] = BVSLE(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == EQ:
                nodemap[nid] = BVComp(B2BV(getnode(nids[1])),
                                      B2BV(getnode(nids[2])))

            if ntype == NEQ:
                nodemap[nid] = BVNot(BVComp(getnode(nids[1]),
                                            getnode(nids[2])))

            if ntype == MUL:
                nodemap[nid] = BVMul(B2BV(getnode(nids[1])),
                                     B2BV(getnode(nids[2])))

            if ntype == SLICE:
                nodemap[nid] = BVExtract(B2BV(getnode(nids[1])), int(nids[3]),
                                         int(nids[2]))

            if ntype == SLL:
                nodemap[nid] = BVLShl(getnode(nids[1]), getnode(nids[2]))

            if ntype == SRA:
                nodemap[nid] = BVAShr(getnode(nids[1]), getnode(nids[2]))

            if ntype == SRL:
                nodemap[nid] = BVLShr(getnode(nids[1]), getnode(nids[2]))

            if ntype == ITE:
                if (get_type(getnode(nids[2])) == BOOL) or (get_type(
                        getnode(nids[3])) == BOOL):
                    nodemap[nid] = Ite(BV2B(getnode(nids[1])),
                                       B2BV(getnode(nids[2])),
                                       B2BV(getnode(nids[3])))
                else:
                    nodemap[nid] = Ite(BV2B(getnode(nids[1])),
                                       getnode(nids[2]), getnode(nids[3]))

            if ntype == NEXT:
                if (get_type(getnode(nids[1])) == BOOL) or (get_type(
                        getnode(nids[2])) == BOOL):
                    lval = TS.get_prime(getnode(nids[1]))
                    rval = B2BV(getnode(nids[2]))
                else:
                    lval = TS.get_prime(getnode(nids[1]))
                    rval = getnode(nids[2])

                nodemap[nid] = EqualsOrIff(lval, rval)

                ftrans.append((lval, [(TRUE(), rval)]))

            if ntype == INIT:
                if (get_type(getnode(nids[1])) == BOOL) or (get_type(
                        getnode(nids[2])) == BOOL):
                    nodemap[nid] = EqualsOrIff(BV2B(getnode(nids[1])),
                                               BV2B(getnode(nids[2])))
                elif get_type(getnode(nids[1])).is_array_type():
                    _type = get_type(getnode(nids[1]))
                    nodemap[nid] = EqualsOrIff(
                        getnode(nids[1]),
                        Array(_type.index_type, default=getnode(nids[2])))
                else:
                    nodemap[nid] = EqualsOrIff(getnode(nids[1]),
                                               getnode(nids[2]))
                initlist.append(getnode(nid))

            if ntype == CONSTRAINT:
                nodemap[nid] = BV2B(getnode(nids[0]))
                invarlist.append(getnode(nid))

            if ntype == BAD:
                nodemap[nid] = getnode(nids[0])

                if len(nids) > 1:
                    assert_name = nids[1]
                    description = "Embedded assertion: {}".format(assert_name)
                else:
                    assert_name = 'embedded_assertion_%i' % prop_count
                    description = 'Embedded assertion number %i' % prop_count
                    prop_count += 1

                # Following problem format (name, description, strformula)
                invar_props.append(
                    (assert_name, description, Not(BV2B(getnode(nid)))))

            if nid not in nodemap:
                Logger.error("Unknown node type \"%s\"" % ntype)

            # get wirename if it exists
            if ntype not in {STATE, INPUT, OUTPUT, BAD}:
                # disregard comments at the end of the line
                try:
                    symbol_idx = nids.index(';')
                    symbol_idx -= 1  # the symbol should be before the comment
                except:
                    # the symbol is just the end
                    symbol_idx = -1

                # check for wirename, if it's an integer, then it's a node ref
                try:
                    a = int(nids[symbol_idx])
                except:
                    try:
                        name = str(nids[symbol_idx])
                        # use the exact name, unless it has already been used
                        wire = Symbol(name, getnode(nids[0]))
                        if wire in ts.vars:
                            wire = FreshSymbol(getnode(nids[0]),
                                               template=name + "%d")
                        invarlist.append(EqualsOrIff(wire, B2BV(nodemap[nid])))
                        ts.add_var(wire)
                    except:
                        pass

        if Logger.level(1):
            name = lambda x: str(nodemap[x]) if nodemap[x].is_symbol() else x
            uncovered = [name(x) for x in nodemap if x not in node_covered]
            uncovered.sort()
            if len(uncovered) > 0:
                Logger.warning("Unlinked nodes \"%s\"" % ",".join(uncovered))

        if not self.symbolic_init:
            init = simplify(And(initlist))
        else:
            init = TRUE()

        invar = simplify(And(invarlist))

        # instead of trans, we're using the ftrans format -- see below
        ts.set_behavior(init, TRUE(), invar)

        # add ftrans
        for var, cond_assign_list in ftrans:
            ts.add_func_trans(var, cond_assign_list)

        hts.add_ts(ts)

        return (hts, invar_props, ltl_props)
Beispiel #24
0
 def _get_cases(self, ph):
     try:
         pats = self.ctor_pats[get_type(ph)](ph)
         return [SmtLibSExpression(p) for p in pats]
     except KeyError:
         return []
Beispiel #25
0
 def binary_op(bvop, bop, left, right):
     if (get_type(left) == BOOL) and (get_type(right) == BOOL):
         return bop(left, right)
     return bvop(B2BV(left), B2BV(right))
Beispiel #26
0
 def unary_op(bvop, bop, left):
     if (get_type(left) == BOOL):
         return bop(left)
     return bvop(left)
Beispiel #27
0
def vlog_match_widths(left: FNode,
                      right: FNode,
                      extend=False) -> Tuple[FNode, FNode]:
    '''
    Match the bit-widths for assignment using the Verilog standard semantics.

    if extend:
       zero extend to largest width
    else:
       left_width == right_width: no change
       left_width > right_width: right side is zero extended or sign extended depending on signedness
       left_width < right_width: right side is truncated (MSBs removed)
    '''
    assert type(left) == FNode and get_type(
        left).is_bv_type(), "Expecting a bit-vector"
    assert type(right) == FNode and get_type(
        right).is_bv_type(), "Expecting a bit-vector"

    left_width, right_width = left.bv_width(), right.bv_width()

    if left_width == right_width:
        pass
    elif left_width > right_width:
        # TODO: Check signed-ness of right-side

        fun = None
        padding = 0

        # handle ops with overflow:
        if right.is_bv_add():
            fun = BVAdd
            padding = 1
        elif right.is_bv_mul():
            fun = BVMul
            padding = 1
        elif right.is_bv_lshl():
            fun = BVLShl
            padding = left_width - right_width

        assert padding >= 0, "Expecting a non-negative padding"

        # TODO: Handle signed values here as well
        # re-build the node
        if padding > 0:
            args = [BVZExt(a, padding) for a in right.args()]
            right = fun(*args)

        # re-evauluate left_width and right_width, in case they're updated
        left_width, right_width = left.bv_width(), right.bv_width()

        assert left_width >= right_width, "Unexpected bitwidth mismatch"

        if left_width > right_width:
            right = BVZExt(right, left_width - right_width)

    else:
        if extend:
            left = BVZExt(left, right_width - left_width)
        else:
            right = BVExtract(right, 0, left_width - 1)

    return simplify(left), simplify(right)