はじめに
前回の記事……見ました?
なんですかね、UVMやるとか言っておきながら、結局最後まで一ミリもそんな要素なかったじゃないですか。おい、責任者をだせ!詐欺師め!「UVM」って単語さえ出しておけば、RTL界隈からページビューが稼げて広告収入、アフィリエイトでウハウハ、不労所得で人生勝ち組、早期リタイアでついに半導体業界から足を洗えるぜ……とか考えていたんだろ!ほら、白状しろ!1
……っというわけで、はい、じゃあ今日の授業はじめまーす、みんな席についてー
UVMテストベンチの構成(一般論)
なにこれぇ。
ええ、そうです、これがUVMの一般的な構成として紹介される、いつものやつです。もうね、この時点でね、やる気なくしちゃうじゃないですか。なにこれ、私は一体これからどれだけ沢山のことを、この「UVM」とやらのために学ばないといけないわけ? こんなんやってたら、私のワークライフバランス壊れちゃうよぉ2……ふぇぇ、ってね。
Pankaj S. Vitankar - UVM ARCHITECTURE FOR VERIFICATIONから引用
UVMテストベンチの構成(お手軽UVM)
一方で、今回私たちが作るテストベンチがこちら。
わお、驚きの白さ。Testの中に何もありません。Environment?Agent?SequenceにDriver、Monitor?そんなものは世界の果てに置いてきた。ここにあるのは、ほとんど空っぽのTestコンポーネント、ただそれだけだ。
テストベンチ
私たちが今回作るテストベンチの大体のカタチが分かったところで、さっそくコーディングを始めていきましょう。
コードを書き終わったあと、時間があればぜひ、前回の記事で紹介した従来型のモジュールベースのテストベンチと比較しながら、コード全体を少し眺めてみてください。きっと、(何だかよくわからない儀式めいた呪文が各所でちょいちょい使われている以外は)前回のモジュールベースのテストベンチと大差ない……と感じると思います3。
そうそう、こわくない、こわくないよー。UVMはこわくないからねー。
そーっと、そーっと近づいてなでなでして仲良くなろうねー
module top;
timeunit 1ns;
timeprecision 1ps;
`include "uvm_macros.svh"
import uvm_pkg::*;
parameter realtime clk_period = 1ns;
bit clk = 1'b0;
initial begin
forever begin
#(0.5*clk_period);
clk = ~clk;
end
end
logic d;
logic rstn;
logic q;
DFF dut (
.D(d),
.CLK(clk),
.RSTN(rstn),
.Q(q)
);
initial begin
run_test();
end
class simple_test extends uvm_test;
`uvm_component_utils(simple_test)
function new (string name="simple_test", uvm_component parent=null);
super.new(name, parent);
endfunction
parameter realtime output_skew = 0.2ns;
virtual task run_phase (uvm_phase phase);
phase.raise_objection(this);
`uvm_info(get_type_name(), "Started", UVM_MEDIUM)
@(posedge top.clk);
#(output_skew);
top.d <= 1'b0;
top.rstn <= 1'b0;
`uvm_info(get_type_name(), "RSTN = 0", UVM_MEDIUM)
@(posedge top.clk);
#(output_skew);
top.rstn <= 1'b1;
`uvm_info(get_type_name(), "RSTN = 1", UVM_MEDIUM)
@(posedge top.clk);
#(output_skew);
top.d <= 1'b1;
`uvm_info(get_type_name(), "D = 1", UVM_MEDIUM)
@(posedge top.clk);
#(output_skew);
top.d <= 1'b0;
`uvm_info(get_type_name(), "D = 0", UVM_MEDIUM)
repeat (2) begin
@(posedge top.clk);
end
`uvm_info(get_type_name(), "Finished", UVM_MEDIUM)
phase.drop_objection(this);
endtask
endclass
endmodule
DSimの実行スクリプト
シミュレーション実行時に必要なオプションがちょっと増えました。具体的には、下記のoptions.txt
の// UVM
と書いてあるあたりです4。今回はUVM-1.2を使っていますが、どうやらお高い商用シミュレータでは「UVM 2020-2.0」というのもしっかり内蔵されていて簡単に選べるらしいです5。え?UVMのVersionごとの細かい違いは何かって?うーん、オラァ難しいことはよくわがんねぇだ。だがら業界標準として普及してそうな「UVM-1.2」のほうにしておくだぁ。
// DSim
-top top
+acc
-waves waves.vcd
// UVM
-suppress IneffectiveDynamicCast:MissingTimescale
-uvm 1.2
+UVM_NO_RELNOTES
+UVM_TESTNAME=simple_test
+UVM_VERBOSITY=UVM_MEDIUM
// DUT
DFF.v
// Test bench
top.sv
@echo off
set "DSIM_LICENSE=%USERPROFILE%\AppData\Local\metrics-ca\dsim-license.json"
cd "%USERPROFILE%\AppData\Local\metrics-ca\dsim\20240923.7.0"
call shell_activate.bat
cd %~dp0
dsim -f options.txt
pause
exit
シミュレーション結果
run.bat
を実行すると、こんな感じの結果が得られます。
とりあえずなんかまぁ動いてるから、ヨシッ!
おわりに
今回はここまで!
実際のところ、これをUVMベースのテストベンチだと言い張るにはまだちょっと心もとないかもしれませんが、何はともあれ、UVMのライブラリを利用してテストパターンを流すことはできました。これは私たちにとって大きな一歩です。少なくとも、何もしないことより5000兆倍すばらしいです。すごい!UVMできてえらい!6
次回、「Virutal Interfaceを使って、もうちょっとモダンな感じに仕上げよう」
それでは、おつぺこでしたー、ばいばーい!7
2024/12/30 追記
本記事の投稿後、「package内からの階層参照がSystemVerilogの仕様に違反している」ことをご指摘いただきました89。DSimではなぜかコンパイルエラーになりませんでしたが、他のシミュレータだと仕様に従ってエラーを出すようです10。そのため、packageを使わない形にテストベンチを修正し、シミュレーション結果を更新しました。Thanks!
-
マジレスすると、こんな二ッチな世界でPVが稼げるわけないので特にメリットはないです。ほら、3年前に私が作ったこの動画、みてくださいよ。再生数360で……え?360!?一年で120再生、一か月で10再生もされてたってこと!?やべえな、この世界狂ってんな! ↩
-
訓練された半導体エンジニア「ワークライフバランス?ははっ、もちろん完璧ですよ、平日は家に帰ってから25時にちょこっと会議があるだけですし、土曜日も午前中にレビューがあるだけ。日曜日だって、重たいシミュレーションを裏で流しながら無料のE-leaningをだらだら流し見しているだけだし……特に何もやってないかな。それに、月曜日は向こうがまだ日曜で半分休みみたいなもんで、邪魔が入ることもなく自分の作業に集中できますしね。仕事なんてのはあんまりなくて、毎日ほとんど遊んでるみたいなもんですよ。」 ↩
-
UVMベースのテストベンチを初めて見た人は、この時点で、「
run_test()
の定義がどこにもなくね?」「これって結局、どういう仕組みでsimple_test::run_phase()
が呼び出されるの?」「ああああああああああ!!!!」「わけがわからないよ」「もぅマヂ無理。 リスカしょ」……となりがちですが、とりあえず今は細かいことは置いといて、「run_test()
を呼び出すと、背後で何か不思議な力が働き、uvm_test
を継承して作ったsimple_test
のrun_phase()
が勝手に呼ばれ、そこに記述されたテストパターンが流れ始める」くらいに思っておきましょう。 ↩ -
-suppress IneffectiveDynamicCast:MissingTimescale
は、なんかデフォでいろいろ警告が出てきてログが汚れるので勝手に付け足した部分です。「動けばいいんだよ、動けば」の精神で、とりあえずDynamicCastとTimescaleのWarningを-suppress
オプションで勝手にもみ消しちゃいました。てへぺろ。きっとそのうち、どこからともなくだれか心優しい親切な有識者がやってきて、このWarningがどうして出てくるのか、果たして無視していいものなのか……そっと私たちに教えてくれるはずです。インターネットは広いからね。きっとだれかが、この広大な世界のどこかでコメントしてくれることでしょう。知らんけど。 ↩ -
IEEE 1800-2017 SystemVerilog の「26.2 Package declarations」に、「パッケージ内から階層参照はできないよ」的なことが書いてあります。また、Verification Academy Forum の Illegal location for a hierarchical name (in a package) に、この問題に関連した質問と回答があります。 ↩
-
修正前のテストベンチを、DSimではなく、試しにAldec Riviera Pro 2023.04で実行してみたところ、
ERROR VCP7600 "A hierarchical reference found in a package as the first component of the dotted name ""top.d"" has not been found in the current scope of the package."
というエラーが表示されました。他のシミュレータでは仕様通り、package内からの階層参照が禁止されているようです。実際に試してみたい方のために、こちらにEDA Playgourndへのリンクを置いておきます。 ↩