{#
# USB-required commit 2025-06-16
Constraints Template - Timing and Physical Constraints Management

This template generates timing constraints and pin assignments based on the
current tcl_generator.py implementation.

IMPORTANT: Pin assignments are based on existing PCILeech XDC files from the
official repository. For board-specific constraints, refer to:
https://github.com/ufrisk/pcileech-fpga/tree/master/

Available board-specific XDC files:
- CaptainDMA/75t484_x1/src/pcileech_75t484_x1_captaindma_75t.xdc
- CaptainDMA/100t484_x1/src/pcileech_100t484_x1_captaindma_100t.xdc
- And others for different FPGA variants

Please update the pin assignments below for your specific board and FPGA package.

Context variables expected:
- device: Device information (vendor_id, device_id)
- board: Board information (name)
- header: TCL header comment
#}
{{ header }}

puts "Adding constraint files..."

# Get script directory for reliable path resolution
set script_dir [file dirname [info script]]

# Add generated board-specific XDC file if available
{% if generated_xdc_path %}
set generated_xdc "{{ generated_xdc_path }}"
if {[file exists $generated_xdc]} {
    puts "Adding generated XDC constraints: $generated_xdc"
    add_files -fileset constrs_1 -norecurse $generated_xdc
}
{% endif %}

# Add all other constraint files (excluding already added board-specific files)
# Use explicit directory to avoid pulling stale XDC from sibling directories
set xdc_files [glob -nocomplain -directory $script_dir *.xdc]
set already_added_files [list]
{% if board.constraints and board.constraints.xdc_file %}
lappend already_added_files "{{ board.constraints.xdc_file }}"
{% endif %}

# Filter out already added files
set filtered_xdc_files [list]
foreach xdc_file $xdc_files {
    if {[lsearch -exact $already_added_files $xdc_file] == -1} {
        lappend filtered_xdc_files $xdc_file
    }
}

if {[llength $filtered_xdc_files] > 0} {
    puts "Found [llength $filtered_xdc_files] additional constraint files"
    add_files -fileset constrs_1 -norecurse $filtered_xdc_files
    foreach xdc_file $filtered_xdc_files {
        puts "  - $xdc_file"
    }
}

# Generate device-specific timing constraints
puts "Adding device-specific timing constraints..."
# Try to use board-specific XDC constraints if board type is specified
{% if board and board.name %}
puts "Attempting to load board-specific XDC constraints for: {{ board.name }}"

{% if board.constraints and board.constraints.xdc_file %}
# Load board-specific XDC file
puts "Constraints for {{ board.name }}"
set board_xdc_file "{{ board.constraints.xdc_file }}"
if {[file exists $board_xdc_file]} {
    add_files -fileset constrs_1 -norecurse $board_xdc_file
    lappend already_added_files $board_xdc_file
    puts "Added board-specific XDC constraints: $board_xdc_file"
} else {
    error "Missing required XDC for board {{ board.name }} - aborting build."
}
{% elif board_xdc_content %}
# Load XDC constraints from PCILeech repository
# This will be populated by the constraint generation system
# with actual XDC content from the PCILeech FPGA repository
# Write board XDC content to temporary file to avoid brace/semicolon issues
set board_auto_xdc_file [file join $script_dir "{{ board.name }}_auto.xdc"]
set fp [open $board_auto_xdc_file w]
puts $fp {{{ board_xdc_content }}}
close $fp
add_files -fileset constrs_1 -norecurse $board_auto_xdc_file
read_xdc $board_auto_xdc_file
puts "Added auto-generated board XDC: $board_auto_xdc_file"
{% else %}
error "Missing required XDC for board {{ board.name }} - aborting build."
{% endif %}
{% endif %}

# Generate device-specific timing constraints file
{% set sys_clk_period = (1000.0 / (sys_clk_freq_mhz | default(100))) | round(3) %}
set timing_constraints_content {
# Clock constraints - {{ sys_clk_freq_mhz | default(100) }} MHz system clock
create_clock -period {{ sys_clk_period }} -name sys_clk [get_ports clk]

# Input delay constraints for actual input ports
set_input_delay -clock sys_clk 2.000 [get_ports reset_n]

# Device-specific constraints for {{ device.vendor_id }}:{{ device.device_id }}
# Board-specific pin assignments for {{ board.name }}

# NOTE: Pin assignments MUST be loaded from board-specific XDC files from the PCILeech repository.
# We NEVER generate fallback XDC content as it contains critical pin assignments.
}

# Write timing constraints to file
set constraints_file [file join $script_dir "device_constraints.xdc"]
set fp [open $constraints_file w]
puts $fp $timing_constraints_content
close $fp
add_files -fileset constrs_1 -norecurse $constraints_file
read_xdc $constraints_file
set_property PROCESSING_ORDER LATE [get_files $constraints_file]
puts "Generated device constraints file: $constraints_file"

# Quality-of-life tweaks for USB-heavy designs
{% if board.features %}
set_param xicom.use_bs_reader 1
puts "Enabled fast bitstream reader for FT601 board"
{% endif %}

puts "Constraints setup completed"