#               Design Compiler Enhancement functions

 

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

# Graphical version of "man" command: opens

# man results in separate TK window

# Note: download view.tk application and set the correct path to

# this application inside the body of vman procedure

 

# Example : vman report_timing

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

proc vman {args} {

  eval man $args > tmpfile

  exec view.tk tmpfile &

  after 500 file delete tmpfile

}

 

 

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

# Converts collection to TCL list. By default,

# only 200 first collection members are converted.

# In order to make bigger lists, use second parameter

# which defines the number of members

#

# Examples: 

# set inputs_lits [c2l [all_inputs]] - list size is maximum 200.

# set cells_list [c2l [get_cells U18*] 400]  -  list size is maximum 400.

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

proc c2l {collection {max_num 200}} {

  set my_list {}

  set counter 0

  foreach_in_collection coll_element $collection {

    set element [get_object_name $coll_element]

    lappend my_list $element

    incr counter

    if {$counter > $max_num} {break}

  }

  return $my_list

}

 

 

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

# Makes TCL list to be unique. Unfortunately,

# TCL lacks this useful command

#

# Example:  set uniq_list [unique $non_uniq_list]

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

proc unique {bad_list} {

  set good_list {}

  foreach bad_item $bad_list {

    if {[lsearch -exact $good_list $bad_item] < 0} {

       lappend good_list $bad_item

    }

  }

  return $good_list

}

 

 

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

# Creates INPUT pins ONLY collection from the current design.

# All command line options are the same as for dc_shell's

# "get_pins" command (see "man get_pins" for details)

#

# Example: set inpins [c2l [get_inpins byte_controller/*]]

# (creating TCL list of input pins of "byte_controller" cell)

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

proc get_inpins {args} {

  get_pins $args -filter "@pin_direction == in"

}

 

 

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

# Creates OUTPUT pins ONLY collection from the current design.

# All command line options are the same as for dc_shell's

# "get_pins" command (see "man get_pins" for details)

#

# Example: set outpins [c2l [get_outpins byte_controller/*]]

# (creating TCL list of input pins of "byte_controller" cell)

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

proc get_outpins {args} {

  get_pins $args -filter "@pin_direction == out"

}

 

 

 

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

# Creates INPUT ports ONLY collection from the current design.

# All command line options are the same as for dc_shell's

# "get_ports" command (see "man get_ports" for details)

# Can be useful with "set_input_delay" and other timing constraints

# commands

#

# Example: set_input_delay 5 -clock PCI_CLK [get_inports PCI*]]

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

proc get_inports {args} {

  get_ports $args -filter "@port_direction == in"

}

 

 

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

# Creates OUTPUT ports ONLY collection from the current design.

# All command line options are the same as for dc_shell's

# "get_ports" command (see "man get_ports" for details)

# Can be useful with "set_output_delay" and other timing constraints

# commands

#

# Example: set_output_delay 5 -clock PCI_CLK [get_outports PCI*]]

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

proc get_outports {args} {

  get_ports $args -filter "@port_direction == out"

}

 

 

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

# Returns direction of port with given name

# Direction has one of the following values:

# in / out / bidi

#

# Example: get_port_dir MY_PORT_NAME

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

proc get_port_dir {name} {

  get_attribute [get_ports $name]  port_direction

}

 

 

 

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

# Returns direction of pin with given name

# Direction has one of the following values:

# in / out / bidi

#

# Example: get_pin_dir MY_PIN_NAME

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

proc get_pin_dir {name} {

  get_attribute [get_pins $name]  pin_direction

}

 

 

 

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

# Creates collection of PORTS, connected to net with given name.

# Synopsis:  get_cports <net_name> <optional_port_direction>

# Port_direction switch must have one of the following values:

#   -in / -out / -inout

# If no port directions is specified, returns all connected ports.

#

# Example: set port_name [get_cports NET12 -out]

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

proc get_cports {net {direction -all}} {

  if {$direction == "-all"} {

    get_ports [all_connected $net]

  } elseif {$direction == "-in"} {

    get_ports [all_connected $net] -filter "@port_direction == in"

  } elseif {$direction == "-out"} {

    get_ports [all_connected $net] -filter "@port_direction == out"

  } elseif {$direction == "-inout"} {

    get_ports [all_connected $net] -filter "@port_direction == inout"

  } else {

    puts "Error: use -in/-out/-inout values only to specify port direction!"

    return 0

  }

}

 

 

 

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

# Creates collection of PINS, connected to net with given name.

# Synopsis:  get_cpins <net_name> <optional_pin_direction>

# Pin_direction switch must have one of the following values:

#   -in / -out / -inout

# If no pin directions is specified, returns all connected pins.

#

# Example: set conn_pins [get_cpins NET12 -in]

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

proc get_cpins {net {direction -all}} {

  if {$direction == "-all"} {

    get_pins [all_connected $net]

  } elseif {$direction == "-in"} {

    get_pins [all_connected $net] -filter "@pin_direction == in"

  } elseif {$direction == "-out"} {

    get_pins [all_connected $net] -filter "@pin_direction == out"

  } elseif {$direction == "-inout"} {

    get_pins [all_connected $net] -filter "@pin_direction == inout"

  } else {

    puts "Error: use -in/-out/-inout values only to specify pins direction!"

    return 0

  }

}

 

 

 

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

# Returns reference name of cell with givel name

#

# Example: set rname [refname_of U232]

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

proc refname_of {cell} {

  get_attribute $cell ref_name

} 

 

 

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

# Returns fanout of net with given name

#

# Example: if {[fanout_of $my_net] > 7} {lappend hifan_nets $my_net}

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

proc fanout_of {net_name} {

  return [expr [sizeof_collection [all_connected $net_name]] -1]

}

 

 

 

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

# Creates collection of cells with given reference name 

#

# Example:

# if {[get_refcells TLATX2] != ""} {

#   echo "Found latches TLATX2 with instance names:"

#   echo [c2l [get_refcells TLATX2]]

# }

#

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

proc get_refcells {ref_name} {

  get_cells * -filter "@ref_name == $ref_name"

}

 

 

 

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

# Disconnects pin with given name

# The only command dc_compiler has for disconnection is 

# "disconnect_net". However, it is not enough to be handy.

# Command returns collection which contains disconnected net

#

# Examples:

# disconnect_pin U123/A

# connect_net [disconnect_pin $pin] [get_pins $new_pin]

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

proc disconnect_pin {pin_name} {

  set conn_net [all_connected [get_pins $pin_name]]

  disconnect_net $conn_net [get_pins $pin_name]

  return $conn_net

}

 

 

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

# Disconnects port with given name

# The only command dc_compiler has for disconnection is 

# "disconnect_net". However, it is not enough to be handy.

# Command returns collection which contains disconnected net

#

# Examples:

# disconnect_port JTAG_TDI

# connect_net [disconnect_port $WRONG_PORT] [get_ports $RIGHT_PORT]

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

proc disconnect_port {port_name} {

  set conn_net [all_connected [get_ports $port_name]]

  disconnect_net $conn_net [get_ports $port_name]

  return $conn_net

}

 

 

 

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

# Renames already exisiting net

# Synopsis:  rename_net <net_name> <new_net_name>

#

# Example: rename_net N762 REGBUS_EN

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

proc rename_net {name new_name} {

  set all_conn [all_connected $name]

  remove_net $name

  create_net $new_name

  connect_net $new_name $all_conn

}

 

 

 

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

# Renames already exisiting cell

# Synopsis:  rename_cell <cell_name> <new_cell_name>

#

# Example: rename_cell U125 MY_AND

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

proc rename_cell {name new_name} {

  create_cell $new_name [refname_of $name]

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

  foreach pin $pins {

    regsub $name $pin $new_name new_pin

    connect_net [disconnect_pin $pin] [get_pins $new_pin]

  }

  remove_cell [get_cells $name]

}

 

 

 

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

# Renames already exisiting port

# Synopsis:  rename_port <port_name> <new_port_name>

#

# Example: rename_port wb_clk_i master_clk

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

proc rename_port {name new_name} {

  create_port $new_name -direction [get_port_dir $name]

  connect_net [disconnect_port $name] [get_ports $new_name]

  remove_port [get_ports $name]

}

 

 

 

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

# Rebinds given cell, replacing it with another cell with given

# reference name and original name

# Can be useful for STA fine tuning etc

# Synopsis:  rebind_cell <cell_name> <new_reference_name>

#

# Example: rebind_cell I235 slow/NAND2X8   - assuming that original

# reference cell of I235 was NAND2X4, increases power level of this cell

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

proc rebind_cell {name new_refname} {

  create_cell $name.tmp $new_refname

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

  foreach pin $pins {

    regsub $name $pin $name.tmp new_pin

    connect_net [disconnect_pin $pin] [get_pins $new_pin]

  }

  remove_cell [get_cells $name]

  rename_cell $name.tmp $name

}

 

 

 

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

# Returns list of disconnected pins in current design.

# Useful for design connectivity checks

# No command line arguments.

#

# Example:

# foreach pin [get_disc_pins] {echo "Disconnected pin: $pin"}

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

proc get_disc_pins {} {

  set ret_list ""

  foreach_in_collection pin [get_pins */*] {

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

      lappend ret_list [c2l $pin]

    }

  }

  return $ret_list

}

 

 

 

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

# Returns list of disconnected ports in current design.

# Useful for design connectivity checks

# No command line arguments.

#

# Example:

# foreach port [get_disc_ports] {echo "Disconnected port: $port"}

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

proc get_disc_ports {} {

  set ret_list ""

  foreach_in_collection port [get_ports *] {

    if {[c2l [all_connected $port]] == ""} {

      lappend ret_list [c2l $port]

    }

  }

  return $ret_list

}

 

 

 

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

# Returns list of disconnected nets in current design.

# Here, the meaning of disconnected net is net without driver (or with 

# fanin equal to zero)

# Useful for design connectivity checks

# No command line arguments.

#

# Example:

# foreach net [get_disc_nets] {echo "Disconnected net: $net"}

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

proc get_disc_nets {} {

  set ret_list ""

  foreach_in_collection net [get_nets *] {

    if {[get_pins [all_connected $net] -filter "@pin_direction == out"] == ""} {

      if {[get_ports [all_connected $net] -filter "@port_direction == in"] == ""} {

        lappend ret_list [c2l $net]

      }

    }

  }

  return $ret_list

}

 

 

 

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

# Returns TCL list of net names with specified fanout number

# Useful for connectivity & STA checks

#

#

# Example:

# set fanout 5

# set nets_exist true

# while {$nets_exist} {

#   set nets [get_nets_by_fanout $fanout]

#   if {$nets != ""} {

#     echo "\n Found nets $nets with fanout $fanout"

#     incr fanout

#   } else {

#     set nets_exist false

#   }

# }

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

proc get_nets_by_fanout {fanout} {

  set ret_list ""

  foreach_in_collection net [get_nets *] {

    if {[sizeof_collection [all_connected [get_nets $net]]] == [expr $fanout + 1]} {

       lappend ret_list [c2l $net]

    }

  }

  return $ret_list

}