キュー

 SystemVerilogキューは、C++ STLのdeque に似ています。 両端での挿入、削除のメソッドがあります。 両端だけでなくランダムアクセスをサポートしており、キューの中間部分も直接読み書きできます。(ただし、キュー両端への挿入・削除がO(1)なのに対し、中間への挿入・削除はO(n)となります)。

 宣言は、次のように [$] でその次元は、キュー配列になります。 
bit [3:0] nibble[$]; 
integer mem[$][$];
time  t1[10][$];
realtime t2[$][10];
longint  t3[$][$];



また、多次元化も可能で、上のように一部を固定サイズ配列として宣言することも可能です。

多次元の場合の解釈は、

integer mem[$][$];
(integer [$] を要素とする)キュー配列mem になります。(  ボトムから integer -> [$]  -> [$] と解釈します。 )

1)Size()

キューは、デフォルトでは、サイズが0になります。
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=0ns
t1は、time[$] を要素として10個(固定)持つ配列になります。この場合、10個は、実行前に確保されるので、10 の表示になります。しかし、要素の一つである、t1[0] についてみれば、[$] ですから、未だメモリは確保されずそのサイズは0になります。このように[$]次元では、実行時にメモリを確保してから使う必要があります。



2) New コンストラクタ 
メモリを確保する構文が、new [ ] です。SystemVerilog for Verificationを見ると、”キューでは、new コンストラクタを使わない” と書かれていますが、LRM上は、禁止してはいないと思います。
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


nibble=new [4]; bit[3:0] 4個分のメモリを確保します。同様に、次の構文、

mem=new [10];

では、integer [$] 分を10個確保します。未だ、[$] が残っているので、実際に使うためには、さらに次元を降りる必要があり、例えば、
mem[1]=new [3];

にします。
メモリを固定サイズメモリと比較してみたのが、上の太字部分です。キューメモリの方は、mem[1]ラインしか確保されませんが、
固定サイズメモリは、

integer mem_fixed[10][3];

によりinteger [3]*[10] 分のメモリが確保されています。(固定メモリの場合 [M]*[N]で、往々にして巨大サイズ配列になります。)

mem[10]=new [3];は、実行時エラーになります。memは、その前の構文new [10] により、mem[0] から mem[9] は、integer [$] のサブ配列を持ちますが、mem[10]は、初期化されておらずメモリが存在しません。

t1は、最初の次元が固定サイズなので、この次元のnewは、不要です。(new してはいけません。) 

t2は、最初の次元でnew することによって、一次元降りた固定サイズのメモリも確保されます。(やはり、固定サイズ次元でのnewは、不要です。)


なお、new [$] は、下のようにインライン形式でも可能です。
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



3)Delete()

上例の最後に下記を追加して、コールしてみます。

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