SystemVerilogのパラメータ付きクラスを試してみた(解決編)
SystemVerilogのパラメータ付きクラスを試してみたを更新してから
Twitterで「Baseクラス作ったらpushできる」と教えて頂き解決しました。
修正したコード
module top(); class c_hoge_base; //Baseクラス追加 virtual function void print(); endfunction endclass //Baseクラス継承 class c_hoge #(int k = 0) extends c_hoge_base; function void print(); //Warning対策にvoidを追加 $display("k = %d",k); endfunction endclass:c_hoge //型をBaseクラスにする c_hoge_base q_c_hoge[$]; c_hoge_base h_c_hoge[*]; c_hoge_base i_c_hoge_base; initial begin c_hoge#(0) i0_c_hoge; c_hoge#(1) i1_c_hoge; c_hoge#(2) i2_c_hoge; c_hoge#(3) i3_c_hoge; i0_c_hoge = new(); i1_c_hoge = new(); i2_c_hoge = new(); i3_c_hoge = new(); i0_c_hoge.print(); i1_c_hoge.print(); i2_c_hoge.print(); i3_c_hoge.print(); q_c_hoge.push_back(i0_c_hoge); h_c_hoge["hoge0"] = i0_c_hoge; q_c_hoge.push_back(i1_c_hoge); h_c_hoge["hoge1"] = i1_c_hoge; $display("pop_front"); i_c_hoge_base = q_c_hoge.pop_front(); i_c_hoge_base.print(); i_c_hoge_base = q_c_hoge.pop_front(); i_c_hoge_base.print(); $display("hash table"); h_c_hoge["hoge0"].print(); end endmodule
実行結果
# k = 0 # k = 1 # k = 2 # k = 3 # pop_front # k = 0 # k = 1 # hash table # k = 0
これでパラメータ付きクラスでもキューや連想配列に入れる事が出来ました。
後、newの引数でいいじゃんというツッコミも頂いたので私の使用例を載せました。
このコードでやりたい事は
- モジュールtest_modelをgenerateで複数インスタンス
- test_model内にはtaskが宣言されていてこれをクラスから参照したい。
- writeタスクは手が入れれないのでパス指定で呼び出すしかない。(writeタスクをクラスに移動できるならこんな事しなくても大丈夫ですが・・・)
- できるだけループ宣言を使って記述を減らしたい(ただしこの例では減らせませんでした^^;
後、enumと連想配列使ってクラス配列を任意の文字列で呼び出すのが
どのモデルにつながっているか見わかりやすくて好きなので使っています。
typedef enum { test_model_A, test_model_B, test_model_C, test_model_D, test_model_E } e_model_name; parameter MODEL_NUM = 5; /*************test_module**************/ /*変更できないモデル*/ module test_model(); task write(int a); $display("test_model write task %d",a); endtask endmodule : test_model /***************prg_top*****************/ module prg_top(); class piyo_base; virtual task start(); endtask virtual task exec(); endtask endclass class piyo#(e_model_name k = test_model_A) extends piyo_base; int m_val; e_model_name m_e_model_name; function new(int val); m_val = val; m_e_model_name = k; endfunction task start(); $display("start : This Class %s , m_val = %0d",m_e_model_name,m_val); endtask task exec(); $display("exec : This Class %s , m_val = %0d",m_e_model_name,m_val); $root.top.model_loop[k].i_test_model.write(m_val);//ここのkはパラメータでないとダメ(変数は使えない) endtask endclass piyo_base piyo_h_array[e_model_name]; piyo#(test_model_A) i_piyo0; piyo#(test_model_B) i_piyo1; piyo#(test_model_C) i_piyo2; piyo#(test_model_D) i_piyo3; piyo#(test_model_E) i_piyo4; initial begin i_piyo0 = new(10); i_piyo1 = new(20); i_piyo2 = new(30); i_piyo3 = new(40); i_piyo4 = new(50); piyo_h_array[test_model_A] = i_piyo0; piyo_h_array[test_model_B] = i_piyo1; piyo_h_array[test_model_C] = i_piyo2; piyo_h_array[test_model_D] = i_piyo3; piyo_h_array[test_model_E] = i_piyo4; $display("\n-----start task-----"); foreach (piyo_h_array[i]) begin piyo_h_array[i].start; end $display("\n-----exec task-----"); piyo_h_array[test_model_B].exec; piyo_h_array[test_model_C].exec; $finish; end endmodule:prg_top /***************top*****************/ module top(); generate genvar i; for(i=0; i<MODEL_NUM;i=i+1)begin : model_loop test_model i_test_model(); end endgenerate prg_top i_prg_top(); endmodule : top
実行結果
# # -----start task----- # start : This Class test_model_A , m_val = 10 # start : This Class test_model_B , m_val = 20 # start : This Class test_model_C , m_val = 30 # start : This Class test_model_D , m_val = 40 # start : This Class test_model_E , m_val = 50 # # -----exec task----- # exec : This Class test_model_B , m_val = 20 # test_model write task 20 # exec : This Class test_model_C , m_val = 30 # test_model write task 30 # ** Note: $finish : E:/altera/13.0/test/test2.sv(81)
i_piyo0~i_piyo4までの宣言をループ内に入れる事が出来ればもっと
コードが短くなると思いますがやり方が思いつきませんでした。
そもそもこんなやり方しなくてももっと良い方法があるかも・・・
7/4追記:
コメントで指摘してもらったdefineマクロで
i_piyo0~i_piyo4が簡潔にならないか試してみました。
//マクロ定義 `define PIYO_INSTANCE(val) piyo#(val``) i_piyo``val``; `define PIYO_SET(val,init) i_piyo``val`` = new(init``); \ piyo_h_array[``val``] = i_piyo``val``; //宣言(一部抜粋) `PIYO_INSTANCE(0) //piyo#(test_model_A) i_piyo0; `PIYO_INSTANCE(1) //piyo#(test_model_B) i_piyo1; `PIYO_INSTANCE(2) //piyo#(test_model_C) i_piyo2; `PIYO_INSTANCE(3) //piyo#(test_model_D) i_piyo3; `PIYO_INSTANCE(4) //piyo#(test_model_E) i_piyo4; initial begin `PIYO_SET(0,10) //i_piyo0 = new(10); piyo_h_array[test_model_A] = i_piyo0; `PIYO_SET(1,20) //i_piyo1 = new(20); piyo_h_array[test_model_B] = i_piyo1; `PIYO_SET(2,30) //i_piyo2 = new(30); piyo_h_array[test_model_C] = i_piyo2; `PIYO_SET(3,40) //i_piyo3 = new(40); piyo_h_array[test_model_D] = i_piyo3; `PIYO_SET(4,50) //i_piyo4 = new(50); piyo_h_array[test_model_E] = i_piyo4;
ちょっと記述は少なくなったかな?
本当は↓の様にループで書ければ良かったのだが残念ながらエラーになりました。
generate genvar j; for(j=0; j<MODEL_NUM;j=j+1)begin : model_loop `PIYO_INSTANCE(j) end endgenerate