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)
|
cmake_policy(SET CMP0086 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(STA VERSION 2.3.2
|
project(STA VERSION 2.3.3
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue