{#- PCILeech Project Generation Script Template -#}
{#- This replaces the current 7-script approach with PCILeech's unified project generation -#}
{{ header_comment }}
# PCILeech Unified Project Generation Script
# Generated by PCILeechFWGenerator - PCILeech Integration
# Board: {{ board_name }}
# FPGA: {{ fpga_part }}
# Family: {{ fpga_family }}

# Set error handling
set_msg_config -id {Common 17-55} -suppress
set_msg_config -id {Vivado 12-1387} -suppress

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

# PCILeech directory structure
set src_dir "{{ pcileech.src_dir }}"
set ip_dir "{{ pcileech.ip_dir }}"

# Create project directory if it doesn't exist
file mkdir $project_dir

# Create Vivado project
create_project $project_name $project_dir -part $fpga_part -force

# Set project properties
set_property target_language Verilog [current_project]
set_property simulator_language Mixed [current_project]
set_property default_lib xil_defaultlib [current_project]

{% if fpga_family == "ultrascale" or fpga_family == "ultrascale_plus" %}
# UltraScale/UltraScale+ specific settings
set_property XPM_LIBRARIES {XPM_CDC XPM_MEMORY XPM_FIFO} [current_project]
{% endif %}

# Create source directory structure
file mkdir [file join $project_dir $src_dir]
file mkdir [file join $project_dir $ip_dir]

puts "Created PCILeech directory structure:"
puts "  Source directory: $src_dir"
puts "  IP directory: $ip_dir"

# Add SystemVerilog source files
{% if pcileech.source_files %}
puts "Adding SystemVerilog source files..."
{% for source_file in pcileech.source_files %}
if {[file exists "{{ source_file }}"]} {
    add_files -norecurse "{{ source_file }}"
    puts "  Added: {{ source_file }}"
} else {
    puts "  Warning: Source file not found: {{ source_file }}"
}
{% endfor %}
{% else %}
# Add all SystemVerilog files from src directory
if {[file exists $src_dir]} {
    set sv_files [glob -nocomplain [file join $src_dir "*.sv"]]
    set v_files [glob -nocomplain [file join $src_dir "*.v"]]
    
    foreach sv_file $sv_files {
        add_files -norecurse $sv_file
        puts "  Added SystemVerilog: [file tail $sv_file]"
    }
    
    foreach v_file $v_files {
        add_files -norecurse $v_file
        puts "  Added Verilog: [file tail $v_file]"
    }
}
{% endif %}

# Configure PCIe IP Core based on FPGA family
puts "Configuring PCIe IP Core for {{ pcie_ip_type }}..."

{% if pcie_ip_type == "axi_pcie" %}
# AXI PCIe IP for smaller Artix-7 devices
create_ip -name axi_pcie -vendor xilinx.com -library ip -module_name pcie_axi_bridge
set_property -dict [list \
    CONFIG.LINK_SPEED {2.5_GT/s} \
    CONFIG.PCIE_CAP_SLOT_IMPLEMENTED {false} \
    CONFIG.BAR0_ENABLED {true} \
    CONFIG.BAR0_TYPE {Memory} \
    CONFIG.BAR0_64BIT {true} \
    CONFIG.BAR0_SIZE "{1}" \
    CONFIG.DEVICE_ID "{{ device.device_id if device.device_id else 0x7021 }}" \
    CONFIG.VENDOR_ID "{{ device.vendor_id if device.vendor_id else 0x10EE }}" \
    CONFIG.Class_Code_Base "2" \
    CONFIG.Class_Code_Interface "0" \
    CONFIG.Class_Code_Sub "0" \
    CONFIG.REV_ID "{{ device.revision_id if device.revision_id else 0x00 }}" \
    CONFIG.SUBSYSTEM_ID "{0x0007}" \
    CONFIG.SUBSYSTEM_VENDOR_ID "{{ device.vendor_id if device.vendor_id else 0x10EE }}" \
] [get_ips pcie_axi_bridge]

{% elif pcie_ip_type == "pcie_ultrascale" %}
# UltraScale PCIe IP
create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie_ultrascale_bridge
set_property -dict [list \
    CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \
    CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X{{ max_lanes }}} \
    CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \
    CONFIG.PF0_DEVICE_ID {{ device.device_id if device.device_id else "0x9021" }} \
    CONFIG.PF0_VENDOR_ID {{ device.vendor_id if device.vendor_id else "0x10EE" }} \
    CONFIG.PF0_CLASS_CODE {{ device.class_code if device.class_code else "0x058000" }} \
    CONFIG.PF0_REVISION_ID {{ device.revision_id if device.revision_id else "0x00" }} \
    CONFIG.PF0_SUBSYSTEM_ID {0x0007} \
    CONFIG.PF0_SUBSYSTEM_VENDOR_ID {{ device.vendor_id if device.vendor_id else "0x10EE" }} \
    CONFIG.PF0_BAR0_ENABLED {true} \
    CONFIG.PF0_BAR0_64BIT {true} \
    CONFIG.PF0_BAR0_SIZE {1} \
] [get_ips pcie_ultrascale_bridge]

{% else %}
# TEMPLATE FILE: /src/templates/tcl/pcileech_generate_project.j2
# 7-Series PCIe IP (default)
create_ip -name pcie_7x -vendor xilinx.com -library ip -module_name pcie_7x_bridge
set_property -dict [list \
    CONFIG.Link_Speed {2.5_GT/s} \
    CONFIG.Maximum_Link_Width X1 \
    CONFIG.Device_ID {{ device_id if device_id else 28705 }} \
    CONFIG.Vendor_ID {{ vendor_id if vendor_id else 4332 }} \
    CONFIG.Revision_ID {{ revision_id if revision_id else 0 }} \
    CONFIG.Class_Code_Base {02} \
    CONFIG.Class_Code_Interface {00} \
    CONFIG.Class_Code_Sub {00} \
    CONFIG.Subsystem_ID {{ device.subsys_device_id if device.subsys_device_id else 7 }} \
    CONFIG.Subsystem_Vendor_ID {{ device.subsys_vendor_id if device.subsys_vendor_id else 4332 }} \
    CONFIG.Bar0_Enabled {true} \
    CONFIG.Bar0_Type {Memory} \
    CONFIG.Bar0_64bit {true} \
    CONFIG.Bar0_Size {1}{% if supports_msi %} \
    CONFIG.MSI_Enabled {true}{% endif %}{% if supports_msix %} \
    CONFIG.MSIx_Enabled {true}{% endif %} \
] [get_ips pcie_7x_bridge]
{% endif %}

# Add IP files to project
{% if pcileech.ip_files %}
puts "Adding IP core files..."
{% for ip_file in pcileech.ip_files %}
if {[file exists "{{ ip_file }}"]} {
    add_files -norecurse "{{ ip_file }}"
    puts "  Added IP: {{ ip_file }}"
} else {
    puts "  Warning: IP file not found: {{ ip_file }}"
}
{% endfor %}
{% endif %}

# Add coefficient files if present
{% if pcileech.coefficient_files %}
puts "Adding coefficient files..."
{% for coeff_file in pcileech.coefficient_files %}
if {[file exists "{{ coeff_file }}"]} {
    add_files -norecurse "{{ coeff_file }}"
    puts "  Added coefficient file: {{ coeff_file }}"
} else {
    puts "  Warning: Coefficient file not found: {{ coeff_file }}"
}
{% endfor %}
{% endif %}

# Add constraint files
puts "Adding constraint files..."
{% if constraint_files %}
{% for constraint_file in constraint_files %}
if {[file exists "{{ constraint_file }}"]} {
    add_files -fileset constrs_1 -norecurse "{{ constraint_file }}"
    puts "  Added constraint: {{ constraint_file }}"
} else {
    puts "  Warning: Constraint file not found: {{ constraint_file }}"
}
{% endfor %}
{% else %}
# Add all XDC files from current directory
set xdc_files [glob -nocomplain "*.xdc"]
foreach xdc_file $xdc_files {
    add_files -fileset constrs_1 -norecurse $xdc_file
    puts "  Added constraint: [file tail $xdc_file]"
}
{% endif %}

# Set top-level module
{% if pcileech.source_files and pcileech.source_files|length > 0 %}
# Try to determine top module from first source file
set top_module [file rootname [file tail "{{ pcileech.source_files[0] }}"]]
{% else %}
# Top module will be auto-detected by Vivado
set top_module ""
{% endif %}

# Set source management mode to manual before setting top
set_property source_mgmt_mode None [current_project]
if {$top_module != ""} {
    set_property top $top_module [current_fileset]
    puts "Set top module: $top_module"
} else {
    puts "Top module will be auto-detected by Vivado"
}

# Update compile order
update_compile_order -fileset sources_1

# Generate IP cores
puts "Generating IP cores..."
generate_target all [get_files *.xci]
catch {config_ip_cache -export [get_ips -all]}

# Skip validation (validate_design is not available in all Vivado versions)
puts "Skipping design validation..."
# validate_design -quiet

puts "PCILeech project generation completed successfully!"
puts "Project: $project_name"
puts "Location: $project_dir"
puts "FPGA Part: $fpga_part"
puts "PCIe IP Type: {{ pcie_ip_type }}"
puts "Max Lanes: {{ max_lanes }}"
{% if supports_msi %}
puts "MSI Support: Enabled"
{% endif %}
{% if supports_msix %}
puts "MSI-X Support: Enabled"
{% endif %}

# Save project
save_project_as $project_name $project_dir -force

puts "Project saved. Ready for build phase."
