NetBSDでFPAG開発を始めてみる(PyRTL) 準備編

この記事は、NetBSD Advent Calendar 2025の24日目の記事です。

はじめに

21日目から23日目にかけて、安価に購入したFPGA基板であるTang Nano 9Kのための開発環境をNetBSD上に整え、基本的にはNetBSDだけで開発できることを確認しました。 でも、合成や配置配線にもベンダー特有の最適化が必要であるかもしれません。 また、GOWIN FPGA Designerでは、A/Dコンバーターなどの各種ロジックやArm Cortex-M0やRISC-Vなどのアーキテクチャーのマイクロコントローラーを選択するメニューがありました。 どこまで無料で使えるのか分かっていませんが、そういうものはNetBSD上では使いようがなさそうです。

とは言え、私がVerilogを学んだり、Tang Nano 9Kを購入したのは、PyRTLという教育用のHDLを使ってみたかったためでした。 なので、そういう便利なものは使えなくても困りません。 PyRTLはVerilogのソースコードを出力してくれるので、21日目のように作業できれば、最適化は別として、それで良いとも言えます。

ですが、マイナーなものを使うと、世界で最初に困る人になってしまいがちです。 PyRTLにはJupyer Notebook/JupyeterLabで学べるような教材が用意されているのですが、少なくとも2025年12月28日現在lpkgsrc経由で利用できるJupyter Notebook/JupyterLabではエラーになりウェーブフォームをウェブブラウザー上では見ることができません。 せっかくPyRTLにはシミュレーション機能が内蔵されているのに、それを活用することができません。

おそらくNetBSDで作業しているから発生する問題ではないと思われるものの、pkgsrc/cad/py-PyRTL-0.12が壊れているのは困りますので、直すことにしました。

エラーの内容

まず、私は以下のようなJupyter NotebookとJupyterLabのパッケージをインストールしています。 これ以外にも関連するものはありますが、そこまで厳密である必要はないでしょう。

py314-jupyter-lsp-2.3.0
py314-jupyter_server_terminals-0.5.3
py314-jupyter_client-8.7.0
py314-jupyterlab-4.4.10
py314-jupyter_core-5.9.1
py314-jupyterlab-pygments-0.3.0
py314-jupyter_events-0.12.0
py314-jupyterlab-server-2.28.0
py314-jupyter_server-2.17.0

エラーの内容は非常に簡単です。ipynb-examples/example1-combologic.ipynbと言う教材のStep 2の3個目のセルのsim.tracer.render_trace(symbol_len=2)が失敗します。 エラーメッセージはJavascript Error: $ is not definedです。 FirefoxのDevelopert toolのconsoleには何も出ていませんが、Jupyter Notebook/JupyterLabの画面上に表示されるエラーです。

実を言うと、ipynb-examples/example1-combologic.ipynbは、examples/example1-combologic.pyから自動生成されています。 と言うことで、examples/example1-combologic.pyの内容をそのままJupyter Notebook/JupyterLabの1つのセルで実行して、どこがいけないのか調査することにしました。

エラーを調査する

ipynbファイルを保存すると、以下のような内容が含まれています。 この内容は元々のipynbにはありません。 どこかで自動的に挿入されているはずです。

(snip)
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/skins/default.js"),
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/wavedrom.min.js"),
(snip)

ここまで特徴的であれば、/usr/pkg/lib以下を探しても迷うことはありません。 pyrtl/simulation.pyというファイルに含まれていることが分かりました。 そして、この$は、jQueryが提供されることが期待されているようです。 ですが、私のインストールしているJupyter NotebookもJupyterLabも、ウェブブラウザー上でjQueryの$は提供していないようです。 少なくとも$.getScript関数は使えません。

どこかでjQueryのgetScript関数は使うなと言われたような記憶もありますが、最新版では使えるのかもしれません。 いずれにしても、PyRTLの教材を動かすのには十分なはずです。 と言うことで、jQueryを読み込んだ後に、問題の箇所を実行するようにすれば良さそうです。

エラーを修正する

オリジナルのPyRTL-0.12のソースコードで関連する箇所を以下に示します。 この中の1775行目からのjs_code変数の中身を書き換えれば良さそうです。 改めて見ると、問題の箇所は、当然ですがJupyter Notebook/JupyterLabで実行した場合のみ呼び出されるようになっています。

  1760          if _currently_in_jupyter_notebook():
  1761              from IPython.display import (
  1762                  HTML,
  1763                  Javascript,
  1764                  display,
  1765              )
  1766
  1767              from pyrtl.visualization import trace_to_html
  1768
  1769              htmlstring = trace_to_html(
  1770                  self, trace_list=trace_list, sortkey=_trace_sort_key
  1771              )
  1772              html_elem = HTML(htmlstring)
  1773              display(html_elem)
  1774              # print(htmlstring)
  1775              js_stuff = """
  1776              $.when(
  1777              $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/skins/default.js"),
  1778              $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/wavedrom.min.js"),
  1779              $.Deferred(function( deferred ){
  1780                  $( deferred.resolve );
  1781              })).done(function(){
  1782                  WaveDrom.ProcessAll();
  1783              });"""
  1784              display(Javascript(js_stuff))

Jupyter NotebookやJupyterLabを実行できるウェブブラウザーであれば、fetch関数やpromiseのサポートは持っているはずな気がします。 と言うことで、安直ですがfetchして実行する関数を用意し、jQueryを読み込んだ後に、promiseを使って、既存のロジックを実行させることにしました。

以下のようなパッチを作成して適用しました。

@@ -1773,6 +1773,16 @@ class SimulationTrace:
             display(html_elem)
             # print(htmlstring)
             js_stuff = """
+            function fetchAndRunScript(uri) {
+              return fetch(uri)
+                .then(resp => resp.text())
+                .then(scrtext => {
+                  const scrfunc = new Function(scrtext);
+                  scrfunc();
+                })
+                .catch(err => console.error('Cannot load script:', err));
+            }
+            fetchAndRunScript("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js").then(() => {
             $.when(
             $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/skins/default.js"),
             $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/wavedrom.min.js"),
@@ -1780,7 +1790,7 @@ class SimulationTrace:
                 $( deferred.resolve );
             })).done(function(){
                 WaveDrom.ProcessAll();
-            });"""
+            });});"""
             display(Javascript(js_stuff))
         else:
             self.render_trace_to_text(

こうすることで、ウェブブラウザー上でウェーブフォームを表示させることができるようになりました。 これで、FPGAに実装する前のチェックが簡単になります。

pkgsrc/cad/py-PyRTL-0.12nb1としてcommitしておこうと思います。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

NetBSDでFPAG開発を始めてみる(PyRTL) 準備編

この記事は、 NetBSD Advent Calendar 2025 の24日目の記事です。 はじめに 21日目から23日目にかけて、安価に購入したFPGA基板であるTang Nano 9Kのための開発環境をNetBSD上に整え、基本的にはNetBSDだけで開発...