bit [3:0] nibble[$];
integer mem[$][$];
time t1[10][$];
realtime t2[$][10];
longint t3[$][$];
module queue13f;
bit [3:0] nibble[$];
integer mem[$][$];
time t1[10][$];
realtime t2[$][10];
longint t3[$][$];
initial begin
$display("nibble.size()=%d",nibble.size());
$display("mem.size()=%d",mem.size());
$display("t1.size()=%d",t1.size());
$display("t1[0].size()=%d",t1[0].size());
$display("t2.size()=%d",t2.size());
$display("t3.size()=%d",t3.size());
end
endmodule
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 ***** nibble.size()= 0 mem.size()= 0 t1.size()= 10 t1[0].size()= 0 t2.size()= 0 t3.size()= 0 ---------- シミュレーションを終了します。time=0nst1は、time[$] を要素として10個(固定)持つ配列になります。この場合、10個は、実行前に確保されるので、10 の表示になります。しかし、要素の一つである、t1[0] についてみれば、[$] ですから、未だメモリは確保されずそのサイズは0になります。このように[$]次元では、実行時にメモリを確保してから使う必要があります。
module dynamic_array; bit [3:0] nibble[$]; integer mem[$][$];// [] ごとにnew が必要 integer mem_fixed[10][3]; time t1[2][$]; realtime t2[$][3]; longint t3[$][$]; int arr1 [$][2][3]; initial begin nibble=new [4]; foreach (nibble[i]) $display(" nibble[%1d]=%b",i,nibble[i]); $display(""); mem=new [10]; mem[1]=new [3]; foreach (mem[i,j]) $display(" mem[%1d][%1d]=%b",i,j,mem[i][j]); $display(""); foreach (mem_fixed[i,j]) $display(" mem_fixed[%1d][%1d]=%b",i,j,mem_fixed[i][j]); $display(""); t1[0]=new[3]; foreach (t1[i,j]) $display(" t1[%1d][%1d]=%b",i,j,t1[i][j]); $display(""); t2=new[4]; foreach (t2[i,j]) $display(" t2[%1d][%1d]=%f",i,j,t2[i][j]); $display(""); arr1=new[3]; foreach (arr1[i,j,k]) $display(" arr1[%1d][%1d][%1d]=%b",i,j,k,arr1[i][j][k]); end endmodule
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 *****
nibble[0]=0000
nibble[1]=0000
nibble[2]=0000
nibble[3]=0000
mem[1][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem[1][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem[1][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[0][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[0][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[0][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[1][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[1][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[1][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[2][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[2][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[2][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[3][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[3][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[3][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[4][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[4][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[4][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[5][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[5][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[5][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[6][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[6][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[6][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[7][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[7][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[7][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[8][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[8][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[8][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[9][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[9][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mem_fixed[9][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
t1[0][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
t1[0][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
t1[0][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
t2[0][0]=0.000000
t2[0][1]=0.000000
t2[0][2]=0.000000
t2[1][0]=0.000000
t2[1][1]=0.000000
t2[1][2]=0.000000
t2[2][0]=0.000000
t2[2][1]=0.000000
t2[2][2]=0.000000
t2[3][0]=0.000000
t2[3][1]=0.000000
t2[3][2]=0.000000
arr1[0][0][0]=00000000000000000000000000000000
arr1[0][0][1]=00000000000000000000000000000000
arr1[0][0][2]=00000000000000000000000000000000
arr1[0][1][0]=00000000000000000000000000000000
arr1[0][1][1]=00000000000000000000000000000000
arr1[0][1][2]=00000000000000000000000000000000
arr1[1][0][0]=00000000000000000000000000000000
arr1[1][0][1]=00000000000000000000000000000000
arr1[1][0][2]=00000000000000000000000000000000
arr1[1][1][0]=00000000000000000000000000000000
arr1[1][1][1]=00000000000000000000000000000000
arr1[1][1][2]=00000000000000000000000000000000
arr1[2][0][0]=00000000000000000000000000000000
arr1[2][0][1]=00000000000000000000000000000000
arr1[2][0][2]=00000000000000000000000000000000
arr1[2][1][0]=00000000000000000000000000000000
arr1[2][1][1]=00000000000000000000000000000000
arr1[2][1][2]=00000000000000000000000000000000
module queue14;
int arr1 [$][1][3] = new [2];
int arr2 [$][$] = new [2];
initial begin
$display("arr1.size()=%d",arr1.size());
$display("arr2.size()=%d",arr2.size());
end
endmodule
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 *****
arr1.size()= 2
arr2.size()= 2
---------- シミュレーションを終了します。time=0ns
上例の最後に下記を追加して、コールしてみます。
function void delete(); $display("delete method "); arr1.delete(); foreach (arr1[i,j,k]) $display(" arr1[%1d][%1d][%1d]=%b",i,j,k,arr1[i][j][k]); $display(""); t2.delete(); foreach (t2[i,j]) $display(" t2[%1d][%1d]=%f",i,j,t2[i][j]); $display(""); t1[0].delete(); foreach (t1[i,j]) $display(" t1[%1d][%1d]=%b",i,j,t1[i][j]); $display(""); mem[2]=new[3]; mem[1].delete(); foreach (mem[i,j]) $display(" mem[%1d][%1d]=%b",i,j,mem[i][j]); $display(""); endfunction
deleteされた次元の配列は、サイズが0になります。(foreachは、ループが周らなくなり表示されません。)
結果です。
mem[2][0]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx mem[2][1]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx mem[2][2]=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
4)代入
アンパックド配列間の代入が可能になっています。ただし、条件が二つあります。
下の例で見ましょう。
module queue16; int A[2][10:1]; int B[$] = new[10]; int C[$] = new[8]; int D [3][$][$]; `define GEN_ERROR initial begin D[2] = new [2]; D[2][0] = new [10]; D[2][1] = new [10];//LRM ERROR ? A[1] = B; // OK. Both are arrays of 10 ints `ifdef GEN_ERROR A[1] = C; // type check error: different sizes (10 vs. 8 ints) `endif A = D[2]; // A foreach (D[i,j,k]) $display(" D[%1d][%1d][%1d]=%b",i,j,k,D[i][j][k]); end endmodule
最初の
A[1] = B;
は、A[1]は、10個のint固定配列です。一方、Bは、10個のキュー配列です。両方とも一次元、サイズも10個、タイプもint
で、条件にマッチするので
代入可能です。
次の
A[1] = C;
は、Cは8個のint キュー配列ですので、サイズが合いません。実行時エラーになります。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 ***** G:\sv_test\queue\queue16.sv(16)::Fatal Error : array size is not matched.
次の
A = D[2];
は、[2][10] という次元と要素をどちらも、持つので、代入可能です。
ifdef 定義をオフにした場合の実行結果です。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 *****
D[2][0][0]=00000000000000000000000000000000
D[2][0][1]=00000000000000000000000000000000
D[2][0][2]=00000000000000000000000000000000
D[2][0][3]=00000000000000000000000000000000
D[2][0][4]=00000000000000000000000000000000
D[2][0][5]=00000000000000000000000000000000
D[2][0][6]=00000000000000000000000000000000
D[2][0][7]=00000000000000000000000000000000
D[2][0][8]=00000000000000000000000000000000
D[2][0][9]=00000000000000000000000000000000
D[2][1][0]=00000000000000000000000000000000
D[2][1][1]=00000000000000000000000000000000
D[2][1][2]=00000000000000000000000000000000
D[2][1][3]=00000000000000000000000000000000
D[2][1][4]=00000000000000000000000000000000
D[2][1][5]=00000000000000000000000000000000
D[2][1][6]=00000000000000000000000000000000
D[2][1][7]=00000000000000000000000000000000
D[2][1][8]=00000000000000000000000000000000
D[2][1][9]=00000000000000000000000000000000
---------- シミュレーションを終了します。time=0ns
次の例は、ダイナミック配列に対する代入です。ダイナミック配列に対する代入の場合、サイズ一致の制限はありません。サイズに関係なく、自由に代入できます。
例えば、ダイナミック配列Bに対する代入は、
B = A;
このとき、B=new [A.size()];が、暗黙的に実行されます。これにより、今までのBの内容は、捨てられて、新しい領域がA.size()分確保されてます。
その後に、Aの各要素がBにコピーされます。
B= new [C.size()](C);
は、B=Cに等価です。まず、Cと同じ領域だけメモリを確保して、その後にCの内容をBにコピーします。
このように、ダイナミック配列に対するアンパックド配列次元の代入は、暗黙的にnew 動作が入っていることに注意してください。
確保される領域の大きさと、内容を別に制御したい場合には、次のようにします。
B=new [B.size()*2](B);
は、今までのBのサイズの2倍の新しい領域を確保します。このとき、新しい領域は、default値で埋められます。その後に、Bの内容を新しい領域にコピーします。
B=new [B.size()/2](B);
は、Bのサイズの1/2の新しい領域を確保します。その後にBの内容が新しい領域にコピーされます。結果的に、トランケートされた内容になります。
module queue17;
int A[10:1]; // fixed-size array of 100 elements
int B[$]; // empty dynamic array
int C[$] = new[8]; // dynamic array of size 8
initial begin
B = A;
foreach (B[i]) $display(" B[%1d]=%1d",i,B[i]);
$display("");
B = C;
foreach (B[i]) $display(" B[%1d]=%1d",i,B[i]);
$display("");
foreach (C[i]) C[i]=i;
B= new [C.size()](C);//B=C
foreach (B[i]) $display(" B[%2d]=%2d",i,B[i]);
$display("");
B=new [B.size()*2](B);
foreach (B[i]) $display(" B[%2d]=%2d",i,B[i]);
$display("");
B=new [B.size()/2](B);
foreach (B[i]) $display(" B[%2d]=%2d",i,B[i]);
$display("");
end
endmodule
実行結果です。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 *****
B[0]=0
B[1]=0
B[2]=0
B[3]=0
B[4]=0
B[5]=0
B[6]=0
B[7]=0
B[8]=0
B[9]=0
B[0]=0
B[1]=0
B[2]=0
B[3]=0
B[4]=0
B[5]=0
B[6]=0
B[7]=0
B[ 0]= 0
B[ 1]= 1
B[ 2]= 2
B[ 3]= 3
B[ 4]= 4
B[ 5]= 5
B[ 6]= 6
B[ 7]= 7
B[ 0]= 0
B[ 1]= 1
B[ 2]= 2
B[ 3]= 3
B[ 4]= 4
B[ 5]= 5
B[ 6]= 6
B[ 7]= 7
B[ 8]= 0
B[ 9]= 0
B[10]= 0
B[11]= 0
B[12]= 0
B[13]= 0
B[14]= 0
B[15]= 0
B[ 0]= 0
B[ 1]= 1
B[ 2]= 2
B[ 3]= 3
B[ 4]= 4
B[ 5]= 5
B[ 6]= 6
B[ 7]= 7
---------- シミュレーションを終了します。time=0ns
4)サブルーチンに対する代入
制限は、上で述べたことに同じです。
module queue18; int b[4:1] ='{1,2,3,4}; int c[5:2] ='{5,4,3,2}; int d[$]='{6,5,4,3}; initial begin t(b); t(c); t(d); t_dynamic(b); t_dynamic(c); t_dynamic(d); d=new [5](d); t_dynamic(d); t(d); end task t( input int mem[4:1]) ; foreach (mem[i]) $display("mem[%1d]=%1d",i,mem[i]); $display(""); endtask task t_dynamic( input int dmem[$]) ; foreach (dmem[i]) $display("dmem[%1d]=%1d",i,dmem[i]); $display(""); endtask endmodule
実行結果です。
宣言の昇降順によらず、宣言順に各要素が代入されます。
d[$] は、 内部的には、d[0 :d.size()-1] で扱われます。
d[0] -> mem[4]
d[1] -> mem[3]
d[2] -> mem[2]
d[1] -> mem[1]
という具合にコピーされます。
ダイナミック配列から固定サイズ配列にコピーされるときに、要素数が合わないと、下記の最後のように、実行時エラーとなります。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 *****
mem[4]=1
mem[3]=2
mem[2]=3
mem[1]=4
mem[4]=5
mem[3]=4
mem[2]=3
mem[1]=2
mem[4]=6
mem[3]=5
mem[2]=4
mem[1]=3
dmem[0]=1
dmem[1]=2
dmem[2]=3
dmem[3]=4
dmem[0]=5
dmem[1]=4
dmem[2]=3
dmem[3]=2
dmem[0]=6
dmem[1]=5
dmem[2]=4
dmem[3]=3
dmem[0]=6
dmem[1]=5
dmem[2]=4
dmem[3]=3
dmem[4]=0
G:\sv_test\queue\qiueue18.sv(20)::Fatal Error : array size is not matched.
ストリング配列の例です。
module queue18; string b[4:1] ='{"a","b","c","d"}; string c[5:2] ='{"d","e","f","g"}; string d[$]= '{"h","i","j","k"}; initial begin t(b); t(c); t(d); t_dynamic(b); t_dynamic(c); t_dynamic(d); d=new [5](d); t_dynamic(d); t(d); end task t( input string mem[4:1]) ; foreach (mem[i]) $display("mem[%1d]=%s",i,mem[i]); $display(""); endtask task t_dynamic( input string dmem[$]) ; foreach (dmem[i]) $display("dmem[%1d]=%s",i,dmem[i]); $display(""); endtask endmodule
実行結果です。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 ***** mem[4]=a mem[3]=b mem[2]=c mem[1]=d mem[4]=d mem[3]=e mem[2]=f mem[1]=g mem[4]=h mem[3]=i mem[2]=j mem[1]=k dmem[0]=a dmem[1]=b dmem[2]=c dmem[3]=d dmem[0]=d dmem[1]=e dmem[2]=f dmem[3]=g dmem[0]=h dmem[1]=i dmem[2]=j dmem[3]=k dmem[0]=h dmem[1]=i dmem[2]=j dmem[3]=k dmem[4]= G:\sv_test\queue\qiueue20.sv(21)::Fatal Error : array size is not matched.
6)ダイナミック配列ーキュー配列間の代入は、自由
固定配列への代入は、各配列次元同士のサイズが合っているか、気を使う必要がありますが、ダイナミック配列ーキュー配列間では、気にすることなく自由に行えます。
module queue11; int m[][4]; int m1[4][]; int m2[][$]; int m3[][]; int m4[$][]; int m5[$][$]; int m6[4][$]; int m7[$][4]; int m8[4][4]; initial begin m=new [4]; foreach (m[i,j]) begin m[i][j]=i*j; $display("m[%1d][%1d]=%1d",i,j,m[i][j]); end $display(""); m1=m; m2=m1; m3=m2; m4=m3; m5=m4; m6=m5; m7=m6; m8=m7; foreach(m8[i,j]) $display("m8[%1d][%1d]=%1d",i,j,m8[i][j]); end endmodule
実行結果です。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 ***** m[0][0]=0 m[0][1]=0 m[0][2]=0 m[0][3]=0 m[1][0]=0 m[1][1]=1 m[1][2]=2 m[1][3]=3 m[2][0]=0 m[2][1]=2 m[2][2]=4 m[2][3]=6 m[3][0]=0 m[3][1]=3 m[3][2]=6 m[3][3]=9 m8[0][0]=0 m8[0][1]=0 m8[0][2]=0 m8[0][3]=0 m8[1][0]=0 m8[1][1]=1 m8[1][2]=2 m8[1][3]=3 m8[2][0]=0 m8[2][1]=2 m8[2][2]=4 m8[2][3]=6 m8[3][0]=0 m8[3][1]=3 m8[3][2]=6 m8[3][3]=9
7)キュ-の特徴的なメソッド
上で見てきたように、キューは、ダイナミック配列と殆ど同じように扱えます。では、キューとダイナミック配列は、なにが違うのでしょうか?
違いは、次のメソッドがキューには、備わっていることです。
-このために、内部のデータ構造は、ダイナミック配列より複雑です。VeritakSVでは、リングバッファで実装しています。
最もアクセス速度が速いのは、push../pop..で、実際こちらは、よく使います。
内部データ構造の性質上、先頭と最後尾の挿入と削除は、(*大抵の場合、)配列のサイズによらず固定時間でアクセスが可能です。一方、insert/delete
系は、配列のサイズに比例して遅くなります。
*固定時間と説明される事が多いのですが、メモリプールの取得時(実装によりますが、配列サイズが2のべき乗になるとき)は、やはりメモリ確保の時間がプラスされます。
ここで、element_tは、要素を現しています。従ってメソッド元の次元より一次元だけ低くなります。
* SystemVerilog for Verification には、q.insert(3,q)のような同一次元の挿入例が載っていますが、挿入される型は、挿入先のelement_tであるべきです。(誤植か、古い仕様だと思います->第3版(2012発行)では訂正されていました。
使い方です。 注意する点は、pop_back()/pop_front()系で、queue がもう空になっているのに、さらに、読み込もうとすると、実行時エラーとなって停止してしまうことです。
module queue21a;
int i;
int q[$];
initial begin
$display("1,2,3を後ろに追加します。");
q.push_back(1);
q.push_back(2);
q.push_back(3);
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("4,5,6を前から追加します。");
q.push_front(4);
q.push_front(5);
q.push_front(6);
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("インデックス0に7を追加します。");
q.insert(0,7);
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("インデックスq.size()-2(=5)に8を挿入します。");
q.insert(q.size()-2,8);
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("インデックス4の要素を削除します。");
q.delete(4);
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最後の要素を取得ます。その後最後の要素を削除します。");
i=q.pop_back();
$display("最後の要素は、%1d",i);
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最初の要素を取得します。その後最初の要素を削除します。");
i=q.pop_front();
$display("最初の要素は、%1d",i);
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最初の要素は、%1d",q.pop_front());
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最初の要素は、%1d",q.pop_front());
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最初の要素は、%1d",q.pop_front());
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最初の要素は、%1d",q.pop_front());
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最初の要素は、%1d",q.pop_front());
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
$display("最初の要素は、%1d",q.pop_front());
foreach (q[k]) $display("q[%1d]=%1d",k,q[k]);$display("");
end
endmodule
実行結果です。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 ***** 1,2,3を後ろに追加します。 q[0]=1 q[1]=2 q[2]=3 4,5,6を前から追加します。 q[0]=6 q[1]=5 q[2]=4 q[3]=1 q[4]=2 q[5]=3 インデックス0に7を追加します。 q[0]=7 q[1]=6 q[2]=5 q[3]=4 q[4]=1 q[5]=2 q[6]=3 インデックスq.size()-2(=5)に8を挿入します。 q[0]=7 q[1]=6 q[2]=5 q[3]=4 q[4]=1 q[5]=8 q[6]=2 q[7]=3 インデックス4の要素を削除します。 q[0]=7 q[1]=6 q[2]=5 q[3]=4 q[4]=8 q[5]=2 q[6]=3 最後の要素を取得ます。その後最後の要素を削除します。 最後の要素は、3 q[0]=7 q[1]=6 q[2]=5 q[3]=4 q[4]=8 q[5]=2 最初の要素を取得します。その後最初の要素を削除します。 最初の要素は、7 q[0]=6 q[1]=5 q[2]=4 q[3]=8 q[4]=2 最初の要素は、6 q[0]=5 q[1]=4 q[2]=8 q[3]=2 最初の要素は、5 q[0]=4 q[1]=8 q[2]=2 最初の要素は、4 q[0]=8 q[1]=2 最初の要素は、8 q[0]=2 最初の要素は、2 G:\sv_test\queue\queue21a.sv(59)::Fatal Error : Queue is empty.
多次元キューの例です。下で、
QType q[$]
は、int q[$][$] と等価です。 q にpush_backするときは、qの要素であるQTypeにキャスティングしたアサインメントパターンを使用します。
module queue21b; typedef int QType[$]; QType q[$]; QType q1; initial begin $display("'{1,2,3}を後ろに追加します。"); q.push_back( QType '{1,2,3}); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); $display("'{4,5,6}を前から追加します。"); q.push_front( QType '{4,5,6}); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); $display("7,8,9を前から追加します。"); q[0].push_front(7); q[0].push_front(8); q[0].push_front(9); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); $display("4,5,6を前から追加します。"); q[1].push_front(4); q[1].push_front(5); q[1].push_front(6); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); $display("インデックス0に '{7,8,9}を追加します。"); q.insert(0,QType '{7,8,9 }); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); $display("インデックスq.size()-2に0を挿入します。"); q[0].insert(q.size()-2,0); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); $display("インデックス2の要素を削除します。"); q[0].delete(2); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); $display("最後の要素を取得ます。(その後最後の要素を削除します。)"); q1=q.pop_back(); $display("最後の要素は、"); foreach (q1[k]) $display("q1[%1d]=%1d",k,q1[k]);$display(""); $display("最初の要素を取得します。(その後最初の要素を削除します。)"); q1=q.pop_front(); $display("最初の要素は、"); foreach (q1[k]) $display("q1[%1d]=%1d",k,q1[k]);$display(""); foreach (q[j,k]) $display("q[%1d][%1d]=%1d",j,k,q[j][k]);$display(""); end endmodule : queue21b
実行結果です。
***** Veritak SV Engine Version 0.431 Build Oct.15.2011 ***** '{1,2,3}を後ろに追加します。 q[0][0]=1 q[0][1]=2 q[0][2]=3 '{4,5,6}を前から追加します。 q[0][0]=4 q[0][1]=5 q[0][2]=6 q[1][0]=1 q[1][1]=2 q[1][2]=3 7,8,9を前から追加します。 q[0][0]=9 q[0][1]=8 q[0][2]=7 q[0][3]=4 q[0][4]=5 q[0][5]=6 q[1][0]=1 q[1][1]=2 q[1][2]=3 4,5,6を前から追加します。 q[0][0]=9 q[0][1]=8 q[0][2]=7 q[0][3]=4 q[0][4]=5 q[0][5]=6 q[1][0]=6 q[1][1]=5 q[1][2]=4 q[1][3]=1 q[1][4]=2 q[1][5]=3 インデックス0に '{7,8,9}を追加します。 q[0][0]=7 q[0][1]=8 q[0][2]=9 q[1][0]=9 q[1][1]=8 q[1][2]=7 q[1][3]=4 q[1][4]=5 q[1][5]=6 q[2][0]=6 q[2][1]=5 q[2][2]=4 q[2][3]=1 q[2][4]=2 q[2][5]=3 インデックスq.size()-2に0を挿入します。 q[0][0]=7 q[0][1]=0 q[0][2]=8 q[0][3]=9 q[1][0]=9 q[1][1]=8 q[1][2]=7 q[1][3]=4 q[1][4]=5 q[1][5]=6 q[2][0]=6 q[2][1]=5 q[2][2]=4 q[2][3]=1 q[2][4]=2 q[2][5]=3 インデックス2の要素を削除します。 q[0][0]=7 q[0][1]=0 q[0][2]=9 q[1][0]=9 q[1][1]=8 q[1][2]=7 q[1][3]=4 q[1][4]=5 q[1][5]=6 q[2][0]=6 q[2][1]=5 q[2][2]=4 q[2][3]=1 q[2][4]=2 q[2][5]=3 最後の要素を取得ます。(その後最後の要素を削除します。) 最後の要素は、 q1[0]=6 q1[1]=5 q1[2]=4 q1[3]=1 q1[4]=2 q1[5]=3 最初の要素を取得します。(その後最初の要素を削除します。) 最初の要素は、 q1[0]=7 q1[1]=0 q1[2]=9 q[0][0]=9 q[0][1]=8 q[0][2]=7 q[0][3]=4 q[0][4]=5 q[0][5]=6
8)最大値制限付キュ-
下のようにキューの最大値制限付の宣言も可能です。この場合、インデックス255までしか書き込めません。(最大値を超えての書き込みはWarningが発生し、書き込みは、無視されます。)
module queue26;
integer q2[$:255];
int i;
initial begin
i=0;
repeat(1000) begin
q2.push_back(i);
$display("q2.size()=%d %d",q2.size(),i);
i+=1;
end
foreach (q2[i]) $display("q2[%1d]=%d",i,q2[i]);
end
endmodule
実行結果です。
..略 q2.size()= 253 252 q2.size()= 254 253 q2.size()= 255 254 q2.size()= 256 255 G:\sv_test\queue\queue26.sv(9):: Warning:Maximum Queue size is limited to 256. q2.size()= 256 256 G:\sv_test\queue\queue26.sv(9):: Warning:Maximum Queue size is limited to 256. q2.size()= 256 257 G:\sv_test\queue\queue26.sv(9):: Warning:Maximum Queue size is limited to 256. ..略 q2[248]= 248 q2[249]= 249 q2[250]= 250 q2[251]= 251 q2[252]= 252 q2[253]= 253 q2[254]= 254 q2[255]= 255 ---------- シミュレーションを終了します。time=0ns