S-функции для многозадачных окружений с многозадачностью

О S-функциях для многозадачных окружений с многозадачностью

S-функции могут использоваться в моделях с несколькими скоростями дискретизации и развертываться в многозадачных целевых окружениях. Аналогичным образом, сами S-функции могут иметь несколько скоростей, с которыми они работают. Генератор кода производит код для многозадачных моделей многозадачности с помощью подхода, называемого группировкой скорости. В коде, сгенерированном для целевых объектов на основе ERT, группировка скоростей генерирует отдельные model_step функции для задачи базовой скорости и каждой задачи подрейса в модели. Хотя группировка скоростей является функцией генерации кода, найденной только в целевых устройствах ERT, ваши S-функции могут использовать ее в других контекстах, когда вы кодируете их, как объяснено ниже.

Поддержка группировки скоростей в S-функциях

Чтобы воспользоваться преимуществами группировки скоростей, необходимо встроить мультирейсовые S-функции, если вы этого не сделали. Вам необходимо следовать определенным протоколам Target Language Compiler, чтобы использовать группировку скоростей. Кодирование TLC для использования группировки скоростей не препятствует правильному функционированию встроенных S-функций в GRT. Точно так же ваши встроенные S-функции все еще будут генерировать действительные ERT кода даже если вы не сделаете их совместимыми с группировкой скоростей. Однако, если вы это сделаете, они сгенерируют более эффективный код для многоскоростных моделей.

Инструкции и примеры кода Target Language Compiler, иллюстрирующие, как создать и обновить 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-функциях. Они не охватывают случаи, когда нет ни детерминизма, ни целостности. Поддержка обработки на основе фрейма не влияет на требования.

Примечание

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

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

Правила, которые мультирейт S-функций должен наблюдать для входов,

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

  • Обычно входные данные записываются в DWork, и DWork можно затем получить доступ с более медленной (нисходящей) скоростью.

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

Правила, которые мультирейт S-функций должен наблюдать для выходов,

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

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

Если эти условия выполняются, блок S-Function может указать, что входной порт и выходной порт могут быть локальными и переиспользуемыми.

Можно включать оптимизацию, когда обработка данных практически не требуется. В таких случаях код скорости входа может непосредственно записать в вывод (вместо использования DWork), когда есть специальная выборка хит. Однако если вы делаете это, необходимо объявить порт вывода глобальным и не переиспользуемым. Это результаты оптимизации на единицу меньше memcpy но вводит неоднородные требования к обработке на более высокой скорости.

Используете ли вы эту оптимизацию или нет, самые последние входные данные, как видно из более медленной скорости, являются значением, когда и более быстрая, и более медленная скорость имели свои удары (и возможные более ранние входные данные также, в зависимости от алгоритма). Последующие шаги по более высокой скорости и связанным обновлениям входных данных не видны по более низкой скорости до тех пор, пока не произойдет следующее попадание по медленной скорости.

Псевдокодные примеры перехода скорости от быстрого к медленному

Псевдокод ниже абстрагирует, как вы должны записать свой код C MEX для обработки быстрых к медленным переходам, иллюстрируя со скоростью входом 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;}