mirror of https://github.com/openXC7/prjxray.git
141 lines
3.6 KiB
Python
141 lines
3.6 KiB
Python
#!/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 PS7 pin dump from Vivado and groups pins into ports. Also
|
|
assigns each port a class that indicates its function. The classes are:
|
|
|
|
- "normal": A port that connects to the PL (FPGA)
|
|
- "test": A port used for testing, not accessible from the PL.
|
|
- "debug": A debug port, not accessible.
|
|
- "mio": The "mio" ports go directly to die pads, not relevant for routing.
|
|
|
|
Ports are then written to a JSON file.
|
|
"""
|
|
import argparse
|
|
import csv
|
|
import json
|
|
import re
|
|
|
|
from collections import defaultdict
|
|
|
|
# =============================================================================
|
|
|
|
|
|
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="PS7 pin dump file")
|
|
parser.add_argument(
|
|
"json",
|
|
type=str,
|
|
help="Output JSON file with PS7 pins grouped into ports")
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Load pin dump
|
|
with open(args.csv, "r") as fp:
|
|
pin_dump = list(csv.DictReader(fp))
|
|
|
|
# Group pins into ports
|
|
ports = defaultdict(lambda :{
|
|
"direction": None,
|
|
"min": None,
|
|
"max": None,
|
|
"width": 0
|
|
})
|
|
|
|
for pin in list(pin_dump):
|
|
|
|
# Get port name and signal index
|
|
match = BUS_REGEX.match(pin["name"])
|
|
if match:
|
|
name = match.group(1)
|
|
idx = int(match.group(2))
|
|
else:
|
|
name = pin["name"]
|
|
idx = 0
|
|
|
|
# Get direction
|
|
is_input = int(pin["is_input"])
|
|
is_output = int(pin["is_output"])
|
|
is_bidir = int(pin["is_bidir"])
|
|
|
|
if is_input and not is_output and not is_bidir:
|
|
direction = "input"
|
|
elif not is_input and is_output and not is_bidir:
|
|
direction = "output"
|
|
elif not is_input and not is_output and is_bidir:
|
|
direction = "inout"
|
|
else:
|
|
assert False, pin
|
|
|
|
# Add to port
|
|
port = ports[name]
|
|
|
|
if port["direction"] is None:
|
|
port["direction"] = direction
|
|
else:
|
|
assert port["direction"] == direction
|
|
|
|
if port["min"] is None:
|
|
port["min"] = idx
|
|
else:
|
|
port["min"] = min(port["min"], idx)
|
|
|
|
if port["max"] is None:
|
|
port["max"] = idx
|
|
else:
|
|
port["max"] = max(port["max"], idx)
|
|
|
|
port["width"] = port["max"] - port["min"] + 1
|
|
|
|
# Sort ports by their purpose
|
|
for name, port in ports.items():
|
|
|
|
# A test pin (unconnected)
|
|
if name.startswith("TEST"):
|
|
cls = "test"
|
|
|
|
# A debug pin (unconnected)
|
|
elif name.startswith("DEBUG"):
|
|
cls = "debug"
|
|
|
|
# A MIO/DDR pin.
|
|
elif name.startswith("MIO") or name.startswith("DDR") and \
|
|
name != "DDRARB":
|
|
cls = "mio"
|
|
|
|
# PS7 clock/reset
|
|
elif name in ["PSCLK", "PSPORB", "PSSRSTB"]:
|
|
cls = "mio"
|
|
|
|
# "Normal" pin
|
|
else:
|
|
cls = "normal"
|
|
|
|
port["class"] = cls
|
|
|
|
# Write pin ports to a JSON file
|
|
with open(args.json, "w") as fp:
|
|
json.dump(ports, fp, indent=1, sort_keys=True)
|
|
|
|
|
|
# =============================================================================
|
|
|
|
if __name__ == "__main__":
|
|
main()
|