ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

multichannel descriptor

Verilogの規格書を見ていたら面白い機能を見つけました。他の言語で見たことが無い機能なので紹介します。

Verilog の$fopenはCのfopenと同じように、ファイル名とファイルタイプを指定して呼び出します。戻り値multichannel descriptorはintegerで受けます。

integer fd1, fd2, fd3;
fd1 = $fopen("foo.txt", "w");
fd2 = $fopen("baa.txt", "w");

ここまでは普通の言語と同じですが、Verilogではmultichannel descriptorのorを取る事ができます。

fd3 = fd1 | fd2;
$fdisplay(fd3, "hello");

fd3を使った出力はfd1(foo.txt)、fd2(baa.txt)の両方に同じ値を出力します。またfd3 = fd1 | fd2 | 1;と1とのorを取ることで標準出力にも表示するようになります。ちなみにveritakでの実装を見てみるとfd1は0x00000008、fd2は00000010の値になりました。

Verilog2005の規格書(IEEE Std 1364.-2005)17.2.2 File output system tasksに例があります。この機能を使うと、各ブロックのログとシミュレーション全体のログを綺麗に書き分けることが出来ます。

integer
	messages, broadcast,
	cpu_chann, alu_chann, mem_chann;
initial begin
	cpu_chann = $fopen("cpu.dat");
	if (cpu_chann == 0) $finish;
	alu_chann = $fopen("alu.dat");
	if (alu_chann == 0) $finish;
	mem_chann = $fopen("mem.dat");
	if (mem_chann == 0) $finish;
	messages = cpu_chann | alu_chann | mem_chann;
	// broadcast includes standard output
	broadcast = 1 | messages;
end

broadcastを使ったときは全てのファイルと標準出力にメッセージを出します。

$fdisplay( broadcast, "system reset at time %d", $time );
$fdisplay( messages, "Error occurred on address bus",
" at time %d, address = %h", $time, address );
forever @(posedge clock)
	$fdisplay( alu_chann, "acc= %h f=%h a=%h b=%h", acc, f, a, b );

私はログは出すだけ出してPerlで切り分けていたのですが、この機能を使うと別にプログラムを作らなくてもよさそうです。