#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Copyright (C) 2017-2020 The Project X-Ray Authors. # # Use of this source code is governed by a ISC-style # license that can be found in the LICENSE file or at # https://opensource.org/licenses/ISC # # SPDX-License-Identifier: ISC """ TileSegbitsAlias provides an alias from one tile type to another. TileSegbitsAlias performs severals functions to achieve the alias: - Remaps tile type from the original tile type to the alias tile type - Offsets the bits from the original to the alias type - Renames sites from the original to the alias type - Filters bits outside of the alias. """ from prjxray import bitstream from prjxray.grid_types import Bits from prjxray.tile_segbits import read_ppips from prjxray.util import OpenSafeFile class TileSegbitsAlias(object): def __init__(self, db, tile_type, bits_map): # Name of tile_type that is using the alias self.tile_type = tile_type # Name of aliased tile_type self.alias_tile_type = None # BlockType -> BitAlias map self.alias = {} self.bits_map = bits_map # BlockType -> aliased Bits map self.alias_bits_map = {} # aliased site name to site name map self.sites_rev_map = {} for block_type in bits_map: self.alias[block_type] = bits_map[block_type].alias self.alias_bits_map[block_type] = Bits( base_address=bits_map[block_type].base_address, frames=bits_map[block_type].frames, offset=bits_map[block_type].offset - self.alias[block_type].start_offset, words=bits_map[block_type].words, alias=None, ) if self.alias_tile_type is None: self.alias_tile_type = self.alias[block_type].tile_type else: assert self.alias_tile_type == self.alias[block_type].tile_type self.sites_rev_map[block_type] = {} for site, alias_site in self.alias[block_type].sites.items(): assert alias_site not in self.sites_rev_map[block_type] self.sites_rev_map[block_type][alias_site] = site tile_db = db.tile_types[self.tile_type] self.ppips = {} if tile_db.ppips is not None: with OpenSafeFile(tile_db.ppips) as f: self.ppips = read_ppips(f) self.tile_segbits = db.get_tile_segbits(self.alias_tile_type) def map_feature_to_segbits(self, feature): """ Map from the output feature name to the aliased feature name. """ parts = feature.split('.') assert parts[0] == self.tile_type parts[0] = self.alias_tile_type for block_type in self.alias: if len(parts) > 1 and parts[1] in self.alias[block_type].sites: parts[1] = self.alias[block_type].sites[parts[1]] return '.'.join(parts) def map_feature_from_segbits(self, feature): """ Map from the aliases feature name to the output feature name. """ parts = feature.split('.') assert parts[0] == self.alias_tile_type parts[0] = self.tile_type for block_type in self.alias: if len(parts) > 1 and parts[1] in self.sites_rev_map[block_type]: parts[1] = self.sites_rev_map[block_type][parts[1]] return '.'.join(parts) def match_filter(self, block_type, query_bit): word = query_bit.word_bit // bitstream.WORD_SIZE_BITS real_word = word - self.alias[block_type].start_offset if real_word < 0 or real_word >= self.bits_map[block_type].words: return False return True def match_bitdata(self, block_type, bits, bitdata): alias_bits = self.alias_bits_map[block_type] for bits_found, alias_feature in self.tile_segbits.match_bitdata( block_type, alias_bits, bitdata, match_filter=self.match_filter): feature = self.map_feature_from_segbits(alias_feature) yield (bits_found, feature) def feature_to_bits(self, bits_map, feature, address=0): if feature in self.ppips: return alias_feature = self.map_feature_to_segbits(feature) for block_type, bit in self.tile_segbits.feature_to_bits( self.alias_bits_map, alias_feature, address): yield block_type, bit