[dvsim] Synthesis target integration

This adds the following features to dvsim:
- SynCfg for synthesis targets
- Dashboard for single synthesis runs (summaries from master configs are
not yet supported)
- Configuration and run / parsing scripts for wire-load-model-based
synthesis flow in DC

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/util/dvsim/utils.py b/util/dvsim/utils.py
index e42c2a6..2d734be 100644
--- a/util/dvsim/utils.py
+++ b/util/dvsim/utils.py
@@ -206,17 +206,45 @@
 
 
 def htmc_color_pc_cells(text):
-    '''This function finds cells in a html table that contains a "%" sign. It then
-    uses the number in front if the % sign to color the cell based on the value
-    from a shade from red to green. These color styles are encoded in ./style.css
-    which is assumed to be accessible by the final webpage.
+    '''This function finds cells in a html table that contain numerical values
+    (and a few known strings) followed by a single space and an identifier.
+    Depending on the identifier, it shades the cell in a specific way. A set of
+    12 color palettes for setting those shades are encoded in ./style.css.
+    These are 'cna' (grey), 'c0' (red), 'c1' ... 'c10' (green). The shade 'cna'
+    is used for items that are maked as 'not applicable'. The shades 'c1' to
+    'c9' form a gradient from red to lime-green to indicate 'levels of
+    completeness'. 'cna' is used for greying out a box for 'not applicable'
+    items, 'c0' is for items that are considered risky (or not yet started) and
+    'c10' for items that have completed successfully, or that are
+    'in good standing'.
 
-    This function is now augmented to also take "E" or "W" as identifiers along
-    with "%". For example, '10 W' is indicative of 10 warnings, and will be color
-    coded with yellow. Likewise, "7 E" indicates 7 errors and will be color coded
-    with red. A value of 0 in both cases will be color coded with green.
+    These are the supported identifiers: %, %u, G, B, E, W, EN, WN.
+    The shading behavior for these is described below.
 
-    Note that a space between the value and the indicators (%, E, W) is mandatory.
+    %:  Coloured percentage, where the number in front of the '%' sign is mapped
+        to a color for the cell ranging from red ('c0') to green ('c10').
+    %u: Uncoloured percentage, where no markup is applied and '%u' is replaced
+        with '%' in the output.
+    G:  This stands for 'Good' and results in a green cell.
+    B:  This stands for 'Bad' and results in a red cell.
+    E:  This stands for 'Errors' and the cell is colored with red if the number
+        in front of the indicator is larger than 0. Otherwise the cell is
+        colored with green.
+    W:  This stands for 'Warnings' and the cell is colored with yellow ('c6')
+        if the number in front of the indicator is larger than 0. Otherwise
+        the cell is colored with green.
+    EN: This stands for 'Errors Negative', which behaves the same as 'E' except
+        that the cell is colored red if the number in front of the indicator is
+        negative.
+    WN: This stands for 'Warnings Negative', which behaves the same as 'W'
+        except that the cell is colored yellow if the number in front of the
+        indicator is negative.
+
+    N/A items can have any of the following indicators and need not be
+    preceeded with a numerical value:
+
+    '--', 'NA', 'N.A.', 'N.A', 'N/A', 'na', 'n.a.', 'n.a', 'n/a'
+
     '''
 
     # Replace <td> with <td class="color-class"> based on the fp
@@ -234,10 +262,10 @@
     na_list_patterns = '|'.join(na_list)
 
     # List of floating point patterns: '0', '0.0' & '.0'
-    fp_patterns = "\d+|\d+\.\d+|\.\d+"
+    fp_patterns = "[\+\-]?\d+\.?\d*"
 
     patterns = fp_patterns + '|' + na_list_patterns
-    indicators = "%|E|W"
+    indicators = "%|%u|G|B|E|W|EN|WN"
     match = re.findall(
         r"(<td.*>\s*(" + patterns + ")\s+(" + indicators + ")\s*</td>)", text)
     if len(match) > 0:
@@ -261,8 +289,8 @@
                     log.error("Percentage item \"%s\" in cell \"%s\" is not an " + \
                               "integer or a floating point number", fp_num, cell)
                     continue
+                # Percentage, colored.
                 if indicator == "%":
-                    # Item is a percentage.
                     if fp >= 0.0 and fp < 10.0: subst = color_cell(cell, "c0")
                     elif fp >= 10.0 and fp < 20.0:
                         subst = color_cell(cell, "c1")
@@ -284,15 +312,33 @@
                         subst = color_cell(cell, "c9")
                     elif fp >= 100.0:
                         subst = color_cell(cell, "c10")
-                else:
-                    # Item is a error or a warning num.
-                    # Use "c6" (yellow) for warnings and "c0" (red) for errors.
-                    if fp == 0:
+                # Percentage, uncolored.
+                elif indicator == "%u":
+                    subst = cell.replace("%u", "%")
+                # Good: green
+                elif indicator == "G":
+                    subst = color_cell(cell, "c10", indicator)
+                # Bad: red
+                elif indicator == "B":
+                    subst = color_cell(cell, "c0", indicator)
+                # Bad if positive: red for errors, yellow for warnings,
+                # otherwise green.
+                elif indicator in ["E", "W"]:
+                    if fp <= 0:
                         subst = color_cell(cell, "c10", indicator)
                     elif indicator == "W":
                         subst = color_cell(cell, "c6", indicator)
                     elif indicator == "E":
                         subst = color_cell(cell, "c0", indicator)
+                # Bad if negative: red for errors, yellow for warnings,
+                # otherwise green.
+                elif indicator in ["EN", "WN"]:
+                    if fp >= 0:
+                        subst = color_cell(cell, "c10", indicator)
+                    elif indicator == "WN":
+                        subst = color_cell(cell, "c6", indicator)
+                    elif indicator == "EN":
+                        subst = color_cell(cell, "c0", indicator)
             subst_list[cell] = subst
         for item in subst_list:
             text = text.replace(item, subst_list[item])