report_checks -endpoint_path_count speedup
commit 265f5d69051c823656fcfedfa7e086255c4df4d2
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Feb 26 14:43:28 2025 -0800
PathEnum::makeDivertedPath rm visited set
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit bbf28deab4f01eb925b4d7c86e23f4ec39e8d11d
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 22 11:37:38 2025 -0700
Search::always_save_prev_paths_
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit fd587877c3931ea6dd05d2f21d53365fd70d4268
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 22 08:33:34 2025 -0700
PathVertexRep -> PathPrev
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 3c972474b85875c1acaea808eb66fcfd26356120
Author: James Cherry <cherry@parallaxsw.com>
Date: Fri Feb 21 11:26:02 2025 -0700
PathVertexPtr
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 3755de934a8ecd292595d781ef794d60f0f5a67b
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 20 17:19:34 2025 -0700
PathVertexPtr for ClkInfo
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 3dca0c21c0117bc2fc64ee94ddb1513f3ff92d30
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 20 17:19:15 2025 -0700
PathVertexPtr for ClkInfo
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 419f78f75d1393b8b07de1e7028960a5fb7c8cad
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 20 16:05:44 2025 -0700
PathVertexRep rm unused funcs
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 32052f32eb09e6fe7fb2e3c3953ee55b5aaf976f
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 20 14:49:19 2025 -0700
PathVertexRep rm vertex_id_
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 89c65de68b12daa1c3869b83a5fd9afbcb2ce098
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 20 09:21:16 2025 -0700
rm Search::arrivalInvalidDelete
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 7d5d88ed124b94e08da433e1c6ea70629aa6c6e7
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 20 09:17:35 2025 -0700
passes fast
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit e6810d64993938e912b7cf89a4c36b24d744270f
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Feb 19 21:05:45 2025 -0700
always save prev_path
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
f5cd0b24c7
commit
0f379ffcad
|
|
@ -189,9 +189,10 @@ set(STA_SOURCE
|
||||||
search/PathEnumed.cc
|
search/PathEnumed.cc
|
||||||
search/PathExpanded.cc
|
search/PathExpanded.cc
|
||||||
search/PathGroup.cc
|
search/PathGroup.cc
|
||||||
|
search/PathPrev.cc
|
||||||
search/PathRef.cc
|
search/PathRef.cc
|
||||||
search/PathVertex.cc
|
search/PathVertex.cc
|
||||||
search/PathVertexRep.cc
|
search/PathVertexPtr.cc
|
||||||
search/Property.cc
|
search/Property.cc
|
||||||
search/ReportPath.cc
|
search/ReportPath.cc
|
||||||
search/Search.cc
|
search/Search.cc
|
||||||
|
|
|
||||||
|
|
@ -613,17 +613,17 @@ Graph::deleteRequireds(Vertex *vertex)
|
||||||
vertex->setRequireds(nullptr);
|
vertex->setRequireds(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertexRep *
|
PathPrev *
|
||||||
Graph::prevPaths(const Vertex *vertex) const
|
Graph::prevPaths(const Vertex *vertex) const
|
||||||
{
|
{
|
||||||
return vertex->prevPaths();
|
return vertex->prevPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertexRep *
|
PathPrev *
|
||||||
Graph::makePrevPaths(Vertex *vertex,
|
Graph::makePrevPaths(Vertex *vertex,
|
||||||
uint32_t count)
|
uint32_t count)
|
||||||
{
|
{
|
||||||
PathVertexRep *prev_paths = new PathVertexRep[count];
|
PathPrev *prev_paths = new PathPrev[count];
|
||||||
vertex->setPrevPaths(prev_paths);
|
vertex->setPrevPaths(prev_paths);
|
||||||
return prev_paths;
|
return prev_paths;
|
||||||
}
|
}
|
||||||
|
|
@ -1167,7 +1167,7 @@ Vertex::setRequireds(Required *requireds)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Vertex::setPrevPaths(PathVertexRep *prev_paths)
|
Vertex::setPrevPaths(PathPrev *prev_paths)
|
||||||
{
|
{
|
||||||
delete [] prev_paths_;
|
delete [] prev_paths_;
|
||||||
prev_paths_ = prev_paths;
|
prev_paths_ = prev_paths;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
#include "Delay.hh"
|
#include "Delay.hh"
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
#include "VertexId.hh"
|
#include "VertexId.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -55,7 +55,7 @@ typedef ObjectId EdgeId;
|
||||||
|
|
||||||
static constexpr EdgeId edge_id_null = object_id_null;
|
static constexpr EdgeId edge_id_null = object_id_null;
|
||||||
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
||||||
static constexpr ObjectIdx vertex_idx_null = object_id_null;
|
static constexpr ObjectIdx vertex_idx_null = object_idx_null;
|
||||||
|
|
||||||
// The graph acts as a BUILDER for the graph vertices and edges.
|
// The graph acts as a BUILDER for the graph vertices and edges.
|
||||||
class Graph : public StaState
|
class Graph : public StaState
|
||||||
|
|
@ -104,9 +104,9 @@ public:
|
||||||
uint32_t count);
|
uint32_t count);
|
||||||
Required *requireds(const Vertex *vertex) const;
|
Required *requireds(const Vertex *vertex) const;
|
||||||
void deleteRequireds(Vertex *vertex);
|
void deleteRequireds(Vertex *vertex);
|
||||||
PathVertexRep *makePrevPaths(Vertex *vertex,
|
PathPrev *makePrevPaths(Vertex *vertex,
|
||||||
uint32_t count);
|
uint32_t count);
|
||||||
PathVertexRep *prevPaths(const Vertex *vertex) const;
|
PathPrev *prevPaths(const Vertex *vertex) const;
|
||||||
void deletePrevPaths(Vertex *vertex);
|
void deletePrevPaths(Vertex *vertex);
|
||||||
// Private to Search::deletePaths(Vertex).
|
// Private to Search::deletePaths(Vertex).
|
||||||
void deletePaths(Vertex *vertex);
|
void deletePaths(Vertex *vertex);
|
||||||
|
|
@ -271,8 +271,8 @@ public:
|
||||||
const Slew *slews() const { return slews_; }
|
const Slew *slews() const { return slews_; }
|
||||||
Arrival *arrivals() const { return arrivals_; }
|
Arrival *arrivals() const { return arrivals_; }
|
||||||
Arrival *requireds() const { return requireds_; }
|
Arrival *requireds() const { return requireds_; }
|
||||||
PathVertexRep *prevPaths() const { return prev_paths_; }
|
PathPrev *prevPaths() const { return prev_paths_; }
|
||||||
void setPrevPaths(PathVertexRep *prev_paths);
|
void setPrevPaths(PathPrev *prev_paths);
|
||||||
TagGroupIndex tagGroupIndex() const;
|
TagGroupIndex tagGroupIndex() const;
|
||||||
void setTagGroupIndex(TagGroupIndex tag_index);
|
void setTagGroupIndex(TagGroupIndex tag_index);
|
||||||
// Slew is annotated by sdc set_annotated_transition cmd.
|
// Slew is annotated by sdc set_annotated_transition cmd.
|
||||||
|
|
@ -337,7 +337,7 @@ protected:
|
||||||
// Search
|
// Search
|
||||||
Arrival *arrivals_;
|
Arrival *arrivals_;
|
||||||
Arrival *requireds_;
|
Arrival *requireds_;
|
||||||
PathVertexRep *prev_paths_;
|
PathPrev *prev_paths_;
|
||||||
|
|
||||||
// These fields are written by multiple threads, so they
|
// These fields are written by multiple threads, so they
|
||||||
// cannot share the same word as the following bit fields.
|
// cannot share the same word as the following bit fields.
|
||||||
|
|
@ -382,7 +382,9 @@ public:
|
||||||
Edge();
|
Edge();
|
||||||
~Edge();
|
~Edge();
|
||||||
Vertex *to(const Graph *graph) const { return graph->vertex(to_); }
|
Vertex *to(const Graph *graph) const { return graph->vertex(to_); }
|
||||||
|
VertexId to() const { return to_; }
|
||||||
Vertex *from(const Graph *graph) const { return graph->vertex(from_); }
|
Vertex *from(const Graph *graph) const { return graph->vertex(from_); }
|
||||||
|
VertexId from() const { return from_; }
|
||||||
TimingRole *role() const;
|
TimingRole *role() const;
|
||||||
bool isWire() const;
|
bool isWire() const;
|
||||||
TimingSense sense() const;
|
TimingSense sense() const;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SdcClass.hh"
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc.
|
||||||
|
class PathPrev
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathPrev();
|
||||||
|
PathPrev(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
|
const StaState *sta);
|
||||||
|
void init();
|
||||||
|
void init(const PathPrev *path);
|
||||||
|
void init(const PathPrev &path);
|
||||||
|
void init(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
|
const StaState *sta);
|
||||||
|
bool isNull() const;
|
||||||
|
const char *name(const StaState *sta) const;
|
||||||
|
Vertex *vertex(const StaState *sta) const;
|
||||||
|
VertexId vertexId(const StaState *sta) const;
|
||||||
|
Edge *prevEdge(const StaState *sta) const;
|
||||||
|
TimingArc *prevArc(const StaState *sta) const;
|
||||||
|
Tag *tag(const StaState *sta) const;
|
||||||
|
TagIndex tagIndex() const { return prev_tag_index_; }
|
||||||
|
Arrival arrival(const StaState *sta) const;
|
||||||
|
void prevPath(const StaState *sta,
|
||||||
|
// Return values.
|
||||||
|
PathRef &prev_path,
|
||||||
|
TimingArc *&prev_arc) const;
|
||||||
|
|
||||||
|
static bool equal(const PathPrev *path1,
|
||||||
|
const PathPrev *path2);
|
||||||
|
static bool equal(const PathPrev &path1,
|
||||||
|
const PathPrev &path2);
|
||||||
|
static int cmp(const PathPrev &path1,
|
||||||
|
const PathPrev &path2);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EdgeId prev_edge_id_;
|
||||||
|
TagIndex prev_tag_index_:tag_index_bit_count;
|
||||||
|
unsigned prev_arc_idx_:2;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -49,6 +49,8 @@ public:
|
||||||
void init(const PathRef *path);
|
void init(const PathRef *path);
|
||||||
void init(const PathVertex &path);
|
void init(const PathVertex &path);
|
||||||
void init(const PathVertex *path);
|
void init(const PathVertex *path);
|
||||||
|
void init(const PathPrev &path,
|
||||||
|
const StaState *sta);
|
||||||
void init(Vertex *vertex,
|
void init(Vertex *vertex,
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
int arrival_index);
|
int arrival_index);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
class PathVertexRep;
|
class PathPrev;
|
||||||
|
class PathVertexPtr;
|
||||||
|
|
||||||
// Implements Path API for a vertex.
|
// Implements Path API for a vertex.
|
||||||
class PathVertex : public Path
|
class PathVertex : public Path
|
||||||
|
|
@ -38,9 +39,11 @@ public:
|
||||||
PathVertex();
|
PathVertex();
|
||||||
PathVertex(const PathVertex &path);
|
PathVertex(const PathVertex &path);
|
||||||
PathVertex(const PathVertex *path);
|
PathVertex(const PathVertex *path);
|
||||||
PathVertex(const PathVertexRep *path,
|
PathVertex(const PathPrev *path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
PathVertex(const PathVertexRep &path,
|
PathVertex(const PathPrev &path,
|
||||||
|
const StaState *sta);
|
||||||
|
PathVertex(const PathVertexPtr &path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
// If tag is not in the vertex tag group isNull() is true.
|
// If tag is not in the vertex tag group isNull() is true.
|
||||||
PathVertex(Vertex *vertex,
|
PathVertex(Vertex *vertex,
|
||||||
|
|
@ -50,9 +53,11 @@ public:
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
int arrival_index);
|
int arrival_index);
|
||||||
void init();
|
void init();
|
||||||
void init(const PathVertexRep *path,
|
void init(const PathPrev *path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
void init(const PathVertexRep &path,
|
void init(const PathPrev &path,
|
||||||
|
const StaState *sta);
|
||||||
|
void init(const PathVertexPtr &path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
void init(Vertex *vertex,
|
void init(Vertex *vertex,
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
// "Pointer" to a vertex path because there is no real path object to point to.
|
||||||
|
class PathVertexPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathVertexPtr();
|
||||||
|
PathVertexPtr(const PathVertex *path,
|
||||||
|
const StaState *sta);
|
||||||
|
void init();
|
||||||
|
void init(const PathVertexPtr *path);
|
||||||
|
void init(const PathVertexPtr &path);
|
||||||
|
void init(const PathVertex *path,
|
||||||
|
const StaState *sta);
|
||||||
|
bool isNull() const;
|
||||||
|
const char *name(const StaState *sta) const;
|
||||||
|
Vertex *vertex(const StaState *sta) const;
|
||||||
|
VertexId vertexId() const { return vertex_id_; }
|
||||||
|
Tag *tag(const StaState *sta) const;
|
||||||
|
TagIndex tagIndex() const { return tag_index_; }
|
||||||
|
Arrival arrival(const StaState *sta) const;
|
||||||
|
|
||||||
|
static bool equal(const PathVertexPtr *path1,
|
||||||
|
const PathVertexPtr *path2);
|
||||||
|
static bool equal(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2);
|
||||||
|
static int cmp(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
VertexId vertex_id_;
|
||||||
|
TagIndex tag_index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -29,34 +29,30 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
// Path representation that references a vertex arrival via a tag.
|
// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc.
|
||||||
// This does not implement the Path API which uses virtual functions
|
|
||||||
// that would make it larger.
|
|
||||||
class PathVertexRep
|
class PathVertexRep
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PathVertexRep();
|
PathVertexRep();
|
||||||
explicit PathVertexRep(const PathVertexRep *path);
|
PathVertexRep(const PathVertex *path,
|
||||||
PathVertexRep(const PathVertexRep &path);
|
const Edge *prev_edge,
|
||||||
explicit PathVertexRep(const PathVertex *path,
|
const TimingArc *prev_arc,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
explicit PathVertexRep(const PathVertex &path,
|
|
||||||
const StaState *sta);
|
|
||||||
explicit PathVertexRep(VertexId vertex_id,
|
|
||||||
TagIndex tag_index,
|
|
||||||
bool is_enum);
|
|
||||||
void init();
|
void init();
|
||||||
void init(const PathVertexRep *path);
|
void init(const PathVertexRep *path);
|
||||||
void init(const PathVertexRep &path);
|
void init(const PathVertexRep &path);
|
||||||
void init(const PathVertex *path,
|
void init(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
void init(const PathVertex &path,
|
bool isNull() const;
|
||||||
const StaState *sta);
|
const char *name(const StaState *sta) const;
|
||||||
bool isNull() const { return vertex_id_ == 0; }
|
Vertex *vertex(const StaState *sta) const;
|
||||||
Vertex *vertex(const StaState *) const;
|
VertexId vertexId(const StaState *sta) const;
|
||||||
VertexId vertexId() const { return vertex_id_; }
|
Edge *prevEdge(const StaState *sta) const;
|
||||||
|
TimingArc *prevArc(const StaState *sta) const;
|
||||||
Tag *tag(const StaState *sta) const;
|
Tag *tag(const StaState *sta) const;
|
||||||
TagIndex tagIndex() const { return tag_index_; }
|
TagIndex tagIndex() const { return prev_tag_index_; }
|
||||||
Arrival arrival(const StaState *sta) const;
|
Arrival arrival(const StaState *sta) const;
|
||||||
void prevPath(const StaState *sta,
|
void prevPath(const StaState *sta,
|
||||||
// Return values.
|
// Return values.
|
||||||
|
|
@ -67,15 +63,13 @@ public:
|
||||||
const PathVertexRep *path2);
|
const PathVertexRep *path2);
|
||||||
static bool equal(const PathVertexRep &path1,
|
static bool equal(const PathVertexRep &path1,
|
||||||
const PathVertexRep &path2);
|
const PathVertexRep &path2);
|
||||||
static int cmp(const PathVertexRep *path1,
|
|
||||||
const PathVertexRep *path2);
|
|
||||||
static int cmp(const PathVertexRep &path1,
|
static int cmp(const PathVertexRep &path1,
|
||||||
const PathVertexRep &path2);
|
const PathVertexRep &path2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VertexId vertex_id_;
|
EdgeId prev_edge_id_;
|
||||||
TagIndex tag_index_;
|
TagIndex prev_tag_index_:tag_index_bit_count;
|
||||||
bool is_enum_:1;
|
unsigned prev_arc_idx_:2;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,6 @@ public:
|
||||||
void arrivalsInvalid();
|
void arrivalsInvalid();
|
||||||
// Invalidate vertex arrival time.
|
// Invalidate vertex arrival time.
|
||||||
void arrivalInvalid(Vertex *vertex);
|
void arrivalInvalid(Vertex *vertex);
|
||||||
void arrivalInvalidDelete(Vertex *vertex);
|
|
||||||
void arrivalInvalid(const Pin *pin);
|
void arrivalInvalid(const Pin *pin);
|
||||||
// Invalidate all required times.
|
// Invalidate all required times.
|
||||||
void requiredsInvalid();
|
void requiredsInvalid();
|
||||||
|
|
@ -373,6 +372,7 @@ public:
|
||||||
bool unconstrained,
|
bool unconstrained,
|
||||||
bool thru_latches);
|
bool thru_latches);
|
||||||
VertexSeq filteredEndpoints();
|
VertexSeq filteredEndpoints();
|
||||||
|
bool alwaysSavePrevPaths() const { return always_save_prev_paths_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void init(StaState *sta);
|
void init(StaState *sta);
|
||||||
|
|
@ -613,6 +613,7 @@ protected:
|
||||||
std::mutex pending_latch_outputs_lock_;
|
std::mutex pending_latch_outputs_lock_;
|
||||||
VertexSet *endpoints_;
|
VertexSet *endpoints_;
|
||||||
VertexSet *invalid_endpoints_;
|
VertexSet *invalid_endpoints_;
|
||||||
|
bool always_save_prev_paths_;
|
||||||
// Filter exception to tag arrivals for
|
// Filter exception to tag arrivals for
|
||||||
// report_timing -from pin|inst -through.
|
// report_timing -from pin|inst -through.
|
||||||
// -to is always nullptr.
|
// -to is always nullptr.
|
||||||
|
|
@ -760,6 +761,7 @@ protected:
|
||||||
void constrainedRequiredsInvalid(Vertex *vertex,
|
void constrainedRequiredsInvalid(Vertex *vertex,
|
||||||
bool is_clk);
|
bool is_clk);
|
||||||
bool always_to_endpoints_;
|
bool always_to_endpoints_;
|
||||||
|
bool always_save_prev_paths_;
|
||||||
TagGroupBldr *tag_bldr_;
|
TagGroupBldr *tag_bldr_;
|
||||||
TagGroupBldr *tag_bldr_no_crpr_;
|
TagGroupBldr *tag_bldr_no_crpr_;
|
||||||
SearchPred *adj_pred_;
|
SearchPred *adj_pred_;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ class Corner;
|
||||||
class Path;
|
class Path;
|
||||||
class PathRep;
|
class PathRep;
|
||||||
class PathVertex;
|
class PathVertex;
|
||||||
class PathVertexRep;
|
class PathPrev;
|
||||||
|
class PathVertexPtr;
|
||||||
class PathRef;
|
class PathRef;
|
||||||
class PathEnumed;
|
class PathEnumed;
|
||||||
class PathEnd;
|
class PathEnd;
|
||||||
|
|
@ -136,7 +137,8 @@ enum class ReportPathFormat { full,
|
||||||
json
|
json
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TagIndex tag_index_max = std::numeric_limits<uint32_t>::max();
|
static const TagIndex tag_index_bit_count = 28;
|
||||||
|
static const TagIndex tag_index_max = (1 << tag_index_bit_count) - 1;
|
||||||
static const TagIndex tag_index_null = tag_index_max;
|
static const TagIndex tag_index_null = tag_index_max;
|
||||||
static const int path_ap_index_bit_count = 8;
|
static const int path_ap_index_bit_count = 8;
|
||||||
// One path analysis point per corner min/max.
|
// One path analysis point per corner min/max.
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
|
||||||
float latency,
|
float latency,
|
||||||
ClockUncertainties *uncertainties,
|
ClockUncertainties *uncertainties,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
PathVertexRep &crpr_clk_path,
|
PathVertexPtr &crpr_clk_path,
|
||||||
const StaState *sta) :
|
const StaState *sta) :
|
||||||
clk_edge_(clk_edge),
|
clk_edge_(clk_edge),
|
||||||
clk_src_(clk_src),
|
clk_src_(clk_src),
|
||||||
|
|
@ -213,7 +213,7 @@ clkInfoEqual(const ClkInfo *clk_info1,
|
||||||
&& clk_info1->clkSrc() == clk_info2->clkSrc()
|
&& clk_info1->clkSrc() == clk_info2->clkSrc()
|
||||||
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
|
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
|
||||||
&& (!crpr_on
|
&& (!crpr_on
|
||||||
|| (PathVertexRep::equal(clk_info1->crprClkPath(),
|
|| (PathVertexPtr::equal(clk_info1->crprClkPath(),
|
||||||
clk_info2->crprClkPath())))
|
clk_info2->crprClkPath())))
|
||||||
&& ((uncertainties1 == nullptr
|
&& ((uncertainties1 == nullptr
|
||||||
&& uncertainties2 == nullptr)
|
&& uncertainties2 == nullptr)
|
||||||
|
|
@ -279,9 +279,9 @@ clkInfoCmp(const ClkInfo *clk_info1,
|
||||||
|
|
||||||
bool crpr_on = sta->sdc()->crprActive();
|
bool crpr_on = sta->sdc()->crprActive();
|
||||||
if (crpr_on) {
|
if (crpr_on) {
|
||||||
const PathVertexRep &crpr_path1 = clk_info1->crprClkPath();
|
const PathVertexPtr &crpr_path1 = clk_info1->crprClkPath();
|
||||||
const PathVertexRep &crpr_path2 = clk_info2->crprClkPath();
|
const PathVertexPtr &crpr_path2 = clk_info2->crprClkPath();
|
||||||
int path_cmp = PathVertexRep::cmp(crpr_path1, crpr_path2);
|
int path_cmp = PathVertexPtr::cmp(crpr_path1, crpr_path2);
|
||||||
if (path_cmp != 0)
|
if (path_cmp != 0)
|
||||||
return path_cmp;
|
return path_cmp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
#include "Transition.hh"
|
#include "Transition.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathVertexPtr.hh"
|
||||||
|
#include "Sdc.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -45,7 +46,7 @@ public:
|
||||||
float latency,
|
float latency,
|
||||||
ClockUncertainties *uncertainties,
|
ClockUncertainties *uncertainties,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
PathVertexRep &crpr_clk_path,
|
PathVertexPtr &crpr_clk_path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
~ClkInfo();
|
~ClkInfo();
|
||||||
const char *asString(const StaState *sta) const;
|
const char *asString(const StaState *sta) const;
|
||||||
|
|
@ -64,8 +65,8 @@ public:
|
||||||
PathAPIndex pathAPIndex() const { return path_ap_index_; }
|
PathAPIndex pathAPIndex() const { return path_ap_index_; }
|
||||||
// Clock path used for crpr resolution.
|
// Clock path used for crpr resolution.
|
||||||
// Null for clocks because the path cannot point to itself.
|
// Null for clocks because the path cannot point to itself.
|
||||||
PathVertexRep &crprClkPath() { return crpr_clk_path_; }
|
PathVertexPtr &crprClkPath() { return crpr_clk_path_; }
|
||||||
const PathVertexRep &crprClkPath() const { return crpr_clk_path_; }
|
const PathVertexPtr &crprClkPath() const { return crpr_clk_path_; }
|
||||||
VertexId crprClkVertexId() const;
|
VertexId crprClkVertexId() const;
|
||||||
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
|
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
|
||||||
bool refsFilter(const StaState *sta) const;
|
bool refsFilter(const StaState *sta) const;
|
||||||
|
|
@ -80,7 +81,7 @@ private:
|
||||||
const ClockEdge *clk_edge_;
|
const ClockEdge *clk_edge_;
|
||||||
const Pin *clk_src_;
|
const Pin *clk_src_;
|
||||||
const Pin *gen_clk_src_;
|
const Pin *gen_clk_src_;
|
||||||
PathVertexRep crpr_clk_path_;
|
PathVertexPtr crpr_clk_path_;
|
||||||
ClockUncertainties *uncertainties_;
|
ClockUncertainties *uncertainties_;
|
||||||
Arrival insertion_;
|
Arrival insertion_;
|
||||||
float latency_;
|
float latency_;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "PathVertex.hh"
|
#include "PathVertex.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
#include "Path.hh"
|
#include "Path.hh"
|
||||||
#include "PathAnalysisPt.hh"
|
#include "PathAnalysisPt.hh"
|
||||||
#include "ClkInfo.hh"
|
#include "ClkInfo.hh"
|
||||||
|
|
@ -63,7 +63,7 @@ CheckCrpr::clkPathPrev(const PathVertex *path,
|
||||||
int arrival_index;
|
int arrival_index;
|
||||||
bool exists;
|
bool exists;
|
||||||
path->arrivalIndex(arrival_index, exists);
|
path->arrivalIndex(arrival_index, exists);
|
||||||
PathVertexRep *prevs = graph_->prevPaths(vertex);
|
PathPrev *prevs = graph_->prevPaths(vertex);
|
||||||
if (prevs)
|
if (prevs)
|
||||||
prev.init(prevs[arrival_index], this);
|
prev.init(prevs[arrival_index], this);
|
||||||
else
|
else
|
||||||
|
|
@ -74,7 +74,7 @@ PathVertex
|
||||||
CheckCrpr::clkPathPrev(Vertex *vertex,
|
CheckCrpr::clkPathPrev(Vertex *vertex,
|
||||||
int arrival_index)
|
int arrival_index)
|
||||||
{
|
{
|
||||||
PathVertexRep *prevs = graph_->prevPaths(vertex);
|
PathPrev *prevs = graph_->prevPaths(vertex);
|
||||||
if (prevs)
|
if (prevs)
|
||||||
return PathVertex(prevs[arrival_index], this);
|
return PathVertex(prevs[arrival_index], this);
|
||||||
else {
|
else {
|
||||||
|
|
@ -90,7 +90,7 @@ CheckCrpr::clkPathPrev(Vertex *vertex,
|
||||||
Arrival
|
Arrival
|
||||||
CheckCrpr::maxCrpr(ClkInfo *clk_info)
|
CheckCrpr::maxCrpr(ClkInfo *clk_info)
|
||||||
{
|
{
|
||||||
const PathVertexRep &crpr_clk_path = clk_info->crprClkPath();
|
const PathVertexPtr &crpr_clk_path = clk_info->crprClkPath();
|
||||||
if (!crpr_clk_path.isNull()) {
|
if (!crpr_clk_path.isNull()) {
|
||||||
PathVertex crpr_clk_vpath(crpr_clk_path, this);
|
PathVertex crpr_clk_vpath(crpr_clk_path, this);
|
||||||
if (!crpr_clk_vpath.isNull()) {
|
if (!crpr_clk_vpath.isNull()) {
|
||||||
|
|
@ -166,7 +166,7 @@ CheckCrpr::checkCrpr1(const Path *src_path,
|
||||||
const Clock *src_clk = src_clk_info->clock();
|
const Clock *src_clk = src_clk_info->clock();
|
||||||
const Clock *tgt_clk = tgt_clk_info->clock();
|
const Clock *tgt_clk = tgt_clk_info->clock();
|
||||||
PathVertex src_clk_path1;
|
PathVertex src_clk_path1;
|
||||||
PathVertexRep &src_crpr_clk_path = src_clk_info->crprClkPath();
|
const PathVertexPtr &src_crpr_clk_path = src_clk_info->crprClkPath();
|
||||||
const PathVertex *src_clk_path = nullptr;
|
const PathVertex *src_clk_path = nullptr;
|
||||||
if (src_tag->isClock()) {
|
if (src_tag->isClock()) {
|
||||||
src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this);
|
src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this);
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
#include "PathAnalysisPt.hh"
|
#include "PathAnalysisPt.hh"
|
||||||
#include "Levelize.hh"
|
#include "Levelize.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathVertexPtr.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -856,7 +856,7 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex,
|
||||||
{
|
{
|
||||||
Arrival *arrivals = graph_->arrivals(vertex);
|
Arrival *arrivals = graph_->arrivals(vertex);
|
||||||
if (arrivals) {
|
if (arrivals) {
|
||||||
PathVertexRep *prev_paths = graph_->prevPaths(vertex);
|
PathPrev *prev_paths = graph_->prevPaths(vertex);
|
||||||
TagGroup *tag_group = search_->tagGroup(vertex);
|
TagGroup *tag_group = search_->tagGroup(vertex);
|
||||||
if (tag_group) {
|
if (tag_group) {
|
||||||
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
||||||
|
|
@ -866,7 +866,7 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex,
|
||||||
arrival_iter.next(tag, arrival_index);
|
arrival_iter.next(tag, arrival_index);
|
||||||
if (tag->isGenClkSrcPath()) {
|
if (tag->isGenClkSrcPath()) {
|
||||||
Arrival arrival = arrivals[arrival_index];
|
Arrival arrival = arrivals[arrival_index];
|
||||||
PathVertexRep *prev_path = prev_paths
|
PathPrev *prev_path = prev_paths
|
||||||
? &prev_paths[arrival_index]
|
? &prev_paths[arrival_index]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
tag_bldr->setArrival(tag, arrival, prev_path);
|
tag_bldr->setArrival(tag, arrival, prev_path);
|
||||||
|
|
@ -903,7 +903,7 @@ Genclks::recordSrcPaths(Clock *gclk)
|
||||||
bool has_edges = gclk->edges() != nullptr;
|
bool has_edges = gclk->edges() != nullptr;
|
||||||
|
|
||||||
for (const Pin *gclk_pin : gclk->leafPins()) {
|
for (const Pin *gclk_pin : gclk->leafPins()) {
|
||||||
PathVertexRep *src_paths = new PathVertexRep[path_count];
|
PathVertexPtr *src_paths = new PathVertexPtr[path_count];
|
||||||
genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths);
|
genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths);
|
||||||
|
|
||||||
Vertex *gclk_vertex = srcPathVertex(gclk_pin);
|
Vertex *gclk_vertex = srcPathVertex(gclk_pin);
|
||||||
|
|
@ -920,7 +920,7 @@ Genclks::recordSrcPaths(Clock *gclk)
|
||||||
bool inverting_path = (rf != src_clk_rf);
|
bool inverting_path = (rf != src_clk_rf);
|
||||||
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
||||||
int path_index = srcPathIndex(rf, path_ap);
|
int path_index = srcPathIndex(rf, path_ap);
|
||||||
PathVertexRep &src_path = src_paths[path_index];
|
PathVertexPtr &src_path = src_paths[path_index];
|
||||||
if ((!divide_by_1
|
if ((!divide_by_1
|
||||||
|| (inverting_path == invert))
|
|| (inverting_path == invert))
|
||||||
&& (!has_edges
|
&& (!has_edges
|
||||||
|
|
@ -999,7 +999,7 @@ Genclks::srcPath(const Clock *gclk,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const PathAnalysisPt *path_ap) const
|
const PathAnalysisPt *path_ap) const
|
||||||
{
|
{
|
||||||
PathVertexRep *src_paths =
|
PathVertexPtr *src_paths =
|
||||||
genclk_src_paths_.findKey(ClockPinPair(gclk, src_pin));
|
genclk_src_paths_.findKey(ClockPinPair(gclk, src_pin));
|
||||||
if (src_paths) {
|
if (src_paths) {
|
||||||
int path_index = srcPathIndex(rf, path_ap);
|
int path_index = srcPathIndex(rf, path_ap);
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Map<Clock*, GenclkInfo*> GenclkInfoMap;
|
typedef Map<Clock*, GenclkInfo*> GenclkInfoMap;
|
||||||
typedef Map<ClockPinPair, PathVertexRep*, ClockPinPairLess> GenclkSrcPathMap;
|
typedef Map<ClockPinPair, PathVertexPtr*, ClockPinPairLess> GenclkSrcPathMap;
|
||||||
|
|
||||||
class Genclks : public StaState
|
class Genclks : public StaState
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -354,13 +354,15 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
|
||||||
PathEnumed *after_div_copy;
|
PathEnumed *after_div_copy;
|
||||||
// Make the diverted path end to check slack with from_path crpr.
|
// Make the diverted path end to check slack with from_path crpr.
|
||||||
makeDivertedPathEnd(from_path, arc, div_end, after_div_copy);
|
makeDivertedPathEnd(from_path, arc, div_end, after_div_copy);
|
||||||
// Only enumerate paths with greater slack.
|
if (div_end) {
|
||||||
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
|
// Only enumerate paths with greater slack.
|
||||||
reportDiversion(arc, from_path);
|
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
|
||||||
path_enum_->makeDiversion(div_end, after_div_copy);
|
reportDiversion(arc, from_path);
|
||||||
|
path_enum_->makeDiversion(div_end, after_div_copy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete div_end;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
delete div_end;
|
|
||||||
}
|
}
|
||||||
// Only enumerate slower/faster paths.
|
// Only enumerate slower/faster paths.
|
||||||
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) {
|
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) {
|
||||||
|
|
@ -384,8 +386,12 @@ PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
|
||||||
PathEnumed *div_path;
|
PathEnumed *div_path;
|
||||||
path_enum_->makeDivertedPath(path_end_->path(), &before_div_, after_div,
|
path_enum_->makeDivertedPath(path_end_->path(), &before_div_, after_div,
|
||||||
div_arc, div_path, after_div_copy);
|
div_arc, div_path, after_div_copy);
|
||||||
div_end = path_end_->copy();
|
if (after_div_copy) {
|
||||||
div_end->setPath(div_path);
|
div_end = path_end_->copy();
|
||||||
|
div_end->setPath(div_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
div_end = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -539,17 +545,15 @@ PathEnum::makeDivertedPath(Path *path,
|
||||||
PathEnumed *&div_path,
|
PathEnumed *&div_path,
|
||||||
PathEnumed *&after_div_copy)
|
PathEnumed *&after_div_copy)
|
||||||
{
|
{
|
||||||
|
div_path = nullptr;
|
||||||
|
after_div_copy = nullptr;
|
||||||
// Copy the diversion path.
|
// Copy the diversion path.
|
||||||
bool found_div = false;
|
bool found_div = false;
|
||||||
PathEnumedSeq copies;
|
PathEnumedSeq copies;
|
||||||
PathRef p(path);
|
PathRef p(path);
|
||||||
bool first = true;
|
bool first = true;
|
||||||
PathEnumed *prev_copy = nullptr;
|
PathEnumed *prev_copy = nullptr;
|
||||||
VertexSet visited(graph_);
|
while (!p.isNull()) {
|
||||||
while (!p.isNull()
|
|
||||||
// Break latch loops.
|
|
||||||
&& !visited.hasKey(p.vertex(this))) {
|
|
||||||
visited.insert(p.vertex(this));
|
|
||||||
PathRef prev;
|
PathRef prev;
|
||||||
TimingArc *prev_arc;
|
TimingArc *prev_arc;
|
||||||
p.prevPath(this, prev, prev_arc);
|
p.prevPath(this, prev, prev_arc);
|
||||||
|
|
@ -562,10 +566,12 @@ PathEnum::makeDivertedPath(Path *path,
|
||||||
prev_copy->setPrevPath(copy);
|
prev_copy->setPrevPath(copy);
|
||||||
copies.push_back(copy);
|
copies.push_back(copy);
|
||||||
|
|
||||||
if (first)
|
|
||||||
div_path = copy;
|
|
||||||
if (Path::equal(&p, after_div, this))
|
if (Path::equal(&p, after_div, this))
|
||||||
after_div_copy = copy;
|
after_div_copy = copy;
|
||||||
|
if (first)
|
||||||
|
div_path = copy;
|
||||||
|
else if (network_->isLatchData(p.pin(this)))
|
||||||
|
break;
|
||||||
if (Path::equal(&p, before_div, this)) {
|
if (Path::equal(&p, before_div, this)) {
|
||||||
copy->setPrevArc(div_arc);
|
copy->setPrevArc(div_arc);
|
||||||
// Update the delays forward from before_div to the end of the path.
|
// Update the delays forward from before_div to the end of the path.
|
||||||
|
|
@ -598,7 +604,7 @@ PathEnum::updatePathHeadDelays(PathEnumedSeq &paths,
|
||||||
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_),
|
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_),
|
||||||
arc, edge, false, path_ap);
|
arc, edge, false, path_ap);
|
||||||
Arrival arrival = prev_arrival + arc_delay;
|
Arrival arrival = prev_arrival + arc_delay;
|
||||||
debugPrint(debug_, "path_enum", 3, "update arrival %s %s %s -> %s",
|
debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s",
|
||||||
path->vertex(this)->name(network_),
|
path->vertex(this)->name(network_),
|
||||||
path->tag(this)->asString(this),
|
path->tag(this)->asString(this),
|
||||||
delayAsString(path->arrival(this), this),
|
delayAsString(path->arrival(this), this),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#include "PathPrev.hh"
|
||||||
|
|
||||||
|
#include "Graph.hh"
|
||||||
|
#include "TimingArc.hh"
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
#include "Tag.hh"
|
||||||
|
#include "TagGroup.hh"
|
||||||
|
#include "Search.hh"
|
||||||
|
#include "PathAnalysisPt.hh"
|
||||||
|
#include "PathVertex.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
PathPrev::PathPrev()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init()
|
||||||
|
{
|
||||||
|
prev_edge_id_ = edge_id_null;
|
||||||
|
prev_arc_idx_ = 0;
|
||||||
|
prev_tag_index_ = tag_index_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init(const PathPrev *path)
|
||||||
|
{
|
||||||
|
if (path) {
|
||||||
|
prev_edge_id_ = path->prev_edge_id_;
|
||||||
|
prev_arc_idx_ = path->prev_arc_idx_;
|
||||||
|
prev_tag_index_ = path->prev_tag_index_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init(const PathPrev &path)
|
||||||
|
{
|
||||||
|
prev_edge_id_ = path.prev_edge_id_;
|
||||||
|
prev_arc_idx_ = path.prev_arc_idx_;
|
||||||
|
prev_tag_index_ = path.prev_tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (path == nullptr || path->isNull())
|
||||||
|
init();
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
prev_edge_id_ = graph->id(prev_edge);
|
||||||
|
prev_arc_idx_ = prev_arc->index();
|
||||||
|
prev_tag_index_ = path->tag(sta)->index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
PathPrev::name(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Network *network = sta->network();
|
||||||
|
const Search *search = sta->search();
|
||||||
|
Vertex *vertex = this->vertex(sta);
|
||||||
|
if (vertex) {
|
||||||
|
const char *vertex_name = vertex->name(network);
|
||||||
|
const Tag *tag = this->tag(search);
|
||||||
|
const RiseFall *rf = tag->transition();
|
||||||
|
const char *rf_str = rf->asString();
|
||||||
|
const PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta);
|
||||||
|
int ap_index = path_ap->index();
|
||||||
|
const char *min_max = path_ap->pathMinMax()->asString();
|
||||||
|
TagIndex tag_index = tag->index();
|
||||||
|
return stringPrintTmp("%s %s %s/%d %d",
|
||||||
|
vertex_name, rf_str, min_max,
|
||||||
|
ap_index, tag_index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathPrev::isNull() const
|
||||||
|
{
|
||||||
|
return prev_edge_id_ == edge_id_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexId
|
||||||
|
PathPrev::vertexId(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return vertex_id_null;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
const Edge *edge = graph->edge(prev_edge_id_);
|
||||||
|
return edge->from();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex *
|
||||||
|
PathPrev::vertex(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
const Edge *edge = graph->edge(prev_edge_id_);
|
||||||
|
return edge->from(graph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Edge *
|
||||||
|
PathPrev::prevEdge(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
return graph->edge(prev_edge_id_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TimingArc *
|
||||||
|
PathPrev::prevArc(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
const Edge *edge = graph->edge(prev_edge_id_);
|
||||||
|
TimingArcSet *arc_set = edge->timingArcSet();
|
||||||
|
return arc_set->findTimingArc(prev_arc_idx_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag *
|
||||||
|
PathPrev::tag(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Search *search = sta->search();
|
||||||
|
return search->tag(prev_tag_index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrival
|
||||||
|
PathPrev::arrival(const StaState *sta) const
|
||||||
|
{
|
||||||
|
Graph *graph = sta->graph();
|
||||||
|
const Search *search = sta->search();
|
||||||
|
Tag *tag = search->tag(prev_tag_index_);
|
||||||
|
Vertex *vertex = this->vertex(sta);
|
||||||
|
TagGroup *tag_group = search->tagGroup(vertex);
|
||||||
|
if (tag_group) {
|
||||||
|
int arrival_index;
|
||||||
|
bool arrival_exists;
|
||||||
|
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
||||||
|
if (!arrival_exists)
|
||||||
|
sta->report()->critical(1420, "tag group missing tag");
|
||||||
|
Arrival *arrivals = graph->arrivals(vertex);
|
||||||
|
if (arrivals)
|
||||||
|
return arrivals[arrival_index];
|
||||||
|
else
|
||||||
|
sta->report()->critical(1421, "missing arrivals");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sta->report()->error(1422, "missing arrivals.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::prevPath(const StaState *sta,
|
||||||
|
// Return values.
|
||||||
|
PathRef &prev_path,
|
||||||
|
TimingArc *&prev_arc) const
|
||||||
|
{
|
||||||
|
PathVertex path_vertex(this, sta);
|
||||||
|
path_vertex.prevPath(sta, prev_path, prev_arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathPrev::equal(const PathPrev *path1,
|
||||||
|
const PathPrev *path2)
|
||||||
|
{
|
||||||
|
return path1->prev_edge_id_ == path2->prev_edge_id_
|
||||||
|
&& path1->prev_tag_index_ == path2->prev_tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathPrev::equal(const PathPrev &path1,
|
||||||
|
const PathPrev &path2)
|
||||||
|
{
|
||||||
|
return path1.prev_edge_id_ == path2.prev_edge_id_
|
||||||
|
&& path1.prev_tag_index_ == path2.prev_tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PathPrev::cmp(const PathPrev &path1,
|
||||||
|
const PathPrev &path2)
|
||||||
|
{
|
||||||
|
EdgeId edge_id1 = path1.prev_edge_id_;
|
||||||
|
EdgeId edge_id2 = path2.prev_edge_id_;
|
||||||
|
if (edge_id1 == edge_id2) {
|
||||||
|
TagIndex tag_index1 = path1.prev_tag_index_;
|
||||||
|
TagIndex tag_index2 = path2.prev_tag_index_;
|
||||||
|
if (tag_index1 == tag_index2)
|
||||||
|
return 0;
|
||||||
|
else if (tag_index1 < tag_index2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (edge_id1 < edge_id2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -96,6 +96,26 @@ PathRef::init(const PathVertex &path)
|
||||||
path_vertex_ = path;
|
path_vertex_ = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathRef::init(const PathPrev &path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
int arrival_index = 0;
|
||||||
|
TagIndex tag_index = path.tagIndex();
|
||||||
|
Tag *tag = nullptr;
|
||||||
|
if (tag_index != tag_index_null) {
|
||||||
|
const Search *search = sta->search();
|
||||||
|
tag = search->tag(tag_index);
|
||||||
|
Vertex *vertex = path.vertex(sta);
|
||||||
|
TagGroup *tag_group = search->tagGroup(vertex);
|
||||||
|
if (tag_group) {
|
||||||
|
bool arrival_exists;
|
||||||
|
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path_vertex_.init(path.vertex(sta), tag, arrival_index);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathRef::init(Vertex *vertex,
|
PathRef::init(Vertex *vertex,
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@
|
||||||
#include "TagGroup.hh"
|
#include "TagGroup.hh"
|
||||||
#include "PathAnalysisPt.hh"
|
#include "PathAnalysisPt.hh"
|
||||||
#include "PathRef.hh"
|
#include "PathRef.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
|
#include "PathVertexPtr.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -83,7 +84,7 @@ PathVertex::PathVertex(Vertex *vertex,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertex::PathVertex(const PathVertexRep *path,
|
PathVertex::PathVertex(const PathPrev *path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (path)
|
if (path)
|
||||||
|
|
@ -92,7 +93,16 @@ PathVertex::PathVertex(const PathVertexRep *path,
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertex::PathVertex(const PathVertexRep &path,
|
PathVertex::PathVertex(const PathPrev &path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (path.isNull())
|
||||||
|
init();
|
||||||
|
else
|
||||||
|
init(path.vertex(sta), path.tag(sta), sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
PathVertex::PathVertex(const PathVertexPtr &path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (path.isNull())
|
if (path.isNull())
|
||||||
|
|
@ -140,7 +150,7 @@ PathVertex::init(Vertex *vertex,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathVertex::init(const PathVertexRep *path,
|
PathVertex::init(const PathPrev *path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (path)
|
if (path)
|
||||||
|
|
@ -150,7 +160,17 @@ PathVertex::init(const PathVertexRep *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathVertex::init(const PathVertexRep &path,
|
PathVertex::init(const PathPrev &path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (!path.isNull())
|
||||||
|
init(path.vertex(sta), path.tag(sta), sta);
|
||||||
|
else
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertex::init(const PathVertexPtr &path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (!path.isNull())
|
if (!path.isNull())
|
||||||
|
|
@ -481,9 +501,19 @@ PathVertex::prevPath(const StaState *sta,
|
||||||
PathRef &prev_path,
|
PathRef &prev_path,
|
||||||
TimingArc *&prev_arc) const
|
TimingArc *&prev_arc) const
|
||||||
{
|
{
|
||||||
PathVertex prev;
|
const Graph *graph = sta->graph();
|
||||||
prevPath(sta, prev, prev_arc);
|
Vertex *vertex = this->vertex(graph);
|
||||||
prev.setRef(prev_path);
|
PathPrev *prev_paths = vertex->prevPaths();
|
||||||
|
if (prev_paths) {
|
||||||
|
PathPrev &prev = prev_paths[arrival_index_];
|
||||||
|
prev_path.init(prev, sta);
|
||||||
|
prev_arc = prev.isNull() ? nullptr : prev.prevArc(sta);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PathVertex prev;
|
||||||
|
prevPath(sta, prev, prev_arc);
|
||||||
|
prev.setRef(prev_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#include "PathVertexPtr.hh"
|
||||||
|
|
||||||
|
#include "Graph.hh"
|
||||||
|
#include "TimingArc.hh"
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
#include "Tag.hh"
|
||||||
|
#include "TagGroup.hh"
|
||||||
|
#include "Search.hh"
|
||||||
|
#include "PathAnalysisPt.hh"
|
||||||
|
#include "PathVertex.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
PathVertexPtr::PathVertexPtr() :
|
||||||
|
vertex_id_(vertex_id_null),
|
||||||
|
tag_index_(tag_index_null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PathVertexPtr::PathVertexPtr(const PathVertex *path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
init(path, sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init()
|
||||||
|
{
|
||||||
|
vertex_id_ = vertex_id_null;
|
||||||
|
tag_index_ = tag_index_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init(const PathVertexPtr *path)
|
||||||
|
{
|
||||||
|
if (path) {
|
||||||
|
vertex_id_ = path->vertex_id_;
|
||||||
|
tag_index_ = path->tag_index_;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertex_id_ = vertex_id_null;
|
||||||
|
tag_index_ = tag_index_null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init(const PathVertexPtr &path)
|
||||||
|
{
|
||||||
|
vertex_id_ = path.vertex_id_;
|
||||||
|
tag_index_ = path.tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init(const PathVertex *path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (path == nullptr || path->isNull())
|
||||||
|
init();
|
||||||
|
else {
|
||||||
|
vertex_id_ = path->vertexId(sta);
|
||||||
|
tag_index_ = path->tagIndex(sta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
PathVertexPtr::name(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Network *network = sta->network();
|
||||||
|
const Search *search = sta->search();
|
||||||
|
Vertex *vertex = this->vertex(sta);
|
||||||
|
if (vertex) {
|
||||||
|
const char *vertex_name = vertex->name(network);
|
||||||
|
const Tag *tag = this->tag(search);
|
||||||
|
const RiseFall *rf = tag->transition();
|
||||||
|
const char *rf_str = rf->asString();
|
||||||
|
const PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta);
|
||||||
|
int ap_index = path_ap->index();
|
||||||
|
const char *min_max = path_ap->pathMinMax()->asString();
|
||||||
|
TagIndex tag_index = tag->index();
|
||||||
|
return stringPrintTmp("%s %s %s/%d %d",
|
||||||
|
vertex_name, rf_str, min_max,
|
||||||
|
ap_index, tag_index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathVertexPtr::isNull() const
|
||||||
|
{
|
||||||
|
return vertex_id_ == vertex_id_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex *
|
||||||
|
PathVertexPtr::vertex(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (vertex_id_ == vertex_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
return graph->vertex(vertex_id_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag *
|
||||||
|
PathVertexPtr::tag(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Search *search = sta->search();
|
||||||
|
return search->tag(tag_index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrival
|
||||||
|
PathVertexPtr::arrival(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Vertex *vertex = this->vertex(sta);
|
||||||
|
Arrival *arrivals = sta->graph()->arrivals(vertex);
|
||||||
|
if (arrivals) {
|
||||||
|
const Search *search = sta->search();
|
||||||
|
TagGroup *tag_group = search->tagGroup(vertex);
|
||||||
|
Tag *tag = this->tag(sta);
|
||||||
|
int arrival_index;
|
||||||
|
bool arrival_exists;
|
||||||
|
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
||||||
|
if (arrival_exists)
|
||||||
|
return arrivals[arrival_index];
|
||||||
|
else {
|
||||||
|
sta->report()->error(1403, "missing arrival.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sta->report()->error(1404, "missing arrivals.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathVertexPtr::equal(const PathVertexPtr *path1,
|
||||||
|
const PathVertexPtr *path2)
|
||||||
|
{
|
||||||
|
return path1->vertex_id_ == path2->vertex_id_
|
||||||
|
&& path1->tag_index_ == path2->tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathVertexPtr::equal(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2)
|
||||||
|
{
|
||||||
|
return path1.vertex_id_ == path2.vertex_id_
|
||||||
|
&& path1.tag_index_ == path2.tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PathVertexPtr::cmp(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2)
|
||||||
|
{
|
||||||
|
VertexId vertex_id1 = path1.vertex_id_;
|
||||||
|
VertexId vertex_id2 = path2.vertex_id_;
|
||||||
|
if (vertex_id1 == vertex_id2) {
|
||||||
|
TagIndex tag_index1 = path1.tagIndex();
|
||||||
|
TagIndex tag_index2 = path2.tagIndex();
|
||||||
|
if (tag_index1 == tag_index2)
|
||||||
|
return 0;
|
||||||
|
else if (tag_index1 < tag_index2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (vertex_id1 < vertex_id2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -1,246 +0,0 @@
|
||||||
// OpenSTA, Static Timing Analyzer
|
|
||||||
// Copyright (c) 2025, Parallax Software, Inc.
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
//
|
|
||||||
// The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software.
|
|
||||||
//
|
|
||||||
// Altered source versions must be plainly marked as such, and must not be
|
|
||||||
// misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
#include "PathVertexRep.hh"
|
|
||||||
|
|
||||||
#include "Graph.hh"
|
|
||||||
#include "SearchClass.hh"
|
|
||||||
#include "Tag.hh"
|
|
||||||
#include "TagGroup.hh"
|
|
||||||
#include "Search.hh"
|
|
||||||
#include "PathVertex.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep()
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertexRep *path)
|
|
||||||
{
|
|
||||||
init(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertexRep &path)
|
|
||||||
{
|
|
||||||
init(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertex *path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
init(path, sta);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertex &path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
init(path, sta);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(VertexId vertex_id,
|
|
||||||
TagIndex tag_index,
|
|
||||||
bool is_enum) :
|
|
||||||
vertex_id_(vertex_id),
|
|
||||||
tag_index_(tag_index),
|
|
||||||
is_enum_(is_enum)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init()
|
|
||||||
{
|
|
||||||
vertex_id_ = 0;
|
|
||||||
tag_index_ = tag_index_null;
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertexRep *path)
|
|
||||||
{
|
|
||||||
if (path) {
|
|
||||||
vertex_id_ = path->vertex_id_;
|
|
||||||
tag_index_ = path->tag_index_;
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertexRep &path)
|
|
||||||
{
|
|
||||||
vertex_id_ = path.vertex_id_;
|
|
||||||
tag_index_ = path.tag_index_;
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertex *path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
if (path == nullptr || path->isNull())
|
|
||||||
init();
|
|
||||||
else {
|
|
||||||
vertex_id_ = sta->graph()->id(path->vertex(sta));
|
|
||||||
tag_index_ = path->tag(sta)->index();
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertex &path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
if (path.isNull())
|
|
||||||
init();
|
|
||||||
else {
|
|
||||||
vertex_id_ = sta->graph()->id(path.vertex(sta));
|
|
||||||
tag_index_ = path.tag(sta)->index();
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vertex *
|
|
||||||
PathVertexRep::vertex(const StaState *sta) const
|
|
||||||
{
|
|
||||||
const Graph *graph = sta->graph();
|
|
||||||
return graph->vertex(vertex_id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Tag *
|
|
||||||
PathVertexRep::tag(const StaState *sta) const
|
|
||||||
{
|
|
||||||
const Search *search = sta->search();
|
|
||||||
return search->tag(tag_index_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Arrival
|
|
||||||
PathVertexRep::arrival(const StaState *sta) const
|
|
||||||
{
|
|
||||||
Graph *graph = sta->graph();
|
|
||||||
const Search *search = sta->search();
|
|
||||||
Tag *tag = search->tag(tag_index_);
|
|
||||||
Vertex *vertex = graph->vertex(vertex_id_);
|
|
||||||
TagGroup *tag_group = search->tagGroup(vertex);
|
|
||||||
if (tag_group) {
|
|
||||||
int arrival_index;
|
|
||||||
bool arrival_exists;
|
|
||||||
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
|
||||||
if (!arrival_exists)
|
|
||||||
sta->report()->critical(1420, "tag group missing tag");
|
|
||||||
Arrival *arrivals = graph->arrivals(vertex);
|
|
||||||
if (arrivals)
|
|
||||||
return arrivals[arrival_index];
|
|
||||||
else
|
|
||||||
sta->report()->critical(1421, "missing arrivals");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sta->report()->error(1422, "missing arrivals.");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::prevPath(const StaState *sta,
|
|
||||||
// Return values.
|
|
||||||
PathRef &prev_path,
|
|
||||||
TimingArc *&prev_arc) const
|
|
||||||
{
|
|
||||||
PathVertex path_vertex(this, sta);
|
|
||||||
path_vertex.prevPath(sta, prev_path, prev_arc);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
bool
|
|
||||||
PathVertexRep::equal(const PathVertexRep *path1,
|
|
||||||
const PathVertexRep *path2)
|
|
||||||
{
|
|
||||||
return path1->vertex_id_ == path2->vertex_id_
|
|
||||||
&& path1->tag_index_ == path2->tag_index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PathVertexRep::equal(const PathVertexRep &path1,
|
|
||||||
const PathVertexRep &path2)
|
|
||||||
{
|
|
||||||
return path1.vertex_id_ == path2.vertex_id_
|
|
||||||
&& path1.tag_index_ == path2.tag_index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PathVertexRep::cmp(const PathVertexRep *path1,
|
|
||||||
const PathVertexRep *path2)
|
|
||||||
{
|
|
||||||
if (path1 && path2) {
|
|
||||||
VertexId vertex_id1 = path1->vertexId();
|
|
||||||
VertexId vertex_id2 = path2->vertexId();
|
|
||||||
if (vertex_id1 == vertex_id2) {
|
|
||||||
TagIndex tag_index1 = path1->tagIndex();
|
|
||||||
TagIndex tag_index2 = path2->tagIndex();
|
|
||||||
if (tag_index1 == tag_index2)
|
|
||||||
return 0;
|
|
||||||
else if (tag_index1 < tag_index2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (vertex_id1 < vertex_id2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (path1 == nullptr
|
|
||||||
&& path2 == nullptr)
|
|
||||||
return 0;
|
|
||||||
else if (path1 == nullptr)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PathVertexRep::cmp(const PathVertexRep &path1,
|
|
||||||
const PathVertexRep &path2)
|
|
||||||
{
|
|
||||||
VertexId vertex_id1 = path1.vertexId();
|
|
||||||
VertexId vertex_id2 = path2.vertexId();
|
|
||||||
if (vertex_id1 == vertex_id2) {
|
|
||||||
TagIndex tag_index1 = path1.tagIndex();
|
|
||||||
TagIndex tag_index2 = path2.tagIndex();
|
|
||||||
if (tag_index1 == tag_index2)
|
|
||||||
return 0;
|
|
||||||
else if (tag_index1 < tag_index2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (vertex_id1 < vertex_id2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
#include "Sim.hh"
|
#include "Sim.hh"
|
||||||
#include "PathVertex.hh"
|
#include "PathVertex.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
#include "PathRef.hh"
|
#include "PathRef.hh"
|
||||||
#include "ClkInfo.hh"
|
#include "ClkInfo.hh"
|
||||||
#include "Tag.hh"
|
#include "Tag.hh"
|
||||||
|
|
@ -255,6 +255,7 @@ Search::init(StaState *sta)
|
||||||
path_groups_ = nullptr;
|
path_groups_ = nullptr;
|
||||||
endpoints_ = nullptr;
|
endpoints_ = nullptr;
|
||||||
invalid_endpoints_ = nullptr;
|
invalid_endpoints_ = nullptr;
|
||||||
|
always_save_prev_paths_ = true;
|
||||||
filter_ = nullptr;
|
filter_ = nullptr;
|
||||||
filter_from_ = nullptr;
|
filter_from_ = nullptr;
|
||||||
filter_to_ = nullptr;
|
filter_to_ = nullptr;
|
||||||
|
|
@ -786,13 +787,6 @@ Search::arrivalInvalid(Vertex *vertex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Search::arrivalInvalidDelete(Vertex *vertex)
|
|
||||||
{
|
|
||||||
arrivalInvalid(vertex);
|
|
||||||
deletePaths(vertex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Search::levelChangedBefore(Vertex *vertex)
|
Search::levelChangedBefore(Vertex *vertex)
|
||||||
{
|
{
|
||||||
|
|
@ -1072,7 +1066,8 @@ Search::findArrivalsSeed()
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
|
ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
|
||||||
PathVisitor(nullptr, sta)
|
PathVisitor(nullptr, sta),
|
||||||
|
always_save_prev_paths_(true)
|
||||||
{
|
{
|
||||||
init0();
|
init0();
|
||||||
init(true);
|
init(true);
|
||||||
|
|
@ -1109,6 +1104,8 @@ ArrivalVisitor::init(bool always_to_endpoints,
|
||||||
always_to_endpoints_ = always_to_endpoints;
|
always_to_endpoints_ = always_to_endpoints;
|
||||||
pred_ = pred;
|
pred_ = pred;
|
||||||
crpr_active_ = sdc_->crprActive();
|
crpr_active_ = sdc_->crprActive();
|
||||||
|
if (search_)
|
||||||
|
always_save_prev_paths_ = search_->alwaysSavePrevPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1241,6 +1238,7 @@ Search::arrivalsChanged(Vertex *vertex,
|
||||||
TagGroupBldr *tag_bldr)
|
TagGroupBldr *tag_bldr)
|
||||||
{
|
{
|
||||||
Arrival *arrivals1 = graph_->arrivals(vertex);
|
Arrival *arrivals1 = graph_->arrivals(vertex);
|
||||||
|
PathPrev *prev_paths1 = graph_->prevPaths(vertex);
|
||||||
if (arrivals1) {
|
if (arrivals1) {
|
||||||
TagGroup *tag_group = tagGroup(vertex);
|
TagGroup *tag_group = tagGroup(vertex);
|
||||||
if (tag_group == nullptr
|
if (tag_group == nullptr
|
||||||
|
|
@ -1257,7 +1255,10 @@ Search::arrivalsChanged(Vertex *vertex,
|
||||||
int arrival_index2;
|
int arrival_index2;
|
||||||
tag_bldr->tagMatchArrival(tag1, tag2, arrival2, arrival_index2);
|
tag_bldr->tagMatchArrival(tag1, tag2, arrival2, arrival_index2);
|
||||||
if (tag2 != tag1
|
if (tag2 != tag1
|
||||||
|| !delayEqual(arrival1, arrival2))
|
|| !delayEqual(arrival1, arrival2)
|
||||||
|
|| (prev_paths1
|
||||||
|
&& !PathPrev::equal(prev_paths1[arrival_index1],
|
||||||
|
tag_bldr->prevPath(arrival_index2))))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1273,10 +1274,10 @@ ArrivalVisitor::visitFromToPath(const Pin *,
|
||||||
Tag *from_tag,
|
Tag *from_tag,
|
||||||
PathVertex *from_path,
|
PathVertex *from_path,
|
||||||
const Arrival &from_arrival,
|
const Arrival &from_arrival,
|
||||||
Edge *,
|
Edge *edge,
|
||||||
TimingArc *,
|
TimingArc *arc,
|
||||||
ArcDelay arc_delay,
|
ArcDelay arc_delay,
|
||||||
Vertex *,
|
Vertex * /* to_vertex */,
|
||||||
const RiseFall *to_rf,
|
const RiseFall *to_rf,
|
||||||
Tag *to_tag,
|
Tag *to_tag,
|
||||||
Arrival &to_arrival,
|
Arrival &to_arrival,
|
||||||
|
|
@ -1307,9 +1308,13 @@ ArrivalVisitor::visitFromToPath(const Pin *,
|
||||||
delayAsString(to_arrival, this),
|
delayAsString(to_arrival, this),
|
||||||
min_max == MinMax::max() ? ">" : "<",
|
min_max == MinMax::max() ? ">" : "<",
|
||||||
tag_match ? delayAsString(arrival, this) : "MIA");
|
tag_match ? delayAsString(arrival, this) : "MIA");
|
||||||
PathVertexRep prev_path;
|
PathPrev prev_path;
|
||||||
if (to_tag->isClock() || to_tag->isGenClkSrcPath())
|
bool always_save_prev_paths = true;
|
||||||
prev_path.init(from_path, this);
|
bool save_prev = always_save_prev_paths
|
||||||
|
|| to_tag->isClock()
|
||||||
|
|| to_tag->isGenClkSrcPath();
|
||||||
|
if (save_prev)
|
||||||
|
prev_path.init(from_path, edge, arc, this);
|
||||||
tag_bldr_->setMatchArrival(to_tag, tag_match,
|
tag_bldr_->setMatchArrival(to_tag, tag_match,
|
||||||
to_arrival, arrival_index,
|
to_arrival, arrival_index,
|
||||||
&prev_path);
|
&prev_path);
|
||||||
|
|
@ -1333,13 +1338,13 @@ ArrivalVisitor::visitFromToPath(const Pin *,
|
||||||
void
|
void
|
||||||
ArrivalVisitor::pruneCrprArrivals()
|
ArrivalVisitor::pruneCrprArrivals()
|
||||||
{
|
{
|
||||||
ArrivalMap::Iterator arrival_iter(tag_bldr_->arrivalMap());
|
|
||||||
CheckCrpr *crpr = search_->checkCrpr();
|
CheckCrpr *crpr = search_->checkCrpr();
|
||||||
while (arrival_iter.hasNext()) {
|
ArrivalMap *arrival_map = tag_bldr_->arrivalMap();
|
||||||
Tag *tag;
|
for (auto arrival_itr = arrival_map->cbegin(); arrival_itr != arrival_map->cend(); ) {
|
||||||
int arrival_index;
|
Tag *tag = arrival_itr->first;
|
||||||
arrival_iter.next(tag, arrival_index);
|
int arrival_index = arrival_itr->second;
|
||||||
ClkInfo *clk_info = tag->clkInfo();
|
ClkInfo *clk_info = tag->clkInfo();
|
||||||
|
bool deleted_tag = false;
|
||||||
if (!tag->isClock()
|
if (!tag->isClock()
|
||||||
&& clk_info->hasCrprClkPin()) {
|
&& clk_info->hasCrprClkPin()) {
|
||||||
PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
|
PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
|
||||||
|
|
@ -1364,10 +1369,13 @@ ArrivalVisitor::pruneCrprArrivals()
|
||||||
if (delayGreater(max_arrival_max_crpr, arrival, min_max, this)) {
|
if (delayGreater(max_arrival_max_crpr, arrival, min_max, this)) {
|
||||||
debugPrint(debug_, "search", 3, " pruned %s",
|
debugPrint(debug_, "search", 3, " pruned %s",
|
||||||
tag->asString(this));
|
tag->asString(this));
|
||||||
tag_bldr_->deleteArrival(tag);
|
arrival_itr = arrival_map->erase(arrival_itr);
|
||||||
|
deleted_tag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!deleted_tag)
|
||||||
|
arrival_itr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2710,7 +2718,10 @@ Search::setVertexArrivals(Vertex *vertex,
|
||||||
else {
|
else {
|
||||||
TagGroup *prev_tag_group = tagGroup(vertex);
|
TagGroup *prev_tag_group = tagGroup(vertex);
|
||||||
Arrival *prev_arrivals = graph_->arrivals(vertex);
|
Arrival *prev_arrivals = graph_->arrivals(vertex);
|
||||||
PathVertexRep *prev_paths = graph_->prevPaths(vertex);
|
PathPrev *prev_paths = graph_->prevPaths(vertex);
|
||||||
|
bool save_prev = always_save_prev_paths_
|
||||||
|
|| tag_bldr->hasClkTag()
|
||||||
|
|| tag_bldr->hasGenClkSrcTag();
|
||||||
|
|
||||||
TagGroup *tag_group = findTagGroup(tag_bldr);
|
TagGroup *tag_group = findTagGroup(tag_bldr);
|
||||||
int arrival_count = tag_group->arrivalCount();
|
int arrival_count = tag_group->arrivalCount();
|
||||||
|
|
@ -2718,7 +2729,7 @@ Search::setVertexArrivals(Vertex *vertex,
|
||||||
// Reuse arrival array if it is the same size.
|
// Reuse arrival array if it is the same size.
|
||||||
if (prev_tag_group
|
if (prev_tag_group
|
||||||
&& arrival_count == prev_tag_group->arrivalCount()) {
|
&& arrival_count == prev_tag_group->arrivalCount()) {
|
||||||
if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag()) {
|
if (save_prev) {
|
||||||
if (prev_paths == nullptr)
|
if (prev_paths == nullptr)
|
||||||
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
||||||
}
|
}
|
||||||
|
|
@ -2751,7 +2762,7 @@ Search::setVertexArrivals(Vertex *vertex,
|
||||||
}
|
}
|
||||||
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
|
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
|
||||||
prev_paths = nullptr;
|
prev_paths = nullptr;
|
||||||
if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag())
|
if (save_prev)
|
||||||
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
||||||
tag_bldr->copyArrivals(tag_group, arrivals, prev_paths);
|
tag_bldr->copyArrivals(tag_group, arrivals, prev_paths);
|
||||||
|
|
||||||
|
|
@ -2771,6 +2782,7 @@ Search::reportArrivals(Vertex *vertex) const
|
||||||
TagGroup *tag_group = tagGroup(vertex);
|
TagGroup *tag_group = tagGroup(vertex);
|
||||||
Arrival *arrivals = graph_->arrivals(vertex);
|
Arrival *arrivals = graph_->arrivals(vertex);
|
||||||
Required *requireds = graph_->requireds(vertex);
|
Required *requireds = graph_->requireds(vertex);
|
||||||
|
PathPrev *prev_paths = graph_->prevPaths(vertex);
|
||||||
if (tag_group) {
|
if (tag_group) {
|
||||||
report_->reportLine("Group %u", tag_group->index());
|
report_->reportLine("Group %u", tag_group->index());
|
||||||
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
||||||
|
|
@ -2791,14 +2803,34 @@ Search::reportArrivals(Vertex *vertex) const
|
||||||
if (!prev.isNull())
|
if (!prev.isNull())
|
||||||
clk_prev = prev.name(this);
|
clk_prev = prev.name(this);
|
||||||
}
|
}
|
||||||
report_->reportLine(" %d %s %s %s / %s %s %s",
|
string prev_str;
|
||||||
|
if (prev_paths) {
|
||||||
|
PathPrev &prev = prev_paths[arrival_index];
|
||||||
|
if (!prev.isNull()) {
|
||||||
|
prev_str += prev.name(this);
|
||||||
|
prev_str += " ";
|
||||||
|
const Edge *prev_edge = prev.prevEdge(this);
|
||||||
|
TimingArc *arc = prev.prevArc(this);
|
||||||
|
prev_str += prev_edge->from(graph_)->name(network_);
|
||||||
|
prev_str += " ";
|
||||||
|
prev_str += arc->fromEdge()->asString();
|
||||||
|
prev_str += " -> ";
|
||||||
|
prev_str += prev_edge->to(graph_)->name(network_);
|
||||||
|
prev_str += " ";
|
||||||
|
prev_str += arc->toEdge()->asString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prev_str = "NULL";
|
||||||
|
}
|
||||||
|
report_->reportLine(" %d %s %s %s / %s %s %s prev %s",
|
||||||
arrival_index,
|
arrival_index,
|
||||||
rf->asString(),
|
rf->asString(),
|
||||||
path_ap->pathMinMax()->asString(),
|
path_ap->pathMinMax()->asString(),
|
||||||
delayAsString(arrivals[arrival_index], this),
|
delayAsString(arrivals[arrival_index], this),
|
||||||
req,
|
req,
|
||||||
tag->asString(true, false, this),
|
tag->asString(true, false, this),
|
||||||
clk_prev);
|
clk_prev,
|
||||||
|
prev_str.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2983,17 +3015,17 @@ Search::findClkInfo(const ClockEdge *clk_edge,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap,
|
||||||
PathVertex *crpr_clk_path)
|
PathVertex *crpr_clk_path)
|
||||||
{
|
{
|
||||||
PathVertexRep crpr_clk_path_rep(crpr_clk_path, this);
|
PathVertexPtr crpr_clk_path_ptr(crpr_clk_path, this);
|
||||||
ClkInfo probe(clk_edge, clk_src, is_propagated, gen_clk_src, gen_clk_src_path,
|
ClkInfo probe(clk_edge, clk_src, is_propagated, gen_clk_src, gen_clk_src_path,
|
||||||
pulse_clk_sense, insertion, latency, uncertainties,
|
pulse_clk_sense, insertion, latency, uncertainties,
|
||||||
path_ap->index(), crpr_clk_path_rep, this);
|
path_ap->index(), crpr_clk_path_ptr, this);
|
||||||
LockGuard lock(clk_info_lock_);
|
LockGuard lock(clk_info_lock_);
|
||||||
ClkInfo *clk_info = clk_info_set_->findKey(&probe);
|
ClkInfo *clk_info = clk_info_set_->findKey(&probe);
|
||||||
if (clk_info == nullptr) {
|
if (clk_info == nullptr) {
|
||||||
clk_info = new ClkInfo(clk_edge, clk_src,
|
clk_info = new ClkInfo(clk_edge, clk_src,
|
||||||
is_propagated, gen_clk_src, gen_clk_src_path,
|
is_propagated, gen_clk_src, gen_clk_src_path,
|
||||||
pulse_clk_sense, insertion, latency, uncertainties,
|
pulse_clk_sense, insertion, latency, uncertainties,
|
||||||
path_ap->index(), crpr_clk_path_rep, this);
|
path_ap->index(), crpr_clk_path_ptr, this);
|
||||||
clk_info_set_->insert(clk_info);
|
clk_info_set_->insert(clk_info);
|
||||||
}
|
}
|
||||||
return clk_info;
|
return clk_info;
|
||||||
|
|
|
||||||
|
|
@ -4609,8 +4609,7 @@ Sta::deletePinBefore(const Pin *pin)
|
||||||
if (edge->role()->isWire()) {
|
if (edge->role()->isWire()) {
|
||||||
// Only notify to vertex (from will be deleted).
|
// Only notify to vertex (from will be deleted).
|
||||||
Vertex *to = edge->to(graph_);
|
Vertex *to = edge->to(graph_);
|
||||||
// to->prev_paths point to vertex, so delete them.
|
search_->arrivalInvalid(to);
|
||||||
search_->arrivalInvalidDelete(to);
|
|
||||||
graph_delay_calc_->delayInvalid(to);
|
graph_delay_calc_->delayInvalid(to);
|
||||||
levelize_->relevelizeFrom(to);
|
levelize_->relevelizeFrom(to);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
#include "Tag.hh"
|
#include "Tag.hh"
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -200,7 +200,7 @@ TagGroupBldr::arrival(int arrival_index) const
|
||||||
void
|
void
|
||||||
TagGroupBldr::setArrival(Tag *tag,
|
TagGroupBldr::setArrival(Tag *tag,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
PathVertexRep *prev_path)
|
PathPrev *prev_path)
|
||||||
{
|
{
|
||||||
Tag *tag_match;
|
Tag *tag_match;
|
||||||
Arrival ignore;
|
Arrival ignore;
|
||||||
|
|
@ -215,7 +215,7 @@ TagGroupBldr::setMatchArrival(Tag *tag,
|
||||||
Tag *tag_match,
|
Tag *tag_match,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
int arrival_index,
|
int arrival_index,
|
||||||
PathVertexRep *prev_path)
|
PathPrev *prev_path)
|
||||||
{
|
{
|
||||||
if (tag_match) {
|
if (tag_match) {
|
||||||
// If the group_tag exists there has to be an arrival map entry for it.
|
// If the group_tag exists there has to be an arrival map entry for it.
|
||||||
|
|
@ -234,7 +234,7 @@ TagGroupBldr::setMatchArrival(Tag *tag,
|
||||||
if (prev_path)
|
if (prev_path)
|
||||||
prev_paths_.push_back(*prev_path);
|
prev_paths_.push_back(*prev_path);
|
||||||
else
|
else
|
||||||
prev_paths_.push_back(PathVertexRep());
|
prev_paths_.push_back(PathPrev());
|
||||||
|
|
||||||
if (tag->isClock())
|
if (tag->isClock())
|
||||||
has_clk_tag_ = true;
|
has_clk_tag_ = true;
|
||||||
|
|
@ -248,12 +248,6 @@ TagGroupBldr::setMatchArrival(Tag *tag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
TagGroupBldr::deleteArrival(Tag *tag)
|
|
||||||
{
|
|
||||||
arrival_map_.erase(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
TagGroup *
|
TagGroup *
|
||||||
TagGroupBldr::makeTagGroup(TagGroupIndex index,
|
TagGroupBldr::makeTagGroup(TagGroupIndex index,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
|
|
@ -285,7 +279,7 @@ TagGroupBldr::makeArrivalMap(const StaState *sta)
|
||||||
void
|
void
|
||||||
TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
||||||
Arrival *arrivals,
|
Arrival *arrivals,
|
||||||
PathVertexRep *prev_paths)
|
PathPrev *prev_paths)
|
||||||
{
|
{
|
||||||
ArrivalMap::Iterator arrival_iter1(arrival_map_);
|
ArrivalMap::Iterator arrival_iter1(arrival_map_);
|
||||||
while (arrival_iter1.hasNext()) {
|
while (arrival_iter1.hasNext()) {
|
||||||
|
|
@ -297,7 +291,7 @@ TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
||||||
if (exists2) {
|
if (exists2) {
|
||||||
arrivals[arrival_index2] = arrivals_[arrival_index1];
|
arrivals[arrival_index2] = arrivals_[arrival_index1];
|
||||||
if (prev_paths) {
|
if (prev_paths) {
|
||||||
PathVertexRep *prev_path = &prev_paths_[arrival_index1];
|
PathPrev *prev_path = &prev_paths_[arrival_index1];
|
||||||
prev_paths[arrival_index2].init(prev_path);
|
prev_paths[arrival_index2].init(prev_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -306,6 +300,12 @@ TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PathPrev &
|
||||||
|
TagGroupBldr::prevPath(int arrival_index)
|
||||||
|
{
|
||||||
|
return prev_paths_[arrival_index];
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ namespace sta {
|
||||||
|
|
||||||
class TagGroupBldr;
|
class TagGroupBldr;
|
||||||
|
|
||||||
typedef Vector<PathVertexRep> PathVertexRepSeq;
|
typedef Vector<PathPrev> PathPrevSeq;
|
||||||
|
|
||||||
class TagGroup
|
class TagGroup
|
||||||
{
|
{
|
||||||
|
|
@ -110,7 +110,6 @@ public:
|
||||||
bool hasGenClkSrcTag() const { return has_genclk_src_tag_; }
|
bool hasGenClkSrcTag() const { return has_genclk_src_tag_; }
|
||||||
bool hasFilterTag() const { return has_filter_tag_; }
|
bool hasFilterTag() const { return has_filter_tag_; }
|
||||||
bool hasLoopTag() const { return has_loop_tag_; }
|
bool hasLoopTag() const { return has_loop_tag_; }
|
||||||
void deleteArrival(Tag *tag);
|
|
||||||
void tagMatchArrival(Tag *tag,
|
void tagMatchArrival(Tag *tag,
|
||||||
// Return values.
|
// Return values.
|
||||||
Tag *&tag_match,
|
Tag *&tag_match,
|
||||||
|
|
@ -119,16 +118,17 @@ public:
|
||||||
Arrival arrival(int arrival_index) const;
|
Arrival arrival(int arrival_index) const;
|
||||||
void setArrival(Tag *tag,
|
void setArrival(Tag *tag,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
PathVertexRep *prev_path);
|
PathPrev *prev_path);
|
||||||
void setMatchArrival(Tag *tag,
|
void setMatchArrival(Tag *tag,
|
||||||
Tag *tag_match,
|
Tag *tag_match,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
int arrival_index,
|
int arrival_index,
|
||||||
PathVertexRep *prev_path);
|
PathPrev *prev_path);
|
||||||
ArrivalMap *arrivalMap() { return &arrival_map_; }
|
ArrivalMap *arrivalMap() { return &arrival_map_; }
|
||||||
|
PathPrev &prevPath(int arrival_index);
|
||||||
void copyArrivals(TagGroup *tag_group,
|
void copyArrivals(TagGroup *tag_group,
|
||||||
Arrival *arrivals,
|
Arrival *arrivals,
|
||||||
PathVertexRep *prev_paths);
|
PathPrev *prev_paths);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int tagMatchIndex();
|
int tagMatchIndex();
|
||||||
|
|
@ -138,7 +138,7 @@ protected:
|
||||||
int default_arrival_count_;
|
int default_arrival_count_;
|
||||||
ArrivalMap arrival_map_;
|
ArrivalMap arrival_map_;
|
||||||
ArrivalSeq arrivals_;
|
ArrivalSeq arrivals_;
|
||||||
PathVertexRepSeq prev_paths_;
|
PathPrevSeq prev_paths_;
|
||||||
bool has_clk_tag_;
|
bool has_clk_tag_;
|
||||||
bool has_genclk_src_tag_:1;
|
bool has_genclk_src_tag_:1;
|
||||||
bool has_filter_tag_;
|
bool has_filter_tag_;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue