| #!/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() |