| #!/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 | 
 | """ Generates a missing feature/bit report for LiteX design. | 
 |  | 
 | This script is fairly fragile, because it depends on the specific observation | 
 | that all of the remaining bits appear to either belong to HCLK_IOI or IOI3 | 
 | tiles.  A more general version of this script could be created, but that was | 
 | not the point of this script. | 
 |  | 
 | """ | 
 | from fasm import parse_fasm_filename | 
 |  | 
 |  | 
 | def main(): | 
 |     fasm_file = 'top.fasm' | 
 |     fasm_model = list(parse_fasm_filename(fasm_file)) | 
 |  | 
 |     unknown_bits = { | 
 |         'HCLK_IOI': {}, | 
 |         'IOI3': {}, | 
 |     } | 
 |  | 
 |     total_unknown = 0 | 
 |     for l in fasm_model: | 
 |         if l.annotations is None: | 
 |             continue | 
 |  | 
 |         annotations = {} | 
 |         for annotation in l.annotations: | 
 |             annotations[annotation.name] = annotation.value | 
 |  | 
 |         if 'unknown_bit' not in annotations: | 
 |             continue | 
 |  | 
 |         total_unknown += 1 | 
 |  | 
 |         frame, word, bit = annotations['unknown_bit'].split('_') | 
 |  | 
 |         frame = int(frame, 16) | 
 |         word = int(word) | 
 |         bit = int(bit) | 
 |  | 
 |         frame_offset = frame % 0x80 | 
 |         base_frame = frame - frame_offset | 
 |  | 
 |         # All remaining LiteX bits appear to be in this one IO bank, so limit | 
 |         # the tool this this one IO bank. | 
 |         assert base_frame == 0x00401580, hex(frame) | 
 |  | 
 |         SIZE = 4 | 
 |         INITIAL_OFFSET = -2 | 
 |  | 
 |         if word == 50: | 
 |             group = 'HCLK_IOI' | 
 |             offset = 45 | 
 |         elif word < 50: | 
 |             group = 'IOI3' | 
 |             offset = ((word - INITIAL_OFFSET) // SIZE) * SIZE + INITIAL_OFFSET | 
 |         else: | 
 |             group = 'IOI3' | 
 |             word -= 1 | 
 |             offset = ((word - INITIAL_OFFSET) // SIZE) * SIZE + INITIAL_OFFSET | 
 |             offset += 1 | 
 |             word += 1 | 
 |  | 
 |         bit = '{}_{:02d}'.format( | 
 |             frame_offset, | 
 |             (word - offset) * 32 + bit, | 
 |         ) | 
 |  | 
 |         if bit not in unknown_bits[group]: | 
 |             unknown_bits[group][bit] = 0 | 
 |         unknown_bits[group][bit] += 1 | 
 |  | 
 |     print('Total unknown bits: {}'.format(total_unknown)) | 
 |     for group in unknown_bits: | 
 |         print('Group {} (count = {}):'.format(group, len(unknown_bits[group]))) | 
 |         for bit in sorted(unknown_bits[group]): | 
 |             print('  {} (count = {})'.format(bit, unknown_bits[group][bit])) | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     main() |