Skip to content
Snippets Groups Projects
Commit ca2af9b1 authored by Mikael Henriksson's avatar Mikael Henriksson :runner:
Browse files

Added SIGINT and SIGTERM signal handling to sweep script.

parent faa59c7b
No related branches found
No related tags found
No related merge requests found
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
# Author: Mikael Henriksson # Author: Mikael Henriksson
# #
# #
# Global sweeping settings. # Global sweeping settings begin:
# ------------------------- # -------------------------------
# #
# Top level design entity name. # Top level design entity name.
...@@ -23,18 +24,18 @@ DESIGN_NAME="my_divider" ...@@ -23,18 +24,18 @@ DESIGN_NAME="my_divider"
# BASH-style array with design files to be analyzed by Design Compiler. Analisys # BASH-style array with design files to be analyzed by Design Compiler. Analisys
# of files are done from left (first element) to right (last element). # of files are done from left (first element) to right (last element).
DESIGN_FILES=("divider.vhdl") DESIGN_FILES=("div.vhdl")
# BASH-style array with periods (in the technology time unit) to be sweept. # BASH-style array with periods (in the technology time unit) to be sweept.
PERIODS=(10.00 5.00 2.50 1.25) PERIODS=(10.0 5.0 3.333 2.5 2.0 1.666 1.428 1.25 1.111 1.0)
# BASH-style array with generics to be sweept. Leave empty if no design generic # BASH-style array with generics to be sweept. Leave empty if no design generic
# should be set. Multiple generics can be assigned for one sweep by comma # should be set. Multiple generics can be assigned for one sweep by comma
# separating each generic assignment in the BASH-array element. # separating each generic assignment in the BASH-array element.
GENERICS=("pipeline=0" "pipeline=1" "pipeline=2") GENERICS=( "float_ip=0,pipe_stages=1" "float_ip=0,pipe_stages=2"
#GENERICS=() "float_ip=1,pipe_stages=1" "float_ip=1,pipe_stages=2" )
# Design clock name to be sweept. The design must have a clock signal. # Design clock name to be sweept. The design MUST have a clock signal.
CLOCK_NAME="clk" CLOCK_NAME="clk"
# Enable Design Compiler adaptive retime through 'set_optimize_registers' for # Enable Design Compiler adaptive retime through 'set_optimize_registers' for
...@@ -96,10 +97,7 @@ function sweep_to_csv() { ...@@ -96,10 +97,7 @@ function sweep_to_csv() {
} }
# Join elements of BASH array, or white space separated string, in $2 by the # Join elements of BASH array, or white space separated string, in $2 by the
# string in $1. Example usage: # string in $1.
#| > MY_ARRAY=('a' 'b' 'c')
#| > echo join_by '---' "${MY_ARRAY[@]}"
#| a---b---c
function join_by { function join_by {
local d=$1; shift; local f=$1; shift; printf %s "$f" "${@/#/$d}"; local d=$1; shift; local f=$1; shift; printf %s "$f" "${@/#/$d}";
} }
...@@ -128,6 +126,7 @@ function generate_synthesis_script() { ...@@ -128,6 +126,7 @@ function generate_synthesis_script() {
# and invoke this function. Note to programmer, that means this function cannot # and invoke this function. Note to programmer, that means this function cannot
# access any unexported items (variables, functions, etc). # access any unexported items (variables, functions, etc).
function run_design_compiler() { function run_design_compiler() {
# Change directory to design directory. # Change directory to design directory.
local design_directory="$1" local design_directory="$1"
cd "$design_directory" || exit 1 cd "$design_directory" || exit 1
...@@ -166,15 +165,23 @@ function run_design_compiler() { ...@@ -166,15 +165,23 @@ function run_design_compiler() {
fi fi
} }
# Export functions and variables needed by the forked instances of this script # Signal SIGINT and SIGTERM interrupt handlers. Both are registered once the
# that run the run_design_compiler function. # setup is complete and the actual sweep has started.
function sigint_handler() {
echo "${0}: SIGINT ignored. Send SIGTERM to terminate sweep."
}
function sigterm_handler() {
echo "${0}: SIGTERM recieved, propagating to workers and terminating."
kill -s SIGTERM -"${1}"
exit 1
}
# Export functions and variables needed by the forked workers.
export -f run_design_compiler export -f run_design_compiler
export DESIGN_NAME export DESIGN_NAME
export PERIOD_DIM export PERIOD_DIM
#
# Sanity checks for the global settings. # Sanity checks for the global settings.
#
if [ -z "$CLOCK_NAME" ]; then if [ -z "$CLOCK_NAME" ]; then
echo "Error: No clock name (\$CLOCK_NAME) provided." echo "Error: No clock name (\$CLOCK_NAME) provided."
exit 1 exit 1
...@@ -236,9 +243,21 @@ want to continure? [y/N] " response ...@@ -236,9 +243,21 @@ want to continure? [y/N] " response
fi fi
fi fi
# Get absolute path of design files, which is necessary for the sweep.
DESIGN_FILES_ABS=()
for file in "${DESIGN_FILES[@]}"; do
DESIGN_FILES_ABS+=("$(realpath "$file")")
done
# Get script launch date. # Get script launch date.
SCRIPT_LAUNCH_DATE=$(date +"%F_%H:%M:%S") SCRIPT_LAUNCH_DATE=$(date +"%F_%H:%M:%S")
#
# Setup of sweep complete. Generate the sweep top directory, launch all sweep
# workers according to the max concurreny and register signal handlers.
#
# Create sweep top directory. # Create sweep top directory.
if [ -z "$TOP_DIR_APPEND" ]; then if [ -z "$TOP_DIR_APPEND" ]; then
TOP_DIR="sweep_${DESIGN_NAME}_${SCRIPT_LAUNCH_DATE}" TOP_DIR="sweep_${DESIGN_NAME}_${SCRIPT_LAUNCH_DATE}"
...@@ -252,12 +271,6 @@ fi ...@@ -252,12 +271,6 @@ fi
echo "Created top directory: '$TOP_DIR'" echo "Created top directory: '$TOP_DIR'"
echo "" echo ""
# Get absolute path of design files, which is necessary for the sweep.
DESIGN_FILES_ABS=()
for file in "${DESIGN_FILES[@]}"; do
DESIGN_FILES_ABS+=("$(realpath "$file")")
done
# Initialize designs. We create one sub directory for each design that is # Initialize designs. We create one sub directory for each design that is
# to be sweept. A 'design' is exactly one setting from ${DESIGN_GENERICS[@]}. # to be sweept. A 'design' is exactly one setting from ${DESIGN_GENERICS[@]}.
# Further, we substitue design options into 'template.tcl' and copy the # Further, we substitue design options into 'template.tcl' and copy the
...@@ -335,14 +348,35 @@ else # "${GENERICS[@]}" is empty. ...@@ -335,14 +348,35 @@ else # "${GENERICS[@]}" is empty.
done done
fi fi
# Print start of process pool log. # Display start of process pool log message.
printf "\nParallel synthesis log ($MAX_CONCURRENCY concurrent processes):\n" printf "\nParallel synthesis log (max $MAX_CONCURRENCY concurrent processes):\n"
# Launch workers according to the max concurrency with xargs. # Trap incoming SIGINT signals, which might be accidental and can prematurely
printf '%s' "${SYNTH_DIRS%?}" | xargs -L1 -d "|" --max-procs="$MAX_CONCURRENCY"\ # terminate the sweep. User should use SIGTERM to terminate sweep beyond this
bash -c 'run_design_compiler $@' _ # point.
#trap 'echo "$0: SIGINT ignored. Send SIGTERM to terminate sweep."' SIGINT
trap 'sigint_handler' SIGINT
# Launch workers according to the max concurrency with XARGS. By launching XARGS
# through SETSID, all workers are launched in the same process group, and more
# importantly, in a new process group different from that of this parent sweep
# script. This shileds all worker processes from recieving SIGINT on accidental
# shell <Ctrl+C>. The process group id (PGID) of all workers is equal to the
# process id (PID) of XARGS, and can be used if a signal must be sent to all
# workers.
printf '%s' "${SYNTH_DIRS%?}" | setsid xargs -L1 -d "|" --max-procs="$MAX_CONCURRENCY"\
bash -c 'run_design_compiler $@' _ &
XARGS_PID="$!"
# Register SIGTERM handler.
trap "sigterm_handler ${XARGS_PID}" SIGTERM
# Wait for all sweep workers to finish.
while kill -s 0 ${XARGS_PID} 1>/dev/null 2>&1; do
wait ${XARGS_PID}
done
# Print end of process pool log. # Display end of process pool log message.
echo "End of parallel synthesis log." echo "End of parallel synthesis log."
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment