diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 1219b86a..eac66166 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -46,7 +46,6 @@ #include "ClockGatingCheck.hh" #include "ClockGroups.hh" #include "DeratingFactors.hh" -#include "Graph.hh" #include "search/Levelize.hh" #include "Corner.hh" @@ -77,11 +76,6 @@ typedef Set PvtSet; static ExceptionThruSeq * clone(ExceptionThruSeq *thrus, Network *network); -static void -annotateGraphDisabledWireEdge(Pin *from_pin, - Pin *to_pin, - bool annotate, - Graph *graph); //////////////////////////////////////////////////////////////// @@ -409,15 +403,6 @@ Sdc::initInstancePvtMaps() //////////////////////////////////////////////////////////////// -void -Sdc::searchPreamble() -{ - ensureClkHpinDisables(); - ensureClkGroupExclusions(); -} - -//////////////////////////////////////////////////////////////// - bool Sdc::isConstrained(const Pin *pin) const { @@ -1444,49 +1429,6 @@ Sdc::makeClkHpinDisable(Clock *clk, } } -void -Sdc::ensureClkHpinDisables() -{ - if (!clk_hpin_disables_valid_) { - clk_hpin_disables_.deleteContentsClear(); - for (auto clk : clocks_) { - for (Pin *src : clk->pins()) { - if (network_->isHierarchical(src)) { - FindClkHpinDisables visitor(clk, network_, this); - visitHpinDrvrLoads(src, network_, &visitor); - // Disable fanouts from the src driver pins that do - // not go thru the hierarchical src pin. - for (Pin *lpin : clk->leafPins()) { - Vertex *vertex, *bidirect_drvr_vertex; - graph_->pinVertices(lpin, vertex, bidirect_drvr_vertex); - makeVertexClkHpinDisables(clk, vertex, visitor); - if (bidirect_drvr_vertex) - makeVertexClkHpinDisables(clk, bidirect_drvr_vertex, visitor); - } - } - } - } - clk_hpin_disables_valid_ = true; - } -} - -void -Sdc::makeVertexClkHpinDisables(Clock *clk, - Vertex *vertex, - FindClkHpinDisables &visitor) -{ - VertexOutEdgeIterator edge_iter(vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (edge->isWire()) { - Pin *drvr = edge->from(graph_)->pin(); - Pin *load = edge->to(graph_)->pin(); - if (!visitor.drvrLoadExists(drvr, load)) - makeClkHpinDisable(clk, drvr, load); - } - } -} - void Sdc::clkHpinDisablesInvalid() { @@ -1573,8 +1515,6 @@ Sdc::setClockLatency(Clock *clk, clk_latencies_.insert(latency); } latency->setDelay(rf, min_max, delay); - if (pin && graph_ && network_->isHierarchical(pin)) - annotateHierClkLatency(pin, latency); // set_clock_latency removes set_propagated_clock on the same object. if (clk && pin == nullptr) @@ -1597,8 +1537,6 @@ void Sdc::deleteClockLatency(ClockLatency *latency) { const Pin *pin = latency->pin(); - if (pin && graph_ && network_->isHierarchical(pin)) - deannotateHierClkLatency(pin); clk_latencies_.erase(latency); delete latency; } @@ -2564,9 +2502,6 @@ Sdc::setDataCheck(Pin *from, data_checks_to_map_[to] = checks; } checks->insert(check); - - if (graph_) - annotateGraphConstrained(to, true); } void @@ -3000,8 +2935,6 @@ Sdc::makeOutputDelay(Pin *pin, output_delay_leaf_pin_map_[lpin] = leaf_outputs; } leaf_outputs->insert(output_delay); - if (graph_) - annotateGraphConstrained(lpin, true); } return output_delay; } @@ -3625,19 +3558,11 @@ void Sdc::disable(Port *port) { disabled_ports_.insert(port); - if (graph_) { - Pin *pin = network_->findPin(network_->topInstance(), port); - annotateGraphDisabled(pin, true); - } } void Sdc::removeDisable(Port *port) { - if (graph_) { - Pin *pin = network_->findPin(network_->topInstance(), port); - annotateGraphDisabled(pin, false); - } disabled_ports_.erase(port); } @@ -3659,9 +3584,6 @@ Sdc::disable(Instance *inst, disabled_inst->setDisabledTo(to); else disabled_inst->setDisabledAll(); - - if (graph_) - setEdgeDisabledInstPorts(disabled_inst, true); } void @@ -3671,8 +3593,6 @@ Sdc::removeDisable(Instance *inst, { DisabledInstancePorts *disabled_inst = disabled_inst_ports_.findKey(inst); if (disabled_inst) { - if (graph_) - setEdgeDisabledInstPorts(disabled_inst, false); if (from && to) disabled_inst->removeDisabledFromTo(from, to); else if (from) @@ -3692,8 +3612,6 @@ Sdc::disable(Pin *from, if (!disabled_wire_edges_.hasKey(&probe)) { PinPair *pair = new PinPair(from, to); disabled_wire_edges_.insert(pair); - if (graph_) - annotateGraphDisabledWireEdge(from, to, true, graph_); } } @@ -3701,7 +3619,6 @@ void Sdc::removeDisable(Pin *from, Pin *to) { - annotateGraphDisabledWireEdge(from, to, false, graph_); PinPair probe(from, to); disabled_wire_edges_.erase(&probe); } @@ -3759,8 +3676,6 @@ DisableEdgesThruHierPin::visit(Pin *drvr, if (!pairs_->hasKey(&probe)) { PinPair *pair = new PinPair(drvr, load); pairs_->insert(pair); - if (graph_) - annotateGraphDisabledWireEdge(drvr, load, true, graph_); } } @@ -3772,17 +3687,15 @@ Sdc::disable(Pin *pin) DisableEdgesThruHierPin visitor(&disabled_wire_edges_, graph_); visitDrvrLoadsThruHierPin(pin, network_, &visitor); } - else { + else disabled_pins_.insert(pin); - if (graph_) - annotateGraphDisabled(pin, true); - } } class RemoveDisableEdgesThruHierPin : public HierPinThruVisitor { public: - RemoveDisableEdgesThruHierPin(PinPairSet *pairs, Graph *graph); + RemoveDisableEdgesThruHierPin(PinPairSet *pairs, + Graph *graph); protected: virtual void visit(Pin *drvr, Pin *load); @@ -3806,8 +3719,6 @@ void RemoveDisableEdgesThruHierPin::visit(Pin *drvr, Pin *load) { - if (graph_) - annotateGraphDisabledWireEdge(drvr, load, false, graph_); PinPair probe(drvr, load); PinPair *pair = pairs_->findKey(&probe); if (pair) { @@ -3824,11 +3735,8 @@ Sdc::removeDisable(Pin *pin) RemoveDisableEdgesThruHierPin visitor(&disabled_wire_edges_, graph_); visitDrvrLoadsThruHierPin(pin, network_, &visitor); } - else { - if (graph_) - annotateGraphDisabled(pin, false); + else disabled_pins_.erase(pin); - } } bool @@ -6090,370 +5998,6 @@ Sdc::clkHpinDisablesChanged(Pin *pin) //////////////////////////////////////////////////////////////// -// Annotate constraints to the timing graph. -void -Sdc::annotateGraph(bool annotate) -{ - Stats stats(debug_); - // All output pins are considered constrained because - // they may be downstream from a set_min/max_delay -from that - // does not have a set_output_delay. - annotateGraphConstrainOutputs(); - annotateDisables(annotate); - annotateGraphOutputDelays(annotate); - annotateGraphDataChecks(annotate); - annotateHierClkLatency(annotate); - stats.report("Annotate constraints to graph"); -} - -void -Sdc::annotateGraphConstrainOutputs() -{ - Instance *top_inst = network_->topInstance(); - InstancePinIterator *pin_iter = network_->pinIterator(top_inst); - while (pin_iter->hasNext()) { - Pin *pin = pin_iter->next(); - if (network_->direction(pin)->isAnyOutput()) - annotateGraphConstrained(pin, true); - } - delete pin_iter; -} - -void -Sdc::annotateDisables(bool annotate) -{ - PinSet::Iterator pin_iter(disabled_pins_); - while (pin_iter.hasNext()) { - Pin *pin = pin_iter.next(); - annotateGraphDisabled(pin, annotate); - } - - if (!disabled_lib_ports_.empty()) { - VertexIterator vertex_iter(graph_); - while (vertex_iter.hasNext()) { - Vertex *vertex = vertex_iter.next(); - Pin *pin = vertex->pin(); - LibertyPort *port = network_->libertyPort(pin); - if (disabled_lib_ports_.hasKey(port)) - annotateGraphDisabled(pin, annotate); - } - } - - Instance *top_inst = network_->topInstance(); - PortSet::Iterator port_iter(disabled_ports_); - while (port_iter.hasNext()) { - Port *port = port_iter.next(); - Pin *pin = network_->findPin(top_inst, port); - annotateGraphDisabled(pin, annotate); - } - - PinPairSet::Iterator pair_iter(disabled_wire_edges_); - while (pair_iter.hasNext()) { - PinPair *pair = pair_iter.next(); - annotateGraphDisabledWireEdge(pair->first, pair->second, annotate, graph_); - } - - EdgeSet::Iterator edge_iter(disabled_edges_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - edge->setIsDisabledConstraint(annotate); - } - - DisabledInstancePortsMap::Iterator disable_inst_iter(disabled_inst_ports_); - while (disable_inst_iter.hasNext()) { - DisabledInstancePorts *disabled_inst = disable_inst_iter.next(); - setEdgeDisabledInstPorts(disabled_inst, annotate); - } -} - -class DisableHpinEdgeVisitor : public HierPinThruVisitor -{ -public: - DisableHpinEdgeVisitor(bool annotate, Graph *graph); - virtual void visit(Pin *from_pin, - Pin *to_pin); - -protected: - bool annotate_; - Graph *graph_; - -private: - DISALLOW_COPY_AND_ASSIGN(DisableHpinEdgeVisitor); -}; - -DisableHpinEdgeVisitor::DisableHpinEdgeVisitor(bool annotate, - Graph *graph) : - HierPinThruVisitor(), - annotate_(annotate), - graph_(graph) -{ -} - -void -DisableHpinEdgeVisitor::visit(Pin *from_pin, - Pin *to_pin) -{ - annotateGraphDisabledWireEdge(from_pin, to_pin, annotate_, graph_); -} - -static void -annotateGraphDisabledWireEdge(Pin *from_pin, - Pin *to_pin, - bool annotate, - Graph *graph) -{ - Vertex *from_vertex = graph->pinDrvrVertex(from_pin); - Vertex *to_vertex = graph->pinLoadVertex(to_pin); - if (from_vertex && to_vertex) { - VertexOutEdgeIterator edge_iter(from_vertex, graph); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (edge->isWire() - && edge->to(graph) == to_vertex) - edge->setIsDisabledConstraint(annotate); - } - } -} - -void -Sdc::annotateGraphDisabled(const Pin *pin, - bool annotate) -{ - Vertex *vertex, *bidirect_drvr_vertex; - graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); - vertex->setIsDisabledConstraint(annotate); - if (bidirect_drvr_vertex) - bidirect_drvr_vertex->setIsDisabledConstraint(annotate); -} - -void -Sdc::setEdgeDisabledInstPorts(DisabledInstancePorts *disabled_inst, - bool annotate) -{ - setEdgeDisabledInstPorts(disabled_inst, disabled_inst->instance(), annotate); -} - -void -Sdc::setEdgeDisabledInstPorts(DisabledPorts *disabled_port, - Instance *inst, - bool annotate) -{ - if (disabled_port->all()) { - InstancePinIterator *pin_iter = network_->pinIterator(inst); - while (pin_iter->hasNext()) { - Pin *pin = pin_iter->next(); - // set_disable_timing instance does not disable timing checks. - setEdgeDisabledInstFrom(pin, false, annotate); - } - delete pin_iter; - } - - // Disable from pins. - LibertyPortSet::Iterator from_iter(disabled_port->from()); - while (from_iter.hasNext()) { - LibertyPort *from_port = from_iter.next(); - Pin *from_pin = network_->findPin(inst, from_port); - if (from_pin) - setEdgeDisabledInstFrom(from_pin, true, annotate); - } - - // Disable to pins. - LibertyPortSet::Iterator to_iter(disabled_port->to()); - while (to_iter.hasNext()) { - LibertyPort *to_port = to_iter.next(); - Pin *to_pin = network_->findPin(inst, to_port); - if (to_pin) { - if (network_->direction(to_pin)->isAnyOutput()) { - Vertex *vertex = graph_->pinDrvrVertex(to_pin); - if (vertex) { - VertexInEdgeIterator edge_iter(vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - edge->setIsDisabledConstraint(annotate); - } - } - } - } - } - - // Disable from/to pins. - LibertyPortPairSet::Iterator from_to_iter(disabled_port->fromTo()); - while (from_to_iter.hasNext()) { - LibertyPortPair *pair = from_to_iter.next(); - const LibertyPort *from_port = pair->first; - const LibertyPort *to_port = pair->second; - Pin *from_pin = network_->findPin(inst, from_port); - Pin *to_pin = network_->findPin(inst, to_port); - if (from_pin && network_->direction(from_pin)->isAnyInput() - && to_pin) { - Vertex *from_vertex = graph_->pinLoadVertex(from_pin); - Vertex *to_vertex = graph_->pinDrvrVertex(to_pin); - if (from_vertex && to_vertex) { - VertexOutEdgeIterator edge_iter(from_vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (edge->to(graph_) == to_vertex) - edge->setIsDisabledConstraint(annotate); - } - } - } - } -} - -void -Sdc::setEdgeDisabledInstFrom(Pin *from_pin, - bool disable_checks, - bool annotate) -{ - if (network_->direction(from_pin)->isAnyInput()) { - Vertex *from_vertex = graph_->pinLoadVertex(from_pin); - if (from_vertex) { - VertexOutEdgeIterator edge_iter(from_vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (disable_checks - || !edge->role()->isTimingCheck()) - edge->setIsDisabledConstraint(annotate); - } - } - } -} - -void -Sdc::annotateGraphOutputDelays(bool annotate) -{ - for (OutputDelay *output_delay : output_delays_) { - for (Pin *lpin : output_delay->leafPins()) - annotateGraphConstrained(lpin, annotate); - } -} - -void -Sdc::annotateGraphDataChecks(bool annotate) -{ - DataChecksMap::Iterator data_checks_iter(data_checks_to_map_); - while (data_checks_iter.hasNext()) { - DataCheckSet *checks = data_checks_iter.next(); - DataCheckSet::Iterator check_iter(checks); - // There may be multiple data checks on a single pin, - // but we only need to mark it as constrained once. - if (check_iter.hasNext()) { - DataCheck *check = check_iter.next(); - annotateGraphConstrained(check->to(), annotate); - } - } -} - -void -Sdc::annotateGraphConstrained(const PinSet *pins, - bool annotate) -{ - PinSet::ConstIterator pin_iter(pins); - while (pin_iter.hasNext()) { - const Pin *pin = pin_iter.next(); - annotateGraphConstrained(pin, annotate); - } -} - -void -Sdc::annotateGraphConstrained(const InstanceSet *insts, - bool annotate) -{ - InstanceSet::ConstIterator inst_iter(insts); - while (inst_iter.hasNext()) { - const Instance *inst = inst_iter.next(); - annotateGraphConstrained(inst, annotate); - } -} - -void -Sdc::annotateGraphConstrained(const Instance *inst, - bool annotate) -{ - InstancePinIterator *pin_iter = network_->pinIterator(inst); - while (pin_iter->hasNext()) { - Pin *pin = pin_iter->next(); - if (network_->direction(pin)->isAnyInput()) - annotateGraphConstrained(pin, annotate); - } - delete pin_iter; -} - -void -Sdc::annotateGraphConstrained(const Pin *pin, - bool annotate) -{ - Vertex *vertex, *bidirect_drvr_vertex; - graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); - // Pin may be hierarchical and have no vertex. - if (vertex) - vertex->setIsConstrained(annotate); - if (bidirect_drvr_vertex) - bidirect_drvr_vertex->setIsConstrained(annotate); -} - -void -Sdc::annotateHierClkLatency(bool annotate) -{ - if (annotate) { - ClockLatencies::Iterator latency_iter(clk_latencies_); - while (latency_iter.hasNext()) { - ClockLatency *latency = latency_iter.next(); - const Pin *pin = latency->pin(); - if (pin && network_->isHierarchical(pin)) - annotateHierClkLatency(pin, latency); - } - } - else - edge_clk_latency_.clear(); -} - -void -Sdc::annotateHierClkLatency(const Pin *hpin, - ClockLatency *latency) -{ - EdgesThruHierPinIterator edge_iter(hpin, network_, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - edge_clk_latency_[edge] = latency; - } -} - -void -Sdc::deannotateHierClkLatency(const Pin *hpin) -{ - EdgesThruHierPinIterator edge_iter(hpin, network_, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - edge_clk_latency_.erase(edge); - } -} - -ClockLatency * -Sdc::clockLatency(Edge *edge) const -{ - return edge_clk_latency_.findKey(edge); -} - -void -Sdc::clockLatency(Edge *edge, - const RiseFall *rf, - const MinMax *min_max, - // Return values. - float &latency, - bool &exists) const -{ - ClockLatency *latencies = edge_clk_latency_.findKey(edge); - if (latencies) - latencies->delay(rf, min_max, latency, exists); - else { - latency = 0.0; - exists = false; - } -} - -//////////////////////////////////////////////////////////////// - // Find the leaf load pins corresponding to pin. // If the pin is hierarchical, the leaf pins are: // hierarchical input - load pins inside the hierarchical instance diff --git a/sdc/SdcGraph.cc b/sdc/SdcGraph.cc new file mode 100644 index 00000000..2237f6e7 --- /dev/null +++ b/sdc/SdcGraph.cc @@ -0,0 +1,443 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2020, Parallax Software, Inc. +// +// 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 +// 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 . + +#include "SdcGraph.hh" + +#include "Graph.hh" + +namespace sta { + +static void +annotateGraphDisabledWireEdge(Pin *from_pin, + Pin *to_pin, + bool annotate, + Graph *graph); + +// Annotate constraints to the timing graph. +void +Sdc::annotateGraph(bool annotate) +{ + Stats stats(debug_); + // All output pins are considered constrained because + // they may be downstream from a set_min/max_delay -from that + // does not have a set_output_delay. + annotateGraphConstrainOutputs(); + annotateDisables(annotate); + annotateGraphOutputDelays(annotate); + annotateGraphDataChecks(annotate); + annotateHierClkLatency(annotate); + stats.report("Annotate constraints to graph"); +} + +void +Sdc::annotateGraphConstrainOutputs() +{ + Instance *top_inst = network_->topInstance(); + InstancePinIterator *pin_iter = network_->pinIterator(top_inst); + while (pin_iter->hasNext()) { + Pin *pin = pin_iter->next(); + if (network_->direction(pin)->isAnyOutput()) + annotateGraphConstrained(pin, true); + } + delete pin_iter; +} + +void +Sdc::annotateDisables(bool annotate) +{ + PinSet::Iterator pin_iter(disabled_pins_); + while (pin_iter.hasNext()) { + Pin *pin = pin_iter.next(); + annotateGraphDisabled(pin, annotate); + } + + if (!disabled_lib_ports_.empty()) { + VertexIterator vertex_iter(graph_); + while (vertex_iter.hasNext()) { + Vertex *vertex = vertex_iter.next(); + Pin *pin = vertex->pin(); + LibertyPort *port = network_->libertyPort(pin); + if (disabled_lib_ports_.hasKey(port)) + annotateGraphDisabled(pin, annotate); + } + } + + Instance *top_inst = network_->topInstance(); + PortSet::Iterator port_iter(disabled_ports_); + while (port_iter.hasNext()) { + Port *port = port_iter.next(); + Pin *pin = network_->findPin(top_inst, port); + annotateGraphDisabled(pin, annotate); + } + + PinPairSet::Iterator pair_iter(disabled_wire_edges_); + while (pair_iter.hasNext()) { + PinPair *pair = pair_iter.next(); + annotateGraphDisabledWireEdge(pair->first, pair->second, annotate, graph_); + } + + EdgeSet::Iterator edge_iter(disabled_edges_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + edge->setIsDisabledConstraint(annotate); + } + + DisabledInstancePortsMap::Iterator disable_inst_iter(disabled_inst_ports_); + while (disable_inst_iter.hasNext()) { + DisabledInstancePorts *disabled_inst = disable_inst_iter.next(); + setEdgeDisabledInstPorts(disabled_inst, annotate); + } +} + +class DisableHpinEdgeVisitor : public HierPinThruVisitor +{ +public: + DisableHpinEdgeVisitor(bool annotate, Graph *graph); + virtual void visit(Pin *from_pin, + Pin *to_pin); + +protected: + bool annotate_; + Graph *graph_; + +private: + DISALLOW_COPY_AND_ASSIGN(DisableHpinEdgeVisitor); +}; + +DisableHpinEdgeVisitor::DisableHpinEdgeVisitor(bool annotate, + Graph *graph) : + HierPinThruVisitor(), + annotate_(annotate), + graph_(graph) +{ +} + +void +DisableHpinEdgeVisitor::visit(Pin *from_pin, + Pin *to_pin) +{ + annotateGraphDisabledWireEdge(from_pin, to_pin, annotate_, graph_); +} + +static void +annotateGraphDisabledWireEdge(Pin *from_pin, + Pin *to_pin, + bool annotate, + Graph *graph) +{ + Vertex *from_vertex = graph->pinDrvrVertex(from_pin); + Vertex *to_vertex = graph->pinLoadVertex(to_pin); + if (from_vertex && to_vertex) { + VertexOutEdgeIterator edge_iter(from_vertex, graph); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (edge->isWire() + && edge->to(graph) == to_vertex) + edge->setIsDisabledConstraint(annotate); + } + } +} + +void +Sdc::annotateGraphDisabled(const Pin *pin, + bool annotate) +{ + Vertex *vertex, *bidirect_drvr_vertex; + graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); + vertex->setIsDisabledConstraint(annotate); + if (bidirect_drvr_vertex) + bidirect_drvr_vertex->setIsDisabledConstraint(annotate); +} + +void +Sdc::setEdgeDisabledInstPorts(DisabledInstancePorts *disabled_inst, + bool annotate) +{ + setEdgeDisabledInstPorts(disabled_inst, disabled_inst->instance(), annotate); +} + +void +Sdc::setEdgeDisabledInstPorts(DisabledPorts *disabled_port, + Instance *inst, + bool annotate) +{ + if (disabled_port->all()) { + InstancePinIterator *pin_iter = network_->pinIterator(inst); + while (pin_iter->hasNext()) { + Pin *pin = pin_iter->next(); + // set_disable_timing instance does not disable timing checks. + setEdgeDisabledInstFrom(pin, false, annotate); + } + delete pin_iter; + } + + // Disable from pins. + LibertyPortSet::Iterator from_iter(disabled_port->from()); + while (from_iter.hasNext()) { + LibertyPort *from_port = from_iter.next(); + Pin *from_pin = network_->findPin(inst, from_port); + if (from_pin) + setEdgeDisabledInstFrom(from_pin, true, annotate); + } + + // Disable to pins. + LibertyPortSet::Iterator to_iter(disabled_port->to()); + while (to_iter.hasNext()) { + LibertyPort *to_port = to_iter.next(); + Pin *to_pin = network_->findPin(inst, to_port); + if (to_pin) { + if (network_->direction(to_pin)->isAnyOutput()) { + Vertex *vertex = graph_->pinDrvrVertex(to_pin); + if (vertex) { + VertexInEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + edge->setIsDisabledConstraint(annotate); + } + } + } + } + } + + // Disable from/to pins. + LibertyPortPairSet::Iterator from_to_iter(disabled_port->fromTo()); + while (from_to_iter.hasNext()) { + LibertyPortPair *pair = from_to_iter.next(); + const LibertyPort *from_port = pair->first; + const LibertyPort *to_port = pair->second; + Pin *from_pin = network_->findPin(inst, from_port); + Pin *to_pin = network_->findPin(inst, to_port); + if (from_pin && network_->direction(from_pin)->isAnyInput() + && to_pin) { + Vertex *from_vertex = graph_->pinLoadVertex(from_pin); + Vertex *to_vertex = graph_->pinDrvrVertex(to_pin); + if (from_vertex && to_vertex) { + VertexOutEdgeIterator edge_iter(from_vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (edge->to(graph_) == to_vertex) + edge->setIsDisabledConstraint(annotate); + } + } + } + } +} + +void +Sdc::setEdgeDisabledInstFrom(Pin *from_pin, + bool disable_checks, + bool annotate) +{ + if (network_->direction(from_pin)->isAnyInput()) { + Vertex *from_vertex = graph_->pinLoadVertex(from_pin); + if (from_vertex) { + VertexOutEdgeIterator edge_iter(from_vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (disable_checks + || !edge->role()->isTimingCheck()) + edge->setIsDisabledConstraint(annotate); + } + } + } +} + +void +Sdc::annotateGraphOutputDelays(bool annotate) +{ + for (OutputDelay *output_delay : output_delays_) { + for (Pin *lpin : output_delay->leafPins()) + annotateGraphConstrained(lpin, annotate); + } +} + +void +Sdc::annotateGraphDataChecks(bool annotate) +{ + DataChecksMap::Iterator data_checks_iter(data_checks_to_map_); + while (data_checks_iter.hasNext()) { + DataCheckSet *checks = data_checks_iter.next(); + DataCheckSet::Iterator check_iter(checks); + // There may be multiple data checks on a single pin, + // but we only need to mark it as constrained once. + if (check_iter.hasNext()) { + DataCheck *check = check_iter.next(); + annotateGraphConstrained(check->to(), annotate); + } + } +} + +void +Sdc::annotateGraphConstrained(const PinSet *pins, + bool annotate) +{ + PinSet::ConstIterator pin_iter(pins); + while (pin_iter.hasNext()) { + const Pin *pin = pin_iter.next(); + annotateGraphConstrained(pin, annotate); + } +} + +void +Sdc::annotateGraphConstrained(const InstanceSet *insts, + bool annotate) +{ + InstanceSet::ConstIterator inst_iter(insts); + while (inst_iter.hasNext()) { + const Instance *inst = inst_iter.next(); + annotateGraphConstrained(inst, annotate); + } +} + +void +Sdc::annotateGraphConstrained(const Instance *inst, + bool annotate) +{ + InstancePinIterator *pin_iter = network_->pinIterator(inst); + while (pin_iter->hasNext()) { + Pin *pin = pin_iter->next(); + if (network_->direction(pin)->isAnyInput()) + annotateGraphConstrained(pin, annotate); + } + delete pin_iter; +} + +void +Sdc::annotateGraphConstrained(const Pin *pin, + bool annotate) +{ + Vertex *vertex, *bidirect_drvr_vertex; + graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); + // Pin may be hierarchical and have no vertex. + if (vertex) + vertex->setIsConstrained(annotate); + if (bidirect_drvr_vertex) + bidirect_drvr_vertex->setIsConstrained(annotate); +} + +void +Sdc::annotateHierClkLatency(bool annotate) +{ + if (annotate) { + ClockLatencies::Iterator latency_iter(clk_latencies_); + while (latency_iter.hasNext()) { + ClockLatency *latency = latency_iter.next(); + const Pin *pin = latency->pin(); + if (pin && network_->isHierarchical(pin)) + annotateHierClkLatency(pin, latency); + } + } + else + edge_clk_latency_.clear(); +} + +void +Sdc::annotateHierClkLatency(const Pin *hpin, + ClockLatency *latency) +{ + EdgesThruHierPinIterator edge_iter(hpin, network_, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + edge_clk_latency_[edge] = latency; + } +} + +void +Sdc::deannotateHierClkLatency(const Pin *hpin) +{ + EdgesThruHierPinIterator edge_iter(hpin, network_, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + edge_clk_latency_.erase(edge); + } +} + +ClockLatency * +Sdc::clockLatency(Edge *edge) const +{ + return edge_clk_latency_.findKey(edge); +} + +void +Sdc::clockLatency(Edge *edge, + const RiseFall *rf, + const MinMax *min_max, + // Return values. + float &latency, + bool &exists) const +{ + ClockLatency *latencies = edge_clk_latency_.findKey(edge); + if (latencies) + latencies->delay(rf, min_max, latency, exists); + else { + latency = 0.0; + exists = false; + } +} + +void +Sdc::ensureClkHpinDisables() +{ + if (!clk_hpin_disables_valid_) { + clk_hpin_disables_.deleteContentsClear(); + for (auto clk : clocks_) { + for (Pin *src : clk->pins()) { + if (network_->isHierarchical(src)) { + FindClkHpinDisables visitor(clk, network_, this); + visitHpinDrvrLoads(src, network_, &visitor); + // Disable fanouts from the src driver pins that do + // not go thru the hierarchical src pin. + for (Pin *lpin : clk->leafPins()) { + Vertex *vertex, *bidirect_drvr_vertex; + graph_->pinVertices(lpin, vertex, bidirect_drvr_vertex); + makeVertexClkHpinDisables(clk, vertex, visitor); + if (bidirect_drvr_vertex) + makeVertexClkHpinDisables(clk, bidirect_drvr_vertex, visitor); + } + } + } + } + clk_hpin_disables_valid_ = true; + } +} + +void +Sdc::makeVertexClkHpinDisables(Clock *clk, + Vertex *vertex, + FindClkHpinDisables &visitor) +{ + VertexOutEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (edge->isWire()) { + Pin *drvr = edge->from(graph_)->pin(); + Pin *load = edge->to(graph_)->pin(); + if (!visitor.drvrLoadExists(drvr, load)) + makeClkHpinDisable(clk, drvr, load); + } + } +} + +//////////////////////////////////////////////////////////////// + +void +Sdc::searchPreamble() +{ + ensureClkHpinDisables(); + ensureClkGroupExclusions(); +} + +} // namespace diff --git a/search/Sta.cc b/search/Sta.cc index f0851495..109e9efd 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -1186,14 +1186,21 @@ Sta::setClockLatency(Clock *clk, const MinMaxAll *min_max, float delay) { + sdcChangedGraph(); sdc_->setClockLatency(clk, pin, rf, min_max, delay); search_->arrivalsInvalid(); } +void +Sta::sdcChangedGraph() +{ +} + void Sta::removeClockLatency(const Clock *clk, const Pin *pin) { + sdcChangedGraph(); sdc_->removeClockLatency(clk, pin); search_->arrivalsInvalid(); } @@ -1384,6 +1391,7 @@ Sta::setDataCheck(Pin *from, const SetupHoldAll *setup_hold, float margin) { + sdcChangedGraph(); sdc_->setDataCheck(from, from_rf, to, to_rf, clk, setup_hold,margin); search_->requiredInvalid(to); } @@ -1428,6 +1436,7 @@ Sta::disable(Instance *inst, LibertyPort *from, LibertyPort *to) { + sdcChangedGraph(); sdc_->disable(inst, from, to); if (from) { @@ -1456,6 +1465,7 @@ Sta::removeDisable(Instance *inst, LibertyPort *from, LibertyPort *to) { + sdcChangedGraph(); sdc_->removeDisable(inst, from, to); if (from) { @@ -1500,6 +1510,7 @@ Sta::removeDisable(LibertyCell *cell, void Sta::disable(LibertyPort *port) { + sdcChangedGraph(); sdc_->disable(port); disableAfter(); } @@ -1507,6 +1518,7 @@ Sta::disable(LibertyPort *port) void Sta::removeDisable(LibertyPort *port) { + sdcChangedGraph(); sdc_->removeDisable(port); disableAfter(); } @@ -1868,6 +1880,7 @@ Sta::setOutputDelay(Pin *pin, sdc_->setOutputDelay(pin, rf, clk, clk_rf, ref_pin, source_latency_included,network_latency_included, min_max, add, delay); + sdcChangedGraph(); search_->requiredInvalid(pin); } @@ -1879,6 +1892,7 @@ Sta::removeOutputDelay(Pin *pin, MinMaxAll *min_max) { sdc_->removeOutputDelay(pin, rf, clk, clk_rf, min_max); + sdcChangedGraph(); search_->arrivalInvalid(pin); }