delay calculation ignore partial parasitic annotations

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-12-25 16:46:48 -07:00
parent 46c683814c
commit 1fae33d950
6 changed files with 143 additions and 65 deletions

View File

@ -24,7 +24,7 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14)
cmake_policy(SET CMP0086 NEW) cmake_policy(SET CMP0086 NEW)
endif() endif()
project(STA VERSION 2.3.2 project(STA VERSION 2.3.3
LANGUAGES CXX LANGUAGES CXX
) )

View File

@ -224,6 +224,15 @@ public:
virtual ParasiticNode *otherNode(const ParasiticDevice *device, virtual ParasiticNode *otherNode(const ParasiticDevice *device,
ParasiticNode *node) const = 0; ParasiticNode *node) const = 0;
// Return true if all loads are annoatated.
virtual bool checkAnnotation(Parasitic *parasitic_network,
const Pin *drvr_pin) = 0;
virtual bool checkAnnotation(const Pin *drvr_pin,
ParasiticNode *drvr_node) = 0;
// Return loads missing path from driver.
virtual PinSet unannotatedLoads(Parasitic *parasitic_network,
const Pin *drvr_pin) = 0;
// Reduce parasitic network to reduce_to model. // Reduce parasitic network to reduce_to model.
virtual void reduceTo(Parasitic *parasitic, virtual void reduceTo(Parasitic *parasitic,
const Net *net, const Net *net,

View File

@ -1610,6 +1610,82 @@ ConcreteParasitics::otherNode(const ParasiticDevice *device,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
bool
ConcreteParasitics::checkAnnotation(Parasitic *parasitic_network,
const Pin *drvr_pin)
{
ParasiticNode *drvr_node = findNode(parasitic_network, drvr_pin);
if (drvr_node)
return checkAnnotation(drvr_pin, drvr_node);
return false;
}
bool
ConcreteParasitics::checkAnnotation(const Pin *drvr_pin,
ParasiticNode *drvr_node)
{
PinSet unannotated_loads = checkAnnotation1(drvr_pin, drvr_node);
return unannotated_loads.empty();
}
PinSet
ConcreteParasitics::unannotatedLoads(Parasitic *parasitic_network,
const Pin *drvr_pin)
{
ParasiticNode *drvr_node = findNode(parasitic_network, drvr_pin);
if (drvr_node)
return checkAnnotation1(drvr_pin, drvr_node);
return PinSet();
}
PinSet
ConcreteParasitics::checkAnnotation1(const Pin *drvr_pin,
ParasiticNode *drvr_node)
{
PinSet loads;
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
if (network_->isLoad(pin) && !network_->isHierarchical(pin))
loads.insert(pin);
}
delete pin_iter;
ParasiticNodeSet visited_nodes;
checkAnnotation2(drvr_pin, drvr_node, nullptr, loads, visited_nodes);
return loads;
}
void
ConcreteParasitics::checkAnnotation2(const Pin *drvr_pin,
ParasiticNode *node,
ParasiticDevice *from_res,
PinSet &loads,
ParasiticNodeSet &visited_nodes)
{
const Pin *pin = parasitics_->connectionPin(node);
if (pin)
loads.erase(const_cast<Pin*>(pin));
visited_nodes.insert(node);
ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node);
while (device_iter->hasNext()) {
ParasiticDevice *device = device_iter->next();
if (parasitics_->isResistor(device)) {
ParasiticNode *onode = parasitics_->otherNode(device, node);
// One commercial extractor creates resistors with identical from/to nodes.
if (onode != node
&& device != from_res
&& visited_nodes.find(onode) == visited_nodes.end())
checkAnnotation2(drvr_pin, onode, device, loads, visited_nodes);
}
}
delete device_iter;
visited_nodes.erase(node);
}
////////////////////////////////////////////////////////////////
void void
ConcreteParasitics::reduceTo(Parasitic *parasitic, ConcreteParasitics::reduceTo(Parasitic *parasitic,
const Net *net, const Net *net,

View File

@ -35,6 +35,7 @@ class ConcreteParasiticDevice;
typedef Map<const Pin*, ConcreteParasitic**> ConcreteParasiticMap; typedef Map<const Pin*, ConcreteParasitic**> ConcreteParasiticMap;
typedef Map<const Net*, ConcreteParasiticNetwork**> ConcreteParasiticNetworkMap; typedef Map<const Net*, ConcreteParasiticNetwork**> ConcreteParasiticNetworkMap;
typedef Set<ParasiticNode*> ParasiticNodeSet;
// This class acts as a BUILDER for all parasitics. // This class acts as a BUILDER for all parasitics.
class ConcreteParasitics : public Parasitics, public EstimateParasitics class ConcreteParasitics : public Parasitics, public EstimateParasitics
@ -150,6 +151,15 @@ public:
virtual ParasiticNode *otherNode(const ParasiticDevice *device, virtual ParasiticNode *otherNode(const ParasiticDevice *device,
ParasiticNode *node) const; ParasiticNode *node) const;
// Return true if all loads are annoatated.
virtual bool checkAnnotation(Parasitic *parasitic_network,
const Pin *drvr_pin);
virtual bool checkAnnotation(const Pin *drvr_pin,
ParasiticNode *drvr_node);
// Return loads missing path from driver.
virtual PinSet unannotatedLoads(Parasitic *parasitic_network,
const Pin *drvr_pin);
virtual Parasitic *estimatePiElmore(const Pin *drvr_pin, virtual Parasitic *estimatePiElmore(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const Wireload *wireload, const Wireload *wireload,
@ -205,6 +215,13 @@ protected:
void deleteReducedParasitics(const Pin *pin); void deleteReducedParasitics(const Pin *pin);
void deleteDrvrReducedParasitics(const Pin *drvr_pin, void deleteDrvrReducedParasitics(const Pin *drvr_pin,
const ParasiticAnalysisPt *ap); const ParasiticAnalysisPt *ap);
PinSet checkAnnotation1(const Pin *drvr_pin,
ParasiticNode *drvr_node);
void checkAnnotation2(const Pin *drvr_pin,
ParasiticNode *node,
ParasiticDevice *from_res,
PinSet &loads,
ParasiticNodeSet &visited_nodes);
// Driver pin to array of parasitics indexed by analysis pt index // Driver pin to array of parasitics indexed by analysis pt index
// and transition. // and transition.

View File

@ -31,8 +31,8 @@ using std::max;
typedef Map<ParasiticNode*, double> ParasiticNodeValueMap; typedef Map<ParasiticNode*, double> ParasiticNodeValueMap;
typedef Map<ParasiticDevice*, double> ParasiticDeviceValueMap; typedef Map<ParasiticDevice*, double> ParasiticDeviceValueMap;
typedef Set<ParasiticNode*> ParasiticNodeSet;
typedef Set<ParasiticDevice*> ParasiticDeviceSet; typedef Set<ParasiticDevice*> ParasiticDeviceSet;
typedef Set<ParasiticNode*> ParasiticNodeSet;
class ReduceToPi : public StaState class ReduceToPi : public StaState
{ {
@ -314,6 +314,7 @@ reduceToPiElmore(Parasitic *parasitic_network,
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s", debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s",
sta->network()->pathName(drvr_pin)); sta->network()->pathName(drvr_pin));
ReduceToPiElmore reducer(sta); ReduceToPiElmore reducer(sta);
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) {
reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node, reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
coupling_cap_factor, RiseFall::rise(), coupling_cap_factor, RiseFall::rise(),
op_cond, corner, cnst_min_max, ap); op_cond, corner, cnst_min_max, ap);
@ -323,6 +324,7 @@ reduceToPiElmore(Parasitic *parasitic_network,
op_cond, corner, cnst_min_max, ap); op_cond, corner, cnst_min_max, ap);
} }
} }
}
ReduceToPiElmore::ReduceToPiElmore(StaState *sta) : ReduceToPiElmore::ReduceToPiElmore(StaState *sta) :
ReduceToPi(sta) ReduceToPi(sta)
@ -479,6 +481,7 @@ reduceToPiPoleResidue2(Parasitic *parasitic_network,
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s", debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s",
sta->network()->pathName(drvr_pin)); sta->network()->pathName(drvr_pin));
ReduceToPiPoleResidue2 reducer(sta); ReduceToPiPoleResidue2 reducer(sta);
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) {
reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node, reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node,
coupling_cap_factor, RiseFall::rise(), coupling_cap_factor, RiseFall::rise(),
op_cond, corner, cnst_min_max, ap); op_cond, corner, cnst_min_max, ap);
@ -488,6 +491,7 @@ reduceToPiPoleResidue2(Parasitic *parasitic_network,
op_cond, corner, cnst_min_max, ap); op_cond, corner, cnst_min_max, ap);
} }
} }
}
void void
ReduceToPiPoleResidue2::makePiPoleResidue2(Parasitic *parasitic_network, ReduceToPiPoleResidue2::makePiPoleResidue2(Parasitic *parasitic_network,

View File

@ -18,6 +18,7 @@
#include "Report.hh" #include "Report.hh"
#include "Network.hh" #include "Network.hh"
#include "NetworkCmp.hh"
#include "Graph.hh" #include "Graph.hh"
#include "Corner.hh" #include "Corner.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
@ -43,10 +44,9 @@ private:
bool report_unannotated_; bool report_unannotated_;
const Corner *corner_; const Corner *corner_;
const MinMax *min_max_; const MinMax *min_max_;
const DcalcAnalysisPt *dcalc_ap_; const ParasiticAnalysisPt *parasitic_ap_;
const ParasiticAnalysisPt *parasitics_ap_; PinSeq unannotated_;
NetSet unannotated_nets_; PinSeq partially_annotated_;
VertexSet partially_annotated_drvrs_;
}; };
void void
@ -65,9 +65,7 @@ ReportParasiticAnnotation::ReportParasiticAnnotation(bool report_unannotated,
report_unannotated_(report_unannotated), report_unannotated_(report_unannotated),
corner_(corner), corner_(corner),
min_max_(MinMax::max()), min_max_(MinMax::max()),
dcalc_ap_(corner_->findDcalcAnalysisPt(min_max_)), parasitic_ap_(corner_->findParasiticAnalysisPt(min_max_))
parasitics_ap_(corner_->findParasiticAnalysisPt(min_max_)),
partially_annotated_drvrs_(graph_)
{ {
} }
@ -81,69 +79,43 @@ ReportParasiticAnnotation::report()
void void
ReportParasiticAnnotation::reportAnnotationCounts() ReportParasiticAnnotation::reportAnnotationCounts()
{ {
report_->reportLine("Found %lu unannotated nets.", unannotated_nets_.size()); report_->reportLine("Found %lu unannotated drivers.", unannotated_.size());
if (report_unannotated_) { if (report_unannotated_) {
for (const Net *net : unannotated_nets_) sort(unannotated_, PinPathNameLess(network_));
report_->reportLine(" %s", network_->pathName(net)); for (Pin *drvr_pin : unannotated_)
report_->reportLine(" %s", network_->pathName(drvr_pin));
} }
report_->reportLine("Found %lu partially unannotated nets.", report_->reportLine("Found %lu partially unannotated drivers.",
partially_annotated_drvrs_.size()); partially_annotated_.size());
if (report_unannotated_) { if (report_unannotated_) {
const RiseFall *rf = RiseFall::rise(); sort(partially_annotated_, PinPathNameLess(network_));
for (Vertex *vertex : partially_annotated_drvrs_) { for (Pin *drvr_pin : partially_annotated_) {
Pin *drvr_pin = vertex->pin(); report_->reportLine(" %s", network_->pathName(drvr_pin));
Net *net = network_->isTopLevelPort(drvr_pin)
? network_->net(network_->term(drvr_pin))
: network_->net(drvr_pin);
report_->reportLine(" %s", network_->pathName(net));
Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap_); Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap_);
VertexOutEdgeIterator edge_iter(vertex, graph_); PinSet unannotated_loads = parasitics_->unannotatedLoads(parasitic, drvr_pin);
while (edge_iter.hasNext()) { for (Pin *load_pin : unannotated_loads)
Edge *edge = edge_iter.next();
Vertex *load_vertex = edge->to(graph_);
Pin *load_pin = load_vertex->pin();
bool elmore_exists = false;
float elmore = 0.0;
parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists);
if (!elmore_exists)
report_->reportLine(" %s", network_->pathName(load_pin)); report_->reportLine(" %s", network_->pathName(load_pin));
} }
} }
} }
}
void void
ReportParasiticAnnotation::findCounts() ReportParasiticAnnotation::findCounts()
{ {
const RiseFall *rf = RiseFall::rise();
VertexIterator vertex_iter(graph_); VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) { while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
if (vertex->isDriver(network_)) { if (vertex->isDriver(network_)) {
Pin *drvr_pin = vertex->pin(); Pin *drvr_pin = vertex->pin();
Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap_); Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap_);
if (parasitic) { if (parasitic) {
VertexOutEdgeIterator edge_iter(vertex, graph_); if (!parasitics_->checkAnnotation(parasitic, drvr_pin))
while (edge_iter.hasNext()) { partially_annotated_.push_back(drvr_pin);
Edge *edge = edge_iter.next();
Vertex *load_vertex = edge->to(graph_);
Pin *load_pin = load_vertex->pin();
bool elmore_exists = false;
float elmore = 0.0;
parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists);
if (!elmore_exists)
partially_annotated_drvrs_.insert(vertex);
}
}
else {
Net *net = network_->isTopLevelPort(drvr_pin)
? network_->net(network_->term(drvr_pin))
: network_->net(drvr_pin);
if (net)
unannotated_nets_.insert(net);
} }
else
unannotated_.push_back(drvr_pin);
} }
} }
} }