forked from f4pga/prjxray
-
Notifications
You must be signed in to change notification settings - Fork 1
/
make_ports.py
113 lines (88 loc) · 2.85 KB
/
make_ports.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/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()