[syn] This adds a simple testsynthesis flow for DC

This adds a similar makefile based test synthesis flow for DC  analogous
to the AscentLint flow. It allows to run a simple wire-load-model-based
synthesis of individual IPs or the top-level.

Two example targets are provided within this PR, and they can be called
by stepping into `hw/syn` and running:
```
make ip-aes_syn
make systems-top_earlgrey_syn
```
Area, timing, power and link reports will be written to
`hw/syn/reports` once synthesis has completed.

Note that this is only a starting point and will soon be extended.

Also, this requires a technology setup scripts and the corresponding
technology wrapper primitives to be present under `hw/foundry/syn/dc`
and `hw/foundry/ip/prim_<tech id>/`

The integration into the dvsim dashboard (analogous to AscentLint) is in
the making and will follow in a subsequent PR (together with more
documentation).

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/aes/aes.core b/hw/ip/aes/aes.core
index 23083d7..cf9c36c 100644
--- a/hw/ip/aes/aes.core
+++ b/hw/ip/aes/aes.core
@@ -73,3 +73,13 @@
         verilator_options:
           - "-Wall"
 
+  syn:
+    <<: *default_target
+    # set default to DC once
+    # this option is available
+    # olofk/edalize#89
+    default_tool: icarus
+    parameters:
+      - SYNTHESIS=true
+
+
diff --git a/hw/syn/Makefile b/hw/syn/Makefile
new file mode 100644
index 0000000..4e2932b
--- /dev/null
+++ b/hw/syn/Makefile
@@ -0,0 +1,67 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Makefile with synthesis targets for OpenTitan
+
+CORE_ROOT ?= ../../
+REPORT_DIR ?= reports
+# this directory contains the library setup file (setup.tcl)
+LIB_SETUP_SCRIPT ?= `pwd`/../foundry/syn/dc/setup.tcl
+# sources for DC
+TOOL_SRCS   = ./tools/dc/start-dc.sh     \
+              ./tools/dc/run-syn.tcl     \
+              ./tools/dc/constraints.sdc
+
+IPS ?=  ip-aes                 \
+        systems-top_earlgrey
+#         ip-alert_handler       \
+#         ip-flash_ctrl          \
+#         ip-gpio                \
+#         ip-hmac                \
+#         ip-i2c                 \
+#         ip-nmi_gen             \
+#         ip-padctrl             \
+#         ip-padring             \
+#         ip-pinmux              \
+#         ip-rv_core_ibex        \
+#         ip-rv_dm               \
+#         ip-rv_plic_example     \
+#         ip-rv_timer            \
+#         ip-spi_device          \
+#         ip-uart                \
+#         ip-usbdev              \
+#         ip-usb_fs_nb_pe        \
+#         ip-usbuart             \
+#         tlul-socket_1n         \
+#         tlul-socket_m1         \
+#         tlul-adapter_reg       \
+#         tlul-adapter_sram      \
+#         tlul-sram2tlul         \
+
+
+ips_syn  = $(addsuffix _syn, $(IPS))
+
+######################
+# synthesis targets #
+######################
+
+all: clean
+	@echo Discovered synth targets:
+	@echo -e "\n $(patsubst %,%\\n,$(strip $(ips_syn)))"
+	$(MAKE) $(ips_lint)
+
+$(ips_syn):
+	mkdir -p ${REPORT_DIR}
+	fusesoc --cores-root ${CORE_ROOT} run --target=syn --tool=icarus --setup lowrisc:$(subst -,:,$(patsubst %_syn,%,$@))
+	cp ${TOOL_SRCS} build/lowrisc_*$(subst -,_,$(patsubst %_syn,%,$@))*/syn-icarus/
+	export TOP_ENTITY="$(patsubst ip-%,%,$(patsubst tlul-%,%,$(patsubst systems-%,%,$(patsubst %_syn,%,$@))))" && \
+	export LIB_SETUP_SCRIPT=${LIB_SETUP_SCRIPT} && \
+	cd build/lowrisc_*$(subst -,_,$(patsubst %_syn,%,$@))*/syn-icarus/ && ./start-dc.sh -f run-syn.tcl
+	cp build/lowrisc_*$(subst -,_,$(patsubst %_syn,%,$@))*/syn-icarus/REPORTS/*.rpt ${REPORT_DIR}/
+
+clean:
+	rm -rf build
+	rm -rf ${REPORT_DIR}/*
+
+.PHONY: all $(ips_syn) clean
diff --git a/hw/syn/tools/dc/constraints.sdc b/hw/syn/tools/dc/constraints.sdc
new file mode 100644
index 0000000..a3bc2d3
--- /dev/null
+++ b/hw/syn/tools/dc/constraints.sdc
@@ -0,0 +1,161 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Generic constraints file for simple testsynthesis flow
+# This held very simple for now and needs to be refined
+
+# note that we do not fix hold timing in this flow
+set SETUP_CLOCK_UNCERTAINTY 0.5
+
+# TODO: consider splitting this into per-IP .sdc files
+if {$TOP_ENTITY == "top_earlgrey"} {
+
+puts "Applying constraints for top level"
+
+# note: this does not account for clock insertion delay and
+# there are no pads instantiated in the netlist (yet)
+
+#####################
+# main clock        #
+#####################
+set MAIN_CLK_PIN clk_i
+set MAIN_RST_PIN rst_ni
+# 125 MHz
+set MAIN_TCK  8.0
+set_ideal_network ${MAIN_CLK_PIN}
+set_ideal_network ${MAIN_RST_PIN}
+
+create_clock ${MAIN_CLK_PIN} -period ${MAIN_TCK}
+set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY}  ${MAIN_CLK_PIN}
+
+set IN_DEL    5.5
+set OUT_DEL   5.5
+
+set_input_delay ${IN_DEL} [get_ports mio_in_i*]          -clock ${MAIN_CLK_PIN}
+set_input_delay ${IN_DEL} [get_ports scanmode_i]         -clock ${MAIN_CLK_PIN}
+set_input_delay ${IN_DEL} [get_ports dio_uart_rx_i]      -clock ${MAIN_CLK_PIN}
+
+set_output_delay ${OUT_DEL} [get_ports mio_out_o*]       -clock ${MAIN_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports mio_oe_o*]        -clock ${MAIN_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_uart_tx_o]    -clock ${MAIN_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_uart_tx_en_o] -clock ${MAIN_CLK_PIN}
+
+#####################
+# USB clock         #
+#####################
+set USB_CLK_PIN clk_usb_48mhz_i
+# 50MHz
+set USB_TCK 20.0
+set_ideal_network ${USB_CLK_PIN}
+
+create_clock ${USB_CLK_PIN} -period ${USB_TCK}
+set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} ${USB_CLK_PIN}
+
+set IN_DEL    17.0
+set OUT_DEL   17.0
+
+set_input_delay ${IN_DEL} [get_ports dio_usbdev_sense_i]       -clock ${USB_CLK_PIN}
+set_input_delay ${IN_DEL} [get_ports dio_usbdev_dp_i]          -clock ${USB_CLK_PIN}
+set_input_delay ${IN_DEL} [get_ports dio_usbdev_dn_i]          -clock ${USB_CLK_PIN}
+
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_pullup_o]    -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_pullup_en_o] -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_o]        -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_en_o]     -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_o]        -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_en_o]     -clock ${USB_CLK_PIN}
+
+#####################
+# JTAG clock        #
+#####################
+set JTAG_CLK_PIN jtag_tck_i
+set JTAG_RST_PIN jtag_trst_ni
+# 40MHz
+set JTAG_TCK 25.0
+set_ideal_network ${JTAG_CLK_PIN}
+set_ideal_network ${JTAG_RST_PIN}
+
+create_clock ${JTAG_CLK_PIN} -period ${JTAG_TCK}
+set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} ${JTAG_CLK_PIN}
+
+set IN_DEL    10.0
+set OUT_DEL   10.0
+
+set_input_delay ${IN_DEL} [get_ports jtag_tms_i]  -clock ${JTAG_CLK_PIN}
+set_input_delay ${IN_DEL} [get_ports jtag_td_i]   -clock ${JTAG_CLK_PIN}
+
+set_output_delay ${OUT_DEL} [get_ports jtag_td_o] -clock ${JTAG_CLK_PIN}
+
+#####################
+# SPI clock         #
+#####################
+set SPI_CLK_PIN dio_spi_device_sck_i
+# 62.5MHz
+set SPI_TCK 16.0
+set_ideal_network ${SPI_CLK_PIN}
+
+create_clock ${SPI_CLK_PIN} -period ${SPI_TCK}
+set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} ${SPI_CLK_PIN}
+
+set IN_DEL    6.0
+set OUT_DEL   6.0
+
+set_input_delay ${IN_DEL} [get_ports dio_spi_device_csb_i]       -clock ${SPI_CLK_PIN}
+set_input_delay ${IN_DEL} [get_ports dio_spi_device_mosi_i]      -clock ${SPI_CLK_PIN}
+
+set_output_delay ${OUT_DEL} [get_ports dio_spi_device_miso_o]    -clock ${SPI_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_spi_device_miso_en_o] -clock ${SPI_CLK_PIN}
+
+#####################
+# CDC               #
+#####################
+
+# this may need some refinement (and max delay / skew needs to be constrained)
+set_clock_groups -name group1 -async -group ${MAIN_CLK_PIN} \
+                                     -group ${JTAG_CLK_PIN} \
+                                     -group ${USB_CLK_PIN}  \
+                                     -group ${SPI_CLK_PIN}
+
+# loopback path can be considered to be a false path
+set_false_path -from dio_uart_rx_i -to dio_uart_tx_o
+
+} else {
+
+#####################
+# main clock        #
+#####################
+set MAIN_CLK_PIN clk_i
+set MAIN_RST_PIN rst_ni
+# set main clock to 125 MHz
+set MAIN_TCK  8.0
+set_ideal_network ${MAIN_CLK_PIN}
+set_ideal_network ${MAIN_RST_PIN}
+set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} ${MAIN_CLK_PIN}
+
+# other timing constraint in ns
+set IN_DEL    1.0
+set OUT_DEL   1.0
+set DELAY     ${MAIN_TCK}
+
+create_clock ${MAIN_CLK_PIN} -period ${MAIN_TCK}
+
+# in to out
+set_max_delay ${DELAY} -from [all_inputs] -to [all_outputs]
+# in to reg / reg to out
+set_input_delay ${IN_DEL} [remove_from_collection [all_inputs] {${MAIN_CLK_PIN}}] -clock ${MAIN_CLK_PIN}
+set_output_delay ${OUT_DEL}  [all_outputs] -clock ${MAIN_CLK_PIN}
+
+}
+
+#####################
+# Common            #
+#####################
+
+# attach load and drivers to IOs to get a more realistic estimate
+set_driving_cell  -no_design_rule -lib_cell ${driving_cell} -pin X [all_inputs]
+set_load [load_of ${load_lib}/${load_cell}/A] [all_outputs]
+
+# set a nonzero critical range to be able to spot the violating paths better
+# in the report
+set_critical_range 0.5 ${TOP_ENTITY}
diff --git a/hw/syn/tools/dc/run-syn.tcl b/hw/syn/tools/dc/run-syn.tcl
new file mode 100644
index 0000000..409bbfc
--- /dev/null
+++ b/hw/syn/tools/dc/run-syn.tcl
@@ -0,0 +1,146 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Simple tcl script for DC to do some wire-load-model-based test syntheses.
+
+#####################
+##  PREPARE FLOW   ##
+#####################
+
+# tool setup
+source [getenv "LIB_SETUP_SCRIPT"]
+
+# paths
+set WORKLIB  "WORK"
+set REPDIR   "REPORTS"
+set DDCDIR   "DDC"
+set VLOGDIR  "NETLISTS"
+
+exec mkdir -p ${REPDIR} ${DDCDIR} ${VLOGDIR} ${WORKLIB}
+
+# define work lib path
+define_design_lib WORK -path $WORKLIB
+
+#######################
+##  DESIGN SOURCES  ###
+#######################
+
+# just compile the "core" toplevel at the moment
+# might want to switch to top_earlgrey_asic later on (with pads)
+set TOP_ENTITY [getenv "TOP_ENTITY"]
+
+# read source list generated by fusesoc
+set fp [open [ls "*.scr"] r]
+set file_data [read $fp]
+close $fp
+set data [split $file_data "\n"]
+
+# this TECH_LIB_SEL selects the appropriate technology by defining
+# PRIM_DEFAULT_IMPL=prim_pkg::Impl<tech identifier>
+# TECH_LIB_SEL is set inside the library setup script
+set DEFINE "PRIM_DEFAULT_IMPL=${PRIM_DEFAULT_IMPL} "
+# go through fusesoc file list and separate +defines from actual source files
+set SRC {}
+foreach item $data {
+  if {[string range $item 0 7] == "+define+"}  {
+    set DEFINE "${DEFINE}[string range $item 8 end] "
+  } elseif {[string range $item 0 7] == "+incdir+"}  {
+    lappend search_path "[string range $item 8 end]"
+  } else {
+    lappend SRC $item
+  }
+}
+
+# additional parameters
+set PARAMS ""
+
+###########################
+##   ELABORATE DESIGN    ##
+###########################
+
+# delete previous designs.
+remove_design -designs
+sh rm -rf $WORKLIB/*
+
+analyze -define ${DEFINE} -format sv ${SRC}
+elaborate  ${TOP_ENTITY} -parameters ${PARAMS}
+link > "${REPDIR}/${TOP_ENTITY}_link.rpt"
+
+write_file -format ddc -hierarchy -output "${DDCDIR}/${TOP_ENTITY}_elab.ddc"
+write_file -format verilog -hierarchy -output "${DDCDIR}/${TOP_ENTITY}_elab.v"
+
+#############################
+##   CLOCK GATING SETUP    ##
+#############################
+
+# be more specific if defaults do not suffice
+# set_clock_gating_style -num_stages 1                   \
+#                        -positive_edge_logic integrated \
+#                        -control_point before           \
+#                        -control_signal scan_enable
+
+###########################
+##   APPLY CONSTRAINTS   ##
+###########################
+
+source constraints.sdc
+
+# If hold time should be fixed
+# set_fix_hold ${CLK_PIN}
+
+######################
+##    MAP DESIGN    ##
+######################
+
+# TODO: we may have to disable a couple of optimizations in order
+# to prevent the tool from optimizing away dummy logic or logic from blocks
+# that are only half-finished
+
+# preserve hierarchy for reports
+compile_ultra -gate_clock -scan -no_autoungroup
+
+#################
+##   REPORTS   ##
+#################
+
+report_timing      -nosplit -nworst 100 > "${REPDIR}/${TOP_ENTITY}_timing.rpt"
+report_timing      -nosplit -nworst 1000 -input -net -trans -cap > "${REPDIR}/${TOP_ENTITY}_timing_long.rpt"
+report_area  -hier -nosplit             > "${REPDIR}/${TOP_ENTITY}_area.rpt"
+report_power -hier -nosplit             > "${REPDIR}/${TOP_ENTITY}_power.rpt"
+report_constraints -all_violators       > "${REPDIR}/${TOP_ENTITY}_constraints.rpt"
+
+#################
+##   NETLIST   ##
+#################
+
+# change_names -rules verilog -hierarchy
+# define_name_rules fixbackslashes -allowed "A-Za-z0-9_" -first_restricted "\\" -remove_chars
+# change_names -rule fixbackslashes -h
+write_file -format ddc     -hierarchy -output "${DDCDIR}/${TOP_ENTITY}_mapped.ddc"
+write_file -format verilog -hierarchy -output "${VLOGDIR}/${TOP_ENTITY}_mapped.v"
+
+# ##############################
+# ##  INCREMENTAL FLATTENING  ##
+# ##############################
+
+# compile_ultra -inc
+
+# #################
+# ##   REPORTS   ##
+# #################
+
+# report_timing      -nosplit -nworst 100 > "${REPDIR}/${TOP_ENTITY}_flat_timing.rpt"
+# report_timing      -nosplit -nworst 1000 -input -net -trans -cap > "${REPDIR}/${TOP_ENTITY}_flat_timing_long.rpt"
+# report_area  -hier -nosplit             > "${REPDIR}/${TOP_ENTITY}_flat_area.rpt"
+# report_power -hier -nosplit             > "${REPDIR}/${TOP_ENTITY}_flat_power.rpt"
+# report_constraints -all_violators       > "${REPDIR}/${TOP_ENTITY}_flat_constraints.rpt"
+
+# #################
+# ##   NETLIST   ##
+# #################
+
+# write_file -format ddc     -hierarchy -output "${DDCDIR}/${TOP_ENTITY}_flat.ddc"
+# write_file -format verilog -hierarchy -output "${VLOGDIR}/${TOP_ENTITY}_flat.v"
+
+exit
diff --git a/hw/syn/tools/dc/start-dc.sh b/hw/syn/tools/dc/start-dc.sh
new file mode 100755
index 0000000..03520fa
--- /dev/null
+++ b/hw/syn/tools/dc/start-dc.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# this is needed for the terminal to respond correctly within DC
+TERM="dtterm" dc_shell-xg-t $@
diff --git a/hw/top_earlgrey/top_earlgrey.core b/hw/top_earlgrey/top_earlgrey.core
index 6d36122..664c511 100644
--- a/hw/top_earlgrey/top_earlgrey.core
+++ b/hw/top_earlgrey/top_earlgrey.core
@@ -96,3 +96,13 @@
         mode: lint-only
         verilator_options:
           - "-Wall"
+
+  syn:
+    <<: *default_target
+    # set default to DC once
+    # this option is available
+    # olofk/edalize#89
+    default_tool: icarus
+    parameters:
+      - SYNTHESIS=true
+    toplevel: top_earlgrey