exponenta event banner

Многословные операции с фиксированной точкой в сгенерированном коде

В этом примере показано, как управлять генерацией многословных операций в сгенерированном коде.

В этом примере вы узнаете:

  • Создание кода для типов больших данных с помощью многословных операций

  • Как предотвратить многословный код, если он не ожидается

Простая многословная операция

Эта модель показывает, как операции с целым числом и фиксированной точкой становятся многословными в сгенерированном коде C. Многословный код обычно запускается с использованием параметров или сигналов с типами данных шире, чем C 'long'.

open_system('fxpdemo_multiword_example1');
set_param('fxpdemo_multiword_example1','SimulationCommand','Update');

Создать код для модели:

evalc('slbuild(''fxpdemo_multiword_example1'');'); % Suppress output

В сгенерированном коде многословные операции реализуются с использованием функций. Эти функции будут иметь имя «MultiWord».

Просмотрите одну из сгенерированных многословных функций: MultiWordAdd()

fid = fopen('fxpdemo_multiword_example1_grt_rtw/fxpdemo_multiword_example1.c') ; ctext = fread(fid, '*char')'; fclose(fid);
match = regexp(ctext, 'void MultiWordAdd.*?\n\}', 'match'); disp(match{1});
void MultiWordAdd(const uint32_T u1[], const uint32_T u2[], uint32_T y[],
                  int32_T n)
{
  int32_T i;
  uint32_T carry = 0U;
  uint32_T u1i;
  uint32_T yi;
  for (i = 0; i < n; i++) {
    u1i = u1[i];
    yi = (u1i + u2[i]) + carry;
    y[i] = yi;
    carry = carry != 0U ? (uint32_T)(yi <= u1i) : (uint32_T)(yi < u1i);
  }
}

Эта функция реализует многословное сложение в C. Два операнда и результат имеют одинаковое количество слов, и сложение выполняется по одному слову за раз.

close_system('fxpdemo_multiword_example1', 0);

Блок реляционного оператора

В приведенном ниже примере блока реляционного оператора предполагается получить многословные функции в сгенерированном коде. Два входных типа данных: uint32 и ufix32_En3. Хорошим типом для сравнения является ufix35_En3, поскольку этот тип может представлять все реальные значения обоих операндов.

Мы ожидаем тип данных ufix35_En3 для реализации с использованием 64-разрядного двухсловного типа данных.

open_system('fxpdemo_multiword_example2');
set_param('fxpdemo_multiword_example2','SimulationCommand','Update');

Эта модель настроена для ЦП с длиной 32-разрядного C-типа. 64-разрядный тип данных будет многословным.

get_param(bdroot, 'ProdBitPerLong')
ans =

    32

Создайте код для модели и просмотрите:

evalc('slbuild(''fxpdemo_multiword_example2'');'); % Suppress output
fid = fopen('fxpdemo_multiword_example2_grt_rtw/fxpdemo_multiword_example2.c') ; ctext = fread(fid, '*char')'; fclose(fid);
match = regexp(ctext, 'void fxpdemo_multiword_example2_step.*?\n\}', 'match'); disp(match{1});
void fxpdemo_multiword_example2_step(void)
{
  /* RelationalOperator: '<Root>/LessThan' incorporates:
   *  Inport: '<Root>/In1'
   *  Inport: '<Root>/In2'
   */
  Y = (U1 < ((U2 & 4U) != 0U) + (U2 >> 3));
}

Многословный код не создан. Этот код является однословным и использует тип данных сравнения uint32. В результате может произойти потеря точности при сравнении.

Simulink балансирует требования для внутреннего типа данных для сравнения. В этом случае, поскольку все типы данных являются одним словом, он реализует эффективный тип данных, который создает небольшой, быстрый код, а не более точные, громоздкие вычисления.

close_system('fxpdemo_multiword_example2', 0);

Чтобы повысить точность этого расчета, выполните одно из следующих действий.

  • Выберите типы входных данных, которые можно сравнить с полной точностью, используя тип сравнения одного слова. Например, 16-разрядные типы или два одинаковых типа.

  • Принудите Simulink использовать многословный тип (во время моделирования и генерации кода), указав многословный тип хотя бы для одного из входов. Это сигнализирует Simulink о необходимости использования многословных операций для этого блока.

  • Настройте модель для 64-разрядной системы.

Функциональный блок MATLAB

В приведенном ниже примере функционального блока MATLAB показано вычисление всего одного слова. Многословный код не ожидается.

open_system('fxpdemo_multiword_example3');
set_param('fxpdemo_multiword_example3','SimulationCommand','Update');

mfb = get_param('fxpdemo_multiword_example3/MATLAB Function','MATLABFunctionConfiguration'); mfb.FunctionScript
ans =

    'function y = fcn(u1, u2)
     %#codegen
     
     y = fi(u1 * u2, 0, 32, 0);'

Создать код для модели:

evalc('slbuild(''fxpdemo_multiword_example3'');'); % Suppress output
fid = fopen('fxpdemo_multiword_example3_grt_rtw/fxpdemo_multiword_example3.c') ; ctext = fread(fid, '*char')'; fclose(fid);
match = regexp(ctext, 'void fxpdemo_multiword_example3_step.*?\n\}', 'match'); disp(match{1});
void fxpdemo_multiword_example3_step(void)
{
  uint64m_T tmp;
  uint64m_T tmp_0;

  /* MATLAB Function: '<Root>/MATLAB Function' incorporates:
   *  Inport: '<Root>/In1'
   *  Inport: '<Root>/In2'
   */
  /* MATLAB Function 'MATLAB Function': '<S1>:1' */
  /* '<S1>:1:4' */
  uMultiWordMul(&U1, 1, &U2, 1, &tmp_0.chunks[0U], 2);
  uMultiWordShrNear(&tmp_0.chunks[0U], 2, 3U, &tmp.chunks[0U], 2);

  /* Outport: '<Root>/Out1' incorporates:
   *  MATLAB Function: '<Root>/MATLAB Function'
   */
  fxpdemo_multiword_example3_Y.Out1 = uMultiWord2uLongSat(&tmp.chunks[0U], 2);
}
close_system('fxpdemo_multiword_example3', 0);

Несмотря на то, что все типы данных в модели были однословными, по-прежнему имеются три вызова многословных функций и две многословные переменные.

Операции с фиксированной точкой в функциональном блоке MATLAB управляются настройками свойств fimath.

fimath
ans = 


        RoundingMethod: Nearest
        OverflowAction: Saturate
           ProductMode: FullPrecision
               SumMode: FullPrecision

Этот fimath задает полную точность ProductMode. Поэтому умножение выполняется таким образом, что сохраняет максимально возможную точность. Тип данных продукта: uint64_En3, реализуется как многословный тип.

Вы можете управлять многословностью при создании кода MATLAB, манипулируя fimath. Например:

  • Настройка свойств fimath в соответствии с требованиями к эффективному коду. В этом примере задайте 'ProductMode' кому 'KeepLSB' и 'OverflowAction' кому 'Wrap'.

  • Определение локальных fimath в функциональном блоке MATLAB, которые адаптированы для конкретных вычислений и не зависят от глобального fimath.

load_system('fxpdemo_multiword_example4'); % No need to show this model. Only show the MATLAB code.
mfb = get_param('fxpdemo_multiword_example4/MATLAB Function','MATLABFunctionConfiguration'); mfb.FunctionScript
ans =

    'function y = fcn(u1, u2)
     %#codegen
     F = fimath('ProductMode','KeepLSB',...
         'ProductWordLength',32,...
         'OverflowAction','Wrap');
     u1 = setfimath(u1,F);
     u2 = setfimath(u2,F);
     y = fi(u1 * u2,0,32,0);
     '

Этот fimath приведет к созданию следующего кода:

evalc('slbuild(''fxpdemo_multiword_example4'');'); % Suppress output
fid = fopen('fxpdemo_multiword_example4_grt_rtw/fxpdemo_multiword_example4.c') ; ctext = fread(fid, '*char')'; fclose(fid);
match = regexp(ctext, 'void fxpdemo_multiword_example4_step.*?\n\}', 'match'); disp(match{1});
void fxpdemo_multiword_example4_step(void)
{
  uint32_T tmp;

  /* MATLAB Function: '<Root>/MATLAB Function' incorporates:
   *  Inport: '<Root>/In1'
   *  Inport: '<Root>/In2'
   */
  /* MATLAB Function 'MATLAB Function': '<S1>:1' */
  /* '<S1>:1:6' */
  /* '<S1>:1:7' */
  /* '<S1>:1:8' */
  tmp = U1 * U2;
  Y1 = ((tmp & 4U) != 0U) + (tmp >> 3);
}
close_system('fxpdemo_multiword_example4', 0);
clear ctext fid match mfb
clear ans

См. также

|