diff --git a/edalize/icestorm.py b/edalize/icestorm.py index ad6e9ce4e..743c06d23 100644 --- a/edalize/icestorm.py +++ b/edalize/icestorm.py @@ -42,8 +42,10 @@ def configure_main(self): {'yosys' : { 'arch' : 'ice40', 'yosys_synth_options' : yosys_synth_options, + 'yosys_read_options' : self.tool_options.get('yosys_read_options', []), 'yosys_as_subtool' : True, 'yosys_template' : self.tool_options.get('yosys_template'), + 'frontend_options' : self.tool_options.get('frontedn_options',[]) }, 'nextpnr' : { 'nextpnr_options' : self.tool_options.get('nextpnr_options', []) diff --git a/edalize/surelog.py b/edalize/surelog.py new file mode 100644 index 000000000..7775f36f1 --- /dev/null +++ b/edalize/surelog.py @@ -0,0 +1,59 @@ + +import logging +import os.path + +from edalize.edatool import Edatool +import shutil + +logger = logging.getLogger(__name__) + +class Surelog(Edatool): + + argtypes = ['vlogdefine', 'vlogparam'] + + @classmethod + def get_doc(cls, api_ver): + if api_ver == 0: + return {'description' : "Surelog", + 'members' : [ + {'name' : 'arch', + 'type' : 'String', + 'desc' : 'Target architecture. Legal values are *xilinx*, *ice40* and *ecp5*'} + ], + 'lists' : [ + {'name' : 'surelog_options', + 'type' : 'String', + 'desc' : 'List of the Surelog parameters'}, + ]} + + def configure_main(self): + (src_files, incdirs) = self._get_fileset_files() + verilog_file_list = [] + systemverilog_file_list = [] + for f in src_files: + if f.file_type.startswith('verilogSource'): + verilog_file_list.append(f.name) + if f.file_type.startswith('systemVerilogSource'): + systemverilog_file_list.append("-sv " + f.name) + + surelog_options = self.tool_options.get('surelog_options', []) + arch = self.tool_options.get('arch', None) + + pattern = len(self.vlogparam.keys()) * " -P%s=%%s" + verilog_params_command = pattern % tuple(self.vlogparam.keys()) % tuple(self.vlogparam.values()) + + verilog_defines_command = "+define" if self.vlogdefine.items() else "" + pattern = len(self.vlogdefine.keys()) * "+%s=%%s" + verilog_defines_command += pattern % tuple(self.vlogdefine.keys()) % tuple(self.vlogdefine.values()) + + pattern = len(incdirs) * " -I%s" + include_files_command = pattern % tuple(incdirs) + + commands = self.EdaCommands() + share_path = os.path.join(os.path.dirname(shutil.which("uhdm-yosys")), "../share/uhdm-yosys") + commands.add(["surelog", f"{' '.join(surelog_options)}", "-parse", f"{verilog_defines_command}", + f"{verilog_params_command}", f"-top {self.toplevel}", f"{include_files_command}", + f"{' '.join(verilog_file_list)}", f"{' '.join(systemverilog_file_list)}"], + ["slpp_all/surelog.uhdm"], []) + commands.add([f"cp slpp_all/surelog.uhdm {self.toplevel}.uhdm"] ,[self.toplevel + '.uhdm'], ["slpp_all/surelog.uhdm"]) + self.commands = commands.commands diff --git a/edalize/symbiflow.py b/edalize/symbiflow.py index 5b255d02c..7d8b3dabe 100644 --- a/edalize/symbiflow.py +++ b/edalize/symbiflow.py @@ -10,6 +10,7 @@ from edalize.edatool import Edatool from edalize.yosys import Yosys +from edalize.surelog import Surelog from importlib import import_module logger = logging.getLogger(__name__) @@ -100,8 +101,11 @@ def configure_nextpnr(self): "yosys" : { "arch" : vendor, "yosys_synth_options" : yosys_synth_options, + "yosys_additional_commands" : yosys_additional_commands, + 'yosys_read_options' : self.tool_options.get('yosys_read_options', []), "yosys_template" : yosys_template, "yosys_as_subtool" : True, + 'frontend_options' : self.tool_options.get('frontend_options', []), } } } diff --git a/edalize/trellis.py b/edalize/trellis.py index 1102f693b..8df5962d3 100644 --- a/edalize/trellis.py +++ b/edalize/trellis.py @@ -32,8 +32,10 @@ def configure_main(self): {'yosys' : { 'arch' : 'ecp5', 'yosys_synth_options' : self.tool_options.get('yosys_synth_options', []), + 'yosys_read_options' : self.tool_options.get('yosys_read_options'), 'yosys_as_subtool' : True, 'yosys_template' : self.tool_options.get('yosys_template'), + 'frontend_options' : self.tool_options.get('frontend_options'), }, 'nextpnr' : { 'nextpnr_options' : self.tool_options.get('nextpnr_options', []) diff --git a/edalize/vivado.py b/edalize/vivado.py index b338f798c..05edfd301 100644 --- a/edalize/vivado.py +++ b/edalize/vivado.py @@ -54,6 +54,17 @@ def get_doc(cls, api_ver): {'name' : 'hw_target', 'type' : 'Description', 'desc' : 'A pattern matching a board identifier. Refer to the Vivado documentation for ``get_hw_targets`` for details. Example: ``*/xilinx_tcf/Digilent/123456789123A``'}, + ], + 'lists' : [ + {'name' : 'yosys_synth_options', + 'type' : 'String', + 'desc' :'Additional options for synth command'}, + {'name' : 'yosys_read_options', + 'type' : 'String', + 'desc' : 'Additional options for Yosys\' read command'}, + {'name' : 'frontend_options', + 'type' : 'String', + 'desc' : 'Additional options for the Yosys frontend'}, ]} """ Get tool version @@ -91,7 +102,9 @@ def configure_main(self): 'arch' : 'xilinx', 'output_format' : 'edif', 'yosys_synth_options' : self.tool_options.get('yosys_synth_options', []), + 'yosys_read_options' : self.tool_options.get('yosys_read_options', []), 'yosys_as_subtool' : True, + 'frontend_options' : self.tool_options.get('frontend_options', []) } yosys = Yosys(self.edam, self.work_root) diff --git a/edalize/yosys.py b/edalize/yosys.py index ec7ca7221..f7dbc12b7 100644 --- a/edalize/yosys.py +++ b/edalize/yosys.py @@ -6,6 +6,7 @@ import os.path from edalize.edatool import Edatool +from edalize.surelog import Surelog logger = logging.getLogger(__name__) @@ -38,6 +39,15 @@ def get_doc(cls, api_ver): {'name' : 'yosys_synth_options', 'type' : 'String', 'desc' : 'Additional options for the synth command'}, + {'name' : 'yosys_read_options', + 'type' : 'String', + 'desc' : 'Addtional options for the read_* command (e.g. read_verlog or read_uhdm)'}, + {'name' : 'yosys_additional_commands', + 'type' : 'String', + 'desc' : 'Additional commands for the yosys script after synth'}, + {'name' : 'frontend_options', + 'type' : 'String', + 'desc' : 'Additional options for the Yosys frontend'}, ]} def configure_main(self): @@ -49,20 +59,51 @@ def configure_main(self): file_table = [] unused_files = [] - for f in self.files: - cmd = "" - if f['file_type'].startswith('verilogSource'): - cmd = 'read_verilog' - elif f['file_type'].startswith('systemVerilogSource'): - cmd = 'read_verilog -sv' - elif f['file_type'] == 'tclSource': - cmd = 'source' - - if cmd: - if not self._add_include_dir(f, incdirs): - file_table.append(cmd + ' {' + f['name'] + '}') - else: - unused_files.append(f) + yosys_read_options = " ".join(self.tool_options.get('yosys_read_options', [])) + yosys_synth_options = self.tool_options.get('yosys_synth_options', []) + + arch = self.tool_options.get('arch', None) + if not arch: + logger.error("ERROR: arch is not defined.") + + use_surelog = False + if "frontend=surelog" in yosys_synth_options: + use_surelog = True + yosys_synth_options.remove("frontend=surelog") + + if use_surelog: + self.edam['tool_options']['surelog'] = { + 'surelog_options' : self.tool_options.get('frontend_options', []), + 'arch' : arch, + } + surelog = Surelog(self.edam, self.work_root) + surelog.configure() + self.vlogparam.clear() + self.vlogdefine.clear() + uhdm_file = os.path.abspath(self.work_root + '/' + self.toplevel + '.uhdm') + file_table.append('read_uhdm' + yosys_read_options + ' {' + uhdm_file + '}') + for f in self.files: + if f['file_type'].startswith('verilogSource') or\ + f['file_type'].startswith('systemVerilogSource') or\ + f['file_type'] == 'tclSource': + continue + else: + unused_files.append(f) + else: + for f in self.files: + cmd = "" + if f['file_type'].startswith('verilogSource'): + cmd = 'read_verilog' + elif f['file_type'].startswith('systemVerilogSource'): + cmd = 'read_verilog -sv' + elif f['file_type'] == 'tclSource': + cmd = 'source' + + if cmd: + if not self._add_include_dir(f, incdirs): + file_table.append(cmd + ' {' + f['name'] + '}') + else: + unused_files.append(f) self.edam['files'] = unused_files of = [ @@ -86,10 +127,6 @@ def configure_main(self): self.toplevel)) output_format = self.tool_options.get('output_format', 'blif') - arch = self.tool_options.get('arch', None) - - if not arch: - logger.error("ERROR: arch is not defined.") template = yosys_template or 'edalize_yosys_template.tcl' template_vars = { @@ -99,7 +136,8 @@ def configure_main(self): 'incdirs' : ' '.join(['-I'+d for d in incdirs]), 'top' : self.toplevel, 'synth_command' : "synth_" + arch, - 'synth_options' : " ".join(self.tool_options.get('yosys_synth_options', '')), + 'synth_options' : " ".join(yosys_synth_options), + 'additional_commands' : self.tool_options.get('yosys_additional_commands', []), 'write_command' : "write_" + output_format, 'default_target' : output_format, 'edif_opts' : '-pvector bra' if arch=='xilinx' else '', @@ -117,9 +155,15 @@ def configure_main(self): template_vars) commands = self.EdaCommands() - commands.add(['yosys', '-l', 'yosys.log', '-p', f'"tcl {template}"'], + dep = [] + yosys = 'yosys' + if use_surelog: + commands.commands += surelog.commands + dep = [self.toplevel + ".uhdm"] + yosys = 'uhdm-' + yosys + commands.add([yosys, '-l', 'yosys.log', '-p', f'"tcl {template}"'], [f'{self.name}.{output}' for output in ['blif', 'json','edif']], - [template]) + [template]+dep) if self.tool_options.get('yosys_as_subtool'): self.commands = commands.commands else: