TT Lab
はじめる
学ぶ 学習パス コース

ケーブルがこだまする

ケーブルがこだまする:波形検証室

TT Labで続きを見る

目標

ngspiceで実際の伝送線路モデルを実行し、Pythonで到着時刻・反射・終端・公差・数値の差を分析します。実物の計測やPCBの認証の手続きではありません。

なぜ重要なのか

速いエッジは、電源より高い瞬間電圧を作ることがあります。抵抗の位置・入力の単位・サンプルの時刻が変わると、もっともらしいグラフも別の質問への答えになります。回路条件と波形、分析コード、検証の範囲をつなげて、確認し直せる成果物を作ります。シェル・Pythonの関数/リスト/辞書・分圧の基礎が必要です。目安は75分なので、基本の60分が終わる前に+時間で延長してください(最大180分)。終了するとファイルは消えるので、別に保管してください。

ステップ

  1. 3.3Vを送ったのに5.5Vが届いた: baseline.jsonにvolts=3.3, driver_ohm=10, series_ohm=0, z0_ohm=50, load_ohm=1000000000, delay_ns=2, rise_ns=0.2, step_ns=0.02, stop_ns=14を保存してください。すべてのファイルは/root/signal-integrityの下にあります。experiment.py --model /root/signal-integrity/baseline.json --out /root/signal-integrity/baselineを実行して、model.cir・trace.csv・run.jsonを生成し、入力/TX/RXの列を確認してください。
  2. ケーブルの時計を読む: arrival.pyにfirst_crossing_ns(rows, threshold_v)を実装してください。rowsは[time_s, drive_v, tx_v, rx_v]の時間昇順のリストです。RXが最初にしきい値に届く時刻を線形補間して、nsで返します。最初の点からしきい値以上なら最初の時刻、最後までなければNoneです。baselineの波形と、小さな別のサンプルをあわせて検査します。
  3. こだまが戻ってくる電圧を予測する: reflections.pyのpredict(vs, source_ohm, z0_ohm, load_ohm)が、launch_v, gamma_source, gamma_load, rx_first_v, rx_second_vを含むオブジェクトを返すようにしてください。source_ohmはドライバーと追加の直列抵抗の合計です。入力は正の有限の数で、負荷は無限大ではない有限の抵抗です。2つ目の受信平坦部は、最初の値に次の往復の変化を足した値です。
  4. 抵抗1つでこだまを減らす: baseline.jsonの条件でseries_ohmだけを40に変えたseries.jsonを作り、--out /root/signal-integrity/seriesで実行してください。基準のファイルは残します。driver_ohm=10を含めた合計のソース抵抗は50Ωです。生成された波形で、最初の送信電圧と最初の受信電圧が異なる理由を確認してください。
  5. 同じ50Ωでも位置が違う: baseline.jsonの条件でload_ohmだけを50に変えたparallel.jsonを作り、--out /root/signal-integrity/parallelで実行してください(series_ohmは0)。tradeoff.pyのload_power(vs, source_ohm, load_ohm)は、十分に時間がたったDC状態のcurrent_aとload_wを返します。電圧V・抵抗Ωを受け取ってA・Wで返し、有限で正の条件を検査します。
  6. 代表値の外にある9本のケーブルを比べる: series.jsonを--out /root/signal-integrity/corners --cornersで実行してください。追加の40Ωは維持し、ドライバー8/10/12Ω × Z0 45/50/55Ωの9つのフォルダーとpeaks.jsonが生成されます。summary.pyのsummarize(records)は、空でない[{case: 名前, peak_v: 最大V}, ...]から、count, min_peak_v, max_peak_v, max_caseを返します。最大値が同じ場合は、辞書順でもっとも先の名前です。
  7. サンプル番号ではなく時間を合わせる: series.jsonでstep_nsだけを0.01に変えたfine.jsonを、--out /root/signal-integrity/fineで実行してください。convergence.pyのmax_difference(coarse, fine)は、coarseの各時刻でfineを線形補間し、TX/RX(col 2,3)の電圧の最大絶対差Vを返します。表は[time_s,drive_v,tx_v,rx_v]で、2点以上、時間は厳密に増加、開始と終了は同じです。実際の波形と異なる刻みの小さな表も検査します。
  8. 根拠をまとめ、限界を残す: 前のステップのファイルを保存したまま、release.jsonを作成してください。model_type=ideal_single_mode_lossless, measured=false, pcb_certified=false, target_verification_required=trueです。release.jsonの形式の例にあるsha256オブジェクトには、提供された相対パスだけをキーに使い、現在のファイルの内容のSHA-256を小文字64桁で入れます。前のステップの波形と分析も、もう一度検証します。バックアップファイルは、リストに入れません。

参考

作業フォルダーを、先にmkdir -p /root/signal-integrityで作ってください。コマンドの形式は、python3 /opt/lab/signal_integrity/experiment.py --model 入力JSON --out 新しい出力フォルダーです。ステップのファイルカードで、入力と生成物の形式を区別してください。生成物の例は省略した形式で、実際のソルバーの出力の代わりに提出することはできません。ヘルパーは、既存の出力フォルダーを上書きしません。再実行するには、前のフォルダーを別の名前で保管してください。正解例は、これを自動で行います。Pythonの分析関数は、ファイルを直接読む代わりに、表や数値を引数で受け取って結果を返し、printのログを入れません。数値の戻り値は相対1e-6または絶対1e-8の許容誤差、JSONのブール値は正確な型を確認します。各ソース・JSONは64KiB、波形のCSVは2MiB以下で、シンボリックリンクではない通常のファイルでなければなりません。関数の実行は、CPU 4秒・実時間5秒・アドレス空間256MiBに制限されます。最終の採点は、公差の下位の波形を含めて、前のステップの資料を確認し直します。追加パッケージのインストール・インターネット・実際の機器は必要ありません。

3.3Vを送ったのに5.5Vが届いた

baseline.jsonにvolts=3.3, driver_ohm=10, series_ohm=0, z0_ohm=50, load_ohm=1000000000, delay_ns=2, rise_ns=0.2, step_ns=0.02, stop_ns=14を保存してください。すべてのファイルは/root/signal-integrityの下にあります。experiment.py --model /root/signal-integrity/baseline.json --out /root/signal-integrity/baselineを実行して、model.cir・trace.csv・run.jsonを生成し、入力/TX/RXの列を確認してください。

ヘルパーのフルパスは/opt/lab/signal_integrity/experiment.pyで、python3で実行します。入力の時間はns、CSVの時間はsです。出力フォルダーはヘルパーが作ります。

ケーブルの時計を読む

arrival.pyにfirst_crossing_ns(rows, threshold_v)を実装してください。rowsは[time_s, drive_v, tx_v, rx_v]の時間昇順のリストです。RXが最初にしきい値に届く時刻を線形補間して、nsで返します。最初の点からしきい値以上なら最初の時刻、最後までなければNoneです。baselineの波形と、小さな別のサンプルをあわせて検査します。

a.rx < threshold <= b.rxとなる最初の区間で、電圧の比率の分だけ時間を進めてください。rowsの数値はすでにfloatで、CSVを開く関数ではありません。

こだまが戻ってくる電圧を予測する

reflections.pyのpredict(vs, source_ohm, z0_ohm, load_ohm)が、launch_v, gamma_source, gamma_load, rx_first_v, rx_second_vを含むオブジェクトを返すようにしてください。source_ohmはドライバーと追加の直列抵抗の合計です。入力は正の有限の数で、負荷は無限大ではない有限の抵抗です。2つ目の受信平坦部は、最初の値に次の往復の変化を足した値です。

進行波AとΓL・ΓSをそれぞれ計算し、2つ目の変化がA×(1+ΓL)×ΓS×ΓLになることを確認してください。負荷が小さいときやソースが大きいときも、符号を保ちます。

抵抗1つでこだまを減らす

baseline.jsonの条件でseries_ohmだけを40に変えたseries.jsonを作り、--out /root/signal-integrity/seriesで実行してください。基準のファイルは残します。driver_ohm=10を含めた合計のソース抵抗は50Ωです。生成された波形で、最初の送信電圧と最初の受信電圧が異なる理由を確認してください。

追加の抵抗を50にすると、合計のソースが60Ωになってしまうミスです。run.jsonのモデルと、使った入力JSONが同じか確認してください。

同じ50Ωでも位置が違う

baseline.jsonの条件でload_ohmだけを50に変えたparallel.jsonを作り、--out /root/signal-integrity/parallelで実行してください(series_ohmは0)。tradeoff.pyのload_power(vs, source_ohm, load_ohm)は、十分に時間がたったDC状態のcurrent_aとload_wを返します。電圧V・抵抗Ωを受け取ってA・Wで返し、有限で正の条件を検査します。

回路ファイルの生成と関数の実装の、2つが必要です。合計の抵抗で電流を求め、負荷の電力はその電流の2乗と負荷抵抗で計算します。

代表値の外にある9本のケーブルを比べる

series.jsonを--out /root/signal-integrity/corners --cornersで実行してください。追加の40Ωは維持し、ドライバー8/10/12Ω × Z0 45/50/55Ωの9つのフォルダーとpeaks.jsonが生成されます。summary.pyのsummarize(records)は、空でない[{case: 名前, peak_v: 最大V}, ...]から、count, min_peak_v, max_peak_v, max_caseを返します。最大値が同じ場合は、辞書順でもっとも先の名前です。

例のリストを直接書かず、実際の9つの波形を生成します。最大値だけを返したり、リストの順番で同じ値を選んだりすると、別の条件で失敗します。

サンプル番号ではなく時間を合わせる

series.jsonでstep_nsだけを0.01に変えたfine.jsonを、--out /root/signal-integrity/fineで実行してください。convergence.pyのmax_difference(coarse, fine)は、coarseの各時刻でfineを線形補間し、TX/RX(col 2,3)の電圧の最大絶対差Vを返します。表は[time_s,drive_v,tx_v,rx_v]で、2点以上、時間は厳密に増加、開始と終了は同じです。実際の波形と異なる刻みの小さな表も検査します。

行番号をzipで合わせると、時刻がずれます。fineから現在のcoarseの時刻を挟む2点を探し、入力電圧のcol 1は、この関数の比較から外してください。

根拠をまとめ、限界を残す

前のステップのファイルを保存したまま、release.jsonを作成してください。model_type=ideal_single_mode_lossless, measured=false, pcb_certified=false, target_verification_required=trueです。release.jsonの形式の例にあるsha256オブジェクトには、提供された相対パスだけをキーに使い、現在のファイルの内容のSHA-256を小文字64桁で入れます。前のステップの波形と分析も、もう一度検証します。バックアップファイルは、リストに入れません。

コードや回路を修正したなら、先に再実行・検証をして、最後にハッシュを作ってください。ファイルが同じであることと、実物の計測が正しいことは、別の主張です。