opencos-eda 0.2.50__py3-none-any.whl → 0.2.52__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.
@@ -0,0 +1,483 @@
1
+ ''' opencos.tools.cocotb - Used by opencos.eda for sim commands with --tool=cocotb.
2
+
3
+ Contains classes for ToolCocotb, CommandSimCocotb.
4
+ '''
5
+
6
+ import os
7
+ import shutil
8
+ import subprocess
9
+
10
+ from opencos import util
11
+ from opencos.eda_base import Tool
12
+ from opencos.commands import CommandSim
13
+ from opencos.utils.str_helpers import sanitize_defines_for_sh
14
+
15
+
16
+ class ToolCocotb(Tool):
17
+ '''ToolCocotb used by opencos.eda for --tool=cocotb'''
18
+
19
+ _TOOL = 'cocotb'
20
+ _EXE = 'python'
21
+ _URL = 'https://github.com/cocotb/cocotb'
22
+
23
+ cocotb_version = ''
24
+ python_exe = ''
25
+
26
+ def get_versions(self) -> str:
27
+ if self._VERSION:
28
+ return self._VERSION
29
+
30
+ # Check if python is available
31
+ python_path = shutil.which('python') or shutil.which('python3')
32
+ if not python_path:
33
+ self.error('"python" or "python3" not in path, required for cocotb')
34
+ else:
35
+ self.python_exe = python_path
36
+
37
+ # Check if cocotb is installed
38
+ try:
39
+ version_ret = subprocess.run(
40
+ [self.python_exe, '-c', 'import cocotb; print(cocotb.__version__)'],
41
+ capture_output=True,
42
+ check=True,
43
+ text=True
44
+ )
45
+ version = version_ret.stdout.strip()
46
+ self.cocotb_version = version
47
+ self._VERSION = version
48
+ util.debug(f'Found cocotb version: {version}')
49
+ return self._VERSION
50
+ except subprocess.CalledProcessError:
51
+ self.error('cocotb package not installed in python environment. '
52
+ 'Install with: pip install cocotb')
53
+ except Exception as e:
54
+ self.error(f'Failed to check cocotb version: {e}')
55
+
56
+ return ''
57
+
58
+ def set_tool_defines(self):
59
+ super().set_tool_defines()
60
+ self.defines.update({
61
+ 'SIMULATION': 1,
62
+ 'COCOTB': 1,
63
+ 'OC_TOOL_COCOTB': None,
64
+ })
65
+
66
+
67
+ class CommandSimCocotb(CommandSim, ToolCocotb):
68
+ '''CommandSimCocotb is a command handler for: eda sim --tool=cocotb'''
69
+
70
+ def __init__(self, config: dict):
71
+ CommandSim.__init__(self, config)
72
+ ToolCocotb.__init__(self, config=self.config)
73
+
74
+ self.args.update({
75
+ 'gui': False,
76
+ 'tcl-file': None,
77
+ 'cocotb-test-module': None,
78
+ 'cocotb-test-runner': 'python',
79
+ 'cocotb-simulator': 'verilator',
80
+ 'cocotb-makefile': False,
81
+ 'cocotb-python-runner': True,
82
+ 'cocotb-standalone-makefile': False,
83
+ })
84
+
85
+ self.args_help.update({
86
+ 'waves': 'Include waveforms by setting COCOTB_ENABLE_WAVES=1',
87
+ 'cocotb-test-module': 'Python test module name (e.g., test_my_design)',
88
+ 'cocotb-test-runner': 'Test runner to use: python (default) or pytest',
89
+ 'cocotb-simulator': ('Simulator backend: verilator (default), icarus, etc.'
90
+ ' Note that iverilog will convert to icarus here'),
91
+ 'cocotb-makefile': 'Use traditional Makefile system instead of Python runner',
92
+ 'cocotb-python-runner': 'Use Python-based runner system (default, cocotb 1.8+)',
93
+ 'cocotb-standalone-makefile': ('Use provided Makefile as-is, '
94
+ 'run make in source directory'),
95
+ })
96
+
97
+ self.cocotb_command_lists = []
98
+ self.cocotb_test_files = []
99
+
100
+ def set_tool_defines(self):
101
+ ToolCocotb.set_tool_defines(self)
102
+
103
+ def prepare_compile(self):
104
+ self.set_tool_defines()
105
+
106
+ # Fix iverilog -> icarus
107
+ if self.args['cocotb-simulator'] == 'iverilog':
108
+ self.args['cocotb-simulator'] = 'icarus'
109
+
110
+ # Find cocotb test files
111
+ self._find_cocotb_test_files()
112
+
113
+ if self.args['cocotb-standalone-makefile']:
114
+ self._prepare_standalone_makefile_system()
115
+ elif self.args['cocotb-makefile']:
116
+ self._prepare_makefile_system()
117
+ else:
118
+ self._prepare_python_runner_system()
119
+
120
+ # Create directories
121
+ paths = ['logs', 'sim_build']
122
+ util.safe_mkdirs(base=self.args['work-dir'], new_dirs=paths)
123
+
124
+ # Write shell scripts
125
+ util.write_shell_command_file(
126
+ dirpath=self.args['work-dir'],
127
+ filename='cocotb_test.sh',
128
+ command_lists=self.cocotb_command_lists,
129
+ line_breaks=True
130
+ )
131
+
132
+ util.write_shell_command_file(
133
+ dirpath=self.args['work-dir'],
134
+ filename='all.sh',
135
+ command_lists=[
136
+ ['./pre_compile_dep_shell_commands.sh'],
137
+ ['./cocotb_test.sh'],
138
+ ]
139
+ )
140
+
141
+ def _find_cocotb_test_files(self):
142
+ '''Find Python test files that contain cocotb tests'''
143
+ self.cocotb_test_files = []
144
+
145
+ # Look for test files in the current directory and deps
146
+ for file_path in self.files_non_source:
147
+ if (file_path.endswith('.py') and
148
+ ('test' in file_path.lower() or 'tb' in file_path.lower())):
149
+ # Check if it's a cocotb test file
150
+ try:
151
+ with open(file_path, 'r', encoding='utf-8') as f:
152
+ content = f.read()
153
+ if 'import cocotb' in content or 'from cocotb' in content:
154
+ self.cocotb_test_files.append(file_path)
155
+ util.debug(f'Found cocotb test file: {file_path}')
156
+ except Exception as e:
157
+ util.debug(f'Could not read {file_path}: {e}')
158
+
159
+ # If no test files found, look for explicit test module
160
+ if not self.cocotb_test_files and self.args.get('cocotb-test-module'):
161
+ test_module = self.args['cocotb-test-module']
162
+ if not test_module.endswith('.py'):
163
+ test_module += '.py'
164
+
165
+ # Look in work directory and target directory
166
+ for search_dir in [self.args['work-dir'], os.path.dirname(self.target or '.')]:
167
+ test_path = os.path.join(search_dir, test_module)
168
+ if os.path.exists(test_path):
169
+ self.cocotb_test_files.append(test_path)
170
+ break
171
+
172
+ if not self.cocotb_test_files:
173
+ self.error('No cocotb test files found. Either include .py files with '
174
+ 'cocotb imports in your deps, or specify --cocotb-test-module')
175
+
176
+ def _prepare_python_runner_system(self):
177
+ '''Prepare cocotb using the Python-based runner system (cocotb 1.8+)'''
178
+
179
+ # Create a Python runner script
180
+ runner_script = self._create_python_runner_script()
181
+
182
+ if self.args['cocotb-test-runner'] == 'pytest':
183
+ # Use pytest to run the tests
184
+ runner_script_name = os.path.basename(runner_script)
185
+ cmd_list = [
186
+ self.python_exe, '-m', 'pytest',
187
+ runner_script_name,
188
+ '-v', '-s'
189
+ ]
190
+ else:
191
+ # Run the Python script directly
192
+ runner_script_name = os.path.basename(runner_script)
193
+ cmd_list = [self.python_exe, runner_script_name]
194
+
195
+ # Set environment variables
196
+ env_vars = self._get_cocotb_env_vars()
197
+
198
+ # Create command with environment variables
199
+ command_list = self._create_env_command(env_vars) + cmd_list
200
+ self.cocotb_command_lists = [util.ShellCommandList(command_list,
201
+ tee_fpath='cocotb_test.log')]
202
+
203
+ def _prepare_makefile_system(self):
204
+ '''Prepare cocotb using the traditional Makefile system'''
205
+
206
+ makefile_path = os.path.join(self.args['work-dir'], 'Makefile')
207
+ with open(makefile_path, 'w', encoding='utf-8') as f:
208
+ f.write(self._create_makefile_content())
209
+
210
+ cmd_list = self._create_shell_command_with_success('make -f Makefile')
211
+ self.cocotb_command_lists = [util.ShellCommandList(cmd_list,
212
+ tee_fpath='cocotb_makefile.log')]
213
+
214
+ def _prepare_standalone_makefile_system(self):
215
+ '''Use provided Makefile as-is, run make in source directory'''
216
+
217
+ # Find the Makefile in our dependencies
218
+ makefile_path = None
219
+ for file_path in self.files_non_source:
220
+ if os.path.basename(file_path).lower() == 'makefile':
221
+ makefile_path = file_path
222
+ break
223
+
224
+ if not makefile_path:
225
+ self.error('No Makefile found in deps for --cocotb-standalone-makefile')
226
+
227
+ makefile_dir = os.path.dirname(os.path.abspath(makefile_path))
228
+ cmd_list = self._create_shell_command_with_success(f'cd {makefile_dir} && make')
229
+ self.cocotb_command_lists = [util.ShellCommandList(
230
+ cmd_list, tee_fpath='cocotb_standalone.log')]
231
+
232
+ def _get_test_module_name(self) -> str:
233
+ '''Get the test module name from args or detected files'''
234
+ if self.args.get('cocotb-test-module'):
235
+ return self.args['cocotb-test-module']
236
+ if self.cocotb_test_files:
237
+ # Use the first test file found, strip .py extension
238
+ test_file = os.path.basename(self.cocotb_test_files[0])
239
+ return test_file.replace('.py', '')
240
+ return 'test_design'
241
+
242
+
243
+ def _get_hdl_sources(self) -> dict:
244
+ '''Get HDL source files organized by type'''
245
+ return {
246
+ 'verilog': (self.files_sv or []) + (self.files_v or []),
247
+ 'vhdl': self.files_vhd or [],
248
+ 'all': (self.files_sv or []) + (self.files_v or []) + (self.files_vhd or [])
249
+ }
250
+
251
+ def _create_python_runner_script(self) -> str:
252
+ '''Create the Python runner script and return its path'''
253
+ test_module = self._get_test_module_name()
254
+ hdl_sources = self._get_hdl_sources()['all']
255
+
256
+ script_content = self._generate_runner_script_content(test_module, hdl_sources)
257
+ script_path = os.path.join(self.args['work-dir'], 'cocotb_runner.py')
258
+
259
+ with open(script_path, 'w', encoding='utf-8') as f:
260
+ f.write(script_content)
261
+
262
+ os.chmod(script_path, 0o755)
263
+
264
+ return script_path
265
+
266
+ def _generate_runner_script_content(self, test_module: str, hdl_sources: list) -> str:
267
+ '''Generate the content for the Python runner script'''
268
+ return f'''#!/usr/bin/env python3
269
+ """
270
+ Cocotb test runner script generated by opencos
271
+ """
272
+
273
+ import os
274
+ import sys
275
+ from pathlib import Path
276
+
277
+ # Add current directory to Python path for test imports
278
+ sys.path.insert(0, os.getcwd())
279
+
280
+ try:
281
+ from cocotb_tools.runner import get_runner
282
+ except ImportError:
283
+ print("ERROR: cocotb not found. Install with: pip install cocotb")
284
+ sys.exit(1)
285
+
286
+ def run_cocotb_test():
287
+ """Run cocotb test using the Python runner system"""
288
+
289
+ # Configuration
290
+ simulator = "{self.args['cocotb-simulator']}"
291
+ hdl_toplevel = "{self.args.get('top', 'top')}"
292
+ test_module = "{test_module}"
293
+
294
+ # HDL source files
295
+ hdl_sources = {hdl_sources!r}
296
+
297
+ # Convert to Path objects and make absolute
298
+ sources = []
299
+ for src in hdl_sources:
300
+ src_path = Path(src)
301
+ if not src_path.is_absolute():
302
+ src_path = Path.cwd() / src_path
303
+ sources.append(src_path)
304
+
305
+ # Include directories
306
+ include_dirs = {list(self.incdirs)!r}
307
+
308
+ # Defines (filter out None values for cocotb compatibility)
309
+ all_defines = {dict(self.defines)!r}
310
+ defines = {{k: v for k, v in all_defines.items() if v is not None}}
311
+
312
+ # Parameters (empty for simple modules without parameters)
313
+ parameters = {{}}
314
+
315
+ try:
316
+ # Get the runner for the specified simulator
317
+ runner = get_runner(simulator)
318
+
319
+ # Build the design
320
+ runner.build(
321
+ sources=sources,
322
+ hdl_toplevel=hdl_toplevel,
323
+ includes=include_dirs,
324
+ defines=defines,
325
+ parameters=parameters,
326
+ build_dir="sim_build",
327
+ )
328
+
329
+ # Run the test
330
+ runner.test(
331
+ hdl_toplevel=hdl_toplevel,
332
+ test_module=test_module,
333
+ test_dir=".",
334
+ )
335
+
336
+ print("{self._get_success_message()}")
337
+
338
+ except Exception as e:
339
+ print(f"ERROR: Cocotb test failed: {{e}}")
340
+ sys.exit(1)
341
+
342
+ if __name__ == "__main__":
343
+ run_cocotb_test()
344
+ '''
345
+
346
+ def _create_makefile_content(self) -> str:
347
+ '''Create Makefile content for cocotb traditional system'''
348
+
349
+ # Determine test module
350
+ test_module = self._get_test_module_name()
351
+
352
+ # Get HDL sources and determine language
353
+ hdl_sources = self._get_hdl_sources()
354
+ verilog_sources = hdl_sources['verilog']
355
+ vhdl_sources = hdl_sources['vhdl']
356
+
357
+ # Determine HDL language
358
+ if vhdl_sources and not verilog_sources:
359
+ hdl_lang = 'vhdl'
360
+ sources_var = 'VHDL_SOURCES'
361
+ sources_list = ' '.join(vhdl_sources)
362
+ else:
363
+ hdl_lang = 'verilog'
364
+ sources_var = 'VERILOG_SOURCES'
365
+ sources_list = ' '.join(verilog_sources)
366
+
367
+ makefile_content = f'''# Cocotb Makefile generated by opencos
368
+
369
+ # Simulator selection
370
+ SIM ?= {self.args['cocotb-simulator']}
371
+
372
+ # HDL language
373
+ TOPLEVEL_LANG = {hdl_lang}
374
+
375
+ # HDL sources
376
+ {sources_var} = {sources_list}
377
+
378
+ # Top level module
379
+ TOPLEVEL = {self.args.get('top', 'top')}
380
+
381
+ # Test module
382
+ MODULE = {test_module}
383
+
384
+ # Include directories
385
+ '''
386
+
387
+ if self.incdirs:
388
+ makefile_content += ('COMPILE_ARGS += ' +
389
+ ' '.join(f'-I{inc}' for inc in self.incdirs) + '\n')
390
+
391
+ # Add defines
392
+ if self.defines:
393
+ define_args = []
394
+ for k, v in self.defines.items():
395
+ if v is None:
396
+ define_args.append(f'-D{k}')
397
+ else:
398
+ define_args.append(f'-D{k}={sanitize_defines_for_sh(v)}')
399
+ makefile_content += 'COMPILE_ARGS += ' + ' '.join(define_args) + '\n'
400
+
401
+ makefile_content += '''
402
+ # Waves support
403
+ ifeq ($(WAVES),1)
404
+ COCOTB_ENABLE_WAVES = 1
405
+ export COCOTB_ENABLE_WAVES
406
+ endif
407
+
408
+ # Include cocotb's Makefile
409
+ include $(shell cocotb-config --makefiles)/Makefile.sim
410
+ '''
411
+
412
+ return makefile_content
413
+
414
+ def _get_success_message(self) -> str:
415
+ '''Get standardized success message'''
416
+ return "Cocotb test completed successfully!"
417
+
418
+ def _create_shell_command_with_success(self, base_command: str) -> list:
419
+ '''Create a shell command list with success message'''
420
+ return ['sh', '-c', f'{base_command} && echo "{self._get_success_message()}"']
421
+
422
+ def _get_cocotb_env_vars(self) -> dict:
423
+ '''Get environment variables for cocotb execution'''
424
+ env_vars = {}
425
+
426
+ # Basic cocotb configuration
427
+ env_vars['SIM'] = self.args['cocotb-simulator']
428
+ env_vars['TOPLEVEL'] = self.args.get('top', 'top')
429
+
430
+ # Enable waves if requested
431
+ if self.args.get('waves', False):
432
+ env_vars['COCOTB_ENABLE_WAVES'] = '1'
433
+
434
+ # Set log level based on verbosity
435
+ if util.args.get('verbose', False):
436
+ env_vars['COCOTB_LOG_LEVEL'] = 'DEBUG'
437
+ else:
438
+ env_vars['COCOTB_LOG_LEVEL'] = 'INFO'
439
+
440
+ # Random seed
441
+ if self.args.get('seed'):
442
+ env_vars['COCOTB_RANDOM_SEED'] = str(self.args['seed'])
443
+
444
+ return env_vars
445
+
446
+ def _create_env_command(self, env_vars: dict) -> list:
447
+ '''Create environment variable command prefix'''
448
+ env_cmd = []
449
+ for key, value in env_vars.items():
450
+ env_cmd.extend(['env', f'{key}={value}'])
451
+ return env_cmd
452
+
453
+ def compile(self):
454
+ # For cocotb, compilation happens as part of the test run
455
+ if self.args['stop-before-compile']:
456
+ return
457
+ util.info('Cocotb: compilation will happen during test execution')
458
+
459
+ def elaborate(self):
460
+ # For cocotb, elaboration happens as part of the test run
461
+ pass
462
+
463
+ def simulate(self):
464
+ if self.args['stop-before-compile'] or self.args['stop-after-compile'] or \
465
+ self.args['stop-after-elaborate']:
466
+ return
467
+
468
+ # Run the cocotb tests
469
+ self.run_commands_check_logs(self.cocotb_command_lists)
470
+
471
+ def get_compile_command_lists(self, **kwargs) -> list:
472
+ # Cocotb handles compilation internally
473
+ return []
474
+
475
+ def get_elaborate_command_lists(self, **kwargs) -> list:
476
+ # Cocotb handles elaboration internally
477
+ return []
478
+
479
+ def get_simulate_command_lists(self, **kwargs) -> list:
480
+ return self.cocotb_command_lists
481
+
482
+ def get_post_simulate_command_lists(self, **kwargs) -> list:
483
+ return []
@@ -1,6 +1,8 @@
1
1
  ''' opencos.tools.questa_fse - Used by opencos.eda for sim/elab commands w/ --tool=questa_fse.
2
2
 
3
3
  Contains classes for CommandSimQuestaFse, CommandElabQuestaFse.
4
+ For: Questa Intel Starter FPGA Edition-64 vsim 20XX.X Simulator
5
+
4
6
  '''
5
7
 
6
8
  # pylint: disable=R0801 # (duplicate code in derived classes, such as if-condition return.)
@@ -79,6 +79,8 @@ class VerilatorSim(CommandSim, ToolVerilator):
79
79
  'lint-only': False,
80
80
  'cc-mode': False,
81
81
  'verilator-coverage-args': [],
82
+ 'x-assign': '',
83
+ 'x-initial': '',
82
84
  })
83
85
 
84
86
  self.args_help.update({
@@ -92,6 +94,14 @@ class VerilatorSim(CommandSim, ToolVerilator):
92
94
  'gui': 'Not supported for Verilator',
93
95
  'cc-mode': 'Run verilator with --cc, requires a sim_main.cpp or similar sources',
94
96
  'optimize': 'Run verilator with: -CLAGS -O3, if no other CFLAGS args are presented',
97
+ 'x-assign': ('String value to added to verilator call: --x-assign <string>;'
98
+ ' where valid string values are: 0, 1, unique, fast.'
99
+ ' Also conditinally adds to verilated exe call:'
100
+ ' +verilator+rand+reset+[0,1,2] for arg values 0, 1, unique|fast'),
101
+ 'x-initial': ('String value to added to verilator call: --x-initial <string>;'
102
+ ' where valid string values are: 0, unique, fast.'
103
+ ' Also conditinally adds to verilated exe call:'
104
+ ' +verilator+rand+reset+[0,2] for arg values 0, unique|fast'),
95
105
  })
96
106
 
97
107
  self.verilate_command_lists = []
@@ -219,6 +229,14 @@ class VerilatorSim(CommandSim, ToolVerilator):
219
229
  '-o', 'sim.exe',
220
230
  ]
221
231
 
232
+ for arg in ('x-assign', 'x-initial'):
233
+ if self.args[arg] and f'--{arg}' not in verilate_command_list:
234
+ # Only add this if arg is set, and not present in verilator call
235
+ # this takes care of it being in our self.tool_config for compile-args.
236
+ verilate_command_list += [
237
+ f'--{arg}', self.args[arg]
238
+ ]
239
+
222
240
  # incdirs
223
241
  for value in self.incdirs:
224
242
  verilate_command_list += [ f"+incdir+{value}" ]
@@ -295,6 +313,19 @@ class VerilatorSim(CommandSim, ToolVerilator):
295
313
  if not any(x.startswith('+verilator+seed+') for x in verilated_exec_command_list):
296
314
  verilated_exec_command_list.append(f'+verilator+seed+{verilator_seed}')
297
315
 
316
+ if any(self.args[arg] in ('unique', 'fast') for arg in ('x-assign', 'x-initial')) and \
317
+ not any(x.startswith('+verilator+rand+reset') for x in verilated_exec_command_list):
318
+ # Only add this if arg is one of x-assign/x-initial is set to "unique" or "fast",
319
+ # we use the encoded value "2" for +verilator+rand+reset+2
320
+ verilated_exec_command_list.append('+verilator+rand+reset+2')
321
+
322
+ if self.args['x-assign'] == '1' and \
323
+ not any(x.startswith('+verilator+rand+reset') for x in verilated_exec_command_list):
324
+ # Only add this if --x-assign=1 (not valid for --x-initial),
325
+ # we use the encoded value "1" for +verilator+rand+reset+1
326
+ verilated_exec_command_list.append('+verilator+rand+reset+1')
327
+
328
+
298
329
  return [
299
330
  util.ShellCommandList(verilated_exec_command_list, tee_fpath='sim.log')
300
331
  ] # single entry list
opencos/tools/yosys.py CHANGED
@@ -117,6 +117,7 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
117
117
  'yosys-blackbox': [], # list of modules that yosys will blackbox.
118
118
  'yosys-scriptfile': [],
119
119
  'sta-scriptfile': [],
120
+ 'rename-module': ''
120
121
  })
121
122
  self.args_help.update({
122
123
  'sta': (
@@ -150,12 +151,14 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
150
151
  ' via: sta -no_init -exit <this-arg>. You can set multiple args for multiple'
151
152
  ' scriptfile (appends)'
152
153
  ),
154
+ 'rename-module': 'Renames the output .v and module name',
153
155
  })
154
156
 
155
157
  self.yosys_out_dir = ''
156
158
  self.yosys_v_path = ''
157
159
  self.full_work_dir = ''
158
160
  self.blackbox_list = []
161
+ self.top_module = ''
159
162
 
160
163
  def do_it(self) -> None:
161
164
  self.set_tool_defines()
@@ -333,6 +336,13 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
333
336
  ]
334
337
  lines += [
335
338
  'opt_clean',
339
+ ]
340
+ if self.args['rename-module']:
341
+ lines += [f'rename {self.args["top"]} {self.args["rename-module"]}']
342
+ self.top_module = self.args['rename-module']
343
+ else:
344
+ self.top_module = self.args["top"]
345
+ lines += [
336
346
  f'write_verilog {self.yosys_v_path}',
337
347
  f'write_json {self.yosys_v_path}.json',
338
348
  ]
@@ -388,7 +398,7 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
388
398
  lines = [
389
399
  'read_liberty ' + self.args['liberty-file'],
390
400
  'read_verilog ' + self.yosys_v_path,
391
- 'link_design ' + self.args['top'],
401
+ 'link_design ' + self.top_module,
392
402
  ]
393
403
  for _file in self.files_sdc:
394
404
  lines.append('read_sdc ' + _file)
@@ -505,12 +515,13 @@ class CommandLecYosys(CommandLec, ToolYosys):
505
515
  })
506
516
 
507
517
  self.synth_work_dirs = [
508
- os.path.join('eda.work', 'lec.design1.synth'),
509
- os.path.join('eda.work', 'lec.design2.synth')
518
+ os.path.join('eda.work', 'lec.Design1.synth'),
519
+ os.path.join('eda.work', 'lec.Design2.synth')
510
520
  ]
511
521
 
512
522
  self.synth_designs_tops = [None, None]
513
523
  self.synth_designs_fpaths = [None, None]
524
+ self.synth_design_top_module_names = [None, None]
514
525
 
515
526
  def get_synth_result_fpath(self, target: str) -> str:
516
527
  '''Overridden from CommandLec'''
@@ -534,9 +545,12 @@ class CommandLecYosys(CommandLec, ToolYosys):
534
545
 
535
546
  synth_cmd_list += [
536
547
  '--work-dir=' + self.synth_work_dirs[design_num],
537
- self.args['designs'][design_num]
548
+ self.args['designs'][design_num],
549
+ f'--rename-module=Design{design_num + 1}'
538
550
  ]
539
551
 
552
+ self.synth_design_top_module_names[design_num] = f'Design{design_num + 1}'
553
+
540
554
  return synth_cmd_list
541
555
 
542
556
 
@@ -663,10 +677,12 @@ class CommandLecYosys(CommandLec, ToolYosys):
663
677
  else:
664
678
  self.error(f' --pre-read-verilog file {x} does not exist')
665
679
  lec_cmd_f_list += [
680
+ '# Design1 (module):',
666
681
  f'read_verilog -sv -icells {self.synth_designs_fpaths[0]}',
682
+ '# Design2 (module):',
667
683
  f'read_verilog -sv -icells {self.synth_designs_fpaths[1]}',
668
684
  'clk2fflogic;',
669
- f'miter -equiv -flatten {" ".join(self.synth_designs_tops)} miter',
685
+ f'miter -equiv -flatten {" ".join(self.synth_design_top_module_names)} miter',
670
686
  ('sat -seq 50 -verify -prove trigger 0 -show-all -show-inputs -show-outputs'
671
687
  ' -set-init-zero miter'),
672
688
  ]