| from collections import namedtuple |
| from utils import bitstream |
| from utils.grid import BlockType |
| import enum |
| import functools |
| |
| |
| class PsuedoPipType(enum.Enum): |
| ALWAYS = 'always' |
| DEFAULT = 'default' |
| HINT = 'hint' |
| |
| |
| def read_ppips(f): |
| ppips = {} |
| |
| for l in f: |
| l = l.strip() |
| if not l: |
| continue |
| |
| feature, ppip_type = l.split(' ') |
| |
| ppips[feature] = PsuedoPipType(ppip_type) |
| |
| return ppips |
| |
| |
| Bit = namedtuple('Bit', 'word_column word_bit isset') |
| |
| |
| def parsebit(val): |
| '''Return "!012_23" => (12, 23, False)''' |
| isset = True |
| # Default is 0. Skip explicit call outs |
| if val[0] == '!': |
| isset = False |
| val = val[1:] |
| # 28_05 => 28, 05 |
| seg_word_column, word_bit_n = val.split('_') |
| |
| return Bit( |
| word_column=int(seg_word_column), |
| word_bit=int(word_bit_n), |
| isset=isset, |
| ) |
| |
| |
| def read_segbits(f): |
| segbits = {} |
| |
| for l in f: |
| # CLBLM_L.SLICEL_X1.ALUT.INIT[10] 29_14 |
| l = l.strip() |
| |
| if not l: |
| continue |
| |
| parts = l.split(' ') |
| |
| assert len(parts) > 1 |
| |
| segbits[parts[0]] = [parsebit(val) for val in parts[1:]] |
| |
| return segbits |
| |
| |
| class TileSegbits(object): |
| def __init__(self, tile_db): |
| self.segbits = {} |
| self.ppips = {} |
| self.feature_addresses = {} |
| |
| if tile_db.ppips is not None: |
| with open(tile_db.ppips) as f: |
| self.ppips = read_ppips(f) |
| |
| if tile_db.segbits is not None: |
| with open(tile_db.segbits) as f: |
| self.segbits[BlockType.CLB_IO_CLK] = read_segbits(f) |
| |
| if tile_db.block_ram_segbits is not None: |
| with open(tile_db.block_ram_segbits) as f: |
| self.segbits[BlockType.BLOCK_RAM] = read_segbits(f) |
| |
| for block_type in self.segbits: |
| for feature in self.segbits[block_type]: |
| sidx = feature.rfind('[') |
| eidx = feature.rfind(']') |
| |
| if sidx != -1: |
| assert eidx != -1 |
| |
| base_feature = feature[:sidx] |
| |
| if base_feature not in self.feature_addresses: |
| self.feature_addresses[base_feature] = {} |
| |
| self.feature_addresses[base_feature][int( |
| feature[sidx + 1:eidx])] = (block_type, feature) |
| |
| def match_bitdata(self, block_type, bits, bitdata, match_filter=None): |
| """ Return matching features for tile bits data (grid.Bits) and bitdata. |
| |
| See bitstream.load_bitdata for details on bitdata structure. |
| |
| """ |
| |
| if block_type not in self.segbits: |
| return |
| |
| for feature, segbit in self.segbits[block_type].items(): |
| match = True |
| skip = False |
| for query_bit in segbit: |
| if match_filter is not None and not match_filter(block_type, |
| query_bit): |
| skip = True |
| break |
| |
| frame = bits.base_address + query_bit.word_column |
| bitidx = bits.offset * bitstream.WORD_SIZE_BITS + query_bit.word_bit |
| |
| if frame not in bitdata: |
| match = not query_bit.isset |
| if match: |
| continue |
| else: |
| break |
| |
| found_bit = bitidx in bitdata[frame][1] |
| match = found_bit == query_bit.isset |
| |
| if not match: |
| break |
| |
| if not match or skip: |
| continue |
| |
| def inner(): |
| for query_bit in segbit: |
| if query_bit.isset: |
| frame = bits.base_address + query_bit.word_column |
| bitidx = bits.offset * bitstream.WORD_SIZE_BITS + query_bit.word_bit |
| yield (frame, bitidx) |
| |
| yield (tuple(inner()), feature) |
| |
| def map_bit_to_frame(self, block_type, bits, bit): |
| """ Convert bit from segbit to frame data. """ |
| return Bit( |
| word_column=bits.base_address + bit.word_column, |
| word_bit=bits.offset * bitstream.WORD_SIZE_BITS + bit.word_bit, |
| isset=bit.isset, |
| ) |
| |
| def feature_to_bits(self, bits_map, feature, address=0): |
| if feature in self.ppips: |
| return |
| |
| for block_type in self.segbits: |
| if address == 0 and feature in self.segbits[block_type]: |
| for bit in self.segbits[block_type][feature]: |
| yield block_type, self.map_bit_to_frame( |
| block_type, bits_map[block_type], bit) |
| return |
| |
| block_type, feature = self.feature_addresses[feature][address] |
| for bit in self.segbits[block_type][feature]: |
| yield block_type, self.map_bit_to_frame( |
| block_type, bits_map[block_type], bit) |