VUnit / vunit

VUnit is a unit testing framework for VHDL/SystemVerilog
http://vunit.github.io/
Other
721 stars 258 forks source link

Provide public API to get VUnit sources #699

Open GlenNicholls opened 3 years ago

GlenNicholls commented 3 years ago

When interfacing with linters and other tools like LSP's, it would be useful to have some public API to fetch all VUnit source files that should be compiled into vunit_lib, including adding OSVVM and JSON-for-VHDL. When looking through the VHDL sources, these are the following files that need special handling depending on the VHDL version:

vunit/vhdl/core/src/
  stop_body_93-2002.vhd
  stop_body_2008p.vhd

vunit/vhdl/data_types/src
  codec_builder.vhd
  codec_builder-2008p.vhd
  codec-2008p.vhd
  integer_vector_ptr_pkg-body-93.vhd
  integer_vector_ptr_pkg-body-2002p.vhd
  queue_pkg.vhd
  queue_pkg-2008p.vhd
  string_ptr_pkg-body-93.vhd
  string_ptr_pkg-body-2002p.vhd

The other considerations are *_depracated.vhd files as I would only want whatever VUnit actually gathers. I am making a parser to create a project file for GHDL LSP and Rust HDL (with future support for others like TerosHDL) and handling all of the naming conventions is annoying because it is not consistent (*-<version>.vhd and *_<version>.vhd).

My first consideration was to call subprocess.Popen() with vunit/vhdl/compile_vunit_lib.py, but this is awkward because I don't want to actually compile anything. I just want a Python dictionary of {"vunit_lib" : [<file paths>]}. I can call python compile_vunit_lib.py --export-json and then parse the JSON file, but this is just a waste of time IMO as I cannot control the VHDL version. I can alternatively just put the following in my script:

from vunit import VUnit

ui = VUnit.from_argv()
ui.main()

But again, I have to then set the VHDL version and waste time compiling files that don't need compilation. Here are my questions:

  1. Is there a better way to gather all of the source files depending on the version without parsing the vhdl directory?
  2. What is the naming convention? Is the following a correct interpretation?
*93.vhd -> only VHDL 93 compatible
*93-2002.vhd -> only VHDL 93-2002 compatible
*2002p.vhd -> only VHDL 2002+ compatible
*<no version>.vhd -> compatible with all versions

In the final case of "compatible with all versions", this is not super easy to recognize in the case of queue_pkg.vhd as it looks like queue_pkg.vhd is VHDL 93-2002 whereas queue_pkg-2008p.vhd is VHDL 2008, but stop_body_*.vhd is more explicit about the accepted standard in the name. I don't like the idea of creating either a hard-coded list of files or a list of file exceptions because this can easily change. Some API to access this information or a file in the repo would make this much more maintainable.

GlenNicholls commented 3 years ago

The other thing I just noticed about calling ui = VUnit.from_argv() is it messes up my parser. I also found get_source_files_in_order which looks like it might do what I need it to do in the short term. How can I define the VUnit class without VUnit.from_argv() such that I can call get_source_files_in_order?

nfrancque commented 2 years ago

@GlenNicholls If you're using vhdl ls in vscode as your LSP, this has been my workaround to get the vunit files. It's not perfect but has gotten the job done so far.

def get_vunit_stuff():
    """
    Gets all vunit libs if applicable

    Returns:
        A dictionary of lists representing all vunit related libraries

    """
    try:
        import vunit

        vunit_install_dir = Path(vunit.__file__).parent
    except:
        # Vunit must not be installed, empty
        return {}
    vunit_vhdl = vunit_install_dir / "vhdl"
    ret = {}
    ret["vunit_lib"] = []
    ret["osvvm"] = []
    for file in vunit_vhdl.rglob("*.vhd"):
        if "osvvm" in str(file):
            lib = "osvvm"
        else:
            lib = "vunit_lib"
        ret[lib].append(str(file.resolve()))
    return ret

Then just dump the dictionary with toml.

It seems to be okay with the duplicates by VHDL version, but you could modify it to only choose the 08 versions if there are multiple. I don't personally care much if it picks the version my simulator will end up using, just that you can go to a definition and see what the behavior of a function etc is expected to be.

GlenNicholls commented 2 years ago

Thanks for that, didn't think about the fact that the version selected shouldn't matter... I do something similar, but I copied the code VUnit uses to gather its own files. Thanks for the tip, that'll help reduce the complexity of that part of my code!