Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ set(STA_SOURCE
parasitics/SpefReader.cc
parasitics/SpefReaderPvt.hh

sdc/SdcClass.cc
sdc/Clock.cc
sdc/ClockGatingCheck.cc
sdc/ClockGroups.cc
Expand Down
14 changes: 7 additions & 7 deletions include/sta/Sdc.hh
Original file line number Diff line number Diff line change
Expand Up @@ -993,27 +993,27 @@ public:
const Clock *clk,
const RiseFall *clk_rf,
const MinMax *min_max,
ExceptionStateSet *&states) const;
ExceptionStates &states) const;
bool exceptionFromStates(const Pin *pin,
const RiseFall *rf,
const Clock *clk,
const RiseFall *clk_rf,
const MinMax *min_max,
bool include_filter,
ExceptionStateSet *&states) const;
ExceptionStates &states) const;
void exceptionFromClkStates(const Pin *pin,
const RiseFall *rf,
const Clock *clk,
const RiseFall *clk_rf,
const MinMax *min_max,
ExceptionStateSet *&states) const;
ExceptionStates &states) const;
void filterRegQStates(const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max,
ExceptionStateSet *&states) const;
ExceptionStates &states) const;
// Return hierarchical -thru exceptions that start between
// from_pin and to_pin.
ExceptionStateSet *exceptionThruStates(const Pin *from_pin,
ExceptionStates exceptionThruStates(const Pin *from_pin,
const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max) const;
Expand Down Expand Up @@ -1176,12 +1176,12 @@ protected:
const RiseFall *rf,
const MinMax *min_max,
bool include_filter,
ExceptionStateSet *&states) const;
ExceptionStates &states) const;
void exceptionThruStates(const ExceptionPathSet *exceptions,
const RiseFall *to_rf,
const MinMax *min_max,
// Return value.
ExceptionStateSet *&states) const;
ExceptionStates &states) const;
void exceptionTo(const ExceptionPathSet *to_exceptions,
ExceptionPathType type,
const Pin *pin,
Expand Down
79 changes: 78 additions & 1 deletion include/sta/SdcClass.hh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#pragma once

#include <unordered_set>
#include "Map.hh"
#include "Set.hh"
#include "Vector.hh"
Expand Down Expand Up @@ -112,7 +113,83 @@ public:
};

class ExceptionPath;
typedef Set<ExceptionState*, ExceptionStateLess> ExceptionStateSet;
class ExceptionStates {
public:
typedef Set<ExceptionState*, ExceptionStateLess> Super;
ExceptionStates() : holder_(nullptr), hasLoopPath_(false), hasFilterPath_(false) {}
ExceptionStates(ExceptionStates&& o) noexcept : holder_(o.holder_), hasLoopPath_(o.hasLoopPath_), hasFilterPath_(o.hasFilterPath_) {
o.holder_ = nullptr;
}
ExceptionStates(const ExceptionStates& o) = delete;
ExceptionStates& operator=(const ExceptionStates & o) = delete;
~ExceptionStates() { delete holder_; }
explicit operator bool () const { return holder_; }
bool hasLoopPath() const { return hasLoopPath_; }
bool hasFilterPath() const { return hasFilterPath_; }

void insert(ExceptionState* state);
void clear();

void to(Super& s) { if (holder_) s.swap(*holder_); }
void takeOver(ExceptionStates&& o) {
clear();
holder_ = o.holder_;
hasLoopPath_ = o.hasLoopPath_;
hasFilterPath_ = o.hasFilterPath_;
o.holder_ = nullptr;
}
private:
Super *holder_;
bool hasLoopPath_;
bool hasFilterPath_;
};

class ExceptionStateSet {
struct Impl : public Set<ExceptionState*, ExceptionStateLess> {
typedef Set<ExceptionState*, ExceptionStateLess> Super;
Impl(ExceptionStates & tmp) : Super(), hash_(hash_init_value), refcount(0), hasLoopPath_(tmp.hasLoopPath()), hasFilterPath_(tmp.hasFilterPath()) { tmp.to(super()); rehash(); }
size_t hash() const { return hash_; }
bool operator == (Impl const & i) const;

size_t hash_;
unsigned refcount :30;
bool hasLoopPath_ :1;
bool hasFilterPath_:1;
protected:
Super& super() { return *this; }
void rehash();
};
Impl* impl;
public:
ExceptionStateSet(ExceptionStates & tmp) : impl(create(tmp)) { incr(impl); }
ExceptionStateSet(const ExceptionStateSet & o) : impl(o.impl) { incr(impl); }
ExceptionStateSet& operator=(const ExceptionStateSet & o) {
Impl* i = o.impl; incr(i); decr(impl); impl = i; return *this;
}
explicit operator bool () const { return impl; }
bool operator==(const ExceptionStateSet& o) const;
bool empty() const { return !impl; }
size_t size() const { return impl ? impl->size() : 0; }
struct ConstIterator : public Impl::Super::ConstIterator {
ConstIterator(const ExceptionStateSet& set) : Impl::Super::ConstIterator(set.impl) {}
};
Impl::Super::const_iterator begin() const { return impl->begin(); }
Impl::Super::const_iterator end() const { return impl->end(); }
int cmp(ExceptionStateSet const & o) const;
bool hasLoopPath() const { return impl && impl->hasLoopPath_; }
bool hasFilterPath() const { return impl && impl->hasFilterPath_; }
size_t hash() const { return impl ? impl->hash() : 0; }
private:
void incr(Impl* i) { if (i) ++i->refcount; }
void decr(Impl* i) { if (i && --i->refcount == 0) { mgr.erase(i); delete i; } }
Impl* create(ExceptionStates & tmp);

struct ImplHash { size_t operator()(Impl* i) const { return i ? i->hash() : 0; } };
struct ImplEqual { bool operator()(Impl* a, Impl* b) const { return a == b || (a && b && *a == *b); } };
typedef std::unordered_set<Impl*,ImplHash, ImplEqual> Manager;
static Impl* unique(Impl* i);
static thread_local Manager mgr;
};

enum class CrprMode { same_pin, same_transition };

Expand Down
3 changes: 1 addition & 2 deletions include/sta/Search.hh
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,7 @@ public:
bool is_clk,
InputDelay *input_delay,
bool is_segment_start,
ExceptionStateSet *states,
bool own_states);
const ExceptionStateSet& states);
void reportTags() const;
void reportClkInfos() const;
virtual ClkInfo *findClkInfo(const ClockEdge *clk_edge,
Expand Down
37 changes: 14 additions & 23 deletions sdc/Sdc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5126,7 +5126,7 @@ Sdc::exceptionFromStates(const Pin *pin,
const Clock *clk,
const RiseFall *clk_rf,
const MinMax *min_max,
ExceptionStateSet *&states) const
ExceptionStates &states) const
{
return exceptionFromStates(pin, rf, clk, clk_rf, min_max, true, states);
}
Expand All @@ -5138,7 +5138,7 @@ Sdc::exceptionFromStates(const Pin *pin,
const RiseFall *clk_rf,
const MinMax *min_max,
bool include_filter,
ExceptionStateSet *&states) const
ExceptionStates &states) const
{
bool srch_from = true;
if (pin) {
Expand Down Expand Up @@ -5170,8 +5170,7 @@ Sdc::exceptionFromStates(const Pin *pin,
pin, clk_rf, min_max, include_filter,
states);
if (!srch_from) {
delete states;
states = nullptr;
states.clear();
}
return srch_from;
}
Expand All @@ -5182,7 +5181,7 @@ Sdc::exceptionFromStates(const ExceptionPathSet *exceptions,
const RiseFall *rf,
const MinMax *min_max,
bool include_filter,
ExceptionStateSet *&states) const
ExceptionStates &states) const
{
if (exceptions) {
for (ExceptionPath *exception : *exceptions) {
Expand All @@ -5201,17 +5200,13 @@ Sdc::exceptionFromStates(const ExceptionPathSet *exceptions,
// Leave the completed false path state as a marker on the tag,
// but flush all other exception states because they are lower
// priority.
if (states == nullptr)
states = new ExceptionStateSet();
states->clear();
states->insert(state);
states.clear();
states.insert(state);
// No need to examine other exceptions from this
// pin/clock/instance.
return false;
}
if (states == nullptr)
states = new ExceptionStateSet();
states->insert(state);
states.insert(state);
}
}
}
Expand All @@ -5224,7 +5219,7 @@ Sdc::exceptionFromClkStates(const Pin *pin,
const Clock *clk,
const RiseFall *clk_rf,
const MinMax *min_max,
ExceptionStateSet *&states) const
ExceptionStates &states) const
{
if (pin) {
if (!first_from_pin_exceptions_.empty())
Expand All @@ -5247,7 +5242,7 @@ void
Sdc::filterRegQStates(const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max,
ExceptionStateSet *&states) const
ExceptionStates &states) const
{
if (!first_from_pin_exceptions_.empty()) {
const ExceptionPathSet *exceptions =
Expand All @@ -5258,22 +5253,20 @@ Sdc::filterRegQStates(const Pin *to_pin,
if (exception->isFilter()
&& exception->matchesFirstPt(to_rf, min_max)) {
ExceptionState *state = exception->firstState();
if (states == nullptr)
states = new ExceptionStateSet();
states->insert(state);
states.insert(state);
}
}
}
}
}

ExceptionStateSet *
ExceptionStates
Sdc::exceptionThruStates(const Pin *from_pin,
const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max) const
{
ExceptionStateSet *states = nullptr;
ExceptionStates states;
exceptionThruStates(first_thru_pin_exceptions_.findKey(to_pin),
to_rf, min_max, states);
if (!first_thru_edge_exceptions_.empty()) {
Expand All @@ -5296,15 +5289,13 @@ Sdc::exceptionThruStates(const ExceptionPathSet *exceptions,
const RiseFall *to_rf,
const MinMax *min_max,
// Return value.
ExceptionStateSet *&states) const
ExceptionStates &states) const
{
if (exceptions) {
for (ExceptionPath *exception : *exceptions) {
if (exception->matchesFirstPt(to_rf, min_max)) {
ExceptionState *state = exception->firstState();
if (states == nullptr)
states = new ExceptionStateSet();
states->insert(state);
states.insert(state);
}
}
}
Expand Down
76 changes: 76 additions & 0 deletions sdc/SdcClass.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "SdcClass.hh"
#include "Sdc.hh"

namespace sta {

void
ExceptionStates::insert(ExceptionState* state) {
if (!holder_) holder_ = new Super;
holder_->insert(state);
if (!hasLoopPath_ && state->exception()->isLoop()) hasLoopPath_ = true;
if (!hasFilterPath_ && state->exception()->isFilter()) hasFilterPath_ = true;
}

void
ExceptionStates::clear() {
delete holder_;
holder_ = nullptr;
hasLoopPath_ = false;
}

bool
ExceptionStateSet::Impl::operator == (Impl const & i) const {
return (*(Super*)this) == (*(Super*)&i);
}

void
ExceptionStateSet::Impl::rehash() {
hash_ = hash_init_value;
for(auto* state : *this) {
hashIncr(hash_, state->hash());
}
}

bool
ExceptionStateSet::operator==(const ExceptionStateSet& o) const {
return impl == o.impl;
}

thread_local ExceptionStateSet::Manager
ExceptionStateSet::mgr;

ExceptionStateSet::Impl*
ExceptionStateSet::unique(Impl* i) {
if (i->empty()) {
delete i;
return nullptr;
}
auto r = mgr.insert(i);
if (!r.second) {
delete i;
i = *r.first;
}
return i;
}

ExceptionStateSet::Impl*
ExceptionStateSet::create(ExceptionStates & tmp) {
return tmp ? unique(new Impl(tmp)) : nullptr;
}

int
ExceptionStateSet::cmp (const ExceptionStateSet & o) const {
size_t sz1 = size();
size_t sz2 = o.size();
if (sz1 != sz2) return sz1 < sz2 ? 1 : -1;
if (!sz1) return true;
auto it1 = begin();
auto it2 = o.begin();
while (*it1 == *it2) {
++it1, ++it2;
}
if (it1 == end()) return 0;
return *it1 < *it2 ? 1 : -1;
}

} // end namespace sta
2 changes: 1 addition & 1 deletion search/CheckMinPulseWidths.cc
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ MinPulseWidthCheck::closePath(const StaState *sta,
open_tag->inputDelay(),
open_tag->isSegmentStart(),
open_tag->states(),
false, sta);
sta);
debugPrint(sta->debug(), "mpw", 3, " open %s",
open_tag->asString(sta));
debugPrint(sta->debug(), "mpw", 3, " close %s",
Expand Down
Loading