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)
endif()
project(STA VERSION 2.3.2
project(STA VERSION 2.3.3
LANGUAGES CXX
)

View File

@ -224,6 +224,15 @@ public:
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
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.
virtual void reduceTo(Parasitic *parasitic,
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
ConcreteParasitics::reduceTo(Parasitic *parasitic,
const Net *net,

View File

@ -35,6 +35,7 @@ class ConcreteParasiticDevice;
typedef Map<const Pin*, ConcreteParasitic**> ConcreteParasiticMap;
typedef Map<const Net*, ConcreteParasiticNetwork**> ConcreteParasiticNetworkMap;
typedef Set<ParasiticNode*> ParasiticNodeSet;
// This class acts as a BUILDER for all parasitics.
class ConcreteParasitics : public Parasitics, public EstimateParasitics
@ -150,6 +151,15 @@ public:
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
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,
const RiseFall *rf,
const Wireload *wireload,
@ -205,6 +215,13 @@ protected:
void deleteReducedParasitics(const Pin *pin);
void deleteDrvrReducedParasitics(const Pin *drvr_pin,
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
// and transition.

View File

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

View File

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