Пример #1
0
    def solve(self) -> List[str] or None:
        logging.info('solving the query..')

        self._query_storage += '(echo "done")'

        lines_response = []
        # TODO: XXX: ugly (know about check-sat + protected): avoiding deadlock due to pipe overfull
        extracting = False
        for l in self._query_storage._output:
            self._process.stdin.write(bytes(l + '\n', 'utf-8'))
            self._process.stdin.flush()  # just in case
            if l.strip().startswith('(check-sat'):
                z3_response = str(self._process.stdout.readline(),
                                  'utf-8').strip()
                if z3_response == 'unsat':
                    self._query_storage = StrAwareList()
                    return None
                if z3_response == 'sat':
                    logging.debug('z3 returned sat, extracting the model')
                    extracting = True
                    continue
                else:
                    assert 0, 'z3 returned unexpected smth: ' + lines_response[
                        0]
            if extracting:
                z3_response = str(self._process.stdout.readline(),
                                  'utf-8').strip()
                lines_response.append(z3_response)

        self._query_storage = StrAwareList()
        return lines_response
Пример #2
0
def _mark_states_with_moore_signals(lts: LTS, state_variable, moore_signals):
    dot_lines = StrAwareList()

    for state in lts.states:
        state_label = Label({state_variable: state})
        value_by_signal = dict()
        for signal in moore_signals:
            signal_model = lts.model_by_signal[signal]
            value = signal_model[state_label]
            value_by_signal[signal] = value

        signals_str = _convert_label_to_dot(value_by_signal)

        color = ''
        if state in lts.init_states:
            color = ', fillcolor="green", style=filled'

        if signals_str != '':
            dot_lines += '"{state}" [label="{out}\\n{state}"{color}]'.format(
                color=color, state=state, out=signals_str)
        else:
            dot_lines += '"{state}" [label="{state}"{color}]'.format(
                color=color, state=state)

    return dot_lines
Пример #3
0
def _colorize_nodes(lts):
    dot_lines = StrAwareList()

    for state in lts.states:
        dot_lines += '"{state}" [{color}]'.format_map({'state': state,
                                                       'color': ['', 'fillcolor="green",style=filled'][
                                                           state in lts.init_states]})

    return dot_lines
Пример #4
0
def to_boolean_nusmv(lts: LTS, specification: SpecProperty) -> str:
    nof_state_bits = int(max(1, math.ceil(math.log(len(lts.states), 2))))
    bits_by_state = dict((state, bin_fixed_list(i, nof_state_bits))
                         for (i, state) in enumerate(sorted(lts.states)))

    state_bits = lmap(_ith_state_bit, range(nof_state_bits))

    _assert_no_intersection(state_bits,
                            list(lts.input_signals) + lts.output_signals)

    dot_lines = StrAwareList()
    dot_lines += 'MODULE main'
    dot_lines += 'IVAR'
    dot_lines += [
        '  {signal} : boolean;'.format(signal=s.name)
        for s in lts.input_signals
    ]

    dot_lines += 'VAR'
    dot_lines += ['  {si} : boolean;'.format(si=si) for si in state_bits]

    dot_lines += 'DEFINE'
    dot_lines += [
        '  {out_name} := {formula} ;'.format(out_name=out_name,
                                             formula=_get_formula(
                                                 out_name, out_model,
                                                 bits_by_state))
        for (out_name, out_model) in lts.model_by_name.items()
    ]

    dot_lines += 'ASSIGN'
    for i, sb in enumerate(state_bits):
        sb_init = str(bits_by_state[list(lts.init_states)[0]][i]).upper()

        dot_lines += '  init({sb}) := {init_sb};'.format(sb=sb,
                                                         init_sb=sb_init)

        dot_lines += '  next({sb}) := '.format(sb=sb)
        dot_lines += '    case'

        for (label, next_state) in lts.tau_model.items():
            sb_next = str(bits_by_state[next_state][i]).upper()
            dot_lines += '      {formula} : {next_state};'.format(
                formula=_clause_to_formula(label, bits_by_state),
                next_state=sb_next)

        dot_lines += '    TRUE : FALSE;'  # default: unreachable states, don't care
        dot_lines += '    esac;'

    expr = BinOp('->', and_expressions(specification.assumptions),
                 and_expressions(specification.guarantees))
    expr = WeakToUntilConverterVisitor().dispatch(
        expr)  # SMV does not have Weak until

    dot_lines += 'LTLSPEC ' + AstToSmvProperty().dispatch(expr)

    return '\n'.join(dot_lines)
Пример #5
0
    def __init__(self, z3_path):
        super().__init__(StrAwareList())

        z3_cmd = z3_path + ' -smt2 -in '
        args = shlex.split(z3_cmd)

        self._process = subprocess.Popen(args,
                                         stdin=subprocess.PIPE,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT)

        logging.info('created z3 process: ' + str(self._process.pid))
Пример #6
0
def _label_states_with_outvalues(lts:LTS, filter='all'):
    dot_lines = StrAwareList()

    for state in lts.states:
        signal_vals_pairs = [(var, vals) for (var, vals) in lts.model_by_name.items()
                             if var in filter or filter == 'all']
        outvals = dict([(var, vals[Label({'state': state})])  # TODO: hack
                        for (var, vals) in signal_vals_pairs])

        outvals_str = _convert_to_dot(outvals)
        if outvals_str != '':
            dot_lines += '"{state}"[label="{out}\\n({state})"]'.format(state=state, out=outvals_str)

    return dot_lines
Пример #7
0
    def _get_init_condition_on_tokens(self):
        conditions = StrAwareList()

        states = self.states_by_process[0]
        s0, s1 = states[0], states[1]

        tok_func_desc = self.outvar_desc_by_process[0][self._has_tok_signal]

        conditions += self.underlying_solver.call_func(
            tok_func_desc, {self.state_arg_name: s1})
        conditions += self.underlying_solver.op_not(
            self.underlying_solver.call_func(tok_func_desc,
                                             {self.state_arg_name: s0}))
        return conditions
Пример #8
0
    def __init__(self, logic: Logic, z3_path, logger):
        super().__init__(StrAwareList(), logic)

        z3_cmd = z3_path + ' -smt2 -in '
        args = shlex.split(z3_cmd)

        self._logger = logger

        self._process = subprocess.Popen(args,
                                         stdin=subprocess.PIPE,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE)

        self._logger.info('created z3 process: ' + str(self._process.pid))
Пример #9
0
    def solve(self):
        self._logger.info('solving the query..')

        self._query_storage += '(echo "done")'

        self._process.stdin.write(bytes(str(self._query_storage), 'utf-8'))
        self._process.stdin.flush()  # just in case

        lines = self._read_block()
        self._assert_no_errors(lines)

        self._query_storage = StrAwareList()

        if lines[0] == 'sat':
            return lines[1:]
        return None
Пример #10
0
    def _restrict_trans(self, impl, permissible_states):
        #: :type: FuncDescription
        trans_func_desc = impl.taus_descs[0]

        assertions = StrAwareList()

        for curr_state in permissible_states:
            free_input_vars = self._get_free_vars(Label(), impl)
            value_by_arg = self._get_proc_tau_args(curr_state, Label(), 0, impl)
            next_state = self._underlying_solver.call_func(trans_func_desc, value_by_arg)
            assertions += self._underlying_solver.assert_(
                self._underlying_solver.forall_bool(free_input_vars,
                                                    self._get_permissible_states_clause(next_state,
                                                                                        permissible_states)))

        return assertions
Пример #11
0
    def get_architecture_requirements(self):
        """
        'One process only possesses the token initially'

        Generic encoder considers different initial configurations of the ring,
        making sure that all possible initial token distributions are verified.
        """
        conditions = StrAwareList()

        states = self.states_by_process[0]
        s0, s1 = states[0], states[1]

        tok_func_desc = self.outvar_desc_by_process[0][
            self._has_tok_signals[0]]

        conditions += self.underlying_solver.call_func(
            tok_func_desc, {self.state_arg_name: s1})
        conditions += self.underlying_solver.op_not(
            self.underlying_solver.call_func(tok_func_desc,
                                             {self.state_arg_name: s0}))

        return conditions
Пример #12
0
def _lts_to_dot(lts: LTS, state_variable, moore_signals):
    logger = logging.getLogger(__file__)

    dot_lines = StrAwareList()
    dot_lines += 'digraph module {\n rankdir=LR;\n'
    dot_lines += _mark_states_with_moore_signals(lts, state_variable,
                                                 moore_signals)

    edge_labels = _build_edge_labels(lts, state_variable, moore_signals)
    logger.debug('non-simplified model: \n' + str(edge_labels))

    simplified_edge_labels = simplify_edge_labels(edge_labels)
    # simplified_edge_labels = edge_labels

    for (src, dst), io_labels in simplified_edge_labels.items():
        if not io_labels:  # possible due to the simplification
            dot_lines += '"{src}" -> "{dst}" [label="1"]'.format(src=src,
                                                                 dst=dst)
        for io_label in io_labels:
            i_vals = dict()
            o_vals = dict()
            for signal, value in io_label.items():
                if signal in lts.input_signals:
                    i_vals[signal] = value
                else:
                    o_vals[signal] = value

            i_vals_str = _convert_label_to_dot(i_vals) or '1'
            o_vals_str = _convert_label_to_dot(o_vals)

            dot_lines += '"{src}" -> "{dst}" [label="{in_}{out}"]'.format(
                src=src,
                dst=dst,
                in_=i_vals_str,
                out=('/' + '\\n' + o_vals_str) if o_vals_str != '' else '')

    dot_lines += '}'

    return '\n'.join(dot_lines)
Пример #13
0
def to_dot(lts:LTS, outvars_treated_as_moore=()):
    logger = logging.getLogger(__file__)

    dot_lines = StrAwareList()
    dot_lines += 'digraph module {\n'

    dot_lines += _colorize_nodes(lts) + '\n'

    dot_lines += _label_states_with_outvalues(lts, outvars_treated_as_moore)

    srcdst_to_io_labels = _build_srcdst_to_io_labels(lts, outvars_treated_as_moore)
    logger.debug('non-simplified model: \n' + str(srcdst_to_io_labels))

    simplified_srcdst_to_io_labels = _simplify_srcdst_to_io_labels(srcdst_to_io_labels)
    logger.debug('the model after edge simplifications: \n' + str(srcdst_to_io_labels))

    for (src, dst), io_labels in simplified_srcdst_to_io_labels.items():
        for io_label in io_labels:
            i_vals = dict()
            o_vals = dict()
            for signal, value in io_label.items():
                if signal in lts.input_signals:
                    i_vals[signal] = value
                else:
                    o_vals[signal] = value

            i_vals_str = _convert_to_dot(i_vals) or '*'
            o_vals_str = _convert_to_dot(o_vals)
            o_vals_str = '/' + '\\n' + o_vals_str if o_vals_str != '' else ''

            dot_lines += '"{state}" -> "{x_state}" [label="{in}{mark_out}"]'.format_map(
                {'state': src,
                 'x_state': dst,
                 'in': i_vals_str,
                 'mark_out': o_vals_str})

    dot_lines += '}'

    return '\n'.join(dot_lines)
Пример #14
0
    def _get_tok_rings_safety_props(
            self) -> StrAwareList:  # TODO: should be able to specify states!
        """
        Return (in SMT form, constraints on non-wrapped tau function):
         G(tok & !sends -> Xtok(tau(!prev)))
         G(sends -> tok)
         G(sends -> X!tok(!prev))
         G(Xtok(prev))
         G(!tok -> !Xtok(!prev))
        """
        smt_lines = StrAwareList()

        tau_desc = self.taus_descs[0]
        tau_signals = self.orig_inputs[0]

        tok_func_desc = self.outvar_desc_by_process[0][self._has_tok_signal]
        sends_func_desc = self.outvar_desc_by_process[0][self._sends_signal]

        prev_is_false_label = Label({self._sends_prev_signal: False})
        prev_is_true_label = Label({self._sends_prev_signal: True})

        states = self.states_by_process[0]
        for state in states:
            state_arg = {self.state_arg_name: state}

            has_tok_expr = call_func(tok_func_desc, state_arg)
            sends_tok_expr = call_func(sends_func_desc, state_arg)

            _, free_vars = build_signals_values(tau_signals,
                                                prev_is_false_label)

            nprev_arg, _ = build_signals_values(tau_signals,
                                                prev_is_false_label)
            nprev_state_arg = add_dicts(nprev_arg, state_arg)

            prev_arg, _ = build_signals_values(tau_signals, prev_is_true_label)
            prev_state_arg = add_dicts(prev_arg, state_arg)

            tau_nprev_expr = call_func(tau_desc, nprev_state_arg)
            tok_of_tau_nprev_expr = call_func(
                tok_func_desc, {self.state_arg_name: tau_nprev_expr})

            tau_prev_expr = call_func(tau_desc, prev_state_arg)
            tok_of_tau_prev_expr = call_func(
                tok_func_desc, {self.state_arg_name: tau_prev_expr})

            #
            tok_dont_disappear = forall_bool(
                free_vars,
                op_implies(op_and([has_tok_expr,
                                   op_not(sends_tok_expr)]),
                           tok_of_tau_nprev_expr))

            sends_with_token_only = forall_bool(
                free_vars, op_implies(sends_tok_expr, has_tok_expr))

            sends_means_release = forall_bool(
                free_vars,
                op_implies(sends_tok_expr, op_not(tok_of_tau_nprev_expr)))

            sends_prev_means_acquire = forall_bool(free_vars,
                                                   tok_of_tau_prev_expr)

            no_sends_prev_no_tok_means_no_next_tok = forall_bool(
                free_vars,
                op_implies(op_not(has_tok_expr),
                           op_not(tok_of_tau_nprev_expr)))

            smt_lines += [
                tok_dont_disappear, sends_with_token_only, sends_means_release,
                sends_prev_means_acquire,
                no_sends_prev_no_tok_means_no_next_tok
            ]

        return smt_lines
Пример #15
0
def lts_to_verilog(lts:LTS) -> str:
    s = StrAwareList()

    s += 'module model(i_clk, \n{inputs}, \n{outputs});'.format(inputs=', '.join(map(lambda sig: sig.name,
                                                                                     lts.input_signals)),
                                                                outputs=', '.join(map(lambda sig: sig.name,
                                                                                      lts.output_signals)))
    s.newline()

    s += 'input i_clk;'
    s += '\n'.join(['input {sig};'.format(sig=sig.name) for sig in lts.input_signals])
    s.newline()

    s += '\n'.join(['output {sig};'.format(sig=sig.name) for sig in lts.output_signals])
    s.newline()

    nof_state_bits = max(1, math.ceil(math.log2(len(lts.states))))
    s += 'reg [{max_bit}:0] {state};'.format(max_bit=nof_state_bits-1, state=lts.state_name)
    s.newline()

    s += '\n'.join(['wire {out};'.format(out=sig.name) for sig in lts.output_signals])
    s.newline()

    for out_sig, value_tuples in lts.output_models.items():
        labels_true = lmap(lambda x: x[0],
                           filter(lambda label_value: label_value[1],
                                  value_tuples.items()))
        assign = 'assign {sig} = {true_expr};'.format(sig=out_sig.name,
                                                      true_expr=' || '.join(map(_label_to_verilog,
                                                                                labels_true))
                                                                if labels_true else '0')
        s += assign
    s.newline()

    s += 'initial begin'
    s += '{state} = 0;'.format(state=lts.state_name)
    s += 'end'
    s.newline()

    s += 'always@(posedge i_clk)'
    s += 'begin'

    tau_items = tuple(lts.tau_model.items())
    s += 'if ({expr}) {state} = {next_val};'.format(expr=_label_to_verilog(tau_items[0][0]),
                                                    state=lts.state_name,
                                                    next_val=tau_items[0][1])
    for lbl, val in tau_items[1:]:
        s += 'else if ({expr}) {state} = {next_val};'.format(expr=_label_to_verilog(lbl),
                                                             state=lts.state_name,
                                                             next_val=val)
    s += 'end'
    s += 'endmodule'
    return s.to_str()
Пример #16
0
def lts_to_verilog(lts:LTS, module_name:str) -> str:
    s = StrAwareList()

    s += 'module {module}({inputs}, {outputs});'.format(
        inputs=', '.join(map(lambda sig: sig.name, lts.input_signals)),
        outputs=', '.join(map(lambda sig: sig.name, lts.output_signals)),
        module=module_name)
    s.newline()

    s += '\n'.join(['input {sig};'.format(sig=sig.name) for sig in lts.input_signals])
    s.newline()

    s += '\n'.join(['output {sig};'.format(sig=sig.name) for sig in lts.output_signals])
    s.newline()

    # TODO: don't use latches for state-less models
    nof_state_bits = math.ceil(math.log2(len(lts.states)))
    s += 'reg [{max_bit}:0] {state};'.format(max_bit=int(max(0., nof_state_bits-1)),  # max_bit is at least 0
                                                         state=lts.state_name)
    s.newline()

    s += '\n'.join(['wire {out};'.format(out=sig.name) for sig in lts.output_signals])
    s.newline()

    for out_sig, value_tuples in lts.output_models.items():
        labels_true = lmap(lambda x: x[0],
                           filter(lambda label_value: label_value[1],
                                  value_tuples.items()))
        assign = 'assign {sig} = {true_expr};'.format(sig=out_sig.name,
                                                      true_expr=' || '.join(map(_label_to_verilog, labels_true))
                                                                if labels_true else '0')
        s += assign
    s.newline()

    s += 'initial begin'
    s += '{state} = 0;'.format(state=lts.state_name)
    s += 'end'
    s.newline()

    s += 'always@($global_clock)'
    s += 'begin'

    # you can also use '=' instead of '<=' here, but we will be strict
    tau_items = tuple(lts.tau_model.items())
    s += 'if ({expr}) {state} <= {next_val};'.format(expr=_label_to_verilog(tau_items[0][0]),
                                                     state=lts.state_name,
                                                     next_val=tau_items[0][1])
    for lbl, val in tau_items[1:]:
        s += 'else if ({expr}) {state} <= {next_val};'.format(expr=_label_to_verilog(lbl),
                                                              state=lts.state_name,
                                                              next_val=val)
    s += 'end'
    s += 'endmodule'
    return s.to_str()
Пример #17
0
def atm_to_verilog(atm: Automaton, sys_inputs: Iterable[Signal],
                   sys_outputs: Iterable[Signal], module_name: str,
                   bad_out_name: str) -> str:
    assert len(lfilter(lambda n: is_final_sink(n), atm.nodes)) == 1,\
        'for now I support only one bad state which must be a sink'
    sys_inputs = set(sys_inputs)
    sys_outputs = set(sys_outputs)

    verilog_by_sig = {s: 'controllable_' + s.name for s in sys_outputs}
    verilog_by_sig.update({s: s.name for s in sys_inputs})

    verilog_by_node = {q: '__q' + q.name for q in atm.nodes}
    sink_q = lfilter(lambda n: is_final_sink(n), atm.nodes)[0]

    module_inputs = list(
        chain(map(lambda i: i.name, sys_inputs),
              map(lambda o: 'controllable_' + o.name, sys_outputs)))

    s = StrAwareList()
    s += 'module {module_name}({inputs}, {output});'.format(
        module_name=module_name,
        inputs=', '.join(module_inputs),
        output=bad_out_name)
    s.newline()

    s += '\n'.join('input %s;' % i for i in module_inputs)
    s.newline()

    s += 'output %s;' % bad_out_name
    s.newline()

    s += '\n'.join('reg %s;' % vq for vq in verilog_by_node.values())
    s.newline()

    s += 'wire %s;' % bad_out_name
    s += 'assign {bad} = {sink_q};'.format(bad=bad_out_name,
                                           sink_q=verilog_by_node[sink_q])
    s.newline()

    s += 'initial begin'
    s += '\n'.join('%s = 1;' % verilog_by_node[iq] for iq in atm.init_nodes)
    s += '\n'.join('%s = 0;' % verilog_by_node[q]
                   for q in atm.nodes - atm.init_nodes)
    s += 'end'
    s.newline()

    s += 'always@($global_clock)'
    s += 'begin'

    def lbl_to_v(lbl: Label) -> str:
        return ' && '.join(
            ('!%s', '%s')[lbl[s]] % verilog_by_sig[s] for s in lbl) or '1'

    for q in atm.nodes:
        incoming_edges = incoming_transitions(q, atm)
        if not incoming_edges:
            update_expr = '0'
        else:
            update_expr = ' || '.join('{src} && {lbl}'.format(
                src=verilog_by_node[edge[0]], lbl=lbl_to_v(edge[1]))
                                      for edge in incoming_edges)
        s += '  {q} <= {update_expr};'.format(q=verilog_by_node[q],
                                              update_expr=update_expr)
    s += 'end'
    s += 'endmodule'
    return s.to_str()
Пример #18
0
def convert(aht:AHT or None, shared_aht:SharedAHT, dstFormPropMgr:DstFormulaPropMgr)\
        -> str:
    def _gen_unique_name(__=[]) -> str:  # mutable default arg is on purpose
        name = '__n' + str(len(__))
        __.append('')
        return name

    transitions = shared_aht.transitions if not aht \
        else get_reachable_from(aht.init_node, shared_aht.transitions, dstFormPropMgr)[1]

    all_nodes = set()  # Set[Node]
    trans_dot = StrAwareList()
    InvisNode = namedtuple('InvisNode', ['name', 'is_existential'])
    invis_nodes = set()  # type: Set['InvNode']
    for t in transitions:  # type: Transition
        all_nodes.add(t.src)

        inv_node = InvisNode(name=_gen_unique_name(),
                             is_existential=t.src.is_existential)
        invis_nodes.add(inv_node)

        trans_dot += '"{src}" -> "{invisible}" [label="{label}"];'.format(
            src=t.src.name, invisible=inv_node.name, label=_label_to_short_string(t.state_label))

        cubes = to_dnf_set(t.dst_expr)  # type: List[List[Expr]]

        colors = 'black blue purple green yellow orange red brown pink gray'.split()
        for cube in cubes:  # type: List[Expr]
            # each cube gets its own color
            color = colors.pop(0) if len(colors) else 'gray'
            for lit in cube:  # type: BinOp
                assert lit.name == '=', "should be prop of the form sig=1; and not negated"
                dstFormProp = dstFormPropMgr.get_dst_form_prop(get_sig_number(lit)[0].name)

                trans_dot += '"{invisible}" -> "{dst}" [color={color}, label="{ext_label}"];'.format(
                    invisible=inv_node.name,
                    dst=dstFormProp.dst_state.name,
                    color=color,
                    ext_label=_ext_label_to_short_string(dstFormProp.ext_label))

                all_nodes.add(dstFormProp.dst_state)
    # end of 'for t in aht.transitions'

    invis_nodes_dot = ['{n} [label="DNF", shape=box, fontsize=6, style=rounded, margin=0, width=0.3, height=0.2];'
                           .format(n=n.name)
                       for n in invis_nodes]
    nodes_dot = '\n'.join(['"{n}" [color="{color}", shape="{shape}" {initial}];'
                               .format(n=n.name,
                                       color=('red', 'green')[n.is_existential],
                                       shape=('ellipse', 'doubleoctagon')[n.is_final],
                                       initial='' if n != (aht.init_node if aht else None) else ', style=filled, fillcolor=gray')
                           for n in all_nodes])

    dot_lines = StrAwareList() + 'digraph "automaton" {' + \
                'rankdir=LR;' + \
                (('label="%s"' % aht.name) if aht else '') + \
                nodes_dot + \
                trans_dot +\
                invis_nodes_dot +\
                '}'

    return '\n'.join(dot_lines)