{#
PCIe UltraScale IP Configuration Template

This template generates PCIe UltraScale IP core configuration for
UltraScale and UltraScale+ parts.

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

puts "Creating PCIe UltraScale IP core for device {{ device.vendor_id }}:{{ device.device_id }}..."
puts "FPGA Part: {{ board.fpga_part }}"
puts "Board: {{ board.name }}"

# Update IP catalog to ensure all IP cores are available
puts "Updating IP catalog..."
update_ip_catalog

# Check available PCIe IP cores
puts "Available PCIe IP cores:"
set available_ips [get_ipdefs -filter {NAME =~ "*pcie*"}]
foreach ip $available_ips {
    puts "  [get_property NAME $ip] - [get_property VERSION $ip]"
}

# Try to create PCIe UltraScale IP core (try without version first)
set pcie_created 0
if {[catch {
    create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_bridge
    set pcie_created 1
    puts "Successfully created PCIe UltraScale IP core (auto version)"
}]} {
    puts "Failed to create PCIe IP without version, trying with version 1.3..."
    if {[catch {
        create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -version 1.3 -module_name pcie4_uscale_plus_bridge
        set pcie_created 1
        puts "Successfully created PCIe UltraScale IP core (version 1.3)"
    }]} {
        puts "Failed to create PCIe IP with version 1.3, trying latest available..."
        # Get the latest available version
        set pcie_versions [get_ipdefs -filter {NAME == "pcie4_uscale_plus"}]
        if {[llength $pcie_versions] > 0} {
            set latest_version [lindex $pcie_versions 0]
            set version_str [get_property VERSION $latest_version]
            puts "Trying latest available version: $version_str"
            if {[catch {
                create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -version $version_str -module_name pcie4_uscale_plus_bridge
                set pcie_created 1
                puts "Successfully created PCIe UltraScale IP core (version $version_str)"
            }]} {
                puts "ERROR: Failed to create PCIe IP core with any available version"
                puts "This may indicate that PCIe IP is not installed or not available for this FPGA part"
                exit 1
            }
        } else {
            puts "ERROR: No PCIe UltraScale IP cores found in catalog"
            puts "Please ensure PCIe IP is installed in Vivado"
            exit 1
        }
    }
}

if {!$pcie_created} {
    puts "ERROR: Failed to create PCIe IP core"
    exit 1
}

# Get IP instance for cleaner code
set ip [get_ips pcie4_uscale_plus_bridge]

# Configure PCIe UltraScale IP core with device-specific settings
set_property -dict [list \
    CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {2.5_GT/s} \
    CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X1} \
    CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \
    CONFIG.PF0_DEVICE_ID {0x{{ device.device_id }}} \
    CONFIG.PF0_VENDOR_ID {0x{{ device.vendor_id }}} \
    CONFIG.PF0_SUBSYSTEM_VENDOR_ID {0x{{ device.vendor_id }}} \
    CONFIG.PF0_SUBSYSTEM_ID {0x0000} \
    CONFIG.PF0_REVISION_ID {0x{{ device.revision_id }}} \
    CONFIG.PF0_CLASS_CODE {0x040300} \
    CONFIG.PF0_BAR0_SCALE {Kilobytes} \
    CONFIG.PF0_BAR0_SIZE {128} \
    CONFIG.PF0_MSI_ENABLED {false} \
    CONFIG.PF0_MSIX_ENABLED {true} \
] $ip

# Generate IP targets for complete synthesis flow
generate_target {instantiation_template synthesis implementation} $ip

# Export IP user files for out-of-context runs
export_ip_user_files -of_objects $ip -force

puts "PCIe UltraScale IP core configuration completed"