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