Ejemplo n.º 1
0
def lookup_table_to_conditional_expression(lookup_table, input_variables):
    conditional_expression = []
    for input_values, output_value in lookup_table.items():
        if len(input_values) == 1:
            conditional = z3p.Eq(input_variables[0], input_values[0])
        elif len(input_values) == 0:
            assert len(lookup_table.values()) == 1
            return [(z3p.BoolVal(True), output_value)]
        else:
            conditional = z3p.And([
                z3p.Eq(var, val)
                for var, val in zip(input_variables, input_values)
            ])
        conditional_expression += [(conditional, output_value)]
    return conditional_expression
Ejemplo n.º 2
0
 def condition_to_resolve_deadlock(self, locations, memory, verbose=1):
     """Locations is a map from automaton to current location
     Memory can contain symbolic values.
     """
     if verbose > 0:
         print "Deadlock locations {}".format(locations)
     candidates = self.candidate_transitions(locations)
     if verbose > 0:
         print "Candidates are {}".format(candidates)
     if len(candidates) == 0:
         return z3p.BoolVal(False)
     else:
         return z3p.Or([z3p.And([a.transition_condition(edge[2]['name'], memory[a])
                                 for a, edge in candidate])
                        for candidate in candidates])
Ejemplo n.º 3
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)
Ejemplo n.º 4
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)))
Ejemplo n.º 5
0
def directory(d, num_caches=2, num_values=1, num_addresses=1):
    transitions = []
    variables = []
    variable_ranges = {}
    DataBlk = z3p.Int('DataBlk')
    ActiveId = z3p.Int('ActiveId')
    Sharers = {}
    for cache_id in range(num_caches):
        Sharers[cache_id] = z3p.Int('Sharers_{}'.format(cache_id))
    NumSharers = z3p.Int('NumSharers')
    Owner = z3p.Int('Owner')

    variable_ranges = {DataBlk: (0, num_values - 1),
                       ActiveId: (0, num_caches - 1),
                       NumSharers: (0, num_caches),
                       Owner: (0, num_caches - 1)}
    for cache_id in range(num_caches):
        variable_ranges[Sharers[cache_id]] = (0, 1)

    # Do i need numsharers

    variables = [DataBlk, ActiveId, NumSharers, Owner] + [Sharers[cache_id] for cache_id in range(num_caches)]

    initial_values = [ZERO, ZERO, ZERO, ZERO] + num_caches * [ZERO]

    locations = ['D_I', 'D_S', 'D_M', 'D_BUSY', 'D_DATA', 'D_PENDING_UNBLOCK_E', 'D_BUSY_DATA']

    # input messages
    input_channels = []
    for c in range(num_caches):
        for a in range(num_addresses):
            input_channels.extend([GetXMsgP[c][d][a], GetSMsgP[c][d][a], WBMsgP[c][d][a], UnblockSMsgP[c][d][a], UnblockEMsgP[c][d][a]])
            for other_c in range(num_caches):
                if other_c != c:
                    input_channels.append(DataMsgC2CP[c][other_c][d][a])

    output_channels = []
    # output messages
    for c in range(num_caches):
        for a in range(num_addresses):
            output_channels.extend([FwdGetXMsg[c][d][a], FwdGetSMsg[c][d][a], DataMsgD2C[c][d][a], WBAckMsg[c][d][a]])

    for c in range(num_caches):
        for a in range(num_addresses):
            # // Transitions from I
            #  D_I on GetXMsg'[c][d][a] { ActiveId := c; } ->
            #  send DataMsgD2C[c][d][a] (DataBlk, 0) -> D_BUSY;
            target = 'D_I2_{}'.format(c)
            transitions.append((None, 'D_I', GetXMsgP[c][d][a], TRUE, [(ActiveId, INT(c))], target))
            transitions.append((None, target, DataMsgD2C[c][d][a], [DataBlk, ZERO], TRUE, [], 'D_BUSY'))
            locations.append(target)
            #  D_I on GetSMsg'[c][d][a] { ActiveId := c; } ->
            #  send DataMsgD2C[c][d][a] (DataBlk, 0) -> D_BUSY;
            target = 'D_I3_{}'.format(c)
            transitions.append((None, 'D_I', GetSMsgP[c][d][a], TRUE, [(ActiveId, INT(c))], target))
            transitions.append((None, target, DataMsgD2C[c][d][a], [DataBlk, ZERO], TRUE, [], 'D_BUSY'))
            locations.append(target)
            #  // Transitions from S
            #  D_S on GetXMsg'[c][d][a] { ActiveId := c; } ->
            #  send DataMsgD2C[c][d][a] (DataBlk, NumSharers) {} ->
            #  foreach c2 in CacheIDType {
            #      if (Sharers[c2]) send FwdGetXMsg[c2][d][a] (c) {};
            #      if (not Sharers[c2]) pass {};
            #  } -> D_BUSY;
            target = 'D_S2_{}'.format(c)
            target2 = 'D_S3_{}'.format(c)
            transitions.append((None, 'D_S', GetXMsgP[c][d][a], TRUE, [(ActiveId, INT(c))], target))
            transitions.append((None, target, DataMsgD2C[c][d][a], [DataBlk, NumSharers - 1], z3p.Eq(Sharers[c], ONE), [], target2))
            transitions.append((None, target, DataMsgD2C[c][d][a], [DataBlk, NumSharers], z3p.Eq(Sharers[c], ZERO), [], target2))
            locations.extend([target, target2])

            last_state = 'D_S3_{}'.format(c)
            other_caches = [other_c for other_c in range(num_caches) if c != other_c]
            for i, other_c in enumerate(other_caches):
                if other_c != c:
                    if i + 1 == len(other_caches):
                        target = 'D_BUSY'
                    else:
                        target = 'D_S3_{}_{}'.format(c, other_c)
                    source = last_state
                    transitions.append((None, source, FwdGetXMsg[other_c][d][a], [z3p.IntVal(c)], z3p.Eq(Sharers[other_c], ONE), [], target))
                    transitions.append((None, source, z3p.Neq(Sharers[other_c], ONE), [], target))
                    locations.extend([target])
                    last_state = target

            #  D_S on GetSMsg'[c][d][a] { ActiveId := c; } ->
            #  send DataMsgD2C[c][d][a] (DataBlk, 0) {} -> D_BUSY;
            target = 'D_S4_{}'.format(c)
            transitions.append((None, 'D_S', GetSMsgP[c][d][a], TRUE, [(ActiveId, INT(c))], target))
            transitions.append((None, target, DataMsgD2C[c][d][a], [DataBlk, ZERO], TRUE, [], 'D_BUSY'))
            locations.append(target)
            #  // Transitions from M
            #  D_M on GetXMsg'[c][d][a] { ActiveId := c; } ->
            #  send FwdGetXMsg[Owner][d][a] (ActiveId) {} -> D_BUSY;
            target = 'D_M2_{}'.format(c)
            transitions.append((None, 'D_M', GetXMsgP[c][d][a], TRUE, [(ActiveId, INT(c))], target))
            for c2 in range(num_caches):
                transitions.append((None, target, FwdGetXMsg[c2][d][a], [ActiveId], z3p.Eq(INT(c2), Owner), [], 'D_BUSY'))
            locations.append(target)
            #  D_M on GetSMsg'[c][d][a] { ActiveId := c; } ->
            #  send FwdGetSMsg[Owner][d][a] (ActiveId) {} -> D_BUSY_DATA;
            target = 'D_M3_{}'.format(c)
            transitions.append((None, 'D_M', GetSMsgP[c][d][a], TRUE, [(ActiveId, INT(c))], target))
            for c2 in range(num_caches):
                transitions.append((None, target, FwdGetSMsg[c2][d][a], [ActiveId], z3p.Eq(INT(c2), Owner), [], 'D_BUSY_DATA'))
            locations.append(target)
            #  D_M on WBMsg'[c][d][a] (v) { DataBlk := v; Sharers[c] := false; } ->
            #  send WBAckMsg[c][d][a] {} -> D_I;
            target = 'D_M4_{}'.format(c)
            transitions.append((None, 'D_M', WBMsgP[c][d][a], z3p.Eq(Sharers[c], ONE), [(DataBlk, WBMsgP[c][d][a]), (Sharers[c], ZERO), (NumSharers, NumSharers - 1)], target))
            # debug
            transitions.append((None, 'D_M', WBMsgP[c][d][a], z3p.Neq(Sharers[c], ONE), [(DataBlk, WBMsgP[c][d][a])], target))

            transitions.append((None, target, WBAckMsg[c][d][a], [ZERO], TRUE, [(ActiveId, ZERO)], 'D_I'))
            locations.append(target)
            #  // Transitions from BUSY
            #  D_BUSY on WBMsg'[c][d][a] (v)
            #  if (= c ActiveId) { DataBlk := v; } -> D_PENDING_UNBLOCK_E;
            #  if (!= c ActiveId) { Sharers[c] := false; DataBlk := v; } ->
            #  send DataMsgD2C[ActiveId][d][a] (DataBlk, 0) -> D_BUSY;
            transitions.append((None, 'D_BUSY', WBMsgP[c][d][a], z3p.Eq(INT(c), ActiveId), [(DataBlk, WBMsgP[c][d][a])], 'D_PENDING_UNBLOCK_E'))
            target = 'D_BUSY2_{}'.format(c)
            transitions.append((None, 'D_BUSY', WBMsgP[c][d][a], z3p.And(z3p.Neq(INT(c), ActiveId), z3p.Eq(Sharers[c], ONE)), [(Sharers[c], ZERO), (NumSharers, NumSharers - 1), (DataBlk, WBMsgP[c][d][a])], target))
            # debug
            transitions.append((None, 'D_BUSY', WBMsgP[c][d][a], z3p.And(z3p.Neq(INT(c), ActiveId), z3p.Eq(Sharers[c], ZERO)), [(DataBlk, WBMsgP[c][d][a])], target))
            for c2 in range(num_caches):
                transitions.append((None, target, DataMsgD2C[c2][d][a], [DataBlk, ONE], z3p.Eq(INT(c2), ActiveId), [], 'D_BUSY'))
            locations.append(target)
            #  D_BUSY on UnblockEMsg'[c][d][a] { Sharers[c] := true; Owner := c; } -> D_M;
            transitions.append((None, 'D_BUSY', UnblockEMsgP[c][d][a], TRUE, [(Sharers[c], ONE), (NumSharers, ONE), (Owner, INT(c)), (ActiveId, ZERO)] + [(Sharers[other_c], ZERO) for other_c in range(num_caches) if other_c != c], 'D_M'))
            #  D_BUSY on UnblockSMsg'[c][d][a] { Sharers[c] := true; Owner := undef; } -> D_S;
            transitions.append((None, 'D_BUSY', UnblockSMsgP[c][d][a], z3p.Eq(Sharers[c], ZERO), [(Sharers[c], ONE), (NumSharers, NumSharers + 1), (Owner, ZERO), (ActiveId, ZERO)], 'D_S'))
            # debug
            transitions.append((None, 'D_BUSY', UnblockSMsgP[c][d][a], z3p.Eq(Sharers[c], ONE), [(Owner, ZERO), (ActiveId, ZERO)], 'D_S'))

            #  foreach c2 in CacheIDType (!= c2 c) {
            #      D_BUSY on DataMsgC2C'[c2][c][d][a] (v) { DataBlk := v; } -> S;
            #  }
            for c2 in range(num_caches):
                if c2 != c:
                    transitions.append((None, 'D_BUSY', DataMsgC2CP[c2][c][d][a], TRUE, [(DataBlk, DataMsgC2CP[c2][c][d][a]), (ActiveId, ZERO)], 'D_S'))
            #  // Transitions from BUSY_DATA
            #  D_BUSY_DATA on UnblockSMsg'[c][d][a] { Sharers[c] := true; } -> D_BUSY;
            #  foreach c2 in CacheIDType (!= c2 c) {
            #      D_BUSY_DATA on DataMsgC2C'[c2][c][d][a] (v) { DataBlk := v; } -> D_BUSY;
            #  }
            transitions.append((None, 'D_BUSY_DATA', UnblockSMsgP[c][d][a], z3p.Eq(Sharers[c], ZERO), [(Sharers[c], ONE), (NumSharers, NumSharers + 1)], 'D_BUSY'))
            # debug
            transitions.append((None, 'D_BUSY_DATA', UnblockSMsgP[c][d][a], z3p.Eq(Sharers[c], ONE), [], 'D_BUSY'))

            for c2 in range(num_caches):
                if c2 != c:
                    transitions.append((None, 'D_BUSY_DATA', DataMsgC2CP[c2][c][d][a], TRUE, [(DataBlk, DataMsgC2CP[c2][c][d][a])], 'D_BUSY'))
            #  D_BUSY_DATA on WBMsg'[c][d][a] (v)
            #  if (= c ActiveId) { DataBlk := v; } -> D_PENDING_UNBLOCK_E;
            #  if (!= c ActiveId) { Sharers[c] := false; DataBlk := v; } ->
            #  send DataMsgD2C[ActiveId][d][a] (DataBlk, 0) -> D_BUSY;
            transitions.append((None, 'D_BUSY_DATA', WBMsgP[c][d][a], z3p.Eq(z3p.IntVal(c), ActiveId), [(DataBlk, WBMsgP[c][d][a])], 'D_PENDING_UNBLOCK_E'))
            target = 'D_BUSY2_{}'.format(c)
            transitions.append((None, 'D_BUSY_DATA', WBMsgP[c][d][a], z3p.And(z3p.Neq(z3p.IntVal(c), ActiveId), z3p.Eq(Sharers[c], ONE)), [(Sharers[c], ZERO), (NumSharers, NumSharers - 1), (DataBlk, WBMsgP[c][d][a])], target))
            # debug
            transitions.append((None, 'D_BUSY_DATA', WBMsgP[c][d][a], z3p.And(z3p.Neq(z3p.IntVal(c), ActiveId), z3p.Eq(Sharers[c], ZERO)), [(DataBlk, WBMsgP[c][d][a])], target))

            # for c2 in range(num_caches):
            #     transitions.append((None, 'D_BUSY_DATA2', DataMsgD2C[c2][a], [DataBlk, ZERO], z3p.Eq(z3p.IntVal(c2), ActiveId), [], 'D_BUSY'))
            #  // Transitions from PENDING_UNBLOCK_E
            #  D_PENDING_UNBLOCK_E on UnblockEMsg'[c][d][a] { Sharers[c] := false; Owner := undef; } -> D_I;
            target = 'D_PENDING_UNBLOCK_E_{}'.format(c)
            transitions.append((None, 'D_PENDING_UNBLOCK_E', UnblockEMsgP[c][d][a], z3p.Eq(Sharers[c], ONE), [(Sharers[c], ZERO), (Owner, ZERO), (NumSharers, NumSharers - 1)], target))
            #debug
            transitions.append((None, 'D_PENDING_UNBLOCK_E', UnblockEMsgP[c][d][a], z3p.Eq(Sharers[c], ZERO), [], target))

            transitions.append((None, target, WBAckMsg[c][d][a], [ZERO], TRUE, [], 'D_I'))
            locations.append(target)

    return automaton.SymbolicAutomaton('directory',
                                       locations,
                                       'D_I',
                                       transitions,
                                       variables=variables,
                                       initial_values=initial_values,
                                       input_channels=input_channels,
                                       output_channels=output_channels,
                                       variable_ranges=variable_ranges)
Ejemplo n.º 6
0
def lossless_non_duplicating_blocking_unordered_channel(
        name, inputs, outputs, data_ranges, port_number_of_fields, capacity):
    variables = []
    initial_values = []
    variable_ranges = {}
    counters = []
    print inputs
    print outputs
    for input in inputs:
        input_name = input.decl().name()
        input_counter = z3p.Int(input_name + '_counter')
        variables.append(input_counter)
        initial_values.append(ZERO)
        variable_ranges[input_counter] = (0, capacity)
        counters.append(input_counter)
        # if the type of the port is unit then all we need is the counter
        if not isinstance(input, z3p.ArrayRef):
            if input in data_ranges:
                for i in range(capacity):
                    variable = z3p.Int('{}_cell{}'.format(
                        input.decl().name(), i))
                    variables.append(variable)
                    initial_values.append(ZERO)
                    variable_ranges[variable] = data_ranges[input]
        else:
            for i in range(capacity):
                for j in range(port_number_of_fields[input]):
                    variable = z3p.Int('{}_field_{}_cell{}'.format(
                        input.decl().name(), j, i))
                    variables.append(variable)
                    initial_values.append(ZERO)
                    variable_ranges[variable] = data_ranges[input[j]]

    locations = ['initial']
    transitions = []

    for input, output in zip(inputs, outputs):
        input_name = input.decl().name()
        output_name = output.decl().name()
        input_counter = z3p.Int(input_name + '_counter')
        for i in range(capacity):
            updates = []
            if not isinstance(input, z3p.ArrayRef):
                if input in data_ranges:
                    variable = z3p.Int('{}_cell{}'.format(
                        input.decl().name(), i))
                    updates.append((variable, input))
            else:
                for j in range(port_number_of_fields[input]):
                    variable = z3p.Int('{}_field_{}_cell{}'.format(
                        input.decl().name(), j, i))
                    updates.append((variable, input[j]))
            last = counters[0]
            for counter in counters[1:]:
                last = z3p.Sum(last, counter)
            counters_sum = last
            transitions.append(
                ('t_{}'.format(input_name), 'initial', input,
                 z3p.And(counters_sum < z3p.IntVal(capacity),
                         z3p.Eq(input_counter, i)),
                 [(input_counter, input_counter + 1)] + updates, 'initial'))
            if i > 0:
                updates = []
                channel_outputs = []
                if not isinstance(input, z3p.ArrayRef):
                    if input in data_ranges:
                        variable = z3p.Int('{}_cell{}'.format(
                            input.decl().name(), i))
                        channel_outputs.append(variable)
                        updates.append((variable, ZERO))
                    else:
                        channel_outputs.append(ZERO)
                else:
                    for j in range(port_number_of_fields[input]):
                        variable = z3p.Int('{}_field_{}_cell{}'.format(
                            input.decl().name(), j, i))
                        channel_outputs.append(variable)
                        updates.append((variable, ZERO))

                transitions.append(
                    ('t_{}'.format(output_name), 'initial', output,
                     channel_outputs, z3p.Eq(input_counter, z3p.IntVal(i)),
                     [(input_counter, input_counter - 1)] + updates,
                     'initial'))
    return automaton.SymbolicAutomaton('{}_channel'.format(name),
                                       locations,
                                       'initial',
                                       transitions,
                                       variables=variables,
                                       initial_values=initial_values,
                                       input_channels=inputs,
                                       output_channels=outputs,
                                       variable_ranges=variable_ranges)