[syn] Print detailed messages to .md if publication is disabled

Signed-off-by: Michael Schaffner <msf@google.com>
diff --git a/util/dvsim/FlowCfg.py b/util/dvsim/FlowCfg.py
index 36ac65c..d6e872d 100644
--- a/util/dvsim/FlowCfg.py
+++ b/util/dvsim/FlowCfg.py
@@ -13,7 +13,7 @@
 import hjson
 
 from Deploy import Deploy
-from utils import VERBOSE, md_results_to_html, parse_hjson, subst_wildcards
+from utils import VERBOSE, md_results_to_html, parse_hjson, print_msg_list, subst_wildcards
 
 
 # Interface class for extensions.
diff --git a/util/dvsim/LintCfg.py b/util/dvsim/LintCfg.py
index 773f534..13f9f2b 100644
--- a/util/dvsim/LintCfg.py
+++ b/util/dvsim/LintCfg.py
@@ -12,20 +12,7 @@
 from tabulate import tabulate
 
 from OneShotCfg import OneShotCfg
-from utils import subst_wildcards
-
-
-# helper function for printing messages
-def _print_msg_list(msg_list_name, msg_list):
-    md_results = ""
-    if msg_list:
-        md_results += "### %s\n" % msg_list_name
-        md_results += "```\n"
-        for msg in msg_list:
-            md_results += msg + "\n\n"
-        md_results += "```\n"
-    return md_results
-
+from utils import print_msg_list, subst_wildcards
 
 class LintCfg(OneShotCfg):
     """Derivative class for linting purposes.
@@ -185,22 +172,22 @@
             self.result_summary["lint_errors"] += self.result["lint_errors"]
 
             # Append detailed messages if they exist
-            if sum([
-                    len(self.result["warnings"]),
-                    len(self.result["errors"]),
-                    len(self.result["lint_warnings"]),
-                    len(self.result["lint_errors"])
-            ]):
-                fail_msgs += "\n## Errors and Warnings for Build Mode `'" + mode.name + "'`\n"
-                fail_msgs += _print_msg_list("Tool Errors",
-                                             self.result["errors"])
-                fail_msgs += _print_msg_list("Tool Warnings",
-                                             self.result["warnings"])
-                fail_msgs += _print_msg_list("Lint Errors",
-                                             self.result["lint_errors"])
-                fail_msgs += _print_msg_list("Lint Warnings",
-                                             self.result["lint_warnings"])
-                # fail_msgs += _print_msg_list("Lint Infos", results["lint_infos"])
+            hdr_key_pairs = [("Tool Warnings", "warnings"),
+                             ("Tool Errors", "errors"),
+                             ("Lint Warnings", "lint_warnings"),
+                             ("Lint Errors", "lint_errors")]
+
+            has_msg = False
+            for _, key in hdr_key_pairs:
+                if key in self.result:
+                    has_msg = True
+                    break
+
+            if has_msg:
+                results_str += "\n### Errors and Warnings for Build Mode `'" + mode.name + "'`\n"
+                for hdr, key in hdr_key_pairs:
+                    msgs = self.result.get(key)
+                    results_str += print_msg_list("#### " + hdr, msgs, self.max_msg_count)
 
         if len(table) > 1:
             self.results_md = results_str + tabulate(
diff --git a/util/dvsim/OneShotCfg.py b/util/dvsim/OneShotCfg.py
index 67677d5..6ff46b4 100644
--- a/util/dvsim/OneShotCfg.py
+++ b/util/dvsim/OneShotCfg.py
@@ -58,6 +58,7 @@
         self.build_modes = []
         self.run_modes = []
         self.regressions = []
+        self.max_msg_count = -1
 
         # Flow results
         self.result = OrderedDict()
diff --git a/util/dvsim/SynCfg.py b/util/dvsim/SynCfg.py
index e3acd62..1cddae3 100644
--- a/util/dvsim/SynCfg.py
+++ b/util/dvsim/SynCfg.py
@@ -12,7 +12,7 @@
 from tabulate import tabulate
 
 from OneShotCfg import OneShotCfg
-from utils import subst_wildcards
+from utils import print_msg_list, subst_wildcards
 
 
 class SynCfg(OneShotCfg):
@@ -343,6 +343,29 @@
             else:
                 results_str += "No power report found\n\n"
 
+            # Append detailed messages if they exist
+            # Note that these messages are omitted in publication mode
+            hdr_key_pairs = [("Flow Warnings", "flow_warnings"),
+                             ("Flow Errors", "flow_errors"),
+                             ("Analyze Warnings", "analyze_warnings"),
+                             ("Analyze Errors", "analyze_errors"),
+                             ("Elab Warnings", "elab_warnings"),
+                             ("Elab Errors", "elab_errors"),
+                             ("Compile Warnings", "compile_warnings"),
+                             ("Compile Errors", "compile_errors")]
+
+            has_msg = False
+            for _, key in hdr_key_pairs:
+                if key in self.result['messages']:
+                    has_msg = True
+                    break
+
+            if has_msg and not self.args.publish:
+                results_str += "\n### Errors and Warnings for Build Mode `'" + mode.name + "'`\n"
+                for hdr, key in hdr_key_pairs:
+                    msgs = self.result['messages'].get(key)
+                    results_str += print_msg_list("#### " + hdr, msgs, self.max_msg_count)
+
             # TODO: add support for pie / bar charts for area splits and
             # QoR history
 
diff --git a/util/dvsim/utils.py b/util/dvsim/utils.py
index 46e655f..fc9df52 100644
--- a/util/dvsim/utils.py
+++ b/util/dvsim/utils.py
@@ -350,3 +350,30 @@
         for item in subst_list:
             text = text.replace(item, subst_list[item])
     return text
+
+
+def print_msg_list(msg_list_title, msg_list, max_msg_count=-1):
+    '''This function prints a list of messages to Markdown.
+
+    The argument msg_list_title contains a string for the list title, whereas
+    the msg_list argument contains the actual list of message strings.
+    max_msg_count limits the number of messages to be printed (set to negative
+    number to print all messages).
+
+    Example:
+
+    print_msg_list("### Tool Warnings", ["Message A", "Message B"], 10)
+    '''
+    md_results = ""
+    if msg_list:
+        md_results += msg_list_title
+        md_results += "```\n"
+        for k, msg in enumerate(msg_list):
+            if k <= max_msg_count or max_msg_count < 0:
+                md_results += msg + "\n\n"
+            else:
+                md_results += "Note: %d more messages have been suppressed (max_msg_count = %d) \n\n" % (
+                    len(msg_list) - max_msg_count, max_msg_count)
+                break
+        md_results += "```\n"
+    return md_results