ClkInfo, Tag cmp

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-09-16 13:53:16 -07:00
parent 9f9ad0b4ab
commit 84989688b7
10 changed files with 151 additions and 93 deletions

View File

@ -166,8 +166,8 @@ public:
== values2->values_[MinMax::maxIndex()]));
}
static bool less(const MinMaxValues *values1,
const MinMaxValues *values2)
static int cmp(const MinMaxValues *values1,
const MinMaxValues *values2)
{
if (!values1->exists_[MinMax::minIndex()]
&& values2->exists_[MinMax::minIndex()])

View File

@ -24,6 +24,7 @@
#include "ClkInfo.hh"
#include "Units.hh"
#include "Network.hh"
#include "Graph.hh"
#include "Sdc.hh"
@ -55,6 +56,7 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
latency_(latency),
is_propagated_(is_propagated),
is_gen_clk_src_path_(is_gen_clk_src_path),
crpr_path_refs_filter_(crpr_clk_path ? crpr_clk_path->tag(sta)->isFilter() : false),
is_pulse_clk_(pulse_clk_sense != nullptr),
pulse_clk_sense_(pulse_clk_sense ? pulse_clk_sense->index() : 0),
path_ap_index_(path_ap_index)
@ -78,7 +80,12 @@ ClkInfo::findHash(const StaState *sta)
hashIncr(hash_, network->vertexId(clk_src_));
if (gen_clk_src_)
hashIncr(hash_, network->vertexId(gen_clk_src_));
hashIncr(hash_, crprClkVertexId(sta));
if (crpr_clk_path_.isNull())
hashIncr(hash_, vertex_id_null);
else {
hashIncr(hash_, crpr_clk_path_.vertexId(sta));
hashIncr(hash_, crpr_clk_path_.tag(sta)->hash(false, sta));
}
if (uncertainties_) {
float uncertainty;
bool exists;
@ -101,19 +108,13 @@ ClkInfo::findHash(const StaState *sta)
VertexId
ClkInfo::crprClkVertexId(const StaState *sta) const
{
if (crpr_clk_path_.isNull())
return vertex_id_null;
else
return crpr_clk_path_.vertexId(sta);
return crpr_clk_path_.vertexId(sta);
}
Path *
ClkInfo::crprClkPath(const StaState *sta)
{
if (crpr_clk_path_.isNull())
return nullptr;
else
return Path::vertexPath(crpr_clk_path_, sta);
return Path::vertexPath(crpr_clk_path_, sta);
}
const Path *
@ -125,6 +126,15 @@ ClkInfo::crprClkPath(const StaState *sta) const
return Path::vertexPath(crpr_clk_path_, sta);
}
const Path *
ClkInfo::crprClkPathRaw() const
{
if (crpr_clk_path_.isNull())
return nullptr;
else
return &crpr_clk_path_;
}
std::string
ClkInfo::to_string(const StaState *sta) const
{
@ -150,13 +160,37 @@ ClkInfo::to_string(const StaState *sta) const
if (!crpr_clk_path_.isNull()) {
const Pin *crpr_clk_pin = crpr_clk_path_.vertex(sta)->pin();
result += " crpr_pin ";
result += " crpr ";
result += network->pathName(crpr_clk_pin);
result += "/";
result += std::to_string(crpr_clk_path_.tag(sta)->index());
}
if (is_gen_clk_src_path_)
result += " genclk";
if (gen_clk_src_) {
result += " ";
result += network->pathName(gen_clk_src_);
}
if (insertion_ > 0.0) {
result += " insert";
result += std::to_string(insertion_);
}
if (uncertainties_) {
result += " uncertain ";
float uncertainty;
bool exists;
uncertainties_->value(MinMax::min(), uncertainty, exists);
if (exists)
result += sta->units()->timeUnit()->asString(uncertainty);
uncertainties_->value(MinMax::max(), uncertainty, exists);
if (exists) {
result += ":";
result += sta->units()->timeUnit()->asString(uncertainty);
}
}
return result;
}
@ -178,13 +212,6 @@ ClkInfo::pulseClkSense() const
return nullptr;
}
bool
ClkInfo::refsFilter(const StaState *sta) const
{
return !crpr_clk_path_.isNull()
&& crpr_clk_path_.tag(sta)->isFilter();
}
////////////////////////////////////////////////////////////////
size_t
@ -204,13 +231,13 @@ bool
ClkInfoEqual::operator()(const ClkInfo *clk_info1,
const ClkInfo *clk_info2) const
{
return clkInfoEqual(clk_info1, clk_info2, sta_);
return ClkInfo::equal(clk_info1, clk_info2, sta_);
}
bool
clkInfoEqual(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta)
ClkInfo::equal(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta)
{
bool crpr_on = sta->crprActive();
ClockUncertainties *uncertainties1 = clk_info1->uncertainties();
@ -220,14 +247,13 @@ clkInfoEqual(const ClkInfo *clk_info1,
&& clk_info1->clkSrc() == clk_info2->clkSrc()
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
&& (!crpr_on
|| Path::equal(clk_info1->crprClkPath(sta),
clk_info2->crprClkPath(sta),
|| Path::equal(clk_info1->crprClkPathRaw(),
clk_info2->crprClkPathRaw(),
sta))
&& ((uncertainties1 == nullptr
&& uncertainties2 == nullptr)
|| (uncertainties1 && uncertainties2
&& MinMaxValues<float>::equal(uncertainties1,
uncertainties2)))
&& ClockUncertainties::equal(uncertainties1, uncertainties2)))
&& clk_info1->insertion() == clk_info2->insertion()
&& clk_info1->latency() == clk_info2->latency()
&& clk_info1->isPropagated() == clk_info2->isPropagated()
@ -247,13 +273,13 @@ bool
ClkInfoLess::operator()(const ClkInfo *clk_info1,
const ClkInfo *clk_info2) const
{
return clkInfoCmp(clk_info1, clk_info2, sta_) < 0;
return ClkInfo::cmp(clk_info1, clk_info2, sta_) < 0;
}
int
clkInfoCmp(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta)
ClkInfo::cmp(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta)
{
const ClockEdge *clk_edge1 = clk_info1->clkEdge();
const ClockEdge *clk_edge2 = clk_info2->clkEdge();
@ -292,8 +318,8 @@ clkInfoCmp(const ClkInfo *clk_info1,
bool crpr_on = sta->crprActive();
if (crpr_on) {
const Path *crpr_path1 = clk_info1->crprClkPath(sta);
const Path *crpr_path2 = clk_info2->crprClkPath(sta);
const Path *crpr_path1 = clk_info1->crprClkPathRaw();
const Path *crpr_path2 = clk_info2->crprClkPathRaw();
int path_cmp = Path::cmp(crpr_path1, crpr_path2, sta);
if (path_cmp != 0)
return path_cmp;
@ -305,13 +331,11 @@ clkInfoCmp(const ClkInfo *clk_info1,
return -1;
if (uncertainties1 && uncertainties2 == nullptr)
return 1;
if (uncertainties1 && uncertainties2
&& MinMaxValues<float>::less(uncertainties1, uncertainties2))
return -1;
if (uncertainties1 && uncertainties2
&& MinMaxValues<float>::less(uncertainties2, uncertainties1))
return 1;
if (uncertainties1 && uncertainties2) {
int uncertain_cmp = ClockUncertainties::cmp(uncertainties1, uncertainties2);
if (uncertain_cmp != 0)
return uncertain_cmp;
}
const Arrival &insert1 = clk_info1->insertion();
const Arrival &insert2 = clk_info2->insertion();
if (delayLess(insert1, insert2, sta))

View File

@ -69,13 +69,20 @@ public:
const Path *crprClkPath(const StaState *sta) const;
VertexId crprClkVertexId(const StaState *sta) const;
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
bool refsFilter(const StaState *sta) const;
// This clk_info/tag is used for a generated clock source path.
bool isGenClkSrcPath() const { return is_gen_clk_src_path_; }
size_t hash() const { return hash_; }
bool crprPathRefsFilter() const { return crpr_path_refs_filter_; }
static int cmp(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
static bool equal(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
protected:
void findHash(const StaState *sta);
const Path *crprClkPathRaw() const;
private:
const ClockEdge *clk_edge_;
@ -88,20 +95,14 @@ private:
size_t hash_;
bool is_propagated_:1;
bool is_gen_clk_src_path_:1;
// This is used to break a circular dependency in Search::deleteFilteredArrival
// between tags and clk infos that reference a filter.
bool crpr_path_refs_filter_:1;
bool is_pulse_clk_:1;
unsigned int pulse_clk_sense_:RiseFall::index_bit_count;
unsigned int path_ap_index_:path_ap_index_bit_count;
};
int
clkInfoCmp(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
bool
clkInfoEqual(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
class ClkInfoLess
{
public:

View File

@ -361,7 +361,7 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path,
Path *tgt_genclk_path = portClkPath(tgt_clk_edge,
tgt_clk_edge->clock()->defaultPin(),
tgt_path_ap);
Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this);
const Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this);
if (src_clk_path)
findCrpr(src_clk_path, tgt_genclk_path, same_pin, crpr, crpr_pin);
}

View File

@ -608,10 +608,20 @@ Path::cmp(const Path *path1,
const Path *path2,
const StaState *sta)
{
if (path1 && path2) {
if (path1 == path2)
return 0;
else if (path1 == nullptr && path2)
return 1;
else if (path1 && path2 == nullptr)
return -1;
else {
VertexId vertex_id1 = path1->vertexId(sta);
VertexId vertex_id2 = path2->vertexId(sta);
if (vertex_id1 == vertex_id2) {
if (vertex_id1 < vertex_id2)
return -1;
else if (vertex_id1 > vertex_id2)
return 1;
else {
TagIndex tag_index1 = path1->tagIndex(sta);
TagIndex tag_index2 = path2->tagIndex(sta);
if (tag_index1 == tag_index2)
@ -621,18 +631,7 @@ Path::cmp(const Path *path1,
else
return 1;
}
else if (vertex_id1 < vertex_id2)
return -1;
else
return 1;
}
else if (path1 == nullptr
&& path2 == nullptr)
return 0;
else if (path1 == nullptr)
return -1;
else
return 1;
}
int

View File

@ -235,7 +235,7 @@ Search::init(StaState *sta)
arrival_iter_ = new BfsFwdIterator(BfsIndex::arrival, nullptr, sta);
required_iter_ = new BfsBkwdIterator(BfsIndex::required, search_adj_, sta);
tag_capacity_ = 128;
tag_set_ = new TagSet(tag_capacity_);
tag_set_ = new TagSet(tag_capacity_, TagHash(sta), TagEqual(sta));
clk_info_set_ = new ClkInfoSet(ClkInfoLess(sta));
tag_next_ = 0;
tags_ = new Tag*[tag_capacity_];
@ -543,8 +543,8 @@ Search::deleteFilteredArrivals()
}
filtered_arrivals_->clear();
deleteFilterTagGroups();
deleteFilterClkInfos();
deleteFilterTags();
deleteFilterClkInfos();
}
deleteFilter();
}
@ -590,7 +590,7 @@ Search::deleteFilterClkInfos()
{
for (auto itr = clk_info_set_->cbegin(); itr != clk_info_set_->cend(); ) {
ClkInfo *clk_info = *itr;
if (clk_info->refsFilter(this)) {
if (clk_info->crprPathRefsFilter()) {
itr = clk_info_set_->erase(itr);
delete clk_info;
}
@ -614,8 +614,7 @@ Search::findFilteredArrivals(bool thru_latches)
if (thru_latches)
enqueuePendingLatchOutputs();
debugPrint(debug_, "search", 1, "find arrivals pass %d", pass);
int arrival_count = arrival_iter_->visitParallel(max_level,
arrival_visitor_);
int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_);
deleteTagsPrev();
debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count);
}
@ -2727,7 +2726,7 @@ Search::mutateTag(Tag *from_tag,
TagGroup *
Search::findTagGroup(TagGroupBldr *tag_bldr)
{
TagGroup probe(tag_bldr);
TagGroup probe(tag_bldr, this);
LockGuard lock(tag_group_lock_);
TagGroup *tag_group = tag_group_set_->findKey(&probe);
if (tag_group == nullptr) {

View File

@ -262,26 +262,32 @@ Tag::findHash()
for (ExceptionState *state : *states_)
hashIncr(hash_, state->hash());
}
hashIncr(hash_, clk_info_->hash());
match_hash_ = hash_;
// Finish hash_.
hashIncr(hash_, clk_info_->hash());
if (input_delay_)
hashIncr(hash_, input_delay_->index());
// Finish match_hash_.
const ClockEdge *clk_edge = clk_info_->clkEdge();
if (clk_edge)
hashIncr(match_hash_, clk_edge->index());
hashIncr(match_hash_, clk_info_->isGenClkSrcPath());
}
size_t
Tag::hash(bool match_crpr_clk_pin,
const StaState *sta) const
{
if (match_crpr_clk_pin)
return hashSum(hash_, clk_info_->crprClkVertexId(sta));
else
return hash_;
}
size_t
Tag::matchHash(bool match_crpr_clk_pin,
const StaState *sta) const
{
if (match_crpr_clk_pin)
// match_hash_ with crpr clk pin thrown in.
return hashSum(match_hash_, clk_info_->crprClkVertexId(sta));
else
return match_hash_;
@ -311,7 +317,7 @@ tagCmp(const Tag *tag1,
ClkInfo *clk_info1 = tag1->clkInfo();
ClkInfo *clk_info2 = tag2->clkInfo();
int clk_cmp = clkInfoCmp(clk_info1, clk_info2, sta);
int clk_cmp = ClkInfo::cmp(clk_info1, clk_info2, sta);
if (clk_cmp != 0)
return clk_cmp;
@ -357,12 +363,13 @@ tagCmp(const Tag *tag1,
bool
tagEqual(const Tag *tag1,
const Tag *tag2)
const Tag *tag2,
const StaState *sta)
{
return tag1 == tag2
|| (tag1->rfIndex() == tag2->rfIndex()
&& tag1->pathAPIndex() == tag2->pathAPIndex()
&& tag1->clkInfo() == tag2->clkInfo()
&& ClkInfo::equal(tag1->clkInfo(), tag2->clkInfo(), sta)
&& tag1->isClock() == tag2->isClock()
&& tag1->inputDelay() == tag2->inputDelay()
&& tag1->isSegmentStart() == tag2->isSegmentStart()
@ -653,17 +660,28 @@ tagStateEqualCrpr(const Tag *tag1,
////////////////////////////////////////////////////////////////
TagHash::TagHash(const StaState *sta) :
sta_(sta)
{
}
size_t
TagHash::operator()(const Tag *tag) const
{
return tag->hash();
bool crpr_on = sta_->crprActive();
return tag->matchHash(crpr_on, sta_);
}
TagEqual::TagEqual(const StaState *sta) :
sta_(sta)
{
}
bool
TagEqual::operator()(const Tag *tag1,
const Tag *tag2) const
{
return tagEqual(tag1, tag2);
return tagEqual(tag1, tag2, sta_);
}
TagMatchHash::TagMatchHash(bool match_crpr_clk_pin,

View File

@ -85,7 +85,8 @@ public:
bool isLoop() const { return is_loop_; }
bool isFilter() const { return is_filter_; }
bool isSegmentStart() const { return is_segment_start_; }
size_t hash() const { return hash_; }
size_t hash(bool match_crpr_clk_pin,
const StaState *sta) const;
size_t matchHash(bool match_crpr_clk_pin,
const StaState *sta) const;
@ -130,19 +131,28 @@ public:
class TagHash
{
public:
TagHash(const StaState *sta);
size_t operator()(const Tag *tag) const;
private:
const StaState *sta_;
};
class TagEqual
{
public:
TagEqual(const StaState *sta);
bool operator()(const Tag *tag1,
const Tag *tag2) const;
private:
const StaState *sta_;
};
bool
tagEqual(const Tag *tag1,
const Tag *tag2);
const Tag *tag2,
const StaState *sta);
int
tagCmp(const Tag *tag1,
const Tag *tag2,

View File

@ -41,9 +41,10 @@ TagGroup::TagGroup(TagGroupIndex index,
bool has_clk_tag,
bool has_genclk_src_tag,
bool has_filter_tag,
bool has_loop_tag) :
bool has_loop_tag,
const StaState *sta) :
path_index_map_(path_index_map),
hash_(pathIndexMapHash(path_index_map)),
hash_(hash(path_index_map, sta)),
ref_count_(0),
index_(index),
has_clk_tag_(has_clk_tag),
@ -54,9 +55,10 @@ TagGroup::TagGroup(TagGroupIndex index,
{
}
TagGroup::TagGroup(TagGroupBldr *tag_bldr) :
TagGroup::TagGroup(TagGroupBldr *tag_bldr,
const StaState *sta) :
path_index_map_(&tag_bldr->pathIndexMap()),
hash_(pathIndexMapHash(path_index_map_)),
hash_(hash(path_index_map_, sta)),
ref_count_(0),
own_path_map_(false)
{
@ -81,11 +83,13 @@ TagGroup::decrRefCount()
}
size_t
TagGroup::pathIndexMapHash(PathIndexMap *path_index_map)
TagGroup::hash(PathIndexMap *path_index_map,
const StaState *sta)
{
bool crpr_on = sta->crprActive();
size_t hash = 0;
for (auto const [tag, path_index] : *path_index_map)
hash += tag->hash();
hash += tag->hash(crpr_on, sta);
return hash;
}
@ -268,7 +272,7 @@ TagGroupBldr::insertPath(Tag *tag,
if (tag->isGenClkSrcPath())
has_genclk_src_tag_ = true;
if (tag->isFilter()
|| tag->clkInfo()->refsFilter(sta_))
|| tag->clkInfo()->crprPathRefsFilter())
has_filter_tag_ = true;
if (tag->isLoop())
has_loop_tag_ = true;
@ -289,7 +293,7 @@ TagGroupBldr::makeTagGroup(TagGroupIndex index,
{
return new TagGroup(index, makePathIndexMap(sta),
has_clk_tag_, has_genclk_src_tag_, has_filter_tag_,
has_loop_tag_);
has_loop_tag_, sta);
}

View File

@ -47,9 +47,11 @@ public:
bool has_clk_tag,
bool has_genclk_src_tag,
bool has_filter_tag,
bool has_loop_tag);
bool has_loop_tag,
const StaState *sta);
// For Search::findTagGroup to probe.
TagGroup(TagGroupBldr *tag_bldr);
TagGroup(TagGroupBldr *tag_bldr,
const StaState *sta);
~TagGroup();
TagGroupIndex index() const { return index_; }
size_t hash() const { return hash_; }
@ -72,7 +74,8 @@ public:
int refCount() const { return ref_count_; }
protected:
static size_t pathIndexMapHash(PathIndexMap *path_index_map);
static size_t hash(PathIndexMap *path_index_map,
const StaState *sta);
// tag -> path index
PathIndexMap *path_index_map_;