Zynq图书教程实验室4-C部分添加指令问题

发布于 2025-01-18 21:18:49 字数 1154 浏览 1 评论 0原文

我正在尝试在 vivado hls 中运行 zynq 书籍教程实验 4 和 c 部分(hls 在新版本中包含 vitis),但是当我在书中所述的添加指令步骤中右键单击时,添加指令窗口不会打开。我在vivado的2015.1、2018.3和2021.2版本中分别尝试了这个,结果在所有版本中都是相同的。我遇到问题的步骤如下。教程书籍链接位于此处。虽然我在互联网上研究了很多这个问题,但没有太多结果,但是在xilinx论坛上遇到这个问题的人在 此链接 他提到这是一个错误,并且可以使用 #pragma 命令行将相同的操作添加到 c 文件中。由于我是这些问题的新手,如果您能帮助我如何使用 #pragma 命令添加指令,我将不胜感激教程中的步骤 (m)。

输入图片这里的描述

提到的c代码如下。

    void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size){
    ap_ufixed<12,12> address;

    temp+=step_size; // Accumulator. Values will wrap around on overflow.

    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.

    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
    }

I am trying run zynq book tutorials lab 4 and c part in vivado hls (hls included vitis in new version) but when I right click in the step of adding directive as described in the book, the add directive window does not open. I tried this separately in 2015.1, 2018.3 and 2021.2 versions of vivado, the result is the same in all of them.The step I'm having trouble with is as follows.Tutorial Book Link is here. Although I researched the problem a lot on the internet, there was not much result, but someone who encountered this problem in xilinx's forum explained in this link He mentioned that this is a bug and that the same operation can be added to the c file with the #pragma command line.Since I am new to these issues, I would appreciate if you could help me how to add the directive by using the #pragma command mentioned in the step (m) in the tutorial.

enter image description here

The c code mentioned is as follows.

    void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size){
    ap_ufixed<12,12> address;

    temp+=step_size; // Accumulator. Values will wrap around on overflow.

    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.

    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你如我软肋 2025-01-25 21:18:49

是的,Vivado(现在的 Vitis)HLS GUI 有时不显示该指令。然而,它因祸得福,因为它迫使您在代码中手动添加编译指示,因此您可能实际上理解编译指示及其对生成的 RTL 的影响。从上面的示例来看,您似乎将使用 INTERFACERESOURCE 编译指示。

作为一名 HLS 爱好者,我想先简要介绍一下这两个编译指示的基本理解和语法,然后您可以最后查看我对您问题的解决方案。


pragma HLS 接口


INTERFACE pragma 指定在接口综合期间如何根据函数定义创建 RTL 端口。
RTL 实现中的端口源自:

  • 指定的任何功能级协议。
  • 函数参数。
  • 由顶级函数访问并在其范围之外定义的全局变量。

以下是 INTERFACE 编译指示的语法:

语法:

#pragma HLS interface <mode> port=<name> bundle=<string> \
register register_mode=<mode> depth=<int> offset=<string> \
clock=<string> name=<string> \
num_read_outstanding=<int> num_write_outstanding=<int> \
max_read_burst_length=<int> max_write_burst_length=<int>

为了明确理解语法中的每个参数,请一定阅读以下参考资料中的详细信息:


pragma HLS资源


指定特定的库资源(核心)用于实现RTL中的变量(数组、算术运算或函数参数)。如果未指定 RESOURCE pragma,Vivado HLS 将确定要使用的资源。

#pragma HLS resource variable=<variable> core=<core>\
latency=<int>

为了明确理解语法中的每个参数,请阅读以下参考文献中的详细信息:


您的解决方案


更新:现在,我在 Vivado HLS 上运行代码后再次发布此解决方案,因此有更多说明:

void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size) {


#pragma HLS RESOURCE variable=sine_sample core=AXI4LiteS
#pragma HLS RESOURCE variable=step_size core=AXI4LiteS
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS RESOURCE variable=return core=AXI4LiteS

    // Define the pcore interface and group into AXI4 slave "slv0"

    /* Value to hold the current address value of the sine LUT
     * 12-bit unsigned fixed-point, all integer bits.
     * Overflow is set to "wrap around" by default. */
    ap_ufixed<12,12> address;

    temp+=step_size; // Accumulator. Values will wrap around on overflow.

    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.

    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
}

在某些 Vivado HLS 版本上,上述解决方案可能会发出如下警告:

警告:[HLS 200-41] 端口“&sine_sample”上的资源核心“AXI4LiteS”已弃用。请使用interface指令来指定AXI接口。

因此,我们对所有变量使用INTERFACE指令,如下所示,不会发出警告:

void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size) {

#pragma HLS INTERFACE s_axilite port=sine_sample
#pragma HLS INTERFACE s_axilite port=step_size
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE ap_ctrl_none port=return

    // Define the pcore interface and group into AXI4 slave "slv0"

    /* Value to hold the current address value of the sine LUT
     * 12-bit unsigned fixed-point, all integer bits.
     * Overflow is set to "wrap around" by default. */
    ap_ufixed<12,12> address;

    temp+=step_size; // Accumulator. Values will wrap around on overflow.

    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.

    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
}

Yes, it happens at times that Vivado (now Vitis) HLS GUI does not show the directive. However, it's a blessing in disguise since it compels you to manually add the pragmas in your code and as a result you may actually understand the pragmas and their effect on the generated RTL. From the example above it seems you will be using INTERFACE and RESOURCE pragmas.

As a HLS enthusiast, I would like to briefly start with the basic understanding and syntax of both pragmas and then you can check my solution to your question in the end.


pragma HLS interface :


The INTERFACE pragma specifies how RTL ports are created from the function definition during interface synthesis .
The ports in the RTL implementation are derived from:

  • Any function-level protocol that is specified.
  • Function arguments.
  • Global variables accessed by the top-level function and defined outside its scope.

Below is the syntax of the INTERFACE pragma:

Syntax:

#pragma HLS interface <mode> port=<name> bundle=<string> \
register register_mode=<mode> depth=<int> offset=<string> \
clock=<string> name=<string> \
num_read_outstanding=<int> num_write_outstanding=<int> \
max_read_burst_length=<int> max_write_burst_length=<int>

In order to explicitly understand each parameter in the syntax please do read the details in following references:


pragma HLS resource:


Specify that a specific library resource (core) is used to implement a variable (array, arithmetic operation or function argument) in the RTL. If the RESOURCE pragma is not specified, Vivado HLS determines the resource to use.

#pragma HLS resource variable=<variable> core=<core>\
latency=<int>

In order to explicitly understand each parameter in the syntax please do read the details in following references:


Your solution:


Updated: Now I again post this solution after running the code myself on my Vivado HLS and hence more clarification:

void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size) {


#pragma HLS RESOURCE variable=sine_sample core=AXI4LiteS
#pragma HLS RESOURCE variable=step_size core=AXI4LiteS
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS RESOURCE variable=return core=AXI4LiteS

    // Define the pcore interface and group into AXI4 slave "slv0"

    /* Value to hold the current address value of the sine LUT
     * 12-bit unsigned fixed-point, all integer bits.
     * Overflow is set to "wrap around" by default. */
    ap_ufixed<12,12> address;

    temp+=step_size; // Accumulator. Values will wrap around on overflow.

    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.

    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
}

On some Vivado HLS versions the above solution may give warning like following:

WARNING: [HLS 200-41] Resource core 'AXI4LiteS' on port '&sine_sample' is deprecated. Please use the interface directive to specify the AXI interface.

Hence, we use INTERFACE directive for all variables as following that will give no warnings:

void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size) {

#pragma HLS INTERFACE s_axilite port=sine_sample
#pragma HLS INTERFACE s_axilite port=step_size
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE ap_ctrl_none port=return

    // Define the pcore interface and group into AXI4 slave "slv0"

    /* Value to hold the current address value of the sine LUT
     * 12-bit unsigned fixed-point, all integer bits.
     * Overflow is set to "wrap around" by default. */
    ap_ufixed<12,12> address;

    temp+=step_size; // Accumulator. Values will wrap around on overflow.

    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.

    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
}
贱贱哒 2025-01-25 21:18:49

我会尽力给您一个更教学的答案,而不是针对您的问题的特定答案。

Xilinx HLS特异性陈列的想法是指导HLS“编译器”来生成靠近设计师意图的硬件组件。
因此,存在很多HLS pragmas,而Xilinx Vitis-HLS用户指南充满了参考。

实际上,根据您要使用的Pragma,您需要将其相应地放在代码中(毕竟,Pragmas与任何其他代码一样)。
例如,在您的代码段中:

void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size){
#pragma HLS INTERFACE port=sine_sample ...
#pragma HLS INTERFACE port=step_size ...
    ap_ufixed<12,12> address;
    static ap_ufixed<12,12> temp = 0;
#pragma HLS RESOURCE variable=temp ...
    temp += step_size; // Accumulator. Values will wrap around on overflow.
    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.
    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current
}

PRAGMA接口可以放置在您功能中的任何位置,因为它参考了函数参数,并且在函数范围中无处可用。另一方面,必须将pragma资源放置 定义变量的界限与 ie temp有限。

Pragma顺序更重要的另一个示例是在循环和嵌套循环中。例如,想象一下将pragma管道放在这三个不同的位置中:

#pragma HLS PIPELINE II=1 // It will appy the pipeline to the whole function, fully unrolls both N-loop and M-loop
for (int i = 0; i < N; ++i) {
#pragma HLS PIPELINE II=1 // It will appy the pipeline to the N-loop and fully unroll the M loop
    for (int j = 0; j < M; ++j) {
#pragma HLS PIPELINE II=1 // It will appy the pipeline to M-loop only, keeping both the N-loop and M-loop rolled, but pipelined
        // ...
    }
}

注意,在示例中,想象一下当时只评论了一个布拉格马斯。我只是为了示例而将它们放在一起(以这种方式活跃并没有多大意义,我相信功能级的Pragma将仅仅接管其他函数)。

通常,我建议您仔细阅读您打算使用的每个布拉格的文档,以及如何以及将其放在代码中。

祝你好运!

I'll try to give you a more pedagogical answer, rather than a specific one to your problem.

The idea of Xilinx HLS-specific pragmas is to guide the HLS "compiler" in generating a hardware component close to the designer intentions.
As such, there exist a lot of those HLS pragmas and the Xilinx Vitis-HLS User Guide is full of references to look up to.

In practice, according to the pragma you want to use, you need to place it accordingly in your code (after all, pragmas are just as any other line of code).
For instance, in your code snippet:

void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size){
#pragma HLS INTERFACE port=sine_sample ...
#pragma HLS INTERFACE port=step_size ...
    ap_ufixed<12,12> address;
    static ap_ufixed<12,12> temp = 0;
#pragma HLS RESOURCE variable=temp ...
    temp += step_size; // Accumulator. Values will wrap around on overflow.
    address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.
    *sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current
}

The pragma INTERFACE can be placed anywhere within your function since it's referring to the function arguments and they're available everywhere in the function scope. On the other side instead, the pragma RESOURCE must be placed after defining the variable is bounded to, i.e. temp.

Another example where pragma order matters even more is in loops and nested loops. For example, imagine placing the pragma PIPELINE in these three different positions:

#pragma HLS PIPELINE II=1 // It will appy the pipeline to the whole function, fully unrolls both N-loop and M-loop
for (int i = 0; i < N; ++i) {
#pragma HLS PIPELINE II=1 // It will appy the pipeline to the N-loop and fully unroll the M loop
    for (int j = 0; j < M; ++j) {
#pragma HLS PIPELINE II=1 // It will appy the pipeline to M-loop only, keeping both the N-loop and M-loop rolled, but pipelined
        // ...
    }
}

Note, in the example, imagine only one of the pragmas commented out at the time. I'm putting them together just for the sake of the example (all active in this way won't make much sense and I believe the function-level pragma will simply take over the other ones).

In general, I would recommend you to carefully read the documentation of each pragma you intend to use and how and where to place it in your code.

Good luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文