Source code for edalize.ghdl

# Copyright edalize contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

import collections
import logging
import os.path
from edalize.edatool import Edatool

logger = logging.getLogger(__name__)


[docs] class Ghdl(Edatool): argtypes = ["vlogparam", "generic"]
[docs] @classmethod def get_doc(cls, api_ver): if api_ver == 0: return { "description": "GHDL is an open source VHDL simulator, which fully supports IEEE 1076-1987, IEEE 1076-1993, IEE 1076-2002 and partially the 1076-2008 version of VHDL", "lists": [ { "name": "analyze_options", "type": "String", "desc": "Options to use for the import (ghdl -i) and make (ghdl -m) phases", }, { "name": "run_options", "type": "String", "desc": "Options to use for the run (ghdl -r) phase", }, ], }
[docs] def configure_main(self): (src_files, incdirs) = self._get_fileset_files() analyze_options = self.tool_options.get("analyze_options", "") # Check of std=xx analyze option, this overyides the dynamic determination of vhdl standard import re rx = re.compile("^--std=([0-9]+)") m = None for o in analyze_options: m = rx.match(o) if m: stdarg = [m.group()] analyze_options.remove(o) break if m: logger.warning( "Analyze option " + m.group() + " given, will override any vhdlSource-xxxx specification\n" ) standard = m.group(1) else: # ghdl does not support mixing incompatible versions # specifying 93c as std should allow 87 syntax # 2008 can't be combined so try to parse everthing with 08 std has87 = has93 = has08 = False for f in src_files: if f.file_type == "vhdlSource-87": has87 = True elif f.file_type == "vhdlSource-93": has93 = True elif f.file_type == "vhdlSource-2008": has08 = True stdarg = [] if has08: if has87 or has93: logger.warning( "ghdl can't mix vhdlSource-2008 with other standard version\n" + "Trying with treating all as vhdlSource-2008" ) stdarg = ["--std=08"] elif has87 and has93: stdarg = ["--std=93c"] elif has87: stdarg = ["--std=87"] elif has93: stdarg = ["--std=93"] else: stdarg = ["--std=93c"] standard = rx.match(stdarg[0]).group(1) run_options = self.tool_options.get("run_options", []) analyze_options = " ".join(analyze_options) _vhdltypes = ("vhdlSource", "vhdlSource-87", "vhdlSource-93", "vhdlSource-2008") libraries = collections.OrderedDict() library_options = "--work={lib} --workdir=./{lib}" ghdlimport = "" vhdl_sources = "" # GHDL versions older than 849a25e0 don't support the dot notation (e.g. # my_lib.top_design) for the top level. # Nonetheless, we unconditionally split the library and the primary unit, # if the user specified the top level using the dot notation. top = self.toplevel.split(".") if len(top) > 2: logger.error("Invalid dot notation in toplevel: {}".format(self.toplevel)) top_libraries = "" if len(top) > 1: libraries[top[0]] = [] top_libraries = library_options.format(lib=top[0]) top_unit = top[-1] for f in src_files: if f.file_type in _vhdltypes: # Files without a specified library will by added to # libraries[None] which is perhaps poor form but avoids # conflicts with user generated names libraries[f.logical_name] = libraries.get(f.logical_name, []) + [f.name] vhdl_sources += " {file}".format(file=f.name) elif f.file_type in ["user"]: pass else: _s = "{} has unknown file type '{}'" logger.warning(_s.format(f.name, f.file_type)) ghdlimport = "" make_libraries_directories = "" for lib, files in libraries.items(): lib_opts = "" if lib: analyze_options += " -P./{}".format(lib) make_libraries_directories += "\tmkdir -p {}\n".format(lib) lib_opts = library_options.format(lib=lib) ghdlimport += "\t$(EDALIZE_LAUNCHER) ghdl -i $(STD) $(ANALYZE_OPTIONS) {} {}\n".format( lib_opts, " ".join(files) ) self.render_template( "Makefile.j2", "Makefile", { "std": " ".join(stdarg), "toplevel": top_unit, "vhdl_sources": vhdl_sources, "standard": standard, "analyze_options": analyze_options, "run_options": " ".join(run_options), "make_libraries_directories": make_libraries_directories, "ghdlimport": ghdlimport, "top_libraries": top_libraries, }, )
[docs] def run_main(self): cmd = "make" args = ["run"] # GHDL doesn't support Verilog, but the backend used vlogparam since # edalize didn't support generic at the time. Now that generic support # has been added support for vlogparam is deprecated and will be # removed in the future. For now support either option. if self.vlogparam: logger.warning( "GHDL backend support for vlogparam is deprecated and will be removed.\n" + "Use generic instead." ) if self.vlogparam or self.generic: extra_options = "EXTRA_OPTIONS=" for d in [self.vlogparam, self.generic]: for k, v in d.items(): extra_options += " -g{}={}".format( k, self._param_value_str(v, '"', bool_is_str=True) ) args.append(extra_options) self._run_tool(cmd, args)