timesN
Objective:, который показывает Этот пример, как можно влиять на поведение цикличного выполнения сгенерированного кода.
Folder: (открытый)
matlabroot/toolbox/rtw/rtwdemos/tlctutorial/timesN
Работа с моделью
sfun_xN
в tlctutorial/timesN
. Это имеет один источник (блок генератора Синусоиды), времена N блок усиления, блок Out и блок Scope.
Пример проводит вас по следующим шагам:
Начало работы Настройте осуществление и запустите модель
Modify the Model — Измените вход width и смотрите результаты
Change the Loop Rolling Threshold — Измените порог и смотрите результаты
More About TLC Loop Rolling — Параметризуйте поведение цикла
Начало работы
Сделайте
tlctutorial/timesN
вашей текущей папкой, так, чтобы можно было использовать обеспеченные файлы.
Примечание
Необходимо использовать или создать рабочую папку за пределами matlabroot
для моделей Simulink®, которые вы делаете. Вы не можете создать модели в исходных папках.
В Командном окне MATLAB® создайте файл MEX для S-функции:
mex timesN.c
Это старается не брать версию, поставленную с Simulink.
Примечание
Ошибка может произойти, если вы ранее не запустили mex -setup
.
Откройте образцовый файл
sfun_xN
.
Просмотрите ранее сгенерированный код в
sfun_xN_grt_rtw/sfun_xN.c
. Обратите внимание на то, что никакие циклы не существуют в коде. Это вызвано тем, что сигналы ввода и вывода являются скаляром.
Измените модель
Замените блок Sine Wave на блок Constant.
Установите параметр для блока Constant к 1:4 и измените главную метку,
model: sfun_xN
, к model: sfun_vec
.
Сохраните отредактированную модель как
sfun_vec
(в tlctutorial/timesN
). Модель теперь выглядит так.
Поскольку блок Constant генерирует вектор значений, это - векторизованная модель. Сгенерируйте код для модели и просмотрите раздел
/*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);
}
Заметьте, что существует четыре экземпляра кода, который генерирует образцовые выходные параметры, соответствуя четырем итерациям.
Установите параметр для блока Constant к 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
используется и инициализируется к массиву выходного сигнала.
Измените порог прокрутки цикла
Генератор кода создает итерации или циклы в зависимости от текущего значения параметра Loop unrolling threshold.
Значением по умолчанию Loop unrolling threshold является
5
. Изменить поведение цикличного выполнения для блоков в модели:
На панели Optimization диалогового окна Configuration Parameters, набор Loop unrolling threshold к
12
и нажимают Apply
.
Параметром
RollThreshold
является теперь 12
. Циклы будут сгенерированы только, когда ширина сигналов, проходящих через блок, превысит 12.
Примечание
Вы не можете изменить RollThreshold
для определенных блоков от диалогового окна Configuration Parameters.
Нажмите 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);
}
Чтобы активировать цикл, прокручивающийся снова, измените Loop unrolling threshold на 10 (или меньше) на панели Optimization.
Прокрутка цикла является важной возможностью TLC оптимизации сгенерированного кода. Не торопитесь, чтобы изучить и исследовать его последствия прежде, чем сгенерировать код для производственных требований.
Больше о прокрутке цикла TLC
Следующий код
%roll
TLC является функцией 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;
LibBlockInputSignal
библиотечных функций TLC и LibBlockOutputSignal
расширяются, чтобы произвести скалярные или векторные идентификаторы, которые называют и индексируют. LibBlockInputSignal
, LibBlockOutputSignal
, и много имели отношение, функции TLC передаются четыре канонических аргумента:
Аргумент | Описание |
---|---|
первый аргумент — | Соответствует индексу входного порта для данного блока. Первый входной порт имеет индекс 0. Второй входной порт имеет индекс 1 и так далее. |
второй аргумент — | Индексная переменная зарезервирована для усовершенствованного использования. На данный момент задайте второй аргумент как пустую строку. В усовершенствованных приложениях можно задать собственное имя переменной, которое будет использоваться в качестве индекса с |
третий аргумент — | Как описано ранее, |
четвертый аргумент — | Позволяет TLC обработать особые случаи. Если |
Похожие темы