端子スコープおよび再利用性を指定する S-Function
mdlInitializeSizes メソッドで次の SimStruct マクロを使用すると、S-Function の入出力端子に使用するメモリのスコープと再利用性を指定できます。
ssSetInputPortOptimOpts:S-Function の入力端子に割り当てられるメモリのスコープと再利用性を指定します。ssSetOutputPortOptimOpts:S-Function の出力端子に割り当てられるメモリのスコープと再利用性を指定します。ssSetInputPortOverWritable:S-Function の入力端子のいずれかを S-Function の出力端子のいずれかで上書きできるかどうかを指定します。ssSetOutputPortOverwritesInputPort:出力端子のメモリ バッファーを、出力端子が入力端子と共有できるかどうかを指定します。
次の 4 つのオプションを ssSetInputPortOptimOpts および ssSetOutputPortOptimOpts マクロに渡すことによって、入力または出力をローカルあるいはグローバルとして宣言し、その再利用性を示します。
SS_NOT_REUSABLE_AND_GLOBAL:入出力端子は、グローバル ブロック入力および出力構造体の個別のメモリ位置に格納されます。SS_NOT_REUSABLE_AND_LOCAL:コード ジェネレーターが入出力端子に対して個々のローカル変数を宣言できることを示します。SS_REUSABLE_AND_LOCAL:コード ジェネレーターが複数の入出力端子に対して単一のローカル変数を再利用できることを示します。SS_REUSABLE_AND_GLOBAL:入出力端子は、グローバル ブロック入力および出力構造体の単一の要素に格納されます。
メモ
入力または出力端子をローカル変数にすることは、コード ジェネレーターが生成コードでローカル変数を使用することを意味するわけではありません。S-Function が mdlOutputs ルーチンでしか入出力にアクセスしない場合、コード ジェネレーターはその入出力をローカル変数として宣言します。ただし、入出力を S-Function のどこかで使用すれば、コード ジェネレーターはグローバル ブロック入力および出力構造体に入出力を含めます。
再利用性の設定は、入出力端子に関連付けられているメモリが上書き可能であるかどうかを示します。入出力端子のメモリを再利用するには、次のようにします。
ssSetInputPortOptimOptsおよびssSetOutputPortOptimOptsマクロでSS_REUSABLE_AND_LOCALまたはSS_REUSABLE_AND_GLOBALオプションを使用して、端子が再利用可能であることを示します。ssSetInputPortOverWritableを使用して入力端子のメモリを上書きできることを示します。S-Function に複数の入出力端子がある場合は、
ssSetOutputPortOverwritesInputPortを使用してメモリを共有する入出力端子を示します。
次の例では、異なるスコープと再利用性がどのように生成コードに影響するかを説明します。次のモデルは、直接 1 次元ルックアップ テーブルを作成する C MEX S-Function に向かっている S-Function ブロックを含みます。matlabroot/toolbox/simulink/simdemos/simfeatures/src/sfun_directlook.c

次のように、S-Function の mdlInitializeSizes メソッドで、入力端子は再利用可能、ローカルおよび上書き可能であるとして宣言され、出力端子は再利用可能でローカルであるとして宣言されます。
static void mdlInitializeSizes(SimStruct *S)
{
/* snip */
ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);
ssSetInputPortOverWritable(S, 0, TRUE);
/* snip */
ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);
/* snip */
}このモデルの生成コードは、次の出力関数に示されているように、単一のローカル変数 rtb_SFunction に入出力信号を格納します。
static void sl_directlook_output(int_T tid)
{
/* local block i/o variables */
real_T rtb_SFunction[2];
/* Sin: '<Root>/Sine Wave' */
rtb_SFunction[0] = sin(((real_T)sl_directlook_DWork.counter[0] +
sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 /
sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[0] +
sl_directlook_P.SineWave_Bias;
rtb_SFunction[1] = sin(((real_T)sl_directlook_DWork.counter[1] +
sl_directlook_P.SineWave_Offset) * 2.0 * 3.1415926535897931E+000 /
sl_directlook_P.SineWave_NumSamp) * sl_directlook_P.SineWave_Amp[1] +
sl_directlook_P.SineWave_Bias;
/* S-Function Block: <Root>/S-Function */
{
const real_T *xData = &sl_directlook_P.SFunction_XData[0];
const real_T *yData = &sl_directlook_P.SFunction_YData [0];
real_T spacing = xData[1] - xData[0];
if (rtb_SFunction[0] <= xData[0] ) {
rtb_SFunction[0] = yData[0];
} else if (rtb_SFunction[0] >= yData[20] ) {
rtb_SFunction[0] = yData[20];
} else {
int_T idx = (int_T)( ( rtb_SFunction[0] - xData[0] ) / spacing );
rtb_SFunction[0] = yData[idx];
}
if (rtb_SFunction[1] <= xData[0] ) {
rtb_SFunction[1] = yData[0];
} else if (rtb_SFunction[1] >= yData[20] ) {
rtb_SFunction[1] = yData[20];
} else {
int_T idx = (int_T)( ( rtb_SFunction[1] - xData[0] ) / spacing );
rtb_SFunction[1] = yData[idx];
}
}
/* Outport: '<Root>/Out1' */
sl_directlook_Y.Out1[0] = rtb_SFunction[0];
sl_directlook_Y.Out1[1] = rtb_SFunction[1];
UNUSED_PARAMETER(tid);
}次の表では、汎用リアルタイム ターゲット (GRT) を使用した場合にこのモデルに生成されるさまざまなコードを示します。行ごとに、S-Function の入出力端子のスコープと再利用性のさまざまな設定を説明します。
| スコープと再利用性 | S-Function mdlInitializeSizes コード | 生成されるコード |
|---|---|---|
入力:ローカル、再利用可能、上書き可能 出力:ローカル、再利用可能 | ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, TRUE); ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); |
/* local block i/o variables */ real_T rtb_SFunction[2]; |
入力:グローバル、再利用可能、上書き可能 出力:グローバル、再利用可能 | ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_GLOBAL); ssSetInputPortOverWritable(S, 0, TRUE); ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_GLOBAL); |
/* Block signals (auto storage) */
typedef struct {
real_T SFunction[2];
} BlockIO_sl_directlook;
/* Sin: '<Root>/Sine Wave' */
sl_directlook_B.SFunction[0] = sin ...
/* snip */
/*S-Function Block:<Root>/S-Function*/
{
const real_T *xData =
&sl_directlook_P.SFunction_XData[0] |
入力:ローカル、再利用不可 出力:ローカル、再利用不可 | ssSetInputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_LOCAL); ssSetInputPortOverWritable(S, 0, FALSE); ssSetOutputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_LOCAL); |
/* local block i/o variables */ real_T rtb_SineWave[2]; real_T rtb_SFunction[2]; |
入力:グローバル、再利用不可 出力:グローバル、再利用不可 | ssSetInputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_GLOBAL); ssSetInputPortOverWritable(S, 0, FALSE); ssSetOutputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_GLOBAL); |
/* Block signals (auto storage) */
typedef struct {
real_T SineWave[2];
real_T SFunction[2];
} BlockIO_sl_directlook;
/* Sin: '<Root>/Sine Wave' */
sl_directlook_B.SineWave[0] = sin ...
/* snip */
/*S-Function Block:<Root>/S-Function*/
{
const real_T *xData =
&sl_directlook_P.SFunction_XData[0] |
S-Function の入力バッファーまたは出力バッファーの再利用が生じているか確認するために、関数 LibBlockInputSignalBufferDstPort を使用できます。