mirror of https://github.com/openXC7/prjxray.git
131 lines
4.2 KiB
Python
131 lines
4.2 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
|
|
""" Tool to cleanup site pins JSON dumps.
|
|
|
|
This tool has two behaviors. This first is to rename site names from global
|
|
coordinates to site local coordinates. The second is remove the tile prefix
|
|
from node names.
|
|
|
|
For example CLBLM_L_X8Y149 contains two sites named SLICE_X10Y149 and
|
|
SLICE_X11Y149. SLICE_X10Y149 becomes X0Y0 and SLICE_X11Y149 becomes X1Y0.
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
import json
|
|
import json5
|
|
import re
|
|
import sys
|
|
import copy
|
|
|
|
# All site names appear to follow the pattern <type>_X<abs coord>Y<abs coord>.
|
|
# Generally speaking, only the tile relatively coordinates are required to
|
|
# assemble arch defs, so we re-origin the coordinates to be relative to the tile
|
|
# (e.g. start at X0Y0) and discard the prefix from the name.
|
|
SITE_COORDINATE_PATTERN = re.compile('^(.+)_X([0-9]+)Y([0-9]+)$')
|
|
|
|
|
|
def find_origin_coordinate(sites):
|
|
""" Find the coordinates of each site within the tile, and then subtract the
|
|
smallest coordinate to re-origin them all to be relative to the tile.
|
|
"""
|
|
|
|
if len(sites) == 0:
|
|
return 0, 0
|
|
|
|
def inner_():
|
|
for site in sites:
|
|
coordinate = SITE_COORDINATE_PATTERN.match(site['name'])
|
|
assert coordinate is not None, site
|
|
|
|
x_coord = int(coordinate.group(2))
|
|
y_coord = int(coordinate.group(3))
|
|
yield x_coord, y_coord
|
|
|
|
x_coords, y_coords = zip(*inner_())
|
|
min_x_coord = min(x_coords)
|
|
min_y_coord = min(y_coords)
|
|
|
|
return min_x_coord, min_y_coord
|
|
|
|
|
|
def create_site_pin_to_wire_maps(tile_name, nodes):
|
|
""" Create a map from site_pin names to nodes.
|
|
|
|
Create a mapping from site pins to tile local wires. For each node that is
|
|
attached to a site pin, there should only be 1 tile local wire.
|
|
|
|
"""
|
|
|
|
# Remove tile prefix (e.g. CLBLM_L_X8Y149/) from node names.
|
|
# Routing resources will not have the prefix.
|
|
tile_prefix = tile_name + '/'
|
|
site_pin_to_wires = {}
|
|
|
|
for node in nodes:
|
|
if len(node['site_pins']) == 0:
|
|
continue
|
|
|
|
wire_names = [
|
|
wire for wire in node['wires'] if wire.startswith(tile_prefix)
|
|
]
|
|
assert len(wire_names) == 1, (node, tile_prefix)
|
|
|
|
for site_pin in node["site_pins"]:
|
|
assert site_pin not in site_pin_to_wires
|
|
site_pin_to_wires[site_pin] = wire_names[0]
|
|
|
|
return site_pin_to_wires
|
|
|
|
|
|
def main():
|
|
site_pins = json5.load(sys.stdin)
|
|
|
|
output_site_pins = {}
|
|
output_site_pins["tile_type"] = site_pins["tile_type"]
|
|
output_site_pins["sites"] = copy.deepcopy(site_pins["sites"])
|
|
|
|
site_pin_to_wires = create_site_pin_to_wire_maps(
|
|
site_pins['tile_name'], site_pins['nodes'])
|
|
min_x_coord, min_y_coord = find_origin_coordinate(site_pins['sites'])
|
|
|
|
for site in output_site_pins['sites']:
|
|
orig_site_name = site['name']
|
|
coordinate = SITE_COORDINATE_PATTERN.match(orig_site_name)
|
|
|
|
x_coord = int(coordinate.group(2))
|
|
y_coord = int(coordinate.group(3))
|
|
site['name'] = 'X{}Y{}'.format(
|
|
x_coord - min_x_coord, y_coord - min_y_coord)
|
|
site['prefix'] = coordinate.group(1)
|
|
site['x_coord'] = x_coord - min_x_coord
|
|
site['y_coord'] = y_coord - min_y_coord
|
|
|
|
for site_pin in site['site_pins']:
|
|
assert site_pin['name'].startswith(orig_site_name + '/')
|
|
if site_pin['name'] in site_pin_to_wires:
|
|
site_pin['wire'] = site_pin_to_wires[site_pin['name']]
|
|
else:
|
|
print(
|
|
(
|
|
'***WARNING***: Site pin {} for tile type {} is not connected, '
|
|
'make sure all instaces of this tile type has this site_pin '
|
|
'disconnected.').format(
|
|
site_pin['name'], site_pins['tile_type']),
|
|
file=sys.stderr)
|
|
|
|
site_pin['name'] = site_pin['name'][len(orig_site_name) + 1:]
|
|
|
|
json.dumps(output_site_pins, indent=2, sort_keys=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|