mirror of https://github.com/openXC7/prjxray.git
156 lines
4.7 KiB
Python
156 lines
4.7 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
|
|
|
|
from utils import xjson
|
|
|
|
|
|
def load_tiles(tiles_fn):
|
|
'''
|
|
"$type $tile $grid_x $grid_y $skip_tile $clock_region $typed_sites"
|
|
typed_sites: foreach t $site_types s $sites
|
|
'''
|
|
tiles = list()
|
|
|
|
with open(tiles_fn) as f:
|
|
for line in f:
|
|
# CLBLM_L CLBLM_L_X10Y98 30 106 SLICEL SLICE_X13Y98 SLICEM SLICE_X12Y98
|
|
record = line.split()
|
|
tile_type, tile_name, grid_x, grid_y, skip_tile = record[0:5]
|
|
grid_x, grid_y = int(grid_x), int(grid_y)
|
|
skip_tile = int(skip_tile) != 0
|
|
sites = {}
|
|
|
|
# prohibits is the list of sites that the Vivado placer will not
|
|
# place at.
|
|
#
|
|
# Speculation: These sites are prohibited not because the hardware
|
|
# doesn't work, but because the interconnect around these sites is
|
|
# extremely narrow due to the hardblocks to the left and right of
|
|
# tiles. As a result, these sites should be avoided because
|
|
# congestion and delays when using these sites might be very very
|
|
# high.
|
|
prohibits = []
|
|
clock_region = None
|
|
if len(record) >= 6:
|
|
clock_region = record[5]
|
|
if clock_region == "NA":
|
|
clock_region = None
|
|
for i in range(6, len(record), 3):
|
|
site_type, site_name, prohibited = record[i:i + 3]
|
|
sites[site_name] = site_type
|
|
if int(prohibited):
|
|
prohibits.append(site_name)
|
|
|
|
if not skip_tile:
|
|
tile = {
|
|
'type': tile_type,
|
|
'name': tile_name,
|
|
'grid_x': grid_x,
|
|
'grid_y': grid_y,
|
|
'sites': sites,
|
|
'prohibited_sites': sorted(prohibits),
|
|
'clock_region': clock_region,
|
|
}
|
|
else:
|
|
# Replace tiles within the exclude_roi with NULL tiles to
|
|
# ensure no gaps in the tilegrid.
|
|
#
|
|
# The name will reflect the original tile.
|
|
tile = {
|
|
'type': 'NULL',
|
|
'name': tile_name,
|
|
'grid_x': grid_x,
|
|
'grid_y': grid_y,
|
|
'sites': {},
|
|
'prohibited_sites': [],
|
|
'clock_region': clock_region,
|
|
}
|
|
|
|
tiles.append(tile)
|
|
|
|
return tiles
|
|
|
|
|
|
def load_pin_functions(pin_func_fn):
|
|
pin_functions = {}
|
|
|
|
with open(pin_func_fn) as f:
|
|
for line in f:
|
|
site, pin_func = line.split()
|
|
assert site not in pin_functions, site
|
|
pin_functions[site] = pin_func
|
|
|
|
return pin_functions
|
|
|
|
|
|
def make_database(tiles, pin_func):
|
|
# tile database with X, Y, and list of sites
|
|
# tile name as keys
|
|
database = dict()
|
|
|
|
for tile in tiles:
|
|
database[tile["name"]] = {
|
|
"type": tile["type"],
|
|
"sites": tile["sites"],
|
|
"grid_x": tile["grid_x"],
|
|
"grid_y": tile["grid_y"],
|
|
"bits": {},
|
|
"pin_functions": {},
|
|
"prohibited_sites": tile['prohibited_sites'],
|
|
}
|
|
|
|
if tile["clock_region"]:
|
|
database[tile["name"]]["clock_region"] = tile["clock_region"]
|
|
|
|
for site in database[tile["name"]]["sites"]:
|
|
if site in pin_func:
|
|
database[tile["name"]]["pin_functions"][site] = pin_func[site]
|
|
|
|
return database
|
|
|
|
|
|
def run(tiles_fn, pin_func_fn, json_fn, verbose=False):
|
|
# Load input files
|
|
tiles = load_tiles(tiles_fn)
|
|
|
|
# Read site map
|
|
pin_func = load_pin_functions(pin_func_fn)
|
|
|
|
# Index input
|
|
database = make_database(tiles, pin_func)
|
|
|
|
# Save
|
|
xjson.pprint(open(json_fn, 'w'), database)
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(
|
|
description='Generate tilegrid.json from bitstream deltas')
|
|
|
|
parser.add_argument('--verbose', action='store_true', help='')
|
|
parser.add_argument('--out', default='/dev/stdout', help='Output JSON')
|
|
parser.add_argument(
|
|
'--tiles',
|
|
default='tiles.txt',
|
|
help='Input tiles.txt tcl output',
|
|
required=True)
|
|
parser.add_argument(
|
|
'--pin_func', help='List of sites with pin functions', required=True)
|
|
args = parser.parse_args()
|
|
|
|
run(args.tiles, args.pin_func, args.out, verbose=args.verbose)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|