tlc与sfunction(三)Inlining sfunction(内联/嵌入型sfunction)

Inlining sfunction(内嵌型/内联sfunction)

内联S函数意味着为S函数块提供一个TLC文件,该文件将替换模拟过程中使用的C、C++、Fortran或MATLAB语言版本的块。

Noninlined S-Function(非内嵌/非内联的sfunction)
如果没有提供内联TLC文件,大多数目标都会通过重新编译块的C MEX S函数来支持该块。如前所述,当使用C/C++编码的S函数和代码生成器上下文中支持的mx*neneneba API调用的有限子集时,内存使用和速度会有开销。如果你想要最有效的生成代码,你必须通过为S函数编写一个TLC文件来内联它们。

当模拟需要执行S函数块的一个函数时,它会调用该函数的MEX文件。当代码生成器执行非联机S函数时,它以类似的方式执行,如图所示。

inlining的类型

-完全inlined S-function(fully inlined sfunction)

-封装inlined S-function(wrapper inlined sfunction)

虽然两者都有效地内联了S函数并消除了非内联S函数的开销,但这两种方法是不同的。下面使用timestwo.tlc的第一个示例被认为是一个完全内联的tlc文件(fully inlined sfunction),其中块的完整实现包含在块的tlc文件中。

第二个示例使用封装的TLC文件(wrapper inlined sfunction)。这个例子调用了一个包含代码体的C函数,而不是在原地生成所有算法代码。使用wrapper TLC文件有几个潜在的好处:

•它为C MEX S函数和生成的代码提供了一种共享C代码的方法。无需重复编写代码。
•调用的C函数是一个优化的例程。
•模型中可能存在几个块,让它们调用一个函数在代码大小方面更有效,而不是每个块都创建相同的算法代码。
•它提供了一种将遗留C代码无缝合并到生成代码中的方法

完全inlined S-function的例子(fully inlined sfunction)

嵌入S函数提供了一种机制,可以将S函数块的代码直接嵌入到模型的生成代码中。代码显示为“内联”,而不是通过函数指针调用单独的源文件并为其维护单独的数据结构(SimStruct),如下图所示。

S函数timestwo.c提供了一个完全内联的S函数的简单示例。该块将其输入乘以2并输出。该块的C MEX版本位于matlabroot/simulink/src/timetwo.C中,该块的内联TLC文件位于matlabroot/toolbox/simulink/blocks/TLC_C/timetwo.TLC中。

timestow.tlc

%implements "timestwo" "C"
%% Function: Outputs ==========================================
%%
%function Outputs(block, system) Output
     /* %<Type> Block: %<Name> */
     %%
    /* Multiply input by two */
    %assign rollVars = ["U", "Y"]
    %roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
        %<LibBlockOutputSignal(0, "", lcv, idx)> = \
        %<LibBlockInputSignal(0, "", lcv, idx)> * 2.0;
    %endroll
%endfunction

上面这个TLC代码块的分析

所有TLC块文件都需要%implementations指令,目标语言编译器使用该指令来验证块的正确块类型和正确的语言支持。%function指令启动函数声明,并显示函数名称、输出以及传递给它的参数、块和系统。这些是该块实例的model.rtw文件中的相关记录。

函数原型的最后一部分是Output。这意味着任何不是TLC指令的行都会由函数输出到TLC中选择的当前文件中。因此,Outputs函数中的任何非指令行都将成为该块的生成代码。

这个TLC块示例中最复杂的部分是%roll指令。
TLC使用此指令提供for循环的自动生成,具体取决于输入/输出宽度以及输入在内存中是否连续。此示例使用从卷体内访问输出和输入的典型形式,使用LibBlockOutputSignalLibBlockInputSignal访问输出和输出并执行乘法和赋值。请注意,此TLC文件支持任何信号宽度。

实现此块所需的唯一功能是输出。
对于更复杂的块,也会声明其他函数。您可以在matlabroot/toolbox/simulink/blocks和matlabroot/stoolbox/simulink/bocks/TLC_c中找到更复杂的内联TLC文件的示例,也可以通过查看matlabroot/rtw/c/TLC/blocks中的内置块代码来找到。

timestwo 模型

这个简单的模型使用timestwo S函数,并从生成的model.c文件中显示MdlOutputs函数,该文件包含内联S函数代码。

模型输出的代码如下:

/* Model output function */
static void timestwo_ex_output(int_T tid)
{
    /* S-Function Block: <Root>/S-Function */
    /* Multiply input by two */
    timestwo_ex_B.timestwo_output = timestwo_ex_P.Constant_Value  * 2.0;
    /* Outport: '<Root>/Out1' */
    timestwo_ex_Y.Out1 = timestwo_ex_B.timestwo_output;
}

封装型内联s-Function的例子

下图说明了将S函数内联为封装型的。该算法直接从生成的模型代码中调用,消除了S函数开销,但保留了用户函数。

这是timestwo块封装版的内联TLC文件。

%implements "timestwo" "C"
%% Function: BlockTypeSetup ==================================
%%
%function BlockTypeSetup(block, system) void
    %% Add function prototype to model's header file
    %<LibCacheFunctionPrototype...
    ("extern void mytimestwo(real_T* in,real_T* out,int_T els);")>
    %% Add file that contains "myfile" to list of files to be compiled
    %<LibAddToModelSources("myfile")>
%endfunction

%% Function: Outputs ==========================================
%%
%function Outputs(block, system) Output
 /* %<Type> Block: %<Name> */
 %assign outPtr = LibBlockOutputSignalAddr(0, "", "", 0)
 %assign inPtr = LibBlockInputSignalAddr(0, "", "",0)
 %assign numEls = LibBlockOutputSignalWidth(0)
 /* Multiply input by two */
 mytimestwo(%<inPtr>,%<outPtr>,%<numEls>);
%endfunction

上述代码分析:

对于模型中的每种类型的块,调用函数BlockTypeSetup一次;它不像Outputs函数那样直接产生输出。使用BlockTypeSetup在model.h文件中包含一个函数原型,并告诉构建过程编译一个额外的文件myfile.c。
现在,Outputs函数调用函数mytimestwo,而不是直接执行乘法。因此,模型中此块的所有实例都将调用相同的函数来执行乘法。

由此产生的模型函数MdlOutputs变为:

static void timestwo_ex_output(int_T tid)
{
    /* S-Function Block: <Root>/S-Function */
    /* Multiply input by two */
    mytimestwo(&model_B.Constant_Value,&model_B.S_Function,1);
    /* Outport Block: <Root>/Out1 */
    model_Y.Out1 = model_B.S_Function;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值