diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index 707cc767..6b57282c 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -80,6 +80,20 @@ for compatibility in this current release. The read_parasitics command has been renamed read_spef and no longer supports the SPF format. +.... + +The make_net command now takes a single net name argument and returns +the net. + +The delete_instance command deletes a single instance instead of a list +of instances. + +The delete_net command deletes a single net instead of a list +of nets. + +The disconnect_pins command is renamed disconnect_pin and disconnects a +single pin. + Release 1.11.0 2017/08/18 ------------------------- diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index 363af13f..cf2d1fa6 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/network/ConcreteNetwork.cc b/network/ConcreteNetwork.cc index ac1e95d2..e6c81ced 100644 --- a/network/ConcreteNetwork.cc +++ b/network/ConcreteNetwork.cc @@ -1231,6 +1231,14 @@ ConcreteNetwork::makeTerm(Pin *pin, return reinterpret_cast(cterm); } +Pin * +ConcreteNetwork::connect(Instance *inst, + LibertyPort *port, + Net *net) +{ + return connect(inst, reinterpret_cast(port), net); +} + Pin * ConcreteNetwork::connect(Instance *inst, Port *port, diff --git a/network/ConcreteNetwork.hh b/network/ConcreteNetwork.hh index 80108f96..4eeb88fe 100644 --- a/network/ConcreteNetwork.hh +++ b/network/ConcreteNetwork.hh @@ -196,6 +196,9 @@ public: virtual Pin *connect(Instance *inst, Port *port, Net *net); + virtual Pin *connect(Instance *inst, + LibertyPort *port, + Net *net); virtual void disconnectPin(Pin *pin); virtual void deletePin(Pin *pin); virtual Net *makeNet(const char *name, diff --git a/network/Network.hh b/network/Network.hh index 681c32cd..a974d1c7 100644 --- a/network/Network.hh +++ b/network/Network.hh @@ -491,6 +491,9 @@ public: virtual Pin *connect(Instance *inst, Port *port, Net *net) = 0; + virtual Pin *connect(Instance *inst, + LibertyPort *port, + Net *net) = 0; // makePin/connectPin replaced by connect. virtual void connectPin(Pin *pin, Net *net) __attribute__ ((deprecated)); diff --git a/network/SdcNetwork.cc b/network/SdcNetwork.cc index 47f0ff55..9c942c69 100644 --- a/network/SdcNetwork.cc +++ b/network/SdcNetwork.cc @@ -943,6 +943,14 @@ NetworkNameAdapter::connect(Instance *inst, return network_edit_->connect(inst, port, net); } +Pin * +NetworkNameAdapter::connect(Instance *inst, + LibertyPort *port, + Net *net) +{ + return network_edit_->connect(inst, port, net); +} + void NetworkNameAdapter::disconnectPin(Pin *pin) { diff --git a/network/SdcNetwork.hh b/network/SdcNetwork.hh index 4e46f7f6..adfa89a5 100644 --- a/network/SdcNetwork.hh +++ b/network/SdcNetwork.hh @@ -130,6 +130,9 @@ public: virtual Pin *connect(Instance *inst, Port *port, Net *net); + virtual Pin *connect(Instance *inst, + LibertyPort *port, + Net *net); virtual void disconnectPin(Pin *pin); virtual void deleteNet(Net *net); virtual void deletePin(Pin *pin); diff --git a/search/Sta.cc b/search/Sta.cc index 96edce7a..381b92ad 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -3673,6 +3673,16 @@ Sta::connectPin(Instance *inst, connectPinAfter(pin); } +void +Sta::connectPin(Instance *inst, + LibertyPort *port, + Net *net) +{ + NetworkEdit *network = networkCmdEdit(); + Pin *pin = network->connect(inst, port, net); + connectPinAfter(pin); +} + void Sta::disconnectPin(Pin *pin) { @@ -3681,6 +3691,47 @@ Sta::disconnectPin(Pin *pin) network->disconnectPin(pin); } +void +Sta::insertBuffer(const char *buffer_name, + LibertyCell *buffer_cell, + Net *net, + PinSeq *load_pins, + const char *buffer_out_net_name) +{ + Instance *parent = network_->topInstance(); + LibertyPort *buffer_in_port = findCellPort(buffer_cell, PortDirection::input()); + LibertyPort *buffer_out_port = findCellPort(buffer_cell, PortDirection::output()); + if (buffer_in_port && buffer_out_port) { + Instance *buffer = makeInstance(buffer_name, buffer_cell, parent); + connectPin(buffer, buffer_in_port, net); + + Net *buffer_out_net = makeNet(buffer_out_net_name, parent); + connectPin(buffer, buffer_out_port, buffer_out_net); + + PinSeq::Iterator pin_iter(load_pins); + while (pin_iter.hasNext()) { + Pin *load_pin = pin_iter.next(); + auto load_inst = network_->instance(load_pin); + auto load_port = network_->port(load_pin); + disconnectPin(load_pin); + connectPin(load_inst, load_port, buffer_out_net); + } + } +} + +LibertyPort * +Sta::findCellPort(LibertyCell *cell, + PortDirection *dir) +{ + LibertyCellPortIterator port_iter(cell); + while (port_iter.hasNext()) { + auto port = port_iter.next(); + if (port->direction() == dir) + return port; + } + return nullptr; +} + //////////////////////////////////////////////////////////////// // // Network edit before/after methods. diff --git a/search/Sta.hh b/search/Sta.hh index 5e11b7fe..95df50be 100644 --- a/search/Sta.hh +++ b/search/Sta.hh @@ -1081,11 +1081,9 @@ public: float elmore); // TCL network edit function support. - // create_cell virtual Instance *makeInstance(const char *name, LibertyCell *cell, Instance *parent); - // remove_cell virtual void deleteInstance(Instance *inst); // replace_cell virtual void replaceCell(Instance *inst, @@ -1097,9 +1095,22 @@ public: virtual void connectPin(Instance *inst, Port *port, Net *net); + virtual void connectPin(Instance *inst, + LibertyPort *port, + Net *net); // disconnect_net virtual void disconnectPin(Pin *pin); + // Insert a buffer_cell instance named inst_name by adding it's input + // pin on net and moving load_pins from net to the output of + // the instance. buffer_cell must have one input and one output port. + // The buffer's parent is the top_instance. + void insertBuffer(const char *buffer_name, + LibertyCell *buffer_cell, + Net *net, + PinSeq *load_pins, + const char *buffer_out_net_name); + // Network edit before/after methods. void makeInstanceAfter(Instance *inst); // Not used by Sta (connectPinAfter). @@ -1292,6 +1303,8 @@ protected: void powerPreamble(); void disableFanoutCrprPruning(Vertex *vertex, int &fanou); + LibertyPort *findCellPort(LibertyCell *cell, + PortDirection *dir); CmdNamespace cmd_namespace_; Instance *current_instance_; diff --git a/tcl/NetworkEdit.i b/tcl/NetworkEdit.i index 0fe381a4..faf7ebc0 100644 --- a/tcl/NetworkEdit.i +++ b/tcl/NetworkEdit.i @@ -93,4 +93,16 @@ disconnect_pin_cmd(Pin *pin) Sta::sta()->disconnectPin(pin); } +void +insert_buffer_cmd(const char *buffer_name, + LibertyCell *buffer_cell, + Net *net, + PinSeq *load_pins, + const char *buffer_out_net_name) +{ + Sta::sta()->insertBuffer(buffer_name, buffer_cell, net, load_pins, + buffer_out_net_name); + delete load_pins; +} + %} // inline diff --git a/tcl/NetworkEdit.tcl b/tcl/NetworkEdit.tcl index 5d9ec0ab..1afb1ecd 100644 --- a/tcl/NetworkEdit.tcl +++ b/tcl/NetworkEdit.tcl @@ -18,7 +18,66 @@ namespace eval sta { +proc connect_pin { net pin } { + set insts_port [parse_connect_pin $pin] + if { $insts_port == 0 } { + return 0 + } + set net [get_net_warn "net" $net] + if { $net == "NULL" } { + return 0 + } + lassign $insts_port inst port + connect_pin_cmd $inst $port $net + return 1 +} + +proc parse_connect_pin { arg } { + set path_regexp [path_regexp] + set insts_port {} + if { [is_object $arg] } { + set object_type [object_type $arg] + if { $object_type == "Pin" } { + set pin $arg + set inst [$pin instance] + set port [$pin port] + } elseif { $object_type == "Port" } { + # Explicit port arg - convert to pin. + set pin [find_pin [get_name $arg]] + set inst [$pin instance] + set port [$pin port] + } else { + sta_error "unsupported object type $object_type." + } + } else { + if {[regexp $path_regexp $arg ignore path_name port_name]} { + set inst [find_instance $path_name] + if { $inst == "NULL" } { + return 0 + } + } else { + set inst [top_instance] + set port_name $arg + } + set cell [$inst cell] + set port [$cell find_port $port_name] + if { $port == "NULL" } { + return 0 + } + set pin [$inst find_pin $port_name] + } + + # Make sure the pin is not currently connected to a net. + if { $pin != "NULL" \ + && ![$pin is_hierarchical] \ + && [$pin net] != "NULL" } { + return 0 + } + return [list $inst $port] +} + proc connect_pins { net pins } { + sta_warn "connect_pins is deprecated. Use connect_pin." # Visit the pins to make sure command will succeed. set insts_ports [parse_connect_pins $pins] if { $insts_ports == 0 } { @@ -36,105 +95,61 @@ proc connect_pins { net pins } { proc parse_connect_pins { arg } { set path_regexp [path_regexp] - set insts_ports {} + set inst_ports {} # Copy backslashes that will be removed by foreach. set arg [string map {\\ \\\\} $arg] foreach obj $arg { - if { [is_object $obj] } { - set object_type [object_type $obj] - if { $object_type == "Pin" } { - set pin $obj - set inst [$pin instance] - set port [$pin port] - } elseif { $object_type == "Port" } { - # Explicit port arg - convert to pin. - set pin [find_pin [get_name $obj]] - set inst [$pin instance] - set port [$pin port] - } else { - sta_error "unsupported object type $object_type." - } - } else { - if {[regexp $path_regexp $obj ignore path_name port_name]} { - set inst [find_instance $path_name] - if { $inst == "NULL" } { - return 0 - } - } else { - set inst [top_instance] - set port_name $obj - } - set cell [$inst cell] - set port [$cell find_port $port_name] - if { $port == "NULL" } { - return 0 - } - set pin [$inst find_pin $port_name] - } - - # Make sure the pin is not currently connected to a net. - if { $pin != "NULL" \ - && ![$pin is_hierarchical] \ - && [$pin net] != "NULL" } { + set inst_port [parse_connect_pin $obj] + if { $inst_port == 0 } { return 0 } - lappend insts_ports $inst $port + set inst_ports [concat $inst_ports $inst_port] } - return $insts_ports + return $inst_ports } ################################################################ -proc delete_instance { instances } { - # Copy backslashes that will be removed by foreach. - set instances1 [string map {\\ \\\\} $instances] - foreach obj $instances1 { - if { [is_object $obj] } { - set object_type [object_type $obj] - if { $object_type == "Instance" } { - set inst $obj - } else { - sta_error "unsupported object type $object_type." - } +proc delete_instance { instance } { + if { [is_object $instance] } { + set object_type [object_type $instance] + if { $object_type == "Instance" } { + set inst $obj } else { - set inst [find_instance $obj] - } - if { $inst != "NULL" } { - delete_instance_cmd $inst + sta_error "unsupported object type $object_type." } + } else { + set inst [find_instance $instance] + } + if { $inst != "NULL" } { + delete_instance_cmd $inst } } ################################################################ -proc delete_net { net_list } { - # Copy backslashes that will be removed by foreach. - set net_list [string map {\\ \\\\} $net_list] - foreach obj $net_list { - if { [is_object $obj] } { - set object_type [object_type $obj] - if { $object_type == "Net" } { - set net $obj - } else { - sta_error "unsupported object type $object_type." - } - } else { - set net [find_net $obj] - } - if { $net != "NULL" } { - delete_net_cmd $net +proc delete_net { net } { + if { [is_object $net] } { + set object_type [object_type $net] + if { $object_type != "Net" } { + sta_error "unsupported object type $object_type." } + } else { + set net [find_net $net] + } + if { $net != "NULL" } { + delete_net_cmd $net } } ################################################################ -proc disconnect_pins { net pins } { +proc disconnect_pin { net pin } { set net [get_net_warn "net" $net] if { $net == "NULL" } { return 0 } - if { $pins == "-all" } { + if { $pin == "-all" } { set iter [$net connected_pin_iterator] while {[$iter has_next]} { set pin [$iter next] @@ -143,46 +158,43 @@ proc disconnect_pins { net pins } { $iter finish return 1 } else { - # Copy backslashes that will be removed by foreach. - set pins [string map {\\ \\\\} $pins] - # Visit the pins to make sure command will succeed. - foreach pin $pins { - set pin1 [get_port_pin_warn "pin" $pin] - if { $pin1 == "NULL" } { - return 0 - } - } - foreach pin $pins { - set pin1 [get_port_pin_warn "pin" $pin] + set pin1 [get_port_pin_warn "pin" $pin] + if { $pin1 == "NULL" } { + return 0 + } else { disconnect_pin_cmd $pin1 + return 1 } - return 1 + } +} + +proc disconnect_pins { net pins } { + sta_warn "disconnect_pins is deprecated. Use disconnect_pin." + foreach pin $pins { + disconnect_pin $net $pins } } ################################################################ -proc make_instance { inst_names lib_cell } { +proc make_instance { inst_path lib_cell } { set lib_cell [get_lib_cell_warn "lib_cell" $lib_cell] if { $lib_cell != "NULL" } { set path_regexp [path_regexp] - foreach inst_path $inst_names { - if {[regexp $path_regexp $inst_path ignore path_name inst_name]} { - set parent [find_instance $path_name] - if { $parent == "NULL" } { - # Parent instance not found. This could be a typo, but since - # SDC does not escape hierarchy dividers it can also be - # an escaped name. - set inst_name $inst_path - set parent [top_instance] - } - } else { + if {[regexp $path_regexp $inst_path ignore path_name inst_name]} { + set parent [find_instance $path_name] + if { $parent == "NULL" } { + # Parent instance not found. This could be a typo, but since + # SDC does not escape hierarchy dividers it can also be + # an escaped name. set inst_name $inst_path set parent [top_instance] } - make_instance_cmd $inst_name $lib_cell $parent + } else { + set inst_name $inst_path + set parent [top_instance] } - return 1 + return [make_instance_cmd $inst_name $lib_cell $parent] } else { return 0 } @@ -190,29 +202,19 @@ proc make_instance { inst_names lib_cell } { ################################################################ -proc make_net { net_list } { - # Visit the net names to make sure command will succeed. - set path_regexp [path_regexp] - foreach net $net_list { - if {[regexp $path_regexp $net ignore path_name net_name]} { - set parent [find_instance $path_name] - if { $parent == "NULL" } { - return 0 - } - } - } +proc make_net { net_name } { # Copy backslashes that will be removed by foreach. - set net_list [string map {\\ \\\\} $net_list] - foreach net $net_list { - if {[regexp $path_regexp $net ignore path_name net_name]} { - set parent [find_instance $path_name] - } else { - set net_name $net - set parent [top_instance] + set net_name [string map {\\ \\\\} $net_name] + set path_regexp [path_regexp] + if {[regexp $path_regexp $net_name ignore path_name net_name]} { + set parent [find_instance $path_name] + if { $parent == "NULL" } { + return 0 } - make_net_cmd $net_name $parent + } else { + set parent [top_instance] } - return 1 + return [make_net_cmd $net_name $parent] } ################################################################ @@ -237,5 +239,23 @@ proc replace_cell { instances lib_cell } { } } +################################################################ + +proc insert_buffer { buffer_name buffer_cell net load_pins buffer_out_net_name } { + set buffer_cell [sta::get_lib_cell_warn "buffer_cell" $buffer_cell] + set net [sta::get_net_warn "net" $net] + + # Copy backslashes that will be removed by foreach. + set load_pins1 [string map {\\ \\\\} $load_pins] + set load_pins {} + foreach pin $load_pins1 { + set pin1 [get_port_pin_warn "pin" $pin] + if { $pin1 != "NULL" } { + lappend load_pins $pin1 + } + } + insert_buffer_cmd $buffer_name $buffer_cell $net $load_pins $buffer_out_net_name +} + # sta namespace end. } diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index 24907782..96048354 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -677,12 +677,16 @@ proc unset_timing_derate { args } { # ################################################################ +define_sta_cmd_args "connect_pin" {net pins} +# deprecated 2.0.16 05/02/2019 define_sta_cmd_args "connect_pins" {net pins} define_sta_cmd_args "delete_instance" {cell_list} define_sta_cmd_args "delete_net" {net_list} +define_sta_cmd_args "disconnect_pin" {net -all|pin} +# deprecated 2.0.16 05/02/2019 define_sta_cmd_args "disconnect_pins" {net -all|pins} define_sta_cmd_args "make_instance" {inst_names lib_cell} @@ -691,6 +695,9 @@ define_sta_cmd_args "make_net" {} define_sta_cmd_args "replace_cell" {instances lib_cell} +define_sta_cmd_args "insert_buffer" {buffer_name buffer_cell net load_pins\ + buffer_out_net_name} + ################################################################ # # Delay calculation commands