( ESNUG 358 Item 10 ) -------------------------------------------- [8/23/00]

Subject: ( ESNUG 357 #6 )  A Useful DC Tcl Script To Fix Hold Violations

> I would appreciate hold-fixing strategies from you/your readers.  One of
> our designs showed up several hold problems between FFs that had no
> intermediate logic in the Q-D paths.  We're now trying to address this
> issue in synthesis land...
>
> The option we're considering is using 'connection_class' in Library
> Compiler to prevent Design Compiler from connecting one FF directly to
> another.  This is obviously a drastic measure, but I couldn't think of
> another way to ensure no two FFs were 'directly' connected.  Area is not
> a big concern for our design, so we're not as concerned w/ additional
> gate count.
>
>    - [ No Names Here ]


From: Al Czamara <czamara@asic-alliance.com>

Hi, John.  I hope all is well with you.

I've done the following in the past for hold-time fixing:

  1) Change every flop in the design to a _hold module, which
     contains the original flop plus a buffer or series of buffers that
     guarantee no hold problems.  This is a brute-force approach that
     obviously will increase the gate count beyond what's required for
     fixing the hold problem.

  2) Use Synopsys.  In dc_shell there is a 'set_fix_hold' attribute you can
     put on a clock.  This will cause dc_shell to add a hold-fixing step,
     which will solve your flop-to-flop problem.  If you're not careful
     with module contraints, you can end up with lots of extra gates,
     unfortunately.  What I've done in the past to get around this problem
     is to do a top-level compile for fixing hold ONLY.  Since all the
     modules are there with a top-level compile, there are few (ASIC I/O
     only) missing contraints that could cause lots of extra gates.
     Putting a set_dont_touch on the very top level will eliminate that
     problem.

  3) Manually fix EACH violating path, by adding buffers.  I've done this
     by hand or with Perl.

I prefer (2) above unless I'm required otherwise by the design process, ASIC
vendor, or where I am in the ASIC release flow.

    - Al Czamara
      ASIC Alliance

         ----    ----    ----    ----    ----    ----   ----

From: "Gregg Lahti" <gregg.d.lahti@intel.com>

Hi, John,

Here's a Tcl script that we had to use to correct hold violations before
going into layout so our router didn't choke and cause yet more problems:


  # filename:    P_proj_insert_buffers.tcl
  #   author:    Doug Hergatt, Gregg Lahti
  #  created:    06/26/00
  ####
  # description: This procedure is used to fix HOLD violations by inserting 
  # strategic buffers in the scan, data or both paths of the design. It is 
  # intended to be invoked pre-layout to reduce the number of violations.
  ####
  # Usage: P_proj_insert_buffers lib_cell_name inst_string fix_hold_mode

  proc P_proj_insert_buffers {lib_cell_name inst_string fix_hold_mode} {

  # Generate list of violators & filter on VIOLATED
  # Hack!  Must dump this to a tmp file because the report_constraint
  # command output can't be set to a variable!  Bad Synopsys!  Bad Synopsys!
  redirect tmp { report_constraint -min_delay -all };
  set violator_list [exec sed -n -e "/VIOLATED/p" tmp];
  sh rm tmp;

  # Check for no violations
  if {$violator_list == ""} {
    echo "#INFO: No MIN violations in current design";
    return;    
  }; # end if

  set si_violator_list "";
  set d_violator_list "";

  # Now filter on "/SI" & create list
  foreach violator $violator_list {
    if [string match */SI $violator] {
      set si_violator_list [concat $si_violator_list $violator];
    }; # end if
    if [string match */D $violator] {
      set d_violator_list [concat $d_violator_list $violator];
    }; # end if
  }; # end foreach

  # Build the list to fix
  if {$fix_hold_mode == "scan"} {
    set all_violator_list $si_violator_list;
  } elseif {$fix_hold_mode == "data"} {
    set all_violator_list $d_violator_list;
  } elseif {$fix_hold_mode == "both"} {
    set all_violator_list [concat $d_violator_list $si_violator_list];
  } else {
      echo "ERROR: Incorrect Fix Hold Mode. Please specify scan, data or both";
  }; # end if

  # Reset cell counter (used to create a unique instance name
  set cell_cnt 0;
  
  echo "#INFO: Fixing Hold violations on the violator paths.";
  
  # Fix all the violations for the violator list
  foreach reg_cell $all_violator_list {
  
    # Get the instance name of the violator
    regexp {(.*)/.*} $reg_cell var1 var2
    set inst_name [file tail $var2];
  
    # Get the hierarchy path to the violating register
    regexp {(.*)/.*} $var2 var1 hier_path
  
    # Increment the cell counter
    set cell_cnt [expr $cell_cnt + 1];

    # Find everything connected to the pin of this register
    set orig_net [all_connected [get_pins $reg_cell]];
    # Create new instance name (HOLD delay cell)
    set new_cell ${inst_name}${inst_string}${cell_cnt};
    # Create new net name (net inserted between new HOLD cell & register pin)
    set new_net ${new_cell}_net;
    
    # Disconnect the orig net & create the new cell & net
    disconnect_net $orig_net $reg_cell;
    create_cell -instance $hier_path $new_cell $lib_cell_name;
    create_net -instance $hier_path $new_net;
  
    # Add the hierarchy path to the new net & cell vars
    set new_net [file join $hier_path $new_net];
    set new_cell_in [file join $hier_path ${new_cell}/A];
    set new_cell_out [file join $hier_path ${new_cell}/O];
  
    # Connect the nets
    connect_net $new_net $reg_cell;
    connect_net $new_net $new_cell_out;
    connect_net $orig_net $new_cell_in;
  }; # end foreach

  echo "#INFO: Added $cell_cnt HOLD cells to the design.";
  }; # end proc 

  # document the procedure!
  define_proc_attributes P_proj_insert_buffers \
  -info "PROJ: Procedure to fix HOLD violations inserting strategic buffers" \
  -define_args {
   {lib_cell_name "Library Cell Name to insert" lib_cell_name string required}
   {inst_string "Instance String to insert in the new cell" inst_string string required}
    {fix_hold_mode "Fix Hold Mode: scan, data, or both" fix_hold_mode string required}
  }


This isn't, by far, the best approach to doing hold time corrections, but
this script got the job done and it provides a nice baseline example for
tackling the problem above in Tcl.  The script could be easily modified to
look for FF-to-FF connections and insert buffers accordingly.

    - Gregg Lahti
      Intel Corp                                    Chandler, AZ


[ Editor's Note:  This is one example from the paper/presentation at Boston
  SNUG '00 (Sept 20-22nd) Gregg will be giving called "Tcl: The Good, The
  Bad, and The Ugly".  Tim Wilson (also of Intel) will be presenting
  another paper at Boston on Tcl-based synthesis called "TOPS".  - John ]


 Sign up for the DeepChip newsletter.
Email
 Read what EDA tool users really think.


Feedback About Wiretaps ESNUGs SIGN UP! Downloads Trip Reports Advertise

"Relax. This is a discussion. Anything said here is just one engineer's opinion. Email in your dissenting letter and it'll be published, too."
This Web Site Is Modified Every 2-3 Days
Copyright 1991-2024 John Cooley.  All Rights Reserved.
| Contact John Cooley | Webmaster | Legal | Feedback Form |

   !!!     "It's not a BUG,
  /o o\  /  it's a FEATURE!"
 (  >  )
  \ - / 
  _] [_     (jcooley 1991)