S-функции могут использоваться в моделях с несколькими частотами дискретизации и развертываться в многозадачных целевых окружениях. Аналогично, сами S-функции могут иметь несколько уровней, на которых они действуют. Генератор кода производит код для многоскоростных многозадачных моделей с помощью названной группировки уровня подхода. В коде, сгенерированном для основанных на ERT целей, группировка уровня генерирует отдельный model
функции _step
для задачи базовой ставки и каждой задачи подуровня в модели. Несмотря на то, что группировка уровня является функцией генерации кода, найденной в целях ERT только, ваши S-функции могут использовать ее в других контекстах, когда вы кодируете их, как объяснено ниже.
Чтобы использовать в своих интересах группировку уровня, необходимо встроить многоскоростные S-функции, если вы не сделали так. Необходимо следовать определенным протоколам Компилятора Выходного языка, чтобы использовать группировку уровня. Кодирование TLC, чтобы использовать группировку уровня не препятствует тому, чтобы ваши встроенные S-функции функционировали правильно в GRT. Аналогично, ваши встроенные S-функции все еще сгенерируют допустимый код ERT, даже если вы не сделаете их "уровнем, группирующимся совместимый". Если вы сделаете так, однако, они сгенерируют более эффективный код для многоскоростных моделей.
Для инструкций и примеров кода Компилятора Выходного языка, иллюстрирующего, как создать и обновить S-функции, чтобы сгенерировать уровень, группирующий совместимый код, смотрите, что Уровень Группирует Проблемы соответствия и Проблемы совместимости (Embedded Coder).
Для каждой многоскоростной S-функции, которая не является совместимым группировкой уровнем, генератор кода выдает следующее предупреждение, когда вы создаете:
Warning: Simulink Coder: Code of output function for multirate block '<Root>/S-Function' is guarded by sample hit checks rather than being rate grouped. This will generate the same code for all rates used by the block, possibly generating dead code. To avoid dead code, you must update the TLC file for the block.
Вы также найдете комментарий, такой как следующее в коде сгенерированным для каждой несовместимой S-функции:
/* Because the output function of multirate block <Root>/S-Function is not rate grouped, the following code might contain unreachable blocks of code. To avoid this, you must update your block TLC file. */
Словами “функция обновления” заменяют “выходную функцию” в этих предупреждениях.
Следующие инструкции показывают, как поддержать и детерминизм данных и целостность данных в многоскоростных S-функциях. Они не покрывают случаи, где нет никакого детерминизма, ни целостности. Поддержка основанной на кадре обработки не влияет на требования.
Низкие скорости должны быть множителями самого быстрого уровня. Инструкции не применяются, когда два соединяемые интерфейсом уровня не являются множителями или когда уровни не являются периодическими.
Правила, что многоскоростные S-функции должны наблюдать для входных параметров,
Вход должен только быть считан на уровне, который сопоставлен с шагом расчета входного порта.
Обычно входные данные записаны в DWork
, и к DWork
можно затем получить доступ на медленнее (нисходящем) уровне.
Вход может быть считан при каждом демонстрационном хите входного уровня и записан в память DWork
, но к этой памяти DWork
не может затем непосредственно получить доступ более медленный уровень. память DWork
, которая будет считана низкой скоростью, должна только быть записана высокой скоростью, когда существует специальный демонстрационный хит. Специальный демонстрационный хит происходит, когда и этот уровень входного порта и уровень, к которому это взаимодействует через интерфейс, имеют хит. В зависимости от их требований и проекта, алгоритмы могут обработать данные в нескольких местоположениях.
Правила, что многоскоростные S-функции должны наблюдать для выходных параметров,
Вывод не должен быть записан уровнем кроме уровня, присвоенного выходному порту, кроме оптимизированного случая, описанного ниже.
Вывод должен всегда писаться, когда частота дискретизации выходного порта имеет хит.
Если эти условия соблюдают, Блок s-function может указать, что входной порт и выходной порт могут и быть сделаны локальными и допускающими повторное использование.
Можно включать оптимизацию, когда минимальная обработка должна быть сделана на данных. В таких случаях входной код уровня может непосредственно записать в вывод (вместо при помощи DWork), когда существует специальный демонстрационный хит. Если вы делаете это, однако, необходимо объявить, что порт выходного порта глобальная переменная и не допускающие повторное использование. Это результаты оптимизации в одном меньшем количестве memcpy
, но действительно вводит неоднородные требования к обработке на более быстром уровне.
Используете ли вы эту оптимизацию или нет, новые входные данные, как замечено более медленным уровнем, значение, когда и быстрее и более медленный уровень имел их хиты (и возможные более ранние входные данные также, в зависимости от алгоритма). Последующие шаги более быстрым уровнем и связанными обновлениями входных данных не замечены более медленным уровнем, пока следующий хит для низкой скорости не происходит.
Псевдокод ниже абстрагирует, как необходимо записать код MEX C, чтобы обработать быстрые-к-медленному переходы, иллюстрирующие с входным уровнем 0,1 вторых управлений нормой выработки одной секунды. Аналогичный подход может быть проявлен при встраивании кода. Блок имеет следующие характеристики:
Файл: sfun_multirate_zoh.c
, уравнение: y = u(tslow)
Входной параметр: локальный и допускающий повторное использование
Вывод : локальный и допускающий повторное использование
DirectFeedthrough: да
OutputFcn if (ssIsSampleHit(".1")) { if (ssIsSepcialSampleHit("1")) { DWork = u; } } if (ssIsSampleHit("1")) { y = DWork; }
Альтернатива, немного оптимизированный подход для простых алгоритмов:
Входной параметр: локальный и допускающий повторное использование
Вывод : глобальная переменная и не допускающий повторное использование, потому что это должно сохраниться между специальными демонстрационными хитами
DirectFeedthrough: да
OutputFcn if (ssIsSampleHit(".1")) { if (ssIsSpecialSampleHit("1")) { y = u; } }
Пример, добавляющий простой алгоритм:
Файл: sfun_multirate_avg.c
; уравнение: y = average(u)
Входной параметр: локальный и допускающий повторное использование
Вывод : локальный и допускающий повторное использование
DirectFeedthrough: да
(Примите, что DWork[0:10]
и DWork[mycounter]
инициализируются, чтобы обнулить),
OutputFcn if (ssIsSampleHit(".1")) { /* In general, processing on 'u' could be done here, it runs on every hit of the fast rate. */ DWork[DWork[mycounter]++] = u; if (ssIsSpecialSampleHit("1")) { /* In general, processing on DWork[0:10] can be done here, but it does cause the faster rate to have nonuniform processing requirements (every 10th hit, more code needs to be run).*/ DWork[10] = sum(DWork[0:9])/10; DWork[mycounter] = 0; } } if (ssIsSampleHit("1")) { /* Processing on DWork[10] can be done here before outputing. This code runs on every hit of the slower task. */ y = DWork[10]; }
Когда нормы выработки быстрее, чем входные уровни, вход должен только быть считан на уровне, который сопоставлен с шагом расчета входного порта, наблюдая следующие правила:
Всегда читайте вход из функции обновления.
Не используйте специальные демонстрационные проверки хита когда вход чтения.
Запишите вход в DWork.
Когда будет специальный демонстрационный хит между уровнями, скопируйте DWork во второй DWork в выходной функции.
Запишите второй DWork в вывод при каждом хите выходной частоты дискретизации.
Блок может запросить, чтобы входной порт был сделан локальным, но это не может быть установлено в допускающий повторное использование. Выходной порт может быть установлен в локальный и допускающее повторное использование.
Как в быстром-к-медленному случае перехода, вход не должен быть считан уровнем кроме того, присвоенного входному порту. Точно так же вывод не должен быть записан в на уровне кроме уровня, присвоенного выходному порту.
Оптимизация может быть сделана, когда реализовываемый алгоритм только требуется запуститься на низкой скорости. В таких случаях вы используете только один DWork. Вход все еще пишет в DWork в функции обновления. Когда существует специальный демонстрационный хит между уровнями, выходная функция копирует тот же DWork непосредственно в вывод. Необходимо установить выходной порт быть глобальной переменной и не допускающие повторное использование в этом случае. Это результаты оптимизации в одном меньшем количестве операции memcpy
на специальный демонстрационный хит.
В любом случае всегда задерживаются данные, с которыми работают вычисления высокой скорости, то есть, данные от предыдущего шага кода низкой скорости.
Псевдокод ниже абстрагирует то, что ваша S-функция должна сделать, чтобы обработать переходы быстрого не спешения, иллюстрирующие с входным уровнем одного второго управления нормой выработки 0,1 секунд. Блок имеет следующие характеристики:
Файл: sfun_multirate_delay.c
, уравнение: y = u(tslow-1)
Входной параметр: Установите на локальную переменную, будет локально, если выведенный/обновленный будут объединены (ERT), то в противном случае будет глобальная переменная. Установите на не допускающий повторное использование, потому что введенные потребности, которые будут сохранены до функции обновления, запускаются.
Вывод : локальный и допускающий повторное использование
DirectFeedthrough: нет
OutputFcn if (ssIsSampleHit(".1") { if (ssIsSpecialSampleHit("1") { DWork[1] = DWork[0]; } y = DWork[1]; } UpdateFcn if (ssIsSampleHit("1")) { DWork[0] = u; }
Альтернативный, оптимизированный подход может использоваться некоторыми алгоритмами:
Входной параметр: Установите на локальную переменную, будет локально, если выведенный/обновленный будут объединены (ERT), то в противном случае будет глобальная переменная. Установите на не допускающий повторное использование, потому что введенные потребности, которые будут сохранены до функции обновления, запускаются.
Вывод : глобальная переменная и не допускающий повторное использование, потому что это должно сохраниться между специальными демонстрационными хитами.
DirectFeedthrough: нет
OutputFcn if (ssIsSampleHit(".1") { if (ssIsSpecialSampleHit("1") { y = DWork; } } UpdateFcn if (ssIsSampleHit("1")) { DWork = u; }
Пример, добавляющий простой алгоритм:
Файл: sfun_multirate_modulate.c
, уравнение: y = sin(tfast) + u(tslow-1)
Входной параметр: Установите на локальную переменную, будет локально, если выведенный/обновленный будут объединены (то функция ERT) в противном случае будет глобальная переменная. Установите на не допускающий повторное использование, потому что введенные потребности, которые будут сохранены до функции обновления, запускаются.
Вывод : локальный и допускающий повторное использование
DirectFeedthrough: нет
OutputFcn if (ssIsSampleHit(".1") { if (ssIsSpecialSampleHit("1") { /* Processing not likely to be done here. It causes * the faster rate to have nonuniform processing * requirements (every 10th hit, more code needs to * be run).*/ DWork[1] = DWork[0]; } /* Processing done at fast rate */ y = sin(ssGetTaskTime(".1")) + DWork[1]; } UpdateFcn if (ssIsSampleHit("1")) { /* Processing on 'u' can be done here. There is a delay of one slow rate period before the fast rate sees it.*/ DWork[0] = u;}