OpenSTA/tcl/CmdArgs.tcl

1054 lines
29 KiB
Tcl
Raw Normal View History

2018-09-28 17:54:21 +02:00
# OpenSTA, Static Timing Analyzer
# Copyright (c) 2025, Parallax Software, Inc.
2018-09-28 17:54:21 +02:00
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2018-09-28 17:54:21 +02:00
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software.
#
# Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
#
# This notice may not be removed or altered from any source distribution.
2018-09-28 17:54:21 +02:00
################################################################
#
# Command helper functions.
#
################################################################
namespace eval sta {
#################################################################
#
# Argument parsing functions.
#
################################################################
# Parse multiple object type args.
# For object name args the search order is as follows:
# clk
# liberty_cell
# liberty_port
# cell
# inst
# port
# pin
# net
proc get_object_args { objects clks_var libcells_var libports_var \
cells_var insts_var ports_var pins_var nets_var \
edges_var timing_arc_sets_var } {
2018-09-28 17:54:21 +02:00
if { $clks_var != {} } {
upvar 1 $clks_var clks
}
if { $libcells_var != {} } {
upvar 1 $libcells_var libcells
}
if { $libports_var != {} } {
upvar 1 $libports_var libports
}
if { $cells_var != {} } {
upvar 1 $cells_var cells
}
if { $insts_var != {} } {
upvar 1 $insts_var insts
}
if { $ports_var != {} } {
upvar 1 $ports_var ports
}
if { $pins_var != {} } {
upvar 1 $pins_var pins
}
if { $nets_var != {} } {
upvar 1 $nets_var nets
}
if { $edges_var != {} } {
upvar 1 $edges_var edges
}
if { $timing_arc_sets_var != {} } {
upvar 1 $timing_arc_sets_var timing_arc_sets
}
# Copy backslashes that will be removed by foreach.
set objects [string map {\\ \\\\} $objects]
foreach obj $objects {
if { [llength $obj] > 1 } {
# List arg. Recursive call without initing objects.
get_object_args $obj $clks_var $libcells_var $libports_var $cells_var $insts_var \
$ports_var $pins_var $nets_var $edges_var $timing_arc_sets_var
2018-09-28 17:54:21 +02:00
} elseif { [is_object $obj] } {
# Explicit object arg.
set object_type [object_type $obj]
if { $pins_var != {} && $object_type == "Pin" } {
lappend pins $obj
2018-09-28 17:54:21 +02:00
} elseif { $insts_var != {} && $object_type == "Instance" } {
lappend insts $obj
2018-09-28 17:54:21 +02:00
} elseif { $nets_var != {} && $object_type == "Net" } {
lappend nets $obj
2018-09-28 17:54:21 +02:00
} elseif { $ports_var != {} && $object_type == "Port" } {
lappend ports $obj
2018-09-28 17:54:21 +02:00
} elseif { $edges_var != {} && $object_type == "Edge" } {
lappend edges $obj
2018-09-28 17:54:21 +02:00
} elseif { $clks_var != {} && $object_type == "Clock" } {
lappend clks $obj
2018-09-28 17:54:21 +02:00
} elseif { $libcells_var != {} && $object_type == "LibertyCell" } {
lappend libcells $obj
2018-09-28 17:54:21 +02:00
} elseif { $libports_var != {} && $object_type == "LibertyPort" } {
lappend libports $obj
2018-09-28 17:54:21 +02:00
} elseif { $cells_var != {} && $object_type == "Cell" } {
lappend cells $obj
2018-09-28 17:54:21 +02:00
} elseif { $timing_arc_sets_var != {} \
&& $object_type == "TimingArcSet" } {
lappend timing_arc_sets $obj
2018-09-28 17:54:21 +02:00
} else {
sta_error 100 "unsupported object type $object_type."
2018-09-28 17:54:21 +02:00
}
} elseif { $obj != {} } {
# Check for implicit arg.
# Search for most general object type first.
set matches {}
if { $clks_var != {} } {
set matches [get_clocks -quiet $obj]
2018-09-28 17:54:21 +02:00
}
if { $matches != {} } {
set clks [concat $clks $matches]
2018-09-28 17:54:21 +02:00
} else {
if { $libcells_var != {} } {
set matches [get_lib_cells -quiet $obj]
}
if { $matches != {} } {
set libcells [concat $libcells $matches]
} else {
if { $libports_var != {} } {
set matches [get_lib_pins -quiet $obj]
}
if { $matches != {} } {
set libports [concat $libports $matches]
} else {
if { $cells_var != {} } {
set matches [find_cells_matching $obj 0 0]
}
if { $matches != {} } {
set cells [concat $cells $matches]
} else {
if { $insts_var != {} } {
set matches [get_cells -quiet $obj]
}
if { $matches != {} } {
set insts [concat $insts $matches]
} else {
if { $ports_var != {} } {
set matches [get_ports -quiet $obj]
}
if { $matches != {} } {
set ports [concat $ports $matches]
} else {
if { $pins_var != {} } {
set matches [get_pins -quiet $obj]
}
if { $matches != {} } {
set pins [concat $pins $matches]
} else {
if { $nets_var != {} } {
set matches [get_nets -quiet $obj]
}
if { $matches != {} } {
set nets [concat $nets $matches]
} else {
sta_warn 101 "object '$obj' not found."
}
}
}
}
}
}
}
2018-09-28 17:54:21 +02:00
}
}
}
}
proc parse_clk_cell_port_args { objects clks_var cells_var ports_var } {
upvar 1 $clks_var clks
upvar 1 $cells_var cells
upvar 1 $ports_var ports
set clks {}
set cells {}
set ports {}
get_object_args $objects clks {} {} cells {} ports {} {} {} {}
}
proc parse_clk_cell_port_pin_args { objects clks_var cells_var ports_var \
pins_arg } {
2018-09-28 17:54:21 +02:00
upvar 1 $clks_var clks
upvar 1 $cells_var cells
upvar 1 $ports_var ports
upvar 1 $pins_arg pins
set clks {}
set cells {}
set ports {}
set pins {}
get_object_args $objects clks {} {} cells {} ports pins {} {} {}
}
proc parse_clk_inst_pin_arg { objects clks_var insts_var pins_var } {
upvar 1 $clks_var clks
upvar 1 $insts_var insts
upvar 1 $pins_var pins
set clks {}
set insts {}
set pins {}
get_object_args $objects clks {} {} {} insts {} pins {} {} {}
}
proc parse_clk_inst_port_pin_arg { objects clks_var insts_var pins_var } {
upvar 1 $clks_var clks
upvar 1 $insts_var insts
upvar 1 $pins_var pins
set clks {}
set insts {}
set pins {}
set ports {}
get_object_args $objects clks {} {} {} insts ports pins {} {} {}
foreach port $ports {
2019-01-17 00:37:31 +01:00
lappend pins [[top_instance] find_pin [get_name $port]]
2018-09-28 17:54:21 +02:00
}
}
proc parse_clk_port_pin_arg { objects clks_var pins_var } {
upvar 1 $clks_var clks
upvar 1 $pins_var pins
set clks {}
set pins {}
set ports {}
get_object_args $objects clks {} {} {} {} ports pins {} {} {}
foreach port $ports {
2019-01-17 00:37:31 +01:00
lappend pins [[top_instance] find_pin [get_name $port]]
2018-09-28 17:54:21 +02:00
}
}
proc parse_libcell_libport_inst_port_pin_edge_timing_arc_set_arg { objects \
libcells_var \
libports_var \
insts_var \
ports_var \
pins_var \
edges_var \
timing_arc_sets_var } {
2018-09-28 17:54:21 +02:00
upvar 1 $libcells_var libcells
upvar 1 $libports_var libports
upvar 1 $insts_var insts
upvar 1 $ports_var ports
upvar 1 $pins_var pins
upvar 1 $edges_var edges
upvar 1 $timing_arc_sets_var timing_arc_sets
set libcells {}
set libports {}
set insts {}
set ports {}
set pins {}
set edges {}
set timing_arc_sets {}
get_object_args $objects {} libcells libports {} insts ports pins {} \
edges timing_arc_sets
}
2020-07-15 16:56:34 +02:00
proc parse_libcell_arg { objects } {
set libcells {}
get_object_args $objects {} libcells {} {} {} {} {} {} {} {}
return $libcells
}
2018-09-28 17:54:21 +02:00
proc parse_libcell_inst_arg { objects libcells_var insts_var } {
upvar 1 $libcells_var libcells
upvar 1 $insts_var insts
set libcells {}
set insts {}
get_object_args $objects {} libcells {} {} insts {} {} {} {} {}
}
proc parse_libcell_inst_net_arg { objects libcells_var insts_var nets_var } {
upvar 1 $libcells_var libcells
upvar 1 $insts_var insts
upvar 1 $nets_var nets
set libcells {}
set insts {}
set nets {}
get_object_args $objects {} libcells {} {} insts {} {} nets {} {}
}
proc parse_cell_arg { objects } {
set cells {}
get_object_args $objects {} {} {} cells {} {} {} {} {} {}
return $cells
}
2018-09-28 17:54:21 +02:00
proc parse_cell_port_args { objects cells_var ports_var } {
upvar 1 $cells_var cells
upvar 1 $ports_var ports
set cells {}
set ports {}
get_object_args $objects {} {} {} cells {} ports {} {} {} {}
}
proc parse_cell_port_pin_args { objects cells_var ports_var pins_var } {
upvar 1 $cells_var cells
upvar 1 $ports_var ports
upvar 1 $pins_var pins
set cells {}
set ports {}
set pins {}
get_object_args $objects {} {} {} cells {} ports pins {} {} {}
}
proc parse_inst_port_pin_arg { objects insts_var pins_var } {
upvar 1 $insts_var insts
upvar 1 $pins_var pins
set insts {}
set pins {}
set ports {}
get_object_args $objects {} {} {} {} insts ports pins {} {} {}
foreach port $ports {
2019-01-17 00:37:31 +01:00
lappend pins [[top_instance] find_pin [get_name $port]]
2018-09-28 17:54:21 +02:00
}
}
proc parse_inst_pin_arg { objects insts_var pins_var } {
upvar 1 $insts_var insts
upvar 1 $pins_var pins
set insts {}
set pins {}
get_object_args $objects {} {} {} {} insts {} pins {} {} {}
}
proc parse_inst_port_pin_net_arg { objects insts_var pins_var nets_var } {
upvar 1 $insts_var insts
upvar 1 $pins_var pins
upvar 1 $nets_var nets
set insts {}
set ports {}
set pins {}
set nets {}
get_object_args $objects {} {} {} {} insts ports pins nets {} {}
foreach port $ports {
2019-01-17 00:37:31 +01:00
lappend pins [[top_instance] find_pin [get_name $port]]
2018-09-28 17:54:21 +02:00
}
}
proc parse_inst_net_arg { objects insts_var nets_var } {
upvar 1 $insts_var insts
upvar 1 $nets_var nets
set insts {}
set nets {}
get_object_args $objects {} {} {} {} insts {} {} nets {} {}
}
proc parse_port_pin_net_arg { objects pins_var nets_var } {
upvar 1 $pins_var pins
upvar 1 $nets_var nets
set ports {}
set pins {}
set nets {}
get_object_args $objects {} {} {} {} {} ports pins nets {} {}
2019-01-17 00:37:31 +01:00
2018-09-28 17:54:21 +02:00
foreach port $ports {
2019-01-17 00:37:31 +01:00
lappend pins [[top_instance] find_pin [get_name $port]]
2018-09-28 17:54:21 +02:00
}
}
proc parse_port_net_args { objects ports_var nets_var } {
upvar 1 $ports_var ports
upvar 1 $nets_var nets
set ports {}
set nets {}
get_object_args $objects {} {} {} {} {} ports {} nets {} {}
}
proc parse_pin_net_args { objects pins_var nets_var } {
upvar 1 $pins_var pins
upvar 1 $nets_var nets
set pins {}
set nets {}
get_object_args $objects {} {} {} {} {} {} pins nets {} {}
}
proc get_ports_or_pins { pattern } {
set matches [find_port_pins_matching $pattern 0 0]
if { $matches != {} } {
return $matches
} else {
return [find_pins_matching $pattern 0 0]
}
}
################################################################
# -scene keyword is optional.
# If -scene keyword is missing:
# one scene: return default
# multiple scenes: error
proc parse_scene { keys_var } {
2018-09-28 17:54:21 +02:00
upvar 1 $keys_var keys
set scene_arg ""
# compabibility 05/29/2025
2018-09-28 17:54:21 +02:00
if { [info exists keys(-corner)] } {
set scene_arg $keys(-corner)
}
if { [info exists keys(-scene)] } {
set scene_arg $keys(-scene)
}
if { $scene_arg != "" } {
if { [is_object $scene_arg] } {
set object_type [object_type $scene_arg]
if { $object_type == "Scene" } {
return $scene_arg
} else {
sta_error 144 "scene object type '$object_type' is not a scene."
}
2018-09-28 17:54:21 +02:00
} else {
set scene [find_scene $scene_arg]
if { $scene == "NULL" } {
sta_error 102 "$scene_arg is not the name of a scene."
} else {
return $scene
}
2018-09-28 17:54:21 +02:00
}
} elseif { [multi_scene] } {
sta_error 103 "-scene keyword required with multi-scene analysis."
2018-09-28 17:54:21 +02:00
} else {
return [cmd_scene]
2018-09-28 17:54:21 +02:00
}
}
# -scene keyword is required.
proc parse_scene_required { keys_var } {
2018-12-05 23:18:41 +01:00
upvar 1 $keys_var keys
set scene_name ""
if { [info exists keys(-scene)] } {
set scene_name $keys(-scene)
}
# compabibility 05/29/2025
2018-12-05 23:18:41 +01:00
if { [info exists keys(-corner)] } {
set scene_name $keys(-corner)
}
if { $scene_name != "" } {
set scene [find_scene $scene_name]
if { $scene == "NULL" } {
sta_error 104 "$scene_name is not the name of a scene."
2018-12-05 23:18:41 +01:00
} else {
return $scene
2018-12-05 23:18:41 +01:00
}
} else {
sta_error 105 "missing -scene arg."
2018-12-05 23:18:41 +01:00
}
}
proc parse_scene_or_default { keys_var } {
2018-11-26 18:15:52 +01:00
upvar 1 $keys_var keys
set scene_name ""
if { [info exists keys(-scene)] } {
set scene_name $keys(-scene)
}
# compabibility 05/29/2025
2018-11-26 18:15:52 +01:00
if { [info exists keys(-corner)] } {
set scene_name $keys(-corner)
}
if { $scene_name != "" } {
set scene [find_scene $scene_name]
if { $scene == "NULL" } {
sta_error 106 "$scene_name is not the name of a scene."
2018-11-26 18:15:52 +01:00
} else {
return $scene
2018-11-26 18:15:52 +01:00
}
} else {
return [cmd_scene]
2018-11-26 18:15:52 +01:00
}
}
# If -scene/-corner return scene, else return NULL.
proc parse_scene_or_null { keys_var } {
2018-09-28 17:54:21 +02:00
upvar 1 $keys_var keys
set scene_name ""
if { [info exists keys(-scene)] } {
set scene_name $keys(-scene)
}
# compabibility 05/29/2025
2018-09-28 17:54:21 +02:00
if { [info exists keys(-corner)] } {
set scene_name $keys(-corner)
}
if { $scene_name != "" } {
set scene [find_scene $scene_name]
if { $scene == "NULL" } {
sta_error 107 "$scene_name is not the name of a scene."
2018-09-28 17:54:21 +02:00
} else {
return $scene
2018-09-28 17:54:21 +02:00
}
} else {
return "NULL"
}
}
# If -scenes/-corner return scenes, else return default scene.
proc parse_scenes_or_default { keys_var } {
upvar 1 $keys_var keys
if { [info exists keys(-scenes)] } {
return [find_scenes $keys(-scenes)]
} elseif { [info exists keys(-corner)] } {
# compabibility 05/29/2025
return [find_scenes $keys(-corner)]
} else {
return [cmd_scene]
}
}
# If -scenes/-corner return scenes, else return all scenes.
proc parse_scenes_or_all { keys_var } {
upvar 1 $keys_var keys
if { [info exists keys(-scenes)] } {
return [find_scenes $keys(-scenes)]
} elseif { [info exists keys(-corner)] } {
# compabibility 05/29/2025
return [find_scenes $keys(-corner)]
} else {
return [scenes]
}
}
proc find_scenes { scene_names } {
set scenes {}
foreach scene_name $scene_names {
set scene [find_scene $scene_name]
if { $scene == "NULL" } {
sta_error 134 "$scene_name is not the name of a scene."
} else {
lappend scenes $scene
}
}
return $scenes
}
2018-09-28 17:54:21 +02:00
################################################################
proc parse_rise_fall_flags { flags_var } {
upvar 1 $flags_var flags
if { [info exists flags(-rise)] && ![info exists flags(-fall)] } {
return "rise"
} elseif { [info exists flags(-fall)] && ![info exists flags(-rise)] } {
return "fall"
} else {
return "rise_fall"
}
}
ccs ceff delay calc commit 87130be63ddbf1a7fb65986b02839eb4c0b13168 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Feb 27 09:49:02 2024 -0700 ccs ceff delay calc Signed-off-by: James Cherry <cherry@parallaxsw.com> commit de0dd38dabda2f7ef51b49c196c2787a0d3c5784 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Feb 27 07:40:11 2024 -0700 dcalc public funcs Signed-off-by: James Cherry <cherry@parallaxsw.com> commit dd7fcb12f929b9b0a391653cad42e617f9cbdd3b Author: James Cherry <cherry@parallaxsw.com> Date: Mon Feb 26 09:08:37 2024 -0700 mv CircuitSim.hh to include Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9663e46d28ece544ee1453f229990c9db9e0efec Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 25 17:58:57 2024 -0700 ArcDcalcArg Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 76b0588034faaefd2302c865c441975f76386d3f Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 25 15:36:46 2024 -0700 ensureVoltageWaveforms Signed-off-by: James Cherry <cherry@parallaxsw.com> commit f88e67b861c56752e5b36efe2b552ba0077a7180 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 25 15:00:02 2024 -0700 const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 8f32cc571dcadee0185b08f951a1f79d46e7984d Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 25 14:57:51 2024 -0700 Graph::gateEdgeArc Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ac3cb35cb6732d7ecbf0532d7351a3ff2a917fc9 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 25 14:31:30 2024 -0700 ConcreteParasiticSubNodeMap, ConcreteParasiticPinNodeMap use id cmp Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cbfe4eac463036c26a64701239d7651d91a09778 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 25 14:08:41 2024 -0700 WriteSpice Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 8b5d30f1a8b1ccb8c9cbd9d7ba93418907c41b2a Author: James Cherry <cherry@parallaxsw.com> Date: Sat Feb 24 09:45:46 2024 -0700 emplace_push Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5335a2eaaf737ed7c7a8cff30654a68c4ac4c8e4 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Feb 23 16:19:30 2024 -0700 Parasitics::findParasiticNode Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ce92f3caf28afb0e0384799f08166cfb0aecfea0 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Feb 23 15:53:28 2024 -0700 Parasitics::findParasiticNode Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 0c591430c725a3ebd50d2892673dca76e023dc32 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Feb 23 09:03:18 2024 -0700 Parsitics::name(node) const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 499c297e64d1487388f549843ff9ea05e8555cfc Author: James Cherry <cherry@parallaxsw.com> Date: Fri Feb 23 09:03:07 2024 -0700 write_spice umr Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 6984c398dbce9e6266fab8377a844bc518481d9d Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 22 18:42:34 2024 -0700 gcc warning Signed-off-by: James Cherry <cherry@parallaxsw.com> commit edec16519806013623194d8201e804dec81a51dd Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 22 17:54:11 2024 -0700 no cuddification Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 4a0e1070c179b2f8615b604c362359ce4b3a0e2e Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 22 17:29:46 2024 -0700 sim const Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 2e941fafa631f6b9bc0f82784b9146de2449e9c5 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 22 17:29:39 2024 -0700 sdc comment Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 1c12f56aee7115fcb06807b5b6c626d1a419ccdc Author: James Cherry <cherry@parallaxsw.com> Date: Wed Feb 21 13:13:29 2024 -0700 Sim use Bdd class Signed-off-by: James Cherry <cherry@parallaxsw.com> commit b70c41d5caec56c3001b834141b6dab89bb933ed Author: James Cherry <cherry@parallaxsw.com> Date: Tue Feb 20 12:18:27 2024 -0700 write_spice coupling caps Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 614d2cd41a1a9cf850dbe480954a5f58ee0dc21e Author: James Cherry <cherry@parallaxsw.com> Date: Mon Feb 19 14:37:30 2024 -0700 write_spice time offset Signed-off-by: James Cherry <cherry@parallaxsw.com> commit f0ba1fca0dfca384e6fb0be302bba9ced71ee41c Author: James Cherry <cherry@parallaxsw.com> Date: Mon Feb 19 10:59:18 2024 -0700 class Bdd for cudd Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 24c94756334fce5e70e97ce0ee31375ae4e59b84 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 18 08:58:30 2024 -0700 WriteSpice Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 47a4505d88bdfe4a85056895f8b7d842e07dce8d Author: James Cherry <cherry@parallaxsw.com> Date: Fri Feb 16 21:34:23 2024 -0700 default sim ngspice Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 06e279555a076e218f0a9c308e8937a6fc8fdea4 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Feb 16 21:34:01 2024 -0700 WriteSpice refactor Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 06e3f0734edbbbd69ad063e97d1d8cca92a83aea Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 15 15:18:35 2024 -0700 mv report_dcalc to DelayCalc.tcl Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 922056471a6d380699bbd0623f95637401d23eff Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 15 14:27:31 2024 -0700 WriteSpice::cell_spice_port_names_ Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 732922ead68097e3f7da268ecc5ae2ca2daa4492 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 15 13:35:13 2024 -0700 WritePathSpice.hh Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 8cd6e2ffc6ad66e831630273b5eacd192259191e Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 15 10:11:39 2024 -0700 small Signed-off-by: James Cherry <cherry@parallaxsw.com> commit f7f6bfb49f43ddc3e45c294f89c8814d60df5220 Author: James Cherry <cherry@parallaxsw.com> Date: Thu Feb 15 09:48:09 2024 -0700 refactor WritePathSpice Signed-off-by: James Cherry <cherry@parallaxsw.com> commit f74db730c3e8c67a24d531266510e4376db463d3 Author: James Cherry <cherry@parallaxsw.com> Date: Wed Feb 14 09:22:01 2024 -0700 Sta.hh Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 051532deef203cae97e32e8af7a2348bfd8912cc Author: James Cherry <cherry@parallaxsw.com> Date: Wed Feb 14 08:14:44 2024 -0700 PowerClass.hh Signed-off-by: James Cherry <cherry@parallaxsw.com> commit bfb8357d1093e5d3da14e708acd21fc21ba3b0dd Author: James Cherry <cherry@parallaxsw.com> Date: Wed Feb 14 08:08:56 2024 -0700 doc Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 8fe28ec91b234d9d8210019aa46a2e8107aa497a Author: James Cherry <cherry@parallaxsw.com> Date: Wed Feb 14 07:32:34 2024 -0700 ClkSkew use seq instead of set Signed-off-by: James Cherry <cherry@parallaxsw.com> commit c4e3a3a0315ab4f6160a707e838423bb734f5363 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Feb 13 19:26:45 2024 -0700 report_clock_latency Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 51fb6657d9706c7443e1c269cfe63cf080b05d50 Author: James Cherry <cherry@parallaxsw.com> Date: Tue Feb 13 11:10:11 2024 -0700 report_clock_latency Signed-off-by: James Cherry <cherry@parallaxsw.com> commit e639ee129d13e1c11b34bca0762b8136b18563f3 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Feb 12 11:19:06 2024 -0700 ClkSkew use map Signed-off-by: James Cherry <cherry@parallaxsw.com> commit e91d3ea8142a73b7b607dfdf53b3fce8e2f16984 Author: James Cherry <cherry@parallaxsw.com> Date: Mon Feb 12 10:18:27 2024 -0700 report_clock_skew report format Signed-off-by: James Cherry <cherry@parallaxsw.com> commit c650b7ec63b83382ba9cec7d187ffee8a031c2ce Author: James Cherry <cherry@parallaxsw.com> Date: Mon Feb 12 09:22:29 2024 -0700 report_clock_skew include macro clock_tree_path_delay Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cf14b230a9944b95ba43ef7c09e553d9014990eb Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 11 11:03:29 2024 -0700 clk skew range iter Signed-off-by: James Cherry <cherry@parallaxsw.com> commit e7e0342e063ac876d00d03fd1ff0eab1715cfde4 Author: James Cherry <cherry@parallaxsw.com> Date: Sun Feb 11 08:11:29 2024 -0700 write_spice sensitize and3 Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 743ceb676c763ac5bcbf05e630a4da1b507c537d Author: James Cherry <cherry@parallaxsw.com> Date: Sat Feb 10 18:07:04 2024 -0700 write spice Signed-off-by: James Cherry <cherry@parallaxsw.com> Signed-off-by: James Cherry <cherry@parallaxsw.com>
2024-02-27 18:00:48 +01:00
proc parse_rise_fall_arg { arg } {
if { $arg eq "r" || $arg eq "^" || $arg eq "rise" } {
return "rise"
} elseif { $arg eq "f" || $arg eq "v" || $arg eq "fall" } {
return "fall"
} else {
error "unknown rise/fall transition name."
}
}
2018-09-28 17:54:21 +02:00
proc parse_min_max_flags { flags_var } {
upvar 1 $flags_var flags
if { [info exists flags(-min)] && [info exists flags(-max)] } {
sta_error 108 "both -min and -max specified."
2018-09-28 17:54:21 +02:00
} elseif { [info exists flags(-min)] && ![info exists flags(-max)] } {
return "min"
} elseif { [info exists flags(-max)] && ![info exists flags(-min)] } {
return "max"
} else {
# Default.
return "max"
}
}
proc parse_min_max_all_flags { flags_var } {
upvar 1 $flags_var flags
if { [info exists flags(-min)] && [info exists flags(-max)] } {
sta_error 109 "both -min and -max specified."
2018-09-28 17:54:21 +02:00
} elseif { [info exists flags(-min)] && ![info exists flags(-max)] } {
return "min"
} elseif { [info exists flags(-max)] && ![info exists flags(-min)] } {
return "max"
} else {
return "min_max"
2018-09-28 17:54:21 +02:00
}
}
# parse_min_max_all_flags and require analysis type to be min/max.
proc parse_min_max_all_check_flags { flags_var } {
upvar 1 $flags_var flags
if { [info exists flags(-min)] && [info exists flags(-max)] } {
return "min_max"
2018-09-28 17:54:21 +02:00
} elseif { [info exists flags(-min)] && ![info exists flags(-max)] } {
return "min"
} elseif { [info exists flags(-max)] && ![info exists flags(-min)] } {
return "max"
} else {
return "min_max"
2018-09-28 17:54:21 +02:00
}
}
proc parse_early_late_flags { flags_var } {
upvar 1 $flags_var flags
if { [info exists flags(-early)] && [info exists flags(-late)] } {
sta_error 110 "only one of -early and -late can be specified."
2018-09-28 17:54:21 +02:00
} elseif { [info exists flags(-early)] } {
return "min"
} elseif { [info exists flags(-late)] } {
return "max"
} else {
sta_error 111 "-early or -late must be specified."
2018-09-28 17:54:21 +02:00
}
}
proc parse_early_late_all_flags { flags_var } {
upvar 1 $flags_var flags
if { [info exists flags(-early)] && [info exists flags(-late)] } {
sta_error 112 "both -early and -late specified."
2018-09-28 17:54:21 +02:00
} elseif { [info exists flags(-early)] && ![info exists flags(-late)] } {
return "min"
} elseif { [info exists flags(-late)] && ![info exists flags(-early)] } {
return "max"
} else {
return "min_max"
2018-09-28 17:54:21 +02:00
}
}
################################################################
proc get_liberty_error { arg_name arg } {
set lib "NULL"
if {[llength $arg] > 1} {
sta_error 113 "$arg_name must be a single library."
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "LibertyLibrary" } {
set lib $arg
} else {
sta_error 114 "$arg_name type '$object_type' is not a library."
2018-09-28 17:54:21 +02:00
}
} else {
set lib [find_liberty $arg]
if { $lib == "NULL" } {
sta_error 115 "library '$arg' not found."
2018-09-28 17:54:21 +02:00
}
}
return $lib
}
proc get_lib_cell_warn { arg_name arg } {
2019-06-13 17:43:38 +02:00
return [get_lib_cell_arg $arg_name $arg sta_warn]
}
proc get_lib_cell_error { arg_name arg } {
return [get_lib_cell_arg $arg_name $arg sta_error]
}
proc get_lib_cell_arg { arg_name arg error_proc } {
2018-09-28 17:54:21 +02:00
set lib_cell "NULL"
if { [llength $arg] > 1 } {
sta_error 116 "$arg_name must be a single lib cell."
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "LibertyCell" } {
set lib_cell $arg
} else {
$error_proc 116 "$arg_name type '$object_type' is not a liberty cell."
2018-09-28 17:54:21 +02:00
}
# Parse library_name/cell_name.
} elseif {[regexp [cell_regexp] $arg ignore lib_name cell_name]} {
set library [find_liberty $lib_name]
if { $library != "NULL" } {
set lib_cell [$library find_liberty_cell $cell_name]
if { $lib_cell == "NULL" } {
$error_proc 117 "liberty cell '$arg' not found."
2018-09-28 17:54:21 +02:00
}
} else {
$error_proc 118 "library '$lib_name' not found."
2018-09-28 17:54:21 +02:00
}
} else {
set lib_cell [find_liberty_cell $arg]
if { $lib_cell == "NULL" } {
$error_proc 119 "liberty cell '$arg' not found."
2018-09-28 17:54:21 +02:00
}
}
return $lib_cell
}
# Not used by OpenSTA
2020-04-26 17:49:09 +02:00
proc get_lib_cells_arg { arg_name arglist error_proc } {
set lib_cells {}
# Copy backslashes that will be removed by foreach.
set arglist [string map {\\ \\\\} $arglist]
foreach arg $arglist {
if {[llength $arg] > 1} {
# Embedded list.
set lib_cells [concat $lib_cells [get_lib_cells_arg $arg_name $arg $error_proc]]
2020-04-26 17:49:09 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "LibertyCell" } {
lappend lib_cells $arg
2020-04-26 17:49:09 +02:00
} else {
$error_proc 120 "unsupported object type $object_type."
2020-04-26 17:49:09 +02:00
}
} elseif { $arg != {} } {
set arg_lib_cells [get_lib_cells1 $arg $error_proc]
2020-04-26 17:49:09 +02:00
if { $arg_lib_cells != {} } {
set lib_cells [concat $lib_cells $arg_lib_cells]
2020-04-26 17:49:09 +02:00
}
}
}
return $lib_cells
}
# Based on get_lib_cells
proc get_lib_cells1 { patterns error_proc } {
global hierarchy_separator
set cells {}
set cell_regexp [cell_regexp_hsc $hierarchy_separator]
foreach pattern $patterns {
if { ![regexp $cell_regexp $pattern ignore lib_name cell_pattern]} {
set lib_name "*"
set cell_pattern $pattern
}
# Allow wildcards in the library name (incompatible).
set libs [get_libs -quiet $lib_name]
if { $libs == {} } {
$error_proc 121 "library '$lib_name' not found."
} else {
foreach lib $libs {
set matches [$lib find_liberty_cells_matching $cell_pattern 0 0]
if {$matches != {}} {
set cells [concat $cells $matches]
}
}
if { $cells == {} } {
$error_proc 122 "cell '$cell_pattern' not found."
}
}
}
return $cells
}
2018-09-28 17:54:21 +02:00
proc get_instance_error { arg_name arg } {
set inst "NULL"
if {[llength $arg] > 1} {
sta_error 123 "$arg_name must be a single instance."
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Instance" } {
2019-06-02 03:41:09 +02:00
set inst $arg
2018-09-28 17:54:21 +02:00
} else {
sta_error 124 "$arg_name type '$object_type' is not an instance."
2018-09-28 17:54:21 +02:00
}
} else {
set inst [find_instance $arg]
if { $inst == "NULL" } {
sta_error 125 "instance '$arg' not found."
2018-09-28 17:54:21 +02:00
}
}
return $inst
}
proc get_instances_error { arg_name arglist } {
set insts {}
# Copy backslashes that will be removed by foreach.
set arglist [string map {\\ \\\\} $arglist]
foreach arg $arglist {
if {[llength $arg] > 1} {
# Embedded list.
set insts [concat $insts [get_instances_error $arg_name $arg]]
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Instance" } {
lappend insts $arg
2018-09-28 17:54:21 +02:00
} else {
sta_error 126 "$arg_name type '$object_type' is not an instance."
2018-09-28 17:54:21 +02:00
}
} elseif { $arg != {} } {
set arg_insts [get_cells -quiet $arg]
if { $arg_insts != {} } {
set insts [concat $insts $arg_insts]
2018-09-28 17:54:21 +02:00
} else {
sta_error 127 "instance '$arg' not found."
2018-09-28 17:54:21 +02:00
}
}
}
return $insts
}
proc get_libcells_error { arg_name arglist } {
set libcells {}
# Copy backslashes that will be removed by foreach.
set arglist [string map {\\ \\\\} $arglist]
foreach arg $arglist {
if {[llength $arg] > 1} {
# Embedded list.
set libcells [concat $libcells [get_libcells_error $arg_name $arg]]
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "LibertyCell" } {
lappend libcells $arg
} else {
sta_error 128 "$arg_name type '$object_type' is not a liberty cell."
}
} elseif { $arg != {} } {
set arg_libcells [get_lib_cells -quiet $arg]
if { $arg_libcells != {} } {
set libcells [concat $libcells $arg_libcells]
} else {
sta_error 129 "liberty cell '$arg' not found."
}
}
}
return $libcells
}
2018-09-28 17:54:21 +02:00
proc get_port_pin_warn { arg_name arg } {
return [get_port_pin_arg $arg_name $arg "warn"]
}
proc get_port_pin_error { arg_name arg } {
return [get_port_pin_arg $arg_name $arg "error"]
}
proc get_port_pin_arg { arg_name arg warn_error } {
set pin "NULL"
if {[llength $arg] > 1} {
sta_warn_error 128 $warn_error "$arg_name must be a single port or pin."
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Pin" } {
set pin $arg
} elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin.
2019-01-17 00:37:31 +01:00
set pin [find_pin [get_name $arg]]
2018-09-28 17:54:21 +02:00
} else {
sta_warn_error 129 $warn_error "$arg_name type '$object_type' is not a pin or port."
2018-09-28 17:54:21 +02:00
}
} else {
set top_instance [top_instance]
set top_cell [$top_instance cell]
set port [$top_cell find_port $arg]
if { $port == "NULL" } {
set pin [find_pin $arg]
} else {
2019-01-17 00:37:31 +01:00
set pin [$top_instance find_pin [get_name $port]]
2018-09-28 17:54:21 +02:00
}
if { $pin == "NULL" } {
sta_warn_error 130 $warn_error "pin $arg not found."
2018-09-28 17:54:21 +02:00
}
}
return $pin
}
proc get_port_pins_error { arg_name arglist } {
set pins {}
# Copy backslashes that will be removed by foreach.
set arglilst [string map {\\ \\\\} $arglist]
foreach arg $arglist {
if {[llength $arg] > 1} {
# Embedded list.
set pins [concat $pins [get_port_pins_error $arg_name $arg]]
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Pin" } {
lappend pins $arg
2018-09-28 17:54:21 +02:00
} elseif { $object_type == "Port" } {
# Convert port to pin.
lappend pins [find_pin [get_name $arg]]
2018-09-28 17:54:21 +02:00
} else {
sta_error 131 "$arg_name type '$object_type' is not a pin or port."
2018-09-28 17:54:21 +02:00
}
} elseif { $arg != {} } {
set arg_pins [get_ports_or_pins $arg]
if { $arg_pins != {} } {
set pins [concat $pins $arg_pins]
2018-09-28 17:54:21 +02:00
} else {
sta_error 132 "pin '$arg' not found."
2018-09-28 17:54:21 +02:00
}
}
}
return $pins
}
proc get_ports_error { arg_name arglist } {
set ports {}
# Copy backslashes that will be removed by foreach.
set arglist [string map {\\ \\\\} $arglist]
foreach arg $arglist {
if {[llength $arg] > 1} {
# Embedded list.
set ports [concat $ports [get_ports_error $arg_name $arg]]
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Port" } {
lappend ports $arg
2018-09-28 17:54:21 +02:00
} else {
sta_error 133 "$arg_name type '$object_type' is not a port."
2018-09-28 17:54:21 +02:00
}
} elseif { $arg != {} } {
set arg_ports [get_ports $arg]
if { $arg_ports != {} } {
set ports [concat $ports $arg_ports]
2018-09-28 17:54:21 +02:00
}
}
}
return $ports
}
proc get_pin_error { arg_name arg } {
return [get_pin_arg $arg_name $arg "error"]
}
proc get_pin_warn { arg_name arg } {
return [get_pin_arg $arg_name $arg "warn"]
}
proc get_pin_arg { arg_name arg warn_error } {
set pin "NULL"
if {[llength $arg] > 1} {
sta_warn_error 134 $warn_error "$arg_name must be a single pin."
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Pin" } {
set pin $arg
} else {
sta_warn_error 135 $warn_error "$arg_name type '$object_type' is not a pin."
2018-09-28 17:54:21 +02:00
}
} else {
set pin [find_pin $arg]
if { $pin == "NULL" } {
sta_warn_error 136 $warn_error "$arg_name pin $arg not found."
2018-09-28 17:54:21 +02:00
}
}
return $pin
}
proc get_clock_warn { arg_name arg } {
return [get_clock_arg $arg_name $arg sta_warn]
}
proc get_clock_error { arg_name arg } {
return [get_clock_arg $arg_name $arg sta_error]
}
proc get_clock_arg { arg_name arg error_proc } {
set clk "NULL"
if {[llength $arg] > 1} {
$error_proc 137 "$arg_name arg must be a single clock, not a list."
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Clock" } {
set clk $arg
} else {
$error_proc 138 "$arg_name arg value is a $object_type, not a clock."
2018-09-28 17:54:21 +02:00
}
} elseif { $arg != {} } {
set clk [find_clock $arg]
if { $clk == "NULL" } {
$error_proc 138 "$arg_name arg '$arg' clock not found."
2018-09-28 17:54:21 +02:00
}
}
return $clk
}
proc get_clocks_warn { arg_name arglist } {
set clks {}
# Copy backslashes that will be removed by foreach.
set arglist [string map {\\ \\\\} $arglist]
foreach arg $arglist {
if {[llength $arg] > 1} {
# Embedded list.
set clks [concat $clks [get_clocks_warn $arg_name $arg]]
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Clock" } {
lappend clks $arg
2018-09-28 17:54:21 +02:00
} else {
sta_warn 139 "unsupported object type $object_type."
2018-09-28 17:54:21 +02:00
}
} elseif { $arg != {} } {
set arg_clocks [get_clocks $arg]
if { $arg_clocks != {} } {
set clks [concat $clks $arg_clocks]
2018-09-28 17:54:21 +02:00
}
}
}
return $clks
}
proc get_net_arg { arg_name arg } {
2018-09-28 17:54:21 +02:00
set net "NULL"
if {[llength $arg] > 1} {
sta_warn 140 "$arg_name must be a single net."
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Net" } {
set net $arg
} else {
sta_warn 141 "$arg_name '$object_type' is not a net."
2018-09-28 17:54:21 +02:00
}
} else {
set net [find_net $arg]
if { $net == "NULL" } {
sta_warn 143 "$arg_name '$arg' not found."
2018-09-28 17:54:21 +02:00
}
}
return $net
}
proc get_nets_arg { arg_name arglist } {
2018-09-28 17:54:21 +02:00
set nets {}
# Copy backslashes that will be removed by foreach.
set arglist [string map {\\ \\\\} $arglist]
foreach arg $arglist {
if {[llength $arg] > 1} {
# Embedded list.
set nets [concat $nets [get_nets_arg $arg_name $arg]]
2018-09-28 17:54:21 +02:00
} elseif { [is_object $arg] } {
set object_type [object_type $arg]
if { $object_type == "Net" } {
lappend nets $arg
2018-09-28 17:54:21 +02:00
} else {
sta_warn 142 "unsupported object type $object_type."
2018-09-28 17:54:21 +02:00
}
} elseif { $arg != {} } {
set arg_nets [get_nets $arg]
2018-09-28 17:54:21 +02:00
if { $arg_nets != {} } {
set nets [concat $nets $arg_nets]
2018-09-28 17:54:21 +02:00
}
}
}
return $nets
}
# sta namespace end.
}