#!/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 """ This script loads the pin dump of the desired BEL from Vivado and groups pins into ports. Ports that are not connected to the PL are not included. These ports are usually test and debug related ports, which are not useful from a P&R perspective. Ports are then written to a JSON file. """ import argparse import csv import json import re from collections import defaultdict from prjxray.util import OpenSafeFile def main(): BUS_REGEX = re.compile("(.*[A-Z_])([0-9]+)$") # Parse arguments parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("csv", type=str, help="BEL pin dump file") parser.add_argument( "json", type=str, help="Output JSON file with BEL pins grouped into ports") parser.add_argument( "--special-pins", default="", type=str, required=False, help="Some pins cannot be decoded with the regex") args = parser.parse_args() # Load pin dump with OpenSafeFile(args.csv, "r") as fp: pin_dump = list(csv.DictReader(fp)) # Group pins into ports ports = defaultdict(lambda: {"direction": None, "width": 0}) special_pins = args.special_pins.split(",") for pin in list(pin_dump): pin_name = pin["name"] name = None if pin_name in special_pins: # Full match name = pin_name else: # Partial match for special_pin in special_pins: if pin_name.startswith(special_pin): name = special_pin break if name is None: match = BUS_REGEX.match(pin_name) if match: name = match.group(1) else: name = pin_name # Get direction is_input = int(pin["is_input"]) is_output = int(pin["is_output"]) is_clock = int(pin["is_clock"]) if is_input: direction = "input" if is_clock: direction = "clock" elif is_output: direction = "output" else: assert False, pin # Add to port port = ports[name] if port["direction"] is None: port["direction"] = direction else: assert port["direction"] == direction, (port, direction, name) port["width"] += 1 # Write pin ports to a JSON file with OpenSafeFile(args.json, "w") as fp: json.dump(ports, fp, indent=1, sort_keys=True) if __name__ == "__main__": main()