Design-For-Test Scripts

 

 

# The number of scan chains will be determined automatically taking into account

# the total number of registers in the core.

# In order to configure a core-level scan insertion, run the following function: 

#---------------------------------------------------------------------------

proc config_scan_chain {max_length} {

  set chains_num [expr [sizeof_collection [all_registers]] / $max_length + 1]

  set_scan_configuration -chain_count $chains_num -dedicated_scan_ports true

  preview_scan -show all

}

 

 

# This script inserts scannable flops insert of non-scannable ones and

# connects them the same way the Design Compiler does: scan data pin of each

# flop is connected to the same flop's output

# Usage:

# Load this file into synopsys dc_shell-t and then run:

# replace_regs <standard cells library name>

# Example:  replace_regs nlc13_slow108V125C

 

 

# Methodological Note

# First, run your compilation without -scan switch (this will avoid Test Compiler

# License usage). Then, run this script on your current design. In case of a

# hierarchical design, run this script:

 

# foreach design [c2l [all_designs]] {

#   current_design $design

#   replace_regs <standard cells library name>

# }

 

# After replacement, run incremental compile with a low effort to fix possible

# timing problems which could appear as a result of the changes.

 

 

# Replaces non-scannable register with the scannable one assuming that addition pins

# names scannable register has are SD (scan data input) and SE (scan enable).

# These name could be changed in a case of problems.

#==================================================================

proc replace_reg {reg_name new_ref} {

  set pins [c2l [get_pins $reg_name/*]]

  foreach pin $pins {

    set net($pin) [c2l [all_connected $pin]]

    disconnect_net $net($pin) [get_pins $pin]

  } 

  remove_cell $reg_name

  create_cell $reg_name $new_ref

  foreach pin $pins {

    connect_net $net($pin) [get_pins $pin]

  }

  set out_pins [get_gate_outputs $reg_name]

  foreach pin $out_pins {

    if {[c2l [all_connected $pin]] != ""} {

      connect_net [get_nets $net($pin)] [get_pins $reg_name/SD]

    }

  }

}

 

# Returns output pins of given gate

#==================================================================

proc get_gate_outputs {name} {

  set ret_list ""

  foreach pin [c2l [get_pins $name/* -filter "@pin_direction == out"]] {

    lappend ret_list $pin

  }

  return $ret_list

}

 

# Converts dc collection to tcl list

#===================================================================

proc c2l {collection} {

  set my_list {}

  foreach_in_collection coll_element $collection {

    set element [get_object_name $coll_element]

    lappend my_list $element

  }

  return $my_list

}

 

# Returns reference name of a given cell

#==================================================================

proc get_ref_name {inst_name} {

  return [get_attribute $inst_name ref_name]

}

 

 

# Replaces all non-scannable register for the scannable ones in the current design.

# Scannable register was chosen by replacing "ff" pattern of original register's ref name for "sff"

# If cell of this type exist in current technology library, it replaces original register.

# (This is library-dependent , please change the pattern inside "regsub .." line in a case of problems)

#==================================================================

proc replace_regs { lib_name} {

  foreach_in_collection reg_ptr [all_registers] {

    set reg [get_object_name $reg_ptr]

    regsub ff [get_ref_name $reg] sff scan_ref

    if {[get_lib_cells $lib_name/$scan_ref] != ""} {

      puts "\nReplacing register $reg ..."

      replace_reg $reg $lib_name/$scan_ref

    }

  }

}

 

 

# Inserts internal scan chain into the current design

#==================================================================

proc create_scan {} {

  create_port -direction "in" {test_si test_se}

  create_net {test_si test_se}

  connect_net test_si [get_ports test_si]

  connect_net test_se [get_ports test_se]

 

  set in_net test_si

  foreach_in_collection reg_ptr [all_registers] {

    set reg [get_object_name $reg_ptr]

    connect_net [find net test_se] [get_pins $reg/SE]

    set out_pins [get_outputs $reg]

    foreach pin $out_pins {

      if {[c2l [all_connected $pin]] != ""} {

        set out_net [c2l [all_connected $pin]]

      }

    }

    disconnect_net $out_net [get_pins $reg/SD]

    connect_net $in_net [get_pins $reg/SD]

    set in_net $out_net

  }

  if {[c2l [get_ports [all_connected $in_net]]] == ""} {

    create_port -direction "out" {test_so}

    connect_net $in_net [get_ports test_so]

    set_attribute [get_ports test_so] scan_out true -type boolean

  } else {

    set so_port [c2l [get_ports [all_connected $in_net]]]

    puts "$so_port is scan out port!"

    set_attribute [get_ports $so_port] scan_out true -type boolean

  }

}