Source code for pacman.operations.routing_info_allocator_algorithms.malloc_based_routing_allocator.utils
# 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/>.
import itertools
from six.moves import reduce, xrange
[docs]def get_possible_masks(n_keys, mask_width=32, contiguous_keys=True):
""" Get the possible masks given the number of keys.
:param n_keys: The number of keys to generate a mask for
:type n_keys: int
:param mask_width: \
Number of bits that are meaningful in the mask. 32 by default.
:param mask_width: int
:param contiguous_keys: \
True if the mask should only have zeros in the LSBs
:return: A generator of all possible masks
:rtype: iterable(int)
"""
# Starting values
n_zeros = (n_keys - 1).bit_length()
assert n_zeros <= mask_width
all_ones_mask = (1 << mask_width) - 1
# Get all possible places where the zero bits could be put; this is an
# ideal way to do it too, as it gives us the one with the bits at the
# bottom (the old generation algorithm) first.
places_for_zeroes = itertools.combinations(xrange(mask_width), n_zeros)
# If the keys are all contiguous, you can only have one possible mask,
# which is the first one
if contiguous_keys:
zero_bits = next(places_for_zeroes)
return [zero_out_bits(all_ones_mask, zero_bits)]
# Convert the selected places for zero bits into an iterable of masks
return (
zero_out_bits(all_ones_mask, zero_bits)
for zero_bits in places_for_zeroes)
[docs]def zero_out_bits(all_ones_mask, bits_to_zero):
""" Takes a mask (with all interesting bits set to 1) and zeroes out the\
bits at the given indices.
:param all_ones_mask: Initial mask
:type all_ones_mask: int
:param bits_to_zero: Which bits to clear. The LSB is zero.
:type bits_to_zero: iterable(int)
:return: A single mask, with zeroes in all required places
:rtype: int
"""
return reduce(
(lambda mask, bit_to_zero_out: mask & ~(1 << bit_to_zero_out)),
bits_to_zero, all_ones_mask)