Simulink Subsystem のセマンティクス
この一連の例では、さまざまなタイプの Simulink® Subsystem と、これらのサブシステムのシミュレーション実行時にどのようなセマンティクスが使用されるかという例を示します。各例では、モデルと、そのモデルの実行方法に関する違いを説明しています。
各サブシステム タイプの例を示しています。
バーチャル サブシステムおよび非バーチャル サブシステム
Function-Call Subsystem
Triggered Subsystem
Enabled Subsystem
Enabled and Triggered Subsystem
If Action Subsystem と Switch Case Action Subsystem
While Iterator Subsystem
For Each Subsystem
For Iterator Subsystem
モデルを開きます。
open('SimulinkSubsystemSemantics.prj'); open_system('sl_subsys_semantics');
バーチャル サブシステムおよび非バーチャル サブシステムの概要
Simulink ソフトウェアには 2 種類のサブシステムがあります。
バーチャル サブシステムはモデルにグラフィカルな階層を提供します。バーチャル サブシステムはモデルの実行に影響しません。モデルの実行中、Simulink エンジンはすべてのバーチャル サブシステムをフラットにします。
非バーチャル サブシステムは、モデルに実行とグラフィカルな階層を提供します。非バーチャル サブシステムは、単一ユニットとして実行されます。これは、アトミック実行と呼ばれます。すべての非バーチャル サブシステムは、Simulink キャンバスで太字の枠線付きで表示されます。
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/Virtual and nonvirtual subsystem overview');
非バーチャル サブシステムを作成するには、Subsystem ブロックを右クリックし、[ブロック パラメーター (Subsystem)] を選択します。[ブロック パラメーター] ダイアログ ボックスで [Atomic サブシステムとして扱う] を選択し、[適用] をクリックします。
バーチャル サブシステムではフラットな実行リストが作成されます。一方、非バーチャル サブシステムには実行階層があります。実行順序を表示するには、Simulink エディターの [デバッグ] タブで [情報のオーバーレイ] を選択し、[実行順序] をクリックします。
Simulink キャンバスに表示された [実行順序ブロック リスト] に実行順序が示されます。
実行順序ブロック リストでは、非バーチャル サブシステム Subsystem2
が単一ユニットとして実行されたことが示されています。
非バーチャル サブシステムでは、実行階層内で代数ループが生じます。ブロック線図を更新すると、代数ループの警告が出されます。
set_param(gcs,'SimulationCommand','Update')
Warning: Model 'sl_subsys_overview' contains 1 algebraic loops.
Function-Call Subsystem
Function-Call Subsystem ブロックには、制御端子が関数呼び出しイベントを受信するたびに実行される条件付き実行サブシステムが含まれています。Function-Call Subsystem は、Simulink ブロックを使用して呼び出し可能な関数を実装します。Stateflow®Chart (Stateflow)、Function-Call Generatorブロック、MATLAB Functionブロック、S-Functionブロック、またはHit Crossing ブロックでは関数呼び出しイベントを提供できます。
詳細については、Function-Call Subsystemを参照してください。
以下の例では、Function-Call Subsystem の有効な使用例と無効な使用例を示します。
close_system('sl_subsys_overview',0) open_system('s_Function_call_subsystems')
入れ子関数呼び出し
このモデルでは、Chart は関数 [d1,d2]=f()
を実行する関数呼び出しイニシエーターです。次に、関数 f
が関数 g
を実行します。f
と g
を呼び出した後に、Chart は、f
と g
で計算された値 d1
と d2
を使用します。
open_system('sl_subsys_fcncall1')
close_system('sl_subsys_fcncall1')
データ共有を使用した入れ子関数呼び出し
Chart ブロックは関数 [d1,d2]=f()
を実行します。次に、f
が g
を実行します。f
を呼び出した後に、Chart は、f
と g
で計算された値 d1
と d2
を使用します。関数 f
と g
は、信号 s(f/Out2 feeds g/In1)
を介してデータを共有します。Simulink は、信号がデータストアであるかのように信号 s
を扱います。
open_system ('sl_subsys_fcncall2')
一般に、Function-Call Subsystem への入力は、共通の関数呼び出しイニシエーターによって実行されるブロックから信号が取得される場合を除き、関数呼び出しイニシエーター (Chart) の前に実行する必要があります。この例では、f()
は g()
の関数呼び出しイニシエーターです。ただし、Chart は f()
の関数呼び出しイニシエーターであるため、Chart は f()
と g()
の共通の関数呼び出しイニシエーターとなります。
その意味で、以下の信号 s
は、f()
と g()
が Chart によって定義された所定の順序で読み書きするデータストアとみなすことができます。
close_system('sl_subsys_fcncall2')
共通のイニシエーターを使用した 2 つの Function-Call Subsystem 間のデータ共有
このモデルでは、d1
と d2
の計算にそれぞれ g()
と f()
が使用されます。Chart は d1
と d2
を入力として使用し、g()
と f()
を呼び出します。関数 f
と g
は信号 s
を介してデータを共有しており、つまり (f/Out1)
が (g/In1)
に送られます。モデルは、信号がデータ ストアであるかのように信号 s
を扱います。
open_system ('sl_subsys_fcncall3')
一般に、Function-Call Subsystem への入力は、共通の関数呼び出しイニシエーターによって実行されるブロックから信号が取得される場合を除き、関数呼び出しイニシエーター (Chart) の前に実行する必要があります。この例では、Chart は f()
と g()
の共通の関数呼び出しイニシエーターです。したがって、信号 s
はデータ ストアとみなすことができます。
close_system('sl_subsys_fcncall3')
データ共有を使用した関数呼び出しイニシエーターを含む Enabled Subsystem
この Enabled Subsystem には、関数 f()
と g()
を呼び出す Stateflow チャートが含まれています。モデル sl_subsys_fcncall4
の Enabled Subsystem は、f()
と g()
の共通の関数呼び出しイニシエーターです。したがって、信号 s
はデータストアとして扱われます。
open_system ('sl_subsys_fcncall4')
close_system('sl_subsys_fcncall4')
Merge ブロックを含む Function-Call Subsystem
このモデルには、2 つの関数呼び出しを実行するチャートが含まれています。このモデルは Merge ブロックを使用して、複数の信号を単一のメモリ位置にマッピングしています。信号 f/d1_out
と g/d1_out
が単一のメモリ位置にマージされ、Chart に d1
としてフィードバックされています。信号 f/k_out
と g/k_out
が単一のメモリ位置にマージされ、f/k_in
にフィードバックされています。信号を単一のメモリ位置にマージして Chart にフィードバックすることで、Chart は値の計算方法について複雑な決定を下すことができます。
open_system ('sl_subsys_fcncall5')
close_system('sl_subsys_fcncall5')
Function-Call Subsystem の複数のイニシエーター
この Function-Call Subsystem は、2 つの異なる関数呼び出しイニシエーター Chart1
および Chart2
から呼び出されます。Chart1/out1
と Chart2/d1
間のデータ接続により、Chart1
が Chart2
の前に実行されることが保証されます。複数の呼び出し元をもつ Function-Call Subsystem を作成する場合は注意が必要です。
たとえば、Chart1
と Chart2
間のデータ接続を削除した場合、優先順位を Chart1
と Chart2
に追加して、これらのブロックの相対実行順序を指定する必要があります。そうしないと、実行順序があいまいになります。
ただし、この条件は特定のケースでは有効である可能性があるため、この条件に対してエラーは出されません。例として、f()
からすべてのステートを削除し、Chart1/out1
を Chart2/d1
に接続しているラインを削除した場合、Chart1
と Chart2
が実行される順序は重要ではなくなります。
open_system ('sl_subsys_fcncall6')
close_system('sl_subsys_fcncall6')
リセット動作を指定する Function-Call Subsystem を含む Enabled Subsystem
この Enabled Subsystem には 2 つの Function-Call Subsystem が含まれています。左側の Function-Call Subsystem は、イネーブル状態の場合はステートの値を保持し、ディセーブル状態の場合は出力の値を保持するように構成されています。右側の Function-Call Subsystem は、イネーブル状態の場合はステートの値をリセットし、ディセーブル状態の場合は出力の値をリセットするように構成されています。
open_system ('sl_subsys_fcncall7')
close_system('sl_subsys_fcncall7')
Function-Call Subsystem での周期的な実行の指定
この Stateflow チャートは、モデル内の Function-Call Subsystem の実行順序をスケジュールします。ただし、Function-Call Subsystem はタイム ステップごとに 1 回だけ実行されます。関数呼び出しでは、条件付き実行を指定するのではなく、サブシステムの相対的な実行順序を制御します。この設定は、データストアを使用してサブシステム間でデータを転送する場合に、データストアに対する読み取りと書き込みの適切な順序を保証するのに役立ちます。Function-Call Subsystem は無条件で実行されることを目的としているため、サブシステムの Trigger ブロックの [サンプル時間] パラメーターを使用して周期的なサンプル時間をもつように指定する必要があります。その結果、シミュレーション中、Simulink エンジンは周期的な Function-Call Subsystem がタイム ステップごとに 1 回だけ実行されることを検証します。
さらに、コードが生成されるとき、Function-Call Subsystem 内の経過時間は、通常の Function-Call Subsystem のようにタイマーに基づいて保持および計算されるのではなく、リテラル値 (指定した定数のサンプル時間) で表されます。したがって、生成されたコードは大幅に効率化します。
サブシステムのサンプル時間を表示するには、[Simulink エディター] の [デバッグ] タブで、[情報のオーバーレイ] を選択し、[色] をクリックします。
open_system ('sl_subsys_fcncall8')
Function-Call Subsystem のサンプル時間の色はシアンではなく赤であり、トリガー サンプル時間ではなく周期的なサンプル時間を示しています。関数呼び出し接続が交換されると、サブシステム内の Data Store Read ブロックと Data Store Write ブロック間の交互作用が変更されるため、結果として 1 タイム ステップ遅延します。
close_system('sl_subsys_fcncall8')
関数呼び出しイニシエーターによるアクティブ イベントと非アクティブ イベントの発行
この Stateflow チャートでは、イベント activate
がステート ON
にバインドされることを指定しています。ステート ON
がアクティブに遷移すると、そのイベントによって開始された Function-Call Subsystem Integrate
がイネーブルになります。また、ステートが非アクティブに遷移すると、そのイベントによって開始された Function-Call Subsystem がディセーブルになります。Function-Call Subsystem がイネーブルになるとステートをリセットし、ディセーブルになると出力をリセットするように構成されている場合、該当するアクションが行われます。この例では、このサブシステムは、イネーブルになったときにステートをリセットし、ディセーブルになったときに出力をリセットします。
open_system ('sl_subsys_fcncall9')
close_system('sl_subsys_fcncall9')
Function-Call Subsystem の出力の解釈
1) 関数呼び出しの戻り値は、Function-Call Subsystem の出力からその関数呼び出しイニシエーターへの直接接続です。たとえば、以下の Stateflow チャート Chart1
は、関数 d1=f1()
を実行する関数呼び出しイニシエーターです。f1
を呼び出した後に、チャートは、同じタイム ステップ内に f1
によって計算された戻り値 d1
を使用します。
2) 2 番目の例では、Unit Delay ブロックの実行は Chart2
によってトリガーされません。したがって、Chart2
の実行中、信号 d2
は、Unit Delay が呼び出された時点に該当する、前のタイム ステップからの値を維持します。
open_system ('sl_subsys_fcncall10')
close_system('sl_subsys_fcncall10')
関数呼び出し信号の分岐
この Stateflow チャートは、入力信号 u
が 1 である時間間隔中に周期 1 の周期的な関数呼び出し信号を開始します。関数呼び出しごとに、サブシステムは、f
、h
、g
の順序で実行されます。この実行順序は、Function-Call Split ブロックで指定された順序の結果であり、ドットで注釈が付けられた端子が先に実行されます。
このモデルを R2015b より前のリリースにエクスポートすると、信号 b
がデータ依存性違反として扱われるため、エラーが発生します。
open_system ('sl_subsys_fcncall11')
この Stateflow チャートは、入力信号 u
が 1 である時間間隔中に周期 1 の周期的な関数呼び出し信号を開始します。
関数呼び出しごとに、サブシステム f1
がサブシステム g1
よりも前に実行されます。この実行順序は、Function-Call Split ブロックで指定された順序の結果であり、ドットで注釈が付けられた端子が先に実行されます。
このモデルを R2015b より前のリリースにエクスポートすると、サブシステム f1
の Inport ブロックの [Function-Call Subsystem 出力のフィードバック信号の入力をラッチする] パラメーターがクリアされている場合、信号 b
がデータ依存性違反として扱われるため、エラーが発生します。
close_system('sl_subsys_fcncall11')
無効な Function-Call Subsystem
無効な Function-Call Subsystem のリストを以下に示します。修正方法は、対応するモデル サブシステムで説明されています。
open_system('s_Function_call_subsystems')
あいまいな実行順序のエラー
関数呼び出しイニシエーターによって駆動されるブロックに関連するデータ依存性違反
2 つの Function-Call Subsystem 間のブロックに関連するデータ依存性違反
変更された関数呼び出し出力のフィードバックに起因するあいまいな実行順序のエラー
2 つのサブシステム間の変更された関数呼び出し出力のフィードバックに起因するあいまいな実行順序のエラー
Merge ブロックと Stateflow チャートに関連するデータ依存性違反
Atomic サブシステムと Gain ブロックに関連するデータ依存性違反
Function-Call Subsystem のサイクル データ依存性違反
間接的なデータ依存性違反
入れ子データ依存性違反
Function-Call Subsystem での周期的な実行の正しくない指定
呼び出されたコンテキスト内で計算される Function-Call Subsystem の入力
分岐した関数呼び出し信号と Function-Call Subsystem を接続するブロックに関連したデータ依存性違反
close_system('s_Function_call_subsystems',0)
If Action Subsystem と Switch Case Action Subsystem
If Action Subsystem は、論理条件が true のときに各タイム ステップで実行されます。Switch Case Action Subsystem は、信号が指定された一連の値のいずれかであるときに実行されます。
詳細については、If Action SubsystemおよびSwitch Case Action Subsystemを参照してください。
以下の例では、If Action Subsystem と Switch Case Action Subsystem を使用する方法について説明します。
open_system('sl_subsys_semantics') open_system('sl_subsys_semantics/If Action and Switch Case Action subsystems')
close_system('sl_subsys_semantics/If Action and Switch Case Action subsystems')
Triggered Subsystem
Triggered Subsystem を使用すれば、ソフトウェア トリガー、ハードウェア トリガー、またはその 2 つの組み合わせを実装できます。Triggered Subsystem ブロックは Simulink ライブラリ ブラウザーから追加できます。あるいは、Triggerブロックを Subsystem ブロック内に配置してこのサブシステムを作成することもできます。
詳細については、Triggered Subsystemを参照してください。
以下の例では、Triggered Subsystem の使用方法を示します。
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/Triggered subsystems')
ソフトウェア トリガーは、次のコードで定義されます。
if (trigger_signal_edge_detected) {
out(t) = f(in(t));
}
ハードウェア トリガーは、次のコードで定義されます。
if (trigger_signal_edge_detected) {
out(t) = f(in(t-h)); // h == last step size
}
Triggered Subsystem の各入力端子は、入力をラッチする必要があるかどうかを構成します。ラッチされた入力は、その入力端子のハードウェア トリガー セマンティクスを提供します。ラッチされた入力端子には、シンボル <L>
が付けられます。
close_system('sl_subsys_semantics/Triggered subsystems')
Enabled Subsystem
Enabled Subsystem を使用すれば、イネーブル信号が 0 より大きい場合にのみ実行される条件付き実行サブシステムを作成できます。Enabled Subsystem により、出力信号の初期値を制御したり、サブシステムがイネーブルになるたびにステートをリセットするかどうかを制御したりできます。
Enabled Subsystem ブロックは Simulink ライブラリ ブラウザーから追加できます。あるいは、Enableブロックを Subsystem ブロック内に配置してこのサブシステムを作成することもできます。
詳細については、Enabled Subsystemを参照してください。
次の例では、Enabled Subsystem の使用方法を示します。
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/Enabled subsystems')
close_system('sl_subsys_semantics/Enabled subsystems')
Enabled and Triggered Subsystem
以下のサブシステムは、ステートと出力端子をリセットするオプションを示したものです。Enabled and Triggered Subsystem は、イネーブル条件とトリガー条件の両方が発生すると実行されます。
Enabled and Triggered Subsystem ブロックは Simulink ライブラリ ブラウザーから追加できます。あるいは、EnableブロックとTriggerブロックの両方を Subsystem ブロック内に配置してこのサブシステムを作成することもできます。
詳細については、Enabled and Triggered Subsystemを参照してください。
以下の例では、Enabled and Triggered Subsystem の使用方法を示します。
open_system('sl_subsys_semantics') open_system('sl_subsys_enabtrig1.slx')
close_system('sl_subsys_enabtrig1.slx')
Resettable Subsystem
Resettable Subsystem を使用すれば、リセット信号に基づいてサブシステム内のブロックのステートをリセットできます。Resettable Subsystem ブロックは Simulink ライブラリ ブラウザーから追加できます。
詳細については、Resettable Subsystemを参照してください。
以下の例では、Resettable Subsystem の使用方法を示します。
open_system('sl_subsys_semantics') open_system('sl_subsys_semantics/Resettable subsystems')
close_system('sl_subsys_semantics/Resettable subsystems')
For Each Subsystem
For Each Subsystem は、シミュレーション タイム ステップ中に、入力信号またはマスク パラメーター配列の各要素またはサブ配列に対して実行を繰り返します。For Each Subsystem ブロックは Simulink ライブラリ ブラウザーから追加できます。あるいは、For Eachブロックを Subsystem ブロック内に配置してこのブロックを作成することもできます。For Each Subsystem は、入力信号の個々の要素またはサブ配列に対してアルゴリズムを繰り返します。For Each Subsystem は、サブシステムが処理する要素またはサブ配列ごとにブロックの状態を個別に保持します。
詳細については、For Each Subsystemを参照してください。
以下の例では、For Each Subsystem の使用方法を示します。
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/For Each subsystems')
close_system('sl_subsys_semantics/For Each subsystems')
While Iterator Subsystem
While Iterator Subsystem は、シミュレーション タイム ステップ中、論理条件が true
である間、実行を繰り返します。While Iterator Subsystem ブロックは Simulink ライブラリ ブラウザーから追加できます。あるいは、While Iteratorブロックを Subsystem ブロック内に配置してこのサブシステムを作成することもできます。While Iterator Subsystem は、各モデル タイム ステップで複数回の反復を実行します。反復回数は while 反復条件によって制御されます。
While Iterator Subsystem は、任意のタイム ステップで任意の回数の反復を実行できるという点で、Function-Call Subsystem と似ています。
While Iterator Subsystem が Function-Call Subsystem と異なる点は、Stateflow Chart のような独立したイニシエーターが含まれていないことです。さらに、While Iterator Subsystem は、オプションで While Iterator ブロックによって生成された現在の反復回数にアクセスできます。
詳細については、While Iterator Subsystemを参照してください。
以下の例では、While Iterator Subsystem の使用方法を示します。
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/While Iterator subsystems')
close_system('sl_subsys_semantics/While Iterator subsystems')
For Iterator Subsystem
For Iterator Subsystem は、シミュレーション タイム ステップ中に、指定された反復回数だけ実行を繰り返します。For Iterator Subsystem ブロックは Simulink ライブラリ ブラウザーから追加できます。あるいは、For Iteratorブロックを Subsystem ブロック内に配置してこのサブシステムを作成することもできます。For Iterator Subsystem は、モデルの各タイム ステップで固定された回数の反復を実行します。この反復回数は、For サブシステムへの外部入力とすることも、For Iterator ブロックで内部的に指定することもできます。
For Iterator Subsystem は While Iterator Subsystem とよく似ていますが、所定のタイム ステップでの反復回数が固定されているという制限があります。
詳細については、For Iterator Subsystemを参照してください。
以下の例では、For Iterator Subsystem の使用方法を示します。
open_system('sl_subsys_semantics'); open_system('sl_subsys_semantics/For Iterator subsystems')
close_system('sl_subsys_semantics/For Iterator subsystems')