おそらく、主なニュースは「バージョン1.1」と呼ばれるコマンドシステムの拡張でしょう。 前のものとの違いは、高度なアドレス指定機能です。 しかし、まず最初に。 危機にwhatしているものを想像するには、コマンドシステムのマップを見てください(写真はクリック可能です)。
まず第一に、あなたの裁判所に連れて行かれたかったのは彼女でした。 コマンドシステムを設計する際、2つの基本的な要件、つまり優れた拡張性と高いコード密度が特定されました。 予約済みの操作コードは、写真上で黄色でマークされています。 写真からわかるように、拡張性の要件を満たすことに成功しました。 ただし、黄色の「セル」が拡張の唯一の機会ではありません。一部の予約は、マルチバイト操作コードの未使用ビットに保存されます。 さらに、2つのプレフィックス(NOTCHおよびKOL)により、操作コードのセマンティクスを拡張できます。 図からわかるように、シングルバイトのプレフィックスの数は簡単に増やすことができます。 これらの要因により、顕著な拡大の機会を述べることが可能になります。 しかし、それだけではありません。 現在、最大命令長は5バイトに制限されています。このサイズは、安価なFPGAの機能に基づいて選択されています。 長い命令(6バイト、7 ...)の命令コードを0xf0から0xffの範囲で割り当てると、コマンドシステムをどれだけ拡張できるかを想像してください。命令の長さは常識によってのみ制限できます。 ですから、コマンドシステムの拡張の可能性について疑いを持たないことを望んでいます。コマンドシステムが存在する場合、コメントで議論することを歓迎します。
しかし、コード密度はどうですか? はい、Habrは厳しく、架空のデータは好きではありません。 主観的な推定によると、現在のコード密度は、RISCアーキテクチャを備えた最初のバージョンのプロセッサーとコード密度で競合する可能性があります。 たとえば、ARMとMIPSの最初のバージョンを検討する場合、このパラメーターではバージョン1.1が優れているようです。 x86と最新のRISCについては、これらのアーキテクチャのチームの豊富さのおかげで、それらのコード密度は高くなっています。 ただし、固有の拡張オプションを適切に活用すれば、パラメーター「コード密度」により、現代の一般的なアーキテクチャを上回ることができます。
x86アセンブラーの作成経験のある多くのプログラマーにとって、「このアセンブラーで作成できます」と言うには、指示のある表をざっと見るだけで十分です。 アセンブラーのニーモニックの名前が特許によってどのように保護されているかはわかりませんが、可能であればx86と一致するように選択されています。 また、0xd0-0xd7の範囲の命令についても述べたいと思います。 これらは4バイトの命令で、2番目のバイトは汎用レジスタを定義し、3番目と4番目は拡張アドレス指定に使用されます。
S / Dビットは、どの引数(2番目のバイトの4ビットレジスタコード)がポインタであるかを決定します-最初または2番目のレジスタ。 3ビットはさらに拡張するために予約されており、0に設定する必要があります。残りのビットは符号なしの数値を定義し、間接アドレッシング中にポインターに追加されます。 これらの操作は、構造化データを使用した作業を簡素化するように見えます。 これについては、たとえばここで参照できます-everest.l4os.ru/aliases_for_registers
特徴的なことは、最初はコードが完全に位置的に独立して開発されたため、コマンドシステムでは絶対アドレスに移動するための命令(条件付きまたは無条件)が見つからないことです。 すべての遷移アドレスは、命令カウンターに対するオフセットとして表されます。 なんで? これは、アーキテクチャレベルで100%の位置的に独立したマシンコードを実装するために行われます。 定数が必要ですか? コマンドカウンターに対するオフセットで選択します。 静的変数、コマンドカウンターに相対するアドレスが必要です。 ただし、異なるアドレッシングモードの実装の詳細は、アセンブラーマクロの背後に確実に隠されます。 絶対アドレス指定なしでシステム関数を呼び出す方法の質問に対する答えは、以下です。
実際、上記のすべてはコマンドシステムに適用されます。 マイクロプロセッサアプリケーションの主な分野は、すでにx86、アーム、ミップ、シンプルなマイクロコントローラに分かれています。 拡張性とコード密度は、デバイス開発者がマイクロプロセッサーを選択する際に考慮する最新のものです。 プロジェクトが開発者にとって興味深いものになるという希望を与えるものは何ですか? これはコマンドシステムであるため、シングルバイト命令IDLE 、 TASK_ID 、 SEND 、 RECV 、 LOCK 、 FREEを見てください 。
プロセッサのチップは、タスクを管理するオペレーティングシステムの小さな部分が内部に隠されており、タスクの概念そのものがマイクロプロセッサに「配線」されています。 新しい指示は、マルチタスクをサポートするのに役立ちます。 IDLEステートメントは無条件にスケジューラーに入ります。 実際、不必要な命令は、スケジューラー自体のデバッグにのみ役立ちます。 TASK_ID命令は、アクティブなタスクの識別子と、次のスケジュールされた時間割り当て操作までのティック数を返します。 LOCK命令とFREE命令のペアは、メッセージバッファをキャプチャして解放するために使用されます。 この場合、LOCK命令の名前とx86命令の一致にもかかわらず、完全に異なる機能を実行します。 プロセッサはタスクの概念で動作するため、タスクの相互作用には手段が必要です。 LOCKステートメントを使用して、タスクはメッセージバッファーをキャプチャし、FREEステートメントを使用して解放します。 メッセージバッファは64個のレジスタで、その交換はSET_MR(RONからの値でメッセージレジスタを書き込む)およびGET_MR命令(RONのメッセージレジスタを読み取る)を使用して行われます。
もちろん、プロジェクト全体が開始された最も重要な指示は、SENDおよびRECV指示-メッセージの送受信の指示です。 これらの命令には2つの引数があります-対話用のタスク番号と操作タイムアウト(レジスタに設定)。 システムにタスク時間を与える、または遅延を実装する最も簡単な方法は、メッセージを自分自身に送信するか、自分からのメッセージを待つことです。スケジューラは、メッセージのタイムアウトが期限切れになる前にブロックされたタスクに制御を転送しません。
SEND操作とRECV操作は同期的です。メッセージがタスク間を通過するには、タスクの1つがRECVと他のSENDを実行する必要があります。 ほとんどの場合、これは、これらの命令のいずれかを完了した最初のタスクが、別のタスクの準備ができるのを待つことをブロックすることを意味します。 何らかの理由でブロックが望ましくない場合、ゼロタイムアウトが設定され、ブロックの代わりにパーティの1つが利用できない場合、タスクはタイムアウトを通知するステータスを受け取ります。
メッセージが送信されると、LOCK命令によって以前にキャプチャされたメッセージバッファが、受信メッセージのタスクに切り替えられます。 メッセージを受信したタスクは、バッファが解放された後に機能するはずです。 たとえば、 putsライブラリ関数の呼び出しは次のようになります。
ロック; メッセージバッファキャプチャ SET_MR MR0、R2; メッセージIDの設定 SET_MR MR1、R3; メッセージ引数の設定 送信 メッセージパッシング RECV メッセージへの返信を待っています GET_MR R0、MR0; リターンコードを読む 無料; 空きメッセージバッファ
このコードは、理解を容易にするために可能な限り単純です。 この例では、LOCK命令によってキャプチャされたバッファがメッセージの送信時にレシーバタスクに委任されているため、FREE命令はRECVステートメントによって受信されたメッセージバッファを解放します。
ソリューションの明らかな複雑さと異常性にもかかわらず、アプリケーションプログラマの観点からは何も変わりません。ライブラリ関数は実装の詳細を慎重に隠します。 しかし、システムプログラマーとライブラリ開発者は、試行する必要があります-プログラム間の相互作用は、要求と回答の形式を記述するプロトコルの形式で記述する必要があるという事実から始めなければなりません-複雑なソフトウェア複合体は、相互作用を通じて特定の問題を解決する相互作用するエンティティのセットとして記述されます
すべての実験は、この奇跡-Mars rover2ボードで行われます:
ご清聴ありがとうございました。 まず、コマンドシステムは既にハードウェアで動作するため、コマンドシステムについて説明します。 マルチタスクのハードウェア拡張に関しては、まだ準備ができていません。マルチタスクのサポートに関する情報は情報提供のために提供されており、実際の実装は記事の内容と一致しない場合があります。