インテル® Hyperflex™ アーキテクチャー高性能デザイン・ハンドブック

ID 683353
日付 10/04/2021
Public
ドキュメント目次

2.4.1.4.2. ループ・パイプラインにおデモ

以下は、サンプルデザインでアキュムレーターを最適化するための適切なループ・パイプライン処理を示しています。元の実装では、入力されるアキュムレーター・データはxで乗算され、前の値outに加算され、yで乗算されます。このデモでは、次の手法を使用してパフォーマンスを改善します。
  1. フォワードロジックの分離を実装する
  2. ループレジスターのリタイミング
  3. カスケードロジックでフィードバックループの等価性を作成する
図 53. 元のループ構造

元のループ構造の例Verilog HDLコード

module orig_loop_strct (rstn, clk, in, x, y, out);
   input clk, rstn, in, x, y;
   output out;
   reg    out;
   reg in_reg;

always @ ( posedge clk )
   if ( !rstn ) begin
      in_reg <= 1'b0;
   end else begin
      in_reg <= in;
   end

always @ ( posedge clk )
   if ( !rstn ) begin
      out <= 1'b0;
   end else begin
      out <= y*out + x*in_reg;
   end
endmodule //orig_loop_strct

最適化の最初の段階は、ロジックを書き直してループからできるだけ多くのロジックを削除し、フォワードロジックブロックを作成することです。書き換えの目標は、フィードバックループから可能な限り多くの作業を削除することです。Compilerは、フィードバックループ内のロジックを自動的に最適化することはできません。ループからロジックを削除する際には、次の推奨事項を考慮してください。

  • ループの値に直接依存しない、ループの前にできるだけ多くの決定を評価し、できるだけ多くの計算を実行します。
  • ループに渡す前に、レジスターステージにロジックを渡す可能性があります。

ロジックを書き換えた後、Compilerは、フォワードパスに移動したロジックのタイミングを自由に変更できるようになりました。

図 54. フォワードロジックとループの分離

次の最適化段階で、ループレジスターのタイミングを変更して、デザインが元のループ回路と同じように機能することを確認します。

図 55. リタイム・ループ・レジスター

最後に、強調表示された境界内のロジックを使用して最初の最適化手順を繰り返すことにより、ループをさらに最適化します。

図 56. Cascade Loop Logic、Hyper-Retimer、およびSynthesis Optimizations(4レベルの最適化)

4レベル最適化の例Verilog HDLコード

module cll_hypr_rtm_synopt ( rstn, clk, x, y, in, out);
   input rstn, clk, x, y, in;

   output out;
   reg    out;

   reg in_reg;

   wire out_add1;
   wire out_add2;
   wire out_add3;
   wire out_add4;

   reg out_add1_reg1;
   reg out_add1_reg2;
   reg out_add1_reg3;
   reg out_add1_reg4;

always @ ( posedge clk )
   if ( !rstn ) begin
      in_reg <= 0;
   end else begin
      in_reg <= in;
   end

always @ ( posedge clk )
   if ( !rstn ) begin
      out_add1_reg1 <= 0;
      out_add1_reg2 <= 0;
      out_add1_reg3 <= 0;
      out_add1_reg4 <= 0;
   end else begin
      out_add1_reg1 <= out_add1;
      out_add1_reg2 <= out_add1_reg1;
      out_add1_reg3 <= out_add1_reg2;
      out_add1_reg4 <= out_add1_reg3;
   end

assign out_add1 = x*in_reg  + ((((y*out_add1_reg4)*y)*y)*y);
assign out_add2 = out_add1 + (y*out_add1_reg1);
assign out_add3 = out_add2 + ((y*out_add1_reg2)*y);
assign out_add4 = out_add3 + (((y*out_add1_reg3)*y)*y);

always @ ( posedge clk ) begin
   if ( !rstn )
      out <= 0;
   else
      out <= out_add4;
end
endmodule //cll_hypr_rtm_synopt