|  | #!/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 | 
|  | ''' | 
|  | Take bitstream .bit files and decode them to FASM. | 
|  | ''' | 
|  |  | 
|  | import contextlib | 
|  | import os | 
|  | import fasm | 
|  | import fasm.output | 
|  | from prjxray import fasm_disassembler | 
|  | from prjxray import bitstream | 
|  | from prjxray.db import Database | 
|  | from prjxray.util import OpenSafeFile | 
|  | import subprocess | 
|  | import tempfile | 
|  |  | 
|  |  | 
|  | def bit_to_bits(bitread, part_yaml, bit_file, bits_file, frame_range=None): | 
|  | """ Calls bitread to create bits (ASCII) from bit file (binary) """ | 
|  | if frame_range: | 
|  | frame_range_arg = '-F {}'.format(frame_range) | 
|  | else: | 
|  | frame_range_arg = '' | 
|  |  | 
|  | subprocess.check_output( | 
|  | '{} --part_file {} {} -o {} -z -y {}'.format( | 
|  | bitread, part_yaml, frame_range_arg, bits_file, bit_file), | 
|  | shell=True) | 
|  |  | 
|  |  | 
|  | def bits_to_fasm(db_root, part, bits_file, verbose, canonical): | 
|  | db = Database(db_root, part) | 
|  | grid = db.grid() | 
|  | disassembler = fasm_disassembler.FasmDisassembler(db) | 
|  |  | 
|  | with OpenSafeFile(bits_file) as f: | 
|  | bitdata = bitstream.load_bitdata(f) | 
|  |  | 
|  | model = fasm.output.merge_and_sort( | 
|  | disassembler.find_features_in_bitstream(bitdata, verbose=verbose), | 
|  | zero_function=disassembler.is_zero_feature, | 
|  | sort_key=grid.tile_key, | 
|  | ) | 
|  |  | 
|  | print(fasm.fasm_tuple_to_string(model, canonical=canonical), end='') | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | import argparse | 
|  |  | 
|  | parser = argparse.ArgumentParser( | 
|  | description='Convert 7-series bit file to FASM.') | 
|  |  | 
|  | database_dir = os.getenv("XRAY_DATABASE_DIR") | 
|  | database = os.getenv("XRAY_DATABASE") | 
|  | db_root_kwargs = {} | 
|  | if database_dir is None or database is None: | 
|  | db_root_kwargs['required'] = True | 
|  | else: | 
|  | db_root_kwargs['required'] = False | 
|  | db_root_kwargs['default'] = os.path.join(database_dir, database) | 
|  |  | 
|  | default_part = os.getenv("XRAY_PART") | 
|  | part_kwargs = {} | 
|  | if default_part is None: | 
|  | part_kwargs['required'] = True | 
|  | else: | 
|  | part_kwargs['required'] = False | 
|  | part_kwargs['default'] = default_part | 
|  |  | 
|  | if os.getenv("XRAY_TOOLS_DIR") is None: | 
|  | default_bitread = 'bitread' | 
|  | else: | 
|  | default_bitread = os.path.join(os.getenv("XRAY_TOOLS_DIR"), 'bitread') | 
|  |  | 
|  | parser.add_argument('--db-root', help="Database root.", **db_root_kwargs) | 
|  | parser.add_argument( | 
|  | '--bits-file', | 
|  | help="Output filename for bitread output, default is deleted tempfile.", | 
|  | default=None) | 
|  | parser.add_argument( | 
|  | '--part', help="Name of part being targetted.", **part_kwargs) | 
|  | parser.add_argument( | 
|  | '--bitread', | 
|  | help="bitread tool to to use", | 
|  | default=default_bitread) | 
|  | parser.add_argument( | 
|  | '--frame_range', help="Frame range to use with bitread.") | 
|  | parser.add_argument('bit_file', help='') | 
|  | parser.add_argument( | 
|  | '--verbose', | 
|  | help='Print lines for unknown tiles and bits', | 
|  | action='store_true') | 
|  | parser.add_argument( | 
|  | '--canonical', help='Output canonical bitstream.', action='store_true') | 
|  | args = parser.parse_args() | 
|  |  | 
|  | with contextlib.ExitStack() as stack: | 
|  | if args.bits_file: | 
|  | bits_file = stack.enter_context(open(args.bits_file, 'wb')) | 
|  | else: | 
|  | bits_file = stack.enter_context(tempfile.NamedTemporaryFile()) | 
|  |  | 
|  | bit_to_bits( | 
|  | bitread=args.bitread, | 
|  | part_yaml=os.path.join(args.db_root, args.part, "part.yaml"), | 
|  | bit_file=args.bit_file, | 
|  | bits_file=bits_file.name, | 
|  | frame_range=args.frame_range, | 
|  | ) | 
|  |  | 
|  | bits_to_fasm( | 
|  | args.db_root, args.part, bits_file.name, args.verbose, | 
|  | args.canonical) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | main() |