pyverilog腳本的使用

2023-08-02 13:02:24 來源:IC技術交流

上節說到pyverilog有很多示例腳本,本節開始逐個分析。


(相關資料圖)

1示例腳本下載及說明

可以在github下載,這里提供百度網盤下載

解壓后可以看到如下示例腳本

unzip Pyverilog-develop.zipcd Pyverilog-develop/exampleslltotal 80-rw-r--r--. 1  3153 Jul 31 18:25 example_active_analyzer.py-rw-r--r--. 1  2996 Jul 31 18:25 example_active_range.py-rw-r--r--. 1  2227 Jul 31 18:25 example_ast_code.py-rw-r--r--. 1  1749 Jul 31 18:25 example_codegen.py-rw-r--r--. 1  3648 Jul 31 18:25 example_controlflow_analyzer.py-rw-r--r--. 1  3176 Jul 31 18:25 example_dataflow_analyzer.py-rw-r--r--. 1  3952 Jul 31 18:25 example_dataflow_codegen.py-rw-r--r--. 1  4555 Jul 31 18:25 example_graphgen.py-rw-r--r--. 1   560 Jul 31 18:25 example_identifierreplace.py-rw-r--r--. 1   508 Jul 31 18:25 example_identifiervisitor.py-rw-r--r--. 1  1549 Jul 31 18:25 example_lexer.py-rw-r--r--. 1  3199 Jul 31 18:25 example_merge.py-rw-r--r--. 1  2230 Jul 31 18:25 example_optimizer.py-rw-r--r--. 1  1599 Jul 31 18:25 example_parser.py-rw-r--r--. 1  1441 Jul 31 18:25 example_preprocessor.py-rw-r--r--. 1  4210 Jul 31 18:25 example_subset.py-rw-r--r--. 1  3138 Jul 31 18:25 example_walker.py-rw-r--r--. 1  2130 Jul 31 18:25 Makefile

2 example_preprocessor.py分析

該腳本的主要作用是預處理verilog文件,預處理verilog中的宏定義和include文件,然后輸出一個純粹的verilog文件,不再受define和include的制約,方便后續處理。

每行腳本分析如下所示:

# 這行代碼是使用絕對導入的未來語法。在Python2.x 版本中,導入模塊時,如果模塊與當前腳本的名稱沖突,Python會優先導入當前腳本。使用from __future__ import absolute_import可以確保導入模塊時,不會優先導入當前腳本。from __future__ import absolute_import#這行代碼是使用print()函數的未來語法。在Python 2.x 版本中,print是一個關鍵字而不是函數,不需要使用括號。使用from __future__ import print_function可以讓Python 2.x 版本中的print行為與Python 3.x 版本中的print()函數一致。from __future__ import print_function# 這行代碼導入了Python標準庫中的sys模塊,用于訪問與Python解釋器相關的變量和函數。import sys# 這行代碼導入了Python標準庫中的os模塊,用于與操作系統進行交互,例如文件和目錄操作。import os# 這行代碼導入了Python標準庫中的optparse模塊中的OptionParser類,用于解析命令行選項和參數。fromoptparseimportOptionParser#thenextlinecanberemovedafterinstallationsys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))# 這行代碼的作用是將腳本所在文件的父目錄添加到Python模塊搜索路徑中# os.path.abspath(__file__):__file__是Python中一個內置變量,表示當前腳本的文件名。os.path.abspath()函數用于獲取當前腳本的絕對路徑。例如,如果腳本文件位于/home/user/example.py,那么os.path.abspath(__file__)將返回/home/user/example.py# os.path.dirname():os.path.dirname()函數用于獲取路徑中的目錄部分。將上一步得到的絕對路徑傳遞給os.path.dirname()函數,將返回/home/user,即父目錄的路徑# os.path.dirname(os.path.dirname(os.path.abspath(__file__)))):通過多次調用os.path.dirname()函數,可以獲取到腳本所在文件的父目錄的父目錄# sys.path.insert(0, ...):sys.path是Python中的一個列表,包含了Python模塊搜索路徑。sys.path.insert(0, ...)將指定的路徑插入到列表的第一個位置,即將腳本所在文件的父目錄添加到Python模塊搜索路徑的最前面# 這行代碼導入了Pyverilog庫,它是一個用于解析和處理Verilog代碼的Python庫。import pyverilog# 這行代碼從Pyverilog庫的vparser.preprocessor模塊中導入了preprocess函數。preprocess函數用于對Verilog代碼進行預處理,包括宏展開、頭文件包含等操作from pyverilog.vparser.preprocessor import preprocessdef main():    INFO = "Verilog Preprocessor"    # pyverilog.__version__是Pyverilog庫的版本號    VERSION = pyverilog.__version__    USAGE = "Usage: python example_preprocessor.py file ..."    # 定義showVersion子函數,打印信息    def showVersion():        print(INFO)        print(VERSION)        print(USAGE)        sys.exit()            # optparser.add_option()方法用于添加選項。每個選項都是一個參數的配置,包括名稱、選項類型、目標變量、默認值和幫助信息等。具體參數解釋如下:    # -v 或--version:短選項和長選項,用來顯示版本號。    # action="store_true":當選項被指定時,將目標變量設為True。    # dest="showversion":將選項的值存儲到showversion變量中。    # default=False:如果選項未被指定,則將showversion變量的默認值設為False。    # help="Show the version":選項的幫助信息。    # -I 或--include:短選項和長選項,用來指定包含路徑。    # dest="include":將選項的值存儲到include變量中。    # action="append":當選項被指定時,將選項的值追加到include變量中。    # default=[]:如果選項未被指定,則將include變量的默認值設為一個空列表。    # help="Include path":選項的幫助信息。    # -D:短選項,用來指定宏定義。    # dest="define":將選項的值存儲到define變量中。    # action="append":當選項被指定時,將選項的值追加到define變量中。# default=[]:如果選項未被指定,則將define變量的默認值設為一個空列表。# help="Macro Definition":選項的幫助信息。    optparser = OptionParser()    optparser.add_option("-v", "--version", action="store_true", dest="showversion",                         default=False, help="Show the version")    optparser.add_option("-I", "--include", dest="include", action="append",                         default=[], help="Include path")    optparser.add_option("-D", dest="define", action="append",                         default=[], help="Macro Definition")# optparser.parse_args()方法用于解析命令行參數,并將解析結果賦值給options和args變量。options是一個對象,包含了解析后的選項和參數的值;args是一個列表,包含了解析后的位置參數的值。    (options, args) = optparser.parse_args()    filelist = args    if options.showversion:        showVersion()    for f in filelist:        if not os.path.exists(f):# os.path.exists()函數判斷文件是否存在。如果文件不存在,則拋出一個IOError異常,并將異常消息設為"file not found: " + f,其中f是文件路徑            raise IOError("file not found: " + f)#如果filist為空,則輸出自定義子函數    if len(filelist) == 0:        showVersion()    # preprocess()函數是在pyverilog.vparser.preprocessor模塊中定義的,用于對Verilog文件進行預處理。它接受三個參數:# filelist:一個包含文件路徑的列表,表示需要進行預處理的文件。    # include:一個包含包含路徑的列表,用于指定預處理時的包含路徑。    # define:一個包含宏定義的列表,用于指定預處理時的宏定義。    # 該函數返回預處理后的文本,將其存儲在text變量中。    text = preprocess(filelist, include=options.include, define=options.define)    print(text)# __name__是一個特殊的內置變量,表示當前模塊的名稱。當一個Python腳本直接被運行時,__name__的值為"__main__";當一個Python模塊被導入時,__name__的值為模塊的名稱。# 因此,if __name__=="__main__":這個條件判斷語句的作用是,只有當當前腳本直接被運行時,才會執行main()函數。#這樣做的好處是,可以在腳本中定義一些測試代碼或者執行一些初始化操作,而這些代碼在腳本被導入時不會執行。只有當腳本直接被運行時,才會執行這些代碼。if __name__ == "__main__":    main()

該腳本的應用示例如下所示:

3 example_parser.py分析

該模塊用于分析verilog代碼,生成抽象語法樹(ATS)和指令列表(directives)。

from __future__ import absolute_importfrom __future__ import print_functionimport sysimport osfromoptparseimportOptionParser# the next line can be removed after installationsys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))import pyverilogfrom pyverilog.vparser.parser import parsedef main():    INFO = "Verilog code parser"    VERSION = pyverilog.__version__    USAGE = "Usage: python example_parser.py file ..."    def showVersion():        print(INFO)        print(VERSION)        print(USAGE)        sys.exit()    optparser = OptionParser()    optparser.add_option("-v", "--version", action="store_true", dest="showversion",                         default=False, help="Show the version")    optparser.add_option("-I", "--include", dest="include", action="append",                         default=[], help="Include path")    optparser.add_option("-D", dest="define", action="append",                         default=[], help="Macro Definition")    (options, args) = optparser.parse_args()    # parse()函數是在pyverilog.vparser.parser模塊中定義的,用于解析Verilog文件。它接受三個參數:    # filelist:一個包含文件路徑的列表,表示需要進行解析的文件。    # preprocess_include:一個包含包含路徑的列表,用于指定預處理時的包含路徑。    # preprocess_define:一個包含宏定義的列表,用于指定預處理時的宏定義。    # 該函數返回解析后的抽象語法樹(AST)和指令(directives),將其分別存儲在ast和directives變量中。    filelist = args    if options.showversion:        showVersion()    for f in filelist:        if not os.path.exists(f):            raise IOError("file not found: " + f)    if len(filelist) == 0:        showVersion()    # ast.show()是AST對象的一個方法,用于以可讀的形式打印出整個抽象語法樹的結構。調用ast.show()后,會將抽象語法樹的結構輸出到控制臺。    # directives是一個包含行號和指令的元組列表。通過循環遍歷directives,可以逐行打印出每個指令的行號和內容。    # 這段代碼的作用是先展示解析后的抽象語法樹的結構,然后逐行打印出每個指令的行號和內容。這樣可以更好地了解解析后的結果,并進行后續的處理或分析。    ast, directives = parse(filelist,                            preprocess_include=options.include,                            preprocess_define=options.define)    ast.show()    for lineno, directive in directives:        print("Line %d : %s" % (lineno, directive))if __name__ == "__main__":    main()

4 example_ast_code.py分析

該腳本用于構建ATS抽象樹,進而生成rtl代碼

# from __future__ import absolute_importfrom __future__ import print_functionimport sysimport os# the next line can be removed after installationsys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))# vast模塊是pyverilog庫中定義的抽象語法樹(AST)的模塊。它包含了用于構建和操作Verilog抽象語法樹的各種類和函數。# ASTCodeGenerator類是pyverilog庫中的一個代碼生成器類。它提供了將抽象語法樹(AST)轉換成為Verilog代碼的功能。#通過導入這兩個模塊和類,我們可以使用vast模塊中的類來構建Verilog抽象語法樹(AST),然后使用ASTCodeGenerator類來將AST轉換成為Verilog代碼。import pyverilog.vparser.ast as vastfrom pyverilog.ast_code_generator.codegen import ASTCodeGeneratordef main():    datawid = vast.Parameter("DATAWID", vast.Rvalue(vast.IntConst("32")))    params = vast.Paramlist([datawid])    clk = vast.Ioport(vast.Input("CLK"))    rst = vast.Ioport(vast.Input("RST"))    width = vast.Width(vast.IntConst("7"), vast.IntConst("0"))    led= vast.Ioport(vast.Output("led", width=width))    ports = vast.Portlist([clk, rst, led])    width = vast.Width(vast.Minus(vast.Identifier("DATAWID"),                                  vast.IntConst("1")), vast.IntConst("0"))    count = vast.Reg("count", width=width)    assign = vast.Assign(        vast.Lvalue(vast.Identifier("led")),        vast.Rvalue(            vast.Partselect(                vast.Identifier("count"),                vast.Minus(vast.Identifier("DATAWID"), vast.IntConst("1")),                 vast.Minus(vast.Identifier("DATAWID"), vast.IntConst("8")))))     sens = vast.Sens(vast.Identifier("CLK"), type="posedge")    senslist = vast.SensList([sens])    assign_count_true = vast.NonblockingSubstitution(        vast.Lvalue(vast.Identifier("count")),        vast.Rvalue(vast.IntConst("0")))    if0_true = vast.Block([assign_count_true])    # count + 1    count_plus_1 = vast.Plus(vast.Identifier("count"), vast.IntConst("1"))    assign_count_false = vast.NonblockingSubstitution(        vast.Lvalue(vast.Identifier("count")),        vast.Rvalue(count_plus_1))    if0_false = vast.Block([assign_count_false])    if0 = vast.IfStatement(vast.Identifier("RST"), if0_true, if0_false)    statement = vast.Block([if0])    always = vast.Always(senslist, statement)    items = []    items.append(count)    items.append(assign)    items.append(always)    ast = vast.ModuleDef("top", params, ports, items)    codegen = ASTCodeGenerator()    rslt = codegen.visit(ast)    print(rslt)if __name__ == "__main__":    main()

生成的verilog代碼如下所示:

module top #(  parameter DATAWID = 32)(  input CLK,  input RST,  output [7:0] led);  reg [DATAWID-1:0] count;  assign led = count[DATAWID-1:DATAWID-8];  always @(posedge CLK) begin    if(RST) begin      count <= 0;    end else begin      count <= count + 1;    end  endendmodule

話說通過ATS生成verilog確實很繁瑣,還不如直接上手寫個veirlog。

本節介紹結束。

審核編輯:湯梓紅

標簽:

上一篇:去耦電容的有效使用方法有哪些
下一篇:最后一頁