blob: 9729e061731e3f51623900a9d2f181eeb1c7a710 [file] [log] [blame]
#!/bin/bash
# Copyright 2022 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Runs multiple nextpnrs, stopping on the first successful run
# TODO: Better argument handling
# TODO: Include support for device, timefailarg and ignoreloops parameters
# TODO: Include support for setting seed (or baseseed in this case)
if [[ $# -ne 5 ]]; then
echo "Expected 5 arguments"
exit 255
fi
name="$(basename "$0")"
JSON="$1"
PDC="$2"
RESULT_FASM="$3"
SEED_COUNT="$4"
SEED_BASE="$5"
### Only bash 5.1 and later have "wait -p"
if ! wait -p ZZZ; then
echo "${name}: ERROR this version of bash (${BASH_VERSION}) does not have"
echo "required feature wait -p."
exit 1
fi
# A standard array containing all child process ids
declare -a CHILD_PIDS
# Associative array mapping child process to seed used to start it
declare -A PID_TO_SEED
# This lets us detect a nextpnr-nexus failure in the pipelines spawned below
set -o pipefail
# Launch a number of nextpnrs
echo "${name}: running ${SEED_COUNT} nextpnr-nexus instances."
rm -rf runs
mkdir runs
for s in $(seq 0 $(("${SEED_COUNT}"-1))); do
seed=$(("${SEED_BASE}" + s))
DIR="runs/seed-${seed}"
mkdir "${DIR}"
(
nextpnr-nexus \
--json "${JSON}" \
--pdc "${PDC}" \
--fasm "${DIR}/output.fasm" \
--device LIFCL-17-8UWG72C \
--report="${DIR}/report.json" \
--detailed-timing-report \
--placer-heap-timingweight 50 \
--estimate-delay-mult 25 \
--seed "${seed}" 2>&1 | \
(while read -r line; do
echo "$(date +%H:%M:%S) ${line}"; done
) > "${DIR}/nextpnr-nexus.log"
) &
PID=$!
# Record process ID
CHILD_PIDS+=("${PID}")
echo "Launched nextpnr with output to ${DIR}"
# Record mapping to seed
PID_TO_SEED[${PID}]="${seed}"
done
# While there are still running children
while [[ ${#CHILD_PIDS} -gt 1 ]]; do
# Wait for a child to finish then check for success or failure
wait -n -p TERMINATED "${CHILD_PIDS[@]}"
result=$?
# Remove finished child from list
new_CHILD_PIDS=()
for p in "${CHILD_PIDS[@]}"; do
# shellcheck disable=SC2154 # TERMINATED assigned above by wait -p
if [[ "${p}" -ne "${TERMINATED}" ]]; then
new_CHILD_PIDS+=("${p}")
fi
done
CHILD_PIDS=("${new_CHILD_PIDS[@]}")
# Take action depending on success or failure
if [[ "${result}" -eq "0" ]]; then
# Child succeeded - copy result and finish
seed="${PID_TO_SEED[${TERMINATED}]}"
echo "SUCCESS: nextpnr with seed=${seed}"
cp "runs/seed-${seed}/output.fasm" "${RESULT_FASM}"
cp "runs/seed-${seed}/nextpnr-nexus.log" nextpnr-nexus.log
cp "runs/seed-${seed}/report.json" report.json
# TODO: find a more elegant solution for halting all children
for p in "${CHILD_PIDS[@]}"; do pkill -P "${p}"; done
exit 0
else
# Child failed - output a message and continue
seed="${PID_TO_SEED[${TERMINATED}]}"
echo "FAIL: nextpnr with seed=${seed}"
fi
done
# No success found
echo "All seeds failed"
exit 1