💎

新しいHDL(ハードウェア記述言語): Veryl

2022/12/21に公開3

はじめに

以下の記事に書いたとおり新しいハードウェア記述言語を作ることにしました。

https://zenn.dev/dalance/articles/17017b7b95b2ca

1週間ほど作業したところでなんとなく動く感じになってきたのと、構文や機能のアイデアをメモしたり議論したりする場所が欲しいと思ったので、作りかけの状態ですが公開することにしました。

Veryl

新言語の名前は "Veryl" です。よくある宝石系プログラミング言語にならって「beryl(緑柱石) + VerilogのV = Veryl」となっています。ソースコードの拡張子は ".vl" です。

https://github.com/dalance/veryl

追加してほしい機能などがあれば Issue にてお願いします。自分の趣味的な部分もあるので必ず取り入れるわけではありませんが、なるべく検討します。

できること

現時点ではビルド済みバイナリの公開などはしていないので Rust がビルドできる環境で

$ cargo install veryl
$ cargo install veryl-ls    # Language Serverを使う場合

としてください。
veryl コマンドが各種処理を実行するコマンドです。
コマンド名だけで実行するとカレントディレクトリ以下の ".vl" ファイル全てを処理しますが、ファイル名を与えるとそのファイルだけを処理します。

veryl check

ソースコードのチェックをします。構文エラーだけでなく、意味的に間違っているものもチェックします。現時点では

  • 数値リテラルにおける不正な数値(ex. 10'b3
  • 数値リテラルのビット幅あふれ(ex. 8'hffff
  • 不正な構文要素の使用(ex. always_ff 以外での if_reset
  • 識別子の重複

をチェックします。

veryl fmt

ソースコードをフォーマットします。特に警告なく上書きするのでご注意ください。
--check オプションでフォーマットのチェックだけして差分を表示します。これはCIでのチェックなどを想定しています。

veryl build

SystemVerilogのソースコードを生成します。少なくとも構文的に正しいことは確認していますが、各種ツールで正常に受け付けられるかは未確認です。

Language Server

上記コマンドのうちチェックとフォーマットは Language Server からも実行可能です。チェックについては入力中にリアルタイムにチェックし表示されます。フォーマットは Laugnage Server のフォーマットコマンドに対応しています。

ソースコード例

現時点で処理可能なソースコードの例は以下になります。言語リファレンスなどはまだないので雰囲気で読んでください…。

https://github.com/dalance/veryl/tree/master/testcases

vl ディレクトリ以下が Veryl のソースコードで、sv ディレクトリ以下がそれを変換した SystemVerilog のソースコードです。
またこのソースコードはフォーマッタの例にもなっていて、スペースやインデントなどを変更しても veryl fmt をかけると必ずこの状態にフォーマットされます。

Discussion

Ryuz88Ryuz88

素晴らしい言語をありがとうございます。とても興味深く見させていただいております。
少し要望等を書かせて頂いても良いでしょうか?(我儘ばかりで恐縮なのですが)

all-x, all-z

localparam int unsigned f = '0;
localparam int unsigned ff = '1;

はあるようですが 'x や 'z も欲しいのですが難しいでしょうか?

ビット幅キャスト

ビット幅キャストとかは不要という考え方なのでしょうか? (個人的には欲しいです)
変換後の sv が verilator の lint に怒られがちな気がしています。

未定義変数

Verilog では未定義の変数が 1bit の wire になってしまうので、よく `default_nettype none 宣言するのですが、相当の機能があると嬉しいです。

属性の指定

FPGA開発で (* mark_debug="true" ) とか ( ram_style="block" *) などの指定を行いたいことがよくあるので、コメント同様にそのままSVにスルーしてもらえると嬉しいです。

ちなみにFPGAでメモリを推論させるのに

(* ram_style="block" *) logic  [15:0]   mem  [0:4093];

のような書き方をするのですが、veryl でも 可能でしょうか?

dalancedalance

ご提案ありがとうございます。
1人で考えていると自分の使っている記述に関するアイデアしか出ないので、たくさん出していただけるのはとても助かります。

all-x, all-z

これは問題ありません。
(普段使わないので存在を忘れていました…)

ビット幅キャスト

ビット幅チェックはやりたいと思っています。
これから式の評価を実装するのでそのあとになる予定です。
キャスト方法や演算によるビット幅増加をどう扱うかなどはまだあまりイメージできていません。

未定義変数

当初やる予定だったのですが、SV側のパッケージを参照している場合など、疑似エラーが出そうだったのでいったん取りやめていました。
階層参照しない単体の識別子なら誤判定もしないと思うので限定して実装しようと思います。

属性の指定

もともと ifdef 関連をRustのようにアトリビュートにしたいと思っていまして、それと一緒に解決できるかな、と思っています。

#[sv(ram_style="block")]
var mem: logic[4096][16];

みたいなイメージです。
(コメントは実は結構扱いが難しいので、できるだけ正式な構文要素としておきたいです)

Ryuz88Ryuz88

ありがとうございます。いろいろと理解できました(勉強になります)。

ビット幅チェックはやりたいと思っています。

Veryl の段階でチェックできると一番嬉しいですね。ただ parameter の bit 幅が決まらないと判定できないところとかは残りそうな気もするので、変換後のSVも lint 通るように二重チェックしたくなる気もします。

階層参照しない単体の識別子なら誤判定もしないと思うので限定して実装しようと思います。

これは有難いです。

もともと ifdef 関連をRustのようにアトリビュートにしたいと思っていまして、それと一緒に解決できるかな、と思っています。

たしかにアトリビュートの方が良い方法に思いました。

コメントは実は結構扱いが難しいので、

なるほど、勉強になります。

今後の進化がとても楽しみです。 よろしくお願いします。