timesN
Руководство по цикламObjective: Этот пример показывает, как можно повлиять на поведение циклов сгенерированного кода.
<reservedrangesplaceholder1> <reservedrangesplaceholder0>
(открыто)/ toolbox/rtw/rtwdemos/tlctutorial/timesN
Работайте с моделью sfun_xN
в tlctutorial/timesN
. Он имеет один источник (блок Sine Wave генератора), блок times N усиления, блок Out и блок Scope.
Учебное руководство поможет вам выполнить следующие шаги:
Getting Started - настройте упражнение и запустите модель
Modify the Model - Измените ширину входа и посмотрите результаты
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 панели диалогового окна Параметров конфигурации задайте 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
код является 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 обрабатывать специальные случаи. В случае, если |