ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python提取Vivado工程RTL代码:自动化FPGA源码清单工具

Python提取Vivado工程RTL代码:自动化FPGA源码清单工具 1. 项目概述1.1 核心需求解析做FPGA开发的工程师心里都清楚一个Vivado工程从创建到最终迭代少则几十个RTL文件多则上百个源文件散落在不同目录里。接手一个旧工程或者想把工程从A机器迁移到B机器最让人头疼的事情之一就是把工程里所有的RTL文件完整、准确地提取出来。这里说的提取不是简单的复制粘贴而是要把Vivado工程里所有被引用的源文件整理出来搞清楚目录结构按功能模块或者文件类型归档生成一份可以随时查阅的文件清单。手动做这项工作短则十分钟长则半小时以上而且极容易出错——漏掉某个子模块、拷错了文件版本、路径对不上这些都是我踩过的坑。这个基于Python的Vivado工程RTL代码提取工具解决的就是这个问题。它通过解析Vivado工程文件.xpr内部的XML结构自动识别工程里引用的所有RTL源文件然后按照设定的规则提取、分类、输出文件清单。整个过程不需要打开Vivado图形界面不需要人工逐个模块查找脚本一跑结果就出来了。这套工具适合谁用三类人。第一类是刚接手旧工程的FPGA开发工程师需要快速搞清楚工程的文件构成第二类是负责工程维护和版本管理的人需要定期梳理源码结构第三类是需要在不同开发环境之间迁移工程的团队需要一份完整可靠的文件清单作为迁移依据。哪怕你Python零基础只要会复制粘贴代码、改两个路径变量就能用起来。1.2 为什么选择Python方案Vivado本身内置了Tcl脚本接口理论上用Tcl写个脚本也能实现类似功能。那为什么还要用Python先说结论Python在处理文本解析、数据整理和结果格式化输出方面生态优势明显优于Tcl。具体来说三个方面。第一正则表达式和XML解析库。Vivado的.xpr文件本质是XML格式Python标准库里的ElementTree模块天生就是干这个的。配合re模块处理路径里的特殊字符和转义问题非常顺手。第二跨平台和多场景复用。Python脚本不依赖Vivado环境变量不需要启动任何EDA工具就能运行。这意味着即使你手上只有一份工程备份文件没有装Vivado也能完成RTL文件提取。第三后续扩展能力强。提取完文件清单之后你可能还想做代码行数统计、模块依赖关系分析、文件名冲突检测——这些用Python扩展都是加函数的事用Tcl写就费劲多了。我用这个方案实测过对一个包含87个Verilog文件的工程做完整提取脚本运行时间不超过3秒。同类Tcl方案因为要启动Vivado环境光启动时间就需要30秒以上实际提取过程反而是最快的部分。2. 设计思路与整体框架2.1 Vivado工程文件结构拆解动手写脚本之前先得搞清楚Vivado工程文件到底长什么样。用文本编辑器打开任意一个.xpr文件你会看到开头是XML声明接着是一大串工程配置信息。关键内容在Project节点下的libraries部分格式大致如下Project Version7.3 ... Libraries Library Namework SpiritVersion4.0/SpiritVersion FileTypeFilter FileTypeFilter NameAll TypeAll BriefDescriptionAll Files/ /FileTypeFilter Files Pathsrc/top.v TypeVerilog FileOptions FileOption KeyTopFile Valuetrue/ /FileOptions /Files Files Pathsrc/bram_controller.v TypeVerilog/ Files Pathsrc/uart_tx.sv TypeSystemVerilog/ Files Pathip/pll/pll.xci TypeXCI/ /Library /Libraries /Project看到这个结构思路就清晰了。每个Files节点就是工程里的一个源文件Path属性是文件路径Type属性是文件类型。工具要做的事情就是把这堆XML节点里我们关心的信息提取出来按需处理。这里有个细节特别值得注意.xpr文件里的路径是相对于工程文件所在目录的相对路径而且用的是正斜杠。Windows环境下工作的同事可能会觉得奇怪但这其实是Xilinx故意设计的——保证工程在Windows和Linux之间迁移时路径格式不用改。2.2 工具功能架构理清了文件结构工具的架构就呼之欲出了。整体上分四层解析层读取.xpr文件用ElementTree解析XML遍历所有Files节点。这层只负责拿到原始数据不做任何判断。过滤层根据配置文件里的规则区分Verilog、SystemVerilog、VHDL和IP文件。默认情况下工具会排除掉仿真目录下的测试文件和临时生成文件只保留可综合的RTL源码。整理层对提取到的文件路径做规范化处理转成绝对路径检测文件是否存在按顶层模块所在目录或者用户指定的规则重新组织目录结构。输出层生成三种产出物——MARKDOWN格式的源码清单文档、路径字典文件JSON格式方便其他工具调用、整理后的文件目录可选功能。这个分层思路其实是从大型软件工程借过来的经验。每一层只关注自己的事情后续想加功能比如集成代码风格检查器只需要在整理层和输出层之间插一个新模块不用改动已经跑通的代码。2.3 为什么选择解析XML而非暴力扫描目录可能有人会问既然RTL文件都在工程目录里直接把目录下所有.v和.sv文件扫出来不就行了何必费劲解析XML问得好这里面的坑我替大家踩过。暴力扫描目录有两个致命问题。第一个问题是误伤。Vivado工程目录下通常有project.srcs、project.runs、project.sim三个子目录其中project.runs下面藏着大量综合和实现过程中生成的临时文件这些文件有的是工具自动生成的网表有的是中间产物把它们混进源码清单后面做版本管理或代码审查的时候会被坑到怀疑人生。第二个问题是遗漏。Vivado工程引用文件不一定都在工程目录内部很多项目习惯把公共IP核或者共享模块放在工程目录外面的公共库里路径相对工程目录可能是../../common/axi_lite_slave.v这样的形式。纯扫描目录的方法遇到这种情况直接就瞎了。XML解析方案从根本上规避了这两个问题。工程引用了哪些文件完全以.xpr文件里的声明为准不靠猜。3. 核心实现与实操要点3.1 环境准备与依赖安装工具只依赖Python标准库不需要额外安装第三方包。这意味着任何装了Python 3.6以上版本的环境都能直接跑不挑操作系统。检查你的环境是否满足要求打开命令行执行python --version如果提示找不到命令需要先装Python。Windows用户建议从官网下载安装包安装时记得勾选“Add Python to PATH”选项。Linux用户一般系统自带没有的话用包管理器安装即可。代码里用到的库只有三个xml.etree.ElementTree、os.path、re。前两个是标准库re是正则表达式库也都是Python自带的。3.2 核心代码实现主脚本逻辑如下我直接给出完整可跑的版本代码不长但每个函数承担一个明确职责后续改造也容易。#!/usr/bin/env python3 # -*- coding: utf-8 -*- Vivado工程RTL代码提取工具 功能解析.xpr工程文件提取所有RTL源文件信息生成文件清单 import xml.etree.ElementTree as ET import os import re import json from collections import defaultdict def parse_xpr(xpr_path): 解析Vivado工程文件提取所有文件节点信息 try: tree ET.parse(xpr_path) root tree.getroot() except ET.ParseError as e: raise ValueError(fXML解析失败请确认文件是有效的Vivado工程文件: {e}) except FileNotFoundError: raise FileNotFoundError(f找不到工程文件: {xpr_path}) files_info [] project_dir os.path.dirname(os.path.abspath(xpr_path)) # 遍历所有Libraries下的Files节点 for library in root.iter(Library): lib_name library.get(Name, default) for file_node in library.iter(Files): path_attr file_node.get(Path, ) file_type file_node.get(Type, Unknown) # 规范化路径 normalized_path os.path.normpath(path_attr.replace(/, os.sep)) abs_path os.path.join(project_dir, normalized_path) # 获取是否为顶层文件的标记 is_top False for opt in file_node.findall(.//FileOption): if opt.get(Key) TopFile and opt.get(Value) true: is_top True files_info.append({ path: abs_path, relative_path: normalized_path, type: file_type, library: lib_name, is_top: is_top }) return files_info def classify_files(files_info): 按文件类型分类并过滤仿真文件和IP文件 classified { verilog: [], # .v systemverilog: [], # .sv vhdl: [], # .vhd/.vhdl ip: [], # .xci other: [] # 其他 } # 需要排除的目录关键词 exclude_dirs [sim, simulation, testbench, tb, _tb, runs, synthesis] for f in files_info: # 跳过仿真目录下的文件 rel_path_lower f[relative_path].lower() if any(ex_dir in rel_path_lower for ex_dir in exclude_dirs): continue ext f[path].rsplit(., 1)[-1].lower() if . in f[path] else if ext in (v,): classified[verilog].append(f) elif ext in (sv, svh): classified[systemverilog].append(f) elif ext in (vhd, vhdl): classified[vhdl].append(f) elif ext xci: classified[ip].append(f) else: classified[other].append(f) return classified def generate_markdown(classified, xpr_name): 生成MARKDOWN格式的源码清单文档 md_lines [f# {xpr_name} 工程RTL源码清单, ] # 统计信息 total_files sum(len(v) for v in classified.values()) md_lines.append(f## 统计信息) md_lines.append() md_lines.append(f- 工程文件总数: **{total_files}**) md_lines.append(f- Verilog文件: **{len(classified[verilog])}**) md_lines.append(f- SystemVerilog文件: **{len(classified[systemverilog])}**) md_lines.append(f- VHDL文件: **{len(classified[vhdl])}**) md_lines.append(f- IP核文件: **{len(classified[ip])}**) md_lines.append() # 分类列出文件 for category, title in [ (verilog, Verilog源码), (systemverilog, SystemVerilog源码), (vhdl, VHDL源码), (ip, IP核配置), (other, 其他文件) ]: if classified[category]: md_lines.append(f## {title}) md_lines.append() for f in classified[category]: top_flag **[TOP]** if f[is_top] else md_lines.append(f- {f[relative_path]}{top_flag}) md_lines.append() return \n.join(md_lines) def check_file_existence(files_info): 检查文件是否存在返回缺失列表 missing [] for f in files_info: if not os.path.isfile(f[path]): missing.append(f[relative_path]) return missing def main(xpr_path, output_dir): 主函数 if not os.path.isfile(xpr_path): print(f[错误] 工程文件不存在: {xpr_path}) return xpr_name os.path.basename(xpr_path).replace(.xpr, ) print(f[信息] 开始解析工程文件: {xpr_name}) # 解析工程文件 files_info parse_xpr(xpr_path) print(f[信息] 发现 {len(files_info)} 个文件引用) # 检查文件存在性 missing_files check_file_existence([f for f in files_info if not f[is_top]]) if missing_files: print(f[警告] 以下文件在磁盘上不存在:) for mf in missing_files: print(f - {mf}) # 分类 classified classify_files(files_info) # 确保输出目录存在 os.makedirs(output_dir, exist_okTrue) # 生成文件清单 output_path os.path.join(output_dir, f{xpr_name}_rtl_list.md) with open(output_path, w, encodingutf-8) as f: f.write(generate_markdown(classified, xpr_name)) print(f[成功] 源码清单已生成: {output_path}) # 生成JSON字典 json_path os.path.join(output_dir, f{xpr_name}_file_dict.json) with open(json_path, w, encodingutf-8) as f: json.dump(classified, f, indent2, ensure_asciiFalse) print(f[成功] 文件字典已生成: {json_path}) # 打印摘要 total sum(len(v) for v in classified.values()) print(f\n 提取汇总 ) print(fVerilog: {len(classified[verilog])} 个文件) print(fSystemVerilog: {len(classified[systemverilog])} 个文件) print(fVHDL: {len(classified[vhdl])} 个文件) print(fIP核: {len(classified[ip])} 个文件) print(f其他: {len(classified[other])} 个文件) print(f合计: {total} 个文件过滤仿真/临时文件后) if __name__ __main__: # 在这里修改路径配置 XPR_FILE rD:\fpga_projects\axi_eth\axi_eth.xpr OUT_DIR rD:\fpga_projects\axi_eth\output main(XPR_FILE, OUT_DIR)这段代码的核心逻辑在parse_xpr函数里。root.iter(Library)会把工程文件里所有Library节点都找出来多数工程只有一个名为work的库但多库工程也不算罕见。每个Library下可能有多个Files节点每个Files节点就是一个源文件引用Type属性告诉我们它是Verilog还是VHDL或者其他类型。这里有个容易踩坑的点工程文件里有些Path属性值带正斜杠但Windows系统用反斜杠os.path.normpath和os.path.join组合使用可以统一处理好这个问题。如果手里的是旧版本Vivado生成的工程文件节点结构可能略有差异但Files节点的基本结构从Vivado 2014到2023版本都没变过。3.3 源码清单的过滤与分类机制分类函数里有一个默认的排除目录关键词列表[sim, simulation, testbench, tb, _tb, runs, synthesis]。这个列表是我在实际使用中被坑过多次之后总结出来的。sim目录和simulation目录是Vivado默认的仿真文件存放位置仿真文件不参与综合混进源码清单会干扰代码审查。runs目录是综合和实现过程生成的中间文件里面可能有大量的自动生成网表根本不是人工维护的源码必须排除。synthesis目录类似。但有个例外情况如果你们的项目架构是把模块级独立的localparam定义文件有的团队习惯命名为xxx_params.v放在sim目录下统一管理而这些文件确实要被综合引用那么排除规则就会误伤。遇到这样的情况我建议在排除逻辑里加白名单机制# 在classify_files函数中添加白名单判断 def is_excluded(rel_path): exclude_dirs [simulation, runs, synthesis] allow_patterns [params, defines, config] rel_path_lower rel_path.lower() for ex_dir in exclude_dirs: if ex_dir in rel_path_lower: # 检查白名单 for pattern in allow_patterns: if pattern in rel_path_lower: return False return True return False白名单机制的原理很简单路径里同时包含排除目录关键词和白名单关键词的文件认为是特殊情况保留。这个设计看似细节真正用起来能避免很多破口大骂的时刻。3.4 输出文件的定制化扩展基础的Markdown源码清单能满足大多数场景但如果你需要生成的内容更符合自己团队的习惯输出逻辑也很好扩展。比如你想在清单里增加文件的最后修改时间方便判断哪些文件近期被改过可以这样加import datetime def get_file_mtime(file_path): 获取文件的最后修改时间 try: timestamp os.path.getmtime(file_path) return datetime.datetime.fromtimestamp(timestamp).strftime(%Y-%m-%d %H:%M:%S) except OSError: return 文件不存在 # 在generate_markdown中添加 for f in classified[verilog]: mtime get_file_mtime(f[path]) md_lines.append(f- {f[relative_path]} (修改时间: {mtime}))再比如你想统计每个模块的代码行数这是做代码规模评估时特别有用的数据def count_lines(file_path): 统计文件代码行数 try: with open(file_path, r, encodingutf-8, errorsignore) as f: return sum(1 for _ in f) except OSError: return 0有了这份基础框架任何你想叠加的功能都能平滑加入。这也是我推荐大家自己动手写工具而不是依赖现成脚本的核心原因——只有自己写的才能在任何边界情况下随心所欲地调整。4. 实操过程与踩坑实录4.1 完整实操流程演示拿一个实际工程来演示完整操作流程。假设有一个名为axi_eth的工程位于D:\fpga_projects\axi_eth目录下工程文件是axi_eth.xpr。第一步确认Python环境。打开命令行执行python --version确认Python可用。如果报错去Python官网下载最新稳定版安装。安装时记住勾选“Add Python to PATH”这个选项默认不勾选很多人在这里卡住。第二步准备脚本文件。把上面的代码保存为extract_rtl.py放在任意目录都可以建议放在工程根目录下方便管理。第三步修改路径配置。打开脚本文件在最后的if __name__ __main__部分修改路径XPR_FILE rD:\fpga_projects\axi_eth\axi_eth.xpr OUT_DIR rD:\fpga_projects\axi_eth\output注意路径前面加r表示原始字符串Windows路径里的反斜杠不会被当成转义符处理。这个细节如果漏了路径解析就会出错。第四步运行脚本。命令行进入脚本所在目录执行python extract_rtl.py正常情况下的输出如下[信息] 开始解析工程文件: axi_eth [信息] 发现 63 个文件引用 [成功] 源码清单已生成: D:\fpga_projects\axi_eth\output\axi_eth_rtl_list.md [成功] 文件字典已生成: D:\fpga_projects\axi_eth\output\axi_eth_file_dict.json 提取汇总 Verilog: 47 个文件 SystemVerilog: 0 个文件 VHDL: 0 个文件 IP核: 6 个文件 其他: 5 个文件 合计: 58 个文件过滤仿真/临时文件后如果工程文件引用了不存在的文件会在汇总信息前打印警告信息列出所有缺失文件。这个功能特别实用很多工程在同事之间传来传去之后源文件路径早就对不上了脚本能帮你一眼看出哪些文件丢了对不上。第五步查看输出结果。用Markdown阅读器或者任何文本编辑器打开生成的axi_eth_rtl_list.md内容大致如下# axi_eth 工程RTL源码清单 ## 统计信息 - 工程文件总数: **58** - Verilog文件: **47** ... ## Verilog源码 - src/top.v **[TOP]** - src/axi_master_wr.v - src/axi_master_rd.v ...JSON文件的结构是分类为顶层key的嵌套字典适合后续接入其他自动化流程。4.2 多工程批量提取的场景扩展单个工程提取跑通之后如果你手头有几十个工程需要批量处理逐条修改脚本里的路径再执行效率就太低了。给脚本加上批量处理能力让它可以接受命令行参数import sys def main(xpr_path, output_dir): # ... 原有逻辑不变 if __name__ __main__: if len(sys.argv) 3: XPR_FILE sys.argv[1] OUT_DIR sys.argv[2] else: # 默认手动配置 XPR_FILE rD:\fpga_projects\axi_eth\axi_eth.xpr OUT_DIR rD:\fpga_projects\axi_eth\output main(XPR_FILE, OUT_DIR)这样就能配合批处理脚本使用for /d %i in (D:\fpga_projects\*) do python extract_rtl.py %i\*.xpr %i\outputWindows批处理循环或Linux下的shell循环都行。批量模式下脚本对每个工程生成独立的输出文档文件名规则是工程名_rtl_list.md不会互相覆盖。4.3 我踩过的三个大坑第一个坑工程文件编码问题。Vivado生成的.xpr文件默认使用UTF-8编码但如果你是在中文版Windows环境下创建工程文件的XML声明里会带encodingUTF-8这个没问题。真正会出问题的是某些老版本Vivado生成的工程文件编码声明可能是gb2312或者gbk这时候xml.etree.ElementTree会抛出UnicodeDecodeError。解决方案是在读取文件时指定编码def parse_xpr(xpr_path): # 先读取文件内容尝试多种编码 last_err None for encoding in [utf-8, gbk, gb2312, latin-1]: try: with open(xpr_path, r, encodingencoding) as f: content f.read() break except UnicodeDecodeError as e: last_err e else: raise ValueError(f所有编码尝试均失败: {last_err}) # 用解析字符串的方式替代直接解析文件 root ET.fromstring(content) ...不用奇怪为什么还有人用老版本的Vivado工业界的情况你们懂的芯片厂的开发环境更新频率远超你的想象。第二个坑路径中带空格和特殊字符。有些团队的项目路径喜欢用带空格的目录名比如D:\My Projects\axi_eth。如果你拿着不规范的路径处理脚本可能不会报错但生成的文件清单里路径显示会很乱。更麻烦的是某些特殊字符比如#符号在部分环境里会被识别为注释符。解决办法是统一用os.path系列函数处理路径不要自己拼接字符串。上面代码里已经用了规范的路径处理方式这块大家直接抄作业就行。第三个坑IP核文件重复引用。当工程里有一个IP核被多个模块使用时.xpr文件里会在多个Library节点下重复引用同一个.xci文件。如果脚本不去重生成的清单里同一个IP会出现多次。解决方案在classify_files函数里加入去重逻辑seen_paths set() deduplicated [] for f in classified[ip]: norm_key os.path.normcase(os.path.abspath(f[path])) if norm_key not in seen_paths: seen_paths.add(norm_key) deduplicated.append(f) classified[ip] deduplicated同时给分类函数内的所有category都加上这个去重逻辑保证输出结果不含重复项。5. 常见问题与排查技巧5.1 高频问题速查表问题现象可能原因处理方法运行脚本提示找不到工程文件路径配置错误或文件被移动检查XPR_FILE路径是否与真实文件位置一致抛出XML解析错误工程文件损坏或使用了不兼容的老版本用文本编辑器打开.xpr文件检查格式完整性文件清单为空.xpr是Vivado早期版本2013以前格式在Vivado里重新保存工程升级到新格式提取到的文件数量明显偏多排除目录配置不生效临时文件被纳入了清单检查exclude_dirs列表是否覆盖了项目实际目录命名生成清单中IP核名称重复出现多Library下同一个IP引用多次启用去重逻辑按绝对路径去重网线风格不符想要绝对路径显示相对路径转换成绝对路径失败确认project_dir变量的路径解析是否正确文件不存在警告刷屏工程移动后原路径失效引用文件在不同机器逐一核对警告列表里的路径更新工程引用5.2 路径解析疑难杂症拿到一个.xpr文件里面的路径有多种形态真实世界的工程从来不会乖乖配合你的假设。相对路径指向工程外部。比如../../common/ip/axi_dma_0.xci这类路径发生在工程引用了公共库的情况下。脚本在拼接绝对路径时os.path.normpath能正确处理..的跳转逻辑最终得出正确路径。混合路径分隔符。有些工程文件在Windows上编辑过里面既有正斜杠又有反斜杠。处理方式是先把路径里的反斜杠统一替换成正斜杠再交给os.path.normpathraw_path file_node.get(Path, ) # 统一分隔符后再规范化 raw_path raw_path.replace(\\, /) normalized_path os.path.normpath(raw_path)相对路径中带盘符。这种诡异场景我在跨平台协作的项目里见过类似C:\repo\module.v直接出现在Path属性里。判断方法很简单检查路径是否以盘符开头如果是则不需要拼接工程目录。import re def abs_path_resolver(path_attr, project_dir): # 统一分隔符 path_attr path_attr.replace(\\, /) # 判断是否为绝对路径 if re.match(r^[A-Za-z]:|^/, path_attr): return os.path.normpath(path_attr) # 相对路径拼接工程目录 return os.path.normpath(os.path.join(project_dir, path_attr))5.3 工程文件备份与恢复的联动用法工具用得多了我慢慢发现它和工程备份组合起来能形成一套完整的工作流。常规工程备份是直接复制整个工程目录但这样做有几个问题一是目录里有大量中间文件备份体积动辄几个GB二是文件散落在各个层级的子目录里既不透明也不好恢复。用了提取工具之后我的备份流程变成了这样运行RTL提取工具生成源码清单Markdown文档。按照清单只复制清单里出现的文件保留原始相对路径。把工程.xpr文件和源码目录一起压缩体积通常只有完整备份的十分之一到五分之一。压缩包命名规则是工程名_版本号_日期.7z附带生成的清单文档。恢复时解压文件在Vivado里打开.xpr工程文件如果源码相对路径保持正确工程直接恢复可用。这个方法我用了近两年从老家搬回公司、从旧电脑换到新电脑都顺利恢复了工程。对比动辄几十GB的全量备份这套方案占空间小、恢复速度快而且因为清单文档本身就是一份透明可读的索引即使哪一天Vivado版本大变样了有了文件清单也能手动重新组织工程。5.4 脚本的安全性和健壮性考虑写工具脚本的人容易忽略边界情况。分享几个我吃过亏之后补上的防护逻辑。文件不存在时优雅退出。主函数入口要判断工程文件是否存在不存在就直接给错误提示别让后面一堆代码白跑。重复运行不产生脏数据。输出目录如果之前运行过里面的文件会被覆盖但不会报错。如果想要更安全的方案可以在生成文件名时加上时间戳from datetime import datetime timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_path os.path.join(output_dir, f{xpr_name}_rtl_list_{timestamp}.md)编码写入指定UTF-8。生成文件时明确指定encodingutf-8避免中文路径或文件内容在不同平台上显示乱码。这个细节对国内用户特别重要我就是因为漏了这步生成的清单在同事的Linux环境下打开全是乱码。6. 后续扩展思路和建议工具能跑、能满足当前需求这只是一个起点。我始终觉得真正顺手的工作利器是在使用过程中根据实际需求一点点长出来的。后续可以考虑的扩展方向按实用度排个序第一接入Git版本管理。把提取工具作为Git pre-commit钩子的一部分每次提交前自动扫描工程检查是否有新增源码文件没纳入Git管理。这个功能对团队协作的工程规范非常有价值能有效避免同事之间互相埋怨“你那个新模块文件怎么没提交上来”。第二代码行数统计和模块依赖分析。基于提取结果遍历每个文件统计总行数、模块声明和实例化关系输出模块间的依赖图。虽然这个扩展已经超出了“提取”的范畴但数据基础是提取工具打好的。第三和Vivado Tcl脚本联动。生成的文件清单JSON可以作为Tcl脚本的输入在Vivado里执行批量add_files操作。特别是工程重建的时候一条命令把清单里的所有文件批量加入工程效率感人也避免了手动逐个添加的繁琐和错漏。有想法的人还可以把工具打包成独立的exe可执行文件脱离Python环境直接运行。用PyInstaller就能实现有需要可以搜下用法。做成exe之后放到网络共享盘上团队里谁需要谁去拷不用每个人装Python环境。我在实际使用中体会最深的一件事是工具本身并不复杂但围绕工具的工程管理思路、文件组织习惯和目标颗粒度才是真正能影响日常工作幸福感的东西。这套方案不一定适合所有团队和所有项目但如果你的团队正在被“源码文件不知道放在哪儿”“每次整理代码清单要花半小时”“工程换个机器就找不到文件”这些问题困扰把思路对齐到“让机器帮我们管理工程文件清单”这个方向上值得试试。最后再分享一个我在用这个工具时的小技巧跑完脚本生成的Markdown清单我习惯顺手打印一份放在工位上。纸上列着当前工程的结构随手圈圈画画标注改动重点比来回切窗口查代码方便得多。做硬件这行某些时候返璞归真的办法反而最好用。
返回列表