3.19 トレースモード

ソースデバッグモードより、詳細にWaveformView表示を行います。
本モードでは、

が可能になります。非常に便利なモードでRTLのデバッグに威力を発揮します。例で見ていきましょう。



トレースモードの設定

プロジェクト設定を、Trace Debug Modeにしてコンパイルします。









WaveformView上の変化点に対応するソース行へのジャンプ


サンプルフォルダに 「1.24の新機能テストその1.prj」というプロジェクトファイルがありますので、それをロードプロジェクト=>Goします。
 すると、次の画面となります。(Version1.24から、作業環境のResotoreが簡単になりました。)


このソースは、以下です。

//Aug.20.2004
//

`timescale 1ns/1ps

module parameter_list_test;
        parameter  dast0=3'd0,dbst=3'd2,dcst=4'd5;

        parameter [3:0] Recovery_mode=3'd0,Trigger_mode=3'd1,Rotate_mode=3'd2,Burst_Error_mode=3'd3;
        parameter [3:0] dummy1=4'b0000;
        parameter [7:0] as=3'd0,bs=3'd1;
        parameter [7:0] ast0=3'd0,bst=3'd2,cst=3'd5;
        parameter [3:0] Astate0=4'h0,Bstate1=4'h1,asx=4'bxxxx,asz=4'bzzzz,
                                    as2=4'h2,as3=4'h3,as4=4'h4,as5=4'h5;
        parameter [1:0] ap0=0,ap1=1,ap2=2;
        parameter [1:0] bp0=0,bp1=1;
        parameter [1:0] cp0=0,cp1=1;
        parameter [1:0] dp0=0,dp1=1;


        reg [3:0] a;
        reg clock=0;
        reg [60*8:1] str;
        reg find_check=0;
        reg zx_sig;
        always #10 clock =~clock;
        initial begin
                $sformat(str,"Veritak Ver.1.24のテストを開始しよう。%3d",$time);
                $display("%s",str);
                zx_sig=1'bx;
                #100
                zx_sig=1'bz;
                #100
                zx_sig=1'b0;
                #100
                zx_sig=1'b1;
                a=Recovery_mode;
                #10
                a=Trigger_mode;
                #10
                a=Rotate_mode;
                #10
                $sformat(str,"Ver.1.24ではドライバへのJUMPが追加されました。%3d",$time);
                $display("%s",str);
                a=Recovery_mode;
                #10
                a=Trigger_mode;
                #10 a=Astate0;
                #10 a=Bstate1;
                #10 a=asx;
                #10 a=asz;
                #10 a=as2;
                #10 a=as3;
                #10 a=as4;
                #10 a=as5;
                #10 a=Recovery_mode;
                #1000;
                #100 a=Astate0;
                #100 a=Bstate1;
                #100 a=asx;
                #100 a=asz;
                $sformat(str,"正確なDRIVERを示すとは限りませんが、役にたつでしょう?%3.1f",$realtime);
                #20
                         a=Rotate_mode;
                #20
                          find_check=1;
                #20
                        find_check=0;
                #20 
                        find_check=1;
                #20
                        find_check=0;
                #20
                        find_check=1;
                #100 a=Burst_Error_mode;
                        $sformat(str,"Version1.24では、parameterのTOOLTIPも付加されました。%3.2f",$realtime);
        
                #100 a=Trigger_mode;
                         find_check=0;
                #100 a=Recovery_mode;

                $sformat(str,"Version1.24では、RESOLVERのJUMPも追加になりました。%3.2f",$realtime);

                #100 a=Trigger_mode;
                #100;
                $sformat(str,"以上は、TraceModeで利用可能です。%4d",$time);

                #1000 $finish;
        end

        
        sub sub0(clock,a);
        sub sub1(clock,a);
        sub sub2(clock,a);
        sub sub3(clock,a);

        
endmodule
module subsub(clock,a);
        parameter  dast0=3'd0,dbst=3'd2,dcst=4'd5;

        parameter [3:0] Astate0=4'h0,Bstate1=4'h1,asx=4'bxxxx,asz=4'bzzzz,
                                    as2=4'h2,as3=4'h3,as4=4'h4,as5=4'h5;
        parameter[3:0] Recovery_mode=4'h0,Trigger_mode=4'h1,Rotate_mode=4'h2,Burst_Error_mode=3;        
        parameter RRmode=4'h0,TRIGGER_MODE=4'h1,ROTATE_MODE=4'h2,BURST_ERROR_MODE=4'h3;

        input clock;
        input [3:0] a;
        wire [3:0] a_func_result=a_func(a);
                function [3:0] a_func;
                        input [3:0] a;
                        case (a)
                                RRmode:a_func=Astate0;
                                TRIGGER_MODE:a_func=Bstate1;
                                ROTATE_MODE:a_func=as2;
                                BURST_ERROR_MODE:a_func=as3;
                                default:a_func=asx;
                        endcase
                endfunction

        
endmodule

module sub (clock,a);
        parameter  dast0=3'd0,dbst=3'd2,dcst=4'd5;

        parameter [3:0] Astate0=4'h0,Bstate1=4'h1,asx=4'bxxxx,asz=4'bzzzz,
                                    as2=4'h2,as3=4'h3,as4=4'h4,as5=4'h5;
        parameter[3:0] Recovery_mode=4'h0,Trigger_mode=4'h1,Rotate_mode=4'h2,Burst_Error_mode=3;        
        input clock;
        input [3:0] a;
        
        reg [1:0] resolve_source;
        reg [7:0] counter=0,bcounter=10;
        wire [1:0] resolve_wire;
        integer i;

         assign resolve_wire=2'b11;
        assign resolve_wire=resolve_source;



        initial begin
                resolve_source=2'b00;
                #100
                resolve_source=2'b11;
                #100
                resolve_source=2'bxx;
                #100
                resolve_source[0]=1;//Driver ソース行へジャンプしたところです。
                #100
                resolve_source=2'b01;
                #100
                resolve_source=2'bzz;
                #100
                resolve_source=2'b10;
                #100
                resolve_source=2'b11;
                
                for (i=0;i<100;i=i+1) begin
                        resolve_source=i;
                        #100;
                end

        end

        always @(posedge clock) begin
                if (counter==100) counter<=0;
                else if (counter==44) counter<=counter+10;
                else if (counter==88) counter<=counter+8;
                else if (counter==12) counter<=bcounter;
                else counter <=counter+1;
        end

        always @(posedge clock) bcounter<=bcounter+1;   

        wire [3:0] a_func_result=a_func(a);
                function [3:0] a_func;
                        input [3:0] a;
                        case (a)
                                Recovery_mode:a_func=Astate0;
                                Trigger_mode:a_func=Bstate1;
                                Rotate_mode:a_func=as2;
                                Burst_Error_mode:a_func=as3;
                                default:a_func=asx;
                        endcase
                endfunction

                subsub totemonagai_instance_mei_nobaai_tooltip_wo_shukushousuru1(clock,a);
                subsub totemonagai_instance_mei_nobaai_tooltip_wo_shukushousuru2(clock,a);
endmodule

[3:0]a のScope列を右クリックして「エディタ ドライバ記述へ飛ぶ」とするとT1カーソル(この画面では、黄色のカーソル)時刻に対応するドライバ箇所に飛びます。




この場合、宣言箇所に飛んでいますが、この時刻では、まだ、代入記述がされていないためです。T1カーソルをずらして、再び「エディタ ドライバ記述へ飛ぶ」とすると、


代入箇所に飛んで行きます。Recover_modeをダブルクリックしてみましょう。(”Recovery_mode”は、パラメータですが、Version1.24からツールチップ表示を可能にしました。)




同様にして、T1カーソルを動かして、任意時刻の、任意信号のドライバ記述に飛ばすことができます。たとえば、下の信号clockは、2階層下(totemonagai..)インスタンスのclock(入力信号)をViewに追加したものです。これで、飛ばすと、TOP層のclock記述箇所に飛んできます。つまり、ドライバは、TOP層で宣言したreg clockであり、2階層下のclockは、それを参照(線でつながっている信号を観測)したという風に理解できます。同じ線でつながっていながら、親と子で名前が違うのは、よくあることです。この機能で、ドライバ(その値を駆動している者)をすぐに特定することができます。



Note:
   任意時刻というのは、正確でありません。$strobeでサンプルされる任意時刻が正しい表現です。


次の例は、Vector信号で飛び先が分かれている例です。信号選択と、T1カーソルを下の図の位置として、ドライバへ飛ばすと、飛び先が分かれていると言われますので、ダブルクリックしてビット展開してください。




ビット展開して飛ばすと、対応記述に飛んできました。2'bxxの後、[0]ビットを1にしている記述ですが、Waveformviewと記述が対応していることが分かります。



次の例は、リゾルバです。[1:0]resolve_wireで、飛ばすと、ビット展開、リゾルバの展開の催促の後、次の画面となります。確かに、resolve_wireという信号は、下の記述のように、二つの信号でドライブされています。VerilogHDL シミュレータでは、、一つの信号名に、二つ以上のドライブソースがあるとき、内部的には、リゾルバで表現しています。


この例の場合、リゾルバはの入力は、constant値の1と、resolve_source信号になります。



出力は、reoslve_wireになります。通常観測できるのは、名前がついているResolverの出力だけですが、トレースモードでは、ダブルクリックすることで、Resolverの入力状態を出力できます。(Reoslverの入力は、たとえば、constant値だったり、a&bの結果だったりして名前がついていないこともあります。その場合は、Resolverという仮想の名前にしています。
 Resolverの論理は、streangthが同じ場合、以下の論理となります。要は、0/1の値が違っていたらx、01/zでは、01が勝ち、01/xでは、xが勝つということです。Waveform上で、Resolverの入力と出力の論理を確認してみてください。


0 1 x z
0 0 x x 0
1 x 1 x 1
x x x x x
z 0 1 x x




<xの解析方法>


どうしてxになっているのが、不明なときがあります。その場合は、Findpatternで、最初のxを見つけて、Resolverの入力を追っていけばいいのです。Resolverの入力は、前述のように必ずしも名前はついていませんが、該当行には飛んでゆきます。そこで、


もう一つの例 Editor-Tree-Scopeの対応例

カーソルを少し前に移動させ、counter 22で飛ばして、counterの値をToolTipで表示しました。(下画面)



確かに、counterは、22になっています。しかし、bcounterをToolTipさせて見ると、


23になっています。そこで、bcounterをWaveformViewに追加します。

WaveformView:counterの下にbcounterが追加されました。選択直後は、defaultHex表示のため17になっていますが、前のクロックを見るとHex16=22decimalになっており、確かに、counterが12から22になったのは、bcounterの値をNon-Blocking文でLoadした結果であることが分かりました。

ソースデバッグモードとの違いをまとめると、下表になります。

ソースデバッグモード(Default:従来) トレースモード(新設)
EditorTooltip
時刻
シミュレーションエンジンが生きている間の現在値を指します。シミュレーションエンジンが終了するとToolTipはでません。 T1カーソルの時刻を指します。シミュレーションエンジンが終了していてもOKですが、T1カーソルが出ていないと時刻が指定されないため、Tooltipはでません。
インスタンス ScopeTreeViewと連動していません。ファイル名と行番号から推定されるインスタンス全部を表示、追加になります。 ScopeTreeViewと連動しています。インスタンスが一つに限定されるため、波形追加もインスタンスを指定した形で限定的に行え、よりトレースしやすくなります。ただし、選択されていないScopeのソースを指定しても無視されます。従いViewからEditorに行くようにしてください。
速度 1とします。 2-3倍に遅くなります。RTL記述によります。
メモリ消費量 1とします。 2-3倍になります。RTL記述によります。
SDF 小規模なら、可能です。 内部でトレースモードはDisableされます。
付加Scope ありません。 Resolve_Scopeという名前のScopeが、TreeViewに表示されます。
これは、Veritak内部で使用しているもので、無視してください。
トレースモードが安定したら、将来、外します。


トレースモードについて

他のシミュレータとの違いは、あらかじめ、トレース信号を限定しなくていいことです。その代わり、Veritakは、内部ノードの回路図出力機能等は、もっていませんし、$strobeにいたる途中経過の出力機能(バックトレース)もありません。名前のない信号を追いかけるより名前のある信号をすぐ見れた方が効率的なRTLデバッグができるのではないか、と思います。