2018/11/08 corners > 2 causes internal error, 2018/11/09 Verilog ignore attributes (* blah *)

This commit is contained in:
James Cherry 2018-11-09 10:04:16 -08:00
parent 7592f12e54
commit e9bde796ec
28 changed files with 686 additions and 456 deletions

View File

@ -412,7 +412,7 @@ AC_FUNC_ERROR_AT_LINE
if test $CXX = clang++; then
# -Wno-deprecated-register to suppress warnings in flex files
CXXFLAGS="-std=c++11 -Wno-deprecated-register -Wcast-qual -pipe"
CXXFLAGS="-std=c++11 -Wall -Wno-deprecated-register -Wcast-qual"
CXX_OPT="-O3"
CXX_DEBUG="-g"
CXX_ASAN="-fsanitize=address -O1 -fno-omit-frame-pointer"

View File

@ -1202,7 +1202,7 @@ GraphDelayCalc1::initWireDelays(Vertex *drvr_vertex,
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
if (!wire_edge->wireDelayAnnotated(tr, ap_index))
if (!graph_->wireDelayAnnotated(wire_edge, tr, ap_index))
graph_->setWireArcDelay(wire_edge, tr, ap_index, delay_init_value);
// Init load vertex slew.
if (init_load_slews
@ -1274,7 +1274,7 @@ GraphDelayCalc1::findArcDelay(LibertyCell *drvr_cell,
if (delayFuzzyGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax())
&& !drvr_vertex->slewAnnotated(drvr_tr, ap_index))
graph_->setSlew(drvr_vertex, drvr_tr, ap_index, gate_slew);
if (!edge->arcDelayAnnotated(arc, ap_index)) {
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
const ArcDelay &prev_gate_delay = graph_->arcDelay(edge,arc,ap_index);
float gate_delay1 = delayAsFloat(gate_delay);
float prev_gate_delay1 = delayAsFloat(prev_gate_delay);
@ -1486,7 +1486,7 @@ GraphDelayCalc1::annotateLoadDelays(Vertex *drvr_vertex,
graph_->setSlew(load_vertex, drvr_tr, ap_index, load_slew);
}
}
if (!wire_edge->wireDelayAnnotated(drvr_tr, ap_index)) {
if (!graph_->wireDelayAnnotated(wire_edge, drvr_tr, ap_index)) {
// Multiple timing arcs with the same output transition
// annotate the same wire edges so they must be combined
// rather than set.
@ -1570,7 +1570,7 @@ GraphDelayCalc1::findCheckEdgeDelays(Edge *edge,
while (ap_iter.hasNext()) {
DcalcAnalysisPt *dcalc_ap = ap_iter.next();
DcalcAPIndex ap_index = dcalc_ap->index();
if (!edge->arcDelayAnnotated(arc, ap_index)) {
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
const Pvt *pvt = sdc_->pvt(inst,dcalc_ap->constraintMinMax());
if (pvt == NULL)
pvt = dcalc_ap->operatingConditions();

View File

@ -2,3 +2,5 @@ Release 2.0 Patches
-------------------
2018/10/23 spash msg embedded quotes seg fault
2018/10/23 read_verilog mod inst with no ports seg fault
2018/11/08 corners > 2 causes internal error
2018/11/09 Verilog ignore attributes (* blah *)

View File

@ -714,6 +714,9 @@ Graph::makeArcDelayPools(ArcIndex arc_count,
DelayPool *pool = new DelayPool(arc_count);
arc_delays_[i] = pool;
}
unsigned annot_size = arc_count * 1.2;
arc_delay_annotated_.resize(annot_size * ap_count);
}
}
@ -743,6 +746,13 @@ Graph::makeEdgeArcDelays(Edge *edge)
*arc_delays++ = 0.0;
}
edge->setArcDelays(arc_index);
// Make sure there is room for delay_annotated flags.
unsigned max_annot_index = arc_index + (arc_count * ap_count_);
if (max_annot_index >= arc_delay_annotated_.size()) {
unsigned size = max_annot_index * 1.2;
arc_delay_annotated_.resize(size);
}
removeDelayAnnotated(edge);
}
}
@ -817,6 +827,46 @@ Graph::setWireArcDelay(Edge *edge,
}
}
bool
Graph::arcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAPIndex ap_index) const
{
int index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
return arc_delay_annotated_[index];
}
void
Graph::setArcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAPIndex ap_index,
bool annotated)
{
int index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
arc_delay_annotated_[index] = annotated;
}
bool
Graph::wireDelayAnnotated(Edge *edge,
const TransRiseFall *tr,
DcalcAPIndex ap_index) const
{
int index = (edge->arcDelays() + TimingArcSet::wireArcIndex(tr)) * ap_count_
+ ap_index;
return arc_delay_annotated_[index];
}
void
Graph::setWireDelayAnnotated(Edge *edge,
const TransRiseFall *tr,
DcalcAPIndex ap_index,
bool annotated)
{
int index = (edge->arcDelays() + TimingArcSet::wireArcIndex(tr)) * ap_count_
+ ap_index;
arc_delay_annotated_[index] = annotated;
}
// This only gets called if the analysis type changes from single
// to bc_wc/ocv or visa versa.
void
@ -846,11 +896,41 @@ Graph::removeDelays()
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
makeEdgeArcDelays(edge);
edge->removeDelayAnnotated();
removeDelayAnnotated(edge);
}
}
}
void
Graph::removeDelayAnnotated(Edge *edge)
{
edge->setDelayAnnotationIsIncremental(false);
TimingArcSet *arc_set = edge->timingArcSet();
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
while (arc_iter->hasNext()) {
TimingArc *arc = arc_iter->next();
for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) {
setArcDelayAnnotated(edge, arc, ap_index, false);
}
}
delete arc_iter;
}
bool
Graph::delayAnnotated(Edge *edge)
{
TimingArcSet *arc_set = edge->timingArcSet();
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
while (arc_iter->hasNext()) {
TimingArc *arc = arc_iter->next();
for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) {
if (arcDelayAnnotated(edge, arc, ap_index))
return true;
}
}
return false;
}
void
Graph::makeSlewPools(VertexIndex vertex_count,
DcalcAPIndex ap_count)
@ -1019,7 +1099,7 @@ Graph::removeDelaySlewAnnotations()
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
edge->removeDelayAnnotated();
removeDelayAnnotated(edge);
}
vertex->removeSlewAnnotated();
}
@ -1272,7 +1352,6 @@ Edge::init(VertexIndex from,
vertex_out_prev_ = 0;
is_bidirect_inst_path_ = false;
is_bidirect_net_path_ = false;
delay_annotated_ = false;
delay_annotation_is_incremental_ = false;
sim_timing_sense_ = timing_sense_unknown;
is_disabled_constraint_ = false;
@ -1292,62 +1371,6 @@ Edge::setArcDelays(ArcIndex arc_delays)
arc_delays_ = arc_delays;
}
bool
Edge::arcDelayAnnotated() const
{
return delay_annotated_ != 0;
}
bool
Edge::arcDelayAnnotated(TimingArc *arc,
DcalcAPIndex ap_index) const
{
int bit_index = ap_index * arc_set_->arcCount() + arc->index();
if (bit_index >= delay_annotation_bit_count)
internalError("arc annotation bit index out of range");
return (delay_annotated_ & (1 << bit_index)) != 0;
}
void
Edge::setArcDelayAnnotated(bool annotated,
TimingArc *arc,
DcalcAPIndex ap_index)
{
int bit_index = ap_index * arc_set_->arcCount() + arc->index();
if (bit_index >= delay_annotation_bit_count)
internalError("arc annotation bit index out of range");
if (annotated)
delay_annotated_ |= (1 << bit_index);
else
delay_annotated_ &= ~(1 << bit_index);
}
bool
Edge::wireDelayAnnotated(const TransRiseFall *tr,
DcalcAPIndex ap_index) const
{
int bit_index = ap_index * TimingArcSet::wireArcCount()
+ TimingArcSet::wireArcIndex(tr);
if (bit_index >= delay_annotation_bit_count)
internalError("arc annotation bit index out of range");
return (delay_annotated_ & (1 << bit_index)) != 0;
}
void
Edge::setWireDelayAnnotated(bool annotated,
const TransRiseFall *tr,
DcalcAPIndex ap_index)
{
int bit_index = ap_index * TimingArcSet::wireArcCount()
+ TimingArcSet::wireArcIndex(tr);
if (bit_index >= delay_annotation_bit_count)
internalError("arc annotation bit index out of range");
if (annotated)
delay_annotated_ |= (1 << bit_index);
else
delay_annotated_ &= ~(1 << bit_index);
}
bool
Edge::delayAnnotationIsIncremental() const
{
@ -1357,19 +1380,9 @@ Edge::delayAnnotationIsIncremental() const
void
Edge::setDelayAnnotationIsIncremental(bool is_incr)
{
if (delay_annotated_ != 0
&& is_incr != delay_annotation_is_incremental_)
delay_annotated_ = 0;
delay_annotation_is_incremental_ = is_incr;
}
void
Edge::removeDelayAnnotated()
{
delay_annotated_ = 0;
delay_annotation_is_incremental_ = false;
}
TimingRole *
Edge::role() const
{

View File

@ -128,6 +128,23 @@ public:
const TransRiseFall *tr,
DcalcAPIndex ap_index,
const ArcDelay &delay);
// Is timing arc delay annotated.
bool arcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAPIndex ap_index) const;
void setArcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAPIndex ap_index,
bool annotated);
bool wireDelayAnnotated(Edge *edge,
const TransRiseFall *tr,
DcalcAPIndex ap_index) const;
void setWireDelayAnnotated(Edge *edge,
const TransRiseFall *tr,
DcalcAPIndex ap_index,
bool annotated);
// True if any edge arc is annotated.
bool delayAnnotated(Edge *edge);
EdgeIndex edgeCount() { return edge_count_; }
virtual ArcIndex arcCount() { return arc_count_; }
@ -205,6 +222,7 @@ protected:
float *makeFloats(ObjectIndex count);
void deleteFloats(float *floats,
ObjectIndex count);
void removeDelayAnnotated(Edge *edge);
VertexPool *vertices_;
EdgePool *edges_;
@ -216,6 +234,7 @@ protected:
VertexIndex vertex_count_;
EdgeIndex edge_count_;
ArcIndex arc_count_;
Vector<bool> arc_delay_annotated_;
int slew_tr_count_;
bool have_arc_delays_;
DcalcAPIndex ap_count_;
@ -339,11 +358,6 @@ private:
friend class VertexOutEdgeIterator;
};
#define max_dcalc_analysis_pt_count 4
// One annotation bit per timing arc per delay calculation analysis point.
#define delay_annotation_bit_count \
((timing_arc_index_max + 1) * max_dcalc_analysis_pt_count)
// There is one Edge between each pair of pins that has a timing
// path between them.
class Edge
@ -359,20 +373,6 @@ public:
void setTimingArcSet(TimingArcSet *set);
ArcIndex arcDelays() const { return arc_delays_; }
void setArcDelays(ArcIndex arc_delays);
// True if any timing arc delay is annotated.
bool arcDelayAnnotated() const;
// Is timing arc delay annotated.
bool arcDelayAnnotated(TimingArc *arc,
DcalcAPIndex ap_index) const;
void setArcDelayAnnotated(bool annotated,
TimingArc *arc,
DcalcAPIndex ap_index);
bool wireDelayAnnotated(const TransRiseFall *tr,
DcalcAPIndex ap_index) const;
void setWireDelayAnnotated(bool annotated,
const TransRiseFall *tr,
DcalcAPIndex ap_index);
void removeDelayAnnotated();
bool delayAnnotationIsIncremental() const;
void setDelayAnnotationIsIncremental(bool is_incr);
// Edge is disabled by set_disable_timing constraint.
@ -406,8 +406,6 @@ protected:
VertexIndex vertex_out_next_; // Vertex out edges doubly linked list.
VertexIndex vertex_out_prev_;
ArcIndex arc_delays_;
// Timing arcs with sdf annotation.
unsigned int delay_annotated_:delay_annotation_bit_count;
unsigned int delay_annotation_is_incremental_:1;
unsigned int is_bidirect_inst_path_:1;
unsigned int is_bidirect_net_path_:1;

View File

@ -40,11 +40,6 @@ TransRiseFall::destroy()
fall_ = NULL;
}
TransRiseFall::~TransRiseFall()
{
stringDelete(short_name_);
}
TransRiseFall::TransRiseFall(const char *name,
const char *short_name,
int sdf_triple_index) :
@ -54,9 +49,15 @@ TransRiseFall::TransRiseFall(const char *name,
{
}
TransRiseFall::~TransRiseFall()
{
stringDelete(short_name_);
}
void
TransRiseFall::setShortName(const char *short_name)
{
stringDelete(short_name_);
short_name_ = stringCopy(short_name);
}
@ -152,6 +153,11 @@ TransRiseFallBoth::TransRiseFallBoth(const char *name,
{
}
TransRiseFallBoth::~TransRiseFallBoth()
{
stringDelete(short_name_);
}
TransRiseFallBoth *
TransRiseFallBoth::find(const char *tr_str)
{
@ -185,6 +191,7 @@ TransRiseFallBoth::matches(const Transition *tr) const
void
TransRiseFallBoth::setShortName(const char *short_name)
{
stringDelete(short_name_);
short_name_ = stringCopy(short_name);
}
@ -289,6 +296,7 @@ Transition::asRiseFallBoth() const
void
Transition::setName(const char *name)
{
stringDelete(name_);
name_ = stringCopy(name);
}

View File

@ -106,6 +106,7 @@ protected:
const char *short_name,
int sdf_triple_index,
TransRiseFall *as_rise_fall);
~TransRiseFallBoth();
const char *name_;
const char *short_name_;

View File

@ -98,6 +98,7 @@ Sdc::Sdc(StaState *sta) :
clk_index_(0),
clk_insertions_(NULL),
clk_group_exclusions_(NULL),
clk_group_same_(NULL),
clk_sense_map_(network_),
clk_gating_check_(NULL),
input_delay_index_(0),
@ -2082,6 +2083,7 @@ Sdc::ensureClkGroupExclusions()
{
if (clk_group_exclusions_ == NULL) {
clk_group_exclusions_ = new ClockPairSet;
clk_group_same_ = new ClockPairSet;
ClockGroupsNameMap::Iterator groups_iter(clk_groups_name_map_);
while (groups_iter.hasNext()) {
ClockGroups *clk_groups = groups_iter.next();
@ -2096,54 +2098,85 @@ Sdc::makeClkGroupExclusions(ClockGroups *clk_groups)
if (!(clk_groups->asynchronous()
&& clk_groups->allowPaths())) {
ClockGroupSet *groups = clk_groups->groups();
if (groups->size() == 1) {
// If there is only one group all clocks not in the group
// are excluded.
ClockGroupSet::Iterator group_iter1(groups);
ClockGroup *group1 = group_iter1.next();
ClockSet *clks1 = group1->clks();
ClockSet::Iterator clk_iter1(clks1);
while (clk_iter1.hasNext()) {
Clock *clk1 = clk_iter1.next();
ClockIterator *clk_iter2 = clockIterator();
while (clk_iter2->hasNext()) {
Clock *clk2 = clk_iter2->next();
if (clk2 != clk1
&& !group1->isMember(clk2)) {
ClockPair *clk_pair = new ClockPair(clk1, clk2);
clk_group_exclusions_->insert(clk_pair);
}
}
delete clk_iter2;
if (groups->size() == 1)
makeClkGroupExclusions1(groups);
else
makeClkGroupExclusions(groups);
}
}
// If there is only one group all clocks not in the group
// are excluded.
void
Sdc::makeClkGroupExclusions1(ClockGroupSet *groups)
{
ClockGroupSet::Iterator group_iter1(groups);
ClockGroup *group1 = group_iter1.next();
ClockSet *clks1 = group1->clks();
ClockSet::Iterator clk_iter1(clks1);
while (clk_iter1.hasNext()) {
Clock *clk1 = clk_iter1.next();
ClockIterator *clk_iter2 = clockIterator();
while (clk_iter2->hasNext()) {
Clock *clk2 = clk_iter2->next();
if (clk2 != clk1
&& !group1->isMember(clk2)) {
ClockPair *clk_pair = new ClockPair(clk1, clk2);
clk_group_exclusions_->insert(clk_pair);
}
}
else {
ClockGroupSet::Iterator group_iter1(groups);
while (group_iter1.hasNext()) {
ClockGroup *group1 = group_iter1.next();
ClockGroupSet::Iterator group_iter2(groups);
while (group_iter2.hasNext()) {
ClockGroup *group2 = group_iter2.next();
if (group1 != group2) {
ClockSet *clks1 = group1->clks();
ClockSet *clks2 = group2->clks();
ClockSet::Iterator clk_iter1(clks1);
while (clk_iter1.hasNext()) {
Clock *clk1 = clk_iter1.next();
ClockSet::Iterator clk_iter2(clks2);
while (clk_iter2.hasNext()) {
Clock *clk2 = clk_iter2.next();
// ClockPair is symmetric so only add one clk1/clk2 pair.
if (clk1->index() < clk2->index()) {
ClockPair *clk_pair = new ClockPair(clk1, clk2);
clk_group_exclusions_->insert(clk_pair);
}
}
delete clk_iter2;
}
makeClkGroupSame(group1);
}
void
Sdc::makeClkGroupExclusions(ClockGroupSet *groups)
{
ClockGroupSet::Iterator group_iter1(groups);
while (group_iter1.hasNext()) {
ClockGroup *group1 = group_iter1.next();
ClockSet *clks1 = group1->clks();
ClockGroupSet::Iterator group_iter2(groups);
while (group_iter2.hasNext()) {
ClockGroup *group2 = group_iter2.next();
if (group1 != group2) {
ClockSet *clks2 = group2->clks();
ClockSet::Iterator clk_iter1(clks1);
while (clk_iter1.hasNext()) {
Clock *clk1 = clk_iter1.next();
ClockSet::Iterator clk_iter2(clks2);
while (clk_iter2.hasNext()) {
Clock *clk2 = clk_iter2.next();
// ClockPair is symmetric so only add one clk1/clk2 pair.
if (clk1->index() < clk2->index()) {
ClockPair *clk_pair = new ClockPair(clk1, clk2);
clk_group_exclusions_->insert(clk_pair);
}
}
}
}
}
makeClkGroupSame(group1);
}
}
void
Sdc::makeClkGroupSame(ClockGroup *group)
{
ClockSet *clks = group->clks();
ClockSet::Iterator clk_iter1(clks);
while (clk_iter1.hasNext()) {
Clock *clk1 = clk_iter1.next();
ClockSet::Iterator clk_iter2(clks);
while (clk_iter2.hasNext()) {
Clock *clk2 = clk_iter2.next();
if (clk1->index() <= clk2->index()) {
ClockPair *clk_pair = new ClockPair(clk1, clk2);
if (!clk_group_same_->hasKey(clk_pair))
clk_group_same_->insert(clk_pair);
}
}
}
}
@ -2152,14 +2185,17 @@ Sdc::clearClkGroupExclusions()
{
if (clk_group_exclusions_) {
clk_group_exclusions_->deleteContents();
clk_group_same_->deleteContents();
delete clk_group_exclusions_;
delete clk_group_same_;
clk_group_exclusions_ = NULL;
clk_group_same_ = NULL;
}
}
bool
Sdc::sameClockGroup(const Clock *clk1,
const Clock *clk2)
const Clock *clk2)
{
if (clk1 && clk2) {
ClockPair clk_pair(clk1, clk2);
@ -2170,6 +2206,14 @@ Sdc::sameClockGroup(const Clock *clk1,
return true;
}
bool
Sdc::sameClockGroupExplicit(const Clock *clk1,
const Clock *clk2)
{
ClockPair clk_pair(clk1, clk2);
return clk_group_same_->hasKey(&clk_pair);
}
void
Sdc::removeClockGroups(const char *name)
{

View File

@ -488,6 +488,9 @@ public:
void removeClockGroupsAsynchronous(const char *name);
bool sameClockGroup(const Clock *clk1,
const Clock *clk2);
// Clocks explicitly excluded by set_clock_group.
bool sameClockGroupExplicit(const Clock *clk1,
const Clock *clk2);
void setClockSense(PinSet *pins,
ClockSet *clks,
ClockSense sense);
@ -1250,6 +1253,9 @@ protected:
void removeClockGroups(ClockGroups *groups);
void ensureClkGroupExclusions();;
void makeClkGroupExclusions(ClockGroups *clk_groups);
void makeClkGroupExclusions1(ClockGroupSet *groups);
void makeClkGroupExclusions(ClockGroupSet *groups);
void makeClkGroupSame(ClockGroup *group);
void clearClkGroupExclusions();
char *makeClockGroupsName();
void setClockSense(const Pin *pin,
@ -1298,6 +1304,8 @@ protected:
ClockGroupsNameMap clk_groups_name_map_;
// clk to clk paths excluded by clock groups.
ClockPairSet *clk_group_exclusions_;
// clks in the same set_clock_group set.
ClockPairSet *clk_group_same_;
ClockSenseMap clk_sense_map_;
ClockGatingCheck *clk_gating_check_;
ClockGatingCheckMap clk_gating_check_map_;

View File

@ -316,7 +316,7 @@ ReportAnnotated::findCounts()
LogicValue from_logic_value;
bool from_logic_value_exists;
sdc_->logicValue(from_pin, from_logic_value,
from_logic_value_exists);
from_logic_value_exists);
VertexOutEdgeIterator edge_iter(from_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
@ -327,14 +327,14 @@ ReportAnnotated::findCounts()
LogicValue to_logic_value;
bool to_logic_value_exists;
sdc_->logicValue(to_pin, to_logic_value,
to_logic_value_exists);
to_logic_value_exists);
edge_count_[index]++;
if (from_logic_value_exists || to_logic_value_exists)
edge_constant_count_[index]++;
if (report_role_[index]) {
if (edge->arcDelayAnnotated()) {
if (graph_->delayAnnotated(edge)) {
edge_annotated_count_[index]++;
if (from_logic_value_exists || to_logic_value_exists)
edge_constant_annotated_count_[index]++;
@ -501,7 +501,7 @@ ReportAnnotated::reportArcs(Vertex *vertex,
Edge *edge = edge_iter.next();
TimingRole *role = edge->role();
const Pin *to_pin = edge->to(graph_)->pin();
if (edge->arcDelayAnnotated() == report_annotated
if (graph_->delayAnnotated(edge) == report_annotated
&& report_role_[roleIndex(role, from_pin, to_pin)]) {
const char *role_name;
if (role->isTimingCheck())

View File

@ -759,7 +759,7 @@ SdfReader::setEdgeArcDelays(Edge *edge,
else
delay = *value_ptr;
graph_->setArcDelay(edge, arc, arc_delay_index, delay);
edge->setArcDelayAnnotated(true, arc, arc_delay_index);
graph_->setArcDelayAnnotated(edge, arc, arc_delay_index, true);
edge->setDelayAnnotationIsIncremental(is_incremental_only_);
}
}
@ -809,13 +809,13 @@ SdfReader::setEdgeArcDelaysCondUse(Edge *edge,
ArcDelay delay(*value);
if (!is_incremental_only_ && in_incremental_)
delay = graph_->arcDelay(edge, arc, arc_delay_index) + *value;
else if (edge->arcDelayAnnotated(arc, arc_delay_index)) {
else if (graph_->arcDelayAnnotated(edge, arc, arc_delay_index)) {
ArcDelay prev_value = graph_->arcDelay(edge, arc, arc_delay_index);
if (delayFuzzyGreater(prev_value, delay, min_max))
delay = prev_value;
}
graph_->setArcDelay(edge, arc, arc_delay_index, delay);
edge->setArcDelayAnnotated(true, arc, arc_delay_index);
graph_->setArcDelayAnnotated(edge, arc, arc_delay_index, true);
edge->setDelayAnnotationIsIncremental(is_incremental_only_);
}
}

View File

@ -61,17 +61,21 @@ CheckMinPeriods::clear()
class MinPeriodViolatorsVisitor : public MinPeriodCheckVisitor
{
public:
MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks);
MinPeriodViolatorsVisitor(const Corner *corner,
MinPeriodCheckSeq &checks);
virtual void visit(MinPeriodCheck &check,
StaState *sta);
private:
DISALLOW_COPY_AND_ASSIGN(MinPeriodViolatorsVisitor);
const Corner *corner_;
MinPeriodCheckSeq &checks_;
};
MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks):
MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(const Corner *corner,
MinPeriodCheckSeq &checks):
corner_(corner),
checks_(checks)
{
}
@ -85,10 +89,10 @@ MinPeriodViolatorsVisitor::visit(MinPeriodCheck &check,
}
MinPeriodCheckSeq &
CheckMinPeriods::violations()
CheckMinPeriods::violations(const Corner *corner)
{
clear();
MinPeriodViolatorsVisitor visitor(checks_);
MinPeriodViolatorsVisitor visitor(corner, checks_);
visitMinPeriodChecks(&visitor);
sort(checks_, MinPeriodSlackLess(sta_));
return checks_;
@ -128,10 +132,12 @@ CheckMinPeriods::visitMinPeriodChecks(Vertex *vertex,
}
}
////////////////////////////////////////////////////////////////
class MinPeriodSlackVisitor : public MinPeriodCheckVisitor
{
public:
MinPeriodSlackVisitor();
MinPeriodSlackVisitor(const Corner *corner);
virtual void visit(MinPeriodCheck &check,
StaState *sta);
MinPeriodCheck *minSlackCheck();
@ -139,10 +145,12 @@ public:
private:
DISALLOW_COPY_AND_ASSIGN(MinPeriodSlackVisitor);
const Corner *corner_;
MinPeriodCheck *min_slack_check_;
};
MinPeriodSlackVisitor::MinPeriodSlackVisitor() :
MinPeriodSlackVisitor::MinPeriodSlackVisitor(const Corner *corner) :
corner_(corner),
min_slack_check_(NULL)
{
}
@ -167,10 +175,10 @@ MinPeriodSlackVisitor::minSlackCheck()
}
MinPeriodCheck *
CheckMinPeriods::minSlackCheck()
CheckMinPeriods::minSlackCheck(const Corner *corner)
{
clear();
MinPeriodSlackVisitor visitor;
MinPeriodSlackVisitor visitor(corner);
visitMinPeriodChecks(&visitor);
MinPeriodCheck *check = visitor.minSlackCheck();
// Save check for cleanup.

View File

@ -36,9 +36,11 @@ public:
~CheckMinPeriods();
void clear();
// All violating min period checks.
MinPeriodCheckSeq &violations();
// corner=NULL checks all corners.
MinPeriodCheckSeq &violations(const Corner *corner);
// Min period check with the least slack.
MinPeriodCheck *minSlackCheck();
// corner=NULL checks all corners.
MinPeriodCheck *minSlackCheck(const Corner *corner);
protected:
void visitMinPeriodChecks(MinPeriodCheckVisitor *visitor);

View File

@ -74,49 +74,59 @@ CheckMinPulseWidths::clear()
checks_.deleteContentsClear();
}
////////////////////////////////////////////////////////////////
class MinPulseWidthChecksVisitor : public MinPulseWidthCheckVisitor
{
public:
explicit MinPulseWidthChecksVisitor(MinPulseWidthCheckSeq &checks);
explicit MinPulseWidthChecksVisitor(const Corner *corner,
MinPulseWidthCheckSeq &checks);
virtual void visit(MinPulseWidthCheck &check,
const StaState *sta);
private:
DISALLOW_COPY_AND_ASSIGN(MinPulseWidthChecksVisitor);
const Corner *corner_;
MinPulseWidthCheckSeq &checks_;
};
MinPulseWidthChecksVisitor::
MinPulseWidthChecksVisitor(MinPulseWidthCheckSeq &checks) :
MinPulseWidthChecksVisitor(const Corner *corner,
MinPulseWidthCheckSeq &checks) :
corner_(corner),
checks_(checks)
{
}
void
MinPulseWidthChecksVisitor::visit(MinPulseWidthCheck &check,
const StaState *)
const StaState *sta)
{
MinPulseWidthCheck *copy = new MinPulseWidthCheck(check.openPath());
checks_.push_back(copy);
if (corner_ == NULL
|| check.corner(sta) == corner_) {
MinPulseWidthCheck *copy = new MinPulseWidthCheck(check.openPath());
checks_.push_back(copy);
}
}
MinPulseWidthCheckSeq &
CheckMinPulseWidths::check()
CheckMinPulseWidths::check(const Corner *corner)
{
clear();
MinPulseWidthChecksVisitor visitor(checks_);
MinPulseWidthChecksVisitor visitor(corner, checks_);
visitMinPulseWidthChecks(&visitor);
sort(checks_, MinPulseWidthSlackLess(sta_));
return checks_;
}
MinPulseWidthCheckSeq &
CheckMinPulseWidths::check(PinSeq *pins)
CheckMinPulseWidths::check(PinSeq *pins,
const Corner *corner)
{
clear();
Graph *graph = sta_->graph();
MinPulseWidthChecksVisitor visitor(checks_);
MinPulseWidthChecksVisitor visitor(corner, checks_);
PinSeq::Iterator pin_iter(pins);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
@ -127,49 +137,59 @@ CheckMinPulseWidths::check(PinSeq *pins)
return checks_;
}
class MinPulseWidthViolatorsVisititor : public MinPulseWidthCheckVisitor
////////////////////////////////////////////////////////////////
class MinPulseWidthViolatorsVisitor : public MinPulseWidthCheckVisitor
{
public:
explicit MinPulseWidthViolatorsVisititor(MinPulseWidthCheckSeq &checks);
explicit MinPulseWidthViolatorsVisitor(const Corner *corner,
MinPulseWidthCheckSeq &checks);
virtual void visit(MinPulseWidthCheck &check,
const StaState *sta);
private:
DISALLOW_COPY_AND_ASSIGN(MinPulseWidthViolatorsVisititor);
DISALLOW_COPY_AND_ASSIGN(MinPulseWidthViolatorsVisitor);
const Corner *corner_;
MinPulseWidthCheckSeq &checks_;
};
MinPulseWidthViolatorsVisititor::
MinPulseWidthViolatorsVisititor(MinPulseWidthCheckSeq &checks) :
MinPulseWidthViolatorsVisitor::
MinPulseWidthViolatorsVisitor(const Corner *corner,
MinPulseWidthCheckSeq &checks) :
corner_(corner),
checks_(checks)
{
}
void
MinPulseWidthViolatorsVisititor::visit(MinPulseWidthCheck &check,
const StaState *sta)
MinPulseWidthViolatorsVisitor::visit(MinPulseWidthCheck &check,
const StaState *sta)
{
if (delayFuzzyLess(check.slack(sta), 0.0)) {
if (delayFuzzyLess(check.slack(sta), 0.0)
&& (corner_ == NULL
|| check.corner(sta) == corner_)) {
MinPulseWidthCheck *copy = new MinPulseWidthCheck(check.openPath());
checks_.push_back(copy);
}
}
MinPulseWidthCheckSeq &
CheckMinPulseWidths::violations()
CheckMinPulseWidths::violations(const Corner *corner)
{
clear();
MinPulseWidthViolatorsVisititor visitor(checks_);
MinPulseWidthViolatorsVisitor visitor(corner, checks_);
visitMinPulseWidthChecks(&visitor);
sort(checks_, MinPulseWidthSlackLess(sta_));
return checks_;
}
////////////////////////////////////////////////////////////////
class MinPulseWidthSlackVisitor : public MinPulseWidthCheckVisitor
{
public:
MinPulseWidthSlackVisitor();
MinPulseWidthSlackVisitor(const Corner *corner);
virtual void visit(MinPulseWidthCheck &check,
const StaState *sta);
MinPulseWidthCheck *minSlackCheck();
@ -177,10 +197,12 @@ public:
private:
DISALLOW_COPY_AND_ASSIGN(MinPulseWidthSlackVisitor);
const Corner *corner_;
MinPulseWidthCheck *min_slack_check_;
};
MinPulseWidthSlackVisitor::MinPulseWidthSlackVisitor() :
MinPulseWidthSlackVisitor::MinPulseWidthSlackVisitor(const Corner *corner) :
corner_(corner),
min_slack_check_(NULL)
{
}
@ -190,11 +212,14 @@ MinPulseWidthSlackVisitor::visit(MinPulseWidthCheck &check,
const StaState *sta)
{
MinPulseWidthSlackLess slack_less(sta);
if (min_slack_check_ == NULL)
min_slack_check_ = check.copy();
else if (slack_less(&check, min_slack_check_)) {
delete min_slack_check_;
min_slack_check_ = check.copy();
if (corner_ == NULL
|| check.corner(sta) == corner_) {
if (min_slack_check_ == NULL)
min_slack_check_ = check.copy();
else if (slack_less(&check, min_slack_check_)) {
delete min_slack_check_;
min_slack_check_ = check.copy();
}
}
}
@ -205,10 +230,10 @@ MinPulseWidthSlackVisitor::minSlackCheck()
}
MinPulseWidthCheck *
CheckMinPulseWidths::minSlackCheck()
CheckMinPulseWidths::minSlackCheck(const Corner *corner)
{
clear();
MinPulseWidthSlackVisitor visitor;
MinPulseWidthSlackVisitor visitor(corner);
visitMinPulseWidthChecks(&visitor);
MinPulseWidthCheck *check = visitor.minSlackCheck();
// Save check for cleanup.
@ -452,6 +477,12 @@ MinPulseWidthCheck::slack(const StaState *sta) const
return width(sta) - minWidth(sta);
}
Corner *
MinPulseWidthCheck::corner(const StaState *sta) const
{
return open_path_.pathAnalysisPt(sta)->corner();
}
////////////////////////////////////////////////////////////////
MinPulseWidthSlackLess::MinPulseWidthSlackLess(const StaState *sta) :

View File

@ -36,13 +36,18 @@ public:
~CheckMinPulseWidths();
void clear();
// Min pulse width checks for pins.
MinPulseWidthCheckSeq &check(PinSeq *pins);
// corner=NULL checks all corners.
MinPulseWidthCheckSeq &check(PinSeq *pins,
const Corner *corner);
// All min pulse width checks.
MinPulseWidthCheckSeq &check();
// corner=NULL checks all corners.
MinPulseWidthCheckSeq &check(const Corner *corner);
// All violating min pulse width checks.
MinPulseWidthCheckSeq &violations();
// corner=NULL checks all corners.
MinPulseWidthCheckSeq &violations(const Corner *corner);
// Min pulse width check with the least slack.
MinPulseWidthCheck *minSlackCheck();
// corner=NULL checks all corners.
MinPulseWidthCheck *minSlackCheck(const Corner *corner);
protected:
void visitMinPulseWidthChecks(MinPulseWidthCheckVisitor *visitor);
@ -68,6 +73,7 @@ public:
float minWidth(const StaState *sta) const;
Slack slack(const StaState *sta) const;
Path *openPath() { return &open_path_; }
Corner *corner(const StaState *sta) const;
const Path *openPath() const { return &open_path_; }
Arrival openArrival(const StaState *sta) const;
void closePath(const StaState *sta,

View File

@ -32,22 +32,26 @@ namespace sta {
class PinSlewLimitSlackLess
{
public:
PinSlewLimitSlackLess(const MinMax *min_max,
PinSlewLimitSlackLess(const Corner *corner,
const MinMax *min_max,
CheckSlewLimits *check_slew_limit,
const StaState *sta);
bool operator()(Pin *pin1,
Pin *pin2) const;
private:
const Corner *corner_;
const MinMax *min_max_;
CheckSlewLimits *check_slew_limit_;
const StaState *sta_;
};
PinSlewLimitSlackLess::PinSlewLimitSlackLess(const MinMax *min_max,
PinSlewLimitSlackLess::PinSlewLimitSlackLess(const Corner *corner,
const MinMax *min_max,
CheckSlewLimits *check_slew_limit,
const StaState *sta) :
corner_(corner),
min_max_(min_max),
check_slew_limit_(check_slew_limit),
sta_(sta)
@ -62,9 +66,9 @@ PinSlewLimitSlackLess::operator()(Pin *pin1,
const TransRiseFall *tr1, *tr2;
Slew slew1, slew2;
float limit1, limit2, slack1, slack2;
check_slew_limit_->checkSlews(pin1, min_max_,
check_slew_limit_->checkSlews(pin1, corner_, min_max_,
corner1, tr1, slew1, limit1, slack1);
check_slew_limit_->checkSlews(pin2, min_max_,
check_slew_limit_->checkSlews(pin2, corner_, min_max_,
corner2, tr2, slew2, limit2, slack2);
return slack1 < slack2
|| (fuzzyEqual(slack1, slack2)
@ -94,41 +98,71 @@ CheckSlewLimits::init(const MinMax *min_max)
void
CheckSlewLimits::checkSlews(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
const Corner *&corner,
// Return the min slack transition.
const Corner *&corner1,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
float &slack) const
{
corner = NULL;
corner1 = NULL;
tr = NULL;
slack = MinMax::min()->initValue();
if (corner)
checkSlews1(pin, corner, min_max,
corner1, tr, slew, limit, slack);
else {
CornerIterator corner_iter(sta_);
while (corner_iter.hasNext()) {
const Corner *corner2 = corner_iter.next();
checkSlews1(pin, corner2, min_max,
corner1, tr, slew, limit, slack);
}
}
}
void
CheckSlewLimits::checkSlews1(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
const Corner *&corner1,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
float &slack) const
{
Vertex *vertex, *bidirect_drvr_vertex;
sta_->graph()->pinVertices(pin, vertex, bidirect_drvr_vertex);
checkSlews1(vertex, corner, min_max,
corner1, tr, slew, limit, slack);
if (bidirect_drvr_vertex)
checkSlews1(bidirect_drvr_vertex, corner, min_max,
corner1, tr, slew, limit, slack);
}
void
CheckSlewLimits::checkSlews1(Vertex *vertex,
const Corner *corner1,
const MinMax *min_max,
// Return values.
const Corner *&corner,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
float &slack) const
{
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr1 = tr_iter.next();
float limit1;
bool limit1_exists;
findLimit(pin, vertex, tr1, min_max, limit1, limit1_exists);
findLimit(vertex->pin(), vertex, tr1, min_max, limit1, limit1_exists);
if (limit1_exists) {
CornerIterator corner_iter(sta_);
while (corner_iter.hasNext()) {
Corner *corner1 = corner_iter.next();
checkSlew(vertex, limit1, tr1, corner1, min_max,
corner, tr, slew, slack, limit);
if (bidirect_drvr_vertex) {
findLimit(pin, bidirect_drvr_vertex, tr1, min_max,
limit1, limit1_exists);
if (limit1_exists) {
checkSlew(bidirect_drvr_vertex, limit1, tr1, corner1, min_max,
corner, tr, slew, slack, limit);
}
}
}
checkSlew(vertex, corner1, min_max, tr1, limit1,
corner, tr, slew, slack, limit);
}
}
}
@ -229,10 +263,10 @@ CheckSlewLimits::clockDomains(const Vertex *vertex,
void
CheckSlewLimits::checkSlew(Vertex *vertex,
float limit1,
const TransRiseFall *tr1,
const Corner *corner1,
const MinMax *min_max,
const TransRiseFall *tr1,
float limit1,
// Return values.
const Corner *&corner,
const TransRiseFall *&tr,
@ -259,7 +293,8 @@ CheckSlewLimits::checkSlew(Vertex *vertex,
}
PinSeq *
CheckSlewLimits::pinSlewLimitViolations(const MinMax *min_max)
CheckSlewLimits::pinSlewLimitViolations(const Corner *corner,
const MinMax *min_max)
{
init(min_max);
const Network *network = sta_->network();
@ -267,17 +302,18 @@ CheckSlewLimits::pinSlewLimitViolations(const MinMax *min_max)
LeafInstanceIterator *inst_iter = network->leafInstanceIterator();
while (inst_iter->hasNext()) {
Instance *inst = inst_iter->next();
pinSlewLimitViolations(inst, min_max, violators);
pinSlewLimitViolations(inst, corner, min_max, violators);
}
delete inst_iter;
// Check top level ports.
pinSlewLimitViolations(network->topInstance(), min_max, violators);
sort(violators, PinSlewLimitSlackLess(min_max, this, sta_));
pinSlewLimitViolations(network->topInstance(), corner, min_max, violators);
sort(violators, PinSlewLimitSlackLess(corner, min_max, this, sta_));
return violators;
}
void
CheckSlewLimits::pinSlewLimitViolations(Instance *inst,
const Corner *corner,
const MinMax *min_max,
PinSeq *violators)
{
@ -285,11 +321,11 @@ CheckSlewLimits::pinSlewLimitViolations(Instance *inst,
InstancePinIterator *pin_iter = network->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
const Corner *corner;
const Corner *corner1;
const TransRiseFall *tr;
Slew slew;
float limit, slack;
checkSlews(pin, min_max, corner, tr, slew, limit, slack);
checkSlews(pin, corner, min_max, corner1, tr, slew, limit, slack );
if (tr && slack < 0.0)
violators->push_back(pin);
}
@ -297,7 +333,8 @@ CheckSlewLimits::pinSlewLimitViolations(Instance *inst,
}
Pin *
CheckSlewLimits::pinMinSlewLimitSlack(const MinMax *min_max)
CheckSlewLimits::pinMinSlewLimitSlack(const Corner *corner,
const MinMax *min_max)
{
init(min_max);
const Network *network = sta_->network();
@ -306,17 +343,18 @@ CheckSlewLimits::pinMinSlewLimitSlack(const MinMax *min_max)
LeafInstanceIterator *inst_iter = network->leafInstanceIterator();
while (inst_iter->hasNext()) {
Instance *inst = inst_iter->next();
pinMinSlewLimitSlack(inst, min_max, min_slack_pin, min_slack);
pinMinSlewLimitSlack(inst, corner, min_max, min_slack_pin, min_slack);
}
delete inst_iter;
// Check top level ports.
pinMinSlewLimitSlack(network->topInstance(), min_max,
pinMinSlewLimitSlack(network->topInstance(), corner, min_max,
min_slack_pin, min_slack);
return min_slack_pin;
}
void
CheckSlewLimits::pinMinSlewLimitSlack(Instance *inst,
const Corner *corner,
const MinMax *min_max,
// Return values.
Pin *&min_slack_pin,
@ -326,11 +364,11 @@ CheckSlewLimits::pinMinSlewLimitSlack(Instance *inst,
InstancePinIterator *pin_iter = network->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
const Corner *corner;
const Corner *corner1;
const TransRiseFall *tr;
Slew slew;
float limit, slack;
checkSlews(pin, min_max, corner, tr, slew, limit, slack);
checkSlews(pin, corner, min_max, corner1, tr, slew, limit, slack);
if (tr
&& (min_slack_pin == 0
|| slack < min_slack)) {

View File

@ -34,24 +34,48 @@ public:
CheckSlewLimits(const StaState *sta);
void init(const MinMax *min_max);
// Requires init().
// corner=NULL checks all corners.
void checkSlews(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
// Corner is NULL for no slew limit.
const Corner *&corner,
const Corner *&corner1,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
float &slack) const;
PinSeq *pinSlewLimitViolations(const MinMax *min_max);
Pin *pinMinSlewLimitSlack(const MinMax *min_max);
// corner=NULL checks all corners.
PinSeq *pinSlewLimitViolations(const Corner *corner,
const MinMax *min_max);
// corner=NULL checks all corners.
Pin *pinMinSlewLimitSlack(const Corner *corner,
const MinMax *min_max);
protected:
void checkSlews1(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
const Corner *&corner1,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
float &slack) const;
void checkSlews1(Vertex *vertex,
const Corner *corner1,
const MinMax *min_max,
// Return values.
const Corner *&corner,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
float &slack) const;
void checkSlew(Vertex *vertex,
float limit1,
const TransRiseFall *tr1,
const Corner *corner1,
const MinMax *min_max,
const TransRiseFall *tr1,
float limit1,
// Return values.
const Corner *&corner,
const TransRiseFall *&tr,
@ -66,9 +90,11 @@ protected:
float &limit1,
bool &limit1_exists) const;
void pinSlewLimitViolations(Instance *inst,
const Corner *corner,
const MinMax *min_max,
PinSeq *violators);
void pinMinSlewLimitSlack(Instance *inst,
const Corner *corner,
const MinMax *min_max,
// Return values.
Pin *&min_slack_pin,

View File

@ -119,11 +119,12 @@ ClkSkews::ClkSkews(StaState *sta) :
void
ClkSkews::reportClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
int digits)
{
ClkSkewMap skews;
findClkSkew(clks, setup_hold, skews);
findClkSkew(clks, corner, setup_hold, skews);
// Sort the clocks to report in a stable order.
ClockSeq sorted_clks;
@ -167,6 +168,7 @@ ClkSkews::reportClkSkew(ClockSet *clks,
void
ClkSkews::findClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
ClkSkewMap &skews)
{
@ -184,7 +186,7 @@ ClkSkews::findClkSkew(ClockSet *clks,
? tr->asRiseFallBoth()
: TransRiseFallBoth::riseFall();
findClkSkewFrom(src_vertex, q_vertex, src_tr, clks,
setup_hold, skews);
corner, setup_hold, skews);
}
}
}
@ -210,6 +212,7 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex,
Vertex *q_vertex,
TransRiseFallBoth *src_tr,
ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
ClkSkewMap &skews)
{
@ -233,7 +236,7 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex,
? tgt_tr1->asRiseFallBoth()
: TransRiseFallBoth::riseFall();
findClkSkew(src_vertex, src_tr, tgt_vertex, tgt_tr,
clks, setup_hold, skews);
clks, corner, setup_hold, skews);
}
}
}
@ -245,6 +248,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
Vertex *tgt_vertex,
TransRiseFallBoth *tgt_tr,
ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
ClkSkewMap &skews)
{
@ -257,32 +261,35 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
if (src_tr->matches(src_path->transition(this))
&& src_path->minMax(this) == setup_hold
&& clks->hasKey(src_clk)) {
Corner *corner = src_path->pathAnalysisPt(this)->corner();
VertexPathIterator tgt_iter(tgt_vertex, this);
while (tgt_iter.hasNext()) {
PathVertex *tgt_path = tgt_iter.next();
Clock *tgt_clk = tgt_path->clock(this);
if (tgt_clk == src_clk
&& tgt_tr->matches(tgt_path->transition(this))
&& tgt_path->minMax(this) == tgt_min_max
&& tgt_path->pathAnalysisPt(this)->corner() == corner) {
ClkSkew probe(src_path, tgt_path, this);
ClkSkew *clk_skew = skews.findKey(src_clk);
debugPrint8(debug_, "clk_skew", 2, "%s %s %s -> %s %s %s crpr = %s skew = %s\n",
network_->pathName(src_path->pin(this)),
src_path->transition(this)->asString(),
time_unit->asString(probe.srcLatency(this)),
network_->pathName(tgt_path->pin(this)),
tgt_path->transition(this)->asString(),
time_unit->asString(probe.tgtLatency(this)),
time_unit->asString(probe.crpr(this)),
time_unit->asString(probe.skew()));
if (clk_skew == NULL) {
clk_skew = new ClkSkew(probe);
skews[src_clk] = clk_skew;
Corner *src_corner = src_path->pathAnalysisPt(this)->corner();
if (corner == NULL
|| src_corner == corner) {
VertexPathIterator tgt_iter(tgt_vertex, this);
while (tgt_iter.hasNext()) {
PathVertex *tgt_path = tgt_iter.next();
Clock *tgt_clk = tgt_path->clock(this);
if (tgt_clk == src_clk
&& tgt_tr->matches(tgt_path->transition(this))
&& tgt_path->minMax(this) == tgt_min_max
&& tgt_path->pathAnalysisPt(this)->corner() == src_corner) {
ClkSkew probe(src_path, tgt_path, this);
ClkSkew *clk_skew = skews.findKey(src_clk);
debugPrint8(debug_, "clk_skew", 2, "%s %s %s -> %s %s %s crpr = %s skew = %s\n",
network_->pathName(src_path->pin(this)),
src_path->transition(this)->asString(),
time_unit->asString(probe.srcLatency(this)),
network_->pathName(tgt_path->pin(this)),
tgt_path->transition(this)->asString(),
time_unit->asString(probe.tgtLatency(this)),
time_unit->asString(probe.crpr(this)),
time_unit->asString(probe.skew()));
if (clk_skew == NULL) {
clk_skew = new ClkSkew(probe);
skews[src_clk] = clk_skew;
}
else if (fuzzyGreater(probe.skew(), clk_skew->skew()))
clk_skew->copy(probe);
}
else if (fuzzyGreater(probe.skew(), clk_skew->skew()))
clk_skew->copy(probe);
}
}
}

View File

@ -33,11 +33,13 @@ public:
ClkSkews(StaState *sta);
// Report clk skews for clks.
void reportClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
int digits);
protected:
void findClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
ClkSkewMap &skews);
bool hasClkPaths(Vertex *vertex,
@ -46,6 +48,7 @@ protected:
Vertex *q_vertex,
TransRiseFallBoth *src_tr,
ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
ClkSkewMap &skews);
void findClkSkew(Vertex *src_vertex,
@ -53,6 +56,7 @@ protected:
Vertex *tgt_vertex,
TransRiseFallBoth *tgt_tr,
ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
ClkSkewMap &skews);
void findFanout(Vertex *from,

View File

@ -63,8 +63,8 @@ ReportField::ReportField(const char *name,
title_(stringCopy(title)),
left_justify_(left_justify),
unit_(unit),
blank_(NULL),
enabled_(enabled)
enabled_(enabled),
blank_(NULL)
{
setWidth(width);
}
@ -1872,7 +1872,7 @@ ReportPath::reportStartEndPoint(const char *pt,
result += pt;
reportEndOfLine(result);
for (int i = 0; i < strlen(key); i++)
for (unsigned i = 0; i < strlen(key); i++)
result += ' ';
result += " (";
@ -2785,7 +2785,7 @@ ReportPath::nextArcAnnotated(const PathRef *next_path,
{
TimingArc *arc = expanded.prevArc(next_index);
Edge *edge = next_path->prevEdge(arc, this);
return edge->arcDelayAnnotated(arc, ap_index);
return graph_->arcDelayAnnotated(edge, arc, ap_index);
}
char *

View File

@ -2384,8 +2384,9 @@ Sta::findPathEnds(ExceptionFrom *from,
{
searchPreamble();
return search_->findPathEnds(from, thrus, to,
corner, min_max, group_count, endpoint_count, unique_pins,
slack_min, slack_max, sort_by_slack, group_names,
corner, min_max, group_count, endpoint_count,
unique_pins, slack_min, slack_max,
sort_by_slack, group_names,
setup, hold,
recovery, removal,
clk_gating_setup, clk_gating_hold);
@ -2462,53 +2463,6 @@ Sta::reportPath(Path *path)
report_path_->reportPath(path);
}
PathEndSeq *
Sta::reportCheckTypes(bool all_violators,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clock_gating_setup,
bool clock_gating_hold)
{
MinMaxAll *path_min_max = MinMaxAll::max();
if ((setup && hold)
|| (recovery && removal)
|| (clock_gating_setup && clock_gating_hold))
path_min_max = MinMaxAll::all();
else if (setup
|| recovery
|| clock_gating_setup)
path_min_max = MinMaxAll::max();
else if (hold
|| removal
|| clock_gating_hold)
path_min_max = MinMaxAll::min();
int group_count;
float slack_min, slack_max;
if (all_violators) {
group_count = std::numeric_limits<int>::max();
slack_min = -INF;
slack_max = 0.0;
}
else {
group_count = 1;
slack_min = -INF;
slack_max = INF;
}
return findPathEnds(NULL, NULL, NULL, // from, thru, to
NULL, // corner
path_min_max, group_count,
1, // endpoint_count
false, // unique_pins
slack_min, slack_max,
false, // sort_by_slack
NULL, // group_names
setup, hold,
recovery, removal,
clock_gating_setup, clock_gating_hold);
}
void
Sta::updateTiming(bool full)
{
@ -2520,13 +2474,14 @@ Sta::updateTiming(bool full)
void
Sta::reportClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
int digits)
{
ensureClkArrivals();
if (clk_skews_ == NULL)
clk_skews_ = new ClkSkews(this);
clk_skews_->reportClkSkew(clks, setup_hold, digits);
clk_skews_->reportClkSkew(clks, corner, setup_hold, digits);
}
////////////////////////////////////////////////////////////////
@ -2966,16 +2921,16 @@ Sta::arcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAnalysisPt *dcalc_ap)
{
return edge->arcDelayAnnotated(arc, dcalc_ap->index());
return graph_->arcDelayAnnotated(edge, arc, dcalc_ap->index());
}
void
Sta::setArcDelayAnnotated(bool annotated,
Edge *edge,
Sta::setArcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAnalysisPt *dcalc_ap)
DcalcAnalysisPt *dcalc_ap,
bool annotated)
{
edge->setArcDelayAnnotated(annotated, arc, dcalc_ap->index());
graph_->setArcDelayAnnotated(edge, arc, dcalc_ap->index(), annotated);
Vertex *to = edge->to(graph_);
search_->arrivalInvalid(to);
search_->requiredInvalid(edge->from(graph_));
@ -3159,7 +3114,7 @@ Sta::setArcDelay(Edge *edge,
DcalcAPIndex ap_index = dcalc_ap->index();
graph_->setArcDelay(edge, arc, ap_index, delay);
// Don't let delay calculation clobber the value.
edge->setArcDelayAnnotated(true, arc, ap_index);
graph_->setArcDelayAnnotated(edge, arc, ap_index, true);
}
if (edge->role()->isTimingCheck())
search_->requiredInvalid(edge->to(graph_));
@ -3326,10 +3281,10 @@ Sta::setPortExtFanout(Port *port,
void
Sta::setNetWireCap(Net *net,
bool subtract_pin_cap,
const Corner *corner,
const MinMaxAll *min_max,
float cap)
{
Corner *corner = corners_->defaultCorner();
MinMaxIterator mm_iter(min_max);
while (mm_iter.hasNext()) {
MinMax *mm = mm_iter.next();
@ -3341,6 +3296,7 @@ Sta::setNetWireCap(Net *net,
void
Sta::connectedCap(Pin *drvr_pin,
const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max,
float &pin_cap,
float &wire_cap) const
@ -3348,7 +3304,6 @@ Sta::connectedCap(Pin *drvr_pin,
pin_cap = 0.0;
wire_cap = 0.0;
bool cap_exists = false;
Corner *corner = corners_->defaultCorner();
const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
Parasitic *parasitic;
bool delete_parasitic;
@ -3371,13 +3326,14 @@ Sta::connectedCap(Pin *drvr_pin,
void
Sta::connectedCap(Net *net,
const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max,
float &pin_cap,
float &wire_cap) const
{
Pin *drvr_pin = findNetParasiticDrvrPin(net);
if (drvr_pin)
connectedCap(drvr_pin, tr, min_max, pin_cap, wire_cap);
connectedCap(drvr_pin, tr, corner, min_max, pin_cap, wire_cap);
else {
pin_cap = 0.0;
wire_cap = 0.0;
@ -4707,17 +4663,19 @@ Sta::checkSlewLimitPreamble()
}
Pin *
Sta::pinMinSlewLimitSlack(const MinMax *min_max)
Sta::pinMinSlewLimitSlack(const Corner *corner,
const MinMax *min_max)
{
checkSlewLimitPreamble();
return check_slew_limits_->pinMinSlewLimitSlack(min_max);
return check_slew_limits_->pinMinSlewLimitSlack(corner, min_max);
}
PinSeq *
Sta::pinSlewLimitViolations(const MinMax *min_max)
Sta::pinSlewLimitViolations(const Corner *corner,
const MinMax *min_max)
{
checkSlewLimitPreamble();
return check_slew_limits_->pinSlewLimitViolations(min_max);
return check_slew_limits_->pinSlewLimitViolations(corner, min_max);
}
void
@ -4728,34 +4686,39 @@ Sta::reportSlewLimitShortHeader()
void
Sta::reportSlewLimitShort(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
const Corner *corner;
const Corner *corner1;
const TransRiseFall *tr;
Slew slew;
float limit, slack;
check_slew_limits_->checkSlews(pin, min_max, corner, tr, slew, limit, slack);
check_slew_limits_->checkSlews(pin, corner, min_max,
corner1, tr, slew, limit, slack);
report_path_->reportSlewLimitShort(pin, tr, slew, limit, slack);
}
void
Sta::reportSlewLimitVerbose(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
const Corner *corner;
const Corner *corner1;
const TransRiseFall *tr;
Slew slew;
float limit, slack;
check_slew_limits_->checkSlews(pin, min_max, corner, tr, slew, limit, slack);
report_path_->reportSlewLimitVerbose(pin, corner, tr, slew,
check_slew_limits_->checkSlews(pin, corner, min_max,
corner, tr, slew, limit, slack);
report_path_->reportSlewLimitVerbose(pin, corner1, tr, slew,
limit, slack, min_max);
}
void
Sta::checkSlews(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
const Corner *&corner,
const Corner *&corner1,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
@ -4763,8 +4726,8 @@ Sta::checkSlews(const Pin *pin,
{
checkSlewLimitPreamble();
check_slew_limits_->init(min_max);
check_slew_limits_->checkSlews(pin, min_max,
corner, tr, slew, limit, slack);
check_slew_limits_->checkSlews(pin, corner, min_max,
corner1, tr, slew, limit, slack);
}
////////////////////////////////////////////////////////////////'
@ -4778,31 +4741,32 @@ Sta::minPulseWidthPreamble()
}
MinPulseWidthCheckSeq &
Sta::minPulseWidthChecks(PinSeq *pins)
Sta::minPulseWidthChecks(PinSeq *pins,
const Corner *corner)
{
minPulseWidthPreamble();
return check_min_pulse_widths_->check(pins);
return check_min_pulse_widths_->check(pins, corner);
}
MinPulseWidthCheckSeq &
Sta::minPulseWidthChecks()
Sta::minPulseWidthChecks(const Corner *corner)
{
minPulseWidthPreamble();
return check_min_pulse_widths_->check();
return check_min_pulse_widths_->check(corner);
}
MinPulseWidthCheckSeq &
Sta::minPulseWidthViolations()
Sta::minPulseWidthViolations(const Corner *corner)
{
minPulseWidthPreamble();
return check_min_pulse_widths_->violations();
return check_min_pulse_widths_->violations(corner);
}
MinPulseWidthCheck *
Sta::minPulseWidthSlack()
Sta::minPulseWidthSlack(const Corner *corner)
{
minPulseWidthPreamble();
return check_min_pulse_widths_->minSlackCheck();
return check_min_pulse_widths_->minSlackCheck(corner);
}
void
@ -4822,17 +4786,17 @@ Sta::reportMpwCheck(MinPulseWidthCheck *check,
////////////////////////////////////////////////////////////////
MinPeriodCheckSeq &
Sta::minPeriodViolations()
Sta::minPeriodViolations(const Corner *corner)
{
minPeriodPreamble();
return check_min_periods_->violations();
return check_min_periods_->violations(corner);
}
MinPeriodCheck *
Sta::minPeriodSlack()
Sta::minPeriodSlack(const Corner *corner)
{
minPeriodPreamble();
return check_min_periods_->minSlackCheck();
return check_min_periods_->minSlackCheck(corner);
}
void

View File

@ -173,6 +173,7 @@ public:
// Set net wire capacitance (set_load -wire net).
void setNetWireCap(Net *net,
bool subtract_pin_load,
const Corner *corner,
const MinMaxAll *min_max,
float cap);
// Port external fanout (used by wireload models).
@ -188,11 +189,13 @@ public:
// wire_cap = annotated net capacitance + port external wire capacitance.
void connectedCap(Pin *drvr_pin,
const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max,
float &pin_cap,
float &wire_cap) const;
void connectedCap(Net *net,
const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max,
float &pin_cap,
float &wire_cap) const;
@ -605,39 +608,53 @@ public:
ClockSet &clks);
// Return the pin with the min/max slew limit slack.
Pin *pinMinSlewLimitSlack(const MinMax *min_max);
// corner=NULL checks all corners.
Pin *pinMinSlewLimitSlack(const Corner *corner,
const MinMax *min_max);
// Return all pins with min/max slew violations.
PinSeq *pinSlewLimitViolations(const MinMax *min_max);
// corner=NULL checks all corners.
PinSeq *pinSlewLimitViolations(const Corner *corner,
const MinMax *min_max);
void reportSlewLimitShortHeader();
void reportSlewLimitShort(Pin *pin,
const Corner *corner,
const MinMax *min_max);
void reportSlewLimitVerbose(Pin *pin,
const Corner *corner,
const MinMax *min_max);
void checkSlews(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
const Corner *&corner,
const Corner *&corner1,
const TransRiseFall *&tr,
Slew &slew,
float &limit,
float &slack);
// Min pulse width check with the least slack.
MinPulseWidthCheck *minPulseWidthSlack();
// corner=NULL checks all corners.
MinPulseWidthCheck *minPulseWidthSlack(const Corner *corner);
// All violating min pulse width checks.
MinPulseWidthCheckSeq &minPulseWidthViolations();
// corner=NULL checks all corners.
MinPulseWidthCheckSeq &minPulseWidthViolations(const Corner *corner);
// Min pulse width checks for pins.
MinPulseWidthCheckSeq &minPulseWidthChecks(PinSeq *pins);
// corner=NULL checks all corners.
MinPulseWidthCheckSeq &minPulseWidthChecks(PinSeq *pins,
const Corner *corner);
// All min pulse width checks.
MinPulseWidthCheckSeq &minPulseWidthChecks();
// corner=NULL checks all corners.
MinPulseWidthCheckSeq &minPulseWidthChecks(const Corner *corner);
void reportMpwChecks(MinPulseWidthCheckSeq *checks,
bool verbose);
void reportMpwCheck(MinPulseWidthCheck *check,
bool verbose);
// Min period check with the least slack.
MinPeriodCheck *minPeriodSlack();
// corner=NULL checks all corners.
MinPeriodCheck *minPeriodSlack(const Corner *corner);
// All violating min period checks.
MinPeriodCheckSeq &minPeriodViolations();
// corner=NULL checks all corners.
MinPeriodCheckSeq &minPeriodViolations(const Corner *corner);
void reportChecks(MinPeriodCheckSeq *checks,
bool verbose);
void reportCheck(MinPeriodCheck *check,
@ -836,13 +853,6 @@ public:
bool removal,
bool clk_gating_setup,
bool clk_gating_hold) __attribute__ ((deprecated));
PathEndSeq *reportCheckTypes(bool all_violators,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clock_gating_setup,
bool clock_gating_hold);
void setReportPathFormat(ReportPathFormat format);
void setReportPathFieldOrder(StringSeq *field_names);
void setReportPathFields(bool report_input_pin,
@ -854,6 +864,7 @@ public:
void setReportPathNoSplit(bool no_split);
// Report clk skews for clks.
void reportClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
int digits);
void reportPathEnds(PathEndSeq *ends);
@ -977,10 +988,10 @@ public:
TimingArc *arc,
DcalcAnalysisPt *dcalc_ap);
// Set/unset the back-annotation flag for a timing arc.
void setArcDelayAnnotated(bool annotated,
Edge *edge,
void setArcDelayAnnotated(Edge *edge,
TimingArc *arc,
DcalcAnalysisPt *dcalc_ap);
DcalcAnalysisPt *dcalc_ap,
bool annotated);
// Make sure levels are up to date and return vertex level.
Level vertexLevel(Vertex *vertex);
GraphLoopSeq *graphLoops();

View File

@ -324,9 +324,10 @@ proc net_connected_pins_sorted { net } {
}
proc report_net_caps { net pins digits } {
report_net_cap $net "Pin" "pin_capacitance" $digits
report_net_cap $net "Wire" "wire_capacitance" $digits
report_net_cap $net "Total" "capacitance" $digits
set corner [default_corner]
report_net_cap $net "Pin" "pin_capacitance" $corner $digits
report_net_cap $net "Wire" "wire_capacitance" $corner $digits
report_net_cap $net "Total" "capacitance" $corner $digits
set pin_count 0
set driver_count 0
@ -347,11 +348,11 @@ proc report_net_caps { net pins digits } {
puts ""
}
proc report_net_cap { net caption cap_msg digits } {
set cap_r_min [$net $cap_msg "rise" "min"]
set cap_r_max [$net $cap_msg "rise" "max"]
set cap_f_min [$net $cap_msg "fall" "min"]
set cap_f_max [$net $cap_msg "fall" "max"]
proc report_net_cap { net caption cap_msg corner digits } {
set cap_r_min [$net $cap_msg "rise" $corner "min"]
set cap_r_max [$net $cap_msg "rise" $corner "max"]
set cap_f_min [$net $cap_msg "fall" $corner "min"]
set cap_f_max [$net $cap_msg "fall" $corner "max"]
puts " $caption capacitance: [capacitances_str $cap_r_min $cap_r_max $cap_f_min $cap_f_max $digits]"
}

View File

@ -2356,18 +2356,20 @@ proc set_input_transition { args } {
################################################################
define_cmd_args "set_load" \
{[-rise] [-fall] [-max] [-min] [-subtract_pin_load] [-pin_load] [-wire_load]\
capacitance objects}
{[-rise] [-fall] [-max] [-min] [-corner corner] [-subtract_pin_load]\
[-pin_load] [-wire_load] capacitance objects}
proc set_load { args } {
parse_key_args "set_load" args keys {} \
flags {-rise -fall -min -max -subtract_pin_load -pin_load -wire_load}
flags {-rise -fall -min -max -corner -subtract_pin_load \
-pin_load -wire_load}
check_argc_eq2 "set_load" $args
set pin_load [info exists flags(-pin_load)]
set wire_load [info exists flags(-wire_load)]
set subtract_pin_load [info exists flags(-subtract_pin_load)]
set corner [parse_corner keys]
set min_max [parse_min_max_all_check_flags flags]
set tr [parse_rise_fall_flags flags]
@ -2399,7 +2401,7 @@ proc set_load { args } {
sta_warn "-rise/-fall not allowed for net objects."
}
foreach net $nets {
set_net_wire_cap $net $subtract_pin_load $min_max $cap
set_net_wire_cap $net $subtract_pin_load $corner $min_max $cap
}
}
}

View File

@ -288,36 +288,36 @@ proc parse_path_group_arg { group_names } {
return $names
}
proc report_slew_limits { min_max all_violators verbose nosplit } {
proc report_slew_limits { corner min_max all_violators verbose nosplit } {
if { $all_violators } {
set violators [pin_slew_limit_violations $min_max]
set violators [pin_slew_limit_violations $corner $min_max]
if { $violators != {} } {
puts "${min_max}_transition"
puts ""
if { $verbose } {
foreach pin $violators {
report_slew_limit_verbose $pin $min_max
report_slew_limit_verbose $pin $corner $min_max
puts ""
}
} else {
report_slew_limit_short_header
foreach pin $violators {
report_slew_limit_short $pin $min_max
report_slew_limit_short $pin $corner $min_max
}
puts ""
}
}
} else {
set pin [pin_min_slew_limit_slack $min_max]
set pin [pin_min_slew_limit_slack $corner $min_max]
if { $pin != "NULL" } {
puts "${min_max}_transition"
puts ""
if { $verbose } {
report_slew_limit_verbose $pin $min_max
report_slew_limit_verbose $pin $corner $min_max
puts ""
} else {
report_slew_limit_short_header
report_slew_limit_short $pin $min_max
report_slew_limit_short $pin $corner $min_max
puts ""
}
}

View File

@ -99,15 +99,16 @@ proc find_timing { args } {
################################################################
define_sta_cmd_args "report_clock_skew" {[-setup|-hold] \
[-clock clocks] \
define_sta_cmd_args "report_clock_skew" {[-setup|-hold]\
[-clock clocks]\
[-corner corner_name]]\
[-digits digits]}
proc_redirect report_clock_skew {
global sta_report_default_digits
parse_key_args "report_clock_skew" args \
keys {-clock -digits} flags {-setup -hold}
keys {-clock -corner -digits} flags {-setup -hold}
check_argc_eq0 "report_clock_skew" $args
if { [info exists flags(-setup)] && [info exists flags(-hold)] } {
@ -125,13 +126,14 @@ proc_redirect report_clock_skew {
} else {
set clks [all_clocks]
}
set corner [parse_corner_or_all keys]
if [info exists keys(-digits)] {
set digits $keys(-digits)
check_positive_integer "-digits" $digits
} else {
set digits $sta_report_default_digits
}
report_clk_skew $clks $setup_hold $digits
report_clk_skew $clks $corner $setup_hold $digits
}
################################################################
@ -141,10 +143,10 @@ define_sta_cmd_args "report_checks" \
[-through through_list|-rise_through through_list|-fall_through through_list]\
[-to to_list|-rise_to to_list|-fall_to to_list]\
[-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max]\
[-corner corner_name]\
[-group_count path_count] \
[-endpoint_count path_count]\
[-unique_paths_to_endpoint]\
[-corner corner_name]\
[-slack_max slack_max]\
[-slack_min slack_min]\
[-sort_by_slack]\
@ -161,7 +163,7 @@ proc_redirect report_checks {
parse_key_args "report_checks" args \
keys {-from -rise_from -fall_from -to -rise_to -fall_to \
-path_delay -group_count -endpoint_count -corner \
-path_delay -corner -group_count -endpoint_count \
-slack_max -slack_min -path_group} \
flags {-sort_by_slack -unique_paths_to_endpoint} 0
@ -203,6 +205,8 @@ proc_redirect report_checks {
check_for_key_args $cmd args
set corner [parse_corner_or_all keys]
set endpoint_count 1
if [info exists keys(-endpoint_count)] {
set endpoint_count $keys(-endpoint_count)
@ -221,8 +225,6 @@ proc_redirect report_checks {
set unique_pins [info exists flags(-unique_paths_to_endpoint)]
set corner [parse_corner_or_all keys]
set slack_min "-1e+30"
if [info exist keys(-slack_min)] {
set slack_min $keys(-slack_min)
@ -254,10 +256,11 @@ proc_redirect report_checks {
}
}
set path_ends [find_path_ends $from $thrus $to $min_max \
$group_count $endpoint_count $unique_pins $corner \
set path_ends [find_path_ends $from $thrus $to $corner $min_max \
$group_count $endpoint_count $unique_pins \
$slack_min $slack_max \
$sort_by_slack $groups]
$sort_by_slack $groups \
1 1 1 1 1 1]
if { [$path_ends empty] } {
if { $sta_report_unconstrained_paths } {
puts "No paths."
@ -274,6 +277,7 @@ proc_redirect report_checks {
define_sta_cmd_args "report_check_types" \
{[-all_violators] [-verbose]\
[-corner corner_name]\
[-format slack_only|end]\
[-max_delay] [-min_delay]\
[-recovery] [-removal]\
@ -286,7 +290,7 @@ define_sta_cmd_args "report_check_types" \
proc_redirect report_check_types {
variable path_options
parse_key_args "report_check_types" args keys {}\
parse_key_args "report_check_types" args keys {-corner}\
flags {-all_violators -verbose -no_line_splits} 0
set all_violators [info exists flags(-all_violators)]
@ -305,6 +309,8 @@ proc_redirect report_check_types {
set min_max "max"
}
set corner [parse_corner_or_all keys]
if { $args == {} } {
if { $min_max == "max" || $min_max == "min_max" } {
set setup 1
@ -362,9 +368,32 @@ proc_redirect report_check_types {
sta_error "positional arguments not supported."
}
set corner [parse_corner_or_all keys]
if { $setup || $hold || $recovery || $removal \
|| $clk_gating_setup || $clk_gating_hold } {
set path_ends [report_check_types_cmd $all_violators \
if { ($setup && $hold) \
|| ($recovery && $removal) \
|| ($clk_gating_setup && $clk_gating_hold) } {
set path_min_max "min_max"
} elseif { $setup || $recovery || $clk_gating_setup } {
set path_min_max "max"
} elseif { $hold || $removal || $clk_gating_hold } {
set path_min_max "min"
}
if { $all_violators } {
set group_count $sta::int_max
set slack_min [expr -$sta::float_inf]
set slack_max 0.0
} else {
set group_count 1
set slack_min [expr -$sta::float_inf]
set slack_max $sta::float_inf
}
set path_ends [find_path_ends "NULL" {} "NULL" \
$corner $path_min_max $group_count 1 0 \
$slack_min $slack_max \
0 {} \
$setup $hold \
$recovery $removal \
$clk_gating_setup $clk_gating_hold]
@ -373,17 +402,17 @@ proc_redirect report_check_types {
}
if { $max_transition } {
report_slew_limits "max" $all_violators $verbose $nosplit
report_slew_limits $corner "max" $all_violators $verbose $nosplit
}
if { $min_transition } {
report_slew_limits "min" $all_violators $verbose $nosplit
report_slew_limits $corner "min" $all_violators $verbose $nosplit
}
if { $min_pulse_width } {
if { $all_violators } {
set checks [min_pulse_width_violations]
set checks [min_pulse_width_violations $corner]
report_mpw_checks $checks $verbose
} else {
set check [min_pulse_width_check_slack]
set check [min_pulse_width_check_slack $corner]
if { $check != "NULL" } {
report_mpw_check $check $verbose
}
@ -391,10 +420,10 @@ proc_redirect report_check_types {
}
if { $min_period } {
if { $all_violators } {
set checks [min_period_violations]
set checks [min_period_violations $corner]
report_min_period_checks $checks $verbose
} else {
set check [min_period_check_slack]
set check [min_period_check_slack $corner]
if { $check != "NULL" } {
report_min_period_check $check $verbose
}
@ -429,22 +458,24 @@ define_sta_cmd_args "report_disabled_edges" {}
################################################################
define_sta_cmd_args "report_pulse_width_checks" \
{[-verbose] [-digits digits] [-no_line_splits] [pins]\
{[-verbose] [-corner corner_name] [-digits digits] [-no_line_splits] [pins]\
[> filename] [>> filename]}
proc_redirect report_pulse_width_checks {
variable path_options
parse_key_args "report_pulse_width_checks" args keys {} flags {-verbose} 0
parse_key_args "report_pulse_width_checks" args keys {-corner} \
flags {-verbose} 0
# Only -digits and -no_line_splits are respected.
parse_report_path_options "report_pulse_width_checks" args "full" 0
check_argc_eq0or1 "report_pulse_width_checks" $args
set corner [parse_corner_or_all keys]
set verbose [info exists flags(-verbose)]
if { [llength $args] == 1 } {
set pins [get_port_pins_error "pins" [lindex $args 0]]
set checks [min_pulse_width_check_pins $pins]
set checks [min_pulse_width_check_pins $pins $corner]
} else {
set checks [min_pulse_width_checks]
set checks [min_pulse_width_checks $corner]
}
if { $checks != {} } {
report_mpw_checks $checks $verbose

View File

@ -2318,6 +2318,9 @@ private:
%inline %{
float float_inf = INF;
int int_max = std::numeric_limits<int>::max();
const char *
version()
{
@ -3163,10 +3166,11 @@ set_port_ext_fanout_cmd(Port *port,
void
set_net_wire_cap(Net *net,
bool subtract_pin_cap,
Corner *corner,
const MinMaxAll *min_max,
float cap)
{
Sta::sta()->setNetWireCap(net, subtract_pin_cap, min_max, cap);
Sta::sta()->setNetWireCap(net, subtract_pin_cap, corner, min_max, cap);
}
void
@ -4414,15 +4418,21 @@ PathEndSeq *
find_path_ends(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
Corner *corner,
const MinMaxAll *delay_min_max,
int group_count,
int endpoint_count,
bool unique_pins,
Corner *corner,
float slack_min,
float slack_max,
bool sort_by_slack,
PathGroupNameSet *groups)
PathGroupNameSet *groups,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clk_gating_setup,
bool clk_gating_hold)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
@ -4430,30 +4440,15 @@ find_path_ends(ExceptionFrom *from,
corner, delay_min_max,
group_count, endpoint_count, unique_pins,
slack_min, slack_max,
sort_by_slack, groups,
true, true, // setup, hold
true, true, // recovery, removal
true, true); // clk gating setup, hold
sort_by_slack,
groups->size() ? groups : NULL,
setup, hold,
recovery, removal,
clk_gating_setup, clk_gating_hold);
delete groups;
return ends;
}
PathEndSeq *
report_check_types_cmd(bool all_violators,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clock_gating_setup,
bool clock_gating_hold)
{
cmdLinkedNetwork();
return Sta::sta()->reportCheckTypes(all_violators,
setup, hold,
recovery, removal,
clock_gating_setup, clock_gating_hold);
}
void
set_report_path_format(ReportPathFormat format)
{
@ -4537,11 +4532,12 @@ report_path_cmd(Path *path)
void
report_clk_skew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
int digits)
{
cmdLinkedNetwork();
Sta::sta()->reportClkSkew(clks, setup_hold, digits);
Sta::sta()->reportClkSkew(clks, corner, setup_hold, digits);
delete clks;
}
@ -4577,33 +4573,35 @@ group_path_pins(const char *group_path_name)
////////////////////////////////////////////////////////////////
MinPulseWidthCheckSeq &
min_pulse_width_violations()
min_pulse_width_violations(const Corner *corner)
{
cmdLinkedNetwork();
return Sta::sta()->minPulseWidthViolations();
return Sta::sta()->minPulseWidthViolations(corner);
}
MinPulseWidthCheckSeq &
min_pulse_width_check_pins(PinSeq *pins)
min_pulse_width_check_pins(PinSeq *pins,
const Corner *corner)
{
cmdLinkedNetwork();
MinPulseWidthCheckSeq &checks = Sta::sta()->minPulseWidthChecks(pins);
Sta *sta = Sta::sta();
MinPulseWidthCheckSeq &checks = sta->minPulseWidthChecks(pins, corner);
delete pins;
return checks;
}
MinPulseWidthCheckSeq &
min_pulse_width_checks()
min_pulse_width_checks(const Corner *corner)
{
cmdLinkedNetwork();
return Sta::sta()->minPulseWidthChecks();
return Sta::sta()->minPulseWidthChecks(corner);
}
MinPulseWidthCheck *
min_pulse_width_check_slack()
min_pulse_width_check_slack(const Corner *corner)
{
cmdLinkedNetwork();
return Sta::sta()->minPulseWidthSlack();
return Sta::sta()->minPulseWidthSlack(corner);
}
void
@ -4623,17 +4621,17 @@ report_mpw_check(MinPulseWidthCheck *check,
////////////////////////////////////////////////////////////////
MinPeriodCheckSeq &
min_period_violations()
min_period_violations(const Corner *corner)
{
cmdLinkedNetwork();
return Sta::sta()->minPeriodViolations();
return Sta::sta()->minPeriodViolations(corner);
}
MinPeriodCheck *
min_period_check_slack()
min_period_check_slack(const Corner *corner)
{
cmdLinkedNetwork();
return Sta::sta()->minPeriodSlack();
return Sta::sta()->minPeriodSlack(corner);
}
void
@ -4779,17 +4777,19 @@ report_delay_calc_cmd(Edge *edge,
}
Pin *
pin_min_slew_limit_slack(const MinMax *min_max)
pin_min_slew_limit_slack(const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
return Sta::sta()->pinMinSlewLimitSlack(min_max);
return Sta::sta()->pinMinSlewLimitSlack(corner, min_max);
}
PinSeq *
pin_slew_limit_violations(const MinMax *min_max)
pin_slew_limit_violations(const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
return Sta::sta()->pinSlewLimitViolations(min_max);
return Sta::sta()->pinSlewLimitViolations(corner, min_max);
}
void
@ -4800,16 +4800,18 @@ report_slew_limit_short_header()
void
report_slew_limit_short(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
Sta::sta()->reportSlewLimitShort(pin, min_max);
Sta::sta()->reportSlewLimitShort(pin, corner, min_max);
}
void
report_slew_limit_verbose(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
Sta::sta()->reportSlewLimitVerbose(pin, min_max);
Sta::sta()->reportSlewLimitVerbose(pin, corner, min_max);
}
EdgeSeq *
@ -4937,13 +4939,14 @@ unset_clock_groups_asynchronous(const char *name)
Sta::sta()->removeClockGroupsAsynchronous(name);
}
// Debugging function.
bool
same_clk_group(Clock *clk1,
Clock *clk2)
{
Sta *sta = Sta::sta();
Sdc *sdc = sta->sdc();
return sdc->sameClockGroup(clk1, clk2);
return sdc->sameClockGroupExplicit(clk1, clk2);
}
void
@ -5725,31 +5728,34 @@ vertices()
float
capacitance(const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
float pin_cap, wire_cap;
Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap);
Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap);
return pin_cap + wire_cap;
}
float
pin_capacitance(const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
float pin_cap, wire_cap;
Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap);
Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap);
return pin_cap;
}
float
wire_capacitance(const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
float pin_cap, wire_cap;
Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap);
Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap);
return wire_cap;
}
@ -5786,31 +5792,34 @@ bool is_ground() { return cmdLinkedNetwork()->isGround(self);}
float
capacitance(const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
float pin_cap, wire_cap;
Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap);
Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap);
return pin_cap + wire_cap;
}
float
pin_capacitance(const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
float pin_cap, wire_cap;
Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap);
Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap);
return pin_cap;
}
float
wire_capacitance(const TransRiseFall *tr,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
float pin_cap, wire_cap;
Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap);
Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap);
return wire_cap;
}

View File

@ -43,6 +43,7 @@ verilogFlushBuffer()
%option never-interactive
%x COMMENT
%x ATTRIBUTE
%x QSTRING
SIGN "+"|"-"
@ -78,6 +79,21 @@ ID_TOKEN {ID_ESCAPED_TOKEN}|{ID_ALPHA_TOKEN}
}
}
"(*" { BEGIN ATTRIBUTE; }
<ATTRIBUTE>{
.
{EOL} { sta::verilog_reader->incrLine(); }
"*)" { BEGIN INITIAL; }
<<EOF>> {
VerilogParse_error("unterminated attribute");
BEGIN(INITIAL);
yyterminate();
}
}
{SIGN}?{UNSIGNED_NUMBER}?"'"[bB][01_xz]+ {
VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text);
return CONSTANT;