Initial commit
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
# Xilinx 平台配置指南 (HOWTO)
|
||||
|
||||
## 目录结构说明
|
||||
|
||||
- **build.bat**: 用于在 Windows 系统上运行的批处理脚本,负责自动化构建整个项目;
|
||||
|
||||
- **launch.bat**: 用于启动 Xilinx SDK 或 Vitis 的批处理脚本,适用于在 Windows 系统上打开开发环境,加载并查看生成的工程;
|
||||
|
||||
- **setenv.bat**: 运行环境配置脚本,用于在 Windows 系统中设置 Xilinx 开发工具的环境变量,通常在构建或启动项目前运行;
|
||||
|
||||
- **template.gitignore**: 针对 Xilinx 工具的 `.gitignore` 模板文件,用户可以将其内容复制到实际的 `.gitignore` 文件中;
|
||||
|
||||
- **template.json**: 项目的 JSON 配置模板文件,定义了工程的基本配置,具体配置参数请参考[配置文件结构](#配置文件结构);
|
||||
|
||||
- **util.tcl**: 包含一组通用工具命令的 TCL 脚本,用于辅助自动化构建过程。此文件在构建过程中被调用,用于与开发工具交互执行 Xilinx 工具相关的特定操作;
|
||||
|
||||
- **xilinx.mk**: 被 [`generic.mk`](../../generic.mk) 定义了 Xilinx 平台的特定的编译规则;
|
||||
|
||||
## 配置文件结构
|
||||
|
||||
配置文件用于定义 Xilinx 平台项目的构建参数、应用配置和库依赖关系等信息,以便于在 `embedded-autobuild` 项目中自动化生成工程。以下是 Xilinx 配置文件各部分的详细说明。
|
||||
|
||||
> **注**:以下针对字段的解释中 **加粗** 字段为必须参数,*斜体* 标注的字段为可选参数,可选参数不填写则使用对应 IDE 的默认配置。
|
||||
|
||||
### 基本字段
|
||||
|
||||
- **project_name**: 项目名称,例如 `"demo"`。
|
||||
- **version**: 项目版本,例如 `"0.0.0"`。
|
||||
- **hw_design**: 硬件设计文件(`.hdf` 或 `.xsa` 文件)路径(相对配置文件路径),例如 `"demo_v0.0.0.hdf"`。
|
||||
|
||||
### *fsbl_patch* (TODO)
|
||||
|
||||
用于配置 `FSBL` (First Stage Bootloader) 的补丁文件。可以包含多个补丁文件以满足自定义的硬件启动需求。
|
||||
|
||||
```json
|
||||
"fsbl_patch": {
|
||||
"<patch_target0>": "<patch_file0>",
|
||||
"<patch_target1>": "<patch_file1>"
|
||||
}
|
||||
```
|
||||
|
||||
其基本格式为 `<patch_target>: <patch_file>`,`<patch_target>` 是 FSBL 中需要被替换的文件,`<patch_file>` 为准备好的替换补丁文件。
|
||||
|
||||
### *bsps*
|
||||
|
||||
该字段用于定义 BSP 或者 Domain 的配置,支持多个 BSP/Domain 配置。
|
||||
|
||||
```json
|
||||
"bsps": {
|
||||
"<bsp_name>": {
|
||||
"os": "<os_type>",
|
||||
"target_cpu": "<cpu_id>",
|
||||
"libs": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
...
|
||||
}
|
||||
}
|
||||
...
|
||||
},
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
...
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
- **os**: 操作系统类型,支持的类型有 `standalone`,`freetos`,`linux`[^1];
|
||||
- **target_cpu**: 目标 CPU[^2],例如 "ps7_cortexa9_0" 表示 Zynq-7000 系列的 ARM Cortex-A9 核;
|
||||
-*libs*: 必要的库及其版本配置[^1],该配置项下可包含多个 `lib` 配置,默认不添加任何 `lib`;
|
||||
- **version**: `lib` 版本 [^1];
|
||||
-*config*: 其他具体 `lib` 设置[^1],不填写则使用 IDE 默认配置;
|
||||
-*config*: 其他具体 BSP/Domain 设置[^1],不填写则使用 IDE 默认配置;
|
||||
|
||||
以下配置添加了一个名为 "standalone" 的 BSP/Domain 工程,添加了 `xilffs` 和 `xilrsa` 两个 `lib,其中` `xilffs` 启用了长文件名(use_lfn)以及exFAT(enable_exfat)支持,并设置了标准输入输出为 `ps7_coresight_comp_0`,sleep 计数器使用 `ps7_globaltimer_0`.
|
||||
|
||||
```json
|
||||
"bsps": {
|
||||
"standalone": {
|
||||
"os": "standalone",
|
||||
"target_cpu": "ps7_cortexa9_0",
|
||||
"libs": {
|
||||
"xilffs": {
|
||||
"version": "4.1",
|
||||
"config": {
|
||||
"use_lfn": true,
|
||||
"enable_exfat": true
|
||||
}
|
||||
},
|
||||
"xilrsa": {
|
||||
"version": "1.5"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"stdin": "ps7_coresight_comp_0",
|
||||
"stdout": "ps7_coresight_comp_0",
|
||||
"sleep_timer": "ps7_globaltimer_0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### apps
|
||||
|
||||
该字段定义应用的具体构建配置,包括目标 CPU、操作系统、内存布局等,编译参数等。
|
||||
|
||||
```json
|
||||
"apps": {
|
||||
"<app_name>": {
|
||||
"sources": ["dir0", "dir1"],
|
||||
"target_cpu": "<cpu_id>",
|
||||
"os": "<os_type>",
|
||||
"language": "<language>",
|
||||
"bsp": "<bsp_name>",
|
||||
"bsp_lib": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bsp_config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
},
|
||||
"mem_layout" : {
|
||||
"heap_size": "<heap_size>",
|
||||
"stack_size": "<stack_size>"
|
||||
},
|
||||
"build_config": {
|
||||
"<config_name>": {
|
||||
"assembler-flags": "<assembler-flags>",
|
||||
"compiler-misc": "<compiler-misc>",
|
||||
"compiler-optimization": "<compiler-optimization>",
|
||||
"linker-misc": "<linker-misc>",
|
||||
"linker-script": "<linker-script>",
|
||||
"define-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"undef-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"include-path": ["<dir0>", "<dir1>"],
|
||||
"libraries": ["<lib0>", "<lib1>"],
|
||||
"library-search-path": ["<dir0>", "<dir1>"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **sources**: 源文件列表(相对配置文件路径);
|
||||
- **target_cpu**: 目标 CPU ID[^2];
|
||||
- **os**: 操作系统类型[^1],必须与 BSP/Domain 匹配;
|
||||
- **language**: 编程语言,"C" 或 "C++";
|
||||
-*bsp*: 应用所使用的 BSP 名称,若未指定则会自动创建名为 `<os>_<cpu_id>` 的 BSP/Domain.
|
||||
-*bsp_lib*: 针对自动创建的 BSP/Domain 所使用库的配置,与 [bsps](#-bsps) 中 `libs` 对应;
|
||||
-*bsp_config*: 针对自动创建的 BSP/Domain 配置与 [bsps](#-bsps) 中 `config` 对应;
|
||||
-*mem_layout*: 应用内存布局,包括堆栈大小和堆大小等;
|
||||
-*heap_size*: 堆大小,必须写为十六进制,例如 "0x80000";
|
||||
-*stack_size*: 栈大小,必须写为十六进制,例如 "0x4000";
|
||||
-*build_config*: 编译目标配置,`release` 或 `debug`;
|
||||
-`assembler-flags`: 汇编器标志;
|
||||
-`compiler-misc`: 其他编译器选项;
|
||||
-`compiler-optimization`: 编译优化选项;
|
||||
-`linker-misc`: 链接器选项;
|
||||
-`linker-script`: 链接脚本路径;
|
||||
-`define-compiler-symbols`: 自定义的编译器宏定义符号列表;
|
||||
-`undef-compiler-symbols`: 要取消定义的符号列表;
|
||||
-`include-path`: 包含文件路径;
|
||||
-`libraries`: 需要链接的库;
|
||||
-`library-search-path`: 库搜索路径;
|
||||
|
||||
以下配置添加了一个名为 `demo_app` 的 Application 工程,该工程没有指定 BSP/Domain 但能够通过 `bsp_lib` 和 `bsp_config` 自动生成一个名为 `standalone_ps7_cortexa9_0` 的 BSP/Domain 工程。
|
||||
|
||||
```json
|
||||
"apps": {
|
||||
"demo_app": {
|
||||
"sources": ["source/"],
|
||||
"target_cpu": "ps7_cortexa9_0",
|
||||
"os": "standalone",
|
||||
"language": "C",
|
||||
"bsp_lib": {
|
||||
"xilffs": {
|
||||
"version": "5.2",
|
||||
"config": {
|
||||
"use_lfn": true,
|
||||
"enable_exfat": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"bsp_config": {
|
||||
"sleep_timer": "ps7_globaltimer_0",
|
||||
"stdin": "ps7_uart_1",
|
||||
"stdout": "ps7_uart_1"
|
||||
},
|
||||
"mem_layout" : {
|
||||
"heap_size": "0x80000",
|
||||
"stack_size": "0x4000"
|
||||
},
|
||||
"build_config": {
|
||||
"debug": {
|
||||
"define-compiler-symbols": ["XILINX_PLATFORM", "_DEBUG_LEVEL_=1"],
|
||||
"include-path": ["source/include"],
|
||||
},
|
||||
"release": {
|
||||
"define-compiler-symbols": ["XILINX_PLATFORM"],
|
||||
"include-path": ["source/include"],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 完整配置示例
|
||||
|
||||
以下为最小化完整配置示例,包含了所有必填字段,可作为基础配置参考。
|
||||
|
||||
```json
|
||||
{
|
||||
"project_name": "demo",
|
||||
"version": "0.0.0",
|
||||
"hw_design": "demo_v0.0.0.hdf",
|
||||
"apps": {
|
||||
"demo_app": {
|
||||
"sources": ["source/"],
|
||||
"target_cpu": "ps7_cortexa9_0",
|
||||
"os": "standalone",
|
||||
"language": "C",
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[^1]: 具体可配置项取决于对应 IDE 版本;
|
||||
|
||||
[^2]: 具体可选 CPU ID 取决于硬件型号;
|
||||
@@ -0,0 +1,44 @@
|
||||
@echo off
|
||||
REM Check if exactly two arguments are provided and not empty
|
||||
if "%~2"=="" (
|
||||
echo Usage: build.bat ^<config^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
if not "%~3"=="" (
|
||||
echo Usage: build.bat ^<config^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Check if the config file exists
|
||||
set "config=%1"
|
||||
if not exist "%config%" (
|
||||
echo Error: Config file "%config%" does not exist.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Check if the build directory already exists
|
||||
set "work_dir=%2"
|
||||
if exist "%work_dir%" (
|
||||
echo Error: The build folder already exists.
|
||||
echo "%work_dir%" folder needs to be deleted before the project can be recreated.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Create the build directory
|
||||
mkdir "%work_dir%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to create the build directory: "%work_dir%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Start xsct and wait for it to finish
|
||||
echo Invoking project build...
|
||||
@REM cmd /c "cd /d %~dp0 && xsct util.tcl create_project \"%config%\" \"%work_dir%\" || exit /b %errorlevel%"
|
||||
xsct %~dp0util.tcl create_project "%config%" "%work_dir%"
|
||||
if %errorlevel% NEQ 0 (
|
||||
echo Error: xsct execution failed with error code %ERRORLEVEL%.
|
||||
echo Please check your configurations.
|
||||
exit /b %ERRORLEVEL%
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
@@ -0,0 +1,53 @@
|
||||
@echo off
|
||||
REM Check if exactly two arguments are provided and not empty
|
||||
if "%~2"=="" (
|
||||
echo Usage: launch.bat ^<version^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
if not "%~3"=="" (
|
||||
echo Usage: launch.bat ^<version^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Use regex to check if input version code is valid
|
||||
set "xilinx_version=%1"
|
||||
set "version_pattern=20[12][01234789][.][12]"
|
||||
echo %xilinx_version% | findstr /r /c:"%version_pattern%" >nul
|
||||
if %errorlevel% NEQ 0 (
|
||||
echo Error: %xilinx_version% is not a valid version coede ^(e.g., 2019.1^)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Check if the build directory already exists
|
||||
set "work_dir=%2"
|
||||
if not exist "%work_dir%" (
|
||||
echo Error: no `%work_dir%' folder
|
||||
echo try to create project before launching SDK
|
||||
pause >nul
|
||||
)
|
||||
|
||||
REM Convert it to a integer
|
||||
for /f "tokens=1,2 delims=." %%a in ("%xilinx_version%") do (
|
||||
set major=%%a
|
||||
set minor=%%b
|
||||
)
|
||||
set /a version_number=%major%%minor%
|
||||
set /a lowest_vits_version=20192
|
||||
set /a new_vits_version=20232
|
||||
|
||||
REM Determine which tool to launch based on the Xilinx version
|
||||
if %version_number% lss %lowest_vits_version% (
|
||||
REM Version is less than 2019.2, use xsdk
|
||||
echo Launching Xilinx SDK...
|
||||
xsdk -workspace "%work_dir%"
|
||||
) else if %version_number% lss %new_vits_version% (
|
||||
REM Version is between 2019.2 and 2023.1, use vitis
|
||||
echo Launching Xilinx Vitis...
|
||||
vitis -workspace "%work_dir%"
|
||||
) else (
|
||||
REM Version is 2023.2 or higher, use vitis -classic
|
||||
echo Launching Xilinx Vitis Classic...
|
||||
vitis -classic -workspace "%work_dir%"
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
@@ -0,0 +1,52 @@
|
||||
@echo off
|
||||
REM Check if exactly two arguments are provided and not empty
|
||||
if "%~1"=="" (
|
||||
echo Usage: setenv_xilinx.bat ^<version^>
|
||||
exit /b 1
|
||||
)
|
||||
if not "%~2"=="" (
|
||||
echo Usage: setenv_xilinx.bat ^<version^>
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Use regex to check if input version code is valid
|
||||
set "xilinx_version=%1"
|
||||
set "version_pattern=20[12][01234789][.][12]"
|
||||
echo %xilinx_version% | findstr /r /c:"%version_pattern%" >nul
|
||||
if %errorlevel% NEQ 0 (
|
||||
echo Error: %xilinx_version% is not a valid version coede ^(e.g., 2019.1^)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Convert it to a integer
|
||||
for /f "tokens=1,2 delims=." %%a in ("%xilinx_version%") do (
|
||||
set major=%%a
|
||||
set minor=%%b
|
||||
)
|
||||
set /a version_number=%major%%minor%
|
||||
set /a lowest_vitis_version=20192
|
||||
|
||||
REM Determine the correct settings.bat path based on the Xilinx version
|
||||
if %version_number% lss %lowest_vitis_version% (
|
||||
echo Setup enviroment for Xilinx SDK.
|
||||
set settings_bat=C:\Xilinx\SDK\%xilinx_version%\settings64.bat
|
||||
) else (
|
||||
echo Setup enviroment for Xilinx Vitis.
|
||||
set settings_bat=C:\Xilinx\Vitis\%xilinx_version%\settings64.bat
|
||||
)
|
||||
|
||||
REM Check if the settings.bat file exists
|
||||
if not exist "%settings_bat%" (
|
||||
echo Error: Could not find settings file at %settings_bat%.
|
||||
echo Please check your Xilinx tools installation.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Call the settings.bat file to set up the environment
|
||||
call "%settings_bat%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to source "%settings_bat%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
@@ -0,0 +1,32 @@
|
||||
# Buid folder
|
||||
build/
|
||||
|
||||
# Xilinx tools generated files
|
||||
.metadata/
|
||||
.settings/
|
||||
.wsdata/
|
||||
.Xil/
|
||||
logs/
|
||||
Packages/
|
||||
*.log*
|
||||
|
||||
# System generated files
|
||||
# -- macOS
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
._*
|
||||
|
||||
# -- Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# -- Linux
|
||||
*~
|
||||
|
||||
# IDEs and editors' files
|
||||
*.idea
|
||||
*.vscode
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"project_name": "<project_name>",
|
||||
"version": "<project_version>",
|
||||
"hw_design": "<hw_design>",
|
||||
"fsbl_patch": {
|
||||
"<patch_target0>": "<patch_file0>",
|
||||
"<patch_target1>": "<patch_file1>"
|
||||
},
|
||||
"bsps": {
|
||||
"<bsp_name>": {
|
||||
"os": "<os_type>",
|
||||
"target_cpu": "<cpu_id>",
|
||||
"lib": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"apps": {
|
||||
"<app_name>": {
|
||||
"sources": ["dir0", "dir1"],
|
||||
"target_cpu": "<cpu_id>",
|
||||
"os": "<os_type>",
|
||||
"language": "<language>",
|
||||
"bsp": "<bsp_name>",
|
||||
"bsp_lib": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bsp_config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
},
|
||||
"mem_layout" : {
|
||||
"heap_size": "<heap_size>",
|
||||
"stack_size": "<stack_size>"
|
||||
},
|
||||
"build_config": {
|
||||
"<config_name>": {
|
||||
"assembler-flags": "<assembler-flags>",
|
||||
"compiler-misc": "<compiler-misc>",
|
||||
"compiler-optimization": "<compiler-optimization>",
|
||||
"linker-misc": "<linker-misc>",
|
||||
"linker-script": "<linker-script>",
|
||||
"define-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"undef-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"include-path": ["<dir0>", "<dir1>"],
|
||||
"libraries": ["<lib0>", "<lib1>"],
|
||||
"library-search-path": ["<dir0>", "<dir1>"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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."
|
||||
@@ -0,0 +1,42 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# ENVIRONMENT VARIABLES
|
||||
#------------------------------------------------------------------------------
|
||||
define tcl_util
|
||||
xsct -nodisp $(PLATFORM_TOOLS)/util.tcl \
|
||||
$(1) \
|
||||
$(CONFIG_FILE) $(BUILD_DIR)
|
||||
endef
|
||||
|
||||
xilinx_sdkopen:
|
||||
$(call print,Launching IDE...)
|
||||
@if [ "$(call check_command,vitis)" = "y" ]; then \
|
||||
if [ "$(XILINX_VITIS_CLASSIC)" = "y" ]; then \
|
||||
vitis -classic -workspace=$(BUILD_DIR); \
|
||||
else \
|
||||
vitis -workspace=$(BUILD_DIR); \
|
||||
fi; \
|
||||
elif [ "$(call check_command,xsdk)" = "y" ]; then \
|
||||
xsdk -workspace=$(BUILD_DIR); \
|
||||
else \
|
||||
echo "No IDE found!" && exit 1; \
|
||||
fi
|
||||
|
||||
PHONY += xilinx_sdkbuild
|
||||
xilinx_sdkbuild:
|
||||
$(call print,[Build] SDK projects in $(BUILD_DIR))
|
||||
$(call tcl_util, build) $(HIDE)
|
||||
|
||||
PHONY += xilinx_sdkclean
|
||||
xilinx_sdkclean:
|
||||
$(call print,[Delete] SDK artefacts from $(BUILD_DIR))
|
||||
$(call tcl_util, clean_project) $(HIDE)
|
||||
|
||||
xilinx_project:
|
||||
$(call mk_dir,$(BUILD_DIR))
|
||||
$(call print,Creating and configuring the IDE project)
|
||||
$(call tcl_util, create_project) $(HIDE)
|
||||
|
||||
xilinx_reset: xilinx_clean_all
|
||||
|
||||
xilinx_clean_all:
|
||||
$(call remove_dir,.Xil) $(HIDE)
|
||||
Reference in New Issue
Block a user