[dvsim] Fix for missing coverage
- The while loop in `Deploy.deploy()` method that sequences the deployed
processes had a bug that caused it to exit when there was more work to
be done. I reordered it so that it works correctly now. `cov_report`
should now get dispatched after `cov_merge`.
- This fixes #1792.
- Some minor fixes to the way things are displayed in stdout.
Signed-off-by: Srikrishna Iyer <sriyer@google.com>
diff --git a/util/dvsim/Deploy.py b/util/dvsim/Deploy.py
index aba91e8..065bfb4 100644
--- a/util/dvsim/Deploy.py
+++ b/util/dvsim/Deploy.py
@@ -311,7 +311,7 @@
@staticmethod
def deploy(items):
dispatched_items = []
- queued_items = items
+ queued_items = []
if Deploy.print_legend:
# Print legend once at the start of the run.
@@ -342,7 +342,7 @@
log.log(VERBOSE, "[%s]: [%s]: [dispatch]:\n%s",
get_etime(), target, item_names[target])
- def track_progress(status, print_status):
+ def track_progress(status, print_status_flag):
all_done = True
for target in status.keys():
if "target_done" in status[target].keys(): continue
@@ -361,7 +361,7 @@
target_done = True
all_done &= target_done
- if print_status:
+ if print_status_flag:
width = "0{}d".format(len(str(stats["T"])))
msg = "["
for s in stats.keys():
@@ -373,16 +373,43 @@
all_done = False
status = {}
+ print_status_flag = True
# Queue all items
+ queued_items.extend(items)
for item in queued_items:
if item.target not in status.keys():
status[item.target] = {}
status[item.target][item] = "Q"
while not all_done:
+ # Get status of dispatched items.
+ for item in dispatched_items:
+ if item.status == "D": item.get_status()
+ if item.status != status[item.target][item]:
+ print_status_flag = True
+ if item.status != "D":
+ if item.status != "P":
+ # Kill its sub items if item did not pass.
+ item.set_sub_status("K")
+ log.error("[%s]: [%s]: [status] [%s: %s]",
+ get_etime(), item.target,
+ item.identifier, item.status)
+ else:
+ log.log(VERBOSE, "[%s]: [%s]: [status] [%s: %s]",
+ get_etime(), item.target, item.identifier,
+ item.status)
+ # Queue items' sub-items if it is done.
+ queued_items.extend(item.sub)
+ for sub_item in item.sub:
+ if sub_item.target not in status.keys():
+ status[sub_item.target] = {}
+ status[sub_item.target][sub_item] = "Q"
+ status[item.target][item] = item.status
+
# Dispatch items from the queue as slots free up.
- if len(queued_items) != 0:
+ all_done = (len(queued_items) == 0)
+ if not all_done:
num_slots = Deploy.max_parallel - Deploy.dispatch_counter
if num_slots > 0:
if len(queued_items) > num_slots:
@@ -394,33 +421,15 @@
dispatched_items.extend(queued_items)
queued_items = []
- # Advance time by 1s.
- time.sleep(1)
- Deploy.num_secs += 1
- print_status = ((Deploy.num_secs % Deploy.print_interval) == 0)
-
- # Get status of dispatched items.
- for item in dispatched_items:
- if item.status == "D": item.get_status()
- if item.status != status[item.target][item]:
- print_status = True
- if item.status != "D":
- if item.status != "P":
- # Kill its sub items if item did not pass.
- item.set_sub_status("K")
- log.log(VERBOSE, "[%s]: [%s]: [status]\n [%s: %s]",
- get_etime(), item.target, item.identifier,
- item.status)
- # Queue items' sub-items if it is done.
- queued_items.extend(item.sub)
- for sub_item in item.sub:
- if sub_item.target not in status.keys():
- status[sub_item.target] = {}
- status[sub_item.target][sub_item] = "Q"
- status[item.target][item] = item.status
-
# Check if we are done and print the status periodically.
- all_done = track_progress(status, print_status)
+ all_done &= track_progress(status, print_status_flag)
+
+ # Advance time by 1s if there is more work to do.
+ if not all_done:
+ time.sleep(1)
+ Deploy.num_secs += 1
+ print_status_flag = ((Deploy.num_secs %
+ Deploy.print_interval) == 0)
class CompileSim(Deploy):
diff --git a/util/dvsim/FlowCfg.py b/util/dvsim/FlowCfg.py
index a001f7b..6e438f8 100644
--- a/util/dvsim/FlowCfg.py
+++ b/util/dvsim/FlowCfg.py
@@ -430,7 +430,7 @@
results = []
for item in self.cfgs:
result = item._gen_results()
- print(result)
+ log.info("[results]: [%s]:\n%s\n\n", item.name, result)
results.append(result)
self.errors_seen |= item.errors_seen
diff --git a/util/dvsim/LintCfg.py b/util/dvsim/LintCfg.py
index 670e5e3..4adfd1e 100644
--- a/util/dvsim/LintCfg.py
+++ b/util/dvsim/LintCfg.py
@@ -41,7 +41,6 @@
# Set the title for lint results.
self.results_title = self.name.upper() + " Lint Results"
-
@staticmethod
def create_instance(flow_cfg_file, proj_root, args):
'''Create a new instance of this class as with given parameters.
@@ -125,7 +124,6 @@
results_str += "### " + self.timestamp_long + "\n"
results_str += "### Lint Tool: " + self.tool.upper() + "\n\n"
-
header = [
"Build Mode", "Tool Warnings", "Tool Errors", "Lint Warnings",
"Lint Errors"
@@ -213,8 +211,8 @@
# Write results to the scratch area
self.results_file = self.scratch_path + "/results_" + self.timestamp + ".md"
- log.info("Detailed results are available at %s", self.results_file)
with open(self.results_file, 'w') as f:
f.write(self.results_md)
+ log.info("[results page]: [%s] [%s]", self.name, results_file)
return self.results_md
diff --git a/util/dvsim/OneShotCfg.py b/util/dvsim/OneShotCfg.py
index 10fff9a..cc78d8c 100644
--- a/util/dvsim/OneShotCfg.py
+++ b/util/dvsim/OneShotCfg.py
@@ -84,30 +84,31 @@
self.__dict__,
ignored_wildcards)
- # Print info
- log.info("Scratch path for %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
+ # 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__()
+ # Post init checks
+ self.__post_init__()
def __post_init__(self):
# Run some post init checks
diff --git a/util/dvsim/SimCfg.py b/util/dvsim/SimCfg.py
index ada0961..6cf16da 100644
--- a/util/dvsim/SimCfg.py
+++ b/util/dvsim/SimCfg.py
@@ -125,26 +125,27 @@
# Set the title for simulation results.
self.results_title = self.name.upper() + " Simulation Results"
- # Print info
- log.info("Scratch path for %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
+ # 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
# TODO: hack to prevent coverage collection if tool != vcs
if self.cov and self.tool != "vcs":
self.cov = False
@@ -514,12 +515,12 @@
# Write results to the scratch area
results_file = self.scratch_path + "/results_" + self.timestamp + ".md"
- log.info("Detailed results are available at %s", results_file)
f = open(results_file, 'w')
f.write(self.results_md)
f.close()
# Return only the tables
+ log.info("[results page]: [%s] [%s]", self.name, results_file)
return results_str
def gen_results_summary(self):
@@ -533,7 +534,7 @@
row = []
for title in item.results_summary:
row.append(item.results_summary[title])
- if len(row) == len(header): table.append(row)
+ if row != []: table.append(row)
self.results_summary_md = "## " + self.results_title + " (Summary)\n"
self.results_summary_md += "### " + self.timestamp_long + "\n"
self.results_summary_md += tabulate(table,