示例#1
0
def lossy_duplicating_tag_data_channel(name):
    input_channel = z3p.Array('{}_input_channel'.format(name), z3p.IntSort(),
                              z3p.IntSort())
    output_channel = z3p.Array('{}_output_channel'.format(name), z3p.IntSort(),
                               z3p.IntSort())
    tag = z3p.Int('{}_channel_tag'.format(name))
    data = z3p.Int('{}_channel_data'.format(name))
    transitions = []
    transitions.append(('t0', 'empty', input_channel,
                        z3p.BoolVal(True), [(tag, input_channel[0]),
                                            (data, input_channel[1])], 'full'))
    transitions.append(
        ('t1', 'full', output_channel, [tag,
                                        data], z3p.BoolVal(True), [], 'empty'))
    transitions.append(
        ('t2', 'full', input_channel, z3p.BoolVal(True), [], 'full'))
    transitions.append(('t_duplication', 'full', output_channel, [tag, data],
                        z3p.BoolVal(True), [], 'full'))
    transitions.append(
        ('t_loss', 'empty', input_channel, z3p.BoolVal(True), [], 'empty'))
    return automaton.SymbolicAutomaton(
        '{}_tag_data_channel'.format(name), ['empty', 'full'],
        'empty',
        transitions,
        input_channels=[input_channel],
        output_channels=[output_channel],
        variables=[tag, data],
        initial_values=[z3p.IntVal(0), z3p.IntVal(0)],
        variable_ranges={
            tag: (0, 1),
            data: (min_value_message, max_value_message)
        },
        compassion=['t1', 't0'])
示例#2
0
def receiver():
    forward_output_channel = z3p.Array('forward_output_channel', z3p.IntSort(),
                                       z3p.IntSort())
    backward_input_channel = z3p.Int('backward_input_channel')
    receive = z3p.Int('receive')
    input_tag = z3p.Int('receiver_tag')
    input_data = z3p.Int('receiver_data')
    expected_tag = z3p.Int('expected_tag')
    transitions = []
    transitions.append(
        ('t0', 'initial', forward_output_channel, z3p.BoolVal(True),
         [(input_tag, forward_output_channel[0]),
          (input_data, forward_output_channel[1])], 'q0'))
    transitions.append(
        ('t1', 'q0', receive, [input_data], z3p.Eq(input_tag,
                                                   expected_tag), [], 'q1'))
    transitions.append(
        ('t2', 'q1', backward_input_channel, [expected_tag],
         z3p.BoolVal(True), [(expected_tag,
                              z3p.If(z3p.Eq(expected_tag, 0), z3p.IntVal(1),
                                     z3p.IntVal(0)))], 'initial'))
    transitions.append(('t3', 'q0', z3p.Neq(input_tag,
                                            expected_tag), [], 'q2'))
    transitions.append(
        ('t4', 'q2', backward_input_channel,
         [z3p.If(z3p.Eq(expected_tag, 0), z3p.IntVal(1),
                 z3p.IntVal(0))], z3p.BoolVal(True), [], 'initial'))
    return automaton.SymbolicAutomaton(
        'receiver', ['initial', 'q0', 'q1', 'q2'],
        'initial',
        transitions,
        input_channels=[forward_output_channel],
        output_channels=[receive, backward_input_channel],
        variables=[input_tag, input_data, expected_tag],
        initial_values=[z3p.IntVal(0),
                        z3p.IntVal(0),
                        z3p.IntVal(0)],
        variable_ranges={
            input_tag: (0, 1),
            input_data: (min_value_message, max_value_message),
            expected_tag: (0, 1)
        },
        output_channel_ranges={
            receive: (min_value_message, max_value_message),
            backward_input_channel: (0, 1)
        },
        justice=['t3', 't1'])
示例#3
0
 def efsm_variable_type(self, variable):
     a = next(a for a in self.automata if variable in a.variables)
     if variable.sort() == z3p.BoolSort():
         return 'TheLTS->MakeRangeType(0, 1)'
     elif variable.sort() == z3p.IntSort():
         low, high = a.variable_ranges[variable]
         return "TheLTS->MakeRangeType({}, {})".format(low, high)
     else:
         raise NotImplementedError("Channel type cannot be defined for channel {} with sort {}.".format(variable, variable.sort()))
示例#4
0
def sender():
    transitions = []
    input_message = z3p.Int('sender_input_message')
    sender_tag = z3p.Int('sender_tag')
    ack_tag = z3p.Int('ack_tag')
    forward_input_channel = z3p.Array('forward_input_channel', z3p.IntSort(),
                                      z3p.IntSort())
    backward_output_channel = z3p.Int('backward_output_channel')
    send = z3p.Int('send')
    timeout = util.new_variable('timeout', 'unit')
    transitions.append(('t0', 'initial', send, z3p.BoolVal(True),
                        [(input_message, send)], 'q0'))
    transitions.append(
        ('t1', 'q0', forward_input_channel, [sender_tag, input_message],
         z3p.BoolVal(True), [], 'q1'))
    transitions.append(('t2', 'q1', timeout, z3p.BoolVal(True), [], 'q0'))
    transitions.append(('t3', 'q1', backward_output_channel, z3p.BoolVal(True),
                        [(ack_tag, backward_output_channel)], 'q2'))
    transitions.append(('t4', 'q2', z3p.Eq(ack_tag, sender_tag), [
        (sender_tag, z3p.If(z3p.Eq(sender_tag, 0), z3p.IntVal(1),
                            z3p.IntVal(0)))
    ], 'initial'))
    transitions.append(('t5', 'q2', z3p.Neq(ack_tag, sender_tag), [], 'q0'))
    return automaton.SymbolicAutomaton(
        'sender', ['initial', 'q0', 'q1', 'q2'],
        'initial',
        transitions,
        variables=[input_message, sender_tag, ack_tag],
        initial_values=[z3p.IntVal(0),
                        z3p.IntVal(0),
                        z3p.IntVal(0)],
        input_channels=[send, timeout, backward_output_channel],
        output_channels=[forward_input_channel],
        variable_ranges={
            input_message: (min_value_message, max_value_message),
            sender_tag: (0, 1),
            ack_tag: (0, 1)
        },
        output_channel_ranges={
            forward_input_channel[1]: (min_value_message, max_value_message),
            forward_input_channel[0]: (0, 1)
        })
示例#5
0
 def efsm_channel_type(self, channel):
     if isinstance(channel, z3p.ArrayRef):
         return "{}Type".format(to_camel_case(channel.decl().name()))
     if channel.sort() == util.UNIT_SORT:
         return "RangeType"
     elif channel.sort() == z3p.BoolSort():
         return "Range01Type"
     elif channel.sort() == z3p.IntSort():
         variables = self.reading_variables_for_channel(channel)
         for v in variables:
             a = next(a for a in self.automata if v in a.variables)
             low, high = a.variable_ranges[v]
             return "Range{}{}Type".format(low, high)
     else:
         raise NotImplementedError("Channel type cannot be defined for channel {} with sort {}.".format(channel, channel.sort()))
示例#6
0
 def create_guard_hole(self, hole_name):
     """ variable is the name of the variable to update
     """
     signature = []
     domains = []
     for variable in self.variables:
         variable_sort = variable.sort()
         signature.append(variable_sort)
         if variable.sort() == z3p.IntSort():
             domains.append(range(self.variable_ranges[variable][0],
                                  self.variable_ranges[variable][1] + 1))
         elif variable.sort() == z3p.BoolSort():
             domains.append([z3p.BoolVal(False), z3p.BoolVal(True)])
         else:
             raise NotImplementedError("Unimplemented type of variable {}".format(variable_sort))
     signature.append(z3p.BoolSort())
     f = z3p.Function(hole_name, *signature)
     return (f, domains, None, None)
示例#7
0
def evaluate_expression(expression,
                        symbolic_memory,
                        concrete_memory,
                        tables=None):
    if isinstance(expression, int):
        return expression
    if isinstance(expression, tuple):
        return expression
    if z3p.is_const(expression):
        if z3p.is_bool_or_int_value(expression):
            return expression
        if expression in symbolic_memory:
            return symbolic_memory[expression]
        elif expression.decl().name().startswith('table_'):
            assert expression.decl().name() in tables
            table_expression = tables[expression.decl().name()]
            first_value = table_expression[0][1]
            if first_value.sort() == z3p.IntSort():
                last_else = z3p.IntVal(0)
            else:
                last_else = z3p.BoolVal(False)
            if_expression = None
            for conditional, value in table_expression:
                guard = evaluate_expression(conditional, symbolic_memory,
                                            concrete_memory)
                last_else = z3p.If(guard, value, last_else)
            return z3p.simplify(last_else)
        else:
            return concrete_memory[expression]
    elif expression.decl().kind() == z3p.Z3_OP_SELECT:
        if expression in symbolic_memory:
            return symbolic_memory[expression]
        else:
            return concrete_memory[expression]
    else:
        new_args = [
            evaluate_expression(expression.arg(i), symbolic_memory,
                                concrete_memory, tables)
            for i in range(expression.num_args())
        ]
        if expression.decl().kind() == z3p.Z3_OP_AND:
            return z3p.And(*new_args)
        else:
            return expression.decl()(*new_args)
示例#8
0
 def channel_range(self, channel):
     if isinstance(channel, z3p.ArrayRef):
         channel_ranges = []
         for i in range(self.array_channel_size(channel)):
             variables = self.reading_variables_for_channel_field(channel[i])
             ranges = set([self.automaton_with_variable(v).variable_ranges[v] for v in variables])
             assert len(ranges) == 1
             channel_ranges.append(ranges)
         return channel_ranges
         # return "{}Type".format(to_camel_case(channel.decl().name()))
     elif channel.sort() == util.UNIT_SORT:
         return (0, 0)
     elif channel.sort() == z3p.BoolSort():
         return (0, 1)
     elif channel.sort() == z3p.IntSort():
         variables = self.reading_variables_for_channel_or_channel_field(channel)
         ranges = set([self.automaton_with_variable(v).variable_ranges[v] for v in variables])
         assert len(ranges) == 1
         return ranges.pop()
     else:
         raise NotImplementedError("Channel type cannot be defined for channel {} with sort {}.".format(channel, channel.sort()))
示例#9
0
 def create_update_hole(self, variable_or_variable_name, hole_name):
     """ variable is the name of the variable to update
     """
     if isinstance(variable_or_variable_name, str):
         variable_to_update = next(v for v in self.variables
                                   if v.decl().name() == variable_or_variable_name)
     else:
         variable_to_update = variable_or_variable_name
     signature = []
     domains = []
     for variable in self.variables:
         variable_sort = variable.sort()
         signature.append(variable_sort)
         if variable.sort() == z3p.IntSort():
             domains.append([z3p.IntVal(i) for i in range(self.variable_ranges[variable][0],
                                                          self.variable_ranges[variable][1] + 1)])
         elif variable.sort() == z3p.BoolSort():
             domains.append([z3p.BoolVal(False), z3p.BoolVal(True)])
         else:
             raise NotImplementedError("Unimplemented type of variable {}".format(variable_sort))
     signature.append(variable_to_update.sort())
     f = z3p.Function(hole_name, *signature)
     constraint = z3p.And([z3p.Or([z3p.Eq(f(*arg), z3p.IntVal(result)) for result in range(self.variable_ranges[variable_to_update][0], self.variable_ranges[variable_to_update][1] + 1)]) for arg in itertools.product(*domains)])
     return (f, domains, constraint, (variable_to_update, self.variables.index(variable_to_update)))
示例#10
0
    def __init__(self, name, locations, initial_location, transitions, variables=None, initial_values=None, input_channels=None, output_channels=None, tables=None, variable_ranges=None, output_channel_ranges=None, compassion=None, justice=None):
        """ Every node represents a control location and has a unique name.
            Transitions are of the form (soruce, channel[, channel expression], guard, update, target)
            where source and target must be automaton control locations,
            channel an input or output channel,
            channel expression is there if the channel is an output one,
            guard is a z3 boolean expression,
            update is a pair (variable, expression).
        """
        super(SymbolicAutomaton, self).__init__()
        self.name = name
        self.variables = variables if variables is not None else []
        self.transitions = transitions
        self.initial_values = initial_values if initial_values is not None else []
        self.initials = {}
        for v, value in zip(self.variables, self.initial_values):
            self.initials[v] = value
        assert len(self.variables) == len(self.initial_values), "# of initial values should match # of variables: variables {}, initials: {}".format(self.variables, self.initial_values)

        self.variable_initial_value = dict(zip([str(v) for v in self.variables],
                                               self.initial_values))
        # TODO change this to work with uninitialized variables
        # change variables input to include initial values
        self.input_channels = input_channels if input_channels is not None else []
        self.output_channels = output_channels if output_channels is not None else []
        # add channel with unit type unit can be an mtype with just one symbol

        for l in locations:
            self.add_node(l)

        for transition in transitions:
            channel_expression = []
            # if it is an input transition, there is no expression for the message to send
            if len(transition) == 6:
                name, source, channel, guard, update, target = transition
                assert channel not in self.output_channels, "Output channel {} used in input transition {}".format(channel, transition)
                kind = 'input'
            # output transitions
            elif len(transition) == 7:
                name, source, channel, channel_expression, guard, update, target = transition
                assert channel not in self.input_channels, "Input channel {} used in output transition {}".format(channel, transition)
                kind = 'output'

            # internal transitios
            elif len(transition) == 5:
                name, source, guard, update, target = transition
                channel = None
            assert source in locations and target in locations, transition
            assert (channel in self.input_channels or
                    channel in self.output_channels or
                    channel is None), transition
            if channel is None:
                kind = 'internal'
            if name is None:
                name = 't_{}'.format(self.number_of_edges())
            self.add_edge(source, target,
                          channel=channel,
                          channel_expression=channel_expression,
                          guard=guard,
                          update=update,
                          name=name,
                          kind=kind,
                          automaton=self)
        assert initial_location in self.nodes()
        self.initial_location = initial_location
        self.tables = {} if tables is None else tables

        self.channel_edges = {}
        self.update_channel_edges()
        self.changes = []
        self.transition_variables = {}
        self.update_transition_variables()
        self.variable_ranges = {} if variable_ranges is None else variable_ranges
        self.output_channel_ranges = {} if output_channel_ranges is None else output_channel_ranges
        for v in self.variables:
            if v.sort() == z3p.IntSort():
                assert v in self.variable_ranges, "No range declared for {}".format(v)
        for variable, variable_range in self.variable_ranges.items():
            assert variable in self.variables, "Variable {} was not declared".format(variable)
            assert variable.sort() == z3p.IntSort()
            assert isinstance(variable_range, tuple) and len(variable_range) == 2
            assert isinstance(variable_range[0], int)
            assert isinstance(variable_range[1], int)
            assert variable_range[0] <= variable_range[1]
        for output_channel_or_field, output_channel_range in self.output_channel_ranges.items():
            if not z3p.is_const(output_channel_or_field) and output_channel_or_field.decl().kind() == z3p.Z3_OP_SELECT:
                assert output_channel_or_field.arg(0) in self.output_channels
            else:
                assert output_channel_or_field in self.output_channels
            # assert output_channel.sort() == z3p.IntSort()
            assert isinstance(output_channel_range, tuple) and len(output_channel_range) == 2
            assert isinstance(output_channel_range[0], int)
            assert isinstance(output_channel_range[1], int)
            assert output_channel_range[0] < output_channel_range[1]
        if compassion is not None:
            self.compassion = compassion
        else:
            self.compassion = []
        if justice is not None:
            self.justice = justice
        else:
            self.justice = []
示例#11
0
def response_channel(address_id, cache_id, directory_id, num_values, num_caches):
    name = 'response_channel_{}_{}_{}'.format(cache_id, address_id, directory_id)
    inputs = []
    outputs = []
    data_ranges = {}
    number_of_fields = {}
    suffix = '_{}_{}_{}'.format(cache_id, directory_id, address_id)
    wbackmsg = 'WBAckMsg'
    wbackmsg_input = util.new_variable(wbackmsg + suffix, 'unit')
    wbackmsg_output = util.new_variable(wbackmsg + 'P' + suffix, 'unit')
    inputs.append(wbackmsg_input)
    outputs.append(wbackmsg_output)

    locations = ['empty']

    transitions = []

    full_state = 'WBAckMsg_full'
    locations.append(full_state)
    transitions.append((None, 'empty', wbackmsg_input, TRUE, [], full_state))
    transitions.append((None, full_state, wbackmsg_output, [ZERO], TRUE, [], 'empty'))

    variable_ranges = {}

    variable_data = z3p.Int('data_{}'.format(name))
    variable_num_caches = z3p.Int('num_caches_{}'.format(name))
    variable_ranges[variable_data] = (0, num_values - 1)
    variable_ranges[variable_num_caches] = (0, num_caches)

    datamsgd2c = 'DataMsgD2C'
    datamsgd2c_input = z3p.Array(datamsgd2c + suffix, z3p.IntSort(), z3p.IntSort())
    datamsgd2c_output = z3p.Array(datamsgd2c + 'P' + suffix, z3p.IntSort(), z3p.IntSort())
    inputs.append(datamsgd2c_input)
    outputs.append(datamsgd2c_output)

    full_state = 'DataMsgD2C_full'
    locations.append(full_state)
    transitions.append((None, 'empty', datamsgd2c_input, TRUE, [(variable_data, datamsgd2c_input[0]), (variable_num_caches, datamsgd2c_input[1])], full_state))
    transitions.append((None, full_state, datamsgd2c_output, [variable_data, variable_num_caches], TRUE, [(variable_data, ZERO), (variable_num_caches, ZERO)], 'empty'))

    datamsgc2c = 'DataMsgC2C'
    invackmsg = 'InvAckMsg'
    for other_cache_id in range(num_caches):
        if other_cache_id != cache_id:
            suffix2 = '_{}{}'.format(other_cache_id, suffix)
            datamsgc2c_input = z3p.Int(datamsgc2c + suffix2)
            datamsgc2c_output = z3p.Int(datamsgc2c + 'P' + suffix2)
            inputs.append(datamsgc2c_input)
            outputs.append(datamsgc2c_output)

            full_state = 'DataMsgC2C_full_{}'.format(other_cache_id)
            locations.append(full_state)
            transitions.append((None, 'empty', datamsgc2c_input, TRUE, [(variable_data, datamsgc2c_input)], full_state))
            transitions.append((None, full_state, datamsgc2c_output, [variable_data], TRUE, [(variable_data, ZERO)], 'empty'))

            invackmsg_input = util.new_variable(invackmsg + suffix2, 'unit')
            invackmsg_output = util.new_variable(invackmsg + 'P' + suffix2, 'unit')
            inputs.append(invackmsg_input)
            outputs.append(invackmsg_output)

            full_state = 'InvAckMsg_full_{}'.format(other_cache_id)
            locations.append(full_state)
            transitions.append((None, 'empty', invackmsg_input, TRUE, [], full_state))
            transitions.append((None, full_state, invackmsg_output, [ZERO], TRUE, [], 'empty'))
    return automaton.SymbolicAutomaton(name,
                                       locations,
                                       'empty',
                                       transitions,
                                       variables=[variable_data, variable_num_caches],
                                       initial_values=[ZERO, ZERO],
                                       input_channels=inputs,
                                       output_channels=outputs,
                                       variable_ranges=variable_ranges)
示例#12
0
        UnblockEMsgP[c][d] = {}

        FwdGetXMsg[c][d] = {}
        FwdGetSMsg[c][d] = {}
        DataMsgD2C[c][d] = {}
        WBAckMsg[c][d] = {}

        for a in range(NUM_ADDRESSES):
            suffix = '_{}_{}_{}'.format(c, d, a)
            LDMsg[c][d][a] = util.new_variable('LDMsg' + suffix, 'unit')
            STMsg[c][d][a] = z3p.Int('STMsg' + suffix)
            EVMsg[c][d][a] = util.new_variable('EVMsg' + suffix, 'unit')
            FwdGetXMsgP[c][d][a] = z3p.Int('FwdGetXMsgP' + suffix)
            FwdGetSMsgP[c][d][a] = z3p.Int('FwdGetSMsgP' + suffix)
            DataMsgD2CP[c][d][a] = z3p.Array('DataMsgD2CP' + suffix,
                                             z3p.IntSort(), z3p.IntSort())
            WBAckMsgP[c][d][a] = util.new_variable('WBAckMsgP' + suffix,
                                                   'unit')
            LDAckMsg[c][d][a] = z3p.Int('LDAckMsg' + suffix)
            STAckMsg[c][d][a] = z3p.Int('STAckMsg' + suffix)
            EVAckMsg[c][d][a] = util.new_variable('EVAckMsg' + suffix, 'unit')
            UnblockSMsg[c][d][a] = util.new_variable('UnblockSMsg' + suffix,
                                                     'unit')
            UnblockEMsg[c][d][a] = util.new_variable('UnblockEMsg' + suffix,
                                                     'unit')
            GetXMsg[c][d][a] = util.new_variable('GetXMsg' + suffix, 'unit')
            GetSMsg[c][d][a] = util.new_variable('GetSMsg' + suffix, 'unit')
            WBMsg[c][d][a] = z3p.Int('WBMsg' + suffix)

            GetXMsgP[c][d][a] = util.new_variable('GetXMsgP' + suffix, 'unit')
            GetSMsgP[c][d][a] = util.new_variable('GetSMsgP' + suffix, 'unit')