opencos-eda 0.2.55__py3-none-any.whl → 0.2.56__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 +10 -0
- opencos/commands/sim.py +31 -0
- opencos/deps/defaults.py +2 -0
- opencos/deps/deps_processor.py +39 -1
- opencos/deps_schema.py +22 -0
- opencos/eda_base.py +108 -10
- opencos/eda_config.py +2 -1
- opencos/export_helper.py +15 -5
- opencos/hw/oc_cli.py +1 -1
- opencos/names.py +4 -1
- opencos/tests/test_eda_synth.py +12 -0
- opencos/tools/invio_helpers.py +25 -4
- opencos/tools/iverilog.py +5 -0
- opencos/tools/modelsim_ase.py +6 -1
- opencos/tools/quartus.py +32 -6
- opencos/tools/riviera.py +17 -3
- opencos/tools/slang.py +5 -0
- opencos/tools/slang_yosys.py +9 -0
- opencos/tools/surelog.py +5 -0
- opencos/tools/verilator.py +5 -0
- opencos/tools/vivado.py +15 -2
- {opencos_eda-0.2.55.dist-info → opencos_eda-0.2.56.dist-info}/METADATA +1 -1
- {opencos_eda-0.2.55.dist-info → opencos_eda-0.2.56.dist-info}/RECORD +28 -28
- {opencos_eda-0.2.55.dist-info → opencos_eda-0.2.56.dist-info}/WHEEL +0 -0
- {opencos_eda-0.2.55.dist-info → opencos_eda-0.2.56.dist-info}/entry_points.txt +0 -0
- {opencos_eda-0.2.55.dist-info → opencos_eda-0.2.56.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.2.55.dist-info → opencos_eda-0.2.56.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.2.55.dist-info → opencos_eda-0.2.56.dist-info}/top_level.txt +0 -0
opencos/commands/flist.py
CHANGED
|
@@ -10,6 +10,7 @@ import os
|
|
|
10
10
|
from opencos import util
|
|
11
11
|
from opencos.eda_base import CommandDesign
|
|
12
12
|
from opencos.utils.str_helpers import strip_all_quotes
|
|
13
|
+
from opencos.commands.sim import parameters_dict_get_command_list
|
|
13
14
|
|
|
14
15
|
class CommandFList(CommandDesign):
|
|
15
16
|
'''Base class command handler for: eda flist ...'''
|
|
@@ -22,6 +23,7 @@ class CommandFList(CommandDesign):
|
|
|
22
23
|
'eda-dir' : 'eda.flist', # user can specify eda-dir if files are generated.
|
|
23
24
|
'out' : "flist.out",
|
|
24
25
|
'emit-define' : True,
|
|
26
|
+
'emit-parameter' : True,
|
|
25
27
|
'emit-incdir' : True,
|
|
26
28
|
'emit-v' : True,
|
|
27
29
|
'emit-sv' : True,
|
|
@@ -29,6 +31,7 @@ class CommandFList(CommandDesign):
|
|
|
29
31
|
'emit-cpp' : True,
|
|
30
32
|
'emit-non-sources' : True, # as comments, from DEPS 'reqs'
|
|
31
33
|
'prefix-define' : "+define+",
|
|
34
|
+
'prefix-parameter' : "-G",
|
|
32
35
|
'prefix-incdir' : "+incdir+",
|
|
33
36
|
'prefix-v' : "",
|
|
34
37
|
'prefix-sv' : "",
|
|
@@ -179,6 +182,13 @@ class CommandFList(CommandDesign):
|
|
|
179
182
|
newline = prefix + qd1 + f"{d}{ed1}{value}" + qd2
|
|
180
183
|
print(newline, file=fo)
|
|
181
184
|
|
|
185
|
+
if self.args['emit-parameter']:
|
|
186
|
+
prefix = strip_all_quotes(self.args['prefix-parameter'])
|
|
187
|
+
for item in parameters_dict_get_command_list(
|
|
188
|
+
params=self.parameters, arg_prefix=prefix
|
|
189
|
+
):
|
|
190
|
+
print(item, file=fo)
|
|
191
|
+
|
|
182
192
|
if self.args['emit-incdir']:
|
|
183
193
|
prefix = strip_all_quotes(self.args['prefix-incdir'])
|
|
184
194
|
for i in self.incdirs:
|
opencos/commands/sim.py
CHANGED
|
@@ -17,6 +17,33 @@ from opencos import util, export_helper
|
|
|
17
17
|
from opencos.eda_base import CommandDesign, Tool
|
|
18
18
|
from opencos.utils import status_constants
|
|
19
19
|
|
|
20
|
+
from opencos.utils.str_helpers import sanitize_defines_for_sh, strip_outer_quotes
|
|
21
|
+
|
|
22
|
+
def parameters_dict_get_command_list(params: dict, arg_prefix: str = '-G') -> list:
|
|
23
|
+
'''Given dict of parameters, returns a command list'''
|
|
24
|
+
|
|
25
|
+
ret_list = []
|
|
26
|
+
if ' ' in arg_prefix:
|
|
27
|
+
arg_list_prefix = arg_prefix.split()
|
|
28
|
+
arg_str_prefix = ''
|
|
29
|
+
else:
|
|
30
|
+
arg_list_prefix = []
|
|
31
|
+
arg_str_prefix = arg_prefix
|
|
32
|
+
|
|
33
|
+
for k,v in params.items():
|
|
34
|
+
if not isinstance(v, (int, str)):
|
|
35
|
+
util.warning(f'parameter {k} has value: {v}, parameters must be int/string types')
|
|
36
|
+
|
|
37
|
+
ret_list.extend(arg_list_prefix)
|
|
38
|
+
if isinstance(v, int):
|
|
39
|
+
ret_list.append(f'{arg_str_prefix}{k}={v}')
|
|
40
|
+
else: # string
|
|
41
|
+
v = strip_outer_quotes(v.strip('\n'))
|
|
42
|
+
v = '"' + v + '"'
|
|
43
|
+
ret_list.append(f'{arg_str_prefix}{k}={sanitize_defines_for_sh(v)}')
|
|
44
|
+
return ret_list
|
|
45
|
+
|
|
46
|
+
|
|
20
47
|
class CommandSim(CommandDesign):
|
|
21
48
|
'''Base class command handler for: eda sim ...'''
|
|
22
49
|
|
|
@@ -80,6 +107,10 @@ class CommandSim(CommandDesign):
|
|
|
80
107
|
|
|
81
108
|
self.args['verilate-args'] = []
|
|
82
109
|
|
|
110
|
+
def process_parameters_get_list(self, arg_prefix: str = '-G') -> list:
|
|
111
|
+
'''Returns list (suitable command list for shell or for tool) from self.parameters'''
|
|
112
|
+
return parameters_dict_get_command_list(params=self.parameters, arg_prefix=arg_prefix)
|
|
113
|
+
|
|
83
114
|
def process_plusarg(self, plusarg: str, pwd: str = os.getcwd()) -> None:
|
|
84
115
|
'''Override for CommandDesign.process_plusarg(..)'''
|
|
85
116
|
maybe_plusarg = CommandDesign.process_plusarg(self, plusarg, pwd)
|
opencos/deps/defaults.py
CHANGED
|
@@ -31,6 +31,7 @@ KNOWN_EDA_COMMANDS = set([
|
|
|
31
31
|
SUPPORTED_TARGET_TABLE_KEYS = set([
|
|
32
32
|
'args',
|
|
33
33
|
'defines',
|
|
34
|
+
'parameters',
|
|
34
35
|
'incdirs',
|
|
35
36
|
'top',
|
|
36
37
|
'deps',
|
|
@@ -52,6 +53,7 @@ SUPPORTED_TAG_KEYS = set([
|
|
|
52
53
|
'deps',
|
|
53
54
|
'reqs',
|
|
54
55
|
'defines',
|
|
56
|
+
'parameters',
|
|
55
57
|
'incdirs',
|
|
56
58
|
'replace-config-tools',
|
|
57
59
|
'additive-config-tools',
|
opencos/deps/deps_processor.py
CHANGED
|
@@ -91,6 +91,22 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
91
91
|
v = v.replace('%SEED%', str(self.args.get('seed', 1)))
|
|
92
92
|
self.command_design_ref.process_plusarg(f'+define+{k}={v}')
|
|
93
93
|
|
|
94
|
+
|
|
95
|
+
def apply_parameters(self, parameters_dict: dict):
|
|
96
|
+
'''Given parameters_dict, applies them to our self.command_design_ref obj'''
|
|
97
|
+
if not isinstance(parameters_dict, dict):
|
|
98
|
+
self.error(f"{parameters_dict=} is not type dict, can't apply defines,",
|
|
99
|
+
f"in {self.caller_info}")
|
|
100
|
+
for k,v in parameters_dict.items():
|
|
101
|
+
if v is None or v == '' or not isinstance(v, (int, str, bool)):
|
|
102
|
+
warning(f'parameter {k} has value: {v}, parameters must be bool/int/string types',
|
|
103
|
+
f'from {self.caller_info}')
|
|
104
|
+
else:
|
|
105
|
+
self.command_design_ref.set_parameter(
|
|
106
|
+
name=k, value=v, caller_info=self.caller_info
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
94
110
|
def apply_incdirs(self, incdirs_list:list):
|
|
95
111
|
'''Given incdirs_list, applies them to our self.command_design_ref obj'''
|
|
96
112
|
if not isinstance(incdirs_list, (str, list)):
|
|
@@ -252,6 +268,8 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
252
268
|
remaining_deps_list += self.process_tags()
|
|
253
269
|
elif key == 'defines':
|
|
254
270
|
self.process_defines()
|
|
271
|
+
elif key == 'parameters':
|
|
272
|
+
self.process_parameters()
|
|
255
273
|
elif key == 'incdirs':
|
|
256
274
|
self.process_incdirs()
|
|
257
275
|
elif key == 'top':
|
|
@@ -426,6 +444,9 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
426
444
|
# apply defines:
|
|
427
445
|
self.apply_defines(value.get('defines', {}))
|
|
428
446
|
|
|
447
|
+
elif key == 'parameters':
|
|
448
|
+
self.apply_parameters(value.get('parameters', {}))
|
|
449
|
+
|
|
429
450
|
elif key == 'incdirs':
|
|
430
451
|
# apply incdirs:
|
|
431
452
|
self.apply_incdirs(value.get('incdirs', []))
|
|
@@ -517,6 +538,22 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
517
538
|
|
|
518
539
|
self.apply_defines(entry_defines)
|
|
519
540
|
|
|
541
|
+
def process_parameters(self):
|
|
542
|
+
'''Returns None, applies parameters (dict, if any) from self.deps_entry to
|
|
543
|
+
self.command_design_ref.'''
|
|
544
|
+
|
|
545
|
+
# Parameters:
|
|
546
|
+
# apply command specific parameters, with higher priority than the a
|
|
547
|
+
# deps_entry['sim']['parameters'] entry,
|
|
548
|
+
# do this with dict1.update(dict2):
|
|
549
|
+
entry_parameters = {}
|
|
550
|
+
entry_parameters.update(self.deps_entry.get('parameters', {}))
|
|
551
|
+
entry_parameters.update(self.entry_eda_command.get('parameters', {}))
|
|
552
|
+
assert isinstance(entry_parameters, dict), \
|
|
553
|
+
f'{entry_parameters=} for in {self.caller_info} must be a dict'
|
|
554
|
+
|
|
555
|
+
self.apply_parameters(entry_parameters)
|
|
556
|
+
|
|
520
557
|
def process_incdirs(self) -> None:
|
|
521
558
|
'''Returns None, applies incdirs (dict, if any) from self.deps_entry to
|
|
522
559
|
self.command_design_ref.'''
|
|
@@ -700,7 +737,8 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
700
737
|
deps_targets_to_resolve.append(command_tuple)
|
|
701
738
|
|
|
702
739
|
|
|
703
|
-
elif isinstance(dep, str) and
|
|
740
|
+
elif isinstance(dep, str) and \
|
|
741
|
+
any(dep.startswith(x) for x in ['+define+', '+incdir+']):
|
|
704
742
|
# Note: we still support +define+ and +incdir in the deps list.
|
|
705
743
|
# check for compile-time Verilog style plusarg, which are supported under targets
|
|
706
744
|
# These are not run-time Verilog style plusargs comsumable from within the .sv:
|
opencos/deps_schema.py
CHANGED
|
@@ -11,6 +11,9 @@ my_target_name:
|
|
|
11
11
|
defines: <---- defines, optional table
|
|
12
12
|
USER_DEFINE_VALUE: 12
|
|
13
13
|
|
|
14
|
+
parameters: <---- parameters, optional table
|
|
15
|
+
USER_PARAM_VALUE: 12
|
|
16
|
+
|
|
14
17
|
incdirs: <---- incdirs, optional array (or string)
|
|
15
18
|
- ./
|
|
16
19
|
|
|
@@ -32,6 +35,9 @@ my_target_name:
|
|
|
32
35
|
defines: <---- defines, optional table of (key: str Or null)
|
|
33
36
|
USER_DEFINE_VALUE: 12
|
|
34
37
|
|
|
38
|
+
parameters: <---- parameters, optional table
|
|
39
|
+
USER_PARAM_VALUE: 12
|
|
40
|
+
|
|
35
41
|
incdirs: <---- incdirs, optional array of strings
|
|
36
42
|
- ./
|
|
37
43
|
|
|
@@ -55,6 +61,7 @@ METADATA: <---- (optional) unstructured table
|
|
|
55
61
|
|
|
56
62
|
my_target_name:
|
|
57
63
|
defines: <---- defines, optional table
|
|
64
|
+
parameters: <---- parameters, optional table
|
|
58
65
|
incdirs: <---- incdirs, optional array (or string)
|
|
59
66
|
top: tb <---- top, optional string
|
|
60
67
|
deps: <---- TARGET_DEPS_CONTENTS schema
|
|
@@ -105,6 +112,8 @@ my_target_name:
|
|
|
105
112
|
to the current target for this named eda command.
|
|
106
113
|
defines: <---- optional table, defines to be applied to the current
|
|
107
114
|
target for this named eda command.
|
|
115
|
+
parameters: <---- optional table, parameters to be applied to the current
|
|
116
|
+
target to for this named eda command.
|
|
108
117
|
incdirs: <---- optional array (or string) incdirs to be applied to
|
|
109
118
|
the current target for this named eda command.
|
|
110
119
|
tags: <---- tags, optional table using TARGET_TAGS_TABLE schema.
|
|
@@ -204,6 +213,9 @@ TARGET_EDA_COMMAND_ENTRY_TABLE = {
|
|
|
204
213
|
Optional('defines'): {
|
|
205
214
|
Optional(str): Or(str, int, type(None)),
|
|
206
215
|
},
|
|
216
|
+
Optional('parameters'): {
|
|
217
|
+
Optional(str): Or(str, int),
|
|
218
|
+
},
|
|
207
219
|
Optional('incdirs'): ARRAY_OR_SPACE_SEPARATED_STRING,
|
|
208
220
|
}
|
|
209
221
|
|
|
@@ -226,6 +238,9 @@ TARGET_TAGS_TABLE = {
|
|
|
226
238
|
Optional('defines'): {
|
|
227
239
|
Optional(str): Or(str, int, type(None)),
|
|
228
240
|
},
|
|
241
|
+
Optional('parameters'): {
|
|
242
|
+
Optional(str): Or(str, int),
|
|
243
|
+
},
|
|
229
244
|
Optional('incdirs'): ARRAY_OR_SPACE_SEPARATED_STRING,
|
|
230
245
|
Optional('replace-config-tools'): dict,
|
|
231
246
|
Optional('additive-config-tools'): dict,
|
|
@@ -244,6 +259,10 @@ TARGET_CONTENTS = Or(
|
|
|
244
259
|
Optional('defines'): {
|
|
245
260
|
Optional(str): Or(str, int, type(None)),
|
|
246
261
|
},
|
|
262
|
+
# parameters: table of key-value
|
|
263
|
+
Optional('parameters'): {
|
|
264
|
+
Optional(str): Or(str, int),
|
|
265
|
+
},
|
|
247
266
|
# incdirs: array
|
|
248
267
|
Optional('incdirs'): ARRAY_OR_SPACE_SEPARATED_STRING,
|
|
249
268
|
# top: string
|
|
@@ -302,6 +321,9 @@ FILE_SIMPLIFIED = Schema(
|
|
|
302
321
|
Optional('defines'): {
|
|
303
322
|
Optional(str): Or(type(None), str),
|
|
304
323
|
},
|
|
324
|
+
Optional('parameters'): {
|
|
325
|
+
Optional(str): str,
|
|
326
|
+
},
|
|
305
327
|
Optional('incdirs'): [str],
|
|
306
328
|
Optional('top'): str,
|
|
307
329
|
Optional('deps'): [str],
|
opencos/eda_base.py
CHANGED
|
@@ -831,7 +831,33 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
831
831
|
lines.append(indent_me(f" --{k:20} : string : {vstr:12}{khelp}"))
|
|
832
832
|
else:
|
|
833
833
|
lines.append(indent_me(f" --{k:20} : <unknown> : {vstr:12}{khelp}"))
|
|
834
|
+
|
|
835
|
+
lines.append('')
|
|
836
|
+
lines.append(indent_me((
|
|
837
|
+
" -G<parameterName>=<value> "
|
|
838
|
+
" Add parameter to top level, support bit/int/string types only."
|
|
839
|
+
" Example: -GDEPTH=8 (DEPTH treated as SV int/integer)."
|
|
840
|
+
" -GENABLE=1 (ENABLED treated as SV bit/int/integer)."
|
|
841
|
+
" -GName=eda (Name treated as SV string \"eda\")."
|
|
842
|
+
)))
|
|
843
|
+
lines.append(indent_me((
|
|
844
|
+
" +define+<defineName> "
|
|
845
|
+
" Add define w/out value to tool ahead of SV sources"
|
|
846
|
+
" Example: +define+SIM_SPEEDUP"
|
|
847
|
+
)))
|
|
848
|
+
lines.append(indent_me((
|
|
849
|
+
" +define+<defineName>=<value> "
|
|
850
|
+
" Add define w/ value to tool ahead of SV sources"
|
|
851
|
+
" Example: +define+TECH_LIB=2 +define+FULL_NAME=\"E D A\""
|
|
852
|
+
)))
|
|
853
|
+
lines.append(indent_me((
|
|
854
|
+
" +incdir+<path> "
|
|
855
|
+
" Add path (absolute or relative) for include directories"
|
|
856
|
+
" for SystemVerilog `include \"<some-file>.svh\""
|
|
857
|
+
" Example: +incdir+../lib"
|
|
858
|
+
)))
|
|
834
859
|
lines.append('')
|
|
860
|
+
|
|
835
861
|
for line in lines:
|
|
836
862
|
print(line)
|
|
837
863
|
|
|
@@ -922,6 +948,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
922
948
|
),
|
|
923
949
|
})
|
|
924
950
|
self.defines = {}
|
|
951
|
+
self.parameters = {}
|
|
925
952
|
self.incdirs = []
|
|
926
953
|
self.files = {}
|
|
927
954
|
self.files_v = []
|
|
@@ -1086,10 +1113,72 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1086
1113
|
# TODO(drew): Use the helper method in util for this instead to peek in file contents?
|
|
1087
1114
|
return os.path.splitext(os.path.basename(name))[0]
|
|
1088
1115
|
|
|
1116
|
+
def set_parameter(
|
|
1117
|
+
self, name: str, value, caller_info: str = '(CLI)',
|
|
1118
|
+
wrap_str_double_quotes: bool = True
|
|
1119
|
+
) -> None:
|
|
1120
|
+
'''Safe wrapper for setting a parameter (can only set once, from CLI or DEPS)'''
|
|
1121
|
+
|
|
1122
|
+
if name in self.parameters:
|
|
1123
|
+
util.debug("Parameter not set because it is already modified",
|
|
1124
|
+
f"(via -G<Name>=<Value>): {name}={value}; orig value",
|
|
1125
|
+
f'{self.parameters[name]} from {caller_info}')
|
|
1126
|
+
else:
|
|
1127
|
+
if isinstance(value, bool):
|
|
1128
|
+
value = int(value)
|
|
1129
|
+
elif isinstance(value, str):
|
|
1130
|
+
value = strip_outer_quotes(value.strip('\n'))
|
|
1131
|
+
if wrap_str_double_quotes:
|
|
1132
|
+
value = '"' + value + '"'
|
|
1133
|
+
self.parameters[name] = value
|
|
1134
|
+
util.debug(f"Parameter (via -G<Name>=<Value>): {name}={value}",
|
|
1135
|
+
f'from {caller_info}')
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
def process_parameter_arg(
|
|
1139
|
+
self, text: str, pwd: str = os.getcwd()
|
|
1140
|
+
) -> None:
|
|
1141
|
+
'''Retuns None, parses -G<Name>=<Value> adds to internal self.parameters.'''
|
|
1142
|
+
|
|
1143
|
+
# Deal with raw CLI/bash/powershell argparser, strip all outer quotes.
|
|
1144
|
+
text = strip_outer_quotes(text)
|
|
1145
|
+
if not pwd:
|
|
1146
|
+
pwd = ''
|
|
1147
|
+
|
|
1148
|
+
if not text.startswith('-G'):
|
|
1149
|
+
self.error(f"Didn't understand -G parameter arg: '{text}'",
|
|
1150
|
+
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1151
|
+
return
|
|
1152
|
+
|
|
1153
|
+
text = text[2:] # strip leading -G
|
|
1154
|
+
m = re.match(r'^(\w+)$', text)
|
|
1155
|
+
if m:
|
|
1156
|
+
k = m.group(1)
|
|
1157
|
+
util.warning(f"Parameter {k} has no value and will not be applied")
|
|
1158
|
+
return
|
|
1159
|
+
m = re.match(r'^(\w+)\=(\S+)$', text)
|
|
1160
|
+
if not m:
|
|
1161
|
+
m = re.match(r'^(\w+)\=(\"[^\"]*\")$', text)
|
|
1162
|
+
if m:
|
|
1163
|
+
k = m.group(1)
|
|
1164
|
+
v = m.group(2)
|
|
1165
|
+
# since this is coming from a CLI string, we have to guess at types,
|
|
1166
|
+
# for int or bool (not str) and convert bool to int:
|
|
1167
|
+
if not isinstance(v, (int, str)):
|
|
1168
|
+
self.error(f"Didn't understand -G parameter arg: name={k} value={v}",
|
|
1169
|
+
f"value must be int/str type, from: '{text}'",
|
|
1170
|
+
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1171
|
+
return
|
|
1172
|
+
try:
|
|
1173
|
+
v = int(v)
|
|
1174
|
+
except ValueError:
|
|
1175
|
+
pass
|
|
1176
|
+
self.set_parameter(k, v)
|
|
1177
|
+
|
|
1089
1178
|
|
|
1090
1179
|
def process_plusarg( # pylint: disable=too-many-branches
|
|
1091
1180
|
self, plusarg: str, pwd: str = os.getcwd()
|
|
1092
|
-
) ->
|
|
1181
|
+
) -> str:
|
|
1093
1182
|
'''Retuns str, parses a +define+, +incdir+, +key=value str; adds to internal.
|
|
1094
1183
|
|
|
1095
1184
|
Adds to self.defines, self.incdirs,
|
|
@@ -1112,7 +1201,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1112
1201
|
k = m.group(1)
|
|
1113
1202
|
self.defines[k] = None
|
|
1114
1203
|
util.debug(f"Defined {k}")
|
|
1115
|
-
return
|
|
1204
|
+
return ''
|
|
1116
1205
|
m = re.match(r'^(\w+)\=(\S+)$', plusarg)
|
|
1117
1206
|
if not m:
|
|
1118
1207
|
m = re.match(r'^(\w+)\=(\"[^\"]*\")$', plusarg)
|
|
@@ -1126,10 +1215,10 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1126
1215
|
v = v.replace('%SEED%', str(self.args.get('seed', 1)))
|
|
1127
1216
|
self.defines[k] = v
|
|
1128
1217
|
util.debug(f"Defined {k}={v}")
|
|
1129
|
-
return
|
|
1218
|
+
return ''
|
|
1130
1219
|
self.error(f"Didn't understand +define+: '{plusarg}'",
|
|
1131
1220
|
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1132
|
-
return
|
|
1221
|
+
return ''
|
|
1133
1222
|
|
|
1134
1223
|
if plusarg.startswith('+incdir+'):
|
|
1135
1224
|
plusarg = plusarg[len('+incdir+'):]
|
|
@@ -1139,16 +1228,16 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1139
1228
|
if incdir not in self.incdirs:
|
|
1140
1229
|
self.incdirs.append(os.path.abspath(incdir))
|
|
1141
1230
|
util.debug(f"Added include dir '{os.path.abspath(incdir)}'")
|
|
1142
|
-
return
|
|
1231
|
+
return ''
|
|
1143
1232
|
self.error(f"Didn't understand +incdir+: '{plusarg}'",
|
|
1144
1233
|
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1145
|
-
return
|
|
1234
|
+
return ''
|
|
1146
1235
|
|
|
1147
1236
|
# remaining plusargs as stored in self.args['unprocessed-plusargs'] (list)
|
|
1148
1237
|
if plusarg.startswith('+'):
|
|
1149
1238
|
if not self.config.get('bare_plusarg_supported', False):
|
|
1150
1239
|
self.error(f"bare plusarg(s) are not supported: {plusarg}'")
|
|
1151
|
-
return
|
|
1240
|
+
return ''
|
|
1152
1241
|
if plusarg not in self.args['unprocessed-plusargs']:
|
|
1153
1242
|
self.args['unprocessed-plusargs'].append(plusarg)
|
|
1154
1243
|
# For anything added to unprocessed-plusarg, we have to return it, to let
|
|
@@ -1157,7 +1246,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1157
1246
|
|
|
1158
1247
|
self.error(f"Didn't understand +plusarg: '{plusarg}'",
|
|
1159
1248
|
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1160
|
-
return
|
|
1249
|
+
return ''
|
|
1161
1250
|
|
|
1162
1251
|
|
|
1163
1252
|
def append_shell_commands(self, cmds : list) -> None:
|
|
@@ -1439,8 +1528,8 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1439
1528
|
unparsed = Command.process_tokens(self, tokens, process_all=False, pwd=pwd)
|
|
1440
1529
|
util.debug(f'CommandDesign - after Command.process_tokens(..) {unparsed=}')
|
|
1441
1530
|
|
|
1442
|
-
# deal with +define
|
|
1443
|
-
# walk the list, remove all items after we're done.
|
|
1531
|
+
# deal with +define+, +incdir+, +(plusargName)+, or -GParameterName=Value:
|
|
1532
|
+
# consume it and remove from unparsed, walk the list, remove all items after we're done.
|
|
1444
1533
|
remove_list = []
|
|
1445
1534
|
for token in unparsed:
|
|
1446
1535
|
# Since this is a raw argparser, we may have args that come from shlex.quote(token),
|
|
@@ -1454,6 +1543,15 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1454
1543
|
plusarg = strip_outer_quotes(token)
|
|
1455
1544
|
self.process_plusarg(plusarg, pwd=pwd)
|
|
1456
1545
|
remove_list.append(token)
|
|
1546
|
+
continue
|
|
1547
|
+
|
|
1548
|
+
# Parameters in -G<word>=<something>
|
|
1549
|
+
m = re.match(r"^\'?\-G\w+\=.+", token)
|
|
1550
|
+
if m:
|
|
1551
|
+
# Copy and strip all outer ' or " on the text:
|
|
1552
|
+
param = strip_outer_quotes(token)
|
|
1553
|
+
self.process_parameter_arg(param, pwd=pwd)
|
|
1554
|
+
remove_list.append(token)
|
|
1457
1555
|
|
|
1458
1556
|
for x in remove_list:
|
|
1459
1557
|
unparsed.remove(x)
|
opencos/eda_config.py
CHANGED
|
@@ -305,7 +305,8 @@ def write_eda_config_and_args(
|
|
|
305
305
|
fullpath = os.path.join(dirpath, filename)
|
|
306
306
|
data = {}
|
|
307
307
|
for x in ['command_name', 'config', 'target', 'args', 'modified_args', 'defines',
|
|
308
|
-
'incdirs', 'files_v', 'files_sv', 'files_vhd'
|
|
308
|
+
'incdirs', 'files_v', 'files_sv', 'files_vhd', 'files_cpp', 'files_sdc',
|
|
309
|
+
'files_non_source']:
|
|
309
310
|
# Use deep copy b/c otherwise these are references to opencos.eda.
|
|
310
311
|
data[x] = copy.deepcopy(getattr(command_obj_ref, x, ''))
|
|
311
312
|
|
opencos/export_helper.py
CHANGED
|
@@ -387,6 +387,13 @@ class ExportHelper:
|
|
|
387
387
|
paths.
|
|
388
388
|
'''
|
|
389
389
|
|
|
390
|
+
# We'll copy files_sv and files_v later, along with discovered included files,
|
|
391
|
+
# need to copy any others:
|
|
392
|
+
remaing_files_to_cp = []
|
|
393
|
+
for x in self.cmd_design_obj.files.keys():
|
|
394
|
+
if x not in self.cmd_design_obj.files_v + self.cmd_design_obj.files_sv:
|
|
395
|
+
remaing_files_to_cp.append(x)
|
|
396
|
+
|
|
390
397
|
# Also sets our list of included files.
|
|
391
398
|
self.included_files = get_list_sv_included_files(
|
|
392
399
|
all_src_files=self.cmd_design_obj.files_sv + self.cmd_design_obj.files_v,
|
|
@@ -398,7 +405,8 @@ class ExportHelper:
|
|
|
398
405
|
|
|
399
406
|
info(f"export_helper: {self.target=} included files {self.included_files=}")
|
|
400
407
|
|
|
401
|
-
|
|
408
|
+
|
|
409
|
+
for filename in remaing_files_to_cp:
|
|
402
410
|
dst = os.path.join(self.out_dir, os.path.split(filename)[1])
|
|
403
411
|
if not os.path.exists(dst):
|
|
404
412
|
shutil.copy(src=filename, dst=dst)
|
|
@@ -415,11 +423,13 @@ class ExportHelper:
|
|
|
415
423
|
|
|
416
424
|
info(f'export_helper: Creating DEPS.yml for {self.target=} in {self.out_dir=}')
|
|
417
425
|
|
|
418
|
-
# Need to strip path information from our files_sv and files_v
|
|
426
|
+
# Need to strip path information from our files_sv and files_v
|
|
427
|
+
# (and all source files: cpp, sdc, etc; but skip the non-source files):
|
|
419
428
|
deps_files = []
|
|
420
|
-
for fullpath in self.cmd_design_obj.
|
|
421
|
-
|
|
422
|
-
|
|
429
|
+
for fullpath in self.cmd_design_obj.files.keys():
|
|
430
|
+
if fullpath not in self.cmd_design_obj.files_non_source:
|
|
431
|
+
filename = os.path.split(fullpath)[1]
|
|
432
|
+
deps_files.append(filename)
|
|
423
433
|
|
|
424
434
|
|
|
425
435
|
data = {
|
opencos/hw/oc_cli.py
CHANGED
|
@@ -2508,7 +2508,7 @@ name_tables = { 'OC_VENDOR' : {},
|
|
|
2508
2508
|
}
|
|
2509
2509
|
|
|
2510
2510
|
def parse_names():
|
|
2511
|
-
name_tables.update(opencos_names.
|
|
2511
|
+
name_tables.update(opencos_names.NAMES) #update our global name_table from names.py
|
|
2512
2512
|
|
|
2513
2513
|
def lookup_table_string(table, index):
|
|
2514
2514
|
if isinstance(table, str) and table in name_tables:
|
opencos/names.py
CHANGED
|
@@ -13,11 +13,12 @@ just needs to set a couple of these statically.
|
|
|
13
13
|
all values in this file are in hex.
|
|
14
14
|
'''
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
NAMES = {
|
|
17
17
|
|
|
18
18
|
'OC_VENDOR': {
|
|
19
19
|
0: "None",
|
|
20
20
|
1: "Xilinx",
|
|
21
|
+
2: "Altera",
|
|
21
22
|
},
|
|
22
23
|
|
|
23
24
|
'OC_BOARD': {
|
|
@@ -28,11 +29,13 @@ table = {
|
|
|
28
29
|
4: "U55N",
|
|
29
30
|
5: "U50C",
|
|
30
31
|
6: "PYNQ-Z2",
|
|
32
|
+
7: "AG3C_DEVKIT",
|
|
31
33
|
},
|
|
32
34
|
|
|
33
35
|
'OC_LIBRARY': {
|
|
34
36
|
0: "None",
|
|
35
37
|
1: "Ultrascale+",
|
|
38
|
+
2: "Agilex3"
|
|
36
39
|
},
|
|
37
40
|
|
|
38
41
|
'PLL_TYPES': {
|
opencos/tests/test_eda_synth.py
CHANGED
|
@@ -8,6 +8,7 @@ import pytest
|
|
|
8
8
|
from opencos import eda, eda_tool_helper
|
|
9
9
|
from opencos.tests import helpers
|
|
10
10
|
from opencos.tests.helpers import Helpers
|
|
11
|
+
from opencos.utils.markup_helpers import yaml_safe_load
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
THISPATH = os.path.dirname(__file__)
|
|
@@ -108,6 +109,17 @@ class TestsSlangYosys(Helpers):
|
|
|
108
109
|
rc = self.log_it(cmd_str, use_eda_wrap=False)
|
|
109
110
|
assert rc == 0
|
|
110
111
|
|
|
112
|
+
# Since vanilla yosys won't use the SDC file, let's at least confirm
|
|
113
|
+
# that EDA used it and tracked it:
|
|
114
|
+
eda_config_yml_path = os.path.join(
|
|
115
|
+
os.getcwd(), 'eda.work', 'oclib_fifo_with_sdc.synth', 'eda_output_config.yml'
|
|
116
|
+
)
|
|
117
|
+
data = yaml_safe_load(eda_config_yml_path)
|
|
118
|
+
assert 'files_sdc' in data
|
|
119
|
+
assert data['files_sdc']
|
|
120
|
+
assert data['files_sdc'][0].endswith('oclib_fifo_yosys.sdc')
|
|
121
|
+
|
|
122
|
+
|
|
111
123
|
@pytest.mark.skipif('vivado' not in tools_loaded, reason="requires vivado")
|
|
112
124
|
@pytest.mark.skipif(not vivado_has_xpms(), reason="requires install to have XPMs")
|
|
113
125
|
class TestsVivado(Helpers):
|
opencos/tools/invio_helpers.py
CHANGED
|
@@ -61,6 +61,12 @@ def write_py_file(
|
|
|
61
61
|
'from invio import init, define_macro, add_include_directory, \\',
|
|
62
62
|
' add_verilog_file, add_sv_file, elaborate, elaborate_pct, analyze, \\',
|
|
63
63
|
' print_instance_hierarchy, write_design, report_analyzed_files',
|
|
64
|
+
]
|
|
65
|
+
if command_design_obj.parameters:
|
|
66
|
+
lines += [
|
|
67
|
+
'from invio import get_parameters, report_parameters, replace_expression_of_parameter'
|
|
68
|
+
]
|
|
69
|
+
lines += [
|
|
64
70
|
'import os, shutil',
|
|
65
71
|
'',
|
|
66
72
|
'for p in ["invio"]:',
|
|
@@ -138,18 +144,34 @@ def write_py_file(
|
|
|
138
144
|
tee_fpath = 'invio.log')]
|
|
139
145
|
})
|
|
140
146
|
|
|
147
|
+
lines += [
|
|
148
|
+
'assert analyze()',
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
if command_design_obj.parameters:
|
|
152
|
+
lines += [
|
|
153
|
+
'',
|
|
154
|
+
f'new_parameters = {command_design_obj.parameters}',
|
|
155
|
+
'for x in get_parameters():',
|
|
156
|
+
' name_parts = x.full_name.split("::")',
|
|
157
|
+
' mod, pname = name_parts[-2], name_parts[-1]',
|
|
158
|
+
f' if pname in new_parameters and mod == "{top}":',
|
|
159
|
+
' new_value = str(new_parameters[pname]) # invio needs str type for all',
|
|
160
|
+
' print(f"PARAMETER UPDATE: {mod}.{pname} ---> {new_value}")',
|
|
161
|
+
' replace_expression_of_parameter(x, new_value)',
|
|
162
|
+
'report_parameters()',
|
|
163
|
+
'',
|
|
164
|
+
]
|
|
165
|
+
|
|
141
166
|
if sim_lint:
|
|
142
167
|
# lint (skip elaborate steps -- from eda.CommandLintInvio)
|
|
143
168
|
lines += [
|
|
144
|
-
'assert analyze()',
|
|
145
|
-
'',
|
|
146
169
|
'report_analyzed_files()',
|
|
147
170
|
'print_instance_hierarchy()',
|
|
148
171
|
]
|
|
149
172
|
elif sim_elab:
|
|
150
173
|
# elab (non-synthesis), runs the following (from eda.CommandElabInvio)
|
|
151
174
|
lines += [
|
|
152
|
-
'assert analyze()',
|
|
153
175
|
f"assert elaborate('{top}', pct_elaboration=True, forceBlackbox={blackbox_list})",
|
|
154
176
|
'assert elaborate_pct()',
|
|
155
177
|
'',
|
|
@@ -159,7 +181,6 @@ def write_py_file(
|
|
|
159
181
|
else:
|
|
160
182
|
# synthesis-style elab (from eda.CommandElabInvioYosys)
|
|
161
183
|
lines += [
|
|
162
|
-
'assert analyze()',
|
|
163
184
|
f"assert elaborate('{top}', rtl_elaboration=True, forceBlackbox={blackbox_list})",
|
|
164
185
|
'',
|
|
165
186
|
'report_analyzed_files()',
|
opencos/tools/iverilog.py
CHANGED
|
@@ -136,6 +136,11 @@ class CommandSimIverilog(CommandSim, ToolIverilog):
|
|
|
136
136
|
# +define+{k}={v}, but also for SystemVerilog plusargs
|
|
137
137
|
command_list += [ '-D', f'{k}={sanitize_defines_for_sh(v)}' ]
|
|
138
138
|
|
|
139
|
+
# parameters
|
|
140
|
+
command_list.extend(
|
|
141
|
+
self.process_parameters_get_list(arg_prefix=f'-P{self.args["top"]}.')
|
|
142
|
+
)
|
|
143
|
+
|
|
139
144
|
if not self.files_sv and not self.files_v:
|
|
140
145
|
if not self.args['stop-before-compile']:
|
|
141
146
|
self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
|
opencos/tools/modelsim_ase.py
CHANGED
|
@@ -94,7 +94,8 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
94
94
|
return
|
|
95
95
|
if self.args['stop-after-compile']:
|
|
96
96
|
vsim_command_lists = self.get_compile_command_lists()
|
|
97
|
-
self.run_commands_check_logs(vsim_command_lists, log_filename='sim.log'
|
|
97
|
+
self.run_commands_check_logs(vsim_command_lists, log_filename='sim.log',
|
|
98
|
+
must_strings=['Errors: 0'], use_must_strings=False)
|
|
98
99
|
|
|
99
100
|
def elaborate(self):
|
|
100
101
|
if self.args['stop-before-compile']:
|
|
@@ -222,6 +223,10 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
222
223
|
typ='waveform', description='Modelsim/Questa Waveform WLF (Wave Log Format) file'
|
|
223
224
|
)
|
|
224
225
|
|
|
226
|
+
# parameters
|
|
227
|
+
if self.parameters:
|
|
228
|
+
voptargs_str += ' ' + ' '.join(self.process_parameters_get_list(arg_prefix='-G'))
|
|
229
|
+
|
|
225
230
|
# TODO(drew): support self.args['sim_libary', 'elab-args', sim-args'] (3 lists)
|
|
226
231
|
# to add to vsim_one_liner.
|
|
227
232
|
|
opencos/tools/quartus.py
CHANGED
|
@@ -19,6 +19,7 @@ from opencos.eda_base import Tool
|
|
|
19
19
|
from opencos.commands import (
|
|
20
20
|
CommandSynth, CommandBuild, CommandFList, CommandProj, CommandUpload, CommandOpen
|
|
21
21
|
)
|
|
22
|
+
from opencos.utils.str_helpers import sanitize_defines_for_sh, strip_outer_quotes
|
|
22
23
|
|
|
23
24
|
class ToolQuartus(Tool):
|
|
24
25
|
'''ToolQuartus used by opencos.eda for --tool=quartus'''
|
|
@@ -225,6 +226,18 @@ class CommandSynthQuartus(CommandSynth, ToolQuartus):
|
|
|
225
226
|
for incdir in self.incdirs:
|
|
226
227
|
tcl_lines.append(f"set_global_assignment -name SEARCH_PATH \"{incdir}\"")
|
|
227
228
|
|
|
229
|
+
# Parameters --> set_parameter -name <Parameter_Name> <Value>
|
|
230
|
+
for k,v in self.parameters.items():
|
|
231
|
+
if not isinstance(v, (int, str)):
|
|
232
|
+
util.warning(f'parameter {k} has value: {v}, parameters must be int/string types')
|
|
233
|
+
if isinstance(v, int):
|
|
234
|
+
tcl_lines.append(f"set_parameter -name {k} {v}")
|
|
235
|
+
else:
|
|
236
|
+
v = strip_outer_quotes(v.strip('\n'))
|
|
237
|
+
v = '"' + v + '"'
|
|
238
|
+
tcl_lines.append(f"set_parameter -name {k} {sanitize_defines_for_sh(v)}")
|
|
239
|
+
|
|
240
|
+
|
|
228
241
|
# Add all include directories as user libraries for better include resolution
|
|
229
242
|
for incdir in self.incdirs:
|
|
230
243
|
if os.path.exists(incdir):
|
|
@@ -307,7 +320,7 @@ class CommandBuildQuartus(CommandBuild, ToolQuartus):
|
|
|
307
320
|
'flow-tcl-files': [],
|
|
308
321
|
})
|
|
309
322
|
|
|
310
|
-
def do_it(self) -> None: # pylint: disable=too-many-branches,too-many-statements
|
|
323
|
+
def do_it(self) -> None: # pylint: disable=too-many-branches,too-many-statements,too-many-locals
|
|
311
324
|
# add defines for this job
|
|
312
325
|
self.set_tool_defines()
|
|
313
326
|
self.write_eda_config_and_args()
|
|
@@ -340,15 +353,25 @@ class CommandBuildQuartus(CommandBuild, ToolQuartus):
|
|
|
340
353
|
# create an eda.flist_input.f that we'll pass to flist:
|
|
341
354
|
with open(os.path.join(self.args['work-dir'], 'eda.flist_input.f'),
|
|
342
355
|
'w', encoding='utf-8') as f:
|
|
356
|
+
|
|
357
|
+
# defines
|
|
358
|
+
for key,value in self.defines.items():
|
|
359
|
+
if value is None:
|
|
360
|
+
f.write(f"+define+{key}\n")
|
|
361
|
+
else:
|
|
362
|
+
f.write(shlex.quote(f"+define+{key}={value}") + "\n")
|
|
363
|
+
|
|
364
|
+
# incdirs:
|
|
365
|
+
for incdir in self.incdirs:
|
|
366
|
+
f.write(f'+incdir+{incdir}\n')
|
|
367
|
+
|
|
368
|
+
# files:
|
|
343
369
|
f.write('\n'.join(self.files_v + self.files_sv + self.files_vhd + ['']))
|
|
370
|
+
|
|
371
|
+
|
|
344
372
|
command_list.append('--input-file=eda.flist_input.f')
|
|
345
373
|
|
|
346
374
|
|
|
347
|
-
for key,value in self.defines.items():
|
|
348
|
-
if value is None:
|
|
349
|
-
command_list += [ f"+define+{key}" ]
|
|
350
|
-
else:
|
|
351
|
-
command_list += [ shlex.quote(f"+define+{key}={value}") ]
|
|
352
375
|
|
|
353
376
|
# Write out a .sh command for debug
|
|
354
377
|
command_list = util.ShellCommandList(command_list, tee_fpath='run_eda_flist.log')
|
|
@@ -487,6 +510,9 @@ class CommandFListQuartus(CommandFList, ToolQuartus):
|
|
|
487
510
|
def __init__(self, config: dict):
|
|
488
511
|
CommandFList.__init__(self, config=config)
|
|
489
512
|
ToolQuartus.__init__(self, config=self.config)
|
|
513
|
+
self.args.update({
|
|
514
|
+
'emit-parameter': False
|
|
515
|
+
})
|
|
490
516
|
|
|
491
517
|
|
|
492
518
|
class CommandProjQuartus(CommandProj, ToolQuartus):
|
opencos/tools/riviera.py
CHANGED
|
@@ -74,6 +74,17 @@ class CommandSimRiviera(CommandSimModelsimAse, ToolRiviera):
|
|
|
74
74
|
# Note: many of these we follow the same flow as CommandSimModelsimAse:
|
|
75
75
|
# do_it, prepare_compile, compile, elaborate, simulate
|
|
76
76
|
|
|
77
|
+
def compile(self):
|
|
78
|
+
'''Override for CommandSimModelsimAse.compile() so we can set our own must_strings'''
|
|
79
|
+
if self.args['stop-before-compile']:
|
|
80
|
+
# don't run anything, save everyting we've already run in _prep_compile()
|
|
81
|
+
return
|
|
82
|
+
if self.args['stop-after-compile']:
|
|
83
|
+
vsim_command_lists = self.get_compile_command_lists()
|
|
84
|
+
self.run_commands_check_logs(vsim_command_lists, log_filename='sim.log',
|
|
85
|
+
must_strings=['Compile success 0 Errors'],
|
|
86
|
+
use_must_strings=False)
|
|
87
|
+
|
|
77
88
|
def get_compile_command_lists(self, **kwargs) -> list:
|
|
78
89
|
# This will also set up a compile.
|
|
79
90
|
vsim_command_list = [
|
|
@@ -128,7 +139,6 @@ class CommandSimRiviera(CommandSimModelsimAse, ToolRiviera):
|
|
|
128
139
|
if v is None:
|
|
129
140
|
vlog_dot_f_lines += [ f'+define+{k}' ]
|
|
130
141
|
else:
|
|
131
|
-
|
|
132
142
|
# if the value v is a double-quoted string, such as v='"hi"', the
|
|
133
143
|
# entire +define+NAME="hi" needs to wrapped in double quotes with the
|
|
134
144
|
# value v double-quotes escaped: "+define+NAME=\"hi\""
|
|
@@ -170,11 +180,15 @@ class CommandSimRiviera(CommandSimModelsimAse, ToolRiviera):
|
|
|
170
180
|
|
|
171
181
|
voptargs_str = ""
|
|
172
182
|
if self.args['gui'] or self.args['waves'] or self.args['coverage']:
|
|
173
|
-
voptargs_str
|
|
174
|
-
|
|
183
|
+
voptargs_str += self.tool_config.get('simulate-waves-args',
|
|
184
|
+
'+accb +accr +access +r+w')
|
|
175
185
|
if self.args['coverage']:
|
|
176
186
|
voptargs_str += self.tool_config.get('coverage-args', '')
|
|
177
187
|
|
|
188
|
+
# parameters
|
|
189
|
+
if self.parameters:
|
|
190
|
+
voptargs_str += ' ' + ' '.join(self.process_parameters_get_list(arg_prefix='-G'))
|
|
191
|
+
|
|
178
192
|
# TODO(drew): support self.args['sim_libary', 'elab-args', sim-args'] (3 lists)
|
|
179
193
|
# to add to vsim_one_liner.
|
|
180
194
|
|
opencos/tools/slang.py
CHANGED
|
@@ -143,6 +143,11 @@ class CommandElabSlang(CommandElab, ToolSlang):
|
|
|
143
143
|
# --define-macro {k}={v}
|
|
144
144
|
command_list.append( f'{k}={sanitize_defines_for_sh(v)}' )
|
|
145
145
|
|
|
146
|
+
# parameters
|
|
147
|
+
command_list.extend(
|
|
148
|
+
self.process_parameters_get_list(arg_prefix='-G ')
|
|
149
|
+
)
|
|
150
|
+
|
|
146
151
|
# Because many elab target-name won't match the --top needed for
|
|
147
152
|
# slang, we'll leave this to arg --slang-top:
|
|
148
153
|
if self.args.get('slang-top', None):
|
opencos/tools/slang_yosys.py
CHANGED
|
@@ -10,6 +10,8 @@ import os
|
|
|
10
10
|
from opencos import util
|
|
11
11
|
from opencos.tools.yosys import ToolYosys, CommonSynthYosys, CommandLecYosys
|
|
12
12
|
|
|
13
|
+
from opencos.commands.sim import parameters_dict_get_command_list
|
|
14
|
+
|
|
13
15
|
class ToolSlangYosys(ToolYosys):
|
|
14
16
|
'''Uses slang.so in yosys plugins directory, called via yosys > plugin -i slang'''
|
|
15
17
|
_TOOL = 'slang_yosys'
|
|
@@ -109,6 +111,13 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
|
|
|
109
111
|
]
|
|
110
112
|
|
|
111
113
|
read_slang_cmd += self.get_yosys_read_verilog_defines_incdirs_files()
|
|
114
|
+
|
|
115
|
+
# For slang step, need to resolve parameters too. We do NOT do this on
|
|
116
|
+
# subsquent yosys read_verilog steps.
|
|
117
|
+
read_slang_cmd += parameters_dict_get_command_list(
|
|
118
|
+
params=self.parameters, arg_prefix='-G '
|
|
119
|
+
)
|
|
120
|
+
|
|
112
121
|
read_slang_cmd.append(f'--top {self.args["top"]}')
|
|
113
122
|
return ' '.join(read_slang_cmd)
|
|
114
123
|
|
opencos/tools/surelog.py
CHANGED
|
@@ -109,6 +109,11 @@ class CommandElabSurelog(CommandElab, ToolSurelog):
|
|
|
109
109
|
for value in self.incdirs:
|
|
110
110
|
command_list.append('+incdir+' + value)
|
|
111
111
|
|
|
112
|
+
# parameters
|
|
113
|
+
command_list.extend(
|
|
114
|
+
self.process_parameters_get_list(arg_prefix='-P')
|
|
115
|
+
)
|
|
116
|
+
|
|
112
117
|
# defines:
|
|
113
118
|
for k,v in self.defines.items():
|
|
114
119
|
if v is None:
|
opencos/tools/verilator.py
CHANGED
|
@@ -244,6 +244,11 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
244
244
|
# +define+{k}={v}, but also for SystemVerilog plusargs
|
|
245
245
|
verilate_command_list += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
|
|
246
246
|
|
|
247
|
+
# parameters
|
|
248
|
+
verilate_command_list.extend(
|
|
249
|
+
self.process_parameters_get_list(arg_prefix='-G')
|
|
250
|
+
)
|
|
251
|
+
|
|
247
252
|
if not self.files_sv and not self.files_v:
|
|
248
253
|
if not self.args['stop-before-compile']:
|
|
249
254
|
self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
|
opencos/tools/vivado.py
CHANGED
|
@@ -22,6 +22,9 @@ from opencos.eda_base import Tool
|
|
|
22
22
|
from opencos.commands import CommandSim, CommandSynth, CommandProj, CommandBuild, \
|
|
23
23
|
CommandFList, CommandUpload, CommandOpen
|
|
24
24
|
|
|
25
|
+
from opencos.commands import sim
|
|
26
|
+
|
|
27
|
+
|
|
25
28
|
class ToolVivado(Tool):
|
|
26
29
|
'''ToolVivado used by opencos.eda for --tool=vivado'''
|
|
27
30
|
|
|
@@ -214,6 +217,12 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
214
217
|
command_list[0] += ".bat"
|
|
215
218
|
command_list += self.tool_config.get('elab-args',
|
|
216
219
|
'-s snapshot -timescale 1ns/1ps --stats').split()
|
|
220
|
+
|
|
221
|
+
# parameters
|
|
222
|
+
command_list.extend(
|
|
223
|
+
self.process_parameters_get_list(arg_prefix='-generic_top ')
|
|
224
|
+
)
|
|
225
|
+
|
|
217
226
|
if self.tool_config.get('elab-waves-args', ''):
|
|
218
227
|
command_list += self.tool_config.get('elab-waves-args', '').split()
|
|
219
228
|
elif self.args['gui'] and self.args['waves']:
|
|
@@ -412,6 +421,9 @@ class CommandSynthVivado(CommandSynth, ToolVivado):
|
|
|
412
421
|
defines = ""
|
|
413
422
|
for key, value in self.defines.items():
|
|
414
423
|
defines += (f"-verilog_define {key}" + (" " if value is None else f"={value} "))
|
|
424
|
+
parameters = ' '.join(
|
|
425
|
+
sim.parameters_dict_get_command_list(params=self.parameters, arg_prefix='-generic ')
|
|
426
|
+
)
|
|
415
427
|
incdirs = ' '.join([f'-include_dirs {x}' for x in self.incdirs])
|
|
416
428
|
flatten = ""
|
|
417
429
|
if self.args['flatten-all']:
|
|
@@ -457,10 +469,10 @@ class CommandSynthVivado(CommandSynth, ToolVivado):
|
|
|
457
469
|
tcl_lines += [
|
|
458
470
|
"# FIRST PASS -- auto_detect_xpm",
|
|
459
471
|
"synth_design -rtl -rtl_skip_ip -rtl_skip_constraints -no_timing_driven -no_iobuf " \
|
|
460
|
-
+ f"-top {top} {incdirs} {defines} {v}",
|
|
472
|
+
+ f"-top {top} {incdirs} {defines} {parameters} {v}",
|
|
461
473
|
f"auto_detect_xpm {v} ",
|
|
462
474
|
f"synth_design -no_iobuf -part {part} {flatten} -constrset constraints_1 " \
|
|
463
|
-
+ f"-top {top} {incdirs} {defines} {v}",
|
|
475
|
+
+ f"-top {top} {incdirs} {defines} {parameters} {v}",
|
|
464
476
|
f"write_verilog -force {top}.vg {v}",
|
|
465
477
|
f"report_utilization -file {top}.flat.util.rpt {v}",
|
|
466
478
|
f"report_utilization -file {top}.hier.util.rpt {v} -hierarchical " \
|
|
@@ -753,6 +765,7 @@ class CommandFListVivado(CommandFList, ToolVivado):
|
|
|
753
765
|
CommandFList.__init__(self, config=config)
|
|
754
766
|
ToolVivado.__init__(self, config=self.config)
|
|
755
767
|
self.args['all-sv'] = False
|
|
768
|
+
self.args['emit-parameter'] = False
|
|
756
769
|
|
|
757
770
|
|
|
758
771
|
class CommandUploadVivado(CommandUpload, ToolVivado):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencos-eda
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.56
|
|
4
4
|
Summary: A simple Python package for wrapping RTL simuliatons and synthesis
|
|
5
5
|
Author-email: Simon Sabato <simon@cognichip.ai>, Drew Ranck <drew@cognichip.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/cognichip/opencos
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
opencos/__init__.py,sha256=RwJA9oc1uUlvNX7v5zoqwjnSRNq2NZwRlHqtS-ICJkI,122
|
|
2
2
|
opencos/_version.py,sha256=XiHFZjCofkkZvI9befTFKsRt5zLouUo1CIwhW4srWU0,582
|
|
3
3
|
opencos/_waves_pkg.sv,sha256=1lbhQOVGc3t_R8czYjP40hssP0I3FlZOpHTkI7yKFbI,1251
|
|
4
|
-
opencos/deps_schema.py,sha256=
|
|
4
|
+
opencos/deps_schema.py,sha256=02pSLBEvWK147lUwE8DRojYgE6HReZBBKP_pzVRow1c,16533
|
|
5
5
|
opencos/eda.py,sha256=otdIufWO8C4YoEmwcaQGMwH06xe-IjyyExYWhw3Xz-8,22765
|
|
6
|
-
opencos/eda_base.py,sha256=
|
|
7
|
-
opencos/eda_config.py,sha256=
|
|
6
|
+
opencos/eda_base.py,sha256=mCkSCGO__Jfjf27-TSOo7IRppL66-aY3kJVK3RBFjXw,105899
|
|
7
|
+
opencos/eda_config.py,sha256=PEVb6yGyEAJpWBsgbcOnEhRWk4G8iryAdvkUfMiosWE,11467
|
|
8
8
|
opencos/eda_config_defaults.yml,sha256=_YwY2OufgfV8GXhQd6Gs7sE-I1z2GkGsCowxipNJZaw,15938
|
|
9
9
|
opencos/eda_config_max_verilator_waivers.yml,sha256=lTAU4IOEbUWVlPzuer1YYhIyxpPINeA4EJqcRIT-Ymk,840
|
|
10
10
|
opencos/eda_config_reduced.yml,sha256=cQ9jY4J7EvAbeHTiP6bvpDSVJAYiitjLZPSxxLKIEbk,1440
|
|
@@ -12,10 +12,10 @@ opencos/eda_deps_bash_completion.bash,sha256=jMkQKY82HBgOnQeMdA1hMrXguRFtB52SMBx
|
|
|
12
12
|
opencos/eda_deps_sanitize.py,sha256=SQjvrte9Hv9JesRY0wljvbdC6pAmLCikI-Wdzzy-D04,1939
|
|
13
13
|
opencos/eda_extract_targets.py,sha256=POlxZfqf2dNH2nc1CEw5B_53vSHAicSTkpU9_-2_6Zw,2851
|
|
14
14
|
opencos/eda_tool_helper.py,sha256=_YgobDLEWW6Fzdr976LxaCDZ4DKRyuMs5CrYQHaTPrU,2558
|
|
15
|
-
opencos/export_helper.py,sha256=
|
|
15
|
+
opencos/export_helper.py,sha256=bUXRnCRXPRV9DlBhiw45YUfNe-Psb2JAEssRUKp6iNI,22497
|
|
16
16
|
opencos/export_json_convert.py,sha256=tSIMbLFtc_Fo66EhFovMii1v_qJYyFZJrPNnoPdW7L0,4182
|
|
17
17
|
opencos/files.py,sha256=aoq0O2KfISzZb-Vi_q_0TTGBER9xJc--FkVZf0ga7pA,1549
|
|
18
|
-
opencos/names.py,sha256=
|
|
18
|
+
opencos/names.py,sha256=Y2aJ5wgpbNIJ-_P5xUXnHMv_h-zMOX2Rt6iLuduqC1Q,1213
|
|
19
19
|
opencos/peakrdl_cleanup.py,sha256=vHNGtalTrIVP335PhRjPt9RhoccgpK1HJAi-E4M8Kc8,736
|
|
20
20
|
opencos/seed.py,sha256=IL9Yg-r9SLSRseMVWaEHmuw2_DNi_eyut11EafoNTsU,942
|
|
21
21
|
opencos/util.py,sha256=9VGc54Rm-snEwbKEbToQRGoeGg8wqBeWpTJBagEbjw0,37770
|
|
@@ -24,26 +24,26 @@ opencos/commands/build.py,sha256=hvjrvg7AbEotuQze6-yz3DOYRMtagkvJ-6TFNJQTwrs,144
|
|
|
24
24
|
opencos/commands/deps_help.py,sha256=WDrU7H9sypzDAxe_CHqhW5B_scbQMzBEdf-v-Jcfd5Q,10682
|
|
25
25
|
opencos/commands/elab.py,sha256=m6Gk03wSzX8UkcmReooK7turF7LpqO0IcdOZwJ8XiyI,1596
|
|
26
26
|
opencos/commands/export.py,sha256=dpTcrtPjIt6TOw-i8LUWhb4ismFAE1QK-dNAHC1jxME,3510
|
|
27
|
-
opencos/commands/flist.py,sha256=
|
|
27
|
+
opencos/commands/flist.py,sha256=uFjNxrXvigQKzG2v8sooz_3iVaTHBKkm-NDYXo9ktAE,9068
|
|
28
28
|
opencos/commands/lec.py,sha256=bshOs_GkuB1nCGd_SntT43_XpSYQYJqNCjVZp6Q1Chc,3879
|
|
29
29
|
opencos/commands/lint.py,sha256=piPb0l0zE3sAtNJkFQ-oNpuHxnaV_RNXkXtEj_9mwGs,1594
|
|
30
30
|
opencos/commands/multi.py,sha256=dCo4rMIkGT3BtlBhUIAd7r31w8qxeJvybpl4H7DR77o,27225
|
|
31
31
|
opencos/commands/open.py,sha256=XckvKUNwvc5KHbYGV-eQ2i0WG4X-yckroDaMC610MB4,804
|
|
32
32
|
opencos/commands/proj.py,sha256=vCsZle3oUJ8xmIFuepgAD6G-YGl35xtTIcTeiVDshNo,1112
|
|
33
33
|
opencos/commands/shell.py,sha256=dFXXtvsDs3Khme41du8LhKdV3qRosxjTfju6SJbOSKM,7599
|
|
34
|
-
opencos/commands/sim.py,sha256=
|
|
34
|
+
opencos/commands/sim.py,sha256=HIyKT3avB844Z5RWidvck1ZhVa5MfS7PTjCactZO3o4,19226
|
|
35
35
|
opencos/commands/sweep.py,sha256=ni4XFgnFF8HLXtwPhETyLWfvc2kgtm4bcxFcKzUhkf0,9343
|
|
36
36
|
opencos/commands/synth.py,sha256=tuxWmxMNmE9hveWXGNfKDelzxi_wK7ZL7V2LiZV6Ypg,4371
|
|
37
37
|
opencos/commands/targets.py,sha256=_jRNhm2Fqj0fmMvTw6Ba39DCsRHf_r_uZCy_R064kpA,1472
|
|
38
38
|
opencos/commands/upload.py,sha256=oyImgcEFGxDkdeY9EYyX2R6fTOmN-lTs-HYxAZqXUUo,871
|
|
39
39
|
opencos/commands/waves.py,sha256=nrp3ALwfJujZns44tgCgia_dEedQyKe0T3fuws8h39U,7697
|
|
40
40
|
opencos/deps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
-
opencos/deps/defaults.py,sha256=
|
|
41
|
+
opencos/deps/defaults.py,sha256=7ETOnG08HERKcJUjynnrKZV1sQQVUsW-zKlwoCN1VkI,1298
|
|
42
42
|
opencos/deps/deps_commands.py,sha256=OlqueYFK8U83loasok3xJGzUDpNcj2DPk37332DfmRo,17039
|
|
43
43
|
opencos/deps/deps_file.py,sha256=nVZWrq6PVhWig1yMNpy8w_7LQJ1rgb7Js0N1ngoqLio,16306
|
|
44
|
-
opencos/deps/deps_processor.py,sha256=
|
|
44
|
+
opencos/deps/deps_processor.py,sha256=i8R6lNSVc_ybTnC16qmGevB3Y-pkcbxkZaT04HTLE8Y,37890
|
|
45
45
|
opencos/hw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
|
-
opencos/hw/oc_cli.py,sha256=
|
|
46
|
+
opencos/hw/oc_cli.py,sha256=U1JGlshLZhtd0LgndZFBZVltAj_HemdhbjO_Zo8ZuVM,132252
|
|
47
47
|
opencos/hw/pcie.py,sha256=VUJljaZJYgScAAx5yn7F6GoA8K9eTcw24otYZbkMpYs,3035
|
|
48
48
|
opencos/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
49
|
opencos/tests/custom_config.yml,sha256=TRoVM9ZFKPOA_8JmlpzaMhnGO1txmaD14N_8P1oqzew,257
|
|
@@ -53,7 +53,7 @@ opencos/tests/test_deps_helpers.py,sha256=f9GJXvzcdE3SGkKJ7q-YBTgRagZcIzeRa6nMVC
|
|
|
53
53
|
opencos/tests/test_deps_schema.py,sha256=T3P9KjaMyKsk8b7snNVvNSsom2hIJcg6Z9apYiXoH9Y,941
|
|
54
54
|
opencos/tests/test_eda.py,sha256=cdxfLCUZq0nNelCQiplZXkeF4eyzmyJlZJFDSo77qeI,39464
|
|
55
55
|
opencos/tests/test_eda_elab.py,sha256=AjU4WMYtFoHpNe1Z4yWWpxDKy4V_hAjL5rl3jqphZrk,3179
|
|
56
|
-
opencos/tests/test_eda_synth.py,sha256=
|
|
56
|
+
opencos/tests/test_eda_synth.py,sha256=BtBrNVJ9C-LJt3K0wNNS5ukEVrET16AbRXl2IzxudJ8,5744
|
|
57
57
|
opencos/tests/test_oc_cli.py,sha256=w-F-LjSSWVql3D2WG8tcV4_C52i-hL_2WT3oDpKQn9s,734
|
|
58
58
|
opencos/tests/test_tools.py,sha256=-WMpDZexAgko0FAcfiuASqSKNNL0Mr1ztag05808Upc,13735
|
|
59
59
|
opencos/tests/deps_files/command_order/DEPS.yml,sha256=vloOzWZ5qU3yGNFaDlrAJdEzYxK6qf8gfac3zqF-0FI,438
|
|
@@ -66,20 +66,20 @@ opencos/tests/deps_files/test_err_fatal/DEPS.yml,sha256=GnXIUJvshQWR9PlYxX67T53e
|
|
|
66
66
|
opencos/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
opencos/tools/cocotb.py,sha256=vcp9wLlmgr6dLBnxEuJJyMjJIorIo96J0Z63tJwP-eE,16759
|
|
68
68
|
opencos/tools/invio.py,sha256=S2ChWr8xMZHSOOhX2hGKQhMmtQY2potVQjc-lsMg73o,3299
|
|
69
|
-
opencos/tools/invio_helpers.py,sha256=
|
|
69
|
+
opencos/tools/invio_helpers.py,sha256=86WOGmSf4m_lEqBtK3DLjWqI0jnqAWzBEBRYfBUGiSY,8804
|
|
70
70
|
opencos/tools/invio_yosys.py,sha256=CszGeTdE1ilnMmWPLW77BrtobbsGb1CKXqot0hGimFU,5996
|
|
71
|
-
opencos/tools/iverilog.py,sha256=
|
|
72
|
-
opencos/tools/modelsim_ase.py,sha256=
|
|
73
|
-
opencos/tools/quartus.py,sha256=
|
|
71
|
+
opencos/tools/iverilog.py,sha256=8dK4z8ktbNYS9cW5QQPm586WoE-pSmOAVJfXajw-Sbg,6420
|
|
72
|
+
opencos/tools/modelsim_ase.py,sha256=reeJhWlHxYyheoziMOXj0gzQRjmUmBexawRuq_bda_A,15486
|
|
73
|
+
opencos/tools/quartus.py,sha256=_TfmPSYpbhmDLw7Dur-rRP0iGwv9hhQ6E5G-XLiYPEM,30486
|
|
74
74
|
opencos/tools/questa.py,sha256=nHImM0Wydcf4YHGibHmQAwmqKHmMxKZUqY-E-vz1o8M,9827
|
|
75
75
|
opencos/tools/questa_fse.py,sha256=hytkeuGg4qImj7rStV1i2kxkz9B0KFheGtcadxmpYAo,2550
|
|
76
|
-
opencos/tools/riviera.py,sha256=
|
|
77
|
-
opencos/tools/slang.py,sha256=
|
|
78
|
-
opencos/tools/slang_yosys.py,sha256=
|
|
79
|
-
opencos/tools/surelog.py,sha256=
|
|
76
|
+
opencos/tools/riviera.py,sha256=qhDiXnXeglqcZTN244fVcuC5r-Q9wMo0jAtJF5_Ndro,11820
|
|
77
|
+
opencos/tools/slang.py,sha256=UpsFeExup2awARxxxADD9f923Hw6ubiSEq2tKtJbS1c,8305
|
|
78
|
+
opencos/tools/slang_yosys.py,sha256=L5vm2TzkmaREaBAy1vNT61FbwiAXt0c_aLPWOT18sHY,10121
|
|
79
|
+
opencos/tools/surelog.py,sha256=S2RAZJyjdISm_tRvAhXbla7_z_tJfotZih5f9Y3m7DQ,5648
|
|
80
80
|
opencos/tools/tabbycad_yosys.py,sha256=2LePPgYXBVdsy7YcffPIWN-I0B7queLQ_f_pme2SCGw,7803
|
|
81
|
-
opencos/tools/verilator.py,sha256=
|
|
82
|
-
opencos/tools/vivado.py,sha256=
|
|
81
|
+
opencos/tools/verilator.py,sha256=ZrmcJ-lt3wXdHRfLMangU0CepGf-GFsp5w0NmdF8Be8,21361
|
|
82
|
+
opencos/tools/vivado.py,sha256=GQdPd1mp02it_uyhMqpFfJgh0AKIMn-20BhHNEDp5HY,41398
|
|
83
83
|
opencos/tools/yosys.py,sha256=7o7uUbqjwuYUC7joGk2GCE1YsmnQN_W-yCZP49yl0X4,26926
|
|
84
84
|
opencos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
85
85
|
opencos/utils/markup_helpers.py,sha256=A8Ev5UJ4EVKjdcF2g85SQbjdPZR4jGpNqCLaBy_4v7Q,4569
|
|
@@ -88,10 +88,10 @@ opencos/utils/str_helpers.py,sha256=726ScK5-v7QkBi-zqESKZLsOl2_ya4vVJ5ZhxJqmBFo,
|
|
|
88
88
|
opencos/utils/subprocess_helpers.py,sha256=xemAGPey6M0sWY_FElvr-Z0phCfdjaC-znP8FKihPaE,3535
|
|
89
89
|
opencos/utils/vscode_helper.py,sha256=2YPjcDH_vTlwJvcITyMfvx8dLzPSRKzAvFRJz7BaJk8,1332
|
|
90
90
|
opencos/utils/vsim_helper.py,sha256=2voGRZI2iAQ2Pv2ZI5g2why6xpgig-To8im-LVXtuDU,1517
|
|
91
|
-
opencos_eda-0.2.
|
|
92
|
-
opencos_eda-0.2.
|
|
93
|
-
opencos_eda-0.2.
|
|
94
|
-
opencos_eda-0.2.
|
|
95
|
-
opencos_eda-0.2.
|
|
96
|
-
opencos_eda-0.2.
|
|
97
|
-
opencos_eda-0.2.
|
|
91
|
+
opencos_eda-0.2.56.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
|
92
|
+
opencos_eda-0.2.56.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
|
|
93
|
+
opencos_eda-0.2.56.dist-info/METADATA,sha256=D2wAzdJIPCFvz0x18DXza-oWoI1AWir2-J4JpZ7rR88,631
|
|
94
|
+
opencos_eda-0.2.56.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
95
|
+
opencos_eda-0.2.56.dist-info/entry_points.txt,sha256=6n1T5NwVYDhN5l1h5zmyT197G4pE0SySDreB0QJzJR0,218
|
|
96
|
+
opencos_eda-0.2.56.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
|
|
97
|
+
opencos_eda-0.2.56.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|