====== 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)