目录

PrimeTime Max Delay(Setup) Violation Fix

To using this script, we should using script PrimeTime 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)