因为APR place位置原因,需要dc综合时,在sram输入输出pin上插一对反相器,如下图,那么应该怎么做呢?
由于设计里sram较多,手工修改网表效率低,且容易出错。我们选择编写tcl脚本来统一处理。
首先,我们需要找到所有的sram inst。如果sram的inst命令有固定的前缀,就比较简单了,可以用get_cells -hier u_sram_*
。由于get_cells返回的是一个collection,并不是inst path的list,因此需要用get_attribte xxx full_name
来转换一下。
set sram_cells [get_attribute [get_cells -hier u_sram_sp_*] full_name]
第二步,为了脚本不影响到其他层次,我们用current_design xxx
切到sram的上一个层次的module里处理。用正则把上一步的sram inst path拆成两部分:sram上层module的inst path和sram本身的inst name。
foreach sram_cell_name $sram_cells {
regexp {(.*)/(.*)} $sram_cell_name matched path_base cell_name
puts ${path_base}
puts ${cell_name}
#...
}
用get_attribute xxx ref_name
获得sram上层module的名字,并切过去。
current_design [get_attribute $path_base ref_name]
用get_pins -hier ${cell_name}/*
找到sram的每一个pin,如下。
foreach_in_collection pin [get_pins -hier ${cell_name}
第三步,对每个pin进行输入和输出方向的判断,因为输入和输出方向的处理方法有差异。
if {[get_attribute $pin pin_direction] == "in"} {
# input pin
} else {
# output pin
}
第四步,对于某个输入pin,需要用get_nets -of_objects $pin_name
先找到pin连接的net名,再把net名中的[]
替换成下划线,然后就可以用create_cell
和create_net
来新建cell和net,最后把该断开的net断开,该连上的net连上。
set pin_name [get_attribute $pin full_name]
set net_name [get_attribute [get_nets -of_objects $pin_name] full_name]
regexp {(.*)/(.*)} $pin_name matched pin_path_base pin_short_name
regsub -all {\[|\]} $pin_short_name "_" safe_pin_name
create_cell "u_INV_${safe_pin_name}_1" ss_max_1p08v_125c/INV_X4_A7TR
create_cell "u_INV_${safe_pin_name}_2" ss_max_1p08v_125c/INV_X4_A7TR
create_net "n_INV_${safe_pin_name}_1"
create_net "n_INV_${safe_pin_name}_2"
disconnect_net ${net_name} ${pin_name}
connect_net "n_INV_${safe_pin_name}_2" ${pin_name}
connect_net "n_INV_${safe_pin_name}_2" "u_INV_${safe_pin_name}_2/Y"
connect_net "n_INV_${safe_pin_name}_1" "u_INV_${safe_pin_name}_2/A"
connect_net "n_INV_${safe_pin_name}_1" "u_INV_${safe_pin_name}_1/Y"
connect_net ${net_name} "u_INV_${safe_pin_name}_1/A"
第五步,对于某个输出pin,方法类似。
set pin_name [get_attribute $sram_pin name]
set net_name [get_attribute [get_nets -of_objects $pin_name] full_name]
regsub -all {\[|\]} $pin_name "_" safe_pin_name
create_cell "u_INV_${safe_pin_name}_1" ss_max_1p08v_125c/INV_X4_A7TR
create_cell "u_INV_${safe_pin_name}_2" ss_max_1p08v_125c/INV_X4_A7TR
create_net "n_INV_${safe_pin_name}_1"
create_net "n_INV_${safe_pin_name}_2"
disconnect_net ${net_name} ${pin_name}
connect_net "n_INV_${safe_pin_name}_2" ${pin_name}
connect_net "n_INV_${safe_pin_name}_2" "u_INV_${safe_pin_name}_2/A"
connect_net "n_INV_${safe_pin_name}_1" "u_INV_${safe_pin_name}_2/Y"
connect_net "n_INV_${safe_pin_name}_1" "u_INV_${safe_pin_name}_1/A"
connect_net ${net_name} "u_INV_${safe_pin_name}_1/Y"
总结:
本文通过get_pins
、get_cells
、get_nets -of_object
、get_attribute
等命令来获取netlist的例化和连接关系。并通过create_cell
、create_net
、disconnect_net
、connect_net
等命令来修改netlist。提值一提的是,本文中通过用get_attribute inst_path ref_name
获得module名字并用current_design
切换设计层次,降低了netlist修改的复杂度。