opencos-eda 0.2.55__tar.gz → 0.2.56__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. {opencos_eda-0.2.55/opencos_eda.egg-info → opencos_eda-0.2.56}/PKG-INFO +1 -1
  2. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/flist.py +10 -0
  3. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/sim.py +31 -0
  4. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/deps/defaults.py +2 -0
  5. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/deps/deps_processor.py +39 -1
  6. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/deps_schema.py +22 -0
  7. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_base.py +108 -10
  8. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_config.py +2 -1
  9. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/export_helper.py +15 -5
  10. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/hw/oc_cli.py +1 -1
  11. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/names.py +4 -1
  12. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_eda_synth.py +12 -0
  13. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/invio_helpers.py +25 -4
  14. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/iverilog.py +5 -0
  15. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/modelsim_ase.py +6 -1
  16. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/quartus.py +32 -6
  17. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/riviera.py +17 -3
  18. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/slang.py +5 -0
  19. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/slang_yosys.py +9 -0
  20. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/surelog.py +5 -0
  21. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/verilator.py +5 -0
  22. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/vivado.py +15 -2
  23. {opencos_eda-0.2.55 → opencos_eda-0.2.56/opencos_eda.egg-info}/PKG-INFO +1 -1
  24. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/pyproject.toml +1 -1
  25. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/LICENSE +0 -0
  26. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/LICENSE.spdx +0 -0
  27. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/README.md +0 -0
  28. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/__init__.py +0 -0
  29. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/_version.py +0 -0
  30. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/_waves_pkg.sv +0 -0
  31. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/__init__.py +0 -0
  32. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/build.py +0 -0
  33. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/deps_help.py +0 -0
  34. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/elab.py +0 -0
  35. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/export.py +0 -0
  36. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/lec.py +0 -0
  37. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/lint.py +0 -0
  38. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/multi.py +0 -0
  39. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/open.py +0 -0
  40. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/proj.py +0 -0
  41. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/shell.py +0 -0
  42. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/sweep.py +0 -0
  43. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/synth.py +0 -0
  44. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/targets.py +0 -0
  45. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/upload.py +0 -0
  46. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/commands/waves.py +0 -0
  47. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/deps/__init__.py +0 -0
  48. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/deps/deps_commands.py +0 -0
  49. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/deps/deps_file.py +0 -0
  50. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda.py +0 -0
  51. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_config_defaults.yml +0 -0
  52. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_config_max_verilator_waivers.yml +0 -0
  53. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_config_reduced.yml +0 -0
  54. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_deps_bash_completion.bash +0 -0
  55. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_deps_sanitize.py +0 -0
  56. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_extract_targets.py +0 -0
  57. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/eda_tool_helper.py +0 -0
  58. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/export_json_convert.py +0 -0
  59. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/files.py +0 -0
  60. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/hw/__init__.py +0 -0
  61. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/hw/pcie.py +0 -0
  62. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/peakrdl_cleanup.py +0 -0
  63. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/seed.py +0 -0
  64. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/__init__.py +0 -0
  65. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/custom_config.yml +0 -0
  66. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
  67. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
  68. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
  69. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
  70. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
  71. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
  72. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
  73. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/helpers.py +0 -0
  74. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_build.py +0 -0
  75. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_deps_helpers.py +0 -0
  76. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_deps_schema.py +0 -0
  77. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_eda.py +0 -0
  78. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_eda_elab.py +0 -0
  79. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_oc_cli.py +0 -0
  80. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tests/test_tools.py +0 -0
  81. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/__init__.py +0 -0
  82. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/cocotb.py +0 -0
  83. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/invio.py +0 -0
  84. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/invio_yosys.py +0 -0
  85. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/questa.py +0 -0
  86. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/questa_fse.py +0 -0
  87. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/tabbycad_yosys.py +0 -0
  88. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/tools/yosys.py +0 -0
  89. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/util.py +0 -0
  90. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/utils/__init__.py +0 -0
  91. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/utils/markup_helpers.py +0 -0
  92. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/utils/status_constants.py +0 -0
  93. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/utils/str_helpers.py +0 -0
  94. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/utils/subprocess_helpers.py +0 -0
  95. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/utils/vscode_helper.py +0 -0
  96. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos/utils/vsim_helper.py +0 -0
  97. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos_eda.egg-info/SOURCES.txt +0 -0
  98. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos_eda.egg-info/dependency_links.txt +0 -0
  99. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos_eda.egg-info/entry_points.txt +0 -0
  100. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos_eda.egg-info/requires.txt +0 -0
  101. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/opencos_eda.egg-info/top_level.txt +0 -0
  102. {opencos_eda-0.2.55 → opencos_eda-0.2.56}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.2.55
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
@@ -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:
@@ -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)
@@ -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',
@@ -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 any(dep.startswith(x) for x in ['+define+', '+incdir']):
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:
@@ -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],
@@ -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
- ) -> None:
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 None
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 None
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 None
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 None
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 None
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 None
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 None
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+ or +incdir+, consume it and remove from unparsed
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)
@@ -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
 
@@ -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
- for filename in self.cmd_design_obj.files_non_source:
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.files_sv + self.cmd_design_obj.files_v:
421
- filename = os.path.split(fullpath)[1]
422
- deps_files.append(filename)
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 = {
@@ -2508,7 +2508,7 @@ name_tables = { 'OC_VENDOR' : {},
2508
2508
  }
2509
2509
 
2510
2510
  def parse_names():
2511
- name_tables.update(opencos_names.table) #update our global name_table from names.py
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:
@@ -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
- table = {
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': {
@@ -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):
@@ -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()',
@@ -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,',
@@ -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
 
@@ -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):
@@ -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 = self.tool_config.get('simulate-waves-args',
174
- '+accb +accr +access +r+w')
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
 
@@ -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):
@@ -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
 
@@ -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:
@@ -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,',
@@ -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.55
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  [project]
4
4
  name = "opencos-eda"
5
- version = "0.2.55"
5
+ version = "0.2.56"
6
6
  dependencies = [
7
7
  # opencos/eda.py dependencies
8
8
  "mergedeep >= 1.3.4",
File without changes
File without changes
File without changes
File without changes