opencos-eda 0.3.11__py3-none-any.whl → 0.3.13__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/flist.py +222 -39
- opencos/commands/multi.py +5 -3
- opencos/commands/sim.py +121 -7
- opencos/commands/sweep.py +1 -1
- opencos/commands/upload.py +4 -4
- opencos/commands/waves.py +44 -0
- opencos/deps/deps_file.py +4 -1
- opencos/deps_schema.py +2 -2
- opencos/eda.py +284 -175
- opencos/eda_base.py +54 -22
- opencos/eda_config.py +51 -24
- opencos/eda_config_defaults.yml +326 -195
- opencos/eda_config_reduced.yml +19 -39
- opencos/eda_tool_helper.py +193 -24
- opencos/tools/cocotb.py +6 -29
- opencos/tools/invio.py +0 -6
- opencos/tools/iverilog.py +16 -16
- opencos/tools/modelsim_ase.py +1 -13
- opencos/tools/quartus.py +81 -24
- opencos/tools/questa.py +0 -14
- opencos/tools/questa_common.py +95 -30
- opencos/tools/questa_fe.py +0 -14
- opencos/tools/questa_fse.py +0 -14
- opencos/tools/riviera.py +56 -25
- opencos/tools/slang.py +15 -12
- opencos/tools/slang_yosys.py +0 -6
- opencos/tools/surelog.py +14 -11
- opencos/tools/tabbycad_yosys.py +1 -7
- opencos/tools/verilator.py +18 -14
- opencos/tools/vivado.py +57 -22
- opencos/tools/yosys.py +2 -4
- opencos/util.py +14 -5
- opencos/utils/str_helpers.py +42 -1
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/METADATA +1 -2
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/RECORD +40 -41
- opencos/eda_config_max_verilator_waivers.yml +0 -39
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/WHEEL +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/entry_points.txt +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/top_level.txt +0 -0
opencos/eda_tool_helper.py
CHANGED
|
@@ -10,15 +10,18 @@ Example uses:
|
|
|
10
10
|
|
|
11
11
|
'''
|
|
12
12
|
|
|
13
|
+
from importlib import import_module
|
|
13
14
|
|
|
14
|
-
from opencos import
|
|
15
|
+
from opencos import eda_config, util
|
|
16
|
+
from opencos.util import Colors
|
|
17
|
+
from opencos.utils import str_helpers
|
|
15
18
|
|
|
16
19
|
# Used by pytest, so we can skip tests if tools aren't present.
|
|
17
20
|
|
|
18
21
|
def get_config_and_tools_loaded( # pylint: disable=dangerous-default-value
|
|
19
22
|
quiet: bool = False, args: list = []
|
|
20
23
|
) -> (dict, set):
|
|
21
|
-
'''Returns config dict and
|
|
24
|
+
'''Returns config dict and list tools_loaded, given the found config.
|
|
22
25
|
|
|
23
26
|
Can BYO args such as --config-yml=MY_OWN_EDA_CONFIG.yml
|
|
24
27
|
'''
|
|
@@ -26,8 +29,13 @@ def get_config_and_tools_loaded( # pylint: disable=dangerous-default-value
|
|
|
26
29
|
# We have to figure out what tools are avaiable w/out calling eda.main,
|
|
27
30
|
# so we can get some of these using eda_config.get_eda_config()
|
|
28
31
|
config, _ = eda_config.get_eda_config(args=args, quiet=quiet)
|
|
32
|
+
|
|
33
|
+
# only import 'eda' here so that other methods in this pymodule can be used
|
|
34
|
+
# within eda, etc, if you already have a valid config or tools_loaded.
|
|
35
|
+
eda = import_module("opencos.eda")
|
|
29
36
|
config = eda.init_config(config=config, quiet=quiet)
|
|
30
|
-
tools_loaded = config.get('tools_loaded',
|
|
37
|
+
tools_loaded = config.get('tools_loaded', []).copy()
|
|
38
|
+
|
|
31
39
|
return config, tools_loaded
|
|
32
40
|
|
|
33
41
|
|
|
@@ -47,25 +55,30 @@ def get_all_handler_commands(config=None, tools_loaded=None) -> dict:
|
|
|
47
55
|
config, tools_loaded = get_config_and_tools_loaded()
|
|
48
56
|
|
|
49
57
|
assert isinstance(config, dict)
|
|
50
|
-
assert isinstance(tools_loaded,
|
|
58
|
+
assert isinstance(tools_loaded, list)
|
|
51
59
|
|
|
52
60
|
# Let's re-walk auto_tools_order to get this ordered per eda command:
|
|
53
|
-
for
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
for command, tools_list in config.get('auto_tools_order', {}).items():
|
|
62
|
+
|
|
63
|
+
for tool in tools_list:
|
|
64
|
+
entry = config.get('tools', {}).get(tool, {})
|
|
65
|
+
assert entry, f'{command=} in auto_tools_order {tool=} not present in tools'
|
|
66
|
+
|
|
67
|
+
if tool not in tools_loaded:
|
|
68
|
+
continue
|
|
69
|
+
|
|
70
|
+
if entry.get('disable-tools-multi', False):
|
|
71
|
+
# Flagged as do-not-add when running eda command: tools-multi
|
|
72
|
+
util.debug(f'eda_tool_helper.py -- skipping {tool=} it is set with flag',
|
|
73
|
+
'disable-tools-multi in config')
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
if command in entry.get('handlers', {}):
|
|
77
|
+
if command not in all_handler_commands:
|
|
78
|
+
# create ordered list from config.
|
|
79
|
+
all_handler_commands[command] = list([tool])
|
|
80
|
+
else:
|
|
81
|
+
all_handler_commands[command].append(tool)
|
|
69
82
|
|
|
70
83
|
return all_handler_commands
|
|
71
84
|
|
|
@@ -73,7 +86,7 @@ def get_all_handler_commands(config=None, tools_loaded=None) -> dict:
|
|
|
73
86
|
def get_handler_tool_version(tool: str, eda_command: str, config: dict) -> str:
|
|
74
87
|
'''Attempts to get a Command Handler's version given tool + eda_command'''
|
|
75
88
|
|
|
76
|
-
entry = config['
|
|
89
|
+
entry = config['tools'].get(tool, {})
|
|
77
90
|
if not entry:
|
|
78
91
|
return ''
|
|
79
92
|
|
|
@@ -83,7 +96,163 @@ def get_handler_tool_version(tool: str, eda_command: str, config: dict) -> str:
|
|
|
83
96
|
|
|
84
97
|
module = util.import_class_from_string(handler_name)
|
|
85
98
|
obj = module(config=config)
|
|
86
|
-
if not getattr(obj, 'get_versions', None):
|
|
87
|
-
return ''
|
|
88
99
|
|
|
89
|
-
|
|
100
|
+
# Some command classes like CommandWaves, don't have get_versions(), but
|
|
101
|
+
# have get_versions_of_tool():
|
|
102
|
+
if getattr(obj, 'get_versions_of_tool', None):
|
|
103
|
+
return obj.get_versions_of_tool(tool)
|
|
104
|
+
|
|
105
|
+
# Note that Tool.get_versions() is supposed to be 'fast', we don't always
|
|
106
|
+
# run the tool if the 'exe -version' takes too long.
|
|
107
|
+
if getattr(obj, 'get_versions', None):
|
|
108
|
+
return obj.get_versions()
|
|
109
|
+
|
|
110
|
+
return ''
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def get_handler_info_with_versions( # pylint: disable=too-many-branches
|
|
115
|
+
config: dict | None = None,
|
|
116
|
+
include_commands: bool = True,
|
|
117
|
+
sort: bool = True
|
|
118
|
+
) -> str:
|
|
119
|
+
'''Creates and returns a dict of
|
|
120
|
+
|
|
121
|
+
{'commands': (what tools/versions can run them),
|
|
122
|
+
'tools': (what version and what commands they can run)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
for arg 'config' you may use:
|
|
126
|
+
|
|
127
|
+
config, tools_loaded = get_config_and_tools_loaded()
|
|
128
|
+
'''
|
|
129
|
+
|
|
130
|
+
if not config:
|
|
131
|
+
config, tools_loaded = get_config_and_tools_loaded()
|
|
132
|
+
else:
|
|
133
|
+
tools_loaded = list(config.get('tools_loaded', []))
|
|
134
|
+
|
|
135
|
+
eda_commands = list(config.get('DEFAULT_HANDLERS', {}).keys())
|
|
136
|
+
show_versions = config.get('show_tool_versions', False)
|
|
137
|
+
|
|
138
|
+
info = {
|
|
139
|
+
'tools': {},
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if not show_versions:
|
|
144
|
+
for tool, path in config.get('auto_tools_found', {}).items():
|
|
145
|
+
info['tools'][tool] = {
|
|
146
|
+
'path': path
|
|
147
|
+
}
|
|
148
|
+
return info
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if include_commands:
|
|
152
|
+
info.update({
|
|
153
|
+
'commands': {}
|
|
154
|
+
})
|
|
155
|
+
for eda_command in eda_commands:
|
|
156
|
+
info['commands'][eda_command] = {} # init
|
|
157
|
+
|
|
158
|
+
for tool in tools_loaded:
|
|
159
|
+
|
|
160
|
+
if include_commands:
|
|
161
|
+
info['tools'][tool] = {
|
|
162
|
+
'version': '',
|
|
163
|
+
'commands': [],
|
|
164
|
+
}
|
|
165
|
+
else:
|
|
166
|
+
info['tools'][tool] = {
|
|
167
|
+
'version': '',
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for eda_command in eda_commands:
|
|
171
|
+
|
|
172
|
+
if not include_commands and info['tools'][tool]['version']:
|
|
173
|
+
# version is already set, and we're not doing for all commands:
|
|
174
|
+
break
|
|
175
|
+
|
|
176
|
+
# Note that if you have a generic handler, or a tool that has
|
|
177
|
+
# several handlers with more than one Tool class, that all can return a
|
|
178
|
+
# non blank-str version, you may have problems.
|
|
179
|
+
ver = get_handler_tool_version(
|
|
180
|
+
tool=tool, eda_command=eda_command, config=config
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
if not ver:
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
info['tools'][tool]['version'] = ver
|
|
187
|
+
|
|
188
|
+
if include_commands:
|
|
189
|
+
info['commands'][eda_command][tool] = ver
|
|
190
|
+
info['tools'][tool]['commands'].append(eda_command)
|
|
191
|
+
|
|
192
|
+
for tool, _ in info['tools'].items():
|
|
193
|
+
if tool in config.get('auto_tools_found', {}):
|
|
194
|
+
info['tools'][tool]['path'] = config['auto_tools_found'][tool]
|
|
195
|
+
|
|
196
|
+
# return the info dict with 'tools' and 'commands' entries sorted:
|
|
197
|
+
if sort:
|
|
198
|
+
for key in list(info.keys()):
|
|
199
|
+
if info[key]:
|
|
200
|
+
info[key] = dict(sorted(info[key].items()))
|
|
201
|
+
|
|
202
|
+
return info
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def pretty_info_handler_tools(
|
|
206
|
+
info: dict | None = None, config: dict | None = None, command: str | None = ''
|
|
207
|
+
) -> None:
|
|
208
|
+
'''Pretty print (via util.info) the result from get_handler_info_with_versions()
|
|
209
|
+
|
|
210
|
+
if info is None or empty, will use config to run get_handler_info_with_versions(..)
|
|
211
|
+
|
|
212
|
+
Does not include commands
|
|
213
|
+
'''
|
|
214
|
+
|
|
215
|
+
if not info:
|
|
216
|
+
info = get_handler_info_with_versions(config=config, include_commands=False, sort=True)
|
|
217
|
+
|
|
218
|
+
if not info.get('tools', {}):
|
|
219
|
+
# No tools detected
|
|
220
|
+
if command and command in config.get('command_tool_is_optional', []):
|
|
221
|
+
# but this command doesn't need tools
|
|
222
|
+
return
|
|
223
|
+
|
|
224
|
+
# if command omitted, or command may need tools, print that we don't have any
|
|
225
|
+
util.info('No tools detected!', color=Colors.yellow)
|
|
226
|
+
return
|
|
227
|
+
|
|
228
|
+
show_versions = any('version' in dvalue for dvalue in info['tools'].values())
|
|
229
|
+
|
|
230
|
+
tools_rows = [
|
|
231
|
+
['--Detected tool--', '--Path--'] # Header row.
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
if show_versions:
|
|
235
|
+
tools_rows[0].append('--Version--')
|
|
236
|
+
|
|
237
|
+
for _tool, dvalue in info['tools'].items():
|
|
238
|
+
path = dvalue.get("path", "")
|
|
239
|
+
if path:
|
|
240
|
+
path = f'({path})'
|
|
241
|
+
|
|
242
|
+
if show_versions:
|
|
243
|
+
version = dvalue.get("version", "")
|
|
244
|
+
# will defer printing again, so we can put them into aligned columns:
|
|
245
|
+
tools_rows.append([_tool, path, version])
|
|
246
|
+
else:
|
|
247
|
+
tools_rows.append([_tool, path])
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# Finally, print detected tools:
|
|
251
|
+
for rownum, row in enumerate(str_helpers.pretty_2dlist_columns(
|
|
252
|
+
tools_rows, return_as_2d_list=True, header_row_centered=False)):
|
|
253
|
+
if rownum == 0:
|
|
254
|
+
util.info(f'{Colors.bgreen}{"".join(row)}')
|
|
255
|
+
else:
|
|
256
|
+
# get the results in a padded 2D list so we can colorize the tool (index 0)
|
|
257
|
+
util.info(f'{Colors.bgreen}{row[0]}{Colors.normal}{Colors.cyan}' \
|
|
258
|
+
+ ''.join(row[1:]))
|
opencos/tools/cocotb.py
CHANGED
|
@@ -4,7 +4,7 @@ Contains classes for ToolCocotb, CommandSimCocotb.
|
|
|
4
4
|
'''
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
|
-
import
|
|
7
|
+
from importlib import metadata
|
|
8
8
|
|
|
9
9
|
from opencos import util
|
|
10
10
|
from opencos.commands import CommandSim
|
|
@@ -38,33 +38,19 @@ class ToolCocotb(Tool):
|
|
|
38
38
|
|
|
39
39
|
# Check if cocotb is installed
|
|
40
40
|
try:
|
|
41
|
-
|
|
42
|
-
[self.python_exe, '-c', 'import cocotb; print(cocotb.__version__)'],
|
|
43
|
-
capture_output=True,
|
|
44
|
-
check=True,
|
|
45
|
-
text=True
|
|
46
|
-
)
|
|
47
|
-
version = version_ret.stdout.strip()
|
|
41
|
+
version = metadata.version('cocotb')
|
|
48
42
|
self.cocotb_version = version
|
|
49
43
|
self._VERSION = version
|
|
50
44
|
util.debug(f'Found cocotb version: {version}')
|
|
51
45
|
return self._VERSION
|
|
52
|
-
except
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
except metadata.PackageNotFoundError:
|
|
47
|
+
util.warning('cocotb package not installed in python environment. '
|
|
48
|
+
'Install with: pip install cocotb; or pypackage: opencos-eda[cocotb]')
|
|
55
49
|
except Exception as e:
|
|
56
|
-
|
|
50
|
+
util.warning(f'Failed to check cocotb version: {e}')
|
|
57
51
|
|
|
58
52
|
return ''
|
|
59
53
|
|
|
60
|
-
def set_tool_defines(self):
|
|
61
|
-
super().set_tool_defines()
|
|
62
|
-
self.defines.update({
|
|
63
|
-
'SIMULATION': 1,
|
|
64
|
-
'COCOTB': 1,
|
|
65
|
-
'OC_TOOL_COCOTB': None,
|
|
66
|
-
})
|
|
67
|
-
|
|
68
54
|
|
|
69
55
|
class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
70
56
|
'''CommandSimCocotb is a command handler for: eda sim --tool=cocotb'''
|
|
@@ -109,9 +95,6 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
109
95
|
self.cocotb_test_files = []
|
|
110
96
|
|
|
111
97
|
|
|
112
|
-
def set_tool_defines(self):
|
|
113
|
-
ToolCocotb.set_tool_defines(self)
|
|
114
|
-
|
|
115
98
|
def help( # pylint: disable=dangerous-default-value
|
|
116
99
|
self, tokens: list = [], no_targets: bool = False
|
|
117
100
|
) -> None:
|
|
@@ -331,12 +314,6 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
331
314
|
'''Generate the content for the Python runner script'''
|
|
332
315
|
|
|
333
316
|
if safe_shutil_which('verilator'):
|
|
334
|
-
# TODO(drew): this shortcuts if verilator is truly usable,
|
|
335
|
-
# consider using eda_tool_helper to get "tools_loaded", which
|
|
336
|
-
# is not set in self.config['tools_loaded'] when --tool=cocotb.
|
|
337
|
-
# Would need minor refactor for eda.py methods auto_tools_order,
|
|
338
|
-
# tool_setup to go into eda_tool_helper.py, and those methods would
|
|
339
|
-
# need hooks to be non-destructive to config.
|
|
340
317
|
tmp_verilator_obj = verilator.VerilatorSim(config=self.config)
|
|
341
318
|
verilator_waivers = tmp_verilator_obj.get_verilator_tool_config_waivers()
|
|
342
319
|
else:
|
opencos/tools/invio.py
CHANGED
|
@@ -26,14 +26,8 @@ class ToolInvio(Tool):
|
|
|
26
26
|
if not spec:
|
|
27
27
|
self.error('"invio" package not in python env')
|
|
28
28
|
|
|
29
|
-
|
|
30
29
|
return super().get_versions()
|
|
31
30
|
|
|
32
|
-
def set_tool_defines(self):
|
|
33
|
-
super().set_tool_defines()
|
|
34
|
-
self.defines.update({
|
|
35
|
-
'OC_TOOL_INVIO': None,
|
|
36
|
-
})
|
|
37
31
|
|
|
38
32
|
class CommandElabInvio(CommandElab, ToolInvio):
|
|
39
33
|
'''Command handler for: eda elab --tool=invio'''
|
opencos/tools/iverilog.py
CHANGED
|
@@ -44,14 +44,6 @@ class ToolIverilog(Tool):
|
|
|
44
44
|
self._VERSION = version
|
|
45
45
|
return self._VERSION
|
|
46
46
|
|
|
47
|
-
def set_tool_defines(self):
|
|
48
|
-
# TODO(drew): come back to this, Tool doesn't have self.defines. Command does.
|
|
49
|
-
self.defines.update({
|
|
50
|
-
'SIMULATION': 1,
|
|
51
|
-
'IVERILOG': 1,
|
|
52
|
-
'OC_ASSERT_PROPERTY_NOT_SUPPORTED': 1,
|
|
53
|
-
})
|
|
54
|
-
|
|
55
47
|
|
|
56
48
|
class CommandSimIverilog(CommandSim, ToolIverilog):
|
|
57
49
|
'''CommandSimIverilog is a command handler for: eda sim --tool=iverilog'''
|
|
@@ -128,17 +120,25 @@ class CommandSimIverilog(CommandSim, ToolIverilog):
|
|
|
128
120
|
for value in self.incdirs:
|
|
129
121
|
command_list += [ '-I', value ]
|
|
130
122
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
123
|
+
if self.args['ext-defines-sv-fname']:
|
|
124
|
+
self.create_ext_defines_sv()
|
|
125
|
+
else:
|
|
126
|
+
for k,v in self.defines.items():
|
|
127
|
+
if v is None:
|
|
128
|
+
command_list += [ '-D', k ]
|
|
129
|
+
else:
|
|
130
|
+
# Generally we should only support int and str python types passed as
|
|
131
|
+
# +define+{k}={v}, but also for SystemVerilog plusargs
|
|
132
|
+
command_list += [ '-D', f'{k}={sanitize_defines_for_sh(v)}' ]
|
|
138
133
|
|
|
139
134
|
# parameters
|
|
135
|
+
# If you do -PName=Value, all parameters in the hierachy with Name will be set,
|
|
136
|
+
# so to only do top level parameters, if hierarchy isn't mentioned in the Name,
|
|
137
|
+
# would need to do -P{self.args['top'].Name=Value
|
|
140
138
|
command_list.extend(
|
|
141
|
-
self.process_parameters_get_list(
|
|
139
|
+
self.process_parameters_get_list(
|
|
140
|
+
arg_prefix='-P', hier_delimiter='.', top_hier_str=f'{self.args["top"]}.'
|
|
141
|
+
)
|
|
142
142
|
)
|
|
143
143
|
|
|
144
144
|
if not self.files_sv and not self.files_v:
|
opencos/tools/modelsim_ase.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
''' opencos.tools.modelsim_ase - Used by opencos.eda for sim/elab commands w/ --tool=modelsim_ase.
|
|
2
2
|
|
|
3
|
-
Contains classes for
|
|
3
|
+
Contains classes for CommandSimModelsimAse, CommandElabModelsimAse.
|
|
4
4
|
|
|
5
5
|
Note that this is for 32-bit Modelsim Student Edition. Consider using --tool=questa_fse instead.
|
|
6
6
|
'''
|
|
@@ -40,18 +40,6 @@ class CommandSimModelsimAse(CommonSimQuesta):
|
|
|
40
40
|
)
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
def set_tool_defines(self):
|
|
44
|
-
# Update any defines from config.tools.modelsim_ase:
|
|
45
|
-
self.defines.update(
|
|
46
|
-
self.tool_config.get(
|
|
47
|
-
'defines',
|
|
48
|
-
# defaults, if not set:
|
|
49
|
-
{'OC_ASSERT_PROPERTY_NOT_SUPPORTED': 1,
|
|
50
|
-
'OC_TOOL_MODELSIM_ASE': 1}
|
|
51
|
-
)
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
43
|
|
|
56
44
|
class CommandElabModelsimAse(CommandSimModelsimAse):
|
|
57
45
|
'''CommandElabModelsimAse is a command handler for: eda elab --tool=modelsim_ase'''
|
opencos/tools/quartus.py
CHANGED
|
@@ -42,6 +42,55 @@ class ToolQuartus(Tool):
|
|
|
42
42
|
'family': 'FPGA family for Quartus (e.g., Stratix IV, Arria 10, etc.)',
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
+
def _try_set_version_from_version_txt(self) -> None:
|
|
46
|
+
'''Attempts to use VSIM_PATH/../version.txt to get version info
|
|
47
|
+
|
|
48
|
+
Return None, may set self._VERSION
|
|
49
|
+
'''
|
|
50
|
+
util.debug(f"quartus path = {self.quartus_exe}")
|
|
51
|
+
version_txt_filepath = os.path.join(self.quartus_base_path, '..', 'version.txt')
|
|
52
|
+
if os.path.isfile(version_txt_filepath):
|
|
53
|
+
with open(version_txt_filepath, encoding='utf-8') as f:
|
|
54
|
+
for line in f.readlines():
|
|
55
|
+
if line.startswith('Version='):
|
|
56
|
+
_, version = line.strip().split('=')
|
|
57
|
+
self._VERSION = version
|
|
58
|
+
break
|
|
59
|
+
|
|
60
|
+
def _try_set_version_from_path(self) -> None:
|
|
61
|
+
'''Attempts to use portions of VSIM_PATH to get version info
|
|
62
|
+
|
|
63
|
+
Return None, may set self._VERSION
|
|
64
|
+
'''
|
|
65
|
+
m = re.search(r'(\d+)\.(\d+)', self.quartus_exe)
|
|
66
|
+
if m:
|
|
67
|
+
version = m.group(1) + '.' + m.group(2)
|
|
68
|
+
self._VERSION = version
|
|
69
|
+
|
|
70
|
+
def _try_set_version_from_exe(self) -> None:
|
|
71
|
+
'''Attempts to run: vsim --version; (max timeout 3 sec) to get version info
|
|
72
|
+
|
|
73
|
+
Return None, may set self._VERSION
|
|
74
|
+
|
|
75
|
+
Since this may fail if we don't have a valid license, we will not error if the version
|
|
76
|
+
is not determined.
|
|
77
|
+
'''
|
|
78
|
+
try:
|
|
79
|
+
result = subprocess.run(
|
|
80
|
+
[self.quartus_exe, '--version'],
|
|
81
|
+
capture_output=True, text=True, timeout=3, check=False
|
|
82
|
+
)
|
|
83
|
+
version_match = re.search(r'Version (\d+\.\d+)', result.stdout)
|
|
84
|
+
if version_match:
|
|
85
|
+
self._VERSION = version_match.group(1)
|
|
86
|
+
else:
|
|
87
|
+
util.debug("Could not determine Quartus version from: quartus_sh --version")
|
|
88
|
+
except (
|
|
89
|
+
subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError
|
|
90
|
+
):
|
|
91
|
+
util.debug("Could not determine Quartus version from: quartus_sh --version")
|
|
92
|
+
|
|
93
|
+
|
|
45
94
|
def get_versions(self) -> str:
|
|
46
95
|
if self._VERSION:
|
|
47
96
|
return self._VERSION
|
|
@@ -58,35 +107,23 @@ class ToolQuartus(Tool):
|
|
|
58
107
|
os.path.join(self.quartus_base_path, 'quartus') # vs quartus_sh
|
|
59
108
|
)
|
|
60
109
|
|
|
61
|
-
# Get version based on install path name
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
[self.quartus_exe, '--version'],
|
|
72
|
-
capture_output=True, text=True, timeout=10, check=False
|
|
73
|
-
)
|
|
74
|
-
version_match = re.search(r'Version (\d+\.\d+)', result.stdout)
|
|
75
|
-
if version_match:
|
|
76
|
-
self._VERSION = version_match.group(1)
|
|
77
|
-
else:
|
|
78
|
-
self.error("Could not determine Quartus version")
|
|
79
|
-
except (
|
|
80
|
-
subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError
|
|
81
|
-
):
|
|
82
|
-
self.error("Could not determine Quartus version")
|
|
110
|
+
# Get version based on install path name:
|
|
111
|
+
# 1. if ../version.txt exists, use that
|
|
112
|
+
# 2. Use the path name if it has version information
|
|
113
|
+
# 3. or by running quartus_sh --version (max timeout=3)
|
|
114
|
+
# If we cannot find the version return '' and warn, do not error.
|
|
115
|
+
self._try_set_version_from_version_txt()
|
|
116
|
+
if not self._VERSION:
|
|
117
|
+
self._try_set_version_from_path()
|
|
118
|
+
if not self._VERSION:
|
|
119
|
+
self._try_set_version_from_exe()
|
|
83
120
|
|
|
84
121
|
if self._VERSION:
|
|
85
122
|
numbers_list = self._VERSION.split('.')
|
|
86
123
|
self.quartus_year = int(numbers_list[0])
|
|
87
124
|
self.quartus_release = int(numbers_list[1])
|
|
88
125
|
else:
|
|
89
|
-
|
|
126
|
+
util.warning(f"Quartus version not found, quartus path = {self.quartus_exe}")
|
|
90
127
|
return self._VERSION
|
|
91
128
|
|
|
92
129
|
def set_tool_defines(self) -> None:
|
|
@@ -513,9 +550,29 @@ class CommandFListQuartus(CommandFList, ToolQuartus):
|
|
|
513
550
|
CommandFList.__init__(self, config=config)
|
|
514
551
|
ToolQuartus.__init__(self, config=self.config)
|
|
515
552
|
self.args.update({
|
|
516
|
-
'emit
|
|
553
|
+
# synth/project style Flist, can't emit these:
|
|
554
|
+
'emit-parameter': False,
|
|
555
|
+
'emit-plusargs': False,
|
|
517
556
|
})
|
|
518
557
|
|
|
558
|
+
def get_flist_plusargs_list(self) -> list:
|
|
559
|
+
'''Overriden from CommandFList.'''
|
|
560
|
+
if self.args['unprocessed-plusargs']:
|
|
561
|
+
util.warning('Command "flist" for --tool=quartus is not intended for simulation',
|
|
562
|
+
'and plusargs were present. They will NOT be included in the flist:',
|
|
563
|
+
f'{self.args["unprocessed-plusargs"]}')
|
|
564
|
+
|
|
565
|
+
return []
|
|
566
|
+
|
|
567
|
+
def get_flist_parameter_list(self) -> list:
|
|
568
|
+
'''Overriden from CommandFList.'''
|
|
569
|
+
if self.parameters:
|
|
570
|
+
util.warning('Command "flist" for --tool=quartus is not intended for simulation',
|
|
571
|
+
'and parameters were present. They will NOT be included in the flist:',
|
|
572
|
+
f'{self.parameters}')
|
|
573
|
+
|
|
574
|
+
return []
|
|
575
|
+
|
|
519
576
|
|
|
520
577
|
class CommandProjQuartus(CommandProj, ToolQuartus):
|
|
521
578
|
'''CommandProjQuartus is a command handler for: eda proj --tool=quartus'''
|
opencos/tools/questa.py
CHANGED
|
@@ -39,20 +39,6 @@ class CommandSimQuesta(CommonSimQuesta):
|
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def set_tool_defines(self):
|
|
43
|
-
'''Override from questa.ToolQuesta'''
|
|
44
|
-
# Update any defines from config.tools.questa_fse:
|
|
45
|
-
self.defines.update(
|
|
46
|
-
self.tool_config.get(
|
|
47
|
-
'defines',
|
|
48
|
-
# defaults, if not set:
|
|
49
|
-
{
|
|
50
|
-
'OC_TOOL_QUESTA': 1
|
|
51
|
-
}
|
|
52
|
-
)
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
|
|
56
42
|
class CommandElabQuesta(CommandSimQuesta):
|
|
57
43
|
'''CommandElabQuesta is a command handler for: eda elab --tool=questa'''
|
|
58
44
|
|