class Path replaces PathVertex etc

commit 08c062d3dd1d0cea846407dda0b5fd75ca64329c
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 25 16:17:42 2025 -0700

    ApiChanges.txt

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit ef72112a00419e466e19b5c1442cac6f2835adaa
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 23 12:37:10 2025 -0700

    crpr29/30

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 2065acfbfbaa84307fde1c46ff51a1c619c45f50
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 23 12:33:55 2025 -0700

    compile error

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit d3133015b90b59f7e8e934c20d1ed8449d543d7b
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 17 15:20:55 2025 -0700

    rebase falout

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 8a4b81755765db823e18ffb497f1fb3f0c64ec7b
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 17 09:22:01 2025 -0700

    rebase fallout

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 7ef00dcaa4ed0b6db3f4205da47013e4f2ef1049
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sat Mar 15 17:00:51 2025 -0700

    deleteEdge clear to path prev_paths

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 912dacbca8f5c286f623f13659c831be6ed4d93e
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sat Mar 15 12:05:06 2025 -0700

    undo 7f8c7adb

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 9944c2ec907e9f07ab46f71af55ec947f3815de0
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Mar 14 21:25:10 2025 -0700

    rm Path::path()

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit a42c28b8447466a445cd8f6fb022eb42e6dcc0f2
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Mar 14 17:12:17 2025 -0700

    const

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 3f72adf1b5ad5581adc81afd3e00be7343ae4183
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Mar 14 17:03:04 2025 -0700

    PathExpanded rm prev_arcs_

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 25879e66eddf9f12db38705807e1270459661810
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 13 12:34:12 2025 -0700

    worst path init path

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 5c7a4fbdf3b8823a1944074a7eb663c6ea8e32df
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 13 10:47:02 2025 -0700

    delete edge -> xelete paths of to vertex

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit aa8d3035489de2cd25f27f7531177193be7a40ac
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 13 09:17:27 2025 -0700

    debug

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 53741b6c624b1313b0464a31e3900472d0b7c8d2
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 13 08:50:01 2025 -0700

    debug

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit cdebd8f3e476e5a2afab1a949449b75dcec9ed97
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 13 08:14:58 2025 -0700

    dbg network_edit

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 60cc960439e65cda8cd244723456b81242ced458
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 13 07:42:22 2025 -0700

    dbg network edit

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit f4e4264ac1c11dafddbe18971ca35127a0ffc171
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 19:23:17 2025 -0700

    rm PathVertex.hh

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit aeba9b293f095aecd01d0f5d16de51640f3d2381
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 13:33:21 2025 -0700

    PathEnum rm divEdge

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit ad97706562da7ceb41b9fbf4c882083de36d578d
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 13:18:38 2025 -0700

    genclks use path vector

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit a9c2563199d0cee3dee3d420c70f8117cfd69221
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 12:42:12 2025 -0700

    group_path_count, end_path_count use size_t

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit f16309a8e09e22964b998bf1b7e0922fbb9f02c1
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 12:30:08 2025 -0700

    Path rm uused

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 51295613c4ab6a6a4170080252397e2846a61bf1
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 12:22:23 2025 -0700

    network_edit3

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 5de6da2190460183cf07d0d4ffc1d1c6ebbe3e10
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 10:33:09 2025 -0700

    leak

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit f52dbc18ce08bd2b14d7107b61a57e614b1e3a07
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 11 08:06:56 2025 -0700

    valgrind 3 leaks left

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit de1a3727d908c4494f3039ff714ddb939d3390b5
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 10 18:21:50 2025 -0700

    Path::prevPath

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit c40aadcac8d2cd6d6dd8ba18f2e9db607358a01f
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 10 18:21:31 2025 -0700

    clk_skew init

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 041c97194553e7f7a4746f506be251ee42eb83ee
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 10 07:38:49 2025 -0700

    delete path groups before paths

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit fb4aed589f9f67ddb39f4260cb2901764cf49a98
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 9 17:23:27 2025 -0700

    leak

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 70b3062872cefdcf1358847025bc7bb1a85f4a5b
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 9 17:09:45 2025 -0700

    1 failure

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 92cd7c33c1eb22e4f574a767a645c5db1c9efe4d
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 9 11:19:59 2025 -0700

    7 failures

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 537ec153a5f8ab30d800cd36130e7668047b67af
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 9 09:05:31 2025 -0700

    11 failures

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit df514124c4daaf90175a89138ed954e20573e02f
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 9 08:37:00 2025 -0700

    25 failures

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 0096e8ee5a83194aee84da2cba95f410931f5c0e
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sat Mar 8 16:05:04 2025 -0700

    33 failures

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 02ba7ffdf38b538cd1659df25837d37e8317e741
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Mar 7 21:39:53 2025 -0700

    delete path groups before pahts

    Signed-Off-by: James Cherry <cherry@parallaxsw.com>

commit 270dbad6bc9303f9255256b5b85cac84deb27a94
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Mar 7 18:27:52 2025 -0700

    no seg faults, 42 failures

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 3ceca5981fd6032294523cd23dc1334b9619f6a0
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 6 15:43:28 2025 -0700

    multiclk1,2 seg fault

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 0441c00dc172817cc1a39bbb740d6369cf163869
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 6 15:29:47 2025 -0700

    gated_clocks15

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 7a1f87737e9c8247acd2c78138ee482d46123952
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Mar 6 09:05:09 2025 -0700

    nworst, crpr

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 74b52e5ac0ed9dac5b7c31835393c4e2dd30ca95
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 5 17:18:47 2025 -0700

    check_timiing6

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 93bddf0d940e9b833d5bc47d5af8b3bdefac67a5
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 5 17:13:24 2025 -0700

    nworst10

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit f1edddbffb2e0d23bc3f4a10733203b9756f2e2e
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 5 16:22:25 2025 -0700

    path enum

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit c57d241b668d305f0492e55e273b3411320692b4
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 5 16:09:11 2025 -0700

    most nwost pass

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit c6fca38e28571e5f2d63236aa67233d572c3a1d6
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 5 09:15:47 2025 -0700

    most genclks

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 82f5e6e9252987433f9699919c5716b3a4321a5d
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 4 17:51:29 2025 -0700

    genclks

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 19f4035496e004c543110b063482928e55bddbc9
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 4 17:33:28 2025 -0700

    nworst1

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit edafefa4e4f98291a3edebe5c7b3e2630988723f
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Mar 4 15:02:38 2025 -0700

    path enum

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 3e4684fd67eacdb474574eee9e51741e75bba907
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 3 21:07:18 2025 -0700

    rm unused Path* files

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 3f04819c01002f8b5eec0f4b8f0caf6798f3a20f
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 3 19:43:35 2025 -0700

    more regressions pass

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 276d70283cda14dfd6c48d1e2e4f45d326bf286c
Author: James Cherry <cherry@parallaxsw.com>
Date:   Mon Mar 3 10:43:30 2025 -0700

    arrival1

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 383a480450833741144b57383bb40a33310fad44
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 19:23:40 2025 -0700

    arrival1 no segfault

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 36e3a6b8d8b19f185a5a71fb4547e17586ea2c44
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 18:40:23 2025 -0700

    VertexPathIterator

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 083c76201e1a5482726e5856f124b15a523453d6
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 18:18:15 2025 -0700

    report_checks3 passes

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 834c076b7e2cb733655d917881463c76ce6196f6
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 14:10:34 2025 -0800

    links

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 371792b1e6dd44ad0c72399b999d86cd2557cbe1
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 13:37:33 2025 -0800

    link errors

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 158e9dafa6d11e0a4fd4e7ef253b0b6cb7595bf6
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 12:30:29 2025 -0800

    compiles

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 8df515dab15c0744abe04eae7e4a7d7688455f03
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 09:41:51 2025 -0800

    PathEnd compiles

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit d94f241d0803376b1526f32e4f5111d081c604af
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sun Mar 2 07:42:51 2025 -0800

    compile progress

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 591997e3bb496c4cc2fd6963c3798a8e17b8f587
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sat Mar 1 10:42:11 2025 -0800

    path unification

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-03-26 18:21:03 -07:00
parent 950d5b3383
commit 8992827b5b
69 changed files with 2148 additions and 3883 deletions

View File

@ -184,15 +184,11 @@ set(STA_SOURCE
search/MakeTimingModel.cc search/MakeTimingModel.cc
search/Path.cc search/Path.cc
search/PathAnalysisPt.cc search/PathAnalysisPt.cc
search/Path.cc
search/PathEnd.cc search/PathEnd.cc
search/PathEnum.cc search/PathEnum.cc
search/PathEnumed.cc
search/PathExpanded.cc search/PathExpanded.cc
search/PathGroup.cc search/PathGroup.cc
search/PathPrev.cc
search/PathRef.cc
search/PathVertex.cc
search/PathVertexPtr.cc
search/Property.cc search/Property.cc
search/ReportPath.cc search/ReportPath.cc
search/Search.cc search/Search.cc

View File

@ -24,6 +24,19 @@
This file summarizes STA API changes for each release. This file summarizes STA API changes for each release.
Release 2.4.0 2025/03/??
-------------------------
The following classes have been replaced by the class Path.
PathEnumed
PathPrev
PathRef
PathVertex
PathVertexPtr
PathVertexRep
The PathExpanded::prevArc function has been removed. Use Path::prevArc instead.
Release 2.4.0 2023/01/19 Release 2.4.0 2023/01/19
------------------------- -------------------------

View File

@ -571,75 +571,25 @@ Graph::gateEdgeArc(const Pin *in_pin,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Arrival * Path *
Graph::makeArrivals(Vertex *vertex, Graph::makePaths(Vertex *vertex,
uint32_t count) uint32_t count)
{ {
Arrival *arrivals = new Arrival[count]; Path *paths = new Path[count];
vertex->setArrivals(arrivals); vertex->setPaths(paths);
return arrivals; return paths;
} }
Arrival * Path *
Graph::arrivals(const Vertex *vertex) const Graph::paths(const Vertex *vertex) const
{ {
return vertex->arrivals(); return vertex->paths();
}
void
Graph::deleteArrivals(Vertex *vertex)
{
vertex->setArrivals(nullptr);
}
Required *
Graph::requireds(const Vertex *vertex) const
{
return vertex->requireds();
}
Required *
Graph::makeRequireds(Vertex *vertex,
uint32_t count)
{
Required *requireds = new Arrival[count];
vertex->setRequireds(requireds);
return requireds;
}
void
Graph::deleteRequireds(Vertex *vertex)
{
vertex->setRequireds(nullptr);
}
PathPrev *
Graph::prevPaths(const Vertex *vertex) const
{
return vertex->prevPaths();
}
PathPrev *
Graph::makePrevPaths(Vertex *vertex,
uint32_t count)
{
PathPrev *prev_paths = new PathPrev[count];
vertex->setPrevPaths(prev_paths);
return prev_paths;
}
void
Graph::deletePrevPaths(Vertex *vertex)
{
vertex->setPrevPaths(nullptr);
} }
void void
Graph::deletePaths(Vertex *vertex) Graph::deletePaths(Vertex *vertex)
{ {
deleteArrivals(vertex); vertex->setPaths(nullptr);
deleteRequireds(vertex);
deletePrevPaths(vertex);
vertex->tag_group_index_ = tag_group_index_max; vertex->tag_group_index_ = tag_group_index_max;
vertex->crpr_path_pruning_disabled_ = false; vertex->crpr_path_pruning_disabled_ = false;
} }
@ -1007,9 +957,7 @@ Vertex::init(Pin *pin,
in_edges_ = edge_id_null; in_edges_ = edge_id_null;
out_edges_ = edge_id_null; out_edges_ = edge_id_null;
slews_ = nullptr; slews_ = nullptr;
arrivals_ = nullptr; paths_ = nullptr;
requireds_ = nullptr;
prev_paths_ = nullptr;
tag_group_index_ = tag_group_index_max; tag_group_index_ = tag_group_index_max;
slew_annotated_ = false; slew_annotated_ = false;
sim_value_ = unsigned(LogicValue::unknown); sim_value_ = unsigned(LogicValue::unknown);
@ -1035,12 +983,8 @@ Vertex::clear()
{ {
delete [] slews_; delete [] slews_;
slews_ = nullptr; slews_ = nullptr;
delete [] arrivals_; delete [] paths_;
arrivals_ = nullptr; paths_ = nullptr;
delete [] requireds_;
requireds_ = nullptr;
delete [] prev_paths_;
prev_paths_ = nullptr;
} }
void void
@ -1153,24 +1097,10 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index)
} }
void void
Vertex::setArrivals(Arrival *arrivals) Vertex::setPaths(Path *paths)
{ {
delete [] arrivals_; delete [] paths_;
arrivals_ = arrivals; paths_ = paths;
}
void
Vertex::setRequireds(Required *requireds)
{
delete [] requireds_;
requireds_ = requireds;
}
void
Vertex::setPrevPaths(PathPrev *prev_paths)
{
delete [] prev_paths_;
prev_paths_ = prev_paths;
} }
LogicValue LogicValue

View File

@ -36,7 +36,7 @@
#include "Delay.hh" #include "Delay.hh"
#include "GraphClass.hh" #include "GraphClass.hh"
#include "VertexId.hh" #include "VertexId.hh"
#include "PathPrev.hh" #include "Path.hh"
#include "StaState.hh" #include "StaState.hh"
namespace sta { namespace sta {
@ -96,19 +96,9 @@ public:
void deleteVertex(Vertex *vertex); void deleteVertex(Vertex *vertex);
bool hasFaninOne(Vertex *vertex) const; bool hasFaninOne(Vertex *vertex) const;
VertexId vertexCount() { return vertices_->size(); } VertexId vertexCount() { return vertices_->size(); }
Arrival *makeArrivals(Vertex *vertex, Path *makePaths(Vertex *vertex,
uint32_t count); uint32_t count);
Arrival *arrivals(const Vertex *vertex) const; Path *paths(const Vertex *vertex) const;
void deleteArrivals(Vertex *vertex);
Required *makeRequireds(Vertex *vertex,
uint32_t count);
Required *requireds(const Vertex *vertex) const;
void deleteRequireds(Vertex *vertex);
PathPrev *makePrevPaths(Vertex *vertex,
uint32_t count);
PathPrev *prevPaths(const Vertex *vertex) const;
void deletePrevPaths(Vertex *vertex);
// Private to Search::deletePaths(Vertex).
void deletePaths(Vertex *vertex); void deletePaths(Vertex *vertex);
// Reported slew are the same as those in the liberty tables. // Reported slew are the same as those in the liberty tables.
@ -269,10 +259,8 @@ public:
void setColor(LevelColor color); void setColor(LevelColor color);
Slew *slews() { return slews_; } Slew *slews() { return slews_; }
const Slew *slews() const { return slews_; } const Slew *slews() const { return slews_; }
Arrival *arrivals() const { return arrivals_; } Path *paths() const { return paths_; }
Arrival *requireds() const { return requireds_; } void setPaths(Path *paths);
PathPrev *prevPaths() const { return 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.
@ -311,7 +299,6 @@ public:
bool isRegClk() const { return is_reg_clk_; } bool isRegClk() const { return is_reg_clk_; }
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;} bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
void setCrprPathPruningDisabled(bool disabled); void setCrprPathPruningDisabled(bool disabled);
bool hasRequireds() const { return requireds_ != nullptr; }
// ObjectTable interface. // ObjectTable interface.
ObjectIdx objectIdx() const { return object_idx_; } ObjectIdx objectIdx() const { return object_idx_; }
@ -324,8 +311,6 @@ protected:
bool is_bidirect_drvr, bool is_bidirect_drvr,
bool is_reg_clk); bool is_reg_clk);
void clear(); void clear();
void setArrivals(Arrival *arrivals);
void setRequireds(Required *requireds);
void setSlews(Slew *slews); void setSlews(Slew *slews);
Pin *pin_; Pin *pin_;
@ -335,9 +320,7 @@ protected:
// Delay calc // Delay calc
Slew *slews_; Slew *slews_;
// Search // Search
Arrival *arrivals_; Path *paths_;
Arrival *requireds_;
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.

View File

@ -37,57 +37,96 @@ namespace sta {
class DcalcAnalysisPt; class DcalcAnalysisPt;
// Abstract base class for Path API.
class Path class Path
{ {
public: public:
Path() {} Path();
virtual ~Path() {} Path(Path *path);
virtual const char *name(const StaState *sta) const; Path(Vertex *vertex,
virtual bool isNull() const = 0; Tag *tag,
virtual Path *path() { return isNull() ? nullptr : this; } const StaState *sta);
virtual const Path *path() const { return isNull() ? nullptr : this; } Path(Vertex *vertex,
virtual void setRef(PathRef *ref) const = 0; Tag *tag,
virtual void setRef(PathRef &ref) const { setRef(&ref); } Arrival arrival,
virtual Vertex *vertex(const StaState *sta) const = 0; Path *prev_path,
virtual VertexId vertexId(const StaState *sta) const = 0; Edge *prev_edge,
virtual Pin *pin(const StaState *sta) const; TimingArc *prev_arc,
virtual Tag *tag(const StaState *sta) const = 0; const StaState *sta);
virtual TagIndex tagIndex(const StaState *sta) const; Path(Vertex *vertex,
virtual ClkInfo *clkInfo(const StaState *sta) const; Tag *tag,
virtual const ClockEdge *clkEdge(const StaState *sta) const; Arrival arrival,
virtual const Clock *clock(const StaState *sta) const; Path *prev_path,
virtual bool isClock(const StaState *sta) const; Edge *prev_edge,
virtual const RiseFall *transition(const StaState *sta) const = 0; TimingArc *prev_arc,
virtual int rfIndex(const StaState *sta) const; bool is_enum,
virtual const MinMax *minMax(const StaState *sta) const; const StaState *sta);
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const = 0; ~Path();
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const; const char *name(const StaState *sta) const;
virtual DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const; bool isNull() const;
virtual Arrival arrival(const StaState *sta) const = 0; // prev_path null
virtual void setArrival(Arrival arrival, void init(Vertex *vertex,
const StaState *sta) = 0; Arrival arrival,
virtual void initArrival(const StaState *sta); const StaState *sta);
virtual bool arrivalIsInitValue(const StaState *sta) const; void init(Vertex *vertex,
virtual const Required &required(const StaState *sta) const = 0; Tag *tag,
virtual void setRequired(const Required &required, Arrival arrival,
const StaState *sta) = 0; Path *prev_path,
virtual void initRequired(const StaState *sta); Edge *prev_edge,
virtual bool requiredIsInitValue(const StaState *sta) const; TimingArc *prev_arc,
virtual Slack slack(const StaState *sta) const; const StaState *sta);
virtual Slew slew(const StaState *sta) const; void init(Vertex *vertex,
Tag *tag,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
Arrival arrival,
const StaState *sta);
Vertex *vertex(const StaState *sta) const;
VertexId vertexId(const StaState *sta) const;
Pin *pin(const StaState *sta) const;
Tag *tag(const StaState *sta) const;
TagIndex tagIndex(const StaState *sta) const;
void setTag(Tag *tag);
size_t pathIndex(const StaState *sta) const;
ClkInfo *clkInfo(const StaState *sta) const;
const ClockEdge *clkEdge(const StaState *sta) const;
const Clock *clock(const StaState *sta) const;
bool isClock(const StaState *sta) const;
const RiseFall *transition(const StaState *sta) const;
int rfIndex(const StaState *sta) const;
const MinMax *minMax(const StaState *sta) const;
PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const;
Arrival &arrival() { return arrival_; }
const Arrival &arrival() const { return arrival_; }
void setArrival(Arrival arrival);
Required &required() { return required_; }
const Required &required() const {return required_; }
void setRequired(const Required &required);
Slack slack(const StaState *sta) const;
Slew slew(const StaState *sta) const;
// This takes the same time as prevPath and prevArc combined. // This takes the same time as prevPath and prevArc combined.
virtual void prevPath(const StaState *sta, Path *prevPath() const;
// Return values. void setPrevPath(Path *prev_path);
PathRef &prev_path, void clearPrevPath(const StaState *sta);
TimingArc *&prev_arc) const = 0; TimingArc *prevArc(const StaState *sta) const;
virtual void prevPath(const StaState *sta, Edge *prevEdge(const StaState *sta) const;
// Return values. Vertex *prevVertex(const StaState *sta) const;
PathRef &prev_path) const; void setPrevEdgeArc(Edge *prev_edge,
virtual TimingArc *prevArc(const StaState *sta) const; TimingArc *prev_arc,
// Find the previous edge given the previous arc found above. const StaState *sta);
Edge *prevEdge(const TimingArc *prev_arc, bool isEnum() const { return is_enum_; }
const StaState *sta) const; void setIsEnum(bool is_enum);
void checkPrevPath(const StaState *sta) const;
void checkPrevPaths(const StaState *sta) const;
static Path *vertexPath(const Path &path,
const StaState *sta);
static Path *vertexPath(const Vertex *vertex,
Tag *tag,
const StaState *sta);
static bool less(const Path *path1, static bool less(const Path *path1,
const Path *path2, const Path *path2,
@ -118,6 +157,18 @@ public:
static bool lessAll(const Path *path1, static bool lessAll(const Path *path1,
const Path *path2, const Path *path2,
const StaState *sta); const StaState *sta);
protected:
Path *prev_path_;
Arrival arrival_;
Required required_;
union {
VertexId vertex_id_;
EdgeId prev_edge_id_;
};
TagIndex tag_index_:tag_index_bit_count;
bool is_enum_:1;
unsigned prev_arc_idx_:2;
}; };
// Compare all path attributes (vertex, transition, tag, analysis point). // Compare all path attributes (vertex, transition, tag, analysis point).
@ -132,4 +183,47 @@ protected:
const StaState *sta_; const StaState *sta_;
}; };
// Iterator for paths on a vertex.
class VertexPathIterator : public Iterator<Path*>
{
public:
// Iterate over all vertex paths.
VertexPathIterator(Vertex *vertex,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt min/max but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max,
const StaState *sta);
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const MinMax *min_max,
const StaState *sta);
virtual ~VertexPathIterator();
virtual bool hasNext();
virtual Path *next();
private:
void findNext();
const Search *search_;
//bool filtered_;
const RiseFall *rf_;
const PathAnalysisPt *path_ap_;
const MinMax *min_max_;
Path *paths_;
size_t path_count_;
//size_t path_index_;
Path *next_;
PathIndexMap::Iterator path_iter_;
};
} // namespace } // namespace

View File

@ -30,7 +30,7 @@
#include "GraphClass.hh" #include "GraphClass.hh"
#include "SdcClass.hh" #include "SdcClass.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "PathRef.hh" #include "Path.hh"
#include "StaState.hh" #include "StaState.hh"
namespace sta { namespace sta {
@ -73,10 +73,9 @@ public:
virtual PathEnd *copy() = 0; virtual PathEnd *copy() = 0;
virtual ~PathEnd(); virtual ~PathEnd();
void deletePath(); void deletePath();
Path *path() { return &path_; } Path *path() { return path_; }
const Path *path() const { return &path_; } const Path *path() const { return path_; }
PathRef &pathRef() { return path_; } virtual void setPath(Path *path);
virtual void setPath(const Path *path);
Vertex *vertex(const StaState *sta) const; Vertex *vertex(const StaState *sta) const;
const MinMax *minMax(const StaState *sta) const; const MinMax *minMax(const StaState *sta) const;
// Synonym for minMax(). // Synonym for minMax().
@ -118,8 +117,8 @@ public:
virtual float sourceClkOffset(const StaState *sta) const = 0; virtual float sourceClkOffset(const StaState *sta) const = 0;
virtual Delay sourceClkLatency(const StaState *sta) const; virtual Delay sourceClkLatency(const StaState *sta) const;
virtual Delay sourceClkInsertionDelay(const StaState *sta) const; virtual Delay sourceClkInsertionDelay(const StaState *sta) const;
virtual PathVertex *targetClkPath(); virtual Path *targetClkPath();
virtual const PathVertex *targetClkPath() const; virtual const Path *targetClkPath() const;
virtual const Clock *targetClk(const StaState *sta) const; virtual const Clock *targetClk(const StaState *sta) const;
virtual const ClockEdge *targetClkEdge(const StaState *sta) const; virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
const RiseFall *targetClkEndTrans(const StaState *sta) const; const RiseFall *targetClkEndTrans(const StaState *sta) const;
@ -149,7 +148,7 @@ public:
virtual MultiCyclePath *multiCyclePath() const; virtual MultiCyclePath *multiCyclePath() const;
virtual TimingArc *checkArc() const { return nullptr; } virtual TimingArc *checkArc() const { return nullptr; }
// PathEndDataCheck data clock path. // PathEndDataCheck data clock path.
virtual const PathVertex *dataClkPath() const { return nullptr; } virtual const Path *dataClkPath() const { return nullptr; }
virtual int setupDefaultCycles() const { return 1; } virtual int setupDefaultCycles() const { return 1; }
virtual Delay clkSkew(const StaState *sta); virtual Delay clkSkew(const StaState *sta);
virtual bool ignoreClkLatency(const StaState * /* sta */) const { return false; } virtual bool ignoreClkLatency(const StaState * /* sta */) const { return false; }
@ -173,11 +172,11 @@ public:
// Helper common to multiple PathEnd classes and used // Helper common to multiple PathEnd classes and used
// externally. // externally.
// Target clock insertion delay + latency. // Target clock insertion delay + latency.
static Delay checkTgtClkDelay(const PathVertex *tgt_clk_path, static Delay checkTgtClkDelay(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta); const StaState *sta);
static void checkTgtClkDelay(const PathVertex *tgt_clk_path, static void checkTgtClkDelay(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta, const StaState *sta,
@ -186,11 +185,11 @@ public:
Delay &latency); Delay &latency);
static float checkClkUncertainty(const ClockEdge *src_clk_edge, static float checkClkUncertainty(const ClockEdge *src_clk_edge,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const PathVertex *tgt_clk_path, const Path *tgt_clk_path,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta); const StaState *sta);
// Non inter-clock uncertainty. // Non inter-clock uncertainty.
static float checkTgtClkUncertainty(const PathVertex *tgt_clk_path, static float checkTgtClkUncertainty(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta); const StaState *sta);
@ -211,14 +210,14 @@ protected:
static float outputDelayMargin(OutputDelay *output_delay, static float outputDelayMargin(OutputDelay *output_delay,
const Path *path, const Path *path,
const StaState *sta); const StaState *sta);
static float pathDelaySrcClkOffset(const PathRef &path, static float pathDelaySrcClkOffset(const Path *path,
PathDelay *path_delay, PathDelay *path_delay,
Arrival src_clk_arrival, Arrival src_clk_arrival,
const StaState *sta); const StaState *sta);
static bool ignoreClkLatency(const PathRef &path, static bool ignoreClkLatency(const Path *path,
PathDelay *path_delay, PathDelay *path_delay,
const StaState *sta); const StaState *sta);
PathRef path_; Path *path_;
}; };
class PathEndUnconstrained : public PathEnd class PathEndUnconstrained : public PathEnd
@ -247,8 +246,8 @@ public:
virtual Delay sourceClkInsertionDelay(const StaState *sta) const; virtual Delay sourceClkInsertionDelay(const StaState *sta) const;
virtual const Clock *targetClk(const StaState *sta) const; virtual const Clock *targetClk(const StaState *sta) const;
virtual const ClockEdge *targetClkEdge(const StaState *sta) const; virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
virtual PathVertex *targetClkPath(); virtual Path *targetClkPath();
virtual const PathVertex *targetClkPath() const; virtual const Path *targetClkPath() const;
virtual float targetClkTime(const StaState *sta) const; virtual float targetClkTime(const StaState *sta) const;
virtual float targetClkOffset(const StaState *sta) const; virtual float targetClkOffset(const StaState *sta) const;
virtual Arrival targetClkArrival(const StaState *sta) const; virtual Arrival targetClkArrival(const StaState *sta) const;
@ -263,13 +262,13 @@ public:
virtual Slack slackNoCrpr(const StaState *sta) const; virtual Slack slackNoCrpr(const StaState *sta) const;
virtual int exceptPathCmp(const PathEnd *path_end, virtual int exceptPathCmp(const PathEnd *path_end,
const StaState *sta) const; const StaState *sta) const;
virtual void setPath(const Path *path); virtual void setPath(Path *path);
protected: protected:
PathEndClkConstrained(Path *path, PathEndClkConstrained(Path *path,
PathVertex *clk_path); Path *clk_path);
PathEndClkConstrained(Path *path, PathEndClkConstrained(Path *path,
PathVertex *clk_path, Path *clk_path,
Crpr crpr, Crpr crpr,
bool crpr_valid); bool crpr_valid);
@ -281,7 +280,7 @@ protected:
virtual Arrival targetClkArrivalNoCrpr(const StaState *sta) const; virtual Arrival targetClkArrivalNoCrpr(const StaState *sta) const;
virtual Required requiredTimeNoCrpr(const StaState *sta) const; virtual Required requiredTimeNoCrpr(const StaState *sta) const;
PathVertex clk_path_; Path *clk_path_;
mutable Crpr crpr_; mutable Crpr crpr_;
mutable bool crpr_valid_; mutable bool crpr_valid_;
}; };
@ -296,10 +295,10 @@ public:
protected: protected:
PathEndClkConstrainedMcp(Path *path, PathEndClkConstrainedMcp(Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp); MultiCyclePath *mcp);
PathEndClkConstrainedMcp(Path *path, PathEndClkConstrainedMcp(Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid); bool crpr_valid);
@ -321,7 +320,7 @@ public:
PathEndCheck(Path *path, PathEndCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
const StaState *sta); const StaState *sta);
virtual PathEnd *copy(); virtual PathEnd *copy();
@ -342,7 +341,7 @@ protected:
PathEndCheck(Path *path, PathEndCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid); bool crpr_valid);
@ -360,7 +359,7 @@ public:
PathEndLatchCheck(Path *path, PathEndLatchCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *disable_path, Path *disable_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathDelay *path_delay, PathDelay *path_delay,
const StaState *sta); const StaState *sta);
@ -371,8 +370,8 @@ public:
virtual bool isLatchCheck() const { return true; } virtual bool isLatchCheck() const { return true; }
virtual PathDelay *pathDelay() const { return path_delay_; } virtual PathDelay *pathDelay() const { return path_delay_; }
virtual PathEnd *copy(); virtual PathEnd *copy();
PathVertex *latchDisable(); Path *latchDisable();
const PathVertex *latchDisable() const; const Path *latchDisable() const;
virtual void reportShort(const ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(const ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual TimingRole *checkRole(const StaState *sta) const; virtual TimingRole *checkRole(const StaState *sta) const;
@ -403,8 +402,8 @@ protected:
PathEndLatchCheck(Path *path, PathEndLatchCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *clk_path, Path *clk_path,
PathVertex *disable, Path *disable,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathDelay *path_delay, PathDelay *path_delay,
Delay src_clk_arrival, Delay src_clk_arrival,
@ -412,7 +411,7 @@ protected:
bool crpr_valid); bool crpr_valid);
private: private:
PathVertex disable_path_; Path *disable_path_;
PathDelay *path_delay_; PathDelay *path_delay_;
// Source clk arrival for set_max_delay -ignore_clk_latency. // Source clk arrival for set_max_delay -ignore_clk_latency.
Arrival src_clk_arrival_; Arrival src_clk_arrival_;
@ -426,7 +425,7 @@ class PathEndOutputDelay : public PathEndClkConstrainedMcp
public: public:
PathEndOutputDelay(OutputDelay *output_delay, PathEndOutputDelay(OutputDelay *output_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
const StaState *sta); const StaState *sta);
virtual PathEnd *copy(); virtual PathEnd *copy();
@ -448,7 +447,7 @@ public:
protected: protected:
PathEndOutputDelay(OutputDelay *output_delay, PathEndOutputDelay(OutputDelay *output_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid); bool crpr_valid);
@ -470,7 +469,7 @@ class PathEndGatedClock : public PathEndClkConstrainedMcp
{ {
public: public:
PathEndGatedClock(Path *gating_ref, PathEndGatedClock(Path *gating_ref,
PathVertex *clk_path, Path *clk_path,
TimingRole *check_role, TimingRole *check_role,
MultiCyclePath *mcp, MultiCyclePath *mcp,
ArcDelay margin, ArcDelay margin,
@ -488,7 +487,7 @@ public:
protected: protected:
PathEndGatedClock(Path *gating_ref, PathEndGatedClock(Path *gating_ref,
PathVertex *clk_path, Path *clk_path,
TimingRole *check_role, TimingRole *check_role,
MultiCyclePath *mcp, MultiCyclePath *mcp,
ArcDelay margin, ArcDelay margin,
@ -504,7 +503,7 @@ class PathEndDataCheck : public PathEndClkConstrainedMcp
public: public:
PathEndDataCheck(DataCheck *check, PathEndDataCheck(DataCheck *check,
Path *data_path, Path *data_path,
PathVertex *data_clk_path, Path *data_clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
const StaState *sta); const StaState *sta);
virtual PathEnd *copy(); virtual PathEnd *copy();
@ -518,26 +517,24 @@ public:
virtual ArcDelay margin(const StaState *sta) const; virtual ArcDelay margin(const StaState *sta) const;
virtual int exceptPathCmp(const PathEnd *path_end, virtual int exceptPathCmp(const PathEnd *path_end,
const StaState *sta) const; const StaState *sta) const;
virtual const PathVertex *dataClkPath() const { return &data_clk_path_; } virtual const Path *dataClkPath() const { return data_clk_path_; }
protected: protected:
PathEndDataCheck(DataCheck *check, PathEndDataCheck(DataCheck *check,
Path *data_path, Path *data_path,
PathVertex *data_clk_path, Path *data_clk_path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid); bool crpr_valid);
void clkPath(PathVertex *path, Path *clkPath(Path *path,
const StaState *sta, const StaState *sta);
// Return value.
PathVertex &clk_path);
Arrival requiredTimeNoCrpr(const StaState *sta) const; Arrival requiredTimeNoCrpr(const StaState *sta) const;
// setup uses zero cycle default // setup uses zero cycle default
virtual int setupDefaultCycles() const { return 0; } virtual int setupDefaultCycles() const { return 0; }
private: private:
PathVertex data_clk_path_; Path *data_clk_path_;
DataCheck *check_; DataCheck *check_;
}; };
@ -554,7 +551,7 @@ public:
// Path delay to timing check. // Path delay to timing check.
PathEndPathDelay(PathDelay *path_delay, PathEndPathDelay(PathDelay *path_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
const StaState *sta); const StaState *sta);
@ -588,7 +585,7 @@ public:
protected: protected:
PathEndPathDelay(PathDelay *path_delay, PathEndPathDelay(PathDelay *path_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
OutputDelay *output_delay, OutputDelay *output_delay,

View File

@ -27,7 +27,7 @@
#include "TimingArc.hh" #include "TimingArc.hh"
#include "GraphClass.hh" #include "GraphClass.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "PathRef.hh" #include "Path.hh"
#include "StaState.hh" #include "StaState.hh"
namespace sta { namespace sta {
@ -48,33 +48,31 @@ public:
size_t size() const { return paths_.size(); } size_t size() const { return paths_.size(); }
// path(0) is the startpoint. // path(0) is the startpoint.
// path(size()-1) is the endpoint. // path(size()-1) is the endpoint.
const PathRef *path(size_t index) const; const Path *path(size_t index) const;
TimingArc *prevArc(size_t index) const;
// Returns the path start point. // Returns the path start point.
// Register/Latch Q pin // Register/Latch Q pin
// Input pin // Input pin
const PathRef *startPath() const; const Path *startPath() const;
const PathRef *startPrevPath() const; const Path *startPrevPath() const;
const PathRef *endPath() const; const Path *endPath() const;
TimingArc *startPrevArc() const; const TimingArc *startPrevArc() const;
size_t startIndex() const; size_t startIndex() const;
void clkPath(PathRef &clk_path) const; const Path *clkPath() const;
void latchPaths(// Return values. void latchPaths(// Return values.
const PathRef *&d_path, const Path *&d_path,
const PathRef *&q_path, const Path *&q_path,
Edge *&d_q_edge) const; Edge *&d_q_edge) const;
protected: protected:
void expandGenclk(PathRef *clk_path); void expandGenclk(const Path *clk_path);
// Convert external index that starts at the path root // Convert external index that starts at the path root
// and increases to an index for paths_ (reversed). // and increases to an index for paths_ (reversed).
size_t pathsIndex(size_t index) const; size_t pathsIndex(size_t index) const;
// The PathRefs in paths_ are in reverse order. // The Paths in paths_ are in reverse order.
// paths_[0] is the endpoint. // paths_[0] is the endpoint.
// paths_[size-1] is the beginning of the path. // paths_[size-1] is the beginning of the path.
PathRefSeq paths_; ConstPathSeq paths_;
TimingArcSeq prev_arcs_;
// Index of the startpoint. // Index of the startpoint.
size_t start_index_; size_t start_index_;
const StaState *sta_; const StaState *sta_;

View File

@ -74,12 +74,12 @@ public:
PathGroupIterator *iterator(); PathGroupIterator *iterator();
// This does NOT delete the path ends. // This does NOT delete the path ends.
void clear(); void clear();
static int group_path_count_max; static size_t group_path_count_max;
protected: protected:
PathGroup(const char *name, PathGroup(const char *name,
int group_path_count, size_t group_path_count,
int endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
float min_slack, float min_slack,
float max_slack, float max_slack,
@ -91,8 +91,8 @@ protected:
void sort(); void sort();
const char *name_; const char *name_;
int group_path_count_; size_t group_path_count_;
int endpoint_path_count_; size_t endpoint_path_count_;
bool unique_pins_; bool unique_pins_;
float slack_min_; float slack_min_;
float slack_max_; float slack_max_;

View File

@ -1,75 +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.
#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

View File

@ -1,94 +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.
#pragma once
#include "Vector.hh"
#include "SearchClass.hh"
#include "Path.hh"
#include "PathVertex.hh"
namespace sta {
// Path reference to either a PathVertex or PathEnum.
// This "could" be made smaller by using a union for
// path_vertex_.vertex_ and path_enumed_ and a non-legal
// value for path_vertex_.arrival_index_ (because a nullptr tag
// in PathVertex is valid).
class PathRef : public Path
{
public:
PathRef();
PathRef(const Path *path);
PathRef(const PathRef &path);
PathRef(const PathRef *path);
PathRef(const PathVertex &path);
void init();
void init(const PathRef &path);
void init(const PathRef *path);
void init(const PathVertex &path);
void init(const PathVertex *path);
void init(const PathPrev &path,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
int arrival_index);
void init(PathEnumed *path);
virtual void setRef(PathRef *ref) const;
virtual bool isNull() const;
virtual Vertex *vertex(const StaState *sta) const;
virtual VertexId vertexId(const StaState *sta) const;
virtual Tag *tag(const StaState *sta) const;
virtual TagIndex tagIndex(const StaState *sta) const;
virtual const RiseFall *transition(const StaState *sta) const;
virtual int rfIndex(const StaState *sta) const;
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
void arrivalIndex(int &arrival_index,
bool &arrival_exists) const;
virtual Arrival arrival(const StaState *sta) const;
virtual void setArrival(Arrival arrival,
const StaState *sta);
virtual const Required &required(const StaState *sta) const;
virtual void setRequired(const Required &required,
const StaState *sta);
virtual void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const;
void deleteRep();
using Path::setRef;
using Path::prevPath;
protected:
PathVertex path_vertex_;
PathEnumed *path_enumed_;
private:
friend class PathVertex;
friend class PathEnumed;
};
} // namespace

View File

@ -1,158 +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.
#pragma once
#include "SearchClass.hh"
#include "Path.hh"
namespace sta {
class PathPrev;
class PathVertexPtr;
// Implements Path API for a vertex.
class PathVertex : public Path
{
public:
PathVertex();
PathVertex(const PathVertex &path);
PathVertex(const PathVertex *path);
PathVertex(const PathPrev *path,
const StaState *sta);
PathVertex(const PathPrev &path,
const StaState *sta);
PathVertex(const PathVertexPtr &path,
const StaState *sta);
// If tag is not in the vertex tag group isNull() is true.
PathVertex(Vertex *vertex,
Tag *tag,
const StaState *sta);
PathVertex(Vertex *vertex,
Tag *tag,
int arrival_index);
void init();
void init(const PathPrev *path,
const StaState *sta);
void init(const PathPrev &path,
const StaState *sta);
void init(const PathVertexPtr &path,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
int arrival_index);
void operator=(const PathVertex &path);
virtual bool isNull() const;
virtual void setRef(PathRef *ref) const;
virtual Vertex *vertex(const StaState *) const { return vertex_; }
virtual VertexId vertexId(const StaState *sta) const;
virtual Tag *tag(const StaState *) const { return tag_; }
virtual TagIndex tagIndex(const StaState *sta) const;
virtual const RiseFall *transition(const StaState *) const;
virtual int rfIndex(const StaState *sta) const;
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
void arrivalIndex(int &arrival_index,
bool &arrival_exists) const;
void setArrivalIndex(int arrival_index);
virtual Arrival arrival(const StaState *sta) const;
virtual void setArrival(Arrival arrival,
const StaState *sta);
virtual const Required &required(const StaState *sta) const;
virtual void setRequired(const Required &required,
const StaState *sta);
virtual void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const;
void prevPath(const StaState *sta,
// Return values.
PathVertex &prev_path) const;
void prevPath(const StaState *sta,
// Return values.
PathVertex &prev_path,
TimingArc *&prev_arc) const;
static bool equal(const PathVertex *path1,
const PathVertex *path2);
using Path::setRef;
using Path::prevPath;
protected:
Vertex *vertex_;
Tag *tag_;
int arrival_index_;
private:
friend class PathRef;
friend class VertexPathIterator;
friend bool pathVertexEqual(const PathVertex *path1,
const PathVertex *path2);
};
// Iterator for vertex paths.
class VertexPathIterator : public Iterator<PathVertex*>
{
public:
// Iterate over all vertex paths.
VertexPathIterator(Vertex *vertex,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt min/max but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max,
const StaState *sta);
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const MinMax *min_max,
const StaState *sta);
virtual ~VertexPathIterator();
virtual bool hasNext();
virtual PathVertex *next();
private:
void findNext();
const Search *search_;
Vertex *vertex_;
const RiseFall *rf_;
const PathAnalysisPt *path_ap_;
const MinMax *min_max_;
ArrivalMap::Iterator arrival_iter_;
PathVertex path_;
PathVertex next_;
};
} // namespace

View File

@ -1,63 +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.
#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

View File

@ -55,7 +55,7 @@ public:
type_library, type_cell, type_port, type_library, type_cell, type_port,
type_liberty_library, type_liberty_cell, type_liberty_port, type_liberty_library, type_liberty_cell, type_liberty_port,
type_instance, type_pin, type_pins, type_net, type_instance, type_pin, type_pins, type_net,
type_clk, type_clks, type_path_refs, type_pwr_activity }; type_clk, type_clks, type_paths, type_pwr_activity };
PropertyValue(); PropertyValue();
PropertyValue(const char *value); PropertyValue(const char *value);
PropertyValue(string &value); PropertyValue(string &value);
@ -77,7 +77,7 @@ public:
PropertyValue(const Clock *value); PropertyValue(const Clock *value);
PropertyValue(ClockSeq *value); PropertyValue(ClockSeq *value);
PropertyValue(ClockSet *value); PropertyValue(ClockSet *value);
PropertyValue(PathRefSeq *value); PropertyValue(ConstPathSeq *value);
PropertyValue(PwrActivity *value); PropertyValue(PwrActivity *value);
// Copy constructor. // Copy constructor.
PropertyValue(const PropertyValue &props); PropertyValue(const PropertyValue &props);
@ -103,7 +103,7 @@ public:
const Net *net() const { return net_; } const Net *net() const { return net_; }
const Clock *clock() const { return clk_; } const Clock *clock() const { return clk_; }
ClockSeq *clocks() const { return clks_; } ClockSeq *clocks() const { return clks_; }
PathRefSeq *pathRefs() const { return path_refs_; } ConstPathSeq *paths() const { return paths_; }
PwrActivity pwrActivity() const { return pwr_activity_; } PwrActivity pwrActivity() const { return pwr_activity_; }
// Copy assignment. // Copy assignment.
@ -129,7 +129,7 @@ private:
const Net *net_; const Net *net_;
const Clock *clk_; const Clock *clk_;
ClockSeq *clks_; ClockSeq *clks_;
PathRefSeq *path_refs_; ConstPathSeq *paths_;
PwrActivity pwr_activity_; PwrActivity pwr_activity_;
}; };
const Unit *unit_; const Unit *unit_;
@ -196,7 +196,7 @@ getProperty(PathEnd *end,
Sta *sta); Sta *sta);
PropertyValue PropertyValue
getProperty(PathRef *end, getProperty(Path *end,
const char *property, const char *property,
Sta *sta); Sta *sta);

View File

@ -1,4 +1,4 @@
// OpenSTA, Static Timing Analyzer // opensta, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc. // Copyright (c) 2025, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
@ -39,6 +39,7 @@
#include "SearchClass.hh" #include "SearchClass.hh"
#include "SearchPred.hh" #include "SearchPred.hh"
#include "VertexVisitor.hh" #include "VertexVisitor.hh"
#include "Path.hh"
namespace sta { namespace sta {
@ -99,8 +100,8 @@ public:
bool unconstrained, bool unconstrained,
const Corner *corner, const Corner *corner,
const MinMaxAll *min_max, const MinMaxAll *min_max,
int group_path_count, size_t group_path_count,
int endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
float slack_min, float slack_min,
float slack_max, float slack_max,
@ -126,6 +127,7 @@ public:
void requiredInvalid(const Pin *pin); void requiredInvalid(const Pin *pin);
// Vertex will be deleted. // Vertex will be deleted.
void deleteVertexBefore(Vertex *vertex); void deleteVertexBefore(Vertex *vertex);
void deleteEdgeBefore(Edge *edge);
// Find all arrival times (propatating thru latches). // Find all arrival times (propatating thru latches).
void findAllArrivals(); void findAllArrivals();
// Find all arrivals (without latch propagation). // Find all arrivals (without latch propagation).
@ -226,7 +228,7 @@ public:
TagIndex tagCount() const; TagIndex tagCount() const;
TagGroupIndex tagGroupCount() const; TagGroupIndex tagGroupCount() const;
void reportTagGroups() const; void reportTagGroups() const;
void reportArrivalCountHistogram() const; void reportPathCountHistogram() const;
virtual int clkInfoCount() const; virtual int clkInfoCount() const;
virtual bool isEndpoint(Vertex *vertex) const; virtual bool isEndpoint(Vertex *vertex) const;
virtual bool isEndpoint(Vertex *vertex, virtual bool isEndpoint(Vertex *vertex,
@ -252,7 +254,7 @@ public:
const RiseFall *to_rf, const RiseFall *to_rf,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
Tag *thruClkTag(PathVertex *from_path, Tag *thruClkTag(Path *from_path,
Vertex *from_vertex, Vertex *from_vertex,
Tag *from_tag, Tag *from_tag,
bool to_propagates_clk, bool to_propagates_clk,
@ -261,7 +263,7 @@ public:
bool arc_delay_min_max_eq, bool arc_delay_min_max_eq,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
ClkInfo *thruClkInfo(PathVertex *from_path, ClkInfo *thruClkInfo(Path *from_path,
Vertex *from_vertex, Vertex *from_vertex,
ClkInfo *from_clk_info, ClkInfo *from_clk_info,
bool from_is_clk, bool from_is_clk,
@ -273,7 +275,7 @@ public:
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info, ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
PathVertex *from_path, Path *from_path,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
void seedClkArrivals(const Pin *pin, void seedClkArrivals(const Pin *pin,
Vertex *vertex, Vertex *vertex,
@ -339,7 +341,7 @@ public:
float latency, float latency,
ClockUncertainties *uncertainties, ClockUncertainties *uncertainties,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
PathVertex *crpr_clk_path); Path *crpr_clk_path);
ClkInfo *findClkInfo(const ClockEdge *clk_edge, ClkInfo *findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src, const Pin *clk_src,
bool is_propagated, bool is_propagated,
@ -378,7 +380,33 @@ public:
bool unconstrained, bool unconstrained,
bool thru_latches); bool thru_latches);
VertexSeq filteredEndpoints(); VertexSeq filteredEndpoints();
bool alwaysSavePrevPaths() const { return always_save_prev_paths_; }
Arrival *arrivals(const Vertex *vertex) const;
Arrival *makeArrivals(const Vertex *vertex,
uint32_t count);
void deleteArrivals(const Vertex *vertex);
Required *requireds(const Vertex *vertex) const;
bool hasRequireds(const Vertex *vertex) const;
Required *makeRequireds(const Vertex *vertex,
uint32_t count);
void deleteRequireds(const Vertex *vertex);
size_t arrivalCount() const;
size_t requiredCount() const;
Path *prevPaths(const Vertex *vertex) const;
Path *makePrevPaths(const Vertex *vertex,
uint32_t count);
void deletePrevPaths(Vertex *vertex);
bool crprPathPruningDisabled(const Vertex *vertex) const;
void setCrprPathPruningDisabled(const Vertex *vertex,
bool disabled);
bool bfsInQueue(const Vertex *vertex,
BfsIndex index) const;
void setBfsInQueue(const Vertex *vertex,
BfsIndex index,
bool value);
TagGroupIndex tagGroupIndex(const Vertex *vertex) const;
void setTagGroupIndex(const Vertex *vertex,
TagGroupIndex tag_index);
protected: protected:
void init(StaState *sta); void init(StaState *sta);
@ -544,7 +572,8 @@ protected:
void tnsNotifyBefore(Vertex *vertex); void tnsNotifyBefore(Vertex *vertex);
bool matchesFilterTo(Path *path, bool matchesFilterTo(Path *path,
const ClockEdge *to_clk_edge) const; const ClockEdge *to_clk_edge) const;
PathRef pathClkPathArrival1(const Path *path) const; const Path *pathClkPathArrival1(const Path *path) const;
void deletePathsState(const Vertex *vertex) const;
void clocks(const Vertex *vertex, void clocks(const Vertex *vertex,
// Return value. // Return value.
ClockSet &clks) const; ClockSet &clks) const;
@ -619,7 +648,6 @@ 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.
@ -682,7 +710,7 @@ protected:
bool visitArc(const Pin *from_pin, bool visitArc(const Pin *from_pin,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
PathVertex *from_path, Path *from_path,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
const Pin *to_pin, const Pin *to_pin,
@ -694,7 +722,7 @@ protected:
virtual bool visitFromPath(const Pin *from_pin, virtual bool visitFromPath(const Pin *from_pin,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
PathVertex *from_path, Path *from_path,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
const Pin *to_pin, const Pin *to_pin,
@ -707,7 +735,7 @@ protected:
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *from_path,
const Arrival &from_arrival, const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
@ -740,7 +768,7 @@ public:
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *from_path,
const Arrival &from_arrival, const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
@ -781,14 +809,14 @@ public:
RequiredCmp(); RequiredCmp();
void requiredsInit(Vertex *vertex, void requiredsInit(Vertex *vertex,
const StaState *sta); const StaState *sta);
void requiredSet(int arrival_index, void requiredSet(size_t path_index,
Required required, Required &required,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta); const StaState *sta);
// Return true if the requireds changed. // Return true if the requireds changed.
bool requiredsSave(Vertex *vertex, bool requiredsSave(Vertex *vertex,
const StaState *sta); const StaState *sta);
Required required(int arrival_index); Required required(size_t path_index);
protected: protected:
ArrivalSeq requireds_; ArrivalSeq requireds_;
@ -811,7 +839,7 @@ protected:
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *from_path,
const Arrival &from_arrival, const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,

View File

@ -41,12 +41,6 @@ namespace sta {
class Search; class Search;
class Corner; class Corner;
class Path; class Path;
class PathRep;
class PathVertex;
class PathPrev;
class PathVertexPtr;
class PathRef;
class PathEnumed;
class PathEnd; class PathEnd;
class PathGroup; class PathGroup;
class Tag; class Tag;
@ -120,12 +114,12 @@ typedef Vector<MaxSkewCheck*> MaxSkewCheckSeq;
typedef StringSet PathGroupNameSet; typedef StringSet PathGroupNameSet;
typedef Vector<PathEnd*> PathEndSeq; typedef Vector<PathEnd*> PathEndSeq;
typedef Vector<Arrival> ArrivalSeq; typedef Vector<Arrival> ArrivalSeq;
typedef Map<Vertex*, int> VertexPathCountMap; typedef Map<Vertex*, size_t> VertexPathCountMap;
typedef UnorderedMap<Tag*, int, TagMatchHash, TagMatchEqual> ArrivalMap; typedef UnorderedMap<Tag*, size_t, TagMatchHash, TagMatchEqual> PathIndexMap;
typedef Vector<PathVertex> PathVertexSeq;
typedef Vector<Slack> SlackSeq; typedef Vector<Slack> SlackSeq;
typedef Delay Crpr; typedef Delay Crpr;
typedef Vector<PathRef> PathRefSeq; typedef Vector<Path*> PathSeq;
typedef vector<const Path*> ConstPathSeq;
enum class ReportPathFormat { full, enum class ReportPathFormat { full,
full_clock, full_clock,

View File

@ -1000,21 +1000,21 @@ public:
VertexPathIterator *vertexPathIterator(Vertex *vertex, VertexPathIterator *vertexPathIterator(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max);
PathRef vertexWorstArrivalPath(Vertex *vertex, Path *vertexWorstArrivalPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
PathRef vertexWorstArrivalPath(Vertex *vertex,
const MinMax *min_max);
PathRef vertexWorstRequiredPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
PathRef vertexWorstRequiredPath(Vertex *vertex,
const MinMax *min_max);
PathRef vertexWorstSlackPath(Vertex *vertex,
const MinMax *min_max);
PathRef vertexWorstSlackPath(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max);
Path *vertexWorstArrivalPath(Vertex *vertex,
const MinMax *min_max);
Path *vertexWorstRequiredPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
Path *vertexWorstRequiredPath(Vertex *vertex,
const MinMax *min_max);
Path *vertexWorstSlackPath(Vertex *vertex,
const MinMax *min_max);
Path *vertexWorstSlackPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
// Find the min clock period for rise/rise and fall/fall paths of a clock // Find the min clock period for rise/rise and fall/fall paths of a clock
// using the slack. This does NOT correctly predict min period when there // using the slack. This does NOT correctly predict min period when there
@ -1112,10 +1112,9 @@ public:
TagIndex tagCount() const; TagIndex tagCount() const;
TagGroupIndex tagGroupCount() const; TagGroupIndex tagGroupCount() const;
int clkInfoCount() const; int clkInfoCount() const;
int arrivalCount() const; int pathCount() const;
int requiredCount() const; int vertexPathCount(Vertex *vertex) const;
int vertexArrivalCount(Vertex *vertex) const; Vertex *maxPathCountVertex() const;
Vertex *maxArrivalCountVertex() const;
LogicValue simLogicValue(const Pin *pin); LogicValue simLogicValue(const Pin *pin);
// Propagate liberty constant functions and pins tied high/low through // Propagate liberty constant functions and pins tied high/low through
@ -1314,7 +1313,7 @@ public:
LibertyLibrarySeq *map_libs); LibertyLibrarySeq *map_libs);
LibertyCellSeq *equivCells(LibertyCell *cell); LibertyCellSeq *equivCells(LibertyCell *cell);
void writePathSpice(PathRef *path, void writePathSpice(Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,

View File

@ -85,7 +85,7 @@ protected:
Path *path, Path *path,
const RiseFall *end_rf, const RiseFall *end_rf,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
PathVertex *ref_path, Path *ref_path,
const MinMax *min_max, const MinMax *min_max,
PathEndVisitor *visitor, PathEndVisitor *visitor,
bool &is_constrained); bool &is_constrained);

View File

@ -50,7 +50,7 @@
#include "DcalcAnalysisPt.hh" #include "DcalcAnalysisPt.hh"
#include "GraphDelayCalc.hh" #include "GraphDelayCalc.hh"
#include "Corner.hh" #include "Corner.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "search/Levelize.hh" #include "search/Levelize.hh"
#include "search/Sim.hh" #include "search/Sim.hh"
#include "Search.hh" #include "Search.hh"
@ -1339,7 +1339,7 @@ Power::findClk(const Pin *to_pin)
if (to_vertex) { if (to_vertex) {
VertexPathIterator path_iter(to_vertex, this); VertexPathIterator path_iter(to_vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
const Clock *path_clk = path->clock(this); const Clock *path_clk = path->clock(this);
if (path_clk if (path_clk
&& (clk == nullptr && (clk == nullptr

View File

@ -30,7 +30,7 @@
#include "Network.hh" #include "Network.hh"
#include "Graph.hh" #include "Graph.hh"
#include "Clock.hh" #include "Clock.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "Search.hh" #include "Search.hh"
@ -199,13 +199,13 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex,
RiseFall *ref_rf = arc->toEdge()->asRiseFall(); RiseFall *ref_rf = arc->toEdge()->asRiseFall();
VertexPathIterator clk_path_iter(vertex, clk_rf, clk_min_max, search); VertexPathIterator clk_path_iter(vertex, clk_rf, clk_min_max, search);
while (clk_path_iter.hasNext()) { while (clk_path_iter.hasNext()) {
PathVertex *clk_path = clk_path_iter.next(); Path *clk_path = clk_path_iter.next();
if (clk_path->isClock(search)) { if (clk_path->isClock(search)) {
const PathAnalysisPt *clk_ap = clk_path->pathAnalysisPt(sta_); const PathAnalysisPt *clk_ap = clk_path->pathAnalysisPt(sta_);
PathAnalysisPt *ref_ap = clk_ap->tgtClkAnalysisPt(); PathAnalysisPt *ref_ap = clk_ap->tgtClkAnalysisPt();
VertexPathIterator ref_path_iter(ref_vertex, ref_rf, ref_ap, sta_); VertexPathIterator ref_path_iter(ref_vertex, ref_rf, ref_ap, sta_);
while (ref_path_iter.hasNext()) { while (ref_path_iter.hasNext()) {
PathVertex *ref_path = ref_path_iter.next(); Path *ref_path = ref_path_iter.next();
if (ref_path->isClock(search)) { if (ref_path->isClock(search)) {
MaxSkewCheck check(clk_path, ref_path, arc, edge); MaxSkewCheck check(clk_path, ref_path, arc, edge);
visitor->visit(check, sta_); visitor->visit(check, sta_);
@ -220,8 +220,8 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
MaxSkewCheck::MaxSkewCheck(PathVertex *clk_path, MaxSkewCheck::MaxSkewCheck(Path *clk_path,
PathVertex *ref_path, Path *ref_path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge) : Edge *check_edge) :
clk_path_(clk_path), clk_path_(clk_path),
@ -234,34 +234,34 @@ MaxSkewCheck::MaxSkewCheck(PathVertex *clk_path,
Pin * Pin *
MaxSkewCheck::clkPin(const StaState *sta) const MaxSkewCheck::clkPin(const StaState *sta) const
{ {
return clk_path_.pin(sta); return clk_path_->pin(sta);
} }
Pin * Pin *
MaxSkewCheck::refPin(const StaState *sta) const MaxSkewCheck::refPin(const StaState *sta) const
{ {
return ref_path_.pin(sta); return ref_path_->pin(sta);
} }
ArcDelay ArcDelay
MaxSkewCheck::maxSkew(const StaState *sta) const MaxSkewCheck::maxSkew(const StaState *sta) const
{ {
Search *search = sta->search(); Search *search = sta->search();
return search->deratedDelay(ref_path_.vertex(sta), return search->deratedDelay(ref_path_->vertex(sta),
check_arc_, check_edge_, false, check_arc_, check_edge_, false,
clk_path_.pathAnalysisPt(sta)); clk_path_->pathAnalysisPt(sta));
} }
Delay Delay
MaxSkewCheck::skew(const StaState *sta) const MaxSkewCheck::skew() const
{ {
return Delay(clk_path_.arrival(sta) - ref_path_.arrival(sta)); return Delay(clk_path_->arrival() - ref_path_->arrival());
} }
Slack Slack
MaxSkewCheck::slack(const StaState *sta) const MaxSkewCheck::slack(const StaState *sta) const
{ {
return maxSkew(sta) - skew(sta); return maxSkew(sta) - skew();
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@
#include "Delay.hh" #include "Delay.hh"
#include "StaState.hh" #include "StaState.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "PathRef.hh" #include "Path.hh"
namespace sta { namespace sta {
@ -57,22 +57,22 @@ protected:
class MaxSkewCheck class MaxSkewCheck
{ {
public: public:
MaxSkewCheck(PathVertex *clk_path, MaxSkewCheck(Path *clk_path,
PathVertex *ref_path, Path *ref_path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge); Edge *check_edge);
const PathVertex *clkPath() const { return &clk_path_; } const Path *clkPath() const { return clk_path_; }
Pin *clkPin(const StaState *sta) const; Pin *clkPin(const StaState *sta) const;
const PathVertex *refPath() const { return &ref_path_; } const Path *refPath() const { return ref_path_; }
Pin *refPin(const StaState *sta) const; Pin *refPin(const StaState *sta) const;
Delay skew(const StaState *sta) const; Delay skew() const;
ArcDelay maxSkew(const StaState *sta) const; ArcDelay maxSkew(const StaState *sta) const;
Slack slack(const StaState *sta) const; Slack slack(const StaState *sta) const;
TimingArc *checkArc() const { return check_arc_; } TimingArc *checkArc() const { return check_arc_; }
private: private:
PathVertex clk_path_; Path *clk_path_;
PathVertex ref_path_; Path *ref_path_;
TimingArc *check_arc_; TimingArc *check_arc_;
Edge *check_edge_; Edge *check_edge_;
}; };

View File

@ -35,8 +35,7 @@
#include "GraphDelayCalc.hh" #include "GraphDelayCalc.hh"
#include "ClkInfo.hh" #include "ClkInfo.hh"
#include "Tag.hh" #include "Tag.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "PathRef.hh"
#include "Corner.hh" #include "Corner.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "SearchPred.hh" #include "SearchPred.hh"
@ -275,10 +274,9 @@ visitMinPulseWidthChecks(Vertex *vertex,
minPulseWidth(path, sta_, min_width, exists); minPulseWidth(path, sta_, min_width, exists);
if (exists) { if (exists) {
MinPulseWidthCheck check(path); MinPulseWidthCheck check(path);
PathVertex close_path; Path *close_path = check.closePath(sta_);
check.closePath(sta_, close_path);
// Don't bother visiting if nobody is home. // Don't bother visiting if nobody is home.
if (!close_path.isNull()) if (close_path)
visitor->visit(check, sta_); visitor->visit(check, sta_);
} }
} }
@ -289,7 +287,7 @@ visitMinPulseWidthChecks(Vertex *vertex,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
MinPulseWidthCheck::MinPulseWidthCheck() : MinPulseWidthCheck::MinPulseWidthCheck() :
open_path_() open_path_(nullptr)
{ {
} }
@ -301,31 +299,29 @@ MinPulseWidthCheck::MinPulseWidthCheck(Path *open_path) :
MinPulseWidthCheck * MinPulseWidthCheck *
MinPulseWidthCheck::copy() MinPulseWidthCheck::copy()
{ {
return new MinPulseWidthCheck(&open_path_); return new MinPulseWidthCheck(open_path_);
} }
Pin * Pin *
MinPulseWidthCheck::pin(const StaState *sta) const MinPulseWidthCheck::pin(const StaState *sta) const
{ {
return open_path_.pin(sta); return open_path_->pin(sta);
} }
const RiseFall * const RiseFall *
MinPulseWidthCheck::openTransition(const StaState *sta) const MinPulseWidthCheck::openTransition(const StaState *sta) const
{ {
return open_path_.transition(sta); return open_path_->transition(sta);
} }
void Path *
MinPulseWidthCheck::closePath(const StaState *sta, MinPulseWidthCheck::closePath(const StaState *sta) const
// Return value.
PathVertex &close) const
{ {
PathAnalysisPt *open_ap = open_path_.pathAnalysisPt(sta); PathAnalysisPt *open_ap = open_path_->pathAnalysisPt(sta);
PathAnalysisPt *close_ap = open_ap->tgtClkAnalysisPt(); PathAnalysisPt *close_ap = open_ap->tgtClkAnalysisPt();
const RiseFall *open_rf = open_path_.transition(sta); const RiseFall *open_rf = open_path_->transition(sta);
const RiseFall *close_rf = open_rf->opposite(); const RiseFall *close_rf = open_rf->opposite();
Tag *open_tag = open_path_.tag(sta); Tag *open_tag = open_path_->tag(sta);
ClkInfo *open_clk_info = open_tag->clkInfo(); ClkInfo *open_clk_info = open_tag->clkInfo();
ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(), ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(),
open_clk_info->clkSrc(), open_clk_info->clkSrc(),
@ -335,7 +331,7 @@ MinPulseWidthCheck::closePath(const StaState *sta,
open_clk_info->pulseClkSense(), open_clk_info->pulseClkSense(),
delay_zero, 0.0, nullptr, delay_zero, 0.0, nullptr,
open_clk_info->pathAPIndex(), open_clk_info->pathAPIndex(),
open_clk_info->crprClkPath(), open_clk_info->crprClkPath(sta),
sta); sta);
Tag close_tag(0, Tag close_tag(0,
close_rf->index(), close_rf->index(),
@ -350,31 +346,30 @@ MinPulseWidthCheck::closePath(const StaState *sta,
open_tag->asString(sta)); open_tag->asString(sta));
debugPrint(sta->debug(), "mpw", 3, " close %s", debugPrint(sta->debug(), "mpw", 3, " close %s",
close_tag.asString(sta)); close_tag.asString(sta));
VertexPathIterator close_iter(open_path_.vertex(sta), close_rf, VertexPathIterator close_iter(open_path_->vertex(sta), close_rf,
close_ap, sta); close_ap, sta);
while (close_iter.hasNext()) { while (close_iter.hasNext()) {
PathVertex *close_path = close_iter.next(); Path *close_path = close_iter.next();
if (tagMatchNoPathAp(close_path->tag(sta), &close_tag)) { if (tagMatchNoPathAp(close_path->tag(sta), &close_tag)) {
debugPrint(sta->debug(), "mpw", 3, " match %s", debugPrint(sta->debug(), "mpw", 3, " match %s",
close_path->tag(sta)->asString(sta)); close_path->tag(sta)->asString(sta));
close = close_path; return close_path;
break;
} }
} }
return nullptr;
} }
Arrival Arrival
MinPulseWidthCheck::openArrival(const StaState *sta) const MinPulseWidthCheck::openArrival(const StaState *) const
{ {
return open_path_.arrival(sta); return open_path_->arrival();
} }
Arrival Arrival
MinPulseWidthCheck::closeArrival(const StaState *sta) const MinPulseWidthCheck::closeArrival(const StaState *sta) const
{ {
PathVertex close; Path *close = closePath(sta);
closePath(sta, close); return close->arrival();
return close.arrival(sta);
} }
Arrival Arrival
@ -392,13 +387,13 @@ MinPulseWidthCheck::closeDelay(const StaState *sta) const
const ClockEdge * const ClockEdge *
MinPulseWidthCheck::openClkEdge(const StaState *sta) const MinPulseWidthCheck::openClkEdge(const StaState *sta) const
{ {
return open_path_.clkEdge(sta->search()); return open_path_->clkEdge(sta->search());
} }
const ClockEdge * const ClockEdge *
MinPulseWidthCheck::closeClkEdge(const StaState *sta) const MinPulseWidthCheck::closeClkEdge(const StaState *sta) const
{ {
Tag *open_tag = open_path_.tag(sta); Tag *open_tag = open_path_->tag(sta);
ClkInfo *open_clk_info = open_tag->clkInfo(); ClkInfo *open_clk_info = open_tag->clkInfo();
return open_clk_info->clkEdge()->opposite(); return open_clk_info->clkEdge()->opposite();
} }
@ -418,7 +413,7 @@ Arrival
MinPulseWidthCheck::width(const StaState *sta) const MinPulseWidthCheck::width(const StaState *sta) const
{ {
return closeArrival(sta) + closeOffset(sta) return closeArrival(sta) + closeOffset(sta)
- open_path_.arrival(sta) - open_path_->arrival()
+ checkCrpr(sta); + checkCrpr(sta);
} }
@ -427,7 +422,7 @@ MinPulseWidthCheck::minWidth(const StaState *sta) const
{ {
float min_width; float min_width;
bool exists; bool exists;
minPulseWidth(&open_path_, sta, min_width, exists); minPulseWidth(open_path_, sta, min_width, exists);
return min_width; return min_width;
} }
@ -469,10 +464,9 @@ Crpr
MinPulseWidthCheck::checkCrpr(const StaState *sta) const MinPulseWidthCheck::checkCrpr(const StaState *sta) const
{ {
CheckCrpr *check_crpr = sta->search()->checkCrpr(); CheckCrpr *check_crpr = sta->search()->checkCrpr();
PathVertex close; Path *close = closePath(sta);
closePath(sta, close); if (close)
if (!close.isNull()) return check_crpr->checkCrpr(openPath(), close);
return check_crpr->checkCrpr(openPath(), &close);
else else
return 0.0; return 0.0;
} }
@ -486,7 +480,7 @@ MinPulseWidthCheck::slack(const StaState *sta) const
Corner * Corner *
MinPulseWidthCheck::corner(const StaState *sta) const MinPulseWidthCheck::corner(const StaState *sta) const
{ {
return open_path_.pathAnalysisPt(sta)->corner(); return open_path_->pathAnalysisPt(sta)->corner();
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -27,7 +27,7 @@
#include "SdcClass.hh" #include "SdcClass.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "StaState.hh" #include "StaState.hh"
#include "PathRef.hh" #include "Path.hh"
namespace sta { namespace sta {
@ -75,13 +75,11 @@ public:
Arrival width(const StaState *sta) const; Arrival width(const StaState *sta) const;
float minWidth(const StaState *sta) const; float minWidth(const StaState *sta) const;
Slack slack(const StaState *sta) const; Slack slack(const StaState *sta) const;
Path *openPath() { return &open_path_; } Path *openPath() { return open_path_; }
Corner *corner(const StaState *sta) const; Corner *corner(const StaState *sta) const;
const Path *openPath() const { return &open_path_; } const Path *openPath() const { return open_path_; }
Arrival openArrival(const StaState *sta) const; Arrival openArrival(const StaState *sta) const;
void closePath(const StaState *sta, Path *closePath(const StaState *sta) const;
// Return value.
PathVertex &close) const;
Arrival closeArrival(const StaState *sta) const; Arrival closeArrival(const StaState *sta) const;
Arrival openDelay(const StaState *sta) const; Arrival openDelay(const StaState *sta) const;
Arrival closeDelay(const StaState *sta) const; Arrival closeDelay(const StaState *sta) const;
@ -92,7 +90,7 @@ public:
protected: protected:
// Open path of the pulse. // Open path of the pulse.
PathRef open_path_; Path *open_path_;
}; };
class MinPulseWidthSlackLess class MinPulseWidthSlackLess

View File

@ -34,7 +34,7 @@
#include "GraphDelayCalc.hh" #include "GraphDelayCalc.hh"
#include "StaState.hh" #include "StaState.hh"
#include "Corner.hh" #include "Corner.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "PortDirection.hh" #include "PortDirection.hh"
#include "Search.hh" #include "Search.hh"
#include "ClkNetwork.hh" #include "ClkNetwork.hh"

View File

@ -38,7 +38,7 @@
#include "Bfs.hh" #include "Bfs.hh"
#include "Search.hh" #include "Search.hh"
#include "Genclks.hh" #include "Genclks.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "Sim.hh" #include "Sim.hh"
namespace sta { namespace sta {
@ -316,7 +316,7 @@ CheckTiming::hasClkedArrival(Vertex *vertex)
{ {
VertexPathIterator path_iter(vertex, this); VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
if (path->clock(this)) if (path->clock(this))
return true; return true;
} }

View File

@ -27,7 +27,7 @@
#include "MinMax.hh" #include "MinMax.hh"
#include "StaState.hh" #include "StaState.hh"
#include "Transition.hh" #include "Transition.hh"
#include "PathVertex.hh" #include "Path.hh"
namespace sta { namespace sta {
@ -43,7 +43,7 @@ public:
Delay &delay, Delay &delay,
float &internal_latency, float &internal_latency,
Delay &latency, Delay &latency,
PathVertex &path, Path &path,
bool &exists) const; bool &exists) const;
void latency(const RiseFall *src_rf, void latency(const RiseFall *src_rf,
const RiseFall *end_rf, const RiseFall *end_rf,
@ -51,28 +51,28 @@ public:
// Return values. // Return values.
Delay &delay, Delay &delay,
bool &exists) const; bool &exists) const;
static Delay latency(PathVertex *clk_path, static Delay latency(Path *clk_path,
StaState *sta); StaState *sta);
void setLatency(const RiseFall *src_rf, void setLatency(const RiseFall *src_rf,
const RiseFall *end_rf, const RiseFall *end_rf,
const MinMax *min_max, const MinMax *min_max,
PathVertex *path, Path *path,
bool include_internal_latency, bool include_internal_latency,
StaState *sta); StaState *sta);
private: private:
static float insertionDelay(PathVertex *clk_path, static float insertionDelay(Path *clk_path,
StaState *sta); StaState *sta);
static float delay(PathVertex *clk_path, static float delay(Path *clk_path,
StaState *sta); StaState *sta);
static float clkTreeDelay(PathVertex *clk_path, static float clkTreeDelay(Path *clk_path,
StaState *sta); StaState *sta);
Delay insertion_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; Delay insertion_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
Delay delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; Delay delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
float internal_latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; float internal_latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
Delay latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; Delay latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
PathVertex path_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; Path path_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
bool exists_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; bool exists_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
}; };

View File

@ -53,12 +53,12 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
float latency, float latency,
ClockUncertainties *uncertainties, ClockUncertainties *uncertainties,
PathAPIndex path_ap_index, PathAPIndex path_ap_index,
PathVertexPtr &crpr_clk_path, Path *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),
gen_clk_src_(gen_clk_src), gen_clk_src_(gen_clk_src),
crpr_clk_path_(is_propagated ? crpr_clk_path : PathVertexPtr()), crpr_clk_path_(is_propagated ? crpr_clk_path : nullptr),
uncertainties_(uncertainties), uncertainties_(uncertainties),
insertion_(insertion), insertion_(insertion),
latency_(latency), latency_(latency),
@ -87,7 +87,7 @@ ClkInfo::findHash(const StaState *sta)
hashIncr(hash_, network->vertexId(clk_src_)); hashIncr(hash_, network->vertexId(clk_src_));
if (gen_clk_src_) if (gen_clk_src_)
hashIncr(hash_, network->vertexId(gen_clk_src_)); hashIncr(hash_, network->vertexId(gen_clk_src_));
hashIncr(hash_, crprClkVertexId()); hashIncr(hash_, crprClkVertexId(sta));
if (uncertainties_) { if (uncertainties_) {
float uncertainty; float uncertainty;
bool exists; bool exists;
@ -108,12 +108,24 @@ ClkInfo::findHash(const StaState *sta)
} }
VertexId VertexId
ClkInfo::crprClkVertexId() const ClkInfo::crprClkVertexId(const StaState *sta) const
{ {
if (crpr_clk_path_.isNull()) if (crpr_clk_path_.isNull())
return 0; return vertex_id_null;
else else
return crpr_clk_path_.vertexId(); return crpr_clk_path_.vertexId(sta);
}
Path *
ClkInfo::crprClkPath(const StaState *sta)
{
return Path::vertexPath(crpr_clk_path_, sta);
}
const Path *
ClkInfo::crprClkPath(const StaState *sta) const
{
return Path::vertexPath(crpr_clk_path_, sta);
} }
const char * const char *
@ -213,8 +225,9 @@ 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
|| (PathVertexPtr::equal(clk_info1->crprClkPath(), || Path::equal(clk_info1->crprClkPath(sta),
clk_info2->crprClkPath()))) clk_info2->crprClkPath(sta),
sta))
&& ((uncertainties1 == nullptr && ((uncertainties1 == nullptr
&& uncertainties2 == nullptr) && uncertainties2 == nullptr)
|| (uncertainties1 && uncertainties2 || (uncertainties1 && uncertainties2
@ -279,9 +292,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 PathVertexPtr &crpr_path1 = clk_info1->crprClkPath(); const Path *crpr_path1 = clk_info1->crprClkPath(sta);
const PathVertexPtr &crpr_path2 = clk_info2->crprClkPath(); const Path *crpr_path2 = clk_info2->crprClkPath(sta);
int path_cmp = PathVertexPtr::cmp(crpr_path1, crpr_path2); int path_cmp = Path::cmp(crpr_path1, crpr_path2, sta);
if (path_cmp != 0) if (path_cmp != 0)
return path_cmp; return path_cmp;
} }

View File

@ -26,12 +26,12 @@
#include "Transition.hh" #include "Transition.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "PathVertexPtr.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Path.hh"
namespace sta { namespace sta {
class PathVertex; class Path;
class ClkInfo class ClkInfo
{ {
@ -46,7 +46,7 @@ public:
float latency, float latency,
ClockUncertainties *uncertainties, ClockUncertainties *uncertainties,
PathAPIndex path_ap_index, PathAPIndex path_ap_index,
PathVertexPtr &crpr_clk_path, Path *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;
@ -65,9 +65,9 @@ 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.
PathVertexPtr &crprClkPath() { return crpr_clk_path_; } Path *crprClkPath(const StaState *sta);
const PathVertexPtr &crprClkPath() const { return crpr_clk_path_; } const Path *crprClkPath(const StaState *sta) const;
VertexId crprClkVertexId() const; VertexId crprClkVertexId(const StaState *sta) 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;
// This clk_info/tag is used for a generated clock source path. // This clk_info/tag is used for a generated clock source path.
@ -81,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_;
PathVertexPtr crpr_clk_path_; Path crpr_clk_path_;
ClockUncertainties *uncertainties_; ClockUncertainties *uncertainties_;
Arrival insertion_; Arrival insertion_;
float latency_; float latency_;

View File

@ -33,7 +33,7 @@
#include "Network.hh" #include "Network.hh"
#include "Clock.hh" #include "Clock.hh"
#include "Graph.hh" #include "Graph.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "StaState.hh" #include "StaState.hh"
#include "Search.hh" #include "Search.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
@ -88,7 +88,7 @@ ClkLatency::reportClkLatency(const Clock *clk,
report_->reportLine("Clock %s", clk->name()); report_->reportLine("Clock %s", clk->name());
for (const RiseFall *src_rf : RiseFall::range()) { for (const RiseFall *src_rf : RiseFall::range()) {
for (const RiseFall *end_rf : RiseFall::range()) { for (const RiseFall *end_rf : RiseFall::range()) {
PathVertex path_min; Path path_min;
Delay insertion_min; Delay insertion_min;
Delay delay_min; Delay delay_min;
float internal_latency_min; float internal_latency_min;
@ -97,7 +97,7 @@ ClkLatency::reportClkLatency(const Clock *clk,
clk_delays.delay(src_rf, end_rf, MinMax::min(), insertion_min, clk_delays.delay(src_rf, end_rf, MinMax::min(), insertion_min,
delay_min, internal_latency_min, latency_min, delay_min, internal_latency_min, latency_min,
path_min, exists_min); path_min, exists_min);
PathVertex path_max; Path path_max;
Delay insertion_max; Delay insertion_max;
Delay delay_max; Delay delay_max;
float internal_latency_max; float internal_latency_max;
@ -153,7 +153,7 @@ ClkLatency::findClkDelays(ConstClockSeq &clks,
for (Vertex *clk_vertex : *graph_->regClkVertices()) { for (Vertex *clk_vertex : *graph_->regClkVertices()) {
VertexPathIterator path_iter(clk_vertex, this); VertexPathIterator path_iter(clk_vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
const ClockEdge *path_clk_edge = path->clkEdge(this); const ClockEdge *path_clk_edge = path->clkEdge(this);
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this); const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
if (path_clk_edge if (path_clk_edge
@ -206,7 +206,7 @@ ClkDelays::delay(const RiseFall *src_rf,
Delay &delay, Delay &delay,
float &lib_clk_delay, float &lib_clk_delay,
Delay &latency, Delay &latency,
PathVertex &path, Path &path,
bool &exists) const bool &exists) const
{ {
int src_rf_index = src_rf->index(); int src_rf_index = src_rf->index();
@ -239,7 +239,7 @@ void
ClkDelays::setLatency(const RiseFall *src_rf, ClkDelays::setLatency(const RiseFall *src_rf,
const RiseFall *end_rf, const RiseFall *end_rf,
const MinMax *min_max, const MinMax *min_max,
PathVertex *path, Path *path,
bool include_internal_latency, bool include_internal_latency,
StaState *sta) StaState *sta)
{ {
@ -267,7 +267,7 @@ ClkDelays::setLatency(const RiseFall *src_rf,
} }
Delay Delay
ClkDelays::latency(PathVertex *clk_path, ClkDelays::latency(Path *clk_path,
StaState *sta) StaState *sta)
{ {
@ -278,16 +278,16 @@ ClkDelays::latency(PathVertex *clk_path,
} }
float float
ClkDelays::delay(PathVertex *clk_path, ClkDelays::delay(Path *clk_path,
StaState *sta) StaState *sta)
{ {
Arrival arrival = clk_path->arrival(sta); Arrival arrival = clk_path->arrival();
const ClockEdge *path_clk_edge = clk_path->clkEdge(sta); const ClockEdge *path_clk_edge = clk_path->clkEdge(sta);
return delayAsFloat(arrival) - path_clk_edge->time(); return delayAsFloat(arrival) - path_clk_edge->time();
} }
float float
ClkDelays::insertionDelay(PathVertex *clk_path, ClkDelays::insertionDelay(Path *clk_path,
StaState *sta) StaState *sta)
{ {
const ClockEdge *clk_edge = clk_path->clkEdge(sta); const ClockEdge *clk_edge = clk_path->clkEdge(sta);
@ -302,7 +302,7 @@ ClkDelays::insertionDelay(PathVertex *clk_path,
} }
float float
ClkDelays::clkTreeDelay(PathVertex *clk_path, ClkDelays::clkTreeDelay(Path *clk_path,
StaState *sta) StaState *sta)
{ {
const Vertex *vertex = clk_path->vertex(sta); const Vertex *vertex = clk_path->vertex(sta);

View File

@ -30,7 +30,7 @@
#include "StaState.hh" #include "StaState.hh"
#include "Transition.hh" #include "Transition.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "ClkDelays.hh" #include "ClkDelays.hh"
namespace sta { namespace sta {

View File

@ -38,7 +38,7 @@
#include "Graph.hh" #include "Graph.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Bfs.hh" #include "Bfs.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "StaState.hh" #include "StaState.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "SearchPred.hh" #include "SearchPred.hh"
@ -55,14 +55,14 @@ class ClkSkew
{ {
public: public:
ClkSkew(); ClkSkew();
ClkSkew(PathVertex *src_path, ClkSkew(Path *src_path,
PathVertex *tgt_path, Path *tgt_path,
bool include_internal_latency, bool include_internal_latency,
StaState *sta); StaState *sta);
ClkSkew(const ClkSkew &clk_skew); ClkSkew(const ClkSkew &clk_skew);
void operator=(const ClkSkew &clk_skew); void operator=(const ClkSkew &clk_skew);
PathVertex *srcPath() { return &src_path_; } Path *srcPath() { return src_path_; }
PathVertex *tgtPath() { return &tgt_path_; } Path *tgtPath() { return tgt_path_; }
float srcLatency(const StaState *sta); float srcLatency(const StaState *sta);
float tgtLatency(const StaState *sta); float tgtLatency(const StaState *sta);
float srcInternalClkLatency(const StaState *sta); float srcInternalClkLatency(const StaState *sta);
@ -75,23 +75,25 @@ public:
const StaState *sta); const StaState *sta);
private: private:
float clkTreeDelay(PathVertex &clk_path, float clkTreeDelay(Path *clk_path,
const StaState *sta); const StaState *sta);
PathVertex src_path_; Path *src_path_;
PathVertex tgt_path_; Path *tgt_path_;
bool include_internal_latency_; bool include_internal_latency_;
float skew_; float skew_;
}; };
ClkSkew::ClkSkew() : ClkSkew::ClkSkew() :
src_path_(nullptr),
tgt_path_(nullptr),
include_internal_latency_(false), include_internal_latency_(false),
skew_(0.0) skew_(0.0)
{ {
} }
ClkSkew::ClkSkew(PathVertex *src_path, ClkSkew::ClkSkew(Path *src_path,
PathVertex *tgt_path, Path *tgt_path,
bool include_internal_latency, bool include_internal_latency,
StaState *sta) : StaState *sta) :
src_path_(src_path), src_path_(src_path),
@ -124,8 +126,8 @@ ClkSkew::operator=(const ClkSkew &clk_skew)
float float
ClkSkew::srcLatency(const StaState *sta) ClkSkew::srcLatency(const StaState *sta)
{ {
Arrival src_arrival = src_path_.arrival(sta); Arrival src_arrival = src_path_->arrival();
return delayAsFloat(src_arrival) - src_path_.clkEdge(sta)->time() return delayAsFloat(src_arrival) - src_path_->clkEdge(sta)->time()
+ clkTreeDelay(src_path_, sta); + clkTreeDelay(src_path_, sta);
} }
@ -138,8 +140,8 @@ ClkSkew::srcInternalClkLatency(const StaState *sta)
float float
ClkSkew::tgtLatency(const StaState *sta) ClkSkew::tgtLatency(const StaState *sta)
{ {
Arrival tgt_arrival = tgt_path_.arrival(sta); Arrival tgt_arrival = tgt_path_->arrival();
return delayAsFloat(tgt_arrival) - tgt_path_.clkEdge(sta)->time() return delayAsFloat(tgt_arrival) - tgt_path_->clkEdge(sta)->time()
+ clkTreeDelay(tgt_path_, sta); + clkTreeDelay(tgt_path_, sta);
} }
@ -150,16 +152,16 @@ ClkSkew::tgtInternalClkLatency(const StaState *sta)
} }
float float
ClkSkew::clkTreeDelay(PathVertex &clk_path, ClkSkew::clkTreeDelay(Path *clk_path,
const StaState *sta) const StaState *sta)
{ {
if (include_internal_latency_) { if (include_internal_latency_) {
const Vertex *vertex = clk_path.vertex(sta); const Vertex *vertex = clk_path->vertex(sta);
const Pin *pin = vertex->pin(); const Pin *pin = vertex->pin();
const LibertyPort *port = sta->network()->libertyPort(pin); const LibertyPort *port = sta->network()->libertyPort(pin);
const MinMax *min_max = clk_path.minMax(sta); const MinMax *min_max = clk_path->minMax(sta);
const RiseFall *rf = clk_path.transition(sta); const RiseFall *rf = clk_path->transition(sta);
float slew = delayAsFloat(clk_path.slew(sta)); float slew = delayAsFloat(clk_path->slew(sta));
return port->clkTreeDelay(slew, rf, min_max); return port->clkTreeDelay(slew, rf, min_max);
} }
else else
@ -170,17 +172,17 @@ Crpr
ClkSkew::crpr(const StaState *sta) ClkSkew::crpr(const StaState *sta)
{ {
CheckCrpr *check_crpr = sta->search()->checkCrpr(); CheckCrpr *check_crpr = sta->search()->checkCrpr();
return check_crpr->checkCrpr(&src_path_, &tgt_path_); return check_crpr->checkCrpr(src_path_, tgt_path_);
} }
float float
ClkSkew::uncertainty(const StaState *sta) ClkSkew::uncertainty(const StaState *sta)
{ {
TimingRole *check_role = (src_path_.minMax(sta) == SetupHold::max()) TimingRole *check_role = (src_path_->minMax(sta) == SetupHold::max())
? TimingRole::setup() ? TimingRole::setup()
: TimingRole::hold(); : TimingRole::hold();
// Uncertainty decreases slack, but increases skew. // Uncertainty decreases slack, but increases skew.
return -PathEnd::checkTgtClkUncertainty(&tgt_path_, tgt_path_.clkEdge(sta), return -PathEnd::checkTgtClkUncertainty(tgt_path_, tgt_path_->clkEdge(sta),
check_role, sta); check_role, sta);
} }
@ -240,8 +242,8 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
int digits) int digits)
{ {
Unit *time_unit = units_->timeUnit(); Unit *time_unit = units_->timeUnit();
PathVertex *src_path = clk_skew.srcPath(); Path *src_path = clk_skew.srcPath();
PathVertex *tgt_path = clk_skew.tgtPath(); Path *tgt_path = clk_skew.tgtPath();
float src_latency = clk_skew.srcLatency(this); float src_latency = clk_skew.srcLatency(this);
float tgt_latency = clk_skew.tgtLatency(this); float tgt_latency = clk_skew.tgtLatency(this);
float src_internal_clk_latency = clk_skew.srcInternalClkLatency(this); float src_internal_clk_latency = clk_skew.srcInternalClkLatency(this);
@ -352,7 +354,7 @@ ClkSkews::hasClkPaths(Vertex *vertex)
{ {
VertexPathIterator path_iter(vertex, this); VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
const Clock *path_clk = path->clock(this); const Clock *path_clk = path->clock(this);
if (clk_set_.find(path_clk) != clk_set_.end()) if (clk_set_.find(path_clk) != clk_set_.end())
return true; return true;
@ -417,7 +419,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
const SetupHold *tgt_min_max = setup_hold_->opposite(); const SetupHold *tgt_min_max = setup_hold_->opposite();
VertexPathIterator src_iter(src_vertex, this); VertexPathIterator src_iter(src_vertex, this);
while (src_iter.hasNext()) { while (src_iter.hasNext()) {
PathVertex *src_path = src_iter.next(); Path *src_path = src_iter.next();
const Clock *src_clk = src_path->clock(this); const Clock *src_clk = src_path->clock(this);
if (src_rf->matches(src_path->transition(this)) if (src_rf->matches(src_path->transition(this))
&& src_path->minMax(this) == setup_hold_ && src_path->minMax(this) == setup_hold_
@ -427,7 +429,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
|| src_corner == corner_) { || src_corner == corner_) {
VertexPathIterator tgt_iter(tgt_vertex, this); VertexPathIterator tgt_iter(tgt_vertex, this);
while (tgt_iter.hasNext()) { while (tgt_iter.hasNext()) {
PathVertex *tgt_path = tgt_iter.next(); Path *tgt_path = tgt_iter.next();
const Clock *tgt_clk = tgt_path->clock(this); const Clock *tgt_clk = tgt_path->clock(this);
if (tgt_clk == src_clk if (tgt_clk == src_clk
&& tgt_path->isClock(this) && tgt_path->isClock(this)
@ -446,7 +448,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
time_unit->asString(probe.tgtLatency(this)), time_unit->asString(probe.tgtLatency(this)),
delayAsString(probe.crpr(this), this), delayAsString(probe.crpr(this), this),
time_unit->asString(probe.skew())); time_unit->asString(probe.skew()));
if (clk_skew.srcPath()->isNull() if (clk_skew.srcPath() == nullptr
|| abs(probe.skew()) > abs(clk_skew.skew())) || abs(probe.skew()) > abs(clk_skew.skew()))
clk_skew = probe; clk_skew = probe;
} }

View File

@ -32,7 +32,7 @@
#include "Transition.hh" #include "Transition.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "SearchPred.hh" #include "SearchPred.hh"
#include "PathVertex.hh" #include "Path.hh"
namespace sta { namespace sta {

View File

@ -32,8 +32,6 @@
#include "Network.hh" #include "Network.hh"
#include "Graph.hh" #include "Graph.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "PathVertex.hh"
#include "PathPrev.hh"
#include "Path.hh" #include "Path.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "ClkInfo.hh" #include "ClkInfo.hh"
@ -54,60 +52,26 @@ CheckCrpr::CheckCrpr(StaState *sta) :
{ {
} }
void
CheckCrpr::clkPathPrev(const PathVertex *path,
PathVertex &prev)
{
Vertex *vertex = path->vertex(this);
int arrival_index;
bool exists;
path->arrivalIndex(arrival_index, exists);
PathPrev *prevs = graph_->prevPaths(vertex);
if (prevs)
prev.init(prevs[arrival_index], this);
else
criticalError(2200, "missing prev paths");
}
PathVertex
CheckCrpr::clkPathPrev(Vertex *vertex,
int arrival_index)
{
PathPrev *prevs = graph_->prevPaths(vertex);
if (prevs)
return PathVertex(prevs[arrival_index], this);
else {
criticalError(2201, "missing prev paths");
return PathVertex();
}
}
////////////////////////////////////////////////////////////////
// Find the maximum possible crpr (clock min/max delta delay) for a // Find the maximum possible crpr (clock min/max delta delay) for a
// path from it's ClkInfo. // path from it's ClkInfo.
Arrival Arrival
CheckCrpr::maxCrpr(ClkInfo *clk_info) CheckCrpr::maxCrpr(ClkInfo *clk_info)
{ {
const PathVertexPtr &crpr_clk_path = clk_info->crprClkPath(); const Path *crpr_clk_path = clk_info->crprClkPath(this);
if (!crpr_clk_path.isNull()) { if (crpr_clk_path) {
PathVertex crpr_clk_vpath(crpr_clk_path, this); Arrival other_arrival = otherMinMaxArrival(crpr_clk_path);
if (!crpr_clk_vpath.isNull()) { float crpr_diff = abs(delayAsFloat(crpr_clk_path->arrival(),
Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath); EarlyLate::late(),
float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this), this)
EarlyLate::late(), - delayAsFloat(other_arrival, EarlyLate::early(),
this) this));
- delayAsFloat(other_arrival, EarlyLate::early(), return crpr_diff;
this));
return crpr_diff;
}
} }
return 0.0F; return 0.0F;
} }
Arrival Arrival
CheckCrpr::otherMinMaxArrival(const PathVertex *path) CheckCrpr::otherMinMaxArrival(const Path *path)
{ {
PathAnalysisPt *other_ap = path->pathAnalysisPt(this)->tgtClkAnalysisPt(); PathAnalysisPt *other_ap = path->pathAnalysisPt(this)->tgtClkAnalysisPt();
Tag *tag = path->tag(this); Tag *tag = path->tag(this);
@ -115,18 +79,18 @@ CheckCrpr::otherMinMaxArrival(const PathVertex *path)
path->transition(this), path->transition(this),
other_ap, this); other_ap, this);
while (other_iter.hasNext()) { while (other_iter.hasNext()) {
PathVertex *other = other_iter.next(); Path *other = other_iter.next();
if (tagMatchCrpr(other->tag(this), tag)) if (tagMatchCrpr(other->tag(this), tag))
return other->arrival(this); return other->arrival();
} }
// No corresponding path found. // No corresponding path found.
// Match the arrival so the difference is zero. // Match the arrival so the difference is zero.
return path->arrival(this); return path->arrival();
} }
Crpr Crpr
CheckCrpr::checkCrpr(const Path *src_path, CheckCrpr::checkCrpr(const Path *src_path,
const PathVertex *tgt_clk_path) const Path *tgt_clk_path)
{ {
Crpr crpr; Crpr crpr;
Pin *crpr_pin; Pin *crpr_pin;
@ -136,7 +100,7 @@ CheckCrpr::checkCrpr(const Path *src_path,
void void
CheckCrpr::checkCrpr(const Path *src_path, CheckCrpr::checkCrpr(const Path *src_path,
const PathVertex *tgt_clk_path, const Path *tgt_clk_path,
// Return values. // Return values.
Crpr &crpr, Crpr &crpr,
Pin *&crpr_pin) Pin *&crpr_pin)
@ -152,7 +116,7 @@ CheckCrpr::checkCrpr(const Path *src_path,
void void
CheckCrpr::checkCrpr1(const Path *src_path, CheckCrpr::checkCrpr1(const Path *src_path,
const PathVertex *tgt_clk_path, const Path *tgt_clk_path,
bool same_pin, bool same_pin,
// Return values. // Return values.
Crpr &crpr, Crpr &crpr,
@ -165,17 +129,11 @@ CheckCrpr::checkCrpr1(const Path *src_path,
ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo(); ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo();
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; const Path *src_clk_path = nullptr;
const PathVertexPtr &src_crpr_clk_path = src_clk_info->crprClkPath(); if (src_tag->isClock())
const PathVertex *src_clk_path = nullptr; src_clk_path = src_path;
if (src_tag->isClock()) { else
src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this); src_clk_path = src_clk_info->crprClkPath(this);
src_clk_path = &src_clk_path1;
}
else if (!src_crpr_clk_path.isNull()) {
src_clk_path1.init(src_crpr_clk_path, this);
src_clk_path = &src_clk_path1;
}
const MinMax *src_clk_min_max = const MinMax *src_clk_min_max =
src_clk_path ? src_clk_path->minMax(this) : src_path->minMax(this); src_clk_path ? src_clk_path->minMax(this) : src_path->minMax(this);
if (src_clk && tgt_clk if (src_clk && tgt_clk
@ -189,42 +147,37 @@ CheckCrpr::checkCrpr1(const Path *src_path,
&& (src_clk_path && (src_clk_path
|| src_clk->isGenerated())) { || src_clk->isGenerated())) {
// Src path from input port clk path can only be from generated clk path. // Src path from input port clk path can only be from generated clk path.
PathVertex port_clk_path;
if (src_clk_path == nullptr) { if (src_clk_path == nullptr) {
portClkPath(src_clk_info->clkEdge(), src_clk_path = portClkPath(src_clk_info->clkEdge(),
src_clk_info->clkSrc(), src_clk_info->clkSrc(),
src_path->pathAnalysisPt(this), src_path->pathAnalysisPt(this));
port_clk_path);
src_clk_path = &port_clk_path;
} }
findCrpr(src_clk_path, tgt_clk_path, same_pin, crpr, crpr_pin); findCrpr(src_clk_path, tgt_clk_path, same_pin, crpr, crpr_pin);
} }
} }
// Find the clk path for an input/output port. // Find the clk path for an input/output port.
void Path *
CheckCrpr::portClkPath(const ClockEdge *clk_edge, CheckCrpr::portClkPath(const ClockEdge *clk_edge,
const Pin *clk_src_pin, const Pin *clk_src_pin,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap)
// Return value.
PathVertex &genclk_path)
{ {
Vertex *clk_vertex = graph_->pinDrvrVertex(clk_src_pin); Vertex *clk_vertex = graph_->pinDrvrVertex(clk_src_pin);
VertexPathIterator path_iter(clk_vertex, clk_edge->transition(), VertexPathIterator path_iter(clk_vertex, clk_edge->transition(),
path_ap, this); path_ap, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
if (path->clkEdge(this) == clk_edge if (path->clkEdge(this) == clk_edge
&& path->isClock(this)) { && path->isClock(this)) {
genclk_path = path; return path;
break;
} }
} }
return nullptr;
} }
void void
CheckCrpr::findCrpr(const PathVertex *src_clk_path, CheckCrpr::findCrpr(const Path *src_clk_path,
const PathVertex *tgt_clk_path, const Path *tgt_clk_path,
bool same_pin, bool same_pin,
// Return values. // Return values.
Crpr &crpr, Crpr &crpr,
@ -232,35 +185,33 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path,
{ {
crpr = 0.0; crpr = 0.0;
crpr_pin = nullptr; crpr_pin = nullptr;
const PathVertex *src_clk_path1 = src_clk_path; const Path *src_clk_path1 = src_clk_path;
const PathVertex *tgt_clk_path1 = tgt_clk_path; const Path *tgt_clk_path1 = tgt_clk_path;
PathVertexSeq src_gclk_paths, tgt_gclk_paths;
if (src_clk_path1->clkInfo(this)->clkSrc() if (src_clk_path1->clkInfo(this)->clkSrc()
!= tgt_clk_path1->clkInfo(this)->clkSrc()) { != tgt_clk_path1->clkInfo(this)->clkSrc()) {
// Push src/tgt genclk src paths into a vector, // Push src/tgt genclk src paths into a vector,
// The last genclk src path is at index 0. // The last genclk src path is at index 0.
genClkSrcPaths(src_clk_path1, src_gclk_paths); ConstPathSeq src_gclk_paths = genClkSrcPaths(src_clk_path1);
genClkSrcPaths(tgt_clk_path1, tgt_gclk_paths); ConstPathSeq tgt_gclk_paths = genClkSrcPaths(tgt_clk_path1);
// Search from the first gen clk toward the end // Search from the first gen clk toward the end
// of the path to find a common root pin. // of the path to find a common root pin.
int i = src_gclk_paths.size() - 1; int i = src_gclk_paths.size() - 1;
int j = tgt_gclk_paths.size() - 1; int j = tgt_gclk_paths.size() - 1;
for (; i >= 0 && j >= 0; i--, j--) { for (; i >= 0 && j >= 0; i--, j--) {
PathVertex &src_path = src_gclk_paths[i]; const Path *src_path = src_gclk_paths[i];
PathVertex &tgt_path = tgt_gclk_paths[j]; const Path *tgt_path = tgt_gclk_paths[j];
if (src_path.clkInfo(this)->clkSrc() if (src_path->clkInfo(this)->clkSrc()
== tgt_path.clkInfo(this)->clkSrc()) { == tgt_path->clkInfo(this)->clkSrc()) {
src_clk_path1 = &src_gclk_paths[i]; src_clk_path1 = src_gclk_paths[i];
tgt_clk_path1 = &tgt_gclk_paths[j]; tgt_clk_path1 = tgt_gclk_paths[j];
} }
else else
break; break;
} }
} }
const PathVertex *src_clk_path2 = src_clk_path1; const Path *src_clk_path2 = src_clk_path1;
const PathVertex *tgt_clk_path2 = tgt_clk_path1; const Path *tgt_clk_path2 = tgt_clk_path1;
PathVertex src_prev, tgt_prev; // src_clk_path2 and tgt_clk_path2 are now in the same (gen)clk src path.
// src_clk_path and tgt_clk_path are now in the same (gen)clk src path.
// Use the vertex levels to back up the deeper path to see if they // Use the vertex levels to back up the deeper path to see if they
// overlap. // overlap.
int src_level = src_clk_path2->vertex(this)->level(); int src_level = src_clk_path2->vertex(this)->level();
@ -268,21 +219,19 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path,
while (src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) { while (src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) {
int level_diff = src_level - tgt_level; int level_diff = src_level - tgt_level;
if (level_diff >= 0) { if (level_diff >= 0) {
clkPathPrev(src_clk_path2, src_prev); src_clk_path2 = src_clk_path2->prevPath();
if (src_prev.isNull()) if (src_clk_path2 == nullptr)
break; break;
src_clk_path2 = &src_prev;
src_level = src_clk_path2->vertex(this)->level(); src_level = src_clk_path2->vertex(this)->level();
} }
if (level_diff <= 0) { if (level_diff <= 0) {
clkPathPrev(tgt_clk_path2, tgt_prev); tgt_clk_path2 = tgt_clk_path2->prevPath();
if (tgt_prev.isNull()) if (tgt_clk_path2 == nullptr)
break; break;
tgt_clk_path2 = &tgt_prev;
tgt_level = tgt_clk_path2->vertex(this)->level(); tgt_level = tgt_clk_path2->vertex(this)->level();
} }
} }
if (!src_clk_path2->isNull() && !tgt_clk_path2->isNull() if (src_clk_path2 && tgt_clk_path2
&& (src_clk_path2->transition(this) == tgt_clk_path2->transition(this) && (src_clk_path2->transition(this) == tgt_clk_path2->transition(this)
|| same_pin)) { || same_pin)) {
debugPrint(debug_, "crpr", 2, "crpr pin %s", debugPrint(debug_, "crpr", 2, "crpr pin %s",
@ -292,30 +241,31 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path,
} }
} }
void ConstPathSeq
CheckCrpr::genClkSrcPaths(const PathVertex *path, CheckCrpr::genClkSrcPaths(const Path *path)
PathVertexSeq &gclk_paths)
{ {
ConstPathSeq gclk_paths;
ClkInfo *clk_info = path->clkInfo(this); ClkInfo *clk_info = path->clkInfo(this);
const ClockEdge *clk_edge = clk_info->clkEdge(); const ClockEdge *clk_edge = clk_info->clkEdge();
const Pin *clk_src = clk_info->clkSrc(); const Pin *clk_src = clk_info->clkSrc();
PathAnalysisPt *path_ap = path->pathAnalysisPt(this); PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
gclk_paths.push_back(path); gclk_paths.push_back(path);
Genclks *genclks = search_->genclks();
while (clk_edge->clock()->isGenerated()) { while (clk_edge->clock()->isGenerated()) {
PathVertex genclk_path = Path *genclk_path = genclks->srcPath(clk_edge, clk_src, path_ap);
search_->genclks()->srcPath(clk_edge, clk_src, path_ap); if (genclk_path == nullptr)
if (genclk_path.isNull())
break; break;
clk_info = genclk_path.clkInfo(this); clk_info = genclk_path->clkInfo(this);
clk_src = clk_info->clkSrc(); clk_src = clk_info->clkSrc();
clk_edge = clk_info->clkEdge(); clk_edge = clk_info->clkEdge();
gclk_paths.push_back(genclk_path); gclk_paths.push_back(genclk_path);
} }
return gclk_paths;
} }
Crpr Crpr
CheckCrpr::findCrpr1(const PathVertex *src_clk_path, CheckCrpr::findCrpr1(const Path *src_clk_path,
const PathVertex *tgt_clk_path) const Path *tgt_clk_path)
{ {
if (pocv_enabled_) { if (pocv_enabled_) {
// Remove variation on the common path. // Remove variation on the common path.
@ -323,8 +273,8 @@ CheckCrpr::findCrpr1(const PathVertex *src_clk_path,
// sigma of the common clock path. // sigma of the common clock path.
const EarlyLate *src_el = src_clk_path->minMax(this); const EarlyLate *src_el = src_clk_path->minMax(this);
const EarlyLate *tgt_el = tgt_clk_path->minMax(this); const EarlyLate *tgt_el = tgt_clk_path->minMax(this);
Arrival src_arrival = src_clk_path->arrival(this); Arrival src_arrival = src_clk_path->arrival();
Arrival tgt_arrival = tgt_clk_path->arrival(this); Arrival tgt_arrival = tgt_clk_path->arrival();
float src_clk_time = src_clk_path->clkEdge(this)->time(); float src_clk_time = src_clk_path->clkEdge(this)->time();
float tgt_clk_time = tgt_clk_path->clkEdge(this)->time(); float tgt_clk_time = tgt_clk_path->clkEdge(this)->time();
float crpr_mean = abs(delayAsFloat(src_arrival) - src_clk_time float crpr_mean = abs(delayAsFloat(src_arrival) - src_clk_time
@ -352,10 +302,10 @@ CheckCrpr::findCrpr1(const PathVertex *src_clk_path,
} }
float float
CheckCrpr::crprArrivalDiff(const PathVertex *path) CheckCrpr::crprArrivalDiff(const Path *path)
{ {
Arrival other_arrival = otherMinMaxArrival(path); Arrival other_arrival = otherMinMaxArrival(path);
float crpr_diff = abs(delayAsFloat(path->arrival(this)) float crpr_diff = abs(delayAsFloat(path->arrival())
- delayAsFloat(other_arrival)); - delayAsFloat(other_arrival));
return crpr_diff; return crpr_diff;
} }
@ -407,13 +357,12 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path,
&& tgt_clk->isGenerated() && tgt_clk->isGenerated()
&& tgt_clk->isPropagated() && tgt_clk->isPropagated()
&& crprPossible(src_clk, tgt_clk)) { && crprPossible(src_clk, tgt_clk)) {
PathVertex tgt_genclk_path; Path *tgt_genclk_path = portClkPath(tgt_clk_edge,
portClkPath(tgt_clk_edge, tgt_clk_edge->clock()->defaultPin(), tgt_path_ap, tgt_clk_edge->clock()->defaultPin(),
tgt_genclk_path); tgt_path_ap);
PathVertex src_clk_path(src_path->clkInfo(this)->crprClkPath(), this); Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this);
if (!src_clk_path.isNull()) { if (src_clk_path)
findCrpr(&src_clk_path, &tgt_genclk_path, same_pin, crpr, crpr_pin); findCrpr(src_clk_path, tgt_genclk_path, same_pin, crpr, crpr_pin);
}
} }
} }

View File

@ -42,9 +42,9 @@ public:
Arrival maxCrpr(ClkInfo *clk_info); Arrival maxCrpr(ClkInfo *clk_info);
// Timing check CRPR. // Timing check CRPR.
Crpr checkCrpr(const Path *src_clk_path, Crpr checkCrpr(const Path *src_clk_path,
const PathVertex *tgt_clk_path); const Path *tgt_clk_path);
void checkCrpr(const Path *src_path, void checkCrpr(const Path *src_path,
const PathVertex *tgt_clk_path, const Path *tgt_clk_path,
// Return values. // Return values.
Crpr &crpr, Crpr &crpr,
Pin *&crpr_pin); Pin *&crpr_pin);
@ -57,18 +57,12 @@ public:
Crpr &crpr, Crpr &crpr,
Pin *&crpr_pin); Pin *&crpr_pin);
// Previous clk path when crpr is enabled.
PathVertex clkPathPrev(const PathVertex *path);
// For Search::reportArrivals.
PathVertex clkPathPrev(Vertex *vertex,
int arrival_index);
private: private:
void clkPathPrev(const PathVertex *path, void clkPathPrev(const Path *path,
PathVertex &prev); Path &prev);
Arrival otherMinMaxArrival(const PathVertex *path); Arrival otherMinMaxArrival(const Path *path);
void checkCrpr1(const Path *src_path, void checkCrpr1(const Path *src_path,
const PathVertex *tgt_clk_path, const Path *tgt_clk_path,
bool same_pin, bool same_pin,
// Return values. // Return values.
Crpr &crpr, Crpr &crpr,
@ -82,22 +76,19 @@ private:
Pin *&crpr_pin); Pin *&crpr_pin);
bool crprPossible(const Clock *clk1, bool crprPossible(const Clock *clk1,
const Clock *clk2); const Clock *clk2);
void genClkSrcPaths(const PathVertex *path, ConstPathSeq genClkSrcPaths(const Path *path);
PathVertexSeq &gclk_paths); void findCrpr(const Path *src_clk_path,
void findCrpr(const PathVertex *src_clk_path, const Path *tgt_clk_path,
const PathVertex *tgt_clk_path,
bool same_pin, bool same_pin,
// Return values. // Return values.
Crpr &crpr, Crpr &crpr,
Pin *&common_pin); Pin *&common_pin);
void portClkPath(const ClockEdge *clk_edge, Path *portClkPath(const ClockEdge *clk_edge,
const Pin *clk_src_pin, const Pin *clk_src_pin,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap);
// Return value. Crpr findCrpr1(const Path *src_clk_path,
PathVertex &port_clk_path); const Path *tgt_clk_path);
Crpr findCrpr1(const PathVertex *src_clk_path, float crprArrivalDiff(const Path *path);
const PathVertex *tgt_clk_path);
float crprArrivalDiff(const PathVertex *path);
}; };
} // namespace } // namespace

View File

@ -40,7 +40,7 @@
#include "Corner.hh" #include "Corner.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "Levelize.hh" #include "Levelize.hh"
#include "PathVertexPtr.hh" #include "Path.hh"
#include "Search.hh" #include "Search.hh"
namespace sta { namespace sta {
@ -137,7 +137,7 @@ Genclks::fanins(const Clock *clk)
} }
Vertex * Vertex *
Genclks::srcPathVertex(const Pin *pin) const Genclks::srcPath(const Pin *pin) const
{ {
bool is_bidirect = network_->direction(pin)->isBidirect(); bool is_bidirect = network_->direction(pin)->isBidirect();
// Insertion delay is to the driver vertex for clks defined on // Insertion delay is to the driver vertex for clks defined on
@ -155,7 +155,7 @@ Genclks::clkPinMaxLevel(const Clock *clk) const
{ {
Level max_level = 0; Level max_level = 0;
for (const Pin *pin : clk->leafPins()) { for (const Pin *pin : clk->leafPins()) {
Vertex *vertex = srcPathVertex(pin); Vertex *vertex = srcPath(pin);
max_level = max(max_level, vertex->level()); max_level = max(max_level, vertex->level());
} }
return max_level; return max_level;
@ -209,9 +209,7 @@ Genclks::ensureInsertionDelays()
// insertion delay, so sort the clocks by source pin level. // insertion delay, so sort the clocks by source pin level.
sort(gclks, ClockPinMaxLevelLess(this)); sort(gclks, ClockPinMaxLevelLess(this));
ClockSeq::Iterator gclk_iter(gclks); for (Clock *gclk : gclks) {
while (gclk_iter.hasNext()) {
Clock *gclk = gclk_iter.next();
if (gclk->masterClk()) { if (gclk->masterClk()) {
findInsertionDelays(gclk); findInsertionDelays(gclk);
recordSrcPaths(gclk); recordSrcPaths(gclk);
@ -546,7 +544,7 @@ Genclks::makeGenclkInfo(Clock *gclk)
VertexSet *fanins = new VertexSet(graph_); VertexSet *fanins = new VertexSet(graph_);
findFanin(gclk, fanins); findFanin(gclk, fanins);
GenclkInfo *genclk_info = new GenclkInfo(gclk, gclk_level, fanins, GenclkInfo *genclk_info = new GenclkInfo(gclk, gclk_level, fanins,
src_filter); src_filter);
genclk_info_map_.insert(gclk, genclk_info); genclk_info_map_.insert(gclk, genclk_info);
return genclk_info; return genclk_info;
} }
@ -684,12 +682,12 @@ Genclks::seedSrcPins(Clock *gclk,
for (auto path_ap : corners_->pathAnalysisPts()) { for (auto path_ap : corners_->pathAnalysisPts()) {
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
const EarlyLate *early_late = min_max; const EarlyLate *early_late = min_max;
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
Tag *tag = makeTag(gclk, master_clk, master_pin, rf, src_filter, Tag *tag = makeTag(gclk, master_clk, master_pin, rf,
path_ap); src_filter, path_ap);
Arrival insert = search_->clockInsertion(master_clk, master_pin, rf, Arrival insert = search_->clockInsertion(master_clk, master_pin, rf,
min_max, early_late, path_ap); min_max, early_late, path_ap);
tag_bldr.setArrival(tag, insert, nullptr); tag_bldr.setArrival(tag, insert);
} }
} }
search_->setVertexArrivals(vertex, &tag_bldr); search_->setVertexArrivals(vertex, &tag_bldr);
@ -854,22 +852,14 @@ void
Genclks::copyGenClkSrcPaths(Vertex *vertex, Genclks::copyGenClkSrcPaths(Vertex *vertex,
TagGroupBldr *tag_bldr) TagGroupBldr *tag_bldr)
{ {
Arrival *arrivals = graph_->arrivals(vertex); Path *paths = graph_->paths(vertex);
if (arrivals) { if (paths) {
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()); for (auto const [tag, path_index] : *tag_group->pathIndexMap()) {
while (arrival_iter.hasNext()) {
Tag *tag;
int arrival_index;
arrival_iter.next(tag, arrival_index);
if (tag->isGenClkSrcPath()) { if (tag->isGenClkSrcPath()) {
Arrival arrival = arrivals[arrival_index]; Path &path = paths[path_index];
PathPrev *prev_path = prev_paths tag_bldr->insertPath(path);
? &prev_paths[arrival_index]
: nullptr;
tag_bldr->setArrival(tag, arrival, prev_path);
} }
} }
} }
@ -881,11 +871,14 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex,
void void
Genclks::clearSrcPaths() Genclks::clearSrcPaths()
{ {
genclk_src_paths_.deleteArrayContents(); for (auto const & [clk_pin, src_paths] : genclk_src_paths_) {
for (const Path &src_path : src_paths)
delete src_path.prevPath();
}
genclk_src_paths_.clear(); genclk_src_paths_.clear();
} }
int size_t
Genclks::srcPathIndex(const RiseFall *clk_rf, Genclks::srcPathIndex(const RiseFall *clk_rf,
const PathAnalysisPt *path_ap) const const PathAnalysisPt *path_ap) const
{ {
@ -903,14 +896,13 @@ 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()) {
PathVertexPtr *src_paths = new PathVertexPtr[path_count]; vector<Path> &src_paths = genclk_src_paths_[ClockPinPair(gclk, gclk_pin)];
genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths); src_paths.resize(path_count);
Vertex *gclk_vertex = srcPath(gclk_pin);
Vertex *gclk_vertex = srcPathVertex(gclk_pin);
bool found_src_paths = false; bool found_src_paths = false;
VertexPathIterator path_iter(gclk_vertex, this); VertexPathIterator path_iter(gclk_vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
const ClockEdge *src_clk_edge = path->clkEdge(this); const ClockEdge *src_clk_edge = path->clkEdge(this);
if (src_clk_edge if (src_clk_edge
&& matchesSrcFilter(path, gclk)) { && matchesSrcFilter(path, gclk)) {
@ -919,24 +911,34 @@ Genclks::recordSrcPaths(Clock *gclk)
const RiseFall *rf = path->transition(this); const RiseFall *rf = path->transition(this);
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); size_t path_index = srcPathIndex(rf, path_ap);
PathVertexPtr &src_path = src_paths[path_index]; Path &src_path = src_paths[path_index];
if ((!divide_by_1 if ((!divide_by_1
|| (inverting_path == invert)) || (inverting_path == invert))
&& (!has_edges && (!has_edges
|| src_clk_rf == gclk->masterClkEdgeTr(rf)) || src_clk_rf == gclk->masterClkEdgeTr(rf))
&& (src_path.isNull() && (src_path.isNull()
|| delayGreater(path->arrival(this), || delayGreater(path->arrival(),
src_path.arrival(this), src_path.arrival(),
early_late, early_late,
this))) { this))) {
debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s", debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s",
network_->pathName(gclk_pin), network_->pathName(gclk_pin),
early_late->asString(), early_late->asString(),
rf->asString(), rf->asString(),
delayAsString(path->arrival(this), this)); delayAsString(path->arrival(), this));
src_path.init(path, this); delete src_path.prevPath();
found_src_paths = true; src_path = *path;
Path *prev_copy = &src_path;
Path *p = path->prevPath();
while (p) {
Path *copy = new Path(p);
copy->setIsEnum(true);
prev_copy->setPrevPath(copy);
prev_copy = copy;
p = p->prevPath();
}
found_src_paths = true;
} }
} }
} }
@ -973,8 +975,8 @@ Genclks::matchesSrcFilter(Path *path,
return false; return false;
} }
PathVertex Path *
Genclks::srcPath(Path *clk_path) const Genclks::srcPath(const Path *clk_path) const
{ {
const Pin *src_pin = clk_path->pin(this); const Pin *src_pin = clk_path->pin(this);
const ClockEdge *clk_edge = clk_path->clkEdge(this); const ClockEdge *clk_edge = clk_path->clkEdge(this);
@ -985,7 +987,7 @@ Genclks::srcPath(Path *clk_path) const
insert_ap); insert_ap);
} }
PathVertex Path *
Genclks::srcPath(const ClockEdge *clk_edge, Genclks::srcPath(const ClockEdge *clk_edge,
const Pin *src_pin, const Pin *src_pin,
const PathAnalysisPt *path_ap) const const PathAnalysisPt *path_ap) const
@ -993,20 +995,52 @@ Genclks::srcPath(const ClockEdge *clk_edge,
return srcPath(clk_edge->clock(), src_pin, clk_edge->transition(), path_ap); return srcPath(clk_edge->clock(), src_pin, clk_edge->transition(), path_ap);
} }
PathVertex Path *
Genclks::srcPath(const Clock *gclk, Genclks::srcPath(const Clock *gclk,
const Pin *src_pin, const Pin *src_pin,
const RiseFall *rf, const RiseFall *rf,
const PathAnalysisPt *path_ap) const const PathAnalysisPt *path_ap) const
{ {
PathVertexPtr *src_paths = auto itr = genclk_src_paths_.find(ClockPinPair(gclk, src_pin));
genclk_src_paths_.findKey(ClockPinPair(gclk, src_pin)); if (itr != genclk_src_paths_.end()) {
if (src_paths) { vector<Path> src_paths = itr->second;
int path_index = srcPathIndex(rf, path_ap); if (!src_paths.empty()) {
return PathVertex(src_paths[path_index], this); size_t path_index = srcPathIndex(rf, path_ap);
Path &src_path = src_paths[path_index];
if (!src_path.isNull()) {
Path *src_vpath = Path::vertexPath(src_path, this);
return src_vpath;
}
}
}
return nullptr;
}
void
Genclks::updateSrcPathPrevs()
{
for (auto const & [clk_pin, src_paths] : genclk_src_paths_) {
for (const Path &src_path : src_paths) {
if (!src_path.isNull()) {
const Path *p = &src_path;
while (p) {
Path *src_vpath = Path::vertexPath(p->vertex(this),
p->tag(this), this);
Path *prev_path = p->prevPath();
if (prev_path) {
Path *prev_vpath = Path::vertexPath(prev_path->vertex(this),
prev_path->tag(this), this);
src_vpath->setPrevPath(prev_vpath);
src_vpath->setPrevEdgeArc(p->prevEdge(this),
p->prevArc(this), this);
}
p = p->prevPath();
}
debugPrint(debug_, "genclk", 3, "repaired src path prev %s",
src_path.name(this));
}
}
} }
else
return PathVertex();
} }
Arrival Arrival
@ -1017,9 +1051,9 @@ Genclks::insertionDelay(const Clock *clk,
const PathAnalysisPt *path_ap) const const PathAnalysisPt *path_ap) const
{ {
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late); PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
PathVertex src_path = srcPath(clk, pin, rf, insert_ap); Path *src_path = srcPath(clk, pin, rf, insert_ap);
if (!src_path.isNull()) if (src_path)
return src_path.arrival(this); return src_path->arrival();
else else
return 0.0; return 0.0;
} }

View File

@ -50,7 +50,7 @@ public:
}; };
typedef Map<Clock*, GenclkInfo*> GenclkInfoMap; typedef Map<Clock*, GenclkInfo*> GenclkInfoMap;
typedef Map<ClockPinPair, PathVertexPtr*, ClockPinPairLess> GenclkSrcPathMap; typedef Map<ClockPinPair, vector<Path>, ClockPinPairLess> GenclkSrcPathMap;
class Genclks : public StaState class Genclks : public StaState
{ {
@ -71,19 +71,20 @@ public:
const EarlyLate *early_late, const EarlyLate *early_late,
const PathAnalysisPt *path_ap) const; const PathAnalysisPt *path_ap) const;
// Generated clock source path for a clock path root. // Generated clock source path for a clock path root.
PathVertex srcPath(Path *clk_path) const; Path *srcPath(const Path *clk_path) const;
// Generated clock source path. // Generated clock source path.
PathVertex srcPath(const ClockEdge *clk_edge, Path *srcPath(const ClockEdge *clk_edge,
const Pin *src_pin, const Pin *src_pin,
const PathAnalysisPt *path_ap) const; const PathAnalysisPt *path_ap) const;
PathVertex srcPath(const Clock *clk, Path *srcPath(const Clock *clk,
const Pin *src_pin, const Pin *src_pin,
const RiseFall *rf, const RiseFall *rf,
const PathAnalysisPt *path_ap) const; const PathAnalysisPt *path_ap) const;
Vertex *srcPathVertex(const Pin *pin) const; Vertex *srcPath(const Pin *pin) const;
Level clkPinMaxLevel(const Clock *clk) const; Level clkPinMaxLevel(const Clock *clk) const;
void copyGenClkSrcPaths(Vertex *vertex, void copyGenClkSrcPaths(Vertex *vertex,
TagGroupBldr *tag_bldr); TagGroupBldr *tag_bldr);
void updateSrcPathPrevs();
private: private:
void findInsertionDelays(); void findInsertionDelays();
@ -94,8 +95,8 @@ private:
void seedClkVertices(Clock *clk, void seedClkVertices(Clock *clk,
BfsBkwdIterator &iter, BfsBkwdIterator &iter,
VertexSet *fanins); VertexSet *fanins);
int srcPathIndex(const RiseFall *clk_rf, size_t srcPathIndex(const RiseFall *clk_rf,
const PathAnalysisPt *path_ap) const; const PathAnalysisPt *path_ap) const;
bool matchesSrcFilter(Path *path, bool matchesSrcFilter(Path *path,
const Clock *gclk) const; const Clock *gclk) const;
void seedSrcPins(Clock *gclk, void seedSrcPins(Clock *gclk,
@ -129,7 +130,6 @@ private:
VertexSet &visited_vertices, VertexSet &visited_vertices,
EdgeSet *&fdbk_edges); EdgeSet *&fdbk_edges);
bool found_insertion_delays_; bool found_insertion_delays_;
GenclkSrcPathMap genclk_src_paths_; GenclkSrcPathMap genclk_src_paths_;
GenclkInfoMap genclk_info_map_; GenclkInfoMap genclk_info_map_;

View File

@ -49,8 +49,8 @@ Latches::Latches(StaState *sta) :
void void
Latches::latchRequired(const Path *data_path, Latches::latchRequired(const Path *data_path,
const PathVertex *enable_path, const Path *enable_path,
const PathVertex *disable_path, const Path *disable_path,
const MultiCyclePath *mcp, const MultiCyclePath *mcp,
const PathDelay *path_delay, const PathDelay *path_delay,
Arrival src_clk_latency, Arrival src_clk_latency,
@ -61,7 +61,7 @@ Latches::latchRequired(const Path *data_path,
Arrival &adjusted_data_arrival, Arrival &adjusted_data_arrival,
Delay &time_given_to_startpoint) const Delay &time_given_to_startpoint) const
{ {
const Arrival data_arrival = data_path->arrival(this); const Arrival data_arrival = data_path->arrival();
float max_delay = 0.0; float max_delay = 0.0;
bool ignore_clk_latency = false; bool ignore_clk_latency = false;
if (path_delay) { if (path_delay) {
@ -149,8 +149,8 @@ Latches::latchRequired(const Path *data_path,
void void
Latches::latchBorrowInfo(const Path *data_path, Latches::latchBorrowInfo(const Path *data_path,
const PathVertex *enable_path, const Path *enable_path,
const PathVertex *disable_path, const Path *disable_path,
const ArcDelay &margin, const ArcDelay &margin,
bool ignore_clk_latency, bool ignore_clk_latency,
// Return values. // Return values.
@ -213,8 +213,8 @@ Latches::latchBorrowInfo(const Path *data_path,
void void
Latches::latchRequired(const Path *data_path, Latches::latchRequired(const Path *data_path,
const PathVertex *enable_path, const Path *enable_path,
const PathVertex *disable_path, const Path *disable_path,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
// Return values. // Return values.
Required &required, Required &required,
@ -243,11 +243,9 @@ Latches::latchRequired(const Path *data_path,
} }
// Find the latch enable open/close path from the close/open path. // Find the latch enable open/close path from the close/open path.
void Path *
Latches::latchEnableOtherPath(const Path *path, Latches::latchEnableOtherPath(const Path *path,
const PathAnalysisPt *tgt_clk_path_ap, const PathAnalysisPt *tgt_clk_path_ap) const
// Return value.
PathVertex &other_path) const
{ {
Vertex *vertex = path->vertex(this); Vertex *vertex = path->vertex(this);
const ClockEdge *clk_edge = path->clkEdge(this); const ClockEdge *clk_edge = path->clkEdge(this);
@ -256,20 +254,18 @@ Latches::latchEnableOtherPath(const Path *path,
RiseFall *other_rf = path->transition(this)->opposite(); RiseFall *other_rf = path->transition(this)->opposite();
VertexPathIterator path_iter(vertex, other_rf, tgt_clk_path_ap, this); VertexPathIterator path_iter(vertex, other_rf, tgt_clk_path_ap, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
if (path->isClock(this) if (path->isClock(this)
&& path->clkEdge(this) == other_clk_edge) { && path->clkEdge(this) == other_clk_edge) {
other_path = path; return path;
break;
} }
} }
return nullptr;
} }
void Path *
Latches::latchEnablePath(const Path *q_path, Latches::latchEnablePath(const Path *q_path,
const Edge *d_q_edge, const Edge *d_q_edge) const
// Return value.
PathVertex &enable_path) const
{ {
const ClockEdge *en_clk_edge = q_path->clkEdge(this); const ClockEdge *en_clk_edge = q_path->clkEdge(this);
@ -283,15 +279,15 @@ Latches::latchEnablePath(const Path *q_path,
if (state == LatchEnableState::enabled) { if (state == LatchEnableState::enabled) {
VertexPathIterator path_iter(en_vertex, en_rf, tgt_clk_path_ap, this); VertexPathIterator path_iter(en_vertex, en_rf, tgt_clk_path_ap, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
const ClockEdge *clk_edge = path->clkEdge(this); const ClockEdge *clk_edge = path->clkEdge(this);
if (path->isClock(this) if (path->isClock(this)
&& clk_edge == en_clk_edge) { && clk_edge == en_clk_edge) {
enable_path = path; return path;
break;
} }
} }
} }
return nullptr;
} }
// The arrival time for a latch D->Q edge is clipped to the window of // The arrival time for a latch D->Q edge is clipped to the window of
@ -324,7 +320,7 @@ Latches::latchOutArrival(const Path *data_path,
if (!(excpt && excpt->isFalse())) { if (!(excpt && excpt->isFalse())) {
arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge, arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge,
false, path_ap); false, path_ap);
q_arrival = data_path->arrival(this) + arc_delay; q_arrival = data_path->arrival() + arc_delay;
q_tag = data_path->tag(this); q_tag = data_path->tag(this);
} }
} }
@ -334,7 +330,7 @@ Latches::latchOutArrival(const Path *data_path,
VertexPathIterator enable_iter(enable_vertex, enable_rf, VertexPathIterator enable_iter(enable_vertex, enable_rf,
tgt_clk_path_ap, this); tgt_clk_path_ap, this);
while (enable_iter.hasNext()) { while (enable_iter.hasNext()) {
PathVertex *enable_path = enable_iter.next(); Path *enable_path = enable_iter.next();
ClkInfo *en_clk_info = enable_path->clkInfo(this); ClkInfo *en_clk_info = enable_path->clkInfo(this);
const ClockEdge *en_clk_edge = en_clk_info->clkEdge(); const ClockEdge *en_clk_edge = en_clk_info->clkEdge();
if (enable_path->isClock(this)) { if (enable_path->isClock(this)) {
@ -342,12 +338,11 @@ Latches::latchOutArrival(const Path *data_path,
// D->Q is disabled when if there is a path delay -to D or EN clk. // D->Q is disabled when if there is a path delay -to D or EN clk.
if (!(excpt && (excpt->isFalse() if (!(excpt && (excpt->isFalse()
|| excpt->isPathDelay()))) { || excpt->isPathDelay()))) {
PathVertex disable_path; Path *disable_path = latchEnableOtherPath(enable_path, tgt_clk_path_ap);
latchEnableOtherPath(enable_path, tgt_clk_path_ap, disable_path);
Delay borrow, time_given_to_startpoint; Delay borrow, time_given_to_startpoint;
Arrival adjusted_data_arrival; Arrival adjusted_data_arrival;
Required required; Required required;
latchRequired(data_path, enable_path, &disable_path, path_ap, latchRequired(data_path, enable_path, disable_path, path_ap,
required, borrow, adjusted_data_arrival, required, borrow, adjusted_data_arrival,
time_given_to_startpoint); time_given_to_startpoint);
if (delayGreater(borrow, 0.0, this)) { if (delayGreater(borrow, 0.0, this)) {
@ -357,7 +352,7 @@ Latches::latchOutArrival(const Path *data_path,
q_arrival = adjusted_data_arrival + arc_delay; q_arrival = adjusted_data_arrival + arc_delay;
// Tag switcheroo - data passing thru gets latch enable tag. // Tag switcheroo - data passing thru gets latch enable tag.
// States and path ap come from Q, everything else from enable. // States and path ap come from Q, everything else from enable.
PathVertex *crpr_clk_path = Path *crpr_clk_path =
sdc_->crprActive() ? enable_path : nullptr; sdc_->crprActive() ? enable_path : nullptr;
ClkInfo *q_clk_info = ClkInfo *q_clk_info =
search_->findClkInfo(en_clk_edge, search_->findClkInfo(en_clk_edge,
@ -448,24 +443,23 @@ Latches::latchTimeGivenToStartpoint(const Path *d_path,
const Edge *d_q_edge, const Edge *d_q_edge,
// Return values. // Return values.
Arrival &time_given, Arrival &time_given,
PathVertex &enable_path) const Path *&enable_path) const
{ {
latchEnablePath(q_path, d_q_edge, enable_path); enable_path = latchEnablePath(q_path, d_q_edge);
if (!enable_path.isNull() if (enable_path
&& enable_path.isClock(this)) { && enable_path->isClock(this)) {
const PathAnalysisPt *path_ap = q_path->pathAnalysisPt(this); const PathAnalysisPt *path_ap = q_path->pathAnalysisPt(this);
const PathAnalysisPt *tgt_clk_path_ap = path_ap->tgtClkAnalysisPt(); const PathAnalysisPt *tgt_clk_path_ap = path_ap->tgtClkAnalysisPt();
PathVertex disable_path; Path *disable_path = latchEnableOtherPath(enable_path, tgt_clk_path_ap);
latchEnableOtherPath(enable_path.path(), tgt_clk_path_ap, disable_path);
Delay borrow; Delay borrow;
Required required; Required required;
Arrival adjusted_data_arrival; Arrival adjusted_data_arrival;
latchRequired(d_path, &enable_path, &disable_path, path_ap, latchRequired(d_path, enable_path, disable_path, path_ap,
required, borrow, adjusted_data_arrival, time_given); required, borrow, adjusted_data_arrival, time_given);
} }
else { else {
time_given = 0.0; time_given = 0.0;
enable_path.init(); enable_path = nullptr;
} }
} }
@ -517,7 +511,7 @@ Latches::latchDtoQEnable(const Edge *d_q_edge,
} }
LatchEnableState LatchEnableState
Latches::latchDtoQState(Edge *edge) const Latches::latchDtoQState(const Edge *edge) const
{ {
const Vertex *from_vertex = edge->from(graph_); const Vertex *from_vertex = edge->from(graph_);
const Pin *from_pin = from_vertex->pin(); const Pin *from_pin = from_vertex->pin();
@ -532,7 +526,7 @@ Latches::latchDtoQState(Edge *edge) const
// Latch D->Q arc looks combinational when the enable pin is disabled // Latch D->Q arc looks combinational when the enable pin is disabled
// or constant. // or constant.
bool bool
Latches::isLatchDtoQ(Edge *edge) const Latches::isLatchDtoQ(const Edge *edge) const
{ {
return edge->role() == TimingRole::latchDtoQ() return edge->role() == TimingRole::latchDtoQ()
&& latchDtoQState(edge) == LatchEnableState::enabled; && latchDtoQState(edge) == LatchEnableState::enabled;

View File

@ -43,10 +43,10 @@ public:
const Edge *d_q_edge, const Edge *d_q_edge,
// Return values. // Return values.
Arrival &time_given, Arrival &time_given,
PathVertex &enable_path) const; Path *&enable_path) const;
void latchRequired(const Path *data_path, void latchRequired(const Path *data_path,
const PathVertex *enable_path, const Path *enable_path,
const PathVertex *disable_path, const Path *disable_path,
const MultiCyclePath *mcp, const MultiCyclePath *mcp,
const PathDelay *path_delay, const PathDelay *path_delay,
Arrival src_clk_latency, Arrival src_clk_latency,
@ -57,8 +57,8 @@ public:
Arrival &adjusted_data_arrival, Arrival &adjusted_data_arrival,
Delay &time_given_to_startpoint) const; Delay &time_given_to_startpoint) const;
void latchRequired(const Path *data_path, void latchRequired(const Path *data_path,
const PathVertex *enable_path, const Path *enable_path,
const PathVertex *disable_path, const Path *disable_path,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
// Return values. // Return values.
Required &required, Required &required,
@ -66,8 +66,8 @@ public:
Arrival &adjusted_data_arrival, Arrival &adjusted_data_arrival,
Delay &time_given_to_startpoint) const; Delay &time_given_to_startpoint) const;
void latchBorrowInfo(const Path *data_path, void latchBorrowInfo(const Path *data_path,
const PathVertex *enable_path, const Path *enable_path,
const PathVertex *disable_path, const Path *disable_path,
const ArcDelay &margin, const ArcDelay &margin,
bool ignore_clk_latency, bool ignore_clk_latency,
// Return values. // Return values.
@ -79,7 +79,7 @@ public:
Crpr &crpr_diff, Crpr &crpr_diff,
Delay &max_borrow, Delay &max_borrow,
bool &borrow_limit_exists) const; bool &borrow_limit_exists) const;
bool isLatchDtoQ(Edge *edge) const; bool isLatchDtoQ(const Edge *edge) const;
// Find the latch EN->Q edge for a D->Q edge. // Find the latch EN->Q edge for a D->Q edge.
void latchDtoQEnable(const Edge *d_q_edge, void latchDtoQEnable(const Edge *d_q_edge,
const Instance *inst, const Instance *inst,
@ -87,15 +87,11 @@ public:
Vertex *&enable_vertex, Vertex *&enable_vertex,
const RiseFall *&enable_rf, const RiseFall *&enable_rf,
LatchEnableState &state) const; LatchEnableState &state) const;
LatchEnableState latchDtoQState(Edge *d_q_edge) const; LatchEnableState latchDtoQState(const Edge *d_q_edge) const;
void latchEnableOtherPath(const Path *path, Path *latchEnableOtherPath(const Path *path,
const PathAnalysisPt *tgt_clk_path_ap, const PathAnalysisPt *tgt_clk_path_ap) const;
// Return value. Path *latchEnablePath(const Path *q_path,
PathVertex &other_path) const; const Edge *d_q_edge) const;
void latchEnablePath(const Path *q_path,
const Edge *d_q_edge,
// Return value.
PathVertex &enable_path) const;
void latchOutArrival(const Path *data_path, void latchOutArrival(const Path *data_path,
const TimingArc *d_q_arc, const TimingArc *d_q_arc,
const Edge *d_q_edge, const Edge *d_q_edge,

View File

@ -280,7 +280,7 @@ MakeEndTimingArcs::visit(PathEnd *path_end)
Network *network = sta_->network(); Network *network = sta_->network();
Debug *debug = sta_->debug(); Debug *debug = sta_->debug();
const MinMax *min_max = path_end->minMax(sta_); const MinMax *min_max = path_end->minMax(sta_);
Arrival data_delay = src_path->arrival(sta_); Arrival data_delay = src_path->arrival();
Delay clk_latency = path_end->targetClkDelay(sta_); Delay clk_latency = path_end->targetClkDelay(sta_);
ArcDelay check_margin = path_end->margin(sta_); ArcDelay check_margin = path_end->margin(sta_);
Delay margin = min_max == MinMax::max() Delay margin = min_max == MinMax::max()
@ -377,11 +377,11 @@ MakeTimingModel::findOutputDelays(const RiseFall *input_rf,
Vertex *output_vertex = graph_->pinLoadVertex(output_pin); Vertex *output_vertex = graph_->pinLoadVertex(output_pin);
VertexPathIterator path_iter(output_vertex, this); VertexPathIterator path_iter(output_vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
if (search_->matchesFilter(path, nullptr)) { if (search_->matchesFilter(path, nullptr)) {
const RiseFall *output_rf = path->transition(sta_); const RiseFall *output_rf = path->transition(sta_);
const MinMax *min_max = path->minMax(sta_); const MinMax *min_max = path->minMax(sta_);
Arrival delay = path->arrival(sta_); Arrival delay = path->arrival();
OutputDelays &delays = output_pin_delays[output_pin]; OutputDelays &delays = output_pin_delays[output_pin];
delays.delays.mergeValue(output_rf, min_max, delays.delays.mergeValue(output_rf, min_max,
delayAsFloat(delay, min_max, sta_)); delayAsFloat(delay, min_max, sta_));
@ -486,12 +486,12 @@ MakeTimingModel::findClkedOutputPaths()
Vertex *output_vertex = graph_->pinLoadVertex(output_pin); Vertex *output_vertex = graph_->pinLoadVertex(output_pin);
VertexPathIterator path_iter(output_vertex, this); VertexPathIterator path_iter(output_vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
const ClockEdge *clk_edge = path->clkEdge(sta_); const ClockEdge *clk_edge = path->clkEdge(sta_);
if (clk_edge) { if (clk_edge) {
const RiseFall *output_rf = path->transition(sta_); const RiseFall *output_rf = path->transition(sta_);
const MinMax *min_max = path->minMax(sta_); const MinMax *min_max = path->minMax(sta_);
Arrival delay = path->arrival(sta_); Arrival delay = path->arrival();
RiseFallMinMax &delays = clk_delays[clk_edge]; RiseFallMinMax &delays = clk_delays[clk_edge];
delays.mergeValue(output_rf, min_max, delays.mergeValue(output_rf, min_max,
delayAsFloat(delay, min_max, sta_)); delayAsFloat(delay, min_max, sta_));
@ -567,7 +567,7 @@ MakeTimingModel::makeClkTreePaths(LibertyPort *lib_port,
const RiseFall *end_rf = (sense == TimingSense::positive_unate) const RiseFall *end_rf = (sense == TimingSense::positive_unate)
? clk_rf ? clk_rf
: clk_rf->opposite(); : clk_rf->opposite();
PathVertex clk_path; Path clk_path;
Delay insertion, delay, latency; Delay insertion, delay, latency;
float lib_clk_delay; float lib_clk_delay;
bool exists; bool exists;

View File

@ -33,17 +33,180 @@
#include "Corner.hh" #include "Corner.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "Tag.hh" #include "Tag.hh"
#include "PathRef.hh" #include "TagGroup.hh"
#include "Search.hh"
namespace sta { namespace sta {
Path::Path() :
prev_path_(nullptr),
arrival_(0.0),
required_(0.0),
vertex_id_(vertex_id_null),
tag_index_(tag_index_null),
is_enum_(false),
prev_arc_idx_(0)
{
}
Path::Path(Path *path) :
prev_path_(path ? path->prev_path_ : nullptr),
arrival_(path ? path->arrival_ : 0.0),
required_(path ? path->required_ : 0.0),
vertex_id_(path ? path->vertex_id_ : vertex_id_null),
tag_index_(path ? path->tag_index_ : tag_index_null),
is_enum_(path ? path->is_enum_ : false),
prev_arc_idx_(path ? path->prev_arc_idx_ : 0)
{
}
Path::Path(Vertex *vertex,
Tag *tag,
const StaState *sta) :
prev_path_(nullptr),
arrival_(0.0),
required_(0.0),
tag_index_(tag->index()),
is_enum_(false),
prev_arc_idx_(0)
{
const Graph *graph = sta->graph();
vertex_id_ = graph->id(vertex);
}
Path::Path(Vertex *vertex,
Tag *tag,
Arrival arrival,
Path *prev_path,
Edge *prev_edge,
TimingArc *prev_arc,
const StaState *sta) :
prev_path_(prev_path),
arrival_(arrival),
required_(0.0),
tag_index_(tag->index()),
is_enum_(false)
{
const Graph *graph = sta->graph();
if (prev_path) {
prev_edge_id_ = graph->id(prev_edge);
prev_arc_idx_ = prev_arc->index();
}
else {
vertex_id_ = graph->id(vertex);
prev_arc_idx_ = 0;
}
}
Path::Path(Vertex *vertex,
Tag *tag,
Arrival arrival,
Path *prev_path,
Edge *prev_edge,
TimingArc *prev_arc,
bool is_enum,
const StaState *sta) :
prev_path_(prev_path),
arrival_(arrival),
required_(0.0),
tag_index_(tag->index()),
is_enum_(is_enum)
{
const Graph *graph = sta->graph();
if (prev_path) {
prev_edge_id_ = graph->id(prev_edge);
prev_arc_idx_ = prev_arc->index();
}
else {
vertex_id_ = graph->id(vertex);
prev_arc_idx_ = 0;
}
}
Path:: ~Path()
{
if (is_enum_ && prev_path_ && prev_path_->is_enum_)
delete prev_path_;
}
void
Path::init(Vertex *vertex,
Arrival arrival,
const StaState *sta)
{
const Graph *graph = sta->graph();
vertex_id_ = graph->id(vertex);
tag_index_ = tag_index_null,
prev_path_ = nullptr;
prev_arc_idx_ = 0;
arrival_ = arrival;
required_ = 0.0;
is_enum_ = false;
}
void
Path::init(Vertex *vertex,
Tag *tag,
const StaState *sta)
{
const Graph *graph = sta->graph();
vertex_id_ = graph->id(vertex);
tag_index_ = tag->index(),
prev_path_ = nullptr;
prev_arc_idx_ = 0;
arrival_ = 0.0;
required_ = 0.0;
is_enum_ = false;
}
void
Path::init(Vertex *vertex,
Tag *tag,
Arrival arrival,
const StaState *sta)
{
const Graph *graph = sta->graph();
vertex_id_ = graph->id(vertex);
tag_index_ = tag->index(),
prev_path_ = nullptr;
prev_arc_idx_ = 0;
arrival_ = arrival;
required_ = 0.0;
is_enum_ = false;
}
void
Path::init(Vertex *vertex,
Tag *tag,
Arrival arrival,
Path *prev_path,
Edge *prev_edge,
TimingArc *prev_arc,
const StaState *sta)
{
const Graph *graph = sta->graph();
tag_index_ = tag->index(),
prev_path_ = prev_path;
if (prev_path) {
prev_edge_id_ = graph->id(prev_edge);
prev_arc_idx_ = prev_arc->index();
}
else {
vertex_id_ = graph->id(vertex);
prev_arc_idx_ = 0;
}
arrival_ = arrival;
required_ = 0.0;
is_enum_ = false;
}
const char * const char *
Path::name(const StaState *sta) const Path::name(const StaState *sta) const
{ {
const Network *network = sta->network(); const Network *network = sta->network();
Vertex *vertex1 = vertex(sta); Vertex *vertex = this->vertex(sta);
if (vertex1) { if (vertex) {
const char *vertex_name = vertex1->name(network); const char *vertex_name = vertex->name(network);
const char *tr_str = transition(sta)->asString(); const char *tr_str = transition(sta)->asString();
const PathAnalysisPt *path_ap = pathAnalysisPt(sta); const PathAnalysisPt *path_ap = pathAnalysisPt(sta);
int ap_index = path_ap->index(); int ap_index = path_ap->index();
@ -57,16 +220,67 @@ Path::name(const StaState *sta) const
return "NULL"; return "NULL";
} }
bool
Path::isNull() const
{
return vertex_id_ == vertex_id_null;
}
Vertex *
Path::vertex(const StaState *sta) const
{
const Graph *graph = sta->graph();
if (prev_path_) {
const Edge *edge = graph->edge(prev_edge_id_);
return edge->to(graph);
}
else
return graph->vertex(vertex_id_);
}
VertexId
Path::vertexId(const StaState *sta) const
{
const Graph *graph = sta->graph();
if (prev_path_) {
const Edge *edge = graph->edge(prev_edge_id_);
return edge->to();
}
else
return vertex_id_;
}
Pin * Pin *
Path::pin(const StaState *sta) const Path::pin(const StaState *sta) const
{ {
return vertex(sta)->pin(); return vertex(sta)->pin();
} }
TagIndex Tag *
Path::tagIndex(const StaState *sta) const Path::tag(const StaState *sta) const
{ {
return tag(sta)->index(); const Search *search = sta->search();
return search->tag(tag_index_);
}
void
Path::setTag(Tag *tag)
{
tag_index_ = tag->index();
}
TagIndex
Path::tagIndex(const StaState *) const
{
return tag_index_;
}
size_t
Path::pathIndex(const StaState *sta) const
{
Vertex *vertex = this->vertex(sta);
Path *paths = vertex->paths();
return this - paths;
} }
ClkInfo * ClkInfo *
@ -118,80 +332,187 @@ Path::slew(const StaState *sta) const
dcalcAnalysisPt(sta)->index()); dcalcAnalysisPt(sta)->index());
} }
const RiseFall *
Path::transition(const StaState *sta) const
{
return tag(sta)->transition();
}
int int
Path::rfIndex(const StaState *sta) const Path::rfIndex(const StaState *sta) const
{ {
return transition(sta)->index(); return transition(sta)->index();
} }
void PathAnalysisPt *
Path::initArrival(const StaState *sta) Path::pathAnalysisPt(const StaState *sta) const
{ {
setArrival(delayInitValue(minMax(sta)), sta); return tag(sta)->pathAnalysisPt(sta);
}
bool
Path::arrivalIsInitValue(const StaState *sta) const
{
return delayIsInitValue(arrival(sta), minMax(sta));
} }
void void
Path::initRequired(const StaState *sta) Path::setArrival(Arrival arrival)
{ {
setRequired(delayInitValue(minMax(sta)->opposite()), sta); arrival_ = arrival;
} }
bool void
Path::requiredIsInitValue(const StaState *sta) const Path::setRequired(const Required &required)
{ {
return delayIsInitValue(required(sta), minMax(sta)->opposite()); required_ = required;
} }
Slack Slack
Path::slack(const StaState *sta) const Path::slack(const StaState *sta) const
{ {
if (minMax(sta) == MinMax::max()) if (minMax(sta) == MinMax::max())
return required(sta) - arrival(sta); return required_ - arrival_;
else else
return arrival(sta) - required(sta); return arrival_ - required_;
}
Path *
Path::prevPath() const
{
return prev_path_;
} }
void void
Path::prevPath(const StaState *sta, Path::setPrevPath(Path *prev_path)
// Return values.
PathRef &prev_path) const
{ {
TimingArc *prev_arc; prev_path_ = prev_path;
prevPath(sta, prev_path, prev_arc); }
void
Path::clearPrevPath(const StaState *sta)
{
// Preserve vertex ID for path when prev edge is no longer valid.
if (prev_path_) {
const Graph *graph = sta->graph();
const Edge *prev_edge = graph->edge(prev_edge_id_);
vertex_id_ = prev_edge->to();
prev_arc_idx_ = 0;
}
prev_path_ = nullptr;
} }
TimingArc * TimingArc *
Path::prevArc(const StaState *sta) const Path::prevArc(const StaState *sta) const
{ {
PathRef prev_path; if (prev_path_) {
TimingArc *prev_arc; const Graph *graph = sta->graph();
prevPath(sta, prev_path, prev_arc); const Edge *edge = graph->edge(prev_edge_id_);
return prev_arc; TimingArcSet *arc_set = edge->timingArcSet();
return arc_set->findTimingArc(prev_arc_idx_);
}
else
return nullptr;
} }
Edge * Edge *
Path::prevEdge(const TimingArc *prev_arc, Path::prevEdge(const StaState *sta) const
const StaState *sta) const
{ {
if (prev_arc) { if (prev_path_) {
TimingArcSet *arc_set = prev_arc->set(); const Graph *graph = sta->graph();
VertexInEdgeIterator edge_iter(vertex(sta), sta->graph()); return graph->edge(prev_edge_id_);
while (edge_iter.hasNext()) { }
Edge *edge = edge_iter.next(); else
if (edge->timingArcSet() == arc_set) return nullptr;
return edge; }
Vertex *
Path::prevVertex(const StaState *sta) const
{
if (prev_path_) {
const Graph *graph = sta->graph();
return graph->edge(prev_edge_id_)->from(graph);
}
else
return nullptr;
}
void
Path::setPrevEdgeArc(Edge *prev_edge,
TimingArc *prev_arc,
const StaState *sta)
{
if (prev_edge) {
const Graph *graph = sta->graph();
prev_edge_id_ = graph->id(prev_edge);
prev_arc_idx_ = prev_arc->index();
}
else
prev_arc_idx_ = 0;
}
void
Path::checkPrevPaths(const StaState *sta) const
{
const Path *path = this;
while (path) {
path->checkPrevPath(sta);
path = path->prevPath();
}
}
void
Path::checkPrevPath(const StaState *sta) const
{
if (prev_path_ && !prev_path_->isNull()) {
Graph *graph = sta->graph();
Edge *edge = prevEdge(sta);
Vertex *prev_vertex = prev_path_->vertex(sta);
Vertex *prev_edge_vertex = edge->from(graph);
if (prev_vertex != prev_edge_vertex) {
Network *network = sta->network();
sta->report()->reportLine("path %s prev path corrupted %s vs %s.",
name(sta),
prev_vertex->name(network),
prev_edge_vertex->name(network));
} }
} }
}
void
Path::setIsEnum(bool is_enum)
{
is_enum_ = is_enum;
}
////////////////////////////////////////////////////////////////
Path *
Path::vertexPath(const Path &path,
const StaState *sta)
{
if (!path.isNull()) {
Vertex *vertex = path.vertex(sta);
Tag *tag = path.tag(sta);
return vertexPath(vertex, tag, sta);
}
return nullptr; return nullptr;
} }
//////////////////////////////////////////////////////////////// Path *
Path::vertexPath(const Vertex *vertex,
Tag *tag,
const StaState *sta)
{
const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex);
if (tag_group) {
size_t path_index;
bool exists;
tag_group->pathIndex(tag, path_index, exists);
if (exists) {
Path *paths = vertex->paths();
Path &src_vpath = paths[path_index];
if (!src_vpath.isNull())
return &src_vpath;
}
}
return nullptr;
}
int int
Path::cmpPinTrClk(const Path *path1, Path::cmpPinTrClk(const Path *path1,
@ -256,11 +577,9 @@ Path::equal(const Path *path1,
const Path *path2, const Path *path2,
const StaState *sta) const StaState *sta)
{ {
bool path1_null = (path1 == nullptr || path1->isNull()); return (path1 == nullptr && path2 == nullptr)
bool path2_null = (path2 == nullptr || path2->isNull()); || (path1
return (path1_null && path2_null) && path2
|| (!path1_null
&& !path2_null
&& path1->vertexId(sta) == path2->vertexId(sta) && path1->vertexId(sta) == path2->vertexId(sta)
// Tag equal implies transition and path ap equal. // Tag equal implies transition and path ap equal.
&& path1->tagIndex(sta) == path2->tagIndex(sta)); && path1->tagIndex(sta) == path2->tagIndex(sta));
@ -340,27 +659,27 @@ Path::cmpAll(const Path *path1,
const Path *path2, const Path *path2,
const StaState *sta) const StaState *sta)
{ {
PathRef p1(path1); const Path *p1 = path1;
PathRef p2(path2); const Path *p2 = path2;
while (!p1.isNull() while (p1 && p2) {
&& !p2.isNull()) { int cmp = Path::cmp(p1, p2, sta);
int cmp = Path::cmp(&p1, &p2, sta);
if (cmp != 0) if (cmp != 0)
return cmp; return cmp;
TimingArc *prev_arc1, *prev_arc2; TimingArc *prev_arc1 = p1->prevArc(sta);
p1.prevPath(sta, p1, prev_arc1); TimingArc *prev_arc2 = p2->prevArc(sta);
p2.prevPath(sta, p2, prev_arc2); p1 = p1->prevPath();
if (equal(&p1, path1, sta)) p2 = p2->prevPath();
if (equal(p1, path1, sta))
// Equivalent latch loops. // Equivalent latch loops.
return 0; return 0;
if ((prev_arc1 && prev_arc1->role()->isLatchDtoQ()) if ((prev_arc1 && prev_arc1->role()->isLatchDtoQ())
|| (prev_arc2 && prev_arc2->role()->isLatchDtoQ())) || (prev_arc2 && prev_arc2->role()->isLatchDtoQ()))
break; break;
} }
if (p1.isNull() && p2.isNull()) if (p1 == nullptr && p2 == nullptr)
return 0; return 0;
else if (p1.isNull() && !p2.isNull()) else if (p1 == nullptr && p2 != nullptr)
return -1; return -1;
else else
return 1; return 1;
@ -374,4 +693,160 @@ Path::lessAll(const Path *path1,
return cmpAll(path1, path2, sta) < 0; return cmpAll(path1, path2, sta) < 0;
} }
////////////////////////////////////////////////////////////////
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const StaState *sta) :
search_(sta->search()),
//filtered_(false),
rf_(nullptr),
path_ap_(nullptr),
min_max_(nullptr),
paths_(vertex->paths()),
path_count_(0),
//path_index_(0),
next_(nullptr)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext();
}
}
// Iterate over vertex paths with the same transition and
// analysis pt but different but different tags.
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const StaState *sta) :
search_(sta->search()),
//filtered_(true),
rf_(rf),
path_ap_(path_ap),
min_max_(nullptr),
paths_(vertex->paths()),
//path_count_(0),
//path_index_(0),
next_(nullptr)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext();
}
}
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max,
const StaState *sta) :
search_(sta->search()),
//filtered_(true),
rf_(rf),
path_ap_(nullptr),
min_max_(min_max),
paths_(vertex->paths()),
//path_count_(0),
//path_index_(0),
next_(nullptr)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext();
}
}
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const MinMax *min_max,
const StaState *sta) :
search_(sta->search()),
//filtered_(true),
rf_(rf),
path_ap_(path_ap),
min_max_(min_max),
paths_(vertex->paths()),
//path_count_(0),
//path_index_(0),
next_(nullptr)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext();
}
}
VertexPathIterator::~VertexPathIterator()
{
}
bool
VertexPathIterator::hasNext()
{
return next_ != nullptr;
}
#if 0
void
VertexPathIterator::findNext()
{
while (path_index_ < path_count_) {
Path *path = &paths_[path_index_++];
if (filtered_) {
const Tag *tag = path->tag(search_);
if ((rf_ == nullptr
|| tag->rfIndex() == rf_->index())
&& (path_ap_ == nullptr
|| tag->pathAPIndex() == path_ap_->index())
&& (min_max_ == nullptr
|| tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) {
next_ = path;
return;
}
}
else {
next_ = path;
return;
}
}
next_ = nullptr;
}
#endif
void
VertexPathIterator::findNext()
{
while (path_iter_.hasNext()) {
Tag *tag;
size_t path_index;
path_iter_.next(tag, path_index);
if ((rf_ == nullptr
|| tag->rfIndex() == rf_->index())
&& (path_ap_ == nullptr
|| tag->pathAPIndex() == path_ap_->index())
&& (min_max_ == nullptr
|| tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) {
next_ = &paths_[path_index];
return;
}
}
next_ = nullptr;
}
Path *
VertexPathIterator::next()
{
Path *path = next_;
findNext();
return path;
}
} // namespace } // namespace

View File

@ -55,31 +55,32 @@ PathEnd::PathEnd(Path *path) :
PathEnd::~PathEnd() PathEnd::~PathEnd()
{ {
path_.deleteRep(); if (path_->isEnum())
delete path_;
} }
void void
PathEnd::setPath(const Path *path) PathEnd::setPath(Path *path)
{ {
path_.init(path); path_ = path;
} }
Vertex * Vertex *
PathEnd::vertex(const StaState *sta) const PathEnd::vertex(const StaState *sta) const
{ {
return path_.vertex(sta); return path_->vertex(sta);
} }
const MinMax * const MinMax *
PathEnd::minMax(const StaState *sta) const PathEnd::minMax(const StaState *sta) const
{ {
return path_.pathAnalysisPt(sta)->pathMinMax(); return path_->pathAnalysisPt(sta)->pathMinMax();
} }
const EarlyLate * const EarlyLate *
PathEnd::pathEarlyLate(const StaState *sta) const PathEnd::pathEarlyLate(const StaState *sta) const
{ {
return path_.pathAnalysisPt(sta)->pathMinMax(); return path_->pathAnalysisPt(sta)->pathMinMax();
} }
const EarlyLate * const EarlyLate *
@ -91,31 +92,31 @@ PathEnd::clkEarlyLate(const StaState *sta) const
const RiseFall * const RiseFall *
PathEnd::transition(const StaState *sta) const PathEnd::transition(const StaState *sta) const
{ {
return path_.transition(sta); return path_->transition(sta);
} }
PathAPIndex PathAPIndex
PathEnd::pathIndex(const StaState *sta) const PathEnd::pathIndex(const StaState *sta) const
{ {
return path_.pathAnalysisPtIndex(sta); return path_->pathAnalysisPtIndex(sta);
} }
PathAnalysisPt * PathAnalysisPt *
PathEnd::pathAnalysisPt(const StaState *sta) const PathEnd::pathAnalysisPt(const StaState *sta) const
{ {
return path_.pathAnalysisPt(sta); return path_->pathAnalysisPt(sta);
} }
const ClockEdge * const ClockEdge *
PathEnd::sourceClkEdge(const StaState *sta) const PathEnd::sourceClkEdge(const StaState *sta) const
{ {
return path_.clkEdge(sta); return path_->clkEdge(sta);
} }
Arrival Arrival
PathEnd::dataArrivalTime(const StaState *sta) const PathEnd::dataArrivalTime(const StaState *) const
{ {
return path_.arrival(sta); return path_->arrival();
} }
Arrival Arrival
@ -133,7 +134,7 @@ PathEnd::requiredTimeOffset(const StaState *sta) const
const RiseFall * const RiseFall *
PathEnd::targetClkEndTrans(const StaState *sta) const PathEnd::targetClkEndTrans(const StaState *sta) const
{ {
const PathVertex *clk_path = targetClkPath(); const Path *clk_path = targetClkPath();
if (clk_path) if (clk_path)
return clk_path->transition(sta); return clk_path->transition(sta);
else { else {
@ -235,13 +236,13 @@ PathEnd::checkRole(const StaState *) const
return nullptr; return nullptr;
} }
PathVertex * Path *
PathEnd::targetClkPath() PathEnd::targetClkPath()
{ {
return nullptr; return nullptr;
} }
const PathVertex * const Path *
PathEnd::targetClkPath() const PathEnd::targetClkPath() const
{ {
return nullptr; return nullptr;
@ -303,7 +304,7 @@ PathEnd::exceptPathCmp(const PathEnd *path_end,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Delay Delay
PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path, PathEnd::checkTgtClkDelay(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta) const StaState *sta)
@ -315,7 +316,7 @@ PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path,
} }
void void
PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path, PathEnd::checkTgtClkDelay(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta, const StaState *sta,
@ -340,7 +341,7 @@ PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path,
|| check_role->isDataCheck()) { || check_role->isDataCheck()) {
// Propagated clock. Propagated arrival is seeded with // Propagated clock. Propagated arrival is seeded with
// early_late==path_min_max insertion delay. // early_late==path_min_max insertion delay.
Arrival clk_arrival = tgt_clk_path->arrival(sta); Arrival clk_arrival = tgt_clk_path->arrival();
Delay path_insertion = search->clockInsertion(tgt_clk, tgt_src_pin, Delay path_insertion = search->clockInsertion(tgt_clk, tgt_src_pin,
tgt_clk_rf, min_max, tgt_clk_rf, min_max,
min_max, tgt_path_ap); min_max, tgt_path_ap);
@ -359,7 +360,7 @@ PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path,
float float
PathEnd::checkClkUncertainty(const ClockEdge *src_clk_edge, PathEnd::checkClkUncertainty(const ClockEdge *src_clk_edge,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const PathVertex *tgt_clk_path, const Path *tgt_clk_path,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta) const StaState *sta)
{ {
@ -375,7 +376,7 @@ PathEnd::checkClkUncertainty(const ClockEdge *src_clk_edge,
} }
float float
PathEnd::checkTgtClkUncertainty(const PathVertex *tgt_clk_path, PathEnd::checkTgtClkUncertainty(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const TimingRole *check_role, const TimingRole *check_role,
const StaState *sta) const StaState *sta)
@ -455,7 +456,7 @@ PathEndUnconstrained::PathEndUnconstrained(Path *path) :
PathEnd * PathEnd *
PathEndUnconstrained::copy() PathEndUnconstrained::copy()
{ {
return new PathEndUnconstrained(path_.path()); return new PathEndUnconstrained(path_);
} }
bool bool
@ -510,7 +511,7 @@ PathEndUnconstrained::typeName() const
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathEndClkConstrained::PathEndClkConstrained(Path *path, PathEndClkConstrained::PathEndClkConstrained(Path *path,
PathVertex *clk_path) : Path *clk_path) :
PathEnd(path), PathEnd(path),
clk_path_(clk_path), clk_path_(clk_path),
crpr_(0.0), crpr_(0.0),
@ -519,7 +520,7 @@ PathEndClkConstrained::PathEndClkConstrained(Path *path,
} }
PathEndClkConstrained::PathEndClkConstrained(Path *path, PathEndClkConstrained::PathEndClkConstrained(Path *path,
PathVertex *clk_path, Path *clk_path,
Crpr crpr, Crpr crpr,
bool crpr_valid) : bool crpr_valid) :
PathEnd(path), PathEnd(path),
@ -530,9 +531,9 @@ PathEndClkConstrained::PathEndClkConstrained(Path *path,
} }
void void
PathEndClkConstrained::setPath(const Path *path) PathEndClkConstrained::setPath(Path *path)
{ {
path_.init(path); path_ = path;
crpr_valid_ = false; crpr_valid_ = false;
} }
@ -559,33 +560,27 @@ PathEndClkConstrained::sourceClkOffset(const ClockEdge *src_clk_edge,
Arrival Arrival
PathEndClkConstrained::sourceClkLatency(const StaState *sta) const PathEndClkConstrained::sourceClkLatency(const StaState *sta) const
{ {
ClkInfo *clk_info = path_.clkInfo(sta); ClkInfo *clk_info = path_->clkInfo(sta);
return clk_info->latency(); return clk_info->latency();
} }
Arrival Arrival
PathEndClkConstrained::sourceClkInsertionDelay(const StaState *sta) const PathEndClkConstrained::sourceClkInsertionDelay(const StaState *sta) const
{ {
ClkInfo *clk_info = path_.clkInfo(sta); ClkInfo *clk_info = path_->clkInfo(sta);
return clk_info->insertion(); return clk_info->insertion();
} }
PathVertex * Path *
PathEndClkConstrained::targetClkPath() PathEndClkConstrained::targetClkPath()
{ {
if (clk_path_.isNull()) return clk_path_;
return nullptr;
else
return &clk_path_;
} }
const PathVertex * const Path *
PathEndClkConstrained::targetClkPath() const PathEndClkConstrained::targetClkPath() const
{ {
if (clk_path_.isNull()) return clk_path_;
return nullptr;
else
return &clk_path_;
} }
float float
@ -602,8 +597,8 @@ PathEndClkConstrained::targetClkOffset(const StaState *sta) const
const ClockEdge * const ClockEdge *
PathEndClkConstrained::targetClkEdge(const StaState *sta) const PathEndClkConstrained::targetClkEdge(const StaState *sta) const
{ {
if (!clk_path_.isNull()) if (clk_path_)
return clk_path_.clkEdge(sta); return clk_path_->clkEdge(sta);
else else
return nullptr; return nullptr;
} }
@ -708,7 +703,7 @@ PathEndClkConstrained::crpr(const StaState *sta) const
{ {
if (!crpr_valid_) { if (!crpr_valid_) {
CheckCrpr *check_crpr = sta->search()->checkCrpr(); CheckCrpr *check_crpr = sta->search()->checkCrpr();
crpr_ = check_crpr->checkCrpr(path_.path(), targetClkPath()); crpr_ = check_crpr->checkCrpr(path_, targetClkPath());
crpr_valid_ = true; crpr_valid_ = true;
} }
return crpr_; return crpr_;
@ -751,7 +746,7 @@ PathEndClkConstrained::exceptPathCmp(const PathEnd *path_end,
if (cmp == 0) { if (cmp == 0) {
const PathEndClkConstrained *path_end2 = const PathEndClkConstrained *path_end2 =
dynamic_cast<const PathEndClkConstrained*>(path_end); dynamic_cast<const PathEndClkConstrained*>(path_end);
const PathVertex *clk_path2 = path_end2->targetClkPath(); const Path *clk_path2 = path_end2->targetClkPath();
return Path::cmp(targetClkPath(), clk_path2, sta); return Path::cmp(targetClkPath(), clk_path2, sta);
} }
else else
@ -761,7 +756,7 @@ PathEndClkConstrained::exceptPathCmp(const PathEnd *path_end,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path, PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp) : MultiCyclePath *mcp) :
PathEndClkConstrained(path, clk_path), PathEndClkConstrained(path, clk_path),
mcp_(mcp) mcp_(mcp)
@ -769,7 +764,7 @@ PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path,
} }
PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path, PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid) : bool crpr_valid) :
@ -781,7 +776,7 @@ PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path,
float float
PathEndClkConstrainedMcp::targetClkMcpAdjustment(const StaState *sta) const PathEndClkConstrainedMcp::targetClkMcpAdjustment(const StaState *sta) const
{ {
return checkMcpAdjustment(path_.path(), targetClkEdge(sta), sta); return checkMcpAdjustment(path_, targetClkEdge(sta), sta);
} }
float float
@ -887,8 +882,8 @@ PathEndClkConstrainedMcp::findHoldMcps(const ClockEdge *tgt_clk_edge,
const StaState *sta) const const StaState *sta) const
{ {
Pin *pin = path_.pin(sta); Pin *pin = path_->pin(sta);
const RiseFall *rf = path_.transition(sta); const RiseFall *rf = path_->transition(sta);
// Mcp may be setup, hold or setup_hold, since all match min paths. // Mcp may be setup, hold or setup_hold, since all match min paths.
const MinMaxAll *mcp_min_max = mcp_->minMax(); const MinMaxAll *mcp_min_max = mcp_->minMax();
Search *search = sta->search(); Search *search = sta->search();
@ -896,7 +891,7 @@ PathEndClkConstrainedMcp::findHoldMcps(const ClockEdge *tgt_clk_edge,
hold_mcp = mcp_; hold_mcp = mcp_;
setup_mcp = setup_mcp =
dynamic_cast<MultiCyclePath*>(search->exceptionTo(ExceptionPathType::multi_cycle, dynamic_cast<MultiCyclePath*>(search->exceptionTo(ExceptionPathType::multi_cycle,
path_.path(), pin, rf, path_, pin, rf,
tgt_clk_edge, tgt_clk_edge,
MinMax::max(), true, MinMax::max(), true,
false)); false));
@ -905,7 +900,7 @@ PathEndClkConstrainedMcp::findHoldMcps(const ClockEdge *tgt_clk_edge,
setup_mcp = mcp_; setup_mcp = mcp_;
hold_mcp = hold_mcp =
dynamic_cast<MultiCyclePath*>(search->exceptionTo(ExceptionPathType::multi_cycle, dynamic_cast<MultiCyclePath*>(search->exceptionTo(ExceptionPathType::multi_cycle,
path_.path(), pin, rf, path_, pin, rf,
tgt_clk_edge, tgt_clk_edge,
MinMax::min(), true, MinMax::min(), true,
false)); false));
@ -937,7 +932,7 @@ PathEndClkConstrainedMcp::exceptPathCmp(const PathEnd *path_end,
PathEndCheck::PathEndCheck(Path *path, PathEndCheck::PathEndCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
const StaState *) : const StaState *) :
PathEndClkConstrainedMcp(path, clk_path, mcp), PathEndClkConstrainedMcp(path, clk_path, mcp),
@ -949,7 +944,7 @@ PathEndCheck::PathEndCheck(Path *path,
PathEndCheck::PathEndCheck(Path *path, PathEndCheck::PathEndCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid) : bool crpr_valid) :
@ -962,8 +957,8 @@ PathEndCheck::PathEndCheck(Path *path,
PathEnd * PathEnd *
PathEndCheck::copy() PathEndCheck::copy()
{ {
return new PathEndCheck(path_.path(), check_arc_, check_edge_, return new PathEndCheck(path_, check_arc_, check_edge_,
&clk_path_, mcp_, crpr_, crpr_valid_); clk_path_, mcp_, crpr_, crpr_valid_);
} }
PathEnd::Type PathEnd::Type
@ -999,7 +994,7 @@ PathEndCheck::checkRole(const StaState *) const
ArcDelay ArcDelay
PathEndCheck::margin(const StaState *sta) const PathEndCheck::margin(const StaState *sta) const
{ {
return sta->search()->deratedDelay(clk_path_.vertex(sta), return sta->search()->deratedDelay(clk_path_->vertex(sta),
check_arc_, check_edge_, false, check_arc_, check_edge_, false,
pathAnalysisPt(sta)); pathAnalysisPt(sta));
} }
@ -1028,20 +1023,20 @@ PathEndCheck::clkSkew(const StaState *sta)
{ {
return sourceClkDelay(sta) - targetClkDelay(sta) - crpr(sta) return sourceClkDelay(sta) - targetClkDelay(sta) - crpr(sta)
// Uncertainty decreases slack, but increases skew. // Uncertainty decreases slack, but increases skew.
- checkTgtClkUncertainty(&clk_path_, clk_path_.clkEdge(sta), checkRole(sta), sta); - checkTgtClkUncertainty(clk_path_, clk_path_->clkEdge(sta),
checkRole(sta), sta);
} }
Delay Delay
PathEndCheck::sourceClkDelay(const StaState *sta) const PathEndCheck::sourceClkDelay(const StaState *sta) const
{ {
PathExpanded expanded(&path_, sta); PathExpanded expanded(path_, sta);
PathRef src_clk_path; const Path *src_clk_path = expanded.clkPath();
expanded.clkPath(src_clk_path); if (src_clk_path) {
if (!src_clk_path.isNull()) { ClkInfo *src_clk_info = path_->tag(sta)->clkInfo();
ClkInfo *src_clk_info = path_.tag(sta)->clkInfo();
if (src_clk_info->isPropagated()) { if (src_clk_info->isPropagated()) {
// Propagated clock. Propagated arrival is seeded with insertion delay. // Propagated clock. Propagated arrival is seeded with insertion delay.
Arrival clk_arrival = src_clk_path.arrival(sta); Arrival clk_arrival = src_clk_path->arrival();
const ClockEdge *src_clk_edge = src_clk_info->clkEdge(); const ClockEdge *src_clk_edge = src_clk_info->clkEdge();
Delay insertion = sourceClkInsertionDelay(sta); Delay insertion = sourceClkInsertionDelay(sta);
return delayRemove(clk_arrival - src_clk_edge->time(), insertion); return delayRemove(clk_arrival - src_clk_edge->time(), insertion);
@ -1072,16 +1067,16 @@ PathEndCheck::macroClkTreeDelay(const StaState *sta) const
const ClockEdge *tgt_clk_edge = targetClkEdge(sta); const ClockEdge *tgt_clk_edge = targetClkEdge(sta);
const Clock *tgt_clk = tgt_clk_edge->clock(); const Clock *tgt_clk = tgt_clk_edge->clock();
const Network *network = sta->network(); const Network *network = sta->network();
const Pin *clk_pin = clk_path_.pin(sta); const Pin *clk_pin = clk_path_->pin(sta);
const Instance *inst = network->instance(clk_pin); const Instance *inst = network->instance(clk_pin);
const LibertyCell *inst_cell = network->libertyCell(inst); const LibertyCell *inst_cell = network->libertyCell(inst);
if (tgt_clk->isIdeal() if (tgt_clk->isIdeal()
&& inst_cell && inst_cell->isMacro()) { && inst_cell && inst_cell->isMacro()) {
LibertyPort *clk_port = network->libertyPort(clk_pin); LibertyPort *clk_port = network->libertyPort(clk_pin);
if (clk_port) { if (clk_port) {
const MinMax *min_max = clk_path_.minMax(sta); const MinMax *min_max = clk_path_->minMax(sta);
const RiseFall *rf = clk_path_.transition(sta); const RiseFall *rf = clk_path_->transition(sta);
float slew = delayAsFloat(clk_path_.slew(sta)); float slew = delayAsFloat(clk_path_->slew(sta));
return clk_port->clkTreeDelay(slew, rf, min_max); return clk_port->clkTreeDelay(slew, rf, min_max);
} }
} }
@ -1093,7 +1088,7 @@ PathEndCheck::macroClkTreeDelay(const StaState *sta) const
PathEndLatchCheck::PathEndLatchCheck(Path *path, PathEndLatchCheck::PathEndLatchCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *disable_path, Path *disable_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathDelay *path_delay, PathDelay *path_delay,
const StaState *sta) : const StaState *sta) :
@ -1102,23 +1097,22 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path,
path_delay_(path_delay), path_delay_(path_delay),
src_clk_arrival_(0.0) src_clk_arrival_(0.0)
{ {
PathVertex enable_path;
Latches *latches = sta->latches(); Latches *latches = sta->latches();
latches->latchEnableOtherPath(disable_path, Path *enable_path =
disable_path->pathAnalysisPt(sta), latches->latchEnableOtherPath(disable_path,
enable_path); disable_path->pathAnalysisPt(sta));
clk_path_ = enable_path; clk_path_ = enable_path;
Search *search = sta->search(); Search *search = sta->search();
// Same as PathEndPathDelay::findRequired. // Same as PathEndPathDelay::findRequired.
if (path_delay_ && ignoreClkLatency(sta)) if (path_delay_ && ignoreClkLatency(sta))
src_clk_arrival_ = search->pathClkPathArrival(&path_); src_clk_arrival_ = search->pathClkPathArrival(path_);
} }
PathEndLatchCheck::PathEndLatchCheck(Path *path, PathEndLatchCheck::PathEndLatchCheck(Path *path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
PathVertex *clk_path, Path *clk_path,
PathVertex *disable_path, Path *disable_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathDelay *path_delay, PathDelay *path_delay,
Delay src_clk_arrival, Delay src_clk_arrival,
@ -1134,8 +1128,8 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path,
PathEnd * PathEnd *
PathEndLatchCheck::copy() PathEndLatchCheck::copy()
{ {
return new PathEndLatchCheck(path_.path(), check_arc_, check_edge_, return new PathEndLatchCheck(path_, check_arc_, check_edge_,
&clk_path_, &disable_path_, mcp_, path_delay_, clk_path_, disable_path_, mcp_, path_delay_,
src_clk_arrival_, crpr_, crpr_valid_); src_clk_arrival_, crpr_, crpr_valid_);
} }
@ -1151,22 +1145,16 @@ PathEndLatchCheck::typeName() const
return "latch_check"; return "latch_check";
} }
PathVertex * Path *
PathEndLatchCheck::latchDisable() PathEndLatchCheck::latchDisable()
{ {
if (disable_path_.isNull()) return disable_path_;
return nullptr;
else
return &disable_path_;
} }
const PathVertex * const Path *
PathEndLatchCheck::latchDisable() const PathEndLatchCheck::latchDisable() const
{ {
if (disable_path_.isNull()) return disable_path_;
return nullptr;
else
return &disable_path_;
} }
void void
@ -1188,7 +1176,7 @@ PathEndLatchCheck::sourceClkOffset(const StaState *sta) const
return pathDelaySrcClkOffset(path_, path_delay_, src_clk_arrival_, sta); return pathDelaySrcClkOffset(path_, path_delay_, src_clk_arrival_, sta);
else else
return PathEndClkConstrained::sourceClkOffset(sourceClkEdge(sta), return PathEndClkConstrained::sourceClkOffset(sourceClkEdge(sta),
disable_path_.clkEdge(sta), disable_path_->clkEdge(sta),
TimingRole::setup(), TimingRole::setup(),
sta); sta);
} }
@ -1196,7 +1184,7 @@ PathEndLatchCheck::sourceClkOffset(const StaState *sta) const
TimingRole * TimingRole *
PathEndLatchCheck::checkRole(const StaState *sta) const PathEndLatchCheck::checkRole(const StaState *sta) const
{ {
if (clk_path_.clkInfo(sta)->isPulseClk()) if (clk_path_->clkInfo(sta)->isPulseClk())
// Pulse latches use register cycle accounting. // Pulse latches use register cycle accounting.
return TimingRole::setup(); return TimingRole::setup();
else else
@ -1211,7 +1199,7 @@ PathEndLatchCheck::requiredTime(const StaState *sta) const
Required required; Required required;
Arrival borrow, adjusted_data_arrival, time_given_to_startpoint; Arrival borrow, adjusted_data_arrival, time_given_to_startpoint;
Latches *latches = sta->latches(); Latches *latches = sta->latches();
latches->latchRequired(path_.path(), targetClkPath(), latchDisable(), latches->latchRequired(path_, targetClkPath(), latchDisable(),
mcp_, path_delay_, src_clk_arrival_, margin(sta), mcp_, path_delay_, src_clk_arrival_, margin(sta),
required, borrow, adjusted_data_arrival, required, borrow, adjusted_data_arrival,
time_given_to_startpoint); time_given_to_startpoint);
@ -1224,7 +1212,7 @@ PathEndLatchCheck::borrow(const StaState *sta) const
Latches *latches = sta->latches(); Latches *latches = sta->latches();
Required required; Required required;
Arrival borrow, adjusted_data_arrival, time_given_to_startpoint; Arrival borrow, adjusted_data_arrival, time_given_to_startpoint;
latches->latchRequired(path_.path(), targetClkPath(), latchDisable(), latches->latchRequired(path_, targetClkPath(), latchDisable(),
mcp_, path_delay_, src_clk_arrival_, margin(sta), mcp_, path_delay_, src_clk_arrival_, margin(sta),
required, borrow, adjusted_data_arrival, required, borrow, adjusted_data_arrival,
time_given_to_startpoint); time_given_to_startpoint);
@ -1240,7 +1228,7 @@ PathEndLatchCheck::latchRequired(const StaState *sta,
Delay &time_given_to_startpoint) const Delay &time_given_to_startpoint) const
{ {
Latches *latches = sta->latches(); Latches *latches = sta->latches();
latches->latchRequired(path_.path(), targetClkPath(), latchDisable(), latches->latchRequired(path_, targetClkPath(), latchDisable(),
mcp_, path_delay_, src_clk_arrival_, margin(sta), mcp_, path_delay_, src_clk_arrival_, margin(sta),
required, borrow, adjusted_data_arrival, required, borrow, adjusted_data_arrival,
time_given_to_startpoint); time_given_to_startpoint);
@ -1259,7 +1247,7 @@ PathEndLatchCheck::latchBorrowInfo(const StaState *sta,
bool &borrow_limit_exists) const bool &borrow_limit_exists) const
{ {
Latches *latches = sta->latches(); Latches *latches = sta->latches();
latches->latchBorrowInfo(path_.path(), targetClkPath(), latchDisable(), latches->latchBorrowInfo(path_, targetClkPath(), latchDisable(),
margin(sta), margin(sta),
path_delay_ && ignoreClkLatency(sta), path_delay_ && ignoreClkLatency(sta),
nom_pulse_width, open_latency, nom_pulse_width, open_latency,
@ -1272,9 +1260,9 @@ Arrival
PathEndLatchCheck::targetClkWidth(const StaState *sta) const PathEndLatchCheck::targetClkWidth(const StaState *sta) const
{ {
const Search *search = sta->search(); const Search *search = sta->search();
Arrival disable_arrival = search->clkPathArrival(&disable_path_); Arrival disable_arrival = search->clkPathArrival(disable_path_);
Arrival enable_arrival = search->clkPathArrival(&clk_path_); Arrival enable_arrival = search->clkPathArrival(clk_path_);
ClkInfo *enable_clk_info = clk_path_.clkInfo(sta); ClkInfo *enable_clk_info = clk_path_->clkInfo(sta);
if (enable_clk_info->isPulseClk()) if (enable_clk_info->isPulseClk())
return disable_arrival - enable_arrival; return disable_arrival - enable_arrival;
else { else {
@ -1297,8 +1285,8 @@ PathEndLatchCheck::exceptPathCmp(const PathEnd *path_end,
dynamic_cast<const PathEndLatchCheck*>(path_end); dynamic_cast<const PathEndLatchCheck*>(path_end);
const TimingArc *check_arc2 = path_end2->check_arc_; const TimingArc *check_arc2 = path_end2->check_arc_;
if (check_arc_ == check_arc2) { if (check_arc_ == check_arc2) {
const Path *disable_path2 = path_end2->disable_path_.path(); const Path *disable_path2 = path_end2->disable_path_;
return Path::cmp(disable_path_.path(), disable_path2, sta); return Path::cmp(disable_path_, disable_path2, sta);
} }
else if (check_arc_ < check_arc2) else if (check_arc_ < check_arc2)
return -1; return -1;
@ -1319,7 +1307,7 @@ PathEndLatchCheck::ignoreClkLatency(const StaState *sta) const
PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay, PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
const StaState *) : const StaState *) :
// No target clk_path_ for output delays. // No target clk_path_ for output delays.
@ -1330,7 +1318,7 @@ PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay,
PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay, PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid) : bool crpr_valid) :
@ -1342,7 +1330,7 @@ PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay,
PathEnd * PathEnd *
PathEndOutputDelay::copy() PathEndOutputDelay::copy()
{ {
return new PathEndOutputDelay(output_delay_, path_.path(), &clk_path_, return new PathEndOutputDelay(output_delay_, path_, clk_path_,
mcp_, crpr_, crpr_valid_); mcp_, crpr_, crpr_valid_);
} }
@ -1373,7 +1361,7 @@ PathEndOutputDelay::reportShort(const ReportPath *report) const
ArcDelay ArcDelay
PathEndOutputDelay::margin(const StaState *sta) const PathEndOutputDelay::margin(const StaState *sta) const
{ {
return outputDelayMargin(output_delay_, path_.path(), sta); return outputDelayMargin(output_delay_, path_, sta);
} }
float float
@ -1393,7 +1381,7 @@ PathEnd::outputDelayMargin(OutputDelay *output_delay,
TimingRole * TimingRole *
PathEndOutputDelay::checkRole(const StaState *sta) const PathEndOutputDelay::checkRole(const StaState *sta) const
{ {
if (path_.minMax(sta) == MinMax::max()) if (path_->minMax(sta) == MinMax::max())
return TimingRole::outputSetup(); return TimingRole::outputSetup();
else else
return TimingRole::outputHold(); return TimingRole::outputHold();
@ -1402,8 +1390,8 @@ PathEndOutputDelay::checkRole(const StaState *sta) const
const ClockEdge * const ClockEdge *
PathEndOutputDelay::targetClkEdge(const StaState *sta) const PathEndOutputDelay::targetClkEdge(const StaState *sta) const
{ {
if (!clk_path_.isNull()) if (clk_path_)
return clk_path_.clkEdge(sta); return clk_path_->clkEdge(sta);
else else
return output_delay_->clkEdge(); return output_delay_->clkEdge();
} }
@ -1411,7 +1399,7 @@ PathEndOutputDelay::targetClkEdge(const StaState *sta) const
Arrival Arrival
PathEndOutputDelay::targetClkArrivalNoCrpr(const StaState *sta) const PathEndOutputDelay::targetClkArrivalNoCrpr(const StaState *sta) const
{ {
if (!clk_path_.isNull()) if (clk_path_)
return PathEndClkConstrained::targetClkArrivalNoCrpr(sta); return PathEndClkConstrained::targetClkArrivalNoCrpr(sta);
else { else {
const ClockEdge *tgt_clk_edge = targetClkEdge(sta); const ClockEdge *tgt_clk_edge = targetClkEdge(sta);
@ -1419,7 +1407,7 @@ PathEndOutputDelay::targetClkArrivalNoCrpr(const StaState *sta) const
return targetClkTime(sta) return targetClkTime(sta)
+ tgtClkDelay(tgt_clk_edge, check_role, sta) + tgtClkDelay(tgt_clk_edge, check_role, sta)
+ targetClkUncertainty(sta) + targetClkUncertainty(sta)
+ checkMcpAdjustment(path_.path(), tgt_clk_edge, sta); + checkMcpAdjustment(path_, tgt_clk_edge, sta);
} }
} }
@ -1428,7 +1416,7 @@ PathEndOutputDelay::crpr(const StaState *sta) const
{ {
if (!crpr_valid_) { if (!crpr_valid_) {
CheckCrpr *check_crpr = sta->search()->checkCrpr(); CheckCrpr *check_crpr = sta->search()->checkCrpr();
crpr_ = check_crpr->outputDelayCrpr(path_.path(), targetClkEdge(sta)); crpr_ = check_crpr->outputDelayCrpr(path_, targetClkEdge(sta));
crpr_valid_ = true; crpr_valid_ = true;
} }
return crpr_; return crpr_;
@ -1437,7 +1425,7 @@ PathEndOutputDelay::crpr(const StaState *sta) const
Delay Delay
PathEndOutputDelay::targetClkDelay(const StaState *sta) const PathEndOutputDelay::targetClkDelay(const StaState *sta) const
{ {
if (!clk_path_.isNull()) if (clk_path_)
return PathEndClkConstrained::targetClkDelay(sta); return PathEndClkConstrained::targetClkDelay(sta);
else else
return tgtClkDelay(targetClkEdge(sta), checkRole(sta), sta); return tgtClkDelay(targetClkEdge(sta), checkRole(sta), sta);
@ -1465,7 +1453,7 @@ PathEndOutputDelay::tgtClkDelay(const ClockEdge *tgt_clk_edge,
// Early late: setup early, hold late. // Early late: setup early, hold late.
const EarlyLate *early_late = check_role->tgtClkEarlyLate(); const EarlyLate *early_late = check_role->tgtClkEarlyLate();
// Latency min_max depends on bc_wc or ocv. // Latency min_max depends on bc_wc or ocv.
const PathAnalysisPt *path_ap = path_.pathAnalysisPt(sta); const PathAnalysisPt *path_ap = path_->pathAnalysisPt(sta);
const MinMax *latency_min_max = path_ap->tgtClkAnalysisPt()->pathMinMax(); const MinMax *latency_min_max = path_ap->tgtClkAnalysisPt()->pathMinMax();
Clock *tgt_clk = tgt_clk_edge->clock(); Clock *tgt_clk = tgt_clk_edge->clock();
RiseFall *tgt_clk_rf = tgt_clk_edge->transition(); RiseFall *tgt_clk_rf = tgt_clk_edge->transition();
@ -1488,7 +1476,7 @@ PathEndOutputDelay::tgtClkDelay(const ClockEdge *tgt_clk_edge,
Delay Delay
PathEndOutputDelay::targetClkInsertionDelay(const StaState *sta) const PathEndOutputDelay::targetClkInsertionDelay(const StaState *sta) const
{ {
if (!clk_path_.isNull()) if (clk_path_)
return PathEndClkConstrained::targetClkInsertionDelay(sta); return PathEndClkConstrained::targetClkInsertionDelay(sta);
else { else {
Arrival insertion, latency; Arrival insertion, latency;
@ -1521,7 +1509,7 @@ PathEndOutputDelay::exceptPathCmp(const PathEnd *path_end,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathEndGatedClock::PathEndGatedClock(Path *gating_ref, PathEndGatedClock::PathEndGatedClock(Path *gating_ref,
PathVertex *clk_path, Path *clk_path,
TimingRole *check_role, TimingRole *check_role,
MultiCyclePath *mcp, MultiCyclePath *mcp,
ArcDelay margin, ArcDelay margin,
@ -1533,7 +1521,7 @@ PathEndGatedClock::PathEndGatedClock(Path *gating_ref,
} }
PathEndGatedClock::PathEndGatedClock(Path *gating_ref, PathEndGatedClock::PathEndGatedClock(Path *gating_ref,
PathVertex *clk_path, Path *clk_path,
TimingRole *check_role, TimingRole *check_role,
MultiCyclePath *mcp, MultiCyclePath *mcp,
ArcDelay margin, ArcDelay margin,
@ -1548,7 +1536,7 @@ PathEndGatedClock::PathEndGatedClock(Path *gating_ref,
PathEnd * PathEnd *
PathEndGatedClock::copy() PathEndGatedClock::copy()
{ {
return new PathEndGatedClock(path_.path(), &clk_path_, check_role_, return new PathEndGatedClock(path_, clk_path_, check_role_,
mcp_, margin_, crpr_, crpr_valid_); mcp_, margin_, crpr_, crpr_valid_);
} }
@ -1606,59 +1594,52 @@ PathEndGatedClock::exceptPathCmp(const PathEnd *path_end,
PathEndDataCheck::PathEndDataCheck(DataCheck *check, PathEndDataCheck::PathEndDataCheck(DataCheck *check,
Path *data_path, Path *data_path,
PathVertex *data_clk_path, Path *data_clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
const StaState *sta) : const StaState *sta) :
PathEndClkConstrainedMcp(data_path, nullptr, mcp), PathEndClkConstrainedMcp(data_path, nullptr, mcp),
data_clk_path_(data_clk_path), data_clk_path_(data_clk_path),
check_(check) check_(check)
{ {
clkPath(data_clk_path, sta, clk_path_); clk_path_ = clkPath(data_clk_path, sta);
} }
// PathExpanded::expand() and PathExpanded::clkPath(). // PathExpanded::expand() and PathExpanded::clkPath().
void Path *
PathEndDataCheck::clkPath(PathVertex *path, PathEndDataCheck::clkPath(Path *path,
const StaState *sta, const StaState *sta)
// Return value.
PathVertex &clk_path)
{ {
PathVertex p(path); Path *p = path;
while (!p.isNull()) { while (p) {
PathVertex prev_path; Path *prev_path = p->prevPath();
TimingArc *prev_arc; TimingArc *prev_arc = p->prevArc(sta);
p.prevPath(sta, prev_path, prev_arc);
if (p.isClock(sta)) { if (p->isClock(sta))
clk_path = p; return p;
return;
}
if (prev_arc) { if (prev_arc) {
TimingRole *prev_role = prev_arc->role(); TimingRole *prev_role = prev_arc->role();
if (prev_role == TimingRole::regClkToQ() if (prev_role == TimingRole::regClkToQ()
|| prev_role == TimingRole::latchEnToQ()) { || prev_role == TimingRole::latchEnToQ()) {
p.prevPath(sta, prev_path, prev_arc); prev_path = p->prevPath();
clk_path = prev_path; return prev_path;
return;
} }
else if (prev_role == TimingRole::latchDtoQ()) { else if (prev_role == TimingRole::latchDtoQ()) {
const Latches *latches = sta->latches(); const Latches *latches = sta->latches();
Edge *prev_edge = p.prevEdge(prev_arc, sta); Edge *prev_edge = p->prevEdge(sta);
PathVertex enable_path; Path *enable_path = latches->latchEnablePath(p, prev_edge);
latches->latchEnablePath(&p, prev_edge, enable_path); return enable_path;
clk_path = enable_path;
return;
} }
} }
p = prev_path; p = prev_path;
} }
return nullptr;
} }
PathEndDataCheck::PathEndDataCheck(DataCheck *check, PathEndDataCheck::PathEndDataCheck(DataCheck *check,
Path *data_path, Path *data_path,
PathVertex *data_clk_path, Path *data_clk_path,
PathVertex *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
Crpr crpr, Crpr crpr,
bool crpr_valid) : bool crpr_valid) :
@ -1671,8 +1652,8 @@ PathEndDataCheck::PathEndDataCheck(DataCheck *check,
PathEnd * PathEnd *
PathEndDataCheck::copy() PathEndDataCheck::copy()
{ {
return new PathEndDataCheck(check_, path_.path(), &data_clk_path_, return new PathEndDataCheck(check_, path_, data_clk_path_,
&clk_path_, mcp_, crpr_, crpr_valid_); clk_path_, mcp_, crpr_, crpr_valid_);
} }
PathEnd::Type PathEnd::Type
@ -1691,14 +1672,14 @@ const ClockEdge *
PathEndDataCheck::targetClkEdge(const StaState *sta) const PathEndDataCheck::targetClkEdge(const StaState *sta) const
{ {
// clk_path_ can be null if data_clk_path is from an input port. // clk_path_ can be null if data_clk_path is from an input port.
return data_clk_path_.clkEdge(sta); return data_clk_path_->clkEdge(sta);
} }
Arrival Arrival
PathEndDataCheck::requiredTimeNoCrpr(const StaState *sta) const PathEndDataCheck::requiredTimeNoCrpr(const StaState *sta) const
{ {
Arrival data_clk_arrival = data_clk_path_.arrival(sta); Arrival data_clk_arrival = data_clk_path_->arrival();
float data_clk_time = data_clk_path_.clkEdge(sta)->time(); float data_clk_time = data_clk_path_->clkEdge(sta)->time();
Arrival data_clk_delay = data_clk_arrival - data_clk_time; Arrival data_clk_delay = data_clk_arrival - data_clk_time;
Arrival tgt_clk_arrival = targetClkTime(sta) Arrival tgt_clk_arrival = targetClkTime(sta)
+ data_clk_delay + data_clk_delay
@ -1717,9 +1698,9 @@ PathEndDataCheck::margin(const StaState *sta) const
{ {
float margin; float margin;
bool margin_exists; bool margin_exists;
check_->margin(data_clk_path_.transition(sta), check_->margin(data_clk_path_->transition(sta),
path_.transition(sta), path_->transition(sta),
path_.minMax(sta), path_->minMax(sta),
margin, margin_exists); margin, margin_exists);
return margin; return margin;
} }
@ -1727,7 +1708,7 @@ PathEndDataCheck::margin(const StaState *sta) const
TimingRole * TimingRole *
PathEndDataCheck::checkRole(const StaState *sta) const PathEndDataCheck::checkRole(const StaState *sta) const
{ {
if (path_.minMax(sta) == MinMax::max()) if (path_->minMax(sta) == MinMax::max())
return TimingRole::dataCheckSetup(); return TimingRole::dataCheckSetup();
else else
return TimingRole::dataCheckHold(); return TimingRole::dataCheckHold();
@ -1794,7 +1775,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
const StaState *sta) : const StaState *sta) :
@ -1809,7 +1790,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
Path *path, Path *path,
PathVertex *clk_path, Path *clk_path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
OutputDelay *output_delay, OutputDelay *output_delay,
@ -1828,7 +1809,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
PathEnd * PathEnd *
PathEndPathDelay::copy() PathEndPathDelay::copy()
{ {
return new PathEndPathDelay(path_delay_, path_.path(), &clk_path_, return new PathEndPathDelay(path_delay_, path_, clk_path_,
check_arc_, check_edge_, output_delay_, check_arc_, check_edge_, output_delay_,
src_clk_arrival_, crpr_, crpr_valid_); src_clk_arrival_, crpr_, crpr_valid_);
} }
@ -1850,7 +1831,7 @@ PathEndPathDelay::findSrcClkArrival(const StaState *sta)
{ {
if (ignoreClkLatency(sta)) { if (ignoreClkLatency(sta)) {
Search *search = sta->search(); Search *search = sta->search();
src_clk_arrival_ = search->pathClkPathArrival(&path_); src_clk_arrival_ = search->pathClkPathArrival(path_);
} }
else else
src_clk_arrival_ = 0.0; src_clk_arrival_ = 0.0;
@ -1895,7 +1876,7 @@ PathEndPathDelay::margin(const StaState *sta) const
pathAnalysisPt(sta)); pathAnalysisPt(sta));
} }
else if (output_delay_) else if (output_delay_)
return outputDelayMargin(output_delay_, path_.path(), sta); return outputDelayMargin(output_delay_, path_, sta);
else else
return delay_zero; return delay_zero;
} }
@ -1914,13 +1895,13 @@ PathEnd::clkSkew(const StaState *)
// Helper shared by PathEndLatchCheck. // Helper shared by PathEndLatchCheck.
float float
PathEnd::pathDelaySrcClkOffset(const PathRef &path, PathEnd::pathDelaySrcClkOffset(const Path *path,
PathDelay *path_delay, PathDelay *path_delay,
Arrival src_clk_arrival, Arrival src_clk_arrival,
const StaState *sta) const StaState *sta)
{ {
float offset = 0.0; float offset = 0.0;
const ClockEdge *clk_edge = path.clkEdge(sta); const ClockEdge *clk_edge = path->clkEdge(sta);
if (clk_edge) { if (clk_edge) {
if (ignoreClkLatency(path, path_delay, sta)) if (ignoreClkLatency(path, path_delay, sta))
offset = -delayAsFloat(src_clk_arrival); offset = -delayAsFloat(src_clk_arrival);
@ -1933,18 +1914,18 @@ PathEnd::pathDelaySrcClkOffset(const PathRef &path,
} }
bool bool
PathEnd::ignoreClkLatency(const PathRef &path, PathEnd::ignoreClkLatency(const Path *path,
PathDelay *path_delay, PathDelay *path_delay,
const StaState *sta) const StaState *sta)
{ {
return path_delay->ignoreClkLatency() && !path.isClock(sta); return path_delay->ignoreClkLatency() && !path->isClock(sta);
} }
const ClockEdge * const ClockEdge *
PathEndPathDelay::targetClkEdge(const StaState *sta) const PathEndPathDelay::targetClkEdge(const StaState *sta) const
{ {
if (!clk_path_.isNull()) if (clk_path_)
return clk_path_.clkEdge(sta); return clk_path_->clkEdge(sta);
else if (output_delay_) else if (output_delay_)
return output_delay_->clkEdge(); return output_delay_->clkEdge();
else else
@ -1968,8 +1949,8 @@ PathEndPathDelay::targetClkArrivalNoCrpr(const StaState *sta) const
if (tgt_clk_edge) if (tgt_clk_edge)
return targetClkDelay(sta) return targetClkDelay(sta)
+ targetClkUncertainty(sta); + targetClkUncertainty(sta);
else if (!clk_path_.isNull()) else if (clk_path_)
return clk_path_.arrival(sta); return clk_path_->arrival();
else else
return 0.0; return 0.0;
} }
@ -1985,8 +1966,8 @@ PathEndPathDelay::requiredTime(const StaState *sta) const
{ {
float delay = path_delay_->delay(); float delay = path_delay_->delay();
if (path_delay_->ignoreClkLatency()) { if (path_delay_->ignoreClkLatency()) {
Required src_offset = path_.isClock(sta) Required src_offset = path_->isClock(sta)
? path_.clkEdge(sta)->time() ? path_->clkEdge(sta)->time()
: src_clk_arrival_; : src_clk_arrival_;
return src_offset + delay return src_offset + delay
+ ((minMax(sta) == MinMax::max()) ? -margin(sta) : margin(sta)); + ((minMax(sta) == MinMax::max()) ? -margin(sta) : margin(sta));

View File

@ -36,8 +36,7 @@
#include "Tag.hh" #include "Tag.hh"
#include "Search.hh" #include "Search.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
#include "PathRef.hh" #include "Path.hh"
#include "PathEnumed.hh"
namespace sta { namespace sta {
@ -104,8 +103,8 @@ deleteDiversionPathEnd(Diversion *div)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathEnum::PathEnum(int group_path_count, PathEnum::PathEnum(size_t group_path_count,
int endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool cmp_slack, bool cmp_slack,
const StaState *sta) : const StaState *sta) :
@ -214,17 +213,16 @@ PathEnum::reportDiversionPath(Diversion *div)
{ {
PathEnd *path_end = div->pathEnd(); PathEnd *path_end = div->pathEnd();
Path *path = path_end->path(); Path *path = path_end->path();
PathRef p; Path *p = path->prevPath();
path->prevPath(this, p);
Path *after_div = div->divPath(); Path *after_div = div->divPath();
while (!p.isNull()) { while (p) {
report_->reportLine("path_enum: %s %s%s", report_->reportLine("path_enum: %s %s%s",
p.name(this), p->name(this),
delayAsString(p.arrival(this), this), delayAsString(p->arrival(), this),
Path::equal(&p, after_div, this) ? " <-diversion" : ""); Path::equal(p, after_div, this) ? " <-diversion" : "");
if (network_->isLatchData(p.pin(this))) if (network_->isLatchData(p->pin(this)))
break; break;
p.prevPath(this, p); p = p->prevPath();
} }
} }
@ -234,19 +232,19 @@ class PathEnumFaninVisitor : public PathVisitor
{ {
public: public:
PathEnumFaninVisitor(PathEnd *path_end, PathEnumFaninVisitor(PathEnd *path_end,
PathRef &before_div, Path *before_div,
bool unique_pins, bool unique_pins,
PathEnum *path_enum); PathEnum *path_enum);
virtual VertexVisitor *copy() const; virtual VertexVisitor *copy() const;
virtual void visit(Vertex *) {} // Not used. virtual void visit(Vertex *) {} // Not used.
void visitFaninPathsThru(Vertex *vertex, void visitFaninPathsThru(Path *before_div,
Vertex *prev_vertex, Vertex *prev_vertex,
TimingArc *prev_arc); TimingArc *prev_arc);
virtual bool visitFromToPath(const Pin *from_pin, virtual bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *from_path,
const Arrival &from_arrival, const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
@ -260,16 +258,18 @@ public:
private: private:
void makeDivertedPathEnd(Path *after_div, void makeDivertedPathEnd(Path *after_div,
Edge *div_edge,
TimingArc *div_arc, TimingArc *div_arc,
// Return values. // Return values.
PathEnd *&div_end, PathEnd *&div_end,
PathEnumed *&after_div_copy); Path *&after_div_copy);
void reportDiversion(TimingArc *div_arc, void reportDiversion(const Edge *edge,
const TimingArc *div_arc,
Path *after_div); Path *after_div);
PathEnd *path_end_; PathEnd *path_end_;
Slack path_end_slack_; Slack path_end_slack_;
PathRef &before_div_; Path *before_div_;
bool unique_pins_; bool unique_pins_;
int before_div_rf_index_; int before_div_rf_index_;
Tag *before_div_tag_; Tag *before_div_tag_;
@ -282,7 +282,7 @@ private:
}; };
PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
PathRef &before_div, Path *before_div,
bool unique_pins, bool unique_pins,
PathEnum *path_enum) : PathEnum *path_enum) :
PathVisitor(path_enum), PathVisitor(path_enum),
@ -290,27 +290,28 @@ PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
path_end_slack_(path_end->slack(this)), path_end_slack_(path_end->slack(this)),
before_div_(before_div), before_div_(before_div),
unique_pins_(unique_pins), unique_pins_(unique_pins),
before_div_rf_index_(before_div_.rfIndex(this)), before_div_rf_index_(before_div_->rfIndex(this)),
before_div_tag_(before_div_.tag(this)), before_div_tag_(before_div_->tag(this)),
before_div_ap_index_(before_div_.pathAnalysisPtIndex(this)), before_div_ap_index_(before_div_->pathAnalysisPtIndex(this)),
before_div_arrival_(before_div_.arrival(this)), before_div_arrival_(before_div_->arrival()),
path_enum_(path_enum), path_enum_(path_enum),
crpr_active_(sdc_->crprActive()) crpr_active_(sdc_->crprActive())
{ {
} }
void void
PathEnumFaninVisitor::visitFaninPathsThru(Vertex *vertex, PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div,
Vertex *prev_vertex, Vertex *prev_vertex,
TimingArc *prev_arc) TimingArc *prev_arc)
{ {
before_div_rf_index_ = before_div_.rfIndex(this); before_div_ = before_div;
before_div_tag_ = before_div_.tag(this); before_div_rf_index_ = before_div_->rfIndex(this);
before_div_ap_index_ = before_div_.pathAnalysisPtIndex(this); before_div_tag_ = before_div_->tag(this);
before_div_arrival_ = before_div_.arrival(this); before_div_ap_index_ = before_div_->pathAnalysisPtIndex(this);
before_div_arrival_ = before_div_->arrival();
prev_arc_ = prev_arc; prev_arc_ = prev_arc;
prev_vertex_ = prev_vertex; prev_vertex_ = prev_vertex;
visitFaninPaths(vertex); visitFaninPaths(before_div_->vertex(this));
} }
VertexVisitor * VertexVisitor *
@ -325,7 +326,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *, const RiseFall *,
Tag *, Tag *,
PathVertex *from_path, Path *from_path,
const Arrival &, const Arrival &,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
@ -351,13 +352,13 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
&& tagMatchNoCrpr(to_tag, before_div_tag_)) { && tagMatchNoCrpr(to_tag, before_div_tag_)) {
if (crpr_active_) { if (crpr_active_) {
PathEnd *div_end; PathEnd *div_end;
PathEnumed *after_div_copy; Path *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, edge, arc, div_end, after_div_copy);
if (div_end) { if (div_end) {
// Only enumerate paths with greater slack. // Only enumerate paths with greater slack.
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) { if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
reportDiversion(arc, from_path); reportDiversion(edge, arc, from_path);
path_enum_->makeDiversion(div_end, after_div_copy); path_enum_->makeDiversion(div_end, after_div_copy);
} }
else else
@ -367,9 +368,9 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
// 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)) {
PathEnd *div_end; PathEnd *div_end;
PathEnumed *after_div_copy; Path *after_div_copy;
makeDivertedPathEnd(from_path, arc, div_end, after_div_copy); makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
reportDiversion(arc, from_path); reportDiversion(edge, arc, from_path);
path_enum_->makeDiversion(div_end, after_div_copy); path_enum_->makeDiversion(div_end, after_div_copy);
} }
} }
@ -378,14 +379,15 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
void void
PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div, PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
Edge *div_edge,
TimingArc *div_arc, TimingArc *div_arc,
// Return values. // Return values.
PathEnd *&div_end, PathEnd *&div_end,
PathEnumed *&after_div_copy) Path *&after_div_copy)
{ {
PathEnumed *div_path; Path *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_edge, div_arc, div_path, after_div_copy);
if (after_div_copy) { if (after_div_copy) {
div_end = path_end_->copy(); div_end = path_end_->copy();
div_end->setPath(div_path); div_end->setPath(div_path);
@ -395,7 +397,8 @@ PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
} }
void void
PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc, PathEnumFaninVisitor::reportDiversion(const Edge *div_edge,
const TimingArc *div_arc,
Path *after_div) Path *after_div)
{ {
if (debug_->check("path_enum", 3)) { if (debug_->check("path_enum", 3)) {
@ -404,19 +407,18 @@ PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc,
Arrival path_delay = path_enum_->cmp_slack_ Arrival path_delay = path_enum_->cmp_slack_
? path_end_->slack(this) ? path_end_->slack(this)
: path_end_->dataArrivalTime(this); : path_end_->dataArrivalTime(this);
Arrival div_delay = path_delay - path_enum_->divSlack(&before_div_, Arrival div_delay = path_delay - path_enum_->divSlack(before_div_,
after_div, after_div, div_edge,
div_arc, path_ap); div_arc, path_ap);
PathRef div_prev; Path *div_prev = before_div_->prevPath();
before_div_.prevPath(this, div_prev);
report_->reportLine("path_enum: diversion %s %s %s -> %s", report_->reportLine("path_enum: diversion %s %s %s -> %s",
path->name(this), path->name(this),
path_enum_->cmp_slack_ ? "slack" : "delay", path_enum_->cmp_slack_ ? "slack" : "delay",
delayAsString(path_delay, this), delayAsString(path_delay, this),
delayAsString(div_delay, this)); delayAsString(div_delay, this));
report_->reportLine("path_enum: from %s -> %s", report_->reportLine("path_enum: from %s -> %s",
div_prev.name(this), div_prev->name(this),
before_div_.name(this)); before_div_->name(this));
report_->reportLine("path_enum: to %s", report_->reportLine("path_enum: to %s",
after_div->name(this)); after_div->name(this));
} }
@ -431,13 +433,13 @@ PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc,
// <--...--before_div<--...--path<---path_end // <--...--before_div<--...--path<---path_end
void void
PathEnum::makeDiversion(PathEnd *div_end, PathEnum::makeDiversion(PathEnd *div_end,
PathEnumed *after_div_copy) Path *after_div_copy)
{ {
Diversion *div = new Diversion(div_end, after_div_copy); Diversion *div = new Diversion(div_end, after_div_copy);
div_queue_.push(div); div_queue_.push(div);
div_count_++; div_count_++;
if (static_cast<int>(div_queue_.size()) > group_path_count_ * 2) if (div_queue_.size() > group_path_count_ * 2)
// We have more potenial paths than we will need. // We have more potenial paths than we will need.
pruneDiversionQueue(); pruneDiversionQueue();
} }
@ -447,7 +449,7 @@ PathEnum::pruneDiversionQueue()
{ {
debugPrint(debug_, "path_enum", 2, "prune queue"); debugPrint(debug_, "path_enum", 2, "prune queue");
VertexPathCountMap path_counts; VertexPathCountMap path_counts;
int end_count = 0; size_t end_count = 0;
// Collect endpoint_path_count diversions per vertex. // Collect endpoint_path_count diversions per vertex.
DiversionSeq divs; DiversionSeq divs;
while (!div_queue_.empty()) { while (!div_queue_.empty()) {
@ -476,11 +478,11 @@ PathEnum::pruneDiversionQueue()
Arrival Arrival
PathEnum::divSlack(Path *before_div, PathEnum::divSlack(Path *before_div,
Path *after_div, Path *after_div,
TimingArc *div_arc, const Edge *div_edge,
const TimingArc *div_arc,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap)
{ {
Arrival arc_arrival = before_div->arrival(this); Arrival arc_arrival = before_div->arrival();
Edge *div_edge = divEdge(before_div, div_arc);
if (div_edge) { if (div_edge) {
ArcDelay div_delay = search_->deratedDelay(div_edge->from(graph_), ArcDelay div_delay = search_->deratedDelay(div_edge->from(graph_),
div_arc, div_edge, div_arc, div_edge,
@ -494,45 +496,30 @@ PathEnum::divSlack(Path *before_div,
} }
} }
Edge *
PathEnum::divEdge(Path *before_div,
TimingArc *div_arc)
{
TimingArcSet *arc_set = div_arc->set();
VertexInEdgeIterator edge_iter(before_div->vertex(this), graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
if (edge->timingArcSet() == arc_set)
return edge;
}
return nullptr;
}
// Make diversions for all arcs that merge into path for paths // Make diversions for all arcs that merge into path for paths
// starting at "before" to the beginning of the path. // starting at "before" to the beginning of the path.
void void
PathEnum::makeDiversions(PathEnd *path_end, PathEnum::makeDiversions(PathEnd *path_end,
Path *before) Path *before)
{ {
PathRef path(before); Path *path = before;
PathRef prev_path; Path *prev_path = path->prevPath();
TimingArc *prev_arc; TimingArc *prev_arc = path->prevArc(this);
path.prevPath(this, prev_path, prev_arc);
PathEnumFaninVisitor fanin_visitor(path_end, path, unique_pins_, this); PathEnumFaninVisitor fanin_visitor(path_end, path, unique_pins_, this);
while (prev_arc while (prev_path
// Do not enumerate paths in the clk network. // Do not enumerate paths in the clk network.
&& !path.isClock(this)) { && !path->isClock(this)) {
// Fanin visitor does all the work. // Fanin visitor does all the work.
// While visiting the fanins the fanin_visitor finds the // While visiting the fanins the fanin_visitor finds the
// previous path and arc as well as diversions. // previous path and arc as well as diversions.
fanin_visitor.visitFaninPathsThru(path.vertex(this), fanin_visitor.visitFaninPathsThru(path, prev_path->vertex(this), prev_arc);
prev_path.vertex(this), prev_arc);
// Do not enumerate beyond latch D to Q edges. // Do not enumerate beyond latch D to Q edges.
// This breaks latch loop paths. // This breaks latch loop paths.
if (prev_arc->role() == TimingRole::latchDtoQ()) if (prev_arc->role() == TimingRole::latchDtoQ())
break; break;
path.init(prev_path); path = prev_path;
path.prevPath(this, prev_path, prev_arc); prev_path = path->prevPath();
prev_arc = path->prevArc(this);
} }
} }
@ -540,47 +527,52 @@ void
PathEnum::makeDivertedPath(Path *path, PathEnum::makeDivertedPath(Path *path,
Path *before_div, Path *before_div,
Path *after_div, Path *after_div,
Edge *div_edge,
TimingArc *div_arc, TimingArc *div_arc,
// Returned values. // Returned values.
PathEnumed *&div_path, Path *&div_path,
PathEnumed *&after_div_copy) Path *&after_div_copy)
{ {
div_path = nullptr; div_path = nullptr;
after_div_copy = nullptr; after_div_copy = nullptr;
// Copy the diversion path. // Copy the diversion path.
bool found_div = false; bool found_div = false;
PathEnumedSeq copies; PathSeq copies;
PathRef p(path); Path *p = path;
bool first = true; bool first = true;
PathEnumed *prev_copy = nullptr; Path *prev_copy = nullptr;
while (!p.isNull()) { while (p) {
PathRef prev; // prev_path made in next pass.
TimingArc *prev_arc; Path *copy = new Path(p->vertex(this),
p.prevPath(this, prev, prev_arc); p->tag(this),
PathEnumed *copy = new PathEnumed(p.vertexId(this), p->arrival(),
p.tagIndex(this), // Replaced on next pass.
p.arrival(this), p->prevPath(),
nullptr, // prev_path made in next pass. p->prevEdge(this),
prev_arc); p->prevArc(this),
true, this);
if (prev_copy) if (prev_copy)
prev_copy->setPrevPath(copy); prev_copy->setPrevPath(copy);
copies.push_back(copy); copies.push_back(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) if (first)
div_path = copy; div_path = copy;
else if (network_->isLatchData(p.pin(this))) else if (network_->isLatchData(p->pin(this)))
break; break;
if (Path::equal(&p, before_div, this)) { if (Path::equal(p, before_div, this)) {
copy->setPrevArc(div_arc); // Replaced on next pass.
copy->setPrevPath(after_div);
copy->setPrevEdgeArc(div_edge, div_arc, this);
// 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.
updatePathHeadDelays(copies, after_div); updatePathHeadDelays(copies, after_div);
p.init(after_div); p = after_div;
found_div = true; found_div = true;
} }
else else
p.init(prev); p = p->prevPath();
prev_copy = copy; prev_copy = copy;
first = false; first = false;
} }
@ -589,16 +581,16 @@ PathEnum::makeDivertedPath(Path *path,
} }
void void
PathEnum::updatePathHeadDelays(PathEnumedSeq &paths, PathEnum::updatePathHeadDelays(PathSeq &paths,
Path *after_div) Path *after_div)
{ {
Tag *prev_tag = after_div->tag(this); Tag *prev_tag = after_div->tag(this);
ClkInfo *prev_clk_info = prev_tag->clkInfo(); ClkInfo *prev_clk_info = prev_tag->clkInfo();
Arrival prev_arrival = search_->clkPathArrival(after_div); Arrival prev_arrival = search_->clkPathArrival(after_div);
for (int i = paths.size() - 1; i >= 0; i--) { for (int i = paths.size() - 1; i >= 0; i--) {
PathEnumed *path = paths[i]; Path *path = paths[i];
TimingArc *arc = path->prevArc(this); TimingArc *arc = path->prevArc(this);
Edge *edge = path->prevEdge(arc, this); Edge *edge = path->prevEdge(this);
if (edge) { if (edge) {
PathAnalysisPt *path_ap = path->pathAnalysisPt(this); PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_), ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_),
@ -607,9 +599,9 @@ PathEnum::updatePathHeadDelays(PathEnumedSeq &paths,
debugPrint(debug_, "path_enum", 5, "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),
delayAsString(arrival, this)); delayAsString(arrival, this));
path->setArrival(arrival, this); path->setArrival(arrival);
prev_arrival = arrival; prev_arrival = arrival;
if (sdc_->crprActive() if (sdc_->crprActive()
// D->Q paths use the EN->Q clk info so no need to update. // D->Q paths use the EN->Q clk info so no need to update.

View File

@ -36,11 +36,9 @@ namespace sta {
class Diversion; class Diversion;
class PathEnumFaninVisitor; class PathEnumFaninVisitor;
class PathEnumed;
class DiversionGreater; class DiversionGreater;
typedef Vector<Diversion*> DiversionSeq; typedef Vector<Diversion*> DiversionSeq;
typedef Vector<PathEnumed*> PathEnumedSeq;
typedef std::priority_queue<Diversion*,DiversionSeq, typedef std::priority_queue<Diversion*,DiversionSeq,
DiversionGreater> DiversionQueue; DiversionGreater> DiversionQueue;
@ -60,8 +58,8 @@ private:
class PathEnum : public Iterator<PathEnd*>, StaState class PathEnum : public Iterator<PathEnd*>, StaState
{ {
public: public:
PathEnum(int group_path_count, PathEnum(size_t group_path_count,
int endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool cmp_slack, bool cmp_slack,
const StaState *sta); const StaState *sta);
@ -75,29 +73,29 @@ private:
void makeDiversions(PathEnd *path_end, void makeDiversions(PathEnd *path_end,
Path *before); Path *before);
void makeDiversion(PathEnd *div_end, void makeDiversion(PathEnd *div_end,
PathEnumed *after_div_copy); Path *after_div_copy);
void makeDivertedPath(Path *path, void makeDivertedPath(Path *path,
Path *before_div, Path *before_div,
Path *after_div, Path *after_div,
Edge *div_edge,
TimingArc *div_arc, TimingArc *div_arc,
// Returned values. // Returned values.
PathEnumed *&div_path, Path *&div_path,
PathEnumed *&after_div_copy); Path *&after_div_copy);
void updatePathHeadDelays(PathEnumedSeq &path, void updatePathHeadDelays(PathSeq &path,
Path *after_div); Path *after_div);
Arrival divSlack(Path *path, Arrival divSlack(Path *path,
Path *after_div, Path *after_div,
TimingArc *div_arc, const Edge *div_edge,
const TimingArc *div_arc,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
void reportDiversionPath(Diversion *div); void reportDiversionPath(Diversion *div);
void pruneDiversionQueue(); void pruneDiversionQueue();
Edge *divEdge(Path *before_div,
TimingArc *div_arc);
void findNext(); void findNext();
bool cmp_slack_; bool cmp_slack_;
int group_path_count_; size_t group_path_count_;
int endpoint_path_count_; size_t endpoint_path_count_;
bool unique_pins_; bool unique_pins_;
DiversionQueue div_queue_; DiversionQueue div_queue_;
int div_count_; int div_count_;

View File

@ -1,192 +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 "PathEnumed.hh"
#include "Set.hh"
#include "Graph.hh"
#include "Corner.hh"
#include "Search.hh"
#include "Tag.hh"
#include "PathRef.hh"
namespace sta {
PathEnumed:: PathEnumed(VertexId vertex_id,
TagIndex tag_index,
Arrival arrival,
PathEnumed *prev_path,
TimingArc *prev_arc) :
Path(),
prev_path_(prev_path),
prev_arc_(prev_arc),
arrival_(arrival),
vertex_id_(vertex_id),
tag_index_(tag_index)
{
}
void
deletePathEnumed(PathEnumed *path)
{
while (path) {
PathEnumed *prev = path->prevPathEnumed();
delete path;
path = prev;
}
}
void
PathEnumed::setRef(PathRef *ref) const
{
ref->init(const_cast<PathEnumed*>(this));
}
Vertex *
PathEnumed::vertex(const StaState *sta) const
{
const Graph *graph = sta->graph();
return graph->vertex(vertex_id_);
}
VertexId
PathEnumed::vertexId(const StaState *) const
{
return vertex_id_;
}
Tag *
PathEnumed::tag(const StaState *sta) const
{
const Search *search = sta->search();
return search->tag(tag_index_);
}
void
PathEnumed::setTag(Tag *tag)
{
tag_index_ = tag->index();
}
const RiseFall *
PathEnumed::transition(const StaState *sta) const
{
return tag(sta)->transition();
}
int
PathEnumed::trIndex(const StaState *sta) const
{
return tag(sta)->rfIndex();
}
PathAnalysisPt *
PathEnumed::pathAnalysisPt(const StaState *sta) const
{
const Corners *corners = sta->corners();
return corners->findPathAnalysisPt(pathAnalysisPtIndex(sta));
}
PathAPIndex
PathEnumed::pathAnalysisPtIndex(const StaState *sta) const
{
return tag(sta)->pathAPIndex();
}
Arrival
PathEnumed::arrival(const StaState *) const
{
return arrival_;
}
void
PathEnumed::setArrival(Arrival arrival,
const StaState *)
{
arrival_ = arrival;
}
const Required &
PathEnumed::required(const StaState *sta) const
{
// Required times are never needed for enumerated paths.
sta->report()->critical(1380, "enumerated path required time");
return delay_zero;
}
void
PathEnumed::setRequired(const Required &,
const StaState *sta)
{
// Required times are never needed for enumerated paths.
sta->report()->critical(1381, "enumerated path required time");
}
Path *
PathEnumed::prevPath(const StaState *) const
{
return prev_path_;
}
void
PathEnumed::prevPath(const StaState *,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const
{
if (prev_path_) {
prev_path_->setRef(prev_path);
prev_arc = prev_arc_;
}
else {
prev_path.init();
prev_arc = nullptr;
}
}
TimingArc *
PathEnumed::prevArc(const StaState *) const
{
return prev_arc_;
}
PathEnumed *
PathEnumed::prevPathEnumed() const
{
return prev_path_;
}
void
PathEnumed::setPrevPath(PathEnumed *prev)
{
prev_path_ = prev;
}
void
PathEnumed::setPrevArc(TimingArc *arc)
{
prev_arc_ = arc;
}
} // namespace

View File

@ -1,80 +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.
#pragma once
#include "Path.hh"
namespace sta {
// Implements Path API for paths returned by PathEnum.
class PathEnumed : public Path
{
public:
PathEnumed(VertexId vertex_id,
TagIndex tag_index,
Arrival arrival,
PathEnumed *prev_path,
TimingArc *prev_arc);
virtual void setRef(PathRef *ref) const;
virtual bool isNull() const { return vertex_id_ == 0; }
virtual Vertex *vertex(const StaState *sta) const;
virtual VertexId vertexId(const StaState *sta) const;
virtual Tag *tag(const StaState *sta) const;
virtual const RiseFall *transition(const StaState *sta) const;
virtual int trIndex(const StaState *) const;
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
virtual Arrival arrival(const StaState *sta) const;
virtual void setArrival(Arrival arrival, const StaState *sta);
virtual const Required &required(const StaState *sta) const;
virtual void setRequired(const Required &required,
const StaState *sta);
virtual Path *prevPath(const StaState *sta) const;
virtual void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const;
virtual TimingArc *prevArc(const StaState *sta) const;
PathEnumed *prevPathEnumed() const;
void setPrevPath(PathEnumed *prev);
void setPrevArc(TimingArc *arc);
void setTag(Tag *tag);
using Path::setRef;
using Path::prevPath;
protected:
// Pointer to previous path.
// A path is traversed by following prev_path/arcs.
PathEnumed *prev_path_;
TimingArc *prev_arc_;
Arrival arrival_;
VertexId vertex_id_;
TagIndex tag_index_;
};
void deletePathEnumed(PathEnumed *path);
} // namespace

View File

@ -29,7 +29,7 @@
#include "Network.hh" #include "Network.hh"
#include "Clock.hh" #include "Clock.hh"
#include "Search.hh" #include "Search.hh"
#include "PathRef.hh" #include "Path.hh"
#include "Latches.hh" #include "Latches.hh"
#include "Genclks.hh" #include "Genclks.hh"
@ -61,35 +61,32 @@ PathExpanded::expand(const Path *path,
bool expand_genclks) bool expand_genclks)
{ {
const Latches *latches = sta_->latches(); const Latches *latches = sta_->latches();
// Push the paths from the end into an array of PathRefs. // Push the paths from the end into an array of Paths.
PathRef p(path); const Path *p = path;
PathRef last_path; const Path *last_path = nullptr;
size_t i = 0; size_t i = 0;
bool found_start = false; bool found_start = false;
while (!p.isNull()) { while (p) {
PathRef prev_path; const Path *prev_path = p->prevPath();
TimingArc *prev_arc; const TimingArc *prev_arc = p->prevArc(sta_);
p.prevPath(sta_, prev_path, prev_arc);
if (!found_start) { if (!found_start) {
if (prev_arc) { if (prev_arc) {
TimingRole *prev_role = prev_arc->role(); const TimingRole *prev_role = prev_arc->role();
if (prev_role == TimingRole::regClkToQ() if (prev_role == TimingRole::regClkToQ()
|| prev_role == TimingRole::latchEnToQ()) { || prev_role == TimingRole::latchEnToQ()) {
start_index_ = i; start_index_ = i;
found_start = true; found_start = true;
} }
else if (prev_role == TimingRole::latchDtoQ()) { else if (prev_role == TimingRole::latchDtoQ()) {
Edge *prev_edge = p.prevEdge(prev_arc, sta_); const Edge *prev_edge = p->prevEdge(sta_);
if (prev_edge && latches->isLatchDtoQ(prev_edge)) { if (prev_edge && latches->isLatchDtoQ(prev_edge)) {
start_index_ = i; start_index_ = i;
found_start = true; found_start = true;
paths_.push_back(p); paths_.push_back(p);
prev_arcs_.push_back(prev_arc);
// Push latch D path. // Push latch D path.
paths_.push_back(prev_path); paths_.push_back(prev_path);
prev_arcs_.push_back(nullptr);
// This breaks latch loop paths. // This breaks latch loop paths.
break; break;
} }
@ -97,43 +94,37 @@ PathExpanded::expand(const Path *path,
} }
} }
paths_.push_back(p); paths_.push_back(p);
prev_arcs_.push_back(prev_arc); last_path = p;
last_path.init(p); p = prev_path;
p.init(prev_path);
i++; i++;
} }
if (!found_start) if (!found_start)
start_index_ = i - 1; start_index_ = i - 1;
if (expand_genclks) if (expand_genclks)
expandGenclk(&last_path); expandGenclk(last_path);
} }
void void
PathExpanded::expandGenclk(PathRef *clk_path) PathExpanded::expandGenclk(const Path *clk_path)
{ {
if (!clk_path->isNull()) { if (clk_path) {
const Clock *src_clk = clk_path->clock(sta_); const Clock *src_clk = clk_path->clock(sta_);
if (src_clk && src_clk->isGenerated()) { if (src_clk && src_clk->isGenerated()) {
PathVertex src_path = sta_->search()->genclks()->srcPath(clk_path); const Path *src_path = sta_->search()->genclks()->srcPath(clk_path);
if (!src_path.isNull()) { if (src_path) {
// The head of the genclk src path is already in paths_, // The head of the genclk src path is already in paths_,
// so skip past it. // so skip past it.
PathRef prev_path; Path *prev_path = src_path->prevPath();
TimingArc *prev_arc; Path *p = prev_path;
src_path.prevPath(sta_, prev_path, prev_arc); Path *last_path = nullptr;
while (p) {
PathRef p(prev_path); prev_path = p->prevPath();
PathRef last_path;
while (!p.isNull()) {
p.prevPath(sta_, prev_path, prev_arc);
paths_.push_back(p); paths_.push_back(p);
prev_arcs_.push_back(prev_arc); last_path = p;
last_path.init(p); p = prev_path;
p.init(prev_path);
} }
expandGenclk(&last_path); expandGenclk(last_path);
} }
} }
} }
@ -153,91 +144,84 @@ PathExpanded::startIndex() const
return pathsIndex(start_index_); return pathsIndex(start_index_);
} }
const PathRef * const Path *
PathExpanded::path(size_t index) const PathExpanded::path(size_t index) const
{ {
if (index < paths_.size()) if (index < paths_.size())
return &paths_[pathsIndex(index)]; return paths_[pathsIndex(index)];
else else
return nullptr; return nullptr;
} }
TimingArc * const Path *
PathExpanded::prevArc(size_t index) const
{
return prev_arcs_[pathsIndex(index)];
}
const PathRef *
PathExpanded::startPath() const PathExpanded::startPath() const
{ {
return &paths_[start_index_]; return paths_[start_index_];
} }
const PathRef * const Path *
PathExpanded::endPath() const PathExpanded::endPath() const
{ {
return &paths_[0]; return paths_[0];
} }
TimingArc * const TimingArc *
PathExpanded::startPrevArc() const PathExpanded::startPrevArc() const
{ {
return prev_arcs_[start_index_]; return paths_[start_index_]->prevArc(sta_);
} }
const PathRef * const Path *
PathExpanded::startPrevPath() const PathExpanded::startPrevPath() const
{ {
size_t start1 = start_index_ + 1; size_t start1 = start_index_ + 1;
if (start1 < paths_.size()) if (start1 < paths_.size())
return &paths_[start1]; return paths_[start1];
else else
return nullptr; return nullptr;
} }
void const Path *
PathExpanded::clkPath(PathRef &clk_path) const PathExpanded::clkPath() const
{ {
const Latches *latches = sta_->latches(); const Latches *latches = sta_->latches();
const PathRef *start = startPath(); const Path *start = startPath();
const TimingArc *prev_arc = startPrevArc(); const TimingArc *prev_arc = startPrevArc();
if (start && prev_arc) { if (start && prev_arc) {
TimingRole *role = prev_arc->role(); TimingRole *role = prev_arc->role();
if (role == TimingRole::latchDtoQ()) { if (role == TimingRole::latchDtoQ()) {
Edge *prev_edge = start->prevEdge(prev_arc, sta_); Edge *prev_edge = start->prevEdge(sta_);
if (prev_edge && latches->isLatchDtoQ(prev_edge)) { if (prev_edge && latches->isLatchDtoQ(prev_edge)) {
PathVertex enable_path; return latches->latchEnablePath(start, prev_edge);
latches->latchEnablePath(start, prev_edge, enable_path);
clk_path.init(enable_path);
} }
} }
else if (role == TimingRole::regClkToQ() else if (role == TimingRole::regClkToQ()
|| role == TimingRole::latchEnToQ()) { || role == TimingRole::latchEnToQ()) {
const PathRef *start_prev = startPrevPath(); const Path *start_prev = startPrevPath();
if (start_prev) if (start_prev)
clk_path.init(start_prev); return start_prev;
} }
} }
else if (start && start->isClock(sta_)) else if (start && start->isClock(sta_))
clk_path.init(start); return start;
return nullptr;
} }
void void
PathExpanded::latchPaths(// Return values. PathExpanded::latchPaths(// Return values.
const PathRef *&d_path, const Path *&d_path,
const PathRef *&q_path, const Path *&q_path,
Edge *&d_q_edge) const Edge *&d_q_edge) const
{ {
d_path = nullptr; d_path = nullptr;
q_path = nullptr; q_path = nullptr;
d_q_edge = nullptr; d_q_edge = nullptr;
const PathRef *start = startPath(); const Path *start = startPath();
const TimingArc *prev_arc = startPrevArc(); const TimingArc *prev_arc = startPrevArc();
if (start if (start
&& prev_arc && prev_arc
&& prev_arc->role() == TimingRole::latchDtoQ()) { && prev_arc->role() == TimingRole::latchDtoQ()) {
Edge *prev_edge = start->prevEdge(prev_arc, sta_); Edge *prev_edge = start->prevEdge(sta_);
// This breaks latch loop paths. // This breaks latch loop paths.
if (prev_edge if (prev_edge
&& sta_->latches()->isLatchDtoQ(prev_edge)) { && sta_->latches()->isLatchDtoQ(prev_edge)) {

View File

@ -46,7 +46,7 @@
namespace sta { namespace sta {
int PathGroup::group_path_count_max = std::numeric_limits<int>::max(); size_t PathGroup::group_path_count_max = std::numeric_limits<size_t>::max();
PathGroup * PathGroup *
PathGroup::makePathGroupSlack(const char *name, PathGroup::makePathGroupSlack(const char *name,
@ -74,8 +74,8 @@ PathGroup::makePathGroupArrival(const char *name,
} }
PathGroup::PathGroup(const char *name, PathGroup::PathGroup(const char *name,
int group_path_count, size_t group_path_count,
int endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
float slack_min, float slack_min,
float slack_max, float slack_max,
@ -148,7 +148,7 @@ PathGroup::enumMinSlackUnderMin(PathEnd *path_end)
path->transition(sta_), path->transition(sta_),
other_ap, sta_); other_ap, sta_);
while (other_iter.hasNext()) { while (other_iter.hasNext()) {
PathVertex *other = other_iter.next(); Path *other = other_iter.next();
if (tagMatchCrpr(other->tag(sta_), tag)) { if (tagMatchCrpr(other->tag(sta_), tag)) {
PathEnd *end_min = path_end->copy(); PathEnd *end_min = path_end->copy();
end_min->setPath(other); end_min->setPath(other);
@ -168,7 +168,7 @@ PathGroup::insert(PathEnd *path_end)
LockGuard lock(lock_); LockGuard lock(lock_);
path_ends_.push_back(path_end); path_ends_.push_back(path_end);
if (group_path_count_ != group_path_count_max if (group_path_count_ != group_path_count_max
&& static_cast<int>(path_ends_.size()) > group_path_count_ * 2) && path_ends_.size() > group_path_count_ * 2)
prune(); prune();
} }
@ -177,7 +177,7 @@ PathGroup::prune()
{ {
sort(); sort();
VertexPathCountMap path_counts; VertexPathCountMap path_counts;
int end_count = 0; size_t end_count = 0;
for (unsigned i = 0; i < path_ends_.size(); i++) { for (unsigned i = 0; i < path_ends_.size(); i++) {
PathEnd *path_end = path_ends_[i]; PathEnd *path_end = path_ends_[i];
Vertex *vertex = path_end->vertex(sta_); Vertex *vertex = path_end->vertex(sta_);
@ -220,7 +220,7 @@ PathGroup::iterator()
void void
PathGroup::ensureSortedMaxPaths() PathGroup::ensureSortedMaxPaths()
{ {
if (static_cast<int>(path_ends_.size()) > group_path_count_) if (path_ends_.size() > group_path_count_)
prune(); prune();
else else
sort(); sort();

View File

@ -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 "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

View File

@ -1,284 +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 "PathRef.hh"
#include "Graph.hh"
#include "TagGroup.hh"
#include "PathEnumed.hh"
#include "PathVertex.hh"
#include "Search.hh"
namespace sta {
PathRef::PathRef() :
path_enumed_(nullptr)
{
}
PathRef::PathRef(const Path *path) :
path_enumed_(nullptr)
{
if (path)
path->setRef(this);
}
PathRef::PathRef(const PathRef &path) :
path_vertex_(path.path_vertex_),
path_enumed_(path.path_enumed_)
{
}
PathRef::PathRef(const PathRef *path) :
path_vertex_(path->path_vertex_),
path_enumed_(path->path_enumed_)
{
}
PathRef::PathRef(const PathVertex &path) :
path_vertex_(&path),
path_enumed_(nullptr)
{
}
void
PathRef::init()
{
path_vertex_.init();
path_enumed_ = nullptr;
}
void
PathRef::init(const PathRef &path)
{
path_vertex_ = path.path_vertex_;
path_enumed_ = path.path_enumed_;
}
void
PathRef::init(const PathRef *path)
{
path_vertex_ = path->path_vertex_;
path_enumed_ = path->path_enumed_;
}
void
PathRef::init(const PathVertex *path)
{
path_vertex_ = path;
}
void
PathRef::init(const PathVertex &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
PathRef::init(Vertex *vertex,
Tag *tag,
int arrival_index)
{
path_vertex_.init(vertex, tag, arrival_index);
path_enumed_ = nullptr;
}
void
PathRef::init(PathEnumed *path)
{
path_enumed_ = path;
}
void
PathRef::setRef(PathRef *ref) const
{
ref->path_vertex_ = path_vertex_;
ref->path_enumed_ = path_enumed_;
}
void
PathRef::deleteRep()
{
if (path_enumed_)
deletePathEnumed(path_enumed_);
}
bool
PathRef::isNull() const
{
return path_enumed_ == nullptr
&& path_vertex_.isNull();
}
Vertex *
PathRef::vertex(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->vertex(sta);
else
return path_vertex_.vertex(sta);
}
VertexId
PathRef::vertexId(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->vertexId(sta);
else
return path_vertex_.vertexId(sta);
}
Tag *
PathRef::tag(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->tag(sta);
else
return path_vertex_.tag(sta);
}
TagIndex
PathRef::tagIndex(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->tagIndex(sta);
else
return path_vertex_.tagIndex(sta);
}
const RiseFall *
PathRef::transition(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->transition(sta);
else
return path_vertex_.transition(sta);
}
int
PathRef::rfIndex(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->rfIndex(sta);
else
return path_vertex_.rfIndex(sta);
}
PathAnalysisPt *
PathRef::pathAnalysisPt(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->pathAnalysisPt(sta);
else
return path_vertex_.pathAnalysisPt(sta);
}
PathAPIndex
PathRef::pathAnalysisPtIndex(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->pathAnalysisPtIndex(sta);
else
return path_vertex_.pathAnalysisPtIndex(sta);
}
Arrival
PathRef::arrival(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->arrival(sta);
else
return path_vertex_.arrival(sta);
}
void
PathRef::setArrival(Arrival arrival,
const StaState *sta)
{
if (path_enumed_)
return path_enumed_->setArrival(arrival, sta);
else
return path_vertex_.setArrival(arrival, sta);
}
const Required &
PathRef::required(const StaState *sta) const
{
if (path_enumed_)
return path_enumed_->required(sta);
else
return path_vertex_.required(sta);
}
void
PathRef::setRequired(const Required &required,
const StaState *sta)
{
if (path_enumed_)
return path_enumed_->setRequired(required, sta);
else
return path_vertex_.setRequired(required, sta);
}
void
PathRef::prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const
{
if (path_enumed_)
path_enumed_->prevPath(sta, prev_path, prev_arc);
else
path_vertex_.prevPath(sta, prev_path, prev_arc);
}
void
PathRef::arrivalIndex(int &arrival_index,
bool &arrival_exists) const
{
return path_vertex_.arrivalIndex(arrival_index, arrival_exists);
}
} // namespace

View File

@ -1,628 +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 "PathVertex.hh"
#include <cmath>
#include "Fuzzy.hh"
#include "Graph.hh"
#include "ExceptionPath.hh"
#include "Sdc.hh"
#include "GraphDelayCalc.hh"
#include "Corner.hh"
#include "Tag.hh"
#include "TagGroup.hh"
#include "PathAnalysisPt.hh"
#include "PathRef.hh"
#include "PathPrev.hh"
#include "PathVertexPtr.hh"
#include "Search.hh"
namespace sta {
PathVertex::PathVertex() :
vertex_(nullptr),
tag_(nullptr),
arrival_index_(0)
{
}
PathVertex::PathVertex(const PathVertex &path) :
vertex_(path.vertex_),
tag_(path.tag_),
arrival_index_(path.arrival_index_)
{
}
PathVertex::PathVertex(const PathVertex *path) :
vertex_(nullptr),
tag_(nullptr),
arrival_index_(0)
{
if (path) {
vertex_ = path->vertex_;
tag_ = path->tag_;
arrival_index_ = path->arrival_index_;
}
}
PathVertex::PathVertex(Vertex *vertex,
Tag *tag,
const StaState *sta)
{
init(vertex, tag, sta);
}
PathVertex::PathVertex(Vertex *vertex,
Tag *tag,
int arrival_index) :
vertex_(vertex),
tag_(tag),
arrival_index_(arrival_index)
{
}
PathVertex::PathVertex(const PathPrev *path,
const StaState *sta)
{
if (path)
init(path->vertex(sta), path->tag(sta), sta);
else
init();
}
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)
{
if (path.isNull())
init();
else
init(path.vertex(sta), path.tag(sta), sta);
}
void
PathVertex::init()
{
vertex_ = nullptr;
tag_ = nullptr;
arrival_index_ = 0;
}
void
PathVertex::init(Vertex *vertex,
Tag *tag,
const StaState *sta)
{
vertex_ = nullptr;
tag_ = nullptr;
arrival_index_ = 0;
const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex);
if (tag_group) {
bool arrival_exists;
tag_group->arrivalIndex(tag, arrival_index_, arrival_exists);
if (arrival_exists) {
vertex_ = vertex;
tag_ = tag;
}
}
}
void
PathVertex::init(Vertex *vertex,
Tag *tag,
int arrival_index)
{
vertex_ = vertex;
tag_ = tag;
arrival_index_ = arrival_index;
}
void
PathVertex::init(const PathPrev *path,
const StaState *sta)
{
if (path)
init(path->vertex(sta), path->tag(sta), sta);
else
init();
}
void
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)
{
if (!path.isNull())
init(path.vertex(sta), path.tag(sta), sta);
else
init();
}
void
PathVertex::operator=(const PathVertex &path)
{
vertex_ = path.vertex_;
tag_ = path.tag_;
arrival_index_ = path.arrival_index_;
}
bool
PathVertex::isNull() const
{
return tag_ == nullptr;
}
void
PathVertex::setRef(PathRef *ref) const
{
ref->init(vertex_, tag_, arrival_index_);
}
VertexId
PathVertex::vertexId(const StaState *sta) const
{
const Graph *graph = sta->graph();
return graph->id(vertex_);
}
TagIndex
PathVertex::tagIndex(const StaState *) const
{
return tag_->index();
}
const RiseFall *
PathVertex::transition(const StaState *) const
{
return tag_->transition();
}
int
PathVertex::rfIndex(const StaState *) const
{
return tag_->rfIndex();
}
PathAnalysisPt *
PathVertex::pathAnalysisPt(const StaState *sta) const
{
return tag_->pathAnalysisPt(sta);
}
PathAPIndex
PathVertex::pathAnalysisPtIndex(const StaState *) const
{
return tag_->pathAPIndex();
}
void
PathVertex::arrivalIndex(int &arrival_index,
bool &arrival_exists) const
{
if (tag_) {
arrival_index = arrival_index_;
arrival_exists = true;
}
else
arrival_exists = false;
}
void
PathVertex::setArrivalIndex(int arrival_index)
{
arrival_index_ = arrival_index;
}
Arrival
PathVertex::arrival(const StaState *sta) const
{
Arrival *arrivals = sta->graph()->arrivals(vertex_);
if (arrivals)
return arrivals[arrival_index_];
else {
sta->report()->error(1400, "missing arrivals.");
return 0.0;
}
}
void
PathVertex::setArrival(Arrival arrival,
const StaState *sta)
{
if (tag_) {
Arrival *arrivals = sta->graph()->arrivals(vertex_);
if (arrivals)
arrivals[arrival_index_] = arrival;
else
sta->report()->error(1401, "missing arrivals.");
}
}
const Required &
PathVertex::required(const StaState *sta) const
{
if (tag_) {
Required *requireds = sta->graph()->requireds(vertex_);
if (requireds)
return requireds[arrival_index_];
}
return delayInitValue(minMax(sta)->opposite());
}
void
PathVertex::setRequired(const Required &required,
const StaState *sta)
{
Graph *graph = sta->graph();
Required *requireds = graph->requireds(vertex_);
if (requireds == nullptr) {
const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex_);
if (tag_group) {
int arrival_count = tag_group->arrivalCount();
requireds = graph->makeRequireds(vertex_, arrival_count);
}
else
sta->report()->error(1402, "missing requireds.");
}
requireds[arrival_index_] = required;
}
bool
PathVertex::equal(const PathVertex *path1,
const PathVertex *path2)
{
return path1->vertex_ == path2->vertex_
&& path1->tag_ == path2->tag_;
}
////////////////////////////////////////////////////////////////
// EvalPred but search to clk source pin.
class PrevPred2 : public SearchPred0
{
public:
explicit PrevPred2(const StaState *sta);
virtual bool searchThru(Edge *edge);
};
PrevPred2::PrevPred2(const StaState *sta) :
SearchPred0(const_cast<StaState*>(sta))
{
}
bool
PrevPred2::searchThru(Edge *edge)
{
const Sdc *sdc = sta_->sdc();
TimingRole *role = edge->role();
return SearchPred0::searchThru(edge)
&& (sdc->dynamicLoopBreaking()
|| !edge->isDisabledLoop())
&& !role->isTimingCheck();
}
class PrevPathVisitor : public PathVisitor
{
public:
PrevPathVisitor(const Path *path,
SearchPred *pred,
const StaState *sta);
virtual VertexVisitor *copy() const;
virtual void visit(Vertex *) {}
virtual bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex,
const RiseFall *from_rf,
Tag *from_tag,
PathVertex *from_path,
const Arrival &from_arrival,
Edge *edge,
TimingArc *arc,
ArcDelay arc_delay,
Vertex *to_vertex,
const RiseFall *to_rf,
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
PathVertex &prevPath() { return prev_path_; }
TimingArc *prevArc() const { return prev_arc_; }
protected:
Tag *unfilteredTag(const Tag *tag) const;
const Path *path_;
Arrival path_arrival_;
Tag *path_tag_;
int path_rf_index_;
PathAPIndex path_ap_index_;
PathVertex prev_path_;
TimingArc *prev_arc_;
float dcalc_tol_;
};
PrevPathVisitor::PrevPathVisitor(const Path *path,
SearchPred *pred,
const StaState *sta) :
PathVisitor(pred, sta),
path_(path),
path_arrival_(path->arrival(sta)),
path_tag_(path->tag(sta)),
path_rf_index_(path->rfIndex(sta)),
path_ap_index_(path->pathAnalysisPtIndex(sta)),
prev_path_(),
prev_arc_(nullptr),
dcalc_tol_(sta->graphDelayCalc()->incrementalDelayTolerance())
{
}
VertexVisitor *
PrevPathVisitor::copy() const
{
return new PrevPathVisitor(path_, pred_, this);
}
bool
PrevPathVisitor::visitFromToPath(const Pin *,
Vertex *,
const RiseFall *,
Tag *from_tag,
PathVertex *from_path,
const Arrival &,
Edge *,
TimingArc *arc,
ArcDelay,
Vertex *,
const RiseFall *to_rf,
Tag *to_tag,
Arrival &to_arrival,
const MinMax *,
const PathAnalysisPt *path_ap)
{
PathAPIndex path_ap_index = path_ap->index();
if (to_rf->index() == path_rf_index_
&& path_ap_index == path_ap_index_
&& delayEqual(to_arrival, path_arrival_)
&& (tagMatch(to_tag, path_tag_, this)
// If the filter exception became active searching from
// from_path to to_path the tag includes the filter, but
// to_vertex still has paths from previous searches that do
// not have the filter.
|| (!from_tag->isFilter()
&& to_tag->isFilter()
&& tagMatch(unfilteredTag(to_tag), path_tag_, this)))) {
int arrival_index;
bool arrival_exists;
from_path->arrivalIndex(arrival_index, arrival_exists);
if (arrival_exists) {
prev_path_ = from_path;
prev_arc_ = arc;
// Stop looking for the previous path/arc.
return false;
}
}
return true;
}
Tag *
PrevPathVisitor::unfilteredTag(const Tag *tag) const
{
ExceptionStateSet *unfiltered_states = nullptr;
const ExceptionStateSet *states = tag->states();
ExceptionStateSet::ConstIterator state_iter(states);
while (state_iter.hasNext()) {
ExceptionState *state = state_iter.next();
ExceptionPath *except = state->exception();
if (!except->isFilter()) {
if (unfiltered_states == nullptr)
unfiltered_states = new ExceptionStateSet();
unfiltered_states->insert(state);
}
}
return search_->findTag(tag->transition(),
corners_->findPathAnalysisPt(tag->pathAPIndex()),
tag->clkInfo(),
tag->isClock(),
tag->inputDelay(),
tag->isSegmentStart(),
unfiltered_states, true);
}
////////////////////////////////////////////////////////////////
void
PathVertex::prevPath(const StaState *sta,
// Return values.
PathVertex &prev_path,
TimingArc *&prev_arc) const
{
PrevPred2 pred(sta);
PrevPathVisitor visitor(this, &pred, sta);
visitor.visitFaninPaths(vertex(sta));
prev_path = visitor.prevPath();
prev_arc = visitor.prevArc();
}
void
PathVertex::prevPath(const StaState *sta,
// Return values.
PathVertex &prev_path) const
{
PrevPred2 pred(sta);
PrevPathVisitor visitor(this, &pred, sta);
visitor.visitFaninPaths(vertex(sta));
prev_path = visitor.prevPath();
}
void
PathVertex::prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const
{
const Graph *graph = sta->graph();
Vertex *vertex = this->vertex(graph);
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);
}
}
////////////////////////////////////////////////////////////////
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const StaState *sta) :
search_(sta->search()),
vertex_(vertex),
rf_(nullptr),
path_ap_(nullptr),
min_max_(nullptr)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
arrival_iter_.init(tag_group->arrivalMap());
findNext();
}
}
// Iterate over vertex paths with the same transition and
// analysis pt but different but different tags.
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const StaState *sta) :
search_(sta->search()),
vertex_(vertex),
rf_(rf),
path_ap_(path_ap),
min_max_(nullptr)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
arrival_iter_.init(tag_group->arrivalMap());
findNext();
}
}
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max,
const StaState *sta) :
search_(sta->search()),
vertex_(vertex),
rf_(rf),
path_ap_(nullptr),
min_max_(min_max)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
arrival_iter_.init(tag_group->arrivalMap());
findNext();
}
}
VertexPathIterator::VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const MinMax *min_max,
const StaState *sta) :
search_(sta->search()),
vertex_(vertex),
rf_(rf),
path_ap_(path_ap),
min_max_(min_max)
{
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
arrival_iter_.init(tag_group->arrivalMap());
findNext();
}
}
VertexPathIterator::~VertexPathIterator()
{
}
bool
VertexPathIterator::hasNext()
{
return !next_.isNull();
}
void
VertexPathIterator::findNext()
{
while (arrival_iter_.hasNext()) {
Tag *tag;
int arrival_index;
arrival_iter_.next(tag, arrival_index);
if ((rf_ == nullptr
|| tag->rfIndex() == rf_->index())
&& (path_ap_ == nullptr
|| tag->pathAPIndex() == path_ap_->index())
&& (min_max_ == nullptr
|| tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) {
next_.init(vertex_, tag, arrival_index);
return;
}
}
next_.init();
}
PathVertex *
VertexPathIterator::next()
{
path_ = next_;
findNext();
return &path_;
}
} // namespace

View File

@ -1,201 +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 "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

View File

@ -37,7 +37,7 @@
#include "Corner.hh" #include "Corner.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
#include "PathExpanded.hh" #include "PathExpanded.hh"
#include "PathRef.hh" #include "Path.hh"
#include "power/Power.hh" #include "power/Power.hh"
#include "Sta.hh" #include "Sta.hh"
@ -318,9 +318,9 @@ PropertyValue::PropertyValue(ClockSet *value) :
} }
} }
PropertyValue::PropertyValue(PathRefSeq *value) : PropertyValue::PropertyValue(ConstPathSeq *value) :
type_(type_path_refs), type_(type_paths),
path_refs_(new PathRefSeq(*value)), paths_(new ConstPathSeq(*value)),
unit_(nullptr) unit_(nullptr)
{ {
} }
@ -384,8 +384,8 @@ PropertyValue::PropertyValue(const PropertyValue &value) :
case Type::type_clks: case Type::type_clks:
clks_ = value.clks_ ? new ClockSeq(*value.clks_) : nullptr; clks_ = value.clks_ ? new ClockSeq(*value.clks_) : nullptr;
break; break;
case Type::type_path_refs: case Type::type_paths:
path_refs_ = value.path_refs_ ? new PathRefSeq(*value.path_refs_) : nullptr; paths_ = value.paths_ ? new ConstPathSeq(*value.paths_) : nullptr;
break; break;
case Type::type_pwr_activity: case Type::type_pwr_activity:
pwr_activity_ = value.pwr_activity_; pwr_activity_ = value.pwr_activity_;
@ -450,8 +450,8 @@ PropertyValue::PropertyValue(PropertyValue &&value) :
// Steal the value. // Steal the value.
value.clks_ = nullptr; value.clks_ = nullptr;
break; break;
case Type::type_path_refs: case Type::type_paths:
path_refs_ = value.path_refs_; paths_ = value.paths_;
// Steal the value. // Steal the value.
value.clks_ = nullptr; value.clks_ = nullptr;
break; break;
@ -473,8 +473,8 @@ PropertyValue::~PropertyValue()
case Type::type_pins: case Type::type_pins:
delete pins_; delete pins_;
break; break;
case Type::type_path_refs: case Type::type_paths:
delete path_refs_; delete paths_;
break; break;
default: default:
break; break;
@ -535,8 +535,8 @@ PropertyValue::operator=(const PropertyValue &value)
case Type::type_clks: case Type::type_clks:
clks_ = value.clks_ ? new ClockSeq(*value.clks_) : nullptr; clks_ = value.clks_ ? new ClockSeq(*value.clks_) : nullptr;
break; break;
case Type::type_path_refs: case Type::type_paths:
path_refs_ = value.path_refs_ ? new PathRefSeq(*value.path_refs_) : nullptr; paths_ = value.paths_ ? new ConstPathSeq(*value.paths_) : nullptr;
break; break;
case Type::type_pwr_activity: case Type::type_pwr_activity:
pwr_activity_ = value.pwr_activity_; pwr_activity_ = value.pwr_activity_;
@ -602,8 +602,8 @@ PropertyValue::operator=(PropertyValue &&value)
clks_ = value.clks_; clks_ = value.clks_;
value.clks_ = nullptr; value.clks_ = nullptr;
break; break;
case Type::type_path_refs: case Type::type_paths:
path_refs_ = value.path_refs_; paths_ = value.paths_;
value.clks_ = nullptr; value.clks_ = nullptr;
break; break;
case Type::type_pwr_activity: case Type::type_pwr_activity:
@ -650,7 +650,7 @@ PropertyValue::asString(const Network *network) const
case Type::type_none: case Type::type_none:
case Type::type_pins: case Type::type_pins:
case Type::type_clks: case Type::type_clks:
case Type::type_path_refs: case Type::type_paths:
case Type::type_pwr_activity: case Type::type_pwr_activity:
return nullptr; return nullptr;
} }
@ -1271,10 +1271,10 @@ getProperty(PathEnd *end,
return PropertyValue(delayPropertyValue(end->slack(sta), sta)); return PropertyValue(delayPropertyValue(end->slack(sta), sta));
else if (stringEqual(property, "points")) { else if (stringEqual(property, "points")) {
PathExpanded expanded(end->path(), sta); PathExpanded expanded(end->path(), sta);
PathRefSeq paths; ConstPathSeq paths;
for (size_t i = expanded.startIndex(); i < expanded.size(); i++) { for (size_t i = expanded.startIndex(); i < expanded.size(); i++) {
const PathRef *path = expanded.path(i); const Path *path = expanded.path(i);
paths.push_back(*path); paths.push_back(path);
} }
return PropertyValue(&paths); return PropertyValue(&paths);
} }
@ -1283,16 +1283,16 @@ getProperty(PathEnd *end,
} }
PropertyValue PropertyValue
getProperty(PathRef *path, getProperty(Path *path,
const char *property, const char *property,
Sta *sta) Sta *sta)
{ {
if (stringEqual(property, "pin")) if (stringEqual(property, "pin"))
return PropertyValue(path->pin(sta)); return PropertyValue(path->pin(sta));
else if (stringEqual(property, "arrival")) else if (stringEqual(property, "arrival"))
return PropertyValue(delayPropertyValue(path->arrival(sta), sta)); return PropertyValue(delayPropertyValue(path->arrival(), sta));
else if (stringEqual(property, "required")) else if (stringEqual(property, "required"))
return PropertyValue(delayPropertyValue(path->required(sta), sta)); return PropertyValue(delayPropertyValue(path->required(), sta));
else if (stringEqual(property, "slack")) else if (stringEqual(property, "slack"))
return PropertyValue(delayPropertyValue(path->slack(sta), sta)); return PropertyValue(delayPropertyValue(path->slack(sta), sta));
else else

View File

@ -48,13 +48,12 @@
#include "GraphDelayCalc.hh" #include "GraphDelayCalc.hh"
#include "ClkInfo.hh" #include "ClkInfo.hh"
#include "Tag.hh" #include "Tag.hh"
#include "PathVertex.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "PathGroup.hh" #include "PathGroup.hh"
#include "CheckMinPulseWidths.hh" #include "CheckMinPulseWidths.hh"
#include "CheckMinPeriods.hh" #include "CheckMinPeriods.hh"
#include "CheckMaxSkews.hh" #include "CheckMaxSkews.hh"
#include "PathRef.hh" #include "Path.hh"
#include "Search.hh" #include "Search.hh"
#include "PathExpanded.hh" #include "PathExpanded.hh"
#include "Latches.hh" #include "Latches.hh"
@ -925,7 +924,7 @@ ReportPath::reportFull(const PathEndDataCheck *end) const
// It is like a target because crpr and uncertainty are reported. // It is like a target because crpr and uncertainty are reported.
// It is always propagated, even if the clock is ideal. // It is always propagated, even if the clock is ideal.
reportTgtClk(end, 0.0, true); reportTgtClk(end, 0.0, true);
const PathVertex *data_clk_path = end->dataClkPath(); const Path *data_clk_path = end->dataClkPath();
if (!data_clk_path->isClock(this)) { if (!data_clk_path->isClock(this)) {
// Report the path from the clk network to the data check. // Report the path from the clk network to the data check.
PathExpanded clk_expanded(data_clk_path, this); PathExpanded clk_expanded(data_clk_path, this);
@ -1037,7 +1036,7 @@ string
ReportPath::pathStartpoint(const PathEnd *end, ReportPath::pathStartpoint(const PathEnd *end,
const PathExpanded &expanded) const const PathExpanded &expanded) const
{ {
const PathRef *start = expanded.startPath(); const Path *start = expanded.startPath();
Pin *pin = start->pin(graph_); Pin *pin = start->pin(graph_);
const char *pin_name = cmd_network_->pathName(pin); const char *pin_name = cmd_network_->pathName(pin);
if (network_->isTopLevelPort(pin)) { if (network_->isTopLevelPort(pin)) {
@ -1103,7 +1102,7 @@ ReportPath::reportJson(const PathEnd *end,
sdc_network_->pathName(endpoint)); sdc_network_->pathName(endpoint));
const ClockEdge *src_clk_edge = end->sourceClkEdge(this); const ClockEdge *src_clk_edge = end->sourceClkEdge(this);
const PathVertex *tgt_clk_path = end->targetClkPath(); const Path *tgt_clk_path = end->targetClkPath();
if (src_clk_edge) { if (src_clk_edge) {
stringAppend(result, " \"source_clock\": \"%s\",\n", stringAppend(result, " \"source_clock\": \"%s\",\n",
src_clk_edge->clock()->name()); src_clk_edge->clock()->name());
@ -1181,7 +1180,7 @@ ReportPath::reportJson(const PathExpanded &expanded,
{ {
stringAppend(result, "%*s\"%s\": [\n", indent, "", path_name); stringAppend(result, "%*s\"%s\": [\n", indent, "", path_name);
for (size_t i = 0; i < expanded.size(); i++) { for (size_t i = 0; i < expanded.size(); i++) {
const PathRef *path = expanded.path(i); const Path *path = expanded.path(i);
const Pin *pin = path->vertex(this)->pin(); const Pin *pin = path->vertex(this)->pin();
const Net *net = network_->net(pin); const Net *net = network_->net(pin);
const Instance *inst = network_->instance(pin); const Instance *inst = network_->instance(pin);
@ -1238,7 +1237,7 @@ ReportPath::reportJson(const PathExpanded &expanded,
stringAppend(result, "%*s \"arrival\": %.3e,\n", stringAppend(result, "%*s \"arrival\": %.3e,\n",
indent, "", indent, "",
delayAsFloat(path->arrival(this))); delayAsFloat(path->arrival()));
if (is_driver) if (is_driver)
stringAppend(result, "%*s \"capacitance\": %.3e,\n", stringAppend(result, "%*s \"capacitance\": %.3e,\n",
indent, "", indent, "",
@ -1592,7 +1591,7 @@ ReportPath::reportShort(const MaxSkewCheck *check) const
reportDescription(what.c_str(), line); reportDescription(what.c_str(), line);
const EarlyLate *early_late = EarlyLate::early(); const EarlyLate *early_late = EarlyLate::early();
reportSpaceFieldDelay(check->maxSkew(this), early_late, line); reportSpaceFieldDelay(check->maxSkew(this), early_late, line);
reportSpaceFieldDelay(check->skew(this), early_late, line); reportSpaceFieldDelay(check->skew(), early_late, line);
reportSpaceSlack(check->slack(this), line); reportSpaceSlack(check->slack(this), line);
report_->reportLineString(line); report_->reportLineString(line);
} }
@ -1621,7 +1620,7 @@ ReportPath::reportVerbose(const MaxSkewCheck *check) const
reportDashLine(); reportDashLine();
reportLine("allowable skew", check->maxSkew(this), EarlyLate::early()); reportLine("allowable skew", check->maxSkew(this), EarlyLate::early());
reportLine("actual skew", check->skew(this), EarlyLate::late()); reportLine("actual skew", check->skew(), EarlyLate::late());
reportDashLine(); reportDashLine();
reportSlack(check->slack(this)); reportSlack(check->slack(this));
} }
@ -1629,7 +1628,7 @@ ReportPath::reportVerbose(const MaxSkewCheck *check) const
// Based on reportTgtClk. // Based on reportTgtClk.
void void
ReportPath::reportSkewClkPath(const char *arrival_msg, ReportPath::reportSkewClkPath(const char *arrival_msg,
const PathVertex *clk_path) const const Path *clk_path) const
{ {
const ClockEdge *clk_edge = clk_path->clkEdge(this); const ClockEdge *clk_edge = clk_path->clkEdge(this);
const Clock *clk = clk_edge->clock(); const Clock *clk = clk_edge->clock();
@ -1767,9 +1766,9 @@ ReportPath::reportStartpoint(const PathEnd *end,
const PathExpanded &expanded) const const PathExpanded &expanded) const
{ {
const Path *path = end->path(); const Path *path = end->path();
const PathRef *start = expanded.startPath(); const Path *start = expanded.startPath();
const TimingArc *prev_arc = expanded.startPrevArc(); const TimingArc *prev_arc = expanded.startPrevArc();
const Edge *prev_edge = start->prevEdge(prev_arc, this); const Edge *prev_edge = start->prevEdge(this);
const Pin *pin = start->pin(graph_); const Pin *pin = start->pin(graph_);
const ClockEdge *clk_edge = path->clkEdge(this); const ClockEdge *clk_edge = path->clkEdge(this);
const Clock *clk = path->clock(search_); const Clock *clk = path->clock(search_);
@ -1795,10 +1794,9 @@ ReportPath::reportStartpoint(const PathEnd *end,
const char *inst_name = cmd_network_->pathName(inst); const char *inst_name = cmd_network_->pathName(inst);
if (clk_edge) { if (clk_edge) {
const RiseFall *clk_rf = clk_edge->transition(); const RiseFall *clk_rf = clk_edge->transition();
PathRef clk_path; const Path *clk_path = expanded.clkPath();
expanded.clkPath(clk_path); bool clk_inverted = clk_path
bool clk_inverted = !clk_path.isNull() && clk_rf != clk_path->transition(this);
&& clk_rf != clk_path.transition(this);
string clk_name = clkName(clk, clk_inverted); string clk_name = clkName(clk, clk_inverted);
const char *reg_desc = edgeRegLatchDesc(prev_edge, prev_arc); const char *reg_desc = edgeRegLatchDesc(prev_edge, prev_arc);
auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str()); auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
@ -1830,8 +1828,8 @@ ReportPath::reportStartpoint(const PathEnd *end,
bool bool
ReportPath::pathFromClkPin(const PathExpanded &expanded) const ReportPath::pathFromClkPin(const PathExpanded &expanded) const
{ {
const PathRef *start = expanded.startPath(); const Path *start = expanded.startPath();
const PathRef *end = expanded.endPath(); const Path *end = expanded.endPath();
const Pin *start_pin = start->pin(graph_); const Pin *start_pin = start->pin(graph_);
return pathFromClkPin(end, start_pin); return pathFromClkPin(end, start_pin);
} }
@ -2069,13 +2067,12 @@ ReportPath::reportSrcClkAndPath(const Path *path,
bool path_from_input = false; bool path_from_input = false;
bool input_has_ref_path = false; bool input_has_ref_path = false;
Arrival clk_delay, clk_end_time; Arrival clk_delay, clk_end_time;
PathRef clk_path; const Path *clk_path = expanded.clkPath();
expanded.clkPath(clk_path);
const RiseFall *clk_end_rf; const RiseFall *clk_end_rf;
if (!clk_path.isNull()) { if (clk_path) {
clk_end_time = search_->clkPathArrival(&clk_path) + time_offset; clk_end_time = search_->clkPathArrival(clk_path) + time_offset;
clk_delay = clk_end_time - clk_time; clk_delay = clk_end_time - clk_time;
clk_end_rf = clk_path.transition(this); clk_end_rf = clk_path->transition(this);
} }
else { else {
// Path from input port or clk used as data. // Path from input port or clk used as data.
@ -2083,16 +2080,16 @@ ReportPath::reportSrcClkAndPath(const Path *path,
clk_delay = clk_insertion + clk_latency; clk_delay = clk_insertion + clk_latency;
clk_end_time = clk_time + clk_delay; clk_end_time = clk_time + clk_delay;
const PathRef *first_path = expanded.startPath(); const Path *first_path = expanded.startPath();
const InputDelay *input_delay = pathInputDelay(first_path); const InputDelay *input_delay = pathInputDelay(first_path);
if (input_delay) { if (input_delay) {
path_from_input = true; path_from_input = true;
const Pin *ref_pin = input_delay->refPin(); const Pin *ref_pin = input_delay->refPin();
if (ref_pin && clk->isPropagated()) { if (ref_pin && clk->isPropagated()) {
PathRef ref_path; Path ref_path;
pathInputDelayRefPath(first_path, input_delay, ref_path); pathInputDelayRefPath(first_path, input_delay, ref_path);
if (!ref_path.isNull()) { if (!ref_path.isNull()) {
const Arrival &ref_end_time = ref_path.arrival(this); const Arrival &ref_end_time = ref_path.arrival();
clk_delay = ref_end_time - clk_time; clk_delay = ref_end_time - clk_time;
clk_end_time = ref_end_time + time_offset; clk_end_time = ref_end_time + time_offset;
input_has_ref_path = true; input_has_ref_path = true;
@ -2105,8 +2102,7 @@ ReportPath::reportSrcClkAndPath(const Path *path,
bool clk_used_as_data = pathFromClkPin(expanded); bool clk_used_as_data = pathFromClkPin(expanded);
bool is_prop = isPropagated(path); bool is_prop = isPropagated(path);
const EarlyLate *early_late = min_max; const EarlyLate *early_late = min_max;
if (reportGenClkSrcPath(clk_path.isNull() ? nullptr : &clk_path, if (reportGenClkSrcPath(clk_path, clk, clk_rf, min_max, early_late)
clk, clk_rf, min_max, early_late)
&& !(path_from_input && !input_has_ref_path)) { && !(path_from_input && !input_has_ref_path)) {
reportClkLine(clk, clk_name.c_str(), clk_end_rf, clk_time, reportClkLine(clk, clk_name.c_str(), clk_end_rf, clk_time,
min_max); min_max);
@ -2137,7 +2133,7 @@ ReportPath::reportSrcClkAndPath(const Path *path,
reportPath1(path, expanded, true, time_offset); reportPath1(path, expanded, true, time_offset);
else { else {
Arrival clk_arrival = clk_end_time; Arrival clk_arrival = clk_end_time;
Arrival end_arrival = path->arrival(this) + time_offset; Arrival end_arrival = path->arrival() + time_offset;
Delay clk_delay = end_arrival - clk_arrival; Delay clk_delay = end_arrival - clk_arrival;
reportLine("clock network delay", clk_delay, reportLine("clock network delay", clk_delay,
end_arrival, early_late); end_arrival, early_late);
@ -2395,10 +2391,10 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
{ {
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late); PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
PathVertex src_path = Path *src_path = search_->genclks()->srcPath(clk, clk_pin,
search_->genclks()->srcPath(clk, clk_pin, clk_rf, insert_ap); clk_rf, insert_ap);
if (!src_path.isNull()) { if (src_path) {
ClkInfo *src_clk_info = src_path.clkInfo(search_); ClkInfo *src_clk_info = src_path->clkInfo(this);
const ClockEdge *src_clk_edge = src_clk_info->clkEdge(); const ClockEdge *src_clk_edge = src_clk_info->clkEdge();
const Clock *src_clk = src_clk_info->clock(); const Clock *src_clk = src_clk_info->clock();
if (src_clk) { if (src_clk) {
@ -2419,12 +2415,12 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
early_late, path_ap); early_late, path_ap);
reportClkSrcLatency(insertion, gclk_time, early_late); reportClkSrcLatency(insertion, gclk_time, early_late);
} }
PathExpanded src_expanded(&src_path, this); PathExpanded src_expanded(src_path, this);
reportPath4(&src_path, src_expanded, skip_first_path, false, reportPath4(src_path, src_expanded, skip_first_path, false,
clk_used_as_data, gclk_time); clk_used_as_data, gclk_time);
if (!clk->isPropagated()) if (!clk->isPropagated())
reportLine("clock network delay (ideal)", 0.0, reportLine("clock network delay (ideal)", 0.0,
src_path.arrival(this), min_max); src_path->arrival(), min_max);
} }
} }
else { else {
@ -2433,7 +2429,7 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
else if (!clk_used_as_data) else if (!clk_used_as_data)
reportLine("clock network delay (ideal)", 0.0, gclk_time, min_max); reportLine("clock network delay (ideal)", 0.0, gclk_time, min_max);
} }
return !src_path.isNull(); return src_path != nullptr;
} }
void void
@ -2610,22 +2606,21 @@ ReportPath::reportPath1(const Path *path,
bool clk_used_as_data, bool clk_used_as_data,
float time_offset) const float time_offset) const
{ {
const PathRef *d_path, *q_path; const Path *d_path, *q_path;
Edge *d_q_edge; Edge *d_q_edge;
expanded.latchPaths(d_path, q_path, d_q_edge); expanded.latchPaths(d_path, q_path, d_q_edge);
if (d_path) { if (d_path) {
Arrival latch_time_given, latch_enable_time; Arrival latch_time_given, latch_enable_time;
PathVertex latch_enable_path; Path *latch_enable_path;
latches_->latchTimeGivenToStartpoint(d_path, q_path, d_q_edge, latches_->latchTimeGivenToStartpoint(d_path, q_path, d_q_edge,
latch_time_given, latch_time_given, latch_enable_path);
latch_enable_path); if (latch_enable_path) {
if (!latch_enable_path.isNull()) { const EarlyLate *early_late = latch_enable_path->minMax(this);
const EarlyLate *early_late = latch_enable_path.minMax(this); latch_enable_time = search_->clkPathArrival(latch_enable_path);
latch_enable_time = search_->clkPathArrival(&latch_enable_path);
if (reportClkPath()) { if (reportClkPath()) {
PathExpanded enable_expanded(&latch_enable_path, this); PathExpanded enable_expanded(latch_enable_path, this);
// Report the path to the latch enable. // Report the path to the latch enable.
reportPath2(&latch_enable_path, enable_expanded, false, reportPath2(latch_enable_path, enable_expanded, false,
time_offset); time_offset);
} }
Arrival time = latch_enable_time + latch_time_given; Arrival time = latch_enable_time + latch_time_given;
@ -2689,8 +2684,8 @@ ReportPath::reportPath4(const Path *path,
Arrival prev_time(0.0); Arrival prev_time(0.0);
if (skip_first_path) { if (skip_first_path) {
path_first_index = 1; path_first_index = 1;
const PathRef *start = expanded.path(0); const Path *start = expanded.path(0);
prev_time = start->arrival(this) + time_offset; prev_time = start->arrival() + time_offset;
} }
size_t path_last_index = expanded.size() - 1; size_t path_last_index = expanded.size() - 1;
if (skip_last_path if (skip_last_path
@ -2719,15 +2714,14 @@ ReportPath::reportPath5(const Path *path,
const MinMax *min_max = path->minMax(this); const MinMax *min_max = path->minMax(this);
DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt(); DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt();
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
PathRef clk_path; const Path *clk_path = expanded.clkPath();
expanded.clkPath(clk_path); Vertex *clk_start = clk_path ? clk_path->vertex(this) : nullptr;
Vertex *clk_start = clk_path.vertex(this);
for (size_t i = path_first_index; i <= path_last_index; i++) { for (size_t i = path_first_index; i <= path_last_index; i++) {
const PathRef *path1 = expanded.path(i); const Path *path1 = expanded.path(i);
TimingArc *prev_arc = expanded.prevArc(i); const TimingArc *prev_arc = path1->prevArc(this);
Vertex *vertex = path1->vertex(this); Vertex *vertex = path1->vertex(this);
Pin *pin = vertex->pin(); Pin *pin = vertex->pin();
Arrival time = path1->arrival(this) + time_offset; Arrival time = path1->arrival() + time_offset;
Delay incr = 0.0; Delay incr = 0.0;
const char *line_case = nullptr; const char *line_case = nullptr;
bool is_clk_start = path1->vertex(this) == clk_start; bool is_clk_start = path1->vertex(this) == clk_start;
@ -2747,7 +2741,7 @@ ReportPath::reportPath5(const Path *path,
// First path. // First path.
reportInputExternalDelay(path1, time_offset); reportInputExternalDelay(path1, time_offset);
size_t next_index = i + 1; size_t next_index = i + 1;
const PathRef *next_path = expanded.path(next_index); const Path *next_path = expanded.path(next_index);
if (network_->isTopLevelPort(pin) if (network_->isTopLevelPort(pin)
&& next_path && next_path
&& !nextArcAnnotated(next_path, next_index, expanded, ap_index) && !nextArcAnnotated(next_path, next_index, expanded, ap_index)
@ -2756,7 +2750,7 @@ ReportPath::reportPath5(const Path *path,
// The delay calculator annotates wire delays on the edges // The delay calculator annotates wire delays on the edges
// from the input to the loads. Report the wire delay on the // from the input to the loads. Report the wire delay on the
// input pin instead. // input pin instead.
Arrival next_time = next_path->arrival(this) + time_offset; Arrival next_time = next_path->arrival() + time_offset;
incr = delayIncr(next_time, time, min_max); incr = delayIncr(next_time, time, min_max);
time = next_time; time = next_time;
line_case = "input_drive"; line_case = "input_drive";
@ -2833,7 +2827,7 @@ ReportPath::reportPath5(const Path *path,
prev_time = time; prev_time = time;
} }
else { else {
reportHierPinsThru(path1, prev_arc); reportHierPinsThru(path1);
if (report_input_pin_ if (report_input_pin_
|| (i == 0) || (i == 0)
|| (i == path_last_index) || (i == path_last_index)
@ -2852,11 +2846,10 @@ ReportPath::reportPath5(const Path *path,
} }
void void
ReportPath::reportHierPinsThru(const Path *path, ReportPath::reportHierPinsThru(const Path *path) const
const TimingArc *prev_arc) const
{ {
if (report_hier_pins_) { if (report_hier_pins_) {
const Edge *prev_edge = path->prevEdge(prev_arc, this); const Edge *prev_edge = path->prevEdge(this);
if (prev_edge && prev_edge->isWire()) { if (prev_edge && prev_edge->isWire()) {
for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) { for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) {
const string what = descriptionField(hpin); const string what = descriptionField(hpin);
@ -2880,13 +2873,13 @@ ReportPath::delayIncr(Delay time,
} }
bool bool
ReportPath::nextArcAnnotated(const PathRef *next_path, ReportPath::nextArcAnnotated(const Path *next_path,
size_t next_index, size_t next_index,
const PathExpanded &expanded, const PathExpanded &expanded,
DcalcAPIndex ap_index) const DcalcAPIndex ap_index) const
{ {
TimingArc *arc = expanded.prevArc(next_index); const TimingArc *arc = expanded.path(next_index)->prevArc(this);
Edge *edge = next_path->prevEdge(arc, this); Edge *edge = next_path->prevEdge(this);
return graph_->arcDelayAnnotated(edge, arc, ap_index); return graph_->arcDelayAnnotated(edge, arc, ap_index);
} }
@ -2983,13 +2976,13 @@ ReportPath::reportInputExternalDelay(const Path *first_path,
const Pin *first_pin = first_path->pin(graph_); const Pin *first_pin = first_path->pin(graph_);
if (!pathFromClkPin(first_path, first_pin)) { if (!pathFromClkPin(first_path, first_pin)) {
const RiseFall *rf = first_path->transition(this); const RiseFall *rf = first_path->transition(this);
Arrival time = first_path->arrival(this) + time_offset; Arrival time = first_path->arrival() + time_offset;
const EarlyLate *early_late = first_path->minMax(this); const EarlyLate *early_late = first_path->minMax(this);
InputDelay *input_delay = pathInputDelay(first_path); InputDelay *input_delay = pathInputDelay(first_path);
if (input_delay) { if (input_delay) {
const Pin *ref_pin = input_delay->refPin(); const Pin *ref_pin = input_delay->refPin();
if (ref_pin) { if (ref_pin) {
PathRef ref_path; Path ref_path;
pathInputDelayRefPath(first_path, input_delay, ref_path); pathInputDelayRefPath(first_path, input_delay, ref_path);
if (!ref_path.isNull() && reportClkPath()) { if (!ref_path.isNull() && reportClkPath()) {
PathExpanded ref_expanded(&ref_path, this); PathExpanded ref_expanded(&ref_path, this);
@ -3018,7 +3011,7 @@ void
ReportPath::pathInputDelayRefPath(const Path *path, ReportPath::pathInputDelayRefPath(const Path *path,
const InputDelay *input_delay, const InputDelay *input_delay,
// Return value. // Return value.
PathRef &ref_path) const Path &ref_path) const
{ {
const Pin *ref_pin = input_delay->refPin(); const Pin *ref_pin = input_delay->refPin();
const RiseFall *ref_rf = input_delay->refTransition(); const RiseFall *ref_rf = input_delay->refTransition();
@ -3028,10 +3021,10 @@ ReportPath::pathInputDelayRefPath(const Path *path,
const ClockEdge *clk_edge = path->clkEdge(this); const ClockEdge *clk_edge = path->clkEdge(this);
VertexPathIterator path_iter(ref_vertex, ref_rf, path_ap, this); VertexPathIterator path_iter(ref_vertex, ref_rf, path_ap, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
if (path->isClock(this) if (path->isClock(this)
&& path->clkEdge(this) == clk_edge) { && path->clkEdge(this) == clk_edge) {
ref_path.init(path); ref_path = path;
break; break;
} }
} }

View File

@ -326,8 +326,7 @@ protected:
bool report_clk_path, bool report_clk_path,
Arrival prev_time, Arrival prev_time,
float time_offset) const; float time_offset) const;
void reportHierPinsThru(const Path *path, void reportHierPinsThru(const Path *path) const;
const TimingArc *prev_arc) const;
void reportInputExternalDelay(const Path *path, void reportInputExternalDelay(const Path *path,
float time_offset) const; float time_offset) const;
void reportLine(const char *what, void reportLine(const char *what,
@ -426,7 +425,7 @@ protected:
const MinMax *min_max) const; const MinMax *min_max) const;
const char *mpwCheckHiLow(const MinPulseWidthCheck *check) const; const char *mpwCheckHiLow(const MinPulseWidthCheck *check) const;
void reportSkewClkPath(const char *arrival_msg, void reportSkewClkPath(const char *arrival_msg,
const PathVertex *clk_path) const; const Path *clk_path) const;
const char *edgeRegLatchDesc(const Edge *edge, const char *edgeRegLatchDesc(const Edge *edge,
const TimingArc *arc) const; const TimingArc *arc) const;
const char *checkRegLatchDesc(const TimingRole *role, const char *checkRegLatchDesc(const TimingRole *role,
@ -434,7 +433,7 @@ protected:
const char *regDesc(const RiseFall *clk_rf) const; const char *regDesc(const RiseFall *clk_rf) const;
const char *latchDesc(const RiseFall *clk_rf) const; const char *latchDesc(const RiseFall *clk_rf) const;
void pathClkPath(const Path *path, void pathClkPath(const Path *path,
const PathRef &clk_path) const; const Path &clk_path) const;
bool isPropagated(const Path *clk_path) const; bool isPropagated(const Path *clk_path) const;
bool isPropagated(const Path *clk_path, bool isPropagated(const Path *clk_path,
const Clock *clk) const; const Clock *clk) const;
@ -443,10 +442,10 @@ protected:
const Pin *start_pin) const; const Pin *start_pin) const;
void latchPaths(const Path *path, void latchPaths(const Path *path,
// Return values. // Return values.
PathRef &d_path, Path &d_path,
PathRef &q_path, Path &q_path,
Edge *&d_q_edge) const; Edge *&d_q_edge) const;
bool nextArcAnnotated(const PathRef *next_path, bool nextArcAnnotated(const Path *next_path,
size_t next_index, size_t next_index,
const PathExpanded &expanded, const PathExpanded &expanded,
DcalcAPIndex ap_index) const; DcalcAPIndex ap_index) const;
@ -458,7 +457,7 @@ protected:
void pathInputDelayRefPath(const Path *path, void pathInputDelayRefPath(const Path *path,
const InputDelay *input_delay, const InputDelay *input_delay,
// Return value. // Return value.
PathRef &ref_path) const; Path &ref_path) const;
const char *asRisingFalling(const RiseFall *rf) const; const char *asRisingFalling(const RiseFall *rf) const;
const char *asRiseFall(const RiseFall *rf) const; const char *asRiseFall(const RiseFall *rf) const;
Delay delayIncr(Delay time, Delay delayIncr(Delay time,

View File

@ -54,9 +54,7 @@
#include "Bfs.hh" #include "Bfs.hh"
#include "Corner.hh" #include "Corner.hh"
#include "Sim.hh" #include "Sim.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "PathPrev.hh"
#include "PathRef.hh"
#include "ClkInfo.hh" #include "ClkInfo.hh"
#include "Tag.hh" #include "Tag.hh"
#include "TagGroup.hh" #include "TagGroup.hh"
@ -142,11 +140,7 @@ DynLoopSrchPred::hasPendingLoopPaths(Edge *edge,
Corners *corners = search->corners(); Corners *corners = search->corners();
Vertex *from_vertex = edge->from(graph); Vertex *from_vertex = edge->from(graph);
TagGroup *prev_tag_group = search->tagGroup(from_vertex); TagGroup *prev_tag_group = search->tagGroup(from_vertex);
ArrivalMap::Iterator arrival_iter(tag_bldr_->arrivalMap()); for (auto const [from_tag, path_index] : tag_bldr_->pathIndexMap()) {
while (arrival_iter.hasNext()) {
Tag *from_tag;
int arrival_index;
arrival_iter.next(from_tag, arrival_index);
if (from_tag->isLoop()) { if (from_tag->isLoop()) {
// Loop false path exceptions apply to rise/fall edges so to_rf // Loop false path exceptions apply to rise/fall edges so to_rf
// does not matter. // does not matter.
@ -255,7 +249,6 @@ 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;
@ -274,6 +267,7 @@ Search::initVars()
Search::~Search() Search::~Search()
{ {
deletePathGroups();
deletePaths(); deletePaths();
deleteTags(); deleteTags();
delete tag_set_; delete tag_set_;
@ -299,7 +293,6 @@ Search::~Search()
delete genclks_; delete genclks_;
delete filtered_arrivals_; delete filtered_arrivals_;
deleteFilter(); deleteFilter();
deletePathGroups();
} }
void void
@ -433,6 +426,8 @@ Search::deletePathsIncr(Vertex *vertex)
void void
Search::deletePaths(Vertex *vertex) Search::deletePaths(Vertex *vertex)
{ {
debugPrint(debug_, "search", 4, "delete paths %s",
vertex->name(network_));
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
if (tag_group) if (tag_group)
graph_->deletePaths(vertex); graph_->deletePaths(vertex);
@ -450,8 +445,8 @@ Search::findPathEnds(ExceptionFrom *from,
bool unconstrained, bool unconstrained,
const Corner *corner, const Corner *corner,
const MinMaxAll *min_max, const MinMaxAll *min_max,
int group_path_count, size_t group_path_count,
int endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
float slack_min, float slack_min,
float slack_max, float slack_max,
@ -490,9 +485,6 @@ Search::findFilteredArrivals(ExceptionFrom *from,
bool thru_latches) bool thru_latches)
{ {
unconstrained_paths_ = unconstrained; unconstrained_paths_ = unconstrained;
// Delete results from last findPathEnds.
// Filtered arrivals are deleted by Sta::searchPreamble.
deletePathGroups();
checkFromThrusTo(from, thrus, to); checkFromThrusTo(from, thrus, to);
filter_from_ = from; filter_from_ = from;
filter_to_ = to; filter_to_ = to;
@ -618,6 +610,7 @@ Search::findFilteredArrivals(bool thru_latches)
int arrival_count = arrival_iter_->visitParallel(max_level, int arrival_count = arrival_iter_->visitParallel(max_level,
arrival_visitor_); arrival_visitor_);
deleteTagsPrev(); deleteTagsPrev();
genclks_->updateSrcPathPrevs();
debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count); debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count);
} }
arrivals_exist_ = true; arrivals_exist_ = true;
@ -725,6 +718,20 @@ Search::deleteVertexBefore(Vertex *vertex)
invalid_endpoints_->erase(vertex); invalid_endpoints_->erase(vertex);
} }
void
Search::deleteEdgeBefore(Edge *edge)
{
Vertex *from = edge->from(graph_);
Vertex *to = edge->to(graph_);
arrivalInvalid(to);
requiredInvalid(from);
VertexPathIterator path_iter(to, graph_);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
path->clearPrevPath(this);
}
}
bool bool
Search::arrivalsValid() Search::arrivalsValid()
{ {
@ -740,6 +747,7 @@ Search::arrivalsInvalid()
// Delete paths to make sure no state is left over. // Delete paths to make sure no state is left over.
// For example, set_disable_timing strands a vertex, which means // For example, set_disable_timing strands a vertex, which means
// the search won't revisit it to clear the previous arrival. // the search won't revisit it to clear the previous arrival.
deletePathGroups();
deletePaths(); deletePaths();
deleteTags(); deleteTags();
genclks_->clear(); genclks_->clear();
@ -865,6 +873,7 @@ Search::findClkArrivals()
arrival_visitor_->init(false, &search_clk); arrival_visitor_->init(false, &search_clk);
arrival_iter_->visitParallel(levelize_->maxLevel(), arrival_visitor_); arrival_iter_->visitParallel(levelize_->maxLevel(), arrival_visitor_);
deleteTagsPrev(); deleteTagsPrev();
genclks_->updateSrcPathPrevs();
arrivals_exist_ = true; arrivals_exist_ = true;
stats.report("Find clk arrivals"); stats.report("Find clk arrivals");
} }
@ -1036,6 +1045,7 @@ Search::findArrivals1(Level level)
Stats stats(debug_, report_); Stats stats(debug_, report_);
int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_); int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_);
deleteTagsPrev(); deleteTagsPrev();
genclks_->updateSrcPathPrevs();
stats.report("Find arrivals"); stats.report("Find arrivals");
if (arrival_iter_->empty() if (arrival_iter_->empty()
&& invalid_arrivals_->empty()) { && invalid_arrivals_->empty()) {
@ -1043,7 +1053,7 @@ Search::findArrivals1(Level level)
arrivals_at_endpoints_exist_ = true; arrivals_at_endpoints_exist_ = true;
} }
arrivals_exist_ = true; arrivals_exist_ = true;
debugPrint(debug_, "search", 1, "found %u arrivals", arrival_count); debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count);
} }
void void
@ -1066,8 +1076,7 @@ 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);
@ -1104,8 +1113,6 @@ 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();
} }
@ -1187,9 +1194,7 @@ ArrivalVisitor::visit(Vertex *vertex)
|| arrivals_changed) || arrivals_changed)
search_->arrivalIterator()->enqueueAdjacentVertices(vertex, adj_pred_); search_->arrivalIterator()->enqueueAdjacentVertices(vertex, adj_pred_);
if (arrivals_changed) { if (arrivals_changed) {
debugPrint(debug_, "search", 4, "arrival changed"); debugPrint(debug_, "search", 4, "arrivals changed");
// Only update arrivals when delays change by more than
// fuzzyEqual can distinguish.
search_->setVertexArrivals(vertex, tag_bldr_); search_->setVertexArrivals(vertex, tag_bldr_);
search_->tnsInvalid(vertex); search_->tnsInvalid(vertex);
constrainedRequiredsInvalid(vertex, is_clk); constrainedRequiredsInvalid(vertex, is_clk);
@ -1239,28 +1244,21 @@ bool
Search::arrivalsChanged(Vertex *vertex, Search::arrivalsChanged(Vertex *vertex,
TagGroupBldr *tag_bldr) TagGroupBldr *tag_bldr)
{ {
Arrival *arrivals1 = graph_->arrivals(vertex); Path *paths1 = graph_->paths(vertex);
PathPrev *prev_paths1 = graph_->prevPaths(vertex); if (paths1) {
if (arrivals1) {
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
if (tag_group == nullptr if (tag_group == nullptr
|| tag_group->arrivalMap()->size() != tag_bldr->arrivalMap()->size()) || tag_group->pathCount() != tag_bldr->pathCount())
return true; return true;
ArrivalMap::Iterator arrival_iter1(tag_group->arrivalMap()); for (auto const [tag1, path_index1] : *tag_group->pathIndexMap()) {
while (arrival_iter1.hasNext()) { Path *path1 = &paths1[path_index1];
Tag *tag1; Path *path2 = tag_bldr->tagMatchPath(tag1);
int arrival_index1; if (path2 == nullptr
arrival_iter1.next(tag1, arrival_index1); || path1->tag(this) != path2->tag(this)
Arrival &arrival1 = arrivals1[arrival_index1]; || !delayEqual(path1->arrival(), path2->arrival())
Tag *tag2; || path1->prevEdge(this) != path2->prevEdge(this)
Arrival arrival2; || path1->prevArc(this) != path2->prevArc(this)
int arrival_index2; || path1->prevPath() != path2->prevPath())
tag_bldr->tagMatchArrival(tag1, tag2, arrival2, arrival_index2);
if (tag2 != tag1
|| !delayEqual(arrival1, arrival2)
|| (prev_paths1
&& !PathPrev::equal(prev_paths1[arrival_index1],
tag_bldr->prevPath(arrival_index2))))
return true; return true;
} }
return false; return false;
@ -1270,11 +1268,11 @@ Search::arrivalsChanged(Vertex *vertex,
} }
bool bool
ArrivalVisitor::visitFromToPath(const Pin *, ArrivalVisitor::visitFromToPath(const Pin * /* from_pin */,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *from_path,
const Arrival &from_arrival, const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
@ -1298,39 +1296,27 @@ ArrivalVisitor::visitFromToPath(const Pin *,
to_tag->asString(this)); to_tag->asString(this));
ClkInfo *to_clk_info = to_tag->clkInfo(); ClkInfo *to_clk_info = to_tag->clkInfo();
bool to_is_clk = to_tag->isClock(); bool to_is_clk = to_tag->isClock();
Arrival arrival; Path *match;
int arrival_index; size_t path_index;
Tag *tag_match; tag_bldr_->tagMatchPath(to_tag, match, path_index);
tag_bldr_->tagMatchArrival(to_tag, tag_match, arrival, arrival_index); if (match == nullptr
if (tag_match == nullptr || delayGreater(to_arrival, match->arrival(), min_max, this)) {
|| delayGreater(to_arrival, arrival, min_max, this)) {
debugPrint(debug_, "search", 3, " %s + %s = %s %s %s", debugPrint(debug_, "search", 3, " %s + %s = %s %s %s",
delayAsString(from_arrival, this), delayAsString(from_arrival, this),
delayAsString(arc_delay, this), delayAsString(arc_delay, this),
delayAsString(to_arrival, this), delayAsString(to_arrival, this),
min_max == MinMax::max() ? ">" : "<", min_max == MinMax::max() ? ">" : "<",
tag_match ? delayAsString(arrival, this) : "MIA"); match ? delayAsString(match->arrival(), this) : "MIA");
PathPrev prev_path; tag_bldr_->setMatchPath(match, path_index, to_tag, to_arrival, from_path, edge, arc);
bool always_save_prev_paths = true;
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,
to_arrival, arrival_index,
&prev_path);
if (crpr_active_ if (crpr_active_
&& !has_fanin_one_ && !has_fanin_one_
&& to_clk_info->hasCrprClkPin() && to_clk_info->hasCrprClkPin()
&& !to_is_clk) { && !to_is_clk) {
tag_bldr_no_crpr_->tagMatchArrival(to_tag, tag_match, tag_bldr_no_crpr_->tagMatchPath(to_tag, match, path_index);
arrival, arrival_index); if (match == nullptr
if (tag_match == nullptr || delayGreater(to_arrival, match->arrival(), min_max, this)) {
|| delayGreater(to_arrival, arrival, min_max, this)) { tag_bldr_no_crpr_->setMatchPath(match, path_index, to_tag, to_arrival,
tag_bldr_no_crpr_->setMatchArrival(to_tag, tag_match, from_path, edge, arc);
to_arrival, arrival_index,
&prev_path);
} }
} }
} }
@ -1341,23 +1327,20 @@ void
ArrivalVisitor::pruneCrprArrivals() ArrivalVisitor::pruneCrprArrivals()
{ {
CheckCrpr *crpr = search_->checkCrpr(); CheckCrpr *crpr = search_->checkCrpr();
ArrivalMap *arrival_map = tag_bldr_->arrivalMap(); PathIndexMap &path_index_map = tag_bldr_->pathIndexMap();
for (auto arrival_itr = arrival_map->cbegin(); arrival_itr != arrival_map->cend(); ) { for (auto path_itr = path_index_map.cbegin(); path_itr != path_index_map.cend(); ) {
Tag *tag = arrival_itr->first; Tag *tag = path_itr->first;
int arrival_index = arrival_itr->second; size_t path_index = path_itr->second;
ClkInfo *clk_info = tag->clkInfo(); ClkInfo *clk_info = tag->clkInfo();
bool deleted_tag = false; 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);
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
Tag *tag_no_crpr; Path *path_no_crpr = tag_bldr_no_crpr_->tagMatchPath(tag);
Arrival max_arrival; if (path_no_crpr) {
int max_arrival_index; Arrival max_arrival = path_no_crpr->arrival();
tag_bldr_no_crpr_->tagMatchArrival(tag, tag_no_crpr, ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this);
max_arrival, max_arrival_index);
if (tag_no_crpr) {
ClkInfo *clk_info_no_crpr = tag_no_crpr->clkInfo();
Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr); Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr);
Arrival max_arrival_max_crpr = (min_max == MinMax::max()) Arrival max_arrival_max_crpr = (min_max == MinMax::max())
? max_arrival - max_crpr ? max_arrival - max_crpr
@ -1367,17 +1350,17 @@ ArrivalVisitor::pruneCrprArrivals()
delayAsString(max_arrival, this), delayAsString(max_arrival, this),
delayAsString(max_crpr, this), delayAsString(max_crpr, this),
delayAsString(max_arrival_max_crpr, this)); delayAsString(max_arrival_max_crpr, this));
Arrival arrival = tag_bldr_->arrival(arrival_index); Arrival arrival = tag_bldr_->arrival(path_index);
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));
arrival_itr = arrival_map->erase(arrival_itr); path_itr = path_index_map.erase(path_itr);
deleted_tag = true; deleted_tag = true;
} }
} }
} }
if (!deleted_tag) if (!deleted_tag)
arrival_itr++; path_itr++;
} }
} }
@ -1506,8 +1489,9 @@ Search::seedArrival(Vertex *vertex)
} }
} }
else { else {
debugPrint(debug_, "search", 2, "arrival enqueue %s", debugPrint(debug_, "search", 4, "arrival enqueue %s %u",
network_->pathName(pin)); network_->pathName(pin),
vertex->level());
arrival_iter_->enqueue(vertex); arrival_iter_->enqueue(vertex);
} }
} }
@ -1599,7 +1583,7 @@ Search::seedClkArrival(const Pin *pin,
sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states); sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states);
Tag *tag = findTag(rf, path_ap, clk_info, true, nullptr, false, states, true); Tag *tag = findTag(rf, path_ap, clk_info, true, nullptr, false, states, true);
Arrival arrival(clk_edge->time() + insertion); Arrival arrival(clk_edge->time() + insertion);
tag_bldr->setArrival(tag, arrival, nullptr); tag_bldr->setArrival(tag, arrival);
} }
void void
@ -1616,7 +1600,7 @@ Search::seedClkDataArrival(const Pin *pin,
if (tag) { if (tag) {
// Data arrivals include insertion delay. // Data arrivals include insertion delay.
Arrival arrival(clk_edge->time() + insertion); Arrival arrival(clk_edge->time() + insertion);
tag_bldr->setArrival(tag, arrival, nullptr); tag_bldr->setArrival(tag, arrival);
} }
} }
@ -1658,7 +1642,7 @@ Search::makeUnclkedPaths(Vertex *vertex,
is_segment_start, is_segment_start,
require_exception); require_exception);
if (tag) { if (tag) {
tag_bldr->setArrival(tag, delay_zero, nullptr); tag_bldr->setArrival(tag, delay_zero);
search_from = true; search_from = true;
} }
} }
@ -1869,7 +1853,7 @@ Search::inputDelayRefPinArrival(Path *ref_path,
Clock *clk = clk_edge->clock(); Clock *clk = clk_edge->clock();
if (clk->isPropagated()) { if (clk->isPropagated()) {
ClkInfo *clk_info = ref_path->clkInfo(this); ClkInfo *clk_info = ref_path->clkInfo(this);
ref_arrival = delayAsFloat(ref_path->arrival(this)); ref_arrival = delayAsFloat(ref_path->arrival());
ref_insertion = delayAsFloat(clk_info->insertion()); ref_insertion = delayAsFloat(clk_info->insertion());
ref_latency = clk_info->latency(); ref_latency = clk_info->latency();
} }
@ -1930,7 +1914,7 @@ Search::seedInputDelayArrival(const Pin *pin,
Tag *tag = inputDelayTag(pin, rf, clk_edge, clk_insertion, clk_latency, Tag *tag = inputDelayTag(pin, rf, clk_edge, clk_insertion, clk_latency,
input_delay, is_segment_start, min_max, path_ap); input_delay, is_segment_start, min_max, path_ap);
if (tag) if (tag)
tag_bldr->setArrival(tag, arrival, nullptr); tag_bldr->setArrival(tag, arrival);
} }
void void
@ -2075,7 +2059,7 @@ PathVisitor::visitEdge(const Pin *from_pin,
TimingArcSet *arc_set = edge->timingArcSet(); TimingArcSet *arc_set = edge->timingArcSet();
VertexPathIterator from_iter(from_vertex, search_); VertexPathIterator from_iter(from_vertex, search_);
while (from_iter.hasNext()) { while (from_iter.hasNext()) {
PathVertex *from_path = from_iter.next(); Path *from_path = from_iter.next();
PathAnalysisPt *path_ap = from_path->pathAnalysisPt(this); PathAnalysisPt *path_ap = from_path->pathAnalysisPt(this);
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
const RiseFall *from_rf = from_path->transition(this); const RiseFall *from_rf = from_path->transition(this);
@ -2098,7 +2082,7 @@ bool
PathVisitor::visitArc(const Pin *from_pin, PathVisitor::visitArc(const Pin *from_pin,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
PathVertex *from_path, Path *from_path,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
const Pin *to_pin, const Pin *to_pin,
@ -2120,7 +2104,7 @@ bool
PathVisitor::visitFromPath(const Pin *from_pin, PathVisitor::visitFromPath(const Pin *from_pin,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
PathVertex *from_path, Path *from_path,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
const Pin *to_pin, const Pin *to_pin,
@ -2135,7 +2119,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
Tag *to_tag = nullptr; Tag *to_tag = nullptr;
const ClockEdge *clk_edge = from_clk_info->clkEdge(); const ClockEdge *clk_edge = from_clk_info->clkEdge();
const Clock *clk = from_clk_info->clock(); const Clock *clk = from_clk_info->clock();
Arrival from_arrival = from_path->arrival(this); Arrival from_arrival = from_path->arrival();
ArcDelay arc_delay = 0.0; ArcDelay arc_delay = 0.0;
Arrival to_arrival; Arrival to_arrival;
if (from_clk_info->isGenClkSrcPath()) { if (from_clk_info->isGenClkSrcPath()) {
@ -2202,7 +2186,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
&& from_tag->isClock())) { && from_tag->isClock())) {
const RiseFall *clk_rf = clk_edge ? clk_edge->transition() : nullptr; const RiseFall *clk_rf = clk_edge ? clk_edge->transition() : nullptr;
ClkInfo *to_clk_info = from_clk_info; ClkInfo *to_clk_info = from_clk_info;
if (from_clk_info->crprClkPath().isNull() if (from_clk_info->crprClkPath(this) == nullptr
|| network_->direction(to_pin)->isInternal()) || network_->direction(to_pin)->isInternal())
to_clk_info = search_->clkInfoWithCrprClkPath(from_clk_info, to_clk_info = search_->clkInfoWithCrprClkPath(from_clk_info,
from_path, path_ap); from_path, path_ap);
@ -2308,7 +2292,7 @@ Search::clkPathArrival(const Path *clk_path,
+ clk_info->latency(); + clk_info->latency();
} }
else else
return clk_path->arrival(this); return clk_path->arrival();
} }
Arrival Arrival
@ -2316,9 +2300,9 @@ Search::pathClkPathArrival(const Path *path) const
{ {
ClkInfo *clk_info = path->clkInfo(this); ClkInfo *clk_info = path->clkInfo(this);
if (clk_info->isPropagated()) { if (clk_info->isPropagated()) {
PathRef src_clk_path = pathClkPathArrival1(path); const Path *src_clk_path = pathClkPathArrival1(path);
if (!src_clk_path.isNull()) if (src_clk_path)
return clkPathArrival(&src_clk_path); return clkPathArrival(src_clk_path);
} }
// Check for input arrival clock. // Check for input arrival clock.
const ClockEdge *clk_edge = path->clkEdge(this); const ClockEdge *clk_edge = path->clkEdge(this);
@ -2328,34 +2312,30 @@ Search::pathClkPathArrival(const Path *path) const
} }
// PathExpanded::expand() and PathExpanded::clkPath(). // PathExpanded::expand() and PathExpanded::clkPath().
PathRef const Path *
Search::pathClkPathArrival1(const Path *path) const Search::pathClkPathArrival1(const Path *path) const
{ {
PathRef p(path); const Path *p = path;
while (!p.isNull()) { while (p) {
PathRef prev_path; Path *prev_path = p->prevPath();
TimingArc *prev_arc; Edge *prev_edge = p->prevEdge(this);
p.prevPath(this, prev_path, prev_arc);
if (p.isClock(this)) if (p->isClock(this))
return p; return p;
if (prev_arc) { if (prev_edge) {
TimingRole *prev_role = prev_arc->role(); TimingRole *prev_role = prev_edge->role();
if (prev_role == TimingRole::regClkToQ() if (prev_role == TimingRole::regClkToQ()
|| prev_role == TimingRole::latchEnToQ()) { || prev_role == TimingRole::latchEnToQ()) {
p.prevPath(this, prev_path, prev_arc); return p->prevPath();
return prev_path;
} }
else if (prev_role == TimingRole::latchDtoQ()) { else if (prev_role == TimingRole::latchDtoQ()) {
Edge *prev_edge = p.prevEdge(prev_arc, this); Path *enable_path = latches_->latchEnablePath(p, prev_edge);
PathVertex enable_path;
latches_->latchEnablePath(&p, prev_edge, enable_path);
return enable_path; return enable_path;
} }
} }
p.init(prev_path); p = prev_path;
} }
return PathRef(); return nullptr;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -2405,7 +2385,7 @@ Search::fromRegClkTag(const Pin *from_pin,
// Insert from_path as ClkInfo crpr_clk_path. // Insert from_path as ClkInfo crpr_clk_path.
ClkInfo * ClkInfo *
Search::clkInfoWithCrprClkPath(ClkInfo *from_clk_info, Search::clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
PathVertex *from_path, Path *from_path,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap)
{ {
if (sdc_->crprActive()) if (sdc_->crprActive())
@ -2447,7 +2427,7 @@ Search::thruTag(Tag *from_tag,
// thruTag for clocks. // thruTag for clocks.
Tag * Tag *
Search::thruClkTag(PathVertex *from_path, Search::thruClkTag(Path *from_path,
Vertex *from_vertex, Vertex *from_vertex,
Tag *from_tag, Tag *from_tag,
bool to_propagates_clk, bool to_propagates_clk,
@ -2479,7 +2459,7 @@ Search::thruClkTag(PathVertex *from_path,
} }
ClkInfo * ClkInfo *
Search::thruClkInfo(PathVertex *from_path, Search::thruClkInfo(Path *from_path,
Vertex *from_vertex, Vertex *from_vertex,
ClkInfo *from_clk_info, ClkInfo *from_clk_info,
bool from_is_clk, bool from_is_clk,
@ -2516,7 +2496,7 @@ Search::thruClkInfo(PathVertex *from_path,
changed = true; changed = true;
} }
PathVertex *to_crpr_clk_path = nullptr; Path *to_crpr_clk_path = nullptr;
if (sdc_->crprActive() if (sdc_->crprActive()
// Update crpr clk path for combinational paths leaving the clock // Update crpr clk path for combinational paths leaving the clock
// network (ie, tristate en->out) and buffer driving reg clk. // network (ie, tristate en->out) and buffer driving reg clk.
@ -2747,54 +2727,27 @@ Search::setVertexArrivals(Vertex *vertex,
deletePathsIncr(vertex); deletePathsIncr(vertex);
else { else {
TagGroup *prev_tag_group = tagGroup(vertex); TagGroup *prev_tag_group = tagGroup(vertex);
Arrival *prev_arrivals = graph_->arrivals(vertex); Path *prev_paths = graph_->paths(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(); size_t path_count = tag_group->pathCount();
bool has_requireds = vertex->hasRequireds(); // Reuse path 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()) { && path_count == prev_tag_group->pathCount()) {
if (save_prev) { tag_bldr->copyPaths(tag_group, prev_paths);
if (prev_paths == nullptr)
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
}
else {
// Prev paths not required.
prev_paths = nullptr;
graph_->deletePrevPaths(vertex);
}
tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths);
vertex->setTagGroupIndex(tag_group->index()); vertex->setTagGroupIndex(tag_group->index());
if (tag_group->hasFilterTag()) { if (tag_group->hasFilterTag()) {
LockGuard lock(filtered_arrivals_lock_); LockGuard lock(filtered_arrivals_lock_);
filtered_arrivals_->insert(vertex); filtered_arrivals_->insert(vertex);
} }
requiredInvalid(vertex);
if (has_requireds) {
requiredInvalid(vertex);
if (tag_group != prev_tag_group)
// Requireds can only be reused if the tag group is unchanged.
graph_->deleteRequireds(vertex);
}
} }
else { else {
if (prev_tag_group) { if (prev_tag_group) {
graph_->deleteArrivals(vertex); graph_->deletePaths(vertex);
if (has_requireds) { requiredInvalid(vertex);
requiredInvalid(vertex);
graph_->deleteRequireds(vertex);
}
} }
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count); Path *paths = graph_->makePaths(vertex, path_count);
prev_paths = nullptr; tag_bldr->copyPaths(tag_group, paths);
if (save_prev)
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
tag_bldr->copyArrivals(tag_group, arrivals, prev_paths);
vertex->setTagGroupIndex(tag_group->index()); vertex->setTagGroupIndex(tag_group->index());
if (tag_group->hasFilterTag()) { if (tag_group->hasFilterTag()) {
@ -2810,56 +2763,38 @@ Search::reportArrivals(Vertex *vertex) const
{ {
report_->reportLine("Vertex %s", vertex->name(sdc_network_)); report_->reportLine("Vertex %s", vertex->name(sdc_network_));
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
Arrival *arrivals = graph_->arrivals(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()); VertexPathIterator path_iter(vertex, this);
while (arrival_iter.hasNext()) { while (path_iter.hasNext()) {
Tag *tag; const Path *path = path_iter.next();
int arrival_index; const Tag *tag = path->tag(this);
arrival_iter.next(tag, arrival_index); const PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
const RiseFall *rf = tag->transition(); const RiseFall *rf = tag->transition();
const char *req = "?"; const char *req = delayAsString(path->required(), this);
if (requireds)
req = delayAsString(requireds[arrival_index], this);
bool report_clk_prev = false;
const char *clk_prev = "";
if (report_clk_prev
&& tag_group->hasClkTag()) {
PathVertex prev = check_crpr_->clkPathPrev(vertex, arrival_index);
if (!prev.isNull())
clk_prev = prev.name(this);
}
string prev_str; string prev_str;
if (prev_paths) { Path *prev_path = path->prevPath();
PathPrev &prev = prev_paths[arrival_index]; if (prev_path) {
if (!prev.isNull()) { prev_str += prev_path->name(this);
prev_str += prev.name(this); prev_str += " ";
prev_str += " "; const Edge *prev_edge = path->prevEdge(this);
const Edge *prev_edge = prev.prevEdge(this); TimingArc *arc = path->prevArc(this);
TimingArc *arc = prev.prevArc(this); prev_str += prev_edge->from(graph_)->name(network_);
prev_str += prev_edge->from(graph_)->name(network_); prev_str += " ";
prev_str += " "; prev_str += arc->fromEdge()->asString();
prev_str += arc->fromEdge()->asString(); prev_str += " -> ";
prev_str += " -> "; prev_str += prev_edge->to(graph_)->name(network_);
prev_str += prev_edge->to(graph_)->name(network_); prev_str += " ";
prev_str += " "; prev_str += arc->toEdge()->asString();
prev_str += arc->toEdge()->asString();
}
else
prev_str = "NULL";
} }
report_->reportLine(" %d %s %s %s / %s %s %s prev %s", else
arrival_index, prev_str = "NULL";
report_->reportLine(" %s %s %s / %s %s prev %s",
rf->asString(), rf->asString(),
path_ap->pathMinMax()->asString(), path_ap->pathMinMax()->asString(),
delayAsString(arrivals[arrival_index], this), delayAsString(path->arrival(), this),
req, req,
tag->asString(true, false, this), tag->asString(true, false, this),
clk_prev,
prev_str.c_str()); prev_str.c_str());
} }
} }
@ -2913,7 +2848,7 @@ Search::reportTagGroups() const
} }
void void
Search::reportArrivalCountHistogram() const Search::reportPathCountHistogram() const
{ {
Vector<int> vertex_counts(10); Vector<int> vertex_counts(10);
VertexIterator vertex_iter(graph_); VertexIterator vertex_iter(graph_);
@ -2921,17 +2856,17 @@ Search::reportArrivalCountHistogram() const
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
if (tag_group) { if (tag_group) {
size_t arrival_count = tag_group->arrivalCount(); size_t path_count = tag_group->pathCount();
if (arrival_count >= vertex_counts.size()) if (path_count >= vertex_counts.size())
vertex_counts.resize(arrival_count * 2); vertex_counts.resize(path_count * 2);
vertex_counts[arrival_count]++; vertex_counts[path_count]++;
} }
} }
for (size_t arrival_count = 0; arrival_count < vertex_counts.size(); arrival_count++) { for (size_t path_count = 0; path_count < vertex_counts.size(); path_count++) {
int vertex_count = vertex_counts[arrival_count]; int vertex_count = vertex_counts[path_count];
if (vertex_count > 0) if (vertex_count > 0)
report_->reportLine("%6lu %6d", arrival_count, vertex_count); report_->reportLine("%6lu %6d",path_count, vertex_count);
} }
} }
@ -3043,19 +2978,18 @@ Search::findClkInfo(const ClockEdge *clk_edge,
float latency, float latency,
ClockUncertainties *uncertainties, ClockUncertainties *uncertainties,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
PathVertex *crpr_clk_path) Path *crpr_clk_path)
{ {
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_ptr, this); path_ap->index(), crpr_clk_path, 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_ptr, this); path_ap->index(), crpr_clk_path, this);
clk_info_set_->insert(clk_info); clk_info_set_->insert(clk_info);
} }
return clk_info; return clk_info;
@ -3234,6 +3168,7 @@ Search::findRequireds(Level level)
seedInvalidRequireds(); seedInvalidRequireds();
int required_count = required_iter_->visitParallel(level, &req_visitor); int required_count = required_iter_->visitParallel(level, &req_visitor);
deleteTagsPrev(); deleteTagsPrev();
genclks_->updateSrcPathPrevs();
requireds_exist_ = true; requireds_exist_ = true;
debugPrint(debug_, "search", 1, "found %d requireds", required_count); debugPrint(debug_, "search", 1, "found %d requireds", required_count);
stats.report("Find requireds"); stats.report("Find requireds");
@ -3398,13 +3333,11 @@ void
FindEndRequiredVisitor::visit(PathEnd *path_end) FindEndRequiredVisitor::visit(PathEnd *path_end)
{ {
if (!path_end->isUnconstrained()) { if (!path_end->isUnconstrained()) {
PathRef &path = path_end->pathRef(); Path *path = path_end->path();
const MinMax *req_min = path.minMax(sta_)->opposite(); const MinMax *min_max = path->minMax(sta_)->opposite();
int arrival_index; size_t path_index = path->pathIndex(sta_);
bool arrival_exists;
path.arrivalIndex(arrival_index, arrival_exists);
Required required = path_end->requiredTime(sta_); Required required = path_end->requiredTime(sta_);
required_cmp_->requiredSet(arrival_index, required, req_min, sta_); required_cmp_->requiredSet(path_index, required, min_max, sta_);
} }
} }
@ -3449,31 +3382,27 @@ RequiredCmp::requiredsInit(Vertex *vertex,
Search *search = sta->search(); Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex); TagGroup *tag_group = search->tagGroup(vertex);
if (tag_group) { if (tag_group) {
requireds_.resize(tag_group->arrivalCount()); size_t path_count = tag_group->pathCount();
ArrivalMap *arrival_entries = tag_group->arrivalMap(); requireds_.resize(path_count);
ArrivalMap::Iterator arrival_iter(arrival_entries); for (auto const [tag, path_index] : *tag_group->pathIndexMap()) {
while (arrival_iter.hasNext()) {
Tag *tag;
int arrival_index;
arrival_iter.next(tag, arrival_index);
PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta); PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta);
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
requireds_[arrival_index] = delayInitValue(min_max->opposite()); requireds_[path_index] = delayInitValue(min_max->opposite());
} }
} }
else else
requireds_.resize(0); requireds_.clear();
have_requireds_ = false; have_requireds_ = false;
} }
void void
RequiredCmp::requiredSet(int arrival_index, RequiredCmp::requiredSet(size_t path_index,
Required required, Required &required,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta) const StaState *sta)
{ {
if (delayGreater(required, requireds_[arrival_index], min_max, sta)) { if (delayGreater(required, requireds_[path_index], min_max, sta)) {
requireds_[arrival_index] = required; requireds_[path_index] = required;
have_requireds_ = true; have_requireds_ = true;
} }
} }
@ -3483,53 +3412,26 @@ RequiredCmp::requiredsSave(Vertex *vertex,
const StaState *sta) const StaState *sta)
{ {
bool requireds_changed = false; bool requireds_changed = false;
bool prev_reqs = vertex->hasRequireds(); Debug *debug = sta->debug();
if (have_requireds_) { VertexPathIterator path_iter(vertex, sta);
if (!prev_reqs) while (path_iter.hasNext()) {
requireds_changed = true; Path *path = path_iter.next();
Debug *debug = sta->debug(); size_t path_index = path->pathIndex(sta);
VertexPathIterator path_iter(vertex, sta); Required req = requireds_[path_index];
while (path_iter.hasNext()) { Required &prev_req = path->required();
PathVertex *path = path_iter.next(); debugPrint(debug, "search", 3, "required save %s -> %s",
int arrival_index; delayAsString(prev_req, sta),
bool arrival_exists; delayAsString(req, sta));
path->arrivalIndex(arrival_index, arrival_exists); requireds_changed |= !delayEqual(prev_req, req);
Required req = requireds_[arrival_index]; path->setRequired(req);
if (prev_reqs) {
Required prev_req = path->required(sta);
if (!delayEqual(prev_req, req)) {
debugPrint(debug, "search", 3, "required save %s -> %s",
delayAsString(prev_req, sta),
delayAsString(req, sta));
path->setRequired(req, sta);
requireds_changed = true;
}
}
else {
debugPrint(debug, "search", 3, "required save MIA -> %s",
delayAsString(req, sta));
path->setRequired(req, sta);
}
}
}
else if (prev_reqs) {
Graph *graph = sta->graph();
const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex);
if (tag_group == nullptr)
requireds_changed = true;
else {
graph->deleteRequireds(vertex);
requireds_changed = true;
}
} }
return requireds_changed; return requireds_changed;
} }
Required Required
RequiredCmp::required(int arrival_index) RequiredCmp::required(size_t path_index)
{ {
return requireds_[arrival_index]; return requireds_[path_index];
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -3575,10 +3477,10 @@ RequiredVisitor::visit(Vertex *vertex)
bool bool
RequiredVisitor::visitFromToPath(const Pin *, RequiredVisitor::visitFromToPath(const Pin *,
Vertex *, Vertex * /* from_vertex */,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *from_path,
const Arrival &, const Arrival &,
Edge *edge, Edge *edge,
TimingArc *, TimingArc *,
@ -3599,15 +3501,14 @@ RequiredVisitor::visitFromToPath(const Pin *,
debugPrint(debug_, "search", 3, " from tag %2u: %s", debugPrint(debug_, "search", 3, " from tag %2u: %s",
from_tag->index(), from_tag->index(),
from_tag->asString(this)); from_tag->asString(this));
int arrival_index; size_t path_index = from_path->pathIndex(this);
bool arrival_exists;
from_path->arrivalIndex(arrival_index, arrival_exists);
const MinMax *req_min = min_max->opposite(); const MinMax *req_min = min_max->opposite();
TagGroup *to_tag_group = search_->tagGroup(to_vertex); TagGroup *to_tag_group = search_->tagGroup(to_vertex);
// Check to see if to_tag was pruned. // Check to see if to_tag was pruned.
if (to_tag_group && to_tag_group->hasTag(to_tag)) { if (to_tag_group && to_tag_group->hasTag(to_tag)) {
PathVertex to_path(to_vertex, to_tag, this); size_t to_path_index = to_tag_group->pathIndex(to_tag);
Required to_required = to_path.required(this); Path &to_path = to_vertex->paths()[to_path_index];
Required &to_required = to_path.required();
Required from_required = to_required - arc_delay; Required from_required = to_required - arc_delay;
debugPrint(debug_, "search", 3, " to tag %2u: %s", debugPrint(debug_, "search", 3, " to tag %2u: %s",
to_tag->index(), to_tag->index(),
@ -3617,8 +3518,8 @@ RequiredVisitor::visitFromToPath(const Pin *,
delayAsString(arc_delay, this), delayAsString(arc_delay, this),
delayAsString(from_required, this), delayAsString(from_required, this),
min_max == MinMax::max() ? "<" : ">", min_max == MinMax::max() ? "<" : ">",
delayAsString(required_cmp_->required(arrival_index), this)); delayAsString(required_cmp_->required(path_index), this));
required_cmp_->requiredSet(arrival_index, from_required, req_min, this); required_cmp_->requiredSet(path_index, from_required, req_min, this);
} }
else { else {
if (search_->crprApproxMissingRequireds()) { if (search_->crprApproxMissingRequireds()) {
@ -3627,10 +3528,10 @@ RequiredVisitor::visitFromToPath(const Pin *,
// as an appromate required. // as an appromate required.
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this); VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this);
while (to_iter.hasNext()) { while (to_iter.hasNext()) {
PathVertex *to_path = to_iter.next(); Path *to_path = to_iter.next();
Tag *to_path_tag = to_path->tag(this); Tag *to_path_tag = to_path->tag(this);
if (tagMatchNoCrpr(to_path_tag, to_tag)) { if (tagMatchNoCrpr(to_path_tag, to_tag)) {
Required to_required = to_path->required(this); Required to_required = to_path->required();
Required from_required = to_required - arc_delay; Required from_required = to_required - arc_delay;
debugPrint(debug_, "search", 3, " to tag %2u: %s", debugPrint(debug_, "search", 3, " to tag %2u: %s",
to_path_tag->index(), to_path_tag->index(),
@ -3640,9 +3541,9 @@ RequiredVisitor::visitFromToPath(const Pin *,
delayAsString(arc_delay, this), delayAsString(arc_delay, this),
delayAsString(from_required, this), delayAsString(from_required, this),
min_max == MinMax::max() ? "<" : ">", min_max == MinMax::max() ? "<" : ">",
delayAsString(required_cmp_->required(arrival_index), delayAsString(required_cmp_->required(path_index),
this)); this));
required_cmp_->requiredSet(arrival_index, from_required, req_min, this); required_cmp_->requiredSet(path_index, from_required, req_min, this);
break; break;
} }
} }
@ -4024,8 +3925,8 @@ void
FindEndSlackVisitor::visit(PathEnd *path_end) FindEndSlackVisitor::visit(PathEnd *path_end)
{ {
if (!path_end->isUnconstrained()) { if (!path_end->isUnconstrained()) {
PathRef &path = path_end->pathRef(); Path *path = path_end->path();
PathAPIndex path_ap_index = path.pathAnalysisPtIndex(sta_); PathAPIndex path_ap_index = path->pathAnalysisPtIndex(sta_);
Slack slack = path_end->slack(sta_); Slack slack = path_end->slack(sta_);
if (delayLess(slack, slacks_[path_ap_index], sta_)) if (delayLess(slack, slacks_[path_ap_index], sta_))
slacks_[path_ap_index] = slack; slacks_[path_ap_index] = slack;

View File

@ -51,11 +51,11 @@ private:
~VertexPathIterator(); ~VertexPathIterator();
}; };
class PathRef class Path
{ {
private: private:
PathRef(); Path();
~PathRef(); ~Path();
}; };
class PathEnd class PathEnd
@ -221,44 +221,32 @@ worst_slack_corner(const Corner *corner,
return worst_slack; return worst_slack;
} }
PathRef * Path *
vertex_worst_arrival_path(Vertex *vertex, vertex_worst_arrival_path(Vertex *vertex,
const MinMax *min_max) const MinMax *min_max)
{ {
Sta *sta = Sta::sta(); Sta *sta = Sta::sta();
sta->ensureLibLinked(); sta->ensureLibLinked();
PathRef path = sta->vertexWorstArrivalPath(vertex, min_max); return sta->vertexWorstArrivalPath(vertex, min_max);
if (!path.isNull())
return new PathRef(path);
else
return nullptr;
} }
PathRef * Path *
vertex_worst_arrival_path_rf(Vertex *vertex, vertex_worst_arrival_path_rf(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
MinMax *min_max) MinMax *min_max)
{ {
Sta *sta = Sta::sta(); Sta *sta = Sta::sta();
sta->ensureLibLinked(); sta->ensureLibLinked();
PathRef path = sta->vertexWorstArrivalPath(vertex, rf, min_max); return sta->vertexWorstArrivalPath(vertex, rf, min_max);
if (!path.isNull())
return new PathRef(path);
else
return nullptr;
} }
PathRef * Path *
vertex_worst_slack_path(Vertex *vertex, vertex_worst_slack_path(Vertex *vertex,
const MinMax *min_max) const MinMax *min_max)
{ {
Sta *sta = Sta::sta(); Sta *sta = Sta::sta();
sta->ensureLibLinked(); sta->ensureLibLinked();
PathRef path = sta->vertexWorstSlackPath(vertex, min_max); return sta->vertexWorstSlackPath(vertex, min_max);
if (!path.isNull())
return new PathRef(path);
else
return nullptr;
} }
int int
@ -280,9 +268,9 @@ report_tag_arrivals_cmd(Vertex *vertex)
} }
void void
report_arrival_count_histogram() report_path_count_histogram()
{ {
Sta::sta()->search()->reportArrivalCountHistogram(); Sta::sta()->search()->reportPathCountHistogram();
} }
int int
@ -310,15 +298,9 @@ clk_info_count()
} }
int int
arrival_count() path_count()
{ {
return Sta::sta()->arrivalCount(); return Sta::sta()->pathCount();
}
int
required_count()
{
return Sta::sta()->requiredCount();
} }
int int
@ -494,13 +476,7 @@ set_report_path_sigmas(bool report_sigmas)
} }
void void
delete_path_ref(PathRef *path) report_path_cmd(Path *path)
{
delete path;
}
void
report_path_cmd(PathRef *path)
{ {
Sta::sta()->reportPath(path); Sta::sta()->reportPath(path);
} }
@ -1245,7 +1221,7 @@ path_end_property(PathEnd *end,
} }
PropertyValue PropertyValue
path_ref_property(PathRef *path, path_ref_property(Path *path,
const char *property) const char *property)
{ {
return getProperty(path, property, Sta::sta()); return getProperty(path, property, Sta::sta());
@ -1275,7 +1251,7 @@ bool is_output_delay() { return self->isOutputDelay(); }
bool is_path_delay() { return self->isPathDelay(); } bool is_path_delay() { return self->isPathDelay(); }
bool is_gated_clock() { return self->isGatedClock(); } bool is_gated_clock() { return self->isGatedClock(); }
Vertex *vertex() { return self->vertex(Sta::sta()); } Vertex *vertex() { return self->vertex(Sta::sta()); }
PathRef *path() { return &self->pathRef(); } Path *path() { return self->path(); }
RiseFall *end_transition() RiseFall *end_transition()
{ return const_cast<RiseFall*>(self->path()->transition(Sta::sta())); } { return const_cast<RiseFall*>(self->path()->transition(Sta::sta())); }
Slack slack() { return self->slack(Sta::sta()); } Slack slack() { return self->slack(Sta::sta()); }
@ -1312,19 +1288,17 @@ Delay clk_skew() { return self->clkSkew(Sta::sta()); }
} }
%extend PathRef { %extend Path {
float float
arrival() arrival()
{ {
Sta *sta = Sta::sta(); return delayAsFloat(self->arrival());
return delayAsFloat(self->arrival(sta));
} }
float float
required() required()
{ {
Sta *sta = Sta::sta(); return delayAsFloat(self->required());
return delayAsFloat(self->required(sta));
} }
float float
@ -1354,12 +1328,10 @@ pins()
{ {
Sta *sta = Sta::sta(); Sta *sta = Sta::sta();
PinSeq pins; PinSeq pins;
PathRef path1(self); Path *path1 = self;
while (!path1.isNull()) { while (path1) {
pins.push_back(path1.vertex(sta)->pin()); pins.push_back(path1->vertex(sta)->pin());
PathRef prev_path; path1 = path1->prevPath();
path1.prevPath(sta, prev_path);
path1.init(prev_path);
} }
return pins; return pins;
} }
@ -1368,11 +1340,10 @@ pins()
%extend VertexPathIterator { %extend VertexPathIterator {
bool has_next() { return self->hasNext(); } bool has_next() { return self->hasNext(); }
PathRef * Path *
next() next()
{ {
Path *path = self->next(); return self->next();
return new PathRef(path);
} }
void finish() { delete self; } void finish() { delete self; }

View File

@ -854,7 +854,6 @@ proc_redirect report_path {
report_line "Tag: [$path tag]" report_line "Tag: [$path tag]"
} }
report_path_cmd $path report_path_cmd $path
delete_path_ref $path
set first 0 set first 0
} }
$path_iter finish $path_iter finish
@ -865,7 +864,6 @@ proc_redirect report_path {
report_line "Tag: [$worst_path tag]" report_line "Tag: [$worst_path tag]"
} }
report_path_cmd $worst_path report_path_cmd $worst_path
delete_path_ref $worst_path
} }
} }
} }

View File

@ -2488,6 +2488,8 @@ Sta::searchPreamble()
findDelays(); findDelays();
updateGeneratedClks(); updateGeneratedClks();
sdc_->searchPreamble(); sdc_->searchPreamble();
// Delete results from last findPathEnds because they point to filtered arrivals.
search_->deletePathGroups();
search_->deleteFilteredArrivals(); search_->deleteFilteredArrivals();
} }
@ -2759,82 +2761,82 @@ Sta::vertexPathIterator(Vertex *vertex,
return new VertexPathIterator(vertex, rf, min_max, this); return new VertexPathIterator(vertex, rf, min_max, this);
} }
PathRef Path *
Sta::vertexWorstArrivalPath(Vertex *vertex, Sta::vertexWorstArrivalPath(Vertex *vertex,
const MinMax *min_max) const MinMax *min_max)
{ {
return vertexWorstArrivalPath(vertex, nullptr, min_max); return vertexWorstArrivalPath(vertex, nullptr, min_max);
} }
PathRef Path *
Sta::vertexWorstArrivalPath(Vertex *vertex, Sta::vertexWorstArrivalPath(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max) const MinMax *min_max)
{ {
PathRef worst_path; Path *worst_path = nullptr;
Arrival worst_arrival = min_max->initValue(); Arrival worst_arrival = min_max->initValue();
VertexPathIterator path_iter(vertex, rf, min_max, this); VertexPathIterator path_iter(vertex, rf, min_max, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
Arrival arrival = path->arrival(this); Arrival arrival = path->arrival();
if (!path->tag(this)->isGenClkSrcPath() if (!path->tag(this)->isGenClkSrcPath()
&& delayGreater(arrival, worst_arrival, min_max, this)) { && delayGreater(arrival, worst_arrival, min_max, this)) {
worst_arrival = arrival; worst_arrival = arrival;
worst_path.init(path); worst_path = path;
} }
} }
return worst_path; return worst_path;
} }
PathRef Path *
Sta::vertexWorstRequiredPath(Vertex *vertex, Sta::vertexWorstRequiredPath(Vertex *vertex,
const MinMax *min_max) const MinMax *min_max)
{ {
return vertexWorstRequiredPath(vertex, nullptr, min_max); return vertexWorstRequiredPath(vertex, nullptr, min_max);
} }
PathRef Path *
Sta::vertexWorstRequiredPath(Vertex *vertex, Sta::vertexWorstRequiredPath(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max) const MinMax *min_max)
{ {
PathRef worst_path; Path *worst_path = nullptr;
const MinMax *req_min_max = min_max->opposite(); const MinMax *req_min_max = min_max->opposite();
Arrival worst_req = req_min_max->initValue(); Arrival worst_req = req_min_max->initValue();
VertexPathIterator path_iter(vertex, rf, min_max, this); VertexPathIterator path_iter(vertex, rf, min_max, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
const Required path_req = path->required(this); const Required path_req = path->required();
if (!path->tag(this)->isGenClkSrcPath() if (!path->tag(this)->isGenClkSrcPath()
&& delayGreater(path_req, worst_req, req_min_max, this)) { && delayGreater(path_req, worst_req, req_min_max, this)) {
worst_req = path_req; worst_req = path_req;
worst_path.init(path); worst_path = path;
} }
} }
return worst_path; return worst_path;
} }
PathRef Path *
Sta::vertexWorstSlackPath(Vertex *vertex, Sta::vertexWorstSlackPath(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max) const MinMax *min_max)
{ {
PathRef worst_path; Path *worst_path = nullptr;
Slack min_slack = MinMax::min()->initValue(); Slack min_slack = MinMax::min()->initValue();
VertexPathIterator path_iter(vertex, rf, min_max, this); VertexPathIterator path_iter(vertex, rf, min_max, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
Slack slack = path->slack(this); Slack slack = path->slack(this);
if (!path->tag(this)->isGenClkSrcPath() if (!path->tag(this)->isGenClkSrcPath()
&& delayLess(slack, min_slack, this)) { && delayLess(slack, min_slack, this)) {
min_slack = slack; min_slack = slack;
worst_path.init(path); worst_path = path;
} }
} }
return worst_path; return worst_path;
} }
PathRef Path *
Sta::vertexWorstSlackPath(Vertex *vertex, Sta::vertexWorstSlackPath(Vertex *vertex,
const MinMax *min_max) const MinMax *min_max)
@ -2891,12 +2893,12 @@ Sta::vertexArrival(Vertex *vertex,
VertexPathIterator path_iter(vertex, rf, path_ap, this); VertexPathIterator path_iter(vertex, rf, path_ap, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
Path *path = path_iter.next(); Path *path = path_iter.next();
const Arrival &path_arrival = path->arrival(this); const Arrival &path_arrival = path->arrival();
ClkInfo *clk_info = path->clkInfo(search_); ClkInfo *clk_info = path->clkInfo(search_);
if ((clk_edge == clk_edge_wildcard if ((clk_edge == clk_edge_wildcard
|| clk_info->clkEdge() == clk_edge) || clk_info->clkEdge() == clk_edge)
&& !clk_info->isGenClkSrcPath() && !clk_info->isGenClkSrcPath()
&& delayGreater(path->arrival(this), arrival, min_max, this)) && delayGreater(path->arrival(), arrival, min_max, this))
arrival = path_arrival; arrival = path_arrival;
} }
return arrival; return arrival;
@ -2949,7 +2951,7 @@ Sta::vertexRequired(Vertex *vertex,
VertexPathIterator path_iter(vertex, rf, path_ap, min_max, this); VertexPathIterator path_iter(vertex, rf, path_ap, min_max, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
const Path *path = path_iter.next(); const Path *path = path_iter.next();
const Required path_required = path->required(this); const Required path_required = path->required();
if ((clk_edge == clk_edge_wildcard if ((clk_edge == clk_edge_wildcard
|| path->clkEdge(search_) == clk_edge) || path->clkEdge(search_) == clk_edge)
&& delayGreater(path_required, required, req_min_max, this)) && delayGreater(path_required, required, req_min_max, this))
@ -3177,7 +3179,7 @@ bool
MinPeriodEndVisitor::pathIsFromInputPort(PathEnd *path_end) MinPeriodEndVisitor::pathIsFromInputPort(PathEnd *path_end)
{ {
PathExpanded expanded(path_end->path(), sta_); PathExpanded expanded(path_end->path(), sta_);
const PathRef *start = expanded.startPath(); const Path *start = expanded.startPath();
Graph *graph = sta_->graph(); Graph *graph = sta_->graph();
const Pin *first_pin = start->pin(graph); const Pin *first_pin = start->pin(graph);
Network *network = sta_->network(); Network *network = sta_->network();
@ -3539,14 +3541,14 @@ Sta::pathDcalcAnalysisPt(Path *path)
} }
Vertex * Vertex *
Sta::maxArrivalCountVertex() const Sta::maxPathCountVertex() const
{ {
Vertex *max_vertex = nullptr; Vertex *max_vertex = nullptr;
int max_count = 0; int max_count = 0;
VertexIterator vertex_iter(graph_); VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) { while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
int count = vertexArrivalCount(vertex); int count = vertexPathCount(vertex);
if (count > max_count) { if (count > max_count) {
max_count = count; max_count = count;
max_vertex = vertex; max_vertex = vertex;
@ -3556,36 +3558,23 @@ Sta::maxArrivalCountVertex() const
} }
int int
Sta::vertexArrivalCount(Vertex *vertex) const Sta::vertexPathCount(Vertex *vertex) const
{ {
TagGroup *tag_group = search_->tagGroup(vertex); TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) if (tag_group)
return tag_group->arrivalCount(); return tag_group->pathCount();
else else
return 0; return 0;
} }
int int
Sta::arrivalCount() const Sta::pathCount() const
{ {
int count = 0; int count = 0;
VertexIterator vertex_iter(graph_); VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) { while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
count += vertexArrivalCount(vertex); count += vertexPathCount(vertex);
}
return count;
}
int
Sta::requiredCount() const
{
int count = 0;
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
if (vertex->hasRequireds())
count += vertexArrivalCount(vertex);
} }
return count; return count;
} }
@ -4195,6 +4184,8 @@ Sta::makePortPin(const char *port_name,
void void
Sta::makeInstanceAfter(const Instance *inst) Sta::makeInstanceAfter(const Instance *inst)
{ {
debugPrint(debug_, "network_edit", 1, "make instance %s",
sdc_network_->pathName(inst));
if (graph_) { if (graph_) {
LibertyCell *lib_cell = network_->libertyCell(inst); LibertyCell *lib_cell = network_->libertyCell(inst);
if (lib_cell) { if (lib_cell) {
@ -4367,6 +4358,9 @@ Sta::replaceCellAfter(const Instance *inst)
void void
Sta::connectPinAfter(const Pin *pin) Sta::connectPinAfter(const Pin *pin)
{ {
debugPrint(debug_, "network_edit", 1, "connect %s to %s",
sdc_network_->pathName(pin),
sdc_network_->pathName(network_->net(pin)));
if (graph_) { if (graph_) {
if (network_->isHierarchical(pin)) { if (network_->isHierarchical(pin)) {
graph_->makeWireEdgesThruPin(pin); graph_->makeWireEdgesThruPin(pin);
@ -4453,6 +4447,9 @@ Sta::connectLoadPinAfter(Vertex *vertex)
void void
Sta::disconnectPinBefore(const Pin *pin) Sta::disconnectPinBefore(const Pin *pin)
{ {
debugPrint(debug_, "network_edit", 1, "disconnect %s from %s",
sdc_network_->pathName(pin),
sdc_network_->pathName(network_->net(pin)));
parasitics_->disconnectPinBefore(pin, network_); parasitics_->disconnectPinBefore(pin, network_);
sdc_->disconnectPinBefore(pin); sdc_->disconnectPinBefore(pin);
sim_->disconnectPinBefore(pin); sim_->disconnectPinBefore(pin);
@ -4500,10 +4497,11 @@ Sta::disconnectPinBefore(const Pin *pin)
void void
Sta::deleteEdge(Edge *edge) Sta::deleteEdge(Edge *edge)
{ {
Vertex *from = edge->from(graph_); debugPrint(debug_, "network_edit", 1, "delete edge %s -> %s",
edge->from(graph_)->name(sdc_network_),
edge->to(graph_)->name(sdc_network_));
Vertex *to = edge->to(graph_); Vertex *to = edge->to(graph_);
search_->arrivalInvalid(to); search_->deleteEdgeBefore(edge);
search_->requiredInvalid(from);
graph_delay_calc_->delayInvalid(to); graph_delay_calc_->delayInvalid(to);
levelize_->relevelizeFrom(to); levelize_->relevelizeFrom(to);
levelize_->deleteEdgeBefore(edge); levelize_->deleteEdgeBefore(edge);
@ -4514,6 +4512,8 @@ Sta::deleteEdge(Edge *edge)
void void
Sta::deleteNetBefore(const Net *net) Sta::deleteNetBefore(const Net *net)
{ {
debugPrint(debug_, "network_edit", 1, "delete net %s",
sdc_network_->pathName(net));
if (graph_) { if (graph_) {
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net); NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
while (pin_iter->hasNext()) { while (pin_iter->hasNext()) {
@ -4540,6 +4540,8 @@ Sta::deleteNetBefore(const Net *net)
void void
Sta::deleteInstanceBefore(const Instance *inst) Sta::deleteInstanceBefore(const Instance *inst)
{ {
debugPrint(debug_, "network_edit", 1, "delete instance %s",
sdc_network_->pathName(inst));
if (network_->isLeaf(inst)) { if (network_->isLeaf(inst)) {
deleteInstancePinsBefore(inst); deleteInstancePinsBefore(inst);
deleteLeafInstanceBefore(inst); deleteLeafInstanceBefore(inst);
@ -5715,7 +5717,7 @@ Sta::activity(const Pin *pin)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void
Sta::writePathSpice(PathRef *path, Sta::writePathSpice(Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,

View File

@ -148,10 +148,10 @@ Tag::asString(bool report_index,
result += network->pathName(clk_src); result += network->pathName(clk_src);
} }
const PathVertex crpr_clk_path(clk_info_->crprClkPath(), sta); const Path *crpr_clk_path = clk_info_->crprClkPath(sta);
if (!crpr_clk_path.isNull()) { if (crpr_clk_path != nullptr) {
result += " crpr_pin "; result += " crpr_pin ";
result += network->pathName(crpr_clk_path.pin(sta)); result += network->pathName(crpr_clk_path->pin(sta));
} }
if (input_delay_) { if (input_delay_) {
@ -280,11 +280,12 @@ Tag::findHash()
} }
size_t size_t
Tag::matchHash(bool match_crpr_clk_pin) const Tag::matchHash(bool match_crpr_clk_pin,
const StaState *sta) const
{ {
if (match_crpr_clk_pin) if (match_crpr_clk_pin)
// match_hash_ with crpr clk pin thrown in. // match_hash_ with crpr clk pin thrown in.
return hashSum(match_hash_, clk_info_->crprClkVertexId()); return hashSum(match_hash_, clk_info_->crprClkVertexId(sta));
else else
return match_hash_; return match_hash_;
} }
@ -421,7 +422,7 @@ tagMatch(const Tag *tag1,
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath() && clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
&& (!match_crpr_clk_pin && (!match_crpr_clk_pin
|| !sta->sdc()->crprActive() || !sta->sdc()->crprActive()
|| clk_info1->crprClkVertexId() == clk_info2->crprClkVertexId()) || clk_info1->crprClkVertexId(sta) == clk_info2->crprClkVertexId(sta))
&& tagStateEqual(tag1, tag2)); && tagStateEqual(tag1, tag2));
} }
@ -482,8 +483,8 @@ tagMatchCmp(const Tag *tag1,
if (match_crpr_clk_pin if (match_crpr_clk_pin
&& sta->sdc()->crprActive()) { && sta->sdc()->crprActive()) {
VertexId crpr_vertex1 = clk_info1->crprClkVertexId(); VertexId crpr_vertex1 = clk_info1->crprClkVertexId(sta);
VertexId crpr_vertex2 = clk_info2->crprClkVertexId(); VertexId crpr_vertex2 = clk_info2->crprClkVertexId(sta);
if (crpr_vertex1 < crpr_vertex2) if (crpr_vertex1 < crpr_vertex2)
return -1; return -1;
if (crpr_vertex1 > crpr_vertex2) if (crpr_vertex1 > crpr_vertex2)
@ -676,7 +677,7 @@ TagMatchHash::TagMatchHash(bool match_crpr_clk_pin,
size_t size_t
TagMatchHash::operator()(const Tag *tag) const TagMatchHash::operator()(const Tag *tag) const
{ {
return tag->matchHash(match_crpr_clk_pin_); return tag->matchHash(match_crpr_clk_pin_, sta_);
} }
TagMatchEqual::TagMatchEqual(bool match_crpr_clk_pin, TagMatchEqual::TagMatchEqual(bool match_crpr_clk_pin,

View File

@ -29,7 +29,7 @@
#include "Transition.hh" #include "Transition.hh"
#include "SdcClass.hh" #include "SdcClass.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "PathRef.hh" #include "Path.hh"
namespace sta { namespace sta {
@ -86,7 +86,8 @@ public:
bool isFilter() const { return is_filter_; } bool isFilter() const { return is_filter_; }
bool isSegmentStart() const { return is_segment_start_; } bool isSegmentStart() const { return is_segment_start_; }
size_t hash() const { return hash_; } size_t hash() const { return hash_; }
size_t matchHash(bool match_crpr_clk_pin) const; size_t matchHash(bool match_crpr_clk_pin,
const StaState *sta) const;
protected: protected:
void findHash(); void findHash();

View File

@ -32,66 +32,70 @@
#include "Tag.hh" #include "Tag.hh"
#include "Corner.hh" #include "Corner.hh"
#include "Search.hh" #include "Search.hh"
#include "PathPrev.hh" #include "Path.hh"
namespace sta { namespace sta {
TagGroup::TagGroup(TagGroupIndex index, TagGroup::TagGroup(TagGroupIndex index,
ArrivalMap *arrival_map, PathIndexMap *path_index_map,
bool has_clk_tag, bool has_clk_tag,
bool has_genclk_src_tag, bool has_genclk_src_tag,
bool has_filter_tag, bool has_filter_tag,
bool has_loop_tag) : bool has_loop_tag) :
arrival_map_(arrival_map), path_index_map_(path_index_map),
hash_(arrivalMapHash(arrival_map_)), hash_(pathIndexMapHash(path_index_map)),
index_(index), index_(index),
has_clk_tag_(has_clk_tag), has_clk_tag_(has_clk_tag),
has_genclk_src_tag_(has_genclk_src_tag), has_genclk_src_tag_(has_genclk_src_tag),
has_filter_tag_(has_filter_tag), has_filter_tag_(has_filter_tag),
has_loop_tag_(has_loop_tag), has_loop_tag_(has_loop_tag),
own_arrival_map_(true) own_path_map_(true)
{ {
} }
TagGroup::TagGroup(TagGroupBldr *tag_bldr) : TagGroup::TagGroup(TagGroupBldr *tag_bldr) :
arrival_map_(tag_bldr->arrivalMap()), path_index_map_(&tag_bldr->pathIndexMap()),
hash_(arrivalMapHash(arrival_map_)), hash_(pathIndexMapHash(path_index_map_)),
own_arrival_map_(false) own_path_map_(false)
{ {
} }
TagGroup::~TagGroup() TagGroup::~TagGroup()
{ {
if (own_arrival_map_) if (own_path_map_)
delete arrival_map_; delete path_index_map_;
} }
size_t size_t
TagGroup::arrivalMapHash(ArrivalMap *arrival_map) TagGroup::pathIndexMapHash(PathIndexMap *path_index_map)
{ {
size_t hash = 0; size_t hash = 0;
ArrivalMap::Iterator arrival_iter(arrival_map); for (auto const [tag, path_index] : *path_index_map)
while (arrival_iter.hasNext()) {
Tag *tag;
int arrival_index;
arrival_iter.next(tag, arrival_index);
hash += tag->hash(); hash += tag->hash();
}
return hash; return hash;
} }
bool bool
TagGroup::hasTag(Tag *tag) const TagGroup::hasTag(Tag *tag) const
{ {
return arrival_map_->hasKey(tag); return path_index_map_->hasKey(tag);
}
size_t
TagGroup::pathIndex(Tag *tag) const
{
size_t path_index;
bool exists;
pathIndex(tag, path_index, exists);
return path_index;
} }
void void
TagGroup::arrivalIndex(Tag *tag, TagGroup::pathIndex(Tag *tag,
int &arrival_index, size_t &path_index,
bool &exists) const bool &exists) const
{ {
arrival_map_->findKey(tag, arrival_index, exists); path_index_map_->findKey(tag, path_index, exists);
} }
void void
@ -99,29 +103,24 @@ TagGroup::report(const StaState *sta) const
{ {
Report *report = sta->report(); Report *report = sta->report();
report->reportLine("Group %u hash = %zu", index_, hash_); report->reportLine("Group %u hash = %zu", index_, hash_);
arrivalMapReport(arrival_map_, sta); pathIndexMapReport(path_index_map_, sta);
} }
void void
TagGroup::reportArrivalMap(const StaState *sta) const TagGroup::reportArrivalMap(const StaState *sta) const
{ {
arrivalMapReport(arrival_map_, sta); pathIndexMapReport(path_index_map_, sta);
} }
void void
arrivalMapReport(const ArrivalMap *arrival_map, pathIndexMapReport(const PathIndexMap *path_index_map,
const StaState *sta) const StaState *sta)
{ {
Report *report = sta->report(); Report *report = sta->report();
ArrivalMap::ConstIterator arrival_iter(arrival_map); for (auto const [tag, path_index] : *path_index_map)
while (arrival_iter.hasNext()) { report->reportLine(" %2zu %s",
Tag *tag; path_index,
int arrival_index;
arrival_iter.next(tag, arrival_index);
report->reportLine(" %2u %s",
arrival_index,
tag->asString(sta)); tag->asString(sta));
}
report->reportBlankLine(); report->reportBlankLine();
} }
@ -129,14 +128,13 @@ arrivalMapReport(const ArrivalMap *arrival_map,
TagGroupBldr::TagGroupBldr(bool match_crpr_clk_pin, TagGroupBldr::TagGroupBldr(bool match_crpr_clk_pin,
const StaState *sta) : const StaState *sta) :
default_arrival_count_(sta->corners()->count() default_path_count_(sta->corners()->count()
* RiseFall::index_count * RiseFall::index_count
* MinMax::index_count), * MinMax::index_count),
arrival_map_(default_arrival_count_, path_index_map_(default_path_count_,
TagMatchHash(match_crpr_clk_pin, sta), TagMatchHash(match_crpr_clk_pin, sta),
TagMatchEqual(match_crpr_clk_pin, sta)), TagMatchEqual(match_crpr_clk_pin, sta)),
arrivals_(default_arrival_count_), paths_(default_path_count_),
prev_paths_(default_arrival_count_),
has_clk_tag_(false), has_clk_tag_(false),
has_genclk_src_tag_(false), has_genclk_src_tag_(false),
has_filter_tag_(false), has_filter_tag_(false),
@ -149,16 +147,15 @@ TagGroupBldr::TagGroupBldr(bool match_crpr_clk_pin,
bool bool
TagGroupBldr::empty() TagGroupBldr::empty()
{ {
return arrival_map_.empty(); return path_index_map_.empty();
} }
void void
TagGroupBldr::init(Vertex *vertex) TagGroupBldr::init(Vertex *vertex)
{ {
vertex_ = vertex; vertex_ = vertex;
arrival_map_.clear(); path_index_map_.clear();
arrivals_.clear(); paths_.clear();
prev_paths_.clear();
has_clk_tag_ = false; has_clk_tag_ = false;
has_genclk_src_tag_ = false; has_genclk_src_tag_ = false;
has_filter_tag_ = false; has_filter_tag_ = false;
@ -168,147 +165,152 @@ TagGroupBldr::init(Vertex *vertex)
void void
TagGroupBldr::reportArrivalEntries() const TagGroupBldr::reportArrivalEntries() const
{ {
arrivalMapReport(&arrival_map_, sta_); pathIndexMapReport(&path_index_map_, sta_);
}
Path *
TagGroupBldr::tagMatchPath(Tag *tag)
{
Path *match;
size_t path_index;
tagMatchPath(tag, match, path_index);
return match;
} }
void void
TagGroupBldr::tagMatchArrival(Tag *tag, TagGroupBldr::tagMatchPath(Tag *tag,
// Return values. // Return values.
Tag *&tag_match, Path *&match,
Arrival &arrival, size_t &path_index)
int &arrival_index) const
{ {
// Find matching group tag. // Find matching group tag.
// Match is not necessarily equal to original tag because it // Match is not necessarily equal to original tag because it
// must only satisfy tagMatch. // must only satisfy tagMatch.
bool exists; bool exists;
arrival_map_.findKey(tag, tag_match, arrival_index, exists); Tag *tag_match;
path_index_map_.findKey(tag, tag_match, path_index, exists);
if (exists) if (exists)
arrival = arrivals_[arrival_index]; match = &paths_[path_index];
else { else {
tag_match = nullptr; match = nullptr;
arrival = -1.0; path_index = 0;
arrival_index = -1;
} }
} }
Arrival Arrival
TagGroupBldr::arrival(int arrival_index) const TagGroupBldr::arrival(size_t path_index) const
{ {
return arrivals_[arrival_index]; return paths_[path_index].arrival();
} }
void void
TagGroupBldr::setArrival(Tag *tag, TagGroupBldr::setArrival(Tag *tag,
const Arrival &arrival, const Arrival &arrival)
PathPrev *prev_path)
{ {
Tag *tag_match;
Arrival ignore;
int arrival_index;
// Find matching group tag (not necessarily equal to original tag). // Find matching group tag (not necessarily equal to original tag).
tagMatchArrival(tag, tag_match, ignore, arrival_index); Path *match;
setMatchArrival(tag, tag_match, arrival, arrival_index, prev_path); size_t path_index;
tagMatchPath(tag, match, path_index);
setMatchPath(match, path_index, tag, arrival, nullptr, nullptr, nullptr);
} }
void void
TagGroupBldr::setMatchArrival(Tag *tag, TagGroupBldr::setMatchPath(Path *match,
Tag *tag_match, size_t path_index,
const Arrival &arrival, Tag *tag,
int arrival_index, Arrival arrival,
PathPrev *prev_path) Path *prev_path,
Edge *prev_edge,
TimingArc *prev_arc)
{ {
if (tag_match) { if (match) {
// If the group_tag exists there has to be an arrival map entry for it. Tag *tag_match = match->tag(sta_);
// If the tag match exists there has to be a path map entry for it.
if (tag_match != tag) { if (tag_match != tag) {
// Replace tag in arrival map. // Replace tag in arrival map.
arrival_map_.erase(tag_match); path_index_map_.erase(tag_match);
arrival_map_.insert(tag, arrival_index); path_index_map_.insert(tag, path_index);
} }
arrivals_[arrival_index] = arrival; paths_[path_index].init(vertex_, tag, arrival, prev_path,
prev_paths_[arrival_index].init(prev_path); prev_edge, prev_arc, sta_);
} }
else { else
arrival_index = arrivals_.size(); insertPath(tag, arrival, prev_path, prev_edge, prev_arc);
arrival_map_.insert(tag, arrival_index); }
arrivals_.push_back(arrival);
if (prev_path)
prev_paths_.push_back(*prev_path);
else
prev_paths_.push_back(PathPrev());
if (tag->isClock()) void
has_clk_tag_ = true; TagGroupBldr::insertPath(Tag *tag,
if (tag->isGenClkSrcPath()) Arrival arrival,
has_genclk_src_tag_ = true; Path *prev_path,
if (tag->isFilter() Edge *prev_edge,
|| tag->clkInfo()->refsFilter(sta_)) TimingArc *prev_arc)
has_filter_tag_ = true;
if (tag->isLoop()) {
has_loop_tag_ = true; size_t path_index = paths_.size();
if (tag->clkInfo()->isPropagated()) path_index_map_.insert(tag, path_index);
has_propagated_clk_ = true; paths_.emplace_back(vertex_, tag, arrival, prev_path,
} prev_edge, prev_arc, sta_);
if (tag->isClock())
has_clk_tag_ = true;
if (tag->isGenClkSrcPath())
has_genclk_src_tag_ = true;
if (tag->isFilter()
|| tag->clkInfo()->refsFilter(sta_))
has_filter_tag_ = true;
if (tag->isLoop())
has_loop_tag_ = true;
if (tag->clkInfo()->isPropagated())
has_propagated_clk_ = true;
}
void
TagGroupBldr::insertPath(const Path &path)
{
insertPath(path.tag(sta_), path.arrival(), path.prevPath(),
path.prevEdge(sta_), path.prevArc(sta_));
} }
TagGroup * TagGroup *
TagGroupBldr::makeTagGroup(TagGroupIndex index, TagGroupBldr::makeTagGroup(TagGroupIndex index,
const StaState *sta) const StaState *sta)
{ {
return new TagGroup(index, makeArrivalMap(sta), return new TagGroup(index, makePathIndexMap(sta),
has_clk_tag_, has_genclk_src_tag_, has_filter_tag_, has_clk_tag_, has_genclk_src_tag_, has_filter_tag_,
has_loop_tag_); has_loop_tag_);
} }
ArrivalMap * PathIndexMap *
TagGroupBldr::makeArrivalMap(const StaState *sta) TagGroupBldr::makePathIndexMap(const StaState *sta)
{ {
ArrivalMap *arrival_map = new ArrivalMap(arrival_map_.size(), PathIndexMap *path_index_map = new PathIndexMap(path_index_map_.size(),
TagMatchHash(true, sta), TagMatchHash(true, sta),
TagMatchEqual(true, sta)); TagMatchEqual(true, sta));
int arrival_index = 0;
ArrivalMap::Iterator arrival_iter(arrival_map_); size_t path_index = 0;
while (arrival_iter.hasNext()) { for (auto const [tag, path_index1] : path_index_map_) {
Tag *tag; path_index_map->insert(tag, path_index);
int arrival_index1; path_index++;
arrival_iter.next(tag, arrival_index1);
arrival_map->insert(tag, arrival_index);
arrival_index++;
} }
return arrival_map; return path_index_map;
} }
void void
TagGroupBldr::copyArrivals(TagGroup *tag_group, TagGroupBldr::copyPaths(TagGroup *tag_group,
Arrival *arrivals, Path *paths)
PathPrev *prev_paths)
{ {
ArrivalMap::Iterator arrival_iter1(arrival_map_); for (auto const [tag1, path_index1] : path_index_map_) {
while (arrival_iter1.hasNext()) { size_t path_index2;
Tag *tag1;
int arrival_index1, arrival_index2;
arrival_iter1.next(tag1, arrival_index1);
bool exists2; bool exists2;
tag_group->arrivalIndex(tag1, arrival_index2, exists2); tag_group->pathIndex(tag1, path_index2, exists2);
if (exists2) { if (exists2)
arrivals[arrival_index2] = arrivals_[arrival_index1]; paths[path_index2] = paths_[path_index1];
if (prev_paths) {
PathPrev *prev_path = &prev_paths_[arrival_index1];
prev_paths[arrival_index2].init(prev_path);
}
}
else else
sta_->report()->critical(1351, "tag group missing tag"); sta_->report()->critical(1351, "tag group missing tag");
} }
} }
PathPrev &
TagGroupBldr::prevPath(int arrival_index)
{
return prev_paths_[arrival_index];
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
size_t size_t
@ -318,19 +320,15 @@ TagGroupHash::operator()(const TagGroup *group) const
} }
static bool static bool
arrivalMapEqual(const ArrivalMap *arrival_map1, pathIndexMapEqual(const PathIndexMap *path_index_map1,
const ArrivalMap *arrival_map2) const PathIndexMap *path_index_map2)
{ {
int arrival_count1 = arrival_map1->size(); if (path_index_map1->size() == path_index_map2->size()) {
int arrival_count2 = arrival_map2->size(); for (auto const [tag1, path_index1] : *path_index_map1) {
if (arrival_count1 == arrival_count2) { Tag *tag2;
ArrivalMap::ConstIterator arrival_iter1(arrival_map1); size_t path_index2;
while (arrival_iter1.hasNext()) {
Tag *tag1, *tag2;
int arrival_index1, arrival_index2;
arrival_iter1.next(tag1, arrival_index1);
bool exists2; bool exists2;
arrival_map2->findKey(tag1, tag2, arrival_index2, exists2); path_index_map2->findKey(tag1, tag2, path_index2, exists2);
if (!exists2 if (!exists2
// ArrivalMap equal function is TagMatchEqual, so make sure // ArrivalMap equal function is TagMatchEqual, so make sure
// the tag is an exact match. // the tag is an exact match.
@ -349,8 +347,8 @@ TagGroupEqual::operator()(const TagGroup *tag_group1,
{ {
return tag_group1 == tag_group2 return tag_group1 == tag_group2
|| (tag_group1->hash() == tag_group2->hash() || (tag_group1->hash() == tag_group2->hash()
&& arrivalMapEqual(tag_group1->arrivalMap(), && pathIndexMapEqual(tag_group1->pathIndexMap(),
tag_group2->arrivalMap())); tag_group2->pathIndexMap()));
} }
} // namespace } // namespace

View File

@ -37,13 +37,11 @@ namespace sta {
class TagGroupBldr; class TagGroupBldr;
typedef Vector<PathPrev> PathPrevSeq;
class TagGroup class TagGroup
{ {
public: public:
TagGroup(TagGroupIndex index, TagGroup(TagGroupIndex index,
ArrivalMap *arrival_map, PathIndexMap *path_index_map,
bool has_clk_tag, bool has_clk_tag,
bool has_genclk_src_tag, bool has_genclk_src_tag,
bool has_filter_tag, bool has_filter_tag,
@ -59,26 +57,27 @@ 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_; }
bool ownArrivalMap() const { return own_arrival_map_; } bool ownPathMap() const { return own_path_map_; }
int arrivalCount() const { return arrival_map_->size(); } size_t pathCount() const { return path_index_map_->size(); }
void arrivalIndex(Tag *tag, void pathIndex(Tag *tag,
int &arrival_index, size_t &path_index,
bool &exists) const; bool &exists) const;
ArrivalMap *arrivalMap() const { return arrival_map_; } size_t pathIndex(Tag *tag) const;
PathIndexMap *pathIndexMap() const { return path_index_map_; }
bool hasTag(Tag *tag) const; bool hasTag(Tag *tag) const;
protected: protected:
size_t arrivalMapHash(ArrivalMap *arrival_map); static size_t pathIndexMapHash(PathIndexMap *path_index_map);
// tag -> arrival index // tag -> path index
ArrivalMap *arrival_map_; PathIndexMap *path_index_map_;
size_t hash_; size_t hash_;
unsigned int index_:tag_group_index_bits; unsigned int index_:tag_group_index_bits;
bool has_clk_tag_:1; bool has_clk_tag_:1;
bool has_genclk_src_tag_:1; bool has_genclk_src_tag_:1;
bool has_filter_tag_:1; bool has_filter_tag_:1;
bool has_loop_tag_:1; bool has_loop_tag_:1;
bool own_arrival_map_:1; bool own_path_map_:1;
}; };
class TagGroupHash class TagGroupHash
@ -106,40 +105,46 @@ public:
void reportArrivalEntries() const; void reportArrivalEntries() const;
TagGroup *makeTagGroup(TagGroupIndex index, TagGroup *makeTagGroup(TagGroupIndex index,
const StaState *sta); const StaState *sta);
size_t pathCount() const { return path_index_map_.size();; }
bool hasClkTag() const { return has_clk_tag_; } bool hasClkTag() const { return has_clk_tag_; }
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_; }
bool hasPropagatedClk() const { return has_propagated_clk_; } bool hasPropagatedClk() const { return has_propagated_clk_; }
void tagMatchArrival(Tag *tag, Path *tagMatchPath(Tag *tag);
// Return values. void tagMatchPath(Tag *tag,
Tag *&tag_match, // Return values.
Arrival &arrival, Path *&match,
int &arrival_index) const; size_t &path_index);
Arrival arrival(int arrival_index) const; Arrival arrival(size_t path_index) const;
// prev_path == hull
void setArrival(Tag *tag, void setArrival(Tag *tag,
const Arrival &arrival, const Arrival &arrival);
PathPrev *prev_path); void setMatchPath(Path *match,
void setMatchArrival(Tag *tag, size_t path_index,
Tag *tag_match, Tag *tag,
const Arrival &arrival, Arrival arrival,
int arrival_index, Path *prev_path,
PathPrev *prev_path); Edge *prev_edge,
ArrivalMap *arrivalMap() { return &arrival_map_; } TimingArc *prev_arc);
PathPrev &prevPath(int arrival_index); void insertPath(Tag *tag,
void copyArrivals(TagGroup *tag_group, Arrival arrival,
Arrival *arrivals, Path *prev_path,
PathPrev *prev_paths); Edge *prev_edge,
TimingArc *prev_arc);
void insertPath(const Path &path);
PathIndexMap &pathIndexMap() { return path_index_map_; }
void copyPaths(TagGroup *tag_group,
Path *paths);
protected: protected:
int tagMatchIndex(); int tagMatchIndex();
ArrivalMap *makeArrivalMap(const StaState *sta); PathIndexMap *makePathIndexMap(const StaState *sta);
Vertex *vertex_; Vertex *vertex_;
int default_arrival_count_; int default_path_count_;
ArrivalMap arrival_map_; PathIndexMap path_index_map_;
ArrivalSeq arrivals_; vector<Path> paths_;
PathPrevSeq prev_paths_;
bool has_clk_tag_; bool has_clk_tag_;
bool has_genclk_src_tag_; bool has_genclk_src_tag_;
bool has_filter_tag_; bool has_filter_tag_;
@ -149,7 +154,7 @@ protected:
}; };
void void
arrivalMapReport(const ArrivalMap *arrival_map, pathIndexMapReport(const PathIndexMap *path_index_map,
const StaState *sta); const StaState *sta);
} // namespace } // namespace

View File

@ -34,7 +34,7 @@
#include "Graph.hh" #include "Graph.hh"
#include "ClkInfo.hh" #include "ClkInfo.hh"
#include "Tag.hh" #include "Tag.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
#include "Search.hh" #include "Search.hh"
@ -91,7 +91,7 @@ VisitPathEnds::visitClkedPathEnds(const Pin *pin,
bool is_segment_start = search_->isSegmentStart(pin); bool is_segment_start = search_->isSegmentStart(pin);
VertexPathIterator path_iter(vertex, this); VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
PathAnalysisPt *path_ap = path->pathAnalysisPt(this); PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
const MinMax *path_min_max = path_ap->pathMinMax(); const MinMax *path_min_max = path_ap->pathMinMax();
const RiseFall *end_rf = path->transition(this); const RiseFall *end_rf = path->transition(this);
@ -161,7 +161,7 @@ VisitPathEnds::visitCheckEnd(const Pin *pin,
VertexPathIterator tgt_clk_path_iter(tgt_clk_vertex, clk_rf, VertexPathIterator tgt_clk_path_iter(tgt_clk_vertex, clk_rf,
tgt_clk_path_ap, this); tgt_clk_path_ap, this);
while (tgt_clk_path_iter.hasNext()) { while (tgt_clk_path_iter.hasNext()) {
PathVertex *tgt_clk_path = tgt_clk_path_iter.next(); Path *tgt_clk_path = tgt_clk_path_iter.next();
ClkInfo *tgt_clk_info = tgt_clk_path->clkInfo(this); ClkInfo *tgt_clk_info = tgt_clk_path->clkInfo(this);
const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this); const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this);
const Clock *tgt_clk = tgt_clk_path->clock(this); const Clock *tgt_clk = tgt_clk_path->clock(this);
@ -318,7 +318,7 @@ VisitPathEnds::visitOutputDelayEnd(const Pin *pin,
RiseFall *ref_rf = output_delay->refTransition(); RiseFall *ref_rf = output_delay->refTransition();
VertexPathIterator ref_path_iter(ref_vertex,ref_rf,path_ap,this); VertexPathIterator ref_path_iter(ref_vertex,ref_rf,path_ap,this);
while (ref_path_iter.hasNext()) { while (ref_path_iter.hasNext()) {
PathVertex *ref_path = ref_path_iter.next(); Path *ref_path = ref_path_iter.next();
if (ref_path->isClock(this) if (ref_path->isClock(this)
&& (tgt_clk == nullptr && (tgt_clk == nullptr
|| ref_path->clock(this) == tgt_clk)) || ref_path->clock(this) == tgt_clk))
@ -343,7 +343,7 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay,
Path *path, Path *path,
const RiseFall *end_rf, const RiseFall *end_rf,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
PathVertex *ref_path, Path *ref_path,
const MinMax *min_max, const MinMax *min_max,
PathEndVisitor *visitor, PathEndVisitor *visitor,
bool &is_constrained) bool &is_constrained)
@ -414,7 +414,7 @@ VisitPathEnds::visitGatedClkEnd(const Pin *pin,
min_max); min_max);
VertexPathIterator clk_path_iter(clk_vertex, clk_rf, clk_path_ap, this); VertexPathIterator clk_path_iter(clk_vertex, clk_rf, clk_path_ap, this);
while (clk_path_iter.hasNext()) { while (clk_path_iter.hasNext()) {
PathVertex *clk_path = clk_path_iter.next(); Path *clk_path = clk_path_iter.next();
const ClockEdge *clk_edge = clk_path->clkEdge(this); const ClockEdge *clk_edge = clk_path->clkEdge(this);
const Clock *clk = clk_edge ? clk_edge->clock() : nullptr; const Clock *clk = clk_edge ? clk_edge->clock() : nullptr;
if (clk_path->isClock(this) if (clk_path->isClock(this)
@ -544,7 +544,7 @@ VisitPathEnds::visitDataCheckEnd1(DataCheck *check,
bool found_from_path = false; bool found_from_path = false;
VertexPathIterator tgt_clk_path_iter(from_vertex,from_rf,clk_ap,this); VertexPathIterator tgt_clk_path_iter(from_vertex,from_rf,clk_ap,this);
while (tgt_clk_path_iter.hasNext()) { while (tgt_clk_path_iter.hasNext()) {
PathVertex *tgt_clk_path = tgt_clk_path_iter.next(); Path *tgt_clk_path = tgt_clk_path_iter.next();
const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this); const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this);
// Ignore generated clock source paths. // Ignore generated clock source paths.
if (tgt_clk_edge if (tgt_clk_edge
@ -584,7 +584,7 @@ VisitPathEnds::visitUnconstrainedPathEnds(const Pin *pin,
{ {
VertexPathIterator path_iter(vertex, this); VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
PathAnalysisPt *path_ap = path->pathAnalysisPt(this); PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
const MinMax *path_min_max = path_ap->pathMinMax(); const MinMax *path_min_max = path_ap->pathMinMax();
if ((corner == nullptr if ((corner == nullptr

View File

@ -28,21 +28,20 @@
#include "Graph.hh" #include "Graph.hh"
#include "Bfs.hh" #include "Bfs.hh"
#include "Search.hh" #include "Search.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
#include "Tag.hh" #include "Tag.hh"
#include "VisitPathEnds.hh" #include "VisitPathEnds.hh"
namespace sta { namespace sta {
typedef Set<PathVertex*, PathLess> PathVertexSet; typedef Set<Path*, PathLess> PathSet;
typedef Map<Vertex*, PathVertexSet*> VertexPathSetMap; typedef Map<Vertex*, PathSet*> VertexPathSetMap;
static void static void
vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map, vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map,
Vertex *vertex, Vertex *vertex,
Tag *tag, Tag *tag,
int arrival_index,
const StaState *sta); const StaState *sta);
// Visit each path end for a vertex and add the worst one in each // Visit each path end for a vertex and add the worst one in each
@ -87,7 +86,7 @@ protected:
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *from_path,
const Arrival &from_arrival, const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
@ -99,8 +98,7 @@ protected:
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
void fromMatches(Vertex *from_vertex, void fromMatches(Vertex *from_vertex,
Tag *from_tag, Tag *from_tag);
int from_arrival_index);
private: private:
VertexVisitor *visitor_; VertexVisitor *visitor_;
@ -139,10 +137,10 @@ visitPathGroupVertices(PathGroup *path_group,
// Cleanup. // Cleanup.
VertexPathSetMap::Iterator matching_iter(matching_path_map); VertexPathSetMap::Iterator matching_iter(matching_path_map);
while (matching_iter.hasNext()) { while (matching_iter.hasNext()) {
PathVertexSet *paths = matching_iter.next(); PathSet *paths = matching_iter.next();
PathVertexSet::Iterator path_iter(paths); PathSet::Iterator path_iter(paths);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathVertex *path = path_iter.next(); Path *path = path_iter.next();
delete path; delete path;
} }
delete paths; delete paths;
@ -181,14 +179,9 @@ VisitPathGroupEnds::visit(PathEnd *path_end)
{ {
PathGroup *group = sta_->search()->pathGroup(path_end); PathGroup *group = sta_->search()->pathGroup(path_end);
if (group == path_group_) { if (group == path_group_) {
PathRef path(path_end->pathRef()); Path *path = path_end->path();
Vertex *vertex = path.vertex(sta_); Vertex *vertex = path->vertex(sta_);
vertexPathSetMapInsertPath(matching_path_map_, vertex, path->tag(sta_), sta_);
int arrival_index;
bool arrival_exists;
path.arrivalIndex(arrival_index, arrival_exists);
vertexPathSetMapInsertPath(matching_path_map_, vertex, path.tag(sta_),
arrival_index, sta_);
vertex_matches_ = true; vertex_matches_ = true;
} }
} }
@ -197,16 +190,15 @@ static void
vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map, vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map,
Vertex *vertex, Vertex *vertex,
Tag *tag, Tag *tag,
int arrival_index,
const StaState *sta) const StaState *sta)
{ {
PathVertexSet *matching_paths = matching_path_map->findKey(vertex); PathSet *matching_paths = matching_path_map->findKey(vertex);
if (matching_paths == nullptr) { if (matching_paths == nullptr) {
PathLess path_less(sta); PathLess path_less(sta);
matching_paths = new PathVertexSet(path_less); matching_paths = new PathSet(path_less);
(*matching_path_map)[vertex] = matching_paths; (*matching_path_map)[vertex] = matching_paths;
} }
PathVertex *vpath = new PathVertex(vertex, tag, arrival_index); Path *vpath = new Path(vertex, tag, sta);
matching_paths->insert(vpath); matching_paths->insert(vpath);
} }
@ -262,7 +254,7 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
Vertex *from_vertex, Vertex *from_vertex,
const RiseFall *, const RiseFall *,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, Path *,
const Arrival &, const Arrival &,
Edge *, Edge *,
TimingArc *, TimingArc *,
@ -274,12 +266,9 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
const MinMax *, const MinMax *,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap)
{ {
PathVertexSet *matching_paths = matching_path_map_->findKey(to_vertex); PathSet *matching_paths = matching_path_map_->findKey(to_vertex);
if (matching_paths) { if (matching_paths) {
int arrival_index; Path to_path(to_vertex, to_tag, this);
bool arrival_exists;
from_path->arrivalIndex(arrival_index, arrival_exists);
PathVertex to_path(to_vertex, to_tag, this);
if (!to_path.isNull()) { if (!to_path.isNull()) {
if (matching_paths->hasKey(&to_path)) { if (matching_paths->hasKey(&to_path)) {
debugPrint(debug_, "visit_path_group", 2, "match %s %s -> %s %s", debugPrint(debug_, "visit_path_group", 2, "match %s %s -> %s %s",
@ -287,13 +276,13 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
from_tag->asString(this), from_tag->asString(this),
to_vertex->name(network_), to_vertex->name(network_),
to_tag->asString(this)); to_tag->asString(this));
fromMatches(from_vertex, from_tag, arrival_index); fromMatches(from_vertex, from_tag);
} }
} }
else { else {
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this); VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this);
while (to_iter.hasNext()) { while (to_iter.hasNext()) {
PathVertex *to_path = to_iter.next(); Path *to_path = to_iter.next();
if (tagMatchNoCrpr(to_path->tag(this), to_tag) if (tagMatchNoCrpr(to_path->tag(this), to_tag)
&& matching_paths->hasKey(to_path)) { && matching_paths->hasKey(to_path)) {
debugPrint(debug_, "visit_path_group", 2, debugPrint(debug_, "visit_path_group", 2,
@ -302,7 +291,7 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
from_tag->asString(this), from_tag->asString(this),
to_vertex->name(network_), to_vertex->name(network_),
to_tag->asString(this)); to_tag->asString(this));
fromMatches(from_vertex, from_tag, arrival_index); fromMatches(from_vertex, from_tag);
} }
} }
} }
@ -312,12 +301,11 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
void void
PathGroupPathVisitor::fromMatches(Vertex *from_vertex, PathGroupPathVisitor::fromMatches(Vertex *from_vertex,
Tag *from_tag, Tag *from_tag)
int from_arrival_index)
{ {
vertex_matches_ = true; vertex_matches_ = true;
vertexPathSetMapInsertPath(matching_path_map_, from_vertex, vertexPathSetMapInsertPath(matching_path_map_, from_vertex,
from_tag, from_arrival_index, this); from_tag, this);
} }
} // namespace } // namespace

View File

@ -45,7 +45,6 @@
#include "Parasitics.hh" #include "Parasitics.hh"
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "Path.hh" #include "Path.hh"
#include "PathRef.hh"
#include "PathExpanded.hh" #include "PathExpanded.hh"
#include "StaState.hh" #include "StaState.hh"
#include "search/Sim.hh" #include "search/Sim.hh"
@ -118,11 +117,11 @@ private:
int stageGateInputPathIndex(Stage stage); int stageGateInputPathIndex(Stage stage);
int stageDrvrPathIndex(Stage stage); int stageDrvrPathIndex(Stage stage);
int stageLoadPathIndex(Stage stage); int stageLoadPathIndex(Stage stage);
const PathRef *stageGateInputPath(Stage stage); const Path *stageGateInputPath(Stage stage);
const PathRef *stageDrvrPath(Stage stage); const Path *stageDrvrPath(Stage stage);
const PathRef *stageLoadPath(Stage stage); const Path *stageLoadPath(Stage stage);
TimingArc *stageGateArc(Stage stage); const TimingArc *stageGateArc(Stage stage);
TimingArc *stageWireArc(Stage stage); const TimingArc *stageWireArc(Stage stage);
Edge *stageGateEdge(Stage stage); Edge *stageGateEdge(Stage stage);
Edge *stageWireEdge(Stage stage); Edge *stageWireEdge(Stage stage);
Pin *stageGateInputPin(Stage stage); Pin *stageGateInputPin(Stage stage);
@ -139,7 +138,7 @@ private:
float findSlew(const Path *path); float findSlew(const Path *path);
float findSlew(const Path *path, float findSlew(const Path *path,
const RiseFall *rf, const RiseFall *rf,
TimingArc *next_arc); const TimingArc *next_arc);
Path *path_; Path *path_;
PathExpanded path_expanded_; PathExpanded path_expanded_;
// Input clock waveform cycles. // Input clock waveform cycles.
@ -246,7 +245,7 @@ float
WritePathSpice::maxTime() WritePathSpice::maxTime()
{ {
Stage input_stage = stageFirst(); Stage input_stage = stageFirst();
const PathRef *input_path = stageDrvrPath(input_stage); const Path *input_path = stageDrvrPath(input_stage);
if (input_path->isClock(this)) { if (input_path->isClock(this)) {
const Clock *clk = input_path->clock(this); const Clock *clk = input_path->clock(this);
float period = clk->period(); float period = clk->period();
@ -264,7 +263,7 @@ WritePathSpice::pathMaxTime()
{ {
float max_time = 0.0; float max_time = 0.0;
for (size_t i = 0; i < path_expanded_.size(); i++) { for (size_t i = 0; i < path_expanded_.size(); i++) {
const PathRef *path = path_expanded_.path(i); const Path *path = path_expanded_.path(i);
const RiseFall *rf = path->transition(this); const RiseFall *rf = path->transition(this);
Vertex *vertex = path->vertex(this); Vertex *vertex = path->vertex(this);
float path_max_slew = railToRailSlew(findSlew(vertex,rf,nullptr), rf); float path_max_slew = railToRailSlew(findSlew(vertex,rf,nullptr), rf);
@ -278,7 +277,7 @@ WritePathSpice::pathMaxTime()
path_max_slew = load_slew; path_max_slew = load_slew;
} }
} }
float path_max_time = delayAsFloat(path->arrival(this)) + path_max_slew * 2.0; float path_max_time = delayAsFloat(path->arrival()) + path_max_slew * 2.0;
if (path_max_time > max_time) if (path_max_time > max_time)
max_time = path_max_time; max_time = path_max_time;
} }
@ -321,7 +320,7 @@ WritePathSpice::writeInputSource()
streamPrint(spice_stream_, "**************\n\n"); streamPrint(spice_stream_, "**************\n\n");
Stage input_stage = stageFirst(); Stage input_stage = stageFirst();
const PathRef *input_path = stageDrvrPath(input_stage); const Path *input_path = stageDrvrPath(input_stage);
if (input_path->isClock(this)) if (input_path->isClock(this))
writeClkWaveform(); writeClkWaveform();
else else
@ -333,9 +332,9 @@ void
WritePathSpice::writeInputWaveform() WritePathSpice::writeInputWaveform()
{ {
Stage input_stage = stageFirst(); Stage input_stage = stageFirst();
const PathRef *input_path = stageDrvrPath(input_stage); const Path *input_path = stageDrvrPath(input_stage);
const RiseFall *rf = input_path->transition(this); const RiseFall *rf = input_path->transition(this);
TimingArc *next_arc = stageGateArc(input_stage + 1); const TimingArc *next_arc = stageGateArc(input_stage + 1);
float slew0 = findSlew(input_path, rf, next_arc); float slew0 = findSlew(input_path, rf, next_arc);
float threshold = default_library_->inputThreshold(rf); float threshold = default_library_->inputThreshold(rf);
@ -358,8 +357,8 @@ void
WritePathSpice::writeClkWaveform() WritePathSpice::writeClkWaveform()
{ {
Stage input_stage = stageFirst(); Stage input_stage = stageFirst();
const PathRef *input_path = stageDrvrPath(input_stage); const Path *input_path = stageDrvrPath(input_stage);
TimingArc *next_arc = stageGateArc(input_stage + 1); const TimingArc *next_arc = stageGateArc(input_stage + 1);
const ClockEdge *clk_edge = input_path->clkEdge(this); const ClockEdge *clk_edge = input_path->clkEdge(this);
const Clock *clk = clk_edge->clock(); const Clock *clk = clk_edge->clock();
@ -403,7 +402,7 @@ WritePathSpice::findSlew(const Path *path)
float float
WritePathSpice::findSlew(const Path *path, WritePathSpice::findSlew(const Path *path,
const RiseFall *rf, const RiseFall *rf,
TimingArc *next_arc) const TimingArc *next_arc)
{ {
Vertex *vertex = path->vertex(this); Vertex *vertex = path->vertex(this);
return findSlew(vertex, rf, next_arc); return findSlew(vertex, rf, next_arc);
@ -419,9 +418,9 @@ WritePathSpice::writeMeasureStmts()
streamPrint(spice_stream_, "********************\n\n"); streamPrint(spice_stream_, "********************\n\n");
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
const PathRef *gate_input_path = stageGateInputPath(stage); const Path *gate_input_path = stageGateInputPath(stage);
const PathRef *drvr_path = stageDrvrPath(stage); const Path *drvr_path = stageDrvrPath(stage);
const PathRef *load_path = stageLoadPath(stage); const Path *load_path = stageLoadPath(stage);
if (gate_input_path) { if (gate_input_path) {
// gate input -> gate output // gate input -> gate output
writeMeasureSlewStmt(stage, gate_input_path); writeMeasureSlewStmt(stage, gate_input_path);
@ -520,7 +519,7 @@ WritePathSpice::writeGateStage(Stage stage)
drvr_port->name()); drvr_port->name());
writeSubcktInst(inst); writeSubcktInst(inst);
const PathRef *drvr_path = stageDrvrPath(stage); const Path *drvr_path = stageDrvrPath(stage);
const RiseFall *drvr_rf = drvr_path->transition(this); const RiseFall *drvr_rf = drvr_path->transition(this);
Edge *gate_edge = stageGateEdge(stage); Edge *gate_edge = stageGateEdge(stage);
@ -550,7 +549,7 @@ WritePathSpice::writeGateStage(Stage stage)
void void
WritePathSpice::writeStageParasitics(Stage stage) WritePathSpice::writeStageParasitics(Stage stage)
{ {
const PathRef *drvr_path = stageDrvrPath(stage); const Path *drvr_path = stageDrvrPath(stage);
DcalcAnalysisPt *dcalc_ap = drvr_path->dcalcAnalysisPt(this); DcalcAnalysisPt *dcalc_ap = drvr_path->dcalcAnalysisPt(this);
ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
const Pin *drvr_pin = stageDrvrPin(stage); const Pin *drvr_pin = stageDrvrPin(stage);
@ -579,7 +578,7 @@ WritePathSpice::findPathCellNames()
{ {
StdStringSet path_cell_names; StdStringSet path_cell_names;
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
TimingArc *arc = stageGateArc(stage); const TimingArc *arc = stageGateArc(stage);
if (arc) { if (arc) {
LibertyCell *cell = arc->set()->libertyCell(); LibertyCell *cell = arc->set()->libertyCell();
if (cell) { if (cell) {
@ -643,64 +642,62 @@ WritePathSpice::stageLoadPathIndex(Stage stage)
return stage * 2 - 1; return stage * 2 - 1;
} }
const PathRef * const Path *
WritePathSpice::stageGateInputPath(Stage stage) WritePathSpice::stageGateInputPath(Stage stage)
{ {
int path_index = stageGateInputPathIndex(stage); int path_index = stageGateInputPathIndex(stage);
return path_expanded_.path(path_index); return path_expanded_.path(path_index);
} }
const PathRef * const Path *
WritePathSpice::stageDrvrPath(Stage stage) WritePathSpice::stageDrvrPath(Stage stage)
{ {
int path_index = stageDrvrPathIndex(stage); int path_index = stageDrvrPathIndex(stage);
return path_expanded_.path(path_index); return path_expanded_.path(path_index);
} }
const PathRef * const Path *
WritePathSpice::stageLoadPath(Stage stage) WritePathSpice::stageLoadPath(Stage stage)
{ {
int path_index = stageLoadPathIndex(stage); int path_index = stageLoadPathIndex(stage);
return path_expanded_.path(path_index); return path_expanded_.path(path_index);
} }
TimingArc * const TimingArc *
WritePathSpice::stageGateArc(Stage stage) WritePathSpice::stageGateArc(Stage stage)
{ {
int path_index = stageDrvrPathIndex(stage); int path_index = stageDrvrPathIndex(stage);
if (path_index >= 0) if (path_index >= 0)
return path_expanded_.prevArc(path_index); return path_expanded_.path(path_index)->prevArc(this);
else else
return nullptr; return nullptr;
} }
TimingArc * const TimingArc *
WritePathSpice::stageWireArc(Stage stage) WritePathSpice::stageWireArc(Stage stage)
{ {
int path_index = stageLoadPathIndex(stage); int path_index = stageLoadPathIndex(stage);
return path_expanded_.prevArc(path_index); return path_expanded_.path(path_index)->prevArc(this);
} }
Edge * Edge *
WritePathSpice::stageGateEdge(Stage stage) WritePathSpice::stageGateEdge(Stage stage)
{ {
const PathRef *path = stageDrvrPath(stage); const Path *path = stageDrvrPath(stage);
TimingArc *arc = stageGateArc(stage); return path->prevEdge(this);
return path->prevEdge(arc, this);
} }
Edge * Edge *
WritePathSpice::stageWireEdge(Stage stage) WritePathSpice::stageWireEdge(Stage stage)
{ {
const PathRef *path = stageLoadPath(stage); const Path *path = stageLoadPath(stage);
TimingArc *arc = stageWireArc(stage); return path->prevEdge(this);
return path->prevEdge(arc, this);
} }
Pin * Pin *
WritePathSpice::stageGateInputPin(Stage stage) WritePathSpice::stageGateInputPin(Stage stage)
{ {
const PathRef *path = stageGateInputPath(stage); const Path *path = stageGateInputPath(stage);
return path->pin(this); return path->pin(this);
} }
@ -714,7 +711,7 @@ WritePathSpice::stageGateInputPort(Stage stage)
Pin * Pin *
WritePathSpice::stageDrvrPin(Stage stage) WritePathSpice::stageDrvrPin(Stage stage)
{ {
const PathRef *path = stageDrvrPath(stage); const Path *path = stageDrvrPath(stage);
return path->pin(this); return path->pin(this);
} }
@ -728,7 +725,7 @@ WritePathSpice::stageDrvrPort(Stage stage)
Pin * Pin *
WritePathSpice::stageLoadPin(Stage stage) WritePathSpice::stageLoadPin(Stage stage)
{ {
const PathRef *path = stageLoadPath(stage); const Path *path = stageLoadPath(stage);
return path->pin(this); return path->pin(this);
} }

View File

@ -39,7 +39,7 @@
#include "Graph.hh" #include "Graph.hh"
#include "search/Sim.hh" #include "search/Sim.hh"
#include "Clock.hh" #include "Clock.hh"
#include "PathVertex.hh" #include "Path.hh"
#include "DcalcAnalysisPt.hh" #include "DcalcAnalysisPt.hh"
#include "Bdd.hh" #include "Bdd.hh"
@ -474,7 +474,7 @@ WriteSpice::pgPortVoltage(LibertyPgPort *pg_port)
float float
WriteSpice::findSlew(Vertex *vertex, WriteSpice::findSlew(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
TimingArc *next_arc) const TimingArc *next_arc)
{ {
float slew = delayAsFloat(graph_->slew(vertex, rf, dcalc_ap_->index())); float slew = delayAsFloat(graph_->slew(vertex, rf, dcalc_ap_->index()));
if (slew == 0.0 && next_arc) if (slew == 0.0 && next_arc)
@ -486,7 +486,7 @@ WriteSpice::findSlew(Vertex *vertex,
// Look up the smallest slew axis value in the timing arc delay table. // Look up the smallest slew axis value in the timing arc delay table.
float float
WriteSpice::slewAxisMinValue(TimingArc *arc) WriteSpice::slewAxisMinValue(const TimingArc *arc)
{ {
GateTableModel *gate_model = arc->gateTableModel(dcalc_ap_); GateTableModel *gate_model = arc->gateTableModel(dcalc_ap_);
if (gate_model) { if (gate_model) {

View File

@ -135,8 +135,8 @@ protected:
const char *spiceTrans(const RiseFall *rf); const char *spiceTrans(const RiseFall *rf);
float findSlew(Vertex *vertex, float findSlew(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
TimingArc *next_arc); const TimingArc *next_arc);
float slewAxisMinValue(TimingArc *arc); float slewAxisMinValue(const TimingArc *arc);
float clkWaveformTimeOffset(const Clock *clk); float clkWaveformTimeOffset(const Clock *clk);
void gatePortValues(const Pin *input_pin, void gatePortValues(const Pin *input_pin,

View File

@ -33,7 +33,7 @@
%inline %{ %inline %{
void void
write_path_spice_cmd(PathRef *path, write_path_spice_cmd(Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,

View File

@ -77,7 +77,7 @@ proc get_object_property { object prop } {
return [edge_property $object $prop] return [edge_property $object $prop]
} elseif { $object_type == "PathEnd" } { } elseif { $object_type == "PathEnd" } {
return [path_end_property $object $prop] return [path_end_property $object $prop]
} elseif { $object_type == "PathRef" } { } elseif { $object_type == "Path" } {
return [path_ref_property $object $prop] return [path_ref_property $object $prop]
} elseif { $object_type == "TimingArcSet" } { } elseif { $object_type == "TimingArcSet" } {
return [timing_arc_set_property $object $prop] return [timing_arc_set_property $object $prop]

View File

@ -42,7 +42,7 @@
#include "Clock.hh" #include "Clock.hh"
#include "Corner.hh" #include "Corner.hh"
#include "Search.hh" #include "Search.hh"
#include "PathRef.hh" #include "Path.hh"
#include "search/Tag.hh" #include "search/Tag.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
@ -1138,17 +1138,17 @@ using namespace sta;
Tcl_SetObjResult(interp, obj); Tcl_SetObjResult(interp, obj);
} }
%typemap(out) PathRefSeq* { %typemap(out) PathSeq* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false); Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj); Tcl_SetObjResult(interp, obj);
Tcl_Obj *list = Tcl_NewListObj(0, nullptr); Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
PathRefSeq *paths = $1; PathSeq *paths = $1;
PathRefSeq::Iterator path_iter(paths); PathSeq::Iterator path_iter(paths);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathRef *path = &path_iter.next(); Path *path = &path_iter.next();
PathRef *copy = new PathRef(path); Path *copy = new Path(path);
Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false); Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_Path, false);
Tcl_ListObjAppendElement(interp, list, obj); Tcl_ListObjAppendElement(interp, list, obj);
} }
Tcl_SetObjResult(interp, list); Tcl_SetObjResult(interp, list);
@ -1354,11 +1354,10 @@ using namespace sta;
Tcl_SetObjResult(interp, list); Tcl_SetObjResult(interp, list);
} }
break; break;
case PropertyValue::Type::type_path_refs: { case PropertyValue::Type::type_paths: {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr); Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (PathRef &path : *value.pathRefs()) { for (const Path *path : *value.paths()) {
PathRef *copy = new PathRef(path); Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast<Path*>(path), SWIGTYPE_p_Path, false);
Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false);
Tcl_ListObjAppendElement(interp, list, obj); Tcl_ListObjAppendElement(interp, list, obj);
} }
Tcl_SetObjResult(interp, list); Tcl_SetObjResult(interp, list);