はじめに
大変ご無沙汰しております。@mizutomo と申します。本当に久しぶりに文を書いています。どれぐらい久しぶりかというと、Qiitaに記事を書くときに、右側にプレビューがon the flyで出てきているのに、びっくりした、というレベルです。
ところで、ランダム検証ってされていますか? 僕は、論理屋じゃないので、使ったこともないです。でも、たまに乱数は使いたくなるんですよね。それで、SystemVerilogで正規分布を生成する関数は。。。。とググったら、「えっ、ないやん><」。
うそ〜ん。ランダム検証とか言ってるぐらいだから、乱数周りに関しては、めちゃくちゃ充実していると思ってた。。。
「安心して下さい。使えます。」
はい。単純にDPI-Cを使えばいいんですね。ないものは、自分で作って組み込め、というのが、SystemVerilogの精神のようです(本当?)。
DPI-Cに関しては、この本を参照して下さい。SystemVerilog設計スタートアップ DPI-Cに関しては、@Vengineer 先生が丁寧に書かれています。
正規分布の生成
さて、乱数を生成する関数は、C言語による乱数生成 こちらのサイトから借用させて頂きます。Mersenne-Twister法を解説されていたりして、非常に助かります。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <svdpi.h>
double uniform() {
return ((double)rand() + 1.0)/((double)RAND_MAX + 2.0);
}
double rand_normal(double mu, double sigma) {
double z = sqrt(-2.0 * log(uniform())) * sin(2.0*M_PI*uniform());
return mu + sigma*z;
}
ここでは、乱数の生成にCのrand()関数を使っています。先ほどのサイトや、Numerical Recipesに解説があるように、Cのrand()関数は、周期性を持った乱数列なので、実用には適しません。実用としては、メルセーヌ-ツイスター法がいいんでしょうかね。
で、実際にSystemVerilogと絡むところって、**#include <svdpi.h>**を置いたぐらいですよね。
正規分布を呼ぶ側
次は、先ほどのCのコードを呼ぶSystemVerilogのコードです。
`timescale 1ns/1ns
import "DPI-C" pure function real rand_normal(real mu, real sigma);
module test();
real rand_val;
int i;
initial begin
for (i = 0; i < 10; i++) begin
rand_val = rand_normal(0, 1);
$monitor("%d: %g", i, rand_val);
#10;
end
$finish;
end
endmodule
おっふ、めちゃくちゃ簡単じゃないですか。実質、Cコードを呼ぶためにやったことは、**import "DPI-C"**としたことぐらいです。
あとは、シミュレータ側で勝手にCのコードをコンパイルして、実行ファイルを作ってくれます。
(昨日、とあるシミュレータで実行したら、稀に共有ライブラリが作成されないことが。そのようなときは、手動で共有ライブラリを作ればよいです。@ginnyu_tei さんの記事が参考になります。)
何に使うの?
私の場合は、デバイス雑音などの効果をデジタルシミュレーションに入れ込むときに、このような方法を使っています。例えば、Kundert先生がVerilog-AMSでモデリングしているVCOの位相雑音のモデルをVerilogで使用する場合ですね。Verilog-AMSには、$rdist_normalというシステムタスクが用意されているので、何も考えずに、正規分布が使えちゃうのですが、それと同じことをVerilogでやろうとすると、、、自分で作らないといけないようです。
何で、Verilog-AMSでできているものを、Verilogシミュレータでやる必要があるの?というと、やっぱり、Verilogシミュレータは高速なんですよね。AMSシミュレータに比べると。でも、HDLシミュレータは、Δ遅延があるので、嫌いです。
ところで、DPI-Cは本当に便利ですね。これだけでも、Verilog HDLを捨てて、SystemVerilogに切り替えるというメリットが有るんじゃないかと思います。みんなが大好きPythonとつなぐのも簡単ですよね〜。ということで、そのうち、誰かがSystemVerilogとPythonをつなぐ記事を書いてくれると期待しています。自分は書きません。
余談
昨日、とあるシミュレータにポーティングしていたのですが、SVには、$absもなかったんですね。かなりびっくりしました。