|  | #!/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 | 
|  | import shutil | 
|  | import sys | 
|  | import subprocess | 
|  | from multiprocessing import Pool | 
|  | from itertools import chain | 
|  | import argparse | 
|  |  | 
|  | # Can be used to redirect vivado tons of output | 
|  | # stdout=DEVNULL in subprocess.check_call | 
|  |  | 
|  |  | 
|  | # Worker function called from threads | 
|  | def start_tiles(argList): | 
|  | blockID, start, stop, total = argList | 
|  | print("Running instance :" + str(blockID) + " / " + str(total)) | 
|  | subprocess.check_call( | 
|  | "${XRAY_VIVADO} -mode batch -source $FUZDIR/jobtiles.tcl -tclargs " + | 
|  | str(blockID) + " " + str(start) + " " + str(stop), | 
|  | shell=True) | 
|  |  | 
|  |  | 
|  | def start_nodes(argList): | 
|  | blockID, start, stop, total = argList | 
|  | print("Running instance :" + str(blockID) + " / " + str(total)) | 
|  | subprocess.check_call( | 
|  | "${XRAY_VIVADO} -mode batch -source $FUZDIR/jobnodes.tcl -tclargs " + | 
|  | str(blockID) + " " + str(start) + " " + str(stop), | 
|  | shell=True) | 
|  |  | 
|  |  | 
|  | # Function called once to get the total numbers of tiles to list | 
|  | def get_nb_tiles(): | 
|  | print("Fetching total number of tiles") | 
|  | subprocess.check_call( | 
|  | "${XRAY_VIVADO} -mode batch -source $FUZDIR/get_tilescount.tcl", | 
|  | shell=True) | 
|  | countfile = open("nb_tiles.txt", "r") | 
|  | return int(countfile.readline()) | 
|  |  | 
|  |  | 
|  | def get_nb_nodes(): | 
|  | print("Fetching total number of nodes") | 
|  | subprocess.check_call( | 
|  | "${XRAY_VIVADO} -mode batch -source $FUZDIR/get_nodescount.tcl", | 
|  | shell=True) | 
|  | countfile = open("nb_nodes.txt", "r") | 
|  | return int(countfile.readline()) | 
|  |  | 
|  |  | 
|  | def run_pool(itemcount, nbBlocks, blocksize, nbParBlock, workFunc): | 
|  | # We handle the case of not integer multiple of pips | 
|  | intitemcount = blocksize * nbBlocks | 
|  | lastRun = False | 
|  | modBlocks = itemcount - intitemcount | 
|  | if modBlocks != 0: | 
|  | lastRun = True | 
|  | nbBlocks = nbBlocks + 1 | 
|  |  | 
|  | print( | 
|  | "Items Count: " + str(itemcount) + " - Number of blocks: " + | 
|  | str(nbBlocks) + " - Parallel blocks: " + str(nbParBlock) + | 
|  | " - Blocksize: " + str(blocksize) + " - Modulo Blocks: " + | 
|  | str(modBlocks)) | 
|  |  | 
|  | blockId = range(0, nbBlocks) | 
|  | startI = range(0, intitemcount, blocksize) | 
|  | stopI = range(blocksize, intitemcount + 1, blocksize) | 
|  | totalBlock = [nbBlocks for _ in range(nbBlocks)] | 
|  |  | 
|  | # In case we have a last incomplete block we add it as a last | 
|  | # element in the arguments list | 
|  | if lastRun == True: | 
|  | startI = chain(startI, [intitemcount]) | 
|  | stopI = chain(stopI, [itemcount]) | 
|  |  | 
|  | argList = zip(blockId, startI, stopI, totalBlock) | 
|  |  | 
|  | with Pool(processes=nbParBlock) as pool: | 
|  | pool.map(workFunc, argList) | 
|  |  | 
|  | return nbBlocks | 
|  |  | 
|  |  | 
|  | # ========================================================================== | 
|  | # ===== FPGA Logic Items data ============================================== | 
|  | # For Artix 7 50T: | 
|  | #   - Total pips: 22002368 | 
|  | #   - Total tiles: 18055 | 
|  | #   - Total nodes: 1953452 | 
|  | # For Kintex 7 70T: | 
|  | #   - Total pips: 29424910 | 
|  | #   - Total tiles: 24453 | 
|  | #   - Total nodes: 2663055 | 
|  | # For Zynq 7 z010: | 
|  | #   - Total pips: 12462138 | 
|  | #   - Total tiles: 13440 | 
|  | #   - Total nodes: 1122477 | 
|  | # ========================================================================= | 
|  | # Dividing by about 64 over 4 core is not optimized but a default to run | 
|  | # on most computer | 
|  | # ========================================================================= | 
|  |  | 
|  |  | 
|  | def main(argv): | 
|  | parser = argparse.ArgumentParser() | 
|  | parser.add_argument( | 
|  | "-p", | 
|  | "--nbPar", | 
|  | help="Number of parallel instances of Vivado", | 
|  | type=int, | 
|  | default=4) | 
|  | parser.add_argument( | 
|  | "-t", | 
|  | "--sizeTilesBlock", | 
|  | help="Define the number of tiles to process per instance", | 
|  | type=int, | 
|  | default=300) | 
|  | parser.add_argument( | 
|  | "-n", | 
|  | "--sizeNodesBlock", | 
|  | help="Define the number of nodes to process per instance", | 
|  | type=int, | 
|  | default=30000) | 
|  | args = parser.parse_args() | 
|  |  | 
|  | nbParBlock = args.nbPar | 
|  | blockTilesSize = args.sizeTilesBlock | 
|  | blockNodesSize = args.sizeNodesBlock | 
|  |  | 
|  | print( | 
|  | " nbPar: " + str(nbParBlock) + " blockTilesSize: " + | 
|  | str(blockTilesSize) + " blockNodesSize: " + str(blockNodesSize)) | 
|  |  | 
|  | tilescount = get_nb_tiles() | 
|  | nbTilesBlocks = int(tilescount / blockTilesSize) | 
|  |  | 
|  | tilesFileCount = run_pool( | 
|  | tilescount, nbTilesBlocks, blockTilesSize, nbParBlock, start_tiles) | 
|  |  | 
|  | nodescount = get_nb_nodes() | 
|  | nbNodesBlocks = int(nodescount / blockNodesSize) | 
|  |  | 
|  | nodeFilesCount = run_pool( | 
|  | nodescount, nbNodesBlocks, blockNodesSize, nbParBlock, start_nodes) | 
|  |  | 
|  | print("Generating final csv files") | 
|  |  | 
|  | with open("root.csv", "w") as wfd: | 
|  | wfd.write("filetype,subtype,filename\n") | 
|  | for j in range(0, tilesFileCount): | 
|  | ftiles = "root_" + str(j) + ".csv" | 
|  | with open(ftiles, "r") as fd: | 
|  | shutil.copyfileobj(fd, wfd) | 
|  | for j in range(0, nodeFilesCount): | 
|  | fnodes = "root_node_" + str(j) + ".csv" | 
|  | with open(fnodes, "r") as fd: | 
|  | shutil.copyfileobj(fd, wfd) | 
|  |  | 
|  | print("Work done !") | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | sys.exit(main(sys.argv)) |