blob: 78aba7f07d481a66251e0d5ddb9709e4de560c94 [file] [log] [blame]
#!/bin/bash
#
##################################################################################################################
##DO NOT CHANGE ANY OF THE BELOW BETWEEN THE TWO DO NOT CHANGE LINES #############################################
##################################################################################################################
if [ -z "$MGLS_LICENSE_FILE" ]; then
echo "Missing MGLS_LICENSE_FILE"
exit 1
fi
if [ -z "$LM_LICENSE_FILE" ]; then
echo "Missing LM_LICENSE_FILE"
exit 1
fi
export CALIBRE_HOME=/usr/local/google/edatools/mentor/calibre/2018.4.34.26/aoj_cal_2018.4_34.26/
export MGC_TMPDIR=/tmp
export MGC_CALIBRE_LAYOUT_TMP_FILE=/tmp/query_results
export CALIBRE_DISABLE_RHEL5_WARNING=1
export USE_CALIBRE_VCO=aoj
export CALIBRE_VERSION_DASH=2018.4_34.26
export CALIBRE_VERSION_DOT=$(echo $CALIBRE_VERSION_DASH | sed -e's/_/./')
export MGC_HOME=/usr/local/google/edatools/mentor/calibre/$CALIBRE_VERSION_DOT/aoj_cal_$CALIBRE_VERSION_DASH/
export PATH=${MGC_HOME}/bin:${PATH}
#
if [ -z $VERSION ];then
echo "Missing VERSION"
exit 1
fi
export TEST_DIR=/usr/local/google/home/tansell/work/openflow-drc-tests/
export JOB_HOME=$TEST_DIR/torture_tests/$VERSION/
export PDK_HOME=$TEST_DIR/pdk/skywater/s130/V2.1.305
if [ ! -d "$JOB_HOME" ]; then
echo "$JOB_HOME doesn't exist?"
exit 1
fi
# see OASIS NOTES at EOF
for GDS_FILE in $JOB_HOME/gds/*.{gds,oas}{,.gz,.lz,.xz}; do
if [ ! -e "$GDS_FILE" ]; then
continue # above brace-expansion keeps non-existent star forms: '.../*.gds.gz'
fi
# check for ambiguity(error); and optionally decompress.
# Keep source & decompress to a .gds/.oas in parallel; and afterwards delete .gds/.oas.
# This due to suspicion TEST_DIR or JOB_HOME elsewhere/later subject to a 'git add --all',
# which would commit (intended temporary) uncompressed files. Better would be decompress
# to a scratch-dir that is git-ignored or outside of TEST_DIR; but without visibility
# into rest of system not clear if works to restructure use of (exports)JOB_HOME,JOB_NAME.
GDS_BASE=${GDS_FILE%.xz}
GDS_BASE=${GDS_BASE%.lz}
GDS_BASE=${GDS_BASE%.gz}
GDS_FILEX=${GDS_BASE}.xz
GDS_FILEL=${GDS_BASE}.lz
GDS_FILEG=${GDS_BASE}.gz
export JOB_EXT=gds
export LAYOUT_SYSTEM=GDSII
GDS_BASE2=${GDS_BASE%.$JOB_EXT}.oas # opposing variant for .gds
DRC_RS_BASE=base
unset LAYSYS_OASIS # so runset (via preprocessor) selects: 'LAYOUT SYSTEM GDSII'
if [[ "$GDS_BASE" == *.oas ]]; then
export JOB_EXT=oas
export LAYOUT_SYSTEM=OASIS
GDS_BASE2=${GDS_BASE%.$JOB_EXT}.gds # opposing variant for .oas
export LAYSYS_OASIS=1 # so runset (via preprocessor) selects: 'LAYOUT SYSTEM OASIS'
fi
GDS_FILEX2=${GDS_BASE2}.xz # compressed opposing variants
GDS_FILEL2=${GDS_BASE2}.lz
GDS_FILEG2=${GDS_BASE2}.gz
GDS_DEL=""
nbr=0
[ -e "$GDS_BASE" ] && (( nbr++ ))
[ -e "$GDS_FILEX" ] && (( nbr++ ))
[ -e "$GDS_FILEL" ] && (( nbr++ ))
[ -e "$GDS_FILEG" ] && (( nbr++ ))
[ -e "$GDS_BASE2" ] && (( nbr++ ))
[ -e "$GDS_FILEX2" ] && (( nbr++ ))
[ -e "$GDS_FILEL2" ] && (( nbr++ ))
[ -e "$GDS_FILEG2" ] && (( nbr++ ))
if [[ $nbr != 1 ]]; then
echo "$GDS_FILE ambiguous, $nbr variants (.gds/.oas with/without .gz/.lz/.xz)"
continue
fi
if [ -e "$GDS_FILEX" ]; then
unxz -c <"$GDS_FILE" >"$GDS_BASE"
stat=$?
if [[ "$stat" != 0 ]]; then
echo "Failed($stat) to: unxz --force $GDS_FILE"
continue
fi
echo "completed: unxz --force $GDS_FILE"
GDS_FILE="$GDS_BASE"
GDS_DEL="$GDS_BASE"
fi
if [ -e "$GDS_FILEL" ]; then
lzip -cd <"$GDS_FILE" >"$GDS_BASE"
stat=$?
if [[ "$stat" != 0 ]]; then
echo "Failed($stat) to: lzip -d --force $GDS_FILE"
continue
fi
echo "completed: lzip -d --force $GDS_FILE"
GDS_FILE="$GDS_BASE"
GDS_DEL="$GDS_BASE"
fi
if [ -e "$GDS_FILEG" ]; then
gunzip -c <"$GDS_FILE" >"$GDS_BASE"
stat=$?
if [[ "$stat" != 0 ]]; then
echo "Failed($stat) to: gunzip --force $GDS_FILE"
continue
fi
echo "completed: gunzip --force $GDS_FILE"
GDS_FILE="$GDS_BASE"
GDS_DEL="$GDS_BASE"
fi
export JOB_NAME="$(basename -s .$JOB_EXT $GDS_FILE)" # extension: .gds or .oas
echo
echo
echo
echo "export JOB_HOME='$JOB_HOME'"
echo "export JOB_NAME='$JOB_NAME'"
echo "====================================="
if [[ ! -e $JOB_HOME/gds/$JOB_NAME.gds && ! -e $JOB_HOME/gds/$JOB_NAME.oas ]]; then
echo "Did not find '$JOB_HOME/gds/$JOB_NAME.gds' or '$JOB_HOME/gds/$JOB_NAME.oas'"
exit 1
fi
set -x
cd $TEST_DIR
git checkout HEAD $TEST_DIR/runsets/*_runset ## TBD: does this do anything? or just fail with error?
#sed -i -e"s@\$JOB_HOME@$JOB_HOME@" $TEST_DIR/runsets/*_runset
cd ~/github/google/skywater-pdk/s8/V1.3.0
##################################################################################################################
##DO NOT CHANGE ANY OF THE ABOVE #################################################################################
##################################################################################################################
##################################################################################################################
# Directories
##################################################################################################################
mkdir -p $JOB_HOME/logs
mkdir -p $JOB_HOME/lvs
mkdir -p $JOB_HOME/spef
mkdir -p $JOB_HOME/cdl
mkdir -p $JOB_HOME/drc
mkdir -p $JOB_HOME/ant
##################################################################################################################
# Variables needed by $TEST_DIR/runsets/local_xrc_rules.2
##################################################################################################################
export JOB_HOME=$JOB_HOME
export JOB_NAME=$JOB_NAME
export LAYOUT_NAME=$JOB_NAME.$JOB_EXT # <-- parameterized ext: gds or oas
export LAYOUT_EXTRACTED=$JOB_NAME.extracted.cdl
export SOURCE_NAME=$JOB_NAME.source.cdl
export LVS_REPORT=report.lvs
export PEX_NETLIST=$JOB_NAME.spef
export LAYOUT_PATH=$JOB_HOME/gds/$LAYOUT_NAME
export SOURCE_PATH=$JOB_HOME/cdl/$SOURCE_NAME
export LVS_REPORT_PATH=$JOB_HOME/lvs/$LVS_REPORT
export PEX_NETLIST_PATH=$JOB_HOME/spef/$PEX_NETLIST
export DRC_RESULTS_FILE=$JOB_HOME/drc/results.drc
export ANT_RESULTS_FILE=$JOB_HOME/ant
export DRC_SUMMARY_REPORT=$JOB_HOME/drc/summary.drc
export SVDB_PATH=$JOB_HOME/svdb
##################################################################################################################
# Runset
##################################################################################################################
s130=0
s8=1
gf180=0
if [ "$s8" == "1" ]; then
export RUNSET_DIR=$TEST_DIR/runsets/s8/V2.0.1
export PDK_HOME=$TEST_DIR/pdk/skywater/s8/V2.0.1
export PDK_HOME2=$TEST_DIR/pdk/skywater/s8/V1.3.0-mr
fi
if [ "$s130" == "1" ]; then
export RUNSET_DIR=$TEST_DIR/runsets/s130/V2.1.305
export PDK_HOME=$TEST_DIR/pdk/skywater/s130/V2.1.305
fi
if [ "$gf180" == "1" ]; then
export RUNSET_DIR=$TEST_DIR/runsets/gf180
fi
export RUNSET=$RUNSET_DIR/LVS/base
# export HCELLS=$RUNSET_DIR/LVS/hcells.txt
export HCELLS=$RUNSET_DIR/hcells.txt
export XCELLS=$RUNSET_DIR/xcells.txt
export TECHDIR=$RUNSET_DIR/
export baseDeckRev=Rev16
##################################################################################################################
# V2LVS flow
##################################################################################################################
run_lvs=0
# all 1 for stdcell-based verilog source, all 0 for full-custom CDL source
run_lvs_rcx=0 # <-- meaningful/used IFF $run_lvs==1
run_lvs_box=0 # <-- meaningful/used IFF $run_lvs==1
run_lvs_catclibs=0 # <-- meaningful/used IFF $run_lvs==1
run_antenna_check=1
run_mr_drc=1
run_full_drc=0
run_oas=0
run_lures=0
run_soft=0
run_stress=0
if [ "$run_lvs" == "1" ]; then
export RUNSET=$RUNSET_DIR/LVS/base
fi
if [ "$run_mr_drc" == "1" ]; then
export RUNSET=$RUNSET_DIR/DRC/base
fi
if [ "$run_lvs" == "1" ]; then
unset DO_LVS_BOX # so runset (via preprocessor) OMITS: INCLUDE .../bbox.<libName>.txt
if [ "$run_lvs_box" == "1" ]; then
export DO_LVS_BOX=1 # so runset (via preprocessor) KEEPS: INCLUDE .../bbox.<libName>.txt
fi
if [ -e $JOB_HOME/verilog/$JOB_NAME.v ] ; then
if [ ! -z "$(ls -A $JOB_HOME/cdl/)" ] ; then
echo "Found cdls under $JOB_HOME/cdl/"
cat $JOB_HOME/cdl/*.cdl > $JOB_HOME/cdl/libraries-merged.cdl
fi
if [ "$run_lvs_catclibs" == "1" ]; then
cat $TEST_DIR/libraries/cdl/*.cdl >> $JOB_HOME/cdl/libraries-merged.cdl
fi
## merge all verilog netlist
for verilog_module in $JOB_HOME/verilog/*; do
echo "" >> $verilog_module
done
for verilog_module in $JOB_HOME/verilog/box/*; do
echo "" >> $verilog_module
done
touch $JOB_HOME/cdl/box.cdl
mkdir -p $JOB_HOME/verilog/box
cat $JOB_HOME/verilog/box/* >> $JOB_HOME/verilog/box/merged.v
cat $JOB_HOME/verilog/* >> $JOB_HOME/verilog/verilog-merged.v
##converts a verilog structural netlist to a SPICE-like netlist for LVS
verilog_input=$JOB_HOME/verilog/$JOB_NAME.v
# verilog to spice with bus delimeter = "<>"
v2lvs -v $JOB_HOME/verilog/box/merged.v -o $JOB_HOME/cdl/box.cdl -e
v2lvs -a "<>" -w 2 -v $JOB_HOME/verilog/verilog-merged.v -o $JOB_HOME/cdl/$JOB_NAME.busworkaround.source.cdl \
-s $JOB_HOME/cdl/libraries-merged.cdl -s $JOB_HOME/cdl/box.cdl \
2>&1 | tee $JOB_HOME/logs/$JOB_NAME.busworkaround.v2lvs.log || true
# -e Specifies that empty .SUBCKT definitions are generated for all modules (no
# instances are translated). This is useful for generating “black box” subcircuits
# from library files. See Using the –e Switch to Create LVS Box Subcircuits
# later in this chapter.
# v2lvs -e -a "<>" -w 2 -v $verilog_input -o $JOB_HOME/cdl/$JOB_NAME.busworkaround.source.cdl \
# | tee $JOB_HOME/logs/$JOB_NAME.busworkaround.v2lvs.log || true
## escape square brackets that are not buses
## then replace <> buses with []
sed 's/\[/\\[/g' -i $JOB_HOME/cdl/$JOB_NAME.busworkaround.source.cdl
sed 's/\]/\\]/g' -i $JOB_HOME/cdl/$JOB_NAME.busworkaround.source.cdl
sed 's/</\[/g' -i $JOB_HOME/cdl/$JOB_NAME.busworkaround.source.cdl
sed 's/>/\]/g' -i $JOB_HOME/cdl/$JOB_NAME.busworkaround.source.cdl
export SOURCE_NAME=$JOB_NAME.busworkaround.source.cdl
export SOURCE_PATH=$JOB_HOME/cdl/$SOURCE_NAME
# just keep this to compare with the workaround
v2lvs -w 2 -v $verilog_input -o $JOB_HOME/cdl/$JOB_NAME.source.cdl \
-s $JOB_HOME/cdl/libraries-merged.cdl 2>&1 | tee $JOB_HOME/logs/$JOB_NAME.v2lvs.log || true
#cp $JOB_HOME/cdl/$JOB_NAME.source.cdl $JOB_HOME/cdl/${SOURCE_NAME}
else
if [ ! -z "$(ls -A $JOB_HOME/cdl/$JOB_NAME.cdl)" ] ; then
if [ "$run_lvs_catclibs" == "1" ]; then
echo ".INCLUDE $JOB_HOME/cdl/libraries-merged.cdl" >> $JOB_HOME/cdl/${SOURCE_NAME}
fi
cat $JOB_HOME/cdl/$JOB_NAME.cdl >> $JOB_HOME/cdl/${SOURCE_NAME}
fi
if [ "$run_lvs_catclibs" == "1" ]; then
cat $TEST_DIR/libraries/cdl/*.cdl >> $JOB_HOME/cdl/libraries-merged.cdl
fi
fi
fi
## end V2LVS flow
##################################################################################################################
# Remove fill cells and tap cells from the source netlist before LVS
##################################################################################################################
# [ -f $JOB_HOME/cdl/$JOB_NAME.source.cdl ] && \
# cp $JOB_HOME/cdl/$JOB_NAME.source.cdl $JOB_HOME/cdl/$JOB_NAME.v2lvs.unfiltered.cdl
# python3 $TEST_DIR/scripts/remove_spice_instances.py $JOB_HOME/cdl/$JOB_NAME.source.cdl \
# sky130_fd_sc_hd__fill_1 \
# sky130_fd_sc_hd__fill_2 \
# sky130_fd_sc_hd__tapvpwrvgnd_1 \
# > $JOB_HOME/logs/$JOB_NAME.remove_spice_instances.log 2>&1
# extra runset rules per JOB_HOME
mkdir -p $JOB_HOME/runset
touch $JOB_HOME/runset/custom
##################################################################################################################
# Run Calibre LVS/XRC
##################################################################################################################
if [ "$run_mr_drc" == "1" ]; then
if [ "$run_oas" == "1" ]; then
export RUNSET=$RUNSET_DIR/s8_drcmr_runset-oas # <-- then why earlier RUNSET=... ?
else
export RUNSET=$RUNSET_DIR/s8_drcmr_runset
fi
calibre -gui -drc -runset $RUNSET -batch > $JOB_HOME/logs/mr_drc.log
fi
if [ "$run_full_drc" == "1" ]; then
if [ "$run_oas" == "1" ]; then
export RUNSET=$RUNSET_DIR/s130_drc_runset-oas # <-- then why earlier RUNSET=... ?
else
export RUNSET=$RUNSET_DIR/s130_drc_runset
fi
calibre -gui -drc -runset $RUNSET -batch > $JOB_HOME/logs/full_drc.log
fi
if [ "$run_stress" == "1" ]; then
export RUNSET=$RUNSET_DIR/s8_stress_runset # <-- then why earlier RUNSET=... ?
calibre -gui -drc -runset $RUNSET -batch > $JOB_HOME/logs/stress.log
fi
if [ "$run_lures" == "1" ]; then
export RUNSET=$RUNSET_DIR/s130_lures_runset # <-- then why earlier RUNSET=... ?
calibre -gui -drc -runset $RUNSET -batch > $JOB_HOME/logs/lures.log
fi
if [ "$run_soft" == "1" ]; then
export RUNSET=$RUNSET_DIR/s8_soft_runset # <-- then why earlier RUNSET=... ?
calibre -gui -drc -runset $RUNSET -batch > $JOB_HOME/logs/soft.log
fi
if [[ "$run_lvs" == "1" && "$run_lvs_rcx" == "0" ]]; then
export RUNSET=$RUNSET_DIR/base # <-- then why earlier RUNSET=... ?
calibre -lvs $RUNSET -spice $JOB_HOME/cdl/$LAYOUT_EXTRACTED -hier 2>&1 | tee $JOB_HOME/logs/lvs.log
fi
if [ "$run_antenna_check" == "1" ]; then
export RUNSET=$RUNSET_DIR/s8_latchup_runset
calibre -gui -drc -runset $RUNSET -batch > $JOB_HOME/logs/latchup.log 2>&1
fi
##calibre -hier -64 -hyper -turbo -hcell $TEST_DIR/runsets/hcells.sky130_fd_sc_hd.txt -spice $JOB_HOME/cdl/$JOB_NAME.extracted.cdl $TEST_DIR/runsets/local_xrc_rules.2
if [[ "$run_lvs" == "1" && "$run_lvs_rcx" == "1" ]]; then
export RUNSET=$RUNSET_DIR/base # <-- then why earlier RUNSET=... ?
calibre -lvs -hier -hcell $HCELLS -spice \
$JOB_HOME/cdl/$LAYOUT_EXTRACTED $RUNSET \
| tee $JOB_HOME/logs/lvs.log
calibre -xrc -phdb -hcell $HCELLS -rc \
$RUNSET \
| tee $JOB_HOME/logs/phdb.log
calibre -xrc -pdb -xcell $XCELLS -rc \
$RUNSET \
| tee $JOB_HOME/logs/pdb.log
calibre -xrc -fmt -fmt_info -fmt_warnings $RUNSET \
| tee $JOB_HOME/logs/fmt.log
sed 's#//#DOUBLE_BACKSLASH#g' -i $PEX_NETLIST_PATH
sed 's#DIVIDER /#DIVIDER DIVIDER_BACKSLASH#g' -i $PEX_NETLIST_PATH
sed 's#/#\\/#g' -i $PEX_NETLIST_PATH
sed 's#DOUBLE_BACKSLASH#//#g' -i $PEX_NETLIST_PATH
sed 's#DIVIDER_BACKSLASH#/#g' -i $PEX_NETLIST_PATH
fi
# clean locally decompressed source-layout (so it avoids below 'find ... sed'; AND not checked-in to output* branch)
if [ -n "$GDS_DEL" ]; then
rm -f "$GDS_DEL"
echo "completed: rm -f $GDS_DEL"
fi
# calibre -lvs -hier -spice $JOB_HOME/cdl/$JOB_NAME.extracted.cdl $TEST_DIR/runsets/local_xrc_rules.2
# calibre -xrc -phdb -rc $TEST_DIR/runsets/local_xrc_rules.2
# calibre -xrc -pdb -rc $TEST_DIR/runsets/local_xrc_rules.2
# calibre -xrc -fmt $TEST_DIR/runsets/local_xrc_rules.2
# calibre -gui -lvs -runset $TEST_DIR/runsets/s8_lvs_runset -batch > $JOB_HOME/$JOB_NAME.lvs_runset.log 2>&1
#calibre -xrc -phdb -hcell $JOB_HOME/hcells.txt $PDK_HOME/LVS/Calibre/extLvsRules_s8_5lm
#calibre -gui -pex -runset $TEST_DIR/runsets/s8/V2.0.1/s8_xRC_runset -batch > $JOB_HOME/$JOB_NAME.xRC_runset.log 2>&1
#calibre -gui -lvs -runset $TEST_DIR/runsets/s8_lvs_runset -batch > $JOB_HOME/$JOB_NAME.lvs_runset.log 2>&1
#calibre --help > $JOB_HOME/$JOB_NAME.calibre--help.txt 2>&1
##################################################################################################################
# No-PEX extraction then using it as an LVS source to pass before running extraction
##################################################################################################################
# export LAYOUT_PRIMARY="$JOB_NAME"
# export LAYOUT_PATH="$JOB_HOME/$JOB_NAME.gds"
# export LAYOUT_NAME=$LAYOUT_PRIMARY
# export LVS_RUNSET_DIR="$PDK_HOME/LVS/Calibre"
# echo -en "LAYOUT SYSTEM GDSII\nLAYOUT PRIMARY $LAYOUT_PRIMARY\nLAYOUT PATH \"$LAYOUT_PATH\"\nERC RESULTS \
# DATABASE "ercdb"\nINCLUDE $LVS_RUNSET_DIR/lvsRules_s8" > spice_runset
#
# calibre -spice $JOB_HOME/$JOB_NAME.extracted.cdlX spice_runset > $JOB_HOME/$JOB_NAME.extract.runset.log 2>&1
# mkdir $JOB_HOME/extract
# mv lvs.rep.ext $JOB_HOME/extract/
# mv ercdb $JOB_HOME/extract/
# cp $JOB_HOME/$JOB_NAME.extracted.cdlX $JOB_HOME/extract/$JOB_NAME.extracted.cdlX
# cp spice_runset $JOB_HOME
##################################################################################################################
# Run Calibre DRC
##################################################################################################################
# calibre -gui -drc -runset $TEST_DIR/runsets/s8_drc_runset -batch > $JOB_HOME/$JOB_NAME.drc_runset.log 2>&1
# calibre -gui -drc -runset $TEST_DIR/runsets/s8_fill_runset -batch > $JOB_HOME/$JOB_NAME.fill_runset.log 2>&1
# calibre -gui -drc -runset $TEST_DIR/runsets/s8_latchup_runset -batch > $JOB_HOME/$JOB_NAME.latchup_runset.log 2>&1
# calibre -gui -drc -runset $TEST_DIR/runsets/s8_lures_runset -batch > $JOB_HOME/$JOB_NAME.lures_runset.log 2>&1
# calibre -gui -drc -runset $TEST_DIR/runsets/s8_soft_runset -batch > $JOB_HOME/$JOB_NAME.soft_runset.log 2>&1
# calibre -gui -drc -runset $TEST_DIR/runsets/s8_stress_runset -batch > $JOB_HOME/$JOB_NAME.stress_runset.log 2>&1
##################################################################################################################
find $JOB_HOME -type f -exec sed -i -e's/... [0-9][0-9] [0-9 ][0-9]:[0-9][0-9]:[0-9][0-9] 2.../... XX XX:XX:XX 2.../' \{\} \+
done
exit 0
#
# Compression: Calibre supposed to NATIVELY support gds.gz & gds.Z compression schemes,
# so why did we need to explicitly decompress 1st? Only for handling others (lz,xz)?
#
# OASIS NOTES: for OASIS (.oas) instead of GDSII (.gds):
# [decompressed] gds-file : ends in .oas.
# /runsets/ dir MAY become /runsets-oas/ which files embed (if not converted to IFDEF below):
# (Or base switched for base-oas which embed):
# *drcLayoutSystem: OASIS (instead of GDSII)
# *drcLayoutPaths: $JOB_HOME/$JOB_NAME.oas (instead of .gds)
#
# More than one of: .gds[.gz/.lz/.xz] .oas[.gz/.lz/.xz] is an error: ambiguous
#
# For runsets/gf180/DRC/base preprocessor (#IFDEF $LAYSYS_OASIS) switches between
# LAYOUT SYSTEM GDSII vs LAYOUT SYSTEM OASIS
# Is there a simpler way to directly substitute LAYOUT_SYSTEM from the shell-env like?:
# Following version has NOT been tried:
# VARIABLE LAYOUT_SYSTEM ENVIRONMENT
# LAYOUT SYSTEM LAYOUT_SYSTEM
#
# Wish to avoid extra oas-specific runsets files by export-ing env-vars LAYOUT_SYSTEM & JOB_EXT and:
# *drcLayoutSystem: $LAYOUT_SYSTEM
# *drcLayoutPaths: $JOB_HOME/$JOB_NAME.$JOB_EXT
#