Loading

优化数字前端工作流的小脚本

使用python编写了两个优化工作流的小脚本。在前端设计工作时,我的工作流是:初步规划端口(markdown)-> 初步rtl代码设计(verilog)-> 完整rtl代码设计(verilog)-> 输出最终端口(markdown)

所以这里涉及两个可以自动化的步骤,一个是把我用markdown下画的表格使用脚本转化成verilog文件。另一个是把编写好的verilog文件转化回markdown表格。所以我又靠AI(还是new bing)写了这两个脚本:

将表格转换成verilog:

def generate_verilog(file_path):
    with open(file_path, 'r') as f:
        table = f.read()
    lines = table.split('\n')
    ports = []
    for line in lines[3:]:
        if line.strip() == '':
            continue
        port, width, direction, function = [x.strip() for x in line.split("|")[1:-1]]
        port = port.strip()
        width = width.strip()
        direction = direction.strip()
        function = function.strip()
        ports.append((port, width, direction,function))
    verilog = 'module my_module (\n'
    for port, width, direction, function in ports:
        if direction == 'input':
            if int(width) == 1:
                verilog += f'  input {port}, // {function}  \n' 
            else:
                verilog += f'  input [{int(width)-1}:0] {port}, // {function}  \n'
        elif direction == 'output':
            if int(width) == 1:
                verilog += f'  output {port}, // {function}  \n'
            else:
                verilog += f'  output [{int(width)-1}:0] {port}, // {function}  \n'
    verilog = verilog + '\n);\n'
    
    for port, width, direction,function in ports:
        if int(width) == 1:
            if direction == 'output':
                verilog += f'reg {port};\n'
        else:
            if direction == 'output':    
                verilog += f'reg [{int(width)-1}:0] {port};\n'
 
    verilog += '\nendmodule'
    return verilog

file_path = input('Enter the file path: ')
verilog_code = generate_verilog(file_path)

output_file_path = input('Enter the output file path: ')
with open(output_file_path, 'w') as f:
    f.write(verilog_code)

例如输入一个表格:

Port Width Direction Function
clk 1 input 时钟
rst_n 1 input 复位
inst_dout 32 input 指令数据
inst_addr 5 output 指令地址

运行脚本后就会自动输出verilog代码:

module my_module (
  input clk, // 时钟  
  input rst_n, // 复位  
  input [31:0] inst_dout, // 指令数据  
  output [4:0] inst_addr, // 指令地址  

);

reg [4:0] inst_addr;

endmodule

注意一下最后一个信号把逗号删除就行。

反过来如果要把verilog转换回表格,使用下面这个脚本:

import re

def verilog_to_markdown(input_file, output_file):
    with open(input_file, 'r') as f:
        verilog_str = f.read()

    # Extract the module declaration
    module_declaration = re.search(r'module\s+\w+\s*\(([^)]*)\);', verilog_str, re.DOTALL)
    if not module_declaration:
        return 'Error: No valid module declaration found'
    port_declarations = module_declaration.group(1).strip().split('\n')

    # Create the markdown table
    markdown_table = '| Port | Width | Direction | Function |\n'
    markdown_table += '| :-----------------------: | :---: | :-------: | :----------------------------------: |\n'
    for port_declaration in port_declarations:
        port_declaration = port_declaration.strip()
        if not port_declaration:
            continue
        direction, port_name = port_declaration.split(' ',1)[:2]
        port_name = port_name.rstrip(',')
        width = 1
        if '[' in port_name:
            width_str = re.search(r'\[(\d+):(\d+)\]', port_name).group()
            msb, lsb = map(int, width_str[1:-1].split(':'))
            width = msb - lsb + 1
            port_name = re.sub(r'\[\d+:\d+\]', '', port_name)

        port_name = port_name.split('//')[0]
        port_name = port_name.replace(',', '')

        # Extract the comment after '//'
        comment = ''
        comment_match = re.search(r'//(.*)', port_declaration)
        if comment_match:
            comment = comment_match.group(1).strip()
        
        markdown_table += f'| {port_name:<23} | {width:^5} | {direction:^9} | {comment:<35} |\n'

    with open(output_file, 'w') as f:
        f.write(markdown_table)

input_file = input('Enter the input file name: ')
output_file = input('Enter the output file name: ')
verilog_to_markdown(input_file, output_file)

例如输入一个verilog的端口声明代码:

module my_module (
  input clk, // 时钟  
  input rst_n, // 复位  
  input [31:0] inst_dout, // 指令数据  
  output [4:0] inst_addr // 指令地址  
);

就能获得一个markdown描述的表格:

Port Width Direction Function
clk 1 input 时钟
rst_n 1 input 复位
inst_dout 32 input 指令数据
inst_addr 5 output 指令地址

当然这两个脚本也不是很完善,后面可以再增加一些新的功能。

最后把数据交给后端时,可以通过把markdown里面的信号拆解到excel表格里面,通过下面这个脚本:

import pandas as pd
from openpyxl import Workbook
import re
import sys

def parse_markdown_table(file_path):
    with open(file_path, 'r') as f:
        lines = f.readlines()

    table_data = []
    for line in lines:
        if '|' in line:
            row = [item.strip() for item in line.split('|')[1:-1]]
            table_data.append(row)

    headers = table_data[0]
    data = {header: [] for header in headers}

    for row in table_data[2:]:
        for i, item in enumerate(row):
            header = headers[i]
            data[header].append(item)

    return data

# 读取命令行参数中的Markdown文件路径
file_path = sys.argv[1]

# 读取Markdown文件中的表格数据
data = parse_markdown_table(file_path)

# 创建一个Excel工作簿
wb = Workbook()
ws = wb.active

# 遍历每个端口
for i in range(len(data['Port'])):
    port = data['Port'][i]
    width = int(data['Width'][i])  # 确保宽度是整数

    # 对于每个端口,生成对应位宽的行
    for j in range(width):
        if width == 1:
            ws.append([f'{port}'])
        else:
            ws.append([f'{port}<{j}>'])

# 保存Excel文件
wb.save('ports.xlsx')

你可以通过命令行运行这个脚本,并将Markdown文件的路径作为第一个参数传递给它,例如:python script.py your_markdown_file.md。这个脚本会读取Markdown文件中的表格数据,然后根据端口名和位宽生成一个名为ports.xlsx的Excel文件。

posted @ 2023-04-24 11:10  sasasatori  阅读(213)  评论(1编辑  收藏  举报