diff --git a/synth.sh b/synth.sh index 05e20c0..6344227 100755 --- a/synth.sh +++ b/synth.sh @@ -1,177 +1,208 @@ #!/bin/bash BBDD_SCRIPT="yosys/bbdd_synth_muxxor.ys" BDD_SCRIPT="yosys/bdd_synth.ys" MUXIG_SCRIPT="yosys/muxig_synth.ys" TEMP_DIR="temp" LIBERTY_FILE="liberty/nem_thesis.lib" TIMEOUT="2m" #1 minute timeout for now TECHMAP_BBDD="yosys/techmap_bbdd.v" TABLE_SIZE="300000" MAX_INPUTS=0 # 0 disables partitioning, i.e. one diagram over all inputs print_options(){ echo "(1) Synthesis Verilog file with bbdd optimization" echo "(2) Synthesis Verilog file with bdd optimization" echo "(3) Synthesis Verilog file with muxig optimization" echo "(e) Exit" } safe_path() { local unsafe_path="$1" echo "$(printf '%s\n' "$unsafe_path" | sed 's/[&/\]/\\&/g')" } process_input() { file_name=$(basename "$file_path") # with extension file_base="${file_name%.*}" # without # get top module name read -p "top module [default=${file_base}] " top_module top_module=${top_module:-${file_base}} #safe_file_path=$(printf '%s\n' "$file_path" | sed 's/[&/\]/\\&/g') safe_file_path=$(safe_path "$file_path") #safe_techmap_path=$(printf '%s\n' "$TECHMAP_BBDD" | sed 's/[&/\]/\\&/g') } run_yosys() { # Run yosys if $nosat; then sat_replacement="#" # comment out {{SAT}} else sat_replacement="" # replace {{SAT}} with nothing fi # options handed to the converter; the bbdd template picks them up through # {{CONV_FLAGS}}. convert_bdd takes no options, and its template has no # placeholder, so the substitution is a no-op there. conv_flags="-t $TABLE_SIZE" if [ "$MAX_INPUTS" -gt 0 ] 2>/dev/null; then conv_flags="$conv_flags -n $MAX_INPUTS" fi echo "Synthesising $file_base" sed -e "s/{{VERILOG_FILE}}/$safe_file_path/g" \ -e "s/{{TEMP_DIR}}/$TEMP_DIR/g" \ -e "s/{{TOP_MODULE}}/$top_module/g" \ -e "s/{{BASE_NAME}}/$file_base/g" \ -e "s/{{TECHMAP_BBDD}}/$safe_techmap_path/g" \ -e "s/{{LIBERTY_FILE}}/$safe_liberty_path/g" \ -e "s/{{OUT_DIR}}/$safe_out_path/g" \ -e "s/{{TIMEOUT}}/$TIMEOUT/g" \ -e "s/{{SAT}}/$sat_replacement/g" \ -e "s/{{CONV_FLAGS}}/$(safe_path "$conv_flags")/g" \ "$yosys_script" > "$TEMP_DIR/${file_base}_synth.ys" + if $STRIP_NOSCOPEINFO; then + sed -i 's/flatten -noscopeinfo/flatten/' "$TEMP_DIR/${file_base}_synth.ys" + fi mkdir -p ${out_dir}/${file_base}/ /usr/bin/time -f "Time: %E\nCPU: %P\nMemory: %M KB" -o ${out_dir}/${file_base}/yosys_${opt_name}_time.txt yosys${yosys_flags} ${TEMP_DIR}/${file_base}_synth.ys if [ -e ${out_dir}/${file_base} ]; then - python ./yosys/print_summary.py ${out_dir}/${file_base} + # The summary is a convenience on top of a finished run, so a missing + # interpreter or an uninstalled plotting dependency must not be reported + # as if the synthesis itself had failed. + if [ -n "$PYTHON" ]; then + "$PYTHON" ./yosys/print_summary.py ${out_dir}/${file_base} \ + || echo "[WARN] print_summary.py failed; results are still in ${out_dir}/${file_base}" + else + echo "[WARN] no python interpreter found; skipping print_summary.py" + fi else echo "${file_base} did not finish in time" fi } synth_verilog() { local yosys_script="$1" local opt_name="$2" if ! $verbose; then yosys_flags=" -q" # is quite mode else yosys_flags="" fi safe_techmap_path=$(safe_path "$TECHMAP_BBDD") safe_liberty_path=$(safe_path "$LIBERTY_FILE") echo "Using script: $yosys_script" read -e -p 'Input file path: ' file_path # Get Output Dir read -e -p 'Output directory: ' out_dir safe_out_path=$(safe_path "$out_dir") out_dir="${out_dir%/}/" if [ -f "$file_path" ]; then process_input run_yosys if ! $nocleanup; then rm ${TEMP_DIR}/${file_base}_synth.ys rm ${TEMP_DIR}/${file_base}.blif rm -f ${TEMP_DIR}/${file_base}_bbdd.blif rm -f ${TEMP_DIR}/${file_base}_bdd.blif fi exit elif [ -d "$file_path" ]; then # extend / if not present file_path="${file_path%/}/" for file in "$file_path"*.v; do if [ -e "$file" ]; then safe_file_path=$(safe_path "$file") file_name=$(basename "$file") # with extension file_base="${file_name%.*}" # without top_module="$file_base" yosys_flags=" -q" run_yosys if ! $nocleanup; then rm ${TEMP_DIR}/${file_base}_synth.ys rm ${TEMP_DIR}/${file_base}.blif rm -f ${TEMP_DIR}/${file_base}_bbdd.blif rm -f ${TEMP_DIR}/${file_base}_bdd.blif fi fi done exit else echo "[ERROR] File ${file_path} does not exist" fi } handle_selection() { case "$1" in 1) synth_verilog $BBDD_SCRIPT "bbdd";; 2) synth_verilog $BDD_SCRIPT "bdd";; 3) synth_verilog $MUXIG_SCRIPT "muxig";; e) echo "Exiting..."; exit 0 ;; *) echo "Invalid option. Please try again." ;; esac } # Initialize booleans as false nocleanup=false nosat=false verbose=false # Parse flags while [[ $# -gt 0 ]]; do case "$1" in -nocleanup) nocleanup=true shift ;; -nosat) nosat=true shift ;; -v) verbose=true shift ;; -n) MAX_INPUTS="$2" shift 2 ;; *) echo "Unknown option: $1" echo "Usage: $0 [-nocleanup] [-nosat] [-v] [-n MAX_INPUTS]" exit 1 ;; esac done +# print_summary.py is invoked through whichever interpreter this host actually +# has; `python` is absent on distributions that ship only python3. +PYTHON="" +for candidate in python3 python; do + if command -v "$candidate" >/dev/null 2>&1; then + PYTHON="$candidate" + break + fi +done + +# yosys 0.40 added `flatten -noscopeinfo`; on older yosys the flag is a hard +# error ("Command syntax error: Unknown option"), and plain `flatten` is +# equivalent there because no $scopeinfo cells are produced in the first place. +# Detect once and patch the rendered script if needed. +STRIP_NOSCOPEINFO=false +if ! yosys -qp "help flatten" 2>/dev/null | grep -q -- "-noscopeinfo"; then + STRIP_NOSCOPEINFO=true + echo "[INFO] yosys $(yosys -V 2>/dev/null | awk '{print $2}') has no 'flatten -noscopeinfo'; stripping the flag" +fi + # get input file mkdir -p $TEMP_DIR while true; do if [ "$nosat" = false ]; then echo "Satisfiability check is enabled" fi print_options read -p "Enter your choice [1-3]: " choice handle_selection "$choice" echo "" done