| """ 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 utils import bitstream | |
| from utils.grid_types import Bits | |
| from utils.tile_segbits import read_ppips | |
| 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 open(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 |