labview-fpga-hdl-tools 2.0.0.dev2__tar.gz → 2.0.0.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/PKG-INFO +5 -5
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/README.md +2 -2
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/__main__.py +3 -2
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/check_syntax.py +21 -27
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/common.py +69 -25
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/compile_modelsim_lib.py +24 -27
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/compile_project.py +25 -31
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/create_lvbitx.py +6 -5
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/create_modelsim_project.py +8 -9
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/create_vivado_project.py +39 -40
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/gen_labview_target_plugin.py +29 -40
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/generate_vhdl.py +20 -17
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/get_window_netlist.py +19 -16
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/install_dependencies.py +14 -4
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/install_labview_target_plugin.py +37 -23
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/launch_modelsim.py +14 -12
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/launch_vivado.py +18 -12
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/migrate_clip.py +28 -26
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/process_constraints.py +3 -3
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/sim_modelsim.py +8 -8
- labview_fpga_hdl_tools-2.0.0.dev4/pyproject.toml +75 -0
- labview_fpga_hdl_tools-2.0.0.dev2/pyproject.toml +0 -50
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/LICENSE +0 -0
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/.gitignore +0 -0
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/__init__.py +0 -0
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/command_config.py +0 -0
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/command_hooks.py +0 -0
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/nihdlsettings_default.py +0 -0
- {labview_fpga_hdl_tools-2.0.0.dev2 → labview_fpga_hdl_tools-2.0.0.dev4}/labview_fpga_hdl_tools/reporting.py +0 -0
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: labview-fpga-hdl-tools
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev4
|
|
4
4
|
Summary: LabVIEW FPGA HDL Tools
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Salvador Santolucito
|
|
7
7
|
Author-email: salvador.santolucito@gmail.com
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.10,<3.15
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
15
|
Requires-Dist: click (>=8.1.8,<8.2)
|
|
16
|
+
Requires-Dist: defusedxml (>=0.7.1)
|
|
17
17
|
Requires-Dist: mako (>=1.3.10)
|
|
18
18
|
Requires-Dist: packaging (>=21.0)
|
|
19
19
|
Requires-Dist: tomli (>=1.1.0) ; python_version < "3.11"
|
|
@@ -66,8 +66,8 @@ You need the external tools your flow uses:
|
|
|
66
66
|
- **ModelSim** — only for simulation (`gen-modelsim`, `sim-modelsim`,
|
|
67
67
|
`launch-modelsim`, `compile-modelsim-lib`). `compile-modelsim-lib` also needs
|
|
68
68
|
Vivado to compile the Xilinx simulation libraries.
|
|
69
|
-
- **Git** and **Python** — the tools support Python 3.
|
|
70
|
-
3.
|
|
69
|
+
- **Git** and **Python** — the tools support Python 3.10–3.14; CI tests on
|
|
70
|
+
3.10 through 3.14 (3.11 is also used for static analysis).
|
|
71
71
|
|
|
72
72
|
### Installing the tools
|
|
73
73
|
|
|
@@ -45,8 +45,8 @@ You need the external tools your flow uses:
|
|
|
45
45
|
- **ModelSim** — only for simulation (`gen-modelsim`, `sim-modelsim`,
|
|
46
46
|
`launch-modelsim`, `compile-modelsim-lib`). `compile-modelsim-lib` also needs
|
|
47
47
|
Vivado to compile the Xilinx simulation libraries.
|
|
48
|
-
- **Git** and **Python** — the tools support Python 3.
|
|
49
|
-
3.
|
|
48
|
+
- **Git** and **Python** — the tools support Python 3.10–3.14; CI tests on
|
|
49
|
+
3.10 through 3.14 (3.11 is also used for static analysis).
|
|
50
50
|
|
|
51
51
|
### Installing the tools
|
|
52
52
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""LVFPGAHDLTools - Command-line interface for LabVIEW FPGA HDL Tools."""
|
|
3
|
+
|
|
3
4
|
# Copyright (c) 2025 National Instruments Corporation
|
|
4
5
|
#
|
|
5
6
|
# SPDX-License-Identifier: MIT
|
|
@@ -11,7 +12,7 @@ import traceback
|
|
|
11
12
|
import click
|
|
12
13
|
|
|
13
14
|
# Import main functions from all the tool modules
|
|
14
|
-
from
|
|
15
|
+
from labview_fpga_hdl_tools import (
|
|
15
16
|
__version__,
|
|
16
17
|
check_syntax,
|
|
17
18
|
command_hooks,
|
|
@@ -32,7 +33,7 @@ from . import (
|
|
|
32
33
|
process_constraints,
|
|
33
34
|
sim_modelsim,
|
|
34
35
|
)
|
|
35
|
-
from .reporting import reporter
|
|
36
|
+
from labview_fpga_hdl_tools.reporting import reporter
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
class SectionGroup(click.Group):
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
import os
|
|
9
9
|
import subprocess
|
|
10
10
|
|
|
11
|
-
from
|
|
12
|
-
from .
|
|
11
|
+
from labview_fpga_hdl_tools import common
|
|
12
|
+
from labview_fpga_hdl_tools.command_config import CommandConfiguration
|
|
13
|
+
from labview_fpga_hdl_tools.reporting import reporter
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def _generate_check_syntax_tcl(config, output_path):
|
|
@@ -83,12 +84,9 @@ def _validate_ini(config):
|
|
|
83
84
|
if invalid_path:
|
|
84
85
|
invalid_paths.append(invalid_path)
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if missing_settings or invalid_paths:
|
|
90
|
-
error_msg += "\nPlease update your configuration file and try again."
|
|
91
|
-
raise ValueError(error_msg)
|
|
87
|
+
error = common.build_settings_error(missing_settings, invalid_paths)
|
|
88
|
+
if error:
|
|
89
|
+
raise ValueError(error)
|
|
92
90
|
|
|
93
91
|
|
|
94
92
|
def _get_check_syntax_status_from_log(log_contents):
|
|
@@ -109,16 +107,7 @@ def _get_check_syntax_status_from_log(log_contents):
|
|
|
109
107
|
|
|
110
108
|
def _run_check_syntax(config, generated_tcl_path):
|
|
111
109
|
"""Run the generated check-syntax TCL script in Vivado batch mode."""
|
|
112
|
-
|
|
113
|
-
if not vivado_executable:
|
|
114
|
-
raise ValueError("VivadoToolsFolder setting is missing from configuration")
|
|
115
|
-
|
|
116
|
-
vivado_abs = os.path.abspath(vivado_executable)
|
|
117
|
-
if not os.path.exists(vivado_abs):
|
|
118
|
-
raise FileNotFoundError(
|
|
119
|
-
f"Vivado executable not found at: {vivado_abs}\n"
|
|
120
|
-
f"Please check your --vivado argument or VivadoToolsFolder setting in nihdlsettings.py"
|
|
121
|
-
)
|
|
110
|
+
vivado_abs = common.resolve_vivado_executable_abs(config)
|
|
122
111
|
|
|
123
112
|
vivado_project_dir = os.path.join(os.getcwd(), config.vivado_project_folder)
|
|
124
113
|
log_path = os.path.join(vivado_project_dir, "check_syntax.log")
|
|
@@ -128,19 +117,24 @@ def _run_check_syntax(config, generated_tcl_path):
|
|
|
128
117
|
if os.path.exists(path):
|
|
129
118
|
os.remove(path)
|
|
130
119
|
|
|
131
|
-
command =
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
120
|
+
command = [
|
|
121
|
+
vivado_abs,
|
|
122
|
+
"-mode",
|
|
123
|
+
"batch",
|
|
124
|
+
"-source",
|
|
125
|
+
generated_tcl_path,
|
|
126
|
+
"-log",
|
|
127
|
+
log_path,
|
|
128
|
+
"-journal",
|
|
129
|
+
journal_path,
|
|
130
|
+
]
|
|
137
131
|
|
|
138
132
|
reporter.detail(f"Generated TCL script: {generated_tcl_path}")
|
|
139
133
|
reporter.detail(f"Vivado executable: {vivado_abs}")
|
|
140
134
|
reporter.detail(f"Working directory: {vivado_project_dir}")
|
|
141
|
-
reporter.detail(f"Running command: {command}")
|
|
135
|
+
reporter.detail(f"Running command: {' '.join(command)}")
|
|
142
136
|
|
|
143
|
-
result = subprocess.run(command, cwd=vivado_project_dir,
|
|
137
|
+
result = subprocess.run(command, cwd=vivado_project_dir, check=False)
|
|
144
138
|
|
|
145
139
|
if not os.path.exists(log_path):
|
|
146
140
|
raise RuntimeError("Vivado check-syntax log file was not created.")
|
|
@@ -185,7 +179,7 @@ def check_syntax(config=None):
|
|
|
185
179
|
int: 0 for success, 1 for error
|
|
186
180
|
"""
|
|
187
181
|
if config is None:
|
|
188
|
-
config =
|
|
182
|
+
config = CommandConfiguration()
|
|
189
183
|
|
|
190
184
|
try:
|
|
191
185
|
_validate_ini(config)
|
|
@@ -14,8 +14,7 @@ from typing import Optional
|
|
|
14
14
|
|
|
15
15
|
from mako.template import Template
|
|
16
16
|
|
|
17
|
-
from .
|
|
18
|
-
from .reporting import reporter
|
|
17
|
+
from labview_fpga_hdl_tools.reporting import reporter
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
def handle_long_path(path):
|
|
@@ -237,7 +236,8 @@ def _parse_vhdl_entity(vhdl_path):
|
|
|
237
236
|
|
|
238
237
|
except Exception as e:
|
|
239
238
|
reporter.error(f"Error parsing VHDL file: {str(e)}")
|
|
240
|
-
|
|
239
|
+
if reporter.verbose:
|
|
240
|
+
traceback.print_exc()
|
|
241
241
|
return None, []
|
|
242
242
|
|
|
243
243
|
|
|
@@ -406,10 +406,16 @@ def apply_hdl_excludes(file_list, excluded_abspaths):
|
|
|
406
406
|
|
|
407
407
|
|
|
408
408
|
def run_command(cmd, cwd=None, capture_output=True, check=False):
|
|
409
|
-
"""Run a
|
|
409
|
+
"""Run a command and return its output.
|
|
410
|
+
|
|
411
|
+
The command is given as a pre-tokenized argument list (for example
|
|
412
|
+
``[vivado_abs, "-mode", "batch", ...]``) and is executed directly without a
|
|
413
|
+
shell. Passing an argument list means arguments containing spaces or
|
|
414
|
+
shell-significant characters are passed through verbatim (no quoting bugs)
|
|
415
|
+
and there is no shell-injection surface.
|
|
410
416
|
|
|
411
417
|
Args:
|
|
412
|
-
cmd:
|
|
418
|
+
cmd: The command to run, as a list of arguments.
|
|
413
419
|
cwd: Working directory to run the command in, if any.
|
|
414
420
|
capture_output: When True, capture stdout and return it as a string.
|
|
415
421
|
When False, let the command's output stream to the console and
|
|
@@ -421,7 +427,7 @@ def run_command(cmd, cwd=None, capture_output=True, check=False):
|
|
|
421
427
|
The captured stdout (stripped) when ``capture_output`` is True, otherwise
|
|
422
428
|
an empty string.
|
|
423
429
|
"""
|
|
424
|
-
reporter.detail(f"Running command: {cmd}")
|
|
430
|
+
reporter.detail(f"Running command: {' '.join(str(arg) for arg in cmd)}")
|
|
425
431
|
|
|
426
432
|
kwargs = {}
|
|
427
433
|
if cwd:
|
|
@@ -429,14 +435,12 @@ def run_command(cmd, cwd=None, capture_output=True, check=False):
|
|
|
429
435
|
|
|
430
436
|
if capture_output:
|
|
431
437
|
# Capture and return output
|
|
432
|
-
result = subprocess.run(
|
|
433
|
-
cmd, shell=True, text=True, capture_output=True, check=check, **kwargs
|
|
434
|
-
)
|
|
438
|
+
result = subprocess.run(cmd, text=True, capture_output=True, check=check, **kwargs)
|
|
435
439
|
# Check if stdout is None before calling strip()
|
|
436
440
|
return result.stdout.strip() if result.stdout is not None else ""
|
|
437
441
|
else:
|
|
438
442
|
# Don't capture output (let it go to console)
|
|
439
|
-
subprocess.run(cmd,
|
|
443
|
+
subprocess.run(cmd, check=check, **kwargs)
|
|
440
444
|
return "" # Return empty string instead of None
|
|
441
445
|
|
|
442
446
|
|
|
@@ -495,6 +499,48 @@ def get_invalid_paths_error(invalid_paths):
|
|
|
495
499
|
return error_msg
|
|
496
500
|
|
|
497
501
|
|
|
502
|
+
def build_settings_error(missing_settings, invalid_paths):
|
|
503
|
+
"""Return the standard missing-settings / invalid-paths message, or "" if none.
|
|
504
|
+
|
|
505
|
+
Combines the missing-settings and invalid-path messages with the shared hint
|
|
506
|
+
used by every ``_validate_ini``. Returns an empty string when there is
|
|
507
|
+
nothing to report, so callers can do ``if error: raise ValueError(error)``
|
|
508
|
+
(or report-and-return) without repeating the concatenation and hint text.
|
|
509
|
+
"""
|
|
510
|
+
if not (missing_settings or invalid_paths):
|
|
511
|
+
return ""
|
|
512
|
+
return (
|
|
513
|
+
get_missing_settings_error(missing_settings)
|
|
514
|
+
+ get_invalid_paths_error(invalid_paths)
|
|
515
|
+
+ "\nPlease update your configuration file and try again."
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
def resolve_vivado_executable_abs(config):
|
|
520
|
+
"""Resolve the Vivado executable to an absolute path.
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
config: CommandConfiguration providing ``vivado_tools_folder``.
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
str: Absolute path to the Vivado executable.
|
|
527
|
+
|
|
528
|
+
Raises:
|
|
529
|
+
ValueError: if the executable cannot be resolved from the configuration.
|
|
530
|
+
FileNotFoundError: if the resolved executable does not exist on disk.
|
|
531
|
+
"""
|
|
532
|
+
vivado_executable = get_vivado_executable(config.vivado_tools_folder)
|
|
533
|
+
if not vivado_executable:
|
|
534
|
+
raise ValueError("VivadoToolsFolder setting is missing from configuration")
|
|
535
|
+
vivado_abs = os.path.abspath(vivado_executable)
|
|
536
|
+
if not os.path.exists(vivado_abs):
|
|
537
|
+
raise FileNotFoundError(
|
|
538
|
+
f"Vivado executable not found at: {vivado_abs}\n"
|
|
539
|
+
"Please check your VivadoToolsFolder setting in nihdlsettings.py"
|
|
540
|
+
)
|
|
541
|
+
return vivado_abs
|
|
542
|
+
|
|
543
|
+
|
|
498
544
|
def collect_missing_settings(config, required):
|
|
499
545
|
"""Return the labels of required settings that are unset (falsy) on config.
|
|
500
546
|
|
|
@@ -517,23 +563,21 @@ def collect_missing_settings(config, required):
|
|
|
517
563
|
def raise_for_missing_settings(missing_settings, invalid_paths):
|
|
518
564
|
"""Raise ``ValueError`` for missing settings or invalid paths, if any.
|
|
519
565
|
|
|
520
|
-
Missing settings take precedence over invalid paths
|
|
521
|
-
|
|
522
|
-
|
|
566
|
+
Missing settings take precedence over invalid paths (only one message is
|
|
567
|
+
raised). Uses the shared ``get_missing_settings_error`` /
|
|
568
|
+
``get_invalid_paths_error`` builders so the wording matches the
|
|
569
|
+
``_validate_ini`` validators. Does nothing when both lists are empty.
|
|
523
570
|
"""
|
|
524
571
|
if missing_settings:
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
raise ValueError(error_msg)
|
|
530
|
-
|
|
572
|
+
raise ValueError(
|
|
573
|
+
get_missing_settings_error(missing_settings)
|
|
574
|
+
+ "\nPlease update your configuration file and try again."
|
|
575
|
+
)
|
|
531
576
|
if invalid_paths:
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
raise ValueError(error_msg)
|
|
577
|
+
raise ValueError(
|
|
578
|
+
get_invalid_paths_error(invalid_paths)
|
|
579
|
+
+ "\nPlease update your configuration file and try again."
|
|
580
|
+
)
|
|
537
581
|
|
|
538
582
|
|
|
539
583
|
def generate_guid():
|
|
@@ -554,7 +598,7 @@ def render_mako_template(template_path, output_path, **kwargs):
|
|
|
554
598
|
output_path (str): Path where the rendered output will be written
|
|
555
599
|
**kwargs: Template variables to substitute
|
|
556
600
|
"""
|
|
557
|
-
template = Template(filename=template_path, input_encoding="utf-8")
|
|
601
|
+
template = Template(filename=template_path, input_encoding="utf-8") # nosec B702
|
|
558
602
|
rendered = str(template.render(**kwargs))
|
|
559
603
|
|
|
560
604
|
# Mako preserves \r\n from template files on Windows. Normalize to \n
|
|
@@ -21,9 +21,10 @@ import os
|
|
|
21
21
|
import subprocess
|
|
22
22
|
import sys
|
|
23
23
|
|
|
24
|
-
from
|
|
25
|
-
from .
|
|
26
|
-
from .
|
|
24
|
+
from labview_fpga_hdl_tools import common
|
|
25
|
+
from labview_fpga_hdl_tools.command_config import CommandConfiguration
|
|
26
|
+
from labview_fpga_hdl_tools.create_modelsim_project import _find_modelsim_executable
|
|
27
|
+
from labview_fpga_hdl_tools.reporting import reporter
|
|
27
28
|
|
|
28
29
|
# Libraries built when nihdlsettings.py does not specify an explicit scope.
|
|
29
30
|
_DEFAULT_XILINX_SIM_LIBRARIES = ["unisim", "secureip"]
|
|
@@ -69,11 +70,9 @@ def _validate_ini(config):
|
|
|
69
70
|
f"{config.modelsim_tools_folder}"
|
|
70
71
|
)
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
error_msg += "\nPlease update your configuration file and try again."
|
|
76
|
-
raise ValueError(error_msg)
|
|
73
|
+
error = common.build_settings_error(missing_settings, invalid_paths)
|
|
74
|
+
if error:
|
|
75
|
+
raise ValueError(error)
|
|
77
76
|
|
|
78
77
|
|
|
79
78
|
def _libraries_already_built(out_folder, libraries):
|
|
@@ -134,16 +133,7 @@ def _is_progress_line(line):
|
|
|
134
133
|
|
|
135
134
|
def _run_compile_simlib(config, tcl_path, out_folder, libraries):
|
|
136
135
|
"""Run the generated compile_simlib TCL script in Vivado batch mode."""
|
|
137
|
-
|
|
138
|
-
if not vivado_executable:
|
|
139
|
-
raise ValueError("VivadoToolsFolder setting is missing from configuration")
|
|
140
|
-
|
|
141
|
-
vivado_abs = os.path.abspath(vivado_executable)
|
|
142
|
-
if not os.path.exists(vivado_abs):
|
|
143
|
-
raise FileNotFoundError(
|
|
144
|
-
f"Vivado executable not found at: {vivado_abs}\n"
|
|
145
|
-
f"Please check your VivadoToolsFolder setting in nihdlsettings.py"
|
|
146
|
-
)
|
|
136
|
+
vivado_abs = common.resolve_vivado_executable_abs(config)
|
|
147
137
|
|
|
148
138
|
os.makedirs(out_folder, exist_ok=True)
|
|
149
139
|
# Use a distinct name for Vivado's session log/journal. compile_simlib
|
|
@@ -165,12 +155,19 @@ def _run_compile_simlib(config, tcl_path, out_folder, libraries):
|
|
|
165
155
|
"try again."
|
|
166
156
|
) from exc
|
|
167
157
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
158
|
+
# Build the argument list explicitly and run without a shell so paths that
|
|
159
|
+
# contain spaces or shell-significant characters are passed through verbatim.
|
|
160
|
+
command = [
|
|
161
|
+
vivado_abs,
|
|
162
|
+
"-mode",
|
|
163
|
+
"batch",
|
|
164
|
+
"-source",
|
|
165
|
+
tcl_path,
|
|
166
|
+
"-log",
|
|
167
|
+
log_path,
|
|
168
|
+
"-journal",
|
|
169
|
+
journal_path,
|
|
170
|
+
]
|
|
174
171
|
|
|
175
172
|
# Run with the MODELSIM environment variable unset so compile_simlib does
|
|
176
173
|
# not read or modify a global modelsim.ini; it writes a fresh one into the
|
|
@@ -181,7 +178,7 @@ def _run_compile_simlib(config, tcl_path, out_folder, libraries):
|
|
|
181
178
|
reporter.detail(f"Vivado executable: {vivado_abs}")
|
|
182
179
|
reporter.detail(f"Output directory: {out_folder}")
|
|
183
180
|
reporter.detail(f"Libraries: {', '.join(libraries)}")
|
|
184
|
-
reporter.detail(f"Running command: {command}")
|
|
181
|
+
reporter.detail(f"Running command: {' '.join(command)}")
|
|
185
182
|
reporter.success("")
|
|
186
183
|
reporter.success("=" * 78)
|
|
187
184
|
reporter.success("Compiling the Xilinx ModelSim simulation libraries with Vivado.")
|
|
@@ -201,7 +198,7 @@ def _run_compile_simlib(config, tcl_path, out_folder, libraries):
|
|
|
201
198
|
process = subprocess.Popen(
|
|
202
199
|
command,
|
|
203
200
|
cwd=out_folder,
|
|
204
|
-
shell=
|
|
201
|
+
shell=False,
|
|
205
202
|
env=env,
|
|
206
203
|
stdout=subprocess.PIPE,
|
|
207
204
|
stderr=subprocess.STDOUT,
|
|
@@ -254,7 +251,7 @@ def compile_modelsim_lib(config=None, force=False):
|
|
|
254
251
|
int: 0 for success, 1 for error.
|
|
255
252
|
"""
|
|
256
253
|
if config is None:
|
|
257
|
-
config =
|
|
254
|
+
config = CommandConfiguration()
|
|
258
255
|
|
|
259
256
|
out_folder = config.xilinx_sim_lib_folder
|
|
260
257
|
if not out_folder:
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
import os
|
|
9
9
|
import subprocess
|
|
10
10
|
|
|
11
|
-
from
|
|
12
|
-
from .
|
|
11
|
+
from labview_fpga_hdl_tools import common
|
|
12
|
+
from labview_fpga_hdl_tools.command_config import CommandConfiguration
|
|
13
|
+
from labview_fpga_hdl_tools.reporting import reporter
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def _generate_compile_project_tcl(config, output_path):
|
|
@@ -25,12 +26,12 @@ def _generate_compile_project_tcl(config, output_path):
|
|
|
25
26
|
|
|
26
27
|
def _validate_ini(config):
|
|
27
28
|
"""Validate required settings and paths for compile-project."""
|
|
28
|
-
missing_settings =
|
|
29
|
+
missing_settings = common.collect_missing_settings(
|
|
30
|
+
config,
|
|
31
|
+
[("vivado_project_folder", "VivadoProjectSettings.VivadoProjectFolder")],
|
|
32
|
+
)
|
|
29
33
|
invalid_paths = []
|
|
30
34
|
|
|
31
|
-
if not config.vivado_project_folder:
|
|
32
|
-
missing_settings.append("VivadoProjectSettings.VivadoProjectFolder")
|
|
33
|
-
|
|
34
35
|
if not config.vivado_tcl_scripts_folder:
|
|
35
36
|
missing_settings.append("VivadoProjectSettings.VivadoTclScriptsFolder")
|
|
36
37
|
else:
|
|
@@ -72,12 +73,9 @@ def _validate_ini(config):
|
|
|
72
73
|
if invalid_path:
|
|
73
74
|
invalid_paths.append(invalid_path)
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if missing_settings or invalid_paths:
|
|
79
|
-
error_msg += "\nPlease update your configuration file and try again."
|
|
80
|
-
raise ValueError(error_msg)
|
|
76
|
+
error = common.build_settings_error(missing_settings, invalid_paths)
|
|
77
|
+
if error:
|
|
78
|
+
raise ValueError(error)
|
|
81
79
|
|
|
82
80
|
|
|
83
81
|
def _get_compile_status_from_log(log_contents):
|
|
@@ -103,16 +101,7 @@ def _get_compile_status_from_log(log_contents):
|
|
|
103
101
|
|
|
104
102
|
def _run_compile_project(config, generated_tcl_path):
|
|
105
103
|
"""Run the generated compile-project TCL script in Vivado batch mode."""
|
|
106
|
-
|
|
107
|
-
if not vivado_executable:
|
|
108
|
-
raise ValueError("VivadoToolsFolder setting is missing from configuration")
|
|
109
|
-
|
|
110
|
-
vivado_abs = os.path.abspath(vivado_executable)
|
|
111
|
-
if not os.path.exists(vivado_abs):
|
|
112
|
-
raise FileNotFoundError(
|
|
113
|
-
f"Vivado executable not found at: {vivado_abs}\n"
|
|
114
|
-
f"Please check your --vivado argument or VivadoToolsFolder setting in nihdlsettings.py"
|
|
115
|
-
)
|
|
104
|
+
vivado_abs = common.resolve_vivado_executable_abs(config)
|
|
116
105
|
|
|
117
106
|
current_dir = os.getcwd()
|
|
118
107
|
vivado_project_dir = os.path.join(current_dir, config.vivado_project_folder)
|
|
@@ -123,18 +112,23 @@ def _run_compile_project(config, generated_tcl_path):
|
|
|
123
112
|
if os.path.exists(path):
|
|
124
113
|
os.remove(path)
|
|
125
114
|
|
|
126
|
-
command =
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
115
|
+
command = [
|
|
116
|
+
vivado_abs,
|
|
117
|
+
"-mode",
|
|
118
|
+
"batch",
|
|
119
|
+
"-source",
|
|
120
|
+
generated_tcl_path,
|
|
121
|
+
"-log",
|
|
122
|
+
log_path,
|
|
123
|
+
"-journal",
|
|
124
|
+
journal_path,
|
|
125
|
+
]
|
|
132
126
|
|
|
133
127
|
reporter.detail(f"Vivado executable: {vivado_abs}")
|
|
134
128
|
reporter.detail(f"Working directory: {vivado_project_dir}")
|
|
135
|
-
reporter.detail(f"Running command: {command}")
|
|
129
|
+
reporter.detail(f"Running command: {' '.join(command)}")
|
|
136
130
|
|
|
137
|
-
result = subprocess.run(command, cwd=vivado_project_dir,
|
|
131
|
+
result = subprocess.run(command, cwd=vivado_project_dir, check=False)
|
|
138
132
|
|
|
139
133
|
if not os.path.exists(log_path):
|
|
140
134
|
raise RuntimeError("Vivado compile-project log file was not created.")
|
|
@@ -194,7 +188,7 @@ def compile_project(config=None):
|
|
|
194
188
|
int: 0 for success, 1 for error
|
|
195
189
|
"""
|
|
196
190
|
if config is None:
|
|
197
|
-
config =
|
|
191
|
+
config = CommandConfiguration()
|
|
198
192
|
|
|
199
193
|
try:
|
|
200
194
|
_validate_ini(config)
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import os # For file and directory operations
|
|
8
8
|
import subprocess # For executing external programs
|
|
9
9
|
|
|
10
|
-
from . import
|
|
11
|
-
from .reporting import reporter
|
|
10
|
+
from labview_fpga_hdl_tools.command_config import CommandConfiguration
|
|
11
|
+
from labview_fpga_hdl_tools.reporting import reporter
|
|
12
12
|
|
|
13
13
|
# createBitfile.exe lives at this path relative to a LabVIEW install root.
|
|
14
14
|
_CREATEBITFILE_RELPATH = os.path.join("vi.lib", "rvi", "CDR", "createBitfile.exe")
|
|
@@ -114,7 +114,7 @@ def _create_lv_bitfile(config=None):
|
|
|
114
114
|
|
|
115
115
|
# Load configuration
|
|
116
116
|
if config is None:
|
|
117
|
-
config =
|
|
117
|
+
config = CommandConfiguration()
|
|
118
118
|
|
|
119
119
|
# Determine path to CodeGenerationResults.lvtxt from TheWindow folder
|
|
120
120
|
if not config.lv_window_netlist_folder:
|
|
@@ -211,7 +211,8 @@ def create_lv_bitx(config=None):
|
|
|
211
211
|
return result # Return the result code
|
|
212
212
|
except Exception as e:
|
|
213
213
|
reporter.error(f"Unhandled exception: {str(e)}")
|
|
214
|
-
|
|
214
|
+
if reporter.verbose:
|
|
215
|
+
import traceback
|
|
215
216
|
|
|
216
|
-
|
|
217
|
+
traceback.print_exc()
|
|
217
218
|
return 1 # Return error code on exception
|
|
@@ -11,8 +11,9 @@ import shutil
|
|
|
11
11
|
import stat
|
|
12
12
|
import subprocess
|
|
13
13
|
|
|
14
|
-
from
|
|
15
|
-
from .
|
|
14
|
+
from labview_fpga_hdl_tools import common, generate_vhdl
|
|
15
|
+
from labview_fpga_hdl_tools.command_config import CommandConfiguration
|
|
16
|
+
from labview_fpga_hdl_tools.reporting import reporter
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
def _validate_ini(config):
|
|
@@ -61,11 +62,9 @@ def _validate_ini(config):
|
|
|
61
62
|
f"{config.modelsim_tools_folder}"
|
|
62
63
|
)
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
error_msg += "\nPlease update your configuration file and try again."
|
|
68
|
-
raise ValueError(error_msg)
|
|
65
|
+
error = common.build_settings_error(missing_settings, invalid_paths)
|
|
66
|
+
if error:
|
|
67
|
+
raise ValueError(error)
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
def _get_vsim_executable(modelsim_path):
|
|
@@ -428,7 +427,7 @@ def create_modelsim_project(overwrite=False, config=None):
|
|
|
428
427
|
- .do files for GUI and batch simulation
|
|
429
428
|
"""
|
|
430
429
|
if config is None:
|
|
431
|
-
config =
|
|
430
|
+
config = CommandConfiguration()
|
|
432
431
|
|
|
433
432
|
try:
|
|
434
433
|
_validate_ini(config)
|
|
@@ -501,7 +500,7 @@ def create_modelsim_project(overwrite=False, config=None):
|
|
|
501
500
|
# This is idempotent: once compiled it is a cheap no-op (and does not
|
|
502
501
|
# even require Vivado). Imported locally to avoid a circular import,
|
|
503
502
|
# since compile_modelsim_lib imports helpers from this module.
|
|
504
|
-
from
|
|
503
|
+
from labview_fpga_hdl_tools import compile_modelsim_lib
|
|
505
504
|
|
|
506
505
|
if compile_modelsim_lib.compile_modelsim_lib(config=config) != 0:
|
|
507
506
|
return 1
|