Associated Array
連想配列は配列の一種ではあるが、数字だけでなく、任意のオブジェクトを配列のキーとして使用できることが特徴だ。
キーとして使用できるのは、
文字列
class
integer, int
signed packed array
unsigned packed array
typedefなどでユーザ定義されたstruct等
と、ほぼなんでもありとなっている。
packed arrayは、あまり馴染みのない表現だと思うが、簡単に言えば、
reg [9:0] a;
など、変数名の左側に配列の要素数が宣言されたものを指す。reg以外にも、bitやlogicなどでも同様だ。
逆に、変数名の右側に配列の要素数が宣言されたものはunpacked arrayになる。
また、packed arrayを使用する場合、ビット長が異なる場合は別のキーとして認識される。つまり、4'h0と8'h0は異なるキーとして認識される。
連想配列の宣言には[*]を使用する。
以下は文字列をキーとして、配列に数値をストアする例だ。
module test();
reg [7:0] mem[*];
initial begin
mem["one"] = 8'h1;
mem["two"] = 8'h2;
mem["three"] = 8'h3;
$display("one = %d", mem["one"]);
$display("two = %d", mem["two"]);
$display("three = %d", mem["three"]);
end
endmodule
# 6.5e
# vsim -do {run -all; quit} -c test
# Loading sv_std.std
# Loading work.test
# run -all
# one = 1
# two = 2
# three = 3
# quit
この機能、検証に便利な機能として使えそうだが、従来のverilogからの移行という意味で手っ取り早くありがたみを感じられるのは、巨大なメモリ空間をエミュレートする時だろう。
連想配列には、宣言時にその使用領域の大きさが決定されず、使用された分だけ動的にメモリが確保されていくという性質がある。
配列を使用して1Gwordの空間を持つ配列を用意するのは非現実的だが、連想配列であれば問題なく実現できる。
module test2();
reg [7:0] mem[*];
initial begin
mem[30'h0000_0000] = 8'haa;
mem[30'h3fff_fffe] = 8'h54;
mem[30'h3fff_ffff] = 8'h55;
$display("Address 30'h0000_0000 = %x", mem[30'h0000_0000]);
$display("Address 30'h3fff_fffe = %x", mem[30'h3fff_fffe]);
$display("Address 30'h3fff_ffff = %x", mem[30'h3fff_ffff]);
$display("Address 30'h0000_0001 = %x", mem[30'h0000_0001]);
$display("Address 32'h0000_0000 = %x", mem[32'h0000_0000]);
end
endmodule
# 6.5e
# vsim -do {run -all; quit} -c test2
# Loading sv_std.std
# Loading work.test2
# run -all
# Address 30'h0000_0000 = aa
# Address 30'h3fff_fffe = 54
# Address 30'h3fff_ffff = 55
# ** Warning: (vsim-3829) test2.sv(12): Non-existent associative array entry. Returning default value.
# Address 30'h0000_0001 = xx
# ** Warning: (vsim-3829) test2.sv(13): Non-existent associative array entry. Returning default value.
# Address 32'h0000_0000 = xx
# quit
本例では、値の代入が行われていない30'h0000_0001と、キーのビット長が異なる32'h0000_0000からの読み出しも行っている。これらのアドレスからはxが読み出されている。ModelSimではWarningも表示されているが、Warningが出るかどうかはシミュレータ依存のようだ。
なお、いくら1GWordの空間が扱えるからといって、全アドレスに書き込みを行ってしまっては、結局それだけのメモリ空間を必要としてしまう。1GWordの空間の、任意の限られたアドレスのみにアクセスする場合に上記手法は有効だ。