アポロ誘導コンピュータ(アポロゆうどうコンピュータ、Apollo Guidance Computer、AGC)とは、アポロ宇宙船の全航行機能を自動制御し、宇宙飛行士が飛行情報を確認/修正するために使われた、リアルタイム組み込みシステムである。ワード長16ビットで、データ15ビット、パリティ1ビットである。AGC上のソフトウェアの大部分はコアロープメモリと呼ばれる特殊なROMに格納されており、小容量の読み書き可能な磁気コアメモリをデータ格納用に備えている。

宇宙飛行士はDSKY(ディスキー)と呼ばれる数値表示部とキーパッドから構成される装置でAGCとやりとりする。AGCとDSKYは、アポロ計画のためにMIT器械工学研究所で開発された。AGCは初期の集積回路を採用したコンピュータの1つである。

アポロの中のAGC 月への飛行には毎回2つのAGCを使った。ひとつは司令船で、もうひとつは月着陸船で使われた。指令船のAGCは誘導/航行システム (G&C) の中央部にあった。月着陸船のAGCでは(Primary Guidance, Navigation and Control System、一次誘導/航行/制御システム)が動作し、頭字語PGNCSを「ピングス」と発音した。

各ミッションでは他にもふたつのコンピュータを使用していた。 サターンV型ロケットのS-IVBにあるIBM製の航行コンピュータ(LDVC) 月着陸船のAbort Guidance System(AGS)というTRW製の小さな機械。AGSはPGNCSの障害が発生したときに使われ、月から離陸して司令船にドッキングするまでを制御する。着陸には使えない。

設計 チャールズ・スターク・ドレイパー率いるMIT器械工学研究所が設計を行った。ハードウェア設計責任者はである。アーキテクチャ設計は、J.H. Laning Jr.、Albert Hopkins、Ramon Alonso、Hugh Blair-Smith が行った。実際に搭載したハードウェアはレイセオンが製造し、同社の Herb Thaler がアーキテクチャ設計チームに加わっていた。マーガレット・ハミルトンがソフトウェアの監督・指導をつとめた。

アポロ誘導コンピュータは初期の集積回路(IC)を使って作られた。Block I バージョンは4,100個のICを使い、それぞれのICは3入力のNORゲートをひとつ構成していた。次の Block II バージョンは2つの3入力NORゲートをひとつのICで構成したものを2,800個使っている。ICはフェアチャイルドセミコンダクター製で、RTLによる実装で、フラットパック (flat-pack) という形でパッケージされている。ICを複数搭載したモジュール同士はワイヤラッピングで相互接続している。モジュールを挿入するソケットから金属棒が出ていて、その金属棒にワイヤーを巻きつけて接続する。金属棒とワイヤーは高圧で押し付けられ、気密結合状態となるため、一般的な半田付けよりも信頼性が高い。配線完了後、ワイヤーはエポキシ樹脂で封止される。すべて同じICを使うことにより、初期のICを使った他のコンピュータ(ミニットマンミサイルの誘導コンピュータ)が悩まされた問題は発生しなかった。

コンピュータのRAMは磁気コアメモリ(2048ワード)でROMはコアロープメモリ(36Kワード)である。どちらもサイクル時間は11.72μ秒。メモリのワード長は16ビットで、そのうち1ビットはパリティビットである。 CPU内の16ビットワードは、14ビットデータと1ビットのオーバーフローフラグ、1ビットの符号フラグから成る(数値は1の補数表現)。

DSKYユーザインタフェース

ユーザインタフェースユニットはDSKY (display and keyboard) と呼ばれ、通常「ディスキー」と発音した。一連の指示灯、数値表示ディスプレイ、電卓型のキーボードから成る。コマンドは数字で入力され、Verb部とNoun部という2つの数値を入力する。Verb は動作の種類を指定し、Noun は Verb コマンドによって変更されるデータを指定する。

表示は高電圧エレクトロルミネセンス・ディスプレイであり、数字毎に7セグメントで表示され、それを並べて数字列を表している。セグメントは電気機械式リレーで制御されるため、表示の更新速度が制限される(Block IIではもっと高速なシリコン制御整流器が使われている)。3行の5桁の数字で八進数か十進数が表示される。この3つの数値で宇宙船の姿勢を表すベクトルを表示したり、必要な速度変化のベクトルを表示したりする。データは内部では国際単位系で保持されているが、表示は米国慣用単位(ヤード・ポンド法)を使っている。この電卓型インタフェースはほぼ同時期に世界初の電卓が市場に現れている。科学技術演算ができるプログラム可能なポケット電卓が現れるのはもっと先のことであった。世界初の携帯可能なプログラム可能電卓はHP-65であり、この電卓はバックアップ用としてアポロ・ソユーズテスト計画 (1975) の際にアポロ司令船に搭載された。、このタイプのものとしては世界初のデジタル制御パネルである。

司令船はふたつのDSKYを備えていた。ひとつはメイン計器パネルにあり、もうひとつは六分儀のそばに設置されて慣性誘導装置を調整するのに使われた。 月着陸船にはひとつのDSKYがAGCに接続されていた。指令船のメイン計器パネルと月着陸船のDSKYには、そのすぐ上にAGCが制御している航行指示装置 (FDAI) がある。

2009年、DSKY1台が Heritage Auctions にて一般向けオークションに出品され、50,788ドルで落札されたApollo Guidance Computer: Original Display and Keyboard (DSKY) Unit.... (Total: 1 Items) Heritage Auctions。

タイミング AGCの駆動クリスタル周波数は2.048MHzである。クロックは分周されて4相の1.024MHzとしてAGC内で使われた。さらにそれを分周して512kHzの信号を生成し、これを「マスター周波数」と呼んだ。この信号はAGC以外のアポロ宇宙船のシステムを同期させるのに使われた。

マスター周波数はさらに分周され5分の1の102.4kHzの信号が作られる。これをさらに分周したF1(51.2kHz)からF17(0.78125Hz)の17種類の信号が作られる。F10(100Hz)はAGCに戻され、リアルタイムクロックとPINC(後述)を使った強制カウンターをインクリメントするのに使われる。F17はAGCがスタンバイモードの場合に定期的に動作させるのに使われた。

セントラルレジスタ AGCは4本の16ビットレジスタを汎用的に使用した。これらをセントラルレジスタと呼ぶ。 A : アキュムレータ、一般に計算に使用される。 Z : プログラムカウンタ、次に実行すべき命令のアドレスを保持する。 Q : DV命令の剰余を保持する。またTC命令後のリターンアドレスを保持する。 LP : MP命令後の積の下位ビット部分を格納する。

コアメモリには4つの場所があり(アドレス20-23)、ここに格納された値が自動的に1ビットシフトや1ビットローテートされるため "editing locations" と呼ばれた。なお、7ビット右シフトする場所はソフトウェアインタプリタが解釈する擬似命令コードを取り出すのに使われた。これはBlock I、Block IIに共通する。

その他のレジスタ thumb|コンピュータ歴史博物館に展示されているDSKYとAGC。AGCは中のロジックモジュールが見えるよう開かれている。 thumb|Block I AGC のロジックモジュールのプロトタイプ thumb|Block II ロジックモジュールとフラットパックIC thumb|AGCデュアルNORゲート thumb|AGCデュアルNORゲートの回路図 AGCには他にも処理の過程で使用するレジスタが存在する。

S :12ビットのメモリアドレスレジスタ。アドレスの下位ビットを保持Bank/Fbank : 4ビットのROMバンクレジスタ。アドレッシングがfixed-switchableモードのときに1キロワードのROMバンク選択に使用Ebank :3ビットのRAMバンクレジスタ。アドレッシングがerasable-switchableモードのときに256ワードのRMバンク選択に使用Sbank (super-bank) :Fbankを拡張する1ビットのレジスタ。ROMが全部で36キロワードであり、最後の4キロワード部分はFbank単独では指定できないため、その場合に使用する。SQ:4ビットのシーケンスレジスタ。現在の命令コード(オペコード)を保持G:16ビットのメモリバッファレジスタ。メモリに読み書きする(した)内容X:加算器への一方の入力。加算器は1の補数で計算。あるいはプログラムカウンタ(Z)をインクリメントする。Y:加算器へのもう一方の入力U:実際にはレジスタではなく、加算器の出力(X+Yの1の補数表現)B:汎用バッファ。命令プリフェッチにも使われる。命令を実行する際、Bレジスタの上位ビット(オペコード部分)をSQレジスタにコピーし、Sレジスタに下位ビット(オペランド=アドレス)をコピーする。C:独立したレジスタではなく、Bレジスタの1の補数表現である。IN:4つの16ビット入力レジスタOUT:5つの16ビット出力レジスタ

命令セット 命令フォーマットは3ビットがオペコードで12ビットがアドレスとなっている。Block Iは11種の命令、TC, CCS, INDEX, XCH, CS, TS, AD, MASK(基本)と SU, MP, DV(拡張)を持つ。先頭の8個は基本命令と呼ばれ3ビットオペコードで直接指定される。残り3個は拡張コード命令と呼ばれ、特別なINDEX命令(EXTENDと呼ぶ)の直後に実行される。

Block I AGC の命令の概要は以下のとおり。

TC (transfer control) 無条件分岐。サブルーチンコールにも使用。アドレス部で分岐先命令のアドレスを指定する。リターンアドレスは自動的にQレジスタに格納される。 CCS (count, compare, and skip) 複雑な条件分岐命令。まずアドレス部で指定された位置のデータをAレジスタにロードする。AGCは1の補数表現を採用しているので、ゼロには2つの表現がある。全ビットが0なら「正のゼロ」、全ビットが1なら「負のゼロ」を意味する。次にDABS (diminished absolute value) という値を計算し、Aレジスタに格納する。元の数値がゼロより大きければ、そこから1を引いた値がDABSであり、負の場合はその1の補数を求めてから(このため「絶対値; absolute value」と呼ぶ)1を差し引いてDABSを求める。"diminished" とは「デクリメントするがゼロより小さくしない」ということを意味する。従ってAGCがDABSを求める際、正の数値は正のゼロに近いほうに向かい、負の数値も同様だが、最初の正負判定の結果によって次に述べる4方向スキップを行う。CCS命令の最後の段階は4方向スキップであり、DABSを行う前のAレジスタの内容によってスキップの仕方が変化する。Aレジスタが0より大きい場合、CCS命令の直後の命令にスキップする(つまりスキップしない)。Aレジスタが正のゼロの場合、CCS命令から2つめの命令にスキップする。Aレジスタが負すなわちゼロより小さい場合、CCS命令から3つめの命令へスキップする。Aレジスタが負のゼロの場合、CCS命令から4つめの命令へスキップする。この命令の第一の用途は正の値のカウンタで制御されるループを形成することであり、CCS命令でループ終了を判断し、TC命令でループの先頭に戻る。ちょうど IBM 360 のBCT命令と等価である。絶対値を求める命令としても重要である。その場合、CCSの後に TC *+2, TC *+2, AD ONE と命令を続ける。奇妙な副次効果として CCS-holes と呼ばれるものがある。評価する値が決して正にならないと判っている場合、2ワードが決して実行されないことになるので、その2ワードにデータを配置できることになっている。 INDEX 命令のアドレス部の指す位置の内容を次の命令のアドレス部に加算する。INDEX命令は次の命令のオペランドをベースアドレスとし、それにインデックス値を加算(または減算)するのに使うことができる。配列やテーブル参照の実装に使用する。また、ワード全体を加算するので、次の命令のオペコードを書き換えるのにも使える。オペコードとオペランドを同時に書き換える使い方もないわけではない。 RESUME INDEX命令の特別な場合 (INDEX 25)。割り込みからの復帰に使われる命令である。割り込まれた位置に戻って実行を再開する。 XCH (exchange) Aレジスタの内容と指定したアドレスのメモリの内容を交換する。指定されたアドレスがROMの範囲内だった場合、メモリ側は書き換えられず、単にAレジスタへのロード命令として機能する。RAMの範囲だった場合、Aレジスタの左端ビットを符号ビットとしてオーバーフロー訂正が行われるが、TS命令のような例外的振る舞いはしない。 CS (clear and subtract) 指定されたアドレスのメモリの内容の1の補数をAレジにロードする。 TS (transfer to storage) Aレジスタの内容を指定されたアドレスにストアする。多ワード長の加減算でキャリー伝播を行う手段としてオーバーフローを検出し訂正する。結果がオーバーフローしていない場合(Aレジスタの左端2ビットが同じ場合)、特に何もしない。オーバーフローが発生している場合(その2ビットが異なる場合)、左端のビットを符号ビットとしてメモリに転記し、Aレジスタの内容は必要に応じて+1または-1され、TS命令の次の命令をスキップする。オーバーフローが起き得る場合で、それが異常なイベントだという場合、TS命令の次にオーバーフローしない場合のコードへ分岐するTC命令を配置しておく。オーバーフローが正常なイベント(多ワード長加減算)の場合、TS命令の次に CAF ZERO(CAF命令とは、ROMへの XCH 命令)を配置し、キャリー(+1、0、-1)を次のワードのために用意する。角度は単精度(1ワード)、距離と速度は倍精度、経過時間が3倍精度で計算していた。 AD (add) アドレス部で指定されたメモリの内容とAレジスタの内容を加算し、結果をAレジスタに置く。Aレジスタの左端2ビットが異なる場合、オーバーフローであることを意味する。加算を連続して行う場合、和がワードで表せる数値範囲の2倍を超えなければ、オーバーフローは単に状態として保持し続けることができる。 MASK アドレス部で指定されたメモリの内容とAレジスタの内容についてビット単位の論理積 (AND)を求め、結果をAレジスタに置く。 MP (multiply) アドレス部で指定されたメモリの内容とAレジスタの内容の乗算を行い、積の上位ワードをAレジスタ、下位ワードをLPレジスタに置く。それぞれの符号は一致している。 DV (divide) Aレジスタの内容を被除数、アドレス部で指定されたメモリの内容を除数として除算する。商をAレジスタ、余りの絶対値をQレジスタに置く。現代のコンピュータとは異なり、数値は固定小数点数の仮数(符号ビットのすぐ右に小数点があるものとされる)として扱われるので、除数が被除数より大きくないと不正な結果が得られる。この場合の対策はとられていなかった。Block II AGC では、AレジスタとLPレジスタを使った倍精度の除算を行い、正しく符号がつけられた余りがLPレジスタに置かれた。これによって倍精度除算のサブルーチンが大幅に単純化された。 SU (subtract) アドレス部で指定されたメモリの内容をAレジスタから減算し、結果をAレジスタに置く。

命令の実装はグループ化された12のステップでなされており、そのステップを「タイミングパルス」と呼ぶ。タイミングパルスはTP1からTP12まである。12のタイミングパルスのそれぞれのグループを命令の「サブシーケンス」と呼ぶ。TC命令のような単純な命令では、12のタイミングパルスを1つのサブシーケンスとして実行する。複雑な命令ではいくつかのサブシーケンスを必要とする。乗算命令 (MP) は8個のサブシーケンスを使用する。最初のサブシーケンスを MP0 と呼び、次の MP1 サブシーケンスは6回反復され、MP3 サブシーケンスで完了する。Block II ではこれが3サブシーケンスに短縮された。

サブシーケンス内の各タイミングパルスは最大5個の「コントロールパルス」を発生できる。コントロールパルスは命令の実際の動作を行わせる信号であり、レジスタの内容をバスに送り出したり、バス上の内容をレジスタに取り込んだりする。

メモリ thumb|250px|AGC コアロープメモリ (ROM) thumb|250px|right|AGC 1024ビット磁気コアメモリモジュール(前面と裏面) Block I AGCのメモリは1024ワードのバンクから成る。最も低いバンク(バンク0)はRAMであり、それ以外はROMである。各AGC命令には12ビットのアドレスフィールドがあり、下位10ビットでバンク内のアドレスを表す。ビット11と12でバンクを表し、00がRAMバンク、01がバンク1、10がバンク2を示す。11はBankレジスタの内容でバンクを指定することを意味する。バンク1とバンク2は常に直接使用可能であるため、"fixed-fixed"メモリと呼ばれる。バンク3およびそれ以上のバンクは"fixed-switchable"メモリと呼ぶ。

Block I AGCは当初12KワードのROMを持っていたが、後に24Kに拡張された。Block II は32KワードのROMと4KワードのRAMを持つ。

AGCはメモリサイクルと呼ばれる処理でGレジスタ経由でメモリとやり取りする。メモリサイクルはタイミングパルス12個分を要する(11.72μ秒)。TP1でフェッチすべきメモリアドレスをSレジスタにロードする。メモリ回路がSレジスタで指定されたアドレスに対応するメモリからデータを読み出す。RAMから読み出したワードはTP6の時点でGレジスタに格納され、ROMから読み出したワードはTP7の時点でGレジスタに格納される。読み出してきたメモリワードはTP7からTP10の間、Gレジスタで使用可能となっている。TP10を過ぎるとGレジスタの内容はメモリに書き戻される。

AGCのメモリサイクルはAGC動作中は連続的に行われている。メモリ上のデータを必要とする命令は、TP7からTP10の間にアクセスしなければならない。AGCがGレジスタの内容を書き換えると、書き換えた内容がTP10以降にメモリに書き込まれる。このようにして常にメモリサイクルが機能しており、メモリとGレジスタの間でデータがやり取りされている。

各メモリワードの下位15ビットが命令またはデータとして使用される。最上位ビットはパリティビットであり、データの保護に使用される。パリティビットはワード内の1の個数が常に奇数になるよう、データの内容によりパリティ生成回路で1か0に設定される。パリティチェック回路はパリティビットとデータの内容が合っているかをチェックする。もし合っていない場合そのメモリワードは壊れたと判断され、操作パネルの PARITY ALARM というライトが点灯する。

割り込みと強制的カウンタ AGCは5種類の割り込みを扱う。

DSRUPTはユーザディスプレイ (DSKY) のアップデートインターバル毎に発生する ERRUPTはハードウェアの障害や警告の場合に発生する KEYRUPTはユーザキーボードのキーが押されたときに発生する。 T3RUPTはAGCのリアルタイムクロックをアップデートするタイミングで定期的に発生する。 UPRUPTは16ビットのアップリンクデータがAGCにロードされたときに発生する。

AGCは割り込みが発生すると、それまで実行していたプログラムの実行を中断し、短い割り込みサービスルーチンを実行して、割り込まれたプログラムに復帰する。

AGCは20個の強制カウンタを持っている。それらはメモリの固定の場所に存在し、アップ/ダウンカウンタとシフトレジスタとして機能する。インクリメント(PINC)、デクリメント(MINC)、シフト(SHINC)は通常の命令と命令の間に挿入されるマイクロ命令によって実行される。

割り込みはカウンタがオーバーフローしたときに発生する。T3RUPTとDSRUPTはこのPINCオーバフローの発生をトリガーとして発生する。UPRUPTはSHINCで16ビットぶんシフトしたときに発生する。これはAGCへのアップリンクデータが16ビットシフトし終わったことを示す。

スタンバイモード AGCは STANDBY ALLOWED スイッチを使ってパワーセービングモードに移行する。このモードはAGCの電源を切り、2.048MHzのクロック(およびその分周クロック)だけを発生させる。分周クロックの1つであるF17信号により、1.28秒間隔でAGCの電源が入る。そこでAGCは STANDBY ALLOWED スイッチの状態をチェックし、もしまだそのモードならば再び電源を切って次のF17信号を待つ。

スタンバイモードではAGCは眠っているので、PINCを実行してリアルタイムクロックをインクリメントすることができない(通常は10ミリ秒単位でインクリメント)。その代わりとして、F17信号で起きたときにリアルタイムクロックを1.28秒ぶん進める。

スタンバイモードは慣性飛行中AGCを使わないときに電力消費を抑えるために設けられた。通常70Wの電力消費が5Wから10Wに低減される。しかし、実際にはAGCは飛行中ずっと使われ、スタンバイモードが使われることはなかった。

データバス AGCは16ビットのリードバスと16ビットのライトバスを持つ。セントラルレジスタ(A、Q、Z、LP)や他の内部レジスタの内容は制御信号によってリードバスに出力される。リードバスとライトバスは非反転バッファでつながっているのでリードバスに出力された内容はライトバスでも観測される。別の制御信号によりライトバスの内容がレジスタに書き込まれる。

データ転送の例:次の命令のアドレスをBレジスタからSレジスタに移動する。 RB(リードB)信号を送信 Bレジスタの内容をリードバスに出力 次いで、それがライトバスに出力される WS(ライトS)信号を送信 ライトバス上のデータをSレジスタに格納

いくつかのレジスタをリードバス上に同時に出力することができる。これが起きるとレジスタの内容が論理和(OR)演算されたビット列がバス上に現れる。これを使ってMASK命令(論理積)を実装している。AGC本体はビット反転ができるので(Cレジスタ)、ド・モルガンの定理に従い、 ふたつのオペランドを反転(NOT)し それらをバスに同時に出力して(OR) 結果を再度反転(NOT)する これでANDに相当することになる。

ソフトウェア AGCの要求仕様が定義されたとき、必要なソフトウェアやプログラミング技法は存在せず、一から設計する必要があった。

AGCのソフトウェアはAGCアセンブリ言語で書かれ、コアロープメモリに格納された。 それは単純なリアルタイムオペレーティングシステムであり、最大8個のジョブをバッチジョブスケジューリングシステム(EXEC)で走行させることができる。これにはプリエンプティブでないマルチタスクが使われる(各ジョブは定期的にEXECに制御を戻す必要があり、優先度のより高いジョブが待ち状態になっていないかチェックされる)。また、割り込み駆動型コンポーネントWAITLISTもあり、複数のタイマー駆動型タスクをスケジュールする。タスクは短いスレッドからなり、実行が終了するときにWAITLISTに自分を再実行してもらうようスケジュールしてもらう。あるいは、割り込み処理の中からEXECに対してもっと長いジョブの実行を指示することもできる。

EXECのジョブは優先度制御される。最も優先度の低いダミージョブが常に存在している。ダミージョブが診断チェックを行い、DSKYの COMPUTER ACTIVITY という緑色ランプを制御する。ダミージョブが動作中ということはAGCが何もすることがないことを意味するので、そのランプは消灯される。ダミージョブは優先度の高いジョブがあると中断され、COMPUTER ACTIVITY ランプを点灯させる。

AGCはMITで開発された洗練されたソフトウェアインタプリタを持っていて、もっと複雑で使いやすいマシンを仮想的に実現している。これは8ビット以上の精度を必要とする航行計算で使われた。この仮想マシンは倍精度のスカラーとベクターを扱うことができ、さらには行列とベクトルの積を求める MXV 命令もあり、それらの命令をAGC本来のコードに混ぜて使うことができる。それら擬似命令を使うとインタプリタがそれをAGCの多数の命令に展開するため余計な時間がかかるが、コードに擬似命令を使うことでプログラムの大きさを縮小する効果があった。当時はメモリ搭載量が何よりも大きな制限だったため、擬似命令はよく使われている。擬似命令の平均実行時間は24ミリ秒である。初期のプロトタイプである Christmas Computer のアセンブラ兼バージョン管理システムは YUL と呼ばれ、ネイティブコードとインタプリタコードの正しい変換を行っていた。

割り込みベースのユーザインタフェースルーチン群 PINBALL によってキーボードとディスプレイを制御する。PINBALLには宇宙飛行士が任意のアドレスのメモリの内容やレジスタの内容を(8進数または10進数で)表示するための機能もある。モニター相当のルーチンもあるので、定期的に特定のメモリの内容を表示させることも可能である。ジョブを起動することもできる。PINBALLはおおざっぱに言ってしまえばUNIXのシェルと同じことができる。

ソフトウェアの大部分は書き換えできないコアロープメモリに置かれていたが、重要な部分は読み書き可能な磁気コアメモリに置かれていた。このため、DSKYインタフェースを使って宇宙飛行士がプログラムを上書きすることも可能であり、アポロ14号で実際にそれが行われた。

Block II Block II バージョンのAGCは1966年に設計された。Block I のアーキテクチャを踏襲したがRAMを1Kワードから2Kワードに拡張している。ROMも24Kワードから36Kワードに拡張されている。命令も11種から34種に拡張され、Block I の入出力関連のレジスタ群が入出力チャネルに置き換えられた。実際に最初に月まで行ったAGCは Block II である。Block I バージョンは無人飛行のアポロ4号から6号までと、事故を起こしてキャンセルされたアポロ1号に装備されていた。