blob: 2eb536e333f8bc7a13dba81b146639c0b4511f89 [file] [log] [blame]
#!/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