Merge remote-tracking branch 'parallax/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2025-07-02 16:20:42 +00:00
commit 9c1a6b8ffc
20 changed files with 14470 additions and 78 deletions

14241
doc/OpenSTA.fodt Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -120,7 +120,6 @@ public:
bool isEnum() const { return is_enum_; }
void setIsEnum(bool is_enum);
void checkPrevPath(const StaState *sta) const;
void checkPrevPaths(const StaState *sta) const;
static Path *vertexPath(const Path *path,
const StaState *sta);

View File

@ -49,6 +49,7 @@ public:
PwrActivity(float density,
float duty,
PwrActivityOrigin origin);
void init();
float density() const { return density_; }
void setDensity(float density);
float duty() const { return duty_; }

View File

@ -408,6 +408,8 @@ public:
TagGroupIndex tagGroupIndex(const Vertex *vertex) const;
void setTagGroupIndex(const Vertex *vertex,
TagGroupIndex tag_index);
void checkPrevPaths() const;
void deletePaths(Vertex *vertex);
protected:
void init(StaState *sta);
@ -543,7 +545,6 @@ protected:
bool is_clk,
const PathAnalysisPt *path_ap);
void deletePaths();
void deletePaths(Vertex *vertex);
// Delete with incremental tns/wns update.
void deletePathsIncr(Vertex *vertex);
TagGroup *findTagGroup(TagGroupBldr *group_bldr);

View File

@ -563,6 +563,20 @@ net_load_pins(Net *net)
return pins;
}
PinSet
net_pins(Net *net)
{
Network *network = Sta::sta()->ensureLinked();
PinSet pins(network);
NetConnectedPinIterator *pin_iter = network->connectedPinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
pins.insert(pin);
}
delete pin_iter;
return pins;
}
const char *
pin_location(const Pin *pin)
{

View File

@ -112,6 +112,13 @@ Power::setGlobalActivity(float density,
activities_valid_ = false;
}
void
Power::unsetGlobalActivity()
{
global_activity_.init();
activities_valid_ = false;
}
void
Power::setInputActivity(float density,
float duty)
@ -120,6 +127,13 @@ Power::setInputActivity(float density,
activities_valid_ = false;
}
void
Power::unsetInputActivity()
{
input_activity_.init();
activities_valid_ = false;
}
void
Power::setInputPortActivity(const Port *input_port,
float density,
@ -133,6 +147,17 @@ Power::setInputPortActivity(const Port *input_port,
}
}
void
Power::unsetInputPortActivity(const Port *input_port)
{
Instance *top_inst = network_->topInstance();
const Pin *pin = network_->findPin(top_inst, input_port);
if (pin) {
user_activity_map_.erase(pin);
activities_valid_ = false;
}
}
void
Power::setUserActivity(const Pin *pin,
float density,
@ -143,6 +168,13 @@ Power::setUserActivity(const Pin *pin,
activities_valid_ = false;
}
void
Power::unsetUserActivity(const Pin *pin)
{
user_activity_map_.erase(pin);
activities_valid_ = false;
}
PwrActivity &
Power::userActivity(const Pin *pin)
{
@ -664,7 +696,7 @@ Power::ensureActivities()
// Initialize default input activity (after sdc is defined)
// unless it has been set by command.
if (input_activity_.density() == 0.0) {
if (input_activity_.origin() == PwrActivityOrigin::unknown) {
float min_period = clockMinPeriod();
float density = 0.1 / (min_period != 0.0
? min_period
@ -1535,6 +1567,7 @@ PwrActivity::PwrActivity(float density,
duty_(duty),
origin_(origin)
{
check();
}
PwrActivity::PwrActivity() :
@ -1542,7 +1575,6 @@ PwrActivity::PwrActivity() :
duty_(0.0),
origin_(PwrActivityOrigin::unknown)
{
check();
}
void
@ -1563,6 +1595,14 @@ PwrActivity::setOrigin(PwrActivityOrigin origin)
origin_ = origin;
}
void
PwrActivity::init()
{
density_ = 0.0;
duty_ = 0.0;
origin_ = PwrActivityOrigin::unknown;
}
void
PwrActivity::set(float density,
float duty,

View File

@ -87,16 +87,20 @@ public:
const Corner *corner);
void setGlobalActivity(float activity,
float duty);
void unsetGlobalActivity();
void setInputActivity(float activity,
float duty);
void unsetInputActivity();
void setInputPortActivity(const Port *input_port,
float activity,
float duty);
void unsetInputPortActivity(const Port *input_port);
PwrActivity pinActivity(const Pin *pin);
void setUserActivity(const Pin *pin,
float activity,
float duty,
PwrActivityOrigin origin);
void unsetUserActivity(const Pin *pin);
void reportActivityAnnotation(bool report_unannotated,
bool report_annotated);
float clockMinPeriod();

View File

@ -84,6 +84,13 @@ set_power_global_activity(float activity,
power->setGlobalActivity(activity, duty);
}
void
unset_power_global_activity()
{
Power *power = Sta::sta()->power();
power->unsetGlobalActivity();
}
void
set_power_input_activity(float activity,
float duty)
@ -92,6 +99,13 @@ set_power_input_activity(float activity,
return power->setInputActivity(activity, duty);
}
void
unset_power_input_activity()
{
Power *power = Sta::sta()->power();
return power->unsetInputActivity();
}
void
set_power_input_port_activity(const Port *input_port,
float activity,
@ -101,6 +115,13 @@ set_power_input_port_activity(const Port *input_port,
return power->setInputPortActivity(input_port, activity, duty);
}
void
unset_power_input_port_activity(const Port *input_port)
{
Power *power = Sta::sta()->power();
return power->unsetInputPortActivity(input_port);
}
void
set_power_pin_activity(const Pin *pin,
float activity,
@ -110,6 +131,13 @@ set_power_pin_activity(const Pin *pin,
return power->setUserActivity(pin, activity, duty, PwrActivityOrigin::user);
}
void
unset_power_pin_activity(const Pin *pin)
{
Power *power = Sta::sta()->power();
return power->unsetUserActivity(pin);
}
float
clock_min_period()
{

View File

@ -289,7 +289,7 @@ proc set_power_activity { args } {
foreach port $ports {
if { [get_property $port "direction"] == "input" } {
if { [is_clock_src [sta::get_port_pin $port]] } {
sta_warn 303 "activity cannot be set on clock ports."
sta_warn 310 "activity cannot be set on clock ports."
} else {
set_power_input_port_activity $port $density $duty
}
@ -306,6 +306,47 @@ proc set_power_activity { args } {
################################################################
define_cmd_args "unset_power_activity" { [-global]\
[-input]\
[-input_ports ports]\
[-pins pins]\
[-clock clock]}
proc unset_power_activity { args } {
parse_key_args "unset_power_activity" args \
keys {-input_ports -pins -clock} \
flags {-global -input}
check_argc_eq0 "unset_power_activity" $args
if { [info exists flags(-global)] } {
unset_power_global_activity
}
if { [info exists flags(-input)] } {
unset_power_input_activity
}
if { [info exists keys(-input_ports)] } {
set ports [get_ports_error "input_ports" $keys(-input_ports)]
foreach port $ports {
if { [get_property $port "direction"] == "input" } {
if { [is_clock_src [sta::get_port_pin $port]] } {
sta_warn 303 "activity cannot be set on clock ports."
} else {
unset_power_input_port_activity $port
}
}
}
}
if { [info exists keys(-pins)] } {
set pins [get_pins $keys(-pins)]
foreach pin $pins {
unset_power_pin_activity $pin
}
}
}
################################################################
# Deprecated 9/2024
define_cmd_args "read_power_activities" { [-scope scope] -vcd filename }

View File

@ -253,7 +253,7 @@ CheckCrpr::genClkSrcPaths(const Path *path)
gclk_paths.push_back(path);
Genclks *genclks = search_->genclks();
while (clk_edge->clock()->isGenerated()) {
Path *genclk_path = genclks->srcPath(clk_edge, clk_src, path_ap);
const Path *genclk_path = genclks->srcPath(clk_edge, clk_src, path_ap);
if (genclk_path == nullptr)
break;
clk_info = genclk_path->clkInfo(this);

View File

@ -685,10 +685,10 @@ Genclks::seedSrcPins(Clock *gclk,
const MinMax *min_max = path_ap->pathMinMax();
const EarlyLate *early_late = min_max;
for (const RiseFall *rf : RiseFall::range()) {
Tag *tag = makeTag(gclk, master_clk, master_pin, rf,
src_filter, path_ap);
Arrival insert = search_->clockInsertion(master_clk, master_pin, rf,
min_max, early_late, path_ap);
Tag *tag = makeTag(gclk, master_clk, master_pin, rf,
src_filter, insert, path_ap);
tag_bldr.setArrival(tag, insert);
}
}
@ -704,6 +704,7 @@ Genclks::makeTag(const Clock *gclk,
const Pin *master_pin,
const RiseFall *master_rf,
FilterPath *src_filter,
Arrival insert,
const PathAnalysisPt *path_ap)
{
ExceptionState *state = src_filter->firstState();
@ -715,7 +716,7 @@ Genclks::makeTag(const Clock *gclk,
states->insert(state);
ClkInfo *clk_info = search_->findClkInfo(master_clk->edge(master_rf),
master_pin, true, nullptr, true,
nullptr, 0.0, 0.0, nullptr,
nullptr, insert, 0.0, nullptr,
path_ap, nullptr);
return search_->findTag(master_rf, path_ap, clk_info, false, nullptr, false,
states, true);
@ -855,11 +856,11 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex,
{
auto itr = vertex_src_paths_map_.find(vertex);
if (itr != vertex_src_paths_map_.end()) {
std::vector<const Path*> &src_paths = itr->second;
const std::vector<const Path*> &src_paths = itr->second;
for (const Path *path : src_paths) {
Path src_path = *path;
Path *prev_path = src_path.prevPath();
if (prev_path) {
if (prev_path && !prev_path->isNull()) {
Path *prev_vpath = Path::vertexPath(prev_path, this);
src_path.setPrevPath(prev_vpath);
}
@ -921,7 +922,7 @@ Genclks::recordSrcPaths(Clock *gclk)
size_t path_index = srcPathIndex(rf, path_ap);
Path &src_path = src_paths[path_index];
if ((!divide_by_1
|| (inverting_path == invert))
|| (inverting_path == invert))
&& (!has_edges
|| src_clk_rf == gclk->masterClkEdgeTr(rf))
&& (src_path.isNull()
@ -934,6 +935,7 @@ Genclks::recordSrcPaths(Clock *gclk)
early_late->to_string().c_str(),
rf->to_string().c_str(),
delayAsString(path->arrival(), this));
// If this path is replacing another one delete the previous one.
delete src_path.prevPath();
src_path = *path;
Path *prev_copy = &src_path;
@ -950,11 +952,13 @@ Genclks::recordSrcPaths(Clock *gclk)
}
}
if (found_src_paths) {
// Record vertex->genclk src paths.
for (const Path &path : src_paths) {
if (!path.isNull()) {
const Path *p = &path;
while (p) {
vertex_src_paths_map_[p->vertex(this)].push_back(p);
while (p && !p->isNull()) {
Vertex *vertex = p->vertex(this);
vertex_src_paths_map_[vertex].push_back(p);
p = p->prevPath();
}
}
@ -968,6 +972,12 @@ Genclks::recordSrcPaths(Clock *gclk)
network_->pathName(gclk_pin),
gclk->masterClk()->name());
}
// This can be narrowed to visited vertices.
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
search_->deletePaths(vertex);
}
}
bool
@ -992,7 +1002,7 @@ Genclks::matchesSrcFilter(Path *path,
return false;
}
Path *
const Path *
Genclks::srcPath(const Path *clk_path) const
{
const Pin *src_pin = clk_path->pin(this);
@ -1004,7 +1014,7 @@ Genclks::srcPath(const Path *clk_path) const
insert_ap);
}
Path *
const Path *
Genclks::srcPath(const ClockEdge *clk_edge,
const Pin *src_pin,
const PathAnalysisPt *path_ap) const
@ -1012,7 +1022,7 @@ Genclks::srcPath(const ClockEdge *clk_edge,
return srcPath(clk_edge->clock(), src_pin, clk_edge->transition(), path_ap);
}
Path *
const Path *
Genclks::srcPath(const Clock *gclk,
const Pin *src_pin,
const RiseFall *rf,
@ -1020,14 +1030,12 @@ Genclks::srcPath(const Clock *gclk,
{
auto itr = genclk_src_paths_.find(ClockPinPair(gclk, src_pin));
if (itr != genclk_src_paths_.end()) {
std::vector<Path> src_paths = itr->second;
const std::vector<Path> &src_paths = itr->second;
if (!src_paths.empty()) {
size_t path_index = srcPathIndex(rf, path_ap);
Path &src_path = src_paths[path_index];
if (!src_path.isNull()) {
Path *src_vpath = Path::vertexPath(src_path, this);
return src_vpath;
}
const Path *src_path = &src_paths[path_index];
if (!src_path->isNull())
return src_path;
}
}
return nullptr;
@ -1042,12 +1050,14 @@ Genclks::updateSrcPathPrevs()
const Path *p = &src_path;
while (p) {
Path *src_vpath = Path::vertexPath(p, this);
Path *prev_path = p->prevPath();
if (prev_path) {
Path *prev_vpath = Path::vertexPath(prev_path, this);
src_vpath->setPrevPath(prev_vpath);
src_vpath->setPrevEdgeArc(p->prevEdge(this),
p->prevArc(this), this);
if (src_vpath) {
Path *prev_path = p->prevPath();
if (prev_path) {
Path *prev_vpath = Path::vertexPath(prev_path, this);
src_vpath->setPrevPath(prev_vpath);
src_vpath->setPrevEdgeArc(p->prevEdge(this),
p->prevArc(this), this);
}
}
p = p->prevPath();
}
@ -1066,7 +1076,7 @@ Genclks::insertionDelay(const Clock *clk,
const PathAnalysisPt *path_ap) const
{
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
Path *src_path = srcPath(clk, pin, rf, insert_ap);
const Path *src_path = srcPath(clk, pin, rf, insert_ap);
if (src_path)
return src_path->arrival();
else

View File

@ -72,15 +72,15 @@ public:
const EarlyLate *early_late,
const PathAnalysisPt *path_ap) const;
// Generated clock source path for a clock path root.
Path *srcPath(const Path *clk_path) const;
const Path *srcPath(const Path *clk_path) const;
// Generated clock source path.
Path *srcPath(const ClockEdge *clk_edge,
const Pin *src_pin,
const PathAnalysisPt *path_ap) const;
Path *srcPath(const Clock *clk,
const Pin *src_pin,
const RiseFall *rf,
const PathAnalysisPt *path_ap) const;
const Path *srcPath(const ClockEdge *clk_edge,
const Pin *src_pin,
const PathAnalysisPt *path_ap) const;
const Path *srcPath(const Clock *clk,
const Pin *src_pin,
const RiseFall *rf,
const PathAnalysisPt *path_ap) const;
Vertex *srcPath(const Pin *pin) const;
Level clkPinMaxLevel(const Clock *clk) const;
void copyGenClkSrcPaths(Vertex *vertex,
@ -113,6 +113,7 @@ private:
const Pin *master_pin,
const RiseFall *rf,
FilterPath *src_filter,
Arrival insert,
const PathAnalysisPt *path_ap);
void seedSrcPins(Clock *clk,
BfsBkwdIterator &iter);

View File

@ -203,13 +203,17 @@ Path::init(Vertex *vertex,
std::string
Path::to_string(const StaState *sta) const
{
const PathAnalysisPt *path_ap = pathAnalysisPt(sta);
return stringPrintTmp("%s %s %s/%d %d",
vertex(sta)->to_string(sta).c_str(),
transition(sta)->to_string().c_str(),
path_ap->pathMinMax()->to_string().c_str(),
path_ap->index(),
tagIndex(sta));
if (isNull())
return "null path";
else {
const PathAnalysisPt *path_ap = pathAnalysisPt(sta);
return stringPrintTmp("%s %s %s/%d %d",
vertex(sta)->to_string(sta).c_str(),
transition(sta)->to_string().c_str(),
path_ap->pathMinMax()->to_string().c_str(),
path_ap->index(),
tagIndex(sta));
}
}
bool
@ -366,10 +370,7 @@ Path::slack(const StaState *sta) const
Path *
Path::prevPath() const
{
if (prev_path_ && prev_path_->isNull())
return nullptr;
else
return prev_path_;
return prev_path_;
}
void
@ -440,19 +441,12 @@ Path::setPrevEdgeArc(Edge *prev_edge,
prev_arc_idx_ = 0;
}
void
Path::checkPrevPaths(const StaState *sta) const
{
const Path *path = this;
while (path) {
path->checkPrevPath(sta);
path = path->prevPath();
}
}
void
Path::checkPrevPath(const StaState *sta) const
{
if (prev_path_ && prev_path_->isNull())
sta->report()->reportLine("path %s prev path is null.",
to_string(sta).c_str());
if (prev_path_ && !prev_path_->isNull()) {
Graph *graph = sta->graph();
Edge *edge = prevEdge(sta);

View File

@ -68,10 +68,9 @@ PathExpanded::expand(const Path *path,
bool found_start = false;
while (p) {
const Path *prev_path = p->prevPath();
const TimingArc *prev_arc = p->prevArc(sta_);
if (!found_start) {
if (prev_arc) {
if (prev_path) {
const TimingArc *prev_arc = p->prevArc(sta_);
const TimingRole *prev_role = prev_arc->role();
if (prev_role == TimingRole::regClkToQ()
|| prev_role == TimingRole::latchEnToQ()) {

View File

@ -2391,8 +2391,8 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
{
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
const MinMax *min_max = path_ap->pathMinMax();
Path *src_path = search_->genclks()->srcPath(clk, clk_pin,
clk_rf, insert_ap);
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 ClockEdge *src_clk_edge = src_clk_info->clkEdge();

View File

@ -1276,8 +1276,9 @@ Search::arrivalsChanged(Vertex *vertex,
|| path1->tag(this) != path2->tag(this)
|| !delayEqual(path1->arrival(), path2->arrival())
|| path1->prevEdge(this) != path2->prevEdge(this)
|| path1->prevArc(this) != path2->prevArc(this))
return true;
|| path1->prevArc(this) != path2->prevArc(this)
|| path1->prevPath() != path2->prevPath())
return true;
}
return false;
}
@ -2498,7 +2499,6 @@ Search::thruClkInfo(Path *from_path,
const MinMax *min_max,
const PathAnalysisPt *path_ap)
{
ClkInfo *to_clk_info = from_clk_info;
bool changed = false;
const ClockEdge *from_clk_edge = from_clk_info->clkEdge();
const RiseFall *clk_rf = from_clk_edge->transition();
@ -2585,13 +2585,15 @@ Search::thruClkInfo(Path *from_path,
changed = true;
}
if (changed)
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;
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);
return to_clk_info;
}
return from_clk_info;
}
// Find the tag for a path going from from_tag thru edge to to_pin.
@ -2785,6 +2787,20 @@ Search::setVertexArrivals(Vertex *vertex,
}
}
void
Search::checkPrevPaths() const
{
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
VertexPathIterator path_iter(vertex, graph_);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
path->checkPrevPath(this);
}
}
}
class ReportPathLess
{
public:

View File

@ -4960,9 +4960,7 @@ Sta::findFaninPins(PinSeq *to,
ensureLevelized();
PinSet fanin(network_);
FaninSrchPred pred(thru_disabled, thru_constants, this);
PinSeq::Iterator to_iter(to);
while (to_iter.hasNext()) {
const Pin *pin = to_iter.next();
for (const Pin *pin : *to) {
if (network_->isHierarchical(pin)) {
EdgesThruHierPinIterator edge_iter(pin, network_, graph_);
while (edge_iter.hasNext()) {

View File

@ -47,7 +47,12 @@ proc get_fanin { args } {
}
parse_port_pin_net_arg $keys(-to) pins nets
foreach net $nets {
lappend pins [net_driver_pins $net]
set net_pins [net_pins $net]
if { $net_pins != {} } {
lappend pins $net_pins
} else {
sta_warn 541 "No load pins connected to net [get_full_name $net]."
}
}
set flat [info exists flags(-flat)]
set only_insts [info exists flags(-only_cells)]