【问题标题】:How do I convert a floating point C code to fixed point?如何将浮点 C 代码转换为定点?
【发布时间】:2011-05-21 02:00:27
【问题描述】:

我有一个使用双精度的 C 代码。我希望能够在 DSP (TMS320) 上运行代码。但是 DSP 不支持双精度数,只支持定点数。将代码转换为定点的最佳方法是什么?有没有很好的定点数的 C 库(实现为整数)?

【问题讨论】:

  • 这是一个相当大的话题。在这个 SO 问题中有一个很好的讨论:stackoverflow.com/questions/79677/…。几乎所有的答案都有一些有用的提示。
  • 出于好奇,DSP的编译器是如何表示定点的?作为两个整数?例如,如何将两个定点数相加?
  • 它们表示为 32 位值 (long),并在类型中隐含移位。例如,如果在点 (_iq16) 之后有 16 位,则在基础类型中用整数 65536 表示定点数 1.0。对于相同类型的定点数的加减,您可以使用标准整数运算。乘法需要额外的移位来纠正缩放。

标签: c signal-processing fixed-point texas-instruments beagleboard


【解决方案1】:

以下代码定义了一个固定类型,使用整数作为其内部表示。只需使用+- 运算符即可执行加法和减法。使用定义的MULT 宏执行乘法。

#include <stdio.h>
typedef int Fixed;

#define FRACT_BITS 16
#define FRACT_BITS_D2 8
#define FIXED_ONE (1 << FRACT_BITS)
#define INT2FIXED(x) ((x) << FRACT_BITS)
#define FLOAT2FIXED(x) ((int)((x) * (1 << FRACT_BITS))) 
#define FIXED2INT(x) ((x) >> FRACT_BITS)
#define FIXED2DOUBLE(x) (((double)(x)) / (1 << FRACT_BITS))
#define MULT(x, y) ( ((x) >> FRACT_BITS_D2) * ((y)>> FRACT_BITS_D2) )

我使用上面的代码来表示我的图像处理算法中的分数。它比使用双精度的版本更快,结果几乎完全相同。

【讨论】:

【解决方案2】:

TI 提供了一个名为“IQmath”的定点库:

http://focus.ti.com/lit/sw/sprc990/sprc990.pdf

转换涉及分析您当前的代码 - 对于每个变量,您需要知道它可以容纳什么范围,以及它需要什么精度。然后您可以决定将其存储在哪种类型中。IQMath 提供的类型从 q30 范围为 +/-2,精度为 0.0000000001 到 q1,范围为 ~+/- 100 万,精度为 0.5。

对于可能溢出变量范围的操作,您需要添加溢出检查,并决定如何处理它 - 将其固定在最大值、以不同的比例存储、引发错误等。

如果不真正深入了解流程的数据流,就真的无法转换为定点。

【讨论】:

    【解决方案3】:

    大多数 DSP 工具链都包含用于在软件中进行浮点仿真的库。这会很慢,但您应该首先使用浮点支持构建您的代码,然后分析以查看是否只有几个地方需要转换为定点以获得足够的性能。您还需要运行浮点数据以在移植到定点时提供比较,以确保您在此过程中没有丢失任何内容。

    【讨论】:

      【解决方案4】:

      如果 C 代码很少/很少使用双精度数,那么您也许可以使用浮点仿真库,而不会导致 C 代码运行速度慢 10 倍到 100 倍。如果不希望性能受到影响并且有很多浮点运算,并且您知道每个实际输入的每个算术和存储操作所需的比例和精度,那么您可以手动将每个算术运算转换为使用缩放的整数数据类型和操作。但是,对于 DSP 类型代码,分析精度要求通常并非易事。有许多关于该主题的 DSP 和数值方法教科书章节。

      【讨论】:

      • ... 详细说明最后一句话,这样才有帮助。
      【解决方案5】:

      有一些图书馆可以为您做到这一点。不过,更可能的是,您设备的 PSP 应该包含某种数学库。应该记录在案。您可能需要重新编写一些代码,因为当您使用 PSP 提供的 API 时,您在执行基于基元的浮点运算时使用的控制结构可能没有意义。

      例如 - 你可以转换这个

      double arraysum = 0.0;
      for (int i = 0; i < arraylen; i++) 
      {
          arraysum += array[i];
      }
      

      到这里

      psp_decimal_t arraysum;
      if (0 != psp_sum_elements(&array, arraylen, &arraysum))
      {
          printf("error!");
      }
      

      【讨论】:

      • 遗憾的是,我无法在其他任何地方找到该内容,也无法找到发布该内容的个人。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-03
      相关资源
      最近更新 更多