opencos-eda 0.3.9__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.
- opencos/commands/deps_help.py +40 -21
- opencos/commands/sim.py +0 -1
- opencos/deps/deps_file.py +82 -79
- opencos/eda.py +46 -9
- opencos/eda_base.py +8 -4
- opencos/eda_config.py +8 -1
- opencos/eda_deps_bash_completion.bash +37 -15
- opencos/tools/questa_common.py +1 -2
- opencos/tools/verilator.py +1 -0
- opencos/utils/str_helpers.py +7 -0
- opencos/utils/vsim_helper.py +47 -22
- {opencos_eda-0.3.9.dist-info → opencos_eda-0.3.10.dist-info}/METADATA +1 -1
- {opencos_eda-0.3.9.dist-info → opencos_eda-0.3.10.dist-info}/RECORD +18 -36
- {opencos_eda-0.3.9.dist-info → opencos_eda-0.3.10.dist-info}/entry_points.txt +1 -0
- opencos/tests/__init__.py +0 -0
- opencos/tests/custom_config.yml +0 -13
- opencos/tests/deps_files/command_order/DEPS.yml +0 -44
- opencos/tests/deps_files/error_msgs/DEPS.yml +0 -55
- opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -4
- opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
- opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -50
- opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -54
- opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -4
- opencos/tests/helpers.py +0 -354
- opencos/tests/test_build.py +0 -12
- opencos/tests/test_deps_helpers.py +0 -207
- opencos/tests/test_deps_schema.py +0 -30
- opencos/tests/test_eda.py +0 -921
- opencos/tests/test_eda_elab.py +0 -110
- opencos/tests/test_eda_synth.py +0 -150
- opencos/tests/test_oc_cli.py +0 -25
- opencos/tests/test_tools.py +0 -404
- {opencos_eda-0.3.9.dist-info → opencos_eda-0.3.10.dist-info}/WHEEL +0 -0
- {opencos_eda-0.3.9.dist-info → opencos_eda-0.3.10.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.3.9.dist-info → opencos_eda-0.3.10.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.3.9.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
|
opencos/tests/test_build.py
DELETED
|
@@ -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
|