Initial commit
This commit is contained in:
@@ -0,0 +1,397 @@
|
||||
package require json
|
||||
|
||||
# Helper procedure for formatted messages
|
||||
proc _info {message} {
|
||||
puts [format "INFO: %s" $message]
|
||||
}
|
||||
proc _warn {message} {
|
||||
puts [format "WARN: %s" $message]
|
||||
}
|
||||
proc _error {message details} {
|
||||
error [format "ERROR: %s. Details: %s" $message $details]
|
||||
}
|
||||
|
||||
# Helper procedure to create hardware platform
|
||||
proc _prepare_platform {hw_file platform_name is_vitis} {
|
||||
if {![file exists $hw_file]} {
|
||||
_error "Hardware design file does not exist" $hw_file
|
||||
}
|
||||
_info "Creating hardware platform: $platform_name"
|
||||
if {$is_vitis} {
|
||||
platform create -name $platform_name -hw $hw_file
|
||||
_info "Platform '$platform_name' created successfully for Vitis."
|
||||
} else {
|
||||
sdk createhw -name $platform_name -hwspec $hw_file
|
||||
_info "Hardware platform '$platform_name' created successfully for Xilinx SDK."
|
||||
}
|
||||
}
|
||||
|
||||
# Helper procedure for BSP configuration
|
||||
proc _configure_bsp {bsp_name bsp_config platform_name is_vitis} {
|
||||
set cpu [dict get $bsp_config target_cpu]
|
||||
set os [dict get $bsp_config os]
|
||||
|
||||
# Create Domain/BSP
|
||||
_info "Creating BSP: $bsp_name for CPU: $cpu and OS: $os"
|
||||
if {$is_vitis} {
|
||||
platform active $platform_name
|
||||
domain create -name $bsp_name -os $os -proc $cpu
|
||||
domain active $bsp_name
|
||||
_info "BSP '$bsp_name' created for Vitis."
|
||||
} else {
|
||||
sdk createbsp -name $bsp_name -hwproject $platform_name -proc $cpu -os $os
|
||||
_info "BSP '$bsp_name' created for Xilinx SDK."
|
||||
}
|
||||
|
||||
# Apply BSP library configurations if they exist
|
||||
if {[dict exists $bsp_config libs]} {
|
||||
_info "Configuring BSP libraries..."
|
||||
dict for {lib_name lib_info} [dict get $bsp_config libs] {
|
||||
if {$is_vitis} {
|
||||
bsp setlib -name $lib_name -ver [dict get $lib_info version]
|
||||
} else {
|
||||
setlib -bsp $bsp_name -lib $lib_name -ver [dict get $lib_info version]
|
||||
}
|
||||
_info "Applied library '$lib_name' version '[dict get $lib_info version]' for BSP '$bsp_name'."
|
||||
if {[dict exists $lib_info config]} {
|
||||
dict for {param value} [dict get $lib_info config] {
|
||||
if {$is_vitis} {
|
||||
bsp config $param $value
|
||||
} else {
|
||||
configbsp -bsp $bsp_name $param $value
|
||||
}
|
||||
_info "Configured library '$lib_name': $param = $value"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Apply BSP configurations if they exist
|
||||
if {[dict exists $bsp_config config]} {
|
||||
_info "Configuring BSP options..."
|
||||
dict for {param value} [dict get $bsp_config config] {
|
||||
if {$is_vitis} {
|
||||
bsp config $param $value
|
||||
} else {
|
||||
configbsp -bsp $bsp_name $param $value
|
||||
}
|
||||
_info "Applied BSP configuration: $param = $value for $bsp_name"
|
||||
}
|
||||
}
|
||||
|
||||
if {$is_vitis} {
|
||||
bsp regenerate
|
||||
} else {
|
||||
regenbsp -bsp $bsp_name
|
||||
projects -build -type bsp -name $bsp_name
|
||||
}
|
||||
_info "BSP '$bsp_name' successfully configured and regenerated."
|
||||
return $bsp_name
|
||||
}
|
||||
|
||||
# Helper procedure to handle source files: link or copy based on LINK_SRCS
|
||||
proc _handle_sources {app_name sources} {
|
||||
# Check environment variable LINK_SRCS
|
||||
set link_srcs "y"
|
||||
if {[info exists ::env(LINK_SRCS)]} {
|
||||
set link_srcs $::env(LINK_SRCS)
|
||||
}
|
||||
|
||||
foreach source_file $sources {
|
||||
set source_path [file normalize $::root/$source_file]
|
||||
set target_path [file join $::ws $app_name [file tail $source_path]]
|
||||
|
||||
# Delete existing symbolic link or file if it exists
|
||||
if {[file exists $target_path]} {
|
||||
file delete -force $target_path
|
||||
_warn "Deleted existing link or file: $target_path"
|
||||
}
|
||||
|
||||
# Handle source based on the value of LINK_SRCS
|
||||
switch $link_srcs {
|
||||
"y" {
|
||||
# Create symbolic link
|
||||
file link -symbolic $target_path $source_path
|
||||
_info "Created symbolic link: $target_path -> $source_path"
|
||||
}
|
||||
"n" {
|
||||
# Copy the source file
|
||||
file copy $source_path $target_path
|
||||
_info "Copied source file: $source_path to $target_path"
|
||||
}
|
||||
default {
|
||||
_error "Unknown value for LINK_SRCS: ${link_srcs}."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc _update_app_mem_layout {app_name mem_layout} {
|
||||
|
||||
# Update heap and stack sizes in linker script if specified
|
||||
set lscript_path "$::ws/$app_name/src/lscript.ld"
|
||||
if {[file exists $lscript_path]} {
|
||||
set file_content {}
|
||||
set file_id [open $lscript_path r]
|
||||
while {[gets $file_id line] >= 0} {
|
||||
if {[regexp {^_HEAP_SIZE =} $line] && [dict exists $mem_layout heap_size]} {
|
||||
set heap_size [dict get $mem_layout heap_size]
|
||||
if {$heap_size ne ""} {
|
||||
set line "_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : $heap_size;"
|
||||
_info "Updating _HEAP_SIZE in linker script to $heap_size"
|
||||
} else {
|
||||
_warn "Empty `heap_size` config, _HEAP_SIZE not updated."
|
||||
}
|
||||
} elseif {[regexp {^_STACK_SIZE =} $line] && [dict exists $mem_layout stack_size]} {
|
||||
set stack_size [dict get $mem_layout stack_size]
|
||||
if {$stack_size ne ""} {
|
||||
set line "_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : $stack_size;"
|
||||
_info "Updating _STACK_SIZE in linker script to $stack_size"
|
||||
} else {
|
||||
_warn "Empty `stack_size` config, _STACK_SIZE not updated."
|
||||
}
|
||||
}
|
||||
lappend file_content $line
|
||||
}
|
||||
close $file_id
|
||||
|
||||
set file_id [open $lscript_path w]
|
||||
puts $file_id [join $file_content \n]
|
||||
close $file_id
|
||||
} else {
|
||||
_warn "Linker script $lscript_path not found for application: $app_name"
|
||||
}
|
||||
}
|
||||
|
||||
proc _update_app_build_config {app_name build_type build_config is_vitis} {
|
||||
set build_types {"debug" "release"}
|
||||
if {[lsearch $build_types $build_type] == -1} {
|
||||
_error "Invalid config type: $build_type" "available types: $build_types"
|
||||
}
|
||||
|
||||
set cmd [list]
|
||||
if {$is_vitis} {
|
||||
lappend cmd app config -name
|
||||
} else {
|
||||
lappend cmd sdk configapp -app
|
||||
}
|
||||
|
||||
_info "Setting build configuration for '$app_name' as $build_type."
|
||||
eval $cmd $app_name -set build-config $build_type
|
||||
|
||||
dict for {param value} $build_config {
|
||||
switch -exact -- $param {
|
||||
"include-path" {
|
||||
foreach path $value {
|
||||
eval $cmd $app_name include-path "../$path"
|
||||
_info "Append included path: $path for $app_name."
|
||||
}
|
||||
}
|
||||
"define-compiler-symbols" -
|
||||
"undef-compiler-symbols" -
|
||||
"libraries" -
|
||||
"library-search-path" {
|
||||
foreach item $value {
|
||||
eval $cmd $app_name $param $item
|
||||
_info "Append parameter $param: $item for $app_name."
|
||||
}
|
||||
}
|
||||
"assembler-flags" -
|
||||
"compiler-misc" -
|
||||
"compiler-optimization" -
|
||||
"linker-misc" -
|
||||
"linker-script" {
|
||||
if {$value ne ""} {
|
||||
eval $cmd $app_name -set $param $value
|
||||
_info "Set $param: $value for $app_name."
|
||||
}
|
||||
}
|
||||
default {
|
||||
_error "Unsupported app build-config option" $param
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Helper procedure for application configuration
|
||||
proc _create_app {app_name app_config platform_name is_vitis} {
|
||||
set cpu [dict get $app_config target_cpu]
|
||||
set os [dict get $app_config os]
|
||||
set lang [dict get $app_config language]
|
||||
set sources [dict get $app_config sources]
|
||||
set bsp_name "${os}_${cpu}"
|
||||
|
||||
# Configure BSP/Domain for application
|
||||
if {[dict exists $app_config bsp] && [dict get $app_config bsp] ne ""} {
|
||||
set bsp_name [dict get $app_config bsp]
|
||||
} else {
|
||||
set bsp_config [dict create]
|
||||
set bsp_config [dict set bsp_config target_cpu $cpu]
|
||||
set bsp_config [dict set bsp_config os $os]
|
||||
if {[dict exists $app_config bsp_lib]} {
|
||||
set bsp_lib [dict get $app_config bsp_lib]
|
||||
set bsp_config [dict merge $bsp_config [dict create libs $bsp_lib]]
|
||||
}
|
||||
if {[dict exists $app_config bsp_config]} {
|
||||
set bsp_cfg [dict get $app_config bsp_config]
|
||||
set bsp_config [dict merge $bsp_config [dict create config $bsp_cfg]]
|
||||
}
|
||||
_configure_bsp $bsp_name $bsp_config $platform_name $is_vitis
|
||||
}
|
||||
|
||||
# Create application
|
||||
_info "Creating application: $app_name"
|
||||
if {$is_vitis} {
|
||||
app create -name $app_name \
|
||||
-platform $platform_name \
|
||||
-domain $bsp_name \
|
||||
-proc $cpu \
|
||||
-os $os \
|
||||
-lang $lang \
|
||||
-sysproj $::project_name \
|
||||
-template "Empty Application($lang)"
|
||||
_info "Application '$app_name' created for Vitis."
|
||||
} else {
|
||||
sdk createapp -name $app_name \
|
||||
-hwproject $platform_name \
|
||||
-bsp $bsp_name \
|
||||
-proc $cpu \
|
||||
-os $os \
|
||||
-lang $lang \
|
||||
-app "Empty Application"
|
||||
_info "Application '$app_name' created for Xilinx SDK."
|
||||
}
|
||||
|
||||
# Handle source files if present
|
||||
if {[llength $sources] > 0} {
|
||||
_info "Handling sources for application: $app_name"
|
||||
_handle_sources $app_name $sources
|
||||
} else {
|
||||
_warn "No source files specified for application: $app_name"
|
||||
}
|
||||
|
||||
# Configure application if additional configs exist
|
||||
_info "Configuring application: $app_name"
|
||||
if {[dict exists $app_config build_config]} {
|
||||
dict for {build_type build_config} [dict get $app_config build_config] {
|
||||
_update_app_build_config $app_name $build_type $build_config $is_vitis
|
||||
}
|
||||
}
|
||||
|
||||
# Update memory layout in linker script if specified
|
||||
_info "Updating memory layout for application: $app_name"
|
||||
if {[dict exists $app_config mem_layout]} {
|
||||
set mem_layout [dict get $app_config mem_layout]
|
||||
_update_app_mem_layout $app_name $mem_layout
|
||||
}
|
||||
}
|
||||
|
||||
# Apply FSBL patches if specified
|
||||
# TODO:
|
||||
proc _apply_fsbl_patches {patches} {
|
||||
_info "Applying FSBL patches."
|
||||
dict for {target_file patch_file} $patches {
|
||||
set target_path "$::ws/fsbl/src/$target_file"
|
||||
set patch_path "$::root/$patch_file"
|
||||
|
||||
file copy -force $patch_path $target_path
|
||||
if {[file exists $patch_path]} {
|
||||
_info "Patched $target_file with $patch_file"
|
||||
} else {
|
||||
_warn "FSBL patch file $patch_path not found, new file $patch_file "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Main procedures
|
||||
proc create_project {} {
|
||||
cd $::ws
|
||||
setws $::ws
|
||||
_info "Workspace set to $::ws."
|
||||
|
||||
set is_vitis [expr {[string first ".hdf" $::hw_file] == -1}]
|
||||
set platform_name "${::project_name}_platform"
|
||||
|
||||
# Prepare hardware platform
|
||||
_prepare_platform $::hw_file $platform_name $is_vitis
|
||||
|
||||
# Process each bsp
|
||||
dict for {bsp_name bsp_config} [dict get $::config bsps] {
|
||||
_configure_bsp $bsp_name $bsp_config $platform_name $is_vitis
|
||||
}
|
||||
|
||||
# Process each application
|
||||
dict for {app_name app_config} [dict get $::config apps] {
|
||||
_create_app $app_name $app_config $platform_name $is_vitis
|
||||
}
|
||||
}
|
||||
|
||||
proc build_project {} {
|
||||
setws $::ws
|
||||
set is_vitis [expr {[string first ".hdf" $::hw_file] == -1}]
|
||||
if {$is_vitis} {
|
||||
# paltform file can be deleted by clean operation ahead
|
||||
platform active ${::project_name}_platform
|
||||
platform generate
|
||||
}
|
||||
|
||||
# Determine build type from environment
|
||||
set build_type "debug"
|
||||
if {[info exists ::env(RELEASE)] && $::env(RELEASE) == "y"} {
|
||||
set build_type "release"
|
||||
}
|
||||
_info "Build type: $build_type"
|
||||
|
||||
dict for {app_name app_config} [dict get $::config apps] {
|
||||
_info "Building application: $app_name"
|
||||
if {$is_vitis} {
|
||||
app config -name $app_name -set build-config $build_type
|
||||
app build -name $app_name
|
||||
_info "Application '$app_name' built for Vitis."
|
||||
} else {
|
||||
sdk configapp -app $app_name -set build-config $build_type
|
||||
projects -build -type app -name $app_name
|
||||
_info "Application '$app_name' built for Xilinx SDK."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc clean_project {} {
|
||||
setws $::ws
|
||||
_info "Cleaning project in workspace: $::ws."
|
||||
|
||||
set is_vitis [expr {[string first ".hdf" $::hw_file] == -1}]
|
||||
|
||||
dict for {app_name app_config} [dict get $::config apps] {
|
||||
_info "Cleaning application: $app_name"
|
||||
if {$is_vitis} {
|
||||
app clean -name $app_name
|
||||
} else {
|
||||
projects -clean -type app -name $app_name
|
||||
}
|
||||
_info "Application '$app_name' cleaned."
|
||||
}
|
||||
}
|
||||
|
||||
# Main execution
|
||||
set function [lindex $argv 0]
|
||||
set config_file [lindex $argv 1]
|
||||
set ws [file normalize [lindex $argv 2]]
|
||||
_info "Working at $ws"
|
||||
|
||||
# Load and parse configuration
|
||||
set config_file_id [open $config_file r]
|
||||
set config_data [read $config_file_id]
|
||||
close $config_file_id
|
||||
set root [file dirname [file normalize $config_file]]
|
||||
set config [json::json2dict $config_data]
|
||||
set project_name [dict get $config project_name]
|
||||
set hw_file [file normalize [file join [file dirname $config_file] [dict get $config hw_design]]]
|
||||
|
||||
_info "Starting process: $function"
|
||||
_info "Project name: $project_name"
|
||||
_info "Hardware design file: $hw_file"
|
||||
|
||||
# Execute requested function
|
||||
$function
|
||||
_info "Process $function completed."
|
||||
Reference in New Issue
Block a user