-
Notifications
You must be signed in to change notification settings - Fork 0
/
manage_hls_projects.sh
executable file
·430 lines (360 loc) · 10.9 KB
/
manage_hls_projects.sh
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
#!/bin/bash
CLEAN_FLAG=false
BUILD_FLAG=false
TEST_FLAG=false
EXPORT_FLAG=false
CLEAN_EXPORT_FLAG=false
# These modules should be folders within ip_sources/hls that contain C++ source files + a Vivado HLS build TCL script
HLS_MODULES=${HLS_MODULES:=""}
# If using the --export flag, where should IP be exported to?
HLS_EXPORT_DIR=${HLS_EXPORT_DIR:="$(realpath ip_artifacts)"}
# Where are the HLS module folders located relative to this script?
HLS_MODULE_DIR="$(realpath ip_sources/hls)"
print_usage() {
echo ""
echo "Usage: "
cat << EOF
${0} [-h|--help]
${0} --clean [projects...]
${0} --build [projects...]
${0} --test [projects...]
${0} --export [projects...]
${0} --clean-export [projects...]
This script is used to clean, generate, or export artifacts from the provided Vivado HLS projects.
If no modules are specified, the following modules will be processed:
${HLS_MODULES}
Options:
[--clean]
Used to remove the generated artifacts associated with a given module or set of modules
[--build]
Used to build a given module or set of modules. Typically, each module will be "cleaned" prior to building via its TCL script.
[--test]
Executes tests for the underlying module or set of modules (if any are specific in their TCL scripts).
[--export]
Used to export generated artifacts associated with a given module or set of modules.
If a given artifact is not build, it triggers a build before exporting.
The export location is generally expected to be used as a Vivado IP repository folder.
[--clean-export]
Used to clean the export directory set by HLS_EXPORT_DIR (current value: ${HLS_EXPORT_DIR})
EOF
}
clean_hls_project() {
# Do we have enough arguments?
if [ "$#" -ne 1 ]; then
echo "${FUNCNAME[0]}: Missing argument <project_name>"
return 1
fi
# Did the one argument we get make sense?
case $1 in
-*)
echo "${FUNCNAME[0]}: Expecting argument to be a folder name"
return 1
;;
*)
# Make sure we're trimming a slash if the user put any
# Since we're going to staple .tcl onto the end
PROJECT_NAME=$(echo $1 | sed 's:/*$::')
;;
esac
# Does this argument correspond to a project directory?
if [ ! -d "${PROJECT_NAME}" ]; then
echo "${FUNCNAME[0]}: ${PROJECT_NAME} directory does not exist. Giving up!"
return 1
fi
pushd "${PROJECT_NAME}" >/dev/null
# Does this project have an old project directory?
if [ -d "${PROJECT_NAME}.proj" ]; then
echo "${FUNCNAME[0]}: Removing old project directory"
(set -x; rm -rf "${PROJECT_NAME}.proj")
else
echo "${FUNCNAME[0]}: No old project directory to clean"
fi
# Any messy log files to clean up?
if stat -t ${PROJECT_NAME}_*.log >/dev/null 2>&1; then
echo "${FUNCNAME[0]}: Removing old log files"
(set -x; rm ${PROJECT_NAME}_*.log)
else
echo "${FUNCNAME[0]}: No old log files to remove"
fi
popd >/dev/null
echo ""
echo "Your project is squeaky clean!"
return 0;
}
build_hls_project() {
# Do we have enough arguments?
if [ "$#" -ne 1 ]; then
echo "${FUNCNAME[0]}: Missing argument <project_name>"
return 1
fi
# Did the one argument we get make sense?
case $1 in
-*)
echo "${FUNCNAME[0]}: Expecting argument to be a folder name"
return 1
;;
*)
# Make sure we're trimming a slash if the user put any
# Since we're going to staple .tcl onto the end
PROJECT_NAME=$(echo $1 | sed 's:/*$::')
;;
esac
# Does this argument correspond to a project directory?
if [ ! -d "${PROJECT_NAME}" ]; then
echo "${FUNCNAME[0]}: ${PROJECT_NAME} directory does not exist. Giving up!"
return 1
fi
pushd "${PROJECT_NAME}" >/dev/null
# Does this project have a TCL script to source?
if [ ! -f "${PROJECT_NAME}.tcl" ]; then
echo "${FUNCNAME[0]}: ${PROJECT_NAME}.tcl does not exist"
return 1
fi
# Do we have vivado_hls available?
if ! type vivado_hls >/dev/null 2>&1; then
echo "${FUNCNAME[0]}: Vivado HLS is not on the current PATH. Please source the appropriate environment script and try again"
return 1
fi
# Run the build process
STAMP=$(date "+%Y.%m.%d-%H.%M.%S")
vivado_hls -f "${PROJECT_NAME}.tcl" -l "${PROJECT_NAME}_build_${STAMP}.log" tclargs "build"
retval="$?"
echo -e "\n\n"
if [ "${retval}" -eq 0 ]; then
echo -e "${FUNCNAME[0]}: Vivado HLS returned a status code of 0, so everything's probably fine (but check \"${PROJECT_NAME}/${PROJECT_NAME}_build_${STAMP}.log\" for details)\n"
popd >/dev/null
return 0
else
echo -e "${FUNCNAME[0]}: Vivado HLS returned a non-zero status code. Might want to check \"${PROJECT_NAME}/${PROJECT_NAME}_build_${STAMP}.log\" for details)\n"
popd >/dev/null
return 1
fi
}
test_hls_project() {
# Do we have enough arguments?
if [ "$#" -ne 1 ]; then
echo "${FUNCNAME[0]}: Missing argument <project_name>"
return 1
fi
# Did the one argument we get make sense?
case $1 in
-*)
echo "${FUNCNAME[0]}: Expecting argument to be a folder name"
return 1
;;
*)
# Make sure we're trimming a slash if the user put any
# Since we're going to staple .tcl onto the end
PROJECT_NAME=$(echo $1 | sed 's:/*$::')
;;
esac
# Does this argument correspond to a project directory?
if [ ! -d "${PROJECT_NAME}" ]; then
echo "${FUNCNAME[0]}: ${PROJECT_NAME} directory does not exist. Giving up!"
return 1
fi
pushd "${PROJECT_NAME}" >/dev/null
# Does this project have a TCL script to source?
if [ ! -f "${PROJECT_NAME}.tcl" ]; then
echo "${FUNCNAME[0]}: ${PROJECT_NAME}.tcl does not exist"
return 1
fi
# Do we have vivado_hls available?
if ! type vivado_hls >/dev/null 2>&1; then
echo "${FUNCNAME[0]}: Vivado HLS is not on the current PATH. Please source the appropriate environment script and try again"
return 1
fi
# Run the testing process
STAMP=$(date "+%Y.%m.%d-%H.%M.%S")
vivado_hls -f "${PROJECT_NAME}.tcl" -l "${PROJECT_NAME}_build_${STAMP}.log" tclargs "test"
retval="$?"
echo -e "\n\n"
if [ "${retval}" -eq 0 ]; then
echo -e "${FUNCNAME[0]}: Vivado HLS returned a status code of 0, so everything's probably fine (but check \"${PROJECT_NAME}/${PROJECT_NAME}_build_${STAMP}.log\" for details)\n"
popd >/dev/null
return 0
else
echo -e "${FUNCNAME[0]}: Vivado HLS returned a non-zero status code. Might want to check \"${PROJECT_NAME}/${PROJECT_NAME}_build_${STAMP}.log\" for details)\n"
popd >/dev/null
return 1
fi
}
export_hls_project() {
# Do we have enough arguments?
if [ "$#" -ne 1 ]; then
echo "${FUNCNAME[0]}: Missing argument <project_name>"
return 1
fi
# Did the one argument we get make sense?
case $1 in
-*)
echo "${FUNCNAME[0]}: Expecting argument to be a folder name"
return 1
;;
*)
# Make sure we're trimming a slash if the user put any
# Since we're going to staple .tcl onto the end
PROJECT_NAME=$(echo $1 | sed 's:/*$::')
;;
esac
# Does this argument correspond to a project directory?
if [ ! -d "${PROJECT_NAME}" ]; then
echo "${FUNCNAME[0]}: ${PROJECT_NAME} directory does not exist. Giving up!"
return 1
fi
# Does this project have a generated project directory?
if [ -d "${PROJECT_NAME}/${PROJECT_NAME}.proj" ]; then
echo "${FUNCNAME[0]}: Project directory exists. No need to build prior to export."
else
echo "${FUNCNAME[0]}: Project directory does not exist. Building prior to export."
build_hls_project ${PROJECT_NAME}
if [ "$?" -ne 0 ]; then
echo "${FUNCNAME[0]}: Project build prior to export failed"
return 1
fi
fi
echo "${FUNCNAME[0]}: Exporting ${PROJECT_NAME} IP to ${HLS_EXPORT_DIR}/${PROJECT_NAME}"
mkdir -p "${HLS_EXPORT_DIR}/${PROJECT_NAME}"
(set -x; rsync -a "${PROJECT_NAME}/${PROJECT_NAME}.proj/soln/impl/ip/" "${HLS_EXPORT_DIR}/${PROJECT_NAME}/" --delete)
echo -e "${FUNCNAME[0]}: IP export complete for ${PROJECT_NAME}\n"
return 0
}
clean_export_for_module() {
# Do we have enough arguments?
if [ "$#" -ne 1 ]; then
echo "${FUNCNAME[0]}: Missing argument <project_name>"
return 1
fi
# Did the one argument we get make sense?
case $1 in
-*)
echo "${FUNCNAME[0]}: Expecting argument to be a folder name"
return 1
;;
*)
# Make sure we're trimming a slash if the user put any
# Since we're going to staple .tcl onto the end
PROJECT_NAME=$(echo $1 | sed 's:/*$::')
;;
esac
# Does this argument correspond to a directory of an exported IP?
if [ ! -d "${HLS_EXPORT_DIR}/${PROJECT_NAME}" ]; then
echo "${FUNCNAME[0]}: Directory ${HLS_EXPORT_DIR}/${PROJECT_NAME} does not exist. Nothing to clean..."
else
echo "${FUNCNAME[0]}: Removing directory ${HLS_EXPORT_DIR}/${PROJECT_NAME}"
(set -x; rm -rf ${HLS_EXPORT_DIR}/${PROJECT_NAME})
fi
echo ""
return 0
}
### Main logic of the script ###
if [ "$#" -lt 1 ]; then
print_usage
exit 1
fi
while (( "$#" )); do
case $1 in
-h|--help)
print_usage
exit 0
;;
--build)
BUILD_FLAG=true
shift 1
;;
--test)
TEST_FLAG=true
shift 1
;;
--clean)
CLEAN_FLAG=true
shift 1
;;
--export)
EXPORT_FLAG=true
shift 1
;;
--clean-export)
CLEAN_EXPORT_FLAG=true
shift 1
;;
*)
HLS_MODULES="$@"
break
;;
esac
done
echo "Entering directory ${HLS_MODULE_DIR}"
pushd ${HLS_MODULE_DIR} >/dev/null
if [ "${CLEAN_FLAG}" = true ]; then
echo ""
echo "Cleaning modules"
cat <<EOF
${HLS_MODULES}
EOF
for module in ${HLS_MODULES}; do
clean_hls_project ${module}
if [ "$?" -ne 0 ]; then
echo "clean_hls_project returned with an error, exiting..."
exit 1
fi
done
fi
if [ "${BUILD_FLAG}" = true ]; then
echo ""
echo "Building modules"
cat <<EOF
${HLS_MODULES}
EOF
for module in ${HLS_MODULES}; do
build_hls_project ${module}
if [ "$?" -ne 0 ]; then
echo "build_hls_project returned with an error, exiting..."
exit 1
fi
done
fi
if [ "${TEST_FLAG}" = true ]; then
echo ""
echo "Testing modules"
cat <<EOF
${HLS_MODULES}
EOF
for module in ${HLS_MODULES}; do
test_hls_project ${module}
if [ "$?" -ne 0 ]; then
echo "test_hls_project returned with an error, exiting..."
exit 1
fi
done
fi
if [ "${EXPORT_FLAG}" = true ]; then
echo ""
echo "Exporting modules"
cat <<EOF
${HLS_MODULES}
EOF
for module in ${HLS_MODULES}; do
export_hls_project ${module}
if [ "$?" -ne 0 ]; then
echo "export_hls_project returned with an error, exiting..."
exit 1
fi
done
fi
if [ "${CLEAN_EXPORT_FLAG}" = true ]; then
echo ""
echo "Cleaning the export directory for modules"
cat <<EOF
${HLS_MODULES}
EOF
for module in ${HLS_MODULES}; do
clean_export_for_module ${module}
if [ "$?" -ne 0 ]; then
echo "clean_export_for_module returned with an error, exiting..."
exit 1
fi
done
fi
popd >/dev/null
exit 0