Commit 4c27b771 authored by Will's avatar Will

Fix make_dependency_sorted_list ordering function.

Previous implelmentaiton only worked for a single level tree of dependencies.
This implementations recursively determines the number of levels below a dep_file and uses this value as the key to sort by. The 'dependendency level is cached in the dep_file object to reduce the number of recursive calls.
Will not handle circular dependencies well.
parent 4b77a820
...@@ -149,7 +149,8 @@ class DepFile(File): ...@@ -149,7 +149,8 @@ class DepFile(File):
self.file_path = file_path self.file_path = file_path
self._rels = set() self._rels = set()
self.depends_on = set() # set of files that the file depends on, items of type DepFile self.depends_on = set() # set of files that the file depends on, items of type DepFile
self.dep_level = None
self.is_parsed = False self.is_parsed = False
if include_paths is None: if include_paths is None:
include_paths = [] include_paths = []
...@@ -190,3 +191,12 @@ class DepFile(File): ...@@ -190,3 +191,12 @@ class DepFile(File):
@property @property
def filename(self): def filename(self):
return os.path.basename(self.file_path) return os.path.basename(self.file_path)
def get_dep_level(self):
if self.dep_level == None:
if len(self.depends_on) == 0:
self.dep_level = 0
else:
# recurse, to find the largest number of levels below.
self.dep_level = 1 + max([dep.get_dep_level() for dep in self.depends_on]);
return self.dep_level
...@@ -29,7 +29,6 @@ from srcfile import VHDLFile, VerilogFile, SVFile ...@@ -29,7 +29,6 @@ from srcfile import VHDLFile, VerilogFile, SVFile
import global_mod import global_mod
class DepParser(object): class DepParser(object):
def __init__(self, dep_file): def __init__(self, dep_file):
self.dep_file = dep_file self.dep_file = dep_file
...@@ -52,7 +51,7 @@ class ParserFactory(object): ...@@ -52,7 +51,7 @@ class ParserFactory(object):
vp.add_search_path(d) vp.add_search_path(d)
return vp return vp
else : else :
raise ValueError("Unecognized file format : %s" % dep_file.file_path) raise ValueError("Unrecognized file format : %s" % dep_file.file_path)
# class DepSolver(object): # class DepSolver(object):
# def solve(self, vhdl_files): # def solve(self, vhdl_files):
...@@ -95,8 +94,6 @@ def solve(fileset): ...@@ -95,8 +94,6 @@ def solve(fileset):
continue continue
satisfied_by = set() satisfied_by = set()
for dep_file in fset: for dep_file in fset:
# if dep_file is investigated_file:
# continue
if dep_file.satisfies(rel): if dep_file.satisfies(rel):
if dep_file is not investigated_file: if dep_file is not investigated_file:
investigated_file.depends_on.add(dep_file) investigated_file.depends_on.add(dep_file)
...@@ -118,40 +115,46 @@ def solve(fileset): ...@@ -118,40 +115,46 @@ def solve(fileset):
def make_dependency_sorted_list(fileset, purge_unused=True): def make_dependency_sorted_list(fileset, purge_unused=True):
# CYCLE_THRESHOLD = 30 """Sort files in order of dependency.
# ret = list(fileset) Files with no dependencies first.
# cur_idx = 0 All files that another depends on will be earlier in the list."""
# other_file_idx = cur_idx + 1 dependable = [f for f in fileset if isinstance(f, DepFile)]
# swapped = 0 non_dependable = [f for f in fileset if not isinstance(f, DepFile)]
# while True: dependable.sort(key=lambda f: f.file_path.lower()) # Not necessary, but will tend to group files more nicely in the output.
# if swapped >= CYCLE_THRESHOLD: dependable.sort(key=DepFile.get_dep_level)
# cur_idx += 1 return non_dependable + dependable
# if cur_idx >= len(ret):
# break def make_dependency_set(fileset, top_level_entity):
# if other_file_idx >= len(ret): """Create a set of all files required to build the named top_level_entity."""
# cur_idx += 1 from srcfile import SourceFileSet
# other_file_idx = cur_idx + 1 from dep_file import DepRelation
# continue assert isinstance(fileset, SourceFileSet)
# dep_file = ret[cur_idx] fset = fileset.filter(DepFile)
# other_file = ret[other_file_idx] # Find the file that provides the named top level entity
# if other_file in dep_file.depends_on: top_rel = DepRelation(top_level_entity,DepRelation.PROVIDE, DepRelation.ENTITY)
# ret[cur_idx], ret[other_file_idx] = ret[other_file_idx], ret[cur_idx] top_file = None
# other_file_idx = cur_idx + 1 for chk_file in fset:
# swapped += 1 for rel in chk_file.rels:
# else: if rel == top_rel:
# other_file_idx += 1 top_file = chk_file
# return ret break;
def compare_dep_files(f1, f2): if top_file:
if f2 in f1.depends_on: break
return 1 if top_file == None:
if f1 in f2.depends_on: logging.critical('Could not find a top level file that provides the top_module="%s". Continuing with the full file set.' % top_level_entity)
return -1 return fileset
return 0 # Collect only the files that the top level entity is dependant on, by walking the dependancy tree.
try:
filelist = list(fileset) dep_file_set = set()
dependable = [file for file in filelist if isinstance(file, DepFile)] file_set = set([top_file])
non_depednable = [file for file in filelist if not isinstance(file, DepFile)] while True:
ret = non_depednable chk_file = file_set.pop()
dependable_sorted = sorted(dependable, cmp=compare_dep_files) dep_file_set.add(chk_file)
ret.extend(dependable_sorted) file_set.update(chk_file.depends_on - dep_file_set)
return ret except KeyError:
# no files left
pass
logging.info("Found %d files as dependancies of %s." % (len(dep_file_set), top_level_entity))
#for dep_file in dep_file_set:
# logging.info("\t" + str(dep_file))
return dep_file_set
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment