This commit is contained in:
James Cherry 2019-02-26 08:26:12 -08:00
parent 1af0963fd4
commit 0f2dba7eff
13 changed files with 141 additions and 70 deletions

View File

@ -657,7 +657,8 @@ GraphDelayCalc1::seedNoDrvrCellSlew(Vertex *drvr_vertex,
drive_delay = cap * drive_res;
slew = cap * drive_res;
}
if (!drvr_vertex->slewAnnotated(tr, ap_index))
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
if (!drvr_vertex->slewAnnotated(tr, slew_min_max))
graph_->setSlew(drvr_vertex, tr, ap_index, slew);
arc_delay_calc->inputPortDelay(drvr_pin, delayAsFloat(slew), tr,
parasitic, dcalc_ap);
@ -674,6 +675,7 @@ GraphDelayCalc1::seedNoDrvrSlew(Vertex *drvr_vertex,
DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc)
{
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
DcalcAPIndex ap_index = dcalc_ap->index();
Slew slew(default_slew);
// Top level bidirect driver uses load slew unless
@ -682,7 +684,7 @@ GraphDelayCalc1::seedNoDrvrSlew(Vertex *drvr_vertex,
Vertex *load_vertex = graph_->pinLoadVertex(drvr_pin);
slew = graph_->slew(load_vertex, tr, ap_index);
}
if (!drvr_vertex->slewAnnotated(tr, ap_index))
if (!drvr_vertex->slewAnnotated(tr, slew_min_max))
graph_->setSlew(drvr_vertex, tr, ap_index, slew);
Parasitic *parasitic;
bool delete_parasitic;
@ -711,8 +713,7 @@ GraphDelayCalc1::seedLoadSlew(Vertex *vertex)
while (ap_iter.hasNext()) {
DcalcAnalysisPt *dcalc_ap = ap_iter.next();
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
DcalcAPIndex ap_index = dcalc_ap->index();
if (!vertex->slewAnnotated(tr, ap_index)) {
if (!vertex->slewAnnotated(tr, slew_min_max)) {
float slew = 0.0;
if (clks) {
slew = slew_min_max->initValue();
@ -724,6 +725,7 @@ GraphDelayCalc1::seedLoadSlew(Vertex *vertex)
slew = clk_slew;
}
}
DcalcAPIndex ap_index = dcalc_ap->index();
graph_->setSlew(vertex, tr, ap_index, slew);
}
}
@ -988,11 +990,12 @@ GraphDelayCalc1::initRootSlews(Vertex *vertex)
DcalcAnalysisPtIterator ap_iter(this);
while (ap_iter.hasNext()) {
DcalcAnalysisPt *dcalc_ap = ap_iter.next();
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
DcalcAPIndex ap_index = dcalc_ap->index();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
if (!vertex->slewAnnotated(tr, ap_index))
if (!vertex->slewAnnotated(tr, slew_min_max))
graph_->setSlew(vertex, tr, ap_index, default_slew);
}
}
@ -1181,9 +1184,10 @@ GraphDelayCalc1::initSlew(Vertex *vertex)
while (ap_iter.hasNext()) {
DcalcAnalysisPt *dcalc_ap = ap_iter.next();
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
DcalcAPIndex ap_index = dcalc_ap->index();
if (!vertex->slewAnnotated(tr, ap_index))
if (!vertex->slewAnnotated(tr, slew_min_max)) {
DcalcAPIndex ap_index = dcalc_ap->index();
graph_->setSlew(vertex, tr, ap_index, slew_min_max->initValue());
}
}
}
}
@ -1213,7 +1217,7 @@ GraphDelayCalc1::initWireDelays(Vertex *drvr_vertex,
graph_->setWireArcDelay(wire_edge, tr, ap_index, delay_init_value);
// Init load vertex slew.
if (init_load_slews
&& !load_vertex->slewAnnotated(tr, ap_index))
&& !load_vertex->slewAnnotated(tr, slew_min_max))
graph_->setSlew(load_vertex, tr, ap_index, slew_init_value);
}
}
@ -1278,8 +1282,9 @@ GraphDelayCalc1::findArcDelay(LibertyCell *drvr_cell,
delayAsString(gate_slew, this));
// Merge slews.
const Slew &drvr_slew = graph_->slew(drvr_vertex, drvr_tr, ap_index);
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
if (delayFuzzyGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax())
&& !drvr_vertex->slewAnnotated(drvr_tr, ap_index))
&& !drvr_vertex->slewAnnotated(drvr_tr, slew_min_max))
graph_->setSlew(drvr_vertex, drvr_tr, ap_index, gate_slew);
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
const ArcDelay &prev_gate_delay = graph_->arcDelay(edge,arc,ap_index);
@ -1479,8 +1484,8 @@ GraphDelayCalc1::annotateLoadDelays(Vertex *drvr_vertex,
load_vertex->name(sdc_network_),
delayAsString(wire_delay, this),
delayAsString(load_slew, this));
if (!load_vertex->slewAnnotated(drvr_tr, ap_index)) {
if (drvr_vertex->slewAnnotated(drvr_tr, ap_index)) {
if (!load_vertex->slewAnnotated(drvr_tr, slew_min_max)) {
if (drvr_vertex->slewAnnotated(drvr_tr, slew_min_max)) {
// Copy the driver slew to the load if it is annotated.
const Slew &drvr_slew = graph_->slew(drvr_vertex,drvr_tr,ap_index);
graph_->setSlew(load_vertex, drvr_tr, ap_index, drvr_slew);

View File

@ -830,10 +830,14 @@ Graph::arcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAPIndex ap_index) const
{
unsigned index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
if (index >= arc_delay_annotated_.size())
internalError("arc_delay_annotated array bounds exceeded");
return arc_delay_annotated_[index];
if (arc_delay_annotated_.size()) {
unsigned index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
if (index >= arc_delay_annotated_.size())
internalError("arc_delay_annotated array bounds exceeded");
return arc_delay_annotated_[index];
}
else
return false;
}
void
@ -1162,6 +1166,8 @@ Vertex::init(Pin *pin,
color_ = vertex_color_white;
level_ = 0;
bfs_in_queue_ = 0;
crpr_path_pruning_disabled_ = false;
requireds_pruned_ = false;
}
const char *
@ -1191,13 +1197,9 @@ Vertex::setColor(VertexColor color)
bool
Vertex::slewAnnotated(const TransRiseFall *tr,
DcalcAPIndex ap_index) const
const MinMax *min_max) const
{
// Track rise/fall/min/max annotations separately, but after that
// only rise/fall.
if (ap_index > 1)
ap_index = 0;
int index = ap_index * transitionCount() + tr->index();
int index = min_max->index() * transitionCount() + tr->index();
return ((1 << index) & slew_annotated_) != 0;
}
@ -1229,6 +1231,18 @@ Vertex::removeSlewAnnotated()
slew_annotated_ = 0;
}
void
Vertex::setCrprPathPruningDisabled(bool disabled)
{
crpr_path_pruning_disabled_ = disabled;
}
void
Vertex::setRequiredsPruned(bool pruned)
{
requireds_pruned_ = pruned;
}
TagGroupIndex
Vertex::tagGroupIndex() const
{

View File

@ -284,7 +284,7 @@ public:
void setTagGroupIndex(TagGroupIndex tag_index);
// Slew is annotated by sdc set_annotated_transition cmd.
bool slewAnnotated(const TransRiseFall *tr,
DcalcAPIndex ap_index) const;
const MinMax *min_max) const;
// True if any rise/fall analysis pt slew is annotated.
bool slewAnnotated() const;
void setSlewAnnotated(bool annotated,
@ -316,6 +316,11 @@ public:
bool bfsInQueue(BfsIndex index) const;
void setBfsInQueue(BfsIndex index, bool value);
bool isRegClk() const { return is_reg_clk_; }
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
void setCrprPathPruningDisabled(bool disabled);
bool requiredsPruned() const { return requireds_pruned_; }
void setRequiredsPruned(bool pruned);
static int transitionCount() { return 2; } // rise/fall
protected:
@ -328,14 +333,23 @@ protected:
PathVertexRep *prev_paths_;
EdgeIndex in_edges_; // Edges to this vertex.
EdgeIndex out_edges_; // Edges from this vertex.
unsigned int tag_group_index_:tag_group_index_bits;
// 4 bytes
unsigned int tag_group_index_:tag_group_index_bits; // 24
// Each bit corresponds to a different BFS queue.
unsigned int bfs_in_queue_:bfs_index_bits; // 4
unsigned int slew_annotated_:slew_annotated_bits;
// 4 bytes (32 bits)
unsigned int level_:16;
// Levelization search state.
unsigned int color_:2;
unsigned int sim_value_:3; // LogicValue
bool has_requireds_:1;
unsigned int slew_annotated_:4;
// Bidirect pins have two vertices.
// This flag distinguishes the driver and load vertices.
bool is_bidirect_drvr_:1;
bool is_reg_clk_:1;
unsigned int sim_value_:3; // LogicValue
bool is_disabled_constraint_:1;
bool is_gated_clk_enable_:1;
// Constrained by timing check edge.
@ -344,11 +358,8 @@ protected:
bool is_check_clk_:1;
bool is_constrained_:1;
bool has_downstream_clk_pin_:1;
// Levelization search state.
unsigned int color_:2;
unsigned int level_:16;
// Each bit corresponds to a different BFS queue.
unsigned int bfs_in_queue_:bfs_index_bits;
bool crpr_path_pruning_disabled_:1;
bool requireds_pruned_:1;
private:
DISALLOW_COPY_AND_ASSIGN(Vertex);

View File

@ -20,6 +20,8 @@
#include "ObjectIndex.hh"
#include "Set.hh"
#include "Vector.hh"
#include "MinMax.hh"
#include "Transition.hh"
namespace sta {
@ -47,6 +49,7 @@ typedef Vector<GraphLoop*> GraphLoopSeq;
// 16,777,215 tags
static const int tag_group_index_bits = 24;
static const TagGroupIndex tag_group_index_max = (1<<tag_group_index_bits)-1;
static const int slew_annotated_bits = MinMax::index_count * TransRiseFall::index_count;
enum BfsIndex {
bfs_dcalc,

View File

@ -211,6 +211,12 @@ TimingArcSet::libertyCell() const
return NULL;
}
TimingArcSetArcIterator *
TimingArcSet::timingArcIterator()
{
return new TimingArcSetArcIterator(this);
}
TimingArcIndex
TimingArcSet::addTimingArc(TimingArc *arc)
{

View File

@ -164,6 +164,8 @@ public:
TimingArc *&arc1,
TimingArc *&arc2);
const TimingArcSeq &arcs() const { return arcs_; }
// Use the TimingArcSetArcIterator(arc_set) constructor instead.
TimingArcSetArcIterator *timingArcIterator();
TimingArcIndex addTimingArc(TimingArc *arc);
void deleteTimingArc(TimingArc *arc);
TimingArc *findTimingArc(unsigned arc_index);

View File

@ -261,7 +261,6 @@ Search::init(StaState *sta)
filter_ = NULL;
filter_from_ = NULL;
filter_to_ = NULL;
have_paths_ = false;
found_downstream_clk_pins_ = false;
}
@ -294,8 +293,8 @@ void
Search::clear()
{
crpr_path_pruning_enabled_ = true;
unconstrained_paths_ = false;
clk_arrivals_valid_ = false;
arrivals_exist_ = false;
arrivals_at_endpoints_exist_ = false;
arrivals_seeded_ = false;
requireds_exist_ = false;
@ -381,13 +380,13 @@ void
Search::deletePaths()
{
debugPrint0(debug_, "search", 1, "delete paths\n");
if (have_paths_) {
if (arrivals_exist_) {
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
deletePaths1(vertex);
}
have_paths_ = false;
arrivals_exist_ = false;
}
}
@ -662,7 +661,6 @@ Search::arrivalsInvalid()
deleteTags();
genclks_->clear();
deleteFilter();
arrivals_exist_ = false;
arrivals_at_endpoints_exist_ = false;
arrivals_seeded_ = false;
requireds_exist_ = false;
@ -1096,8 +1094,11 @@ ArrivalVisitor::visit(Vertex *vertex)
visitFaninPaths(vertex);
if (crpr_active_
&& search->crprPathPruningEnabled()
&& !vertex->crprPathPruningDisabled()
&& !has_fanin_one_)
pruneCrprArrivals();
vertex->setCrprPathPruningDisabled(false);
// Insert paths that originate here but
if (!network->isTopLevelPort(pin)
&& sdc->hasInputDelay(pin))
@ -2769,7 +2770,6 @@ Search::setVertexArrivals(Vertex *vertex,
vertex->setArrivals(arrivals);
vertex->setPrevPaths(prev_paths);
have_paths_ = true;
if (has_requireds) {
requiredInvalid(vertex);
vertex->setHasRequireds(false);
@ -3472,6 +3472,7 @@ RequiredVisitor::visit(Vertex *vertex)
debugPrint1(debug, "search", 2, "find required %s\n",
vertex->name(sta_->network()));
required_cmp_->requiredsInit(vertex, sta_);
vertex->setRequiredsPruned(false);
// Back propagate requireds from fanout.
visitFanoutPaths(vertex);
// Check for constraints at endpoints that set required times.
@ -3488,7 +3489,7 @@ RequiredVisitor::visit(Vertex *vertex)
bool
RequiredVisitor::visitFromToPath(const Pin *,
Vertex *,
Vertex *from_vertex,
const TransRiseFall *from_tr,
Tag *from_tag,
PathVertex *from_path,
@ -3500,7 +3501,7 @@ RequiredVisitor::visitFromToPath(const Pin *,
Tag *to_tag,
Arrival &,
const MinMax *min_max,
const PathAnalysisPt *path_ap)
const PathAnalysisPt *)
{
// Don't propagate required times through latch D->Q edges.
if (edge->role() != TimingRole::latchDtoQ()) {
@ -3533,31 +3534,11 @@ RequiredVisitor::visitFromToPath(const Pin *,
delayAsString(required_cmp_->required(arrival_index), sta_));
required_cmp_->requiredSet(arrival_index, from_required, req_min);
}
else {
// Arrival that differ by crpr_pin may be pruned. Find an arrival
// that matches everything but the crpr_pin.
VertexPathIterator to_iter(to_vertex, to_tr, path_ap, sta_);
while (to_iter.hasNext()) {
PathVertex *to_path = to_iter.next();
Tag *to_path_tag = to_path->tag(sta_);
if (tagMatchNoCrpr(to_path_tag, to_tag)) {
Required to_required = to_path->required(sta_);
Required from_required = to_required - arc_delay;
debugPrint2(debug, "search", 3, " to tag %2u: %s\n",
to_path_tag->index(),
to_path_tag->asString(sta_));
debugPrint5(debug, "search", 3, " %s - %s = %s %s %s\n",
delayAsString(to_required, sta_),
delayAsString(arc_delay, sta_),
delayAsString(from_required, sta_),
min_max == MinMax::max() ? "<" : ">",
delayAsString(required_cmp_->required(arrival_index),
sta_));
required_cmp_->requiredSet(arrival_index, from_required, req_min);
break;
}
}
}
else
from_vertex->setRequiredsPruned(true);
// Propagate requireds pruned flag backwards.
if (to_vertex->requiredsPruned())
from_vertex->setRequiredsPruned(true);
}
return true;
}

View File

@ -525,7 +525,6 @@ protected:
// findPathEnds arg.
bool unconstrained_paths_;
bool have_paths_;
// Search predicates.
SearchPred *search_adj_;
SearchPred *search_clk_;

View File

@ -2713,7 +2713,7 @@ Sta::vertexArrival(Vertex *vertex,
search_->findArrivals(vertex->level());
const MinMax *min_max = path_ap->pathMinMax();
Arrival arrival = min_max->initValue();
VertexPathIterator path_iter(vertex, tr, path_ap, search_);
VertexPathIterator path_iter(vertex, tr, path_ap, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
const Arrival &path_arrival = path->arrival(this);
@ -2744,7 +2744,7 @@ Sta::vertexRequired(Vertex *vertex,
findRequired(vertex);
const MinMax *min_max = path_ap->pathMinMax()->opposite();
Required required = min_max->initValue();
VertexPathIterator path_iter(vertex, tr, path_ap, search_);
VertexPathIterator path_iter(vertex, tr, path_ap, this);
while (path_iter.hasNext()) {
const Path *path = path_iter.next();
const Required path_required = path->required(this);
@ -2794,7 +2794,7 @@ Sta::vertexSlack(Vertex *vertex,
findRequired(vertex);
MinMax *min = MinMax::min();
Slack slack = min->initValue();
VertexPathIterator path_iter(vertex, search_);
VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
if (path->minMax(this) == min_max) {
@ -2813,7 +2813,7 @@ Sta::vertexSlack(Vertex *vertex,
{
findRequired(vertex);
Slack slack = MinMax::min()->initValue();
VertexPathIterator path_iter(vertex, tr, min_max, search_);
VertexPathIterator path_iter(vertex, tr, min_max, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
Slack path_slack = path->slack(this);
@ -2850,7 +2850,7 @@ Sta::vertexSlack1(Vertex *vertex,
{
MinMax *min = MinMax::min();
Slack slack = min->initValue();
VertexPathIterator path_iter(vertex, tr, path_ap, search_);
VertexPathIterator path_iter(vertex, tr, path_ap, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
Slack path_slack = path->slack(this);
@ -2868,6 +2868,44 @@ Sta::findRequired(Vertex *vertex)
searchPreamble();
search_->findAllArrivals();
search_->findRequireds(vertex->level());
if (sdc_->crprEnabled()
&& vertex->requiredsPruned()) {
debugPrint1(debug_, "search", 2, "resurrect pruned required %s\n",
vertex->name(sdc_network_));
// printf("resurrect pruned required %s\n", vertex->name(sdc_network_));
// Invalidate arrivals and requireds and disable
// path pruning on fanout vertices.
int fanout = 0;
disableFanoutCrprPruning(vertex, fanout);
// if (fanout > 100)
// printf("fanout %s %d\n", vertex->name(network_), fanout);
// Find fanout arrivals and requireds with pruning disabled.
search_->findArrivals();
search_->findRequireds(vertex->level());
}
}
// DFS to invalidate arrivals and requireds to
// find arrivals with pruning disabled.
void
Sta::disableFanoutCrprPruning(Vertex *vertex,
int &fanout)
{
if (!vertex->crprPathPruningDisabled()) {
search_->arrivalInvalid(vertex);
search_->requiredInvalid(vertex);
vertex->setCrprPathPruningDisabled(true);
fanout++;
SearchPred *pred = search_->searchAdj();
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph_);
if (pred->searchThru(edge)
&& pred->searchTo(to_vertex))
disableFanoutCrprPruning(to_vertex, fanout);
}
}
}
Slack

View File

@ -1297,6 +1297,8 @@ protected:
const MinMax *min_max);
void parasiticsChangedAfter();
void powerPreamble();
void disableFanoutCrprPruning(Vertex *vertex,
int &fanou);
CmdNamespace cmd_namespace_;
Instance *current_instance_;

View File

@ -1997,7 +1997,7 @@ private:
%inline %{
float float_inf = INF;
int group_count_max = PathGroup::group_count_max;
int group_count_max = PathGroup::group_count_max;
const char *
version()

View File

@ -17,6 +17,7 @@
#include <algorithm> // max
#include <cmath> // abs
#include "Machine.hh"
#include "MinMax.hh" // INF
namespace sta {
@ -66,4 +67,11 @@ fuzzyGreaterEqual(float v1,
return v1 > v2 || fuzzyEqual(v1, v2);
}
bool
fuzzyInf(float value)
{
return fuzzyEqual(value, INF)
|| fuzzyEqual(value, -INF);
}
} // namespace

View File

@ -35,5 +35,7 @@ fuzzyGreater(float v1,
bool
fuzzyGreaterEqual(float v1,
float v2);
bool
fuzzyInf(float value);
} // namespace