timesN
Обзор примера по цикличному выполнениюObjective: В этом примере показано, как можно влиять на поведение цикличного выполнения сгенерированного кода.
Folder:
открытыйmatlabroot
/toolbox/rtw/rtwdemos/tlctutorial/timesN
Работа с моделью sfun_xN
в tlctutorial/timesN
. Это имеет один источник (блок генератора Sine Wave), блок усиления times N, блок Out и блок Scope.
Пример проводит вас по следующим шагам:
Начало работы Настройте осуществление и запустите модель
Modify the Model — Измените вход width и смотрите результаты
Change the Loop Rolling Threshold — Измените порог и смотрите результаты
More About TLC Loop Rolling — Параметрируйте поведение цикла
Сделайте tlctutorial/timesN
ваша текущая папка, так, чтобы можно было использовать обеспеченные файлы.
Примечание
Необходимо использовать или создать рабочую папку за пределами
для моделей Simulink® вы делаете. Вы не можете создать модели в исходных папках.matlabroot
В Командном окне 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 оптимизации сгенерированного кода. Не торопитесь, чтобы изучить и исследовать его последствия прежде, чем сгенерировать код для производственных требований.
Следующий %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;
Библиотечные функции TLC LibBlockInputSignal
и LibBlockOutputSignal
расширьтесь, чтобы произвести скалярные или векторные идентификаторы, которые называют и индексируют. LibBlockInputSignal
, LibBlockOutputSignal
, и много имели отношение, функции TLC передаются четыре канонических аргумента:
Аргумент | Описание |
---|---|
первый аргумент — | Соответствует индексу входного порта для данного блока. Первый входной порт имеет индекс 0. Второй входной порт имеет индекс 1 и так далее. |
второй аргумент — | Индексная переменная зарезервирована для усовершенствованного использования. На данный момент задайте второй аргумент как пустую строку. В усовершенствованных приложениях можно задать собственное имя переменной, которое будет использоваться в качестве индекса с |
третий аргумент — | Аналогичный описанному ранее, |
четвертый аргумент — | Позволяет TLC обработать особые случаи. Если |