インテル® HLS コンパイラー: リファレンス・マニュアル

ID 683349
日付 6/23/2017
Public
ドキュメント目次

1.9.2. hls_merge 属性の使用例

HLSコンパイラーに同じメモリーシステム内の変数を幅方向または深さ方向のいずれかにマージして実装することを強制するオプションがあります。
注: HLSコンパイラーは不一致のデータ型をサポートします。
図 6. hls_merge("label", "direction") 属性の実装の概要

深さに関する hls_merge 属性の実装

次のコンポーネントコードを考察します。

component int depth_manual(bool use_a, int raddr, int waddr, int wdata) {
  int a[128];
  int b[128];

  int rdata;

  // mutually exclusive write
  if (use_a) {
    a[waddr] = wdata;
  } else {
    b[waddr] = wdata;
  }

  // mutually exclusive read
  if (use_a) {
    rdata = a[raddr];
  } else {
    rdata = b[raddr];
  }

  return rdata;
}

コードはローカルメモリーabをそれぞれ独自のロード / ストアー命令を有する 2 つのオンチップ・メモリーブロックとしてHLSコンパイラーに命令します。

図 7. コンポーネント depth_manual でのローカルメモリーの実装

ローカルメモリーabのロード / ストアー命令が相互に排他的なため、下のサンプルコードに示すようにアクセスをマージすることができ、これによりロード / ストアー命令の数が減り、オンチップ・メモリーブロックの数も半減します。

component int depth_manual(bool use_a, int raddr, int waddr, int wdata) {
  int a[128] hls_merge("mem","depth");
  int b[128] hls_merge("mem","depth");;

  int rdata;

  // mutually exclusive write
  if (use_a) {
    a[waddr] = wdata;
  } else {
    b[waddr] = wdata;
  }

  // mutually exclusive read
  if (use_a) {
    rdata = a[raddr];
  } else {
    rdata = b[raddr];
  }

  return rdata;
}
図 8. コンポーネント depth_manual のローカルメモリーの深さ方向のマージ

深さに関してローカルメモリーをマージするとメモリーアクセスの効率が低下する場合があります。深さに関するローカルメモリーをマージするかどうかを決定する前に、HLD レポート ( <result>.prj/reports/report.html) を参照し、予測されたロード / ストアー命令の数で予測されたメモリー構成を生成しているかを確認する必要があります。下の例では、各メモリーへのロード / ストアー命令は互いに排他的ではないため、HLSコンパイラーはローカルメモリーabへのアクセスをマージすべきではありません。

component int depth_manual(bool use_a, int raddr, int waddr, int wdata) {
  int a[128] hls_merge("mem","depth");
  int b[128] hls_merge("mem","depth");

  int rdata;

  // NOT mutually exclusive write

  a[waddr] = wdata;
  b[waddr] = wdata;
  
  // NOT mutually exclusive read

  rdata = a[raddr];
  rdata += b[raddr];
  
  return rdata;
}

この場合、HLSコンパイラーはメモリーシステムを ダブルポンプし、すべてのアクセスに十分なポートを提供する可能性があります。それ以外の場合、アクセスはストールフリーのアクセスを防止するポートを共有する必要があります。

図 9. 相互に排他的ではないアクセスを有するコンポーネント depth_manual のローカルメモリー

幅に関する hls_merge 属性の実装例

次のコンポーネント・コードを考察します。

component short width_manual (int raddr, int waddr, short wdata) {

  short a[256];
  short b[256];

  short rdata = 0;
  
  // Lock step write
  a[waddr] = wdata;
  b[waddr] = wdata;

  // Lock step read 
  rdata += a[raddr];
  rdata += b[raddr];

  return rdata;
}
図 10. コンポーネント width_manual のローカルメモリーの実装

この場合、HLSコンパイラーは、ロード / ストアー命令は同じアドレスへのアクセスであるため、ロード / ストアー命令をローカルメモリーabにマージすることができ、次のように統合されます。

component short width_manual (int raddr, int waddr, short wdata) {

  short a[256] hls_merge("mem","width");
  short b[256] hls_merge("mem","width");

  short rdata = 0;
  
  // Lock step write
  a[waddr] = wdata;
  b[waddr] = wdata;

  // Lock step read 
  rdata += a[raddr];
  rdata += b[raddr];

  return rdata;
}
図 11. コンポーネント width_manual でのローカルメモリーの幅方向のマージ