From 9f4c26c28011ba0d46dc1f1cdcef7bd82a556113 Mon Sep 17 00:00:00 2001 From: Mehdi Khairy Date: Tue, 15 Jan 2019 20:20:37 +0100 Subject: [PATCH] Fuzzer 074 Multi Thread optimisation Signed-off-by: Mehdi Khairy --- fuzzers/074-dump_all/Makefile | 5 +- fuzzers/074-dump_all/generate.sh | 2 +- fuzzers/074-dump_all/get_nodescount.tcl | 13 ++ fuzzers/074-dump_all/get_tilescount.tcl | 13 ++ fuzzers/074-dump_all/jobnodes.tcl | 46 +++++ .../{generate.tcl => jobtiles.tcl} | 50 ++---- fuzzers/074-dump_all/run_fuzzer.py | 166 ++++++++++++++++++ 7 files changed, 261 insertions(+), 34 deletions(-) create mode 100644 fuzzers/074-dump_all/get_nodescount.tcl create mode 100644 fuzzers/074-dump_all/get_tilescount.tcl create mode 100644 fuzzers/074-dump_all/jobnodes.tcl rename fuzzers/074-dump_all/{generate.tcl => jobtiles.tcl} (80%) create mode 100644 fuzzers/074-dump_all/run_fuzzer.py diff --git a/fuzzers/074-dump_all/Makefile b/fuzzers/074-dump_all/Makefile index da907200..f9ba3ed9 100644 --- a/fuzzers/074-dump_all/Makefile +++ b/fuzzers/074-dump_all/Makefile @@ -2,6 +2,9 @@ N := 1 SPECIMENS := $(addprefix build/specimen_,$(shell seq -f '%03.0f' $(N))) SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS)) +MAX_VIVADO_PROCESS ?= 4 +MAX_TILES_INSTANCE ?= 300 +MAX_NODES_INSTANCE ?= 30000 database: $(SPECIMENS_OK) true @@ -13,7 +16,7 @@ pushdb: cp build/output/tileconn.json ${XRAY_DATABASE_DIR}/$(XRAY_DATABASE)/ $(SPECIMENS_OK): - bash generate.sh $(subst /OK,,$@) + bash generate.sh $(subst /OK,,$@) -p=$(MAX_VIVADO_PROCESS) -t=$(MAX_TILES_INSTANCE) -n=$(MAX_NODES_INSTANCE) touch $@ run: diff --git a/fuzzers/074-dump_all/generate.sh b/fuzzers/074-dump_all/generate.sh index 91e9198d..7606ac5b 100644 --- a/fuzzers/074-dump_all/generate.sh +++ b/fuzzers/074-dump_all/generate.sh @@ -2,6 +2,6 @@ source ${XRAY_GENHEADER} -${XRAY_VIVADO} -mode batch -source $FUZDIR/generate.tcl +python3 $FUZDIR/run_fuzzer.py $2 $3 $4 cd $FUZDIR && ./generate_after_dump.sh diff --git a/fuzzers/074-dump_all/get_nodescount.tcl b/fuzzers/074-dump_all/get_nodescount.tcl new file mode 100644 index 00000000..d20532ad --- /dev/null +++ b/fuzzers/074-dump_all/get_nodescount.tcl @@ -0,0 +1,13 @@ +create_project -force -part $::env(XRAY_PART) design design +set_property design_mode PinPlanning [current_fileset] +open_io_design -name io_1 + +#set_param tcl.collectionResultDisplayLimit 0 +set_param messaging.disableStorage 1 + +set nbnodes_fp [open nb_nodes.txt w] + +set nodes [get_nodes] +puts $nbnodes_fp [llength $nodes] + +close $nbnodes_fp diff --git a/fuzzers/074-dump_all/get_tilescount.tcl b/fuzzers/074-dump_all/get_tilescount.tcl new file mode 100644 index 00000000..19469ed1 --- /dev/null +++ b/fuzzers/074-dump_all/get_tilescount.tcl @@ -0,0 +1,13 @@ +create_project -force -part $::env(XRAY_PART) design design +set_property design_mode PinPlanning [current_fileset] +open_io_design -name io_1 + +#set_param tcl.collectionResultDisplayLimit 0 +set_param messaging.disableStorage 1 + +set nbtiles_fp [open nb_tiles.txt w] + +set tiles [get_tiles] +puts $nbtiles_fp [llength $tiles] + +close $nbtiles_fp diff --git a/fuzzers/074-dump_all/jobnodes.tcl b/fuzzers/074-dump_all/jobnodes.tcl new file mode 100644 index 00000000..7f7b4eb5 --- /dev/null +++ b/fuzzers/074-dump_all/jobnodes.tcl @@ -0,0 +1,46 @@ +set blocknb [lindex $argv 0] +set start [expr int([lindex $argv 1])] +set stop [expr int([lindex $argv 2])] + +create_project -force -part $::env(XRAY_PART) $blocknb $blocknb +set_property design_mode PinPlanning [current_fileset] +open_io_design -name io_1 + +#set_param tcl.collectionResultDisplayLimit 0 +set_param messaging.disableStorage 1 + +set root_fp [open "root_node_${blocknb}.csv" w] + +set nodes [get_nodes] + +for {set j $start } { $j < $stop } { incr j } { + + set node [lindex $nodes $j] + + file mkdir [file dirname "${node}"] + set fname $node.json5 + puts $root_fp "node,,$fname" + + set fp [open "${fname}" w] + # node properties: + # BASE_CLOCK_REGION CLASS COST_CODE COST_CODE_NAME IS_BAD IS_COMPLETE + # IS_GND IS_INPUT_PIN IS_OUTPUT_PIN IS_PIN IS_VCC NAME NUM_WIRES PIN_WIRE + # SPEED_CLASS + puts $fp "\{" + puts $fp "\t\"node\": \"$node\"," + puts $fp "\t\"wires\": \[" + foreach wire [get_wires -of_objects $node] { + # wire properties: + # CLASS COST_CODE ID_IN_TILE_TYPE IS_CONNECTED IS_INPUT_PIN IS_OUTPUT_PIN + # IS_PART_OF_BUS NAME NUM_DOWNHILL_PIPS NUM_INTERSECTS NUM_PIPS + # NUM_TILE_PORTS NUM_UPHILL_PIPS SPEED_INDEX TILE_NAME TILE_PATTERN_OFFSET + puts $fp "\t\t\{" + puts $fp "\t\t\t\"wire\":\"$wire\"," + puts $fp "\t\t\}," + } + puts $fp "\t\]" + puts $fp "\}" + close $fp +} + +close $root_fp diff --git a/fuzzers/074-dump_all/generate.tcl b/fuzzers/074-dump_all/jobtiles.tcl similarity index 80% rename from fuzzers/074-dump_all/generate.tcl rename to fuzzers/074-dump_all/jobtiles.tcl index 1b8eaf20..28350f85 100644 --- a/fuzzers/074-dump_all/generate.tcl +++ b/fuzzers/074-dump_all/jobtiles.tcl @@ -1,15 +1,28 @@ -create_project -force -part $::env(XRAY_PART) design design +set blocknb [lindex $argv 0] +set start [expr int([lindex $argv 1])] +set stop [expr int([lindex $argv 2])] + +create_project -force -part $::env(XRAY_PART) $blocknb $blocknb set_property design_mode PinPlanning [current_fileset] open_io_design -name io_1 -set root_fp [open root.csv w] -puts $root_fp "filetype,subtype,filename" -foreach tile [get_tiles] { +#set_param tcl.collectionResultDisplayLimit 0 +set_param messaging.disableStorage 1 + +set root_fp [open "root_${blocknb}.csv" w] +#puts $root_fp "filetype,subtype,filename" + +set tiles [get_tiles] + +for {set j $start } { $j < $stop } { incr j } { + + set tile [lindex $tiles $j] + set fname tile_$tile.json5 set tile_type [get_property TYPE $tile] puts $root_fp "tile,$tile_type,$fname" - set fp [open $fname w] + set fp [open "${fname}" w] puts $fp "\{" puts $fp "\t\"tile\": \"$tile\"," # tile properties: @@ -106,31 +119,4 @@ foreach tile [get_tiles] { close $fp } -foreach node [get_nodes] { - file mkdir [file dirname $node] - set fname $node.json5 - puts $root_fp "node,,$fname" - - set fp [open $fname w] - # node properties: - # BASE_CLOCK_REGION CLASS COST_CODE COST_CODE_NAME IS_BAD IS_COMPLETE - # IS_GND IS_INPUT_PIN IS_OUTPUT_PIN IS_PIN IS_VCC NAME NUM_WIRES PIN_WIRE - # SPEED_CLASS - puts $fp "\{" - puts $fp "\t\"node\": \"$node\"," - puts $fp "\t\"wires\": \[" - foreach wire [get_wires -of_objects $node] { - # wire properties: - # CLASS COST_CODE ID_IN_TILE_TYPE IS_CONNECTED IS_INPUT_PIN IS_OUTPUT_PIN - # IS_PART_OF_BUS NAME NUM_DOWNHILL_PIPS NUM_INTERSECTS NUM_PIPS - # NUM_TILE_PORTS NUM_UPHILL_PIPS SPEED_INDEX TILE_NAME TILE_PATTERN_OFFSET - puts $fp "\t\t\{" - puts $fp "\t\t\t\"wire\":\"$wire\"," - puts $fp "\t\t\}," - } - puts $fp "\t\]" - puts $fp "\}" - close $fp -} - close $root_fp diff --git a/fuzzers/074-dump_all/run_fuzzer.py b/fuzzers/074-dump_all/run_fuzzer.py new file mode 100644 index 00000000..cfd43cd3 --- /dev/null +++ b/fuzzers/074-dump_all/run_fuzzer.py @@ -0,0 +1,166 @@ +import os +import shutil +import sys +import subprocess +import signal +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 % nbBlocks + 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))