このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
コード再利用のための S-Function
モデルの内部とすべての参照モデルの全域に複数のインスタンスとして存在する同一のサブシステムに対しては、生成コードを再利用できます。コードを再利用するためのサブシステムのコード生成の詳細については、サブシステム コードを別々の関数およびファイルとして生成を参照してください。
S-Function でのコード再利用の要件
サブシステムのコード再利用に S-Function を使用するには、その S-Function が次の要件を満たす必要があります。
インライン化されている。
S-Function から生成されたコードでは静的変数を使用しない。
S-Function は
mdlStart
でのみポインター作業ベクトルを初期化する。あらかじめ行っておく必要はない。ワークスペースにデータのログを作成するシンクではない。
S-Function のパラメーターを
mdlSetWorkWidths
でランタイム パラメーターとして登録する (このために、S-Function は関数mdlRTW
でssWriteRTWParameters
を使用してはならない)。デバイス ドライバーではない。
S-Function はSS_OPTION_WORKS_WITH_CODE_REUSE
フラグを関数ssSetOptionsで設定する必要があります。このフラグは、サブシステムのコード再利用のための要件を S-Function が満たしていることを示します。フラグが設定されており、S-Function が要件を満たさない場合、コード ジェネレーターによって再利用可能な関数が生成されず、警告が表示されます。
モデル間で再利用される S-Function
S-Function は再利用可能なライブラリ サブシステム内に配置できます。S-Function ファイルで次の両方のフラグを設定します。
ssSetOptions
関数でのSS_OPTION_WORKS_WITH_CODE_REUSE
フラグ1
またはtrue
に設定されているssSetSupportedForCodeReuseAcrossModels
legacy_code
ツールを使用して S-Function を生成する場合は、S-Function のオプション supportCodeReuseAcrossModels
を使用して、S-Function を含むサブシステムのモデル間でのコード再利用を指定することができます。
S-Function がモデル固有のデータ構造体にアクセスしない場合にのみ、モデル間でコードを再利用するための S-Function の設定を行います。_sharedutils
フォルダー内に生成されるコードが model_ert_rtw folder
内に生成されるコードから個別にコンパイルされるため、この設定が必要です。_sharedutils
フォルダーに生成される再利用可能なライブラリ サブシステム コードでは、model.h
で宣言されたタイプおよびマクロにアクセスできません。再利用可能なライブラリ サブシステム コードは独立していなければなりません。詳細については、モデル間で共有されるライブラリ サブシステムからの再利用可能なコードの生成を参照してください。
外部ヘッダー ファイルで定義されるカスタム関数を S-Function で使用する場合は、関数LibAddtoSystemCustomIncludes(system, incFileName)を S-Function の TLC ファイルに追加します。たとえば、.tlc
ファイルに LibAddtoSystemCustomIncludes("company_math.h")
を追加すると、_sharedutils
フォルダー内の再利用可能なライブラリ サブシステム コードに #company_math.h
ヘッダー ファイルが含まれます。
1. モデル例 SFunctionForCodeReuse
を開きます。このモデル例では、再利用可能なライブラリ サブシステム SFunctionForCodeReuseLibrary
の 2 つのインスタンスを使用します。再利用可能なライブラリ サブシステム内の S-Function sfun_mySrc
では、外部ファイル doubleIt.c
と doubleIt.h
を使用します。
SFunctionForCodeReuse;
2. レガシ コード ツールを使用して S-Function コードを生成します。MATLAB コマンド ウィンドウで次のコマンドを使用します。
def = legacy_code('initialize'); def.SFunctionName = 'sfun_mySrc'; def.SourceFiles = {'doubleIt.c'}; def.HeaderFiles = {'doubleIt.h'}; def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';
3. S-Function でコード再利用のための指定を次のように行います。
def.Options.supportCodeReuseAcrossModels = true;
4. S-Function コードの TLC ブロック ファイルを生成します。次に、S-Function をコンパイルします。
legacy_code('sfcn_tlc_generate',def); legacy_code('sfcn_cmex_generate', def); legacy_code('compile', def);
### Start Compiling sfun_mySrc mex('-I/tmp/Bdoc24a_2550221_86473/tp00a35ec5/simulinkcoder-ex43633418', '-c', '-outdir', '/tmp/Bdoc24a_2550221_86473/tp64749ed0_5668_492d_90d6_2fbcf4ef50f1', '/tmp/Bdoc24a_2550221_86473/tp00a35ec5/simulinkcoder-ex43633418/doubleIt.c') Building with 'gcc'. MEX completed successfully. mex('sfun_mySrc.c', '-I/tmp/Bdoc24a_2550221_86473/tp00a35ec5/simulinkcoder-ex43633418', '/tmp/Bdoc24a_2550221_86473/tp64749ed0_5668_492d_90d6_2fbcf4ef50f1/doubleIt.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_mySrc ### Exit
5. コード ジェネレーターによって、MATLAB 作業フォルダーに S-Function ファイル sfun_mySrc.c
およびその TLC ファイル sfun_mySrc.tlc
が作成されます。sfun_mySrc.c
ファイルでは、コード ジェネレーターによって以下の仕様が追加されます。
file = fullfile('sfun_mySrc.c'); coder.example.extractLines(file,'* All options have the form SS_OPTION_<name>', ... 'ssSetSupportedForCodeReuseAcrossModels(S, 1);',1,1);
* All options have the form SS_OPTION_<name> and are documented in * matlabroot/simulink/include/simstruc.h. The options should be * bitwise or'd together as in * ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2)) */ ssSetOptions(S, SS_OPTION_USE_TLC_WITH_ACCELERATOR | SS_OPTION_CAN_BE_CALLED_CONDITIONALLY | SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_WORKS_WITH_CODE_REUSE | SS_OPTION_SFUNCTION_INLINED_FOR_RTW | SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME ); ssSetSupportedForCodeReuseAcrossModels(S, 1);
sfun_mySrc.c
で、SS_OPTION_WORKS_WITH_CODE_REUSE
フラグが関数 ssSetOptions
で設定され、ssSetSupportedForCodeReuseAcrossModels
が true に設定されます。
6. Simulink® ツールストリップで、"Embedded Coder" アプリまたは "Simulink Coder" アプリを開きます。
7. モデルのコードを生成します。[C コード] タブで、[ビルド] をクリックします。
evalc('slbuild(''SFunctionForCodeReuse'')');
コード ジェネレーターは、モデル間で再利用できる再利用可能関数を _sharedutils
フォルダーに生成します。モデル参照階層内のモデルでは、この _sharedutils
フォルダーを共有し、コードを再利用します。次の例では、再利用可能関数が slprj/grt/_sharedutils/sfunc.c
ファイルに生成されます。
file = fullfile('slprj','grt','_sharedutils','sfunc.c'); coder.example.extractLines(file,'Output and update for atomic system', ... 'rtb_sfun_mySrc',1,1); %
* Output and update for atomic system: * 'ReusableSubsystem' ('SFunctionForCodeReuseLibrary:60') * 'ReusableSubsystem' ('SFunctionForCodeReuseLibrary:60') */ void sfunc(real_T rtu_In1, B_sfunc_T *localB, DW_sfunc_T *localDW) { /* local block i/o variables */ real_T rtb_sfun_mySrc;
モデル内で再利用される S-Function
既定では、サブシステム内の S-Function にモデル内でコードを再利用するための設定は行われません。サブシステム内の S-Function は、モデル内でコードを再利用するために指定できます。S-Function ファイルの関数 ssSetOptions
で SS_OPTION_WORKS_WITH_CODE_REUSE
フラグを設定します。このフラグは、S-Function がサブシステムのコード再利用のための要件を満たし、コード再利用のために設定されていることを示します。フラグが設定されており、S-Function が要件を満たさない場合、コード ジェネレーターによって再利用可能な関数が生成されず、警告が表示されます。
1. モデル例 SFunctionForCodeReuse
の場合は、レガシ コード ツールを使用して S-Function コードを生成します。S-Function のオプション supportCodeReuseAcrossModels
は含めないでください。MATLAB コマンド ウィンドウで次のコマンドを使用します。
def = legacy_code('initialize'); def.SFunctionName = 'sfun_mySrc'; def.SourceFiles = {'doubleIt.c'}; def.HeaderFiles = {'doubleIt.h'}; def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';
2. S-Function コードの TLC ブロック ファイルを生成します。次に、S-Function をコンパイルします。
legacy_code('sfcn_tlc_generate',def); legacy_code('sfcn_cmex_generate', def); legacy_code('compile', def);
### Start Compiling sfun_mySrc mex('-I/tmp/Bdoc24a_2550221_86473/tp00a35ec5/simulinkcoder-ex69241103', '-c', '-outdir', '/tmp/Bdoc24a_2550221_86473/tpa8e0d98d_d85f_4106_af81_247979c35ff8', '/tmp/Bdoc24a_2550221_86473/tp00a35ec5/simulinkcoder-ex69241103/doubleIt.c') Building with 'gcc'. MEX completed successfully. mex('sfun_mySrc.c', '-I/tmp/Bdoc24a_2550221_86473/tp00a35ec5/simulinkcoder-ex69241103', '/tmp/Bdoc24a_2550221_86473/tpa8e0d98d_d85f_4106_af81_247979c35ff8/doubleIt.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_mySrc ### Exit
3. コード ジェネレーターによって、MATLAB 作業フォルダーに S-Function ファイル sfun_mySrc.c
およびその TLC ファイル sfun_mySrc.tlc
が作成されます。
file = fullfile('sfun_mySrc.c'); coder.example.extractLines(file,'* All options have the form SS_OPTION_<name>', ... 'SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME',1,1);
* All options have the form SS_OPTION_<name> and are documented in * matlabroot/simulink/include/simstruc.h. The options should be * bitwise or'd together as in * ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2)) */ ssSetOptions(S, SS_OPTION_USE_TLC_WITH_ACCELERATOR | SS_OPTION_CAN_BE_CALLED_CONDITIONALLY | SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_WORKS_WITH_CODE_REUSE | SS_OPTION_SFUNCTION_INLINED_FOR_RTW | SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME
sfun_mySrc.c
ファイルにはコード ジェネレーターによって既定で、関数 ssSetOptions
で SS_OPTION_WORKS_WITH_CODE_REUSE
フラグが追加されますが、S-Function がモデル間で再利用されることを妨げる ssSetSupportedForCodeReuseAcrossModels
の仕様は含められません。
4. Simulink ツールストリップで、"Embedded Coder" アプリまたは "Simulink Coder" アプリを開きます。
5. モデルのコードを生成します。[C コード] タブで、[ビルド] をクリックします。
evalc('slbuild(''SFunctionForCodeReuse'')');
コード ジェネレーターは、サブシステムに対して再利用可能な関数を SFunctionForCodeReuse.c
ファイルに生成します。このファイルは _sharedutils
フォルダーの外にあります。以下のコードはモデル内で再利用可能ですが、モデル参照階層全体では再利用できません。
file = fullfile('SFunctionForCodeReuse_grt_rtw','SFunctionForCodeReuse.c'); coder.example.extractLines(file,'void sfunc', ... 'localDW->UnitDelay_DSTATE = rtb_sfun_mySrc;',1,1); %
void sfunc_Init(DW_sfunc_T *localDW) { /* InitializeConditions for UnitDelay: '<S1>/Unit Delay' */ localDW->UnitDelay_DSTATE = 0.0; } /* * Output and update for atomic system: * '<Root>/ReusableSubsystem' * '<Root>/ReusableSubsystem1' */ void sfunc(real_T rtu_In1, B_sfunc_T *localB, DW_sfunc_T *localDW) { /* local block i/o variables */ real_T rtb_sfun_mySrc; /* UnitDelay: '<S1>/Unit Delay' */ localB->UnitDelay = localDW->UnitDelay_DSTATE; /* S-Function (sfun_mySrc): '<S1>/sfun_mySrc' */ rtb_sfun_mySrc = doubleIt(rtu_In1); /* Update for UnitDelay: '<S1>/Unit Delay' */ localDW->UnitDelay_DSTATE = rtb_sfun_mySrc;