Каждый блок имеет конечный файл, который определяет, какой код должен быть сгенерирован для блока. Код может отличаться в зависимости от точных параметров блока или типов связей с ним (например, широкий по сравнению со скалярным входом).
В каждом конечном файле блока block functions задает код, который будет выведен для блока в функции start
модели или подсистемы, функции output
, функции update
, и так далее.
Функции, объявленные в каждом из конечных файлов блока, вызваны системными конечными файлами. В этих таблицах block
относится к имени блока Simulink® (например, gain
для блока Gain), и system
относится к подсистеме, в которой находится блок. Первая таблица приводит две функции, которые используются для предварительной обработки и настройки. Ни одна из этих функций выходной сгенерированный код.
Следующие функции генерируют исполняемый код, который генератор кода помещает соответственно:
В условиях объектно-ориентированного программирования эти функции являются полиморфными по своей природе, потому что каждый конечный файл блока содержит те же функции. Компилятор Выходного языка динамически определяет во времени выполнения, которые блокируют функцию, чтобы выполниться в зависимости от типа блока. Таким образом, системный файл только указывает, что функция Outputs
, например, должна быть выполнена. Конкретная функция Outputs
определяется целевым Языковым компилятором в зависимости от типа блока.
Чтобы записать конечный файл блока, используйте эти полиморфные функции блока, объединенные с библиотечными функциями Компилятора Выходного языка. Для полного списка библиотечных функций Компилятора Выходного языка см. Справочное руководство по библиотеке Функции TLC на Компиляторе Выходного языка (Simulink Coder).
Функция BlockInstanceSetup
выполняется для блоков, которые имеют эту функцию, определяемую в их конечных файлах в модели. Например, если модель включает 10 От блоков Рабочей области, то функция BlockInstanceSetup
в fromwks.tlc
выполняется 10 раз, однажды для каждого экземпляра блока From Workspace. Используйте BlockInstanceSetup
, чтобы сгенерировать код для каждого экземпляра данного типа блока.
См. Справочное руководство по библиотеке Функции TLC на Компиляторе Выходного языка (Simulink Coder) для доступных сервисных функций обработки, чтобы вызвать из этой функции блока. Смотрите файл
для примера функции matlabroot/rtw/c/tlc/blocks/lookup2d.tlc
BlockInstanceSetup
.
BlockInstanceSetup(block, system) void block = Reference to a Simulink block system = Reference to a nonvirtual Simulink subsystem
Этот пример использует BlockInstanceSetup
:
%function BlockInstanceSetup(block, system) void %if (block.InMask == "yes") %assign blockName = LibParentMaskBlockName(block) %else %assign blockName = LibGetFormattedBlockPath(block) %endif %if (CodeFormat == "Embedded-C") %if !(ParamSettings.ColZeroTechnique == "NormalInterp" && ... ParamSettings.RowZeroTechnique == "NormalInterp") %selectfile STDOUT Note: Removing repeated zero values from the X and Y axes will produce more efficient code for block: %<blockName>. To locate this block, type open_system('%<blockName>') at the MATLAB command prompt. %selectfile NULL_FILE %endif %endif %endfunction
BlockTypeSetup
выполняется однажды на тип блока, прежде чем генерация кода начнет. Таким образом, если 10 блоков Интерполяционной таблицы существуют в модели, функция BlockTypeSetup
в look_up.tlc
вызвана только в один раз. Используйте эту функцию, чтобы выполнить общую работу для нескольких блоков данного типа.
См. Справочное руководство по библиотеке Функции TLC на Компиляторе Выходного языка (Simulink Coder) для списка соответствующих функций, чтобы вызвать из этой функции блока. Смотрите look_up.tlc
для примера функции BlockTypeSetup
.
BlockTypeSetup(block, system) void block = Reference to a Simulink block system = Reference to a nonvirtual Simulink subsystem
Как пример, учитывая S-функцию foo
, который требует #define
и двух объявлений функции в заголовочном файле, вы могли задать:
%function BlockTypeSetup(block, system) void %% Place a #define in the model's header file %openfile buffer #define A2D_CHANNEL 0 %closefile buffer %<LibCacheDefine(buffer)> %% Place function prototypes in the model's header file %openfile buffer void start_a2d(void); void reset_a2d(void); %closefile buffer %<LibCacheFunctionPrototype(buffer)> %endfunction
Остающиеся функции блока выполняются однажды для каждого блока в модели.
Генератор кода создает функции Enable
для невиртуальной подсистемы каждый раз, когда Подсистема Simulink содержит блок с функцией Enable
. Включая функцию Enable
в местах конечного файла блока конкретный блок включают код в этой подсистеме функция Enable
. Например:
%% Function: Enable ============================================ %% Abstract: %% Subsystem Enable code is required only for the discrete form %% of the Sine Block. Setting the Boolean to TRUE causes the %% Output function to resync its last values of cos(wt) and %% sin(wt). %% %function Enable(block, system) Output %if LibIsDiscrete(TID) /* %<Type> Block: %<Name> */ %<LibBlockIWork(SystemEnable, "", "", 0)> = (int_T) TRUE; %endif %endfunction
Невиртуальные функции Disable
подсистемы создаются каждый раз, когда Подсистема Simulink содержит блок с функцией Disable
. Включая функцию Disable
в местах конечного файла блока конкретный блок отключают код в эту подсистему функция Disable
.
Включайте функцию Start
, чтобы поместить код в функцию Start
. Код в функции Start
выполняется однажды и только однажды. Как правило, вы включаете функцию Start
, чтобы выполнить код однажды в начале симуляции (например, инициализировать значения в векторах работы) или код, который не должен быть повторно выполнен, когда подсистема, в которой это находится, включена. Смотрите constant.tlc
для примера функции Start
.
%% Function: Start ============================================ %% Abstract: %% Set the output to the constant parameter value if the block %% output is visible in the model's start function scope, i.e., %% it is in the global rtB structure. %% %function Start(block, system) Output %if LibBlockOutputSignalIsInBlockIO(0) /* %<Type> Block: %<Name> */ %assign rollVars = ["Y", "P"] %roll idx = RollRegions, lcv = RollThreshold, block, ... "Roller", rollVars %assign yr = LibBlockOutputSignal(0,"", lcv, ... "%<tRealPart>%<idx>") %assign pr = LibBlockParameter(Value, "", lcv, ... "%<tRealPart>%<idx>") %<yr> = %<pr>; %if LibBlockOutputSignalIsComplex(0) %assign yi = LibBlockOutputSignal(0, "", lcv, ... "%<tImagPart>%<idx>") %assign pi = LibBlockParameter(Value, "", lcv, ... "%<tImagPart>%<idx>") %<yi> = %<pi>; %endif %endroll %endif %endfunction %% Start
Код TLC, который сгенерирован от функции InitializeConditions
блока, появляется в одном из двух мест. Невиртуальная подсистема содержит функцию Initialize
, когда она сконфигурирована, чтобы сбросить состояния на, включают. В этом случае код TLC, сгенерированный этой функцией блока, помещается в подсистему функция Initialize
и вызовы функции start
эта подсистема функция Initialize
. Если, однако, блок Simulink находится в корневой системе или в невиртуальной подсистеме, которая не требует функции Initialize
, код, сгенерированный от этой функции блока, помещается непосредственно (встроенный) в функцию start
.
Существует тонкое различие между функциями блока Start
и InitializeConditions
. Как правило, вы включаете функцию Start
, чтобы выполнить код, который не должен повторно выполняться, когда подсистема, в которой он находится, включена. Вы включаете функцию InitializeConditions
, чтобы выполнить код, который должен повторно выполниться, когда подсистема, в которой он находится, включена. Например:
%% Function: InitializeConditions ============================= %% %% Abstract: Invalidate the stored output and input in %% rwork[1 2*blockWidth] by setting the time stamp stored %% in rwork[0]) to rtInf. %% %function InitializeConditions(block, system) Output /* %<Type> Block: %<Name> */ %<LibBlockRWork(PrevT, "", "", 0)> = %<LibRealNonFinite(inf)>; %endfunction
Блок должен обычно включать функцию Outputs
. Код TLC, сгенерированный функцией Outputs
блока, помещается в одно из двух мест. Код помещается непосредственно в функции Outputs
модели, если блок не находится в невиртуальной подсистеме, и в функции Outputs
подсистемы, если блок находится в невиртуальной подсистеме. Например:
%% Function: Outputs ========================================== %% Abstract: %% Y[i] = fabs(U[i]) if U[i] is real or %% Y[i] = sqrt(U[i].re^2 + U[i].im^2) if U[i] is complex. %% %function Outputs(block, system) Output /* %<Type> Block: %<Name> */ %% %assign inputIsComplex = LibBlockInputSignalIsComplex(0) %assign RT_SQUARE = "RT_SQUARE" %% %assign rollVars = ["U", "Y"] %if inputIsComplex %roll sigIdx = RollRegions, lcv = RollThreshold, ... block, "Roller", rollVars %% %assign ur = LibBlockInputSignal( 0, "", lcv, ... "%<tRealPart>%<sigIdx>") %assign ui = LibBlockInputSignal( 0, "", lcv, ... "%<tImagPart>%<sigIdx>") %% %assign y = LibBlockOutputSignal(0, "", lcv, sigIdx) %<y> = sqrt( %<RT_SQUARE>( %<ur> ) + %<RT_SQUARE>( %<ui> ) ); %endroll %else %roll sigIdx = RollRegions, lcv = RollThreshold, ... block, "Roller", rollVars %assign u = LibBlockInputSignal (0, "", lcv, sigIdx) %assign y = LibBlockOutputSignal(0, "", lcv, sigIdx) %<y> = fabs(%<u>); %endroll %endif %endfunction
Код сброса пересечения нулем помещается в функцию Outputs
.
Если вы пишете код TLC, чтобы сгенерировать встроенный код от S-функции, и если код TLC содержит функцию Outputs
, необходимо изменить код TLC, если все эти условия верны:
Выходной порт использует или наследовал постоянный шаг расчета. Выходной порт имеет постоянное значение.
S-функция является многоскоростной S-функцией или использует основанные на порте шаги расчета.
В этом случае код TLC должен сгенерировать код для выходного порта с постоянным знаком при помощи функционального OutputsForTID
вместо функционального Outputs
. Для получения дополнительной информации смотрите Задающий Постоянный Шаг расчета (Inf) для Порта (Simulink).
Включайте функцию Update
, если блок имеет код, который должен быть обновлен на каждом главном временном шаге. Код, сгенерированный от этой функции, помещается или в модель или в функция Update
подсистемы, в зависимости от того, находится ли блок в невиртуальной подсистеме. Например:
%% Function: Update ============================================ %% Abstract: %% X[i] = U[i] %% %function Update(block, system) Output /* %<Type> Block: %<Name> */ %assign rollVars = ["U", "Xd"] %roll idx = RollRegions, lcv = RollThreshold, block, ... "Roller", rollVars %assign u = LibBlockInputSignal(0, "", lcv, idx) %assign x = LibBlockDiscreteState("", lcv, idx) %<x> = %<u>; %endroll %endfunction %% Update
Включайте функцию Derivatives
при генерации кода, чтобы вычислить непрерывные состояния блока. Код, сгенерированный от этой функции, помещается или в модель или в функция Derivatives
подсистемы, в зависимости от того, находится ли блок в невиртуальной подсистеме. Смотрите integrat.tlc
для примера функции Derivatives
.
Включайте функцию Terminate
, чтобы поместить код в MdlTerminate
. Пользовательские конечные файлы S-функции могут использовать эту функцию, чтобы сохранить данные, свободную память, оборудование сброса на цели, и так далее. Смотрите tofile.tlc
для примера функции Terminate
.