Provide public API to get VUnit sources
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:
- Is there a better way to gather all of the source files depending on the version without parsing the
vhdldirectory? - 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.
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?
@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.
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!