def find_features_in_bitstream(self, bitdata, verbose=False): frames = set(bitdata.keys()) tiles_checked = set() while len(frames) > 0: frame = frames.pop() # Skip frames that were emptied in a previous iteration. if not bitdata[frame]: continue # Iterate over all tiles that use this frame. for bits_info in self.segment_map.segment_info_for_frame(frame): # Don't examine a tile twice if bits_info.tile in tiles_checked: continue # Check if this frame has any data for the relevant tile. any_column = False for word_idx in range(bits_info.bits.words): if word_idx + bits_info.bits.offset in bitdata[frame][0]: any_column = True break if not any_column: continue tiles_checked.add(bits_info.tile) for fasm_line in self.find_features_in_tile(bits_info.tile, bits_info.bits, bitdata, verbose=verbose): yield fasm_line if len(bitdata[frame][1]) > 0 and verbose: # Some bits were not decoded, add warning and annotations to # FASM. yield fasm.FasmLine( set_feature=None, annotations=None, comment=" In frame 0x{:08x} {} bits were not converted.". format( frame, len(bitdata[frame][1]), )) for bit in bitdata[frame][1]: wordidx = bit // bitstream.WORD_SIZE_BITS bitidx = bit % bitstream.WORD_SIZE_BITS annotation = fasm.Annotation( 'unknown_bit', '{:08x}_{}_{}'.format(frame, wordidx, bitidx)) yield fasm.FasmLine( set_feature=None, annotations=[annotation], comment=None, )
def find_features_in_bitstream(self, bitdata, fmap=[], verbose=False): solved_bitdata = {} frames = set(bitdata.keys()) tiles_checked = set() emitted_features = set() while len(frames) > 0: frame = frames.pop() # Skip frames that were emptied in a previous iteration. if not bitdata[frame]: continue # Iterate over all tiles that use this frame. for bits_info in self.segment_map.segment_info_for_frame(frame): # Don't examine a tile twice if (bits_info.tile, bits_info.block_type) in tiles_checked: continue # Check if this frame has any data for the relevant tile. any_column = False for word_idx in range(bits_info.bits.words): if word_idx + bits_info.bits.offset in bitdata[frame][0]: any_column = True break if not any_column: continue tiles_checked.add((bits_info.tile, bits_info.block_type)) for fasm_line in self.find_features_in_tile( bits_info.tile, bits_info.block_type, bits_info.bits, solved_bitdata, bitdata, fmap=fmap, verbose=verbose): if fasm_line not in emitted_features: emitted_features.add(fasm_line) yield fasm_line remaining_bits = bitdata[frame][1] if frame in solved_bitdata: remaining_bits -= solved_bitdata[frame] if len(remaining_bits) > 0 and verbose: # Some bits were not decoded, add warning and annotations to # FASM. yield fasm.FasmLine( set_feature=None, annotations=None, comment=" In frame 0x{:08x} {} bits were not converted.". format( frame, len(remaining_bits), )) ff = dict() ff['bit'] = [] ff['bit'].append('bit_{:08x}_{}_{}'.format(frame, 0, 0)) ff['feature'] = 'unknown' fmap.append(ff)
def find_features_in_tile(self, tile_name, block_type, bits, solved_bitdata, bitdata, verbose=False): gridinfo = self.grid.gridinfo_at_tilename(tile_name) try: tile_segbits = self.grid.get_tile_segbits_at_tilename(tile_name) except KeyError as e: if not verbose: return if gridinfo.tile_type in self.decode_warnings: return comment = " WARNING: failed to load DB for tile type {}".format( gridinfo.tile_type) yield fasm.FasmLine( set_feature=None, annotations=None, comment=comment, ) yield fasm.FasmLine( set_feature=None, annotations=( fasm.Annotation('missing_segbits', gridinfo.tile_type), fasm.Annotation('exception', str(e)), ), comment=None, ) self.decode_warnings.add(gridinfo.tile_type) return for ones_matched, feature in tile_segbits.match_bitdata( block_type, bits, bitdata): for frame, bit in ones_matched: if frame not in solved_bitdata: solved_bitdata[frame] = set() solved_bitdata[frame].add(bit) yield mk_fasm(tile_name=tile_name, feature=feature)
def test_comment_file(self): result = list(fasm.parse_fasm_filename(example('comment.fasm'))) self.assertEqual(result, [ fasm.FasmLine( set_feature=None, annotations=None, comment=' Only a comment.', ) ]) check_round_trip(self, result)
def test_comment_file(self): for name, parser in parsers.items(): with self.subTest(name, parser=name): result = list( parser.parse_fasm_filename(example('comment.fasm'))) self.assertEqual(result, [ fasm.FasmLine( set_feature=None, annotations=None, comment=' Only a comment.', ) ]) check_round_trip(self, parser, result)
def test_one_line_feature(self): result = list(fasm.parse_fasm_filename(example('feature_only.fasm'))) self.assertEqual(result, [ fasm.FasmLine( set_feature=fasm.SetFasmFeature( feature='EXAMPLE_FEATURE.X0.Y0.BLAH', start=None, end=None, value=1, value_format=None, ), annotations=None, comment=None, ) ]) self.assertEqual(fasm.fasm_tuple_to_string(result), 'EXAMPLE_FEATURE.X0.Y0.BLAH\n') check_round_trip(self, result)
def process_fasm(db_root, part, fasm_file, canonical): database = db.Database(db_root, part) grid = database.grid() for fasm_line in fasm.parse_fasm_filename(fasm_file): if not fasm_line.set_feature: if not canonical: yield fasm_line for feature in fasm.canonical_features(fasm_line.set_feature): parts = feature.feature.split('.') tile = parts[0] gridinfo = grid.gridinfo_at_tilename(tile) tile_segbits = database.get_tile_segbits(gridinfo.tile_type) address = 0 if feature.start is not None: address = feature.start feature_name = '{}.{}'.format(gridinfo.tile_type, '.'.join(parts[1:])) # Convert feature to bits. If no bits are set, feature is # psuedo pip, and should not be output from canonical FASM. bits = tuple( tile_segbits.feature_to_bits(feature_name, address=address)) if len(bits) == 0 and canonical: continue # In canonical output, only output the canonical features. if canonical: yield fasm.FasmLine( set_feature=feature, annotations=None, comment=None, ) # If not in canonical mode, output original FASM line if not canonical: yield fasm_line
def mk_fasm(tile_name, feature): """ Convert matches tile and feature to FasmLine tuple. """ # Seperate addressing of multi-bit features: # TILE.ALUT[0] -> ('TILE', 'ALUT', '0') # TILE.ALUT.SMALL -> ('TILE', 'ALUT.SMALL', None) m = re.match(r'([A-Za-z0-9_]+).([^\[]+)(\[[0-9]+\])?', feature) tag_post = m.group(2) address = None if m.group(3) is not None: address = int(m.group(3)[1:-1]) feature = '{}.{}'.format(tile_name, tag_post) return fasm.FasmLine(set_feature=fasm.SetFasmFeature( feature=feature, start=address, end=None, value=1, value_format=None, ), annotations=None, comment=None)
def find_features_in_bitstream(self, bitdata, verbose=False): solved_bitdata = {} frames = set(bitdata.keys()) tiles_checked = set() emitted_features = set() while len(frames) > 0: frame = frames.pop() # Skip frames that were emptied in a previous iteration. if not bitdata[frame]: continue # Iterate over all tiles that use this frame. for bits_info in self.segment_map.segment_info_for_frame(frame): # Don't examine a tile twice if bits_info.tile in tiles_checked: continue # Check if this frame has any data for the relevant tile. any_column = False for word_idx in range(bits_info.bits.words): if word_idx + bits_info.bits.offset in bitdata[frame][0]: any_column = True break if not any_column: continue tiles_checked.add(bits_info.tile) for fasm_line in self.find_features_in_tile(bits_info.tile, bits_info.bits, solved_bitdata, bitdata, verbose=verbose): if fasm_line not in emitted_features: emitted_features.add(fasm_line) yield fasm_line remaining_bits = bitdata[frame][1] if frame in solved_bitdata: remaining_bits -= solved_bitdata[frame] if len(remaining_bits) > 0 and verbose: # Some bits were not decoded, add warning and annotations to # FASM. yield fasm.FasmLine( set_feature=None, annotations=None, comment=" In frame 0x{:08x} {} bits were not converted.". format( frame, len(remaining_bits), )) for bit in remaining_bits: frame_offset = frame % bitstream.FRAME_ALIGNMENT aligned_frame = frame - frame_offset wordidx = bit // bitstream.WORD_SIZE_BITS bitidx = bit % bitstream.WORD_SIZE_BITS annotations = [] annotations.append( fasm.Annotation( 'unknown_bit', '{:08x}_{}_{}'.format(frame, wordidx, bitidx))) annotations.append( fasm.Annotation('unknown_segment', '0x{:08x}'.format(aligned_frame))) annotations.append( fasm.Annotation( 'unknown_segbit', '{:02d}_{:02d}'.format(frame_offset, bit))) yield fasm.FasmLine( set_feature=None, annotations=annotations, comment=None, )
def find_features_in_tile(self, tile_name, block_type, bits, solved_bitdata, bitdata, fmap=None, verbose=False): gridinfo = self.grid.gridinfo_at_tilename(tile_name) try: tile_segbits = self.grid.get_tile_segbits_at_tilename(tile_name) except KeyError as e: if not verbose: return if gridinfo.tile_type in self.decode_warnings: return comment = " WARNING: failed to load DB for tile type {}".format( gridinfo.tile_type) yield fasm.FasmLine( set_feature=None, annotations=None, comment=comment, ) yield fasm.FasmLine( set_feature=None, annotations=( fasm.Annotation('missing_segbits', gridinfo.tile_type), fasm.Annotation('exception', str(e)), ), comment=None, ) self.decode_warnings.add(gridinfo.tile_type) return for ones_matched, feature in tile_segbits.match_bitdata( block_type, bits, bitdata): ff = dict() ff['bit'] = [] ff['seg'] = [] for frame, bit in ones_matched: if frame not in solved_bitdata: solved_bitdata[frame] = set() ff['bit'].append('bit_' + ('%08x' % frame) + '_' + ('%03d' % bits.offset) + '_' + str(bit - bits.offset * 32)) ff['seg'].append(('%02d' % (frame - bits.base_address)) + '_' + str(bit - bits.offset * 32)) solved_bitdata[frame].add(bit) ff['tile'] = tile_name ff['feature'] = feature fmap.append(ff) yield mk_fasm(tile_name=tile_name, feature=feature)