🏠

Vitis_HLS_Tutorials 技术深度解析

一句话概括

Vitis_HLS_Tutorials 是一套渐进式学习实验室,它通过三个真实的设计案例(多项式向量化的 NTT 算法、波束成形器的 QR 分解、代码分析器优化流程),手把手地教开发者如何将 C/C++ 算法逐步转化为高性能 FPGA 硬件。这里的每一个 "Version" 都不是简单的代码快照,而是特定优化策略的物理体现——你可以亲手触摸到 PIPELINEUNROLLARRAY_PARTITION 这些 pragma 在硅片上产生的真实效果。


这个模块解决了什么问题?

问题空间:从算法到硬件的"峡谷"

传统的 HLS(高层次综合)教学存在两个极端:

  1. 教科书模式:只讲语法,#pragma HLS PIPELINE 是什么意思?填鸭式灌输。
  2. 工程项目模式:直接扔给你一个百万行的代码库,让你自己去猜为什么要这么写。

Vitis_HLS_Tutorials 填补了中间的断层:它提供了一条可复制的优化路径,让你看到同一个算法从"能跑"(Baseline)到"飞快"(Optimized)的每一个中间状态。

核心挑战:看不见的性能瓶颈

在 FPGA 上,性能不是代码"看起来"的样子决定的,而是由数据流、内存带宽、流水线气泡这些硬件层面的因素决定的。这个模块教会你:

  • 如何读懂 HLS 的报告(不是看个热闹,而是定位真正的瓶颈)
  • 何时该用空间并行UNROLL 展开循环,复制硬件)
  • 何时该用时间并行PIPELINE 让操作重叠执行)
  • 内存布局如何杀死性能ARRAY_PARTITION 决定你能多快读到数据)

心智模型:把这个模块想象成什么?

类比:调音台上的推子(Audio Mixing Console)

想象你面对一个录音棚的调音台,每个通道条上有一排推子:

  • 推子 1:循环展开度(UNROLL factor)— 越高,硬件越多,并行度越高
  • 推子 2:流水线深度(PIPELINE II)— 目标启动间隔,越小吞吐量越高
  • 推子 3:数组分区粒度(ARRAY_PARTITION)— 决定内存端口数
  • 推子 4:数据流架构(DATAFLOW)— 开启函数级流水线

关键洞察:这不是"设置一次就完事"的配置。每个设计点都是多目标优化问题——你推高一个推子,可能要以推低另一个为代价(面积 vs. 速度 vs. 功耗)。

核心抽象:版本即实验(Version as Experiment)

在这个模块中,每一个 Version0Version1Version2Version3 都不是随意的命名,而是受控实验的控制组和对照组

  • Version0(Baseline):"最自然的 C++ 写法",不做任何 HLS 优化。这是你的性能基准线,也是通常最慢的版本。
  • Version1(Initial Vectorization):开始应用基本的向量化技术,可能引入简单的 PIPELINEUNROLL
  • Version2(Intermediate Optimization):深入优化内存访问模式,引入 ARRAY_PARTITION,调整数据流。
  • Version3(Final Implementation):最终的优化版本,可能使用 DATAFLOW、细粒度的并行控制,达到最佳吞吐量。

思考的维度:当你读这些代码时,不要只看"这一行写了什么",而要问"从上一个版本到这一个版本,作者改变了什么优化策略?带来了什么代价?"


数据流:从 C++ 到比特流

端到端的数据旅程

flowchart LR A[C++ Source
polyvec.cpp] --> B[hls_config.cfg
Configuration] B --> C[Vitis HLS
Synthesis Engine] C --> D[RTL Generation
Verilog/VHDL] D --> E[IP Catalog
Packaging] E --> F[Vivado
Implementation] F --> G[Bitstream
Download to FPGA]

关键路径解析

1. 源码层(Source Layer)

输入文件

  • polyvec.cpp / polyvec.h:算法实现(多项式向量化的 NTT)
  • mgs_qrd_wbs.cpp:波束成形器的 QR 分解实现
  • hw.cpp:代码分析器教程的示例硬件代码
  • *_tb.cpp:Testbench 文件,用于 C 仿真和协同仿真

关键抽象:这些不是普通的 C++ 代码,而是可综合的子集(Synthesizable Subset)。例如:

  • 不使用动态内存分配(new/delete
  • 循环边界必须是编译时常量或可静态分析的
  • 不使用递归(通常)

2. 配置层(Configuration Layer)

hls_config.cfg 的核心参数

part=xcvp1202-vsva2785-1LP-i-L  # 目标 FPGA 器件
flow_target=vivado                # 下游流程目标
syn.top=polyvec_ntt              # 顶层函数(HLS 入口点)
syn.file=polyvec.cpp             # 源文件
tb.file=polyvec_tb.cpp           # 测试文件
csim.code_analyzer=1           # 启用代码分析器

关键决策点

  • flow_target=vivado vs. vitis:决定生成的 RTL 是用于 Vivado 独立流程还是 Vitis 统一流程
  • package.output.format=ip_catalog:输出打包为 IP 目录格式,便于在 Vivado 中复用
  • csim.code_analyzer=1关键特性,启用静态代码分析,在编译前发现潜在的合成问题

3. 综合引擎层(Synthesis Engine)

Vitis HLS 的内部工作流

C/C++ Frontend (Clang) → IR (LLVM IR) → Scheduling → Binding → RTL Generation

关键优化阶段

  1. 调度(Scheduling):确定每个操作在哪个时钟周期执行
  2. 绑定(Binding):将操作映射到具体的硬件资源(DSP、BRAM、LUT)
  3. 优化(Optimization):应用 pragma 指导的优化(流水线、展开、分区)

4. 下游流程(Downstream Flow)

IP 目录打包

  • 生成的 RTL 被包装为 Vivado IP(.xci 文件)
  • 包含约束文件(.xdc)、仿真模型、文档

Vivado 实现

  • 综合(Synthesis):RTL → 门级网表
  • 实现(Implementation):布局、布线、时序收敛
  • 比特流生成(Bitstream):最终的 FPGA 配置文件

架构设计与权衡

版本演进策略:渐进式优化

核心哲学:不要一次做所有优化。每个版本都是独立的实验,让你能测量每个优化策略的效果。

版本 关键优化 目标 潜在代价
Version0 无(Baseline) 建立性能基线,验证功能正确性 资源利用率低,吞吐量差
Version1 基本向量化,PIPELINE 启动 II=1 的流水线 面积增加,控制逻辑复杂
Version2 ARRAY_PARTITION,内存优化 消除内存瓶颈,提高数据并行度 BRAM 用量激增,布局压力
Version3 DATAFLOW,任务级并行 函数级流水线,最大化吞吐量 复杂的握手逻辑,调试困难

权衡分析

  • 面积 vs. 速度:Version3 可能达到最高吞吐量,但如果你的设计受限于 BRAM 或 DSP 数量,可能需要回退到 Version2。
  • 编译时间 vs. 优化程度:越激进的优化(如 DATAFLOW),Vitis HLS 的编译时间越长,且 QoR(结果质量)越难预测。
  • 可调试性 vs. 性能:Baseline 版本最容易调试(行为接近原始 C++),而高度优化的版本可能引入硬件特有的时序问题(如流水线气泡、握手死锁)。

代码分析器(Code Analyzer)的架构角色

设计意图:在运行 C 仿真(csim)之前,静态地发现代码中可能导致合成问题的模式。

与传统编译器的区别

  • GCC/Clang:关注语言标准的符合性,目标是生成正确的机器码。
  • Vitis HLS Code Analyzer:关注可综合性,目标是识别无法转化为高效硬件的代码模式(如动态内存、递归、未绑定的循环)。

配置启用

csim.code_analyzer=1  # 在 hls_config.cfg 中启用

价值主张:在早期(C 代码阶段)发现问题,而不是在漫长的综合后发现 RTL 与预期不符。

跨版本依赖管理

挑战:Version0 到 Version3 共享相同的底层多项式向量数学(polyvec 结构),但每个版本可能有不同的优化假设。

依赖图分析: 从核心组件的外部依赖可以看到,每个版本的 polyvec_ntt 都依赖于:

  • AI_Engine_Development.AIE.Design_Tutorials.02-super_sampling_rate_fir.DualSSR16_hw.sw.Makefile.aie_control_xrt.cpp(通用控制接口)
  • 跨版本的 polyvec 数据结构(K, N, Q, QINV, poly, polyvec 等)

设计决策

  • 数据结构的稳定性:数学参数(模数 Q、维度 N)在所有版本中保持一致,确保算法正确性可验证。
  • 代码复用与版本隔离:每个版本有独立的 hls_config.cfg,允许独立的合成参数,但共享相同的 polyvec.h 数学定义。

使用指南与实战建议

如何阅读这个模块的代码

推荐阅读顺序(以 Polynomial Vectorization 为例):

  1. Version0(Baseline)

    • 先读 polyvec.h,理解数据结构(polypolyvec 的定义)。
    • 再读 polyvec.cpp 中的 polyvec_ntt 函数,理解算法的"最自然" C++ 实现。
    • 查看 hls_config.cfg,注意 csim.code_analyzer=0(Baseline 不启用分析器)。
  2. Version1(Initial Vectorization)

    • 对比 polyvec.cpp 与 Version0 的差异,寻找 #pragma HLS PIPELINE#pragma HLS UNROLL 的插入点。
    • 注意 hls_config.cfgcsim.code_analyzer=1 的启用。
  3. Version2(Intermediate Optimization)

    • 关注内存访问模式的改变,寻找 #pragma HLS ARRAY_PARTITION
    • 理解数组分区如何消除存储器瓶颈。
  4. Version3(Final Implementation)

    • 寻找 #pragma HLS DATAFLOW 和函数分解。
    • 理解任务级并行如何最大化吞吐量。

关键配置参数详解

hls_config.cfg 核心段

part=xcvp1202-vsva2785-1LP-i-L  # 目标器件:Versal Premium VP1202
flow_target=vivado               # 目标流程:Vivado(独立 IP 模式)

[hls]
syn.top=polyvec_ntt              # 顶层函数:HLS 的入口点
syn.file=polyvec.cpp             # 源文件列表
syn.file=polyvec.h
tb.file=polyvec_tb.cpp           # 测试平台(C 仿真)

package.output.format=ip_catalog # 输出格式:Vivado IP 目录
package.output.syn=false         # 不自动运行下游 Vivado 综合

csim.code_analyzer=1             # 启用代码分析器(关键!)
csim.clean=true                  # 每次清理临时文件

关键参数解释

part=xcvp1202-vsva2785-1LP-i-L

  • 这是 AMD Versal Premium 系列的 VP1202 器件
  • 选择正确的器件至关重要,因为它决定了:
    • 可用的 DSP 切片数量(影响乘加运算的并行度)
    • BRAM/URAM 容量(影响中间数据的存储策略)
    • 最大时钟频率(影响时序约束的可行性)

flow_target=vivado

  • 决定 HLS 生成的 RTL 如何被消费
  • vivado:生成独立的 IP 核,用于 Vivado 传统流程
  • vitis:生成用于 Vitis 统一软件平台的内核(通常带 extern "C" 接口)

csim.code_analyzer=1

  • 这是 Feature Tutorial 的核心教学点
  • 启用后,Vitis HLS 会在 C 仿真前进行静态分析,标记出:
    • 无法合成的 C++ 特性(动态内存、虚函数、递归)
    • 可能导致时序问题的长组合逻辑链
    • 未初始化的变量或数组越界访问
  • 实战建议:在 Version0(Baseline)中禁用,在 Version1+ 中启用,体验差异。

架构设计与权衡

版本演进策略:渐进式优化

核心哲学:不要一次做所有优化。每个版本都是独立的实验,让你能测量每个优化策略的效果。

版本 关键优化 目标 潜在代价
Version0 无(Baseline) 建立性能基线,验证功能正确性 资源利用率低,吞吐量差
Version1 基本向量化,PIPELINE 启动 II=1 的流水线 面积增加,控制逻辑复杂
Version2 ARRAY_PARTITION,内存优化 消除内存瓶颈,提高数据并行度 BRAM 用量激增,布局压力
Version3 DATAFLOW,任务级并行 函数级流水线,最大化吞吐量 复杂的握手逻辑,调试困难

权衡分析

  • 面积 vs. 速度:Version3 可能达到最高吞吐量,但如果你的设计受限于 BRAM 或 DSP 数量,可能需要回退到 Version2。
  • 编译时间 vs. 优化程度:越激进的优化(如 DATAFLOW),Vitis HLS 的编译时间越长,且 QoR(结果质量)越难预测。
  • 可调试性 vs. 性能:Baseline 版本最容易调试(行为接近原始 C++),而高度优化的版本可能引入硬件特有的时序问题(如流水线气泡、握手死锁)。

代码分析器(Code Analyzer)的架构角色

设计意图:在运行 C 仿真(csim)之前,静态地发现代码中可能导致合成问题的模式。

与传统编译器的区别

  • GCC/Clang:关注语言标准的符合性,目标是生成正确的机器码。
  • Vitis HLS Code Analyzer:关注可综合性,目标是识别无法转化为高效硬件的代码模式(如动态内存、递归、未绑定的循环)。

配置启用

csim.code_analyzer=1  # 在 hls_config.cfg 中启用

价值主张:在早期(C 代码阶段)发现问题,而不是在漫长的综合后发现 RTL 与预期不符。

跨版本依赖管理

挑战:Version0 到 Version3 共享相同的底层多项式向量数学(polyvec 结构),但每个版本可能有不同的优化假设。

依赖图分析: 从核心组件的外部依赖可以看到,每个版本的 polyvec_ntt 都依赖于:

  • AI_Engine_Development.AIE.Design_Tutorials.02-super_sampling_rate_fir.DualSSR16_hw.sw.Makefile.aie_control_xrt.cpp(通用控制接口)
  • 跨版本的 polyvec 数据结构(K, N, Q, QINV, poly, polyvec 等)

设计决策

  • 数据结构的稳定性:数学参数(模数 Q、维度 N)在所有版本中保持一致,确保算法正确性可验证。
  • 代码复用与版本隔离:每个版本有独立的 hls_config.cfg,允许独立的合成参数,但共享相同的 polyvec.h 数学定义。

使用指南与实战建议

如何阅读这个模块的代码

推荐阅读顺序(以 Polynomial Vectorization 为例):

  1. Version0(Baseline)

    • 先读 polyvec.h,理解数据结构(polypolyvec 的定义)。
    • 再读 polyvec.cpp 中的 polyvec_ntt 函数,理解算法的"最自然" C++ 实现。
    • 查看 hls_config.cfg,注意 csim.code_analyzer=0(Baseline 不启用分析器)。
  2. Version1(Initial Vectorization)

    • 对比 polyvec.cpp 与 Version0 的差异,寻找 #pragma HLS PIPELINE#pragma HLS UNROLL 的插入点。
    • 注意 hls_config.cfgcsim.code_analyzer=1 的启用。
  3. Version2(Intermediate Optimization)

    • 关注内存访问模式的改变,寻找 #pragma HLS ARRAY_PARTITION
    • 理解数组分区如何消除存储器瓶颈。
  4. Version3(Final Implementation)

    • 寻找 #pragma HLS DATAFLOW 和函数分解。
    • 理解任务级并行如何最大化吞吐量。

关键配置参数详解

hls_config.cfg 核心段

part=xcvp1202-vsva2785-1LP-i-L  # 目标器件:Versal Premium VP1202
flow_target=vivado               # 目标流程:Vivado(独立 IP 模式)

[hls]
syn.top=polyvec_ntt              # 顶层函数:HLS 的入口点
syn.file=polyvec.cpp             # 源文件列表
syn.file=polyvec.h
tb.file=polyvec_tb.cpp           # 测试平台(C 仿真)

package.output.format=ip_catalog # 输出格式:Vivado IP 目录
package.output.syn=false         # 不自动运行下游 Vivado 综合

csim.code_analyzer=1             # 启用代码分析器(关键!)
csim.clean=true                  # 每次清理临时文件

关键参数解释

part=xcvp1202-vsva2785-1LP-i-L

  • 这是 AMD Versal Premium 系列的 VP1202 器件
  • 选择正确的器件至关重要,因为它决定了:
    • 可用的 DSP 切片数量(影响乘加运算的并行度)
    • BRAM/URAM 容量(影响中间数据的存储策略)
    • 最大时钟频率(影响时序约束的可行性)

flow_target=vivado

  • 决定 HLS 生成的 RTL 如何被消费
  • vivado:生成独立的 IP 核,用于 Vivado 传统流程
  • vitis:生成用于 Vitis 统一软件平台的内核(通常带 extern "C" 接口)

csim.code_analyzer=1

  • 这是 Feature Tutorial 的核心教学点
  • 启用后,Vitis HLS 会在 C 仿真前进行静态分析,标记出:
    • 无法合成的 C++ 特性(动态内存、虚函数、递归)
    • 可能导致时序问题的长组合逻辑链
    • 未初始化的变量或数组越界访问
  • 实战建议:在 Version0(Baseline)中禁用,在 Version1+ 中启用,体验差异。

新贡献者必读:陷阱与最佳实践

常见陷阱(Gotchas)

1. 版本间参数漂移(Version Drift)

现象:你在 Version3 中修改了 polyvec.h 中的常量 N,但发现 Version0 的行为也变了。

原因:所有版本共享相同的头文件(通过依赖图可以看到它们都引用 Vitis_HLS.Design_Tutorials.01-Polynomial_Vectorization.workspace.Version0.polyvec.N 等)。

解决方案

  • 在修改数学参数前,使用 diff 工具检查所有版本的依赖。
  • 如果需要版本特定的参数,考虑在版本目录下创建本地的 params.h

2. Code Analyzer 的误报与漏报

现象:Code Analyzer 报告"无问题",但在综合阶段仍然出现时序违规。

原因:Code Analyzer 是静态分析工具,它检查的是代码的"可综合性",而不是"性能"。它无法预测:

  • 特定的循环展开因子是否会导致 DSP 资源耗尽
  • 特定的数组分区策略是否会导致布线拥塞
  • 特定的流水线深度是否会导致时序难以收敛

解决方案

  • 将 Code Analyzer 视为必要但不充分的条件检查。
  • 始终查看 HLS 综合报告(Synthesis Report),关注 UtilizationTiming 部分。
  • 对于关键路径,使用 csim.sanitize_address=1 检查内存访问错误。

3. HLS Config 的继承与覆盖

现象:你在高层目录设置了 csim.code_analyzer=1,但在特定版本的目录中它似乎没生效。

原因:Vitis HLS 的配置文件不自动继承。每个 hls_config.cfg 都是独立的命名空间。

解决方案

  • 在每个版本的 hls_config.cfg 中显式设置所有需要的参数。
  • 使用脚本生成配置文件,确保一致性:
    # 示例:生成带版本号的配置
    for v in Version0 Version1 Version2 Version3; do
      sed "s/__VERSION__/\(v/g" template.cfg > \)v/hls_config.cfg
    done
    

最佳实践清单

开发流程(Development Workflow)

  1. 从 Baseline 开始

    • 永远不要直接在优化版本上开发。先在 Version0 验证功能正确性。
    • 建立黄金参考(Golden Reference):保存 Version0 的仿真输出,作为后续版本的比较基准。
  2. 增量式优化

    • 每次只修改一个优化参数(如只改 UNROLL 因子,或只改 ARRAY_PARTITION 模式)。
    • 记录每次修改对吞吐量(Throughput)、延迟(Latency)、资源(Utilization)的影响。
  3. 持续验证

    • 每次修改后运行 csim(C 仿真)和 cosim(协同仿真)。
    • 对比 RTL 仿真结果与 C 参考模型的输出。

性能调试(Performance Debugging)

  1. 读懂综合报告(Synthesis Report):

    • 关注 Performance Estimates 部分的 IntervalLatency
    • 查看 Utilization Estimates,确认 BRAM/DSP 用量是否在器件容量内。
  2. 识别瓶颈(Bottleneck Analysis):

    • 如果 II(Initiation Interval)大于 1,查看 Details 部分的 Loop 报告,找到依赖关系。
    • 常见的 II 限制因素:
      • 内存依赖:循环迭代间有数组读写依赖 → 使用 ARRAY_PARTITION dependence pragma。
      • 资源限制:DSP 或 BRAM 端口不足 → 增加 UNROLL 因子或调整 ARRAY_PARTITION 因子。
  3. 使用 Dataflow Viewer(仅 GUI 模式):

    • 对于 DATAFLOW 设计,使用 Vitis HLS GUI 的 Dataflow Viewer 可视化函数间的数据流。
    • 检查 FIFO 深度是否足够(避免出现 stalled 状态)。

跨团队协作(Team Collaboration)

  1. 配置版本控制

    • hls_config.cfg 纳入 Git 版本控制。
    • 使用 git diff 跟踪配置变更(如时钟周期调整、优化 pragma 的启用/禁用)。
  2. 文档化优化决策

    • 在代码注释中不仅写"做了什么",更要写"为什么"。
    • 示例:
      // 选择 UNROLL factor=4 是因为:
      // 1. 数组维度 N=256 可被 4 整除,无边界碎片
      // 2. 目标器件的 DSP 切片充足(估算需 4*8=32 个 DSP)
      // 3. 上一版本 UNROLL=8 导致 BRAM 端口竞争,II 无法达到 1
      #pragma HLS UNROLL factor=4
      
  3. 建立回归测试

    • 使用脚本批量运行所有版本的 csimcosim
    • 对比性能指标(Latency、Interval、Utilization)的历史趋势,防止回归。

依赖关系与系统集成

对外部模块的依赖

核心依赖

  • AI_Engine_Development.AIE.Design_Tutorials.02-super_sampling_rate_fir.DualSSR16_hw.sw.Makefile.aie_control_xrt.cpp
    • 这是一个通用的 AIE(AI Engine)控制接口,用于在 Versal 器件上协调 AIE 和 PL(Programmable Logic)之间的数据移动。
    • 在本模块中,它被用作 XRT(Xilinx Runtime)主机代码的参考模板。

数据类型依赖

  • 所有 polyvec 版本共享相同的数学常量和类型定义(N, K, Q, QINV, poly, polyvec 等)。
  • 这种设计确保了跨版本的算法一致性,同时允许实现细节的独立演进。

与其他 HLS 教程模块的关系

横向关联

纵向层级


子模块概述

本模块包含三个主要子模块,每个都针对特定的 HLS 优化技术或应用场景:

polynomial_vectorization_ntt_versions

核心关注点:渐进式优化流程(Baseline → Vectorized → Optimized → Final)

技术要点

  • Version0:建立性能基线,无 HLS 优化 pragma
  • Version1:引入 PIPELINE 和基本 UNROLL,实现操作级并行
  • Version2:应用 ARRAY_PARTITION 优化内存访问,消除存储器瓶颈
  • Version3:使用 DATAFLOW 实现任务级并行,最大化整体吞吐量

适用场景:学习如何系统地优化计算密集型算法(如多项式乘法、NTT 变换)在 FPGA 上的实现。

beamformer_qrd_design_tutorial

核心关注点:矩阵分解算法的 HLS 实现(Modified Gram-Schmidt QR Decomposition)

技术要点

  • 复杂的矩阵运算数据流设计
  • 精度与资源占用的权衡(定点数 vs 浮点数)
  • 适用于雷达、通信系统中的波束成形应用

适用场景:学习如何实现线性代数密集型算法,理解矩阵运算在硬件上的映射策略。

code_analyzer_feature_tutorial_progression

核心关注点:静态代码分析工具在 HLS 流程中的应用

技术要点

  • tutorial_example:未优化的初始代码,展示代码分析器发现的问题
  • tutorial_example_final:优化后的最终代码,展示如何解决这些问题
  • csim.code_analyzer=1 配置的使用方法和效果

适用场景:学习如何在早期阶段(C 仿真前)发现潜在的合成问题,提高开发效率。


总结:给新加入者的建议

如果你刚加入团队,需要快速掌握这个模块,建议按以下顺序行动:

第 1 周:建立直觉

  1. 阅读 Version0 的 polyvec.cpp,理解 NTT 算法的 C++ 实现。
  2. 运行 vitis_hls -f hls_config.cfg(在 Version0 目录),观察 Baseline 的性能报告。
  3. 对比 Version1 的代码,找到插入的 pragma,理解 PIPELINE 的效果。

第 2 周:深入优化

  1. 逐个对比 Version1→Version2→Version3 的代码差异。
  2. 记录每个版本的 LatencyIntervalUtilization 指标,绘制趋势图。
  3. 尝试手动调整 UNROLL 因子或 ARRAY_PARTITION 模式,观察对 QoR 的影响。

第 3 周:横向扩展

  1. 阅读 beamformer_qrd 的代码,理解矩阵运算的优化策略。
  2. 实践 code_analyzer 教程,故意在代码中引入错误,观察分析器的报告。
  3. 尝试将学到的优化技术应用到自己的算法上。

关键心态

  • 不要试图一次性理解所有版本。把这个模块看作一个时间序列,每个版本是快照。
  • 多问"为什么":为什么从 Version1 到 Version2 要去掉这个 pragma?为什么这里用 cyclic 分区而不是 block 分区?
  • 动手实验:HLS 是一门实验科学。同样的 pragma 在不同的数据类型、不同的循环结构上效果可能完全不同。

文档版本:1.0 最后更新:基于 Vitis_HLS 2023.2 版本 维护者:FPGA 架构团队

On this page