使用开源工具pyverilog解析Verilog生成AST的简单案例

Verilog解析生成AST

工具:pyverilog
Github地址:https://github.com/PyHDI/Pyverilog

Windwos 环境操作最复杂,Ubuntu环境安装比较顺利,centos适用的源不好找,具体操作看二和三。最终三个环境都能够生成AST,但windows环境下.v文件长一些会报WinError206,这个报错还没有找到解决方法。建议直接用ubuntu或Centos,Ubuntu环境安装比较顺利,centos适用的源不好找,具体操作看二和三。速度慢可以换源,常用国内源见文章最后第五部分。

一.Windows环境

Windwos 环境主要会卡在安装pygraphviz,不需要可视化的话可以不安装。

1.直接从官网下载iverilog

官网地址:http://bleyer.org/icarus/
我下载的是 iverilog-v12-20220611-x64_setup
具体版本根据自己的情况去选。

2.直接安装,按提示直接下一步下一步安装就好了
3.安装python环境和依赖
  1. 跟着pyiverilog的操作步骤安装:
pip3 install jinja2 ply
pip3 install pytest pytest-pythonpath
  1. 如果需要可视化,需要python3.9及以下的版本,因为pygraphviz 这个包需要手动安装,并且windows环境只支持到python3.9(也许是我没找到支持高版本的包,地址:https://github.com/CristiFati/Prebuilt-Binaries/tree/master/PyGraphviz,我python3.8,选择3.8对应的版本)
    直接pip install pygraphviz 不报错的话,可以忽略。
    报******.whl什么的错误可以考虑尝试(具体报错没有保留下来,有时间去复现了我再补充)。
# 不需要可视化请忽略这部分
# window安装graphviz请自行google
sudo apt install graphviz
pip3 install pygraphviz # 这条执行报错参考上面3说的
  1. 示例代码(见文章第四部分)

二.Ubuntu环境

ubuntu环境跟着pyverilog写的操作步骤直接一步一步操作即可,没有遇到什么问题,印象中有一些报错,都比较明显和常见,根据提示,执行相应的语句安装依赖即可。具体报错没有保留下来,有时间去复现了我再补充。我的python版本是3.8。

1. 安装环境和依赖
sudo apt install iverilog
pip3 install jinja2 ply
pip3 install pytest pytest-pythonpath
sudo apt install graphviz
pip3 install pygraphviz
2. 示例代码(见文章第四部分)

三.Centos环境

个人最常用的环境,安装过程最曲折,主要是因为没有iverilog适用centos8环境的包不好找,最终是在opensuse找到了,可以直接用opensuse的源安装,也可以下载下来手动安装。我的python版本是3.9。

1. 找适用的iverilog源(这一步找了好久)

我用的 iverilog-11.0-c4m.1.4.1.x86_64.rpm,手动安装
OpenSUSE官网:https://software.opensuse.org/download/package?package=iverilog&project=home%3Averhaegs%3AChips4Makers

2. 手动安装iverilog
yum localinstall iverilog-11.0-c4m.1.4.1.x86_64.rpm 
3. 根据自己的需求安装python依赖
pip3 install jinja2 ply
pip3 install pytest pytest-pythonpath
4. 示例代码(见文章第四部分)

四.示例代码

vim test.v
# test.v 里写个verilog示例代码
`default_nettype none

module TOP(CLK, RST_X, MEM_A, MEM_RE, MEM_WE, MEM_D, MEM_Q, MEM_BUSY, MEM_DONE);
  input CLK;
  input RST_X;

  parameter WA = 32;
  parameter WD = 32;

  output reg [WA-1:0] MEM_A;
  output reg MEM_RE;
  output reg MEM_WE;
  output reg [WD-1:0] MEM_D;
  input [WD-1:0] MEM_Q;
  input MEM_DONE;
  input MEM_BUSY;

  reg [3:0] state;
  reg [3:0] cnt;

  wire [3:0] wire_cnt0;
  assign wire_cnt0 = cnt + 1;
  wire [3:0] wire_cnt1;
  assign wire_cnt1 = wire_cnt0 + 1;

  always @(posedge CLK or negedge RST_X) begin
    if(!RST_X) begin
      MEM_RE <= 0;
    end else begin
      MEM_RE <= 0;
    end
  end

  always @(posedge CLK or negedge RST_X) begin
    if(!RST_X) begin
      state <= 0;
      cnt <= 0;
    end else begin
      if(state == 0) begin
        cnt <= cnt + 1;
        if(cnt == 8) begin
          state <= 1;
          cnt <= 0;
        end
      end else if(state == 1) begin
        cnt <= cnt + 1;
        if(cnt == 8) begin
          state <= 0;
          cnt <= 0;
        end
      end
    end
  end
endmodule
vim test.py
# test.py 里写一个简单的调用示例
import os
from pyverilog.vparser.parser import parse
from pyverilog.vparser.ast import *

def generate_ast(file_path):
    with open(file_path, 'r') as f:
        code = f.read()
    ast, _ = parse(code)
    return ast

def main():
    # 指定路径
    directory_path = '/opt/test'

    # 遍历路径内的所有文件
    for root, dirs, files in os.walk(directory_path):
        for file in files:
            if file.endswith('.v'):  # 只处理.verilog文件
                file_path = os.path.join(root, file)
                ast = generate_ast(file_path)
                ast.show()

if __name__ == '__main__':
    main()
# 运行程序
python test.py
# 部分输出结果(太长了,粘贴一部分出来)
Source:  (at 3)
  Description:  (at 3)
    ModuleDef: TOP (at 3)
      Paramlist:  (at 0)
      Portlist:  (at 3)
        Port: CLK, None (at 3)
        Port: RST_X, None (at 3)
        Port: MEM_A, None (at 3)
        Port: MEM_RE, None (at 3)
        Port: MEM_WE, None (at 3)
        Port: MEM_D, None (at 3)
        Port: MEM_Q, None (at 3)
        Port: MEM_BUSY, None (at 3)
        Port: MEM_DONE, None (at 3)
      Decl:  (at 4)
        Input: CLK, False (at 4)
      Decl:  (at 5)
        Input: RST_X, False (at 5)
      Decl:  (at 7)
        Parameter: WA, False (at 7)
          Rvalue:  (at 7)
            IntConst: 32 (at 7)
      Decl:  (at 8)
        Parameter: WD, False (at 8)
          Rvalue:  (at 8)
            IntConst: 32 (at 8)
      Decl:  (at 10)
        Output: MEM_A, False (at 10)

五.常用的国内源

# 我用的清华源,pip install ****(包名) -i https://pypi.tuna.tsinghua.edu.cn/simple
1. 清华源:https://pypi.tuna.tsinghua.edu.cn/simple
2. 阿里云:http://mirrors.aliyun.com/pypi/simple/
3. 豆瓣:http://pypi.douban.com/simple/
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用pyverilog这个Python库来提取Verilog例化模块的端口信号。具体步骤如下: 1. 安装pyverilog库:可以使用pip install pyverilog命令来安装。 2. 创建一个Verilog解析器对象:可以使用vparser.VerilogCodeParser()来创建一个解析器对象。 3. 解析Verilog代码:可以使用解析器对象的parse()方法来解析Verilog代码。 4. 遍历解析结果:遍历解析结果,找到例化模块的节点,并提取其端口信号。 以下是一个示例代码,可以提取top模块中例化的sub模块的端口信号: ```python from pyverilog.vparser.parser import VerilogCodeParser from pyverilog.vparser.ast import * # 定义一个访问者类 class PortVisitor(NodeVisitor): def __init__(self): self.ports = {} # 访问端口声明节点 def visit_Portname(self, node): # 获取端口名称 portname = node.children()[0].value # 获取端口方向 portdir = node.parent.parent.children()[0].value # 将端口信息保存到字典中 self.ports[portname] = portdir # Verilog代码 code = """ module top( input clk, input rst, output reg out1, output out2 ); sub sub1( .in1(out1), .out1(out2) ); endmodule module sub( input in1, output out1 ); endmodule """ # 创建一个解析器对象 parser = VerilogCodeParser() # 解析Verilog代码 ast = parser.parse(code) # 遍历解析结果,找到sub模块的节点 for node in ast.description.definitions: if isinstance(node, InstanceList): if node.module == "sub": # 创建一个访问者对象 visitor = PortVisitor() # 遍历sub模块节点,提取端口信息 node.accept(visitor) # 打印端口信息 print(visitor.ports) ``` 输出结果为:{'in1': 'input', 'out1': 'output'},表示sub模块有一个输入端口in1和一个输出端口out1。 注意:上述代码只是一个示例,实际应用中需要根据具体的Verilog代码进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值