report paths in multiple matching groups resolves ascenium #145
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
de0f5440a6
commit
98d801d7a6
|
|
@ -68,7 +68,7 @@ public:
|
|||
path_delay
|
||||
};
|
||||
|
||||
virtual PathEnd *copy() = 0;
|
||||
virtual PathEnd *copy() const = 0;
|
||||
virtual ~PathEnd();
|
||||
void deletePath();
|
||||
Path *path() { return path_; }
|
||||
|
|
@ -84,6 +84,8 @@ public:
|
|||
PathAPIndex pathIndex(const StaState *sta) const;
|
||||
virtual void reportShort(const ReportPath *report) const = 0;
|
||||
virtual void reportFull(const ReportPath *report) const = 0;
|
||||
PathGroup *pathGroup() const { return path_group_; }
|
||||
void setPathGroup(PathGroup *path_group);
|
||||
|
||||
// Predicates for PathEnd type.
|
||||
// Default methods overridden by respective types.
|
||||
|
|
@ -216,6 +218,7 @@ protected:
|
|||
PathDelay *path_delay,
|
||||
const StaState *sta);
|
||||
Path *path_;
|
||||
PathGroup *path_group_;
|
||||
};
|
||||
|
||||
class PathEndUnconstrained : public PathEnd
|
||||
|
|
@ -224,7 +227,7 @@ public:
|
|||
explicit PathEndUnconstrained(Path *path);
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual PathEnd *copy();
|
||||
virtual PathEnd *copy() const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual bool isUnconstrained() const;
|
||||
|
|
@ -321,7 +324,7 @@ public:
|
|||
Path *clk_path,
|
||||
MultiCyclePath *mcp,
|
||||
const StaState *sta);
|
||||
virtual PathEnd *copy();
|
||||
virtual PathEnd *copy() const;
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
|
|
@ -367,7 +370,7 @@ public:
|
|||
virtual bool isCheck() const { return false; }
|
||||
virtual bool isLatchCheck() const { return true; }
|
||||
virtual PathDelay *pathDelay() const { return path_delay_; }
|
||||
virtual PathEnd *copy();
|
||||
virtual PathEnd *copy() const;
|
||||
Path *latchDisable();
|
||||
const Path *latchDisable() const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
|
|
@ -428,7 +431,7 @@ public:
|
|||
Path *clk_path,
|
||||
MultiCyclePath *mcp,
|
||||
const StaState *sta);
|
||||
virtual PathEnd *copy();
|
||||
virtual PathEnd *copy() const;
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
|
|
@ -474,7 +477,7 @@ public:
|
|||
MultiCyclePath *mcp,
|
||||
ArcDelay margin,
|
||||
const StaState *sta);
|
||||
virtual PathEnd *copy();
|
||||
virtual PathEnd *copy() const;
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
|
|
@ -506,7 +509,7 @@ public:
|
|||
Path *data_clk_path,
|
||||
MultiCyclePath *mcp,
|
||||
const StaState *sta);
|
||||
virtual PathEnd *copy();
|
||||
virtual PathEnd *copy() const;
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
|
|
@ -560,7 +563,7 @@ public:
|
|||
Path *path,
|
||||
OutputDelay *output_delay,
|
||||
const StaState *sta);
|
||||
virtual PathEnd *copy();
|
||||
virtual PathEnd *copy() const;
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ class PathEndVisitor;
|
|||
typedef PathEndSeq::Iterator PathGroupIterator;
|
||||
typedef Map<const Clock*, PathGroup*> PathGroupClkMap;
|
||||
typedef Map<const char*, PathGroup*, CharPtrLess> PathGroupNamedMap;
|
||||
typedef std::vector<PathGroup*> PathGroupSeq;
|
||||
typedef std::vector<std::string> StdStringSeq;
|
||||
|
||||
// A collection of PathEnds grouped and sorted for reporting.
|
||||
class PathGroup
|
||||
|
|
@ -133,8 +135,8 @@ public:
|
|||
const MinMax *min_max) const;
|
||||
PathGroup *findPathGroup(const Clock *clock,
|
||||
const MinMax *min_max) const;
|
||||
PathGroup *pathGroup(const PathEnd *path_end) const;
|
||||
static std::string pathGroupName(const PathEnd *path_end,
|
||||
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
||||
static StdStringSeq pathGroupNames(const PathEnd *path_end,
|
||||
const StaState *sta);
|
||||
static const char *asyncPathGroupName() { return async_group_name_; }
|
||||
static const char *pathDelayGroupName() { return path_delay_group_name_; }
|
||||
|
|
@ -179,8 +181,6 @@ protected:
|
|||
const MinMax *min_max);
|
||||
bool reportGroup(const char *group_name,
|
||||
PathGroupNameSet *group_names) const;
|
||||
static GroupPath *groupPathTo(const PathEnd *path_end,
|
||||
const StaState *sta);
|
||||
|
||||
int group_path_count_;
|
||||
int endpoint_path_count_;
|
||||
|
|
|
|||
|
|
@ -996,6 +996,12 @@ public:
|
|||
const MinMax *min_max,
|
||||
bool match_min_max_exactly,
|
||||
bool require_to_pin) const;
|
||||
void groupPathsTo(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const ClockEdge *clk_edge,
|
||||
const MinMax *min_max,
|
||||
// Return value.
|
||||
ExceptionPathSeq &group_paths) const;
|
||||
bool isCompleteTo(ExceptionState *state,
|
||||
const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -1164,6 +1170,13 @@ protected:
|
|||
// Return values.
|
||||
ExceptionPath *&hi_priority_exception,
|
||||
int &hi_priority) const;
|
||||
void groupPathsTo(const ExceptionPathSet *to_exceptions,
|
||||
const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const ClockEdge *clk_edge,
|
||||
const MinMax *min_max,
|
||||
// Return value.
|
||||
ExceptionPathSeq &group_paths) const;
|
||||
void makeLoopPath(ExceptionThruSeq *thrus);
|
||||
void makeLoopException(const Pin *loop_input_pin,
|
||||
const Pin *loop_pin,
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ typedef Map<Vertex*, Slack> VertexSlackMap;
|
|||
typedef Vector<VertexSlackMap> VertexSlackMapSeq;
|
||||
typedef Vector<WorstSlacks> WorstSlacksSeq;
|
||||
typedef std::vector<DelayDbl> DelayDblSeq;
|
||||
typedef Vector<ExceptionPath*> ExceptionPathSeq;
|
||||
typedef std::vector<PathGroup*> PathGroupSeq;
|
||||
|
||||
class Search : public StaState
|
||||
{
|
||||
|
|
@ -165,7 +167,7 @@ public:
|
|||
// Clock arrival at the path source/launch point.
|
||||
Arrival pathClkPathArrival(const Path *path) const;
|
||||
|
||||
PathGroup *pathGroup(const PathEnd *path_end) const;
|
||||
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
||||
void deletePathGroups();
|
||||
void makePathGroups(int group_path_count,
|
||||
int endpoint_path_count,
|
||||
|
|
@ -187,6 +189,7 @@ public:
|
|||
const MinMax *min_max,
|
||||
bool match_min_max_exactly,
|
||||
bool require_to_pin) const;
|
||||
ExceptionPathSeq groupPathsTo(const PathEnd *path_end) const;
|
||||
FilterPath *filter() const { return filter_; }
|
||||
void deleteFilter();
|
||||
void deleteFilteredArrivals();
|
||||
|
|
|
|||
43
sdc/Sdc.cc
43
sdc/Sdc.cc
|
|
@ -5362,6 +5362,8 @@ Sdc::exceptionThruStates(const ExceptionPathSet *exceptions,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
Sdc::exceptionTo(ExceptionPathType type,
|
||||
const Pin *pin,
|
||||
|
|
@ -5484,6 +5486,47 @@ Sdc::isCompleteTo(ExceptionState *state,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
Sdc::groupPathsTo(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const ClockEdge *clk_edge,
|
||||
const MinMax *min_max,
|
||||
// Return value.
|
||||
ExceptionPathSeq &group_paths) const
|
||||
{
|
||||
if (!first_to_inst_exceptions_.empty()) {
|
||||
Instance *inst = network_->instance(pin);
|
||||
groupPathsTo(first_to_inst_exceptions_.findKey(inst), pin, rf,
|
||||
clk_edge, min_max, group_paths);
|
||||
}
|
||||
if (!first_to_pin_exceptions_.empty())
|
||||
groupPathsTo(first_to_pin_exceptions_.findKey(pin), pin, rf,
|
||||
clk_edge, min_max, group_paths);
|
||||
if (clk_edge && !first_to_clk_exceptions_.empty())
|
||||
groupPathsTo(first_to_clk_exceptions_.findKey(clk_edge->clock()),
|
||||
pin, rf, clk_edge, min_max, group_paths);
|
||||
}
|
||||
|
||||
void
|
||||
Sdc::groupPathsTo(const ExceptionPathSet *to_exceptions,
|
||||
const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const ClockEdge *clk_edge,
|
||||
const MinMax *min_max,
|
||||
// Return value.
|
||||
ExceptionPathSeq &group_paths) const
|
||||
{
|
||||
if (to_exceptions) {
|
||||
for (ExceptionPath *exception : *to_exceptions) {
|
||||
if (exception->isGroupPath()
|
||||
&& exceptionMatchesTo(exception, pin, rf, clk_edge, min_max, true, false))
|
||||
group_paths.push_back(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Wireload *
|
||||
Sdc::wireload(const MinMax *min_max)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ Path::isClock(const StaState *sta) const
|
|||
const MinMax *
|
||||
Path::minMax(const StaState *sta) const
|
||||
{
|
||||
return pathAnalysisPt(sta)->pathMinMax();
|
||||
return tag(sta)->minMax(sta);
|
||||
}
|
||||
|
||||
PathAPIndex
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@
|
|||
namespace sta {
|
||||
|
||||
PathEnd::PathEnd(Path *path) :
|
||||
path_(path)
|
||||
path_(path),
|
||||
path_group_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +66,12 @@ PathEnd::setPath(Path *path)
|
|||
path_ = path;
|
||||
}
|
||||
|
||||
void
|
||||
PathEnd::setPathGroup(PathGroup *path_group)
|
||||
{
|
||||
path_group_ = path_group;
|
||||
}
|
||||
|
||||
Vertex *
|
||||
PathEnd::vertex(const StaState *sta) const
|
||||
{
|
||||
|
|
@ -454,7 +461,7 @@ PathEndUnconstrained::PathEndUnconstrained(Path *path) :
|
|||
}
|
||||
|
||||
PathEnd *
|
||||
PathEndUnconstrained::copy()
|
||||
PathEndUnconstrained::copy() const
|
||||
{
|
||||
return new PathEndUnconstrained(path_);
|
||||
}
|
||||
|
|
@ -955,7 +962,7 @@ PathEndCheck::PathEndCheck(Path *path,
|
|||
}
|
||||
|
||||
PathEnd *
|
||||
PathEndCheck::copy()
|
||||
PathEndCheck::copy() const
|
||||
{
|
||||
return new PathEndCheck(path_, check_arc_, check_edge_,
|
||||
clk_path_, mcp_, crpr_, crpr_valid_);
|
||||
|
|
@ -1126,7 +1133,7 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path,
|
|||
}
|
||||
|
||||
PathEnd *
|
||||
PathEndLatchCheck::copy()
|
||||
PathEndLatchCheck::copy() const
|
||||
{
|
||||
return new PathEndLatchCheck(path_, check_arc_, check_edge_,
|
||||
clk_path_, disable_path_, mcp_, path_delay_,
|
||||
|
|
@ -1346,7 +1353,7 @@ PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay,
|
|||
}
|
||||
|
||||
PathEnd *
|
||||
PathEndOutputDelay::copy()
|
||||
PathEndOutputDelay::copy() const
|
||||
{
|
||||
return new PathEndOutputDelay(output_delay_, path_, clk_path_,
|
||||
mcp_, crpr_, crpr_valid_);
|
||||
|
|
@ -1552,7 +1559,7 @@ PathEndGatedClock::PathEndGatedClock(Path *gating_ref,
|
|||
}
|
||||
|
||||
PathEnd *
|
||||
PathEndGatedClock::copy()
|
||||
PathEndGatedClock::copy() const
|
||||
{
|
||||
return new PathEndGatedClock(path_, clk_path_, check_role_,
|
||||
mcp_, margin_, crpr_, crpr_valid_);
|
||||
|
|
@ -1668,7 +1675,7 @@ PathEndDataCheck::PathEndDataCheck(DataCheck *check,
|
|||
}
|
||||
|
||||
PathEnd *
|
||||
PathEndDataCheck::copy()
|
||||
PathEndDataCheck::copy() const
|
||||
{
|
||||
return new PathEndDataCheck(check_, path_, data_clk_path_,
|
||||
clk_path_, mcp_, crpr_, crpr_valid_);
|
||||
|
|
@ -1825,7 +1832,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
|
|||
}
|
||||
|
||||
PathEnd *
|
||||
PathEndPathDelay::copy()
|
||||
PathEndPathDelay::copy() const
|
||||
{
|
||||
return new PathEndPathDelay(path_delay_, path_, clk_path_,
|
||||
check_arc_, check_edge_, output_delay_,
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ PathGroup::insert(PathEnd *path_end)
|
|||
{
|
||||
LockGuard lock(lock_);
|
||||
path_ends_.push_back(path_end);
|
||||
path_end->setPathGroup(this);
|
||||
if (group_path_count_ != group_path_count_max
|
||||
&& path_ends_.size() > group_path_count_ * 2)
|
||||
prune();
|
||||
|
|
@ -398,21 +399,27 @@ PathGroups::reportGroup(const char *group_name,
|
|||
|| group_names->hasKey(group_name);
|
||||
}
|
||||
|
||||
PathGroup *
|
||||
PathGroups::pathGroup(const PathEnd *path_end) const
|
||||
PathGroupSeq
|
||||
PathGroups::pathGroups(const PathEnd *path_end) const
|
||||
{
|
||||
PathGroupSeq path_groups;
|
||||
PathGroup *path_group = nullptr;
|
||||
ExceptionPathSeq group_paths = search_->groupPathsTo(path_end);
|
||||
const MinMax *min_max = path_end->minMax(this);
|
||||
int mm_index = min_max->index();
|
||||
GroupPath *group_path = groupPathTo(path_end, this);
|
||||
if (path_end->isUnconstrained())
|
||||
return unconstrained_[mm_index];
|
||||
path_group = unconstrained_[mm_index];
|
||||
// GroupPaths have precedence.
|
||||
else if (group_path) {
|
||||
else if (!group_paths.empty()) {
|
||||
for (ExceptionPath *group_path : group_paths) {
|
||||
if (group_path->isDefault())
|
||||
return path_delay_[mm_index];
|
||||
path_groups.push_back(path_delay_[mm_index]);
|
||||
else {
|
||||
const char *group_name = group_path->name();
|
||||
return findPathGroup(group_name, min_max);
|
||||
PathGroup *group = findPathGroup(group_name, min_max);
|
||||
if (group)
|
||||
path_groups.push_back(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (path_end->isCheck() || path_end->isLatchCheck()) {
|
||||
|
|
@ -420,15 +427,15 @@ PathGroups::pathGroup(const PathEnd *path_end) const
|
|||
const Clock *tgt_clk = path_end->targetClk(this);
|
||||
if (check_role == TimingRole::removal()
|
||||
|| check_role == TimingRole::recovery())
|
||||
return async_[mm_index];
|
||||
path_group = async_[mm_index];
|
||||
else
|
||||
return findPathGroup(tgt_clk, min_max);
|
||||
path_group = findPathGroup(tgt_clk, min_max);
|
||||
}
|
||||
else if (path_end->isOutputDelay()
|
||||
|| path_end->isDataCheck())
|
||||
return findPathGroup(path_end->targetClk(this), min_max);
|
||||
path_group = findPathGroup(path_end->targetClk(this), min_max);
|
||||
else if (path_end->isGatedClock())
|
||||
return gated_clk_[mm_index];
|
||||
path_group = gated_clk_[mm_index];
|
||||
else if (path_end->isPathDelay()) {
|
||||
// Path delays that end at timing checks are part of the target clk group
|
||||
// unless -ignore_clock_latency is true.
|
||||
|
|
@ -436,45 +443,52 @@ PathGroups::pathGroup(const PathEnd *path_end) const
|
|||
const Clock *tgt_clk = path_end->targetClk(this);
|
||||
if (tgt_clk
|
||||
&& !path_delay->ignoreClkLatency())
|
||||
return findPathGroup(tgt_clk, min_max);
|
||||
path_group = findPathGroup(tgt_clk, min_max);
|
||||
else
|
||||
return path_delay_[mm_index];
|
||||
}
|
||||
else {
|
||||
report_->critical(1390, "unknown path end type");
|
||||
return nullptr;
|
||||
path_group = path_delay_[mm_index];
|
||||
}
|
||||
if (path_group)
|
||||
path_groups.push_back(path_group);
|
||||
return path_groups;
|
||||
}
|
||||
|
||||
// Mirrors PathGroups::pathGroup.
|
||||
std::string
|
||||
PathGroups::pathGroupName(const PathEnd *path_end,
|
||||
StdStringSeq
|
||||
PathGroups::pathGroupNames(const PathEnd *path_end,
|
||||
const StaState *sta)
|
||||
{
|
||||
GroupPath *group_path = groupPathTo(path_end, sta);
|
||||
StdStringSeq group_names;
|
||||
const char *group_name = nullptr;
|
||||
const Search *search = sta->search();
|
||||
ExceptionPathSeq group_paths = search->groupPathsTo(path_end);
|
||||
if (path_end->isUnconstrained())
|
||||
return unconstrained_group_name_;
|
||||
group_name = unconstrained_group_name_;
|
||||
else if (!group_paths.empty()) {
|
||||
// GroupPaths have precedence.
|
||||
else if (group_path) {
|
||||
for (ExceptionPath *group_path : group_paths) {
|
||||
if (group_path->isDefault())
|
||||
return path_delay_group_name_;
|
||||
group_names.push_back(path_delay_group_name_);
|
||||
else
|
||||
return group_path->name();
|
||||
group_names.push_back(group_path->name());
|
||||
}
|
||||
}
|
||||
else if (path_end->isCheck() || path_end->isLatchCheck()) {
|
||||
const TimingRole *check_role = path_end->checkRole(sta);
|
||||
const Clock *tgt_clk = path_end->targetClk(sta);
|
||||
if (check_role == TimingRole::removal()
|
||||
|| check_role == TimingRole::recovery())
|
||||
return async_group_name_;
|
||||
group_name = async_group_name_;
|
||||
else
|
||||
return tgt_clk->name();
|
||||
group_name = tgt_clk->name();
|
||||
}
|
||||
else if (path_end->isOutputDelay()
|
||||
|| path_end->isDataCheck())
|
||||
return path_end->targetClk(sta)->name();
|
||||
|| path_end->isDataCheck()) {
|
||||
const Clock *tgt_clk = path_end->targetClk(sta);
|
||||
if (tgt_clk)
|
||||
group_name = tgt_clk->name();
|
||||
}
|
||||
else if (path_end->isGatedClock())
|
||||
return gated_clk_group_name_;
|
||||
group_name = gated_clk_group_name_;
|
||||
else if (path_end->isPathDelay()) {
|
||||
// Path delays that end at timing checks are part of the target clk group
|
||||
// unless -ignore_clock_latency is true.
|
||||
|
|
@ -482,28 +496,13 @@ PathGroups::pathGroupName(const PathEnd *path_end,
|
|||
const Clock *tgt_clk = path_end->targetClk(sta);
|
||||
if (tgt_clk
|
||||
&& !path_delay->ignoreClkLatency())
|
||||
return tgt_clk->name();
|
||||
group_name = tgt_clk->name();
|
||||
else
|
||||
return path_delay_group_name_;
|
||||
group_name = path_delay_group_name_;
|
||||
}
|
||||
else {
|
||||
sta->report()->critical(1391, "unknown path end type");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
GroupPath *
|
||||
PathGroups::groupPathTo(const PathEnd *path_end,
|
||||
const StaState *sta)
|
||||
{
|
||||
const Path *path = path_end->path();
|
||||
const Pin *pin = path->pin(sta);
|
||||
ExceptionPath *exception =
|
||||
sta->search()->exceptionTo(ExceptionPathType::group_path, path,
|
||||
pin, path->transition(sta),
|
||||
path_end->targetClkEdge(sta),
|
||||
path->minMax(sta), false, false);
|
||||
return dynamic_cast<GroupPath*>(exception);
|
||||
if (group_name)
|
||||
group_names.push_back(group_name);
|
||||
return group_names;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -632,8 +631,7 @@ MakePathEnds1::copy() const
|
|||
void
|
||||
MakePathEnds1::visit(PathEnd *path_end)
|
||||
{
|
||||
PathGroup *group = path_groups_->pathGroup(path_end);
|
||||
if (group)
|
||||
for (PathGroup *group : path_groups_->pathGroups(path_end))
|
||||
visitPathEnd(path_end, group);
|
||||
}
|
||||
|
||||
|
|
@ -644,14 +642,15 @@ MakePathEnds1::visitPathEnd(PathEnd *path_end,
|
|||
if (group->saveable(path_end)) {
|
||||
// Only keep the path end with the smallest slack/latest arrival.
|
||||
PathEnd *worst_end = ends_.findKey(group);
|
||||
PathEnd *copy = path_end->copy();
|
||||
if (worst_end) {
|
||||
if (cmp_(path_end, worst_end)) {
|
||||
ends_[group] = path_end->copy();
|
||||
ends_[group] = copy;
|
||||
delete worst_end;
|
||||
}
|
||||
}
|
||||
else
|
||||
ends_[group] = path_end->copy();
|
||||
ends_[group] = copy;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -732,8 +731,7 @@ MakePathEndsAll::~MakePathEndsAll()
|
|||
void
|
||||
MakePathEndsAll::visit(PathEnd *path_end)
|
||||
{
|
||||
PathGroup *group = path_groups_->pathGroup(path_end);
|
||||
if (group)
|
||||
for (PathGroup *group : path_groups_->pathGroups(path_end))
|
||||
visitPathEnd(path_end, group);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -401,8 +401,8 @@ ReportPath::reportEndpointHeader(const PathEnd *end,
|
|||
{
|
||||
PathGroup *prev_group = nullptr;
|
||||
if (prev_end)
|
||||
prev_group = search_->pathGroup(prev_end);
|
||||
PathGroup *group = search_->pathGroup(end);
|
||||
prev_group = prev_end->pathGroup();
|
||||
PathGroup *group = end->pathGroup();
|
||||
if (group && group != prev_group) {
|
||||
if (prev_group)
|
||||
reportBlankLine();
|
||||
|
|
@ -1086,7 +1086,7 @@ ReportPath::reportJson(const PathEnd *end,
|
|||
result += "{\n";
|
||||
stringAppend(result, " \"type\": \"%s\",\n", end->typeName());
|
||||
stringAppend(result, " \"path_group\": \"%s\",\n",
|
||||
search_->pathGroup(end)->name());
|
||||
end->pathGroup()->name());
|
||||
stringAppend(result, " \"path_type\": \"%s\",\n",
|
||||
end->minMax(this)->to_string().c_str());
|
||||
|
||||
|
|
@ -1273,7 +1273,7 @@ ReportPath::reportSlackOnly(const PathEnd *end) const
|
|||
{
|
||||
string line;
|
||||
const EarlyLate *early_late = end->pathEarlyLate(this);
|
||||
reportDescription(search_->pathGroup(end)->name(), line);
|
||||
reportDescription(end->pathGroup()->name(), line);
|
||||
if (end->isUnconstrained())
|
||||
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, line);
|
||||
else
|
||||
|
|
@ -1939,7 +1939,7 @@ ReportPath::reportGroup(const PathEnd *end) const
|
|||
{
|
||||
string line;
|
||||
line = "Path Group: ";
|
||||
PathGroup *group = search_->pathGroup(end);
|
||||
PathGroup *group = end->pathGroup();
|
||||
line += group ? group->name() : "(none)";
|
||||
report_->reportLineString(line);
|
||||
|
||||
|
|
|
|||
|
|
@ -3767,6 +3767,34 @@ Search::exceptionTo(ExceptionPathType type,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Find group paths that end at the path.
|
||||
ExceptionPathSeq
|
||||
Search::groupPathsTo(const PathEnd *path_end) const
|
||||
{
|
||||
ExceptionPathSeq group_paths;
|
||||
const Path *path = path_end->path();
|
||||
const Pin *pin = path->pin(this);
|
||||
const Tag *tag = path->tag(this);
|
||||
const RiseFall *rf = tag->transition();
|
||||
const ClockEdge *clk_edge = path_end->targetClkEdge(this);
|
||||
const MinMax *min_max = tag->minMax(this);
|
||||
const ExceptionStateSet *states = path->tag(this)->states();
|
||||
if (states) {
|
||||
for (auto state : *states) {
|
||||
ExceptionPath *exception = state->exception();
|
||||
if (exception->isGroupPath()
|
||||
&& sdc_->exceptionMatchesTo(exception, pin, rf, clk_edge, min_max,
|
||||
false, false))
|
||||
group_paths.push_back(exception);
|
||||
}
|
||||
}
|
||||
// Check for group_path -to exceptions originating at the end pin or target clock.
|
||||
sdc_->groupPathsTo(pin, rf, clk_edge, min_max, group_paths);
|
||||
return group_paths;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Slack
|
||||
Search::totalNegativeSlack(const MinMax *min_max)
|
||||
{
|
||||
|
|
@ -4095,13 +4123,13 @@ Search::deletePathGroups()
|
|||
path_groups_ = nullptr;
|
||||
}
|
||||
|
||||
PathGroup *
|
||||
Search::pathGroup(const PathEnd *path_end) const
|
||||
PathGroupSeq
|
||||
Search::pathGroups(const PathEnd *path_end) const
|
||||
{
|
||||
if (path_groups_)
|
||||
return path_groups_->pathGroup(path_end);
|
||||
return path_groups_->pathGroups(path_end);
|
||||
else
|
||||
return nullptr;
|
||||
return PathGroupSeq();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -3068,12 +3068,16 @@ EndpointPathEndVisitor::copy() const
|
|||
void
|
||||
EndpointPathEndVisitor::visit(PathEnd *path_end)
|
||||
{
|
||||
if (path_end->minMax(sta_) == min_max_
|
||||
&& PathGroups::pathGroupName(path_end, sta_) == path_group_name_) {
|
||||
if (path_end->minMax(sta_) == min_max_) {
|
||||
StdStringSeq group_names = PathGroups::pathGroupNames(path_end, sta_);
|
||||
for (std::string &group_name : group_names) {
|
||||
if (group_name == path_group_name_) {
|
||||
Slack end_slack = path_end->slack(sta_);
|
||||
if (delayLess(end_slack, slack_, sta_))
|
||||
slack_ = end_slack;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slack
|
||||
|
|
|
|||
|
|
@ -181,6 +181,12 @@ Tag::transition() const
|
|||
return RiseFall::find(rf_index_);
|
||||
}
|
||||
|
||||
const MinMax *
|
||||
Tag::minMax(const StaState *sta) const
|
||||
{
|
||||
return pathAnalysisPt(sta)->pathMinMax();
|
||||
}
|
||||
|
||||
PathAnalysisPt *
|
||||
Tag::pathAnalysisPt(const StaState *sta) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ public:
|
|||
const Pin *clkSrc() const;
|
||||
int rfIndex() const { return rf_index_; }
|
||||
const RiseFall *transition() const;
|
||||
const MinMax *minMax(const StaState *sta) const;
|
||||
PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
|
||||
PathAPIndex pathAPIndex() const { return path_ap_index_; }
|
||||
TagIndex index() const { return index_; }
|
||||
|
|
|
|||
|
|
@ -177,13 +177,15 @@ VisitPathGroupEnds::vertexBegin(Vertex *)
|
|||
void
|
||||
VisitPathGroupEnds::visit(PathEnd *path_end)
|
||||
{
|
||||
PathGroup *group = sta_->search()->pathGroup(path_end);
|
||||
PathGroupSeq groups = sta_->search()->pathGroups(path_end);
|
||||
for (PathGroup *group : groups) {
|
||||
if (group == path_group_) {
|
||||
Path *path = path_end->path();
|
||||
Vertex *vertex = path->vertex(sta_);
|
||||
vertexPathSetMapInsertPath(matching_path_map_, vertex, path->tag(sta_), sta_);
|
||||
vertex_matches_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Reference in New Issue