diff --git a/CMakeLists.txt b/CMakeLists.txt index 67b8de44..89f70ac0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,6 +158,7 @@ set(STA_SOURCE search/CheckSlewLimits.cc search/CheckTiming.cc search/ClkInfo.cc + search/ClkNetwork.cc search/ClkSkew.cc search/Corner.cc search/Crpr.cc @@ -181,7 +182,6 @@ set(STA_SOURCE search/ReportPath.cc search/Search.cc search/SearchPred.cc - search/FindClkPins.cc search/Sim.cc search/Sta.cc search/StaState.cc diff --git a/dcalc/GraphDelayCalc1.cc b/dcalc/GraphDelayCalc1.cc index 99d97673..f4b0a20f 100644 --- a/dcalc/GraphDelayCalc1.cc +++ b/dcalc/GraphDelayCalc1.cc @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include "GraphDelayCalc1.hh" + #include "Debug.hh" #include "Stats.hh" #include "MinMax.hh" @@ -34,7 +36,7 @@ #include "ArcDelayCalc.hh" #include "DcalcAnalysisPt.hh" #include "NetCaps.hh" -#include "GraphDelayCalc1.hh" +#include "ClkNetwork.hh" namespace sta { @@ -1387,7 +1389,7 @@ GraphDelayCalc1::edgeFromSlew(const Vertex *from_vertex, { const TimingRole *role = edge->role(); if (role->genericRole() == TimingRole::regClkToQ() - && isIdealClk(from_vertex)) + && clk_network_->isIdealClock(from_vertex->pin())) return idealClkSlew(from_vertex, from_rf, dcalc_ap->slewMinMax()); else return graph_->slew(from_vertex, from_rf, dcalc_ap->index()); @@ -1399,7 +1401,7 @@ GraphDelayCalc1::idealClkSlew(const Vertex *vertex, const MinMax *min_max) { float slew = min_max->initValue(); - const ClockSet *clks = idealClks(vertex); + const ClockSet *clks = clk_network_->idealClocks(vertex->pin()); ClockSet::ConstIterator clk_iter(clks); while (clk_iter.hasNext()) { Clock *clk = clk_iter.next(); @@ -1585,7 +1587,7 @@ GraphDelayCalc1::checkEdgeClkSlew(const Vertex *from_vertex, const RiseFall *from_rf, const DcalcAnalysisPt *dcalc_ap) { - if (isIdealClk(from_vertex)) + if (clk_network_->isIdealClock(from_vertex->pin())) return idealClkSlew(from_vertex, from_rf, dcalc_ap->checkClkSlewMinMax()); else return graph_->slew(from_vertex, from_rf, dcalc_ap->checkClkSlewIndex()); @@ -1674,15 +1676,49 @@ GraphDelayCalc1::setIdealClks(const Vertex *vertex, ClockSet * GraphDelayCalc1::idealClks(const Vertex *vertex) { - return ideal_clks_map_.findKey(vertex); + ClockSet *ideal_clks = ideal_clks_map_.findKey(vertex); + const ClockSet *ideal_clks2 = clk_network_->idealClocks(vertex->pin()); + if (ideal_clks) { + for (Clock *clk : *ideal_clks) { + if (ideal_clks2) { + if (!ideal_clks2->findKey(clk)) + printf("pin %s clk_net missing1 %s\n", + vertex->name(network_), + clk->name()); + } + else + printf("pin %s clk_net missing2 %s\n", + vertex->name(network_), + clk->name()); + } + if (ideal_clks2) { + for (Clock *clk : *ideal_clks2) { + if (ideal_clks) { + if (!ideal_clks->findKey(clk)) { + printf("pin %s dcalc missing3 %s\n", + vertex->name(network_), + clk->name()); + } + } + else + printf("pin %s dcalc missing4 %s\n", + vertex->name(network_), + clk->name()); + } + } + } + return ideal_clks; } bool GraphDelayCalc1::isIdealClk(const Vertex *vertex) { const ClockSet *clks = idealClks(vertex); - return clks != 0 + bool ideal = clks != 0 && clks->size() > 0; + if (ideal != clk_network_->isIdealClock(vertex->pin())) + printf("ideal missmatch\n"); + return ideal; } float @@ -1765,7 +1801,7 @@ GraphDelayCalc1::reportDelayCalc(Edge *edge, const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, dcalc_ap); int slew_index = dcalc_ap->checkDataSlewIndex(); const Slew &to_slew = graph_->slew(to_vertex, to_rf, slew_index); - bool from_ideal_clk = isIdealClk(from_vertex); + bool from_ideal_clk = clk_network_->isIdealClock(from_vertex->pin()); const char *from_slew_annotation = from_ideal_clk ? " (ideal clock)" : nullptr; arc_delay_calc_->reportCheckDelay(cell, arc, from_slew, from_slew_annotation, to_slew, related_out_cap, pvt, dcalc_ap, diff --git a/dcalc/GraphDelayCalc1.hh b/dcalc/GraphDelayCalc1.hh index 55b4f9d6..3c10aed6 100644 --- a/dcalc/GraphDelayCalc1.hh +++ b/dcalc/GraphDelayCalc1.hh @@ -18,6 +18,7 @@ #include +#include "Delay.hh" #include "GraphDelayCalc.hh" namespace sta { diff --git a/include/sta/ClkNetwork.hh b/include/sta/ClkNetwork.hh new file mode 100644 index 00000000..9175abd3 --- /dev/null +++ b/include/sta/ClkNetwork.hh @@ -0,0 +1,67 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2020, 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 . + +#pragma once + +#include "Map.hh" +#include "Set.hh" +#include "StaState.hh" +#include "NetworkClass.hh" +#include "GraphClass.hh" +#include "SdcClass.hh" + +namespace sta { + +typedef Map PinClksMap; +typedef Map ClkPinsMap; + +class Sta; + +// Find clock network pins. +// This is not as reliable as Search::isClock but is much cheaper. +class ClkNetwork : public StaState +{ +public: + ClkNetwork(StaState *sta); + void ensureClkNetwork(); + void clear(); + bool isClock(const Pin *pin) const; + bool isIdealClock(const Pin *pin) const; + const ClockSet *clocks(const Pin *pin); + const ClockSet *idealClocks(const Pin *pin); + void clkPinsInvalid(); + +protected: + void deletePinBefore(const Pin *pin); + void connectPinAfter(const Pin *pin); + void disconnectPinBefore(const Pin *pin); + friend class Sta; + +private: + void findClkPins(); + void findClkPins(bool ideal_only, + PinClksMap &clk_pin_map); + + bool clk_pins_valid_; + // pin -> clks + PinClksMap pin_clks_map_; + // pin -> ideal clks + PinClksMap pin_ideal_clks_map_; + // clock -> pins + ClkPinsMap clk_pins_map_; +}; + +} // namespace diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index af0b67e1..d971af89 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1145,12 +1145,14 @@ public: //////////////////////////////////////////////////////////////// - void ensureClkPins(); - bool isIdealClock(Pin *pin) const; + void ensureClkNetwork(); + // Assumes ensureClkNetwork() has been called. bool isClock(Pin *pin) const; + // Assumes ensureClkNetwork() has been called. + bool isIdealClock(Pin *pin) const; void clkPinsInvalid(); -//////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// void setTclInterp(Tcl_Interp *interp); Tcl_Interp *tclInterp(); @@ -1235,7 +1237,8 @@ protected: virtual void makeGraphDelayCalc(); virtual void makeSim(); virtual void makeSearch(); - virtual void makeLatches(); + virtual void makeLatches(); + virtual void makeClkNetwork(); virtual void makeCheckTiming(); virtual void makeCheckSlewLimits(); virtual void makeCheckFanoutLimits(); @@ -1330,11 +1333,6 @@ protected: void replaceCell(Instance *inst, Cell *to_cell, LibertyCell *to_lib_cell); - void clkPinsConnectPinAfter(Vertex *vertex); - void clkPinsDisconnectPinBefore(Vertex *vertex); - void findClkPins(); - void findClkPins(bool ideal_only, - PinSet &clk_pins); void sdcChangedGraph(); void ensureGraphSdcAnnotated(); @@ -1356,10 +1354,6 @@ protected: bool update_genclks_; EquivCells *equiv_cells_; bool graph_sdc_annotated_; - // findClkPins - PinSet clk_pins_; - PinSet ideal_clk_pins_; - bool clk_pins_valid_; // Singleton sta used by tcl command interpreter. static Sta *sta_; diff --git a/include/sta/StaState.hh b/include/sta/StaState.hh index 03d1fa2c..21c1c5f5 100644 --- a/include/sta/StaState.hh +++ b/include/sta/StaState.hh @@ -36,6 +36,7 @@ class Parasitics; class ArcDelayCalc; class GraphDelayCalc; class Latches; +class ClkNetwork; class DispatchQueue; // Most STA components use functionality in other components. @@ -114,6 +115,7 @@ protected: Sim *sim_; Search *search_; Latches *latches_; + ClkNetwork *clk_network_; int thread_count_; DispatchQueue *dispatch_queue_; bool pocv_enabled_; diff --git a/search/ClkNetwork.cc b/search/ClkNetwork.cc new file mode 100644 index 00000000..c124e254 --- /dev/null +++ b/search/ClkNetwork.cc @@ -0,0 +1,183 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2020, 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 . + +#include "ClkNetwork.hh" + +#include "Debug.hh" +#include "Network.hh" +#include "Graph.hh" +#include "Bfs.hh" +#include "Sdc.hh" +#include "SearchPred.hh" +#include "Search.hh" + +namespace sta { + +ClkNetwork::ClkNetwork(StaState *sta) : + StaState(sta), + clk_pins_valid_(false) +{ +} + +void +ClkNetwork::ensureClkNetwork() +{ + if (!clk_pins_valid_) + findClkPins(); +} + +void +ClkNetwork::clear() +{ + clk_pins_valid_ = false; + pin_clks_map_.clear(); + clk_pins_map_.clear(); + pin_ideal_clks_map_.clear(); +} + +void +ClkNetwork::clkPinsInvalid() +{ + debugPrint0(debug_, "clk_network", 1, "clk network invalid\n"); + 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 (isClock(pin)) + clkPinsInvalid(); +} + +class ClkSearchPred : public ClkTreeSearchPred +{ +public: + ClkSearchPred(const StaState *sta); + virtual bool searchTo(const Vertex *to); +}; + +ClkSearchPred::ClkSearchPred(const StaState *sta) : + ClkTreeSearchPred(sta) +{ +} + +bool +ClkSearchPred::searchTo(const Vertex *to) +{ + const Sdc *sdc = sta_->sdc(); + return !sdc->isLeafPinClock(to->pin()); +} + +void +ClkNetwork::findClkPins() +{ + debugPrint0(debug_, "clk_network", 1, "find clk network\n"); + 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) +{ + ClkSearchPred srch_pred(this); + BfsFwdIterator bfs(BfsIndex::other, &srch_pred, this); + for (Clock *clk : sdc_->clks()) { + if (!ideal_only + || !clk->isPropagated()) { + PinSet &clk_pins = clk_pins_map_[clk]; + for (Pin *pin : clk->leafPins()) { + if (!ideal_only + || !sdc_->isPropagatedClock(pin)) { + Vertex *vertex, *bidirect_drvr_vertex; + graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); + bfs.enqueue(vertex); + if (bidirect_drvr_vertex) + bfs.enqueue(bidirect_drvr_vertex); + } + } + while (bfs.hasNext()) { + Vertex *vertex = bfs.next(); + 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); + bfs.enqueueAdjacentVertices(vertex); + } + } + } + } +} + +bool +ClkNetwork::isClock(const Pin *pin) const +{ + ClockSet clks; + bool exists; + pin_clks_map_.findKey(pin, clks, exists); + if (exists && clks.empty()) + printf("luse empty clks\n"); + return exists; +} + +bool +ClkNetwork::isIdealClock(const Pin *pin) const +{ + ClockSet clks; + bool exists; + pin_ideal_clks_map_.findKey(pin, clks, exists); + if (exists && clks.empty()) + printf("luse empty clks\n"); + return exists; +} + +const ClockSet * +ClkNetwork::clocks(const Pin *pin) +{ + if (pin_clks_map_.hasKey(pin)) + return &pin_clks_map_[pin]; + else + return nullptr; +} + +const ClockSet * +ClkNetwork::idealClocks(const Pin *pin) +{ + if (pin_ideal_clks_map_.hasKey(pin)) + return &pin_ideal_clks_map_[pin]; + else + return nullptr; +} + +} // namespace diff --git a/search/FindClkPins.cc b/search/FindClkPins.cc deleted file mode 100644 index e497e067..00000000 --- a/search/FindClkPins.cc +++ /dev/null @@ -1,124 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2020, 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 . - -#include "Sta.hh" - -#include "Network.hh" -#include "Graph.hh" -#include "Bfs.hh" -#include "Sdc.hh" -#include "SearchPred.hh" -#include "Search.hh" - -namespace sta { - -void -Sta::ensureClkPins() -{ - if (!clk_pins_valid_) { - ensureLevelized(); - findClkPins(); - clk_pins_valid_ = true; - } -} - -void -Sta::clkPinsInvalid() -{ - clk_pins_valid_ = false; - clk_pins_.clear(); - ideal_clk_pins_.clear(); -} - -void -Sta::clkPinsDisconnectPinBefore(Vertex *vertex) -{ - // If the pin is in the clock network but not a clock endpoint - // everything downstream is invalid. - if (clk_pins_.hasKey(vertex->pin()) - && !isClkEnd(vertex, graph_)) - clk_pins_valid_ = false; -} - -void -Sta::clkPinsConnectPinAfter(Vertex *vertex) -{ - // If the pin fanin is part of the clock network - VertexInEdgeIterator edge_iter(vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - Vertex *from = edge->from(graph_); - if (clk_pins_.hasKey(from->pin())) { - clk_pins_valid_ = false; - break; - } - } -} - -// Find clock network pins. -// This is not as reliable as Search::isClock but is much cheaper. -void -Sta::findClkPins() -{ - // Use two passes to find ideal and propagated clock network pins. - findClkPins(false, clk_pins_); - findClkPins(true, ideal_clk_pins_); -} - -void -Sta::findClkPins(bool ideal_only, - PinSet &clk_pins) -{ - ClkArrivalSearchPred srch_pred(this); - BfsFwdIterator bfs(BfsIndex::other, &srch_pred, this); - for (Clock *clk : sdc_->clks()) { - if (!ideal_only - || !clk->isPropagated()) { - for (Pin *pin : clk->leafPins()) { - if (!ideal_only - || !sdc_->isPropagatedClock(pin)) { - Vertex *vertex, *bidirect_drvr_vertex; - graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); - bfs.enqueue(vertex); - if (bidirect_drvr_vertex) - bfs.enqueue(bidirect_drvr_vertex); - } - } - } - } - while (bfs.hasNext()) { - Vertex *vertex = bfs.next(); - Pin *pin = vertex->pin(); - if (!sdc_->isPropagatedClock(pin)) { - clk_pins.insert(pin); - bfs.enqueueAdjacentVertices(vertex); - } - } -} - -bool -Sta::isClock(Pin *pin) const -{ - return clk_pins_.hasKey(pin); -} - -bool -Sta::isIdealClock(Pin *pin) const -{ - return ideal_clk_pins_.hasKey(pin); -} - -} // namespace diff --git a/search/Sta.cc b/search/Sta.cc index 8063d27e..3ce9849e 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -64,6 +64,7 @@ #include "ReportPath.hh" #include "VisitPathGroupVertices.hh" #include "Genclks.hh" +#include "ClkNetwork.hh" #include "Power.hh" namespace sta { @@ -268,8 +269,7 @@ Sta::Sta() : link_make_black_boxes_(true), update_genclks_(false), equiv_cells_(nullptr), - graph_sdc_annotated_(false), - clk_pins_valid_(false) + graph_sdc_annotated_(false) { } @@ -289,6 +289,7 @@ Sta::makeComponents() makeSim(); makeSearch(); makeLatches(); + makeClkNetwork(); makeSdcNetwork(); makeReportPath(); makePower(); @@ -348,6 +349,7 @@ Sta::updateComponentsState() report_path_->copyState(this); if (check_timing_) check_timing_->copyState(this); + clk_network_->copyState(this); if (power_) power_->copyState(this); } @@ -478,6 +480,12 @@ Sta::makeReportPath() report_path_ = new ReportPath(this); } +void +Sta::makeClkNetwork() +{ + clk_network_ = new ClkNetwork(this); +} + void Sta::makePower() { @@ -525,6 +533,7 @@ Sta::~Sta() delete debug_; delete units_; delete report_; + delete clk_network_; delete power_; delete equiv_cells_; delete dispatch_queue_; @@ -2090,6 +2099,7 @@ Sta::removeConstraints() if (graph_) sdc_->removeGraphAnnotations(); sdc_->clear(); + clk_network_->clear(); } void @@ -3107,7 +3117,7 @@ Sta::findDelays(Level level) void Sta::delayCalcPreamble() { - ensureLevelized(); + ensureClkNetwork(); } void @@ -3986,8 +3996,10 @@ Sta::connectPinAfter(Pin *pin) EdgesThruHierPinIterator edge_iter(pin, network_, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - if (edge->role()->isWire()) + if (edge->role()->isWire()) { connectDrvrPinAfter(edge->from(graph_)); + connectLoadPinAfter(edge->to(graph_)); + } } } else { @@ -4034,12 +4046,13 @@ Sta::connectDrvrPinAfter(Vertex *vertex) search_->endpointInvalid(to_vertex); sdc_->clkHpinDisablesChanged(to_vertex->pin()); } - sdc_->clkHpinDisablesChanged(vertex->pin()); + Pin *pin = vertex->pin(); + sdc_->clkHpinDisablesChanged(pin); graph_delay_calc_->delayInvalid(vertex); search_->requiredInvalid(vertex); search_->endpointInvalid(vertex); - clkPinsConnectPinAfter(vertex); levelize_->invalidFrom(vertex); + clk_network_->connectPinAfter(pin); } void @@ -4054,12 +4067,13 @@ Sta::connectLoadPinAfter(Vertex *vertex) search_->requiredInvalid(from_vertex); sdc_->clkHpinDisablesChanged(from_vertex->pin()); } - sdc_->clkHpinDisablesChanged(vertex->pin()); + Pin *pin = vertex->pin(); + sdc_->clkHpinDisablesChanged(pin); graph_delay_calc_->delayInvalid(vertex); levelize_->invalidFrom(vertex); search_->arrivalInvalid(vertex); search_->endpointInvalid(vertex); - clkPinsConnectPinAfter(vertex); + clk_network_->connectPinAfter(pin); } void @@ -4079,7 +4093,7 @@ Sta::disconnectPinBefore(Pin *pin) if (edge->role()->isWire()) deleteEdge(edge); } - clkPinsDisconnectPinBefore(vertex); + clk_network_->disconnectPinBefore(pin); } } if (network_->isLoad(pin)) { @@ -4092,7 +4106,7 @@ Sta::disconnectPinBefore(Pin *pin) if (edge->role()->isWire()) deleteEdge(edge); } - clkPinsDisconnectPinBefore(vertex); + clk_network_->disconnectPinBefore(pin); } } if (network_->isHierarchical(pin)) { @@ -4100,8 +4114,10 @@ Sta::disconnectPinBefore(Pin *pin) EdgesThruHierPinIterator edge_iter(pin, network_, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - if (edge->role()->isWire()) + if (edge->role()->isWire()) { deleteEdge(edge); + clk_network_->disconnectPinBefore(edge->from(graph_)->pin()); + } } } } @@ -4229,6 +4245,7 @@ Sta::deletePinBefore(Pin *pin) } } sim_->deletePinBefore(pin); + clk_network_->deletePinBefore(pin); } void @@ -4926,7 +4943,7 @@ Sta::checkFanoutLimitPreamble() { if (check_fanout_limits_ == nullptr) makeCheckFanoutLimits(); - ensureClkPins(); + ensureClkNetwork(); } Pin * @@ -4991,7 +5008,7 @@ Sta::checkCapacitanceLimitPreamble() { if (check_capacitance_limits_ == nullptr) makeCheckCapacitanceLimits(); - ensureClkPins(); + ensureClkNetwork(); } Pin * @@ -5244,4 +5261,31 @@ Sta::power(const Instance *inst, power_->power(inst, corner, result); } +//////////////////////////////////////////////////////////////// + +void +Sta::ensureClkNetwork() +{ + ensureLevelized(); + clk_network_->ensureClkNetwork(); +} + +bool +Sta::isClock(Pin *pin) const +{ + return clk_network_->isClock(pin); +} + +bool +Sta::isIdealClock(Pin *pin) const +{ + return clk_network_->isIdealClock(pin); +} + +void +Sta::clkPinsInvalid() +{ + clk_network_->clkPinsInvalid(); +} + } // namespace diff --git a/search/StaState.cc b/search/StaState.cc index fcc87f8d..699d5a0f 100644 --- a/search/StaState.cc +++ b/search/StaState.cc @@ -39,6 +39,7 @@ StaState::StaState() : sim_(nullptr), search_(nullptr), latches_(nullptr), + clk_network_(nullptr), thread_count_(1), dispatch_queue_(nullptr), pocv_enabled_(false), @@ -63,6 +64,7 @@ StaState::StaState(const StaState *sta) : sim_(sta->sim_), search_(sta->search_), latches_(sta->latches_), + clk_network_(sta->clk_network_), thread_count_(sta->thread_count_), dispatch_queue_(sta->dispatch_queue_), pocv_enabled_(sta->pocv_enabled_), @@ -89,6 +91,7 @@ StaState::copyState(const StaState *sta) sim_ = sta->sim_; search_ = sta->search_; latches_ = sta->latches_; + clk_network_ = sta->clk_network_; thread_count_ = sta->thread_count_; dispatch_queue_ = sta->dispatch_queue_; pocv_enabled_ = sta->pocv_enabled_;