[syn] Carry over synthesis flow updates from bronze

This carries over recent updates to the synthesis flow on bronze and fixes
a couple of syntax issues that break several tools (DC, Verilator).

Signed-off-by: Michael Schaffner <msf@google.com>
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
index 4204b13..eacd507 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
@@ -320,6 +320,12 @@
   // Actual connection to flash phy
   ////////////////////////
 
+  wire [3:0] flash_test_mode_a;
+  wire flash_test_voltage_h;
+
+  assign flash_test_mode_a = '0;
+  assign flash_test_voltage_h = '0;
+
   // The actual flash macro wrapper
   // The size of a page is fixed.  However, depending on the sizing of the word,
   // the number of words within a page will change.
@@ -341,8 +347,18 @@
     .prog_data_i(prog_data),
     .ack_o(ack),
     .rd_data_o(flash_rdata),
-    .init_busy_o // TBD this needs to be looked at later. What init do we need to do,
-                 // and where does it make the most sense?
+    .init_busy_o, // TBD this needs to be looked at later. What init do we need to do,
+                  // and where does it make the most sense?
+    .tck_i('0),
+    .tdi_i('0),
+    .tms_i('0),
+    .tdo_o(),
+    .scanmode_i('0),
+    .scan_reset_ni('0),
+    .flash_power_ready_hi('0),
+    .flash_power_down_hi('0),
+    .flash_test_mode_ai(flash_test_mode_a),
+    .flash_test_voltage_hi(flash_test_voltage_h)
   );
 
   /////////////////////////////////
diff --git a/hw/ip/prim/rtl/prim_dom_and_2share.sv b/hw/ip/prim/rtl/prim_dom_and_2share.sv
index 17c0e5a..391bc2f 100644
--- a/hw/ip/prim/rtl/prim_dom_and_2share.sv
+++ b/hw/ip/prim/rtl/prim_dom_and_2share.sv
@@ -44,7 +44,10 @@
 
   logic [DW-1:0] t0_d, t0_q, t1_d, t1_q;
   logic [DW-1:0] t_a0b1, t_a1b0, t_a0b0, t_a1b1;
-  //synopsys keep_signal_name "t_a0b1 t_a1b0 t_a0b0 t_a1b1"
+  //synopsys keep_signal_name t_a0b1
+  //synopsys keep_signal_name t_a1b0
+  //synopsys keep_signal_name t_a0b0
+  //synopsys keep_signal_name t_a1b1
 
   // Preserve the logic sequence for XOR not to preceed the AND
   assign t_a0b1 = a0_i & b1_i;
diff --git a/hw/ip/prim_generic/rtl/prim_generic_flash.sv b/hw/ip/prim_generic/rtl/prim_generic_flash.sv
index 1bfd9a3..29fbabc 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_flash.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_flash.sv
@@ -28,7 +28,17 @@
   input [DataWidth-1:0]              prog_data_i,
   output logic                       ack_o,
   output logic [DataWidth-1:0]       rd_data_o,
-  output logic                       init_busy_o
+  output logic                       init_busy_o,
+  input                              tck_i,
+  input                              tdi_i,
+  input                              tms_i,
+  output logic                       tdo_o,
+  input                              scanmode_i,
+  input                              scan_reset_ni,
+  input                              flash_power_ready_hi,
+  input                              flash_power_down_hi,
+  inout [3:0]                        flash_test_mode_ai,
+  inout                              flash_test_voltage_hi
 );
 
   // Emulated flash macro values
@@ -315,4 +325,7 @@
 
   assign rd_data_o = held_part == flash_ctrl_pkg::FlashPartData ? rd_data_main : rd_data_info;
 
+  // hard-wire assignment for now
+  assign tdo_o = 1'b0;
+
 endmodule // prim_generic_flash
diff --git a/hw/syn/data/dc.hjson b/hw/syn/data/dc.hjson
index 3dec810..7f242fa 100644
--- a/hw/syn/data/dc.hjson
+++ b/hw/syn/data/dc.hjson
@@ -8,7 +8,8 @@
               "{proj_root}/hw/foundry/syn/{tool}/lib-setup.tcl"
               "{proj_root}/hw/foundry/syn/{tool}/ram-macros-setup.tcl"
               "{proj_root}/hw/syn/tools/{tool}/run-syn.tcl"
-              "{sdc_path}/{sdc_file}"]
+              "{sdc_path}/{sdc_file}"
+              "{foundry_sdc_path}/{foundry_sdc_file}"]
 
   // Environment variables that are needed in the synthesis script
   exports: [{"DUT"       : "{dut}"},
@@ -21,7 +22,7 @@
   build_opts: ["-f run-syn.tcl"]
 
   // DC-specific results parsing script that is called after running synthesis
-  report_cmd: "{proj_root}/hw/syn/tools/{tool}/parse-syn-report.py "
+  report_cmd: "{proj_root}/hw/syn/tools/{tool}/parse-syn-report.py --depth {area_depth}"
   report_opts: ["--dut {dut}",
                 "--logpath {build_dir} ",
                 "--reppath {build_dir}/REPORTS/ ",
diff --git a/hw/syn/tools/dc/parse-syn-report.py b/hw/syn/tools/dc/parse-syn-report.py
index 4b53ff3..7d83ffb 100755
--- a/hw/syn/tools/dc/parse-syn-report.py
+++ b/hw/syn/tools/dc/parse-syn-report.py
@@ -55,7 +55,7 @@
     return (nums, errs)
 
 
-def _extract_messages(full_file, results, key):
+def _extract_messages(full_file, results, key, args):
     """
     This extracts error and warning messages from the sting buffer full_file.
     """
@@ -71,7 +71,7 @@
     return results
 
 
-def _extract_gate_equiv(full_file, results, key):
+def _extract_gate_equiv(full_file, results, key, args):
     """
     This reads out the unit gate-equivalent.
     """
@@ -93,7 +93,7 @@
         return abs(val - ref) / ref
 
 
-def _extract_area(full_file, results, key):
+def _extract_area(full_file, results, key, args):
     """
     This extracts detailed area information from the report.
     Area will be reported in gate equivalents.
@@ -114,6 +114,16 @@
 
     # aggregate one level of sub-modules
     pattern = r"^([\.0-9A-Za-z_\[\]]+){1}(?:(?:/[\.0-9A-Za-z_\[\]]+)*)"
+
+    if args.depth == 2:
+        pattern = r"^args.dut/([\.0-9A-Za-z_\[\]]+){1}" + \
+                  r"(?:(?:/[\.0-9A-Za-z_\[\]]+)*)"
+    elif args.depth > 2:
+        results['messages']['flow_warnings'] += [
+            "Warning: unsupported hierarchy depth="
+            "%d specified, defaulting to depth=1" % args.depth
+            ]
+
     for k in range(5):
         pattern += r"\s+(" + FP_NUMBER + r")"
     matches = re.findall(pattern, full_file, flags=re.MULTILINE)
@@ -167,7 +177,7 @@
     return results
 
 
-def _extract_clocks(full_file, results, key):
+def _extract_clocks(full_file, results, key, args):
     """
     Parse out the clocks and their period
     """
@@ -191,7 +201,7 @@
     return results
 
 
-def _extract_timing(full_file, results, key):
+def _extract_timing(full_file, results, key, args):
     """
     This extracts the TNS and WNS for all defined clocks.
     """
@@ -241,7 +251,7 @@
     return results
 
 
-def _extract_units(full_file, results, key):
+def _extract_units(full_file, results, key, args):
     """
     Get the SI units configuration of this run
     """
@@ -285,7 +295,7 @@
     return results
 
 
-def _extract_power(full_file, results, key):
+def _extract_power(full_file, results, key, args):
     """
     This extracts power estimates for the top module from the report.
     """
@@ -309,20 +319,20 @@
     return results
 
 
-def _parse_file(path, name, results, handler, key):
+def _parse_file(path, name, results, handler, key, args):
     """
     Attempts to open and aprse a given report file with the handler provided.
     """
     try:
         with Path(path).joinpath(name).open() as f:
             full_file = f.read()
-            results = handler(full_file, results, key)
+            results = handler(full_file, results, key, args)
     except IOError as err:
         results["messages"]["flow_errors"] += ["IOError: %s" % err]
     return results
 
 
-def get_results(logpath, reppath, dut):
+def get_results(args):
     """
     Parse report and corresponding logfiles and extract error, warning
     and info messages for each IP present in the result folder
@@ -371,34 +381,35 @@
         }
     }
 
-    results["top"] = dut
+    results["top"] = args.dut
 
     # flow messages
-    results = _parse_file(logpath, 'synthesis.log', results, _extract_messages,
-                          "flow")
+    results = _parse_file(args.logpath, 'synthesis.log', results, _extract_messages,
+                          "flow", args)
 
     # messages
     for rep_type in ["analyze", "elab", "compile"]:
-        results = _parse_file(reppath, '%s.rpt' % rep_type, results,
-                              _extract_messages, rep_type)
+        results = _parse_file(args.reppath, '%s.rpt' % rep_type, results,
+                              _extract_messages, rep_type, args)
 
     # get gate equivalents
-    results = _parse_file(reppath, 'gate_equiv.rpt', results,
-                          _extract_gate_equiv, "area")
+    results = _parse_file(args.reppath, 'gate_equiv.rpt', results,
+                          _extract_gate_equiv, "area", args)
     # area
-    results = _parse_file(reppath, 'area.rpt', results, _extract_area, "area")
+    results = _parse_file(args.reppath, 'area.rpt', results, _extract_area,
+                          "area", args)
     # clocks. this complements the timing report later below
-    results = _parse_file(reppath, 'clocks.rpt', results, _extract_clocks,
-                          "timing")
+    results = _parse_file(args.reppath, 'clocks.rpt', results, _extract_clocks,
+                          "timing", args)
     # timing
-    results = _parse_file(reppath, 'timing.rpt', results, _extract_timing,
-                          "timing")
+    results = _parse_file(args.reppath, 'timing.rpt', results, _extract_timing,
+                          "timing", args)
     # power
-    results = _parse_file(reppath, 'power.rpt', results, _extract_power,
-                          "power")
+    results = _parse_file(args.reppath, 'power.rpt', results, _extract_power,
+                          "power", args)
     # units
-    results = _parse_file(reppath, 'power.rpt', results, _extract_units,
-                          "units")
+    results = _parse_file(args.reppath, 'power.rpt', results, _extract_units,
+                          "units", args)
 
     return results
 
@@ -511,8 +522,13 @@
                         help="""Output directory for the 'results.hjson' file.
                         Defaults to './'""")
 
+    parser.add_argument('--depth',
+                        type=int,
+                        default=1,
+                        help="""Area Report with hierarchical depth""")
+
     args = parser.parse_args()
-    results = get_results(args.logpath, args.reppath, args.dut)
+    results = get_results(args)
 
     with Path(args.outdir).joinpath("results.hjson").open("w") as results_file:
         hjson.dump(results,
diff --git a/hw/top_earlgrey/syn/top_earlgrey_syn_cfg.hjson b/hw/top_earlgrey/syn/top_earlgrey_syn_cfg.hjson
index 33c880f..c930c89 100644
--- a/hw/top_earlgrey/syn/top_earlgrey_syn_cfg.hjson
+++ b/hw/top_earlgrey/syn/top_earlgrey_syn_cfg.hjson
@@ -11,10 +11,6 @@
   import_cfgs: [// Project wide common synthesis config file
                 "{proj_root}/hw/syn/data/common_syn_cfg.hjson"]
 
-  // Timing constraints for this module
-  sdc_path: "{proj_root}/hw/top_earlgrey/syn"
-  sdc_file: "constraints.sdc"
-
   // Overrides
   overrides: [
     {
@@ -23,5 +19,14 @@
     }
   ]
 
-  // TODO: add support for loading the constraints here
+  // Timing constraints for this module
+  sdc_path: "{proj_root}/hw/top_earlgrey/syn"
+  sdc_file: "constraints.sdc"
+
+  // Technology specific timing constraints for this module
+  foundry_sdc_path: "{proj_root}/hw/foundry/top_earlgrey/syn"
+  foundry_sdc_file: "foundry.constraints.sdc"
+
+  // Configuration for result parser script
+  area_depth: 1
  }