Main Content

非バーチャル バスのコードの生成

Simulink® Coder™ を所有している場合、バーチャル バスまたは非バーチャル バスを使用できるかどうかは、生成されたコードの効率性、サイズおよび可読性に大きな違いが生じる可能性があります。

  • バーチャル バスは生成されたコードで構造体またはその他のまとまった単位としては示されません。バスを操作するアルゴリズムのコピーが要素ごとに別々に存在します。一般的に、バーチャル バスは生成されたコードに影響しません。

  • 生成されたコードでは非バーチャル バスは構造体で表され、バスを使用するアルゴリズムのコピーが 1 つのみ存在します。モデルとコード間の対応を追跡する際に、生成されたコードの構造体を使用すると便利です。

たとえば、バスは Unit Delay ブロックを介して渡されるとします。簡単にするために、バスに含まれている要素は abc のみです。

バーチャル バスには、型定義は必要ありません。生成された model.h ファイルは、バーチャル バスの要素につき 1 つの Unit Delay ブロックを定義します。

typedef struct {
  real_T UnitDelay_1_DSTATE;  /* '<Root>/Unit Delay' */
  real_T UnitDelay_2_DSTATE;  /* '<Root>/Unit Delay' */
  real_T UnitDelay_3_DSTATE;  /* '<Root>/Unit Delay' */
} DW_model_T;

非バーチャル バスには型定義が必要です。Simulink.Bus オブジェクトは、非バーチャル バスの構造体として生成された model_types.h ファイルに表示されます。

typedef struct {
  real_T a;
  real_T b;
  real_T c;
} BusObject;

生成された model.h ファイルでは BusObject 構造体を使用して、非バーチャル バスに対して 1 つの Unit Delay ブロックが定義されます。

typedef struct {
  BusObject UnitDelay_DSTATE;  /* '<Root>/Unit Delay' */
} DW_model_T;

生成されたコードで信号を構造体にグループ化するには、非バーチャル バスを使用します。生成されたコードにおける構造体へのデータの整理 (Simulink Coder)を参照してください。

バスを使用するモデルのコードを効率的に生成するには、バス信号の効率的なコードの生成 (Simulink Coder)を参照してください。非バーチャル バスのコードを生成すると、いくつかのバスの複数のコピーが生成される場合があります。

参照モデルへの入力または参照モデルからの出力として非バーチャル バスを使用する場合、以下のようになります。

  • 非バーチャル バスを使用しているとき、または C++ クラス インターフェイスに [既定] スタイルを使用しているときにのみ、参照モデルの C++ クラス インターフェイスの [I/O 引数 step メソッド] スタイルを設定できます。

  • 参照モデルに関数プロトタイプの制御を構成できるのは、非バーチャル バスを使用しているときのみです。

初期条件構造体フィールドのデータ型の制御

MATLAB® 構造体を使用して、バス内の信号要素を初期化します。バス要素の初期条件の指定を参照してください。

MATLAB 構造体を作成して、double 以外の数値データ型を使用する要素を含むバスを初期化する場合、構造体フィールドの値を設定する必要があります。値を設定するために選択する手法は、生成されたコードの効率性と可読性に影響します。

  • フィールドのデータ型と信号要素のデータ型を手動で一致させることを回避するには、型なし式を使用してフィールドの値を設定します。モデルを開発し、プロトタイプを迅速に作成する場合は、この手法を使用すると便利です。

  • より効率的な量産コードを生成し、コード内の浮動小数点のストレージを回避するには、構造体のフィールドのデータ型を対応する信号要素のデータ型と一致させます。

生成されたコードでの調整可能な初期条件に関する例および詳細については、生成されたコードにおける信号および状態の初期化の制御 (Simulink Coder)を参照してください。

生成コードにおける構造体フィールドの数値のインライン化

[既定のパラメーター動作] コンフィギュレーション パラメーターを [インライン] に設定した場合、既定では、初期条件構造体のフィールド値が生成コード内にインライン化された数値 (調整不可) として表示されます。これらの構造体に対して、型なし式を使用して Simulink でフィールドの値を設定します。構造体は生成されたコードで調整可能ではないため、フィールドの値にはデータ型は必要ない。

ただし、後で [既定のパラメーター動作][調整可能] に設定するか、Simulink.Parameter オブジェクトを使用して構造体にストレージ クラスを適用する場合は、コードに浮動小数点のストレージ、非効率な明示的型変換とビット シフトを含めることができます。こうした問題を回避するために、構造体フィールドのデータ型を対応する信号要素のデータ型と一致させることを検討してください。

ブロックのダイアログ ボックスで直接指定された調整可能な構造体の生成

(構造体を変数または Simulink.Parameter オブジェクトに保存するのではなく) ブロック ダイアログ ボックスで初期条件構造体を直接指定するか、Simulink.Signal オブジェクトで、struct('signal1',5,'signal2',7.2) のような式を使用するとします。この場合、調整可能な構造体をコードで生成するために、[既定のパラメーター動作][調整可能] に設定します。

次の表を使用して、これらの初期条件構造体のフィールドのデータ型を制御する方法を決定します。

目的手法

非バーチャル バスを使用する。

型なし式を使用して、フィールドの値を設定する。

バーチャル バスを使用する。

フィールドのデータ型を信号要素のデータ型と手動で一致させない。

型なし式を使用して、フィールドの値を設定する。

さらに効率的なコードを生成し、浮動小数点のストレージを避ける。

構造体のフィールドのデータ型を信号要素の型と一致させる。型付き式を使用してフィールドの値を設定して、データ型情報を struct に保存する。

変数またはパラメーター オブジェクトに保存される調整可能な構造体の生成

ベース ワークスペース内またはデータ ディクショナリで作成する変数または Simulink.Parameter オブジェクトに初期条件構造体を保存するとします。たとえば、この手法を使用して複数のブロック間の構造体を共有するか、[既定のパラメーター動作][インライン] に設定している場合は調整可能な構造体を生成します。この場合、次の表を使用して、初期条件構造体のフィールドのデータ型を制御する方法を決定します。

目的手法

フィールドのデータ型を信号要素のデータ型と手動で一致させない。

型なし式を使用して、フィールドの値を設定する。生成されたコードでは、構造体フィールドはデータ型 double を使用する。生成されたアルゴリズムは明示的な型変換を使用して、データ型の不一致を調整する。

さらに効率的なコードを生成し、浮動小数点のストレージを避ける。

構造体のフィールドのデータ型を信号要素の型と一致させる。データ型情報を構造体フィールドに保存するか、Simulink.Bus オブジェクトを使用して、フィールドのデータ型と信号要素を同時に制御する。

モデル アドバイザーを使用して、計算量が多くなる可能性のあるデータ型の不一致があるかどうかモデルを確認するには、Check structure parameter usage with bus signalsを参照する。

構造体の配列を使用して参照モデルのバス配列を初期化する。構造体の配列を Model ブロックのモデル引数の値として参照モデルに渡す。

構造体のフィールドのデータ型を信号要素の型と一致させる。データ型情報を構造体フィールドに保存するか、Simulink.Bus オブジェクトを使用して、構造体フィールドのデータ型と信号要素を同時に制御する。

構造体を参照モデルにモデル引数として渡さない場合、非バーチャル バスに関する他のガイドラインに従って、データ型の制御方法を決定します。

型なし式を使用したフィールド値の設定

型なし式を使用して、構造体フィールドの値を設定できます。フィールドはデータ型 double を暗黙的に使用します。フィールドの値を設定して、理想的な現実の初期化値を表します。

フィールドのデータ型と対応する信号要素のデータ型を手動で一致させないようにします。ただし、バスの仮想性、初期条件に適用するために使用する方法およびその他の要素によっては、浮動小数点ストレージおよび非効率になりうる型変換を生成されたコードに導入することが可能です。

次の信号要素を使用してバス myBusSig を作成するとします。各要素は特定のデータ型を使用します。

myBusSig
   signalElement1 (int32)
   signalElement2 (boolean)
   signalElement3 (single)

初期条件構造体 initStruct を作成します。型なし式を使用して、フィールドの値を指定します。オプションで、Boolean のフィールド signalElement2 の可読性を向上するために、0 ではなく値 false を使用します。

initStruct.signalElement1 = 3;
initStruct.signalElement2 = false;
initStruct.signalElement3 = 17.35;

関数 Simulink.Bus.createMATLABStruct を使用して構造体を作成する場合、この関数によってデータ型情報が構造体フィールドに保存されます。構造体を作成すると、必要に応じて型なし式を使用してフィールドの値を変更できます。Simulink.Bus.createMATLABStruct を使用した構造体の作成を参照してください。

構造体フィールドへのデータ型情報の保存

データ型情報を構造型フィールドに保存するには、型付き式を使用してフィールド値を設定するか、関数 Simulink.Bus.createMATLABStruct を使用して構造体を作成します。これらの手法を使用して、浮動小数点のストレージと非効率になりうる明示的型変換を取り除くことで効率的なコードを生成します。

対応する信号要素のデータ型を変更するときに新しいデータ型を構造体フィールドに手動で適用しないようにするには、Simulink.Bus オブジェクトを使用して構造体とバスのデータ型を同時に制御することを検討してください。

型付き式を使用したフィールド値の設定.  特定のデータ型を使用する次の要素をもつバス myBusSig を作成するとします。

  • signalElement1 (int32)

  • signalElement2 (boolean)

  • signalElement3 (single)

型付き式を使用してフィールドの値を設定して、初期条件構造体 initStruct を作成します。フィールドのデータ型を対応する信号要素のデータ型と一致させます。

initStruct.signalElement1 = int32(3);
initStruct.signalElement2 = false;
initStruct.signalElement3 = single(17.35);

構造体フィールドにはデータ型情報が保存されます。信号要素のデータ型を後で変更する場合、新しいデータ型を対応する構造体フィールドに手動で適用します。

固定小数点データ型を一致させるには、fi (Fixed-Point Designer) オブジェクトを使用してフィールド値を設定します。

データ型情報の保持によるフィールド値の変更.  既存の初期条件構造体のフィールドの値を変更すると仮定します。データ型情報をフィールドに保持するには、添字付き代入 ((:) の構文) を使用します。

initStruct.signalElement3(:) = 16.93;

添字を使用した代入を使用しない場合、型付き式を使用してデータ型を忘れずに保持しなければなりません。

initStruct.signalElement3 = single(16.93);

これらの手法のいずれかを使用しないと、フィールドのデータ型情報は失われます。

initStruct.signalElement3 = 16.93; % Field data type is now 'double'.

Simulink.Bus.createMATLABStruct を使用した構造体の作成.  関数 Simulink.Bus.createMATLABStruct を使用して、すべてのフィールドの値がグラウンド値 (通常は 0) である構造体を作成します。この関数を使用する前に信号要素のデータ型を設定する場合 (たとえば信号要素を生成するブロックの出力データ型を設定する)、出力構造体の各フィールドでは対応する信号要素と同じデータ型が使用されます。フィールドには、型付き式を使用して値が設定されたものとしてデータ型情報が保存されます。

関数に部分構造体を渡すことで、グラウンド値以外の値を使用して信号要素の一部を初期化できます。この部分構造体を作成する場合、型付き式を使用して各フィールドのデータ型を対応する信号要素のデータ型と一致させます。詳細と例については、Simulink.Bus.createMATLABStruct を参照してください。

構造体のフィールドの値を後で変更する場合、以下のいずれかの手法を選択して新しい値を設定します。

  • 型なし式。フィールド値にはデータ型情報が保存されません。

  • 型付き式または添字を使用した代入。フィールド値にはデータ型情報が引き続き保存されます。

初期条件構造体のデータ型としてのバス オブジェクトの使用

データ型情報を構造体フィールドに保存するか、型なし式を使用してフィールド値を設定する場合、初期条件全体のデータ型として Simulink.Bus オブジェクトを使用します。するとフィールド値とデータ型を別個に管理できます。

この手法を使用する場合は、型なし式を使用してフィールド値を設定することを検討してください。そうすると、信号要素のデータ型を変更するときにフィールドのデータ型を手動で一致させる必要はありません。フィールドと信号要素のデータ型を制御するには、バス オブジェクトの要素の DataType プロパティを使用します。

Bus Creator ブロックを使用して、次の要素をもつバス myBusSig を作成するとします。

  • signalElement1 (int32)

  • signalElement2 (boolean)

  • signalElement3 (single)

  1. 型エディターを開きます。

    typeeditor

  2. バスに対応するバス オブジェクト myBus を作成します。

    Bus object named myBus in the Type Editor

  3. 初期条件構造体 initStruct を作成します。フィールド値の設定に型なし式を使用しました。フィールド signalElement2 の可読性を向上させるために、0 ではなくブール値 false を使用します。

    initStruct.signalElement1 = 3;
    initStruct.signalElement2 = false;
    initStruct.signalElement3 = 17.35;
    

  4. 構造体を表すには、Simulink.Parameter オブジェクトを作成します。

    initStruct = Simulink.Parameter(initStruct);
    

  5. パラメーター オブジェクトを使用して、バスの初期条件を指定します。たとえば、Unit Delay ブロック ダイアログ ボックスで、[初期条件]initStruct に設定します。

  6. バス オブジェクトを使用して、パラメーター オブジェクトのデータ型を指定します。

    initStruct.DataType = 'Bus: myBus';

  7. バス オブジェクトを使用して、バスのデータ型を指定します。たとえば、Bus Creator ブロック ダイアログ ボックスで、[出力データ型][Bus: myBus] に設定します。

シミュレーション中および生成されたコードでは、構造体フィールドと信号要素はバス オブジェクトで指定されたデータ型を使用します。シミュレーションおよびコード生成の前に、パラメーター オブジェクトは構造体フィールドをバス オブジェクトで指定されたデータ型にキャストします。

バス オブジェクトに関する基本的な情報については、バス オブジェクトでのバス プロパティの指定を参照してください。

既存の構造体のデータ型の設定

データ型情報を構造体のすべてのフィールドから削除するには、フィールド値を double 型で置き換えるカスタム関数を作成します。サンプル関数 castStructToDbl をテンプレートとして使用します。

function outStruct = castStructToDbl(inStruct)
%outStruct = castStructToDbl(inStruct) casts the leaf fields of inStruct to
%doubles and returns the resulting structure as outStruct. This function
%operates on nested structures and one-dimensional arrays of structures.
%
%Use this function on a structure parameter that you previously created for
%bus signal initialization. The resulting structure contains only doubles,
%logicals, and instances of enumerated types. When you simulate, the bus
%elements cast the values of the structure fields.
%
%To prevent loss of data, save the original structure inStruct in
%a MAT-file or .m file.
%
%This function casts only leaf fields whose data types are floating-point,
%integer, and fixed-point types.

% Copy the input struct.
outStruct = inStruct;

% Get a list of all of the field names. Even if the structure contains
% nested structures, this list includes only the names of the fields of
% inStruct.
fieldNamesList = fieldnames(inStruct);

% If this structure is an array of structures, iterate through the
% structures.
for j = 1:length(inStruct)

for i = 1:length(fieldNamesList)
    
    tempField = inStruct(j).(fieldNamesList{i});
    
    % If this field is another structure, use castStructToDbl().
    if isstruct(tempField)
        outStruct(j).(fieldNamesList{i}) = castStructToDbl(tempField);
        
    % If this field is not a structure, a Boolean, or an
    % enum, but is numeric, then cast it to double.
    elseif ~isenum(tempField) && ~islogical(tempField) && isnumeric(tempField)
        outStruct(j).(fieldNamesList{i}) = cast(tempField,'double');
        
    end % if
end % for
end % for
end % function

double を使用する構造体をデータ型情報を保存する構造体に変換するには、関数 Simulink.Bus.createMATLABStruct を使用して参照構造体を作成できます。カスタム関数を作成して、フィールド値を参照構造体のデータ型にキャストできます。サンプル関数 castStructFromDbl をテンプレートとして使用します。

function outStruct = castStructFromDbl(inStruct,refStruct)
%outStruct = castStructFromDbl(inStruct,refStruct) casts the leaf fields of
%inStruct to the data types used by the corresponding fields of refStruct 
%and returns the resulting structure as outStruct.
%
%Use this function on a structure parameter, inStruct, that you previously 
%created for bus signal initialization. The fields of outStruct 
%use the ideal values specified in inStruct and the data types specified in 
%refStruct.
%
%To create refStruct, use the function Simulink.Bus.createMATLABStruct to
%generate a structure from a bus signal in a model or from a bus object.
%Each field in the generated structure uses the same data type as the 
%corresponding bus element.
%
%To prevent loss of data, save the original structure inStruct in
%a MAT-file or .m file.
%
%This function casts only leaf fields of inStruct whose data types are floating-point,
%integer, and fixed-point types.

% Copy the input struct.
outStruct = inStruct;

% Get a list of all of the field names. Even if the structure contains
% nested structures, this list includes only the names of the fields of
% inStruct.
fieldNamesList = fieldnames(inStruct);

% If this structure is an array of structures, iterate through the
% structures.
for j = 1:length(inStruct)

for i = 1:length(fieldNamesList)
    
    tempField = inStruct(j).(fieldNamesList{i});
    
    % If this field is another structure, use castStructFromDbl().
    if isstruct(tempField)
        tempfieldref = refStruct.(fieldNamesList{i});
        outStruct(j).(fieldNamesList{i}) = castStructFromDbl(tempField,tempfieldref);
        
    % If this field is not a structure, a Boolean, or an
    % enum, but is numeric, then cast it to the corresponding type in
    % refStruct.
    elseif ~isenum(tempField) && ~islogical(tempField) && isnumeric(tempField)
        outStruct(j).(fieldNamesList{i}) = cast(tempField,'like',...
            refStruct.(fieldNamesList{i}));
        
    end % if
end % for
end % for
end % function

モデル アドバイザーを使用したデータ型の不一致の確認

構造体フィールドのデータ型が関連付けられたバス要素と一致していないことを検出するには、モデル アドバイザーを使用します。

  1. [モデル化] タブで [モデル アドバイザー] をクリックします。

  2. [OK] をクリックします。

  3. [タスク別][バスによる信号およびパラメーターのモデル化] で、[バス信号を使った構造体パラメーターの使用のチェック] を選択します。

  4. [このチェックを実行] ボタンをクリックします。

バス配列のコード生成

バス配列を含むモデルに対してコードを生成する場合、基になるバス型を表す typedef が、*_types.h ファイルに表示されます。

コード生成では、構造体の配列を使用するレガシ C コードと統合できる C 構造体の配列が生成されます。バス変数 (配列) のコードは、必要に応じて以下の構造体で生成されます。

  • ブロック IO

  • 状態

  • 外部入力

  • 外部出力

次にバス配列に対して生成されたコードの単純な例を示します。

Generated code for an array of buses

コードでは構造体として表示される、非バーチャル バスのコード生成の基本的な情報については、生成されたコードにおける構造体へのデータの整理 (Simulink Coder)を参照してください。

関連するトピック