Задайте повторное использование буфера при помощи Simulink .Signal объектов

Если ваша модель имеет оптимальные настройки параметров для удаления копий данных, вы можете удалить дополнительные копии данных при помощи Simulink.Signal объекты для задания повторного использования буфера. После изучения сгенерированного кода и отчета Static Code Metrics Report и определения областей, где, по вашему мнению, повторное использование буфера возможно, вы задаете объекты сигнала на сигнальных линиях.

Можно задать повторное использование буфера для сигналов, которые включают пару корневых входных и выходных сигналов. Можно также задать повторное использование буфера только на паре корневых сигналов inport и outport. Эта оптимизация уменьшает потребление ПЗУ и ОЗУ, потому что в сгенерированном коде меньше глобальных переменных и копий данных. Скорость выполнения кода также увеличивается.

Пример модели

rtwdemo_reusable_csc модели содержит непереиспользуемую подсистему DeltaSubsystem и блок MATLAB Function Downsample. DeltaSubsystem содержит блоки MATLAB Function DeltaX и DeltaY.

model ='rtwdemo_reusable_csc';
open_system(model);

Задайте объект Simulink Signal для повторного использования

  1. В галерее галерей Apps в разделе Генерация кода нажмите Embedded Coder. Откроется вкладка Кода С.

  2. Чтобы открыть редактор Отображения, выберите Code Interface > Individual Element Code Mappings.

  3. В модели выберите RCSC_REAL сигнальная линия. Чтобы просмотреть этот сигнал или любой сигнал в редакторе Отображения, на вкладке Signals/States, нажмите кнопку Add selected signals to code mappings.

  4. Для строки, которая представляет сигнальную линию, смотрите столбец «Класс памяти». Объект сигнала использует класс памяти Reusable, что означает, что объект появляется в сгенерированном коде как глобальная переменная с именем RCSC_REAL.

  5. В модели перейдите в DeltaSubsystem подсистема.

  6. Выберите RCSC_REAL сигнальная линия в этой подсистеме. Этот сигнал также разрешается к объекту сигнала в базовом рабочем пространстве.

С Reusable класс памяти, сгенерированный код может хранить выходы Complex to Real-Imag блок (на корневом уровне модели) и выход DeltaX блок (в подсистеме) в RCSC_REAL глобальная переменная.

Сгенерируйте код

Создайте модель.

currentDir = pwd;
[~,cgDir] = rtwdemodir();
slbuild(model);
### Starting build procedure for: rtwdemo_reusable_csc
### Successful completion of build procedure for: rtwdemo_reusable_csc

Build Summary

Top model targets built:

Model                 Action                       Rebuild Reason                                    
=====================================================================================================
rtwdemo_reusable_csc  Code generated and compiled  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 16.799s

Для повторного использования буфера, rtwdemo_reusable_csc.c файл содержит следующие глобальные переменные:

  • static real_T RCSC_IMAG[1048576];

  • static real_T RCSC_IMAG2[262144];

  • static real_T RCSC_REAL[1048576];

  • static real_T RCSC_REAL2[262144];

The rtwdemo_reusable_csc.c файл содержит этот код:

cfile = fullfile(cgDir,...
    'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c');
rtwdemodbtype(cfile,...
    '/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',...
    '/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0);
rtwdemodbtype(cfile,...
    '/* Model step function */','/* Model initialize function */',1,0);
/* Output and update for atomic system: '<Root>/DeltaSubsystem' */
static void DeltaSubsystem(void)
{
  /* SignalConversion generated from: '<S1>/DeltaX' incorporates:
   *  MATLAB Function: '<S1>/DeltaX'
   */
  DeltaX((&(RCSC_REAL2[0])), (&(RCSC_IMAG2[0])), (&(RCSC_REAL[0])),
         (&(RCSC_IMAG[0])));

  /* SignalConversion generated from: '<S1>/DeltaY' incorporates:
   *  MATLAB Function: '<S1>/DeltaY'
   */
  DeltaY((&(RCSC_REAL[0])), (&(RCSC_IMAG[0])), (&(RCSC_REAL2[0])),
         (&(RCSC_IMAG2[0])));
}

/* Model step function */
void rtwdemo_reusable_csc_step(void)
{
  int32_T i;

  /* ComplexToRealImag: '<Root>/Complex to Real-Imag' incorporates:
   *  Inport: '<Root>/ComplexData'
   */
  for (i = 0; i < 1048576; i++) {
    RCSC_REAL[i] = rtU.ComplexData[i].re;
    RCSC_IMAG[i] = rtU.ComplexData[i].im;
  }

  /* End of ComplexToRealImag: '<Root>/Complex to Real-Imag' */

  /* MATLAB Function: '<Root>/Downsample' */
  Downsample((&(RCSC_REAL[0])), (&(RCSC_IMAG[0])), (&(RCSC_REAL2[0])),
             (&(RCSC_IMAG2[0])));

  /* Outputs for Atomic SubSystem: '<Root>/DeltaSubsystem' */
  DeltaSubsystem();

  /* End of Outputs for SubSystem: '<Root>/DeltaSubsystem' */

  /* Outport: '<Root>/Out1' incorporates:
   *  RealImagToComplex: '<Root>/Real-Imag to Complex'
   *  SignalConversion generated from: '<S1>/DeltaY'
   * */
  for (i = 0; i < 261121; i++) {
    rtY.Out1[i].re = RCSC_REAL2[i];
    rtY.Out1[i].im = RCSC_IMAG2[i];
  }

  /* End of Outport: '<Root>/Out1' */
}

Переменные RCSC_REAL и RCSC_IMAG удерживать выходы блока Complex to Real-Image и DeltaX. Эти переменные содержат входы в DeltaY блок. Переменные RCSC_REAL2 и RCSC_IMAG2 удерживать выходы Downsample и DeltaY. Эти переменные содержат входы в DeltaX блок. Путем чередования буферов таким образом, вы устраняете глобальные переменные в сгенерированном коде.

Чтобы удалить объекты сигнала из сигнальных линий и перегенерировать код, в Командном окне MATLAB введите следующие команды:

portHandles = get_param(...
    'rtwdemo_reusable_csc/Complex to Real-Imag','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

portHandles = get_param(...
    'rtwdemo_reusable_csc/Downsample','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

portHandles = get_param(...
    'rtwdemo_reusable_csc/DeltaSubsystem/DeltaX','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

portHandles = get_param(...
    'rtwdemo_reusable_csc/DeltaSubsystem/DeltaY','portHandles');
set_param(portHandles.Outport(1),'MustResolveToSignalObject','off');
set_param(portHandles.Outport(2),'MustResolveToSignalObject','off');

slbuild(model);
### Starting build procedure for: rtwdemo_reusable_csc
### Successful completion of build procedure for: rtwdemo_reusable_csc

Build Summary

Top model targets built:

Model                 Action                       Rebuild Reason                   
====================================================================================
rtwdemo_reusable_csc  Code generated and compiled  Generated code was out of date.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 11.54s

The rtwdemo_reusable_csc.c файл теперь содержит этот код.

cfile = fullfile(cgDir,...
    'rtwdemo_reusable_csc_ert_rtw','rtwdemo_reusable_csc.c');
rtwdemodbtype(cfile,...
    '/* Output and update for atomic system: ''<Root>/DeltaSubsystem'' */',...
    '/* Output and update for atomic system: ''<Root>/Downsample'' */',1,0);
rtwdemodbtype(cfile,...
    '/* Model step function */','/* Model initialize function */',1,0);
/* Output and update for atomic system: '<Root>/DeltaSubsystem' */
static void DeltaSubsystem(void)
{
  /* MATLAB Function: '<S1>/DeltaX' */
  DeltaX(rtDWork.z2, rtDWork.z1, rtDWork.z1_m, rtDWork.z2_c);

  /* MATLAB Function: '<S1>/DeltaY' */
  DeltaY(rtDWork.z1_m, rtDWork.z2_c, &rtDWork.z1[0], &rtDWork.z2[0]);
}

/* Model step function */
void rtwdemo_reusable_csc_step(void)
{
  int32_T i;

  /* ComplexToRealImag: '<Root>/Complex to Real-Imag' incorporates:
   *  Inport: '<Root>/ComplexData'
   */
  for (i = 0; i < 1048576; i++) {
    rtDWork.RCSC_REAL[i] = rtU.ComplexData[i].re;
    rtDWork.RCSC_IMAG[i] = rtU.ComplexData[i].im;
  }

  /* End of ComplexToRealImag: '<Root>/Complex to Real-Imag' */

  /* MATLAB Function: '<Root>/Downsample' */
  Downsample(rtDWork.RCSC_REAL, rtDWork.RCSC_IMAG, rtDWork.z2, rtDWork.z1);

  /* Outputs for Atomic SubSystem: '<Root>/DeltaSubsystem' */
  DeltaSubsystem();

  /* End of Outputs for SubSystem: '<Root>/DeltaSubsystem' */

  /* Outport: '<Root>/Out1' incorporates:
   *  RealImagToComplex: '<Root>/Real-Imag to Complex'
   */
  for (i = 0; i < 261121; i++) {
    rtY.Out1[i].re = rtDWork.z1[i];
    rtY.Out1[i].im = rtDWork.z2[i];
  }

  /* End of Outport: '<Root>/Out1' */
}

Сгенерированный код содержит две дополнительные глобальные переменные для хранения входных и выходных входов блоков.

Примечание: Вы можете задать повторное использование буфера на сигналах, которые генератор кода не может реализовать. В этих случаях используйте две диагностики, чтобы задать тип сообщения, которое отображается в модели. В диалоговом окне Параметров конфигурации эти диагностики: Обнаружение неиспользуемых пользовательских классов памяти и Обнаружение неоднозначных конечных значений пользовательского класса памяти.

bdclose(model)
rtwdemoclean;
cd(currentDir)

Повторное использование буфера для блоков Unit Delay и задержки

Чтобы повторно использовать сигнал блока Unit Delay или Delay, используйте ту же спецификацию переиспользуемого класса памяти для пары аргументов входа и состояния или пару аргументов выхода и состояния блока Unit Delay или Delay. Для блоков Delay необходимо задать параметр Delay length равным 1 и Начальное условие > Источник к Dialog. Чтобы получить доступ к этим параметрам, в модели откройте Property Inspector и щелкните блок в модели.

Ограничения для корневых входных и выходных сигналов

Эти ограничения применяются к модели, в которой вы задаете повторное использование буфера для пары корневых сигналов inport и outport:

  • Порты выхода не могут быть условными.

  • Если генератор кода не может повторно использовать тот же буфер в верхней модели, сгенерированный код содержит дополнительные буферы. Если модель верхней части является образцом модели, генератор кода сообщает об ошибке. Чтобы устранить ошибку, удалите спецификацию Simulink.signal из сигнала, который соединяется с выходным портом.

  • Когда вы запускаете исполняемый файл, который производит генератор кода, и вы повторно используете пару корневых сигналов inport и outport, когда корневое входное значение равно нулю, корневое выходное значение также должно быть нулем. Если выходное значение ненулевое, и вы повторно используете сигналы, то результаты симуляции могут отличаться от результатов, которые создает исполняемый файл.

  • Может быть симуляция и несоответствие генерации кода, когда вы присваиваете тот же класс памяти Reusable паре корневых входных и корневых выходных сигналов. Это несоответствие происходит, когда блок Assignment управляет блоком Root Outport, и блок Assignment не присваивает значение каждому элементу выхода сигнала, потому что порт Y блока Assignment не активен. На этом изображении показана модель, в которой происходит несовпадение:

Во время симуляции неписанные выходные значения блока Assignment равны нулю. Во время генерации кода неписанные выходные значения совпадают с входными.

Ограничения для модели

Эти ограничения применяются к модели, в которой вы задаете повторное использование буфера для сигналов:

  • Сигналы, которые вы задаете для повторного использования, должны иметь совпадающие типы данных и частот дискретизации.

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

  • Для моделей, в которых генератор кода переупорядочивает блок операции так, что Simulink.Signal повторное использование может произойти, вы можете наблюдать различие в отсортированном порядке. На вкладке Отладки в разделе Diagnostics выберите раскрывающуюся стрелу Information Overlays. В разделе « Блоках» диалогового окна выберите «Порядок выполнения». Чтобы отобразить отсортированный порядок выполнения во время симуляции, на вкладке Modeling, выберите Update Model. Чтобы отобразить порядок выполнения в сгенерированном коде, на вкладке Код С, выберите Build Model.

  • Можно задать повторное использование буфера для цепи переиспользуемых подсистем, пока эти подсистемы не будут повторно использоваться нигде в модели.

Похожие темы