opencos-eda 0.3.8__py3-none-any.whl → 0.3.10__py3-none-any.whl

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.
Files changed (42) hide show
  1. opencos/commands/deps_help.py +40 -21
  2. opencos/commands/sim.py +0 -1
  3. opencos/deps/deps_file.py +82 -79
  4. opencos/eda.py +108 -17
  5. opencos/eda_base.py +8 -4
  6. opencos/eda_config.py +8 -1
  7. opencos/eda_config_defaults.yml +14 -5
  8. opencos/eda_deps_bash_completion.bash +37 -15
  9. opencos/tools/modelsim_ase.py +19 -378
  10. opencos/tools/questa.py +42 -247
  11. opencos/tools/questa_common.py +480 -0
  12. opencos/tools/questa_fe.py +84 -0
  13. opencos/tools/questa_fse.py +7 -8
  14. opencos/tools/riviera.py +27 -10
  15. opencos/tools/verilator.py +1 -0
  16. opencos/utils/str_helpers.py +7 -0
  17. opencos/utils/vsim_helper.py +53 -21
  18. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/METADATA +2 -1
  19. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/RECORD +24 -40
  20. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/entry_points.txt +1 -0
  21. opencos/tests/__init__.py +0 -0
  22. opencos/tests/custom_config.yml +0 -13
  23. opencos/tests/deps_files/command_order/DEPS.yml +0 -44
  24. opencos/tests/deps_files/error_msgs/DEPS.yml +0 -55
  25. opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -4
  26. opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
  27. opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -50
  28. opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -54
  29. opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -4
  30. opencos/tests/helpers.py +0 -354
  31. opencos/tests/test_build.py +0 -12
  32. opencos/tests/test_deps_helpers.py +0 -207
  33. opencos/tests/test_deps_schema.py +0 -30
  34. opencos/tests/test_eda.py +0 -921
  35. opencos/tests/test_eda_elab.py +0 -110
  36. opencos/tests/test_eda_synth.py +0 -150
  37. opencos/tests/test_oc_cli.py +0 -25
  38. opencos/tests/test_tools.py +0 -404
  39. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/WHEEL +0 -0
  40. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/licenses/LICENSE +0 -0
  41. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/licenses/LICENSE.spdx +0 -0
  42. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/top_level.txt +0 -0
opencos/tests/helpers.py DELETED
@@ -1,354 +0,0 @@
1
- '''opencos.tests.helpers - methods used to assist in various pytests on opencos'''
2
-
3
- # pylint: disable=dangerous-default-value # list arg w/ default values.
4
-
5
- import json
6
- import os
7
- import shutil
8
- from pathlib import Path
9
-
10
- from contextlib import redirect_stdout, redirect_stderr
11
-
12
- from opencos import eda, eda_tool_helper, deps_schema
13
- from opencos.utils import status_constants
14
- from opencos.utils.markup_helpers import yaml_safe_load
15
- from opencos.utils.subprocess_helpers import subprocess_run_background
16
-
17
- # Figure out what tools the system has available, without calling eda.main(..)
18
- config, tools_loaded = eda_tool_helper.get_config_and_tools_loaded()
19
- known_tool_versions = {}
20
-
21
-
22
- def eda_wrap_is_sim_fail(rc: int, quiet: bool = False) -> bool:
23
- '''Because eda_wrap calls eda_main(..) and will continue running
24
-
25
- after the first error, we may get a higher return code.'''
26
- if not quiet:
27
- print(f'eda_wrap_is_sim_fail({rc=})')
28
- return rc in (
29
- status_constants.EDA_COMMAND_MISSING_TOP,
30
- status_constants.EDA_SIM_LOG_HAS_BAD_STRING,
31
- status_constants.EDA_SIM_LOG_MISSING_MUST_STRING,
32
- status_constants.EDA_EXEC_NONZERO_RETURN_CODE2,
33
- status_constants.EDA_DEFAULT_ERROR
34
- )
35
-
36
- def handle_tool_version(tool: str, eda_command: str, cfg: dict = config) -> None:
37
- '''Attempts to use a command handler for tool + eda_command and we'll
38
- track the version globally'''
39
-
40
- if not known_tool_versions.get(tool, ''):
41
- handler_version = eda_tool_helper.get_handler_tool_version(
42
- tool=tool, eda_command=eda_command, config=cfg
43
- )
44
- known_tool_versions[tool] = handler_version
45
-
46
- def can_run_eda_command(*commands, cfg: dict = config) -> bool:
47
- '''Returns True if we have any installed tool that can run: eda <command>'''
48
- runnable = []
49
- for command in list(commands):
50
- handler = cfg['command_handler'].get(command, None)
51
- if not handler:
52
- return False
53
- if handler and getattr(handler, 'CHECK_REQUIRES', []):
54
- if not all(issubclass(handler, x) for x in getattr(handler, 'CHECK_REQUIRES', [])):
55
- return False
56
-
57
- # We cannot run tools that have disable-auto set:
58
- tool = getattr(handler, '_TOOL', '')
59
- if handler and tool:
60
- entry = cfg['auto_tools_order'][0].get(tool, {})
61
- if entry and entry.get('disable-auto', False):
62
- # This tool cannot automatically run our command.
63
- return False
64
- # While we're here, set known tool versions.
65
- handle_tool_version(tool=tool, eda_command=command, cfg=cfg)
66
-
67
- runnable.append(True)
68
- return runnable and all(runnable)
69
-
70
- def can_uvm(tool: str) -> bool:
71
- '''Returns True if we can run UVM, per tool'''
72
-
73
- if tool not in tools_loaded:
74
- return False
75
-
76
- if tool == 'verilator':
77
- # requires UVM_HOME to be set with uvm_pkg.sv existing.
78
- uvm_home = os.environ.get('UVM_HOME', '')
79
- uvm_pkg = os.path.join(uvm_home, 'uvm_pkg.sv')
80
- if not all((os.path.isdir(uvm_home), os.path.isfile(uvm_pkg))):
81
- return False
82
-
83
- handle_tool_version(tool=tool, eda_command='sim', cfg=config)
84
- version_list = known_tool_versions.get('verilator', '').split('.')
85
- if int(version_list[0]) < 5 or \
86
- (int(version_list[0]) == 5 and int(version_list[1]) < 42):
87
- return False
88
-
89
- return True
90
-
91
- # default return False:
92
- return False
93
-
94
- def can_run_eda_sim(cfg: dict = config) -> bool:
95
- '''Returns True if we have any installed tool that can run: eda sim'''
96
- return can_run_eda_command('sim', cfg=cfg)
97
-
98
- def can_run_eda_elab(cfg: dict = config) -> bool:
99
- '''Returns True if we have any installed tool that can run: eda elab'''
100
- return can_run_eda_command('elab', cfg=cfg)
101
-
102
- def chdir_remove_work_dir(startpath, relpath):
103
- '''Changes dir to startpath/relpath, removes the work directories (eda.work, eda.export*)'''
104
- os.chdir(os.path.join(str(Path(startpath)), str(Path(relpath))))
105
- for outdir in ['eda.export', 'eda.work']:
106
- fullp = os.path.join(os.getcwd(), outdir)
107
- if fullp and ('eda.' in fullp) and os.path.isdir(fullp):
108
- shutil.rmtree(fullp)
109
-
110
- def eda_wrap(*args):
111
- '''Calls eda.main, prefer seed=1 to avoid seed based simulation fails in pytests'''
112
- main_args = [x for x in list(args) if '--seed' not in x]
113
- return eda.main('--seed=1', *main_args)
114
-
115
- def eda_sim_wrap(*args):
116
- '''Calls eda.main for 'sim' prefer seed=1 to avoid seed based simulation fails in pytests'''
117
- main_args = [x for x in list(args) if (x != 'sim' and '--seed' not in x)]
118
- return eda.main('sim', '--seed=1', *main_args)
119
-
120
- def eda_elab_wrap(*args):
121
- '''Calls eda.main for 'elab'.'''
122
- main_args = [x for x in list(args) if (x != 'elab' and '--seed' not in x)]
123
- return eda.main('elab', *main_args)
124
-
125
- def eda_lint_wrap(*args):
126
- '''Calls eda.main for 'elab'.'''
127
- main_args = [x for x in list(args) if (x != 'lint' and '--seed' not in x)]
128
- return eda.main('lint', *main_args)
129
-
130
- def assert_sim_log_passes(
131
- filepath: str, want_str: str = 'TEST PASS',
132
- err_strs: list = ['Error', 'ERROR', 'TEST FAIL']
133
- ) -> None:
134
- '''Checks log in filepath, makes sure it has a want_str and no err_strs'''
135
- test_passed = False
136
- test_failed = False
137
-
138
- assert os.path.exists(filepath), f'{filepath=} does not exist'
139
- if not want_str:
140
- # we don't have a want_str, so looks like it passes no matter what
141
- test_passed = True
142
- with open(filepath, encoding='utf-8') as f:
143
- for line in f.readlines():
144
- if want_str and want_str in line:
145
- test_passed = True
146
- if any(x in line for x in err_strs):
147
- test_failed = True
148
- assert test_passed, f'{filepath=} did not have {want_str=}'
149
- assert not test_failed, f'{filepath=} has one of {err_strs=}'
150
-
151
- def assert_gen_deps_yml_good(filepath:str, want_target:str='') -> dict:
152
- '''Generated DEPS files should be coming from --export style args,
153
-
154
- so we also confirm they pass the deps_schema.FILE_SIMPLIFIED'''
155
- assert os.path.exists(filepath), f'{filepath=} does not exist'
156
- data = yaml_safe_load(filepath)
157
- assert len(data.keys()) > 0
158
- if want_target:
159
- assert want_target, f'{want_target=} not in {filepath=} {data=}'
160
- assert 'deps' in data[want_target], f' key "deps" is not in {want_target=} in {data=}'
161
- assert deps_schema.check_files(filepath, schema_obj=deps_schema.FILE_SIMPLIFIED)
162
- return data
163
-
164
-
165
- def assert_export_json_good(filepath:str) -> dict:
166
- '''Checks that an exported JSON (from eda export, or eda <command> --export) has known keys'''
167
- assert os.path.isfile(filepath), f'{filepath=} does not exist'
168
- with open(filepath, encoding='utf-8') as f:
169
- data = json.load(f)
170
- assert 'tests' in data
171
- assert len(data.get('tests', [])) >= 1
172
- for test in data.get('tests', []):
173
- check_test_runner_schema(test)
174
- return data
175
-
176
- def check_test_runner_schema(test: dict) -> None:
177
- '''Confirm that a single test's JSON/JSONL schema is OK.'''
178
- assert 'correlationId' in test
179
- assert 'jobType' in test
180
- assert 'cmd' in test
181
- assert 'filesList' in test # 0 files is OK.
182
-
183
-
184
- def assert_export_jsonl_good(filepath:str, jsonl:bool=True) -> list:
185
- '''Checks that an exported JSONL (from eda multi --export) has known keys'''
186
- assert os.path.isfile(filepath), f'{filepath=} does not exist'
187
- ret = []
188
- with open(filepath, encoding='utf-8') as f:
189
- if jsonl:
190
- print(f'Using JSONL for {filepath=}')
191
- for line in f.readlines():
192
- line = line.strip()
193
- test = json.loads(line)
194
- check_test_runner_schema(test)
195
- ret.append(test)
196
- else:
197
- print(f'Using JSON for {filepath=}')
198
- data = json.load(f)
199
- assert 'tests' in data
200
- assert len(data.get('tests', [])) >= 1
201
- for test in data.get('tests', []):
202
- check_test_runner_schema(test)
203
- ret.append(test)
204
-
205
- return ret
206
-
207
-
208
- class Helpers:
209
- '''We do so much with logging in this file, might as well make it reusable'''
210
- DEFAULT_DIR = ''
211
- DEFAULT_LOG_DIR = os.getcwd()
212
- DEFAULT_LOG = os.path.join(DEFAULT_LOG_DIR, '.pytest.eda.log')
213
-
214
- # How should the job run? subprocess? eda_wrap? eda.main?
215
- # Note - if using eda.main, args like --debug will persist in opencos.util.args,
216
- # so if you need those to be re-loaded, set RUN_IN_SUBPROCESS=True.
217
- # Note - if you mess with os.enviorn, it may persist through subprocess.
218
- RUN_IN_SUBPROCESS = True
219
- USE_EDA_WRAP = True
220
- PRESERVE_ENV = False
221
-
222
- def chdir(self):
223
- '''Changes directory to self.DEFAULT_DIR and removes eda.work, eda.export paths'''
224
- chdir_remove_work_dir('', self.DEFAULT_DIR)
225
-
226
-
227
- def _resolve_logfile(self, logfile=None) -> str:
228
- '''Returns the logfile's filepath'''
229
- ret = logfile
230
- if ret is None:
231
- ret = self.DEFAULT_LOG
232
- else:
233
- left, right = os.path.split(logfile)
234
- if not left or left in [os.path.sep, '.', '..']:
235
- # relative logfile put in DEFAULT_LOG_DIR:
236
- ret = os.path.join(self.DEFAULT_LOG_DIR, right)
237
- return ret
238
-
239
- def log_it(
240
- self, command_str: str, logfile=None, use_eda_wrap: bool = True,
241
- run_in_subprocess: bool = False, include_default_log: bool = False,
242
- preserve_env: bool = False
243
- ) -> int:
244
- '''Replacement for calling eda.main or eda_wrap, when you want an internal logfile
245
-
246
- Usage:
247
- rc = self.log_it('sim foo')
248
- assert rc == 0
249
-
250
- Note this will run with --no-default-log to avoid a Windows problem with stomping
251
- on a log file.
252
- '''
253
-
254
- if self.PRESERVE_ENV or preserve_env:
255
- saved_env = os.environ.copy()
256
-
257
- logfile = self._resolve_logfile(logfile)
258
- rc = 50
259
-
260
- eda_log_arg = '--no-default-log'
261
- if include_default_log:
262
- eda_log_arg = ''
263
-
264
- # TODO(drew): There are some issues with log_it redirecting stdout from vivado
265
- # and modelsim_ase. So this may not work for all tools, you may have to directly
266
- # look at eda.work/{target}.sim/sim.log or xsim.log.
267
- print(f'{os.getcwd()=}')
268
- print(f'{command_str=}')
269
- if run_in_subprocess or self.RUN_IN_SUBPROCESS:
270
- command_list = ['eda', eda_log_arg] + command_str.split()
271
- _, _, rc = subprocess_run_background(
272
- work_dir=self.DEFAULT_DIR,
273
- command_list=command_list,
274
- background=True,
275
- tee_fpath=logfile
276
- )
277
- print(f'Wrote: {os.path.abspath(logfile)=}')
278
- else:
279
- with open(logfile, 'w', encoding='utf-8') as f:
280
- with redirect_stdout(f), redirect_stderr(f):
281
- if use_eda_wrap or self.USE_EDA_WRAP:
282
- rc = eda_wrap(eda_log_arg, *(command_str.split()))
283
- else:
284
- rc = eda.main(eda_log_arg, *(command_str.split()))
285
- print(f'Wrote: {os.path.abspath(logfile)=}')
286
-
287
- if self.PRESERVE_ENV or preserve_env:
288
- os.environ = saved_env
289
-
290
- return rc
291
-
292
- def is_in_log(
293
- self, *want_str, logfile=None, windows_path_support: bool = False
294
- ) -> bool:
295
- '''Check if want_str (joined) is in the logfile, or self.DEFAULT_LOG'''
296
- logfile = self._resolve_logfile(logfile)
297
- want_str0 = ' '.join(list(want_str))
298
- want_str1 = want_str0.replace('/', '\\')
299
- with open(logfile, encoding='utf-8') as f:
300
- for line in f.readlines():
301
- if want_str0 in line or \
302
- (windows_path_support and want_str1 in line):
303
- return True
304
- return False
305
-
306
- def get_log_lines_with(
307
- self, *want_str, logfile=None, windows_path_support: bool = False
308
- ) -> list:
309
- '''gets all log lines with any of want_str args are in the logfile, or self.DEFAULT_LOG'''
310
- logfile = self._resolve_logfile(logfile)
311
- ret_list = []
312
- with open(logfile, encoding='utf-8') as f:
313
- for line in f.readlines():
314
- if any(x in line for x in list(want_str)):
315
- ret_list.append(line)
316
- elif windows_path_support and \
317
- any(x.replace('/', '\\') in line for x in list(want_str)):
318
- ret_list.append(line)
319
- return ret_list
320
-
321
- def get_log_lines_with_all(
322
- self, *want_str, logfile=None, windows_path_support: bool = False
323
- ) -> list:
324
- '''gets all log lines with ALL of want_str args are in the logfile, or self.DEFAULT_LOG'''
325
- logfile = self._resolve_logfile(logfile)
326
- ret_list = []
327
- with open(logfile, encoding='utf-8') as f:
328
- for line in f.readlines():
329
- if all(x in line for x in list(want_str)):
330
- ret_list.append(line)
331
- elif windows_path_support and \
332
- all(x.replace('/', '\\') in line for x in list(want_str)):
333
- ret_list.append(line)
334
- return ret_list
335
-
336
- def get_log_words_with(self, *want_str, logfile=None, windows_path_support=False):
337
- '''gets all log words with any of *want_str within a single word
338
- in the logfile or self.DEFAULT_LOG
339
- '''
340
- logfile = self._resolve_logfile(logfile)
341
- ret_list = []
342
- with open(logfile, encoding='utf-8') as f:
343
- for line in f.readlines():
344
- if any(x in line for x in list(want_str)):
345
- for word in line.split():
346
- if any(x in word for x in list(want_str)):
347
- ret_list.append(word)
348
- elif windows_path_support and \
349
- any(x.replace('/', '\\') in line for x in list(want_str)):
350
- for word in line.split():
351
- if any(x.replace('/', '\\') in word for x in list(want_str)):
352
- ret_list.append(word)
353
-
354
- return ret_list
@@ -1,12 +0,0 @@
1
- '''pytest functions for making sure the build has expected members (version, etc)'''
2
-
3
- import opencos
4
-
5
- def test_version():
6
- '''tests that opencos.__version__ works'''
7
- __version__ = opencos.__version__
8
- print(f'{__version__=}')
9
- assert __version__
10
- assert __version__ != 'unknown'
11
- numbers = __version__.split('.')
12
- assert any(int(number) != 0 for number in numbers)
@@ -1,207 +0,0 @@
1
- '''pytests for opencos.deps modules'''
2
-
3
- # TODO(drew): these need to be refactored if we cleanup opencos.deps commands;
4
- # this uses the old DEPS (non-markup) command format, such as 'shell@some bash command'
5
-
6
- # TODO(drew): for now, ignore long lines and docstrings
7
- # pylint: disable=line-too-long,missing-function-docstring
8
-
9
- from pathlib import Path
10
- import os
11
- import pytest
12
-
13
- from opencos import eda_tool_helper
14
-
15
- from opencos.deps import deps_file, deps_commands
16
-
17
- THISPATH = os.path.dirname(__file__)
18
-
19
- # Figure out what tools the system has avail, without calling eda.main(..)
20
- config, tools_loaded = eda_tool_helper.get_config_and_tools_loaded()
21
-
22
-
23
- def test_get_all_targets():
24
- '''Makes sure that deps_file.get_all_targets(filter_str:str) works'''
25
-
26
- targets = deps_file.get_all_targets(
27
- dirs=[
28
- str(Path('../../lib/tests')),
29
- str(Path('../../lib/rams/tests')),
30
- ],
31
- base_path=str(Path(THISPATH)),
32
- filter_str='*test',
33
- )
34
- print(f'{targets=}')
35
- assert str(Path('../../lib/rams/tests/oclib_ram2rw_test')) in targets
36
- assert str(Path('../../lib/tests/oclib_fifo_test')) in targets
37
- for t in targets:
38
- assert t.endswith('test'), f'target {t} filter did not work *test'
39
-
40
-
41
- @pytest.mark.skipif(
42
- not('vivado' in tools_loaded or
43
- 'verilator' in tools_loaded),
44
- reason="requires vivado or verilator"
45
- )
46
- def test_get_all_targets_eda_multi():
47
- '''Makes sure that deps_file.get_all_targets(filter_using_mult:str) works'''
48
-
49
- targets = deps_file.get_all_targets(
50
- base_path=THISPATH,
51
- filter_using_multi='sim ../../lib/tests/*test ../../lib/rams/tests/*test',
52
- )
53
- print(f'{targets=}')
54
- assert '../../lib/rams/tests/oclib_ram2rw_test' in targets
55
- assert '../../lib/tests/oclib_fifo_test' in targets
56
- for t in targets:
57
- assert t.endswith('test'), f'target {t} filter did not work *test'
58
-
59
-
60
- def test_parse_deps_shell_str__no_parse():
61
- line = 'some_file.sv'
62
- d = deps_commands.parse_deps_shell_str(line, '', '', attributes={})
63
- assert not d, f'{d=}'
64
-
65
- line = 'some_target:'
66
- d = deps_commands.parse_deps_shell_str(line, '', '', attributes={})
67
- assert not d, f'{d=}'
68
-
69
- line = ' csr@some_file.sv'
70
- d = deps_commands.parse_deps_shell_str(line, '', '', attributes={})
71
- assert not d, f'{d=}'
72
-
73
- def test_parse_deps_shell_str__cp():
74
- line = ' shell@ cp ./oclib_fifo_test.sv oclib_fifo_test_COPY.sv ;'
75
- d = deps_commands.parse_deps_shell_str(line, '', '', attributes={})
76
- assert d, f'{d=}'
77
- assert d['exec_list'] == ['cp', './oclib_fifo_test.sv', 'oclib_fifo_test_COPY.sv', ';'], f'{d=}'
78
-
79
- def test_parse_deps_shell_str__echo():
80
- line = ' shell@echo "hello world"'
81
- d = deps_commands.parse_deps_shell_str(line, '', '', attributes={})
82
- assert d, f'{d=}'
83
- assert d['exec_list'] == ['echo', '"hello', 'world"'], f'{d=}'
84
-
85
- def test_parse_deps_shell_str__enable_filepath_replacement():
86
- # Dealing w/ relative paths, change the current working directory to the module directory
87
- # Default is enabled.
88
- module_dir = os.path.dirname(os.path.abspath(__file__))
89
- os.chdir(module_dir)
90
- line = 'shell@cp ../deps/deps_commands.py .pytest.copied.py'
91
- d = deps_commands.parse_deps_shell_str(
92
- line, target_path='./', target_node='foo_target', attributes={}
93
- )
94
- assert d, f'{d=}'
95
- spath = os.path.abspath(os.path.join('..', 'deps', 'deps_commands.py'))
96
- assert d['exec_list'] == ['cp', spath, '.pytest.copied.py'], f'{d=}'
97
- assert d['target_node'] == 'foo_target'
98
- assert d['target_path'] == os.path.abspath('./')
99
-
100
- def test_parse_deps_shell_str__disable_filepath_replacement():
101
- # Dealing w/ relative paths, change the current working directory to the module directory
102
- module_dir = os.path.dirname(os.path.abspath(__file__))
103
- os.chdir(module_dir)
104
- line = 'shell@cp ../deps/deps_commands.py .pytest.copied.py'
105
- d = deps_commands.parse_deps_shell_str(
106
- line, target_path='./', target_node='foo_target',
107
- attributes={'filepath-subst-target-dir': False}
108
- )
109
- assert d, f'{d=}'
110
- assert d['exec_list'] == ['cp', '../deps/deps_commands.py', '.pytest.copied.py'], f'{d=}'
111
- assert d['target_node'] == 'foo_target'
112
- assert d['target_path'] == os.path.abspath('./')
113
-
114
- def test_parse_deps_shell_str__enable_dirpath_replacement():
115
- # Dealing w/ relative paths, change the current working directory to the module directory
116
- module_dir = os.path.dirname(os.path.abspath(__file__))
117
- os.chdir(module_dir)
118
- line = 'shell@ls -ltr ./'
119
- d = deps_commands.parse_deps_shell_str(
120
- line, target_path='./', target_node='foo_target',
121
- attributes={'dirpath-subst-target-dir': True}
122
- )
123
- assert d, f'{d=}'
124
- assert d['exec_list'] == ['ls', '-ltr', os.path.abspath('./')], f'{d=}'
125
- assert d['target_node'] == 'foo_target'
126
- assert d['target_path'] == os.path.abspath('./')
127
-
128
- def test_parse_deps_shell_str__disable_dirpath_replacement():
129
- # Dealing w/ relative paths, change the current working directory to the module directory
130
- # Default is disabled.
131
- module_dir = os.path.dirname(os.path.abspath(__file__))
132
- os.chdir(module_dir)
133
- line = 'shell@ls -ltr ./'
134
- d = deps_commands.parse_deps_shell_str(
135
- line, target_path='./', target_node='foo_target',
136
- attributes={}
137
- )
138
- assert d, f'{d=}'
139
- assert d['exec_list'] == ['ls', '-ltr', './'], f'{d=}'
140
- assert d['target_node'] == 'foo_target'
141
- assert d['target_path'] == os.path.abspath('./')
142
-
143
-
144
- def test_parse_deps_work_dir_add_srcs__no_parse():
145
- line = 'some_file.sv'
146
- d = deps_commands.parse_deps_work_dir_add_srcs(line, '', '', {})
147
- assert not d, f'{d=}'
148
-
149
- line = 'some_target:'
150
- d = deps_commands.parse_deps_work_dir_add_srcs(line, '', '', {})
151
- assert not d, f'{d=}'
152
-
153
- line = ' csr@some_file.sv'
154
- d = deps_commands.parse_deps_work_dir_add_srcs(line, '', '', {})
155
- assert not d, f'{d=}'
156
-
157
- def test_parse_deps_work_dir_add_srcs__single_file():
158
- line = ' work_dir_add_srcs@ single_file.txt'
159
- d = deps_commands.parse_deps_work_dir_add_srcs(line, '', '', {})
160
- assert d, f'{d=}'
161
- assert d['file_list'] == ['single_file.txt']
162
-
163
- def test_parse_deps_work_dir_add_srcs__several_file():
164
- line = ' work_dir_add_srcs@ single_file.txt another.sv gen-verilog/mine.v ./gen-vhdl/wordy.vhdl'
165
- d = deps_commands.parse_deps_work_dir_add_srcs(line, '', '', {})
166
- assert d, f'{d=}'
167
- assert d['file_list'] == [
168
- 'single_file.txt', 'another.sv', 'gen-verilog/mine.v', './gen-vhdl/wordy.vhdl'
169
- ]
170
-
171
-
172
- def test_parse_deps_peakrdl__no_parse():
173
- line = 'some_file.sv'
174
- d = deps_commands.parse_deps_peakrdl(line, '', '', {})
175
- assert not d, f'{d=}'
176
-
177
- line = 'some_target:'
178
- d = deps_commands.parse_deps_peakrdl(line, '', '', {})
179
- assert not d, f'{d=}'
180
-
181
- line = ' csr@some_file.sv'
182
- d = deps_commands.parse_deps_peakrdl(line, '', '', {})
183
- assert not d, f'{d=}'
184
-
185
- def test_parse_deps_peakrdl__with_top():
186
- line = ' peakrdl@ --cpuif axi4-lite-flat --top my_fancy_csrs ./my_csrs.rdl'
187
- d = deps_commands.parse_deps_peakrdl(line, '', '', {})
188
- assert d, f'{d=}'
189
- assert len(d['shell_commands_list']) > 0
190
- assert d['work_dir_add_srcs']['file_list'] == ['peakrdl/my_fancy_csrs_pkg.sv',
191
- 'peakrdl/my_fancy_csrs.sv']
192
-
193
- def test_parse_deps_peakrdl__with_top2():
194
- line = ' peakrdl@ --cpuif axi4-lite-flat --top=my_fancy_csrs ./my_csrs.rdl'
195
- d = deps_commands.parse_deps_peakrdl(line, '', '', {})
196
- assert d, f'{d=}'
197
- assert len(d['shell_commands_list']) > 0
198
- assert d['work_dir_add_srcs']['file_list'] == ['peakrdl/my_fancy_csrs_pkg.sv',
199
- 'peakrdl/my_fancy_csrs.sv']
200
-
201
- def test_parse_deps_peakrdl__infer_top():
202
- line = ' peakrdl@ --cpuif axi4-lite-flat ./my_csrs.rdl'
203
- d = deps_commands.parse_deps_peakrdl(line, '', '', {})
204
- assert d, f'{d=}'
205
- assert len(d['shell_commands_list']) > 0
206
- assert d['work_dir_add_srcs']['file_list'] == ['peakrdl/my_csrs_pkg.sv',
207
- 'peakrdl/my_csrs.sv']
@@ -1,30 +0,0 @@
1
- '''test_deps_schema - pytest to check schema of all DEPS.[markup] files in the repo'''
2
-
3
- import os
4
-
5
- from opencos.deps_schema import check_files
6
-
7
- def test_all_deps():
8
- '''Find all DEPS files and confirm the schema is error-free
9
-
10
- uses opencos.deps_schema.check_files (aka package script eda_deps_schema) which
11
- is using pypackage 'schema'.
12
- '''
13
-
14
- # get all the files
15
- all_deps_files = []
16
- for root, _, files in os.walk(os.getcwd()):
17
- for fname in files:
18
- if fname.startswith('DEPS') and \
19
- any(fname.endswith(x) for x in [
20
- '.yml', '.yaml', '.json', '.toml', 'DEPS'
21
- ]):
22
-
23
- all_deps_files.append(os.path.join(root, fname))
24
-
25
- # run all the files, but one at a time:
26
- for fname in all_deps_files:
27
- passes = check_files(all_deps_files)
28
- assert passes, f'{fname=} did not pass schema checks'
29
-
30
- assert len(all_deps_files) > 0