delay calculation ignore partial parasitic annotations
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
46c683814c
commit
1fae33d950
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,6 +314,7 @@ reduceToPiElmore(Parasitic *parasitic_network,
|
|||
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s",
|
||||
sta->network()->pathName(drvr_pin));
|
||||
ReduceToPiElmore reducer(sta);
|
||||
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) {
|
||||
reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, RiseFall::rise(),
|
||||
op_cond, corner, cnst_min_max, ap);
|
||||
|
|
@ -323,6 +324,7 @@ reduceToPiElmore(Parasitic *parasitic_network,
|
|||
op_cond, corner, cnst_min_max, ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReduceToPiElmore::ReduceToPiElmore(StaState *sta) :
|
||||
ReduceToPi(sta)
|
||||
|
|
@ -479,6 +481,7 @@ reduceToPiPoleResidue2(Parasitic *parasitic_network,
|
|||
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s",
|
||||
sta->network()->pathName(drvr_pin));
|
||||
ReduceToPiPoleResidue2 reducer(sta);
|
||||
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) {
|
||||
reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, RiseFall::rise(),
|
||||
op_cond, corner, cnst_min_max, ap);
|
||||
|
|
@ -488,6 +491,7 @@ reduceToPiPoleResidue2(Parasitic *parasitic_network,
|
|||
op_cond, corner, cnst_min_max, ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReduceToPiPoleResidue2::makePiPoleResidue2(Parasitic *parasitic_network,
|
||||
|
|
|
|||
|
|
@ -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,69 +79,43 @@ 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)
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue