Netgen version 1.4 Tutorialの翻訳

内容

免責条項

Netgen イントロダクション

NetgenのLVSアルゴリズム

ソースからネットリストを作成する

LVSの設定

LVSの実行

バッチモードの LVS

LVS結果の解釈

マッチしないエレメントの数

階層が混在した例

マッチしないサブセル名の扱い

トップレベルで混在した階層

素子パラメータの不一致

回路階層の自己同型(オートモルフィズム)

設定ファイルのそのほかのヒント

大規模ネットとごちゃごちゃの出力についてのヒント

Tutorial history

免責条項

このチュートリアルはNetgen version 1.4.75かそれ以降に対応してます。開発者は、内容が正確かつ最新であるよう努めていますが、コード修正と新しい開発のため、それをいつも保証できるわけではありません。チュートリアルに書いてあるように動作しない場合は開発者にコンタクトしてください(email情報はページの最後にあります)。

Netgenとはネットリスト操作と比較のためのツール

Netgenプログラムの目的は2つです:1つは、異なるフォーマットのネットリストを変換すること、もう1つは2つのネットリストが同一であるか比較し、同一でない場合、どこが違うか見つけることです。ネットリスト変換は、netgenの簡単な一面です。というのは、ネットリストはだいたい同じような情報をもっており、互いに似通っているからです。このチュートリアルは、主にネットリスト比較を扱います。ネットリスト比較は、しばしば”LVS”あるいは”Layout vs. Schematic”とよばれます。なぜならその主目的がVLSIレイアウトが、そのもとになるネットリストと同一であることを検証することだからです。

回路設計者にとっては、設計するシステムの回路図が出発点です。回路図は一般に階層的であり、基本回路から始まり、上位は全体チップの表現で終わります。回路図を描くプログラムは、通常スケマキャプチャツールや回路図描画ツールです。スケマキャプチャは、描かれた設計を入力として、単に回路の素子と接続を表現するネットリストに変換します。ネットリストは、一般的にSPICEのようなよく知られた形式で、シミュレーションとネットリスト比較によく用いられます(必ずしも同一のネットリストを両方に用いるわけではありませんが)。

レイアウト設計者(回路設計者の場合もそうでない場合もある)は回路図から、素子の配置や向き、接続する配線の幅、レイアウトに規定される図形の配置と大きさの設計ルールを考慮しながら、回路のレイアウトを生成します。設計内容とツールによりますが、このプロセスは全自動から完全手作業まで幅があります。しかしVLSIの設計では、とくにアナログとミックスシグナル(アナログとデジタル混在)の設計では、レイアウトはしばしば回路図と独立して作成され、多くの気にしなくてはならないことを考慮するため、レイアウトは主に手作業で行われます。レイアウトが出来上がれば、レイアウトツール(あるいは別のツールのこともある)で設計抽出を行い、すべての素子を見つけ出し、他の素子との接続を決め、その情報をもったネットリストを書き出します。そのため、回路図とレイアウトから生成された2つのネットリストが存在し、それらはどこかのレベルで同一の回路を表現しているはずです。

カスタムの手作業のレイアウトは難しいものなので、LVSの典型的な目的は、レイアウトエンジニアがレイアウトを作成する間に作り込んだエラーをチェックすることです。回路図は、一般に(正しい)基準とされますが、それは回路は大抵シミュレーションに適用されており、シミュレーション結果は、回路(あるいは全体チップ)が仕様どおりに動くか動かないかを知らせるからです。レイアウトが自動生成(シンセシス)されるデジタル設計でも、例えばチップのメタル層の再設計の際の設計修正では、LVSは決定的に助けになります。この場合、再配線は通常手作業でおこなわれるので、それが正しいかを回路図に対してチェックする必要があります。そのほかの理由は、回路合成が主張の通りに正しく仕事したかをチェックすることです。シンセシスはとても複雑な処理なので、そして多くの設定ファイルを必要とするので、容易に間違いは起こります。1つのファイルのピン配置がほかのファイルのピン配置と一致してないだけで、合成ツールは間違った箇所に配線して間違った動かない回路を生成します。LVSはその手の問題を正確に突き止める助けになります。

確かに、チップを完全にネットリストをトップレベルのレイアウトから抽出し、すべての機能をしらみつぶしにテストしすべてが動くことを確認すれば、シミュレーションだけで検証することはできます。しかし、チップの規模と複雑度にもよりますが、それには、何年ものシミュレーション時間がかかりますし、シミュレーションが失敗したとき、レイアウトのどこが間違っているかを見つけるのは容易ではありません。

マッチしないレイアウトのどこが間違っているかを見つけるには、マッチングアルゴリズムについてのある程度の知識が必要なので、このチュートリアルでそれを説明します。

アルゴリズム

Netgenのアルゴリズムはとてもエレガントですが、もしあなたがそれがどう動くのか理解しないと、不可解な結果を生み出します。それは、"粉砕=fracturing”という手法で動作し、一連の繰り返しの段階から成り立っています。最初の段階では、(どっちがどっちということはなく両方の回路で)設計に含まれるすべてのものが、すべての素子のリストと、すべてのネットのリストのグループに集められます。そして、それぞれの素子のそれぞれのピンには(設計のなかのその素子のすべてのインスタンスの同じピンが同じ値を持つように)ランダムな識別値がつけられます。それぞれの素子タイプには、ユニークな識別値が与えられます。それぞれのネットには、特定の識別値、すなわちネットのファンアウト値(それがつながる素子のピンの数)が与えられます。

素子リストはそれぞれの段階で、同じ識別値をもった素子のいくつかのリストに粉砕(”分割”)されます。そして第1段階の後で、1つの素子リストはそれぞれの素子タイプごとに別々のリストに分けられます。同様にネットのリストは同一の識別値を持った素子別の複数のリストに粉砕されます。だから第1段階の後では、1つのノードリストは、同一のファンアウトをもったネットの別々のリストに分けられます。

それぞれの素子の分割にはユニークな識別番号が振られ、ネットの分割にもユニークな識別番号が振られます。

さてここが手の込んだところです:それぞれの素子にはそれぞれのネット分割(の識別子)およびその素子が接続しているすべてのネットの識別子とを組み合わせて作られた新しい識別子が付けられます(これは、ネット分割の識別子のexclusive-orのそれぞれのピンの結果とネットの個々の識別子を足し合わせて行われます)。それぞれのネットには、それぞれの素子分割の識別子とそのネットがつながるすべての素子ピン(同じ手法を使って)のピンを組み合わせて作られる新しい識別子があたえられます。

同じ値の素子とネットを粉砕する分割のステップのところから繰り返します。それぞれのステップでそれぞれの分割に含まれる素子とネットの数は著しく少なくなります。もしも2つの回路が等価なら、すべての分割には正確に2つの素子とネット、1つは最初の回路のもの、もう一つは第2の回路のものが含まれる、という最終結果になります。

回路には区別のつかない複数のインスタンスが含まれる場合もあることに注意してください。回路がほかのものと完全に見分けがつかない場合、何回繰り返しても同一の分割に終始します。これらは自己同型("automorphisms")と呼ばれます。これらは、分割のなかの一対の素子に特定の識別子を与え、それらをそれら自身の分割とし、すべての素子とネットがユニークに認識されるまで続けることで処理できます。

粉砕アルゴリズムは、非常に高速で効率が良いですが、回路全体の構造を本当に理解しているわけではないという深刻な欠点を持つことを理解することは重要です。LVSツールには、設計者にマッチしない回路について修正するためにどういう変更が必要かを教えようとするツールもあります。エラーが単純なものでない場合、何がおかしいのかを見つけるのはしばしば非常に困難です。このチュートリアルの目的は、1つのエラーを選び抜きほかの本質的でない情報を無視するにはどうすればよいかを示すことです。2、3の単純な戦略により、もっとも恐ろしくずたずたになった設計でもなんとか迅速に問題を修正できます。

NetgenはLVSを階層的に実行できます。これは(全体チップのような)非常に大規模な回路に対し有益で、回路全体をフラット化する必要性と手に負えないくらいの大量の出力結果の生成を防止します。比較している回路の中で等価なサブサーキットに対し明らかに対にできるそれぞれのサブサーキットを、サブサーキットのレベルで一致させることができます。それらの回路が一致するなら、比較は階層の次のレベルに移動し、そこではそのサブサーキットのすべてのインスタンスはピンをもった個別の素子として扱われます。

もしもサブサーキットにもう1つの回路にマッチするものがなければ、つまりサブサーキット間の比較が失敗なら、サブサーキットの中のそれぞれのインスタンスは親のセルに取り込まれ、そのサブサーキットは除去されます。2つのネットリストはピンの順序が異なるサブサーキットを定義しているかもしれないので、ピンのリストはお互いにマッチしなくてはなりません。ピンをマッチできない場合というのは、サブサーキットの内容を展開するもう1つの理由になります。

回路図とレイアウトからネットリストを生成する

Nextgenは多くの異なるツールのネットリストを入力にすることができます。基本のフォーマットはSPICEですが、素のBerkeley版SPICE3のシンタックスを拡張したよくある多くのものを受け入れます。とても多くのそのほかのネットリスト形式も知っていますが、基本のデバイスの記述が完全でなかったり、素子のプロパティの解釈が理解できなかったり、階層を扱えないものもあります。

このチュートリアルの目的に合わせて、ここでは XCircuitQflow (ネットリストは自動生成される)の回路図から生成されるネットリストと Magicというレイアウトツールから抽出して生成されたネットリストを用います。

チュートリアルは以下のファイルを使うので、今すぐか必要になったときにダウロードしてください:

ファイル "map9v3.spice" は magic レイアウトツールを使って Qflow(実際はqflowの前身のツール)のverilogソースから合成されたVLSI設計のネットリストです。デジタル回路は、比較的小さくnetgenのさまざまな機能をデモするのに適しています(その回路がどう動くかわかるでしょ!)。残りのファイル"map9v3_testn.spice"は、もともとのネットリストを手で変更したもので、LVSエラーの原因を見つけいかに修正できるかを示すために意図的にネットリストをだめにしたものです。"map9v3_synth.spice は、それとは別に合成されたネットリストから作られたもので、レイアウト(配置と配線)を生成する以前のものです。合成ツールはロジックゲートのレベルで(トランジスタレベルではなく)動作するので、ネットリストはロジックゲート名だけを含み、それで"osu035_stdcells.sp"のファイルには、それぞれのロジックセルの内容の記述を含めています。

LVSの設定

比較のアルゴリズムはネットリストのトポロジー、つまり設計の中の様々な素子の接続関係だけを理解します。SPICEは確立されたネットリスト形式なので、SPICEのネットリストではLVSシステムは、例えばトランジスタとキャパシタと抵抗を区別できるように、素子について少しよく理解しています。これらのSPICE形式で確立された外部ピンを持つ低レベルの素子は、基本素子と呼ばれます。SPICEは、トランジスタやそのほかの素子の定義の詳細についてはネットリストに記載せず、それらをモデル名で指定します。モデル名は、素子のデフォルトのプロパティを定義するモデル定義を参照します。モデル定義は、どこかほかの(例えばシミュレーション用の完全な)SPICEネットリストの中に見つけることができます。多くのシステムでは、モデルは別のファイルに置かれてシミュレーションの前にネットリストに追加される仕組みになっています。これは、ネットリスト比較にとっては、良いことでも悪いことでもあります。良い面では、回路図から持ってきたネットリストと、レイアウトから持ってきたネットリストが同一の素子に対し同一のモデルを参照しているなら、モデル名を使って素子を比較するのが容易です。しかし、もしも回路図とレイアウトが別のモデル名を使用している場合は、ネットリスト比較プログラムに追加の情報を与えなくてはなりません。そのためにLVSは設定ファイルを使用します。回路図とレイアウトから持ってきた素子モデル名が同じで、サブサーキット名が同じで、階層も同じなら、すべては単純で、設定ファイルは不要です。それより何かが複雑な場合は、以下に説明するように設定ファイルが必要です。

Netgenの設定ファイルの概念は非常にシンプルです。設定ファイルは、netgenのコマンド入力にあらわれるコマンドそのものを含んだファイルにすぎません。ファイルは、ほかのTclスクリプト同様sourceされるので、Tcl/Tkのコマンドとnetgenのコマンドも同じく設定ファイルで使用できます。

最初にこのチュートリアルでは、複雑な例の前に、設定ファイルを必要としない、いくつかの簡単な例をざっと見てみます。

LVSの実行

簡単な例から始めます。bufferA.spicebufferB.spiceをダウンロードしてください。このチュートリアルのすべてのファイルと同様、これらはspiceネットリストです。自分の好みのエディタで両方のファイル例を調べてみてください。2つのファイルのフォーマットにはいくつもの違いがあります。bufferA.spice は、Magicのレイアウトから抽出されました。Magicでは、なんらかの歴史的な理由で、トランジスタ素子を1000から番号付けし、トランジスタの面積と周辺長の情報を付加するのでシミュレーションの精度が向上します。bufferB.spice は、回路図入力ツールで作られたか、もしかしたら手で書かれたものかも知れません。改行文字とコメント行はWindows環境が使われたことを物語っています。標準的でない(つまり非Berkley SPICE的な)".backanno"というキーワードが使われています。"inverter"サブサーキットの定義で、ピンの順番は、最初のネットリストと異なっています。それには素子の幅と長さの情報は含まれますが、面積と周囲長はありません。そのようなシンタックス上の違いはあっても、これらは同一の回路を表現しています。トランジスタレベルを下の階層に持つバッファ回路の回路図を以下に示します。

Figure 1: Schematic of the buffer circuit used in the first examples.

コマンド行を使ってnetgenを起動します:

netgen

以下のようなコンソールウィンドウが出てきます:

コンソールウィンドウのプロンプトに、以下のコマンドを入力します

lvs bufferA.spice bufferB.spice

netgenが何をどうしているかを説明するいくらかの出力の後、最後に以下の行が表示されます。

Result: Circuits match uniquely.(回路は比類なくマッチします)

LVS Done(LVS終了)

これは、netgenが2つのネットリストが同一の回路をあらわしていると認めたことを意味します。出力を見返すと、いろいろなもの、netgenが不明な".backanno"コマンドをどう処理したとか、おのおののセルが1つのnFETトランジスタと1つのpFETトランジスタを含んでいるとか、ノード数と素子数のカウントとか、1つの回路のインバータのピンの順番をもう1つに合わせたなどが表示されています。

完全な出力はnetgenが出力したcomp.outというテキストファイルの中にあります。今ここでこのファイルを編集するか表示してみてください。このファイルの中では、2つのネットリストを左右に並べて比較しています。それぞれが階層的に分解されています。最初に、"inverter" サブセルが提示され、それが含む素子とそれぞれの数が見えます。次に、インバータサブサーキットだけの比較結果が存在します。それは、マッチしているという結果であり、そのあとインバータサブサーキットのピンのリストが続き、2つのファイル間で一致しています。ここで、ほとんどのピンは2つのファイルで同じ名前を持っていることに気がつきます。例外は、"bufferA"が "Gnd" をグランドノードの名前に使っているのに対し、"bufferB"のファイルは、"0" をグランドノード名に使っています。

インバータサブサーキットのピンリストに続いて、トップレベル回路に対する出力が繰り返されています。おのおのの回路の素子がそれぞれの数とともに表示されています。この場合、素子としては1つのタイプ、”inverter"サブサーキットがあるだけで、おのおののファイルにはそれぞれ2つのインスタンスが存在します。2つの回路の比較結果が続きます(回路が完全に一致するので、これも大変短いものです)。トップレベルの回路にはピンは無いので、ファイルの最後の部分に、トップレベルセルに対するピンリストがマッチするとは書いてません。これは、完全に一致する一対のネットリストの例であり、このような情報が最小限に少ない出力はLVS実行の望ましい目標です。2つの回路に関わるエラーの数が増えるだけ、"comp.out"ファイルの出力量も通常指数的に増えます。マッチしてない回路からの大量の出力にどう対処するかを示すのが、このチュートリアルの主要な目標です。

netgenを終了するには、コンソールのプロンプトに"quit"と入力するか、コンソールのプルダウンメニュから"File->Quit"を選んでください。

バッチモードのLVS

ちょっと余談ですが、このチュートリアルではすべてのセッションをコンソールウィンドウで表示していることに気づいて欲しいですが、netgenをバッチモードで実行することは可能(だし、しばしば望ましい)です。バッチモードスクリプトの簡単な例として、上のダウンロードボックスから"runlvs.sh"というshellスクリプトファイルをダウンロードしてください。そのスクリプトは38バイトの長さです。それが実行することは、netgenを "-noconsole"オプションで実行し、コマンド行から2つの引数を受け取り、それを、あたかも上記のセクションでコンソールにタイプ入力したようにnetgenの"lvs"コマンドの引数に渡すことです。このshellスクリプトを現在のワークディレクトリに置いて、パーミッションを実行可能に設定してください。端末のshellのプロンプトに対し、以下を実行します:

runlvs.sh bufferA.spice bufferB.spice

すると、出力が端末に送られること(したがって例えばログファイルにリダイレクトできます)を除いて、前と同じ結果を得ることができます。そして、最後にnetgenは終了し、shellプロンプトに戻ります。このバッチスタイルのnetgenの実行は、対話的なコマンドを使わないチュートリアルのどの例でも使用可能です。

LVS結果の解釈

完全にマッチしたネットリストは申し分なく良いものですが、LVSで重要なのは、2つの回路がマッチしないときの出力をどう解釈し、ネットリストをマッチさせるために何を修正すべきかを理解することです。

前のステップからbufferA.spicebufferB.spiceのファイルはすでに手元にあるので、ここでbufferBx.spiceをダウンロードしましょう。2つのファイルbufferB.spicebufferBx.spiceを見較べると、bufferBx.spiceファイルから".global Vdd 0"という行が欠落している以外は同じだとわかるでしょう。このファイルでは0Vddのノードがグローバルであることを宣言し損なったので、インバータサブサーキットで使ったこれらの名前は、これらのノードはサブサーキット内でローカルということになります。トップレベルに同じ名前のノードが存在する事実には、意味がありません。これらのノードはFET素子のバルク端子(例えばnetのサブストレートやpfetのn-well)を定義しています。

SPICEファイルで使われるノード 0 は、一般にグローバルと見なされます。しかし、netgenは異なったフォーマットを扱うので、またそのほかのフォーマットではノード 0を暗黙的にグローバルとするということはないため、そのような一般化はしていません。ネットリストで、ノード0を使っているにも関わらず、明示的にグローバルと宣言してない場合、最良の戦略は、設定ファイルでnetgenのノード0をグローバルだと設定することです。

好みのエディタを使って"setup.tcl"というファイルを作成し、以下の行を追加してください:

global bufferBx.spice 0

global bufferBx.spice Vdd

さてそこで、netgenを実行し、プロンプトで "lvs bufferB.spice bufferBx.spice" とタイプ入力してください。2つのネットリストは等価であるという出力が表示されるはずです。ファイルに無かった".global"行は、設定ファイルのグローバル宣言が面倒を見てくれました。

netgenを終了し、setup.tclファイルを削除してください。netgenを同じコマンド"lvs bufferB.spice bufferBx.spice"で再度実行しましょう。今回の出力は以下です:

Result: Graphs do not match.

マッチしない理由は、わかっていますね、2つのノード Vdd0がローカルノードとして扱われたからです。このことはnetgenの出力からどのようにわかるでしょうか?

出力ファイルcomp.outを見てください。2つのインバータ回路はファイルの最初の数行で比較され、マッチしていると明言されています。単一のサブサーキットの中では、ノードがローカルかグローバルかを知ることは不可能です。netgenのやり方ではグローバルノードをサブサーキットの中ではローカルと扱いますが、親の回路にはサブサーキットに追加するピンを通じてそれらを渡します。comp.out出力には、サブサーキットがマッチするとの記述のあと、2つのサブサーキットのピンのリストが存在し、それらはお互いにマッチしています。

ここで、"bufferB.spice"回路のグローバルノード("Vdd"と"0")は、サブサーキットのポートに変換されていることがわかります。一方、bufferBx.spiceには等価なピンがありません。これが最初の手がかりであり、この情報だけでも問題のデバッグはできます。それでも、出力ファイルも見てみましょう。

netgenが、2つのネットリストでサブサーキット"inverter" のすべてのピンのマッチに失敗した後、サブサーキットは親回路にマージ、いいかえれば親回路の階層を部分的にフラットにします。なぜそうするかといえば、回路設計ではしばしば、レイアウトまたは回路図には余分の階層が含まれる、すなわち異なる階層構造が存在するからです。回路は正しくても、階層のすべてのレベルですべてのサブサーキットが正しい(同じ)とは限りません。サブサーキットがマッチしないときは、回路を選択的にフラットにすることで、階層マッチをあきらめることなくnetgenはそのような構造の違いをうまく扱います。ネットリストのあちこちでグローバルノードが使われているがグローバルとは宣言されてない場合、ネットリストマッチングの最後には、回路は完全にフラット化されることもあります。

この出力では、最初の"Subcircuit summary:"に、2つの回路の名前(いまやトップレベルなので、回路名は、ファイル名と同じになる)と、素子(部品)のリストが得られます。インバータサブサーキットは部分的にフラットになっているので、そして、それぞれのトップレベル回路には2つのインバータが含まれるので、それぞれのフラット化されたネットリストは2つのインバータ、さらに2つのpfetと2つのnfetということになります。そのリストの後ろには、素子数とそれぞれのセルに含まれるノード(ネット)の総数が表示されます。エラー解明の第2の手がかりは、回路2は9つのノードであるのに対し、回路1はたった5つのノードしかないことです。

メインの診断出力は、回路summaryの後に続きます。それは2つのセクションに分かれています:最初は、"Illegal element partitions"リスト、次は、"Illegal node partitions"のリストです。2つの回路で、1対1マッチができなかった素子はすべて、最終的にひとつまたは複数のillegal element partitionになり、1対1にマッチできなかったノードは最終的にすべてひとつまたは複数のillegal node partitionになります。

それぞれのパーティション(素子またはノード)は、素子/ネットのリストを、左が回路1のもの、右が回路2のものというように持っています。このリストの中では、順番には意味が無いということを理解するのは重要です!左側のリストの最初の項目は右側のリストの最初の項目に対応するとは思わないでください。(それはそれとして、分別のある2つのリストのマッチングのためにnetgenがなんらかのヒューリスティック手法を使う可能性はありますが、これは将来リリースされるプロジェクトでの話です。)

一般的に、素子のパーティションの情報は、一番役に立ちませんが、とはいえそれが何を意味するのかここで説明します。最初のパーティションの出力を見てみましょう:

最初の行は、素子名です。階層はフラットにされたので、その名前には、その素子が現れるサブサーキットの名前を含んでいます。この場合、その名前は2つの回路で同じです。素子のモデルは"nfet"で、そのサブサーキットを呼び出しているSPICE行のインスタンス名は"XU2"です。この素子は"inverter"サブサーキットの中にあり、SPICE行ではインスタンスは"X1"でした。それぞれの名前は、モデルまたはサブサーキット名とインスタンス名を中に含みます。この命名法はnetgen特有のものですが、誰でもそのインスタンスがSPICEファイルのどの行からきているかを見つけることができるくらい明快です。

素子名の後に、netgenは素子のそれぞれのピンのファンアウト数を出力します。ファンアウトのリストとは、そのピンにつながっている素子のピンの総数で、自分自身を含みます(同一の素子の複数のピンでは別々にカウントされます)。ですから、最小のカウントは1であり、もしも素子のファンアウトとして"1"が表示されていれば、それはほかのどこにも接続されていないピンが存在することを意味し、ほとんど常にそれはエラーです。手がかりの3は次の通りです:2つ目の回路のillegal element partitionリストで、回路内のすべてのFET素子の"bulk"ピンのファンアウトが"1"ということは、それぞれの素子で"bulk"はどこにも繋がれていないことを意味し、これは明らかなエラーです。

"(drain,source) = (4,2)"の意味を簡単に説明します:FET素子は "source" と "drain"という2つの端子を持っていて、普通ソースは素子の上で電源供給線に近い側(nFET素子ではグランド、pFETでは電源)です。物理的に、VLSIのレイアウトでは、標準のFET素子は完全に対称なので、"source"と"drain"という用語はほとんど象徴的なもので、なぜならそれらは電気的にも機能的にも全く同じだからです(特別なFET素子には、ソースとドレインで属性が違うものがありますが、それは関係無い話です)。回路の構造や、電源がどちらかについての知識がなくては、素子のどちら端がソースかドレインかを、回路抽出プログラムは決めることはできません。

素子は対称なので、素子のどちら端が”source"でどちらが"drain"と呼ばれようがどちらでもよいことです。それゆえ、これらの2つのピンは"permutable"(入れ替え可能)と呼ばれます。netgenには、"permute default"というコマンドがあって、それは"lvs"という手続き(ないしはコマンド)のスクリプトの一部として実行されます。このコマンドは、netgenに対し、すべての抵抗の両端と、"nfet"と"pfet"と呼ばれるすべての素子のソースとドレインピンを入れ替え可能であると指示します。

そのコマンドが発行されると、片方の回路のトランジスタの上端がソースにまた下端がドレインに接続され、他方の回路の等価なトランジスタで、下端がソースで上端がドレインに接続されていても、両者はマッチします。このチュートリアルの後の方で、"permute"コマンドのそのほかの使用例やピンの入れ替え可能性全般について見てみます。さて、出力の話に戻ると、"(drain,source) = (4,2)"という行は、この素子では、"drain"と"source"は入れ替え可能なピンであることを意味します。netgenは、どちらがどちらとはわかりませんが、どちらかのファンアウトが4(他の3つの素子に接続していて、自分を含めると4)であり、もう一つのファンアウトは2であることは知っています。だから、このあいまいさを記述するために、上記のシンタックスを用いてファンアウト数を書き出しています。

さて、illegal node partitionの出力を見てみましょう。これは、一般にエラーを特定するためにもっとも有用です。ここで、最初のパーティションは以下の出力で始まります:

Net: Vdd

pfet/(drain|source) = 2

pfet/bulk = 2

Net: Vdd

pfet/(drain|source) = 2

おのおのの出力のブロックの最初の行は"Net:"により、ネット名を与えます。その後、素子のパーティションの出力と同じようなファンアウトが続きますが、ファンアウトリストのそれぞれの項目が素子のタイプ(インスタンスの指定はありません)とその名前のネットにつながるピンという点が異なります。ここで、"Vdd" というネットはドレイン(またはソース)と回路1の中の2つのpFET素子のバルクにつながっていて、それは回路2では2つのpFET素子のドレイン(またはソース)だけにつながっています。明らかに、回路2の中では、VddはpFETのバルク端子にはつながっていません。これがまさに問題です。これが最後で最終の手がかりであり、すべての手がかりはバルクの接続が切れていることを示しており、それはVddに対しグローバル宣言が欠落していることに帰着できます。

ノードパーティションの出力で、もしも素子の2つかそれ以上のピンが入れ替え可能なら、それらはカッコのなかに、OR論理という意味で"|" で区切って、上記の出力では "pfet/(drain|source) = 2"のようにリストアップされることに注目してください。この構文は、そのネットは2つのpfetのピンに接続され、そのおのおのはドレインまたはソースに接続されていることを意味します。

素子とネットについての詳細情報を得るには

すべての手がかりが与えられても、エラーがどこにあるのかわからない場合を想定します。 comp.out のファイルは、問題のある素子とノードのパーティションについて、全部の情報を含んでますが、すべてについて完璧に記述しているわけではありません。例えば、素子はそれぞれのピンのファンアウト数をリストしますが、何という名のネットがそれぞれのピンに接続されているかは示しません。ネットは、そのネットに接続する素子のファンアウト数をリストしますが、それらの素子のどのインスタンスが接続されるかは特定しません。

LVSを走らせた後でnetgenのコンソールウィンドウがまだ開いているなら、これらのことを、netgenのコマンド行から問い合わせることができます。出力ファイルには、回路2の "Instance: inverterX1/pfetXU1" のコラムに"bulk = 1"とあります。これは、分離したノードを示しています。もしもこの素子についての詳細な情報が欲しいなら、コンソールに次のようにタイプします:

nodes inverterX1/pfetXU1 bufferBx.spice bufferBx.spice

"bufferBx.spice"は、トップレベルのセルの名前であると同時に回路2のファイル名でもあるので、上記の行には2回現れることに注意してください。このノードについての質問に対する出力は、以下の通りです:

Element 'inverterX1/pfetXU1' Pins:

Pin 1 (drain) = Vout

Pin 2 (gate) = N001

Pin 3 (source) = Vdd

Pin 4 (bulk) = inverterX1/Vdd

欲しかったすべての情報がここにはあります。この特定の素子のインスタンスのバルクの接続先は、"inverterX1/Vdd "です。このケースの場合"Vdd" という名前の前にインスタンス名がついているので、ノードは"Vdd"そのものとは違います。それは、"inverterX1"というインスタンスにローカルなノードです。

ノードに、それに繋がるすべての素子について、問い合わせることもできます。ノード"inverterX1/Vdd"にそのほかの素子のピンが接続してないかを調べるには、次のようなコマンドを使うことができます:

elements inverterX1/Vdd bufferBx.spice

出力は以下のようになります:

Node 'inverterX1/Vdd' in cell 'bufferBx.spice' connects to:

inverterX1/pfetXU1/bulk

これは、"inverterX1/pfetXU1"のバルク接続には、何もほかのものが接続されてないこと(このことはすでにcomp.outファイルの中で、この接続のファンアウトは1と明言されてる)を示しています。

"nodes"や"elements"コマンドで表示されるネットリストは、LVSが終了したときの最後の状態を反映しています。マッチしなかったためネットリスト比較の過程でフラットにされたセルについても問い合わせできます。例えば、以下のコマンドを使ってみましょう:

nodes pfetXU1 inverter bufferB.spice

そうすると結果は:

Element 'pfetXU1' Pins:

Pin 1 (drain) = out (port of inverter)

Pin 2 (gate) = in (port of inverter)

Pin 3 (source) = pos (port of inverter)

Pin 4 (bulk) = Vdd (port of inverter)

一方、以下のコマンドを実行すると

nodes pfetXU1 inverter bufferBx.spice

結果はこうなります:

Element 'pfetXU1' Pins:

Pin 1 (drain) = out (port of inverter)

Pin 2 (gate) = in (port of inverter)

Pin 3 (source) = pos (port of inverter)

Pin 4 (bulk) = Vdd

これは、トランジスタのバルク接続はグローバルノードかcellのポートでなくてはならなかったのですが、実はローカルノードだったということを示す別の方法です。

マッチしないエレメントの数

最後のネットリストのまま続けて、素子数がマッチしない場合の出力を見てみましょう。 "bufferB.spice"のネットリストを編集し、最後にといっても".end" 行の前ですが(つまり、インバータサブサーキットの中ではなく、必ずトップレベルセルの中に定義するよう注意して)、以下の行を追加してください:

MXU3 Vdd Vdd Vdd Vdd pfet W=1.8u L=0.6u

これは典型的なダミートランジスタであり、別々のトランジスタのマッチング特性を

改善するためにレイアウトのアレーや差動対に加えるものです。それらを回路図に描き忘れることはしょっちゅうありますので、そのためにネットリストがマッチしない原因になることを理解するのは意味があります。ネットリストを修正してnetgenを再度起動し、"lvs bufferA.spice bufferB.spice"というコマンドを入力します。

今度は、エラーについての手がかりが出力ファイルcomp.outに2つ存在します。最初は、トップレベル回路のサマリーにあります:

inverter (2)

(no matching element)

Number of elements: 2 **Mismatch**

inverter (2)

pfet (1)

Number of elements: 3 **Mismatch**

これは、何が起きたかを明確に示します:サマリーは両方の回路が2つのインバータを持つことを示しますが、回路2にはさらに回路1には存在しない"pfet"というものが存在します。繰り返しますが、このエラーは、illegal element partitionリストと、illegal node partitionリストの両方に現れています。element partitionリストは"(no matching instance)"の表示とともに、余分のpfetを表示し、一方回路1には、インスタンスの名前("pfetXU3")が表示されていますので、我々は、ネットリストファイルの中の"XXU3 ... pfet ..." という行を注視するよう仕向けられます。illegal node partitionからは、Vddネットはpetのドレイン(ソース)、ゲートとバルクに接続することがわかり、ダミートランジスタの存在とつじつまがあっています。

混在した階層の例

最初の例で、ネットリストで、サブサーキットを選択的にフラットにしましたが、それは、同一のネットリストを表現しているにもかかわらず、片方の回路の階層構造が他方と異なるような、階層が混在した回路でマッチングを正しく確認するためでした。

hier1.spicehier2.spiceの回路は、混在した階層とは何かを示しています。まだなら今2つのファイルをダウンロードしてください。この回路は前の例と同様、単純なバッファーです。しかし、hier1.spiceを見ると、それにはもう1階層"buffer"というサブサーキットが定義されトップレベルでインスタンス化されていることがわかります。hier2.spiceにも"buffer"サブサーキットは定義され、トップレベルでインスタンス化されていますが、そこには追加のサブサーキットとして"inverter"は定義されておらず、その代わりに2つのインバータを4つのトランジスタからなる回路として実現しています。

netgenを起動し、"lvs hier1.spice hier2.spice"コマンドを実行してください。netgenは2つの回路はマッチしていると宣言することがわかります。"comp.out"の出力の中を見れば、サブセルである"invert"についての比較は全く含まれてないことが見て取れます。ファイルの先頭の行は、次の通りです:

Flattening unmatched subcell invert in circuit buffer(buffer回路でマッチしなかったサブセルinvertをフラット化する)

netgenが2つのネットリストファイルを読み込むと、回路図とレイアウトは(トップレベルセルは別として)回路階層の全体で同じ名前を使っているだろうという想定のもと、サブサーキットを名前によりマッチしようとします。通常これは妥当な想定です。それがそうでない場合どうするかを次のチュートリアルで扱います。この例の場合、netgenは両方のネットリストで"buffer"という名前のサブサーキットを見つけ、それらがマッチするに違いないと想定します。しかし、片方のネットリストには"invert"というサブサーキットが存在し、他方には存在しません。それにはマッチするものがないということで、静かに"invert"サブサーキットだけをフラット化しbuffer回路の比較を継続します。

マッチしないサブセル名の扱い

機能的に同じセルに、回路図とレイアウトで別の名前が付けられることは時々あります。単に片方が小文字で他方が大文字というケースも多いです。SPICEでは、大文字と小文字の区別はなく、それらは同じ名前とみなされる。Netgenは、比較対象の両方のセルがSPICEネットリストの場合、大文字小文字の問題を無視します。しかし時々は、回路図とレイアウトの間で、セルや機能素子に別の名前が付けられる場合があります。

map9v3.spicemap9v3_test2.spiceという2つのネットリストの場合を見てみましょう。ダウンロードがまだならダウンロードしてください。map9v3.spiceセルは、これから3つの例で使用します。これはもともとverilogのソースコードから作られたスタンダードセルのレイアウトを元にしています。この例では、ネットリストの両方ともレイアウトから作られていますが、このチュートリアルのために2つ目は手で編集しています。

まず、好みのエディタで2つのファイルの中身を見てください。これらはほとんど同じですが、2つ目のネットリストでは、すべてのセル名が別の名前に置き換えられ、さらにエラーが一つファイルに挿入されています。

注意:このチュートリアルのもともとのバージョンでは、名前に小文字対大文字を使いました。SPICEネットリストフォーマットは大文字と小文字の区別をしないので、netgenはversion 1.4.55(2014年2月)から両方のファイルがSPICEフォーマットの場合、名前の大文字と小文字を区別しないよう変更しました。このバージョンとそれ以降では、netgenは、例えば片方のネットリストでセル名"NAND2"は他方のネットリストでセル名"nand2"とマッチします。

netgenを起動して、コマンド"lvs map9v3.spice ap9v3_test2.spice"を入力してください。この結果は、"Graphs do not match(グラフはマッチしません)"です。ここで、comp.outファイルをよく見てください。一番上にすべてのセルがフラットにされた長いリストがありますね。LVSの実行時間がとても長かったことにも気がついたかも知れません。何が起きたかというと、netgenはどの大文字名も小文字名にマッチするとは考えませんでした。サブサーキットを名前でマッチさせないということで、比較の前にすべてをフラットにし、トランジスタレベルでネットリスト比較を行ったのです。ファイルの最後の方に2つのネットリストの内容のサマリーが見えますが、ネットリストをいくつものスタンダードセルの集まりとは表示せずに、多くの数のトランジスタの集まりとして表示しています。2つ目のファイルに挿入したエラーは、内部ネットの名前を変えるというちょっとしたものだったのですが、階層がたった深さ2だったので、出力の解釈はとても簡単でエラーを見つけるのも簡単でした。しかし、何万トランジスタもの回路で複雑なエラーをたどることを想像してみてください!

ところで、comp.outの出力からmap9v3.spiceファイルには"OAI22X1_3/Y"というたった1つのネットワークがあり、それは明らかにmap9v3_test2.spiceの中の2つのネットにマッチします。2つ目のネットリストでは、意図的にその中の1つのネットが2つに切り離されており、そのため、これらの2つのネットはつなぎ直さなくてはならないと結論づけることは極めて簡単です(このネットリストは手で編集したものなので、ネットリストを修正する正解は"BADNODE"というネット名を "oai22X1_3/Y"に変更することです)。

このようにnetgenはセル名をマッチしてくれません。これについてどうしましょうか?ここで設定ファイルが非常に役に立ちます。setup.tcl.saveというファイルのダウンロードがまだならダウンロードしsetup.tclにコピーしてください。このファイルを開けてみてください。それは"equate classes"といういくつかのコマンドの集まりで、それぞれの行は最初のネットリストでのセルの名前付けと2つ目のネットリストでのセルの名前付けです。これはコマンド上に示された2つのセルは可能性として同一であることをnetgenに示唆しています。こうすることで、親のセルにフラット化されるのではなく、2つのセルがお互いに比較されるようになります。

setup.tclファイルを正しく置いて、netgenを起動し、同じコマンド"lvs map9v3.spice map9v3_test2.spice"を実行してください。comp.outファイルを良く見てください。特に"Flattening"という単語を探してください。見つからないでしょう。このことは2つのことを意味しています:netgenはそれぞれの回路のそれぞれのサブセルをマッチさせることができたこと、また(あなたが修正してないとすれば)エラーはサブセルの中にあるわけではないこと(そうだとするとサブセルはマッチしないことになり、フラット化を強いられることになる)。

netgenの実行速度が相当速くなったことにも気がついたかも知れません。ファイルの最後を見ると、それぞれのネットリストの中身はスタンダードセルの集まりでありトランジスタではありません。エラーはもちろん同じで、解決法も同じですが、出力からエラーは階層のトップレベルにあり、サブサーキットの中にはないことは明白で、これはエラーを見つけ修正するのに役立つ1つの真実です。

おすすめの良い練習があります:(1)ネットリストのエラーを訂正し、netgenに"Graphs match uniquely"というメッセージを出力させ、(2)手でサブセルにエラーを挿入し出力にどういう影響が出るか調べる。例えば、map9v3_test2.spiceの中の1つのサブセルの適当なノードの名前を"BADNODE2"に変える。すぐにcomp.out出力ファイルのエラー出力が、以前よりもずっと増えることに気がつくでしょう。なぜなら、サブサーキットが間違っているところで、そのエラーはサブサーキットのインスタンスのすべてで複製されるからです。

netgenでは2つのネットリストのサブサーキットの比較が成功しないとき、すべてのインスタンスが展開されてトップレベルのセルでエラーが複製されます。そういうエラーの原因を突き止めるとき出力ファイルの中で、最初に" ILLEGAL node partitions"が起きている場所を見つける必要があります。この出力は、サブセルの1つで作られていることに気付いているならば、サブセルのエラーこそ最初に処置(修正)しなくてはならないことを示唆しています。そうすることで、トップレベルのセル比較による大量の出力との苦闘を回避できます。

最初にトップレベルセルの出力を見ているなら、2つの回路の出力に低レベルの素子 "nfet" と"pfet"が現れていることに上手に気づかされるでしょう。どちらの回路もスタンダードセルから作られているのですから、これらの低レベルの素子の存在は、サブセルで何かエラーが発生したためにサブセルがフラット化されたという警告に他なりません。

トップレベルで混在した階層

手で編集したよりはもっと現実的な、めったに無い訳ではない例があります。ネットリストファイル "map9v3_synth.spice"とライブラリファイル "osu035_stdcells.sp"をダウンロードしてください。verilog(ハードウェア記述言語)からデジタル回路を合成する際に、合成のプロセスでは最初にネットリストを生成し次にレイアウトを生成します。以前既に、合成したレイアウトからネットリスト抽出して作られたネットリストを見ました。ここでは、合成ツールから生成されたネットリストから直接に変換された回路を用います。netgenを起動し、"lvs map9v3.spice map9v3_synth.spice"というコマンドを実行します。Netgenは、セルをボトムアップに比較して、comp.outファイルを出力します。しかしコンソールあるいは端末にプリントされる最後の出力は:

Contents of circuit 2: Cell: 'map9v3_synth.spice'

Cell map9v3_synth.spice contains 0 instances.

"map9v3_synth.spice"セルにはいろんなものが入っているようなので、この結果は少し奇妙に見えます。しかしこのファイルをよく見ると、回路は"map9v3"というサブサーキットを含むにもかかわらず、どこにもインスタンスがありません。つまり、そのファイルには、"X"で始まり "map9v3"で終わる行が存在しないのです。このファイルには、まるでそれを含むライブラリファイル("osu035_stdcells.sp")のように、そこにはサブサーキットは定義されているが実際の回路自身は含まれない(インスタンス化されてない)のです。

しかしここで本当にやりたいのは、 "map9v3.spice" のファイルの中のトップレベル回路と "map9v3_synth.spice"ファイルに定義されているサブサーキットを比較することです。それを行う1つの方法は、2番目のネットリストファイルから".subckt ..."という行と".ends"という行を取り除くことでしょう。しかし、ファイルの中身を変更せずに比較を実行するより簡単な方法があります。netgenを再度起動し、今回は"lvs map9v3.spice {map9v3_synth.spice map9v3}"というコマンドを実行します。今回は、適正な比較が行われます。そして2つのネットリストはマッチしないことがわかります。なぜだかわかりますか?

第1のヒント:"ILLEGAL node partition"の最初にリストされた2つのネットを良く見てください。

第2のヒント:合成されたロジック回路は、行の形に配置され、配線プログラムにすべての行の間に電源とグランドを接続するよう誰かが指示しなくてはなりません。

しかし、この練習の主要な点は、2つの名前の Tcl リスト"{filename cellname}"はnetgenにファイルfilenameの中の特定のサブサーキット名cellnameに対して比較を行うよう指示しているということです。このサブサーキットは実際階層の深いところに存在する回路かも知れません。あなたは、例えば、netgenを起動してコマンド "lvs {map9v3.spice BUFX2} {map9v3_synth.spice BUFX2}" を実行し、"BUFX2"という名前のサブセルについてだけの比較結果を得るかも知れません。

注記:Tclの"tkcon"コンソールウィンドウで、{filename cell name}のリストは、中かっこのかわりに引用符で定義しても構いませんでした、なぜならそれはTcl/Tkでリストを指定する別の方法ですので。しかしバッチファイルで実行する場合は、Tclのリストをshellにより変更されない方法で指定することはちょっと危険かも知れません。バッチモードの"runlvs.sh" コマンドでファイルとセルの両方を指定する正しいやり方は、次の通りです:

runlvs.sh map9v3.spice "{map9v3_synth.spice map9v3}"

素子パラメータの不一致

"map9v3_test.spice"ファイルをダウンロードしてください。"setup.tcl"ファイルがまだ正しい位置にあることを確認してください。netgenを起動し、"lvs map9v3.spice map9v3_test.spice"コマンドを実行します。以下が、正しい出力です:

Result: Circuits match uniquely.

The following cells had property errors: BUFX2

LVS Done

この出力を解釈すると、2つのネットリストの構造は同じですが、ネットリスト中の素子(1つまたは複数)には2つのネットリストでプロパティの異なるものがあります。プロパティとは、トランジスタの幅や長さ、抵抗やキャパシタの素子値などのように素子に渡される値です。

Netgenはトランジスタの幅と長さのようなほとんどの標準的なパラメータや、2つのネットリストで名前が一致するパラメータを構文解析します。Netgenは、片方のネットリストには現れるが他方には現れないパラメータについて、欠落したパラメータはネットリスト比較に関係ないものとみなして無視します。

このnetgen実行結果のファイルcomp.outを見て下さい。コンソールウィンドウにあらわれるproperty errorsの警告は、comp.outファイルの中で "Property errors"という文字列を見つけよという合図だと思ってください。その通りにすれば、エラーの説明のすべてがわかります:

Circuits match uniquely.

Property errors were found.

Graphs match uniquely.

There were property errors.

nfet1003 vs. nfet4:

width circuit1: 4e-06 circuit2: 2e-06 (delta=5e+01%, cutoff= 1%)

このエラーは"map9v3.spice"回路の"BUFX2"セルの"nfet1003"トレンジスタの幅が4umなのに対し、マッチした"map9v3_test.spice"回路の"bufX2"セルのトランジスタ"nfet4"の幅は2umであることを、正確に指摘しています。残りの文章は、差異が50%(最初の回路のトランジスタは2つ目の回路のトランジスタの50%の幅)であり、ネットリスタは1%の切り捨て基準である、つまり幅の違いが1%以下なら無視する(マッチしたとみなす)と言っています。この切り捨て基準は、測定におけるほんのすこしの違い、例えばまるめたトランジスタやスケーリングにおける丸め誤差、を避けるために必要です。

これらのエラーは、ネットリストで追跡できます。SPICEネットで、"map9v3.spice"ファイルの10行目のように"nfet1003"の素子は、トランジスタ登記は"M1003"で素子モデルは"nfet"です:

M1003 Y a_10_30# gnd Gnd nfet w=4u l=0.4u

+ ad=8.8p pd=18.4u as=4p ps=10u

一方"nfet4"素子は、"map9v3_test.spice"ファイルの7行目で、素子モデル"nfet"のトランジスタ登記は"M4"です:

M4 Y a_10_30# gnd Gnd nfet w=2u l=0.4u

"map9v3.spice"ファイルには、それぞれのトランジスタについての追加の情報である、トランジスタのソースとドレインの面積と周囲長が含まれていることに注意してください。これらは一方のファイルには現れますが、他方には現れませんので、netgenはこれらを無視しエラーにはしません。

回路階層の自己同型(オートモルフィズム)

アルゴリズムのセクションで、自己同型(オートモリフィズム)は同一の接続関係を有する部分回路であるため、相互に見分けがつかないと説明しました。オートモルフィズムをもった回路を構成するのはきわめて容易です。例えば、2つファイルmorph1.spicemorph2.spiceをダウンロードし、中をよく見てください。内容は以下の図のような回路図に示されます:

見ての通り、2つの回路は等価ですが、同じセルで入力は異なるインバータに接続されています。ネットリストに関する限り、3つのインバータは同一で見分けがつきません。そのため2つのサブセルのネットリスト"triinvert" には多重のオートモルフィズムが存在します。これらの2つのファイルに対しLVSを実行すると、出力のレポートは以下のようになります:

Graphs match with 4 automorphisms.

Circuits match correctly.

Reordering pins on instance triinvert1

設定ファイルのそのほかのヒント

(To be completed)

大規模ネットとごちゃごちゃの出力についてのヒント

(To be completed)

Tutorial History

November 24, 2007

Placeholder created for netgen tutorial

October 8, 2012

Finally getting around to writing the tutorial. . .

November 1, 2012

Moving on to describing the examples.

email:

Last updated: October 8, 2014 at 5:43pm