| #!/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 |
| import sys |
| import glob |
| import os |
| import re |
| import difflib |
| |
| |
| def get_file_pairs(): |
| pairs_list = list() |
| for path1 in glob.glob('*.bits'): |
| for path2 in glob.glob('*.bits'): |
| file1 = os.path.basename(path1) |
| file2 = os.path.basename(path2) |
| if file1 == file2: |
| continue |
| files_pair = [file1, file2] |
| files_pair.sort() |
| pairs_list.append(files_pair[0] + ":" + files_pair[1]) |
| pairs_set = set(pairs_list) |
| for pair in pairs_set: |
| file1, file2 = pair.split(":") |
| yield file1, file2 |
| |
| |
| def extract_parameters_string(basename): |
| params_str = re.search('^design_(.*).bits$', basename) |
| return params_str.group(1) |
| |
| |
| def extract_parameters(basename): |
| iostandard, slew, drive = extract_parameters_string(basename).split('_') |
| return iostandard, slew, drive |
| |
| |
| def generate_differing_bits(basename1, basename2): |
| with open(basename1, 'r') as path1: |
| with open(basename2, 'r') as path2: |
| diff = difflib.unified_diff( |
| path1.read().splitlines(), |
| path2.read().splitlines(), |
| fromfile='path1', |
| tofile='path2') |
| for line in diff: |
| if line.startswith('---'): |
| continue |
| if line.startswith('+++'): |
| continue |
| if line.startswith('@'): |
| continue |
| if line.startswith('-'): |
| yield extract_parameters_string(basename1), line.strip('-') |
| continue |
| if line.startswith('+'): |
| yield extract_parameters_string(basename2), line.strip('+') |
| continue |
| |
| |
| class Database(): |
| def __init__(self, convert_bits=False): |
| self.all_bits = set() |
| self.properties_bits = dict() |
| self.convert_bits = convert_bits |
| self.populate() |
| |
| def populate(self): |
| for file1, file2 in get_file_pairs(): |
| #print(file1 + " vs " + file2) |
| for property_str, bit in generate_differing_bits(file1, file2): |
| #print(property_str + " " + bit) |
| self.update_all_bits(bit) |
| if property_str in self.properties_bits: |
| self.properties_bits[property_str].add(bit) |
| else: |
| self.properties_bits[property_str] = set() |
| self.properties_bits[property_str].add(bit) |
| |
| def update_all_bits(self, bit): |
| self.all_bits.add(bit) |
| |
| def print_all_bits(self): |
| print(self.all_bits) |
| |
| def get_keys(self): |
| return self.properties_bits.keys() |
| |
| def print_bits(self, key): |
| if key in self.properties_bits: |
| print("%s: %s" % (key, self.properties_bits[key])) |
| else: |
| print("The specified property is not in the database") |
| |
| def convert_bit_format(self, item): |
| dummy, address, word, bit = item.split("_") |
| address = int(address[-2:], 16) |
| bit = int(word) % 4 * 32 + int(bit) |
| return "{address}_{bit}".format(address=address, bit=bit) |
| |
| def convert_header(self, header): |
| converted_bits = [] |
| for bit in header: |
| #print(bit + ":" + self.convert_bit_format(bit)) |
| converted_bits.append(self.convert_bit_format(bit)) |
| return converted_bits |
| |
| def get_csv_header(self): |
| header = list(self.all_bits) |
| header.sort() |
| self.csv_header = header |
| if self.convert_bits: |
| header = self.convert_header(header) |
| line = "property,v,i,r," |
| for title in header: |
| line += title + "," |
| return line + '\n' |
| |
| def extract_rvi_parameters(self, rvi): |
| iostandard, slew, drive = rvi.split("_") |
| if iostandard[-2:] == "12": |
| voltage = 1.2 |
| elif iostandard[-2:] == "15": |
| voltage = 1.5 |
| elif iostandard[-2:] == "18": |
| voltage = 1.8 |
| elif iostandard[-2:] == "25": |
| voltage = 2.5 |
| else: |
| voltage = 3.3 |
| resistance = voltage / (int(drive) * 0.001) |
| return "%.1f,%s,%.3f" % (voltage, drive, resistance) |
| |
| def get_csv_body(self): |
| lines = "" |
| keys = list(self.get_keys()) |
| keys.sort() |
| for properties_key in keys: |
| line = properties_key + "," + self.extract_rvi_parameters( |
| properties_key) + "," |
| for title in self.csv_header: |
| if title in self.properties_bits[properties_key]: |
| line += "X," |
| else: |
| line += " ," |
| line += '\n' |
| lines += line |
| return lines |
| |
| def write_csv(self, filename): |
| filename = os.getcwd() + "/" + filename |
| fp = open(filename, 'w') |
| fp.write(self.get_csv_header()) |
| fp.write(self.get_csv_body()) |
| fp.close() |
| print("Written results to %s file.\n" % filename) |
| |
| |
| def main(): |
| database = Database(True) |
| database.write_csv("differences.csv") |
| |
| |
| if __name__ == '__main__': |
| main() |