mirror of
https://github.com/The-OpenROAD-Project/OpenSTA.git
synced 2026-09-01 18:36:42 +02:00
commit 4075953c9798444b9d5275f8fa0320f74b9bf1ef Author: James Cherry <[email protected]> Date: Sat Jul 4 09:00:48 2026 -0700 bfs resort hasNext Signed-off-by: James Cherry <[email protected]> commit 4fb0dd19e479f507935129fe940bcd1cf93b29d0 Author: James Cherry <[email protected]> Date: Thu Jul 2 12:23:54 2026 -0700 ApiChanges Signed-off-by: James Cherry <[email protected]> commit 510afbc1403c9fd2b764b4f3a71dddabd696f052 Author: James Cherry <[email protected]> Date: Thu Jul 2 11:07:44 2026 -0700 bfs enqueueFanin/out Signed-off-by: James Cherry <[email protected]> commit 9a5aa570e910c289b276a519bdf532dfa2e28c5f Author: James Cherry <[email protected]> Date: Thu Jul 2 10:41:27 2026 -0700 Revert "bfs continueFrom/enqueueFanin/out" This reverts commit d18498c947a7df2b615fafda38fbdbe8033eca9d. commit 02a253ab252f6637cfea29bdd788cb25da16813d Author: James Cherry <[email protected]> Date: Thu Jul 2 08:21:49 2026 -0700 Revert "Bfs rm search_pred" This reverts commit d858b3380b5e1d81ff6162b6378672a6099a246f. commit 0adf03613d91c5774545d12cba1dc52052ca732a Author: James Cherry <[email protected]> Date: Thu Jul 2 08:08:04 2026 -0700 Genclks::ensureMaster Signed-off-by: James Cherry <[email protected]> commit 089b373c548b77f9189a2617c3168867de620dfe Author: James Cherry <[email protected]> Date: Wed Jul 1 17:50:43 2026 -0700 Search::ensureDownstreamClkPins() use dfs Signed-off-by: James Cherry <[email protected]> commit 000ca16adb9bdcb92266e5f242629bc3e8612658 Author: James Cherry <[email protected]> Date: Wed Jul 1 10:03:57 2026 -0700 ApiChangeLog Signed-off-by: James Cherry <[email protected]> commit d858b3380b5e1d81ff6162b6378672a6099a246f Author: James Cherry <[email protected]> Date: Wed Jul 1 09:56:53 2026 -0700 Bfs rm search_pred Signed-off-by: James Cherry <[email protected]> commit d18498c947a7df2b615fafda38fbdbe8033eca9d Author: James Cherry <[email protected]> Date: Wed Jul 1 08:07:15 2026 -0700 bfs continueFrom/enqueueFanin/out Signed-off-by: James Cherry <[email protected]> commit a8c55b12b3ad7a1041766775727ad758ae8c6d18 Author: James Cherry <[email protected]> Date: Tue Jun 30 10:07:46 2026 -0700 bfs continue Signed-off-by: James Cherry <[email protected]> commit 8530dcd86b7ee736f1858143c3b2cee57cdbc991 Author: James Cherry <[email protected]> Date: Tue Jun 30 07:15:28 2026 -0700 Graph::visitFanin/out uninline edge iter Signed-off-by: James Cherry <[email protected]> commit 1ba1f4576f4b72c64db742369a63dcf8726ba002 Author: James Cherry <[email protected]> Date: Mon Jun 29 21:09:17 2026 -0700 BfsIterator rm Iterator<Vector> subclass Signed-off-by: James Cherry <[email protected]> commit b3ddd2580298958ad6da8225ecac0d255315504c Author: James Cherry <[email protected]> Date: Mon Jun 29 20:15:23 2026 -0700 ClkNetwork::findClkPins use VertexQueue instead of bfs Signed-off-by: James Cherry <[email protected]> commit 9e73154db48a7301be4039a25aec1fef589ef18a Author: James Cherry <[email protected]> Date: Mon Jun 29 18:39:39 2026 -0700 Search::ensureDownstreamClkPins use VertexQueue Signed-off-by: James Cherry <[email protected]> commit 9cd1b160e126ccacc47375ef508fdbb580bfa162 Author: James Cherry <[email protected]> Date: Mon Jun 29 11:18:03 2026 -0700 comment Signed-off-by: James Cherry <[email protected]> commit 0baf3838e2b8faa5fea560b0c95431b277631fea Author: James Cherry <[email protected]> Date: Mon Jun 29 10:57:39 2026 -0700 findClkArrivals use invalid for clk fringe Signed-off-by: James Cherry <[email protected]> commit e82ccd10a5e4bd69e41ce889685d7a130ae79ed6 Author: James Cherry <[email protected]> Date: Sun Jun 28 20:36:48 2026 -0700 Search::findClkArrivals Signed-off-by: James Cherry <[email protected]> commit cb66a72686c8728141c72ceb593b8a4b895ff696 Author: James Cherry <[email protected]> Date: Sun Jun 28 10:11:55 2026 -0700 rm Search::postponeClkFanouts Signed-off-by: James Cherry <[email protected]> Signed-off-by: James Cherry <[email protected]>
281 lines
6.3 KiB
C++
281 lines
6.3 KiB
C++
// OpenSTA, Static Timing Analyzer
|
|
// Copyright (c) 2026, Parallax Software, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software.
|
|
//
|
|
// Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
//
|
|
// This notice may not be removed or altered from any source distribution.
|
|
|
|
#include "ClkNetwork.hh"
|
|
|
|
#include <queue>
|
|
|
|
#include "Debug.hh"
|
|
#include "Graph.hh"
|
|
#include "Mode.hh"
|
|
#include "Network.hh"
|
|
#include "Sdc.hh"
|
|
#include "Search.hh"
|
|
#include "SearchPred.hh"
|
|
|
|
namespace sta {
|
|
|
|
ClkNetwork::ClkNetwork(Mode *mode,
|
|
StaState *sta) :
|
|
StaState(sta),
|
|
mode_(mode)
|
|
{
|
|
}
|
|
|
|
ClkNetwork::~ClkNetwork()
|
|
{
|
|
deleteContents(clk_pins_map_);
|
|
}
|
|
|
|
void
|
|
ClkNetwork::ensureClkNetwork()
|
|
{
|
|
if (!clk_pins_valid_)
|
|
findClkPins();
|
|
}
|
|
|
|
void
|
|
ClkNetwork::clear()
|
|
{
|
|
clk_pins_valid_ = false;
|
|
pin_clks_map_.clear();
|
|
deleteContents(clk_pins_map_);
|
|
pin_ideal_clks_map_.clear();
|
|
}
|
|
|
|
void
|
|
ClkNetwork::clkPinsInvalid()
|
|
{
|
|
debugPrint(debug_, "clk_network", 1, "clk network invalid");
|
|
clk_pins_valid_ = false;
|
|
}
|
|
|
|
void
|
|
ClkNetwork::deletePinBefore(const Pin *pin)
|
|
{
|
|
if (isClock(pin))
|
|
clkPinsInvalid();
|
|
}
|
|
|
|
void
|
|
ClkNetwork::disconnectPinBefore(const Pin *pin)
|
|
{
|
|
if (isClock(pin))
|
|
clkPinsInvalid();
|
|
}
|
|
|
|
void
|
|
ClkNetwork::connectPinAfter(const Pin *pin)
|
|
{
|
|
if (network_->isRegClkPin(pin))
|
|
clkPinsInvalid();
|
|
}
|
|
|
|
class ClkSearchPred : public ClkTreeSearchPred
|
|
{
|
|
public:
|
|
ClkSearchPred(const StaState *sta);
|
|
bool searchTo(const Vertex *to,
|
|
const Mode *mode) const override;
|
|
};
|
|
|
|
ClkSearchPred::ClkSearchPred(const StaState *sta) :
|
|
ClkTreeSearchPred(sta)
|
|
{
|
|
}
|
|
|
|
bool
|
|
ClkSearchPred::searchTo(const Vertex *to,
|
|
const Mode *mode) const
|
|
{
|
|
return !mode->sdc()->isLeafPinClock(to->pin());
|
|
}
|
|
|
|
void
|
|
ClkNetwork::findClkPins()
|
|
{
|
|
debugPrint(debug_, "clk_network", 1, "find clk network");
|
|
clear();
|
|
findClkPins(false, pin_clks_map_);
|
|
findClkPins(true, pin_ideal_clks_map_);
|
|
clk_pins_valid_ = true;
|
|
}
|
|
|
|
void
|
|
ClkNetwork::findClkPins(bool ideal_only,
|
|
PinClksMap &pin_clks_map)
|
|
{
|
|
const Sdc *sdc = mode_->sdc();
|
|
ClkSearchPred srch_pred(this);
|
|
for (Clock *clk : sdc->clocks()) {
|
|
if (!ideal_only
|
|
|| !clk->isPropagated()) {
|
|
PinSet *clk_pins = clk_pins_map_[clk];
|
|
if (clk_pins == nullptr) {
|
|
clk_pins = new PinSet(network_);
|
|
clk_pins_map_[clk] = clk_pins;
|
|
}
|
|
std::queue<Vertex *> queue;
|
|
VertexSet visited = makeVertexSet(this);
|
|
auto enqueue = [&queue, &visited] (Vertex *vertex) {
|
|
if (vertex && !visited.contains(vertex)) {
|
|
visited.insert(vertex);
|
|
queue.push(vertex);
|
|
}
|
|
};
|
|
for (const Pin *pin : clk->leafPins()) {
|
|
if (!ideal_only
|
|
|| !sdc->isPropagatedClock(pin)) {
|
|
Vertex *vertex, *bidirect_drvr_vertex;
|
|
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
|
|
enqueue(vertex);
|
|
enqueue(bidirect_drvr_vertex);
|
|
}
|
|
}
|
|
while (!queue.empty()) {
|
|
Vertex *vertex = queue.front();
|
|
queue.pop();
|
|
const Pin *pin = vertex->pin();
|
|
if (!ideal_only
|
|
|| !sdc->isPropagatedClock(pin)) {
|
|
clk_pins->insert(pin);
|
|
ClockSet &pin_clks = pin_clks_map[pin];
|
|
pin_clks.insert(clk);
|
|
graph_->visitFanouts(vertex, &srch_pred,
|
|
[&queue, &visited] (Vertex *fanout) {
|
|
if (!visited.contains(fanout)) {
|
|
visited.insert(fanout);
|
|
queue.push(fanout);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
ClkNetwork::isClock(const Pin *pin) const
|
|
{
|
|
return pin_clks_map_.contains(pin);
|
|
}
|
|
|
|
bool
|
|
ClkNetwork::isClock(const Vertex *vertex) const
|
|
{
|
|
return isClock(vertex->pin());
|
|
}
|
|
|
|
bool
|
|
ClkNetwork::isClock(const Net *net) const
|
|
{
|
|
bool is_clk = false;
|
|
NetConnectedPinIterator *pin_iter = network_->pinIterator(net);
|
|
while (pin_iter->hasNext()) {
|
|
const Pin *pin = pin_iter->next();
|
|
if (isClock(pin)) {
|
|
is_clk = true;
|
|
break;
|
|
}
|
|
}
|
|
delete pin_iter;
|
|
return is_clk;
|
|
}
|
|
|
|
bool
|
|
ClkNetwork::isIdealClock(const Pin *pin) const
|
|
{
|
|
return pin_ideal_clks_map_.contains(pin);
|
|
}
|
|
|
|
bool
|
|
ClkNetwork::isIdealClock(const Vertex *vertex) const
|
|
{
|
|
return isIdealClock(vertex->pin());
|
|
}
|
|
|
|
bool
|
|
ClkNetwork::isPropagatedClock(const Pin *pin) const
|
|
{
|
|
return pin_clks_map_.contains(pin)
|
|
&& !pin_ideal_clks_map_.contains(pin);
|
|
}
|
|
|
|
const ClockSet *
|
|
ClkNetwork::clocks(const Pin *pin) const
|
|
{
|
|
auto itr = pin_clks_map_.find(pin);
|
|
if (itr != pin_clks_map_.end())
|
|
return &itr->second;
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
const ClockSet *
|
|
ClkNetwork::clocks(const Vertex *vertex) const
|
|
{
|
|
return clocks(vertex->pin());
|
|
}
|
|
|
|
const ClockSet *
|
|
ClkNetwork::idealClocks(const Pin *pin) const
|
|
{
|
|
auto itr = pin_ideal_clks_map_.find(pin);
|
|
if (itr != pin_ideal_clks_map_.end())
|
|
return &itr->second;
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
const PinSet *
|
|
ClkNetwork::pins(const Clock *clk)
|
|
{
|
|
if (clk_pins_map_.contains(clk))
|
|
return clk_pins_map_[clk];
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
float
|
|
ClkNetwork::idealClkSlew(const Pin *pin,
|
|
const RiseFall *rf,
|
|
const MinMax *min_max) const
|
|
{
|
|
const ClockSet *clks = idealClocks(pin);
|
|
if (clks && !clks->empty()) {
|
|
float slew = min_max->initValue();
|
|
for (Clock *clk : *clks) {
|
|
float clk_slew = clk->slew(rf, min_max);
|
|
if (min_max->compare(clk_slew, slew))
|
|
slew = clk_slew;
|
|
}
|
|
return slew;
|
|
}
|
|
else
|
|
return 0.0;
|
|
}
|
|
|
|
} // namespace sta
|