Pyverilogの紹介
verilogで設計をしてる時に、回路の構造をプログラム的に処理することにより、
何か悪い構造などをサーチしたいときがある。
そんなとき、私が頼りにしているのがPyverilogだ。
Verilog HDLのデザイン解析・コード生成のためのPythonベースのオープンソースツールキットPyverilogをリリースしました - shtaxxx日記
オープンソースで当然フリー。プログラミング言語Pythonによって記述されている。
インストールにはいくつか条件があるが、私はコード生成器 (ast_code_generator)やデータフロー可視化のためのGraphvizとPygraphviz は使わず、最低限必要なIcarus Verilogのみをインストールして使用している。
Pyverilogでたとえばデータフロー解析器を使用すると、各信号がどのような式で記述されているかを理解することが出来る。
例えば
always @(posedge CLK) begin
if(RST) begin
reg0[1:0] <= 0;
reg1 <= 0;
end else if(WRITE) begin
case(ADDR)
0:reg0[1:0] <= WRITE_DATA;
1:reg1 <= WRITE_DATA[0];
endcase
end
end
always @* begin
case(ADDR)
0:READ_DATA[1:0] = reg0[1:0];
1:READ_DATA[1:0] = {1'b0,reg1};
endcase
end
のような読み書き可能なレジスタを解析してみる。
すると、
Bind:
(Bind dest:TOP._rn1_READ_DATA msb:'d1 lsb:'d0 tree:(Concat Next:(IntConst 1'b0),(Terminal TOP.reg1)))
(Bind dest:TOP.reg0 msb:'d1 lsb:'d0 tree:(Branch Cond:(Terminal TOP.RST) True:(IntConst 0) False:(Branch Cond:(Terminal TOP.WRITE) True:(Branch Cond:(Operator Eq Next:(Terminal TOP.ADDR),(IntConst 0)) True:(Terminal TOP.WRITE_DATA)))))
(Bind dest:TOP.reg1 tree:(Branch Cond:(Terminal TOP.RST) True:(IntConst 0) False:(Branch Cond:(Terminal TOP.WRITE) True:(Branch Cond:(Operator Eq Next:(Terminal TOP.ADDR),(IntConst 0)) False:(Branch Cond:(Operator Eq Next:(Terminal TOP.ADDR),(IntConst 1)) True:(Partselect Var:(Terminal TOP.WRITE_DATA) MSB:(IntConst 0) LSB:(IntConst 0)))))))
(Bind dest:TOP._rn0_READ_DATA msb:'d1 lsb:'d0 tree:(Partselect Var:(Terminal TOP.reg0) MSB:(IntConst 1) LSB:(IntConst 0)))
(Bind dest:TOP.READ_DATA msb:'d1 lsb:'d0 tree:(Branch Cond:(Operator Eq Next:(Terminal TOP.ADDR),(IntConst 0)) True:(Terminal TOP._rn0_READ_DATA) False:(Branch Cond:(Operator Eq Next:(Terminal TOP.ADDR),(IntConst 1)) True:(Terminal TOP._rn1_READ_DATA))))
のような形で出てくる。
なんのこっちゃという感じではあるが、PythonプログラムがverilogHDLにおける構造を理解できるということはレジスタマップ推定や組み合わせ回路ループの把握などを有料のEDAなしにできるということである。
次回はこれらの実装であるPyverilog_toolboxライブラリについて紹介したい。