3---Python初体験の簡単TestBench自動生成+Verilogモジュール信号抽出
Pythonの基礎文法を勉強した後、確かにPythonの優美な表現に惹かれたので、Pythonで何かをしたいと思っていましたが、これまでMATLABスクリプトでTestBenchの自動生成を完成させたいと思っていましたが、ここはちょうどPythonで完成しました.TestBenchは主に以下の3つの部分を含む.基本クロックclkとリセットrstの生成 ファイルのデータを読み込む .は、モジュールのインタフェース信号を抽出し、 を実例化する.
最初の2つの部分は通常のファイル書き込み操作で完了し、3番目の部分は少し複雑で、正規表現でモジュールの名前、信号の名前、ビット幅などを抽出する必要があります.総じて言えば、これは簡単なコードです.
また、第3部をVerilogサブモジュールの最上位ファイルとして自動的に生成し、接続線をコピーして貼り付ける手間を省くことができます.
分刻みでPythonをマスターするリンクを貼ります.http://www.code123.cc/1049.html
1.プログラム構造と実行プロセス
1.1プログラム構造
このプログラムには3つのファイルがあります.
プライマリファイル
文字列ファイル
モジュール抽出関数ファイル
verilog_tb_gen.py
config.py
extract_interface.py
_文字列ファイルには、いくつかの固定印刷情報 が格納されている.モジュール抽出関数ファイルでは、モジュールインタフェース情報全体の抽出と印刷が完了する .マスターファイル完了スケジューリング管理 1.2運転プロセス simファイルを開くか新規作成します. configからクロックとリセットを生成する文字列を抽出しsimファイルに書き込む. 同上:memory初期化文字列を抽出する; 同上:memoryデータ読み出しのalwaysブロック文字列を抽出する; 呼び出しモジュール抽出関数は、指定されたファイルのインタフェース情報を抽出しsimファイルに書き込む. ファイルを閉じます._モジュール抽出関数フロー:この関数には3つのセクションがあり、各セクションのフローはほぼ一致しています. 抽出ファイルの文字を行ごとに文字列リストに分離し、変数に付与する. インタフェース情報を含む正規表現をプリコンパイルする. forループを利用して各行の中でこの正規表現を検索し、検索したら次のステップに進む. 検索された文字列をスペースまたはカンマで個別の文字列に分離することで、下付き文字に基づいてインタフェースの情報を抽出することができる. は、抽出された情報をsimファイルに書き込む.
2.プロセスで使用する操作説明
1.2の流れで:1.開く、閉じる、書き込みなどのファイル操作は他の言語とほぼ一致しており、詳細はリンクを参照してください.http://blog.csdn.net/qq_16923717/article/details/77716137 2. 2、3、4ステップは基本的な印刷とテキストの置換であり、一般的なprintと同じである.3.モジュールインタフェース情報抽出に用いる操作及び参考リンクは以下の通りである.はread()とsplitline()を使用して読み取り、支店化されます.http://blog.csdn.net/nanjunxiao/article/details/9086079 正規表現、注意re.matchとre.searchの違い、およびなぜ正規表現を事前にコンパイルするのか菜鳥教程正規表現廖雪峰Python教程正規表現 正規表現の説明:プログラムで最も長い正規表現を次に示します.
この正規表現は、入力信号と出力信号の名前とビット幅情報がマッチしています.Verilogが書く様々な状況を考慮しているので、この正規表現はそんなに長くはありません.インタフェースが規範的であれば、実は短いです.正規表現の3つの記号に注意してください.反スラッシュ'':式のs+は少なくとも1つのスペースを一致させ、w+は少なくとも1つのアルファベット、数字、または下線を一致させ、d+は少なくとも1つの数字を一致させるなど、エスケープ文字として使用されます. 縦線’|’:表示または操作、例えば(input|output)入力と出力とを一致させることができる. 括弧():論理分離 Verilog入出力の可能な書き方は以下の通りです.
3.付録
verilog_tb_gen.pyコード
config.pyコード
extract_interface.pyコード
生成されたtbファイルは、tbがまだ完全なtbではないことに注意してください.
抽出されたソースファイルインタフェースfir.v
fir_hdl.v
最初の2つの部分は通常のファイル書き込み操作で完了し、3番目の部分は少し複雑で、正規表現でモジュールの名前、信号の名前、ビット幅などを抽出する必要があります.総じて言えば、これは簡単なコードです.
また、第3部をVerilogサブモジュールの最上位ファイルとして自動的に生成し、接続線をコピーして貼り付ける手間を省くことができます.
分刻みでPythonをマスターするリンクを貼ります.http://www.code123.cc/1049.html
1.プログラム構造と実行プロセス
1.1プログラム構造
このプログラムには3つのファイルがあります.
プライマリファイル
文字列ファイル
モジュール抽出関数ファイル
verilog_tb_gen.py
config.py
extract_interface.py
_
2.プロセスで使用する操作説明
1.2の流れで:1.開く、閉じる、書き込みなどのファイル操作は他の言語とほぼ一致しており、詳細はリンクを参照してください.http://blog.csdn.net/qq_16923717/article/details/77716137 2. 2、3、4ステップは基本的な印刷とテキストの置換であり、一般的なprintと同じである.3.モジュールインタフェース情報抽出に用いる操作及び参考リンクは以下の通りである.
re_interface = re.compile('(input|output)(\s+|\[\d+:0\]|\s+\[\d+:0\]|\[\d+:0\]\s+|\s+\[\d+:0\]\s+)\w+(,(\s+|)\w+){0,10}')
この正規表現は、入力信号と出力信号の名前とビット幅情報がマッチしています.Verilogが書く様々な状況を考慮しているので、この正規表現はそんなに長くはありません.インタフェースが規範的であれば、実は短いです.正規表現の3つの記号に注意してください.
//
input sig_1;
output sig_2;
// ,
input signal_1; // 1,
input[1:0]signal_2; //
input [1:0]signal_3; //
input[1:0] signal_4; //
input [1:0] signal_5; //
// '\w+'
// , ', signal_7', 10
input signal_6, signal_7; // ,
input signal_8,signal_9; //
3.付録
verilog_tb_gen.pyコード
'''
Verilog testbench generator
'''
import re
import config
import extract_interface
# parameter
NAME = 'fir_sim' # tb name
PERIOD = 10 # clock period: ns
RST_DELAY = 200 # reset delay : ns
DATA_WIDTH = 32 # rom data width
DATA_LEN = 301 # rom data length
PATH = r'D:\my_prj\my_filter_hdl_1\my_filter_hdl_1.srcs\msg.dat'
# memory path
# open and truncate file
fp = open('%s.v' % NAME, 'w')
fp.truncate()
# print clk and rst
fp.write(config.mod_clk_rst % (NAME, PERIOD, RST_DELAY))
fp.write(config.divide)
# print rom
fp.write(config.memory % (DATA_WIDTH - 1, DATA_LEN, PATH.replace('\\','/')))
fp.write(config.divide)
# print source data
fp.write(config.src_data % (DATA_WIDTH - 1, DATA_LEN))
fp.write(config.divide)
fp.write(config.divide)
'''
Extract module interface
'''
extract_interface.extract_print('fir_hdl.v', 0, fp) # Extract file1
extract_interface.extract_print('fir.v', 1, fp) # Extract file2
# The end, close the file
fp.write('
endmodule')
fp.close()
config.pyコード
'''
Verilog testbench generator
String
'''
# module clk rst
mod_clk_rst = 'module %s;
\
parameter PERIOD = %d;
\
reg clk = 1;
\
reg rst = 1;
\
initial begin
\
forever
\
#(PERIOD/2) clk = ~clk;
\
end
\
initial begin
\
#%d
\
rst = 0;
\
end
\
'
# divide
divide = '//------------------------------------------------------------
'
# memory
memory = 'reg [%d:0] datain[0:%d];
\
initial begin
\
$readmemb("%s", datain);
\
end
\
'
# source data
src_data = "reg\t[15:0]\t\ti;
\
reg\t[%d:0]\t\tsource_data;
\
reg\t\t\t\tsource_data_vld;
\
always @ (posedge clk) begin
\
if (rst) begin
\
i <= 'd0;
\
source_data <= 'd0;
\
source_data_vld <= 'd0;
\
end
\
else if (i < %d) begin
\
i <= i + 1;
\
source_data <= datain[i];
\
source_data_vld <= 1;
\
end
\
else begin
\
i <= i;
\
source_data <= 'd0;
\
source_data_vld <= 'd0;
\
end
\
end
\
"
extract_interface.pyコード
'''
Verilog testbench generator
Extract module interface
'''
import re
def extract_print( path, u, fp ): # u
with open(path, 'r') as dotv:
split_as_lines = dotv.read().splitlines()
# Extract output wire
re_wire = re.compile('output(\s+|\[\d+:0\]|\s+\[\d+:0\]|\[\d+:0\]\s+|\s+\[\d+:0\]\s+)\w+(,(\s+|)\w+){0,10}')
for i in range(len(split_as_lines)):
x = re_wire.search(split_as_lines[i])
if x:
wire_list = re.split(r'[\s\,]+', x.group(0))
if re.match('\[', wire_list[1]):
width_info = wire_list[1]
indx = 2
else:
width_info = '\t'
indx = 1
for j in range(len(wire_list) - indx):
fp.write('wire\t%s\t\t%-20s;
' % (width_info, wire_list[j + indx]))
fp.write('
')
# Extract module name
re_module_name = re.compile('module\s+\w+') #
for i in range(len(split_as_lines)):
y = re_module_name.search(split_as_lines[i])
if y:
module_name = re.split('\s+', y.group(0))[1]
fp.write('%-19su%-6d(
' % (module_name, u)) # module name
# Extract interface
re_interface = re.compile('(input|output)(\s+|\[\d+:0\]|\s+\[\d+:0\]|\[\d+:0\]\s+|\s+\[\d+:0\]\s+)\w+(,(\s+|)\w+){0,10}')
k = 0
for i in range(len(split_as_lines)):
z = re_interface.search(split_as_lines[i])
if z:
interface_string = re.sub(r'\[\d+:0\]', ' ', z.group(0))
interface_list = re.split(r'[\s\,]+', interface_string)
for j in range(len(interface_list) - 1):
if (k == 0):
fp.write('\t.%-21s( %-20s)
' % (interface_list[j+1], interface_list[j+1]))
else:
fp.write('\t,.%-20s( %-20s)
' % (interface_list[j+1], interface_list[j+1]))
k += 1
fp.write('\t);
')
return
生成されたtbファイルは、tbがまだ完全なtbではないことに注意してください.
module fir_sim;
parameter PERIOD = 10;
reg clk = 1;
reg rst = 1;
initial begin
forever
#(PERIOD/2) clk = ~clk;
end
initial begin
#200
rst = 0;
end
//------------------------------------------------------------
reg [31:0] datain[0:301];
initial begin
$readmemb("D:/my_prj/my_filter_hdl_1/my_filter_hdl_1.srcs/msg.dat", datain);
end
//------------------------------------------------------------
reg [15:0] i;
reg [31:0] source_data;
reg source_data_vld;
always @ (posedge clk) begin
if (rst) begin
i <= 'd0;
source_data <= 'd0;
source_data_vld <= 'd0;
end
else if (i < 301) begin
i <= i + 1;
source_data <= datain[i];
source_data_vld <= 1;
end
else begin
i <= i;
source_data <= 'd0;
source_data_vld <= 'd0;
end
end
//------------------------------------------------------------
//------------------------------------------------------------
wire [31:0] fir_out ;
fir_hdl u0 (
.clk ( clk )
,.fir_in ( fir_in )
,.fir_out ( fir_out )
);
wire [31:0] fir_out_TDATA ;
wire fir_in_TREADY ;
wire fir_out_TVALID ;
fir u1 (
.fir_in_TDATA ( fir_in_TDATA )
,.fir_out_TDATA ( fir_out_TDATA )
,.ap_clk ( ap_clk )
,.ap_rst_n ( ap_rst_n )
,.fir_in_TVALID ( fir_in_TVALID )
,.fir_in_TREADY ( fir_in_TREADY )
,.fir_out_TVALID ( fir_out_TVALID )
,.fir_out_TREADY ( fir_out_TREADY )
);
endmodule
抽出されたソースファイルインタフェースfir.v
module fir (
fir_in_TDATA,
fir_out_TDATA,
ap_clk,
ap_rst_n,
fir_in_TVALID,
fir_in_TREADY,
fir_out_TVALID,
fir_out_TREADY
);
input [31:0] fir_in_TDATA;
output [31:0] fir_out_TDATA;
input ap_clk;
input ap_rst_n;
input fir_in_TVALID;
output fir_in_TREADY;
output fir_out_TVALID;
input fir_out_TREADY;
fir_hdl.v
module fir_hdl(
input clk,
input [31:0] fir_in,
output [31:0] fir_out
);