{#- PCILeech Build Script Template -#}
{#- This handles synthesis, implementation, and bitstream generation in batch mode -#}
{{ header_comment }}
# PCILeech Batch Build Script
# Generated by PCILeechFWGenerator - PCILeech Integration
# Board: {{ board_name }}
# FPGA: {{ fpga_part }}
# Family: {{ fpga_family }}

# Set batch mode for automated builds
{%- if batch_mode %}
set_param general.maxThreads {{ build.jobs }}
set_param synth.maxThreads {{ build.jobs }}
set_param place.maxThreads {{ build.jobs }}
set_param route.maxThreads {{ build.jobs }}
{%- endif %}

# Error handling configuration
set_msg_config -id {Common 17-55} -suppress
set_msg_config -id {Vivado 12-1387} -suppress
set_msg_config -id {Synth 8-3331} -suppress
set_msg_config -id {Synth 8-3332} -suppress

# Project configuration
set project_name "{{ project_name }}"
set project_dir "{{ project_dir }}"
set fpga_part "{{ fpga_part }}"
set board_name "{{ board_name }}"

# Build strategies
set synthesis_strategy "{{ synthesis_strategy }}"
set implementation_strategy "{{ implementation_strategy }}"

# Open existing project
puts "Opening PCILeech project: $project_name"
if {[file exists [file join $project_dir "${project_name}.xpr"]]} {
    open_project [file join $project_dir "${project_name}.xpr"]
} else {
    puts "ERROR: Project file not found. Run project generation script first."
    exit 1
}

# Verify project is properly configured
if {[get_property PART [current_project]] != $fpga_part} {
    puts "ERROR: Project FPGA part mismatch. Expected: $fpga_part"
    exit 1
}

puts "Project opened successfully"
puts "FPGA Part: [get_property PART [current_project]]"
puts "Target Language: [get_property TARGET_LANGUAGE [current_project]]"

# Reset runs to ensure clean build
reset_run synth_1
reset_run impl_1

# Configure synthesis strategy
puts "Configuring synthesis strategy: $synthesis_strategy"
set_property strategy $synthesis_strategy [get_runs synth_1]

{%- if fpga_family == "ultrascale" or fpga_family == "ultrascale_plus" %}
# UltraScale-specific synthesis options
set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value {-mode out_of_context} -objects [get_runs synth_1]
set_property -name {STEPS.SYNTH_DESIGN.ARGS.FLATTEN_HIERARCHY} -value {rebuilt} -objects [get_runs synth_1]
{%- else %}
# 7-Series synthesis options
set_property -name {STEPS.SYNTH_DESIGN.ARGS.FLATTEN_HIERARCHY} -value {rebuilt} -objects [get_runs synth_1]
set_property -name {STEPS.SYNTH_DESIGN.ARGS.GATED_CLOCK_CONVERSION} -value {off} -objects [get_runs synth_1]
{%- endif %}

# Configure implementation strategy
puts "Configuring implementation strategy: $implementation_strategy"
set_property strategy $implementation_strategy [get_runs impl_1]

# Advanced implementation options for PCILeech
set_property -name {STEPS.PLACE_DESIGN.ARGS.MORE OPTIONS} -value {-timing_summary} -objects [get_runs impl_1]
set_property -name {STEPS.ROUTE_DESIGN.ARGS.MORE OPTIONS} -value {-timing_summary} -objects [get_runs impl_1]

{%- if batch_mode %}
# Batch mode specific settings
set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value {-no_iobuf} -objects [get_runs synth_1]
{%- endif %}

# Start synthesis
puts "Starting synthesis..."
puts "Strategy: $synthesis_strategy"
puts "Jobs: {{ build.jobs }}"

launch_runs synth_1 -jobs {{ build.jobs }}
wait_on_run synth_1

# Check synthesis results
if {[get_property PROGRESS [get_runs synth_1]] != "100%"} {
    puts "ERROR: Synthesis failed"
    exit 1
}

if {[get_property NEEDS_REFRESH [get_runs synth_1]] == 1} {
    puts "ERROR: Synthesis needs refresh"
    exit 1
}

puts "Synthesis completed successfully"

# Generate synthesis reports
puts "Generating synthesis reports..."
open_run synth_1 -name synth_1
report_timing_summary -delay_type min_max -report_unconstrained -check_timing_verbose -max_paths 10 -input_pins -routable_nets -file timing_synth.rpt
report_utilization -file utilization_synth.rpt
report_power -file power_synth.rpt

# Start implementation
puts "Starting implementation..."
puts "Strategy: $implementation_strategy"

launch_runs impl_1 -jobs {{ build.jobs }}
wait_on_run impl_1

# Check implementation results
if {[get_property PROGRESS [get_runs impl_1]] != "100%"} {
    puts "ERROR: Implementation failed"
    exit 1
}

if {[get_property NEEDS_REFRESH [get_runs impl_1]] == 1} {
    puts "ERROR: Implementation needs refresh"
    exit 1
}

puts "Implementation completed successfully"

# Generate implementation reports
puts "Generating implementation reports..."
open_run impl_1
report_timing_summary -delay_type min_max -report_unconstrained -check_timing_verbose -max_paths 10 -input_pins -routable_nets -file timing_impl.rpt
report_utilization -file utilization_impl.rpt
report_power -file power_impl.rpt
report_drc -file drc.rpt
report_methodology -file methodology.rpt

# Check timing closure
set timing_met 0.0
set hold_met 0.0

catch {
    set timing_met [get_property STATS.WNS [get_runs impl_1]]
    set hold_met [get_property STATS.WHS [get_runs impl_1]]
}

puts "Timing Results:"
puts "  Setup (WNS): $timing_met ns"
puts "  Hold (WHS): $hold_met ns"

if {$timing_met < 0} {
    puts "WARNING: Setup timing not met (WNS: $timing_met ns)"
}

if {$hold_met < 0} {
    puts "WARNING: Hold timing not met (WHS: $hold_met ns)"
}

# Generate bitstream
puts "Starting bitstream generation..."

# Configure bitstream options
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]

{%- if fpga_family == "7series" %}
# 7-Series specific bitstream options
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
set_property BITSTREAM.STARTUP.STARTUPCLK CCLK [current_design]
{%- elif fpga_family == "ultrascale" or fpga_family == "ultrascale_plus" %}
# UltraScale specific bitstream options
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
{%- endif %}

launch_runs impl_1 -to_step write_bitstream -jobs {{ build.jobs }}
wait_on_run impl_1

# Check bitstream generation
if {[get_property PROGRESS [get_runs impl_1]] != "100%"} {
    puts "ERROR: Bitstream generation failed"
    exit 1
}

puts "Bitstream generation completed successfully"

# Copy output files to root directory
set bit_file [file join $project_dir "${project_name}.runs" "impl_1" "*.bit"]
set ltx_file [file join $project_dir "${project_name}.runs" "impl_1" "*.ltx"]

# Find and copy bitstream file
set bit_files [glob -nocomplain $bit_file]
if {[llength $bit_files] > 0} {
    set source_bit [lindex $bit_files 0]
    set dest_bit "${board_name}.bit"
    file copy -force $source_bit $dest_bit
    puts "Bitstream copied to: $dest_bit"
    
    # Get file size for validation
    set bit_size [file size $dest_bit]
    set bit_size_mb [expr {$bit_size / 1024.0 / 1024.0}]
    puts "Bitstream size: [format "%.2f" $bit_size_mb] MB"
    
    if {$bit_size_mb < 0.5} {
        puts "WARNING: Bitstream size is unusually small"
    }
} else {
    puts "ERROR: Bitstream file not found"
    exit 1
}

# Copy debug probes file if it exists
set ltx_files [glob -nocomplain $ltx_file]
if {[llength $ltx_files] > 0} {
    set source_ltx [lindex $ltx_files 0]
    set dest_ltx "${board_name}.ltx"
    file copy -force $source_ltx $dest_ltx
    puts "Debug probes copied to: $dest_ltx"
}

# Generate MCS file for flash programming
puts "Generating MCS file for flash programming..."
set mcs_file "${board_name}.mcs"

{%- if fpga_family == "7series" %}
write_cfgmem -format mcs -size 16 -interface SPIx4 -loadbit "up 0x0 $dest_bit" -file $mcs_file
{%- elif fpga_family == "ultrascale" or fpga_family == "ultrascale_plus" %}
write_cfgmem -format mcs -size 32 -interface SPIx4 -loadbit "up 0x0 $dest_bit" -file $mcs_file
{%- endif %}

if {[file exists $mcs_file]} {
    puts "MCS file generated: $mcs_file"
} else {
    puts "WARNING: MCS file generation failed"
}

# Final build summary
puts ""
puts "========================================="
puts "PCILeech Build Summary"
puts "========================================="
puts "Board: $board_name"
puts "FPGA: $fpga_part"
puts "Project: $project_name"
puts "Synthesis Strategy: $synthesis_strategy"
puts "Implementation Strategy: $implementation_strategy"
puts "Setup Timing (WNS): $timing_met ns"
puts "Hold Timing (WHS): $hold_met ns"
puts "Output Files:"
puts "  Bitstream: $dest_bit ([format "%.2f" $bit_size_mb] MB)"
if {[file exists $mcs_file]} {
    puts "  Flash File: $mcs_file"
}
if {[file exists $dest_ltx]} {
    puts "  Debug Probes: $dest_ltx"
}
puts "========================================="

if {$timing_met >= 0 && $hold_met >= 0} {
    puts "BUILD SUCCESSFUL - All timing constraints met"
} else {
    puts "BUILD COMPLETED - WARNING: Timing constraints not met"
}

# Close project
close_project

puts "PCILeech build completed!"