RTLを語る会(12)でChisel 3/FIRRTL+自作HDL試作のLTをしてきた

2016年9月28日水曜日

9/25(日)に秋葉原界隈でおこなわれた「RTLを語る会(12)」に参加し、ついでにLTをしてきたので補足などをまとめます。

RTLを語る会。

RTLを語る会(12) 〜Vivado HLS GO〜です。参加するのは2度めで、前回「どえらく濃い場に来てしまったぞ・・・」と感じた記憶があります。
今回もVivado HLS(Xilinxの高位合成系)を使い倒して得られた諸々の話が展開されていて「貴重な場だ・・・」という感想でした(KONMAI感)。資料が公開されている分についてはイベント資料一覧で確認できます。一部の資料は公開されていません(これも大変得るものが多いセッションで、現地参加して本当によかったと思いました)。

LTをしてきた

LTとしては長めの15分枠にて、RTLコードを生成するための(alt-)HDLであるChisel HDLの簡単な紹介とその新バージョン(Chisel 3)に関する話をしました。色々と端折りましたが、実際には18分ぐらい喋っていた気がします。

Chiselに関してはこのblogでも既に(告知) C90 3日目西a-05abでScala+Chisel入門記事の載った技術書が出ますChiselで開発を始める小冊子(MFT2016配布物)の小改訂版を100円で販売しますで紹介しているのでここでは触れません。Chisel 3とそのバックエンドであるFIRRTLについてこれまであまり言及していないので書きます。

Chisel 3のアーキテクチャ

Chisel 3はChisel 2とほぼ互換性を保った記法を採用していますが、中身の実装が大きく異なります。代表的な違いは、構造のフロントエンドとバックエンドが切り分けられた点です(図1)。
図1 Chisel 3の実行時アーキテクチャ
Chisel 2は実行時に回路情報に基づいた.v/.cppファイルを自前生成し、.cppの場合はそれをコンパイルして開発環境用のネイティブバイナリを生成します。そして生成されたバイナリをDUTとしてChisel側に用意したテストコードと接続してシミュレーション検証をおこないます。
これに対してChisel 3では、バックエンドがFIRRTLというプロジェクトへ切り出されました。Chisel本体が担うのはFIRRTLの生成と、FIRRTLの先で生成されたバイナリとの通信によるシミュレーション検証作業のみへと軽減されます。
Chisel 2でマルチクロック利用などの込み入ったコードを書くと、回避の面倒なバグを踏むことが多くあります(代表的なのが#696です)。また、Chisel 2から生成した.cppコードがそもそもコンパイルを通らないケースもあります(マルチクロック利用時にcpp側のスコープ切りがおかしいパターンほか)。
Chisel 3+FIRRTLでは.cppコードの生成がChisel内部からFIRRTL側へ移っただけでなく、生成にVerilator*1を利用するようになりました*2
[*1] Verilatorは高速なHDLシミュレータ兼、HDL→C++コードの生成ユーティリティです。10年以上に渡り粛々と開発が進んでいて脱帽する系です
[*2] このためVerilatorのバージョンへの依存が激しい状態にもなっていますが、そのうち落ち着くはずです

LTのネタパート

割と真面目にChisel 2/3とFIRRTLの話をしたところで本題です。
Chisel 3世代では、バギーでメンテしづらいC++コード生成系を切り離せたことで今後のChiselプロジェクトの見通しがよくなることを期待できる一方、Chiselと同列にあたるFIRRTLのフロントエンドを比較的簡単に作れるようになりました。

Chisel 3の基盤を使ってHDL生成用DSLを自作する話

実は最近、Kindleへ突っ込んでおいたFIRRTLの言語仕様書を空いた時間でせっせと読んでいました。
そして、今回は運良く会場へのまとまった移動時間がありました。そこで「FIRRTLのフロントエンドとなる自前DSLを作ってみよう。C#ターゲットで」と思い立ち、作ってみました。
ここでC#を選択したのは自分が使い慣れているのに加えて、IDEが充実しており「プログラマ負荷の低いHDLを構築できる下地がある」可能性があるためです。なおFIRRTLのフロントエンドとしては、FIRRTL言語仕様に従ったコードを生成する機能があれば最低限の要件を満たせます(これに加えてDUTとの通信・テスト機能などを適宜作り込むことになります)。

FIRRTL#

そして作ったのがFIRRTL#という処理系です。.NET向けのクラスとして書いており、「回路内の単一モジュール定義と、モジュールの入出力ポートでAND/XOR処理をできる」ものです。
つまり、次のコードを書くと・・・
using FirrtlSharp;

namespace FirrtlSharpHalfAdder
{
    class HalfAdder : Module
    {
        public HalfAdder()
        {
            var io = new
            {
                a = new UInt(isOut: false),
                b = new UInt(isOut: false),
                s = new UInt(isOut: true),
                c = new UInt(isOut: true)
            };
            this.io = io;

            io.s.Assign(io.a + io.b);
            io.c.Assign(io.a ^ io.b);
        }
    }

    public class AdderGenerator
    {
        public static void Main()
        {
            FirrtlSharp.Generator.GenerateHDL(new HalfAdder());
        }
    }
}
FIRRTL経由で次のようなVerilog HDLコードを生成できます。
...
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif

module HalfAdder(
  input   clk,
  input   reset,
  input   io_a,
  input   io_b,
  output  io_s,
  output  io_c
);
  assign io_s = io_a & io_b;
  assign io_c = io_a ^ io_b;
endmodule
module TopHalfAdder(
  input   clk,
  input   reset
);
  wire  halfadder_clk;
  wire  halfadder_reset;
  wire  halfadder_io_a;
...

FIRRTL#、おいしいの?

おいしくありません。
今回はC# 6時点の構文でどの程度直感的かつ柔軟なHDL記法を実現できるか、という検討を重視しました。パッと見で厳しそうだな、と思ったところは案の定厳しいものです。
I/OポートのIDEでのコード補完ぐらいは効きます。I/O内の信号宣言時に個別の型指定をおこなうことで、型検証の道を残しつつ簡便な記法を維持することもできました。
これを育てていけば形になりそうにも見えますが、実際は次のように大きな問題が複数あります。
まず致命的なのが、C#を利用している限り<=を信号の受け渡し用演算子として自然な記法で成立させられないことです。これは演算子のオーバーロードでは解決できない問題で、C#が1;のような記述を許さないためです。
無理やり
  if (io.s <= io.a ^ io.b);
のようなif+空ステートメントの組み合わせでコードを記述できますが、この構文を許容するぐらいなら圧倒的にScalaを学んだほうが生産的です。ちなみに=をオーバーライドすることもできないので、io.s = io.a ^ io.b;という微妙に嫌な構文で妥協することも許されません。delegateをうまく利用すればio.s => io.a ^ io.b;といった記法は可能かもしれませんが、許容しがたい記法なので深く検討していません。
また、C#は構文上の制約としてシンボルに指定できる文字種が少ないため、たとえば<==といったメソッドを作るのも無理筋です(さらに、中置記法もないので自然な形には収められません)。
このあたりを満たす言語を作って、そこからC#コードを生成するという手はなくもないのですがFIRRTLの性質を考えると本末転倒です。

FIRRTL#実装の裏側

名前は.NET向け各種バインディングの慣習に従ってFIRRTL#と付けましたが、大したことはやっていません。
firrtl-sharpにてコードを公開しておきます。C# 6時点の構文でどの程度直感的かつ柔軟な記法を実現できるか、という検討に時間を多く使った結果、FIRRTLコード生成部分は見るも無残な感じになりました。これを拡張してもどこにもたどり着きはしないと思います。他言語でFIRRTL対応DSLを組むために最低限必要な要素が何かを知りたい場合には多少参考になるかもしれません。
今回はC# embedded languageとしてのHDL生成系がコンセプトとしてアリか否かを検討し、可能な範囲で試作してみるというのがメイン目的だったので、目的は満たせました。
当然テストハーネスなどは作っていないので、生成されたHDLの自動テストができるわけでもありません。

まとめ

FIRRTLによってHDL生成系を分離できたのはChiselの将来にとって良さそうで、この先割と良いバランスの立ち位置に落ち着きそう。

.NET Core Cliを20倍高速に自前ビルドするtips

2016年8月28日日曜日

こんにちは、皆さん今日も.NET Core Cliをビルドしていますか?
私は昨日ひさびさに.NET Core Cliをビルドしてみたところ、割とビルド時間の長さが苦痛でした。もう少しスナックに.NET Core Cliへ手を入れるために、いくつかビルド時間を短縮するための方法を考えたのでメモしておきます。

そもそもビルドに失敗する系

Windows: Quartus Primeをインストールしている場合

どうもおかしいなぁと思ってパス解決部分を調べていったところ、まさかのAltera社Quartus Prime関連(正確にはModelSim for Altera Lite)でエラーを吐いていることに気付きました。そんなばかな。
文字列ダンプは図1の通りです。
図1 AlteraのQuartus Primeのパス設定に謎の改行コード群が含まれる
環境変数設定ダイアログを使って慎重にパスを編集しましょう。

Windows: NFTSのジャンクション利用に注意

私の作業用PCでは、SSD容量の都合からC:\Users\muo\workspaceE:\workspaceへジャンクションによってマッピングしています。
Windows版のGitクライアントは、一部のサブコマンドにおいてジャンクションをうまく参照できません。
このため、.NET Core Cliビルド序盤でgit "rev-list" "--count" "HEAD"が実行されるポイントで
fatal: Unable to read current working directory: No error
というエラーを吐いて止まってしまいます。
ジャンクションで参照されている側のドライブ/ディレクトリへ移動してビルドを実行しましょう。

ビルドが遅い系

公式の開発ガイドに従ってビルドをおこないます。通常はbuild.cmdまたはbuild.shを叩くことになります。
Windowsでのビルドについて、あまりPowerShellスクリプトのinvokeを使いたくないので私は
build_projects/dotnet-cli-build/build.ps1
を直接実行しています。

ビルドが実際遅い

Gitからcloneしてきたままのそのままの状態のビルドは結構遅いです。
MacBookでは57分ぐらい(56分41秒)かかります。MacBook(2015)でやることではないと思いますが。

tip: ビルド冒頭でのNuGetパッケージ削除をやめる

2回ビルドして所要時間がほとんど変わらなかったため、毎回クリーンビルドが走っているのではという疑いを持ちました。特に、ビルドの序盤ステージで大量のパッケージのdotnet restoreをおこなう部分で毎回数分間かかっていました。
ビルドスクリプトをざっと確認したところ、https://github.com/dotnet/cli/blob/rel/1.0.0/build_projects/dotnet-cli-build/build.sh#L103-L106できっちり削除しています。Windows版はhttps://github.com/dotnet/cli/blob/rel/1.0.0/build_projects/dotnet-cli-build/build.ps1#L82-L83でクリアしています。
これらをコメントアウトしてローカルの生成物を維持すれば、ほとんどコード変更が無い場合のビルド時間を短縮できそうです。試したところ、うまくいきました。
しかしMacBook上で52分程度(52分8秒)と、4.5分ぐらいしか縮んでいません。

tip: ビルド後半のテスト工程をごっそり削る

.NET Core Cliのビルド後段はほとんどテスト実行なので、試行錯誤フェーズでは不要と切り捨てることにしました。
build.shには--targets Prepare,Compileを渡し、build.ps1には-Targets Prepare,Compileを渡すことでテストフェーズを飛ばせます。
この結果、MacBookではビルドが12分半(12分36秒)で完了するようになりました。依然として結構な時間がかかっていますが、最初から比べると5倍近いのでよしとしましょう(大きめのAndroidアプリをビルドするのにかかる時間とあまり変わらない)か。きっと、まともなCPUを積んだMacであれば5分そこらで終わるのでしょう、めでたしめでたし。

適当なWindows PCでのビルド時間が案外長い

さすがに常用環境としてMacBookでビルドするのは厳しいので、普段はWindows上で開発をおこないます。
MacBookで12分ということはWindows PCでは4-5分ぐらいだろうと考えました。しかしWindows上でのビルド時間を計測したところ、Core i5-4460を搭載したPCにて前述の2つの対応をおこなった状態で7分程度でした。
このCPUは4コア積んでいて、その割にはMacBookと時間差があまりついていないのが気になります。
ビルド中にCPU使用率の状態を簡単に確認していた限りではほぼ1コアしか使われていないようでした。ビルドシステム自体がパラレルビルドをサポートしていないこと、シリアルのビルドでコアを複数利用できていないという事情がありそうでした。
あと、特に時間を食っているのがLZMAへの圧縮工程です。
publish: Published to E:\workspace\cli\artifacts\win10-x64\tools
Published 1/1 projects successfully
[EXEC       <] [ OK ] [00:01:32.596] E:\workspace\cli\artifacts\win10-x64\stage1\dotnet.exe "publish" "--output" "E:\wor
kspace\cli\artifacts\win10-x64\tools" "--configuration" "Debug" exited with 0
[EXEC       >] [....] [00:01:32.597] E:\workspace\cli\artifacts\win10-x64\tools\Archiver.exe "-a" "E:\workspace\cli\arti
facts\win10-x64\intermediate\nuGetPackagesArchive.lzma" "E:\workspace\cli\artifacts\win10-x64\intermediate\nuGetPackages
ArchiveFolder"
Adding E:\workspace\cli\artifacts\win10-x64\intermediate\nuGetPackagesArchiveFolder 100% 2112 ms
Archiving files 100% 1099 ms
Compressing 100% 296120 ms
今回の場合、実に全体ビルド時間の7割をここで食っています。ビルド結果ディレクトリを確認したところ、12MB程度の.lzmaファイルがいくつか存在します。
当然、これLZMAの-9圧縮でエグい時間かけてるのでは…という疑いがかかります。

tip: LZMA圧縮部分の時間を削る

src/Microsoft.DotNet.Archiveディレクトリ内にLZMAエンコーダも含めているようですね。呼び出し側はtools/Archiverで、そのproject.jsonを読むと実体はsrc/dotnet-archive/以下であることがわかります。
ここのコマンドラインオプションに圧縮レベル指定があれば平和に解決したのですが、https://github.com/dotnet/cli/blob/rel/1.0.0/src/dotnet-archive/Program.cs#L29-L32を読むと残念ながらそのような気の利いたオプションはありませんでした。
諦めて、もう少しまじめにコードを読みます。https://github.com/dotnet/cli/blob/rel/1.0.0/build_projects/dotnet-cli-build/CompileTargets.cs#L311-L337のあたりがアーカイブの圧縮をおこなっている部分です。
とてもまじめな改善方針としては「ここで使っているLZMA圧縮のC#実装を改善して、圧縮レベルを指定できるようにする」というものが立ちます。しかしあいにく私はLZMAについて「圧縮がめっちゃ遅いけど展開が速くて圧縮率も良い、雰囲気bzip2をさらにエッジーにしたようなやつ」という程度しか知りません。アルゴリズムに改修を加えるのは荷が重いです。
Cmdの呼び出し部分をしれっと7-zipへ変更して-1をくっつける、というお手頃策も考えはしましたが、ここで圧縮アルゴリズムがLZMAであることは分かってもファイル構造が7-zip準拠かどうかは分かっていないので避けました。
LZMA圧縮/展開部分のコードが確実にアーカイブ作成時と展開時に共有される前提が立つならば、「LZMAで圧縮したように見せかけてストリームを右から左へコピーする偽圧縮アルゴリズムに差し替える」と方針も考えられます。しかし、展開箇所をきっちり調べずに手を動かし始めるのは危険そうな手段です。
結果、より強引な「このアーカイブがビルド成否確認の上で必要かイマイチわからないし生成スキップする」という策をとりました。これは、lzmaでCliコードをgrepかけたところ、少なくともこのファイルが後のビルドフェーズで参照されることはなさそうと判断したためです。
さて、NuGetアーカイブを作成するか否かを決めているCompileCliSdkメソッドは幸いCompileTargets.cs内からしか呼ばれていません。このため変更すべきはhttps://github.com/dotnet/cli/blob/rel/1.0.0/build_projects/dotnet-cli-build/CompileTargets.cs#L113のみです。容赦なくgenerateNugetPackagesArchive: true記述をgenerateNugetPackagesArchive: falseへ変更しましょう。
もちろん、src/Microsoft.DotNet.Cli.Utilsを辿っていくとnuGetPackagesArchiveを展開するくだりが存在するので、このhackは到底production向けのものではありません。「とにかく複数パッケージ間での依存関係に問題がなく、ビルドを通せるのかどうか」を早く知りたい場合には不要というだけです。実際にビルドしたパッケージ群を利用して実行テストをおこなう際には、LZMA圧縮のスキップはおこなわないほうが良いでしょう。

全部あわせてビルド時間が1/20になった

LZMAのアーカイブ生成をスキップする対応も含めて再度ビルドしたところ、私のMacBook上では3分ちょうど(2分59秒)、Windows PC上では1分半(1分30秒)でビルドが完了するようになりました。この程度なら待てます。MacBook上でのビルド時間を94.7%削れたので、20倍高速化したといってよさそうですね。
コードをサクサクと変更して最低限の整合性チェックまでをおこなうことができて、今度こそめでたしめでたし、です。

Chiselでサッとデジタル回路設計を始める小冊子(MFT2016配布物)の小改訂版を100円で販売します

2016年8月25日木曜日

Maker Faire Tokyo 2016(MFT2016)へ会社の有志チームで参加したことは以前書きました(参照: Making of "至って普通のWebカメラ"展示 - MFT2016出展記)。
私が出展したのはシンプルなカメラモジュール(定番のOV7670)→モニタ出力をおこなうWebカメラ(自称)で、物自体はありふれています。出力側でのTMDS変換回路とTMDS信号のシリアライズ出力部分をScala+Chiselで書いたというのが特徴でした。
今回は、出展と共に無料配布していた小冊子(図1)の話です。
展示に先立って社内の出展メンバーチャットで「MFTでは出展物の説明などの資料を配布して良い」ということが話題になっていました。せっかくなので私もWebカメラ(自称)の重要要素であるScala+Chiselに関する簡単な説明を書いて配布したいと思ったのがきっかけでした。

MFT 2016で配布した冊子の内容

12ページと短いため、コンパクトな3つのパートで構成しました。

1: 夏コミ頒布の「The Web Explorer 2」に寄稿した原稿の冒頭部分収録

「The Web Explorer 2 - 第8章 Scalaでイージーにハードを設計する」の冒頭4ページをそのまま(章番号の違いと原稿変換の都合上すこし手を入れて)収録しました。この本はつい最近booth.pmで電子版を販売し始めたようなので、よければそちらも確認ください(https://techbooster.booth.pm/items/299592)。目次をみてみると、TensorFlowやFirebaseなど私以外の章でも面白いぐらいWeb外の技術が混ざっていますね。

2: さらっとChiselを試してみようというメインコンテンツ

一定の前提知識を要求するものの、実際にこれにもとづいて最後までやってくれた方もいたので、なんとかなったようです。
そしてミス指摘までもらいました。ありがたいことです。

3: Chisel 3を軽く使ってみようというおまけ

Chisel 3は、基盤のFIRRTLも含めて絶賛開発中の次世代Chiselです。まだかなり不安定ですが、Chiselでの 非同期リセットについての現状整理、RocketChip事情を添えてでも書いたように新機能はおおむねChisel 3をターゲットに開発されるようになってきています。
このため、そろそろChisel 2向けの自プロジェクトがChisel 3でまともに動くか否かを確認し始めるのが無難です。しかしChisel 3はまだバイナリ配布がおこなわれておらず、ビルド手順が長く時間がかかるため、手元で環境を作るのが苦痛です。そんな中でChisel 3スナップショット版入りDockerイメージを作成して公開(3-snapshotタグ)したので、これを使って簡単に試してみようという話を書きました。

SBTによる依存パッケージダウンロード遅さの謎

Chisel 3のスナップショットDockerイメージのビルドにはDocker Hub上でも30分程度かかります。この理由のうち4割程度は「SBTからパッケージを拾ってくるのがやたらと遅い」というものです。あまりちゃんと追っていませんが、Scala+SBT界隈では有名な問題のようです。http://stackoverflow.com/a/31712249の「So my solution is that you have to wait a bit.(まあしばらく待っていればいいよ。)」という回答が心に来ます。相手サーバへの接続時にIPv6→タイムアウトでv4のフォールバックなどやってるのかな、などいくつか考えましたが、途中で考えるのをやめました。

冊子構成上のこだわり要素

Chiselの最初の一歩ということで、環境をサクッと用意して試してみるという点にフォーカスしました。ここでの選択肢として、今回はDockerを選びました。Windows 10上でのDocker環境は、Docker for Windows(Toolboxのことは忘れよう)によってずいぶん扱いやすくなっています(図2)。Ubuntu on Windows環境でのJava利用がまだまだ怪しいため、当分はDocker利用が最良だと思います。
図2 Docker for Windows+PowerShellからChiselのコンパイル・テスト実行をしたところ
Docker利用前提での執筆にあたっては、先日Dockerイメージを作ってDocker Hubで公開しておいたのが役立ちました。Chisel 3のスナップショット入りDockerイメージは、作成と動作確認が間に合うか微妙でしたが間に合ったので内容に盛り込みました。
たまたま先日Windows環境でのDocker(Docker for Windows)+IntelliJ IDEAでの動作確認もおこなっていたので、Windows環境でうまくChiselを扱う方法も書きました*1
さらに、執筆していた当日にChiselのGitHub issuesで起こっていた大きめの動きも書いてみました。直前まで内容をいじることのできるコピー本(コンビニのコピー機でせっせとプリントしてホッチキス製本するもの)ならではの鮮度、という感じでした。あまり読む方に伝わらない気もしましたが、少なくとも書いていて楽しかったです。
[*1] ちなみに本をPDFへコンパイルする作業もWindows上のDocker環境でおこないました

MFT 2016版を無料配布、最新版をgumroadで販売しています

MFT 2016で配布した版のPDFを無料で公開します(PDFダウンロード)。
そして、前述の指摘をもらって直しを入れた最新版をgumroadで販売しています。
100円なので、よければ投げ銭がてら買ってください!gumroadへのアカウント登録は不要です。
100円で押せる「やる気スイッチ」です、なにとぞ。

作った感想: コピー本も良いですね

雑誌寄稿時にはせいぜい発売10日前の時点でギリギリすべりこみ微調整できるぐらいです*2。TechBoosterの夏コミ/冬コミ同人誌への寄稿であればだいたい頒布の15日前時点がデッドラインです。ひとっ風呂浴びている時に思いついた変更を速やかに反映できるなども、とても便利な感じでした。
表紙と裏表紙はわりと最後までいじってました。
[*2] たまに校了から3日で発売というすごい雑誌もありますが、私は寄稿したことがありません

謝辞

Chiselを開発し、メンテナンスしているUCBのチームがなければ話が始まりませんでしたし、その周辺コミュニティがGitHubやMLへ残してきた痕跡がなければ中身の理解も難しいものでした。
出展にあたって声をかけてくれた同僚、設営を手伝ってくれた同僚、製本を手伝ってくれた同僚(同一人物の場合があります)には感謝ばかりです。MFT 2016で冊子を取りにきて速やかに試した結果のレポートをくれて記述ミスの指摘までしてくれた@cinimlにも感謝しきりです。
「本(冊子)を作ろう!」と思い立ち、すぐに試行錯誤しながら形にして即日完成まで持っていけたのはRe:VIEWのおかげですし、編集環境としてはAtom+language-reviewがもはや手放せません。これらのソフトウェア作者各位、そして「The Web Explorer 2」への寄稿記事の一部を収録することを快諾してくれたTechBoosterの@mhidakaにも感謝します。

クラウドでASICを利用する時代の必読論文が出ていたので紹介する(Bitcoin、Litecoin、H.265動画変換、ディープラーニング用のASIC試作/検討からのあふれる知見:ISCA2016)

2016年8月24日水曜日

どのような論文か

クラウドを構築するデータセンターでのASIC(特定用途向け集積回路)利用が伸びるというのを大前提として(実際、お金に直結するBitcoinではASICマイニングが主流だから当然だよね!と)、業界の流れ分析に始まり各種ワークロードの特性分析から総所有コスト最適化、排熱シミュレーションまでを幅広く扱った論文です。超オススメです。
次のURLから入手できます。
最初にこの論文を読んだ時は、12ページ(参照込みで13ページ)とコンパクトながら怒涛の情報量であったため、大変衝撃を受けました。「特に読むべきポイントは?」と聞かれたら「全部!」と答えたいところですが、せっかくなので本エントリではいくつかポイントを絞って紹介してみます。
ちなみに発表資料内で「今回の研究のために8種類のBitCoinマイナー*1を購入してリバース・エンジニアリングしたよ。サンディエゴへ見においでよ」とスナックに書いていたりします(図1)。本気度がやばいです。
図1 ASIC Clouds Exist Today(ISCA2016での発表資料PDFのp.16より)
[*1] マイニング用のチップ/ボード/クラスタを指している

前提

発表資料のp.4で、今回の話の前提を紹介しています。
コンピューティングがモバイルのSoCとクラウド(データセンター)へ二極化し、デナード則の終焉とダークシリコン問題を意識した設計が必要な時代

クラウドで使われつつあるASIC

データセンターでFPGAを使っている例としてはMicrosoftのProject Catapultや各種HFT(High Frequency Trading)がよく知られています。
いっぽう、ASICの利用(ASIC Cloud)例として論文内ではBitcoinのマイニング専用マシンを主要なものとして紹介しています。プロセス世代としては、当初130/110nmという旧世代プロセスで始まったものの、65nm→55nm→28nm→Intel 22nm/TSMC 16nmプロセスのものへと爆発的に進化していったと紹介されています。
本blogエントリを書いている2016年8月下旬の時点では、クラウドでのASIC利用といえばAlphaGoの李・セドル氏対局でも使われたGoogleのTPU(Tensor Processing Unit)*2が有名です。おそらくこの論文が投稿されたタイミングではTPUが発表されていなかったため、論文内ではカバーされていません。

TCO(総所有コスト)が最低になるポイントを探る

ASIC化にあたってはどれだけの電力と資金を投下してどれだけのパフォーマンスを得るか、という選択をおこないます。ここでは設計上のいくつかのパラメータ設定が重要です。
チップのコア電圧を下げると消費電力を劇的に下げられる反面、稼働可能な最大クロック数も低下します。このため、1チップあたりの処理性能が落ちます。
ある程度コア電圧を下げて1チップあたりの消費電力を削り、その一方でサーバスペースへ大量のチップを実装して適切な通信系を整備することでボード全体の性能を高めることになります。
しかしチップ数を増やすことでインターコネクトが複雑化したり、実装面積が不足してデータセンター内の領域を圧迫してしまっては元も子もありません。
この論文では、なんとこの面の分析をきっちりおこなっています。まず、パフォーマンスあたりのコストと処理あたりのエネルギーという2軸のパレート最適を分析しています(例:図2)。そして、これらの状態群に対して、各パラメータへの適切な重み付けをおこなうことでTCO(総所有コスト)の最適化検討までおこないます。
図2 Bitcoinマイニング用ASICのパレートカーブ(投稿論文PDFのp.19より)
外部メモリへのアクセス性能が重要な場合は、1つの処理チップあたりいくつのDRAMチップを接続するか、などでも性能が変わります。このため動画変換(H.265)のケースでは重要要素として検討されています。
データセンターでのASIC利用の前提は「チップの設計や製造にかかるコストよりも消費電力とファシリティ維持コストのほうが支配的になる」ことですが、その中でも具体的なコスト最適化プランの枠組みが提示されていることの意味は大きいと感じました。

ボードへのチップ配置方法に関する検討

チップの安定稼働にとって熱は敵なので、うまい排熱方法を確立しておく必要があります。
データセンター内では通常、サーバラック手前から冷たい空気を吸気し、ラック内のサーバモジュールを冷やし、背面へ排気するという構造をとります*3。このため、背面に近いチップほど前面に近いチップからの排熱を受けた熱い空気を使って排熱することになり、効率が悪くなります。
この論文ではサーバモジュール(ボード)上の各要素が発する熱を勘案して排熱効率を数値流体力学によってシミュレーションしています。
図3 ASIC Server Thermal Optimization(ISCA2016での発表資料PDFのp.33より)
そして、チップをどのように配置すると排熱効率を高められるかという検討もおこなっています。
図4 ASIC Placement: Duct Wins(ISCA2016での発表資料PDFのp.34より)
普通に並べたもの<チップを入れ違いに並べたもの<ダクトを設置したもの、という結果が紹介されています。
[*3] 液浸によって冷却するシステムも見かけますが、コストやメンテナンス性の面から少なくとも商用データセンターにおいて現時点の主流ではありません

各ユースケースにあわせた性能ファクタ検討

ISCA 2016での発表資料のp.40に、アクセラレータの特性を決める要素が各ユースケースの評価と共に紹介されています。
図5 Accelerator Properties(ISCA2016での発表資料PDFのp.40より)
  • Bitcoinは特定プリフィックスを持つハッシュのゴリ押し検索という計算特性から、ロジックをいかに詰め込んでひたすらに回せるかが重要(On-chip Logic Intensityに偏ったケース)
  • LitecoinはScryptという、計算に一定のメモリ領域が必要でランダムアクセスの必要もあるという計算特性から、チップ上に搭載するメモリとの兼ね合いが重要(On-chip RAM Intensityに偏ったケース)
  • 動画変換(H.265)は対象データ量が多くDRAMアクセスのスループットが必要なことからDRAM or I/O Intensityが高い(他の根拠は論文内で示されていないものの、内部で利用される計算式の複雑さのためOn-chip Logic Intensityも高めの評価と解釈)
  • 畳み込みニューラルネット(DaDianNaoベース)は大量のDRAMアクセスが発生するのに加えてチップ間の通信にHyperTransport(HT)を利用するため、Latency Sensitivityを強く評価

おわりに

本エントリではこの論文の良さの5%も伝えられていない気がします。ここで紹介しなかった要素が多いのに加えて、ここで紹介した内容だけに関しても、それぞれもっと具体的なことが論文に書かれているので、ぜひ読んでみてください。

Chiselでの非同期リセットについての現状整理、RocketChip事情を添えて

2016年8月23日火曜日

同期リセットと非同期リセット

HDLから回路の初期状態を設定するための主要な方法として、同期リセットと非同期リセットがあります。
これらの差について詳しくは述べませんが、FPGAの文脈ではXilinxが同期リセットを推奨し、Alteraが非同期リセットを推奨しているという事情があります*1
Chiselで回路を組むうえで、(特にASICの)レジスタ初期化に非同期リセットを表現する仕組みが欲しいと感じたことがある方も多いでしょう。今回はChiselの処理トリガ実装を簡単に紹介したうえで、非同期リセットに関する現状と議論を整理します。
[*1] 同期リセットと非同期リセットでの配置配線結果差については@marsee101さんのFPGAの部屋 FPGAの非同期リセットと同期リセットの比較シリーズが詳しいです。

Chisel 2.2.35時点の処理トリガ実装

Chiselの最終出力がVerilog HDLである以上、Chiselが持つ表現力の限界はVerilog HDLコードのエミッタ部分を読めばわかるはずです。
Chisel 2.2.35に含まれる、指定信号のエッジにあわせた処理をおこなうためのVerilog HDLコード生成部分は次のとおりです(https://github.com/ucb-bar/chisel/blob/7dd686d968/src/main/scala/Verilog.scala#L531-L536を抜粋*2)。
  for ((clock, dom) <- clkDomains ; if !dom.isEmpty) {
    if (res.isEmpty) res.append("\n")
    res.append("  always @(posedge " + emitRef(clock) + ") begin\n")
    res.append(dom)
    res.append("  end\n")
  }
各クロックドメインにロジックが含まれていれば、クロックの立ち上がりエッジにあわせてクロックドメインのコードを書き出すという具合ですね。
Chiselのソースコード上でposedgeというキーワードが登場するのは、この部分とVerilog HDL用のキーワード列挙部分のみです。ちなみにposedgeと対をなすnegedgeは、テストハーネスコードの生成部分(と、posedge同様Verilog HDL用のキーワード列挙部分)でしか登場しません。
つまり、ChiselのVerilog HDLコード生成系はposedgeでの駆動、しかも個別のクロック信号に基づく処理を記述する能力しかありません。
このため、Chiselで組んだ回路から次のようなVerilog HDLコードを直接生成することはできません。
always @(posedge clk or negedge RST) begin
...
end
BlackBoxを利用してゴリ押せば別ですが、BlackBox内のコードは当然Chiselの言語仕様もランタイムも一切文句をつけてくれない(=守ってくれない)エリアです。JavaScriptのevalと同程度には気を配って使うべきでしょう。
[*2] Chiselのコードはhttps://github.com/ucb-bar/chisel/blob/7dd686d96/src/main/scala/Verilog.scala#L1-L29に記載のライセンスに基づいて利用しています

Chiselでの非同期リセットサポートに関するissuesと議論

非同期リセット不要論

ChiselのMLアーカイブにAsync reset in generated Verilog always blocksというスレッドがあります(2015/02/17-2015/03/18)。
マクロを使えばなんとかなるよ!というたくましい解決方法などが提案されていますが、原則的にChisel側で非同期リセットをサポートするつもりはないという結論です。当時UCB内での議論はhttps://groups.google.com/d/msg/chisel-users/4cc4SyB5mk8/AVSI-GLjrmUJに集約されていたようです*3
この半年ほど後にGitHubのissueとしても似た話がSupport for asynchronous resets in Verilog backend #549(2015/09/27-引き続きopen)として出ていました。
[*3] これが公式見解かというと微妙なところですが、少なくとも返信しているのはUCBの博士課程(Architecture Researchではない?)に在籍されていた方なので、学内主流の意見を取り上げて投稿しているものと解釈しました

2016年8月の急展開

非同期リセットのサポートはChisel 2で決着がつきませんでしたが、Chisel 3のバックエンドであるFIRRTLのSupport for asynchronously-resettable registers #219というissue(2016/08/05-)によってサポートの見通しが立ちました。
事態が動くきっかけになったのはRocketChipのAdd asynchronous FIFOs as an option for clock domain crossings. #190というpull-reqです。これは、RocketChip内で利用している回路間接続ユーティリティであるjunctionsライブラリ(https://github.com/ucb-bar/junctions)をRocketChip側で独自に拡張してFIFO機能を持たせようというものです。
このpull-reqへレビュアーとしてアサインされた方が「すでにjunctions側でこの実装を書いていたけれど、MemとSeqMemをふたつのクロックドメインから安全に利用できない限りマージすべきでないためしなかった。同じ理由でこっちもダメ」と突っぱねたことで流れが変わってきました。科学と魔法が交差した瞬間ですね。
この事情説明に続いて非同期リセットが必要という話が展開され、同氏の「SiFiveの人たちに、とにかく全リセットを非同期にすべきとうるさく言っているけれど、今のところ効果なし」というコメントがダメ押しとなってついに前述のfirrtl#219へと至りました。enhancement扱いなので優先度はさほど高くありませんが、これまでよりもかなり前進しました。
なお、時系列がややこしいのですが、前述のRocketChipへのpull-reqと前後して、当初Gitのsubmoduleとして取り込まれていたjunctionsはRocketChip側リポジトリの中にソースコードレベルで取り込まれるようになりました。さらに、2016/08/20のコミットで置き場所がhttps://github.com/ucb-bar/rocket-chip/tree/7b20609d4/src/main/scala/junctionsへと移動しました。pull-reqやコード本体を追う際には注意しましょう。

進むChisel 3、置いていかれるChisel 2

FIRRTL/Chisel 3で非同期リセットをサポートする方針になったのは良いのですが、現在主流のChisel 2はどうなるのでしょうか。
Chisel 2に対する各種の修正/変更は最近あまり優先度高くおこなわれない状況にあります。
たとえば、Chisel 2で複数クロックドメインを生成して、それらの間でデータのやり取りをおこなうコードを書いた場合、C++バックエンドを生成するとErro in C++ backend : (error: ‘T54’ was not declared in this scope) #464のようなエラーへ頻繁に行き当たります。要はC++コード生成部分で中間状態(wireと同等のもの)のスコープを適切に処理できておらず、暗黙のクロックに依存するコードが生成されるためですが、このissueは長く放置されています。
Chisel 2の問題に対する取り組み指針を伺わせる別の例としては、Compilation Error when assigning from other clock #696というクロックドメインまたぎに関するissueへのコメントが挙げられます。
このなかに、
Then again, it may be worth punting on this issue (to chisel3). A clock domain check is particularly amenable to a FIRRTL pass and, further, it is a FIRRTL pass that users may want to customize.
という発言があります。不要不急の変更をChisel 2に加えるのはなるべく避け、問題解決はFIRRTL/Chisel 3でおこないたいということですね。
このようにChiselプロジェクトの進行を見ていると、全体的に「はやくFIRRTLベースのChisel 3へ移行して、つぎはぎだらけのC++/Verilog HDL生成系から解放されたい。つらい苦しい」という雰囲気が出ています。

結論

Chisel 3では非同期リセットがサポートされる見込みです。非同期リセットを書きたい用途ではChisel 3への移行をそろそろ考え始めたほうがいい(今すぐ非同期リセットを使えるとは言っていない)です。どうしてもすぐに使いたければ、yet another Scalaでデジタル回路を書く仕組み: Spinal HDLを参考にChiselインスパイア系言語であるSpinal HDLを試してみても良いかもしれません。

yet another Scalaでデジタル回路を書く仕組み: Spinal HDL

2016年8月22日月曜日

先日あれこれと調べている時にSpinal HDLを見つけて気になったので、簡単に調べた結果をまとめておきます。今のところは主に自分用の備忘録というか下調べ状態です*1
[*1] そもそもyet anotherというのは3番手以降に出てきたものについて付けられる修飾子な気がしますね

Spinal HDLとは何か

Spinal HDLは、Dolu1990氏が中心となって開発している、ハードウェア(デジタル回路)設計用のScala組み込み言語(DSL)です。Gitのコミット履歴をみる限りでは2015/01/25に始まったものです*2
[*2] これに続く書き溜め分コミットの内容から、実際には2014年8月に開発を開始し、2015年1月に一旦の区切りまで到達したらしいことがわかります
ハードウェア記述言語(HDL)としての立ち位置はChisel HDLと似ています。いわゆる高位合成系ではなく、HaskellのLavaと近い位置付けのDSL+ライブラリ群です。

Spinal HDLとChisel(Chisel HDL)の関係

Chisel → Spinal HDL

登場順序でいうとSpinal HDLはChiselの後発プロジェクトです。ソースコード考古学的な意味ではChisel(Chisel HDL)の派生物にはあたらず、私が把握している限りでのコード共有はありません。Chiselに触発されて生まれた新実装です。
ライセンスも両者で異なります。Chiselは修正BSD(いわゆる3条項BSD)ライセンスです*3。Spinal HDLはコア部分がLGPL 3、周辺ライブラリがMITライセンスです。
[*3] 完全に蛇足ですが、Chiselを開発しているUC BerkeleyはBSD/修正BSDライセンスの本家本元でもあります
もともとDolu1990氏はChiselを使っていて、行き当たった問題などをissuesとしていくつか登録しています(#207, #213, #265)*4
[*4] issueコメントで2014年3月頃からChiselを学び始めたと書いています

ChiselとSpinal HDLの違い

Spinal HDLのドキュメントには「Chiselとどう違うのか?」について詳細に述べたページがあるので、参照してください。かいつまんで紹介すると、次のような問題を指摘しています。

Chiselはいくつか構文上の問題や下回りの実装に起因する実用上の窮屈さを持つ

  • プログラマがミスを犯しやすい局面で警告を出してくれないパターンがいくつかある
  • 標準で用意されているライブラリが物足りない
  • 生成されるVerilog HDLコードが到底人に読めるものではない
  • クロックドメインを複数持つ回路の実装が大変(リセット信号の扱いが中途半端、非同期リセットを持たないなど)
  • Scalaの型とChisel用の型を暗黙変換すべき
これらに対して、issueやPRという形でおこなわれた改善提案があまり実を結んでいないこと、Chiselプロジェクトの立ち上がりから経過した時間の長さを考えると今後も取り込まれる見込みが薄いことからSpinal HDLを開発するに至ったと記されています。

Spinal HDLの機能と仕様に関するメモ

あまりまとまっていませんが、構文面はChiselとキーワード差程度で似ていて、実際に使うと勝手が異なる雰囲気です。
  • 最終出力先のHDLとしてVerilog HDLだけではなくVHDLもサポートする
  • ChiselでModuleクラスを拡張して回路を組むところでComponentクラスを拡張する
    • 出力先としてVHDLも選択できる事情によると考えられる
  • Bundleの扱いはChiselと似ている
    • 互換性のないBundle同士を<>でつなぐのはコンパイルか検証時に弾かれそう(未確認)
  • 論理回路を組んでいく部分は基本的にChiselと似た構文で書ける
    • 演算時のbit幅拡張仕様は異なる雰囲気(未確認)
  • 回路記述負荷を低減するための構文やライブラリがある程度存在する(後述)
  • ChiselのようなC++コード経由でシミュレータ(DUT)を生成してScalaコードとつないでテスト、の仕組みは持たない*5
[*5] Describe testbench from within Spinalで話題になっていますが、当面はRTL(コードの生成)側へ注力するようです。

Spinal HDLの良さそうな点(主観)

クロックとリセットの扱いが圧倒的にChiselよりもうまい

Spinal HDLは作者自身が前述のChiselに対する不満点で書いている、クロックとリセットの扱いに力を入れています。少なくともドキュメントを読む限りでは、これらは圧倒的にChiselよりも練られています。
  • 特にClockingAreaという、モジュール(Component)の一部を指定クロックによって駆動する仕組みがクール
  • Chiselで最近ようやく導入に向かってる非同期リセットも当然のように存在する
  • クロックドメインまたぎで面倒なメタステーブル現象の回避のために、ChiselのAsyncFifoよりも扱いやすいバッファ(BufferCC)を用意している
詳しくはクロックドメインに関するドキュメントを参照してください。

ステートマシン構築の苦労を減らす仕組みを用意している

Spinal HDLが(Chiselと同様)高位合成系ではない以上、アルゴリズム記述のうえで問題になるのがロジックのステートマシンへの分解です。
Spinal HDLの標準ライブラリには、ステートマシン(FSM)を構築して状態間の遷移記述を省力化するライブラリが含まれています(ステートマシンの説明)。
ここでは以下の要素が登場します。
  • 状態開始時の処理: onEntry
  • 状態中の処理: whenIsActive
  • 状態を抜ける際の処理: onExit
これら3種類の処理と、状態間を遷移するためのgoto呼び出しでロジックを構成します*6。ソフトウェア方面から来ると、キーワードを見た瞬間に「ヒッ、gotoだ!!」となるような気もしますが、つまりは必要悪です。
[*6] 2016/07/27のSFM: Added whenIsInactive.コミットで、なんとinactive時の処理も書けるようになりました。whenIsInactiveでステート間のgotoを発生させたらどうなってしまうのか…。
Chiselでenumを使ってシンプルな状態管理をしていくと、どうにもコードのネストが深くなりがちですが、この記法だとある程度コンパクトなコード群に分解できるのがメリットでしょうか。とはいえ、さすがに30-40ステートに及ぶものを書くならば諦めてC/C++からの高位合成系へ放り込んでBlackBoxとして組み込んだほうが良さそうですが。

せっせとComponentを切らなくともロジックの塊を記述できる仕組みがある

ロジックのまとまりを書いてローカルなスコープで利用したい場面は多いです。Spinal HDLでは、Componentを継承してioを定義せずともlightweightにロジック群を書く仕組みとしてAreaを用意しています(Areaの説明)。
実はすでに紹介した指定クロックドメイン用ロジックを書くためのClockingAreaはこの一種です。
Chiselでインライン定義モジュールを作るためには内部でio変数を定義して入出力接続をおこなう必要があります。Chiselは設計上の判断としてこのような仕組みを用意していない印象ですが、クロージャにどっぷり浸かった民としてはやはり欲しいところです。

標準ライブラリに各種バスが揃っていて脳汁が出る

Spinal HDLのライブラリを覗いてみると、AMBA3(AHB-Lite、APB)、AMBA4(AXI4、AXI4-Lite)にAvalonMMもあります。実際に試してみないと性能のほどはわかりませんが、少なくとも既存のIPと指定バスでつないで実験をするあたりまでは省力で進められることを期待できます。

少人数プロジェクトゆえの小回りの効く開発

StateMachineの「泥臭いけど必要」な設計といい、Dolu1990氏が取捨選択を決定できる圧倒的な身軽さがある(そして精力的に開発している)ため進化速度がはやいです。なお弱点はそっくり裏返しで、アクティブ開発者がDolu1990氏含めて2名のみというところですね。

まとめ

Chiselインスパイア系言語/環境のSpinal HDLは、Chiselへの不満を解消するように多くの工夫を凝らして作られています。Spinal HDL環境には、Chiselにも欲しいなーと思うようなものがいくつも存在し、Chiselへ輸入できそうなものも多いです。
Spinal HDL→Chiselの輸入のためにChiselをforkするよりは大人しくSpinal HDLを使っても良いのかも、と感じるところもありました。しかし私がChiselの仕組みで特に気に入っているのがテスト周りで、この仕組みを現状のSpinal HDLは持たないので、すぐにこれを実用してみるイメージは湧いていません。
個人的にはNode.js対io.jsの構図で、Chiselの新仕様をせっせと練る場としてSpinal HDLが機能して、最終的に統合されるシナリオであると安心して両方を掘っていけるのですが、その実現には両者のユーザ規模が1万倍ぐらい足りませんね…。
今回書いたのは実用した評価レポートなどではないため、今後実際に触ってみて印象が変わる可能性も大いにあります。これからもたまにSpinal HDL事情を調べて、時折触ってみようと思います。

Making of "至って普通のWebカメラ"展示 - MFT2016出展記

2016年8月12日金曜日

MFT出展報告

8/6-8/7に開催されたMFT 2016(Maker Faire Tokyo 2016、図1)からぼちぼち1週間が経つので、忘れないうちに振り返りと反省と、そして夏コミ3日目で出る同人誌の宣伝をします。
図1 MFT 2016会場の図

出展したもの

中身のデジタル回路をScala+Chiselで一部自作したWebカメラ(図2)展示と、関連する12ページのコピー本(Scalaでハードウェアを設計するはじめの一歩!、図3)の無料頒布です。
図2 展示したWebカメラっぽいもの

準備にかかった期間

社内で最初に出展の話が出たのは4月の下旬だったと記憶しています。
実際の作業にかかったのは展示のおおよそ8週間前、そこからコミケの原稿準備と並行して休日を突っ込み続けて完成へ至った、というタイムラインです。

準備の流れ

基本的に「実現したい夢仕様」から現実的なラインまで仕様を削っていく作業でした。
お題の大本は4/25発売のFPGAマガジンNo.13掲載の記事です。TMDS変換と出力データのシリアライズをおこなう回路の作成を作成してあとは展示待ちというところでした。が、前日に「コピー本を作って配布したいなぁ」と思いました(図4)。
図4 Slackでふと思いつきを書いたところ
そういうわけで今回は物理パート、論理パート、勉強パートの3面、それと最後に加わったコピー本の順で準備段階のあれこれを紹介します。

物理パート

カメラモジュールを入手してブレッドボード用ワイヤなどで配線

最初にカメラモジュールを注文したのは6月上旬です。この時はOV5642という少々高性能なモジュールを入手しました(お高かったです)。軽く手元のワイヤを投入して接続、動作確認し、「これは配線ノイズでかいので基板を起こさないと厳しい」「早晩モジュールをぶっ壊す」と考えました。
OV5642よりもと、多少扱いの面でも楽(コマンド体系が8-bit列なので)なOV7670を1つ購入し、さきの仮組み状態で仮動作確認しました。これは、まあまあいい感じに動きました。OV7670はOV5642の半額程度で入手できるので、最悪破壊しても泣かずに済むというのもありました。

基板の設計と発注

KiCadで雑基板のスライドを読み、ついに「ああぁぁ、KiCadってこういうことだったの!!」というアハ体験(古い)をしました。
6月下旬、Elecrowへと基板の注文(注文オプションは4-7 days, Shenzhen DHL)をおこないました。なんと2日後には「発送したやで~」というメールが届き、その週内に入手できました。DHLのセンター(最近新しくなったっぽい)へ出向いて荷物をピックアップするという体験、個人的に割と楽しかったので、回を改めて書きます基板をピックアップした足でそのまま秋葉原へ向かい、秋月と千石を回ってコネクタを入手しました。今回は基板上に抵抗もコンデンサも実装しない、単純に可搬性と配線の確実性を確保するためのものなので、そういう感じです。
これ、実は技術書典の日なんですね。とにかく急いで確認せねばということで基板にコネクタをハンダ付けして動作させてみました。

基板の動作確認

OV7670をつないだところ、なんだか動きません。そもそもカメラモジュールの電源が入っていないような挙動です。
元々動いていたユニバーサル基板ベースのものに挿し替えてみても、どうにも反応がありません。
状況を追うこと数十分、コネクタの向きを完全に間違えていた事に気づきました。
これはカメラモジュールを破損させてしまったかなと、恐る恐る(何度も確認して)OV5642を逆向きに挿したところ、少なくともノイズ入りの映像は取得できました

基板失敗からの現実逃避

OV7670を破損させたショックと基板設計ミス(確認は何度かしたつもりだった)のショックでその日は作業をやめて、ひとまず技術書典へ向かいました。
余談ですが、途中で
のアナウンスを見て焦りました。
なんとかギリギリ整理券を確保できた図です。
技術書典から引き上げた後は、さきのショックの影響で数日呑んだくれました。

基板設計リトライ

翌週半ばに気持ちが復活し、直した版の基板設計を仕上げました。そして追加注文したOV7670(今度は念のため2つ買いました)を使って前の基板の表裏逆版がきちんと動作することを確認したうえで入稿しました。特に今回の場合は関係ないのですが、チュートリアル動画の出来がよかったので等長配線(差動ペアではない)とskew調整も込みでやってみました。
図5 KiCadでの回路設計リトライ版
余計なことをした結果またミスってたらどうするかというのは考えました。しかしここらはいろんな仕組みを試してはショット撃ってなんぼです。最悪ダメだったらもう一度いそいで作り直し、Elecrowの特急コースへ金の弾丸を叩き込む覚悟をしていました。PCBのCADデータ入稿時点で6月の末、今回はちょうど1週間程度で発送通知がきました。これで7月の上旬まで溶けた格好です。

リトライ版の動作確認

届いた基板の動作確認をして、問題ないことをあっさり確認できました。
展示の1ヶ月前にはハードウェア側をfixして残りはソフトウェアに充てたいと考えていたので、この時点で時間切れです。いい感じの筐体なども用意することなく、基板強度を活かして剥き出し展示でいくこともほぼ決まりました。コミケ向けの記事執筆に十分な時間を取らないとクオリティ面で問題が残りそうというのも見えていました。

論理パート

前半はコミケに向けて記事を書く傍らでほぼFPGAマガジンNo.13に掲載のままのコードを動作させていました。部品を注文して届くまでの間や基板を発注して届くまでの待ち時間は記事執筆にあてました。
ソフトウェアに関しては、NiosII/eプロセッサからSCCBの16-bitコマンドインタフェースでOV5642をコンフィグするあたりに結構時間を費やしました。しかし物理パートで述べたようにOV7660での動作を先に安定化しないとまずい状況になってきたため、結局コード的にはほぼ雑誌掲載コードのダウンロード版のまま開発を進める方針へと転換しました。
その後、夏コミ用の記事が進捗すると共に、Chisel版のTMDSコードも進捗しました。Chisel版のTMDS変換コードを書き上げてからしばらくは放っていて、休み(いわゆる毎年捨てられてしまう年休)を2日確保してシリアライズ回路のChisel化をおこないました。さらに、PCがなくてもコンフィグ済み状態でFPGAボードを起動できるようにpofファイルを作成してフラッシュメモリ領域へ書き込んで完成ということにしました。

勉強パート

Chiselの各種ドキュメントは、この期間中にあるだけ全部読みました。UCBでのアサインメントの資料なども参考になる部分は一定ありましたが、このあたりは今後紹介してみたいところです。

FPGAマガジン No.13

AlteraのMAX10シリーズFPGAをさまざまに利用するという特集号です。昨年購入したBeMicro Max10がちょうどそのまま使えるな、ということで展示物を考えるヒントになりました。

実用HDLサンプル記述集―まねして身につけるディジタル回路設計

知識と経験の不足を補うために最初に買った本が「実用HDLサンプル記述集―まねして身につけるディジタル回路設計」です。これは良い本なのですが、読み進めるうちに自分が必要としているのはもう少し手前から紹介している本じゃないかなー?と考え始めました。

HDLによる高性能ディジタル回路設計

その後、7月に入ったあたりで「HDLによる高性能ディジタル回路設計 - ソフトウェア感覚を離れてハードウェアを意識する」を買って読みました。
この本は、デジタル回路に関する理解の足りないところを補ううえで大変役立ちました。特にメタステーブル現象など回路動作を不安定にする要因の説明と対策の章が素晴らしいものでした。
また、これまでデジタル回路系はVerilog HDLで書いてきたため、読み始めには「えー、VHDLなのーー?」と思っていました。しかし読み終わる頃にはどっちでもよくなっていた(一定範囲のコードであればVerilog HDLでもVHDLでも問題なく読めるようになった)ので本当にありがたい本です。

コピー本から当日入場まで

思いつき

MFTの会場で新作のコピー本を配布して、あわよくばコミケでのTechBooster本(特にThe Web Explorer 2)の宣伝をしようと思い立ちました。思い付いたのが前日だったので、取り急ぎTechBooster代表のひつじ(@mhidaka)に「記事の冒頭4p収録したいんだけどよいかな?」と転載の打診をしました。結果は「52ページあるし、冒頭4pぐらい構わんじゃろ」という雰囲気だった気がします(記憶が曖昧)。okを得られたので、予告編4ページを含む12ページの冊子を作ることにしました。表紙と裏表紙を除くと新規に書くのは6ページで現実ラインです。ともかく、さっさと退勤して内容を詰めていくことにしました。

骨子を固める

まずは内容の骨子です。内容はコミケで頒布する本の中の記事を補完しつつ予告編となるようにしようと考えました。
また、先日SBT+Chisel向けの環境一式が入ったDockerイメージを作っていて、さらにChisel 3を試すためにそのChisel 3版も作っていました。リンク
これらを利用してサクッとお試し入門してみようという話と、加えてコミケ版でほとんど言及しなかったWindows環境でのChisel開発について補足することにしました。せっかくコピー本なので最新事情(GitHubのChiselリポジトリ上での当日の議論)についても言及し、Chisel 3の現プレビュー版を利用してビルドするとどの程度のエラーが出てくるのか、簡単に試せればそこから次のステップが見えてくるかも、と考えてそれも含めることにしました。

資材調達

書くことが決まったら、まずは資材の調達です。原稿が仕上がらなければ最悪ページ数を減らせば良いのですが、製本工程でつまづくと面倒そうだったので、コピー本向けの製本グッズを購入します。
コピー本といえば縦とじのできるステープラー(ホッチキス)なので、Amazon Prime Nowで買いました。なお、ステープラーだけだと500円ぐらいで、Prime Nowの最低額へあわせるために芯を大量購入すると何万本も手元に残ることになりそうでした。特に買いたいBlu-rayなどもなかったのですが、ちょうど手元在庫が切れていたアサヒのウィルキンソンタンサン(500ml)x24が1,900円だったので、渡りに船という感じでカートへ追加しました(図6)。
図6 Amazon Prime Nowで資材調達
私の出展物は写真中央あたりのモニタに映っているものです。
中央右に見える箱は@tenntennのVRゴーグルです。

原稿の大枠を整備

前述の骨子に従って書き始める前に、最後の段階で足をすくわれると面倒な下回り整備をおこないました。骨子を考えてから一旦頭の中をクールダウンしたいというのもあったので、雑務を先に片付けた格好でもあります。
ここで具体的にやったのはRe:VIEWで冊子を作る際のコンフィグです。まず、今回の冊子は12ページしかないので、目次に1ページ持って行かれては面倒です。表紙の2ページ先のトビラも当然無し、奥付も無し、という具合にconfig.ymlをいじって調整していきました。
この段階で書く内容ごとのページ数は決まっていたため、仮(アタリ)の内容を埋めてレイアウトをざっくり確認しました。とりわけ、Chisel 3のくだりはページ数が極端に少ない(1ページ)ため、なるべく不要な領域を詰めたいという事情がありました。多少レイアウトは不自然になりますが、この章はpostdef扱いにしました。
120ページ級の書籍とは綴じ方から何から違うため、本来は紙面レイアウトのパディングを減らしたいところでした。しかしコミケ版の原稿をそのまま4ページ拾ってきて掲載する都合上レイアウトが変わるのは避けたかったので、そのまま(いわゆるてくぶレイアウトを維持)にしました。
ひとまずその4ページを拾ってきて貼り付けたあたりで着地点が十分に可視化されて、テンションが上がってきました。

原稿執筆

ひたすら書きました。基本的にホームグラウンド(Dockerまわり)の話を中心に書くことにしたため、あまり手が止まらずに進みました。

表紙と裏表紙の作成

あまり手が止まらなかったとはいっても、さすがに途中で疲れてきたので現実逃避に表紙と裏表紙を作りました図7。
図7 頒布した本の表紙(左)と裏表紙(右)
最近はもっぱらAcrobat DC専用と化していたAdobe CCですが、Illustratorが大変役立ちました。
下敷きにしている画像は、今回作った「自称Webカメラ」の写真です。iPhoneでササッと撮りました。
裏表紙は普通に文章を書こうかと思ったのですが、Re:VIEWでは図への回り込みなどを扱いづらいので避けることにしました。Keynoteでぺたぺた貼り付ける策も考えましたが、なるべくWindows上で作業したかったのとKeynoteからPDFへのエクスポート時の画像解像度の扱いが少々不安だったのでやめました。裏表紙もIllustratorで作ることにしました。

完成から印刷・会場へ

表紙と裏表紙が完成して、いくらか追記をおこなって大筋完成後は、文章のおかしなところをセルフレビューしました。展示当日朝に全体を通して確認していくつか軽い変更を加え、「もうこれ以上はいじらない」と覚悟を決めてセブン-イレブンへ向かいました。まず1部出力したところ、サイズをミスって完成サイズがA5になったので慌てて完成がB5になるように設定変更しました。あとは問題なく出力できました。今回の展示物では、19インチモニタが多少持ち運びにくい程度だったので、ささっと荷詰めをして会場へ向かいました(図8)。
図8 さっさと荷詰め
途中で朝ご飯を食べて、展示ブースの下にべろんと貼り付けておく紹介資料をKeynoteでそいやっと作りました。内容は概ね冊子のサマリなのでサクサクできました(なお、これをA3横で作ってしまったため、6人出展のブースで幅を取り過ぎて周りの人に迷惑をかけてしまったりもしました)。あとは最寄りのファミマで印刷してめでたし、です。
ビッグサイトへ移動して設営を終えました(図9)。
図9 設営を終えた会社の有志6名ブース

出展中

トータルで1日目10部、2日目25部を配布しました。部数設定が少なすぎると感じるかもしれません。とにかく余らせたくなかったのと、コンビニのコピー機でそこそこ身軽に印刷できる規模の数にしたかったというのがあります
今回のゴールは「大量に配布する」ではなく、「余らせずになるべく興味を持った人の手に届ける」でした。
考えてみると、10部でもB5用紙60枚相当、15部だと90枚相当あるわけで、手元に残って破棄するよりは少部数にとどめておきたいと感じるものです。

1日目

1日目は10部+見本を作成して持ち込みました。
12時開場で、13時過ぎには残部がなくなっていたようでした(交代で展示番をしていたのですが、戻ってくる前に捌けていました)。
engadgetの方がTwitterで見て欲しかったんですよーと言って持って行ってくれましたよ、と後で教えてもらいました。ありがたや。
自分がブースに居る時はあれやこれやと説明したり、Chiselを布教したりしていました。
実現できているものが凄いとかそういう展示ではなく、こういう作り方(手法)があるよという紹介が主題の展示物というのが初めてだったので、難儀する部分もありました。相手がどういう方なのか分からない、完全なオープンコンテキストの中で説明するのって割とむずいな、みたいなことを今更のように思いました。
HDLでの開発者の方、PyCoRAMとSynthesijerを使ったことのある方、Scalaでソフトウェア開発をしている方など、多くの方と話せたのでよかったです。HDLや高位合成系の経験者の方にChiselの良さは割と紹介しやすいものでした

2日目

2日目は15部を持ち込みました。
なんかミスって最初にA4仕上がりを1部作ってしまいました。15部は例によって(2日目は開始が早いこともあり)13時ぐらいまでに捌けました。そういうわけで、増刷することにしました。幸い文字系のイベントではないためかビッグサイト内のセブン-イレブンの複合機は空き時間が多いことが前日に分かっていました。部数は10と決め打ちして印刷、製本作業をおこないました。
問題は配布方法です。前日から「読んでくれそうな人に届いてほしいな」というところが少々気になっていました。もちろん、気軽に1部持って行って欲しいし、読んでみてワンチャン興味を持って何かにつながれば良いというのが大半の気持ちです。
それでも、前日に興味を持って熱心に話を聞いてくださった方へ残部なしがゆえに渡せなかったという心残りがありました。
こういう場合、鉄板なのは有料頒布(たとえば100円、10円でも可)にすることです。「なんか無料で冊子を配ってるから、とりあえず持って帰って気が向いたら後で読もう」というところから、10円ないし100円という「金銭的に痛くないけれど、明確な意思を持って入手した」という状況へと大きく変わります。今回の場合は、MFT2016前日の告知時点で無料と言い切っていますし、そもそもがコミケ本のプロモーションという位置づけで書いた部分が大きいので、これはダメです。釣り銭の用意もありませんし、一緒に出展していた5人への周知とある程度の負担が必要になる点もあります。
次の策は「見本誌を手にとってくれた方へ無条件でお渡しする」です。自分がブースに居ないタイミングでも、ある程度オペレーションを回しやすい方法だと思います。少々迷いましたが、この時点で展示時間が残半分を割りつつあったので、他の人への周知その他を考えた結果、これも採用しないことにしました。
結果、「10部中の5部は従来通りブースへ置いておいて自由にとってもらえるようにする」「残5部は自分で持ち歩いて、会場内の他ブースの(主に旧知の)方へ挨拶ついでに押し付けたりして回る」ということにしました。これはとても重要な結果につながるのですが、その話は本題から逸れるので別の機会に書きます。最終的には、無事に残部なく(一緒に出展していた社内のメンバーへ渡すつもりだった予備まで含めて)配布できました。

反省

冊子の配り方は目的に応じてあらかじめ工夫を考えておくべき

あまり細かくセグメントすると感じ悪いというのもあって、今回は原則宣伝用と割り切りました。MFTの展示自体にどの程度お金をかけることを許容するかという話でもありますが、やはり効率的に多くの方に届けたいものです。

主要モジュールは2つ買うこと

2つ買うのは高すぎるから無理、というものはそもそも十分な経験を持って扱うのでない限り不適です。避けたほうが良いです。何がおかしいのかをトラブルシュートしていった際に最後にモジュール差し替えて確認という手段をとれるのはとても大きいです。

基板色を黒指定すると、基板パターンがよく分からないので要注意

Elecrowでは基板の色を緑以外に指定しても料金が変わらないので、ついつい他の色を試してみたくなります。
青ならば基板上のパターンが割と見えるのですが、黒を指定すると見えづらいです(図10)。
図10 黒基板でパターンが見えづらい
狙ってやるならば問題ありませんが、基板上のパターンを話のタネにしたい場合には大変な地味さゆえ「よくわからんな?」となります。

基本筋は真面目で良いので、フックになる要素を考える(ダメならダメで諦める)

今回、展示物が気持ちファンキーな見た目になっていたのは、来場者に興味を持ってもらう上で一定の意味があったと感じています。
お題はWebカメラっぽいものですが、本当に普通のWebカメラっぽい出力だと、なんか監視カメラで撮られてる感じがしてブースへ寄り付きたくない感じがします。
今回はカメラモジュール内のレジスタ設定をおこなわずに起動しただけの状態で画を出したので、なかなかファンキーな感じになりました。メディアアート作品?と聞いてくださる方も居たそうです(私がブースに居なかったタイミングで、後から知りました)。今回は半ば怪我の功名というところがあり、あまり意識しすぎるのも良くないのですが、次以降の展示でも「嫌悪感を引き起こさないもの」「なんか気になるもの」というのは意識してみようかな、と感じたところです。

ぼっち開発での戦い方

回路にしてもソフトウェアにしても、レビューしてくれる人が居てチームで組んでいくならば取れる策も一定あります。一人でやる場合、基本戦術は次のとおりです。
  • 慎重に進める。十分に勉強してから取り組む
  • 似た特性の安価なモジュール(壊しても泣かない)で仕組みを十分確立してから高価なモジュールを使う
  • トライアル間隔を狭める
    • 自信がない選択肢に行き会った場合、全ての選択肢に同時張りする(例えば基板設計なら、有力な全候補を書き上げてまとめて入稿する)
      • 片方は失敗してロスする可能性が高いのですが、十分な確信なしで物事を進めなければならない状況は時間的に切羽詰っていることが大半なので、やむなしです
  • 金の弾丸で全てのパーツを余分に購入してバッファを持つ

宣伝

コミックマーケット90(C90)の3日目(8/14)、TechBoosterという技術書サークル(西a-05ab)にて「The Web Explorer 2」という本が出ます。このなかに、私の書いた「Scalaでイージーにハードを設計する」という記事が収録されます。Scala言語とChisel(Chisel HDL)というライブラリを利用してデジタル回路を設計する入門記事です。
図11の、めちゃめちゃかわいい表紙が目印です。
図11 The Web Explorer 2の表紙(イラスト: Jecyさん、デザイン: siosioさん)

そういうわけで

ブースにお越しいただいた皆様、会場で話をできた皆様、運営スタッフの皆様、同僚各位、ありがとうございました。とても良い場でした。
今回作成した12ページの冊子は、コミケが終わって少々落ち着いたら何かしらの形で配布しようと思っています。