コナンくんのアレを作る技術 その2

みんなさん、こんにちは!Nefrockの長期インターン生Peterです!

去年3月もここで報告したように、Nefrockではただいま「リアルタイムで声質を変換するハードウェア KUROFUNE」を開発しています。 前の記事ではNefrockの@shiwazaki1がそれを「FPGA上になんとか実装したい」と述べましたけど、今回の記事でまさにその実装について書きたいと思います!

FPGAって、なに?

FPGAとは、「Field Programmable Gate Array」の略称です。つまり「現場で組み替えられる論理回路」という意味になります。「現場」は、この件の場合Nefrockのことで、「論理回路」は計算機という認識で問題ないでしょう。 計算機としての立場は、一般的なパソコンにも入っているCPUと、ASICという専用ICの間です。 自動車業界で使用されるASICと比べて消費電力の効率がやや悪いが、開発コストが低いです。FPGAはCPUみたいに容易にいろんなソフトが使えないが、逆に計算効率が高いです。以下の図もご確認ください。

fpga_compare Source: https://bto.applied.ne.jp/img/solution2/item_fpga1.png

コナンくんのアレといえば、つまり携帯できるリアルタイムの音声変換機ですので、FPGAには最適なアプリケーションです。

FPGAプログラミング

組替可能とはいっても、実際にどういうふうに組み替えるでしょうか? 普段はVHDLやVerilog-HDLなどのHDLでハードウェアを細かく記述し、FPGAメーカが提供する専用ツール(Xilinx社の場合Vivado)がそれを実際のハードウェア構造に翻訳してくれます。出力されるバイナリはCDやDVDを焼くようにFPGAに簡単焼けます。

実際にVHDLで書かれたコードを見てみると、なかなか読みづらく複雑なプログラムを組むにはあまり向いている言語ではないことに気づかずにはいられないでしょう。以下のプログラムは、簡単なカウンターの実装で、enable, clk, resetなどハードウェア専門知識がないと知らないようなものが入ってたり、全体的に分かりにくい感じです。

entity counter is
    port (
        cout   :out std_logic_vector (7 downto 0);
        enable :in  std_logic;
        clk    :in  std_logic;
        reset  :in  std_logic
    );
end entity;

architecture rtl of counter is
    signal count :std_logic_vector (7 downto 0);
begin
    process (clk, reset) begin
        if (reset = '1') then
            count <= (others=>'0');
        elsif (rising_edge(clk)) then
            if (enable = '1') then
                count <= count + 1;
            end if;
        end if;
    end process;
    cout <= count;
end architecture;

それと比べて同じ機能をC/C++で書くと下記になります。

int counter(bool reset=false) {
  static int count = 0;
  if (reset) count = 0;
  else count += 1;
  return count;
}

長さだけでみても全然違いますし、プログラミングに慣れていない方もおそらく何が起きているか見当がつくでしょう。 FPGAのプログラムもC/C++でかければいいのになぁ、、と思うのは、さすがに我々だけでなく、FPGAメーカもこのニーズに気づいています。 ちなみにFPGAメーカと言っても、ほとんどXilinx (マーケットシェア~50%) とIntel (40%) しかありません。 今回はXilinxのFPGAを使っているので、以下の話はIntelのFPGA開発に当てはまらない場合もあります。

高位合成によるFPGAプログラミング

VHDL・Verilog-HDLでFPGAのプログラムを書くのは大変で、専門知識が必要です。FPGAをより多くの人に使ってもらうように、XilinxがVitis HLSというツールを提供してくれます。 Vitisは製品名で、HLSとはHigh Level Synthesis(高位合成)という意味です。Vitis HLSはC/C++で書かれたプログラムをHDL(VHDL・Verilog-HDL)に翻訳してくれます。 そのHDL表現から上述のVivadoの流れで更にバイナリが生成出来ます。「高位」というのは、人間にとって「より分かりやすい」、しかし機械にとっては「分かりにくい」という意味です。 よく知られている例でいうと、アセンブリは低位で、Pythonなどは高位の言語です。

つまりVitis HLSなら上の簡単なカウンターの実装がそのまま使えます。素晴らしいです! もちろんHDLで細かく調整し効率のより良いプログラムも書けますし、高位合成では使えない機能もあります。 しかし最近HLSの技術が進んでいて、WaveNetの実装も可能でした。

おわりに

WaveNetが実装できましたと言いましたが、実は単純にC/C++で書いてすぐFPGAで動いてくれた訳ではありません。 高位合成でもある程度FPGAに向けた書き方をしないと効率の良いハードウェアにならず、何ならVivadoがそもそもバイナリ生成に失敗することも多いです。 量子化、dataflow、回路の再利用などCPU向けの開発では考えなくてもいいようなものが沢山あって、また今度の記事で紹介したいと思います!