|  | # Copyright lowRISC contributors. | 
|  | # Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | # SPDX-License-Identifier: Apache-2.0 | 
|  | r""" | 
|  | Class describing a one-shot build configuration object | 
|  | """ | 
|  |  | 
|  | import logging as log | 
|  | import os | 
|  | import sys | 
|  | from collections import OrderedDict | 
|  |  | 
|  | from Deploy import CompileOneShot | 
|  | from FlowCfg import FlowCfg | 
|  | from Modes import BuildModes, Modes | 
|  | from utils import find_and_substitute_wildcards | 
|  |  | 
|  |  | 
|  | class OneShotCfg(FlowCfg): | 
|  | """Simple one-shot build flow for non-simulation targets like | 
|  | linting, synthesis and FPV. | 
|  | """ | 
|  | def __init__(self, flow_cfg_file, proj_root, args): | 
|  | super().__init__(flow_cfg_file, proj_root, args) | 
|  |  | 
|  | assert args.tool is not None | 
|  |  | 
|  | # Options set from command line | 
|  | self.tool = args.tool | 
|  | self.verbose = args.verbose | 
|  | self.flist_gen_cmd = "" | 
|  | self.flist_gen_opts = [] | 
|  | self.sv_flist_gen_dir = "" | 
|  | self.flist_file = "" | 
|  | self.build_cmd = "" | 
|  | self.build_opts = [] | 
|  | self.build_log = "" | 
|  | self.report_cmd = "" | 
|  | self.report_opts = [] | 
|  | self.build_opts.extend(args.build_opts) | 
|  | self.build_unique = args.build_unique | 
|  | self.build_only = args.build_only | 
|  |  | 
|  | # Options built from cfg_file files | 
|  | self.project = "" | 
|  | self.flow = "" | 
|  | self.flow_makefile = "" | 
|  | self.scratch_path = "" | 
|  | self.build_dir = "" | 
|  | self.run_dir = "" | 
|  | self.sw_build_dir = "" | 
|  | self.pass_patterns = [] | 
|  | self.fail_patterns = [] | 
|  | self.name = "" | 
|  | self.dut = "" | 
|  | self.fusesoc_core = "" | 
|  | self.ral_spec = "" | 
|  | self.build_modes = [] | 
|  | self.run_modes = [] | 
|  | self.regressions = [] | 
|  | self.max_msg_count = -1 | 
|  |  | 
|  | # Flow results | 
|  | self.result = OrderedDict() | 
|  | self.result_summary = OrderedDict() | 
|  |  | 
|  | self.dry_run = args.dry_run | 
|  |  | 
|  | # Not needed for this build | 
|  | self.verbosity = "" | 
|  | self.en_build_modes = [] | 
|  |  | 
|  | # Generated data structures | 
|  | self.links = {} | 
|  | self.build_list = [] | 
|  | self.deploy = [] | 
|  | self.cov = args.cov | 
|  | # Parse the cfg_file file tree | 
|  | self.parse_flow_cfg(flow_cfg_file) | 
|  | self._post_parse_flow_cfg() | 
|  |  | 
|  | # If build_unique is set, then add current timestamp to uniquify it | 
|  | if self.build_unique: | 
|  | self.build_dir += "_" + self.timestamp | 
|  |  | 
|  | # Process overrides before substituting the wildcards. | 
|  | self._process_overrides() | 
|  |  | 
|  | # Make substitutions, while ignoring the following wildcards | 
|  | # TODO: Find a way to set these in sim cfg instead | 
|  | ignored_wildcards = ["build_mode", "index", "test"] | 
|  | self.__dict__ = find_and_substitute_wildcards(self.__dict__, | 
|  | self.__dict__, | 
|  | ignored_wildcards) | 
|  |  | 
|  | # Stuff below only pertains to individual cfg (not master cfg). | 
|  | if not self.is_master_cfg: | 
|  | # Print info | 
|  | log.info("[scratch_dir]: [%s]: [%s]", self.name, self.scratch_path) | 
|  |  | 
|  | # Set directories with links for ease of debug / triage. | 
|  | self.links = { | 
|  | "D": self.scratch_path + "/" + "dispatched", | 
|  | "P": self.scratch_path + "/" + "passed", | 
|  | "F": self.scratch_path + "/" + "failed", | 
|  | "K": self.scratch_path + "/" + "killed" | 
|  | } | 
|  |  | 
|  | # Use the default build mode for tests that do not specify it | 
|  | if not hasattr(self, "build_mode"): | 
|  | setattr(self, "build_mode", "default") | 
|  |  | 
|  | self._process_exports() | 
|  |  | 
|  | # Create objects from raw dicts - build_modes, sim_modes, run_modes, | 
|  | # tests and regressions, only if not a master cfg obj | 
|  | self._create_objects() | 
|  |  | 
|  | # Post init checks | 
|  | self.__post_init__() | 
|  |  | 
|  | def __post_init__(self): | 
|  | # Run some post init checks | 
|  | super().__post_init__() | 
|  |  | 
|  | # Purge the output directories. This operates on self. | 
|  | def _purge(self): | 
|  | if self.scratch_path: | 
|  | try: | 
|  | log.info("Purging scratch path %s", self.scratch_path) | 
|  | os.system("/bin/rm -rf " + self.scratch_path) | 
|  | except IOError: | 
|  | log.error('Failed to purge scratch directory %s', | 
|  | self.scratch_path) | 
|  |  | 
|  | def _create_objects(self): | 
|  | # Create build and run modes objects | 
|  | build_modes = Modes.create_modes(BuildModes, | 
|  | getattr(self, "build_modes")) | 
|  | setattr(self, "build_modes", build_modes) | 
|  |  | 
|  | # All defined build modes are being built, h | 
|  | # ence extend all with the global opts. | 
|  | for build_mode in build_modes: | 
|  | build_mode.build_opts.extend(self.build_opts) | 
|  |  | 
|  | def _print_list(self): | 
|  | for list_item in self.list_items: | 
|  | log.info("---- List of %s in %s ----", list_item, self.name) | 
|  | if hasattr(self, list_item): | 
|  | items = getattr(self, list_item) | 
|  | for item in items: | 
|  | log.info(item) | 
|  | else: | 
|  | log.error("Item %s does not exist!", list_item) | 
|  |  | 
|  | def _create_dirs(self): | 
|  | '''Create initial set of directories | 
|  | ''' | 
|  | # Invoking system calls has a performance penalty. | 
|  | # Construct a single command line chained with '&&' to invoke | 
|  | # the system call only once, rather than multiple times. | 
|  | create_link_dirs_cmd = "" | 
|  | for link in self.links.keys(): | 
|  | create_link_dirs_cmd += "/bin/rm -rf " + self.links[link] + " && " | 
|  | create_link_dirs_cmd += "mkdir -p " + self.links[link] + " && " | 
|  | create_link_dirs_cmd += " true" | 
|  |  | 
|  | try: | 
|  | os.system(create_link_dirs_cmd) | 
|  | except IOError: | 
|  | log.error("Error running when running the cmd \"%s\"", | 
|  | create_link_dirs_cmd) | 
|  | sys.exit(1) | 
|  |  | 
|  | def _create_deploy_objects(self): | 
|  | '''Create deploy objects from build modes | 
|  | ''' | 
|  | builds = [] | 
|  | build_map = {} | 
|  | for build in self.build_modes: | 
|  | item = CompileOneShot(build, self) | 
|  | builds.append(item) | 
|  | build_map[build] = item | 
|  |  | 
|  | self.builds = builds | 
|  | self.deploy = builds | 
|  |  | 
|  | # Create initial set of directories before kicking off the regression. | 
|  | self._create_dirs() |