Compare commits

...

15 Commits

Author SHA1 Message Date
Ethan Mahintorabi 8d18d9c4f9
Merge 545566cb0c into 2debe54ede 2025-09-23 14:02:31 -04:00
Matt Liberty 2debe54ede Merge remote-tracking branch 'parallax/master' 2025-09-23 18:01:05 +00:00
James Cherry f18df8a1a2 Edge::arcDelayAnnotateBit resolves issue #299
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-18 15:48:37 -07:00
James Cherry 892a9a4a3d vcd min time resolves #165
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-18 08:47:43 -07:00
James Cherry c020334e07 power propagate activies across test_cell resolves #295
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-17 15:59:00 -07:00
Mike Inouye cf060169aa
Add PropertyRegistry for Clock. (#298)
* Add PropertyRegistry for Clock.

Signed-off-by: Mike Inouye <mikeinouye@google.com>

* Remove extra blank line.

---------

Signed-off-by: Mike Inouye <mikeinouye@google.com>
2025-09-17 14:19:22 -07:00
James Cherry 8e50916693 deleteFilterTags
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-17 09:10:14 -07:00
James Cherry 17cf87b4c6 Tag::clkInfo const
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-16 15:30:16 -07:00
James Cherry 8580cfd813 pathIndexMapEqual
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-16 15:16:05 -07:00
James Cherry a296abc15c Tag use static cmp functions
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-16 14:49:01 -07:00
James Cherry 7c6a473bbc cleanup
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-16 14:25:24 -07:00
James Cherry 7a41a7f839 ClkInfo::hash resolves #287
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-16 14:17:30 -07:00
James Cherry 84989688b7 ClkInfo, Tag cmp
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-16 13:53:16 -07:00
James Cherry 9f9ad0b4ab clkInfoCmp, tagCmp
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-14 11:43:59 -07:00
James Cherry ab39366f7b tagStateCmp use +exceptionStateLess
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-09-12 09:10:03 -07:00
34 changed files with 537 additions and 458 deletions

View File

@ -1322,7 +1322,7 @@ Edge::arcDelayAnnotated(const TimingArc *arc,
{
size_t index = arc->index() * ap_count + ap_index;
if (arc_delay_annotated_is_bits_)
return arc_delay_annotated_.bits_ & (1 << index);
return arc_delay_annotated_.bits_ & arcDelayAnnotateBit(index);
else
return (*arc_delay_annotated_.seq_)[index];
}
@ -1334,7 +1334,7 @@ Edge::setArcDelayAnnotated(const TimingArc *arc,
bool annotated)
{
size_t index = arc->index() * ap_count + ap_index;
if (index > sizeof(intptr_t) * 8
if (index > sizeof(uintptr_t) * 8
&& arc_delay_annotated_is_bits_) {
arc_delay_annotated_is_bits_ = false;
size_t bit_count = ap_count * RiseFall::index_count * 2;
@ -1342,9 +1342,9 @@ Edge::setArcDelayAnnotated(const TimingArc *arc,
}
if (arc_delay_annotated_is_bits_) {
if (annotated)
arc_delay_annotated_.bits_ |= (1 << index);
arc_delay_annotated_.bits_ |= arcDelayAnnotateBit(index);
else
arc_delay_annotated_.bits_ &= ~(1 << index);
arc_delay_annotated_.bits_ &= ~arcDelayAnnotateBit(index);
}
else
(*arc_delay_annotated_.seq_)[index] = annotated;
@ -1368,6 +1368,12 @@ Edge::setDelayAnnotationIsIncremental(bool is_incr)
delay_annotation_is_incremental_ = is_incr;
}
uintptr_t
Edge::arcDelayAnnotateBit(size_t index)
{
return static_cast<uintptr_t>(1) << index;
}
const TimingRole *
Edge::role() const
{

View File

@ -667,6 +667,10 @@ private:
int index_;
};
bool
exceptionStateLess(const ExceptionState *state1,
const ExceptionState *state2);
// Exception thrown by check.
class EmptyExpceptionPt : public Exception
{

View File

@ -421,6 +421,7 @@ protected:
DcalcAPIndex ap_index,
DcalcAPIndex ap_count,
bool annotated);
static uintptr_t arcDelayAnnotateBit(size_t index);
TimingArcSet *arc_set_;
VertexId from_;

View File

@ -149,8 +149,8 @@ public:
exists_[mm_index] = false;
}
static bool equal(MinMaxValues *values1,
MinMaxValues *values2)
static bool equal(const MinMaxValues *values1,
const MinMaxValues *values2)
{
return ((!values1->exists_[MinMax::minIndex()]
&& !values2->exists_[MinMax::minIndex()])
@ -166,6 +166,32 @@ public:
== values2->values_[MinMax::maxIndex()]));
}
static int cmp(const MinMaxValues *values1,
const MinMaxValues *values2)
{
if (!values1->exists_[MinMax::minIndex()]
&& values2->exists_[MinMax::minIndex()])
return -1;
if (values1->exists_[MinMax::minIndex()]
&& !values2->exists_[MinMax::minIndex()])
return 1;
if (!values1->exists_[MinMax::maxIndex()]
&& values2->exists_[MinMax::maxIndex()])
return -1;
if (values1->exists_[MinMax::maxIndex()]
&& !values2->exists_[MinMax::maxIndex()])
return 1;
if (values1->values_[MinMax::minIndex()] < values2->values_[MinMax::minIndex()])
return -1;
if (values1->values_[MinMax::minIndex()] > values2->values_[MinMax::minIndex()])
return 1;
if (values1->values_[MinMax::maxIndex()] < values2->values_[MinMax::maxIndex()])
return -1;
if (values1->values_[MinMax::maxIndex()] > values2->values_[MinMax::maxIndex()])
return 1;
return 0;
}
private:
TYPE values_[MinMax::index_count];
bool exists_[MinMax::index_count];

View File

@ -41,7 +41,7 @@ class Path
{
public:
Path();
Path(Path *path);
Path(const Path *path);
Path(Vertex *vertex,
Tag *tag,
const StaState *sta);
@ -89,7 +89,7 @@ public:
TagIndex tagIndex(const StaState *sta) const;
void setTag(Tag *tag);
size_t pathIndex(const StaState *sta) const;
ClkInfo *clkInfo(const StaState *sta) const;
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;

View File

@ -94,10 +94,10 @@ public:
const std::string property);
// Define handler for external property.
// proerties->defineProperty("foo",
// [] (const Instance *, Sta *) -> PropertyValue {
// return PropertyValue("bar");
// });
// properties->defineProperty("foo",
// [] (const Instance *, Sta *) -> PropertyValue {
// return PropertyValue("bar");
// });
void defineProperty(std::string &property,
PropertyRegistry<const Library *>::PropertyHandler handler);
void defineProperty(std::string &property,
@ -116,6 +116,8 @@ public:
PropertyRegistry<const Pin *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const Net *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const Clock *>::PropertyHandler handler);
protected:
PropertyValue portSlew(const Port *port,
@ -159,6 +161,7 @@ protected:
PropertyRegistry<const Instance*> registry_instance_;
PropertyRegistry<const Pin*> registry_pin_;
PropertyRegistry<const Net*> registry_net_;
PropertyRegistry<const Clock*> registry_clock_;
Sta *sta_;
};

View File

@ -64,7 +64,7 @@ class CheckCrpr;
class Genclks;
class Corner;
typedef Set<ClkInfo*, ClkInfoLess> ClkInfoSet;
typedef Set<const ClkInfo*, ClkInfoLess> ClkInfoSet;
typedef UnorderedSet<Tag*, TagHash, TagEqual> TagSet;
typedef UnorderedSet<TagGroup*, TagGroupHash, TagGroupEqual> TagGroupSet;
typedef Map<Vertex*, Slack> VertexSlackMap;
@ -158,7 +158,7 @@ public:
// Clock arrival respecting ideal clock insertion delay and latency.
Arrival clkPathArrival(const Path *clk_path) const;
Arrival clkPathArrival(const Path *clk_path,
ClkInfo *clk_info,
const ClkInfo *clk_info,
const ClockEdge *clk_edge,
const MinMax *min_max,
const PathAnalysisPt *path_ap) const;
@ -244,7 +244,7 @@ public:
const RiseFall *from_rf,
const Clock *clk,
const RiseFall *clk_rf,
ClkInfo *clk_info,
const ClkInfo *clk_info,
const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max,
@ -263,20 +263,20 @@ public:
bool arc_delay_min_max_eq,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
ClkInfo *thruClkInfo(Path *from_path,
Vertex *from_vertex,
ClkInfo *from_clk_info,
bool from_is_clk,
Edge *edge,
Vertex *to_vertex,
const Pin *to_pin,
bool to_is_clk,
bool arc_delay_min_max_eq,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
Path *from_path,
const PathAnalysisPt *path_ap);
const ClkInfo *thruClkInfo(Path *from_path,
Vertex *from_vertex,
const ClkInfo *from_clk_info,
bool from_is_clk,
Edge *edge,
Vertex *to_vertex,
const Pin *to_pin,
bool to_is_clk,
bool arc_delay_min_max_eq,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
const ClkInfo *clkInfoWithCrprClkPath(const ClkInfo *from_clk_info,
Path *from_path,
const PathAnalysisPt *path_ap);
void seedClkArrivals(const Pin *pin,
Vertex *vertex,
TagGroupBldr *tag_bldr);
@ -323,7 +323,7 @@ public:
Tag *findTag(const RiseFall *rf,
const PathAnalysisPt *path_ap,
ClkInfo *tag_clk,
const ClkInfo *tag_clk,
bool is_clk,
InputDelay *input_delay,
bool is_segment_start,
@ -331,22 +331,22 @@ public:
bool own_states);
void reportTags() const;
void reportClkInfos() const;
virtual ClkInfo *findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
const Pin *gen_clk_src,
bool gen_clk_src_path,
const RiseFall *pulse_clk_sense,
Arrival insertion,
float latency,
ClockUncertainties *uncertainties,
const PathAnalysisPt *path_ap,
Path *crpr_clk_path);
ClkInfo *findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
Arrival insertion,
const PathAnalysisPt *path_ap);
const ClkInfo *findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
const Pin *gen_clk_src,
bool gen_clk_src_path,
const RiseFall *pulse_clk_sense,
Arrival insertion,
float latency,
ClockUncertainties *uncertainties,
const PathAnalysisPt *path_ap,
Path *crpr_clk_path);
const ClkInfo *findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
Arrival insertion,
const PathAnalysisPt *path_ap);
// Timing derated arc delay for a path analysis point.
ArcDelay deratedDelay(const Vertex *from_vertex,
const TimingArc *arc,
@ -515,13 +515,13 @@ protected:
const Pin *from_pin,
const RiseFall *from_rf,
bool from_is_clk,
ClkInfo *from_clk_info,
const ClkInfo *from_clk_info,
const Pin *to_pin,
const RiseFall *to_rf,
bool to_is_clk,
bool to_is_reg_clk,
bool to_is_segment_start,
ClkInfo *to_clk_info,
const ClkInfo *to_clk_info,
InputDelay *to_input_delay,
const MinMax *min_max,
const PathAnalysisPt *path_ap);

View File

@ -490,6 +490,9 @@ PropActivityVisitor::visit(Vertex *vertex)
}
if (network_->isDriver(pin)) {
LibertyPort *port = network_->libertyPort(pin);
LibertyCell *test_cell = port->libertyCell()->testCell();
if (test_cell)
port = test_cell->findLibertyPort(port->name());
if (port) {
FuncExpr *func = port->function();
if (func) {
@ -519,23 +522,28 @@ PropActivityVisitor::visit(Vertex *vertex)
}
if (changed) {
LibertyCell *cell = network_->libertyCell(inst);
if (network_->isLoad(pin) && cell) {
if (cell->hasSequentials()) {
debugPrint(debug_, "power_activity", 3, "pending seq %s",
network_->pathName(inst));
visited_regs_.insert(inst);
}
// Gated clock cells latch the enable so there is no EN->GCLK timing arc.
if (cell->isClockGate()) {
const Pin *enable, *clk, *gclk;
power_->clockGatePins(inst, enable, clk, gclk);
if (gclk) {
Vertex *gclk_vertex = graph_->pinDrvrVertex(gclk);
bfs_->enqueue(gclk_vertex);
}
if (cell) {
LibertyCell *test_cell = cell->libertyCell()->testCell();
if (network_->isLoad(pin)) {
if (cell->hasSequentials()
|| (test_cell
&& test_cell->hasSequentials())) {
debugPrint(debug_, "power_activity", 3, "pending seq %s",
network_->pathName(inst));
visited_regs_.insert(inst);
}
// Gated clock cells latch the enable so there is no EN->GCLK timing arc.
if (cell->isClockGate()) {
const Pin *enable, *clk, *gclk;
power_->clockGatePins(inst, enable, clk, gclk);
if (gclk) {
Vertex *gclk_vertex = graph_->pinDrvrVertex(gclk);
bfs_->enqueue(gclk_vertex);
}
}
}
bfs_->enqueueAdjacentVertices(vertex);
}
bfs_->enqueueAdjacentVertices(vertex);
}
}
@ -725,12 +733,9 @@ Power::ensureActivities()
int pass = 1;
while (!regs.empty() && pass < max_activity_passes_) {
visitor.init();
InstanceSet::Iterator reg_iter(regs);
while (reg_iter.hasNext()) {
const Instance *reg = reg_iter.next();
for (const Instance *reg : regs)
// Propagate activiities across register D->Q.
seedRegOutputActivities(reg, bfs);
}
// Propagate register output activities through
// combinational logic.
bfs.visit(levelize_->maxLevel(), &visitor);
@ -771,7 +776,11 @@ Power::seedRegOutputActivities(const Instance *inst,
BfsFwdIterator &bfs)
{
LibertyCell *cell = network_->libertyCell(inst);
for (Sequential *seq : cell->sequentials()) {
LibertyCell *test_cell = cell->testCell();
const SequentialSeq &seqs = test_cell
? test_cell->sequentials()
: cell->sequentials();
for (Sequential *seq : seqs) {
seedRegOutputActivities(inst, seq, seq->output(), false);
seedRegOutputActivities(inst, seq, seq->outputInv(), true);
// Enqueue register output pins with functions that reference
@ -780,6 +789,8 @@ Power::seedRegOutputActivities(const Instance *inst,
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
LibertyPort *port = network_->libertyPort(pin);
if (test_cell)
port = test_cell->findLibertyPort(port->name());
if (port) {
FuncExpr *func = port->function();
Vertex *vertex = graph_->pinDrvrVertex(pin);

View File

@ -52,8 +52,8 @@ VcdParse::read(const char *filename,
Stats stats(debug_, report_);
filename_ = filename;
reader_ = reader;
file_line_ = 1;
stmt_line_ = 1;
file_line_ = 0;
stmt_line_ = 0;
std::string token = getToken();
while (!token.empty()) {
if (token == "$date")
@ -205,11 +205,19 @@ void
VcdParse::parseVarValues()
{
string token = getToken();
bool first_time = true;
while (!token.empty()) {
char char0 = toupper(token[0]);
if (char0 == '#' && token.size() > 1) {
prev_time_ = time_;
time_ = stoll(token.substr(1));
VcdTime time = stoll(token.substr(1));
if (first_time) {
prev_time_ = time;
first_time = false;
reader_->setTimeMin(time);
}
else
prev_time_ = time_;
time_ = time;
if (time_ > prev_time_)
reader_->varMinDeltaTime(time_ - prev_time_);
}
@ -286,20 +294,18 @@ VcdParse::getToken()
{
string token;
int ch = gzgetc(stream_);
if (ch == '\n')
file_line_++;
// skip whitespace
while (ch != EOF && isspace(ch)) {
ch = gzgetc(stream_);
if (ch == '\n')
file_line_++;
ch = gzgetc(stream_);
}
while (ch != EOF && !isspace(ch)) {
token.push_back(ch);
ch = gzgetc(stream_);
if (ch == '\n')
file_line_++;
}
if (ch == '\n')
file_line_++;
if (ch == EOF)
return "";
else

View File

@ -104,7 +104,8 @@ public:
virtual void setTimeUnit(const std::string &time_unit,
double time_unit_scale,
double time_scale) = 0;
virtual void setTimeMax(VcdTime time_max) = 0;
virtual void setTimeMin(VcdTime time) = 0;
virtual void setTimeMax(VcdTime time) = 0;
virtual void varMinDeltaTime(VcdTime min_delta_time) = 0;
virtual bool varIdValid(const std::string &id) = 0;
virtual void makeVar(const VcdScope &scope,

View File

@ -127,6 +127,7 @@ public:
Report *report,
Debug *debug);
VcdTime timeMax() const { return time_max_; }
VcdTime timeMin() const { return time_min_; }
const VcdIdCountsMap &countMap() const { return vcd_count_map_; }
double timeScale() const { return time_scale_; }
@ -137,7 +138,8 @@ public:
void setTimeUnit(const string &time_unit,
double time_unit_scale,
double time_scale) override;
void setTimeMax(VcdTime time_max) override;
void setTimeMin(VcdTime time) override;
void setTimeMax(VcdTime time) override;
void varMinDeltaTime(VcdTime) override {}
bool varIdValid(const string &id) override;
void makeVar(const VcdScope &scope,
@ -164,6 +166,7 @@ private:
Debug *debug_;
double time_scale_;
VcdTime time_min_;
VcdTime time_max_;
VcdIdCountsMap vcd_count_map_;
};
@ -177,7 +180,8 @@ VcdCountReader::VcdCountReader(const char *scope,
report_(report),
debug_(debug),
time_scale_(1.0),
time_max_(0.0)
time_min_(0),
time_max_(0)
{
}
@ -190,9 +194,15 @@ VcdCountReader::setTimeUnit(const string &,
}
void
VcdCountReader::setTimeMax(VcdTime time_max)
VcdCountReader::setTimeMin(VcdTime time)
{
time_max_ = time_max;
time_min_ = time;
}
void
VcdCountReader::setTimeMax(VcdTime time)
{
time_max_ = time;
}
bool
@ -400,14 +410,16 @@ ReadVcdActivities::readActivities()
void
ReadVcdActivities::setActivities()
{
VcdTime time_min = vcd_reader_.timeMin();
VcdTime time_max = vcd_reader_.timeMax();
VcdTime time_delta = time_max - time_min;
double time_scale = vcd_reader_.timeScale();
for (auto& [id, vcd_counts] : vcd_reader_.countMap()) {
for (const VcdCount &vcd_count : vcd_counts) {
double transition_count = vcd_count.transitionCount();
VcdTime high_time = vcd_count.highTime(time_max);
float duty = static_cast<double>(high_time) / time_max;
float density = transition_count / (time_max * time_scale);
float duty = static_cast<double>(high_time) / time_delta;
float density = transition_count / (time_delta * time_scale);
if (debug_->check("read_vcd_activities", 1)) {
for (const Pin *pin : vcd_count.pins()) {
debugPrint(debug_, "read_vcd_activities", 1,
@ -433,8 +445,9 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin,
double transition_count)
{
VcdTime time_max = vcd_reader_.timeMax();
VcdTime time_min = vcd_reader_.timeMin();
double time_scale = vcd_reader_.timeScale();
double sim_period = time_max * time_scale / (transition_count / 2.0);
double sim_period = (time_max - time_min) * time_scale / (transition_count / 2.0);
ClockSet *clks = sdc_->findLeafPinClocks(pin);
if (clks) {
for (Clock *clk : *clks) {
@ -449,4 +462,4 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin,
}
}
}
} // namespace

View File

@ -2280,17 +2280,23 @@ ExceptionState::hash() const
}
bool
ExceptionStateLess::operator()(const ExceptionState *state1,
const ExceptionState *state2) const
exceptionStateLess(const ExceptionState *state1,
const ExceptionState *state2)
{
const ExceptionPath *except1 = state1->exception();
const ExceptionPath *except2 = state2->exception();
return except1->id() < except2->id()
//return except1 < except2
return except1->id() < except2->id()
|| (except1 == except2
&& state1->index() < state2->index());
}
bool
ExceptionStateLess::operator()(const ExceptionState *state1,
const ExceptionState *state2) const
{
return exceptionStateLess(state1, state2);
}
////////////////////////////////////////////////////////////////
ExceptionPathLess::ExceptionPathLess(const Network *network) :

View File

@ -322,17 +322,17 @@ MinPulseWidthCheck::closePath(const StaState *sta) const
const RiseFall *open_rf = open_path_->transition(sta);
const RiseFall *close_rf = open_rf->opposite();
Tag *open_tag = open_path_->tag(sta);
ClkInfo *open_clk_info = open_tag->clkInfo();
ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(),
open_clk_info->clkSrc(),
open_clk_info->isPropagated(),
open_clk_info->genClkSrc(),
open_clk_info->isGenClkSrcPath(),
open_clk_info->pulseClkSense(),
delay_zero, 0.0, nullptr,
open_clk_info->pathAPIndex(),
open_clk_info->crprClkPath(sta),
sta);
const ClkInfo *open_clk_info = open_tag->clkInfo();
const ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(),
open_clk_info->clkSrc(),
open_clk_info->isPropagated(),
open_clk_info->genClkSrc(),
open_clk_info->isGenClkSrcPath(),
open_clk_info->pulseClkSense(),
delay_zero, 0.0, nullptr,
open_clk_info->pathAPIndex(),
open_clk_info->crprClkPath(sta),
sta);
Tag close_tag(0,
close_rf->index(),
close_ap->index(),
@ -350,7 +350,7 @@ MinPulseWidthCheck::closePath(const StaState *sta) const
close_ap, sta);
while (close_iter.hasNext()) {
Path *close_path = close_iter.next();
if (tagMatchNoPathAp(close_path->tag(sta), &close_tag)) {
if (Tag::matchNoPathAp(close_path->tag(sta), &close_tag)) {
debugPrint(sta->debug(), "mpw", 3, " match %s",
close_path->tag(sta)->to_string(sta).c_str());
return close_path;
@ -394,7 +394,7 @@ const ClockEdge *
MinPulseWidthCheck::closeClkEdge(const StaState *sta) const
{
Tag *open_tag = open_path_->tag(sta);
ClkInfo *open_clk_info = open_tag->clkInfo();
const ClkInfo *open_clk_info = open_tag->clkInfo();
return open_clk_info->clkEdge()->opposite();
}

View File

@ -24,6 +24,9 @@
#include "ClkInfo.hh"
#include <functional>
#include "Units.hh"
#include "Network.hh"
#include "Graph.hh"
#include "Sdc.hh"
@ -44,7 +47,7 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
float latency,
ClockUncertainties *uncertainties,
PathAPIndex path_ap_index,
Path *crpr_clk_path,
const Path *crpr_clk_path,
const StaState *sta) :
clk_edge_(clk_edge),
clk_src_(clk_src),
@ -55,6 +58,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,19 +82,26 @@ 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));
}
std::hash<float> hash_float;
if (uncertainties_) {
float uncertainty;
bool exists;
uncertainties_->value(MinMax::min(), uncertainty, exists);
if (exists)
hashIncr(hash_, uncertainty * 1E+12F);
hashIncr(hash_, hash_float(uncertainty));
uncertainties_->value(MinMax::max(), uncertainty, exists);
if (exists)
hashIncr(hash_, uncertainty * 1E+12F);
hashIncr(hash_, hash_float(uncertainty));
}
hashIncr(hash_, latency_ * 1E+12F);
hashIncr(hash_, delayAsFloat(insertion_) * 1E+12F);
hashIncr(hash_, hash_float(latency_));
hashIncr(hash_, hash_float(delayAsFloat(insertion_)));
hashIncr(hash_, is_propagated_);
hashIncr(hash_, is_gen_clk_src_path_);
hashIncr(hash_, is_pulse_clk_);
@ -101,19 +112,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 +130,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 +164,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 +216,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,36 +235,15 @@ 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();
ClockUncertainties *uncertainties2 = clk_info2->uncertainties();
return clk_info1->clkEdge() == clk_info2->clkEdge()
&& clk_info1->pathAPIndex() == clk_info2->pathAPIndex()
&& clk_info1->clkSrc() == clk_info2->clkSrc()
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
&& (!crpr_on
|| Path::equal(clk_info1->crprClkPath(sta),
clk_info2->crprClkPath(sta),
sta))
&& ((uncertainties1 == nullptr
&& uncertainties2 == nullptr)
|| (uncertainties1 && uncertainties2
&& MinMaxValues<float>::equal(uncertainties1,
uncertainties2)))
&& clk_info1->insertion() == clk_info2->insertion()
&& clk_info1->latency() == clk_info2->latency()
&& clk_info1->isPropagated() == clk_info2->isPropagated()
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
&& clk_info1->isPulseClk() == clk_info2->isPulseClk()
&& clk_info1->pulseClkSenseTrIndex() == clk_info2->pulseClkSenseTrIndex();
return ClkInfo::cmp(clk_info1, clk_info2, sta) == 0;
}
////////////////////////////////////////////////////////////////
@ -247,13 +257,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();
@ -271,24 +281,29 @@ clkInfoCmp(const ClkInfo *clk_info1,
if (path_ap_index1 > path_ap_index2)
return 1;
const Network *network = sta->network();
const Pin *clk_src1 = clk_info1->clkSrc();
const Pin *clk_src2 = clk_info2->clkSrc();
if (clk_src1 < clk_src2)
int clk_src_id1 = clk_src1 ? network->id(clk_src1) : -1;
int clk_src_id2 = clk_src2 ? network->id(clk_src2) : -1;
if (clk_src_id1 < clk_src_id2)
return -1;
if (clk_src1 > clk_src2)
if (clk_src_id1 > clk_src_id2)
return 1;
const Pin *gen_clk_src1 = clk_info1->genClkSrc();
const Pin *gen_clk_src2 = clk_info2->genClkSrc();
if (gen_clk_src1 < gen_clk_src2)
int gen_clk_src_id1 = gen_clk_src1 ? network->id(gen_clk_src1) : -1;
int gen_clk_src_id2 = gen_clk_src2 ? network->id(gen_clk_src2) : -1;
if (gen_clk_src_id1 < gen_clk_src_id2)
return -1;
if (gen_clk_src1 > gen_clk_src2)
if (gen_clk_src_id1 > gen_clk_src_id2)
return 1;
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;
@ -296,11 +311,15 @@ clkInfoCmp(const ClkInfo *clk_info1,
const ClockUncertainties *uncertainties1 = clk_info1->uncertainties();
const ClockUncertainties *uncertainties2 = clk_info2->uncertainties();
if (uncertainties1 < uncertainties2)
if (uncertainties1 == nullptr && uncertainties2)
return -1;
if (uncertainties1 > uncertainties2)
if (uncertainties1 && uncertainties2 == nullptr)
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))
@ -336,8 +355,8 @@ clkInfoCmp(const ClkInfo *clk_info1,
if (is_pulse_clk1 && !is_pulse_clk2)
return 1;
int pulse_clk_sense_index1 = clk_info1->pulseClkSenseTrIndex();
int pulse_clk_sense_index2 = clk_info2->pulseClkSenseTrIndex();
int pulse_clk_sense_index1 = clk_info1->pulseClkSenseRfIndex();
int pulse_clk_sense_index2 = clk_info2->pulseClkSenseRfIndex();
if (pulse_clk_sense_index1 < pulse_clk_sense_index2)
return -1;
if (pulse_clk_sense_index1 > pulse_clk_sense_index2)

View File

@ -46,7 +46,7 @@ public:
float latency,
ClockUncertainties *uncertainties,
PathAPIndex path_ap_index,
Path *crpr_clk_path,
const Path *crpr_clk_path,
const StaState *sta);
~ClkInfo();
std::string to_string(const StaState *sta) const;
@ -57,7 +57,7 @@ public:
const Pin *genClkSrc() const { return gen_clk_src_; }
bool isPulseClk() const { return is_pulse_clk_; }
const RiseFall *pulseClkSense() const;
int pulseClkSenseTrIndex() const { return pulse_clk_sense_; }
int pulseClkSenseRfIndex() const { return pulse_clk_sense_; }
float latency() const { return latency_; }
Arrival &insertion() { return insertion_; }
const Arrival &insertion() const { return insertion_; }
@ -69,11 +69,18 @@ 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_; }
const Path *crprClkPathRaw() const;
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);
@ -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

@ -293,7 +293,7 @@ ClkDelays::insertionDelay(Path *clk_path,
const ClockEdge *clk_edge = clk_path->clkEdge(sta);
const Clock *clk = clk_edge->clock();
const RiseFall *clk_rf = clk_edge->transition();
ClkInfo *clk_info = clk_path->clkInfo(sta);
const ClkInfo *clk_info = clk_path->clkInfo(sta);
const Pin *src_pin = clk_info->clkSrc();
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(sta);
const MinMax *min_max = clk_path->minMax(sta);

View File

@ -56,7 +56,7 @@ CheckCrpr::CheckCrpr(StaState *sta) :
// Find the maximum possible crpr (clock min/max delta delay) for a
// path from it's ClkInfo.
Arrival
CheckCrpr::maxCrpr(ClkInfo *clk_info)
CheckCrpr::maxCrpr(const ClkInfo *clk_info)
{
const Path *crpr_clk_path = clk_info->crprClkPath(this);
if (crpr_clk_path) {
@ -81,7 +81,7 @@ CheckCrpr::otherMinMaxArrival(const Path *path)
other_ap, this);
while (other_iter.hasNext()) {
Path *other = other_iter.next();
if (tagMatchCrpr(other->tag(this), tag))
if (Tag::matchCrpr(other->tag(this), tag))
return other->arrival();
}
// No corresponding path found.
@ -126,8 +126,8 @@ CheckCrpr::checkCrpr1(const Path *src_path,
crpr = 0.0;
crpr_pin = nullptr;
const Tag *src_tag = src_path->tag(this);
ClkInfo *src_clk_info = src_tag->clkInfo();
ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo();
const ClkInfo *src_clk_info = src_tag->clkInfo();
const ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo();
const Clock *src_clk = src_clk_info->clock();
const Clock *tgt_clk = tgt_clk_info->clock();
const Path *src_clk_path = nullptr;
@ -246,7 +246,7 @@ ConstPathSeq
CheckCrpr::genClkSrcPaths(const Path *path)
{
ConstPathSeq gclk_paths;
ClkInfo *clk_info = path->clkInfo(this);
const ClkInfo *clk_info = path->clkInfo(this);
const ClockEdge *clk_edge = clk_info->clkEdge();
const Pin *clk_src = clk_info->clkSrc();
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
@ -350,7 +350,7 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path,
{
crpr = 0.0;
crpr_pin = nullptr;
ClkInfo *src_clk_info = src_path->tag(this)->clkInfo();
const ClkInfo *src_clk_info = src_path->tag(this)->clkInfo();
const Clock *tgt_clk = tgt_clk_edge->clock();
const Clock *src_clk = src_path->clock(this);
if (src_clk && tgt_clk
@ -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

@ -39,7 +39,7 @@ public:
explicit CheckCrpr(StaState *sta);
// Find the maximum possible crpr (clock min/max delta delay) for path.
Arrival maxCrpr(ClkInfo *clk_info);
Arrival maxCrpr(const ClkInfo *clk_info);
// Timing check CRPR.
Crpr checkCrpr(const Path *src_clk_path,
const Path *tgt_clk_path);

View File

@ -711,12 +711,12 @@ Genclks::makeTag(const Clock *gclk,
state = state->nextState();
ExceptionStateSet *states = new ExceptionStateSet();
states->insert(state);
ClkInfo *clk_info = search_->findClkInfo(master_clk->edge(master_rf),
master_pin, true, nullptr, true,
nullptr, insert, 0.0, nullptr,
path_ap, nullptr);
return search_->findTag(master_rf, path_ap, clk_info, false, nullptr, false,
states, true);
const ClkInfo *clk_info = search_->findClkInfo(master_clk->edge(master_rf),
master_pin, true, nullptr, true,
nullptr, insert, 0.0, nullptr,
path_ap, nullptr);
return search_->findTag(master_rf, path_ap, clk_info, false,
nullptr, false, states, true);
}
class GenClkArrivalSearchPred : public EvalPred

View File

@ -331,7 +331,7 @@ Latches::latchOutArrival(const Path *data_path,
tgt_clk_path_ap, this);
while (enable_iter.hasNext()) {
Path *enable_path = enable_iter.next();
ClkInfo *en_clk_info = enable_path->clkInfo(this);
const ClkInfo *en_clk_info = enable_path->clkInfo(this);
const ClockEdge *en_clk_edge = en_clk_info->clkEdge();
if (enable_path->isClock(this)) {
ExceptionPath *excpt = exceptionTo(data_path, en_clk_edge);
@ -353,7 +353,7 @@ Latches::latchOutArrival(const Path *data_path,
// Tag switcheroo - data passing thru gets latch enable tag.
// States and path ap come from Q, everything else from enable.
Path *crpr_clk_path = crprActive() ? enable_path : nullptr;
ClkInfo *q_clk_info =
const ClkInfo *q_clk_info =
search_->findClkInfo(en_clk_edge,
en_clk_info->clkSrc(),
en_clk_info->isPropagated(),

View File

@ -49,7 +49,7 @@ Path::Path() :
{
}
Path::Path(Path *path) :
Path::Path(const Path *path) :
prev_path_(path ? path->prev_path_ : nullptr),
arrival_(path ? path->arrival_ : 0.0),
required_(path ? path->required_ : 0.0),
@ -279,7 +279,7 @@ Path::pathIndex(const StaState *sta) const
return this - paths;
}
ClkInfo *
const ClkInfo *
Path::clkInfo(const StaState *sta) const
{
return tag(sta)->clkInfo();
@ -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
@ -643,7 +642,7 @@ Path::cmpNoCrpr(const Path *path1,
VertexId vertex_id1 = path1->vertexId(sta);
VertexId vertex_id2 = path2->vertexId(sta);
if (vertex_id1 == vertex_id2)
return tagMatchCmp(path1->tag(sta), path2->tag(sta), false, sta);
return Tag::matchCmp(path1->tag(sta), path2->tag(sta), false, sta);
else if (vertex_id1 < vertex_id2)
return -1;
else

View File

@ -330,7 +330,7 @@ PathEnd::checkTgtClkDelay(const Path *tgt_clk_path,
const MinMax *min_max = tgt_clk_path->minMax(sta);
const EarlyLate *early_late = check_role->tgtClkEarlyLate();
const PathAnalysisPt *tgt_path_ap = tgt_clk_path->pathAnalysisPt(sta);
ClkInfo *clk_info = tgt_clk_path->clkInfo(sta);
const ClkInfo *clk_info = tgt_clk_path->clkInfo(sta);
const Pin *tgt_src_pin = clk_info->clkSrc();
const Clock *tgt_clk = tgt_clk_edge->clock();
const RiseFall *tgt_clk_rf = tgt_clk_edge->transition();
@ -560,14 +560,14 @@ PathEndClkConstrained::sourceClkOffset(const ClockEdge *src_clk_edge,
Arrival
PathEndClkConstrained::sourceClkLatency(const StaState *sta) const
{
ClkInfo *clk_info = path_->clkInfo(sta);
const ClkInfo *clk_info = path_->clkInfo(sta);
return clk_info->latency();
}
Arrival
PathEndClkConstrained::sourceClkInsertionDelay(const StaState *sta) const
{
ClkInfo *clk_info = path_->clkInfo(sta);
const ClkInfo *clk_info = path_->clkInfo(sta);
return clk_info->insertion();
}
@ -1033,7 +1033,7 @@ PathEndCheck::sourceClkDelay(const StaState *sta) const
PathExpanded expanded(path_, sta);
const Path *src_clk_path = expanded.clkPath();
if (src_clk_path) {
ClkInfo *src_clk_info = path_->tag(sta)->clkInfo();
const ClkInfo *src_clk_info = path_->tag(sta)->clkInfo();
if (src_clk_info->isPropagated()) {
// Propagated clock. Propagated arrival is seeded with insertion delay.
Arrival clk_arrival = src_clk_path->arrival();
@ -1280,7 +1280,7 @@ PathEndLatchCheck::targetClkWidth(const StaState *sta) const
const Search *search = sta->search();
Arrival disable_arrival = search->clkPathArrival(disable_path_);
Arrival enable_arrival = search->clkPathArrival(clk_path_);
ClkInfo *enable_clk_info = clk_path_->clkInfo(sta);
const ClkInfo *enable_clk_info = clk_path_->clkInfo(sta);
if (enable_clk_info->isPulseClk())
return disable_arrival - enable_arrival;
else {

View File

@ -393,7 +393,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
// These paths fanin to before_div_ so we know to_vertex matches.
if ((!unique_pins_ || from_vertex != prev_vertex_)
&& arc != prev_arc_
&& tagMatchNoCrpr(to_tag, before_div_tag_)) {
&& Tag::matchNoCrpr(to_tag, before_div_tag_)) {
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
from_path->to_string(this).c_str(),
to_vertex->to_string(this).c_str(),
@ -644,7 +644,7 @@ PathEnum::updatePathHeadDelays(PathSeq &paths,
Path *after_div)
{
Tag *prev_tag = after_div->tag(this);
ClkInfo *prev_clk_info = prev_tag->clkInfo();
const ClkInfo *prev_clk_info = prev_tag->clkInfo();
Arrival prev_arrival = search_->clkPathArrival(after_div);
int path_idx_max = paths.size() - 1;
// paths[0] is the path endpoint

View File

@ -149,7 +149,7 @@ PathGroup::enumMinSlackUnderMin(PathEnd *path_end)
other_ap, sta_);
while (other_iter.hasNext()) {
Path *other = other_iter.next();
if (tagMatchCrpr(other->tag(sta_), tag)) {
if (Tag::matchCrpr(other->tag(sta_), tag)) {
PathEnd *end_min = path_end->copy();
end_min->setPath(other);
float slack = delayAsFloat(end_min->slackNoCrpr(sta_));

View File

@ -1240,8 +1240,14 @@ Properties::getProperty(const Clock *clk,
return PropertyValue(clk->isVirtual());
else if (property == "is_propagated")
return PropertyValue(clk->isPropagated());
else
throw PropertyUnknown("clock", property);
else {
PropertyValue value = registry_clock_.getProperty(clk, property,
"clock", sta_);
if (value.type() != PropertyValue::Type::type_none)
return value;
else
throw PropertyUnknown("clock", property);
}
}
////////////////////////////////////////////////////////////////
@ -1376,6 +1382,13 @@ Properties::defineProperty(std::string &property,
registry_net_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string &property,
PropertyRegistry<const Clock *>::PropertyHandler handler)
{
registry_clock_.defineProperty(property, handler);
}
////////////////////////////////////////////////////////////////
template<class TYPE>

View File

@ -2112,7 +2112,7 @@ ReportPath::reportSrcClkAndPath(const Path *path,
else if (clk_used_as_data
&& pathFromGenPropClk(path, path->minMax(this))) {
reportClkLine(clk, clk_name.c_str(), clk_end_rf, clk_time, min_max);
ClkInfo *clk_info = path->tag(search_)->clkInfo();
const ClkInfo *clk_info = path->tag(search_)->clkInfo();
if (clk_info->isPropagated())
reportClkSrcLatency(clk_insertion, clk_time, early_late);
reportPath1(path, expanded, true, time_offset);
@ -2259,7 +2259,7 @@ ReportPath::tgtClkInsertionOffet(const Path *clk_path,
const EarlyLate *early_late,
const PathAnalysisPt *path_ap) const
{
ClkInfo *clk_info = clk_path->clkInfo(this);
const ClkInfo *clk_info = clk_path->clkInfo(this);
const Pin *src_pin = clk_info->clkSrc();
const ClockEdge *clk_edge = clk_info->clkEdge();
const Clock *clk = clk_edge->clock();
@ -2278,7 +2278,7 @@ bool
ReportPath::pathFromGenPropClk(const Path *clk_path,
const EarlyLate *early_late) const
{
ClkInfo *clk_info = clk_path->tag(search_)->clkInfo();
const ClkInfo *clk_info = clk_path->tag(search_)->clkInfo();
const ClockEdge *clk_edge = clk_info->clkEdge();
if (clk_edge) {
const Clock *clk = clk_edge->clock();
@ -2393,7 +2393,7 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
const Path *src_path = search_->genclks()->srcPath(clk, clk_pin,
clk_rf, insert_ap);
if (src_path) {
ClkInfo *src_clk_info = src_path->clkInfo(this);
const ClkInfo *src_clk_info = src_path->clkInfo(this);
const ClockEdge *src_clk_edge = src_clk_info->clkEdge();
const Clock *src_clk = src_clk_info->clock();
if (src_clk) {

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();
}
@ -576,7 +576,8 @@ Search::deleteFilterTags()
for (TagIndex i = 0; i < tag_next_; i++) {
Tag *tag = tags_[i];
if (tag
&& tag->isFilter()) {
&& (tag->isFilter()
|| tag->clkInfo()->crprPathRefsFilter())) {
tags_[i] = nullptr;
tag_set_->erase(tag);
delete tag;
@ -589,13 +590,13 @@ void
Search::deleteFilterClkInfos()
{
for (auto itr = clk_info_set_->cbegin(); itr != clk_info_set_->cend(); ) {
ClkInfo *clk_info = *itr;
if (clk_info->refsFilter(this)) {
const ClkInfo *clk_info = *itr;
if (clk_info->crprPathRefsFilter()) {
itr = clk_info_set_->erase(itr);
delete clk_info;
}
else
itr++;
itr++;
}
}
@ -614,8 +615,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);
}
@ -1216,11 +1216,10 @@ ArrivalVisitor::visit(Vertex *vertex)
// If vertex is a latch data input arrival that changed from the
// previous eval pass enqueue the latch outputs to be re-evaled on the
// next pass.
if (network_->isLatchData(pin)) {
if (arrivals_changed
&& network_->isLatchData(pin))
search_->enqueueLatchDataOutputs(vertex);
}
if (arrivals_changed
&& network_->isLatchData(pin))
search_->enqueueLatchDataOutputs(vertex);
if (!search_->arrivalsAtEndpointsExist()
|| always_to_endpoints_
|| arrivals_changed)
@ -1326,7 +1325,7 @@ ArrivalVisitor::visitFromToPath(const Pin * /* from_pin */,
from_tag->to_string(this).c_str());
debugPrint(debug_, "search", 3, " to tag : %s",
to_tag->to_string(this).c_str());
ClkInfo *to_clk_info = to_tag->clkInfo();
const ClkInfo *to_clk_info = to_tag->clkInfo();
bool to_is_clk = to_tag->isClock();
Path *match;
size_t path_index;
@ -1363,7 +1362,7 @@ ArrivalVisitor::pruneCrprArrivals()
for (auto path_itr = path_index_map.cbegin(); path_itr != path_index_map.cend(); ) {
Tag *tag = path_itr->first;
size_t path_index = path_itr->second;
ClkInfo *clk_info = tag->clkInfo();
const ClkInfo *clk_info = tag->clkInfo();
bool deleted_tag = false;
if (!tag->isClock()
&& clk_info->hasCrprClkPin()) {
@ -1372,7 +1371,7 @@ ArrivalVisitor::pruneCrprArrivals()
Path *path_no_crpr = tag_bldr_no_crpr_->tagMatchPath(tag);
if (path_no_crpr) {
Arrival max_arrival = path_no_crpr->arrival();
ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this);
const ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this);
Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr);
Arrival max_arrival_max_crpr = (min_max == MinMax::max())
? max_arrival - max_crpr
@ -1610,9 +1609,9 @@ Search::seedClkArrival(const Pin *pin,
// Propagate liberty "pulse_clock" transition to transitive fanout.
LibertyPort *port = network_->libertyPort(pin);
const RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr);
ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated, nullptr, false,
pulse_clk_sense, insertion, latency,
uncertainties, path_ap, nullptr);
const ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated, nullptr, false,
pulse_clk_sense, insertion, latency,
uncertainties, path_ap, nullptr);
// Only false_paths -from apply to clock tree pins.
ExceptionStateSet *states = nullptr;
sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states);
@ -1652,8 +1651,8 @@ Search::clkDataTag(const Pin *pin,
if (sdc_->exceptionFromStates(pin, rf, clk, rf, min_max, states)) {
bool is_propagated = (clk->isPropagated()
|| sdc_->isPropagatedClock(pin));
ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated,
insertion, path_ap);
const ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated,
insertion, path_ap);
return findTag(rf, path_ap, clk_info, false, nullptr, false, states, true);
}
else
@ -1888,7 +1887,7 @@ Search::inputDelayRefPinArrival(Path *ref_path,
{
Clock *clk = clk_edge->clock();
if (clk->isPropagated()) {
ClkInfo *clk_info = ref_path->clkInfo(this);
const ClkInfo *clk_info = ref_path->clkInfo(this);
ref_arrival = delayAsFloat(ref_path->arrival());
ref_insertion = delayAsFloat(clk_info->insertion());
ref_latency = clk_info->latency();
@ -2011,15 +2010,15 @@ Search::inputDelayTag(const Pin *pin,
ExceptionStateSet *states = nullptr;
Tag *tag = nullptr;
if (sdc_->exceptionFromStates(pin,rf,clk,clk_rf,min_max,states)) {
ClkInfo *clk_info = findClkInfo(clk_edge, clk_pin, is_propagated, nullptr,
false, nullptr, clk_insertion, clk_latency,
clk_uncertainties, path_ap, nullptr);
const ClkInfo *clk_info = findClkInfo(clk_edge, clk_pin, is_propagated, nullptr,
false, nullptr, clk_insertion, clk_latency,
clk_uncertainties, path_ap, nullptr);
tag = findTag(rf, path_ap, clk_info, false, input_delay, is_segment_start,
states, true);
}
if (tag) {
ClkInfo *clk_info = tag->clkInfo();
const ClkInfo *clk_info = tag->clkInfo();
// Check for state changes on existing tag exceptions (pending -thru pins).
tag = mutateTag(tag, pin, rf, false, clk_info,
pin, rf, false, false, is_segment_start, clk_info,
@ -2151,7 +2150,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
{
const TimingRole *role = edge->role();
Tag *from_tag = from_path->tag(this);
ClkInfo *from_clk_info = from_tag->clkInfo();
const ClkInfo *from_clk_info = from_tag->clkInfo();
Tag *to_tag = nullptr;
const ClockEdge *clk_edge = from_clk_info->clkEdge();
const Clock *clk = from_clk_info->clock();
@ -2221,7 +2220,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
// passed thru reg/latch D->Q edges.
&& from_tag->isClock())) {
const RiseFall *clk_rf = clk_edge ? clk_edge->transition() : nullptr;
ClkInfo *to_clk_info = from_clk_info;
const ClkInfo *to_clk_info = from_clk_info;
if (from_clk_info->crprClkPath(this) == nullptr
|| network_->direction(to_pin)->isInternal())
to_clk_info = search_->clkInfoWithCrprClkPath(from_clk_info,
@ -2304,7 +2303,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
Arrival
Search::clkPathArrival(const Path *clk_path) const
{
ClkInfo *clk_info = clk_path->clkInfo(this);
const ClkInfo *clk_info = clk_path->clkInfo(this);
const ClockEdge *clk_edge = clk_info->clkEdge();
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this);
const MinMax *min_max = path_ap->pathMinMax();
@ -2313,7 +2312,7 @@ Search::clkPathArrival(const Path *clk_path) const
Arrival
Search::clkPathArrival(const Path *clk_path,
ClkInfo *clk_info,
const ClkInfo *clk_info,
const ClockEdge *clk_edge,
const MinMax *min_max,
const PathAnalysisPt *path_ap) const
@ -2338,7 +2337,7 @@ Search::clkPathArrival(const Path *clk_path,
Arrival
Search::pathClkPathArrival(const Path *path) const
{
ClkInfo *clk_info = path->clkInfo(this);
const ClkInfo *clk_info = path->clkInfo(this);
if (clk_info->isPropagated()) {
const Path *src_clk_path = pathClkPathArrival1(path);
if (src_clk_path)
@ -2393,7 +2392,7 @@ Search::fromUnclkedInputTag(const Pin *pin,
ExceptionStateSet *states = nullptr;
if (sdc_->exceptionFromStates(pin, rf, nullptr, nullptr, min_max, states)
&& (!require_exception || states)) {
ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap);
const ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap);
return findTag(rf, path_ap, clk_info, false, nullptr,
is_segment_start, states, true);
}
@ -2405,7 +2404,7 @@ Search::fromRegClkTag(const Pin *from_pin,
const RiseFall *from_rf,
const Clock *clk,
const RiseFall *clk_rf,
ClkInfo *clk_info,
const ClkInfo *clk_info,
const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max,
@ -2423,8 +2422,8 @@ Search::fromRegClkTag(const Pin *from_pin,
}
// Insert from_path as ClkInfo crpr_clk_path.
ClkInfo *
Search::clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
const ClkInfo *
Search::clkInfoWithCrprClkPath(const ClkInfo *from_clk_info,
Path *from_path,
const PathAnalysisPt *path_ap)
{
@ -2456,7 +2455,7 @@ Search::thruTag(Tag *from_tag,
Vertex *to_vertex = edge->to(graph_);
const Pin *to_pin = to_vertex->pin();
const RiseFall *from_rf = from_tag->transition();
ClkInfo *from_clk_info = from_tag->clkInfo();
const ClkInfo *from_clk_info = from_tag->clkInfo();
bool to_is_reg_clk = to_vertex->isRegClk();
Tag *to_tag = mutateTag(from_tag, from_pin, from_rf, false, from_clk_info,
to_pin, to_rf, false, to_is_reg_clk, false,
@ -2481,7 +2480,7 @@ Search::thruClkTag(Path *from_path,
Vertex *to_vertex = edge->to(graph_);
const Pin *to_pin = to_vertex->pin();
const RiseFall *from_rf = from_tag->transition();
ClkInfo *from_clk_info = from_tag->clkInfo();
const ClkInfo *from_clk_info = from_tag->clkInfo();
bool from_is_clk = from_tag->isClock();
bool to_is_reg_clk = to_vertex->isRegClk();
const TimingRole *role = edge->role();
@ -2489,19 +2488,20 @@ Search::thruClkTag(Path *from_path,
&& to_propagates_clk
&& (role->isWire()
|| role == TimingRole::combinational()));
ClkInfo *to_clk_info = thruClkInfo(from_path, from_vertex, from_clk_info, from_is_clk,
edge, to_vertex, to_pin, to_is_clk,
arc_delay_min_max_eq, min_max, path_ap);
const ClkInfo *to_clk_info = thruClkInfo(from_path, from_vertex,
from_clk_info, from_is_clk,
edge, to_vertex, to_pin, to_is_clk,
arc_delay_min_max_eq, min_max, path_ap);
Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info,
to_pin, to_rf, to_is_clk, to_is_reg_clk, false,
to_clk_info, nullptr, min_max, path_ap);
return to_tag;
}
ClkInfo *
const ClkInfo *
Search::thruClkInfo(Path *from_path,
Vertex *from_vertex,
ClkInfo *from_clk_info,
const ClkInfo *from_clk_info,
bool from_is_clk,
Edge *edge,
Vertex *to_vertex,
@ -2598,11 +2598,13 @@ Search::thruClkInfo(Path *from_path,
}
if (changed) {
ClkInfo *to_clk_info = findClkInfo(from_clk_edge, from_clk_info->clkSrc(),
to_clk_prop, gen_clk_src,
from_clk_info->isGenClkSrcPath(),
to_pulse_sense, to_insertion, to_latency,
to_uncertainties, path_ap, to_crpr_clk_path);
const ClkInfo *to_clk_info = findClkInfo(from_clk_edge,
from_clk_info->clkSrc(),
to_clk_prop, gen_clk_src,
from_clk_info->isGenClkSrcPath(),
to_pulse_sense, to_insertion, to_latency,
to_uncertainties, path_ap,
to_crpr_clk_path);
return to_clk_info;
}
return from_clk_info;
@ -2614,13 +2616,13 @@ Search::mutateTag(Tag *from_tag,
const Pin *from_pin,
const RiseFall *from_rf,
bool from_is_clk,
ClkInfo *from_clk_info,
const ClkInfo *from_clk_info,
const Pin *to_pin,
const RiseFall *to_rf,
bool to_is_clk,
bool to_is_reg_clk,
bool to_is_segment_start,
ClkInfo *to_clk_info,
const ClkInfo *to_clk_info,
InputDelay *to_input_delay,
const MinMax *min_max,
const PathAnalysisPt *path_ap)
@ -2727,7 +2729,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) {
@ -2828,7 +2830,7 @@ bool
ReportPathLess::operator()(const Path *path1,
const Path *path2) const
{
return tagCmp(path1->tag(sta_), path2->tag(sta_), sta_) < 0;
return Tag::cmp(path1->tag(sta_), path2->tag(sta_), sta_) < 0;
}
void
@ -2967,7 +2969,7 @@ Search::tagCount() const
Tag *
Search::findTag(const RiseFall *rf,
const PathAnalysisPt *path_ap,
ClkInfo *clk_info,
const ClkInfo *clk_info,
bool is_clk,
InputDelay *input_delay,
bool is_segment_start,
@ -3037,17 +3039,17 @@ Search::reportTags() const
void
Search::reportClkInfos() const
{
Vector<ClkInfo*> clk_infos;
Vector<const ClkInfo*> clk_infos;
// set -> vector for sorting.
for (ClkInfo *clk_info : *clk_info_set_)
for (const ClkInfo *clk_info : *clk_info_set_)
clk_infos.push_back(clk_info);
sort(clk_infos, ClkInfoLess(this));
for (ClkInfo *clk_info : clk_infos)
for (const ClkInfo *clk_info : clk_infos)
report_->reportLine("%s", clk_info->to_string(this).c_str());
report_->reportLine("%zu clk infos", clk_info_set_->size());
}
ClkInfo *
const ClkInfo *
Search::findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
@ -3064,7 +3066,7 @@ Search::findClkInfo(const ClockEdge *clk_edge,
pulse_clk_sense, insertion, latency, uncertainties,
path_ap->index(), crpr_clk_path, this);
LockGuard lock(clk_info_lock_);
ClkInfo *clk_info = clk_info_set_->findKey(&probe);
const ClkInfo *clk_info = clk_info_set_->findKey(&probe);
if (clk_info == nullptr) {
clk_info = new ClkInfo(clk_edge, clk_src,
is_propagated, gen_clk_src, gen_clk_src_path,
@ -3075,7 +3077,7 @@ Search::findClkInfo(const ClockEdge *clk_edge,
return clk_info;
}
ClkInfo *
const ClkInfo *
Search::findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
@ -3612,7 +3614,7 @@ RequiredVisitor::visitFromToPath(const Pin *,
while (to_iter.hasNext()) {
Path *to_path = to_iter.next();
Tag *to_path_tag = to_path->tag(this);
if (tagMatchNoCrpr(to_path_tag, to_tag)) {
if (Tag::matchNoCrpr(to_path_tag, to_tag)) {
Required to_required = to_path->required();
Required from_required = to_required - arc_delay;
debugPrint(debug_, "search", 3, " to tag %2u: %s",

View File

@ -2881,7 +2881,7 @@ Sta::vertexArrival(Vertex *vertex,
while (path_iter.hasNext()) {
Path *path = path_iter.next();
const Arrival &path_arrival = path->arrival();
ClkInfo *clk_info = path->clkInfo(search_);
const ClkInfo *clk_info = path->clkInfo(search_);
if ((clk_edge == clk_edge_wildcard
|| clk_info->clkEdge() == clk_edge)
&& !clk_info->isGenClkSrcPath()

View File

@ -38,20 +38,10 @@
namespace sta {
static int
tagStateCmp(const Tag *tag1,
const Tag *tag2);
static bool
tagStateEqual(ExceptionStateSet *states1,
ExceptionStateSet *states2);
static bool
tagStateEqualCrpr(const Tag *tag1,
const Tag *tag2);
Tag::Tag(TagIndex index,
int rf_index,
PathAPIndex path_ap_index,
ClkInfo *clk_info,
const ClkInfo *clk_info,
bool is_clk,
InputDelay *input_delay,
bool is_segment_start,
@ -262,26 +252,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_;
@ -298,20 +294,20 @@ bool
TagLess::operator()(const Tag *tag1,
const Tag *tag2) const
{
return tagCmp(tag1, tag2, sta_) < 0;
return Tag::cmp(tag1, tag2, sta_) < 0;
}
int
tagCmp(const Tag *tag1,
const Tag *tag2,
const StaState *sta)
Tag::cmp(const Tag *tag1,
const Tag *tag2,
const StaState *sta)
{
if (tag1 == tag2)
return 0;
ClkInfo *clk_info1 = tag1->clkInfo();
ClkInfo *clk_info2 = tag2->clkInfo();
int clk_cmp = clkInfoCmp(clk_info1, clk_info2, sta);
const ClkInfo *clk_info1 = tag1->clkInfo();
const ClkInfo *clk_info2 = tag2->clkInfo();
int clk_cmp = ClkInfo::cmp(clk_info1, clk_info2, sta);
if (clk_cmp != 0)
return clk_cmp;
@ -338,8 +334,8 @@ tagCmp(const Tag *tag1,
InputDelay *input_delay1 = tag1->inputDelay();
InputDelay *input_delay2 = tag2->inputDelay();
int input_delay_index1 = input_delay1 ? input_delay1->index() : 0;
int input_delay_index2 = input_delay2 ? input_delay2->index() : 0;
int input_delay_index1 = input_delay1 ? input_delay1->index() : -1;
int input_delay_index2 = input_delay2 ? input_delay2->index() : -1;
if (input_delay_index1 < input_delay_index2)
return -1;
if (input_delay_index1 > input_delay_index2)
@ -352,21 +348,15 @@ tagCmp(const Tag *tag1,
if (is_segment_start1 && !is_segment_start2)
return 1;
return tagStateCmp(tag1, tag2);
return stateCmp(tag1, tag2);
}
bool
tagEqual(const Tag *tag1,
const Tag *tag2)
Tag::equal(const Tag *tag1,
const Tag *tag2,
const StaState *sta)
{
return tag1 == tag2
|| (tag1->rfIndex() == tag2->rfIndex()
&& tag1->pathAPIndex() == tag2->pathAPIndex()
&& tag1->clkInfo() == tag2->clkInfo()
&& tag1->isClock() == tag2->isClock()
&& tag1->inputDelay() == tag2->inputDelay()
&& tag1->isSegmentStart() == tag2->isSegmentStart()
&& tagStateEqual(tag1, tag2));
return cmp(tag1, tag2, sta) == 0;
}
////////////////////////////////////////////////////////////////
@ -391,45 +381,33 @@ bool
TagMatchLess::operator()(const Tag *tag1,
const Tag *tag2) const
{
return tagMatchCmp(tag1, tag2, match_crpr_clk_pin_, sta_) < 0;
return Tag::matchCmp(tag1, tag2, match_crpr_clk_pin_, sta_) < 0;
}
////////////////////////////////////////////////////////////////
bool
tagMatch(const Tag *tag1,
const Tag *tag2,
const StaState *sta)
Tag::match(const Tag *tag1,
const Tag *tag2,
const StaState *sta)
{
return tagMatch(tag1, tag2, true, sta);
return Tag::matchCmp(tag1, tag2, true, sta) == 0;
}
bool
tagMatch(const Tag *tag1,
const Tag *tag2,
bool match_crpr_clk_pin,
const StaState *sta)
Tag::match(const Tag *tag1,
const Tag *tag2,
bool match_crpr_clk_pin,
const StaState *sta)
{
const ClkInfo *clk_info1 = tag1->clkInfo();
const ClkInfo *clk_info2 = tag2->clkInfo();
return tag1 == tag2
|| (clk_info1->clkEdge() == clk_info2->clkEdge()
&& tag1->rfIndex() == tag2->rfIndex()
&& tag1->pathAPIndex() == tag2->pathAPIndex()
&& tag1->isClock() == tag2->isClock()
&& tag1->isSegmentStart() == tag2->isSegmentStart()
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
&& (!match_crpr_clk_pin
|| !sta->crprActive()
|| clk_info1->crprClkVertexId(sta) == clk_info2->crprClkVertexId(sta))
&& tagStateEqual(tag1, tag2));
return Tag::matchCmp(tag1, tag2, match_crpr_clk_pin, sta) == 0;
}
int
tagMatchCmp(const Tag *tag1,
const Tag *tag2,
bool match_crpr_clk_pin,
const StaState *sta)
Tag::matchCmp(const Tag *tag1,
const Tag *tag2,
bool match_crpr_clk_pin,
const StaState *sta)
{
if (tag1 == tag2)
return 0;
@ -490,12 +468,12 @@ tagMatchCmp(const Tag *tag1,
return 1;
}
return tagStateCmp(tag1, tag2);
return stateCmp(tag1, tag2);
}
bool
tagMatchNoCrpr(const Tag *tag1,
const Tag *tag2)
Tag::matchNoCrpr(const Tag *tag1,
const Tag *tag2)
{
const ClkInfo *clk_info1 = tag1->clkInfo();
const ClkInfo *clk_info2 = tag2->clkInfo();
@ -505,12 +483,12 @@ tagMatchNoCrpr(const Tag *tag1,
&& tag1->pathAPIndex() == tag2->pathAPIndex()
&& tag1->isClock() == tag2->isClock()
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
&& tagStateEqual(tag1, tag2));
&& Tag::stateEqual(tag1, tag2));
}
bool
tagMatchNoPathAp(const Tag *tag1,
const Tag *tag2)
Tag::matchNoPathAp(const Tag *tag1,
const Tag *tag2)
{
const ClkInfo *clk_info1 = tag1->clkInfo();
const ClkInfo *clk_info2 = tag2->clkInfo();
@ -520,12 +498,12 @@ tagMatchNoPathAp(const Tag *tag1,
&& tag1->isClock() == tag2->isClock()
&& tag1->isSegmentStart() == tag2->isSegmentStart()
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
&& tagStateEqual(tag1, tag2));
&& Tag::stateEqual(tag1, tag2));
}
bool
tagMatchCrpr(const Tag *tag1,
const Tag *tag2)
Tag::matchCrpr(const Tag *tag1,
const Tag *tag2)
{
const ClkInfo *clk_info1 = tag1->clkInfo();
const ClkInfo *clk_info2 = tag2->clkInfo();
@ -535,14 +513,14 @@ tagMatchCrpr(const Tag *tag1,
&& tag1->isClock() == tag2->isClock()
&& tag1->isSegmentStart() == tag2->isSegmentStart()
&& clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath()
&& tagStateEqualCrpr(tag1, tag2));
&& stateEqualCrpr(tag1, tag2));
}
////////////////////////////////////////////////////////////////
static int
tagStateCmp(const Tag *tag1,
const Tag *tag2)
int
Tag::stateCmp(const Tag *tag1,
const Tag *tag2)
{
ExceptionStateSet *states1 = tag1->states();
ExceptionStateSet *states2 = tag2->states();
@ -571,54 +549,25 @@ tagStateCmp(const Tag *tag1,
&& state_iter2.hasNext()) {
ExceptionState *state1 = state_iter1.next();
ExceptionState *state2 = state_iter2.next();
if (state1 < state2)
if (exceptionStateLess(state1, state2))
return -1;
if (state1 > state2)
if (exceptionStateLess(state2, state1))
return 1;
}
return 0;
}
bool
tagStateEqual(const Tag *tag1,
const Tag *tag2)
Tag::stateEqual(const Tag *tag1,
const Tag *tag2)
{
return tagStateEqual(tag1->states(), tag2->states());
}
static bool
tagStateEqual(ExceptionStateSet *states1,
ExceptionStateSet *states2)
{
bool states_null1 = (states1 == nullptr || states1->empty());
bool states_null2 = (states2 == nullptr || states2->empty());
if (states_null1 && states_null2)
return true;
else if (states_null1 != states_null2)
return false;
size_t state_size1 = states1->size();
size_t state_size2 = states2->size();
if (state_size1 == state_size2) {
ExceptionStateSet::Iterator state_iter1(states1);
ExceptionStateSet::Iterator state_iter2(states2);
while (state_iter1.hasNext()
&& state_iter2.hasNext()) {
ExceptionState *state1 = state_iter1.next();
ExceptionState *state2 = state_iter2.next();
if (state1 != state2)
return false;
}
return true;
}
else
return false;
return stateCmp(tag1, tag2) == 0;
}
// Match loop exception states only for crpr min/max paths.
static bool
tagStateEqualCrpr(const Tag *tag1,
const Tag *tag2)
bool
Tag::stateEqualCrpr(const Tag *tag1,
const Tag *tag2)
{
ExceptionStateSet *states1 = tag1->states();
ExceptionStateSet *states2 = tag2->states();
@ -653,17 +602,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 Tag::equal(tag1, tag2, sta_);
}
TagMatchHash::TagMatchHash(bool match_crpr_clk_pin,
@ -690,7 +650,7 @@ bool
TagMatchEqual::operator()(const Tag *tag1,
const Tag *tag2) const
{
return tagMatch(tag1, tag2, match_crpr_clk_pin_, sta_);
return Tag::match(tag1, tag2, match_crpr_clk_pin_, sta_);
}
} // namespace

View File

@ -54,7 +54,7 @@ public:
Tag(TagIndex index,
int rf_index,
PathAPIndex path_ap_index,
ClkInfo *clk_info,
const ClkInfo *clk_info,
bool is_clk,
InputDelay *input_delay,
bool is_segment_start,
@ -66,7 +66,7 @@ public:
std::string to_string(bool report_index,
bool report_rf_min_max,
const StaState *sta) const;
ClkInfo *clkInfo() const { return clk_info_; }
const ClkInfo *clkInfo() const { return clk_info_; }
bool isClock() const { return is_clk_; }
const ClockEdge *clkEdge() const;
const Clock *clock() const;
@ -85,15 +85,48 @@ 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;
static int cmp(const Tag *tag1,
const Tag *tag2,
const StaState *sta);
static int matchCmp(const Tag *tag1,
const Tag *tag2,
bool match_clk_clk_pin,
const StaState *sta);
static bool match(const Tag *tag1,
const Tag *tag2,
bool match_crpr_clk_pin,
const StaState *sta);
static bool equal(const Tag *tag1,
const Tag *tag2,
const StaState *sta);
static bool matchNoPathAp(const Tag *tag1,
const Tag *tag2);
static bool matchCrpr(const Tag *tag1,
const Tag *tag2);
static bool matchNoCrpr(const Tag *tag1,
const Tag *tag2);
protected:
void findHash();
// Match tag clock edge, clock driver and exception states but not clk info.
static bool match(const Tag *tag1,
const Tag *tag2,
const StaState *sta);
static bool stateEqual(const Tag *tag1,
const Tag *tag2);
static int stateCmp(const Tag *tag1,
const Tag *tag2);
static bool stateEqualCrpr(const Tag *tag1,
const Tag *tag2);
private:
ClkInfo *clk_info_;
const ClkInfo *clk_info_;
InputDelay *input_delay_;
ExceptionStateSet *states_;
size_t hash_;
@ -130,51 +163,22 @@ 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);
int
tagCmp(const Tag *tag1,
const Tag *tag2,
const StaState *sta);
// Match tag clock edge, clock driver and exception states but not clk info.
bool
tagMatch(const Tag *tag1,
const Tag *tag2,
const StaState *sta);
bool
tagMatch(const Tag *tag1,
const Tag *tag2,
bool match_crpr_clk_pin,
const StaState *sta);
bool
tagStateEqual(const Tag *tag1,
const Tag *tag2);
bool
tagMatchNoCrpr(const Tag *tag1,
const Tag *tag2);
int
tagMatchCmp(const Tag *tag1,
const Tag *tag2,
bool match_clk_clk_pin,
const StaState *sta);
bool
tagMatchNoPathAp(const Tag *tag1,
const Tag *tag2);
bool
tagMatchCrpr(const Tag *tag1,
const Tag *tag2);
} // namespace

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);
}
@ -339,10 +343,7 @@ pathIndexMapEqual(const PathIndexMap *path_index_map1,
size_t path_index2;
bool exists2;
path_index_map2->findKey(tag1, tag2, path_index2, exists2);
if (!exists2
// ArrivalMap equal function is TagMatchEqual, so make sure
// the tag is an exact match.
|| tag2 != tag1)
if (!exists2)
return false;
}
return true;

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_;

View File

@ -162,7 +162,7 @@ VisitPathEnds::visitCheckEnd(const Pin *pin,
tgt_clk_path_ap, this);
while (tgt_clk_path_iter.hasNext()) {
Path *tgt_clk_path = tgt_clk_path_iter.next();
ClkInfo *tgt_clk_info = tgt_clk_path->clkInfo(this);
const ClkInfo *tgt_clk_info = tgt_clk_path->clkInfo(this);
const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this);
const Clock *tgt_clk = tgt_clk_path->clock(this);
const Pin *tgt_pin = tgt_clk_vertex->pin();

View File

@ -283,7 +283,7 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this);
while (to_iter.hasNext()) {
Path *to_path = to_iter.next();
if (tagMatchNoCrpr(to_path->tag(this), to_tag)
if (Tag::matchNoCrpr(to_path->tag(this), to_tag)
&& matching_paths->hasKey(to_path)) {
debugPrint(debug_, "visit_path_group", 2,
"match crpr %s %s -> %s %s",