Skip to content

Commit 7f71d14

Browse files
erikwaolofk
authored andcommitted
Encapsulate FuseSoC functionality from main.py in a Fusesoc class to make it easier to run FuseSoC from third-party python code
1 parent 247dbd0 commit 7f71d14

File tree

3 files changed

+277
-255
lines changed

3 files changed

+277
-255
lines changed

fusesoc/coremanager.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,17 @@ def eq_vln(this, that):
207207

208208

209209
class CoreManager:
210-
def __init__(
211-
self, config, resolve_env_vars=False, allow_additional_properties=False
212-
):
210+
def __init__(self, config, library_manager=None):
213211
self.config = config
214212
self.db = CoreDB()
215-
self._lm = LibraryManager(config.library_root)
216-
self.resolve_env_vars = resolve_env_vars
217-
self.allow_additional_properties = allow_additional_properties
218-
self.core2parser = Core2Parser(resolve_env_vars, allow_additional_properties)
213+
self._lm = (
214+
LibraryManager(config.library_root)
215+
if library_manager == None
216+
else library_manager
217+
)
218+
self.core2parser = Core2Parser(
219+
config.resolve_env_vars_early, config.allow_additional_properties
220+
)
219221

220222
def find_cores(self, library, ignored_dirs):
221223
found_cores = []

fusesoc/fusesoc.py

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Copyright FuseSoC contributors
2+
# Licensed under the 2-Clause BSD License, see LICENSE for details.
3+
# SPDX-License-Identifier: BSD-2-Clause
4+
5+
import logging
6+
import os
7+
from importlib import import_module
8+
9+
from fusesoc.config import Config
10+
from fusesoc.coremanager import CoreManager, DependencyError
11+
from fusesoc.edalizer import Edalizer
12+
from fusesoc.librarymanager import Library, LibraryManager
13+
from fusesoc.utils import Launcher, setup_logging, yaml_fread
14+
from fusesoc.vlnv import Vlnv
15+
16+
try:
17+
from edalize.edatool import get_edatool
18+
except ImportError:
19+
from edalize import get_edatool
20+
21+
logger = logging.getLogger(__name__)
22+
23+
24+
class Fusesoc:
25+
def __init__(self, config):
26+
self.config = config
27+
28+
self.lm = LibraryManager(config.library_root)
29+
self.cm = CoreManager(self.config, library_manager=self.lm)
30+
31+
self._register_libraries()
32+
33+
def _register_libraries(self):
34+
cores_root_libs = [Library(acr, acr) for acr in self.config.cores_root]
35+
# Add libraries from config file, env var and command-line
36+
for library in self.config.libraries + cores_root_libs:
37+
try:
38+
self.add_library(library)
39+
except (RuntimeError, OSError) as e:
40+
_s = "Failed to register library '{}'"
41+
logger.warning(_s.format(str(e)))
42+
43+
@staticmethod
44+
def init_logging(verbose, monochrome, log_file=None):
45+
"""
46+
Call before instantiation of fusesoc.Fusesoc or fusesoc.Config classes if logging is required.
47+
"""
48+
level = logging.DEBUG if verbose else logging.INFO
49+
50+
setup_logging(level, monochrome, log_file)
51+
52+
if verbose:
53+
logger.debug("Verbose output")
54+
else:
55+
logger.debug("Concise output")
56+
57+
if monochrome:
58+
logger.debug("Monochrome output")
59+
else:
60+
logger.debug("Colorful output")
61+
62+
def add_library(self, library):
63+
self.cm.add_library(library, self.config.ignored_dirs)
64+
65+
def get_library(self, library_name):
66+
return self.lm.get_library(library_name)
67+
68+
def update_libraries(self, library_names):
69+
self.lm.update(library_names)
70+
71+
def get_libraries(self):
72+
return self.lm.get_libraries()
73+
74+
def get_core(self, name):
75+
return self.cm.get_core(Vlnv(name))
76+
77+
def get_cores(self):
78+
return self.cm.get_cores()
79+
80+
def find_cores(self, library):
81+
return self.cm.find_cores(library, self.config.ignored_dirs)
82+
83+
def get_generators(self):
84+
return self.cm.get_generators()
85+
86+
def get_work_root(self, core, flags):
87+
flow = core.get_flow(flags)
88+
89+
target = flags["target"]
90+
91+
build_root = os.path.join(self.config.build_root, core.name.sanitized_name)
92+
93+
if flow:
94+
logger.debug(f"Using flow API (flow={flow})")
95+
work_root = os.path.join(build_root, target)
96+
else:
97+
logger.debug("flow not set. Falling back to tool API")
98+
if "tool" in flags:
99+
tool = flags["tool"]
100+
else:
101+
tool_error = "No flow or tool was supplied on command line or found in '{}' core description"
102+
raise RuntimeError(tool_error.format(core.name.sanitized_name))
103+
104+
work_root = os.path.join(build_root, f"{target}-{tool}")
105+
106+
return work_root
107+
108+
def get_backend(self, core, flags, backendargs=[]):
109+
110+
work_root = self.get_work_root(core, flags)
111+
112+
if not self.config.no_export:
113+
export_root = os.path.join(work_root, "src")
114+
logger.debug(f"Setting export_root to {export_root}")
115+
else:
116+
export_root = None
117+
118+
edam_file = os.path.join(work_root, core.name.sanitized_name + ".eda.yml")
119+
120+
flow = core.get_flow(flags)
121+
122+
backend_class = None
123+
if flow:
124+
try:
125+
backend_class = getattr(
126+
import_module(f"edalize.flows.{flow}"), flow.capitalize()
127+
)
128+
except ModuleNotFoundError:
129+
raise RuntimeError(f"Flow {flow!r} not found")
130+
except ImportError:
131+
raise RuntimeError(
132+
"Selected Edalize version does not support the flow API"
133+
)
134+
135+
else:
136+
try:
137+
backend_class = get_edatool(flags["tool"])
138+
except ImportError:
139+
raise RuntimeError(f"Backend {tool!r} not found")
140+
141+
edalizer = Edalizer(
142+
toplevel=core.name,
143+
flags=flags,
144+
core_manager=self.cm,
145+
work_root=work_root,
146+
export_root=export_root,
147+
system_name=self.config.system_name,
148+
resolve_env_vars=self.config.resolve_env_vars_early,
149+
)
150+
151+
try:
152+
edam = edalizer.run()
153+
edalizer.parse_args(backend_class, backendargs, edam)
154+
edalizer.export()
155+
except SyntaxError as e:
156+
raise RuntimeError(e.msg)
157+
except RuntimeError as e:
158+
raise RuntimeError("Setup failed : {}".format(str(e)))
159+
160+
if os.path.exists(edam_file):
161+
old_edam = yaml_fread(edam_file, self.config.resolve_env_vars_early)
162+
else:
163+
old_edam = None
164+
165+
if edam != old_edam:
166+
edalizer.to_yaml(edam_file)
167+
168+
return edam_file, backend_class(
169+
edam=edam, work_root=work_root, verbose=self.config.verbose
170+
)

0 commit comments

Comments
 (0)