This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 在 EVE/VCOP 上使用组合式输入/输出缓冲器

Guru**** 2984730 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/665039/using-combined-in-out-buffer-on-eve-vcop

大家好、

我正在尝试实施 EVE 应用程序、将两个16位值合并为一个32位值。 目标是使用新计算出的值覆盖输入缓冲器中的值、以便我只处理一个组合输入/输出缓冲器、而不是两个单独的缓冲器。 这在 VCOP 上是可行的、还是 VCOP 内核始终包含一个指定的输入和输出缓冲器(IbufL 和 IbufH)?

如果可能、我可以将 IbufL 和 IbufH "合并"到一个缓冲区、以便我处理32kB 而不是16kB 的数据、而不重新布局缓冲区(通过 EDMA)吗?

此致、

托比亚斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Tobias、

    我已将您的问题转交给 EVE 专家。

    此致、
    Yordan
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Tobias、

       您的问题有两个部分。 一种是重复使用 EVE 的内部存储器、另一种是与外部存储器之间的内部缓冲器 DMA。 我正在为这两个问题写我的答复:

    第1部分:重复使用 EVE 的内部存储器

       VCOP 对内部缓冲器没有限制、您可以对同一缓冲器进行读写。 但是、您应该确保您不会从您所写的同一位置读回内容、因为这可能会导致比赛条件、因为商店和货物是独立发生的。 另一个需要考虑的因素是对性能的影响、因为您将读取和写入同一个缓冲区、如果您对不同缓冲区进行读取和写入、则需要2个周期、而不是1个周期。 关于使用32KB 全部存储器的问题、同样、VCOP 对存储器没有限制、但问题将出现在 DMA 中、我 将在本视频的第二部分对此进行解释  

    第2部分:内部缓冲器到外部存储器的 DMA。

       如果您将32KB 的全部内容用于输入、并将其重新用于输出、则 DMA 会出现问题、因为您必须将32KB 的数据从外部存储器 DMA 传输到内部存储器、同时必须将已计算的32KB DMA 处理完 从内部存储器到外部存储器的数据。 如果您在写入新数据之前先将所有计算的数据从 DMA 中取出、则可以执行此操作。 因此、在对 DMA 进行编程时应小心谨慎。  

    此致、

    安州

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Anshu、

    我使用了非 BAM 示例"efelib fir_filter_2D"作为参考、并将 DMA 自定义为按我的需要工作(并按照您提到的顺序处理输入/输出写入)。 现在、我使用一个针对输入和输出的组合缓冲器、如上所述。 但是、如果我想使用 VCOP 处理超过16kB 的数据、EVE-Simulator 会生成多个错误消息:

    "multi_eve_subsystem.eve_0.MEM_switch:对保留空间的无效访问"

    只有当我调试应用并单步执行内核的执行函数时、才会发生这些情况。 如果我在没有断点的情况下运行整个应用程序、它可以正常工作。 如果我直接在 EVE (例如 TDA3 EVM)上运行同一应用程序、则当应用程序想要第二次执行内核时、该应用程序会被阻塞在循环中。 在首次执行时、所有计算的数据和存储器写入都正常。

    那么、当我想更改 IBUFL/IBUFH 的存储器范围时、还有什么需要编辑的呢?

    谢谢、
    托比亚斯
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Tobias、

      当您使用我们的示例之一时、我假设您使用的是别名存储器视图? 因此、在本例中 、您将具有16KB 的 IBUFH 和16KB 的 IBUFL (输入和输出总共为32KB)。 从错误的角度看、您的内核内部将超出这两个缓冲区、并访问受限区域。 我们将需要研究内核并就此发表更多评论。


    此致、

    安州

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Anshu、

    是的、我正在使用别名存储器视图。 内核用于处理两个10位输入值(存储在16位缓冲区中) 并将其合并为一个20位值(存储在32位缓冲区中)。 这意味着我们的输入是输出的两倍。 这是等效的 C 代码:

    uint16 *pFrameAdd16 =(uint16*) ipcMsg->frameAddr;
    uint32 *pFrameAdd32 =(uint32*) ipcMsg->frameAddr;
    uint32 numPixel = ipcMsg->vPixel * ipcMsg->hamePixel;
    
    for (uint32*) ipcAdd16+<uint32
    
    
    *(uint32) i)<uint1 +[frameixel <uint32](uint32)<uint1 +[framex 32)<uint32 +[framex <uint32
    

    我生成的内核代码如下所示:

    #define ELEMSZ sizeof (* in1_ptr)
    #define VECTORSZ (VCOP_SIMD _width*ELEMSZ)
    #define shift (10)
    
    void buffer_merge
    (
    __vptr_uint16 in1_ptr、
    __vptr_UINT32 optr、
    unsigned short width、
    unsigned short height
    )
    {
    __vector Vin1;
    __vector Vin2;
    __vector Vout;
    __Vector Vinshift;
    __vector Vin1s vector v1s;__vector vector v1 vector v1 vector v1 vector v
    
    Vshift = shift;
    
    对于(int I1 = 0;I1 <高度;I1++)
    {
    对于(int I2 = 0;I2 <宽度/VCOP_SIMD 宽度;I2++)
    {
    _agen Addr_out;
    
    ADDR_OUT = I1*width*ELEMSZ*2 +I2*VECTORSZ*2;
    
    (Vin1、Vin2)= in1_ptr[Addr_out].deinterleave ();
    Vin1s=(Vin1 << Vshift);
    输出电压 = Vin1s | Vin2;
    OPTR[Addr_OUT]=输出电压;
    }
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在 Simulator 中会出现错误消息、但整体输出值正常。 如前所述、在实际硬件上、应用程序会卡在循环中。
    下面的屏幕截图显示了 VCOP 处理一个32kB 块后组合存储器 IBUFL/IBUFH 的结束。
    它写入地址0x40050000到0x40057FFD。

      


    此致、
    托比亚斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Tobias、

    调用函数时、以下4个参数的值是多少?
    _vptr uint16 in1_ptr、
    __vptr_uint32 optr,
    无符号短宽度、
    无符号短高度

    谢谢、
    此致、
    Pramod
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Hi Pramod,

     __vptr_uint16 in1_ptr:指向 VCOP buf 的指针,在本例中(uint16_t*) 0x40050000

    __vptr_uint32 optr:指向同一 VCOP 缓冲器的指针,因为我想将整个 VCOP 存储器用作一个输入/输出缓冲器,所以这里是(uint32_t*) 0x40050000

    无符号短宽度:连续的输入像素数、此处为16384

    无符号短高度:在本例中为1、因为我要以2D 方式处理后续数据、而不是数据

    此致、

    托比亚斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Tobias、
    此内核有两个问题。
    1.由于宽度范围为16384,因此当 icnt2 = 2047时,addr_out = 2047*8*2 = 32752。 由于输出数据为32位、因此您将访问32752 + 8 * 4字节= 32784、超过32KB。 这就是仿真器发出警告的原因。 由于这是最后一个条目、因此您的输出可能看起来像预期的那样。
    第二个问题是我之前在这个主题中提到的问题。 您的内核从同一位置读取和写入、但不能确保您的负载不是从与存储相同的位置读取和写入。 在第一次迭代之后、您将读取8 * sizeof (uint16_t)= 16字节、但您将写入8 * sizeof (uint32_t)= 32字节。 因此您已经改写了输入。

    此致、
    安州
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Tobias、
    我只是注意到您的输入是通过去交错负载实现的、因此我的第二点不正确。 您可以忽略我的第二条评论。 但第一条评论仍然很好、这会导致您观察到的问题。

    此致、
    安州
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Tobias、
    在内核上添加以下几个要点:
    您可以直接使用 Vdst |= Vsrc1 <<Vsrc2;// VSHFOR Vsrc1、Vsrc2、Vdst、Vdst 而不是使用两条指令来执行相同的操作。
    2.此内核是数据绑定的,即您正在为 DMA 执行的操作,然后是实际的计算本身。 通常、在这种情况下、您应该尝试通过添加更多内核来进行更多处理、以便有效利用 VCOP 的计算能力。
    3.目前您的内核没有有效地利用 VCOP,因为它只使用一个功能单元。 当前、每次迭代生成8个输出需要2个周期。 您可以通过处理更多数据并智能地放置输入和输出缓冲器来改进它。 我正在将一些修改粘贴到您的内核中以进行改进(我尚未编译、因此可能会出错)。 通过这些修改,此内核应花费2个周期来生成每个迭代的16个输出,而不是8个输出。 在这里、我已经将输入块分为2个部分、第一个部分位于 IBUFL 中、第二个部分位于 IBUFH 中(您可以通过 DMA 轻松实现此操作)。

    void buffer_merge
    (
    __vptr_uint16 inPtrL、
    __vptr_uint16 int16 intptrH、
    _vptr_uint32 optrL、
    _vptr_uint32 optrH、
    无符号短宽度/*最大应为8192、因为宽度应以元素大小*/为单位
    无符号短高度
    )
    {
    _vector Vin1、Vin2;
    _vector Vin3、Vin4;
    _矢量 Vshift;

    Vshift =移位;

    对于(int I1 = 0;I1 <高度;I1++)
    {
    对于(int I2 = 0;I2 < width/(VCOP_SIMD 宽);I2++)
    {
    _agen Addr_out;

    ADDR_OUT = I1*width*ELEMSZ*2 +I2*VECTORSZ*2;

    (Vin1、Vin2)= inPtrL[Addr_Out].deinterleave ();
    (Vin3、Vin4)= inPtrH[Addr_Out].deinterleave ();

    Vin2 |= Vin1 << Vshift;
    Vin4 = Vin3 << Vshift;

    optrL[Addr_OUT]= Vin2;
    optrH[Addr_OUT]= Vin4;
    }
    }
    }
    此致、
    安州
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Anshu、

    非常感谢您在我的内核上提供提示。 我在初始内核代码中使用的宽度是正确的。 它太大、因此在最后一个 VCOP 周期中超出了存储器边界。 我修复了这一问题、现在我的应用程序不会陷入循环中、也不会再抛出错误。

    我还尝试了您对内核的改进、并进行了一些更改(例如将 VCOP_SIMD 宽度更改为16)、效果很好。

    如前所述、我的应用程序现在始终在完成时不会出现与代码相关的错误、但我遇到了另一个问题:每当我选择大于或等于16kB 的 VCOP 缓冲器大小时、我的输出缓冲器包含错误的值。 每次我重新启动应用程序时、这些值始终从不断变化的位置显示、甚至不接近于预期值。

    奇怪的是、这些错误/错误值仅在我启动我的应用时出现、而没有任何断点(直接在 EVE/TDA3x 上)。 如果我使用断点运行它并通过它进行调试、则所有值都是可以的。 在 EVE 仿真器中、输出看起来也很好(代码中有和没有断点)。 我是否 需要注意运行时问题? 或者这可能是 EDMA 错误吗?

    附加的图像显示错误的值。 预期值应始终比上一个值高一、直到[2098039]。

    再次感谢大家的问候!

    托比亚斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Tobias、

       这看起来您的 DMA 正在覆盖输出数据的某些部分。 如本例前面所述、因为您必须在将新数据读取到同一存储器位置的同时写入输出数据、这可能会导致此问题。 您是否在代码中确保在读取新数据之前先完成输出数据的写入? 您能否在每个 EDMA 之后明确地等待、并查看您是否仍然看到问题?

    此致、

    安州

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Anshu、Tobias、

    由于标题为(在 EVE/VCOP 上使用组合式输入/输出缓冲器)的第一个查询已得到解答和解决、我建议关闭此主题并针对不同的问题启动新主题。 它使 E2E 中的搜索更简单、并使区分不同讨论的方法更清晰。

    谢谢、

    此致、

    Pramod

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Anshu、

    我找到了解决我的问题的方法。 显然、EDMA 设置了一些假参数(或其用途与我希望的不同)。 这会导致一个奇怪的情况、即 DMA 第二次将已经处理的块复制到随机位置。 仅当我在硬件上执行了程序并且没有断点时、才会发生此错误。 在 EVE 仿真器中、当单步执行时、它工作正常。 现在我自己设置了参数、它工作正常。

    此致
    托比亚斯