sdc non-incr graph annotation
This commit is contained in:
parent
d45a28a258
commit
da94fbe6ef
464
sdc/Sdc.cc
464
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<Pvt*> 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
|
||||
|
|
|
|||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
#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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue