1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

HDLAdvent Calendar 2013

Day 10

[SystemVerilog]連想配列の話など

Posted at

はじめに

こんにちは。@imatatsuです。
ネタとして新しいものではないですが、SystemVerilogの連想配列についてちょっとだけご紹介します。
SystemVerilogよく使ってるつもりですが、厳密な部分はよくわからないのでテキトウに書きます。

連想配列ってなに?

Wikipediaより
http://ja.wikipedia.org/wiki/%E9%80%A3%E6%83%B3%E9%85%8D%E5%88%97

配列の添字に色々なデータ型が使えるよ!ってやつですね。
まぁ、何物なのかってことより、
何に使えて、何がうれしいのか
というのがポイントだと思います。

使い方

様々な使い道はあると思いますが一番簡単な使い道としては、
テストベンチ上にメモリを作成する場合に使用します。

32bitアドレスのメモリをテストベンチ上に作成する場合、
静的配列で下記のように宣言しているのをたまに見かけます。

  reg [31:0] memory[0:1073741823];

配列のサイズが小さいうちはこれでもいいのですが、
64bitアドレスなど、大きいサイズになるとシミュレータがギブアップします。
ちなみに某社のシミュレータでは2147483648が最大でした。

どうせ全部は使わないから使う部分だけを宣言するとか、
何個かに分けるとか方法が無くはないのですが、なんにせよ面倒です。
32bitアドレスでテストシナリオが既に作ってあって、
別のプロジェクトで64bitアドレスにする、とかなった場合はそれなりの作業が発生する場合があります。

とゆうことで、静的配列を使うのはやめて、連想配列を使いましょう。
下記のコードのlogic [7:0] mem[longint unsigned]の部分が連想配列の宣言になります。

test1.sv
`timescale 1ns/1ps
module test1();
  logic [7:0] mem[longint unsigned];

  initial begin
    mem[1] = 8'h01;
    mem[3] = 8'h03;
    mem[5] = 8'h05;
    mem[7] = 8'h07;
    mem[9] = 8'h09;
    
    for(int i=0; i<10; i++) begin
      logic [7:0] data;

      data = mem.exists(i) ? mem[i] : 8'h00;

      $display("mem[%0d] = 0x%02h", i, data);
    end
  end
  
endmodule : test1

mem[1] = 8'h01・・・と書いてある部分が連想配列への代入です。
代入した所だけ領域が確保されるのでサイズを気にしないですみます(たぶん)。

領域が確保されているかどうかはexistsというメソッドで調べる事ができます。
Readした時に、1度もWriteした事が無い番地だったら、existsで調べて、
0なり不定なりを返すようにすれば静的配列と同じ動きをさせることができます。

実行結果はこちら

mem[0] = 0x00
mem[1] = 0x01
mem[2] = 0x00
mem[3] = 0x03
mem[4] = 0x00
mem[5] = 0x05
mem[6] = 0x00
mem[7] = 0x07
mem[8] = 0x00
mem[9] = 0x09

応用編

たいした応用ではないですが、
連想配列はforeachと組み合わせて使用するとより強力になります。
foreachでまわすと、確保されている部分だけ実行されます。

ということで下記のようなuvm_report_infoもどきに
連想配列+foreachを組み込んでみました。

final begin~endの部分がforeachで回してる部分です。
my_dispに渡されたkindの内容が何であろうが、
INFOやERRORの個数を分別できるという仕組みです。

test2.sv
`timescale 1ns/1ps
module test2();
  
// ----------------------------------------------------------------------------
// variables
// ----------------------------------------------------------------------------
  longint unsigned num[string][string];
  
// ----------------------------------------------------------------------------
// function
// ----------------------------------------------------------------------------
  // my_disp
  function my_disp(
      string msg      = ""
    , string kind     = ""
    , string severity = "INFO"
  );
    $write("%0tps [%-10s][%-5s] %s", $time, kind, severity, msg);
    num[kind][severity]++;
  endfunction : my_disp

  // my_checker
  function my_checker(logic [7:0] data, logic [7:0] exp);
    if(data === exp) begin
      my_disp($psprintf("Data = 0x%02h, EXP = 0x%02h\n", data, exp), "DATA_CHK", "OKAY");
    end
    else begin
      my_disp($psprintf("Data = 0x%02h, EXP = 0x%02h\n", data, exp), "DATA_CHK", "ERROR");
    end
  endfunction : my_checker
  
// ----------------------------------------------------------------------------
// scenario
// ----------------------------------------------------------------------------
  initial begin
    logic [7:0] data = 8'hA5;
    logic [7:0] exp  = 8'hA5;
    
    #10; my_disp("Test Message: INFO\n" , "TEST", "INFO" );
    #10; my_disp("Test Message: OKAY\n" , "TEST", "OKAY" );
    #10; my_disp("Test Message: WARN\n" , "TEST", "WARN" );
    #10; my_disp("Test Message: ERROR\n", "TEST", "ERROR");

    $display("");
    
    my_checker(data, exp);
    data = 8'h5A;
    my_checker(data, exp);
    data = 8'h00;
    my_checker(data, exp);

    $finish(2);
  end

  final begin
    $display("--------------------");
    $display(" Simulation Resullt ");
    $display("--------------------");

    foreach(num[k]) begin
      $display("%s", k);
      foreach(num[k][s]) begin
        $display("    %-5s: %0d", s, num[k][s]);
      end
      $display("");
    end
  end

endmodule : test2

実行結果

10000ps [TEST      ][INFO ] Test Message: INFO
20000ps [TEST      ][OKAY ] Test Message: OKAY
30000ps [TEST      ][WARN ] Test Message: WARN
40000ps [TEST      ][ERROR] Test Message: ERROR

40000ps [DATA_CHK  ][OKAY ] Data = 0xa5, EXP = 0xa5
40000ps [DATA_CHK  ][ERROR] Data = 0x5a, EXP = 0xa5
40000ps [DATA_CHK  ][ERROR] Data = 0x00, EXP = 0xa5

--------------------
 Simulation Resullt
--------------------
DATA_CHK
    ERROR: 2
    OKAY : 1

TEST
    ERROR: 1
    INFO : 1
    OKAY : 1
    WARN : 1
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?