Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding csv mapping support for files and libraries #349

Merged
merged 25 commits into from
Jun 28, 2018

Conversation

davidmedinasigasi
Copy link
Contributor

No description provided.

vunit/ui.py Outdated
for lib_name in libs_and_files.keys():
files = libs_and_files[lib_name]
lib = self.add_library(lib_name)
lib.add_source_files(files)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other functions that add files return the list of files added.

vunit/ui.py Outdated
for row in content:
if len(row) == 2:
lib_name = row[0].strip()
file_name = row[1].strip()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be reasonable to interpret the file name as relative to the location of the .csv file or an absolute path rather than relative to the current working directory when this code is executing,

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean with the file name in this context is the file name that is written inside the csv file.

For example if a have the following structure:
/directory/proj.csv
/directory/file.vhd
/run.py

If proj.csv contains "lib, file.vhd" and I run "python run.py" in the root directory it should refer to /directory/proj.csv making the semantics of the proj.csv file independent on the current working directory where the run.py script is executed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand what you want me to do, I just don't know how, can you please explain a little more?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can achieve what I describe by.

from os.path import normpath, join, dirname
normpath(join(dirname(csv_file_name), file_name))

It will make file_name relative to the parent directory of the csv file unless file name is an absolute path already.

vunit/ui.py Outdated
@@ -393,6 +394,36 @@ def add_external_library(self, library_name, path, vhdl_standard=None):
self._project.add_library(library_name, abspath(path), vhdl_standard, is_external=True)
return self.library(library_name)

def add_csv(self, project_csv_path, vhdl_standard=None):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add_source_files_from_csv would be a better name

vunit/ui.py Outdated
@@ -393,6 +394,36 @@ def add_external_library(self, library_name, path, vhdl_standard=None):
self._project.add_library(library_name, abspath(path), vhdl_standard, is_external=True)
return self.library(library_name)

def add_csv(self, project_csv_path, vhdl_standard=None):
"""
Add a project configuration, mapping all the libraries and files
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description does not describe the format of the csv file or the meaning of relative paths of the file names.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some WIP related to a similar approach with JSON:

where the 'generic' run-py contains:

and the example JSON itself is:

I'd be glad if the format/approach was explicitly documented, in order to follow the same pattern when I return to it.

vunit/ui.py Outdated
@@ -422,7 +424,7 @@ def add_csv(self, project_csv_path, vhdl_standard=None):
for lib_name in libs_and_files.keys():
files = libs_and_files[lib_name]
lib = self.add_library(lib_name)
lib.add_source_files(files)
return lib.add_source_files(files)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug: return inside for-loop only works for single library in the csv file

vunit/ui.py Outdated
for lib_name in libs_and_files.keys():
files = libs_and_files[lib_name]
lib = self.add_library(lib_name)
return lib.add_source_files(files)
list_of_source_files.append(lib.add_source_files(files))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will create a list of lists and not a single list of all files added.

vunit/ui.py Outdated
@@ -426,7 +426,10 @@ def add_source_files_from_csv(self, project_csv_path, vhdl_standard=None):
files = libs_and_files[lib_name]
lib = self.add_library(lib_name)
list_of_source_files.append(lib.add_source_files(files))
return list_of_source_files

list_of_source_files_flattened = [val for sublist in list_of_source_files for val in sublist]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+= would have been nicer. Also it seems this should have a unit test since there were so many bugs.

Copy link
Collaborator

@kraigher kraigher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there now. Some things left though.


source_files = ui.add_source_files_from_csv('test_returns.csv')

for i in range(len(source_files)):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is flawed. source_files could just be empty or miss the last element and the test would still pass. Use list_of_files as the iteration length source instead. Or even better just compare the lists directly with self.assertEqual([source_file.name for source_file in source_files, list_of_files)

vunit/ui.py Outdated
def add_source_files_from_csv(self, project_csv_path, vhdl_standard=None):
"""
Add a project configuration, mapping all the libraries and files
:param project_csv_path: path to csv project specification, each line contains the name
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation should also say that relative file names are relative to the parent folder of the csv file.

vunit/ui.py Outdated
elif len(row) > 2:
LOGGER.error("More than one library and one file in csv description")

list_of_source_files = list()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

= SourceFileList()

Otherwise the return value will be a list() and not a SourceFileList like the documentation claims.

@kraigher
Copy link
Collaborator

Good now you just have to fix the lint violations to make the Travis CI check pass.
You can run pylint and pycodestyle locally as decribed here: http://vunit.github.io/contributing.html#running-the-tests

pytest vunit/test/lint/


for index, library_name in enumerate(libraries):
file_name = files[index]
file_name_from_ui = ui.add_source_files_from_csv(file_name, library_name)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line does not make sense. You add the file_name as a csv file but the file is an empty vhdl_file.
Did you mean to do get_source_file?

"""

libraries = ['lib', 'lib1', 'lib2']
files = ['tb_example.vhdl', 'tb_example1.vhd', 'tb_example2.vhd', ' tb,ex3.vhd']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tb,ext3.vhd is unnessary?

vunit/ui.py Outdated
lib = self.library(lib_name) if lib_name in libs else self.add_library(lib_name)
libs.add(lib_name)
file_ = lib.add_source_file(file_name_)
if file_before is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This circumvents the dependency scanning performed by VUnit, why are you creating manual dependencies? VUnit will still can the files added for dependencies unless you add the no_parse argument to add_source_file.

Copy link
Collaborator

@kraigher kraigher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason you do not want to use the VUnit dependency scanning? Just having a linear dependency order is much worse. Since the order is linear some files later in the list will not depend on files further up in the list and thus it will cause unnecessary compilation. A compile order should be a tree and not a list.

vunit/ui.py Outdated
@@ -393,6 +394,46 @@ def add_external_library(self, library_name, path, vhdl_standard=None):
self._project.add_library(library_name, abspath(path), vhdl_standard, is_external=True)
return self.library(library_name)

def add_source_files_from_csv(self, project_csv_path, vhdl_standard=None, is_in_order=True):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default should not be to disable the VUnit dependency scanning.

vunit/ui.py Outdated
file_name_ = normpath(join(dirname(project_csv_path), no_normalized_file))
lib = self.library(lib_name) if lib_name in libs else self.add_library(lib_name)
libs.add(lib_name)
file_ = lib.add_source_file(file_name_, no_parse=is_in_order)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No parse will also inhibit any test_benches/tests from being detected from the source file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When sigasi generates the csv file, we resolve all dependencies in a way that the first file is a dependency for the next one, for example
lib, example.vhd
lib2, example2.vhd // This one depends on lib, example.vhd
lib, example3.vhd // This one depends on lib2, example2.vhd
lib3, example4.vhd // This one depends on lib, example3.vhd

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependencies are never linear they are a tree. To force them to be linear creates a lot of unnecessary re-compilation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the case with 200 files with 20 groups of 10 files. Each group has a linear dependency but the groups are independent. If you can only express a linear order some group will be first and some group will be last. If a file in the first group is modified it causes 200 files to be recompiled instead of only 10.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sigasi for sure has a dependency tree internally. It is only when you need to generate a sequence of compile commands for the initial compile that it is useful to generate an ordered list of files. For subsequent incremental compiles which is a big feature of VUnit a new ordered list of compile commands has to generated based on the files changes and the dependency tree.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In summary: I think skipping the VUnit dependency scanning in favor of a linear dependency list from Sigasi is a bad idea that will lead to worse re-compilation times. Also as the feature is implemented now it does not work since no_parse=True will also inhibit VUnit form recognizing any tests in the added files (which probably is not what you want). My recommendation would be to skip the is_in_order=True variant completely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're planning to improve how Sigasi export the csv description. Right now we want a fist approach to the integration with Vunit. We're thinking to optimize the compile order generated by Sigasi in the near future

@kraigher
Copy link
Collaborator

The function to get built in libraries should not be a part of this pull request. It should be reviewed separately. You need to use feature branches in your fork to separate the issues.

vunit/ui.py Outdated
@@ -393,6 +394,46 @@ def add_external_library(self, library_name, path, vhdl_standard=None):
self._project.add_library(library_name, abspath(path), vhdl_standard, is_external=True)
return self.library(library_name)

def add_source_files_from_csv(self, project_csv_path, vhdl_standard=None, is_in_order=False):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way is_in_order works now is just bad. VUnit will still scan all files for dependencies in addition to the sub-optimal linear dependency list enforced on top by is_in_order=True. I think you should remove the is_in_order option from this function as it does not make sense as implemented. I think the option should be removed and no manual dependency order defined.

@kraigher kraigher merged commit d2e7bd8 into VUnit:master Jun 28, 2018
nathanaelhuffman pushed a commit to nathanaelhuffman/vunit that referenced this pull request Jul 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants