Source code for pacman.utilities.algorithm_utilities.field_based_system_utilities
# Copyright (c) 2017-2019 The University of Manchester
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from enum import Enum
from pacman.model.constraints.key_allocator_constraints import (
ContiguousKeyRangeContraint, FixedKeyFieldConstraint,
FixedKeyAndMaskConstraint, FixedMaskConstraint, FlexiKeyFieldConstraint)
from pacman.exceptions import PacmanConfigurationException
from pacman.utilities import utility_calls
from pacman.utilities.utility_objs import Field
from pacman.utilities.utility_objs.flexi_field import SUPPORTED_TAGS
NUM_BITS_IN_ROUTING = 31
ROUTING_MASK_BIT = 1
START_OF_ROUTING_KEY_POSITION = 0
[docs]class TYPES_OF_FIELDS(Enum):
FIXED_MASK = 0
FIXED_KEY = 1
FIXED_FIELD = 2
[docs]def deduce_types(graph):
""" Deducing the number of applications required for this key space.
:param graph:
"""
seen_fields = dict()
known_fields = list()
for partition in graph.outgoing_edge_partitions:
for constraint in partition.constraints:
if isinstance(constraint, ContiguousKeyRangeContraint):
continue
if isinstance(constraint, FlexiKeyFieldConstraint):
handle_flexi_field(constraint, seen_fields, known_fields)
if isinstance(constraint, FixedKeyAndMaskConstraint):
if TYPES_OF_FIELDS.FIXED_KEY.name not in seen_fields:
seen_fields[TYPES_OF_FIELDS.FIXED_KEY.name] = list()
seen_fields[TYPES_OF_FIELDS.FIXED_KEY.name].extend(
constraint.keys_and_masks)
if isinstance(constraint, FixedMaskConstraint):
fields = convert_mask_into_fields(constraint.mask)
if TYPES_OF_FIELDS.FIXED_MASK.name not in seen_fields:
seen_fields[TYPES_OF_FIELDS.FIXED_MASK.name] = dict()
for field in fields:
if field.value not in seen_fields[
TYPES_OF_FIELDS.FIXED_MASK.name]:
# add a new list for this mask type
seen_fields[TYPES_OF_FIELDS.FIXED_MASK.name][
field.value] = list()
if field not in seen_fields[
TYPES_OF_FIELDS.FIXED_MASK.name][field.value]:
seen_fields[TYPES_OF_FIELDS.FIXED_MASK.name][
field.value].append(field)
if isinstance(constraint, FixedKeyFieldConstraint):
if TYPES_OF_FIELDS.FIXED_FIELD not in seen_fields:
seen_fields[TYPES_OF_FIELDS.FIXED_FIELD.name] = list()
seen_fields[TYPES_OF_FIELDS.FIXED_FIELD.name].append(
constraint.fields)
return seen_fields
[docs]def handle_flexi_field(constraint, seen_fields, known_fields):
"""
:param constraint:
:param seen_fields:
:param known_fields:
:rtype: None:
"""
# set the level of search
current_level = seen_fields
for constraint_field in constraint.fields:
found_field = None
# try to locate field in level
for seen_field in current_level:
if constraint_field.name == seen_field:
found_field = seen_field
# seen the field before but not at this level. error
if found_field is None and constraint_field in known_fields:
raise PacmanConfigurationException(
"Can't find the field {} in the expected position".format(
constraint_field))
# if not seen the field before
if found_field is None and constraint_field.name not in known_fields:
next_level = dict()
instance_level = dict()
current_level[constraint_field.name] = instance_level
instance_level[constraint_field] = next_level
known_fields.append(constraint_field.name)
current_level = next_level
# if found a field, check if its instance has indeed been put in
# before
if found_field is not None:
instances = current_level[constraint_field.name]
if constraint_field in instances:
current_level = instances[constraint_field]
elif constraint_field.value not in instances:
next_level = dict()
instance_level = dict()
instances[constraint_field] = instance_level
instances[constraint_field] = next_level
current_level = next_level
[docs]def convert_mask_into_fields(entity):
"""
:param entity:
"""
results = list()
expanded_mask = utility_calls.expand_to_bit_array(entity)
# set up for first location
detected_change_position = NUM_BITS_IN_ROUTING
detected_last_state = expanded_mask[NUM_BITS_IN_ROUTING]
# iterate up the key looking for fields
for position in range(NUM_BITS_IN_ROUTING - 1,
START_OF_ROUTING_KEY_POSITION - 2, -1):
# check for last bit iteration
if position == -1:
# if last bit has changed, create new field
if detected_change_position != position:
# create field with correct routing tag
if detected_last_state == ROUTING_MASK_BIT:
tag = SUPPORTED_TAGS.ROUTING
else:
tag = SUPPORTED_TAGS.APPLICATION
results.append(Field(
NUM_BITS_IN_ROUTING - detected_change_position,
NUM_BITS_IN_ROUTING, entity, tag.name))
else:
# check for bit iteration
if expanded_mask[position] != detected_last_state:
# if changed state, a field needs to be created. check for
# which type of field to support
if detected_last_state == ROUTING_MASK_BIT:
tag = SUPPORTED_TAGS.ROUTING
else:
tag = SUPPORTED_TAGS.APPLICATION
results.append(Field(
NUM_BITS_IN_ROUTING - detected_change_position,
NUM_BITS_IN_ROUTING - (position + 1), entity, tag.name))
# update positions
detected_last_state = expanded_mask[position]
detected_change_position = position
return results