timesN Обзор учебного пособия по закольцовываниюЦель: В этом примере показано, как можно влиять на циклическое поведение сгенерированного кода.
Папка:
(открыто)matlabroot/toolbox/rtw/rtwdemos/tlctutorial/timesN
Работа с моделью sfun_xN в tlctutorial/timesN. Он имеет один источник (блок генератора синусоидальной волны), блок усиления с умножением N, блок Out и блок Scope.
В учебном пособии описаны следующие шаги.
Начало работы - настройка упражнения и запуск модели
Изменить модель (Modify the Model) - изменение ширины ввода и просмотр результатов
Изменение порога свертывания цикла - изменение порога и просмотр результатов
Дополнительные сведения о качении цикла TLC - параметризация поведения цикла
Сделать tlctutorial/timesN текущую папку, чтобы можно было использовать предоставленные файлы.
Примечание
Необходимо использовать или создавать рабочую папку вне для моделей Simulink ®. Нельзя строить модели в исходных папках.matlabroot
В окне команд MATLAB ® создайте файл MEX для функции S:
mex timesN.c
Это позволяет избежать выбора версии, поставляемой с Simulink.
Примечание
Ошибка может возникнуть, если вы ранее не запускали mex -setup.
Открытие файла модели sfun_xN.

Просмотр ранее созданного кода в sfun_xN_grt_rtw/sfun_xN.c. Обратите внимание, что в коде не существует циклов. Это происходит потому, что входной и выходной сигналы являются скалярными.
Замените блок синусоидальной волны блоком константы.
Установите для параметра блока «Константа» значение 1:4 и измените верхнюю метку. model: sfun_xNКому model: sfun_vec.
Сохранить отредактированную модель как sfun_vec (в tlctutorial/timesN). Модель теперь выглядит так.

Поскольку блок константы генерирует вектор значений, это векторизированная модель. Создание кода для модели и просмотр /*Model output function */ раздел sfun_vec.c в редакторе, чтобы наблюдать, как переменные и for обрабатываются петли. Эта функция выглядит следующим образом:
/* Model output function */
static void sfun_vec_output(int_T tid)
{
/* S-Function Block: <Root>/S-Function */
/* Multiply input by 3.0 */
sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0;
sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0;
sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0;
sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0;
/* Outport: '<Root>/Out' */
sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0];
sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1];
sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2];
sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3];
UNUSED_PARAMETER(tid);
}Обратите внимание, что существует четыре экземпляра кода, который генерирует выходные данные модели, соответствующие четырем итерациям.
Задайте для параметра блока «Константа» значение 1:10 и сохраните модель.
Создание кода для модели и просмотр /*Model output function */ раздел sfun_vec.c в редакторе, чтобы наблюдать, как переменные и for обрабатываются петли. Эта функция выглядит следующим образом:
/* Model output function */
static void sfun_vec_output(int_T tid)
{
/* S-Function Block: <Root>/S-Function */
/* Multiply input by 3.0 */
{
int_T i1;
const real_T *u0 = &sfun_vec_P.Constant_Value[0];
real_T *y0 = sfun_vec_B.timesN_output;
for (i1=0; i1 < 10; i1++) {
y0[i1] = u0[i1] * 3.0;
}
}
{
int32_T i;
for (i = 0; i < 10; i++) {
/* Outport: '<Root>/Out' */
sfun_vec_Y.Out[i] = sfun_vec_B.timesN_output[i];
}
}
UNUSED_PARAMETER(tid);
}Обратите внимание, что:
Код, генерирующий выходные данные модели, «сворачивается» в цикл. Это происходит по умолчанию, когда число итераций превышает 5.
Индекс цикла i1 выполняется от 0 до 9.
Указатель *y0 используется и инициализируется в матрице выходных сигналов.
Генератор кода создает итерации или циклы в зависимости от текущего значения параметра Порог разгрузки цикла.
Значение по умолчанию для порога разгрузки цикла: 5. Чтобы изменить поведение цикла для блоков в модели, выполните следующие действия.
На панели Оптимизация (Optimization) диалогового окна Параметры конфигурации (Configuration Parameters) установите значение Порог разгрузки цикла (Loop unrolling threshold) 12 и нажмите Apply.
Параметр RollThreshold сейчас 12. Петли будут генерироваться только тогда, когда ширина сигналов, проходящих через блок, превысит 12.
Примечание
Изменение невозможно RollThreshold для определенных блоков в диалоговом окне «Параметры конфигурации».
Нажмите Ctrl + B, чтобы регенерировать выходные данные.
Осмотреть sfun_vec.c. Это будет выглядеть следующим образом:
/* Model output function */
static void sfun_vec_output(int_T tid)
{
/* S-Function Block: <Root>/S-Function */
/* Multiply input by 3.0 */
sfun_vec_B.timesN_output[0] = sfun_vec_P.Constant_Value[0] * 3.0;
sfun_vec_B.timesN_output[1] = sfun_vec_P.Constant_Value[1] * 3.0;
sfun_vec_B.timesN_output[2] = sfun_vec_P.Constant_Value[2] * 3.0;
sfun_vec_B.timesN_output[3] = sfun_vec_P.Constant_Value[3] * 3.0;
sfun_vec_B.timesN_output[4] = sfun_vec_P.Constant_Value[4] * 3.0;
sfun_vec_B.timesN_output[5] = sfun_vec_P.Constant_Value[5] * 3.0;
sfun_vec_B.timesN_output[6] = sfun_vec_P.Constant_Value[6] * 3.0;
sfun_vec_B.timesN_output[7] = sfun_vec_P.Constant_Value[7] * 3.0;
sfun_vec_B.timesN_output[8] = sfun_vec_P.Constant_Value[8] * 3.0;
sfun_vec_B.timesN_output[9] = sfun_vec_P.Constant_Value[9] * 3.0;
/* Outport: '<Root>/Out' */
sfun_vec_Y.Out[0] = sfun_vec_B.timesN_output[0];
sfun_vec_Y.Out[1] = sfun_vec_B.timesN_output[1];
sfun_vec_Y.Out[2] = sfun_vec_B.timesN_output[2];
sfun_vec_Y.Out[3] = sfun_vec_B.timesN_output[3];
sfun_vec_Y.Out[4] = sfun_vec_B.timesN_output[4];
sfun_vec_Y.Out[5] = sfun_vec_B.timesN_output[5];
sfun_vec_Y.Out[6] = sfun_vec_B.timesN_output[6];
sfun_vec_Y.Out[7] = sfun_vec_B.timesN_output[7];
sfun_vec_Y.Out[8] = sfun_vec_B.timesN_output[8];
sfun_vec_Y.Out[9] = sfun_vec_B.timesN_output[9];
UNUSED_PARAMETER(tid);
}Чтобы снова активировать прокрутку цикла, измените пороговое значение для разворачивания цикла на 10 (или менее) на панели Оптимизация (Optimization).
Циклическая обработка является важной функцией TLC для оптимизации генерируемого кода. Уделите некоторое время изучению и изучению его последствий перед созданием кода для производственных требований.
Следующий TLC %roll код - Outputs функция timesN.tlc:
%function Outputs(block, system) Output
/* %<Type> Block: %<Name> */
%%
/* Multiply input by %<gain> */
%assign rollVars = ["U", "Y"]
%roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%<LibBlockOutputSignal(0, "", lcv, idx)> = \
%<LibBlockInputSignal(0, "", lcv, idx)> * %<gain>;
%endroll
%endfunction %% Outputs%rollЛинии между %roll и%endroll может быть повторен или закольцован. Ключ к пониманию %roll директива в своих аргументах:
%roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
| Аргумент | Описание |
|---|---|
sigIdx | Укажите индекс в вектор (сигнала), который используется в сгенерированном коде. Если сигнал является скалярным, при анализе этого блока |
lcv | Управляющая переменная, обычно указанная в |
block | Это сообщает TLC, что он работает с объектами блока. Код TLC для S-функций использует этот аргумент. |
"Roller" | Это, указано в |
rollVars | Сообщает TLC, какие типы элементов должны быть свернуты: входные сигналы, выходные сигналы и/или параметры. Вы не должны использовать все из них. В предыдущей строке %assign rollVars = ["U", "Y"] U) и выходных сигналов (Y). В случаях, когда блоки задают массив параметров вместо скалярного параметра, rollvars указывается как%assign rollVars = ["U", "Y", "P"] |
Посмотрите на линии, которые появляются между %roll и %endroll:
%<LibBlockOutputSignal(0, "", lcv, idx)> = \ %<LibBlockInputSignal (0, "", lcv, idx)> * 2.0;
Функции библиотеки TLC LibBlockInputSignal и LibBlockOutputSignal разверните, чтобы создать скалярные или векторные идентификаторы, которые именуются и индексируются. LibBlockInputSignal, LibBlockOutputSignalи ряду связанных функций TLC передаются четыре канонических аргумента:
| Аргумент | Описание |
|---|---|
первый аргумент - | Соответствует индексу входного порта для данного блока. Первый входной порт имеет индекс 0. Второй входной порт имеет индекс 1 и т.д. |
второй аргумент - | Переменная индекса, зарезервированная для расширенного использования. Теперь укажите второй аргумент как пустую строку. В расширенных приложениях можно определить собственное имя переменной для использования в качестве индекса с |
третий аргумент - | Как описано выше, |
четвертый аргумент - | Позволяет TLC обрабатывать особые случаи. В случае, если |