aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/tools/scripts/setupenv_base.sh
blob: 4fa00d8436c374bae7122651eb56da3620059817 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
#!/bin/bash
#
# Copyright 2015 Ettus Research
#

#----------------------------------------------------------------------------
# Global defaults
#----------------------------------------------------------------------------
export VIV_PLATFORM=$(uname -o)

# Vivado specific
if [[ $VIV_PLATFORM = "Cygwin" ]]; then
    if [[ -d "/cygdrive/c/Xilinx/Vivado_Lab" ]]; then
        VIVADO_BASE_PATH="/cygdrive/c/Xilinx/Vivado_Lab"
    else
        VIVADO_BASE_PATH="/cygdrive/c/Xilinx/Vivado"
    fi
    MODELSIM_BASE_PATH="/cygdrive/c/mentor/modelsim"
else
    if [[ -d "/tools/Xilinx/Vivado_Lab" ]]; then
        VIVADO_BASE_PATH="/tools/Xilinx/Vivado_Lab"
    elif [[ -d "/tools/Xilinx/Vivado" ]]; then
        VIVADO_BASE_PATH="/tools/Xilinx/Vivado"
    elif [[ -d "/opt/Xilinx/Vivado_Lab" ]]; then
        VIVADO_BASE_PATH="/opt/Xilinx/Vivado_Lab"
    else
        VIVADO_BASE_PATH="/opt/Xilinx/Vivado"
    fi
    MODELSIM_BASE_PATH="/opt/mentor/modelsim"
fi

function resolve_viv_path {
    if [[ $VIV_PLATFORM = "Cygwin" ]]; then
        echo $(cygpath -aw $1)
    else
        echo $1
    fi
}

#----------------------------------------------------------------------------
# Help message display function
#----------------------------------------------------------------------------
function setupenv_help {
    cat <<EOHELP

Usage: source setupenv.sh [--help|-h] [--vivado-path=<PATH>] [--modelsim-path=<PATH>]

--vivado-path   : Path to the base install directory for Xilinx Vivado if it is
                  not installed in one of the default search locations (e.g.,
                  /opt/Xilinx/Vivado).
--modelsim-path : Path to the base install directory for ModelSim if it is not
                  installed in one of the default search locations (e.g.,
                  /opt/mentor/modelsim). This simulation tool is optional.
--help -h       : Shows this message.

This script sets up the environment required to build FPGA images for the Ettus Research
${DISPLAY_NAME}. It will also optionally set up the the environment to run the
Modelsim simulator (although this tool is not required).

Required tools: Xilinx Vivado $VIVADO_VER (Synthesis and Simulation)
Optional tools: Mentor Graphics Modelsim (Simulation)

EOHELP
}


#----------------------------------------------------------------------------
# Validate prerequisites
#----------------------------------------------------------------------------
# Ensure required variables
if [ -z "$REPO_BASE_PATH" ]; then
    echo "ERROR: Please define the variable REPO_BASE_PATH before calling this script"
    return
fi
if [ -z "$VIVADO_VER" ]; then
    echo "ERROR: Please define the variable VIVADO_VER before calling this script"
    return
fi
if [ -z "$DISPLAY_NAME" ]; then
    echo "ERROR: Please define the variable DISPLAY_NAME before calling this script"
    return
fi
if [ ${#PRODUCT_ID_MAP[@]} -eq 0 ]; then
    echo "ERROR: Please define the variable PRODUCT_ID_MAP before calling this script"
    return
fi

# Ensure that the script is sourced directly or from another script, and not
# executed.
if [[ ${BASH_SOURCE[0]} == "$0" || ${BASH_SOURCE[1]} == "$0" ]]; then
    echo "ERROR: This script must be sourced."
    setupenv_help
    exit 1
fi

#----------------------------------------------------------------------------
# Setup and parse command line
#----------------------------------------------------------------------------
# Detect platform bitness
if [ "$(uname -m)" = "x86_64" ]; then
    BITNESS="64"
else
    BITNESS="32"
fi

# Go through cmd line options
MODELSIM_REQUESTED=0
MODELSIM_FOUND=0
PARSE_STATE=""
for i in "$@"; do
    case $i in
        -h|--help)
            setupenv_help
            return 0
            ;;
        --vivado-path=*)
            VIVADO_BASE_PATH="${i#*=}"
            PARSE_STATE=""
        ;;
        --vivado-path)
            PARSE_STATE="vivado-path"
        ;;
        --vivado-version=*)
            VIVADO_USER_VER="${i#*=}"
            PARSE_STATE=""
        ;;
        --vivado-version)
            PARSE_STATE="vivado-version"
        ;;
        --modelsim-path=*)
            MODELSIM_BASE_PATH="${i#*=}"
            MODELSIM_REQUESTED=1
            PARSE_STATE=""
        ;;
        --modelsim-path)
            PARSE_STATE="modelsim-path"
        ;;
        *)
            case $PARSE_STATE in
                vivado-path)
                    VIVADO_BASE_PATH="$i"
                    PARSE_STATE=""
                ;;
                vivado-version)
                    VIVADO_USER_VER="$i"
                    PARSE_STATE=""
                ;;
                modelsim-path)
                    MODELSIM_BASE_PATH="$i"
                    MODELSIM_REQUESTED=1
                    PARSE_STATE=""
                ;;
                *)
                    echo "ERROR: Unrecognized option: $i"
                    setupenv_help
                    return 1
                ;;
            esac
        ;;
    esac
done

# Vivado environment setup
if [[ ${VIVADO_VER^^} = "CMDLINE_ARG" ]]; then
    if [[ -z $VIVADO_USER_VER ]]; then
        echo "ERROR: The --vivado-version argument must be specified when the env version is \"CMDLINE_ARG\""
        return 1
    else
        VIVADO_VER=$VIVADO_USER_VER
    fi
fi
export VIVADO_PATH=$VIVADO_BASE_PATH/$VIVADO_VER

echo "Setting up a ${BITNESS}-bit FPGA build environment for the ${DISPLAY_NAME}..."
#----------------------------------------------------------------------------
# Prepare Vivado environment
#----------------------------------------------------------------------------
if [ -d "$VIVADO_PATH/bin" ]; then
    echo "- Vivado: Found ($VIVADO_PATH/bin)"
else
    echo "- Vivado: Version $VIVADO_VER not found in $VIVADO_BASE_PATH (ERROR.. Builds and simulations will not work)"
    if [[ -z $VIVADO_USER_VER ]]; then
        echo "          Use the --vivado-path option to override the search path"
    else
        echo "          Use the --vivado-path option to override the search path or specify the correct --vivado-version"
    fi
    unset VIVADO_USER_VER
    return 1
fi

$VIVADO_PATH/settings${BITNESS}.sh
if [[ -e $VIVADO_PATH/.settings${BITNESS}-Vivado_Lab.sh ]]; then
    $VIVADO_PATH/.settings${BITNESS}-Vivado_Lab.sh
else
    $VIVADO_PATH/.settings${BITNESS}-Vivado.sh
fi
if [[ -e $(readlink -f $VIVADO_BASE_PATH/..)/DocNav/.settings${BITNESS}-DocNav.sh ]]; then
    $(readlink -f $VIVADO_BASE_PATH/..)/DocNav/.settings${BITNESS}-DocNav.sh
fi

if [[ -x `which tput 2>/dev/null` ]] ; then
    export VIV_COLOR_SCHEME=default
fi
VIVADO_EXEC="$REPO_BASE_PATH/tools/scripts/launch_vivado.sh"

# If an extended (i.e. full) version is provided, use Vivado to check
# that the installed version is correct.
# This optional env variable may be used to check for specific Vivado
# Updates or Patches to be installed.
# If multiple patches are installed, it is recommended that the user
# runs 'vivado -version' from the installation directory to determine
# the order in which patches were applied by Vivado.
# Example:
#   VIVADO_VER=2019.1
#   VIVADO_VER_FULL=2019.1.1_AR73068
# The setupenv.sh script will setup Vivado 2019.1, but it will also
# verify that both Update 1 and patch AR73068 are installed.
if [[ -n $VIVADO_VER_FULL ]]; then
    INSTALLED_VIV=$($VIVADO_PATH/bin/vivado -version | grep $VIVADO_VER_FULL)
    if [[ $? -eq 0 ]]; then
        echo "          Installed version is $INSTALLED_VIV"
    else
        echo "- Vivado: ERROR! Requested version ($VIVADO_VER_FULL) not installed."
        echo "          Install the required updates/patches and verify that the env variable"
        echo "          \"VIVADO_VER_FULL\" matches the version printed by \"vivado -version\"."
        return 1
    fi
fi

#----------------------------------------------------------------------------
# Prepare Modelsim environment
#----------------------------------------------------------------------------
if [[ -d $MODELSIM_BASE_PATH ]]; then
    if [[ $VIV_PLATFORM = "Cygwin" ]]; then
        VSIM_PATH=$(find -L $MODELSIM_BASE_PATH -maxdepth 3 -wholename '*win*/vsim.exe' | head -n 1)
    else
        VSIM_PATH=$(find -L $MODELSIM_BASE_PATH -maxdepth 3 -wholename '*linux*/vsim' | head -n 1)
    fi
fi
if [[ $VSIM_PATH ]]; then
    if [[ $($VSIM_PATH -version) =~ .*ModelSim[[:space:]](.+)[[:space:]]vsim.* ]]; then
        MODELSIM_VER=${BASH_REMATCH[1]}
        MODELSIM_PATH=$(dirname $VSIM_PATH)
    fi
    case $MODELSIM_VER in
        DE-64|SE-64)
            export MODELSIM_64BIT=1
            if [[ -z $MSIM_VIV_COMPLIBDIR ]]; then
                export SIM_COMPLIBDIR=$VIVADO_PATH/modelsim64
            else
                export SIM_COMPLIBDIR=$MSIM_VIV_COMPLIBDIR
            fi
        ;;
        DE|SE|PE)
            export MODELSIM_64BIT=0
            if [[ -z $MSIM_VIV_COMPLIBDIR ]]; then
                export SIM_COMPLIBDIR=$VIVADO_PATH/modelsim32
            else
                export SIM_COMPLIBDIR=$MSIM_VIV_COMPLIBDIR
            fi
        ;;
        *)
        ;;
    esac
    # If MSIM_MODELSIM_INI is not defined, use the modelsim.ini in the compiled
    # libraries directory. Otherwise use the one defined by MSIM_MODELSIM_INI.
    # Set MSIM_MODELSIM_INI to an empty string to use the modelsim.ini in the
    # ModelSim installation folder.
    if [[ ! -v MSIM_MODELSIM_INI ]]; then
        export MODELSIM_INI=$SIM_COMPLIBDIR/modelsim.ini
    fi
fi

function build_simlibs {
    mkdir -p $SIM_COMPLIBDIR
    pushd $SIM_COMPLIBDIR
    CMD_PATH=`mktemp XXXXXXXX.vivado_simgen.tcl`
    if [[ $MODELSIM_64BIT -eq 1 ]]; then
        echo "compile_simlib -force -simulator modelsim -family all -language all -library all -directory $SIM_COMPLIBDIR" > $CMD_PATH
    else
        echo "compile_simlib -force -simulator modelsim -family all -language all -library all -32 -directory $SIM_COMPLIBDIR" > $CMD_PATH
    fi
    $VIVADO_EXEC -mode batch -source $(resolve_viv_path $CMD_PATH) -nolog -nojournal
    rm -f $CMD_PATH
    popd
}

if [[ $MODELSIM_VER ]]; then
    echo "- Modelsim: Found ($MODELSIM_VER, $MODELSIM_PATH)"
    if [[ -e "$SIM_COMPLIBDIR/modelsim.ini" ]]; then
        echo "- Modelsim Compiled Libs: Found ($SIM_COMPLIBDIR)"
    else
        echo "- Modelsim Compiled Libs: Not found! (Run build_simlibs to generate them.)"
    fi
else
    if [[ $MODELSIM_REQUESTED -eq 1 ]]; then
        echo "- Modelsim: Not found in $MODELSIM_BASE_PATH (WARNING.. Simulations with vsim will not work)"
    fi
fi

#----------------------------------------------------------------------------
# Misc export variables
#----------------------------------------------------------------------------
export PATH=$(echo ${PATH} | tr ':' '\n' | awk '$0 !~ "/Vivado/"' | paste -sd:)
export PATH=${PATH}:$VIVADO_PATH:$VIVADO_PATH/bin:$VIVADO_HLS_PATH:$VIVADO_HLS_PATH/bin:$MODELSIM_PATH

for prod in "${!PRODUCT_ID_MAP[@]}"; do
    IFS='/' read -r -a prod_tokens <<< "${PRODUCT_ID_MAP[$prod]}"
    if [ ${#prod_tokens[@]} -eq 6 ]; then
        export XIL_ARCH_${prod}=${prod_tokens[0]}
        export XIL_PART_ID_${prod}=${prod_tokens[1]}/${prod_tokens[2]}/${prod_tokens[3]}/${prod_tokens[4]}/${prod_tokens[5]}
    elif [ ${#prod_tokens[@]} -eq 5 ]; then
        export XIL_ARCH_${prod}=${prod_tokens[0]}
        export XIL_PART_ID_${prod}=${prod_tokens[1]}/${prod_tokens[2]}/${prod_tokens[3]}/${prod_tokens[4]}
    elif [ ${#prod_tokens[@]} -eq 4 ]; then
        export XIL_ARCH_${prod}=${prod_tokens[0]}
        export XIL_PART_ID_${prod}=${prod_tokens[1]}/${prod_tokens[2]}/${prod_tokens[3]}
    else
        echo "ERROR: Invalid PRODUCT_ID_MAP entry: \"${PRODUCT_ID_MAP[$prod]}\". Must be <arch>/<part>/<pkg>/<sg>[/<tg>[/<rev>]]."
        return 1
    fi
done

#----------------------------------------------------------------------------
# Define IP management aliases
#----------------------------------------------------------------------------
# Vivado specific
VIV_IP_UTILS=$REPO_BASE_PATH/tools/scripts/viv_ip_utils.tcl

function viv_create_ip {
    if [[ -z $1 || -z $2 || -z $3 || -z $4 ]]; then
        echo "Create a new Vivado IP instance and a Makefile for it"
        echo ""
        echo "Usage: viv_create_new_ip <IP Name> <IP Location> <IP VLNV> <Product>"
        echo "- <IP Name>: Name of the IP instance"
        echo "- <IP Location>: Base location for IP"
        echo "- <IP VLNV>: The vendor, library, name, and version (VLNV) string for the IP as defined by Xilinx"
        echo "- <Product>: Product to generate IP for. Choose from: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi

    ip_name=$1
    ip_dir=$(readlink -f $2)
    ip_vlnv=$3
    part_name=$(python3 $REPO_BASE_PATH/tools/scripts/viv_gen_part_id.py "${PRODUCT_ID_MAP[$4]}")
    if [[ $? -ne 0 ]]; then
        echo "ERROR: Invalid product name $4. Supported: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi
    if [[ -d $ip_dir/$ip_name ]]; then
        echo "ERROR: IP $ip_dir/$ip_name already exists. Please choose a different name."
        return 1
    fi

    $VIVADO_EXEC -mode gui -source $(resolve_viv_path $VIV_IP_UTILS) -nolog -nojournal -tclargs create $part_name $ip_name $(resolve_viv_path $ip_dir) $ip_vlnv
    echo "Generating Makefile..."
    python3 $REPO_BASE_PATH/tools/scripts/viv_gen_ip_makefile.py --ip_name=$ip_name --dest=$ip_dir/$ip_name
    echo "Done generating IP in $ip_dir/$ip_name"
}

function viv_modify_ip {
    if [[ -z $1 ]]; then
        echo "Modify an existing Vivado IP instance"
        echo ""
        echo "Usage: viv_modify_ip <IP XCI Path>"
        echo "- <IP XCI Path>: Path to the IP XCI file."
        return 1
    fi

    xci_path=$(readlink -f $1)
    part_name=$(python3 $REPO_BASE_PATH/tools/scripts/viv_ip_xci_editor.py read_part $xci_path)
    if [[ -z $part_name ]]; then
        echo "ERROR: Invalid part name $part_name. XCI parse error."
        return 1
    fi
    if [[ -f $xci_path ]]; then
        $VIVADO_EXEC -mode gui -source $(resolve_viv_path $VIV_IP_UTILS) -nolog -nojournal -tclargs modify $part_name $(resolve_viv_path $xci_path)
    else
        echo "ERROR: IP $xci_path not found."
        return 1
    fi
}

function viv_modify_bd {
    if [[ -z $1 || -z $2 ]]; then
        echo "Modify an existing Vivado Block Design instance"
        echo ""
        echo "Usage: viv_modify_bd <BD Path> <Product>"
        echo "- <BD Path>: Path to the BD file."
        echo "- <Product>: Product to generate IP for. Choose from: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi

    bd_path=$(readlink -f $1)
    part_name=$(python3 $REPO_BASE_PATH/tools/scripts/viv_gen_part_id.py "${PRODUCT_ID_MAP[$2]}")
    if [[ $? -ne 0 ]]; then
        echo "ERROR: Invalid product name $2. Supported: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi
    if [[ -f $bd_path ]]; then
        $VIVADO_EXEC -mode gui -source $(resolve_viv_path $VIV_IP_UTILS) -nolog -nojournal -tclargs modify $part_name $(resolve_viv_path $bd_path)
    else
        echo "ERROR: IP $bd_path not found."
        return 1
    fi
}

function viv_modify_tcl_bd {
    if [[ -z $1 || -z $2 ]]; then
        echo "Modify an existing Vivado TCL-based Block Design instance."
        echo ""
        echo "Usage: viv_modify_bd_tcl <TCL Path> <Product>"
        echo "- <TCL Path>: Path to the TCL source file."
        echo "- <Product> : Product to generate IP for. Choose from: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi

    src_path=$(readlink -f $1)
    part_name=$(python3 $REPO_BASE_PATH/tools/scripts/viv_gen_part_id.py "${PRODUCT_ID_MAP[$2]}")
    if [[ $? -ne 0 ]]; then
        echo "ERROR: Invalid product name $2. Supported: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi
    bd_ip_repo="${src_path%/top*}/lib/vivado_ipi"
    if [[ -f $src_path ]]; then
        $VIVADO_EXEC -mode gui -source $(resolve_viv_path $VIV_IP_UTILS) -nolog -nojournal -tclargs modify_bdtcl $part_name $(resolve_viv_path $src_path) $(resolve_viv_path $bd_ip_repo)
        echo "INFO: Vivado BD was closed, writing source TCL..."
        $VIVADO_EXEC -mode batch -source $(resolve_viv_path $VIV_IP_UTILS) -nolog -nojournal -tclargs write_bdtcl $part_name $(resolve_viv_path $src_path)
    else
        echo "ERROR: IP $src_path not found."
        return 1
    fi
}

function viv_ls_ip {
    if [[ -z $1 ]]; then
        echo "List the items in the Vivado IP catalog"
        echo ""
        echo "Usage: viv_ls_ip <Product>"
        echo "- <Product>: Product to generate IP for. Choose from: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi

    part_name=$(python3 $REPO_BASE_PATH/tools/scripts/viv_gen_part_id.py "${PRODUCT_ID_MAP[$1]}")
    if [[ $? -ne 0 ]]; then
        echo "ERROR: Invalid product name $1. Supported: ${!PRODUCT_ID_MAP[@]}"
        return 1
    fi
    $VIVADO_EXEC -mode batch -source $(resolve_viv_path $VIV_IP_UTILS) -nolog -nojournal -tclargs list $part_name | grep -v -E '(^$|^#|\*\*)'
    test ${PIPESTATUS[0]} -eq 0
}

function viv_upgrade_ip {
    if [[ -z $1 ]]; then
        echo "Upgrade one or more Xilinx IP targets"
        echo ""
        echo "Usage: viv_upgrade_ip <IP Directory> [--recursive]"
        echo "- <IP Directory>: Path to the IP XCI file."
        return 1
    fi
    max_depth="-maxdepth 1"
    if [[ $2 == "--recursive" ]]; then
        max_depth=""
    fi
    search_path=$(readlink -f $1)
    IFS='' read -r -a xci_files <<< $(find $search_path $max_depth | grep .xci | xargs)
    for xci_path in $xci_files; do
        if [[ -f $xci_path ]]; then
            echo "Upgrading $xci_path..."
            part_name=$(python3 $REPO_BASE_PATH/tools/scripts/viv_ip_xci_editor.py read_part $xci_path)
            $VIVADO_EXEC -mode batch -source $(resolve_viv_path $VIV_IP_UTILS) -nolog -nojournal -tclargs upgrade $part_name $(resolve_viv_path $xci_path) | grep -v -E '(^$|^#|\*\*)'
            test ${PIPESTATUS[0]} -eq 0
        else
            echo "ERROR: IP $xci_path not found."
            return 1
        fi
    done
}

#----------------------------------------------------------------------------
# Define hardware programming aliases
#----------------------------------------------------------------------------
VIV_HW_UTILS=$REPO_BASE_PATH/tools/scripts/viv_hardware_utils.tcl

function viv_hw_console {
    vivado -mode tcl -source $(resolve_viv_path $VIV_HW_UTILS) -nolog -nojournal
}

function viv_jtag_list {
    $VIVADO_EXEC -mode batch -source $(resolve_viv_path $VIV_HW_UTILS) -nolog -nojournal -tclargs list | grep -v -E '(^$|^#|\*\*)'
    test ${PIPESTATUS[0]} -eq 0
}

function viv_jtag_program {
    if [[ -z $1 ]]; then
        echo "Downloads a bitfile to an FPGA device using Vivado"
        echo ""
        echo "Usage: viv_jtag_program <Bitfile Path> [<FTDI Serial> = .] [<Device Address> = 0:0]"
        echo "- <Bitfile Path>: Path to a .bit FPGA configuration file"
        echo "- <FTDI Serial>: Regular expression for filtering out devices by"
        echo "                 their FTDI serial"
        echo "- <Device Address>: Address to the device in the form <Target>:<Device>"
        echo "                    Run viv_jtag_list to get a list of connected devices"
        return 1
    fi
    $VIVADO_EXEC -mode batch -source $(resolve_viv_path $VIV_HW_UTILS) -nolog -nojournal -tclargs program $* | grep -v -E '(^$|^#|\*\*)'
    test ${PIPESTATUS[0]} -eq 0
}

function probe_bitfile {
    if [[ -z $1 ]]; then
        echo "Probe a Xilinx bit file and report header information"
        echo ""
        echo "Usage: probe_bitfile <Bitfile Path>"
        echo "- <Bitfile Path>: Path to a .bit FPGA configuration file"
        return 1
    fi
    python3 $REPO_BASE_PATH/tools/scripts/xil_bitfile_parser.py --info $1
}

echo
echo "Environment successfully initialized."
return 0