Skip to content

Commit

Permalink
coremanager: Pick preferred cores for virtual VLNVs
Browse files Browse the repository at this point in the history
Add "conflicts" constraints for each core implementing virtual VLNVs, so
no two cores implementing the same virtual VLNV may be selected
simultaneously.

This change should prevent more than a single implementing core from
being selected as the implementation for a virtual VLNV, and when there
is an explicit dependency in the tree, that one should be selected.

Signed-off-by: Alexander Williams <awill@opentitan.org>
  • Loading branch information
a-will authored and GregAC committed Jan 24, 2024
1 parent e20b928 commit a8fb3df
Showing 1 changed file with 35 additions and 0 deletions.
35 changes: 35 additions & 0 deletions fusesoc/coremanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,35 @@ def _hash_flags_dict(self, flags):
def solve(self, top_core, flags):
return self._solve(top_core, flags)

def _get_conflict_map(self):
"""Return a map of cores to their conflicts
Only one core that implements a virtual VLNV may be selected in a
dependency tree. For each core that implements a virtual VLNV, create a
set representing all other cores that implement one of the same virtual
VLNVs. In the resulting package definitions, these must get "conflicts"
constraints.
"""
conflict_map = {}
virtual_map = {}
for core_data in self._cores.values():
core = core_data["core"]
_virtuals = core.get_virtuals()
for virtual in _virtuals:
for simple in virtual.simpleVLNVs():
virtual_pkg = self._package_name(simple)
# FIXME: The real package should include version info
real_pkg = self._package_name(core.name)
virtual_set = virtual_map.setdefault(virtual_pkg, set())
virtual_set.add(real_pkg)
for virtual_pkg, virtual_set in virtual_map.items():
for real_pkg in virtual_set:
conflict_set = conflict_map.setdefault(real_pkg, set())
conflict_set |= virtual_set
for real_pkg, conflict_set in conflict_map.items():
conflict_set.remove(real_pkg)
return conflict_map

def _solve(self, top_core, flags={}, only_matching_vlnv=False):
def eq_vln(this, that):
return (
Expand All @@ -130,6 +159,8 @@ def eq_vln(this, that):
repo = Repository()
_flags = flags.copy()
cores = [x["core"] for x in self._cores.values()]
conflict_map = self._get_conflict_map()

for core in cores:
if only_matching_vlnv:
if not any(
Expand All @@ -151,6 +182,10 @@ def eq_vln(this, that):
if _virtuals:
_s = "; provides ( {} )"
package_str += _s.format(self._parse_virtual(_virtuals))
conflict_set = conflict_map.get(self._package_name(core.name), set())
if len(conflict_set) > 0:
_s = "; conflicts ( {} )"
package_str += _s.format(", ".join(list(conflict_set)))

# Add dependencies only if we want to build the whole dependency
# tree.
Expand Down

0 comments on commit a8fb3df

Please sign in to comment.