# Xilinx Vivado Synthesis script for non-project TCL mode
# Generated by Xeda

# These settings are set by Xeda
set vhdl_std              {{design.language.vhdl.standard}}
set nthreads              {{settings.nthreads}}
set fail_critical_warning {{settings.fail_critical_warning}}

set reports_dir           {{settings.reports_dir}}
set settings.outputs_dir  {{settings.settings.outputs_dir}}
set checkpoints_dir       {{settings.checkpoints_dir}}
set fpga_part             {{settings.fpga.part}}

{% include 'util.tcl' %}


set_param general.maxThreads {{settings.nthreads}}

file mkdir ${settings.outputs_dir}
file mkdir ${reports_dir}
file mkdir [file join ${reports_dir} post_synth]
file mkdir [file join ${reports_dir} post_place]
file mkdir [file join ${reports_dir} post_route]
file mkdir ${checkpoints_dir}

# suppress some warning messages
# warning partial connection
set_msg_config -id "\[Synth 8-350\]" -suppress
# info do synthesis
set_msg_config -id "\[Synth 8-256\]" -suppress
set_msg_config -id "\[Synth 8-638\]" -suppress
# BRAM mapped to LUT due to optimization
set_msg_config -id "\[Synth 8-3969\]" -suppress
# BRAM with no output register
set_msg_config -id "\[Synth 8-4480\]" -suppress
# DSP without input pipelining
set_msg_config -id "\[Drc 23-20\]" -suppress
# Update IP version
set_msg_config -id "\[Netlist 29-345\]" -suppress   

set_param tcl.collectionResultDisplayLimit 0
set parts [get_parts]

puts "\n================================( Read Design Files and Constraints )================================"

if {[lsearch -exact $parts $fpga_part] < 0} {
    puts "ERROR: device $fpga_part is not supported!"
    puts "Supported devices:"
    puts [join $parts " "]
    quit
}

puts "Targeting device: $fpga_part"

# DO NOT use per file vhdl version as not supported universally (even though our data structures support it)
set vhdl_std_opt [expr {$vhdl_std == "08" ?  "-vhdl2008": ""}];

{% for src in design.rtl.sources %}
{%- if src.type == 'verilog' %}
{%- if src.variant == 'systemverilog' %}
puts "Reading SystemVerilog file {{src.file}}"
if { [catch {eval read_verilog -sv {{src.file}} } myError]} {
    errorExit $myError
}
{% else %}
puts "Reading Verilog file {{src.file}}"
if { [catch {eval read_verilog {{src.file}} } myError]} {
    errorExit $myError
}
{%- endif %}
{%- endif %}
{% if src.type == 'vhdl' -%}
puts "Reading VHDL file {{src.file}} ${vhdl_std_opt}"
if { [catch {eval read_vhdl ${vhdl_std_opt} {{src.file}} } myError]} {
    errorExit $myError
}
{%- endif %}
{%- endfor %}

# TODO: Skip saving some artifects in case timing not met or synthesis failed for any reason

{% for xdc_file in xdc_files -%}
read_xdc {{xdc_file}}
{% endfor %}

puts "\n===========================( RTL Synthesize and Map )==========================="
eval synth_design -part $fpga_part -top {{design.rtl.top}} {{settings.synth.steps.synth|flatten_dict}} {{design.rtl.generics|vivado_generics}}

{% if settings.synth.strategy == "Debug" -%}
set_property KEEP_HIERARCHY true [get_cells -hier * ]
set_property DONT_TOUCH true [get_cells -hier * ]
{% endif %}
showWarningsAndErrors


{% if settings.synth.steps.opt != None -%}
puts "\n==============================( Optimize Design )================================"
eval opt_design {{settings.synth.steps.opt|flatten_dict}}
{% endif %}

{% if settings.write_checkpoint -%}
write_checkpoint -force ${checkpoints_dir}/post_synth
{% endif %}
report_timing_summary -file ${reports_dir}/post_synth/timing_summary.rpt
report_utilization -hierarchical -force -file ${reports_dir}/post_synth/hierarchical_utilization.rpt
# reportCriticalPaths ${reports_dir}/post_synth/critpath_report.csv
# report_methodology  -file ${reports_dir}/post_synth/methodology.rpt

{% if settings.optimize_power and not settings.optimize_power_postplace -%}
puts "\n===============================( Post-synth Power Optimization )================================"
# this is more effective than Post-placement Power Optimization but can hurt timing
eval power_opt_design
report_power_opt -file ${reports_dir}/post_synth/power_optimization.rpt
showWarningsAndErrors
{% endif %}

puts "\n================================( Place Design )================================="
eval place_design {{settings.impl.steps.place|flatten_dict}}
showWarningsAndErrors


{% if settings.optimize_power_postplace %}
puts "\n===============================( Post-placement Power Optimization )================================"
eval power_opt_design
report_power_opt -file ${reports_dir}/post_place/post_place_power_optimization.rpt
showWarningsAndErrors
{% endif %}

{% if settings.impl.steps.place_opt != None -%}
puts "\n==============================( Post-place optimization )================================"
eval opt_design {{settings.impl.steps.place_opt|flatten_dict}}

{% if settings.impl.steps.place_opt2 != None -%}
puts "\n==============================( Post-place optimization 2)================================"
eval opt_design {{settings.impl.steps.place_opt2|flatten_dict}}
{% endif %}

{% endif %}


{% if settings.impl.steps.phys_opt != None -%}
puts "\n========================( Post-place Physical Optimization )=========================="
eval phys_opt_design {{settings.impl.steps.phys_opt|flatten_dict}}
{% if settings.impl.steps.phys_opt2 != None -%}
puts "\n========================( Post-place Physical Optimization 2 )=========================="
eval phys_opt_design {{settings.impl.steps.phys_opt2|flatten_dict}}
{% endif %}
{% endif %}

{% if settings.write_checkpoint -%}
write_checkpoint -force ${checkpoints_dir}/post_place
report_timing_summary -file ${reports_dir}/post_place/timing_summary.rpt
report_utilization -hierarchical -force -file ${reports_dir}/post_place/hierarchical_utilization.rpt
{% endif %}

puts "\n================================( Route Design )================================="
eval route_design {{settings.impl.steps.route|flatten_dict}}
showWarningsAndErrors

{% if settings.impl.steps.phys_opt != None -%}
puts "\n=========================( Post-Route Physical Optimization )=========================="
phys_opt_design {{settings.impl.steps.phys_opt|flatten_dict}}
showWarningsAndErrors
{% endif %}

{% if settings.write_checkpoint -%}
puts "\n=============================( Writing Checkpoint )=============================="
write_checkpoint -force ${checkpoints_dir}/post_route
{% endif %}

puts "\n==============================( Writing Reports )================================"
report_timing_summary -check_timing_verbose -no_header -report_unconstrained -path_type full -input_pins -max_paths 10 -delay_type min_max -file ${reports_dir}/post_route/timing_summary.rpt
report_timing  -no_header -input_pins  -unique_pins -sort_by group -max_paths 100 -path_type full -delay_type min_max -file ${reports_dir}/post_route/timing.rpt
reportCriticalPaths ${reports_dir}/post_route/critpath_report.csv
## report_clock_utilization           -force -file ${reports_dir}/post_route/clock_utilization.rpt
report_utilization                 -force -file ${reports_dir}/post_route/utilization.rpt
report_utilization                 -force -file ${reports_dir}/post_route/utilization.xml -format xml
report_utilization -hierarchical   -force -file ${reports_dir}/post_route/hierarchical_utilization.xml -format xml
report_utilization -hierarchical   -force -file ${reports_dir}/post_route/hierarchical_utilization.rpt
## report_utilization -hierarchical   -force -file ${reports_dir}/post_route/hierarchical_utilization.xml -format xml
report_power                       -file ${reports_dir}/post_route/power.rpt
report_drc                         -file ${reports_dir}/post_route/drc.rpt
## report_ram_utilization             -file ${reports_dir}/post_route/ram_utilization.rpt -append
report_methodology                 -file ${reports_dir}/post_route/methodology.rpt
## report_qor_suggestions -force      -file ${reports_dir}/post_route/qor_suggestions.rpt

set timing_slack [get_property SLACK [get_timing_paths]]

if {[string is double -strict $timing_slack]} {
    puts "Final timing slack: $timing_slack ns"

    if {[string is double -strict $timing_slack] && ($timing_slack < 0)} {
        puts "ERROR: Failed to meet timing by $timing_slack, see [file join ${reports_dir} post_route timing_summary.rpt] for details"
    {% if settings.fail_timing -%}
        exit 1
    {% endif %}
    }
} 

{%- if settings.write_netlist -%}
puts "\n==========================( Writing Netlist and SDF )============================="
write_sdf -mode timesim -process_corner slow -force -file ${settings.outputs_dir}/impl_timesim.sdf
# should match sdf
write_verilog -mode timesim -sdf_anno false -force -file ${settings.outputs_dir}/impl_timesim.v
##    write_verilog -mode timesim -sdf_anno false -include_xilinx_libs -write_all_overrides -force -file ${settings.outputs_dir}/impl_timesim_inlined.v
##    write_verilog -mode funcsim -force ${settings.outputs_dir}/impl_funcsim_noxlib.v
##    write_vhdl    -mode funcsim -include_xilinx_libs -write_all_overrides -force -file ${settings.outputs_dir}/impl_funcsim.vhd
write_xdc -no_fixed_only -force ${settings.outputs_dir}/impl.xdc
{% endif %}

{%- if settings.write_bitstream -%}
puts "\n==============================( Writing Bitstream )==============================="
write_bitstream -force ${settings.outputs_dir}/bitstream.bit
{% endif %}

showWarningsAndErrors
puts "\n===========================( *DISABLE ECHO* )==========================="
