#----------------------------------------------------------------------------
#   The confidential and proprietary information contained in this file may
#   only be used by a person authorised under and to the extent permitted
#   by a subsisting licensing agreement from Arm Limited or its affiliates.
#
#          (C) COPYRIGHT 2024 Arm Limited or its affiliates.
#              ALL RIGHTS RESERVED
#
#   This entire notice must be reproduced on all copies of this file
#   and copies of this file may only be made by a person if such person is
#   permitted to do so under the terms of a subsisting license agreement
#   from Arm Limited or its affiliates.
#
#    Release Information : $State$
#
#----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Function: Read the RTL, setup DFT and synthesise to generic gates
# -----------------------------------------------------------------------------
set step_name "syn_generic"
puts "ARM_INFO: Step syn_generic"
## MJ Metrics 04/12/23
push_snapshot_stack
# -----------------------------------------------------------------------------
# Source flow setup files and initialise the step
# -----------------------------------------------------------------------------
source $env(CONFIG_PATH)/technology.tcl
source $env(CONFIG_PATH)/design.tcl
source $env(CONFIG_PATH)/setup.tcl
#START_FLEX_INSERT_ANCHOR: genus pre db load config
################################################################################
# Genus attributes (design & library not required)
################################################################################

set_db source_verbose    true
set_db flow_verbose      false
set_db information_level 9


################################################################################
# ATTRIBUTES APPLIED BEFORE LOADING A LIBRARY OR DATABASE
################################################################################

# General attributes
#-------------------------------------------------------------------------------

set_multi_cpu_usage -local_cpu $env(LSB_MAX_NUM_PROCESSORS)

# Force timing and capacitance unit to be ns and pf
# It avoids discrepancy issue due to libraries having different units
# Need to be set before reading of libraries it also force sdc and reports units
set_db timing_time_unit 1ns
set_db timing_cap_unit  1pf

set_db super_thread_debug_directory           "./thread_debug_logs"

set_db wlec_set_cdn_synth_root                true
set_db error_on_lib_lef_pin_inconsistency     true

set_db write_vlog_empty_module_for_logic_abstract   false
set_db gen_module_prefix                            "arcadia_complex_"

## to enable output of mask statements in tracks etc
set_db def_output_version 5.8
# Design attributes  [get_db -category design]

set_db remove_assigns true

#-------------------------------------------------------------------------------
set_db design_process_node              5

# HDL attributes [get_db -category hdl]
#-------------------------------------------------------------------------------

set_db hdl_error_on_blackbox              true
set_db hdl_error_on_latch                 $design_vars(error_on_latch)
set_db hdl_error_on_logic_abstract        true
set_db hdl_error_on_negedge               true

set_db hdl_array_naming_style             %s_%d
set_db hdl_flatten_complex_port           true
set_db hdl_generate_index_style           %s_%d
set_db hdl_generate_separator             _
set_db hdl_record_naming_style            %s_%s_
set_db hdl_reg_naming_style               %s_reg%s
set_db hdl_resolve_instance_with_libcell  true
set_db hdl_use_cw_first                   true

# Alias the pins name of CDN_flop to be able to put a constraints on an un-mapped flop
set_db hdl_rename_cdn_flop_pins           {{clk CK} {d D}}

# Force synthesis to not assume any value on any unconnected pins
set_db hdl_unconnected_value              none

# Avoid merging flops: could avoid merging flop being duplicated only by user (timing reason mainly)...
set_db optimize_merge_flops                   false

#This attribute helps with detecting where combinational loops are
set_db print_ports_nets_preserved_for_cb  true

# Optimization attributes  [get_db -category netlist]
#-------------------------------------------------------------------------------
set_db syn_generic_effort                     high
set_db syn_map_effort                         high
set_db syn_opt_effort                         high
set_db use_multibit_cells                     true
set_db use_multibit_combo_cells               true
set_db multibit_cells_from_different_busses   false

set_db multibit_prefix_string                 "MBIT_"
set_db use_multibit_iso_cells                 true
set_db multibit_mapping_effort_level          high
set_db force_merge_seqs_into_multibit_cells   false
set_db force_merge_combos_into_multibit_cells false
set_db dft_shift_register_with_mbci           false
set_db use_multibit_seq_and_tristate_cells    true
set_db auto_ungroup                           none

# Disable register replication
set_db iopt_sequential_duplication            false

# Timing attributes  [get_db -category tim]
#-------------------------------------------------------------------------------
set_db time_recovery_arcs true

# Datapath attributes  [get_db -category dp]
#-------------------------------------------------------------------------------

# Leakage Power attributes  [get_db -category lp_opt lib_ui]
#-------------------------------------------------------------------------------
set_db lp_insert_clock_gating                 true
if { [get_db program_major_version] >= 21.10 } {
  set_db design_power_effort                    high
} else {
  set_db leakage_power_effort                   high
}

# DFT attributes  [get_db -category dft]
#-------------------------------------------------------------------------------
set_db dft_wait_for_license                               true

## Define the Test Clock Waveform Attributes to target ATPG speed of 200MHz
set_db dft_clock_waveform_divide_fall                     100
set_db dft_clock_waveform_divide_period                   100
set_db dft_clock_waveform_divide_rise                     90
set_db dft_clock_waveform_fall                            50
set_db dft_clock_waveform_period                          5000
set_db dft_clock_waveform_rise                            1
set_db dft_include_test_signal_outputs_in_abstract_model  false

# ensure scan flop input be only used for scan
## CCR 2463365	Ensure RAM scan segment having SI/SO in different power domains is included in power domain aware scan chain of inst PD
if {[regsub {\-.*} [get_db program_version] {}]  >= 21.11} {
  set_db dft_use_abstract_segment_instance_power_domain_for_scan_connection true
}
set_db use_scan_seqs_for_non_dft                          false

if {[regsub {\-.*} [get_db program_version] {}] >= 21.10} {
  # pick up instance power domain rather than pin power domain for memory scan connections. CCR 2649133
  set_db dft_use_abstract_segment_instance_power_domain_for_scan_connection true
}

# Physical attributes  [get_db -category phys]
#-------------------------------------------------------------------------------
# set_db scale_of_cap_per_unit_length           1.15
# set_db scale_of_res_per_unit_length           1.15
# Prevent merging unused bits into MBIT FFs/Combo cells,
# which will cause MBIT cell re-naming issue in INVS Multi-Bit
# optimization flow and CLP:ISO_MISSING_MATCHING_CELL errors
# on optimized input pins of Combo cells
set_db multibit_allow_unused_bits             false

#END_FLEX_INSERT_ANCHOR: genus pre db load config

puts "ARM_INFO: Set variables"

# Setup the number of CPUs to use
#START_FLEX_INSERT_ANCHOR: CPU Usage
set_db max_cpus_per_server $env(LSB_DJOB_NUMPROC)
#END_FLEX_INSERT_ANCHOR: CPU Usage

#REVISIT: This should be removed when Genus fully supports the set_data_check command
#Genus currently does not support set_data_check when it is applied between different instances. This variable is used to skip sections of the SDC constraints file
set ARM_SKIP_SET_DATA_CHECKS true
#REVISIT: This should be removed when Genus fully supports the set_max_delay command (expected 19.12)
#Genus currently does not support set_max_delay -ignore_clock_latency. This variable is used to skip sections of the SDC constraints file
set ARM_SKIP_SET_MAX_DELAY_IGNORE_CLOCK_LATENCY true

# Create the report dir
set report_dir [file normalize [file join ../reports $step_name]]
file mkdir $report_dir

#START_FLEX_INSERT_ANCHOR: Log Message Handling
# -----------------------------------------------------------------------------
# Log message to upgrade
# -----------------------------------------------------------------------------
foreach el $flow_vars(${step_name}_messages_to_upgrade) {
  set message_code [lindex $el 0]
  set reason [lindex $el 1]
  set new_severity [lindex $el 2]

  #Unlike demoting, when choosing to upgrade a message a user shouldn't use "default" because what's the point?
  puts "ARM_WARNING: Upgrading message $message_code, Reason: $reason"
  puts "ARM_INFO: New severity = $new_severity"
  set_db [get_db messages $message_code] .severity $new_severity
  if {[llength $el] > 3} {
    set max_print [lindex $el 3]
    puts "ARM_INFO: Maximum print = $max_print"
    set_db [get_db messages $message_code] .max_print $max_print
  }
}
# -----------------------------------------------------------------------------
# Log message to downgrade
# -----------------------------------------------------------------------------
foreach el $flow_vars(${step_name}_messages_to_downgrade) {
  set message_code [lindex $el 0]
  set reason [lindex $el 1]
  set new_severity [lindex $el 2]

  puts "ARM_WARNING: Downgrading/Hiding message $message_code, Reason: $reason"
  if {$new_severity != "default"} {
    puts "ARM_INFO: New severity = $new_severity"
    set_db [get_db messages $message_code] .severity $new_severity
  }
  if {[llength $el] > 3} {
    set max_print [lindex $el 3]
    puts "ARM_INFO: Maximum print = $max_print"
    set_db [get_db messages $message_code] .max_print $max_print
  }
}
#END_FLEX_INSERT_ANCHOR: Log Message Handling

#- Store non-default root attributes to metrics
set flow_root_config [report_obj -tcl]
foreach key [dict keys $flow_root_config] {
  if {[string length [dict get $flow_root_config $key]] > 200} {
    dict set flow_root_config $key "\[long value truncated\]"
  }
}

set_metric -name flow.root_config -value $flow_root_config
set detected_errors 0
#START_FLEX_INSERT_ANCHOR: genus dp_analytical setting
#END_FLEX_INSERT_ANCHOR: genus dp_analytical setting

# -----------------------------------------------------------------------------
# Initialise the design
# -----------------------------------------------------------------------------
if {[get_db current_design] eq ""} {
  #- setup library information
  read_mmmc             $env(CONFIG_PATH)/mmmc_config.synthesis.tcl
  read_physical  -lef $tech_vars(synthesis,lef)

  #- read and elaborate design
  source ../constraints/syn_load_rtl.tcl
  set_db init_hdl_search_path $dir_list

  if {[info exists elab_only]} {
     set_db statistics_automatic_logging false
     set_db statistics_log_data false
     set_db statistics_metrics false
     set_db wireload_mode none
  }
  set cmd "read_hdl -sv $verilog_filelist"
  puts "FLOW: started $cmd"
  eval $cmd
  #Determine if parameters are needed for elaboration
  set params_list ""
  if {($design_vars(elab_params) != "") && ($design_vars(elab_params_file) != "")} {
    puts "ARM_ERROR: both design_vars(elab_params) & design_vars(elab_params_file) have been defined. Only one can be defined"
    exit 1
  } elseif {$design_vars(elab_params) != ""} {
    puts "ARM_INFO: Elaboration with following parameters: $design_vars(elab_params)"
    set params_list $design_vars(elab_params)
  } elseif {$design_vars(elab_params_file) != ""} {
    source $design_vars(elab_params_file)
    if {$design_vars(elab_params_variable) != ""} {
      puts "ARM_INFO: Elaboration with following parameters: [set $design_vars(elab_params_variable)]"
      set params_list [set $design_vars(elab_params_variable)]
    } else {
      puts "ARM_ERROR: $design_vars(elab_params_variable) from $design_vars(elab_params_file) was not found"
      exit 1
    }
  }

  #Elaborate Design
  if {[llength $params_list] > 0} {
    elaborate -parameter $params_list arcadia_complex
  } else {
    puts "ARM_INFO: Elaboration without parameters"
    elaborate arcadia_complex
  }
  # REVISIT: moving the elaborated design to "arcadia_complex" so that it doesn't have all the parameter names on the end
  # REVISIT: This is temporary so that it works with existing SDC files etc. as we may want to keep parameters on the design name in the future
  rename_obj [find_unique_design] arcadia_complex

  
  #- optionally setup power intent from UPF/CPF/1801
  read_power_intent ${env(LOGICAL_ROOT)}/arcadia/logical/arcadia/power_intent/upf/arcadia_complex0.upf
  # create_cost_group genus_uniquify
  set_db ui_respects_preserve false
  uniquify [current_design]
  set_db ui_respects_preserve true

  #Add any top-level port connections
  foreach hookup_list $design_vars(pin_to_port_hookup_list) {
    #Sanity check we have the correct number of elements defined
    if {([llength $hookup_list] == 5) || ([llength $hookup_list] == 7)} {
      set instance_pattern [lindex $hookup_list 0]
      set module_pattern [lindex $hookup_list 1]
      set pin_pattern [lindex $hookup_list 2]
      set top_level_port_name [lindex $hookup_list 3]
      set top_level_port_direction [lindex $hookup_list 4]

      # Check if the design actually has the pin_pattern, note the pin could be a bus so check for both pin_pattern and pin_pattern[*]
      # Store the output from get_db to speed up runtime
      set all_matching_pins [get_db pins *${pin_pattern} *${pin_pattern}\[*\] -if {.inst.name==$instance_pattern && .inst.base_cell.name==$module_pattern}]
      if {[llength $all_matching_pins] > 0} {

        # First determine pairs of pins and ports that must be connected together. If the signal is a single bit connection
        # then the list will be made up of {pin port}, if a MSB and LSB of the signal has been defined then the list is
        # made up of {pin[lsb] port[lsb] pin[lsb+1] port[lsb+1]...pin[msb] port[msb]}
        if {[llength $hookup_list] == 7} {
          set msb [lindex $hookup_list 5]
          set lsb [lindex $hookup_list 6]

          #To be used when creating the top level port
          set left_bit "-left_bit $msb"; set right_bit "-right_bit $lsb"

          set pin_port_pair_list {}
          for {set i $lsb} {$i <= $msb} {incr i} {
            lappend pin_port_pair_list ${pin_pattern}\[$i\] $top_level_port_name\[$i\]
          }
        } else {
          set pin_port_pair_list [list $pin_pattern $top_level_port_name]

          #To be used when creating the top level port
          set left_bit "" ; set right_bit ""
        }

        # Create the top level port for the connection
        # if the pin_port_pair_list has more than 2 elements we know a lsb/msb was defined so we can
        # create the port as a bus of (msb+1-lsb) bits otherwise simply create a single bit top-level port
        if ![llength [get_port -quiet $top_level_port_name ]] {
          eval "create_port_bus -name $top_level_port_name $left_bit $right_bit -$top_level_port_direction"
        }

        # Finally: All the pins matching the instance_pattern and module_pattern along with the pin from the pin_port_pair_list are
        # found and then connected with the port defined in the pair
        foreach {pin port} $pin_port_pair_list {
          foreach inst_pin [get_db $all_matching_pins *${pin}] {
            disconnect $inst_pin
            puts "ARM_INFO: Connecting $inst_pin with port $port"
            connect [get_ports $port] $inst_pin -prefix [regsub -all -- {[^[:alnum:]_]+} $port {_}]
          }
        }
      } else {
        puts "ARM_ERROR: No pins found with:\n  Instance pattern=$instance_pattern\n  Module pattern=$module_pattern\n  Pin pattern=${pin_pattern}"
      }
    } else {
      puts "ARM_ERROR: [llength $hookup_list] elements found in design_vars(pin_to_port_hookup_list) entry. Either 5 or 7 entries expected. Entries = $hookup_list"
      exit 1
    }
  }

  #START_FLEX_INSERT_ANCHOR: Add top level ports
  # -----------------------------------------------------------------------------
  # Function: create power interface
  # -----------------------------------------------------------------------------
  # REVISIT(ramsri01, BET, add_top_level_ports.tcl script in NFF master needs to be made generic to work with RAM connections in different power domains, NUFLEXFLOW-643)
  # This script is currently here as workaround till we clean up add_top_level_ports.tcl to work for both power gated and non power gated design.
  # Below version will work for designs like A55 with 2 domains or Hayes with 5 domains
  proc arm_create_port {port_name dir {left_bit ""} {right_bit ""} } {
    if { $left_bit != "" } {
      set left_bit "-left_bit $left_bit"
    }
    if { $right_bit != ""} {
      set right_bit "-right_bit $right_bit"
    }

    if ![llength [get_port -quiet $port_name ]]    {
      set cmd "create_port_bus -name $port_name  $left_bit $right_bit -$dir"
      eval $cmd
      puts "ARM_INFO: Port $port_name created"
    } else {
      puts "ARM_INFO: Port $port_name already exists"
    }
  }

  proc arm_netlist_connect { port pin {object ""}} {
    foreach obj_pin [get_db [get_pin -quiet -of_objects [get_cell * -hier -filter "ref_name =~$object"] -filter "full_name=~$pin"]] {
      disconnect $obj_pin
      puts "ARM_USER_INFO: Connecting $obj_pin with port $port"
      connect [get_ports $port] $obj_pin -prefix [regsub -all -- {[^[:alnum:]_]+} $port {_}]
    }
  }
  uniquify [find_unique_design]
  if {[llength [get_db insts .pins.name *EMA*]] > 0} {
  # Single port register file - RFS and FCI*RFS
    if {[get_cell * -hier -filter "ref_name =~ *RFS*"] != ""} {
      arm_create_port RF_EMA  input 2 0
      arm_create_port RF_EMAW input 1 0
      arm_create_port RF_EMAS  input

      uniquify [find_unique_design]

      # Single port register file: EMA connections
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect RF_EMA[${i}] *EMA[${i}] *RFS*
      }
      for {set i 0} {$i < 2} {incr i} {
        arm_netlist_connect RF_EMAW[${i}] *EMAW[${i}] *RFS*
      }
      arm_netlist_connect RF_EMAS *EMAS *RFS*
    }

    # Dual port register file
    if {[get_cell * -hier -filter "ref_name =~ *RF2P*"] != ""} {
      arm_create_port RF2P_EMAA input 2 0
      arm_create_port RF2P_EMAB input 2 0
      arm_create_port RF2P_EMASA input

      edit_netlist uniquify [find_unique_design]

      # Dual ports register file: EMA connections
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect RF2P_EMAA[${i}] *EMAA[${i}] *RF2P*
      }
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect RF2P_EMAB[${i}] *EMAB[${i}] *RF2P*
      }
      arm_netlist_connect RF2P_EMASA *EMASA *RF2P*
    }

    # Single port SRAM memory
    if {[get_cell * -hier -filter "ref_name =~ *SRAM*"] != ""} {
      arm_create_port SRAM_EMA input 2 0
      arm_create_port SRAM_EMAW input 1 0
      arm_create_port SRAM_EMAS input

      edit_netlist uniquify [find_unique_design]
      # SRAM memories
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect SRAM_EMA[${i}] *EMA[${i}] *SRAM*
      }
      for {set i 0} {$i < 2} {incr i} {
        arm_netlist_connect SRAM_EMAW[${i}] *EMAW[${i}] *SRAM*
      }
        arm_netlist_connect SRAM_EMAS *EMAS *SRAM*

      # Create read assist mask port only if the port exists in the RAM.
      if {[get_pins -of_objects [get_cell * -hier -filter "ref_name =~ *SRAM*"] -filter " full_name=~*RAWL* " ]  != ""} {
        arm_create_port SRAM_RAWLM input 1 0
        arm_create_port SRAM_RAWL input

        edit_netlist uniquify [find_unique_design]

        for {set i 0} {$i < 2} {incr i} {
          arm_netlist_connect SRAM_RAWLM[${i}] *RAWLM[${i}] *SRAM*
        }

        arm_netlist_connect SRAM_RAWL *RAWL *SRAM*
      }
    # Create write assist mask port only if the port exists in the RAM.
    if {[get_pins -of_objects [get_cell * -hier -filter "ref_name =~ *SRAM*"] -filter " full_name=~*WABL* " ]  != ""} {
      arm_create_port SRAM_WABLM input 2 0
      arm_create_port SRAM_WABL input

      edit_netlist uniquify [find_unique_design]

      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect SRAM_WABLM[${i}] *WABLM[${i}] *SRAM*
      }

      arm_netlist_connect SRAM_WABL *WABL *SRAM*
    }
    }
  }
  #END_FLEX_INSERT_ANCHOR: Add top level ports

  # do not init dft if comb-only block
  if { [llength [get_db insts -if .is_sequential]] } {

    # Always map the flops to scannable flops, even if insert_dft = false
    set_db current_design  .dft_scan_map_mode force_all

    #Jalves - create DFT hinst for compressor
    create_module -name DFT
    create_hinst -name u_dft -module [get_db modules *DFT] -parent [get_db designs .name]
    set_db [get_db hinsts u_dft] .preserve true
    
  # DFT setup
  source ../scripts/cdns_dft/setup_for_dft.tcl
  source ../scripts/cdns_dft/dft_flow_and_execution_set_variables.tcl
  source ../scripts/cdns_dft/create_dft_ports.tcl
  set_db root: .ui_respects_preserve false
  #reading ctl abstract model for resync FF
  if {[info exists tech_vars(resynchro_flop_ctl_view)]} {
    foreach model $tech_vars(resynchro_flop_ctl_view) {
      set model_name [file rootname [file tail ${model}]]
      set uniquify 0
      get_db insts -if ".is_sequential && !.is_macro && .base_cell.name == ${model_name}" -foreach {
        puts "ARM_INFO: instance: $obj(.name)"
        puts "ARM_INFO: ctlFile : ${model}"
        puts "ARM_INFO: reading dft abstract model for instance $obj(.name)"
        read_dft_abstract_model -ctl -segment_prefix "[file tail $obj(.name)]_${uniquify}_" -instance $obj(.name) ${model}
        incr uniquify
      }
    }
  }
  source ../scripts/cdns_dft/run_me_setup_for_DFT.tcl
  set_db root: .ui_respects_preserve true
  redirect $report_dir/dft_check_setup.rpt {check_dft_rules}

  # REVISIT: echarra
  # REVISIT: why does the cdn script dedicated code not do the job?
  # REVISIT: Message is printed
  # REVISIT: DFT_INFO: ... Connecting 'DFTRAMBYP' for instance 'inst: ...
  # REVISIT: but connection is not actually done if we do not add code below.
  # Workaround: Force reconnection of DFTRAMBYP in case not connected
  foreach instance [get_db insts * -if {.is_memory}] {
    if { [llength  [get_db pins [get_db ${instance} .name]/DFTRAMBYP] ] > 0} {
      puts "ARM_INFO: ... Connecting DFTRAMBYP for instance [get_db $instance .name]"
      disconnect [get_db ${instance} .pins */DFTRAMBYP]
      connect [get_port DFTRAMBYP] [get_pins [get_db ${instance} .name]/DFTRAMBYP] -prefix DFTRAMBYP
    }
  }
 }
  
  #- initialize library and design information
  init_design
  if {[file exists ../scripts/genus/memory_daisychain.tcl]} {
    source -verbose ../scripts/genus/memory_daisychain.tcl
  }
  puts "ARM_INFO: sdc_failed commands $::dc::sdc_failed_commands"
      check_dft_rules > $report_dir/dft_check_setup.rpt
  foreach testpin {nISOLATE_PDCOMPLEX nISOLATE_PDCORE0 nISOLATE_PDCORE1 nISOLATE_PDVPU} {
    define_test_mode -active high -scan_shift $testpin
  }
  #- Load floorplan DEF file
  puts "ARM_INFO: Load floorplan /arm/projectscratch/pd/arcadia_pj33000026/impl/users/fraric01/2024-02-22_103/arcadia/implementation/arcadia_complex.def.gz "
  set_db find_fuzzy_match true
  
#  read_def $flow_vars(floorplan_def) -add_power_switch -keep_welltap_cells -keep_filler_cells
#  read_def /dpc/tsmc_project41/mdatta/Arm_Hayes_N5/EC87704/users/jalves/arcadia/downloads/240317/flow3/data/syn_map/arcadia_complex.def.gz -add_power_switch -keep_welltap_cells -keep_filler_cells
#  read_def /dpc/tsmc_project41/mdatta/Arm_Hayes_N5/EC87704/users/jalves/arcadia/downloads/arcadia_complex.def.gz -add_power_switch -keep_welltap_cells -keep_filler_cells
  read_def /dpc/tsmc_project41/mdatta/Arm_Hayes_N5/EC87704/users/jalves/arcadia/downloads/240319/arcadia_complex_tag_fix.def.gz  -add_power_switch -keep_welltap_cells -keep_filler_cells 
  set_db find_fuzzy_match false

  # Check the PSO networks are well connected or not after read_def
  set PSO_ports [concat [get_object_name [get_db ports nPWRUP_*]] [get_object_name [get_db ports nPWRUPHAMMER_*]] [get_object_name [get_db ports nPWRUPACK_*]] [get_object_name [get_db ports nPWRUPHAMMERACK_*]]]
  set pso_check_errors 0
  foreach port $PSO_ports {
    if {[llength [get_db ports $port -if {.direction == in}]] == 1 && ([get_db [get_db ports $port] .net.num_loads] == 0 || [get_db [get_db ports $port] .net.num_loads] == "")} {
      puts "ARM_ERROR: [get_object_name $port] without any PSW connection, please check the input DEF file"
      incr pso_check_errors
    } elseif {[llength [get_db ports $port -if {.direction == out}]] == 1 && ([get_db [get_db ports $port] .net.num_drivers] == 0 || [get_db [get_db ports $port] .net.num_drivers] == "")} {
      puts "ARM_ERROR: [get_object_name $port] without any PSW connection, please check the input DEF file"
      incr pso_check_errors
    } else {
      puts "ARM_INFO: [get_object_name $port] is well connected"
    }
  }
  if {$pso_check_errors} {
    puts "ARM_ERROR: At least $pso_check_errors error(s) detected in the PSO connection check"
    write_db -to_file ../data/dbs/syn_elab.db
    exit 1
  }
  #ARM_INTERNAL Checks to make sure RTL is ok for synthesis
  check_timing_intent -verbose > $report_dir/timing_lint_elab.rpt
  check_design -multiple_driver -undriven -unresolved  > $report_dir/check_design_elab.rpt

  # DFT not present if comb-only block
  if { [llength [get_db insts -if .is_sequential]] } {
    #Check the output of the check_dft_rules
    set dft_report [open $report_dir/dft_check_setup.rpt r]
    while { [gets $dft_report line] >= 0} {
      if {[regexp {that fail DFT rules:\s+(\d+)} $line -> num_failures]} {
        if {$num_failures > 0} {
          puts "ARM_ERROR: DFT rules failed with $num_failures failing elements, please see $report_dir/dft_check_setup.rpt"
          incr detected_errors
        }
      } elseif {[regexp {registers that are scannable:\s+([\d\.]+)} $line -> percentage_scannable]} {
        if {$percentage_scannable < 100} {
          puts "ARM_ERROR: DFT rules failed with <100% scannable elements, please see $report_dir/dft_check_setup.rpt"
          incr detected_errors
        }
      }
    }
    close $dft_report
  }
  #Check for Cadence loop breaker instances in the netlist
  # *cdn_loop_breaker* cells are only added after a timing analysis has been done
  # Therefore you can only perform this below check after an init_design and a call to
  # either report_timing or check_timing_intent has been done
  if {[llength [get_db insts .name *cdn_loop_breaker*]] > 0} {
    puts "ARM_ERROR: Combinational loops detected in the design, search the log for ELABUTL-133 for more details"
    write_hdl > ../data/elab.v
    report_loop
    incr detected_errors
  }
  if {[check_design -multiple_driver -status]} {
    puts "ARM_ERROR: Signals with multiple drivers are detected, review the list in $report_dir/check_design_elab.rpt"
    incr detected_errors
  }
  # Check sdc_vars(list_of_useful_skew) hierarchies are valid and otherwise error out
  puts "ARM_INFO: sdc_vars(list_of_useful_skew) is used, running a check to see if hierarchy exists"
  foreach user_selected_group_for_useful_skew $sdc_vars(list_of_useful_skew) {
    set hierarchy_name [lindex $user_selected_group_for_useful_skew 1]
    if {[get_db pins ${hierarchy_name}] != ""} {
      puts "ARM_INFO: User selected hierarchy for useful skew: ${hierarchy_name} exists"
    } else {
      puts "ARM_ERROR: User selected hierarchy for useful skew: ${hierarchy_name} does not exist"
      incr detected_errors
    }
  }
  #Stop here if errors have been detected in the elaboration and setup of the design
  if {$detected_errors} {
    puts "ARM_ERROR: At least $detected_errors error(s) detected in the elaboration and setup of the design"
    write_db ../data/dbs/syn_elab.db
    exit 1
  }
  #ARM_INTERNAL end of checks for RTL
  #If we are doing elaboration only (for RTL health check) then stop here
  if {[info exists elab_only]} {
    write_sdc -view [lindex [get_db analysis_views -if {.is_setup}] 0] > ../data/dbs/syn_elab.sdc
    write_db ../data/dbs/syn_elab.db
    exit
  }
  #- add cells and commit power rules
# REVISIT(kenlin01, EAC, Need to enable extra attribute for level shifter inserion since Genus 19.14, PJ02607-7721)
# Allow Genus to insert low power cells on power switch networks
set_db cpi_insert_on_switch_network true
puts "ARM_INFO: Commit power intent"
  commit_power_intent
  # List of preserve register
  foreach flop $design_vars(preserve_register_list) {
    set_db [get_db insts $flop -if {.is_sequential}] .preserve map_size_ok
  }
  ## load tool configs which require design information
  #START_FLEX_INSERT_ANCHOR: genus post db load config
  ################################################################################
  # ATTRIBUTES APPLIED AFTER LOADING A LIBRARY OR DATABASE
  ################################################################################
  # General attributes
  #-------------------------------------------------------------------------------
  set_db number_of_routing_layers                               [get_db [get_db layers -if .name==$tech_vars(max_route_layer)] .route_index]

  # Low-power attributes [get_db -category lp_cg]
  #-------------------------------------------------------------------------------
  set_db current_design .lp_clock_gating_min_flops              $design_vars(lp_clock_gating_min_flops)
  set_db current_design .lp_clock_gating_max_flops              64
  set_db current_design .lp_clock_gating_auto_path_adjust       fixed
  set_db lp_clock_gating_infer_enable                           false

  # Reporting attributes
  #-------------------------------------------------------------------------------
  set_db timing_report_time_unit ns
  set_db timing_report_load_unit pf
  set_db timing_report_fields { timing_point cell fanout load transition delay arrival user_derate total_derate }
  #END_FLEX_INSERT_ANCHOR: genus post db load config

}

# -----------------------------------------------------------------------------
# Update the clock max uncertainty for this step
# -----------------------------------------------------------------------------

#START_FLEX_INSERT_ANCHOR: Uncertainty update
foreach constraint_mode [get_db [get_db analysis_views -if {.is_setup}] .constraint_mode.name] {
  if {[info exists sdc_vars($constraint_mode,overconstraint)] && ([lsearch -exact -index 0 $sdc_vars($constraint_mode,overconstraint) $step_name] >= 0)} {
    set step_overconstraint_list_index [lsearch -exact -index 0 $sdc_vars($constraint_mode,overconstraint) $step_name]
    set overconstraint_value_list [lrange [lindex $sdc_vars($constraint_mode,overconstraint) $step_overconstraint_list_index] 1 end]

    set_interactive_constraint_mode $constraint_mode
    puts "ARM_INFO: update clock max uncertainty for $constraint_mode"

    for {set index 0} {$index < [llength $sdc_vars(real_clocks)]} {incr index} {
      set clock [lindex $sdc_vars(real_clocks) $index]
      regsub {__.*} $constraint_mode {} pvt
      set clock_period            [format "%.3f" [expr 1 / [lindex $sdc_vars($constraint_mode,frequency_target) $index]]]
      set setup_margin            [expr $tech_vars($pvt,clock_margin_offset)+min($tech_vars(clock_margin_ratio)*$clock_period, $tech_vars(max_setup_margin))]

      if {[llength $overconstraint_value_list] > 1} {
        if {[llength $overconstraint_value_list] != [llength $sdc_vars(real_clocks)]} {
          puts "ARM_ERROR: There is more than 1 value defined in the overconstraint list, but the length of the list does not match the number of clocks defined in sdc_vars(real_clocks)"
          exit 1
        } else {
          set overconstraint [lindex $overconstraint_value_list $index]
        }
      } else {
        set overconstraint $overconstraint_value_list
      }

      set clock_max_uncertainty   [format "%.3f" [expr $setup_margin + $overconstraint]]
      set duty_cycle_uncertainty  [format "%.3f" [expr ($clock_period * $tech_vars(clock_duty_cycle_variation))]]

      if {[get_clocks -quiet ${clock}] != ""} {
        puts "ARM_INFO: CLOCKS: Updating the uncertainty for the following clock:"
        puts "ARM_INFO: CLOCKS: Clock Name:             $clock"
        puts "ARM_INFO: CLOCKS: Max Uncertainty:        ${clock_max_uncertainty}ns"
        puts "ARM_INFO: CLOCKS: Duty Cycle Variation:   ${duty_cycle_uncertainty}ns"
        set_clock_uncertainty ${clock_max_uncertainty} -setup [get_clocks ${clock} ]
        set_clock_uncertainty ${duty_cycle_uncertainty} -rise_from [get_clocks ${clock} ] -fall_to [get_clocks ${clock} ]
        set_clock_uncertainty ${duty_cycle_uncertainty} -fall_from [get_clocks ${clock} ] -rise_to [get_clocks ${clock} ]

      }
    }
  } else {
    puts "ARM_INFO: No max uncertainty overconstraint defined for $constraint_mode in the $step_name step"
  }
}
#END_FLEX_INSERT_ANCHOR: Uncertainty update

# -----------------------------------------------------------------------------
# Coarse clock skewing for endpoints defined in sdc_vars(list_of_useful_skew)
# -----------------------------------------------------------------------------

#START_FLEX_INSERT_ANCHOR: Endpoint skewing
foreach constraint_mode [get_db [get_db analysis_views -if {.is_setup}] .constraint_mode.name] {
  puts "ARM_INFO: Useful skew set up for $constraint_mode"

  set_interactive_constraint_mode $constraint_mode

  if {![info exists sdc_vars(list_of_useful_skew)]} {
     puts "ARM_ERROR: sdc_vars(list_of_useful_skew) is not defined"
     exit 0
  }

  foreach el $sdc_vars(list_of_useful_skew) {
    # Extract reference clock
    set pin_found 0
    set pins [get_db pins [lindex $el 1] -if {.is_clock}]
    if { [llength $pins] } {
      foreach pin $pins {
        set target_clock [lindex [get_db $pin .clocks.base_name] 0]

        set clk_match 0
        for {set index 0} {$index < [llength $sdc_vars(real_clocks)]} {incr index} {
          set clock [lindex $sdc_vars(real_clocks) $index]

          # Escape square brackets for clocks with buses
          set clk_pattern [string map {\[ \\[ \] \\]} $clock]
          if { [string match $clk_pattern $target_clock] } {
            incr clk_match
            set pre_cts_clock_latency   [lindex $sdc_vars($constraint_mode,network_latency) $index]
            set pre_cts_clock_frequency [lindex $sdc_vars($constraint_mode,frequency_target) $index]
          }
        }
        if { $clk_match <= 0 } {
          puts "ARM_WARNING: $target_clock doesn't match any clock in sdc_vars(real_clocks)."
        } elseif { $clk_match > 1 } {
          puts "ARM_WARNING: $target_clock match more than one clock in sdc_vars(real_clocks), last defined one will be used to set preskew."
        }
        set clock_period [expr 1/$pre_cts_clock_frequency]
        foreach p $pin {
          set pin_latency($p) [expr ${pre_cts_clock_latency} + ([lindex $el 0] * $clock_period)]
        }
      }
    } else {
        puts "ARM_WARNING: No pin matching pattern [lindex $el 1] has been found"
    }
  }

  set preskew_sdc [ open "./preskew.sdc" w ]

  foreach pin [array names pin_latency] {
    set cmd "set_clock_latency $pin_latency($pin) \[get_pin [get_db $pin .name]\]"
    puts "ARM_INFO: $cmd"
    puts $preskew_sdc $cmd
    eval $cmd
  }

  close $preskew_sdc
}
#END_FLEX_INSERT_ANCHOR: Endpoint skewing
# Loop through all given patterns and set dont_touch according to config
foreach pattern {*HANDINST* *DFT_ANCHOR_BUF*} {
  get_db insts $pattern -foreach { set_db $object .dont_touch size_ok }
}

#START_FLEX_INSERT_ANCHOR: Clock Gate Adjusts
set all_cg_list [get_db insts -if {.is_integrated_clock_gating}]
foreach v [get_db [get_db analysis_views -if { .is_setup==true } ] .name] {
  if { [info exists design_vars($v,ckg_path_adjust)] } {
    foreach pa $design_vars($v,ckg_path_adjust) {
      set pattern [lindex $pa 0]
      set value   [lindex $pa 1]
      puts "ARM_INFO: creates list of clock gates using pattern \"$pattern\", and apply ${value}ns path_adjust on them"
      set cg_list [get_db $all_cg_list -if {.name==$pattern}]
      if {[llength $cg_list]} {
        #The value used is converted to ps as genus works in ps
        set_path_adjust -view $v -to $cg_list -delay [expr $value * 1000]
      } else {
        puts "ARM_WARNING: \"$pattern\" does not match any clock gates"
      }
    }
  }
}
#END_FLEX_INSERT_ANCHOR: Clock Gate Adjusts

# manage_dont_use
foreach cell [get_db lib_cells -if { .is_integrated_clock_gating } -unique] {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use false
}

#START_FLEX_INSERT_ANCHOR: Libscore dont use cell setting
#END_FLEX_INSERT_ANCHOR: Libscore dont use cell setting

foreach cell $tech_vars(dont_use_list) {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use true
}
foreach cell $tech_vars(tie_cells) {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use false
}
foreach cell $tech_vars(cts_clock_gating_cells) {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use false
}

# create_cost_group genus_set_derating
foreach analysis_view [get_db analysis_views -if {.is_setup}] {
  set delay_corner    [get_db $analysis_view .delay_corner.name]
  set constraint_mode [get_db $analysis_view .constraint_mode.name]
  puts "delay_corner $delay_corner"
  regsub "__.*" $delay_corner "" corner
  puts "corner $corner"
#START_FLEX_INSERT_ANCHOR: cell and net derates
  if {[file exist $env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl]} {
    puts "ARM_INFO: applying cell and net derating for $delay_corner from file : $env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl"
    source $env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl
  } else {
    puts "ARM_ERROR: couldn't find cell and net derating for $delay_corner from file: ($env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl)"
  }
#END_FLEX_INSERT_ANCHOR: cell and net derates
  if {[info exists tech_vars($corner,cell_check_late)]} {
    puts "Execute set_timing_derate -cell_check -late $tech_vars($corner,cell_check_late)"
    set_timing_derate -cell_check -late $tech_vars($corner,cell_check_late) -delay_corner $corner
  }
  if {[info exist sdc_vars($constraint_mode,ram_derate) ]} {
    foreach ram_derate $sdc_vars($constraint_mode,ram_derate) {
      set ram_cell_name    [lindex $ram_derate 0]
      set cell_delay_derate [lindex $ram_derate 1]
      set cell_check_derate [lindex $ram_derate 2]
      if { [get_cells -hier -filter "ref_name =~ $ram_cell_name" -quiet] != "" } {
        puts "ARM_INFO: DERATE: Derating $ram_cell_name by $cell_delay_derate on cell_delay and $cell_check_derate on cell_check"
        set_timing_derate $cell_delay_derate -delay_corner $delay_corner -late -cell_delay [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
        set_timing_derate $cell_check_derate -delay_corner $delay_corner -late -cell_check [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
        set_timing_derate $cell_delay_derate -delay_corner $delay_corner -early -cell_delay [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
        set_timing_derate $cell_check_derate -delay_corner $delay_corner -early -cell_check [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
      }
    }
  }
}

# create_cost_group genus_ungrouping
foreach inst $design_vars(ungroup_inst_list) {
  set hinst_list [get_db [get_db hinsts $inst] .name]
  if { $hinst_list != ""} {
    puts "ARM_INFO: $inst forces to be ungrouped"
    ungroup -flatten $hinst_list -only_user_hierarchy
  } else {
    puts "ARM WARNING: $inst to be removed from ungroup list ..."
  }
}

foreach inst $design_vars(no_autoungroup_list) {
  puts "ARM_INFO: $inst wont be ungrouped"
  set_db [get_db hinsts $inst] .ungroup_ok false
}

foreach inst [get_db insts -if { .is_integrated_clock_gating==true && (.name==*_clk_gate*)}] {
  puts "ARM_INFO: $inst wont be ungrouped"
  if {[regsub {\-.*} [get_db program_version] {}] >= 20.10} {
    set_db $inst .parent.ungroup_ok false
  } else {
    set_db $inst .ungroup_ok false
  }
}

#START_FLEX_INSERT_ANCHOR: Additional syn_generic settings
# CDN CCMPR02168913: Resolve potentially redundant AON buffer for on --> off crossing where fanout is in multiple domains
set_db pias_aon_enable_mode_analysis true
set_db pias_aon_check_pg_together 1
#END_FLEX_INSERT_ANCHOR: Additional syn_generic settings

#START_FLEX_INSERT_ANCHOR: Hierarchical flow setup
#END_FLEX_INSERT_ANCHOR: Hierarchical flow setup

## Define cost and path groups to allow genus to optimise each group independently
set inps      [all_inputs -no_clocks]
set outs      [all_outputs]
set seqs      [all_registers]
set regs      [filter_collection $seqs "is_integrated_clock_gating_cell == false && is_macro == false" ]
set icgs      [filter_collection $seqs "is_integrated_clock_gating_cell == true" ]
set mems      [filter_collection $seqs "is_macro == true" ]
set l1_insts  [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_l1/.*"]
set l2_insts  [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/u_l2/.*"]
set dpu_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_dpu/.*"]
set ifu_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_ifu/.*"]
set tlb_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/u_tlb/.*"]
set etm_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_etm/.*"]
set vpu_shared_insts [filter_collection -regexp $seqs "(hierarchical_name =~ u_vcomplex/.*u_vpu/.*)"]
set vpu_core_insts   [filter_collection -regexp $seqs "(hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_vpu_core/.*)"]

## Define cost and path groups to allow genus to optimise each group independently
define_cost_group -name in2out
define_cost_group -name in2reg
define_cost_group -name in2icg
define_cost_group -name reg2reg
define_cost_group -name reg2out
define_cost_group -name clkgate
define_cost_group -name reg2mem
define_cost_group -name mem2reg
define_cost_group -name mem2mem

define_cost_group -name l1
define_cost_group -name l2
define_cost_group -name dpu
define_cost_group -name vpushared
define_cost_group -name vpucore
define_cost_group -name ifu
define_cost_group -name tlb
define_cost_group -name etm
define_cost_group -name l12dpu
define_cost_group -name dpu2l1
define_cost_group -name ifu2dpu
define_cost_group -name dpu2ifu
define_cost_group -name ifu2l1
define_cost_group -name l12ifu
define_cost_group -name l12l2
define_cost_group -name l22l1
define_cost_group -name dpu2vpushared
define_cost_group -name vpushared2dpu
define_cost_group -name dpu2vpucore
define_cost_group -name vpucore2dpu
define_cost_group -name l12vpucore
define_cost_group -name vpucore2l1
define_cost_group -name vpucore2vpushared
define_cost_group -name vpushared2vpucore

foreach view [get_db [get_db analysis_views -if {.is_setup}] .constraint_mode.name] {
  path_group -view $view -from $inps -to $outs -group in2out  -name in2out
  path_group -view $view -from $inps -to $regs -group in2reg  -name in2reg
  path_group -view $view -from $inps -to $icgs -group in2icg  -name in2icg
  path_group -view $view -from $regs -to $regs -group reg2reg -name reg2reg
  path_group -view $view -from $regs -to $outs -group reg2out -name reg2out
  path_group -view $view -from $regs -to $icgs -group clkgate -name clkgate
  path_group -view $view -from $regs -to $mems -group reg2mem -name reg2mem
  path_group -view $view -from $mems -to $regs -group mem2reg -name mem2reg
  path_group -view $view -from $mems -to $mems -group mem2mem -name mem2mem
  path_group -view $view -from $seqs         -to $l1_insts           -group  l1        -name l1
  path_group -view $view -from $seqs         -to $l2_insts           -group  l2        -name l2
  path_group -view $view -from $seqs         -to $dpu_insts          -group  dpu       -name dpu
  path_group -view $view -from $seqs         -to $ifu_insts          -group  ifu       -name ifu
  path_group -view $view -from $seqs         -to $tlb_insts          -group  tlb       -name tlb
  path_group -view $view -from $seqs         -to $etm_insts          -group  etm       -name etm
  path_group -view $view -from $seqs         -to $vpu_shared_insts   -group  vpushared -name vpushared
  path_group -view $view -from $seqs         -to $vpu_core_insts     -group  vpucore   -name vpucore
  path_group -view $view -from $l1_insts     -to $dpu_insts          -group  l12dpu    -name l12dpu
  path_group -view $view -from $dpu_insts    -to $l1_insts           -group  dpu2l1    -name dpu2l1
  path_group -view $view -from $ifu_insts    -to $dpu_insts          -group  ifu2dpu   -name ifu2dpu
  path_group -view $view -from $dpu_insts    -to $ifu_insts          -group  dpu2ifu   -name dpu2ifu
  path_group -view $view -from $ifu_insts    -to $l1_insts           -group  ifu2l1    -name ifu2l1
  path_group -view $view -from $l1_insts     -to $ifu_insts          -group  l12ifu    -name l12ifu
  path_group -view $view -from $l1_insts     -to $l2_insts           -group  l12l2     -name l12l2
  path_group -view $view -from $l2_insts     -to $l1_insts           -group  l22l1     -name l22l1
  path_group -view $view -from $vpu_shared_insts -to $dpu_insts      -group  vpushared2dpu   -name vpushared2dpu
  path_group -view $view -from $dpu_insts        -to $vpu_core_insts -group  dpu2vpucore     -name dpu2vpucore
  path_group -view $view -from $vpu_core_insts   -to $dpu_insts      -group  vpucore2dpu     -name vpucore2dpu
  path_group -view $view -from $l1_insts         -to $vpu_core_insts -group  l12vpucore      -name l12vpucore
  path_group -view $view -from $vpu_core_insts   -to $l1_insts       -group  vpucore2l1      -name vpucore2l1
  path_group -view $view -from $dpu_insts        -to $vpu_shared_insts   -group  dpu2vpushared     -name dpu2vpushared
  path_group -view $view -from $vpu_core_insts   -to $vpu_shared_insts   -group  vpucore2vpushared -name vpucore2vpushared
  path_group -view $view -from $vpu_shared_insts -to $vpu_core_insts     -group  vpushared2vpucore -name vpushared2vpucore
}
# Dump out all the database attributes into a report
# Do this just before the main optimisation super command to understand what is affecting the QoR
redirect $report_dir/tool_settings.rpt "get_db *"


# -----------------------------------------------------------------------------
# Run the generic synthesis
# -----------------------------------------------------------------------------
# Using a physical syn_gen on the given floorplan def in the build
puts "ARM_INFO: A floorplan def file exists in this build, using this def file to run `syn_generic -physical`"

syn_generic 

write_reports -directory ../reports/ -tag ${step_name}
# -----------------------------------------------------------------------------
# Write out the design information and exit
# -----------------------------------------------------------------------------

puts "ARM_INFO: write Netlist"
set basename [file join ../data ${step_name} [get_db current_design .name]]
write_hdl      > ${basename}.v.gz
write_hdl -pg  > ${basename}_pg.v.gz
write_hdl -lec > ${basename}_lec.v.gz

if {[info exist no_intermediate_db ] && $no_intermediate_db == "true"} {
  puts "ARM_INFO: No intermediate DB will be written out, set $no_intermediate_db to false if DB are required"
} else {
  write_db ../data/dbs/${step_name}.db
}

## MJ 04/12/23 For metrics collection
pop_snapshot_stack
create_snapshot -name ${step_name}

if {![info exist all_steps ]} {
  time_info syn_generic
  exit
}
#----------------------------------------------------------------------------
#   The confidential and proprietary information contained in this file may
#   only be used by a person authorised under and to the extent permitted
#   by a subsisting licensing agreement from Arm Limited or its affiliates.
#
#          (C) COPYRIGHT 2024 Arm Limited or its affiliates.
#              ALL RIGHTS RESERVED
#
#   This entire notice must be reproduced on all copies of this file
#   and copies of this file may only be made by a person if such person is
#   permitted to do so under the terms of a subsisting license agreement
#   from Arm Limited or its affiliates.
#
#    Release Information : $State$
#
#----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Function: Read the RTL, setup DFT and synthesise to generic gates
# -----------------------------------------------------------------------------
set step_name "syn_generic"
puts "ARM_INFO: Step syn_generic"
## MJ Metrics 04/12/23
push_snapshot_stack
# -----------------------------------------------------------------------------
# Source flow setup files and initialise the step
# -----------------------------------------------------------------------------
source $env(CONFIG_PATH)/technology.tcl
source $env(CONFIG_PATH)/design.tcl
source $env(CONFIG_PATH)/setup.tcl
#START_FLEX_INSERT_ANCHOR: genus pre db load config
################################################################################
# Genus attributes (design & library not required)
################################################################################

set_db source_verbose    true
set_db flow_verbose      false
set_db information_level 9


################################################################################
# ATTRIBUTES APPLIED BEFORE LOADING A LIBRARY OR DATABASE
################################################################################

# General attributes
#-------------------------------------------------------------------------------

set_multi_cpu_usage -local_cpu $env(LSB_MAX_NUM_PROCESSORS)

# Force timing and capacitance unit to be ns and pf
# It avoids discrepancy issue due to libraries having different units
# Need to be set before reading of libraries it also force sdc and reports units
set_db timing_time_unit 1ns
set_db timing_cap_unit  1pf

set_db super_thread_debug_directory           "./thread_debug_logs"

set_db wlec_set_cdn_synth_root                true
set_db error_on_lib_lef_pin_inconsistency     true

set_db write_vlog_empty_module_for_logic_abstract   false
set_db gen_module_prefix                            "arcadia_complex_"

## to enable output of mask statements in tracks etc
set_db def_output_version 5.8
# Design attributes  [get_db -category design]

set_db remove_assigns true

#-------------------------------------------------------------------------------
set_db design_process_node              5

# HDL attributes [get_db -category hdl]
#-------------------------------------------------------------------------------

set_db hdl_error_on_blackbox              true
set_db hdl_error_on_latch                 $design_vars(error_on_latch)
set_db hdl_error_on_logic_abstract        true
set_db hdl_error_on_negedge               true

set_db hdl_array_naming_style             %s_%d
set_db hdl_flatten_complex_port           true
set_db hdl_generate_index_style           %s_%d
set_db hdl_generate_separator             _
set_db hdl_record_naming_style            %s_%s_
set_db hdl_reg_naming_style               %s_reg%s
set_db hdl_resolve_instance_with_libcell  true
set_db hdl_use_cw_first                   true

# Alias the pins name of CDN_flop to be able to put a constraints on an un-mapped flop
set_db hdl_rename_cdn_flop_pins           {{clk CK} {d D}}

# Force synthesis to not assume any value on any unconnected pins
set_db hdl_unconnected_value              none

# Avoid merging flops: could avoid merging flop being duplicated only by user (timing reason mainly)...
set_db optimize_merge_flops                   false

#This attribute helps with detecting where combinational loops are
set_db print_ports_nets_preserved_for_cb  true

# Optimization attributes  [get_db -category netlist]
#-------------------------------------------------------------------------------
set_db syn_generic_effort                     high
set_db syn_map_effort                         high
set_db syn_opt_effort                         high
set_db use_multibit_cells                     true
set_db use_multibit_combo_cells               true
set_db multibit_cells_from_different_busses   false

set_db multibit_prefix_string                 "MBIT_"
set_db use_multibit_iso_cells                 true
set_db multibit_mapping_effort_level          high
set_db force_merge_seqs_into_multibit_cells   false
set_db force_merge_combos_into_multibit_cells false
set_db dft_shift_register_with_mbci           false
set_db use_multibit_seq_and_tristate_cells    true
set_db auto_ungroup                           none

# Disable register replication
set_db iopt_sequential_duplication            false

# Timing attributes  [get_db -category tim]
#-------------------------------------------------------------------------------
set_db time_recovery_arcs true

# Datapath attributes  [get_db -category dp]
#-------------------------------------------------------------------------------

# Leakage Power attributes  [get_db -category lp_opt lib_ui]
#-------------------------------------------------------------------------------
set_db lp_insert_clock_gating                 true
if { [get_db program_major_version] >= 21.10 } {
  set_db design_power_effort                    high
} else {
  set_db leakage_power_effort                   high
}

# DFT attributes  [get_db -category dft]
#-------------------------------------------------------------------------------
set_db dft_wait_for_license                               true

## Define the Test Clock Waveform Attributes to target ATPG speed of 200MHz
set_db dft_clock_waveform_divide_fall                     100
set_db dft_clock_waveform_divide_period                   100
set_db dft_clock_waveform_divide_rise                     90
set_db dft_clock_waveform_fall                            50
set_db dft_clock_waveform_period                          5000
set_db dft_clock_waveform_rise                            1
set_db dft_include_test_signal_outputs_in_abstract_model  false

# ensure scan flop input be only used for scan
## CCR 2463365	Ensure RAM scan segment having SI/SO in different power domains is included in power domain aware scan chain of inst PD
if {[regsub {\-.*} [get_db program_version] {}]  >= 21.11} {
  set_db dft_use_abstract_segment_instance_power_domain_for_scan_connection true
}
set_db use_scan_seqs_for_non_dft                          false

if {[regsub {\-.*} [get_db program_version] {}] >= 21.10} {
  # pick up instance power domain rather than pin power domain for memory scan connections. CCR 2649133
  set_db dft_use_abstract_segment_instance_power_domain_for_scan_connection true
}

# Physical attributes  [get_db -category phys]
#-------------------------------------------------------------------------------
# set_db scale_of_cap_per_unit_length           1.15
# set_db scale_of_res_per_unit_length           1.15
# Prevent merging unused bits into MBIT FFs/Combo cells,
# which will cause MBIT cell re-naming issue in INVS Multi-Bit
# optimization flow and CLP:ISO_MISSING_MATCHING_CELL errors
# on optimized input pins of Combo cells
set_db multibit_allow_unused_bits             false

#END_FLEX_INSERT_ANCHOR: genus pre db load config

puts "ARM_INFO: Set variables"

# Setup the number of CPUs to use
#START_FLEX_INSERT_ANCHOR: CPU Usage
set_db max_cpus_per_server $env(LSB_DJOB_NUMPROC)
#END_FLEX_INSERT_ANCHOR: CPU Usage

#REVISIT: This should be removed when Genus fully supports the set_data_check command
#Genus currently does not support set_data_check when it is applied between different instances. This variable is used to skip sections of the SDC constraints file
set ARM_SKIP_SET_DATA_CHECKS true
#REVISIT: This should be removed when Genus fully supports the set_max_delay command (expected 19.12)
#Genus currently does not support set_max_delay -ignore_clock_latency. This variable is used to skip sections of the SDC constraints file
set ARM_SKIP_SET_MAX_DELAY_IGNORE_CLOCK_LATENCY true

# Create the report dir
set report_dir [file normalize [file join ../reports $step_name]]
file mkdir $report_dir

#START_FLEX_INSERT_ANCHOR: Log Message Handling
# -----------------------------------------------------------------------------
# Log message to upgrade
# -----------------------------------------------------------------------------
foreach el $flow_vars(${step_name}_messages_to_upgrade) {
  set message_code [lindex $el 0]
  set reason [lindex $el 1]
  set new_severity [lindex $el 2]

  #Unlike demoting, when choosing to upgrade a message a user shouldn't use "default" because what's the point?
  puts "ARM_WARNING: Upgrading message $message_code, Reason: $reason"
  puts "ARM_INFO: New severity = $new_severity"
  set_db [get_db messages $message_code] .severity $new_severity
  if {[llength $el] > 3} {
    set max_print [lindex $el 3]
    puts "ARM_INFO: Maximum print = $max_print"
    set_db [get_db messages $message_code] .max_print $max_print
  }
}
# -----------------------------------------------------------------------------
# Log message to downgrade
# -----------------------------------------------------------------------------
foreach el $flow_vars(${step_name}_messages_to_downgrade) {
  set message_code [lindex $el 0]
  set reason [lindex $el 1]
  set new_severity [lindex $el 2]

  puts "ARM_WARNING: Downgrading/Hiding message $message_code, Reason: $reason"
  if {$new_severity != "default"} {
    puts "ARM_INFO: New severity = $new_severity"
    set_db [get_db messages $message_code] .severity $new_severity
  }
  if {[llength $el] > 3} {
    set max_print [lindex $el 3]
    puts "ARM_INFO: Maximum print = $max_print"
    set_db [get_db messages $message_code] .max_print $max_print
  }
}
#END_FLEX_INSERT_ANCHOR: Log Message Handling

#- Store non-default root attributes to metrics
set flow_root_config [report_obj -tcl]
foreach key [dict keys $flow_root_config] {
  if {[string length [dict get $flow_root_config $key]] > 200} {
    dict set flow_root_config $key "\[long value truncated\]"
  }
}

set_metric -name flow.root_config -value $flow_root_config
set detected_errors 0
#START_FLEX_INSERT_ANCHOR: genus dp_analytical setting
#END_FLEX_INSERT_ANCHOR: genus dp_analytical setting

# -----------------------------------------------------------------------------
# Initialise the design
# -----------------------------------------------------------------------------
if {[get_db current_design] eq ""} {
  #- setup library information
  read_mmmc             $env(CONFIG_PATH)/mmmc_config.synthesis.tcl
  read_physical  -lef $tech_vars(synthesis,lef)

  #- read and elaborate design
  source ../constraints/syn_load_rtl.tcl
  set_db init_hdl_search_path $dir_list

  if {[info exists elab_only]} {
     set_db statistics_automatic_logging false
     set_db statistics_log_data false
     set_db statistics_metrics false
     set_db wireload_mode none
  }
  set cmd "read_hdl -sv $verilog_filelist"
  puts "FLOW: started $cmd"
  eval $cmd
  #Determine if parameters are needed for elaboration
  set params_list ""
  if {($design_vars(elab_params) != "") && ($design_vars(elab_params_file) != "")} {
    puts "ARM_ERROR: both design_vars(elab_params) & design_vars(elab_params_file) have been defined. Only one can be defined"
    exit 1
  } elseif {$design_vars(elab_params) != ""} {
    puts "ARM_INFO: Elaboration with following parameters: $design_vars(elab_params)"
    set params_list $design_vars(elab_params)
  } elseif {$design_vars(elab_params_file) != ""} {
    source $design_vars(elab_params_file)
    if {$design_vars(elab_params_variable) != ""} {
      puts "ARM_INFO: Elaboration with following parameters: [set $design_vars(elab_params_variable)]"
      set params_list [set $design_vars(elab_params_variable)]
    } else {
      puts "ARM_ERROR: $design_vars(elab_params_variable) from $design_vars(elab_params_file) was not found"
      exit 1
    }
  }

  #Elaborate Design
  if {[llength $params_list] > 0} {
    elaborate -parameter $params_list arcadia_complex
  } else {
    puts "ARM_INFO: Elaboration without parameters"
    elaborate arcadia_complex
  }
  # REVISIT: moving the elaborated design to "arcadia_complex" so that it doesn't have all the parameter names on the end
  # REVISIT: This is temporary so that it works with existing SDC files etc. as we may want to keep parameters on the design name in the future
  rename_obj [find_unique_design] arcadia_complex

  
  #- optionally setup power intent from UPF/CPF/1801
  read_power_intent ${env(LOGICAL_ROOT)}/arcadia/logical/arcadia/power_intent/upf/arcadia_complex0.upf
  # create_cost_group genus_uniquify
  set_db ui_respects_preserve false
  uniquify [current_design]
  set_db ui_respects_preserve true

  #Add any top-level port connections
  foreach hookup_list $design_vars(pin_to_port_hookup_list) {
    #Sanity check we have the correct number of elements defined
    if {([llength $hookup_list] == 5) || ([llength $hookup_list] == 7)} {
      set instance_pattern [lindex $hookup_list 0]
      set module_pattern [lindex $hookup_list 1]
      set pin_pattern [lindex $hookup_list 2]
      set top_level_port_name [lindex $hookup_list 3]
      set top_level_port_direction [lindex $hookup_list 4]

      # Check if the design actually has the pin_pattern, note the pin could be a bus so check for both pin_pattern and pin_pattern[*]
      # Store the output from get_db to speed up runtime
      set all_matching_pins [get_db pins *${pin_pattern} *${pin_pattern}\[*\] -if {.inst.name==$instance_pattern && .inst.base_cell.name==$module_pattern}]
      if {[llength $all_matching_pins] > 0} {

        # First determine pairs of pins and ports that must be connected together. If the signal is a single bit connection
        # then the list will be made up of {pin port}, if a MSB and LSB of the signal has been defined then the list is
        # made up of {pin[lsb] port[lsb] pin[lsb+1] port[lsb+1]...pin[msb] port[msb]}
        if {[llength $hookup_list] == 7} {
          set msb [lindex $hookup_list 5]
          set lsb [lindex $hookup_list 6]

          #To be used when creating the top level port
          set left_bit "-left_bit $msb"; set right_bit "-right_bit $lsb"

          set pin_port_pair_list {}
          for {set i $lsb} {$i <= $msb} {incr i} {
            lappend pin_port_pair_list ${pin_pattern}\[$i\] $top_level_port_name\[$i\]
          }
        } else {
          set pin_port_pair_list [list $pin_pattern $top_level_port_name]

          #To be used when creating the top level port
          set left_bit "" ; set right_bit ""
        }

        # Create the top level port for the connection
        # if the pin_port_pair_list has more than 2 elements we know a lsb/msb was defined so we can
        # create the port as a bus of (msb+1-lsb) bits otherwise simply create a single bit top-level port
        if ![llength [get_port -quiet $top_level_port_name ]] {
          eval "create_port_bus -name $top_level_port_name $left_bit $right_bit -$top_level_port_direction"
        }

        # Finally: All the pins matching the instance_pattern and module_pattern along with the pin from the pin_port_pair_list are
        # found and then connected with the port defined in the pair
        foreach {pin port} $pin_port_pair_list {
          foreach inst_pin [get_db $all_matching_pins *${pin}] {
            disconnect $inst_pin
            puts "ARM_INFO: Connecting $inst_pin with port $port"
            connect [get_ports $port] $inst_pin -prefix [regsub -all -- {[^[:alnum:]_]+} $port {_}]
          }
        }
      } else {
        puts "ARM_ERROR: No pins found with:\n  Instance pattern=$instance_pattern\n  Module pattern=$module_pattern\n  Pin pattern=${pin_pattern}"
      }
    } else {
      puts "ARM_ERROR: [llength $hookup_list] elements found in design_vars(pin_to_port_hookup_list) entry. Either 5 or 7 entries expected. Entries = $hookup_list"
      exit 1
    }
  }

  #START_FLEX_INSERT_ANCHOR: Add top level ports
  # -----------------------------------------------------------------------------
  # Function: create power interface
  # -----------------------------------------------------------------------------
  # REVISIT(ramsri01, BET, add_top_level_ports.tcl script in NFF master needs to be made generic to work with RAM connections in different power domains, NUFLEXFLOW-643)
  # This script is currently here as workaround till we clean up add_top_level_ports.tcl to work for both power gated and non power gated design.
  # Below version will work for designs like A55 with 2 domains or Hayes with 5 domains
  proc arm_create_port {port_name dir {left_bit ""} {right_bit ""} } {
    if { $left_bit != "" } {
      set left_bit "-left_bit $left_bit"
    }
    if { $right_bit != ""} {
      set right_bit "-right_bit $right_bit"
    }

    if ![llength [get_port -quiet $port_name ]]    {
      set cmd "create_port_bus -name $port_name  $left_bit $right_bit -$dir"
      eval $cmd
      puts "ARM_INFO: Port $port_name created"
    } else {
      puts "ARM_INFO: Port $port_name already exists"
    }
  }

  proc arm_netlist_connect { port pin {object ""}} {
    foreach obj_pin [get_db [get_pin -quiet -of_objects [get_cell * -hier -filter "ref_name =~$object"] -filter "full_name=~$pin"]] {
      disconnect $obj_pin
      puts "ARM_USER_INFO: Connecting $obj_pin with port $port"
      connect [get_ports $port] $obj_pin -prefix [regsub -all -- {[^[:alnum:]_]+} $port {_}]
    }
  }
  uniquify [find_unique_design]
  if {[llength [get_db insts .pins.name *EMA*]] > 0} {
  # Single port register file - RFS and FCI*RFS
    if {[get_cell * -hier -filter "ref_name =~ *RFS*"] != ""} {
      arm_create_port RF_EMA  input 2 0
      arm_create_port RF_EMAW input 1 0
      arm_create_port RF_EMAS  input

      uniquify [find_unique_design]

      # Single port register file: EMA connections
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect RF_EMA[${i}] *EMA[${i}] *RFS*
      }
      for {set i 0} {$i < 2} {incr i} {
        arm_netlist_connect RF_EMAW[${i}] *EMAW[${i}] *RFS*
      }
      arm_netlist_connect RF_EMAS *EMAS *RFS*
    }

    # Dual port register file
    if {[get_cell * -hier -filter "ref_name =~ *RF2P*"] != ""} {
      arm_create_port RF2P_EMAA input 2 0
      arm_create_port RF2P_EMAB input 2 0
      arm_create_port RF2P_EMASA input

      edit_netlist uniquify [find_unique_design]

      # Dual ports register file: EMA connections
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect RF2P_EMAA[${i}] *EMAA[${i}] *RF2P*
      }
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect RF2P_EMAB[${i}] *EMAB[${i}] *RF2P*
      }
      arm_netlist_connect RF2P_EMASA *EMASA *RF2P*
    }

    # Single port SRAM memory
    if {[get_cell * -hier -filter "ref_name =~ *SRAM*"] != ""} {
      arm_create_port SRAM_EMA input 2 0
      arm_create_port SRAM_EMAW input 1 0
      arm_create_port SRAM_EMAS input

      edit_netlist uniquify [find_unique_design]
      # SRAM memories
      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect SRAM_EMA[${i}] *EMA[${i}] *SRAM*
      }
      for {set i 0} {$i < 2} {incr i} {
        arm_netlist_connect SRAM_EMAW[${i}] *EMAW[${i}] *SRAM*
      }
        arm_netlist_connect SRAM_EMAS *EMAS *SRAM*

      # Create read assist mask port only if the port exists in the RAM.
      if {[get_pins -of_objects [get_cell * -hier -filter "ref_name =~ *SRAM*"] -filter " full_name=~*RAWL* " ]  != ""} {
        arm_create_port SRAM_RAWLM input 1 0
        arm_create_port SRAM_RAWL input

        edit_netlist uniquify [find_unique_design]

        for {set i 0} {$i < 2} {incr i} {
          arm_netlist_connect SRAM_RAWLM[${i}] *RAWLM[${i}] *SRAM*
        }

        arm_netlist_connect SRAM_RAWL *RAWL *SRAM*
      }
    # Create write assist mask port only if the port exists in the RAM.
    if {[get_pins -of_objects [get_cell * -hier -filter "ref_name =~ *SRAM*"] -filter " full_name=~*WABL* " ]  != ""} {
      arm_create_port SRAM_WABLM input 2 0
      arm_create_port SRAM_WABL input

      edit_netlist uniquify [find_unique_design]

      for {set i 0} {$i < 3} {incr i} {
        arm_netlist_connect SRAM_WABLM[${i}] *WABLM[${i}] *SRAM*
      }

      arm_netlist_connect SRAM_WABL *WABL *SRAM*
    }
    }
  }
  #END_FLEX_INSERT_ANCHOR: Add top level ports

  # do not init dft if comb-only block
  if { [llength [get_db insts -if .is_sequential]] } {

    # Always map the flops to scannable flops, even if insert_dft = false
    set_db current_design  .dft_scan_map_mode force_all

    #Jalves - create DFT hinst for compressor
    create_module -name DFT
    create_hinst -name u_dft -module [get_db modules *DFT] -parent [get_db designs .name]
    set_db [get_db hinsts u_dft] .preserve true
    
    # DFT setup
    source ../scripts/cdns_dft/setup_for_dft.tcl
    source ../scripts/cdns_dft/dft_flow_and_execution_set_variables.tcl
    source ../scripts/cdns_dft/create_dft_ports.tcl
    set_db root: .ui_respects_preserve false
    #reading ctl abstract model for resync FF
    if {[info exists tech_vars(resynchro_flop_ctl_view)]} {
      foreach model $tech_vars(resynchro_flop_ctl_view) {
        set model_name [file rootname [file tail ${model}]]
        set uniquify 0
        get_db insts -if ".is_sequential && !.is_macro && .base_cell.name == ${model_name}" -foreach {
          puts "ARM_INFO: instance: $obj(.name)"
          puts "ARM_INFO: ctlFile : ${model}"
          puts "ARM_INFO: reading dft abstract model for instance $obj(.name)"
          read_dft_abstract_model -ctl -segment_prefix "[file tail $obj(.name)]_${uniquify}_" -instance $obj(.name) ${model}
          incr uniquify
        }
      }
    }
    source ../scripts/cdns_dft/run_me_setup_for_DFT.tcl
    set_db root: .ui_respects_preserve true
    redirect $report_dir/dft_check_setup.rpt {check_dft_rules}

    # REVISIT: echarra
    # REVISIT: why does the cdn script dedicated code not do the job?
    # REVISIT: Message is printed
    # REVISIT: DFT_INFO: ... Connecting 'DFTRAMBYP' for instance 'inst: ...
    # REVISIT: but connection is not actually done if we do not add code below.
    # Workaround: Force reconnection of DFTRAMBYP in case not connected
    foreach instance [get_db insts * -if {.is_memory}] {
      if { [llength  [get_db pins [get_db ${instance} .name]/DFTRAMBYP] ] > 0} {
        puts "ARM_INFO: ... Connecting DFTRAMBYP for instance [get_db $instance .name]"
        disconnect [get_db ${instance} .pins */DFTRAMBYP]
        connect [get_port DFTRAMBYP] [get_pins [get_db ${instance} .name]/DFTRAMBYP] -prefix DFTRAMBYP
      }
    }
  }
  
  #- initialize library and design information
  init_design

  if {[file exists ../scripts/genus/memory_daisychain.tcl]} {
    source -verbose ../scripts/genus/memory_daisychain.tcl
  }
  puts "ARM_INFO: sdc_failed commands $::dc::sdc_failed_commands"
  check_dft_rules > $report_dir/dft_check_setup.rpt
  foreach testpin {nISOLATE_PDCOMPLEX nISOLATE_PDCORE0 nISOLATE_PDCORE1 nISOLATE_PDVPU} {
    define_test_mode -active high -scan_shift $testpin
  }
  #- Load floorplan DEF file
  puts "ARM_INFO: Load floorplan /arm/projectscratch/pd/arcadia_pj33000026/impl/users/fraric01/2024-02-22_103/arcadia/implementation/arcadia_complex.def.gz "
  set_db find_fuzzy_match true
  
  #read_def $flow_vars(floorplan_def) -add_power_switch -keep_welltap_cells -keep_filler_cells
  #read_def /dpc/tsmc_project41/mdatta/Arm_Hayes_N5/EC87704/users/jalves/arcadia/downloads/240317/flow3/data/syn_map/arcadia_complex.def.gz -add_power_switch -keep_welltap_cells -keep_filler_cells
  #read_def /dpc/tsmc_project41/mdatta/Arm_Hayes_N5/EC87704/users/jalves/arcadia/downloads/arcadia_complex.def.gz -add_power_switch -keep_welltap_cells -keep_filler_cells
  read_def /dpc/tsmc_project41/mdatta/Arm_Hayes_N5/EC87704/users/jalves/arcadia/downloads/240319/arcadia_complex_tag_fix.def.gz  -add_power_switch -keep_welltap_cells -keep_filler_cells 
  set_db find_fuzzy_match false

  # Check the PSO networks are well connected or not after read_def
  set PSO_ports [concat [get_object_name [get_db ports nPWRUP_*]] [get_object_name [get_db ports nPWRUPHAMMER_*]] [get_object_name [get_db ports nPWRUPACK_*]] [get_object_name [get_db ports nPWRUPHAMMERACK_*]]]
  set pso_check_errors 0
  foreach port $PSO_ports {
    if {[llength [get_db ports $port -if {.direction == in}]] == 1 && ([get_db [get_db ports $port] .net.num_loads] == 0 || [get_db [get_db ports $port] .net.num_loads] == "")} {
      puts "ARM_ERROR: [get_object_name $port] without any PSW connection, please check the input DEF file"
      incr pso_check_errors
    } elseif {[llength [get_db ports $port -if {.direction == out}]] == 1 && ([get_db [get_db ports $port] .net.num_drivers] == 0 || [get_db [get_db ports $port] .net.num_drivers] == "")} {
      puts "ARM_ERROR: [get_object_name $port] without any PSW connection, please check the input DEF file"
      incr pso_check_errors
    } else {
      puts "ARM_INFO: [get_object_name $port] is well connected"
    }
  }
  if {$pso_check_errors} {
    puts "ARM_ERROR: At least $pso_check_errors error(s) detected in the PSO connection check"
    write_db -to_file ../data/dbs/syn_elab.db
    exit 1
  }
  #ARM_INTERNAL Checks to make sure RTL is ok for synthesis
  check_timing_intent -verbose > $report_dir/timing_lint_elab.rpt
  check_design -multiple_driver -undriven -unresolved  > $report_dir/check_design_elab.rpt

  # DFT not present if comb-only block
  if { [llength [get_db insts -if .is_sequential]] } {
    #Check the output of the check_dft_rules
    set dft_report [open $report_dir/dft_check_setup.rpt r]
    while { [gets $dft_report line] >= 0} {
      if {[regexp {that fail DFT rules:\s+(\d+)} $line -> num_failures]} {
        if {$num_failures > 0} {
          puts "ARM_ERROR: DFT rules failed with $num_failures failing elements, please see $report_dir/dft_check_setup.rpt"
          incr detected_errors
        }
      } elseif {[regexp {registers that are scannable:\s+([\d\.]+)} $line -> percentage_scannable]} {
        if {$percentage_scannable < 100} {
          puts "ARM_ERROR: DFT rules failed with <100% scannable elements, please see $report_dir/dft_check_setup.rpt"
          incr detected_errors
        }
      }
    }
    close $dft_report
  }
  #Check for Cadence loop breaker instances in the netlist
  # *cdn_loop_breaker* cells are only added after a timing analysis has been done
  # Therefore you can only perform this below check after an init_design and a call to
  # either report_timing or check_timing_intent has been done
  if {[llength [get_db insts .name *cdn_loop_breaker*]] > 0} {
    puts "ARM_ERROR: Combinational loops detected in the design, search the log for ELABUTL-133 for more details"
    write_hdl > ../data/elab.v
    report_loop
    incr detected_errors
  }
  if {[check_design -multiple_driver -status]} {
    puts "ARM_ERROR: Signals with multiple drivers are detected, review the list in $report_dir/check_design_elab.rpt"
    incr detected_errors
  }
  # Check sdc_vars(list_of_useful_skew) hierarchies are valid and otherwise error out
  puts "ARM_INFO: sdc_vars(list_of_useful_skew) is used, running a check to see if hierarchy exists"
  foreach user_selected_group_for_useful_skew $sdc_vars(list_of_useful_skew) {
    set hierarchy_name [lindex $user_selected_group_for_useful_skew 1]
    if {[get_db pins ${hierarchy_name}] != ""} {
      puts "ARM_INFO: User selected hierarchy for useful skew: ${hierarchy_name} exists"
    } else {
      puts "ARM_ERROR: User selected hierarchy for useful skew: ${hierarchy_name} does not exist"
      incr detected_errors
    }
  }
  #Stop here if errors have been detected in the elaboration and setup of the design
  if {$detected_errors} {
    puts "ARM_ERROR: At least $detected_errors error(s) detected in the elaboration and setup of the design"
    write_db ../data/dbs/syn_elab.db
    exit 1
  }
  #ARM_INTERNAL end of checks for RTL
  #If we are doing elaboration only (for RTL health check) then stop here
  if {[info exists elab_only]} {
    write_sdc -view [lindex [get_db analysis_views -if {.is_setup}] 0] > ../data/dbs/syn_elab.sdc
    write_db ../data/dbs/syn_elab.db
    exit
  }
  #- add cells and commit power rules
  # REVISIT(kenlin01, EAC, Need to enable extra attribute for level shifter inserion since Genus 19.14, PJ02607-7721)
  # Allow Genus to insert low power cells on power switch networks
  set_db cpi_insert_on_switch_network true
  puts "ARM_INFO: Commit power intent"
  commit_power_intent
  # List of preserve register
  foreach flop $design_vars(preserve_register_list) {
    set_db [get_db insts $flop -if {.is_sequential}] .preserve map_size_ok
  }
  ## load tool configs which require design information
  #START_FLEX_INSERT_ANCHOR: genus post db load config
  ################################################################################
  # ATTRIBUTES APPLIED AFTER LOADING A LIBRARY OR DATABASE
  ################################################################################
  # General attributes
  #-------------------------------------------------------------------------------
  set_db number_of_routing_layers                               [get_db [get_db layers -if .name==$tech_vars(max_route_layer)] .route_index]

  # Low-power attributes [get_db -category lp_cg]
  #-------------------------------------------------------------------------------
  set_db current_design .lp_clock_gating_min_flops              $design_vars(lp_clock_gating_min_flops)
  set_db current_design .lp_clock_gating_max_flops              64
  set_db current_design .lp_clock_gating_auto_path_adjust       fixed
  set_db lp_clock_gating_infer_enable                           false

  # Reporting attributes
  #-------------------------------------------------------------------------------
  set_db timing_report_time_unit ns
  set_db timing_report_load_unit pf
  set_db timing_report_fields { timing_point cell fanout load transition delay arrival user_derate total_derate }
  #END_FLEX_INSERT_ANCHOR: genus post db load config

}

# -----------------------------------------------------------------------------
# Update the clock max uncertainty for this step
# -----------------------------------------------------------------------------

#START_FLEX_INSERT_ANCHOR: Uncertainty update
foreach constraint_mode [get_db [get_db analysis_views -if {.is_setup}] .constraint_mode.name] {
  if {[info exists sdc_vars($constraint_mode,overconstraint)] && ([lsearch -exact -index 0 $sdc_vars($constraint_mode,overconstraint) $step_name] >= 0)} {
    set step_overconstraint_list_index [lsearch -exact -index 0 $sdc_vars($constraint_mode,overconstraint) $step_name]
    set overconstraint_value_list [lrange [lindex $sdc_vars($constraint_mode,overconstraint) $step_overconstraint_list_index] 1 end]

    set_interactive_constraint_mode $constraint_mode
    puts "ARM_INFO: update clock max uncertainty for $constraint_mode"

    for {set index 0} {$index < [llength $sdc_vars(real_clocks)]} {incr index} {
      set clock [lindex $sdc_vars(real_clocks) $index]
      regsub {__.*} $constraint_mode {} pvt
      set clock_period            [format "%.3f" [expr 1 / [lindex $sdc_vars($constraint_mode,frequency_target) $index]]]
      set setup_margin            [expr $tech_vars($pvt,clock_margin_offset)+min($tech_vars(clock_margin_ratio)*$clock_period, $tech_vars(max_setup_margin))]

      if {[llength $overconstraint_value_list] > 1} {
        if {[llength $overconstraint_value_list] != [llength $sdc_vars(real_clocks)]} {
          puts "ARM_ERROR: There is more than 1 value defined in the overconstraint list, but the length of the list does not match the number of clocks defined in sdc_vars(real_clocks)"
          exit 1
        } else {
          set overconstraint [lindex $overconstraint_value_list $index]
        }
      } else {
        set overconstraint $overconstraint_value_list
      }

      set clock_max_uncertainty   [format "%.3f" [expr $setup_margin + $overconstraint]]
      set duty_cycle_uncertainty  [format "%.3f" [expr ($clock_period * $tech_vars(clock_duty_cycle_variation))]]

      if {[get_clocks -quiet ${clock}] != ""} {
        puts "ARM_INFO: CLOCKS: Updating the uncertainty for the following clock:"
        puts "ARM_INFO: CLOCKS: Clock Name:             $clock"
        puts "ARM_INFO: CLOCKS: Max Uncertainty:        ${clock_max_uncertainty}ns"
        puts "ARM_INFO: CLOCKS: Duty Cycle Variation:   ${duty_cycle_uncertainty}ns"
        set_clock_uncertainty ${clock_max_uncertainty} -setup [get_clocks ${clock} ]
        set_clock_uncertainty ${duty_cycle_uncertainty} -rise_from [get_clocks ${clock} ] -fall_to [get_clocks ${clock} ]
        set_clock_uncertainty ${duty_cycle_uncertainty} -fall_from [get_clocks ${clock} ] -rise_to [get_clocks ${clock} ]

      }
    }
  } else {
    puts "ARM_INFO: No max uncertainty overconstraint defined for $constraint_mode in the $step_name step"
  }
}
#END_FLEX_INSERT_ANCHOR: Uncertainty update

# -----------------------------------------------------------------------------
# Coarse clock skewing for endpoints defined in sdc_vars(list_of_useful_skew)
# -----------------------------------------------------------------------------

#START_FLEX_INSERT_ANCHOR: Endpoint skewing
foreach constraint_mode [get_db [get_db analysis_views -if {.is_setup}] .constraint_mode.name] {
  puts "ARM_INFO: Useful skew set up for $constraint_mode"

  set_interactive_constraint_mode $constraint_mode

  if {![info exists sdc_vars(list_of_useful_skew)]} {
     puts "ARM_ERROR: sdc_vars(list_of_useful_skew) is not defined"
     exit 0
  }

  foreach el $sdc_vars(list_of_useful_skew) {
    # Extract reference clock
    set pin_found 0
    set pins [get_db pins [lindex $el 1] -if {.is_clock}]
    if { [llength $pins] } {
      foreach pin $pins {
        set target_clock [lindex [get_db $pin .clocks.base_name] 0]

        set clk_match 0
        for {set index 0} {$index < [llength $sdc_vars(real_clocks)]} {incr index} {
          set clock [lindex $sdc_vars(real_clocks) $index]

          # Escape square brackets for clocks with buses
          set clk_pattern [string map {\[ \\[ \] \\]} $clock]
          if { [string match $clk_pattern $target_clock] } {
            incr clk_match
            set pre_cts_clock_latency   [lindex $sdc_vars($constraint_mode,network_latency) $index]
            set pre_cts_clock_frequency [lindex $sdc_vars($constraint_mode,frequency_target) $index]
          }
        }
        if { $clk_match <= 0 } {
          puts "ARM_WARNING: $target_clock doesn't match any clock in sdc_vars(real_clocks)."
        } elseif { $clk_match > 1 } {
          puts "ARM_WARNING: $target_clock match more than one clock in sdc_vars(real_clocks), last defined one will be used to set preskew."
        }
        set clock_period [expr 1/$pre_cts_clock_frequency]
        foreach p $pin {
          set pin_latency($p) [expr ${pre_cts_clock_latency} + ([lindex $el 0] * $clock_period)]
        }
      }
    } else {
        puts "ARM_WARNING: No pin matching pattern [lindex $el 1] has been found"
    }
  }

  set preskew_sdc [ open "./preskew.sdc" w ]

  foreach pin [array names pin_latency] {
    set cmd "set_clock_latency $pin_latency($pin) \[get_pin [get_db $pin .name]\]"
    puts "ARM_INFO: $cmd"
    puts $preskew_sdc $cmd
    eval $cmd
  }

  close $preskew_sdc
}
#END_FLEX_INSERT_ANCHOR: Endpoint skewing
# Loop through all given patterns and set dont_touch according to config
foreach pattern {*HANDINST* *DFT_ANCHOR_BUF*} {
  get_db insts $pattern -foreach { set_db $object .dont_touch size_ok }
}

#START_FLEX_INSERT_ANCHOR: Clock Gate Adjusts
set all_cg_list [get_db insts -if {.is_integrated_clock_gating}]
foreach v [get_db [get_db analysis_views -if { .is_setup==true } ] .name] {
  if { [info exists design_vars($v,ckg_path_adjust)] } {
    foreach pa $design_vars($v,ckg_path_adjust) {
      set pattern [lindex $pa 0]
      set value   [lindex $pa 1]
      puts "ARM_INFO: creates list of clock gates using pattern \"$pattern\", and apply ${value}ns path_adjust on them"
      set cg_list [get_db $all_cg_list -if {.name==$pattern}]
      if {[llength $cg_list]} {
        #The value used is converted to ps as genus works in ps
        set_path_adjust -view $v -to $cg_list -delay [expr $value * 1000]
      } else {
        puts "ARM_WARNING: \"$pattern\" does not match any clock gates"
      }
    }
  }
}
#END_FLEX_INSERT_ANCHOR: Clock Gate Adjusts

# manage_dont_use
foreach cell [get_db lib_cells -if { .is_integrated_clock_gating } -unique] {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use false
}

#START_FLEX_INSERT_ANCHOR: Libscore dont use cell setting
#END_FLEX_INSERT_ANCHOR: Libscore dont use cell setting

foreach cell $tech_vars(dont_use_list) {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use true
}
foreach cell $tech_vars(tie_cells) {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use false
}
foreach cell $tech_vars(cts_clock_gating_cells) {
  set_db [get_db [get_lib_cells $cell] .base_cell] .dont_use false
}

# create_cost_group genus_set_derating
foreach analysis_view [get_db analysis_views -if {.is_setup}] {
  set delay_corner    [get_db $analysis_view .delay_corner.name]
  set constraint_mode [get_db $analysis_view .constraint_mode.name]
  puts "delay_corner $delay_corner"
  regsub "__.*" $delay_corner "" corner
  puts "corner $corner"
  #START_FLEX_INSERT_ANCHOR: cell and net derates
  if {[file exist $env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl]} {
    puts "ARM_INFO: applying cell and net derating for $delay_corner from file : $env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl"
    source $env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl
  } else {
    puts "ARM_ERROR: couldn't find cell and net derating for $delay_corner from file: ($env(CONFIG_PATH)/cln05fb41001.signoff.$delay_corner.cell.net.derates.tcl)"
  }
#END_FLEX_INSERT_ANCHOR: cell and net derates
  if {[info exists tech_vars($corner,cell_check_late)]} {
    puts "Execute set_timing_derate -cell_check -late $tech_vars($corner,cell_check_late)"
    set_timing_derate -cell_check -late $tech_vars($corner,cell_check_late) -delay_corner $corner
  }
  if {[info exist sdc_vars($constraint_mode,ram_derate) ]} {
    foreach ram_derate $sdc_vars($constraint_mode,ram_derate) {
      set ram_cell_name    [lindex $ram_derate 0]
      set cell_delay_derate [lindex $ram_derate 1]
      set cell_check_derate [lindex $ram_derate 2]
      if { [get_cells -hier -filter "ref_name =~ $ram_cell_name" -quiet] != "" } {
        puts "ARM_INFO: DERATE: Derating $ram_cell_name by $cell_delay_derate on cell_delay and $cell_check_derate on cell_check"
        set_timing_derate $cell_delay_derate -delay_corner $delay_corner -late -cell_delay [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
        set_timing_derate $cell_check_derate -delay_corner $delay_corner -late -cell_check [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
        set_timing_derate $cell_delay_derate -delay_corner $delay_corner -early -cell_delay [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
        set_timing_derate $cell_check_derate -delay_corner $delay_corner -early -cell_check [get_cells -hierarchical -filter "ref_name =~ $ram_cell_name"]
      }
    }
  }
}

# create_cost_group genus_ungrouping
foreach inst $design_vars(ungroup_inst_list) {
  set hinst_list [get_db [get_db hinsts $inst] .name]
  if { $hinst_list != ""} {
    puts "ARM_INFO: $inst forces to be ungrouped"
    ungroup -flatten $hinst_list -only_user_hierarchy
  } else {
    puts "ARM WARNING: $inst to be removed from ungroup list ..."
  }
}

foreach inst $design_vars(no_autoungroup_list) {
  puts "ARM_INFO: $inst wont be ungrouped"
  set_db [get_db hinsts $inst] .ungroup_ok false
}

foreach inst [get_db insts -if { .is_integrated_clock_gating==true && (.name==*_clk_gate*)}] {
  puts "ARM_INFO: $inst wont be ungrouped"
  if {[regsub {\-.*} [get_db program_version] {}] >= 20.10} {
    set_db $inst .parent.ungroup_ok false
  } else {
    set_db $inst .ungroup_ok false
  }
}

#START_FLEX_INSERT_ANCHOR: Additional syn_generic settings
# CDN CCMPR02168913: Resolve potentially redundant AON buffer for on --> off crossing where fanout is in multiple domains
set_db pias_aon_enable_mode_analysis true
set_db pias_aon_check_pg_together 1
#END_FLEX_INSERT_ANCHOR: Additional syn_generic settings

#START_FLEX_INSERT_ANCHOR: Hierarchical flow setup
#END_FLEX_INSERT_ANCHOR: Hierarchical flow setup

## Define cost and path groups to allow genus to optimise each group independently
set inps      [all_inputs -no_clocks]
set outs      [all_outputs]
set seqs      [all_registers]
set regs      [filter_collection $seqs "is_integrated_clock_gating_cell == false && is_macro == false" ]
set icgs      [filter_collection $seqs "is_integrated_clock_gating_cell == true" ]
set mems      [filter_collection $seqs "is_macro == true" ]
set l1_insts  [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_l1/.*"]
set l2_insts  [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/u_l2/.*"]
set dpu_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_dpu/.*"]
set ifu_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_ifu/.*"]
set tlb_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/u_tlb/.*"]
set etm_insts [filter_collection -regexp $seqs "hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_etm/.*"]
set vpu_shared_insts [filter_collection -regexp $seqs "(hierarchical_name =~ u_vcomplex/.*u_vpu/.*)"]
set vpu_core_insts   [filter_collection -regexp $seqs "(hierarchical_name =~ u_vcomplex/g_cpu_[01]_u_cpu/u_vpu_core/.*)"]

## Define cost and path groups to allow genus to optimise each group independently
define_cost_group -name in2out
define_cost_group -name in2reg
define_cost_group -name in2icg
define_cost_group -name reg2reg
define_cost_group -name reg2out
define_cost_group -name clkgate
define_cost_group -name reg2mem
define_cost_group -name mem2reg
define_cost_group -name mem2mem

define_cost_group -name l1
define_cost_group -name l2
define_cost_group -name dpu
define_cost_group -name vpushared
define_cost_group -name vpucore
define_cost_group -name ifu
define_cost_group -name tlb
define_cost_group -name etm
define_cost_group -name l12dpu
define_cost_group -name dpu2l1
define_cost_group -name ifu2dpu
define_cost_group -name dpu2ifu
define_cost_group -name ifu2l1
define_cost_group -name l12ifu
define_cost_group -name l12l2
define_cost_group -name l22l1
define_cost_group -name dpu2vpushared
define_cost_group -name vpushared2dpu
define_cost_group -name dpu2vpucore
define_cost_group -name vpucore2dpu
define_cost_group -name l12vpucore
define_cost_group -name vpucore2l1
define_cost_group -name vpucore2vpushared
define_cost_group -name vpushared2vpucore

foreach view [get_db [get_db analysis_views -if {.is_setup}] .constraint_mode.name] {
  path_group -view $view -from $inps -to $outs -group in2out  -name in2out
  path_group -view $view -from $inps -to $regs -group in2reg  -name in2reg
  path_group -view $view -from $inps -to $icgs -group in2icg  -name in2icg
  path_group -view $view -from $regs -to $regs -group reg2reg -name reg2reg
  path_group -view $view -from $regs -to $outs -group reg2out -name reg2out
  path_group -view $view -from $regs -to $icgs -group clkgate -name clkgate
  path_group -view $view -from $regs -to $mems -group reg2mem -name reg2mem
  path_group -view $view -from $mems -to $regs -group mem2reg -name mem2reg
  path_group -view $view -from $mems -to $mems -group mem2mem -name mem2mem
  path_group -view $view -from $seqs         -to $l1_insts           -group  l1        -name l1
  path_group -view $view -from $seqs         -to $l2_insts           -group  l2        -name l2
  path_group -view $view -from $seqs         -to $dpu_insts          -group  dpu       -name dpu
  path_group -view $view -from $seqs         -to $ifu_insts          -group  ifu       -name ifu
  path_group -view $view -from $seqs         -to $tlb_insts          -group  tlb       -name tlb
  path_group -view $view -from $seqs         -to $etm_insts          -group  etm       -name etm
  path_group -view $view -from $seqs         -to $vpu_shared_insts   -group  vpushared -name vpushared
  path_group -view $view -from $seqs         -to $vpu_core_insts     -group  vpucore   -name vpucore
  path_group -view $view -from $l1_insts     -to $dpu_insts          -group  l12dpu    -name l12dpu
  path_group -view $view -from $dpu_insts    -to $l1_insts           -group  dpu2l1    -name dpu2l1
  path_group -view $view -from $ifu_insts    -to $dpu_insts          -group  ifu2dpu   -name ifu2dpu
  path_group -view $view -from $dpu_insts    -to $ifu_insts          -group  dpu2ifu   -name dpu2ifu
  path_group -view $view -from $ifu_insts    -to $l1_insts           -group  ifu2l1    -name ifu2l1
  path_group -view $view -from $l1_insts     -to $ifu_insts          -group  l12ifu    -name l12ifu
  path_group -view $view -from $l1_insts     -to $l2_insts           -group  l12l2     -name l12l2
  path_group -view $view -from $l2_insts     -to $l1_insts           -group  l22l1     -name l22l1
  path_group -view $view -from $vpu_shared_insts -to $dpu_insts      -group  vpushared2dpu   -name vpushared2dpu
  path_group -view $view -from $dpu_insts        -to $vpu_core_insts -group  dpu2vpucore     -name dpu2vpucore
  path_group -view $view -from $vpu_core_insts   -to $dpu_insts      -group  vpucore2dpu     -name vpucore2dpu
  path_group -view $view -from $l1_insts         -to $vpu_core_insts -group  l12vpucore      -name l12vpucore
  path_group -view $view -from $vpu_core_insts   -to $l1_insts       -group  vpucore2l1      -name vpucore2l1
  path_group -view $view -from $dpu_insts        -to $vpu_shared_insts   -group  dpu2vpushared     -name dpu2vpushared
  path_group -view $view -from $vpu_core_insts   -to $vpu_shared_insts   -group  vpucore2vpushared -name vpucore2vpushared
  path_group -view $view -from $vpu_shared_insts -to $vpu_core_insts     -group  vpushared2vpucore -name vpushared2vpucore
}
# Dump out all the database attributes into a report
# Do this just before the main optimisation super command to understand what is affecting the QoR
redirect $report_dir/tool_settings.rpt "get_db *"


# -----------------------------------------------------------------------------
# Run the generic synthesis
# -----------------------------------------------------------------------------
# Using a physical syn_gen on the given floorplan def in the build
puts "ARM_INFO: A floorplan def file exists in this build, using this def file to run `syn_generic -physical`"

syn_generic 

write_reports -directory ../reports/ -tag ${step_name}
# -----------------------------------------------------------------------------
# Write out the design information and exit
# -----------------------------------------------------------------------------

puts "ARM_INFO: write Netlist"
set basename [file join ../data ${step_name} [get_db current_design .name]]
write_hdl      > ${basename}.v.gz
write_hdl -pg  > ${basename}_pg.v.gz
write_hdl -lec > ${basename}_lec.v.gz

if {[info exist no_intermediate_db ] && $no_intermediate_db == "true"} {
  puts "ARM_INFO: No intermediate DB will be written out, set $no_intermediate_db to false if DB are required"
} else {
  write_db ../data/dbs/${step_name}.db
}

## MJ 04/12/23 For metrics collection
pop_snapshot_stack
create_snapshot -name ${step_name}

if {![info exist all_steps ]} {
  time_info syn_generic
  exit
}
 

Tool Command Language(TCL) online compiler

Write, Run & Share TCL code online using OneCompiler's TCL online compiler for free. It's one of the robust, feature-rich online compilers for TCL language, running the latest TCL version 8.6. Getting started with the OneCompiler's TCL editor is easy and fast. The editor shows sample boilerplate code when you choose language as TCL and start coding.

Taking inputs (stdin)

OneCompiler's TCL online editor supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample TCL program which takes name as input and prints hello message with your name.

set name [gets stdin]
puts "Hello $name"

About TCL

Tool Command Language(TCL) is a general purpose scripting language which is commonly used for GUIs and for testing. Everything is by default string in TCL. It was created by John Osterhout in 1989.

Syntax help

Variables

Variable is a identifier which is used to hold the value. set is used to create variables.

Examples

set name onecompiler

Loops

1. If-Else:

When ever you want to perform a set of operations based on a condition IF-ELSE is used.

if(conditional-expression) {
   #code
} else {
   #code
}

You can also use if-else for nested Ifs and If-Else-If ladder when multiple conditions are to be performed on a single variable.

2. Switch:

Switch is an alternative to If-Else-If ladder.

switch(conditional-expression) {    
value1 {     
 # code
}    
value1 {     
 # code
}    
...
default {
# code
} 

3. For:

For loop is used to iterate a set of statements based on a condition.

for{start}{test}{next}{  
  # code  
} 

4. While:

While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.

while(condition) {  
 # code 
}  

Arrays

Array is a collection of similar data which is stored in continuous memory addresses. Array values can be fetched using index. Index starts from 0 to size-1.

Syntax

set ArrayName(Index) value

Procedures

Procedure is a sub-routine which contains set of statements. Uusually procedures are required when multiple calls are made to same set of statements. Procedures increases re-usuability and modularity.

Syntax

proc procedureName {arguments} {
   # code
}