NetBSDでFPAG開発を始めてみる(NVCとVHDL)

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

はじめに

本当は、PyRTLで書いたロジックをTnag Nano 9Kで動かしてみたいのですが、これから勉強しないといけないので、しばらく先に進めそうにありません。 と言うことで、22日目23日目でVHDLを使ってみていましたが、その際に試していたNVCというVHDLのシミュレーターについて、試したことを書いておきたいと思います。

NVCできること

NVCは、GHDLとは違い、合成をすることはできません。 あくまで、IEEE 1076-2008のほとんどをシミュレーションできるだけのようです。 VHDLについては、普通の利用者は、GOWIN FPGA Designerを使うでしょうから、良いシミュレーターであるだけでも大きな意味があるのだと思います。 NVCはJ-Core Open Processorでも使われているようです。

NVCをインストールする

pkgsrc/cad/nvcとして、nvc-1.18.2を用意しました。 この後にインポートしておきたいと思います。

と言うことで、以下のようにインストールすれば良いでしょう。

# cd /usr/pkgsrc/cad/nvc
# make install

これによって、/usr/pkg/bin/nvcがインストールされます。 これを使って、22日目のGHDLによるシミュレーション用のMakefileに、NVCを使ったパターンも追加してみます。 analysisをするにはanalysisnvcターゲット、elaborateにはelaboratenvcターゲット、シミュレーションを実行してvcdウェーブフォームファイルを得るにはrunnvcターゲットを用意しました。

$ cat Makefile
TARG=   counter

GHDL_FLAGS+=    -fsynopsys

.PHONY: analysis elaborate run clean analysisnvc elaboratenvc runnvc

analysis: ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}_tb.vhdl

analysisnvc: ${TARG}.vhdl ${TARG}_tb.vhdl
        nvc -a ${TARG}.vhdl ${TARG}_tb.vhdl

elaborate: work-obj93.cf
        ghdl -e ${GHDL_FLAGS} ${TARG}
        ghdl -e ${GHDL_FLAGS} ${TARG}_tb

elaboratenvc: analysisnvc
        nvc -e counter_tb

run: elaborate
        ghdl -r ${GHDL_FLAGS} --time-resolution=ns ${TARG}_tb --vcd=counter.vcd --stop-time=1ms

runnvc: elaboratenvc
        nvc -r --format=vcd --wave=counter-nvc.vcd --stop-time=1ms counter_tb

clean:
        rm -f counter.vcd
        rm -f work-obj93.cf
        rm -f counter-nvc.vcd
        rm -fr work

ただし、nvcの生成したcounter-nvc.vcdファイルのタイムスケールはfs単位になっていて、変更ができないようです。

結果のvcdファイルをGtkWaveで表示してみる

Zoom-outしていくと、下図のように表示できました。 既定の表示は非常にZoom-inされた状態ですが…。

これで、GHDLだけでなくシミュレーションを実行できるようになりました。 検証も確実さを上げることができそうです。

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しておこうと思います。

NetBSDでFPAG開発を始めてみる(VHDL) (2/2)

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

はじめに

22日目の記事では、GHDLを導入し、VerilogのプログラムをVHDLに移植して、そのウェーブフォームを見て、どうやら正しく移植できていそうということが確認できました。 今回は、YosysでVHDLで書かれたロジックを合成し、FPAGに反映してみます。

ghdl-yosys-pluginを導入する

ghdl-yosys-pluginをpkgsrc/devel/ghdl-yosys-pluginとしてインポートしました。 これを以下のようにインストールしておきます。 21日目を参照して、pkgsrc/devel/nextpnr-himbaechelとpkgsrc/devel/openFPGALoaderをインストールしておいてください。 pkgsrc/deve/yosysは、以下のようpkgsrc/devel/ghdl-yosys-pluginをインストールすると、依存パッケージとしてインストールされます。 もちろん、先にインストールされていても全く問題ありません。

# cd /usr/pkgsrc/devel/ghdl-yosys-plugin
# make install

合成と配置配線、ロードを実行する

元々のverilog用のMakefileを改造して、以下のようなVHDL用のMakefileを用意しておきます。

$ cat Makefile
BOARD=tangnano9k
FAMILY=GW1N-9C
DEVICE=GW1NR-LV9QN88PC6/I5

all: counter.fs

# Analysis
analysis: counter.vhdl
        ghdl -a -fsynopsys counter.vhdl

# Synthesis
counter.json: analysis
        yosys -m ghdl -p "ghdl -fsynopsys counter; synth_gowin -top counter -json counter.json"

# Place and Route
counter_pnr.json: counter.json
        nextpnr-himbaechel --json counter.json --write counter_pnr.json --freq 27 --device ${DEVICE} --vopt family=${FAMILY} --vopt cst=${BOARD}.cst

# Generate Bitstream
counter.fs: counter_pnr.json
        gowin_pack-3.14 -d ${FAMILY} -o counter.fs counter_pnr.json

# Program Board
load: counter.fs
        openFPGALoader -b ${BOARD} counter.fs -f

.PHONY: load analysis
.INTERMEDIATE: counter_pnr.json counter.json

また、なんとなくVerilogで小文字だった入出力のポート名称を大文字にしてしまったので、Tang Nano 9Kの端子への接続を指定するtangnano9k.cstファイルも以下のように作成しておきます。

$ cat tangnano9k.cst
IO_LOC "CLK" 52;
IO_PORT "CLK" PULL_MODE=UP;
IO_LOC "LED[0]" 10;
IO_LOC "LED[1]" 11;
IO_LOC "LED[2]" 13;
IO_LOC "LED[3]" 14;
IO_LOC "LED[4]" 15;
IO_LOC "LED[5]" 16;

ここまで来たら、実際にTang Nano 9KをNetBSDマシンに接続して、以下のように実行します。

$ make load

書き込みが終わると、Tang Nano 9Kの橙色のLCDの点滅が開始されます。 どうやらVerilogの場合と同様に2進数でカウントアップしてくれているようです。

これで、VerilogだけでなくVHDLでも、Tang Nano 9Kを利用できそうです。

でも私の本当の目的はPyRTLを使ってみることなのです。 これについても機会を見付けて試してみて、書いておきたいと思います。

NetBSDでFPAG開発を始めてみる(VHDL) (1/2)

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

はじめに

21日目では、Sipeed tang Nano 9KというGowin製のFPGAの搭載された基板を使い、Gowinの提供する開発ツールであるGOWIN FPGA Designner (21日目の記事ではGowin EDAと書きましたが、実際にインストールして起動してライセンスを割り当ててみたところ、こういう名前のソフトウェアでした)を使わずに、NetBSDだけでFPGAをプログラムしてみました。

その際は、Tang Nano 9Kで動くことが分かっているものでないと動作確認にもならないため、GitHubで公開されているlushaylabs/tangnano9k-series-examplesリポジトリーのcounterという例をpkgsrcに合わせて修正したものを使っていました。 この例はVerilogで書かれており、私が多少は分かるというのも良い点でした。

ただ、私はVHDLも体験してみたいと思っていました。 VHDLで書かれたものをyosysで扱えるものとして、ghdl-yosys-pluginというYosysのプラグインが用意されています。 まだ実験段階で扱えないVHDLの機能もあるのかもしれませんが、今回はこのghdl-yosys-pluginを使うために、VHDLでcounterを書き直して、シミュレーションを実行したいと思います。 明日は、Tang Nano 9Kをプログラムして、実際に動かしてみたいと思います。

VHDLを学ぶ環境を作る

VHDLのシミュレーションをするには、GHDLNVCが使えそうです。 ただ、今回はghdl-yosys-pluginを使うつもりですので、GHDLを使うことにしました。 GHDLは、pkgsrc/cad/ghdlとしてNetBSD上でも利用できます。 以下のようにインストールすれば良いでしょう。

# cd /usr/pkgsrc/cad/ghdl
# make install

これによって、ghdlコマンドを利用できるようになります。 実際の使い方は、後ほど試して行く中で探って行きたいと思います。

Verilogで書かれたcounterをVHDLに移植する

ところで、私は全くVHDLを知りませんでした。 ただ、かつてVHDLを学ぼうと思ったことはあったようで、図解VHDL実習 --ゼロから分かるハードウェア記述言語-- 堀 桂太郎著という本を持っていました。 第2版も出ているようですが、私が持っていて参照したのは無印のものです。 これで、VHDLでのロジック記載の基本的構造と、テストベンチの書き方を学ぶことができました。 もう少しちゃんと読めば、VHDLの良さを理解できそうです。 また、テストベンチの書き方については、GHDLのドキュメントも参考になりました。

Verilogで書かれたcounterは以下のようです。

$ cat counter.v
module counter
(
    input clk,
    output [5:0] led
);

localparam WAIT_TIME = 13500000;
reg [5:0] ledCounter = 0;
reg [23:0] clockCounter = 0;

always @(posedge clk) begin
    clockCounter <= clockCounter + 1;
    if (clockCounter == WAIT_TIME) begin
        clockCounter <= 0;
        ledCounter <= ledCounter + 1;
    end
end

assign led = ~ledCounter;
endmodule

これを逐一VHDLで書き直してみると、以下のようになりそうです。 VHDLでよくある書き方になっているとは思いませんが、一応後で実行するテストベンチの結果を見る限り機能は移植できているっぽいです。 第一印象としては、Verilogより固めに書かないといけないような印象を持ちました。

$ cat counter.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter is
        Port (CLK : in std_logic;
              LED : out std_logic_vector(5 downto 0));
end counter;

architecture behavior of counter is
        constant WAIT_TIME : integer := 13500000;
        signal ledCounter : std_logic_vector(5 downto 0) := "000000";
        signal clockCounter : std_logic_vector(23 downto 0) := "000000000000000000000000";
begin
        process(CLK)
        begin
                if(CLK'event and CLK = '1') then
                        clockCounter &t;= clockCounter + 1;
                        if(clockCounter = WAIT_TIME) then
                                clockCounter <= "000000000000000000000000";
                                ledCounter <= ledCounter + 1;
                        end if;
                end if;
        end process;

        LED <= not ledCounter;
end behavior;

VHDLで書いたプログラムをテストする

上で移植したプログラムが想定通り動くはずかは、FPGAに書き込む前にテストしておきたいです。 openFPGALoaderで書き込む際には、今の利用方法だとフラッシュメモリーに書き込むようなので、書き換え回数も上限があります。 図解VHDL実習でのテストベンチの書き方の説明と、GHDLのドキュメントにある実例を元に、Verilogで書く場合をVHDLに移植するイメージで書くと、以下のようでテストベンチは良さそうです。

$ cat counter_tv.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter_tb is
end counter_tb;

architecture behavior of counter_tb is
        component counter
                Port (CLK : in std_logic;
                      LED : out std_logic_vector(5 downto 0));
        end component;

        for counter_0: counter use entity work.counter;
        signal CLK : std_logic := '0';
        signal LED : std_logic_vector(5 downto 0) := "000000";
begin
        counter_0: counter port map (CLK => CLK, LED => LED);

        process
        begin
                CLK <= not CLK;
                wait for 1 ns;
        end process;
end behavior;

また、counter.vhdlも待ちサイクルがテストするにはあまりに長いので、以下のように3回のクロック立ち上がりで次のLED店頭パターンになるように書き変えておきます。 おそらく、こんな改造をすることなくテストする方法もあってしかるべきだと思いますが、分かっていません。

$ cat counter.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter is
        Port (CLK : in std_logic;
              LED : out std_logic_vector(5 downto 0));
end counter;

architecture behavior of counter is
        --constant WAIT_TIME : integer := 13500000;
        -- 3 is only for testbench
        constant WAIT_TIME : integer := 3;
        signal ledCounter : std_logic_vector(5 downto 0) := "000000";
        signal clockCounter : std_logic_vector(23 downto 0) := "000000000000000000000000";
begin
        process(CLK)
        begin
                if(CLK'event and CLK = '1') then
                        clockCounter &t;= clockCounter + 1;
                        if(clockCounter = WAIT_TIME) then
                                clockCounter &t;= "000000000000000000000000";
                                ledCounter &t;= ledCounter + 1;
                        end if;
                end if;
        end process;

        LED &t;= not ledCounter;
end behavior;

ghdlコマンドはステップを積み上げて実行しないと、VCDウェーブフォームファイルを得られません。 以下のようなmakefileを使って、make runと実行すれば、VCDウェーブフォームファイルを正常に得られると思います。 得られたVCDウェーブフォームファイル (counter.vcd)は。pkgsrc/cad/gtkwaveで閲覧することができます。 3回のクロック立ち上がりで次のLCD点灯パターンになるので、6nsごとにLED[5:0]が変わっていることが分かると思います。

$ cat Makefile
TARG=   counter

GHDL_FLAGS+=    -fsynopsys

.PHONY: analysis elaborate run clean

analysis: ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}_tb.vhdl

elaborate: work-obj93.cf
        ghdl -e ${GHDL_FLAGS} ${TARG}
        ghdl -e ${GHDL_FLAGS} ${TARG}_tb

run: elaborate
        ghdl -r ${GHDL_FLAGS} --time-resolution=ns ${TARG}_tb --vcd=counter.vcd --stop-time=1ms

clean:
        rm -f counter.vcd
        rm -f work-obj93.cf

23日目は、ここで移植したVHDLによるcounterをyosysで合成し、nextpnrで配置配線し、FPGAをプログラムして、動作を確認してみます。

NetBSDでFPAG開発を始めてみる

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

はじめに

Verilogや他のHDL (Hardware Description Language; ハードウェア記述言語)を勉強して来ましたが、シミュレーションだけでハードウェアとして実現したことはありませんでした。 XilinxやAlteraのFPGAを搭載した基板は高価ですし、LatticeやMicrochip (旧Actel)のFPGA基板で良いものがどれかも良く分かりません。 そもそも、何も分からない段階で真に良いものを選べる気もしません。

誰が言及していたのか全く記憶から消えてしまいましたが、ディジタル回路とVerilog入門というチュートリアルを読みました。 Verilogについて納得が行くまで解説がされている感じはしなくて、ちょっと悩んでしまう気がしましたが、おもしろいチュートリアルだと思います。 その中で、秋月電子通商で売られているSipeed製のTang Nano 9Kという基板が紹介されていました。 これには、中国のGowin Semiconductor製のFPGAが搭載されています。 記事中の2,500円という価格よりは値上げされて、2,710円 (消費税込みで2,980円)になっていましたが、3,000円せずに購入できるのは、最初の一歩としては手軽です。

Gowin Semiconductor社は、Gowin EDAという開発環境を提供しています。WindowsとLinuxで利用できるようです。 Apply LicenseのページからWindows用のGowin EDAのライセンスを申請すると、5分もせずにライセンスファイルが返送されて来ました。 ですが、まだインストールしていません。 近々試してみないといけません。

一方で、ウェブ検索をすると、Tang Nano 9KはYosys等のオープンソースなツールのみで扱うことも可能なようです。 と言うことで、NetBSD/amd64 11.99.4のみでTang Nano 9Kをプログラムしてみました。

必要なソフトウェアを用意する

Verilogを勉強するには、非常に小規模なロジック以外に書いたことがありませんので、Icarus Verilogを使って来ました。 ですが、これは単なるシミュレーターなので、ハードウェアに書き込むのには使えません。 FPGAで自分が書いたロジックを動かすには、シミュレーターで正常に動くはずであることを確認し、合成して、配置と配線をして、FPGAが読み込めるデータに変換し、書き込む(プログラムする)という流れが必要なはずです。

Gowin製のFPGAの場合、オープンソースなツールとしては、合成はYosysで、配置と配線はnextpnrで、データ(ビットストリームと呼ばれている)への変換はapycula、プログラムするのはopenFPGALoaderを使えば良いようです。

ちょうどpkgsrc-2025Q4のフリーズが終わったので、ちゃんとアップデートやインポートをしないといけませんが、それはこの記事を書いた後にすることにして、必要なツールは以下のようにインストールすれば良いでしょう。 pkgsrc/devel/openFPGALoaderはpkgsrc/devel/libftdi1を使いますが、libftdi1はpkgsrc/devel/swig4がインストールされていると、swig3がインストールされていてもswig4を使ってしまい、ビルドすることができません。 ですので、まずはswig4は削除しておく必要があります。 swig4は基本的には何かのFull dependencyになっていることはなさそうですから、問題にはならないはずと思います。

# pkg_delete swig4
# cd /usr/pkgsrc/devel/yosys
# make install
# cd /usr/pkgsrc/devel/nextpnr-himbaechel
# make install
# cd /usr/pkgsrc/devel/py-apycula
# make install
# cd /usr/pkgsrc/devel/openFPGALoader
# make install

一方で、自分の書いたVerilogのコードをプログラムしても、ちゃんと動かない場合に、これらのツールが動いているか否かの動作確認ができる気がしません。 github.com/lushaylabs/tangnano9k-series-examplesにある、counterというプロジェクトを利用して動作確認することにします。 ただ、現状では古いツールチェイン用の記述になっていますし、pkgsrcのやり方には沿っていないので、私がforkして修正点を反映させたものを今回は利用します。 以下のように、手元に取得しておきます。

$ git clone git@github.com:ryoon/tangnano9k-series-examples.git
$ cd tangnano9k-series-examples
$ git pull origin newer-toolchain-pkgsrc
$ git switch newer-toolchain-pkgsrc

実際に合成からプログラムまでを実行してみる

counter/Makefileに実行すべきコマンドは既に記載されています。 まずはTang Nano 9KをNetBSDマシンに接続してみます。 Tang Nano 9KにはUSB A to USB Type-Cケーブルが付属していますが、手元に出してあったいつも使っているケーブルを利用しました。 dmesgは以下のようです。 普通にugen(4)として認識されている状態です。

ugenif0 at uhub1 port 2 configuration 1 interface 0
ugenif0: SIPEED (0x0403) JTAG Debugger (0x6010), rev 2.00/5.00, addr 2
ugenif1 at uhub1 port 2 configuration 1 interface 1
ugenif1: SIPEED (0x0403) JTAG Debugger (0x6010), rev 2.00/5.00, addr 2

/dev/ugen0.*/dev/ugen1.*はrootユーザーしか読み書きできないので、私のユーザーはwheelグループに所属していますので、以下のようにパーミッションを変更しておきます。

# chmod 660 /dev/ugen0.*
# chmod 660 /dev/ugen1.*

と言うことで、まずは実行してみましょう。 以下のように実行すれば、FPGAのプログラムまで完了します。 CRC Check: Successになれば正常終了しているはずです。

$ make load
(snip)
openFPGALoader -b tangnano9k counter.fs -f
empty
write to flash
Jtag frequency : requested 6.00MHz   -> real 6.00MHz
Parse file Parse counter.fs:
Done
DONE
Jtag frequency : requested 2.50MHz   -> real 2.00MHz
Erase SRAM DONE
Erase FLASH DONE
Erasing FLASH: [==================================================] 100.00%
Done
write Flash: [==================================================] 100.00%
Done
CRC check: Success

正常終了すると、以下の写真のようにTang Nano 9K内蔵のLEDが橙色に点滅します。

Tang Nano 9Kには、LUTはLUT4ということで、4入力で1出力なのでしょうか。 また9Kということで、LUTは8640個あるそうです。 パッケージにはEntry-Level FPGA Kit For RISC-Vと書かれていますが、NetBSDが動くようなRISC-V環境が作れる訳ではない仕様な気がします。 でも、自分で書いたHDLのコードが、シミュレーションではなく実際のFPGAで動かせるというのは、学習を一歩先に進めるのには役立ちそうです。

NetBSD上でYubiKey 5 NFCの各機能を使ってみる (2)

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

はじめに

(1)では各機能を概観しました。 今回は、私がYubiKey 5 NFCで利用しようと当初から考えていたパスキーによるログインを試したいと思います。

現状を確認する

実を言いますと、既に3つのFIDO credentialsが登録済みになっています。 ですが、実際に意味があるのは1つだけです。 その状況を確認してみます。

また、FIDO機能のためのPINも設定済みです。 これはykman-3.14 fido access change-pinで設定したはずです。

$ ykman-3.14 fido info
AAGUID:                       XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
PIN:                          8 attempt(s) remaining
Minimum PIN length:           4
Always Require UV:            Off
Credential storage remaining: 97

$ ykman-3.14 fido credentials list
Enter your PIN: (あらかじめ設定したPINを入力してEnterキーを押す)
Credential ID  RP ID                Username          Display name
XXXXXXXX...    webauthn.io          ryoon
YXXXXXXX...    login.microsoft.com  ????????@hotmail.com
ZXXXXXXX...    google.com           ????????@gmail.com

この3番目のgmail.comのusernameのものだけが実際に有用なものです。 webauthn.ioのものは、pkgsrc/www/firefoxの動作確認の際に作ったものです。 login.microsoft.comのものは、設定途中で進まなくなってしまい、実際にMicrosoftアカウントには紐付いていません。

と言うことで、不要なものはまず削除してしまいましょう。

$ ykman-3.14 fido credentials delete XXXXXXXX
Enter your PIN: (あらかじめ設定したPINを入力してEnterキーを押す)
Delete webauthn.io ryoon  (XXXXXXXX(snip))? [y/N]: y (yと入力してEnterキーを押す)
Deleting credential, DO NOT REMOVE YOUR YUBIKEY!
Credential deleted.
$ ykman-3.14 fido credentials delete YXXXXXXX
Enter your PIN: (あらかじめ設定したPINを入力してEnterキーを押す)
Delete login.microsoft.com ????????@hotmail.com  (YXXXXXXX(snip))? [y/N]: y
Deleting credential, DO NOT REMOVE YOUR YUBIKEY!
Credential deleted.

これでFIDO credentialsの状況を再度確認してみましょう。

$ ykman-3.14 fido credentials list
Enter your PIN:
Credential ID  RP ID       Username          Display name
ZXXXXXXX...    google.com  ????????@gmail.com

必要なものを残して、削除できていました。

登録してみる

GoogleアカウントとMicrosoftアカウントで使うように設定してみました。 全く問題ないと言いたいところですが、そうは行きませんでした。 利用しているのは、pkgsrc/www/firefox-146.0.1です。

登録の手順は、GoogleやMicrosoftのウェブサイトを確認してもらえば良いでしょう。

結果から言うと、Googleアカウントは、既に上でも触れたように使えています。 登録もログインも想定通りにできます。 ですが、Microsoftアカウントは、パスキーの設定はでき、YubiKey 5 NFCに登録もできますが、 NetBSD/amd64 11.99.4上のFirefox 146.0.1では、ログイン時にパスキーを使ったログインはできませんでした。 選択肢にも出て来ません。 Windows 11 25H2上のFirefox 146.0.1 (64ビット版)では、パスキーでのログインが提案されます。

いずれ、証券会社等の最近パスキーに熱心なサービスでも使えるか試してみたいと思います。 ただ、現時点でNTTドコモのdアカウント等はYubiKey 5 NFCでの設定はできない所までは分かっています。

NetBSD上でYubiKey 5 NFCの各機能を使ってみる (1)

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

はじめに

以前、YubiKey 5 NFCを日本国内の代理店から購入したのですが、その直後にそのYubiKey 5 NFCのファームウェアには脆弱性が見付かってしまいました。 しかも、FIDO credentialsの登録数が十分ではなく、あまり活用できない常態でした。 今回は、YubiKeyの公式オンラインストアからファームウェアバージョン5.7.4のものを購入しました。 これは既存の脆弱性はないようですし、FIDO credentialsの登録可能数も十分のようです。

YubiKey 5 NFCはいろいろな機能があるようです。製品紹介のページの表を見ると、 以下の9つの機能があるようです。ただ、YubiKeyの提供する機能と1:1と言う訳ではないような気もします。 各機能をNetBSD/amd64-currentから使ってみたいと思います。

  1. WebAuthn
  2. FIDO (CTAP 1, 2, 2.1)
  3. Universal Second Factor (U2F)
  4. Smart Card / PIV
  5. Yubico OTP
  6. OATH - HOTP (Event)
  7. OATH - TOTP (Time)
  8. OpenPGP
  9. Secure Static Password

NetBSDでYubiKeyを管理するツールをインストールする

YubiKey Managerのページには、QTで書かれたGUIツールと、CLIのツールの2つが紹介されています。 pkgsrcにはいずれも収録されているのですが、今回はCLIツールであるykmanコマンドの方を使ってみます。 以下のようにインストールすれば良いでしょう。 今回はPython 3.14ベースで使ってみます。 ちなみに、NetBSDで正常に使えるのは、py314-yubikey-manager-5.8.0nb1以降のバージョンです。

# /usr/pkgsrc/security/py-yubikey-manager
# make install

ところが、これだけでは全てのYubiKey 5 NFCの機能を使うことができません。 py314-yubikey-manager-5.8.0nb1は、機能ごとにpcscd(8)経由かuhid(4)経由でYubiKey 5 NFCにアクセスします。 uhid(4)は追加のソフトウェアは不要 えすが、pcscd(8)経由でアクセスするには、以下のように実行する必要があります。

; ccidパッケージがpcscd(8)経由でSmart Cardとしてアクセスするのに必要です。
# /usr/pkgsrc/security/ccid
# make install
; その上で、pcscd(8)を起動させておく必要があります。
# cp /usr/pkg/share/examples/rc.d/pcscd /etc/rc.d
# echo "psccd=YES" >> /etc/rc.conf
# service pcscd start

ここまで実施すれば、YubiKey 5 NFCの機能にアクセスすることはできるように見えます。 現時点で全ての動作を確認してはいないので、必要になったら追加のセットアップを考えたいと思います。

YubiKey 5 NFCの情報を取得する

yumanコマンドは、複数のPythonインタープリターで動くものを共存できるように、alternative frameworkでPythonインタープリターのバージョン番号付きのコマンド名にするようになっています。 Python 3.14ベースの場合には、ykmanコマンドはykman-3.14という名前になっているはずです。

何のオプションも指定せずにykmanコマンドを実行すると、使えるオプションとサブコマンドを表示させることができます。 以下のように表示されるので、一通り情報を表示させてみます。

Usage: ykman-3.14 [OPTIONS] COMMAND [ARGS]...

  Configure your YubiKey via the command line.

  Examples:

    List connected YubiKeys, only output serial number:
    $ ykman list --serials

    Show information about YubiKey with serial number 123456:
    $ ykman --device 123456 info

Options:
  -d, --device SERIAL             specify which YubiKey to interact with by
                                  serial number
  -r, --reader NAME               specify a YubiKey by smart card reader name
                                  (can't be used with --device or list)
  -t, --scp-ca FILENAME           specify the CA to use to verify the SCP11
                                  card key (CA-KLCC)
  -s, --scp CRED                  specify private key and certificate chain
                                  for secure messaging, can be used multiple
                                  times to provide key and certificates in
                                  multiple files (private key, certificates in
                                  leaf-last order), OR SCP03 keys in hex
                                  separated by colon (:) K-ENC:K-MAC[:K-DEK]
  -p, --scp-password PASSWORD     specify a password required to access the
                                  --scp file, if needed
  -l, --log-level [error|warning|info|debug|traffic]
                                  enable logging at given verbosity level
  --log-file FILE                 write log to FILE instead of printing to
                                  stderr (requires --log-level)
  --diagnose                      show diagnostics information useful for
                                  troubleshooting
  -v, --version                   show version information about the app
  --full-help                     show --help output, including hidden
                                  commands
  -h, --help                      show this message and exit

Commands:
  info     show general information
  list     list connected YubiKeys
  script   run a python script
  config   configure the YubiKey, enable or disable applications
  fido     manage the FIDO applications
  hsmauth  manage the YubiHSM Auth application
  oath     manage the OATH application
  openpgp  manage the OpenPGP application
  otp      manage the YubiOTP application
  piv      manage the PIV application

これによると、infoで全体の情報を表示させ、fido、hsmauth、oath、openpgp、otp、pivという6つのサブコマンドで機能を管理できるようです。

$ ykman-3.14 info
Device type: YubiKey 5 NFC
Serial number: XXXXXXXX
Firmware version: 5.7.4
Form factor: Keychain (USB-A)
Enabled USB interfaces: OTP, FIDO, CCID
NFC transport is enabled

Applications    USB     NFC
Yubico OTP      Enabled Enabled
FIDO U2F        Enabled Enabled
FIDO2           Enabled Enabled
OATH            Enabled Enabled
PIV             Enabled Enabled
OpenPGP         Enabled Enabled
YubiHSM Auth    Enabled Enabled

ここで見ると、FIDO U2FとFIDO2は別々の機能になっているようです。 できることも違ったはずなので、当然かもしれません。

6つのサブコマンドでinfoコマンドを実行した結果を掲載したいと思います。

$ ykman-3.14 fido info
AAGUID:                       XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
PIN:                          8 attempt(s) remaining
Minimum PIN length:           4
Always Require UV:            Off
Credential storage remaining: 97
$ ykman-3.14 hsmauth info
YubiHSM Auth version:             5.7.4
Management key retries remaining: 8/8
$ ykman-3.14 oath info
OATH version:        5.7.4
Password protection: disabled
$ ykman-3.14 openpgp info
OpenPGP version:            3.4
Application version:        5.7.4
PIN tries remaining:        3
Reset code tries remaining: 0
Admin PIN tries remaining:  3
Require PIN for signature:  Once
KDF enabled:                False
$ ykman-3.14 otp info
Slot 1: programmed
Slot 2: empty
$ ykman-3.14 piv info
PIV version:              5.7.4
PIN tries remaining:      3/3
PUK tries remaining:      3/3
Management key algorithm: AES192
WARNING: Using default PIN!
WARNING: Using default PUK!
WARNING: Using default Management key!
CHUID: No data available
CCC:   No data available

このYubiKey 5 NFCは、実は既にFirefox経由でPINの設定と3つのFIDO credentialsを登録済みになっています。 今日はここまでにして、次回はfidoサブコマンドで管理できる機能を使ってみたいと思います。

NetBSD上のmplayerで、audioデバイスとvideoデバイスを指定して表示させる

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

はじめに

mplayerで出力するオーディオデバイスを指定する方法は、pkgsrc/multimedia/mplayerをpulseaudioオプションを有効にして使っている私には有用です。 OSSしか使っていない場合にも、HDMIコネクターの内蔵されたマシンを利用している場合には、内蔵スピーカーとHDMI出力を切り替える必要があると思いますので、 有用かもしれません。

一方で、webcamの画像を画面に表示させるというのは、Video4Linux2サポートの確認をする以外には有用ではないかもしれません。 ですが、それ故に、デバイスを選択し、いろいろなモードを指定できることは重要かもしれません。

オーディオデバイスの初期設定

mplayerの設定の前に、私のマシンに特有かもしれませんが、初期設定をしておきます。 私のマシンは、以下のようにオーディオデバイスが認識されています。

hdaudio0 at pci3 dev 0 function 1: HD Audio Controller
hdaudio0: interrupting at msi1 vec 0
hdaudio0: HDA ver. 1.0, OSS 4, ISS 0, BSS 0, SDO 1, 64-bit
hdafg0 at hdaudio0: ATI R6xx HDMI
hdafg0: HDMI00 2ch: Digital Out [Jack]
hdafg0: HDMI01 2ch: Digital Out [Jack]
hdafg0: 2ch/0ch 32000Hz 44100Hz 48000Hz PCM16 AC3
audio0 at hdafg0: playback
audio0: slinear_le:16 2ch 48000Hz, blk 1920 bytes (10ms) for playback
spkr1 at audio0: PC Speaker (synthesized)
wsbell at spkr1 not configured
(snip)
hdaudio1 at pci3 dev 0 function 6: HD Audio Controller
hdaudio1: interrupting at msi4 vec 0
hdaudio1: HDA ver. 1.0, OSS 4, ISS 4, BSS 0, SDO 1, 64-bit
hdafg1 at hdaudio1: Realtek product 0245
hdafg1: DAC00 2ch: Speaker [Built-In]
hdafg1: DAC01 2ch: HP Out [Jack]
hdafg1: ADC02 2ch: Mic In [Jack]
hdafg1: 2ch/2ch 44100Hz 48000Hz 96000Hz 192000Hz PCM16 PCM20 PCM24
audio1 at hdafg1: playback, capture, full duplex, independent
audio1: slinear_le:16 2ch 48000Hz, blk 1920 bytes (10ms) for playback
audio1: slinear_le:16 2ch 48000Hz, blk 1920 bytes (10ms) for recording
spkr2 at audio1: PC Speaker (synthesized)
wsbell at spkr2 not configured

一方で、/dev以下は、このようになっています。 audio0はHDMI出力なので、このままでは内蔵スピーカーからは音を出すのが面倒です。 しかも、DRMKMSのサポートがないマシンなので、そもそもHDMI経由でオーディオ出力はできません。

$ ls -l /dev/audio* /dev/sound*
lrwxr-xr-x  1 root  wheel       11 May 11  2025 /dev/audio -> /dev/audio0
crw-rw-rw-  1 root  wheel  42, 128 May 10  2025 /dev/audio0
crw-rw-rw-  1 root  wheel  42, 129 May 10  2025 /dev/audio1
crw-rw-rw-  1 root  wheel  42, 130 May 10  2025 /dev/audio2
crw-rw-rw-  1 root  wheel  42, 131 May 10  2025 /dev/audio3
lrwxr-xr-x  1 root  wheel       14 May 11  2025 /dev/audioctl -> /dev/audioctl0
crw-rw-rw-  1 root  wheel  42, 192 May 10  2025 /dev/audioctl0
crw-rw-rw-  1 root  wheel  42, 193 May 10  2025 /dev/audioctl1
crw-rw-rw-  1 root  wheel  42, 194 May 10  2025 /dev/audioctl2
crw-rw-rw-  1 root  wheel  42, 195 May 10  2025 /dev/audioctl3
lrwxr-xr-x  1 root  wheel       11 May 11  2025 /dev/sound -> /dev/sound0
crw-rw-rw-  1 root  wheel  42,   0 May 10  2025 /dev/sound0
crw-rw-rw-  1 root  wheel  42,   1 May 10  2025 /dev/sound1
crw-rw-rw-  1 root  wheel  42,   2 May 10  2025 /dev/sound2
crw-rw-rw-  1 root  wheel  42,   3 May 10  2025 /dev/sound3

cd /dev ; ln -sf audio1 audio ; ln -sf audioctl1 audioctl ; ln -sf sound1 soundと 実行しても良いのですが、audiocfg default 1とすれば、同じことをしてくれます。 結果は、以下のようになりました。 これで/dev/audioを使って、内蔵スピーカーから音を出力できることができるようにします。

$ ls -l /dev/audio* /dev/sound*
lrwxr-xr-x  1 root  wheel       11 May 11  2025 /dev/audio -> /dev/audio1
crw-rw-rw-  1 root  wheel  42, 128 May 10  2025 /dev/audio0
crw-rw-rw-  1 root  wheel  42, 129 May 10  2025 /dev/audio1
crw-rw-rw-  1 root  wheel  42, 130 May 10  2025 /dev/audio2
crw-rw-rw-  1 root  wheel  42, 131 May 10  2025 /dev/audio3
lrwxr-xr-x  1 root  wheel       14 May 11  2025 /dev/audioctl -> /dev/audioctl1
crw-rw-rw-  1 root  wheel  42, 192 May 10  2025 /dev/audioctl0
crw-rw-rw-  1 root  wheel  42, 193 May 10  2025 /dev/audioctl1
crw-rw-rw-  1 root  wheel  42, 194 May 10  2025 /dev/audioctl2
crw-rw-rw-  1 root  wheel  42, 195 May 10  2025 /dev/audioctl3
lrwxr-xr-x  1 root  wheel       11 May 11  2025 /dev/sound -> /dev/sound1
crw-rw-rw-  1 root  wheel  42,   0 May 10  2025 /dev/sound0
crw-rw-rw-  1 root  wheel  42,   1 May 10  2025 /dev/sound1
crw-rw-rw-  1 root  wheel  42,   2 May 10  2025 /dev/sound2
crw-rw-rw-  1 root  wheel  42,   3 May 10  2025 /dev/sound3

オーディオデバイスを指定する

私はpkgsrc/multimedia/mplayerで、ossとSDL-1.2、PulseAudio経由でオーディオを再生できるようにしているので、それぞれを試してみます。 他にも設定できるパラメーターはあると思いますが…。

; OSSでデフォルトのオーディオデバイスで再生する場合
$ mplayer -ao oss ./test.mp4
; OSSで/dev/audio1で再生する場合
$ mplayer -ao oss:/dev/audio1 ./test.mp4
; PulseAudio経由で再生する場合
$ mplayer -ao pulse ./test.mp4
; SDL-1.2経由でPulseAudioで再生する場合
SDL_AUDIODRIVER=pulse mplayer -ao sdl ./test.mp4
; SDL-1.2経由でOSSの/dev/audioで再生する場合
SDL_AUDIODRIVER=dsp mplayer -ao sdl ./test.mp4
; SDL-1.2経由でOSSの/dev/audioで再生する場合
SDL_AUDIODRIVER=dsp mplayer -ao sdl ./test.mp4
; SDL-1.2経由でOSSの/dev/audio1で再生する場合
$ SDL_AUDIODRIVER=dsp AUDIODEV=/dev/audio1 mplayer -ao sdl ./test.mp4

webcamを開く

webcamにもいろいろ設定はあるはずですが、以下のようにすれば、Video4Linux2サポートの確認には良さそうです。

$ mplayer tv:// -tv driver=v4l2:device=/dev/video1:width=1280:height=720:outfmt=yv12 -fps 15

おわりに

とりあえず、これでwebcamやサウンドカードの動作確認をするのには十分そうです。 でも、今日時点のNetBSD/amd64-currentだと、オーディオ出力と入力の組み合わがおかしいような…。 ちゃんと調べた方が良いかもしれません。 勘違いだと良いのですが…。

NetBSDでCDをリッピングしてみる(一応成功)

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

はじめに

furandon pigさんの10日目の記事でAudio CDのリッピングに失敗されていました。 ですが、私は過去にリッピングしていたはずです。

私の環境は、NetBSD/amd64 11.99.4にUSB 3接続のBD-Rドライブであるパイオニア製のBDR-XD08SVです。 ちなみに、いつの間にかパイオニアは光学ディスクドライブからは撤退しているように見えます。残念です。

pkgsrc/sysutils/cdrtoolsのcdda2wavコマンドを試してみる

cdrtoolsには、cdda2wavというコマンドが含まれています。 これであればリッピングできるはずです。 今回の光学ディスクドライブはcd0として認識されています。 ですが、一般ユーザーで実行したいので、まずは/dev/rcd0*のパーミッションを設定しておきます。 私が使っているユーザーはoperatorグループに所属していますので、以下のように設定すれば良いでしょう。

# chmod 660 /dev/rcd0*

その上でcdrtoolsをインストールしましょう。以下のように実行すれば良いでしょう。

# cd /usr/pkgsrc/sysutils/cdrtools
# make install

cdda2wav(1)のmap pageにあるように以下のように実行すれば良いでしょう。

$ cdda2wav -vall cddb=0 speed=4 -paranoia paraopts=proof -B
cdda2wav: Insufficient 'file read' privileges. You will not be able to open all needed devices.
cdda2wav: Insufficient 'file write' privileges. You will not be able to open all needed devices.
cdda2wav: Insufficient 'device' privileges. You may not be able to send all needed SCSI commands, this my cause various unexplainable problems.
cdda2wav: Insufficient 'priocntl' privileges. You may get jitter.
cdda2wav: Insufficient 'network' privileges. You will not be able to do remote SCSI.
No target specified, trying to find one...
Using dev=31,0,0.
Type: ROM, Vendor 'PIONEER ' Model 'BD-RW   BDR-XD08' Revision '1.02' MMC+CDDA
274432 bytes buffer memory requested, transfer size 61440 bytes, 4 buffers, 23 sectors
#Cdda2wav version 2024/03/18 3.02_netbsd_11.99.4_amd64_x86_64, real time sched., soundcard, libparanoia support
cdda2wav: Bad status from freedb server during hello: 500 Command syntax error.
.
cdda2wav: Bad status from freedb server during quit: 500 Unrecognized command, closing connection.
.
AUDIOtrack pre-emphasis  copy-permitted tracktype channels
      1-11           no              no     audio    2
Table of Contents: total tracks:11, (total time 48:35.00)
  1.( 2:00.42),  2.( 3:58.73),  3.( 4:58.40),  4.( 4:28.20),  5.( 4:12.57),
  6.( 4:39.13),  7.( 4:55.05),  8.( 4:43.70),  9.( 4:47.17), 10.( 3:56.45),
 11.( 5:53.68)

Table of Contents: starting sectors
  1.(       0),  2.(    9042),  3.(   26965),  4.(   49355),  5.(   69475),
  6.(   88432),  7.(  109370),  8.(  131500),  9.(  152795), 10.(  174337),
 11.(  192082), lead-out(  218625)
CDINDEX discid: xxh_sS61wqdXnYPsHKLlN3v5y1c-
CDDB discid: 0x830b630b
CD-Text: not detected
CD-Extra: not detected
Media catalog number: 4988022106978
T:  2 ISRC: JP-TA0-92-20030
T:  3 ISRC: JP-TA0-92-20040
T:  4 ISRC: JP-TA0-92-20050
T:  5 ISRC: JP-TA0-92-20060
T:  6 ISRC: JP-TA0-92-20070
T:  7 ISRC: JP-TA0-92-20080
T:  8 ISRC: JP-TA0-92-20090
T:  9 ISRC: JP-TA0-92-20100
T: 10 ISRC: JP-TA0-92-20110
T: 11 ISRC: JP-TA0-92-20120

index scan: 11...
samplefile size will be 514206044 bytes.
recording 2915.0000 seconds stereo with 16 bits @ 44100.0 Hz ->'audio'...
using c2check to verify reads.
using lib paranoia for reading.
cdda2wav: Operation not permitted. Cannot set posix realtime scheduling policy.
percent_done:
100%  track  1 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  896 reads(212.3%) 24 overlap(20 .. 20)
100%  track  2 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  1736 reads(207.6%) 62 overlap(20 .. 20)
100%  track  3 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  2184 reads(209.0%) 78 overlap(20 .. 20)
100%  track  4 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  1960 reads(208.7%) 70 overlap(20 .. 20)
100%  track  5 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  1792 reads(202.6%) 64 overlap(20 .. 20)
100%  track  6 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  2072 reads(212.1%) 74 overlap(20 .. 20)
100%  track  7 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  2128 reads(206.1%) 76 overlap(20 .. 20)
100%  track  8 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  2072 reads(208.5%) 74 overlap(20 .. 20)
100%  track  9 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  2072 reads(206.1%) 74 overlap(20 .. 20)
100%  track 10 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  1736 reads(209.6%) 62 overlap(20 .. 20)
100%  track 11 recorded successfully
100%  0 rderr, 0 skip, 0 atom, 0 edge, 0 drop, 0 dup, 0 drift, 0 0 c2
100%  2530 reads(204.2%) 92 overlap(20 .. 20)
$ ls
audio_01.inf audio_03.inf audio_05.inf audio_07.inf audio_09.inf audio_11.inf
audio_01.wav audio_03.wav audio_05.wav audio_07.wav audio_09.wav audio_11.wav
audio_02.inf audio_04.inf audio_06.inf audio_08.inf audio_10.inf
audio_02.wav audio_04.wav audio_06.wav audio_08.wav audio_10.wav

audio_01.wavからaudio_11.wavが生成できました。

できたwavファイルをmp3ファイルに変換する

MP3の特許は、少なくとも日本では既の期限を迎えているようです。 ですので、MP3にエンコードしても特許侵害にはならないでしょう。 と言うことで、pkgsrc/audio/lameを使うことにします。 以下のようにインストールすれば良いでしょう。

# cd /usr/pkgsrc/audio/lame

おそらくとても贅沢な気がするのですが、最近のamd64なマシンにとってMP3エンコードなど負荷にもならないと思います。 以下のようにMP3ファイルを生成しました。

$ for f in *.wav
do lame -q0 -b256 $f `basename $f .wav`.mp3
done
LAME 3.100 64bits (http://lame.sf.net)
Using polyphase lowpass filter, transition band: 19383 Hz - 19916 Hz
Encoding audio_01.wav to audio_01.mp3
Encoding as 44.1 kHz j-stereo MPEG-1 Layer III (5.5x) 256 kbps qval=0
    Frame          |  CPU time/estim | REAL time/estim | play/CPU |    ETA
  4617/4617  (100%)|    0:13/    0:13|    0:13/    0:13|   8.6830x|    0:00
-------------------------------------------------------------------------------
   kbps        LR    MS  %     long switch short %
  256.0       99.0   1.0        88.6   5.2   6.2
Writing LAME Tag...done
ReplayGain: +4.8dB
LAME 3.100 64bits (http://lame.sf.net)
Using polyphase lowpass filter, transition band: 19383 Hz - 19916 Hz
Encoding audio_02.wav to audio_02.mp3
(snip)

mp3ファイルのタグを設定し、ファイル名を変更する

pkgsrc/audio/easytagを使うと、MP3にIDv2のタグを設定すると同時に、ファイル名も「アーティスト名-曲名」等に変更することができます。 pkgsrc/audio/easytagはヘルプを表示するためにpkgsrc/misc/yelp3を利用するため、間接的にpkgsrc/www/webkit-gtkを利用することになります。 自分でpkgsrc/audio/easytagをビルドしてインストールするのであれば、以下のようにpkgsrc/www/webkit-gtkは使わないようにインストールした方が良いかもしれません。

# cd /usr/pkgsrc/audio/easytag
# make PKG_OPTIONS.easytag=-doc install

おわりに

でも良く考えるとpkgsrc/audio/abcdeは、私が以前試した時に動いていたはずです (abcde -d /dev/rcd0)。 もしかしたらNetBSDでは、/dev/cd0ではなく/dev/rcd0を使わないといけないというだけかもしれません。 他のGUI付きのソフトウェアの方が便利かもしれません。 いずれ試してみたいと思います。

USBシリアルアダプターをUEFIブートの場合にconsoleとして使う機能を試してみる

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

はじめに

2025年10月9日のmanu@のコミットと関連するコミットで、UEFIブートの際にuftdi(4)として認識されるUSBシリアルコンバーターをconsoleとして利用できるようになっていました。 ちょうど手元にFTDI製のチップを使ったUSBシリアルコンバーターを持っていましたので、試してみました。

本来は、DDBとかも使えるらしいのですが、今回はシリアルコンソール経由でログインするのみです。

初期設定

NetBSD/amd64 l11.99.4をインストールしたラップトップに、Windows 11 25H2上のPuTTYからログインしてみます。 単にログインするだけであれば、NetBSD側で以下のように設定すれば良いでしょう。

# vi /etc/ttys
(snip)
ttyU0   "/usr/libexec/getty std.115200" vt100 on secure

こうすれば、115200 bpsで通信するPuTTYでloginプロンプトを得ることができます。 具体的には下図のように設定します。

この設定は、以下の設定をしても必要ですので、この時点で設定して置くのが良いでしょう。

ucom0 at uftdi0をconsoleに設定する

以下のように認識されるデバイスをNetBSD側に接続してあります。

uftdi0 at uhub9 port 1 configuration 1 interface 0
uftdi0: FTDI (0x0403) USB HS SERIAL CONVERTER (0x6001), rev 1.10/4.00, addr 4
ucom0 at uftdi0 portno 0

その上で再起動させ、UEFIブートローダーで以下のように設定して、起動させます。

> kconsdev ucom0,115200
> boot

Windows 11上のPuTTYでは、ucom0が認識される所からブートメッセージが表示されます。

[   3.7030449] ucom0: console
[   4.1930474] uhidev1 at uhub8 port 2 configuration 1 interface 0
[   4.1930474] uhidev1: ActionStar (0x2101) product 0201 (0x0201), rev 1.10/1.00, addr 5, iclass 3/0
[   4.2030475] uhid7 at uhidev1: input=2, output=2, feature=0
[   4.7030507] uhidev2 at uhub8 port 3 configuration 1 interface 0
[   4.7030507] uhidev2: Logitech (0x046d) USB Receiver (0xc53f), rev 2.00/55.02, addr 6, iclass 3/1
[   4.7130541] ukbd0 at uhidev2
[   4.7130541] wskbd1 at ukbd0 mux 1
[   4.7330511] uhidev3 at uhub8 port 3 configuration 1 interface 1
[   4.7330511] uhidev3: Logitech (0x046d) USB Receiver (0xc53f), rev 2.00/55.02, addr 6, iclass 3/1
[   4.7430515] uhidev3: 8 report ids
[   4.7430515] ums0 at uhidev3 reportid 2: 16 buttons, W and Z dirs
[   4.7430515] wsmouse2 at ums0 mux 0
[   4.7430515] uhid8 at uhidev3 reportid 3: input=4, output=0, feature=0
[   4.7430515] uhid9 at uhidev3 reportid 4: input=1, output=0, feature=0
[   4.7430515] uhid10 at uhidev3 reportid 8: input=1, output=0, feature=0
[   4.7430515] uhidev4 at uhub8 port 3 configuration 1 interface 2
[   4.7430515] uhidev4: Logitech (0x046d) USB Receiver (0xc53f), rev 2.00/55.02, addr 6, iclass 3/0
[   9.7530773] uhidev4: no report descriptor
[   9.7530773] swwdog0: software watchdog initialized
[   9.7530773] usb8 at vhci0: USB revision 2.0
[   9.7730770] uhub10 at usb8: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.7730770] usb9 at vhci1: USB revision 2.0
[   9.7930776] uhub11 at usb9: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.7930776] usb10 at vhci2: USB revision 2.0
[   9.8130773] uhub12 at usb10: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.8130773] usb11 at vhci3: USB revision 2.0
[   9.8330781] uhub13 at usb11: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.8330781] usb12 at vhci4: USB revision 2.0
[   9.8530774] uhub14 at usb12: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.8530774] usb13 at vhci5: USB revision 2.0
[   9.8730810] uhub15 at usb13: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.8730810] usb14 at vhci6: USB revision 2.0
[   9.8930773] uhub16 at usb14: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.8930773] usb15 at vhci7: USB revision 2.0
[   9.9130776] uhub17 at usb15: NetBSD (0x0000) VHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
[   9.9130776] WARNING: 4 errors while detecting hardware; check system log.
[   9.9130776] boot device: ld0
[   9.9130776] root on dk1 dumps on dk2
[   9.9130776] root file system type: ffs
[   9.9130776] kern.module.path=/netbsd/modulesystem type: ffTue Dec  9 10:46:12 -00 2025
9130776] root file system type: ffTue Dec  9 10:46:12 -00 2025
Starting root file system check:
/dev/rdk1: file system is clean; not checking
Starting devpubd.
Setting sysctl variables:
ddb.onpanic: 1 -> 0
swapctl: setting dump device to /dev/dk2
swapctl: adding /dev/dk2 as swap device at priority 0
Starting file system checks:
/dev/rdk4: file system is clean; not checking
/dev/rdk3: file system is clean; not checking
Loaded entropy from /var/db/entropy-file.
Waiting for entropy...done
Setting tty flags.
Starting network.
Hostname: castella
IPv6 mode: host
Configuring network interfaces:.
Adding interface aliases:.
Waiting for duplicate address detection to finish...
Building databases: dev, utmp, utmpx.
Keyboard encoding -> us.swapctrlcaps
Starting syslogd.
Mounting all file systems...
Clearing temporary files.
Checking quotas: done.
swapctl: setting dump device to /dev/dk2
Starting virecover.
Checking for core dump...
savecore: no core dump
Starting local daemons:.
Updating motd.
Starting pcscd.
/etc/rc.d/pcscd exited with code 1
Starting powerd.
Starting sshd.
Starting postfix.
postfix/postlog: starting the Postfix mail system
Starting multiskkserv.
Setting mixerctl variables...
mixerctl: field record.mic2 does not exist
Starting inetd.
Starting dbus.
Starting cupsd.
Starting cron.
The following components reported failures:
    /etc/rc.d/pcscd
See /var/run/rc.log for) (ttyU0)

login: 

代わりに、NetBSDのディスプレイにはloginプロンプトのみが表示されます。

pcscdの起動が失敗するのは別の問題なようです。

NetBSD上のpkgsrc/www/firefoxでwebcamを使えない問題を解析した

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

はじめに

いまいちどの時点からか分からなくなってしまったのですが、pkgsrc/www/firefoxでは、私の今利用しているHP Envy 14 fa0000にインストールしたNetBSD/amd64-currentではwebcamを利用できなくなってしまっていました。 もしかしたら、PCを変えたタイミングだったかもしれませんが、全く分かりません。

いずれにしても、WebRTCでwebcamの映像を使えないのは残念です。 しばらく放置してしまっていましたが、直すことにしました。

認識されないのを確認できるウェブサイトを特定する

HP Envy 14にインストールされたNetBSD/amd64-currentでは、以下のようにvideo0からvideo3の4つのデバイスが認識されます。

uvideo0 at uhub3 port 1 configuration 1 interface 0: SunplusIT Inc (0x04f2) HP 5MP Camera (0xb7fe), rev 2.01/0.06, addr 1
video0 at uvideo0: SunplusIT Inc (0x04f2) HP 5MP Camera (0xb7fe), rev 2.01/0.06, addr 1
video1 at uvideo0: SunplusIT Inc (0x04f2) HP 5MP Camera (0xb7fe), rev 2.01/0.06, addr 1
uvideo1 at uhub3 port 1 configuration 1 interface 2: SunplusIT Inc (0x04f2) HP 5MP Camera (0xb7fe), rev 2.01/0.06, addr 1
video2 at uvideo1: SunplusIT Inc (0x04f2) HP 5MP Camera (0xb7fe), rev 2.01/0.06, addr 1
video3 at uvideo1: SunplusIT Inc (0x04f2) HP 5MP Camera (0xb7fe), rev 2.01/0.06, addr 1

ただし、pkgsrc/multimedia/mplayerで確認してみると、video1とvideo3だけが使えます。 ちなみに、確認した方法は以下のようです。

$ mplayer tv:// -tv device=/dev/video1
$ mplayer tv:// -tv device=/dev/video3

mplayerでのvideo(4)デバイスの動作確認の方法は、別に書いていた方が良いかもしれません。

これまでは、getUserMedia / getDisplayMedia Test Pageを使って来たのですが、 これはそもそも複数のwebcamを選択することはできないので、適切ではありません。 そこで、WebRTC samplesSelect sources & outputsを利用することにします。 ここでは、webcamを選択することができます。 ちなみに、現時点ではwebcamを選択するまでもなくエラーになってしまいます。

エラーにつながる箇所を特定する

広大なFirefoxのソースコードベースの中で、getUserMediaでそもそもエラーになってしまう箇所の当たりを付けるのは大変なはずですが、 third_party/libwebrtc以下にしかwebcamを認識するロジックはないはずなのと、 おそらくVideo4Linix2のioctlでエラーになっていて、それによりwebcamを選択するまでもなくエラーになっているはずということは当たりがついています。 なので、third_party/libwebrtc以下にあるmoz.buildを読んで、NetBSDである場合にbuildされるsource codeのうち、ioctlでVIDIOC_*を第2引数に与えている箇所を探せば良さそうと思いました。

と言うことは、grep -r "ioctl.*VIDIOC_" ${WRKSRC}/third_party/libwebrtcを実行した上で、moz.buildと照合すれば良さそうです。

$ ugrep -r "ioctl.*VIDIOC_" third_party/libwebrtc
third_party/libwebrtc/modules/video_capture/linux/device_info_v4l2.cc: (snip)
(snip)
third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc: (snip)
(snip)

moz.buildを見るまでもなく、NtBSDでも使っているファイルです。 と言うことで、各ioctlの結果が分かるようにprintfを入れてbuildしてみました。

解析の結果と修正案

結果として、以下の188行目のioctlが返すfmtに返って来ている内容が想定外であり、そのために全てのwebcamが認識されなっくなっていました。

$ cat -n third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc
(snip)
   181    // Enumerate image formats.
   182    struct v4l2_fmtdesc fmt;
   183    int fmtsIdx = nFormats;
   184    memset(&fmt, 0, sizeof(fmt));
   185    fmt.index = 0;
   186    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   187    RTC_LOG(LS_INFO) << "Video Capture enumerats supported image formats:";
   188    while (ioctl(_deviceFd, VIDIOC_ENUM_FMT, &fmt) == 0) {
   189      RTC_LOG(LS_INFO) << "  { pixelformat = " << GetFourccName(fmt.pixelformat)
   190                       << ", description = '" << fmt.description << "' }";
   191      // Match the preferred order.
   192      for (int i = 0; i < nFormats; i++) {
   193        if (fmt.pixelformat == fmts[i] && i < fmtsIdx)
   194          fmtsIdx = i;
   195      }
   196      // Keep enumerating.
   197      fmt.index++;
   198    }
(snip)

更に良く見ていくと、以下のように最初はioctl(fd, VIDIOC_QUERYCAP, &cap)でのみwebcamが利用可能か認識して使えるとなっているのに、この箇所でエラーになってしまうという流れになっており、これが想定外なようです。

$ cat -n third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc
    86    /* detect /dev/video [0-63] entries */
    87    int n;
    88    for (n = 0; n < 64; n++) {
    89      snprintf(device, sizeof(device), "/dev/video%d", n);
    90      if ((fd = open(device, O_RDONLY)) != -1) {
    91        // query device capabilities
    92        struct v4l2_capability cap;
    93        if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) {
    94          if (cap.bus_info[0] != 0) {
    95            if (strncmp((const char*)cap.bus_info,
    96                        (const char*)deviceUniqueIdUTF8,
    97                        strlen((const char*)deviceUniqueIdUTF8)) ==
    98                0) {  // match with device id
    99              close(fd);
   100              found = true;
   101              break;  // fd matches with device unique id supplied
   102            }
   103          }
   104        }
   105        close(fd);  // close since this is not the matching device
   106      }
   107    }
   108    if (!found) {
(snip)

と言うことで、最初からioctl(_deviceFd, VIDIOC_ENUM_FMT, &fmt)もチェックしておけば良さそうです。

--- third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc.orig	2025-12-05 17:43:20.000000000 +0000
+++ third_party/libwebrtc/modules/video_capture/linux/video_capture_v4l2.cc
@@ -90,18 +90,28 @@ int32_t VideoCaptureModuleV4L2::Init(con
     if ((fd = open(device, O_RDONLY)) != -1) {
       // query device capabilities
       struct v4l2_capability cap;
+#if defined(VIDIOC_QUERYCAP)
       if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) {
         if (cap.bus_info[0] != 0) {
           if (strncmp((const char*)cap.bus_info,
                       (const char*)deviceUniqueIdUTF8,
                       strlen((const char*)deviceUniqueIdUTF8)) ==
               0) {  // match with device id
-            close(fd);
-            found = true;
-            break;  // fd matches with device unique id supplied
+            struct v4l2_fmtdesc fmt;
+            memset(&fmt, 0, sizeof(fmt));
+            fmt.index = 0;
+            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+            if (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) == 0) {
+              if (fmt.pixelformat != 0) {
+                close(fd);
+                found = true;
+                break;  // fd matches with device unique id supplied
+              }
+            }
           }
         }
       }
+#endif
       close(fd);  // close since this is not the matching device
     }
   }

とりあえず、pkgsrc/www/firefoxを146.0にアップデートする際には含めておきたいと思います。 ですが、そもそもこのwebcamのvideo0とvideo2をサポートした方が良いかもしれません。

NetBSD/amd64上でFree Pascalでプログラムを書いてみる

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

Free Pascalとは?

Free Pascalとは、オープンソースのPascalとObject Pascalコンパイラーで、 オリジナルのPascal言語だけでなく、Turbo PascalのPascal言語やDelphiのObject Pascal言語もサポートしているようです。

私はPascalの熱心なユーザーであったことはないのですが、書籍の中では疑似コードとしてPascal風のソースコードを目にしたことは数多くあります。

Free Pascalとしては、NetBSDをサポートしていたようなのですが、pkgsrcには取り込まれていなかったようです。 Free Pascalコンパイラーを使っている人にとっては当たり前なのかもしれませんが、NetBSD上でコンパイルする場合に 必要だった事項を記載しておきたいと思います。

Free Pascalコンパイラーをインストールする

NetBSD/amd64でFree Pascalコンパイラーのバージョン3.2.2を利用することができます。 pkgsrc/lang/fpcとしてインポートされており、 Free Pascalのコンパイラーは、/usr/pkg/bin/fpcとしてインストールされます。 以下のように実行してインストールすれば良いでしょう。

# cd /usr/pkgsrc/lang/fpc
# make install

また、以下のように実行すると、fpcのバージョンを確認することができます。

$ fpc
Free Pascal Compiler version 3.2.2 [2025/12/08] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
fpc [options] <inputfile> [options]
 Only options valid for the default or selected platform are listed.
(以下略)

初期設定

まず、Free Pascalでプログラミングするために使うディレクトリーを作り、そのディレクトリーへ移動します。

$ mkdir free-pascal
$ cd free-pascal

次に、以下のように実行して、fpc.cfgという設定ファイルを作成します。 これがfpcコマンドの実行時に参照されるファイルで、この中で標準的な設定が定義されています。 個々をコマンドライン引数でfpcへ渡しても良いのかもしれませんが、 繰り返し入力するには、相当長いコマンドライン引数になりそうです。

$ fpcmkcfg -d basepath=/usr/pkg/lib/fpc/3.2.2 > fpc.cfg

サンプルプログラムをコンパイルしてみる

Hello worldは、以下のように書けば良いようです。 hello.pasとして保存しておきます。

program Hello;
begin
  writeln ('Hello, world.');
end.

以下のようにコンパイルし、実行します。

$ fpc hello.pas
$ ls hello*
hello hello.o hello.pas
# ./hello
Hello, world.

もう少し複雑なものとして、階乗を再帰で実装してみます。 factorial.pasとして保存しておきます。

program factorial;

function fact(n: integer): longint;
begin
    if (n = 0) then
        fact := 1
    else
        fact := n * fact(n - 1);
end;

var
    n: integer;

begin
    for n := 0 to 16 do
        writeln(n, '! = ', fact(n));
end.

以下のようにコンパイルし、実行します。

$ fpc factorial.pas
Free Pascal Compiler version 3.2.2 [2025/12/08] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: NetBSD for x86-64
Compiling factorial.pas
Linking factorial
17 lines compiled, 0.1 sec
$ ls factorial*
factorial       factorial.o     factorial.pas
$ ./factorial
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184

おわりに

Pascalコンパイラーとしては、pkgsrcにはGNU Pascal Compiler (GPC)もpkgsrc/lang/gpcとして収録されているようです。 こちらもいずれ使ってみたいと思います。

NetBSD-currentのwscons(4)で256色表示を試してみる

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

2025年11月2日のniaのコミットで、 wscons(4)でのVT100エミュレーションで、256色表示がサポートされました。 NetBSD/amd64-currentで実際に確認してみました。

今回は、VMware Workstation Pro 25H2 for Microsoft WindowsでNetBSD/amd64-currentを動かしてみました。

これでw3mでウェブブラウジングした際に便利だろうと思ったのですが、Google検索がw3mで利用できなくなってしまったため、 あまり役立てることができていません。

NetBSDでFPAG開発を始めてみる(NVCとVHDL)

この記事は、 NetBSD Advent Calendar 2025 の25日目の記事です。 はじめに 本当は、PyRTLで書いたロジックをTnag Nano 9Kで動かしてみたいのですが、これから勉強しないといけないので、しばらく先に進めそうにありません。 ...