OpenSTA/sdc/SdcGraph.cc

398 lines
10 KiB
C++
Raw Normal View History

2020-05-19 22:07:52 +02:00
// 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 <https://www.gnu.org/licenses/>.
2020-07-12 08:56:39 +02:00
#include "Stats.hh"
#include "PortDirection.hh"
#include "Network.hh"
2020-05-19 22:07:52 +02:00
#include "Graph.hh"
2020-07-12 08:56:39 +02:00
#include "DisabledPorts.hh"
#include "PortDelay.hh"
#include "ClockLatency.hh"
#include "Sdc.hh"
2020-05-19 22:07:52 +02:00
namespace sta {
static void
annotateGraphDisabledWireEdge(Pin *from_pin,
Pin *to_pin,
Graph *graph);
// Annotate constraints to the timing graph.
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraph()
2020-05-19 22:07:52 +02:00
{
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();
2020-07-12 17:55:44 +02:00
annotateDisables();
annotateGraphOutputDelays();
annotateGraphDataChecks();
annotateHierClkLatency();
2020-05-19 22:07:52 +02:00
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())
2020-07-12 17:55:44 +02:00
annotateGraphConstrained(pin);
2020-05-19 22:07:52 +02:00
}
delete pin_iter;
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateDisables()
2020-05-19 22:07:52 +02:00
{
PinSet::Iterator pin_iter(disabled_pins_);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
2020-07-12 17:55:44 +02:00
annotateGraphDisabled(pin);
2020-05-19 22:07:52 +02:00
}
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))
2020-07-12 17:55:44 +02:00
annotateGraphDisabled(pin);
2020-05-19 22:07:52 +02:00
}
}
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);
2020-07-12 17:55:44 +02:00
annotateGraphDisabled(pin);
2020-05-19 22:07:52 +02:00
}
PinPairSet::Iterator pair_iter(disabled_wire_edges_);
while (pair_iter.hasNext()) {
PinPair *pair = pair_iter.next();
2020-07-12 17:55:44 +02:00
annotateGraphDisabledWireEdge(pair->first, pair->second, graph_);
2020-05-19 22:07:52 +02:00
}
EdgeSet::Iterator edge_iter(disabled_edges_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
2020-07-12 17:55:44 +02:00
edge->setIsDisabledConstraint(true);
2020-05-19 22:07:52 +02:00
}
DisabledInstancePortsMap::Iterator disable_inst_iter(disabled_inst_ports_);
while (disable_inst_iter.hasNext()) {
DisabledInstancePorts *disabled_inst = disable_inst_iter.next();
2020-07-12 17:55:44 +02:00
setEdgeDisabledInstPorts(disabled_inst);
2020-05-19 22:07:52 +02:00
}
}
class DisableHpinEdgeVisitor : public HierPinThruVisitor
{
public:
2020-07-12 17:55:44 +02:00
DisableHpinEdgeVisitor(Graph *graph);
2020-05-19 22:07:52 +02:00
virtual void visit(Pin *from_pin,
Pin *to_pin);
protected:
bool annotate_;
Graph *graph_;
private:
DISALLOW_COPY_AND_ASSIGN(DisableHpinEdgeVisitor);
};
2020-07-12 17:55:44 +02:00
DisableHpinEdgeVisitor::DisableHpinEdgeVisitor(Graph *graph) :
2020-05-19 22:07:52 +02:00
HierPinThruVisitor(),
graph_(graph)
{
}
void
DisableHpinEdgeVisitor::visit(Pin *from_pin,
Pin *to_pin)
{
2020-07-12 17:55:44 +02:00
annotateGraphDisabledWireEdge(from_pin, to_pin, graph_);
2020-05-19 22:07:52 +02:00
}
static void
annotateGraphDisabledWireEdge(Pin *from_pin,
Pin *to_pin,
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)
2020-07-12 17:55:44 +02:00
edge->setIsDisabledConstraint(true);
2020-05-19 22:07:52 +02:00
}
}
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraphDisabled(const Pin *pin)
2020-05-19 22:07:52 +02:00
{
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
2020-07-12 17:55:44 +02:00
vertex->setIsDisabledConstraint(true);
2020-05-19 22:07:52 +02:00
if (bidirect_drvr_vertex)
2020-07-12 17:55:44 +02:00
bidirect_drvr_vertex->setIsDisabledConstraint(true);
2020-05-19 22:07:52 +02:00
}
void
2020-07-12 17:55:44 +02:00
Sdc::setEdgeDisabledInstPorts(DisabledInstancePorts *disabled_inst)
2020-05-19 22:07:52 +02:00
{
2020-07-12 17:55:44 +02:00
setEdgeDisabledInstPorts(disabled_inst, disabled_inst->instance());
2020-05-19 22:07:52 +02:00
}
void
Sdc::setEdgeDisabledInstPorts(DisabledPorts *disabled_port,
2020-07-12 17:55:44 +02:00
Instance *inst)
2020-05-19 22:07:52 +02:00
{
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.
2020-07-12 17:55:44 +02:00
setEdgeDisabledInstFrom(pin, false);
2020-05-19 22:07:52 +02:00
}
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)
2020-07-12 17:55:44 +02:00
setEdgeDisabledInstFrom(from_pin, true);
2020-05-19 22:07:52 +02:00
}
// 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();
2020-07-12 17:55:44 +02:00
edge->setIsDisabledConstraint(true);
2020-05-19 22:07:52 +02:00
}
}
}
}
}
// 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)
2020-07-12 17:55:44 +02:00
edge->setIsDisabledConstraint(true);
2020-05-19 22:07:52 +02:00
}
}
}
}
}
void
Sdc::setEdgeDisabledInstFrom(Pin *from_pin,
2020-07-12 17:55:44 +02:00
bool disable_checks)
2020-05-19 22:07:52 +02:00
{
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())
2020-07-12 17:55:44 +02:00
edge->setIsDisabledConstraint(true);
2020-05-19 22:07:52 +02:00
}
}
}
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraphOutputDelays()
2020-05-19 22:07:52 +02:00
{
for (OutputDelay *output_delay : output_delays_) {
for (Pin *lpin : output_delay->leafPins())
2020-07-12 17:55:44 +02:00
annotateGraphConstrained(lpin);
2020-05-19 22:07:52 +02:00
}
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraphDataChecks()
2020-05-19 22:07:52 +02:00
{
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();
2020-07-12 17:55:44 +02:00
annotateGraphConstrained(check->to());
2020-05-19 22:07:52 +02:00
}
}
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraphConstrained(const PinSet *pins)
2020-05-19 22:07:52 +02:00
{
PinSet::ConstIterator pin_iter(pins);
while (pin_iter.hasNext()) {
const Pin *pin = pin_iter.next();
2020-07-12 17:55:44 +02:00
annotateGraphConstrained(pin);
2020-05-19 22:07:52 +02:00
}
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraphConstrained(const InstanceSet *insts)
2020-05-19 22:07:52 +02:00
{
InstanceSet::ConstIterator inst_iter(insts);
while (inst_iter.hasNext()) {
const Instance *inst = inst_iter.next();
2020-07-12 17:55:44 +02:00
annotateGraphConstrained(inst);
2020-05-19 22:07:52 +02:00
}
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraphConstrained(const Instance *inst)
2020-05-19 22:07:52 +02:00
{
InstancePinIterator *pin_iter = network_->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
if (network_->direction(pin)->isAnyInput())
2020-07-12 17:55:44 +02:00
annotateGraphConstrained(pin);
2020-05-19 22:07:52 +02:00
}
delete pin_iter;
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateGraphConstrained(const Pin *pin)
2020-05-19 22:07:52 +02:00
{
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
// Pin may be hierarchical and have no vertex.
if (vertex)
2020-07-12 17:55:44 +02:00
vertex->setIsConstrained(true);
2020-05-19 22:07:52 +02:00
if (bidirect_drvr_vertex)
2020-07-12 17:55:44 +02:00
bidirect_drvr_vertex->setIsConstrained(true);
2020-05-19 22:07:52 +02:00
}
void
2020-07-12 17:55:44 +02:00
Sdc::annotateHierClkLatency()
2020-05-19 22:07:52 +02:00
{
2020-07-12 17:55:44 +02:00
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);
2020-05-19 22:07:52 +02:00
}
}
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;
}
}
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;
}
}
2020-07-12 17:55:44 +02:00
////////////////////////////////////////////////////////////////
2020-07-12 08:56:39 +02:00
2020-05-19 22:07:52 +02:00
void
2020-07-12 17:55:44 +02:00
Sdc::removeGraphAnnotations()
2020-05-19 22:07:52 +02:00
{
2020-07-12 17:55:44 +02:00
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
vertex->setIsDisabledConstraint(false);
vertex->setIsConstrained(false);
2020-05-19 22:07:52 +02:00
2020-07-12 17:55:44 +02:00
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
edge->setIsDisabledConstraint(false);
2020-05-19 22:07:52 +02:00
}
}
2020-07-12 17:55:44 +02:00
edge_clk_latency_.clear();
2020-05-19 22:07:52 +02:00
}
void
Sdc::searchPreamble()
{
ensureClkHpinDisables();
ensureClkGroupExclusions();
}
} // namespace