====== PrimeTime Max Delay(Setup) Violation Fix ======
To using this script, we should using script [[vlsi:pt:report]] to generate reports.
===== Swap Cells =====
Swap between different VT cells. Change HVT to LVT cells.
#! /tools/cfr/bin/python
import os
import sys
import re
import sets
from collections import defaultdict
def get_all_setup_rpt():
modes = 'func mbist bisr scan merged'.split(' ')
all_corners = 'max maxlt min minht maxrc minrc'.split(' ')
content = ""
for mode in modes:
for corner in all_corners:
#print mode, corner
ddir = "postlayout_%s_%s" % (mode, corner)
#setup_rpt_name = "sfvs_%s_%s_setup.rpt" % (mode, corner)
setup_rpt_name = "zgdh_timing_setup_reg2reg_startend.rpt"
setup_rpt = os.path.join(ddir, setup_rpt_name)
if os.path.exists(setup_rpt):
print "# Reading report: %s" % setup_rpt
content += open(setup_rpt).read()
return content
def get_faster_lib_cel(master):
xp_patt = """[^LF]XP"""
lxp_patt = """LXP"""
new_lib_cel = ""
if re.findall(xp_patt, master):
new_lib_cel = 'g65fxp/' + master.replace('XP', 'FXP')
if re.findall(lxp_patt, master):
new_lib_cel = 'g65xp/' + master.replace('LXP', 'XP')
return new_lib_cel
def swap_cells(setup_vio_reports):
patt = """^([a-zA-Z0-9\[\]\/_]*)/[^/ ]*\s+\(([^ ]*)\)\s+[\.\d]+\s+[\.\d]+ \&"""
lines = setup_vio_reports.split("\n")
all_cmd = sets.Set()
for line in lines:
line = line.strip()
if not line: continue
instance_master = re.findall(patt, line)
if instance_master:
instance_master = instance_master[0]
master = instance_master[1]
instance = instance_master[0]
if master == "net" or master.startswith("RR") or master.startswith("FD"):
pass
else:
new_master = get_faster_lib_cel(master)
if new_master:
cmd = "size_cell %s %s" % (instance, new_master)
all_cmd.add(cmd)
else:
cmd = "# no change: %s %s" % (master, instance)
return all_cmd
if __name__ == "__main__":
all_setup_rpt = get_all_setup_rpt()
#size_large_delay_cells(all_setup_paths, cell_delay_threshold=0.15)
all_cmd = swap_cells(all_setup_rpt)
print "\n".join(all_cmd)
===== Size Cells =====
This is not verified. More verification to do.
#! /tools/cfr/bin/python
import os
import sys
import re
from collections import defaultdict
def get_lib_cell_swap_dict():
size_cell_dict = {}
size_cell_dict['BUFM2XP'] = 'g65xp/BUFM10XPV1'
size_cell_dict['BUFM2LXP'] = 'g65xp/BUFM10XPV1'
size_cell_dict['BUFM3XP'] = 'g65xp/BUFM10XPV1'
size_cell_dict['N1M1XPV1'] = 'g65xp/N1M8XPV1'
size_cell_dict['N1M3XP'] = 'g65xp/N1M8XPV1'
size_cell_dict['N1M05LXPV1'] = 'g65xp/N1M8XPV1'
size_cell_dict['AO222M05XPV1'] = 'g65xp/AO222M2XPV1'
size_cell_dict['OAI211M05XP'] = 'g65xp/OAI211M8XPV1'
size_cell_dict['OAI211M1XPV1'] = 'g65xp/OAI211M8XPV1'
size_cell_dict['OAI211M2XPV1'] = 'g65xp/OAI211M8XPV1'
size_cell_dict['NR2BNM05LXPV1'] = 'g65xp/NR2ANM8XPV1'
size_cell_dict['NR2BNM2XP'] = 'g65xp/NR2ANM8XPV1'
size_cell_dict['OR2M05XPV1'] = 'g65xp/OR2M6XPV1'
size_cell_dict['FA1AM05LXPV1'] = 'g65xp/FA1AM2XP'
size_cell_dict['FA1AM1LXPV1'] = 'g65xp/FA1AM2XP'
size_cell_dict['MUX21LM05LXP'] = 'g65xp/MUX21LM4XPV1'
size_cell_dict['AND3M05LXPV1'] = 'g65xp/AND3M4XP'
size_cell_dict['AOI21M05LXPV1'] = 'g65xp/AOI21M4XPV1'
size_cell_dict['AOI22M05LXPV1'] = 'g65xp/AOI22M4XPV1'
size_cell_dict['ENM05LXPV1'] = 'g65xp/ENM4XPV1'
size_cell_dict['EOM05LXPV1'] = 'g65xp/EOM4XPV1'
size_cell_dict['HA1M05LXPV1'] = 'g65xp/HA1M4XP'
size_cell_dict['NR2M05LXPV1'] = 'g65xp/NR2M4XP'
size_cell_dict['OR2M05LXPV1'] = 'g65xp/OR2M4XP'
size_cell_dict['ENM075LXPV1'] = 'g65xp/ENM4XPV1'
size_cell_dict['EOM075LXPV1'] = 'g65xp/EOM4XPV1'
size_cell_dict['MUX21LM075LXPV1'] = 'g65xp/MUX21LM4XPV1'
size_cell_dict['MUX21LM075XPV1'] = 'g65xp/MUX21LM4XPV1'
return size_cell_dict
def get_slack_from_path(timing_path):
patt="""slack \(VIOLATED\)\s+(-?[\d\.]+)"""
slacks = re.findall(patt, timing_path, re.DOTALL)
slack = 0
if slacks:
slack = float(slacks[0])
return slack
def get_all_setup_paths():
modes = 'func mbist bisr scan merged'.split(' ')
all_corners = 'max maxlt min minht maxrc minrc'.split(' ')
content = ""
for mode in modes:
for corner in all_corners:
#print mode, corner
ddir = "postlayout_%s_%s" % (mode, corner)
#setup_rpt_name = "sfvs_%s_%s_setup.rpt" % (mode, corner)
setup_rpt_name = "zgdh_timing_setup_reg2reg_startend.rpt"
setup_rpt = os.path.join(ddir, setup_rpt_name)
if os.path.exists(setup_rpt):
print "# Reading report: %s" % setup_rpt
content += open(setup_rpt).read()
timing_paths = content.split('Startpoint')
new_timing_paths = []
for p in timing_paths:
if p.strip():
new_timing_paths.append( 'Startpoint'+p )
return new_timing_paths
def get_large_delay_cells(all_setup_vio_rpt, delay_threshold = 0.10):
cell_delay_dic = defaultdict(list)
patt = """^([a-zA-Z0-9\[\]\/_]*)/[^/ ]*\s+\(([^ ]*)\)\s+[\.\d]+\s+([\.\d]+)"""
for line in all_setup_vio_rpt.split("\n"):
line = line.strip()
if not line: continue
instance_masters = re.findall(patt, line)
if instance_masters:
master = instance_masters[0][1]
instance = instance_masters[0][0]
if master == "net" or master.startswith("RR") or master.startswith("FD"):
pass
else:
cell_delay = float(instance_masters[0][2])
if cell_delay >= delay_threshold:
#print instance_masters
cell_delay_dic[master].append(instance_masters[0][2])
return cell_delay_dic
def size_large_delay_cells(setup_paths, setup_slack_threshold = -0.10, cell_delay_threshold = 0.20):
instance_masters_uniq = {}
fix_cmd_icc = ""
lib_cell_swap_dict = get_lib_cell_swap_dict()
for setup_path in all_setup_paths:
all_instance_masters = get_sizing_instances(setup_path, setup_slack_threshold, cell_delay_threshold)
for im in all_instance_masters:
instance = im[0]
master = im[1]
print "#", im
instance_masters_uniq[instance] = master
for instance, master in instance_masters_uniq.items():
print "# %s %s " % (instance, master)
dest_cell = lib_cell_swap_dict.get(master, "")
if dest_cell:
#fix_cmd_icc += "size_cell %s %s\n" % (instance, dest_cell)
print "size_cell %s %s" % (instance, dest_cell)
else:
print "#-#-# No predefined: %s, %s" % (master, instance)
print
def get_sizing_instances(setup_path, setup_slack_threshold = -0.10, cell_delay_threshold = 0.10):
cell_delay_dic = defaultdict(list)
patt = """^([a-zA-Z0-9\[\]\/_]*)/[^/ ]*\s+\(([^ ]*)\)\s+[\.\d]+\s+([\.\d]+) \&"""
setup_slack = get_slack_from_path(setup_path)
all_sizing_instance_masters = []
instance_master = None
if setup_slack > setup_slack_threshold:
pass
else:
for line in setup_path.split("\n"):
line = line.strip()
if not line: continue
instance_master = re.findall(patt, line)
if instance_master:
instance_master = instance_master[0]
master = instance_master[1]
instance = instance_master[0]
if master == "net" or master.startswith("RR") or master.startswith("FD"):
pass
else:
cell_delay = float(instance_master[2])
if cell_delay >= cell_delay_threshold:
#print "#-- ", instance_master
all_sizing_instance_masters.append(instance_master)
return all_sizing_instance_masters
if __name__ == "__main__":
patt = """^([a-zA-Z0-9\[\]\/_]*)/[^/ ]*\s+\(([^ ]*)\)\s+[\.\d]+\s+([\.\d]+)"""
all_setup_paths = get_all_setup_paths()
size_large_delay_cells(all_setup_paths, cell_delay_threshold=0.15)
# lib_cell_swap_dict = get_lib_cell_swap_dict()
# large_delay_cells_dict = get_large_delay_cells(all_setup_vio_paths)
# for key, v in large_delay_cells_dict.items():
# v.sort
# print v[-1], len(v), key
# print size_large_delay_cells(all_setup_vio_paths)