2022年05月21日 Pythonで高位合成
PythonのプログラムからVerilogのRTLに変換できる高位合成環境が
あるようなので試しに使ってみました。
以下は、いろいろメモです。
あるようなので試しに使ってみました。
以下は、いろいろメモです。
polyphonyをインストールする。
% pip3 install polyphony
高位合成実行。
% polyphony -vm -vd fact.py
で、Verilogファイルが生成できました。
結果的にはすごく簡単なのですが、参考にしたWebページのとおりにやっても
うまく動かなかったりで、途中過程は意外と苦労しました。。。
ちなみに、変換前後のコードは最後の方に貼り付けておきます。
可読性はあまり良くないですが、一応それらしい回路が出力されているようです。
あと、「Icarus Verilog」という、OSSのVerilogシミュレータも入れてみました。
あと、「Icarus Verilog」という、OSSのVerilogシミュレータも入れてみました。
Icarus Verilogをインストールする。
sudo apt install iverilogsudo apt install gtkwave
SIM実行
iverilog -o sim -s test test.v polyphony_out.v./sim
波形確認
gtkwave test.vcd &
ちなみに、今回はUbuntu(Jetson Nano)で試していますが、
ひとまず簡単なプログラムであれば、Verilogに変換できることはわかったのですが、
深堀できていないので、使い物になるのかどうかはまだよくわかりません。
とりあえずNumPy とかの便利なライブラリは使えないようです(コンパイルでエラーになるので)。
あとは、ネットで検索しても、polyphonyについて詳しく説明しているページがあまりなさそうで、
あとは、ネットで検索しても、polyphonyについて詳しく説明しているページがあまりなさそうで、
polyphony公式のGitHubのサンプルプログラムを見ながら試していくしかなさそうな感じですかね。
以下、階乗計算プログラムの変換前後のコード例です。
Pythonプログラム
from polyphony import testbenchdef fact(x):y = 1for i in range(1, x+1):y = y * ireturn y@testbenchdef test():for i in range(0,10):fact(i)test()
Verilog RTL(本体)
module fact(input wire clk,input wire rst,input wire fact_ready,input wire fact_accept,output reg fact_valid,input wire signed [31:0] fact_in_x,output reg signed [31:0] fact_out_0);//localparamslocalparam fact_b1_INIT = 0;localparam fact_b1_S0 = 1;localparam fact_b1_S1 = 2;localparam fact_forelse5_FINISH = 3;localparam fact_L1_fortest2_S0 = 4;localparam fact_L1_forbody3_S0 = 5;localparam fact_L1_forbody3_S1 = 6;//signals:wire c71;reg [2:0] fact_state;wire signed [31:0] i3;wire signed [31:0] t65;wire signed [31:0] y3;reg signed [31:0] i2;reg signed [31:0] x;reg signed [31:0] y2;//combinations:assign c71 = (i2 < t65);assign i3 = (i2 + 1);assign t65 = (x + 1);assign y3 = (y2 * i2);always @(posedge clk) beginif (rst) beginfact_out_0 <= 0;i2 <= 0;x <= 0;y2 <= 0;fact_state <= fact_b1_INIT;end else begin //if (rst)case(fact_state)fact_b1_INIT: beginfact_valid <= 0;if (fact_ready == 1) beginx <= fact_in_x;i2 <= 1;y2 <= 1;fact_state <= fact_b1_S1;endendfact_b1_S1: begin/* t65 <= (x + 1); */fact_state <= fact_L1_fortest2_S0;endfact_L1_fortest2_S0: begin/* c71 <= (i2 < t65); */if (c71) begin/* y3 <= (y2 * i2); *//* i3 <= (i2 + 1); */i2 <= i3;y2 <= y3;fact_state <= fact_L1_fortest2_S0;end else beginfact_valid <= 1;if (fact_accept == 1) beginfact_state <= fact_b1_INIT;endfact_out_0 <= y2;endendendcaseendendendmodule
Verilog RTL(テストベンチ)
module test();//localparamslocalparam CLK_PERIOD = 10;localparam CLK_HALF_PERIOD = 5;localparam INITIAL_RESET_SPAN = 100;localparam test_b1_INIT = 0;localparam test_b1_S1 = 1;localparam test_forelse5_S0 = 2;localparam test_forelse5_FINISH = 3;localparam test_L1_fortest2_S0 = 4;localparam test_L1_forbody3_S0 = 5;localparam test_L1_forbody3_S1 = 6;localparam test_L1_forbody3_S2 = 7;localparam test_L1_forbody3_S3 = 8;localparam test_L1_forbody3_S4 = 9;localparam test_L1_forbody3_S5 = 10;localparam test_L1_forbody3_S6 = 11;localparam test_L1_forbody3_S7 = 12;//signals:wire c69;wire fact_0_valid;reg clk;reg fact_0_accept;reg fact_0_ready;reg rst;reg [3:0] test_state;reg signed [31:0] i2;reg signed [31:0] i3;//signals: in_xreg [31:0] fact_0_in_x;//signals: out_0wire [31:0] fact_0_out_0;//combinations:assign c69 = (i2 < 10);//sub modules//fact_0 instancefact fact_0(.clk(clk),.rst(rst),.fact_ready(fact_0_ready),.fact_accept(fact_0_accept),.fact_valid(fact_0_valid),.fact_in_x(fact_0_in_x),.fact_out_0(fact_0_out_0));initial begin$monitor("%5t:fact_0_in_x=%4d, fact_0_out_0=%4d", $time, fact_0_in_x, fact_0_out_0);$dumpfile("test.vcd");$dumpvars(0, test);endinitial beginclk = 0;#CLK_HALF_PERIODforever #CLK_HALF_PERIOD clk = ~clk;endinitial beginrst <= 1;#INITIAL_RESET_SPANrst <= 0;endalways @(posedge clk) beginif (rst) beginfact_0_accept <= 0;fact_0_ready <= 0;i2 <= 0;i3 <= 0;test_state <= test_b1_INIT;end else begin //if (rst)case(test_state)test_b1_INIT: begini2 <= 0;test_state <= test_L1_fortest2_S0;endtest_forelse5_FINISH: begin$display("%5t:finish", $time);$finish();endtest_L1_fortest2_S0: begin/* c69 <= (i2 < 10); */if (c69) beginfact_0_ready <= 1;fact_0_in_x <= i2;test_state <= test_L1_forbody3_S1;end else begintest_state <= test_forelse5_FINISH;endendtest_L1_forbody3_S1: beginfact_0_ready <= 0;test_state <= test_L1_forbody3_S2;endtest_L1_forbody3_S2: beginif (fact_0_valid == 1) beginfact_0_accept <= 1;test_state <= test_L1_forbody3_S4;endendtest_L1_forbody3_S4: beginfact_0_accept <= 0;test_state <= test_L1_forbody3_S5;endtest_L1_forbody3_S5: begini3 <= (i2 + 1);test_state <= test_L1_forbody3_S6;endtest_L1_forbody3_S6: begini2 <= i3;test_state <= test_L1_fortest2_S0;endendcaseendendendmodule
PR