Loading

Synopsys数字前端工程自动产生脚本

随手弄了个Synopsys数字前端工程自动产生脚本,使用方式是在要创建工程的路径下python env_setup.py即可自动创建工程文件夹,随后进入prj子文件夹使用makefile调用工具即可。

写的比较仓促,有的功能没怎么测到,欢迎有bug或者修改意见在评论区反馈。

env_setup内容:

import os

# 定义文件树结构
file_tree = {
    'lib': {},
    'netlist': {},
    'prj': {
        'filelist.f': None,
        'makefile': None
    },
    'src': {
        'rtl': {},
        'sdc': {}
    },
    'tb': {},
    'work': {
        'dc': {
            'outputs': {},
            'reports': {},
            'scripts': {
                'dc_post_syn.tcl': None,
                'dc_read_design.tcl': None,
                'dc_set_cons.tcl': None,
                'dc_set_env.tcl': None,
                'dc_setup.tcl': None,
                'dc_syn.tcl': None,
                'run_dc.tcl': None
            }
        },
        'sg': {
            'scripts': {}
        },
        'vcs': {},
        'verdi': {}
    }
}

# 创建文件树
def create_file_tree(base_path, tree, root_name):
    for name, subtree in tree.items():
        path = os.path.join(base_path, name)
        if subtree is None:
            # 创建文件
            open(path, 'a').close()
        else:
            # 创建文件夹
            os.makedirs(path, exist_ok=True)
            create_file_tree(path, subtree, root_name)
    
    # 在rtl文件夹下生成与root_dir同名的.v文件
    if 'rtl' in tree:
        rtl_file_path = os.path.join(base_path, 'rtl', f"{root_name}.v")
        with open(rtl_file_path, 'w') as f:
            rtl_content = f"""module {root_name} (
    input clk,
    input rst_n,
    input [31:0] a,
    input [31:0] b,
    output reg [31:0] c
);

always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
        c <= 32'h00000000;
    else
        c <= a + b;
end

endmodule
"""
            f.write(rtl_content)
    
    # 在tb文件夹下生成tb_{root_name}.v文件
    if 'tb' in tree:
        tb_file_path = os.path.join(base_path, 'tb', f"tb_{root_name}.v")
        with open(tb_file_path, 'w') as f:
            tb_content = f"""module tb_{root_name}();

reg clk;
reg rst_n;
reg [31:0] a;
reg [31:0] b;
wire [31:0] c;

always #10 clk = ~clk;  //50MHz

initial begin
    clk = 1'b0;
    rst_n = 1'b0;
    a = 32'h00000000;
    b = 32'h00000000;
    #10;
    rst_n = 1'b1;
    a = 32'h00001234;
    b = 32'h00004321;
    #100;
    $finish;
end

{root_name} u_{root_name} (
    .clk(clk),
    .rst_n(rst_n),
    .a(a),
    .b(b),
    .c(c)
);

`ifdef FSDB
    initial begin
        $fsdbDumpfile("tb_{root_name}.fsdb");
        $fsdbDumpvars;
        $fsdbDumpMDA();
    end
`endif

endmodule
"""
            f.write(tb_content)
    
    # 在sdc文件夹下生成与root_dir同名的.sdc文件
    if 'sdc' in tree:
        sdc_file_path = os.path.join(base_path, 'sdc', f"{root_name}.sdc")
        with open(sdc_file_path, 'w') as f:
            sdc_content = f"""# Definition of Clock
set Tclk 20 ;#50MHz
set clk_name "clk"
set unc_perc 0.05

create_clock -name $clk_name -period $Tclk [get_ports clk]
set_clock_uncertainty -setup [expr $Tclk * $unc_perc]  [get_clocks $clk_name]
set_clock_transition 0.4 [all_clocks]

# Set Ideal Network
set_dont_touch_network [get_ports clk]
set_ideal_network [get_port clk]

set_dont_touch_network [get_ports rst_n]

# Definition of IO
set_input_delay  [expr $Tclk*1/5.0] -clock $clk_name [all_inputs]
remove_input_delay [get_ports clk]

set_output_delay [expr $Tclk*1/5.0] -clock $clk_name [all_outputs]

# Other Constraint
set_max_transition  0.6  [current_design]
set_max_fanout      64   [current_design]
set_max_capacitance 2    [current_design]
set_input_transition -max 0.5  [all_inputs]
set_load 2 [all_outputs]

set_max_leakage_power 0
set_max_area 0
"""
            f.write(sdc_content)

    # 在sdc文件夹下生成与root_dir同名的.sgdc文件
    if 'sdc' in tree:
        sgdc_file_path = os.path.join(base_path, 'sdc', f"{root_name}.sgdc")
        with open(sgdc_file_path, 'w') as f:
            sgdc_content = f"""current_design {root_name}
sdc_data -file ../../src/sdc/{root_name}.sdc
"""
            f.write(sgdc_content)
    
    # 在sg/scripts文件夹下生成run_sg.tcl文件
    if 'scripts' in tree.get('sg', {}):
        sg_script_path = os.path.join(base_path, 'sg', 'scripts', 'run_sg.tcl')
        with open(sg_script_path, 'w') as f:
            sg_script_content = f"""set design_name "{root_name}"

# read in files
read_file -type sourcelist ../../prj/filelist.f
# read_file -type gateslib ../../lib/ 
read_file -type sgdc ../../src/sdc/${{design_name}}.sgdc

# setup
set_option top ${{design_name}}
set_option sdc2sgdc yes
current_goal Design_Read -top ${{design_name}}
link_design -force

# run lint
current_goal lint/lint_rtl -top ${{design_name}}
run_goal

# save project
save_project -force
"""
            f.write(sg_script_content)
    
    # 在dc/scripts文件夹下生成多个tcl文件
    if 'scripts' in tree.get('dc', {}):
        dc_scripts = [
            'dc_post_syn.tcl',
            'dc_read_design.tcl',
            'dc_set_cons.tcl',
            'dc_set_env.tcl',
            'dc_setup.tcl',
            'dc_syn.tcl',
            'run_dc.tcl'
        ]
        for script in dc_scripts:
            script_path = os.path.join(base_path, 'dc', 'scripts', script)
            open(script_path, 'a').close()

# 获取用户输入的根目录
root_dir = input("请输入根目录路径: ")

# 获取根目录名称
root_name = os.path.basename(root_dir)

# 创建文件树
create_file_tree(root_dir, file_tree, root_name)

# 在makefile中生成内容
makefile_content = f""".PHONY:vcs verdi dc sg dve

OUTPUT = {root_name}
TIMESCALE = 1ns/1ps

#start vcs
vcs:
\tcd ../work/vcs && vcs -R -sverilog -full64 +v2k -debug_pp -timescale=${{TIMESCALE}} -cpp g++ -cc gcc -LDFLAGS -no-pie -LDFLAGS -Wl,--no-as-needed -CFLAGS -fPIE -fsdb -f ../../prj/filelist.f -o ${{OUTPUT}} -l compile.log

#start verdi
verdi:
\tcd ../work/verdi && verdi -sv -f ../../prj/filelist.f -ssf ../vcs/tb_${{OUTPUT}}.fsdb

#start dc
dc:
\tcd ../work/dc && dc_shell -f ./scripts/run_dc.tcl | tee ./syn.log && rm -r ~/synopsys_cache_O-2018.06-SP1

#start sg
sg:
\tcd ../work/sg && sg_shell -tcl ./scripts/run_sg.tcl

#start dve
dve:
\tcd ../work/vcs && ./${{OUTPUT}} -gui
"""

makefile_path = os.path.join(root_dir, 'prj', 'makefile')
with open(makefile_path, 'w') as f:
    f.write(makefile_content)

# 在filelist.f中生成内容
filelist_content = f"""//Macro define
+define+FSDB

// pre_sim
../../src/rtl/{root_name}.v

// post_sim
//../../netlist/

// library
//../../lib/

// testbench
../../tb/tb_{root_name}.v
"""

filelist_path = os.path.join(root_dir, 'prj', 'filelist.f')
with open(filelist_path, 'w') as f:
    f.write(filelist_content)

# 在run_dc.tcl中生成内容
run_dc_content = f""" # dc setup
source ./scripts/dc_setup.tcl

# read design
source ./scripts/dc_read_design.tcl

# define design environment
source ./scripts/dc_set_env.tcl

# set design constraints
source ./scripts/dc_set_cons.tcl

# synthesis and optimize design
source ./scripts/dc_syn.tcl

# analyze and resolve design problems
source ./scripts/dc_post_syn.tcl
"""

run_dc_path = os.path.join(root_dir, 'work', 'dc', 'scripts', 'run_dc.tcl')
with open(run_dc_path, 'w') as f:
    f.write(run_dc_content)

# 在dc_syn.tcl中生成内容
dc_syn_content = f"""
check_design > $report_path/check_design_before_compile.rpt
check_timing > $report_path/check_timing_before_compile.rpt

compile_ultra

compile_ultra -incremental
"""

dc_syn_path = os.path.join(root_dir, 'work', 'dc', 'scripts', 'dc_syn.tcl')
with open(dc_syn_path, 'w') as f:
    f.write(dc_syn_content)

# 在dc_setup.tcl中生成内容
dc_setup_content = f"""
set design_name "{root_name}"

# standard cell library
set stdcel_libs "
../../lib/
"

# memory library
set memory_libs "
../../lib/
"

# ip library
set ip_libs "
../../lib/
"

set target_library "$stdcel_libs"
set link_library   "* $target_library $memory_libs $ip_libs"

sh mkdir -p ./reports
sh mkdir -p ./outputs

set report_path "./reports"
set output_path "./outputs"

set_svf $output_path/${{design_name}}.svf
"""

dc_setup_path = os.path.join(root_dir, 'work', 'dc', 'scripts', 'dc_setup.tcl')
with open(dc_setup_path, 'w') as f:
    f.write(dc_setup_content)

# 在dc_set_env.tcl中生成内容
dc_set_env_content = f"""
set_operating_conditions "" -library ""

set_wire_load_model -name ""
set_wire_load_mode top

set_host_options -max_cores 16

set_dp_smartgen_options -all_options auto -optimize_for speed

set_critical_range 3 [current_design]

set_app_var enable_page_mode false
"""

dc_set_env_path = os.path.join(root_dir, 'work', 'dc', 'scripts', 'dc_set_env.tcl')
with open(dc_set_env_path, 'w') as f:
    f.write(dc_set_env_content)

# 在dc_set_cons.tcl中生成内容
dc_set_cons_content = f"""
set sdc_path "../../src/sdc" 

read_sdc "$sdc_path/${{design_name}}.sdc"
"""

dc_set_cons_path = os.path.join(root_dir, 'work', 'dc', 'scripts', 'dc_set_cons.tcl')
with open(dc_set_cons_path, 'w') as f:
    f.write(dc_set_cons_content)

# 在dc_read_design.tcl中生成内容
dc_read_design_content = f"""
analyze -f verilog -vcs "-f ../../prj/filelist.f"

elaborate $design_name

current_design $design_name
link
"""

dc_read_design_path = os.path.join(root_dir, 'work', 'dc', 'scripts', 'dc_read_design.tcl')
with open(dc_read_design_path, 'w') as f:
    f.write(dc_read_design_content)

# 在dc_post_syn.tcl中生成内容
dc_post_syn_content = f"""
write_sdf -version 2.1         $output_path/${{design_name}}_post_dc.sdf
write -f ddc -hier -output     $output_path/${{design_name}}_post_dc.ddc
write -f verilog -hier -output $output_path/${{design_name}}_post_dc.v
write_sdc                      $output_path/${{design_name}}_post_dc.sdc

report_constraint -all_violators -verbose          > $report_path/constraint.rpt
report_qor                > $report_path/qor.rpt
report_power              > $report_path/power.rpt
report_area               > $report_path/area.rpt
report_cell               > $report_path/cell.rpt
report_clock              > $report_path/clk.rpt
report_hierarchy          > $report_path/hierarchy.rpt
report_design             > $report_path/design.rpt
report_reference          > $report_path/reference.rpt
report_timing             > $report_path/timing.rpt

check_design > $report_path/check_design_post_compile.rpt
check_timing > $report_path/check_timing_post_compile.rpt
"""

dc_post_syn_path = os.path.join(root_dir, 'work', 'dc', 'scripts', 'dc_post_syn.tcl')
with open(dc_post_syn_path, 'w') as f:
    f.write(dc_post_syn_content)

print(f"模板工程已在 {root_dir} 生成")

posted @ 2024-09-04 22:45  sasasatori  阅读(248)  评论(0编辑  收藏  举报