diff --git a/third_party/fasm b/third_party/fasm index 46eadd95..f78c27ec 160000 --- a/third_party/fasm +++ b/third_party/fasm @@ -1 +1 @@ -Subproject commit 46eadd95407381752160a62972ec256a97e03f3d +Subproject commit f78c27ecc34236df3cd4c845c13bdf279d30608c diff --git a/utils/bits2fasm.py b/utils/bits2fasm.py index 7b132036..c86169d1 100755 --- a/utils/bits2fasm.py +++ b/utils/bits2fasm.py @@ -9,15 +9,15 @@ from prjxray import db from prjxray import fasm_disassembler from prjxray import bitstream -def run(db_root, bits_file): +def run(db_root, bits_file, verbose, canonical): disassembler = fasm_disassembler.FasmDisassembler(db.Database(db_root)) with open(bits_file) as f: bitdata = bitstream.load_bitdata(f) - for fasm_line in disassembler.find_features_in_bitstream(bitdata): - for line in fasm.fasm_line_to_string(fasm_line): - print(line) + print(fasm.fasm_tuple_to_string( + disassembler.find_features_in_bitstream(bitdata, verbose=verbose), + canonical=canonical)) def main(): import argparse @@ -39,9 +39,11 @@ def main(): parser.add_argument('bits_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() - run(args.db_root, args.bits_file) + run(args.db_root, args.bits_file, args.verbose, args.canonical) if __name__ == '__main__': main() diff --git a/utils/fasm2fasm.py b/utils/fasm2fasm.py new file mode 100644 index 00000000..4b9f3139 --- /dev/null +++ b/utils/fasm2fasm.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +''' +Takes input FASM and outputs optionally canonical FASM. +''' + +import os +import fasm +from prjxray import db + +def process_fasm(db_root, fasm_file, canonical): + database = db.Database(db_root) + 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 run(db_root, fasm_file, canonical): + print(fasm.fasm_tuple_to_string( + process_fasm(db_root, fasm_file, canonical), + canonical=canonical)) + +def main(): + import argparse + + parser = argparse.ArgumentParser( + description='Read FASM file, check against database, and output optionally canonical 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) + + parser.add_argument( + '--db_root', help="Database root.", **db_root_kwargs) + parser.add_argument('fasm_file', help='Input FASM file') + parser.add_argument('--canonical', help='Output canonical bitstream.', + action='store_true') + args = parser.parse_args() + + run(args.db_root, args.fasm_file, args.canonical) + +if __name__ == '__main__': + main() +