Merge pull request #307 from The-OpenROAD-Project-staging/upstream

Upstream
This commit is contained in:
Matt Liberty 2026-03-09 23:26:52 +00:00 committed by GitHub
commit a0b629462d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
83 changed files with 2443 additions and 2657 deletions

View File

@ -241,8 +241,6 @@ set(STA_SOURCE
util/RiseFallMinMaxDelay.cc util/RiseFallMinMaxDelay.cc
util/RiseFallValues.cc util/RiseFallValues.cc
util/Stats.cc util/Stats.cc
util/StringSeq.cc
util/StringSet.cc
util/StringUtil.cc util/StringUtil.cc
util/Transition.cc util/Transition.cc

View File

@ -118,7 +118,7 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
ref_time_ = output_waveforms_->referenceTime(in_slew_); ref_time_ = output_waveforms_->referenceTime(in_slew_);
debugPrint(debug_, "ccs_dcalc", 1, "%s %s", debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
drvr_cell->name(), drvr_cell->name(),
drvr_rf_->to_string().c_str()); drvr_rf_->shortName());
ArcDelay gate_delay; ArcDelay gate_delay;
Slew drvr_slew; Slew drvr_slew;
gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew); gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew);

View File

@ -25,6 +25,7 @@
#include "DelayCalc.hh" #include "DelayCalc.hh"
#include <map> #include <map>
#include <string>
#include "ContainerHelpers.hh" #include "ContainerHelpers.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
@ -37,9 +38,9 @@
namespace sta { namespace sta {
typedef std::map<const char*, MakeArcDelayCalc, CharPtrLess> DelayCalcMap; typedef std::map<std::string, MakeArcDelayCalc> DelayCalcMap;
static DelayCalcMap *delay_calcs = nullptr; static DelayCalcMap delay_calcs;
void void
registerDelayCalcs() registerDelayCalcs()
@ -54,26 +55,23 @@ registerDelayCalcs()
} }
void void
registerDelayCalc(const char *name, registerDelayCalc(const std::string &name,
MakeArcDelayCalc maker) MakeArcDelayCalc maker)
{ {
if (delay_calcs == nullptr) delay_calcs[name] = maker;
delay_calcs = new DelayCalcMap;
(*delay_calcs)[name] = maker;
} }
void void
deleteDelayCalcs() deleteDelayCalcs()
{ {
delete delay_calcs; delay_calcs.clear();
delay_calcs = nullptr;
} }
ArcDelayCalc * ArcDelayCalc *
makeDelayCalc(const char *name, makeDelayCalc(const std::string &name,
StaState *sta) StaState *sta)
{ {
MakeArcDelayCalc maker = findKey(delay_calcs, name); MakeArcDelayCalc maker = findKey(&delay_calcs, name);
if (maker) if (maker)
return maker(sta); return maker(sta);
else else
@ -81,16 +79,16 @@ makeDelayCalc(const char *name,
} }
bool bool
isDelayCalcName(const char *name) isDelayCalcName(const std::string &name)
{ {
return delay_calcs->contains(name); return delay_calcs.contains(name);
} }
StringSeq StringSeq
delayCalcNames() delayCalcNames()
{ {
StringSeq names; StringSeq names;
for (const auto [name, make_dcalc] : *delay_calcs) for (const auto &[name, make_dcalc] : delay_calcs)
names.push_back(name); names.push_back(name);
return names; return names;
} }

View File

@ -125,7 +125,7 @@ class DmpAlg : public StaState
{ {
public: public:
DmpAlg(int nr_order, StaState *sta); DmpAlg(int nr_order, StaState *sta);
virtual ~DmpAlg(); ~DmpAlg() override = default;
virtual const char *name() = 0; virtual const char *name() = 0;
// Set driver model and pi model parameters for delay calculation. // Set driver model and pi model parameters for delay calculation.
virtual void init(const LibertyLibrary *library, virtual void init(const LibertyLibrary *library,
@ -156,7 +156,7 @@ public:
// Return values. // Return values.
double &vo, double &vo,
double &dol_dt); double &dol_dt);
// Load responce to driver waveform. // Load response to driver waveform.
void Vl(double t, void Vl(double t,
// Return values. // Return values.
double &vl, double &vl,
@ -288,8 +288,6 @@ DmpAlg::DmpAlg(int nr_order,
fjac_[i] = fjac_storage_ + i * max_nr_order_; fjac_[i] = fjac_storage_ + i * max_nr_order_;
} }
DmpAlg::~DmpAlg() = default;
void void
DmpAlg::init(const LibertyLibrary *drvr_library, DmpAlg::init(const LibertyLibrary *drvr_library,
const LibertyCell *drvr_cell, const LibertyCell *drvr_cell,
@ -1645,7 +1643,8 @@ gateModelRd(const LibertyCell *cell,
gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1); gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1);
gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2); gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2);
double vth = cell->libertyLibrary()->outputThreshold(rf); double vth = cell->libertyLibrary()->outputThreshold(rf);
float rd = -std::log(vth) * std::abs(delayAsFloat(d1) - delayAsFloat(d2)) / (cap2 - cap1); float rd = -std::log(vth) * std::abs(delayAsFloat(d1) - delayAsFloat(d2))
/ (cap2 - cap1);
return rd; return rd;
} }

View File

@ -604,7 +604,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
{ {
debugPrint(debug_, "delay_calc", 2, " driver cell %s %s", debugPrint(debug_, "delay_calc", 2, " driver cell %s %s",
drvr_cell->name(), drvr_cell->name(),
rf->to_string().c_str()); rf->shortName());
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) { for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) {
for (TimingArc *arc : arc_set->arcs()) { for (TimingArc *arc : arc_set->arcs()) {
if (arc->toEdge()->asRiseFall() == rf) { if (arc->toEdge()->asRiseFall() == rf) {
@ -1114,8 +1114,7 @@ GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
const Pin *from_pin = from_vertex->pin(); const Pin *from_pin = from_vertex->pin();
const RiseFall *from_rf = arc1->fromEdge()->asRiseFall(); const RiseFall *from_rf = arc1->fromEdge()->asRiseFall();
const RiseFall *drvr_rf = arc1->toEdge()->asRiseFall(); const RiseFall *drvr_rf = arc1->toEdge()->asRiseFall();
Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max); const Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
const Pin *drvr_pin1 = drvr_vertex1->pin(); const Pin *drvr_pin1 = drvr_vertex1->pin();
float load_cap; float load_cap;
@ -1694,7 +1693,7 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
related_out_cap, scene, min_max, digits); related_out_cap, scene, min_max, digits);
} }
else { else {
const Slew &from_slew = edgeFromSlew(from_vertex, from_rf, edge, scene, min_max); const Slew from_slew = edgeFromSlew(from_vertex, from_rf, edge, scene, min_max);
const Parasitic *to_parasitic; const Parasitic *to_parasitic;
float load_cap; float load_cap;
parasiticLoad(to_pin, to_rf, scene, min_max, nullptr, arc_delay_calc_, parasiticLoad(to_pin, to_rf, scene, min_max, nullptr, arc_delay_calc_,

View File

@ -231,7 +231,7 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
output_waveforms_[drvr_idx] = output_waveforms; output_waveforms_[drvr_idx] = output_waveforms;
debugPrint(debug_, "ccs_dcalc", 1, "%s %s", debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
dcalc_arg.drvrCell()->name(), dcalc_arg.drvrCell()->name(),
drvr_rf_->to_string().c_str()); drvr_rf_->shortName());
LibertyCell *drvr_cell = dcalc_arg.drvrCell(); LibertyCell *drvr_cell = dcalc_arg.drvrCell();
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary(); const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
bool vdd_exists; bool vdd_exists;
@ -744,7 +744,7 @@ PrimaDelayCalc::dcalcResults()
debugPrint(debug_, "ccs_dcalc", 2, debugPrint(debug_, "ccs_dcalc", 2,
"load %s %s delay %s slew %s", "load %s %s delay %s slew %s",
network_->pathName(load_pin), network_->pathName(load_pin),
drvr_rf_->to_string().c_str(), drvr_rf_->shortName(),
delayAsString(wire_delay, this), delayAsString(wire_delay, this),
delayAsString(load_slew, this)); delayAsString(load_slew, this));

View File

@ -40,7 +40,7 @@ StaState::clk_network__ moved to Mode
StaState::parasitics_ moved to Scene StaState::parasitics_ moved to Scene
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet* Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
to StdStringSeq&. to StringSeq&.
Sta::isClock has been removed. Use mode->clkNetwork()->isClock instead. Sta::isClock has been removed. Use mode->clkNetwork()->isClock instead.

View File

@ -3,7 +3,7 @@ OpenSTA Timing Analyzer Release Notes
This file summarizes user visible changes for each release. This file summarizes user visible changes for each release.
2025/02/24 2026/02/24
---------- ----------
The define_scene -library argument now takes a the library name or a The define_scene -library argument now takes a the library name or a
@ -201,7 +201,7 @@ to remove paths through identical pins and rise/fall edges.
Instances now have pins for verilog netlist power/ground connections, Instances now have pins for verilog netlist power/ground connections,
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet* Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
to StdStringSeq&. to StringSeq&.
Release 2.6.1 2025/03/30 Release 2.6.1 2025/03/30
------------------------- -------------------------

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -299,7 +299,7 @@ latch_d_to_q_en()
if (enable_port) if (enable_port)
return stringPrintTmp("%s %s", return stringPrintTmp("%s %s",
enable_port->name(), enable_port->name(),
enable_rf->to_string().c_str()); enable_rf->shortName());
} }
return ""; return "";
} }

View File

@ -77,9 +77,9 @@ public:
void remove(Vertex *vertex); void remove(Vertex *vertex);
void reportEntries() const; void reportEntries() const;
virtual bool hasNext(); bool hasNext() override;
bool hasNext(Level to_level); bool hasNext(Level to_level);
virtual Vertex *next(); Vertex *next() override;
// Apply visitor to all vertices in the queue in level order. // Apply visitor to all vertices in the queue in level order.
// Returns the number of vertices that are visited. // Returns the number of vertices that are visited.
@ -131,19 +131,19 @@ public:
SearchPred *search_pred, SearchPred *search_pred,
StaState *sta); StaState *sta);
virtual ~BfsFwdIterator(); virtual ~BfsFwdIterator();
virtual void enqueueAdjacentVertices(Vertex *vertex, void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred); SearchPred *search_pred) override;
virtual void enqueueAdjacentVertices(Vertex *vertex, void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred, SearchPred *search_pred,
const Mode *mode); const Mode *mode) override;
using BfsIterator::enqueueAdjacentVertices; using BfsIterator::enqueueAdjacentVertices;
protected: protected:
virtual bool levelLessOrEqual(Level level1, bool levelLessOrEqual(Level level1,
Level level2) const; Level level2) const override;
virtual bool levelLess(Level level1, bool levelLess(Level level1,
Level level2) const; Level level2) const override;
virtual void incrLevel(Level &level) const; void incrLevel(Level &level) const override;
}; };
class BfsBkwdIterator : public BfsIterator class BfsBkwdIterator : public BfsIterator
@ -153,19 +153,19 @@ public:
SearchPred *search_pred, SearchPred *search_pred,
StaState *sta); StaState *sta);
virtual ~BfsBkwdIterator(); virtual ~BfsBkwdIterator();
virtual void enqueueAdjacentVertices(Vertex *vertex, void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred); SearchPred *search_pred) override;
virtual void enqueueAdjacentVertices(Vertex *vertex, void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred, SearchPred *search_pred,
const Mode *mode); const Mode *mode) override;
using BfsIterator::enqueueAdjacentVertices; using BfsIterator::enqueueAdjacentVertices;
protected: protected:
virtual bool levelLessOrEqual(Level level1, bool levelLessOrEqual(Level level1,
Level level2) const; Level level2) const override;
virtual bool levelLess(Level level1, bool levelLess(Level level1,
Level level2) const; Level level2) const override;
virtual void incrLevel(Level &level) const; void incrLevel(Level &level) const override;
}; };
} // namespace } // namespace

View File

@ -60,7 +60,6 @@ public:
comp_(comp), comp_(comp),
min_heap_comp_(comp) min_heap_comp_(comp)
{ {
heap_.reserve(max_size);
} }
// Copy constructor // Copy constructor
@ -107,7 +106,12 @@ public:
setMaxSize(size_t max_size) setMaxSize(size_t max_size)
{ {
max_size_ = max_size; max_size_ = max_size;
heap_.reserve(max_size); }
void
reserve(size_t size)
{
heap_.reserve(size);
} }
// Insert an element into the heap. // Insert an element into the heap.
@ -172,8 +176,6 @@ public:
{ {
// Convert heap to sorted vector (best to worst) // Convert heap to sorted vector (best to worst)
std::sort_heap(heap_.begin(), heap_.end(), min_heap_comp_); std::sort_heap(heap_.begin(), heap_.end(), min_heap_comp_);
// Reverse to get best first (according to user's comparison)
std::reverse(heap_.begin(), heap_.end());
std::vector<T> result = std::move(heap_); std::vector<T> result = std::move(heap_);
heap_.clear(); heap_.clear();
return result; return result;
@ -181,11 +183,10 @@ public:
// Extract all elements sorted from best to worst (const version). // Extract all elements sorted from best to worst (const version).
// Creates a copy since we can't modify the heap. // Creates a copy since we can't modify the heap.
std::vector<T> extract() const std::vector<T> contents() const
{ {
std::vector<T> temp_heap = heap_; std::vector<T> temp_heap = heap_;
std::sort_heap(temp_heap.begin(), temp_heap.end(), min_heap_comp_); std::sort_heap(temp_heap.begin(), temp_heap.end(), min_heap_comp_);
std::reverse(temp_heap.begin(), temp_heap.end());
return temp_heap; return temp_heap;
} }
@ -245,7 +246,7 @@ private:
Compare comp_; Compare comp_;
explicit MinHeapCompare(const Compare& c) : comp_(c) {} explicit MinHeapCompare(const Compare& c) : comp_(c) {}
bool operator()(const T& a, const T& b) const { bool operator()(const T& a, const T& b) const {
return comp_(b, a); // Inverted: worst is at root return comp_(a, b); // comp = less puts largest at root (worst)
} }
}; };

View File

@ -264,8 +264,8 @@ class ConcreteCellPortBitIterator : public Iterator<ConcretePort*>
{ {
public: public:
ConcreteCellPortBitIterator(const ConcreteCell *cell); ConcreteCellPortBitIterator(const ConcreteCell *cell);
virtual bool hasNext(); bool hasNext() override;
virtual ConcretePort *next(); ConcretePort *next() override;
private: private:
void findNext(); void findNext();

View File

@ -24,7 +24,9 @@
#pragma once #pragma once
#include "StringSeq.hh" #include <string>
#include "StringUtil.hh"
namespace sta { namespace sta {
@ -38,10 +40,10 @@ void
registerDelayCalcs(); registerDelayCalcs();
// Register a delay calculator for the set_delay_calc command. // Register a delay calculator for the set_delay_calc command.
void void
registerDelayCalc(const char *name, registerDelayCalc(const std::string &name,
MakeArcDelayCalc maker); MakeArcDelayCalc maker);
bool bool
isDelayCalcName(const char *name); isDelayCalcName(const std::string &name);
StringSeq StringSeq
delayCalcNames(); delayCalcNames();
void void
@ -49,7 +51,7 @@ deleteDelayCalcs();
// Make a registered delay calculator by name. // Make a registered delay calculator by name.
ArcDelayCalc * ArcDelayCalc *
makeDelayCalc(const char *name, makeDelayCalc(const std::string &name,
StaState *sta); StaState *sta);
} // namespace } // namespace

View File

@ -427,8 +427,8 @@ class VertexIterator : public Iterator<Vertex*>
{ {
public: public:
VertexIterator(Graph *graph); VertexIterator(Graph *graph);
virtual bool hasNext() { return vertex_ || bidir_vertex_; } bool hasNext() override { return vertex_ || bidir_vertex_; }
virtual Vertex *next(); Vertex *next() override;
private: private:
bool findNextPin(); bool findNextPin();
@ -450,8 +450,8 @@ public:
const Graph *graph); const Graph *graph);
VertexInEdgeIterator(VertexId vertex_id, VertexInEdgeIterator(VertexId vertex_id,
const Graph *graph); const Graph *graph);
bool hasNext() { return (next_ != nullptr); } bool hasNext() override { return (next_ != nullptr); }
Edge *next(); Edge *next() override;
private: private:
Edge *next_; Edge *next_;
@ -463,8 +463,8 @@ class VertexOutEdgeIterator : public VertexEdgeIterator
public: public:
VertexOutEdgeIterator(Vertex *vertex, VertexOutEdgeIterator(Vertex *vertex,
const Graph *graph); const Graph *graph);
bool hasNext() { return (next_ != nullptr); } bool hasNext() override { return (next_ != nullptr); }
Edge *next(); Edge *next() override;
private: private:
Edge *next_; Edge *next_;
@ -478,8 +478,8 @@ public:
EdgesThruHierPinIterator(const Pin *hpin, EdgesThruHierPinIterator(const Pin *hpin,
Network *network, Network *network,
Graph *graph); Graph *graph);
virtual bool hasNext(); bool hasNext() override;
virtual Edge *next(); Edge *next() override;
private: private:
EdgeSet edges_; EdgeSet edges_;

View File

@ -56,8 +56,8 @@ public:
{ {
} }
bool hasNext() { return seq_ && itr_ != seq_->end(); } bool hasNext() override { return seq_ && itr_ != seq_->end(); }
OBJ_TYPE next() { return *itr_++; } OBJ_TYPE next() override { return *itr_++; }
protected: protected:
const VECTOR_TYPE *seq_; const VECTOR_TYPE *seq_;
@ -80,8 +80,8 @@ public:
{ {
} }
bool hasNext() { return map_ && itr_ != map_->end(); } bool hasNext() override { return map_ && itr_ != map_->end(); }
OBJ_TYPE next() { OBJ_TYPE next() override {
OBJ_TYPE next = itr_->second; OBJ_TYPE next = itr_->second;
itr_++; itr_++;
return next; return next;
@ -108,8 +108,8 @@ public:
{ {
} }
bool hasNext() { return set_ && itr_ != set_->end(); } bool hasNext() override { return set_ && itr_ != set_->end(); }
OBJ_TYPE next() { return *itr_++; } OBJ_TYPE next() override { return *itr_++; }
protected: protected:
const SET_TYPE *set_; const SET_TYPE *set_;

View File

@ -458,8 +458,8 @@ class LibertyCellIterator : public Iterator<LibertyCell*>
{ {
public: public:
LibertyCellIterator(const LibertyLibrary *library); LibertyCellIterator(const LibertyLibrary *library);
bool hasNext(); bool hasNext() override;
LibertyCell *next(); LibertyCell *next() override;
private: private:
ConcreteLibraryCellIterator iter_; ConcreteLibraryCellIterator iter_;
@ -715,8 +715,8 @@ class LibertyCellPortIterator : public Iterator<LibertyPort*>
{ {
public: public:
LibertyCellPortIterator(const LibertyCell *cell); LibertyCellPortIterator(const LibertyCell *cell);
bool hasNext(); bool hasNext() override;
LibertyPort *next(); LibertyPort *next() override;
private: private:
ConcreteCellPortIterator iter_; ConcreteCellPortIterator iter_;
@ -727,8 +727,8 @@ class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
public: public:
LibertyCellPortBitIterator(const LibertyCell *cell); LibertyCellPortBitIterator(const LibertyCell *cell);
virtual ~LibertyCellPortBitIterator(); virtual ~LibertyCellPortBitIterator();
bool hasNext(); bool hasNext() override;
LibertyPort *next(); LibertyPort *next() override;
private: private:
ConcreteCellPortBitIterator *iter_; ConcreteCellPortBitIterator *iter_;
@ -980,8 +980,8 @@ class LibertyPortMemberIterator : public Iterator<LibertyPort*>
public: public:
LibertyPortMemberIterator(const LibertyPort *port); LibertyPortMemberIterator(const LibertyPort *port);
virtual ~LibertyPortMemberIterator(); virtual ~LibertyPortMemberIterator();
virtual bool hasNext(); bool hasNext() override;
virtual LibertyPort *next(); LibertyPort *next() override;
private: private:
ConcretePortMemberIterator *iter_; ConcretePortMemberIterator *iter_;

View File

@ -71,7 +71,7 @@ public:
bool unique_edges, bool unique_edges,
float min_slack, float min_slack,
float max_slack, float max_slack,
StdStringSeq &group_names, StringSeq &group_names,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,

View File

@ -204,8 +204,8 @@ public:
const MinMax *min_max, const MinMax *min_max,
const StaState *sta); const StaState *sta);
virtual ~VertexPathIterator(); virtual ~VertexPathIterator();
virtual bool hasNext(); bool hasNext() override;
virtual Path *next(); Path *next() override;
private: private:
void findNext(); void findNext();

View File

@ -153,9 +153,13 @@ public:
static bool less(const PathEnd *path_end1, static bool less(const PathEnd *path_end1,
const PathEnd *path_end2, const PathEnd *path_end2,
// Compare slack (if constrained), or arrival when false.
bool cmp_slack,
const StaState *sta); const StaState *sta);
static int cmp(const PathEnd *path_end1, static int cmp(const PathEnd *path_end1,
const PathEnd *path_end2, const PathEnd *path_end2,
// Compare slack (if constrained), or arrival when false.
bool cmp_slack,
const StaState *sta); const StaState *sta);
static int cmpSlack(const PathEnd *path_end1, static int cmpSlack(const PathEnd *path_end1,
const PathEnd *path_end2, const PathEnd *path_end2,
@ -611,11 +615,13 @@ protected:
class PathEndLess class PathEndLess
{ {
public: public:
PathEndLess(const StaState *sta); PathEndLess(bool cmp_slack,
const StaState *sta);
bool operator()(const PathEnd *path_end1, bool operator()(const PathEnd *path_end1,
const PathEnd *path_end2) const; const PathEnd *path_end2) const;
protected: protected:
bool cmp_slack_;
const StaState *sta_; const StaState *sta_;
}; };
@ -623,11 +629,13 @@ protected:
class PathEndSlackLess class PathEndSlackLess
{ {
public: public:
PathEndSlackLess(const StaState *sta); PathEndSlackLess(bool cmp_slack,
const StaState *sta);
bool operator()(const PathEnd *path_end1, bool operator()(const PathEnd *path_end1,
const PathEnd *path_end2) const; const PathEnd *path_end2) const;
protected: protected:
bool cmp_slack_;
const StaState *sta_; const StaState *sta_;
}; };

View File

@ -29,10 +29,12 @@
#include <map> #include <map>
#include <mutex> #include <mutex>
#include "BoundedHeap.hh"
#include "SdcClass.hh" #include "SdcClass.hh"
#include "StaState.hh" #include "StaState.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "PathEnd.hh"
namespace sta { namespace sta {
@ -48,7 +50,6 @@ using PathGroupSeq = std::vector<PathGroup*>;
class PathGroup class PathGroup
{ {
public: public:
~PathGroup();
// Path group that compares compare slacks. // Path group that compares compare slacks.
static PathGroup *makePathGroupArrival(const char *name, static PathGroup *makePathGroupArrival(const char *name,
int group_path_count, int group_path_count,
@ -66,9 +67,9 @@ public:
float min_slack, float min_slack,
float max_slack, float max_slack,
const StaState *sta); const StaState *sta);
const char *name() const { return name_.c_str(); } const std::string &name() const { return name_; }
const MinMax *minMax() const { return min_max_;} const MinMax *minMax() const { return min_max_;}
const PathEndSeq &pathEnds() const { return path_ends_; } PathEndSeq pathEnds() const;
void insert(PathEnd *path_end); void insert(PathEnd *path_end);
// Push group_path_count into path_ends. // Push group_path_count into path_ends.
void pushEnds(PathEndSeq &path_ends); void pushEnds(PathEndSeq &path_ends);
@ -76,15 +77,14 @@ public:
bool saveable(PathEnd *path_end); bool saveable(PathEnd *path_end);
bool enumMinSlackUnderMin(PathEnd *path_end); bool enumMinSlackUnderMin(PathEnd *path_end);
int maxPaths() const { return group_path_count_; } int maxPaths() const { return group_path_count_; }
PathEndSeq &pathEnds() { return path_ends_; }
// This does NOT delete the path ends. // This does NOT delete the path ends.
void clear(); void clear();
static size_t group_path_count_max; static int group_path_count_max;
protected: protected:
PathGroup(const char *name, PathGroup(const char *name,
size_t group_path_count, int group_path_count,
size_t endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges, bool unique_edges,
float min_slack, float min_slack,
@ -92,21 +92,17 @@ protected:
bool cmp_slack, bool cmp_slack,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta); const StaState *sta);
void ensureSortedMaxPaths();
void prune();
void sort();
std::string name_; std::string name_;
size_t group_path_count_; int group_path_count_;
size_t endpoint_path_count_; int endpoint_path_count_;
bool unique_pins_; bool unique_pins_;
bool unique_edges_; bool unique_edges_;
float slack_min_; float slack_min_;
float slack_max_; float slack_max_;
PathEndSeq path_ends_;
const MinMax *min_max_; const MinMax *min_max_;
bool compare_slack_; bool cmp_slack_;
float threshold_; BoundedHeap<PathEnd*, PathEndLess> heap_;
std::mutex lock_; std::mutex lock_;
const StaState *sta_; const StaState *sta_;
}; };
@ -120,7 +116,7 @@ public:
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
StdStringSeq &group_names, StringSeq &group_names,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,
@ -144,7 +140,7 @@ public:
PathGroup *findPathGroup(const Clock *clock, PathGroup *findPathGroup(const Clock *clock,
const MinMax *min_max) const; const MinMax *min_max) const;
PathGroupSeq pathGroups(const PathEnd *path_end) const; PathGroupSeq pathGroups(const PathEnd *path_end) const;
static StdStringSeq pathGroupNames(const PathEnd *path_end, static StringSeq pathGroupNames(const PathEnd *path_end,
const StaState *sta); const StaState *sta);
static const char *asyncPathGroupName() { return async_group_name_; } static const char *asyncPathGroupName() { return async_group_name_; }
static const char *pathDelayGroupName() { return path_delay_group_name_; } static const char *pathDelayGroupName() { return path_delay_group_name_; }
@ -184,17 +180,17 @@ protected:
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
StdStringSet &group_names, StringSet &group_names,
bool setup_hold, bool setup_hold,
bool async, bool async,
bool gated_clk, bool gated_clk,
bool unconstrained, bool unconstrained,
const MinMax *min_max); const MinMax *min_max);
bool reportGroup(const char *group_name, bool reportGroup(const char *group_name,
StdStringSet &group_names) const; StringSet &group_names) const;
static GroupPath *groupPathTo(const PathEnd *path_end, static GroupPath *groupPathTo(const PathEnd *path_end,
const StaState *sta); const StaState *sta);
StdStringSeq pathGroupNames(); StringSeq pathGroupNames();
const Mode *mode_; const Mode *mode_;
int group_path_count_; int group_path_count_;

View File

@ -41,7 +41,6 @@ enum class PwrActivityOrigin
propagated, propagated,
clock, clock,
constant, constant,
defaulted,
unknown unknown
}; };

View File

@ -28,7 +28,6 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include "StringSeq.hh"
#include "GraphClass.hh" #include "GraphClass.hh"
#include "SearchClass.hh" #include "SearchClass.hh"

View File

@ -30,7 +30,6 @@
#include <mutex> #include <mutex>
#include "StringUtil.hh" #include "StringUtil.hh"
#include "StringSet.hh"
#include "MinMax.hh" #include "MinMax.hh"
#include "StaState.hh" #include "StaState.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
@ -149,7 +148,7 @@ using ExceptionPathPtHash = std::map<size_t, ExceptionPathSet>;
using ClockLatencies = std::set<ClockLatency*, ClockLatencyLess>; using ClockLatencies = std::set<ClockLatency*, ClockLatencyLess>;
using EdgeClockLatencyMap = std::map<PinPair, ClockLatency*, PinPairLess>; using EdgeClockLatencyMap = std::map<PinPair, ClockLatency*, PinPairLess>;
using PinClockUncertaintyMap = std::map<const Pin*, ClockUncertainties*>; using PinClockUncertaintyMap = std::map<const Pin*, ClockUncertainties*>;
using InterClockUncertaintySet = std::set<InterClockUncertainty*, InterClockUncertaintyLess>; using InterClockUncertaintySet=std::set<InterClockUncertainty*,InterClockUncertaintyLess>;
using ClockGatingCheckMap = std::map<const Clock*, ClockGatingCheck*>; using ClockGatingCheckMap = std::map<const Clock*, ClockGatingCheck*>;
using InstanceClockGatingCheckMap = std::map<const Instance*, ClockGatingCheck*>; using InstanceClockGatingCheckMap = std::map<const Instance*, ClockGatingCheck*>;
using PinClockGatingCheckMap = std::map<const Pin*, ClockGatingCheck*>; using PinClockGatingCheckMap = std::map<const Pin*, ClockGatingCheck*>;
@ -1306,6 +1305,7 @@ protected:
bool clk_hpin_disables_valid_; bool clk_hpin_disables_valid_;
PinSet propagated_clk_pins_; PinSet propagated_clk_pins_;
ClockLatencies clk_latencies_; ClockLatencies clk_latencies_;
PinSet clk_latency_pins_;
EdgeClockLatencyMap edge_clk_latency_map_; EdgeClockLatencyMap edge_clk_latency_map_;
ClockInsertions clk_insertions_; ClockInsertions clk_insertions_;
PinClockUncertaintyMap pin_clk_uncertainty_map_; PinClockUncertaintyMap pin_clk_uncertainty_map_;

View File

@ -100,14 +100,14 @@ public:
bool unconstrained, bool unconstrained,
const SceneSeq &scenes, const SceneSeq &scenes,
const MinMaxAll *min_max, const MinMaxAll *min_max,
size_t group_path_count, int group_path_count,
size_t endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
StdStringSeq &group_names, StringSeq &group_names,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,

View File

@ -29,7 +29,6 @@
#include <map> #include <map>
#include "VectorMap.hh" #include "VectorMap.hh"
#include "StringSet.hh"
#include "MinMaxValues.hh" #include "MinMaxValues.hh"
#include "Delay.hh" #include "Delay.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"

View File

@ -29,7 +29,6 @@
#include <string_view> #include <string_view>
#include <functional> #include <functional>
#include "StringSeq.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "LibertyClass.hh" #include "LibertyClass.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
@ -126,11 +125,11 @@ public:
void setThreadCount(int thread_count); void setThreadCount(int thread_count);
// define_corners compatibility. // define_corners compatibility.
void makeScenes(StringSeq *scene_names); void makeScenes(const StringSeq &scene_names);
void makeScene(const std::string &name, void makeScene(const std::string &name,
const std::string &mode_name, const std::string &mode_name,
const StdStringSeq &liberty_min_files, const StringSeq &liberty_min_files,
const StdStringSeq &liberty_max_files, const StringSeq &liberty_max_files,
const std::string &spef_min_file, const std::string &spef_min_file,
const std::string &spef_max_file); const std::string &spef_max_file);
Scene *findScene(const std::string &name) const; Scene *findScene(const std::string &name) const;
@ -653,7 +652,7 @@ public:
const Sdc *sdc) __attribute__ ((deprecated)); const Sdc *sdc) __attribute__ ((deprecated));
bool isPathGroupName(const char *group_name, bool isPathGroupName(const char *group_name,
const Sdc *sdc) const; const Sdc *sdc) const;
StdStringSeq pathGroupNames(const Sdc *sdc) const; StringSeq pathGroupNames(const Sdc *sdc) const;
void resetPath(ExceptionFrom *from, void resetPath(ExceptionFrom *from,
ExceptionThruSeq *thrus, ExceptionThruSeq *thrus,
ExceptionTo *to, ExceptionTo *to,
@ -966,7 +965,7 @@ public:
bool sort_by_slack, bool sort_by_slack,
// Path groups to report. // Path groups to report.
// Empty list reports all groups. // Empty list reports all groups.
StdStringSeq &group_names, StringSeq &group_names,
// Predicates to filter the type of path // Predicates to filter the type of path
// ends returned. // ends returned.
bool setup, bool setup,
@ -976,7 +975,7 @@ public:
bool clk_gating_setup, bool clk_gating_setup,
bool clk_gating_hold); bool clk_gating_hold);
void setReportPathFormat(ReportPathFormat format); void setReportPathFormat(ReportPathFormat format);
void setReportPathFieldOrder(StringSeq *field_names); void setReportPathFieldOrder(const StringSeq &field_names);
void setReportPathFields(bool report_input_pin, void setReportPathFields(bool report_input_pin,
bool report_hier_pins, bool report_hier_pins,
bool report_net, bool report_net,
@ -1388,7 +1387,7 @@ public:
LibertyLibrarySeq *map_libs); LibertyLibrarySeq *map_libs);
LibertyCellSeq *equivCells(LibertyCell *cell); LibertyCellSeq *equivCells(LibertyCell *cell);
void writePathSpice(Path *path, void writePathSpice(const Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,
@ -1588,8 +1587,8 @@ protected:
void setThreadCount1(int thread_count); void setThreadCount1(int thread_count);
void updateLibertyScenes(); void updateLibertyScenes();
void updateSceneLiberty(Scene *scene, void updateSceneLiberty(Scene *scene,
const StdStringSeq &liberty_min_files, const StringSeq &liberty_min_files,
const StdStringSeq &liberty_max_files); const StringSeq &liberty_max_files);
Scene *makeScene(const std::string &name, Scene *makeScene(const std::string &name,
Mode *mode, Mode *mode,

View File

@ -1,38 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, 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.
#pragma once
#include <vector>
#include "StringUtil.hh"
namespace sta {
using StringSeq = std::vector<const char*>;
void
deleteContents(StringSeq *strings);
} // namespace

View File

@ -1,38 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, 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.
#pragma once
#include <set>
#include "StringUtil.hh"
namespace sta {
using StringSet = std::set<const char*, CharPtrLess>;
using StdStringSet = std::set<std::string>;
void
deleteContents(StringSet *strings);
} // namespace

View File

@ -28,12 +28,14 @@
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <vector> #include <vector>
#include <set>
#include "Machine.hh" // __attribute__ #include "Machine.hh" // __attribute__
namespace sta { namespace sta {
using StdStringSeq = std::vector<std::string>; using StringSeq = std::vector<std::string>;
using StringSet = std::set<std::string>;
inline bool inline bool
stringEq(const char *str1, stringEq(const char *str1,
@ -204,7 +206,7 @@ void
trimRight(std::string &str); trimRight(std::string &str);
// Spit text into delimiter separated tokens and skip whitepace. // Spit text into delimiter separated tokens and skip whitepace.
StdStringSeq StringSeq
parseTokens(const std::string &s, parseTokens(const std::string &s,
const char delimiter); const char delimiter);

View File

@ -22,33 +22,24 @@
// //
// This notice may not be removed or altered from any source distribution. // This notice may not be removed or altered from any source distribution.
#include "ArcDelayCalc.hh"
#include "StringSet.hh"
#include "StringSeq.hh"
#include <tcl.h> #include <tcl.h>
#include "ArcDelayCalc.hh"
#include "StringUtil.hh"
namespace sta { namespace sta {
#if TCL_MAJOR_VERSION < 9 #if TCL_MAJOR_VERSION < 9
typedef int Tcl_Size; typedef int Tcl_Size;
#endif #endif
StringSet * StringSeq
tclListSetConstChar(Tcl_Obj *const source,
Tcl_Interp *interp);
StringSeq *
tclListSeqConstChar(Tcl_Obj *const source,
Tcl_Interp *interp);
StdStringSeq
tclListSeqStdString(Tcl_Obj *const source, tclListSeqStdString(Tcl_Obj *const source,
Tcl_Interp *interp); Tcl_Interp *interp);
StdStringSeq * StringSeq *
tclListSeqStdStringPtr(Tcl_Obj *const source, tclListSeqStdStringPtr(Tcl_Obj *const source,
Tcl_Interp *interp); Tcl_Interp *interp);
StdStringSet * StringSet *
tclListSetStdString(Tcl_Obj *const source, tclListSetStdString(Tcl_Obj *const source,
Tcl_Interp *interp); Tcl_Interp *interp);

View File

@ -48,8 +48,7 @@ public:
static const RiseFall *fall() { return &fall_; } static const RiseFall *fall() { return &fall_; }
static int riseIndex() { return rise_.sdf_triple_index_; } static int riseIndex() { return rise_.sdf_triple_index_; }
static int fallIndex() { return fall_.sdf_triple_index_; } static int fallIndex() { return fall_.sdf_triple_index_; }
const std::string &to_string_long() const { return name_; } const std::string &to_string(bool use_short = false) const;
const std::string &to_string() const { return short_name_; }
const char *name() const { return name_.c_str(); } const char *name() const { return name_.c_str(); }
const char *shortName() const { return short_name_.c_str(); } const char *shortName() const { return short_name_.c_str(); }
int index() const { return sdf_triple_index_; } int index() const { return sdf_triple_index_; }
@ -94,7 +93,7 @@ public:
static const RiseFallBoth *rise() { return &rise_; } static const RiseFallBoth *rise() { return &rise_; }
static const RiseFallBoth *fall() { return &fall_; } static const RiseFallBoth *fall() { return &fall_; }
static const RiseFallBoth *riseFall() { return &rise_fall_; } static const RiseFallBoth *riseFall() { return &rise_fall_; }
const std::string &to_string() const { return short_name_; } const std::string &to_string(bool use_short = false) const;
const char *name() const { return name_.c_str(); } const char *name() const { return name_.c_str(); }
const char *shortName() const { return short_name_.c_str(); } const char *shortName() const { return short_name_.c_str(); }
int index() const { return sdf_triple_index_; } int index() const { return sdf_triple_index_; }

View File

@ -28,7 +28,7 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include "StringSet.hh" #include "StringUtil.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
namespace sta { namespace sta {
@ -173,7 +173,7 @@ protected:
void makeNamedPortRefCellPorts(Cell *cell, void makeNamedPortRefCellPorts(Cell *cell,
VerilogModule *module, VerilogModule *module,
VerilogNet *mod_port, VerilogNet *mod_port,
StdStringSet &port_names); StringSet &port_names);
void checkModuleDcls(VerilogModule *module, void checkModuleDcls(VerilogModule *module,
std::set<std::string> &port_names); std::set<std::string> &port_names);
void makeModuleInstBody(VerilogModule *module, void makeModuleInstBody(VerilogModule *module,

View File

@ -31,7 +31,6 @@
#include "Debug.hh" #include "Debug.hh"
#include "Error.hh" #include "Error.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "StringSet.hh"
#include "PatternMatch.hh" #include "PatternMatch.hh"
#include "Units.hh" #include "Units.hh"
#include "Transition.hh" #include "Transition.hh"
@ -1367,17 +1366,14 @@ LibertyCell::makeTimingArcPortMaps()
LibertyPort *from = arc_set->from(); LibertyPort *from = arc_set->from();
LibertyPort *to = arc_set->to(); LibertyPort *to = arc_set->to();
if (from && to) { if (from && to) {
LibertyPortPair from_to_pair(from, to); TimingArcSetSeq &sets = port_timing_arc_set_map_[{from, to}];
TimingArcSetSeq &sets = port_timing_arc_set_map_[from_to_pair];
sets.push_back(arc_set); sets.push_back(arc_set);
} }
LibertyPortPair from_pair(from, nullptr); TimingArcSetSeq &from_sets = port_timing_arc_set_map_[{from, nullptr}];
TimingArcSetSeq &from_sets = port_timing_arc_set_map_[from_pair];
from_sets.push_back(arc_set); from_sets.push_back(arc_set);
LibertyPortPair to_pair(nullptr, to); TimingArcSetSeq &to_sets = port_timing_arc_set_map_[{nullptr, to}];
TimingArcSetSeq &to_sets = port_timing_arc_set_map_[to_pair];
to_sets.push_back(arc_set); to_sets.push_back(arc_set);
const TimingRole *role = arc_set->role(); const TimingRole *role = arc_set->role();
@ -1411,8 +1407,7 @@ LibertyCell::timingArcSets(const LibertyPort *from,
const LibertyPort *to) const const LibertyPort *to) const
{ {
static const TimingArcSetSeq null_set; static const TimingArcSetSeq null_set;
const LibertyPortPair port_pair(from, to); auto itr = port_timing_arc_set_map_.find({from, to});
auto itr = port_timing_arc_set_map_.find(port_pair);
return (itr == port_timing_arc_set_map_.end()) ? null_set : itr->second; return (itr == port_timing_arc_set_map_.end()) ? null_set : itr->second;
} }
@ -1437,8 +1432,8 @@ LibertyCell::timingArcSetCount() const
bool bool
LibertyCell::hasTimingArcs(LibertyPort *port) const LibertyCell::hasTimingArcs(LibertyPort *port) const
{ {
return port_timing_arc_set_map_.contains(LibertyPortPair(port, nullptr)) return port_timing_arc_set_map_.contains({port, nullptr})
|| port_timing_arc_set_map_.contains(LibertyPortPair(nullptr, port)); || port_timing_arc_set_map_.contains({nullptr, port});
} }
void void

View File

@ -78,8 +78,7 @@ LibertyReader::LibertyReader(const char *filename,
debug_(network->debug()), debug_(network->debug()),
network_(network), network_(network),
builder_(debug_, report_), builder_(debug_, report_),
library_(nullptr), library_(nullptr)
first_cell_(true)
{ {
defineVisitors(); defineVisitors();
} }
@ -148,13 +147,13 @@ LibertyReader::beginLibrary(const LibertyGroup *library_group,
} }
void void
LibertyReader::endLibrary(const LibertyGroup *group, LibertyReader::endLibrary(const LibertyGroup *library_group,
LibertyGroup *) LibertyGroup *)
{ {
// If a library hasno cells endCell is not called. // If a library has no cells endCell is not called.
if (first_cell_) readLibraryAttributes(library_group);
readLibraryAttributes(group); checkThresholds(library_group);
delete group; delete library_group;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -167,12 +166,7 @@ LibertyReader::endCell(const LibertyGroup *cell_group,
// Normally they are all defined by the first cell, but there // Normally they are all defined by the first cell, but there
// are libraries that define table templates and bus tyupes // are libraries that define table templates and bus tyupes
// between cells. // between cells.
if (first_cell_) readLibraryAttributes(library_group);
readLibraryAttributes(library_group);
else {
readTableTemplates(library_group);
readBusTypes(nullptr, library_group);
}
const char *name = cell_group->firstName(); const char *name = cell_group->firstName();
if (name) { if (name) {
@ -182,8 +176,10 @@ LibertyReader::endCell(const LibertyGroup *cell_group,
} }
else else
libWarn(1193, cell_group, "cell missing name."); libWarn(1193, cell_group, "cell missing name.");
// Delete the cell group and preceding library attributes
// and groups so they are not revisited and reduce memory peak.
library_group->clear(); library_group->clear();
first_cell_ = false;
} }
void void
@ -524,24 +520,28 @@ void
LibertyReader::readThresholds(const LibertyGroup *library_group) LibertyReader::readThresholds(const LibertyGroup *library_group)
{ {
for (const RiseFall *rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
std::string suffix = rf->to_string_long(); std::string suffix = rf->to_string();
readLibAttrFloat(library_group, ("input_threshold_pct_" + suffix).c_str(), readLibAttrFloat(library_group, ("input_threshold_pct_" + suffix).c_str(),
&LibertyLibrary::setInputThreshold, rf, 0.01F); &LibertyLibrary::setInputThreshold, rf, 0.01F);
if (library_->inputThreshold(rf) == 0.0)
libWarn(1145, library_group, "input_threshold_pct_%s not found.", rf->name());
readLibAttrFloat(library_group, ("output_threshold_pct_" + suffix).c_str(), readLibAttrFloat(library_group, ("output_threshold_pct_" + suffix).c_str(),
&LibertyLibrary::setOutputThreshold, rf, 0.01F); &LibertyLibrary::setOutputThreshold, rf, 0.01F);
if (library_->outputThreshold(rf) == 0.0)
libWarn(1146, library_group, "output_threshold_pct_%s not found.", rf->name());
readLibAttrFloat(library_group, ("slew_lower_threshold_pct_" + suffix).c_str(), readLibAttrFloat(library_group, ("slew_lower_threshold_pct_" + suffix).c_str(),
&LibertyLibrary::setSlewLowerThreshold, rf, 0.01F); &LibertyLibrary::setSlewLowerThreshold, rf, 0.01F);
if (library_->slewLowerThreshold(rf) == 0.0)
libWarn(1147, library_group, "slew_lower_threshold_pct_%s not found.", rf->name());
readLibAttrFloat(library_group, ("slew_upper_threshold_pct_" + suffix).c_str(), readLibAttrFloat(library_group, ("slew_upper_threshold_pct_" + suffix).c_str(),
&LibertyLibrary::setSlewUpperThreshold, rf, 0.01F); &LibertyLibrary::setSlewUpperThreshold, rf, 0.01F);
}
}
void
LibertyReader::checkThresholds(const LibertyGroup *library_group) const
{
for (const RiseFall *rf : RiseFall::range()) {
if (library_->inputThreshold(rf) == 0.0)
libWarn(1145, library_group, "input_threshold_pct_%s not found.", rf->name());
if (library_->outputThreshold(rf) == 0.0)
libWarn(1146, library_group, "output_threshold_pct_%s not found.", rf->name());
if (library_->slewLowerThreshold(rf) == 0.0)
libWarn(1147, library_group, "slew_lower_threshold_pct_%s not found.", rf->name());
if (library_->slewUpperThreshold(rf) == 0.0) if (library_->slewUpperThreshold(rf) == 0.0)
libWarn(1148, library_group, "slew_upper_threshold_pct_%s not found.", rf->name()); libWarn(1148, library_group, "slew_upper_threshold_pct_%s not found.", rf->name());
} }
@ -907,7 +907,7 @@ void
LibertyReader::readSlewDegradations(const LibertyGroup *library_group) LibertyReader::readSlewDegradations(const LibertyGroup *library_group)
{ {
for (const RiseFall *rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
const std::string group_name = rf->to_string_long() + "_transition_degradation"; const std::string group_name = rf->to_string() + "_transition_degradation";
const LibertyGroup *degradation_group = const LibertyGroup *degradation_group =
library_group->findSubgroup(group_name.c_str()); library_group->findSubgroup(group_name.c_str());
if (degradation_group) { if (degradation_group) {
@ -1480,7 +1480,7 @@ LibertyReader::readCapacitance(const LibertyPortSeq &ports,
for (LibertyPort *port : ports) { for (LibertyPort *port : ports) {
// rise/fall_capacitance // rise/fall_capacitance
for (const RiseFall *rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
std::string attr_name = rf->to_string_long() + "_capacitance"; std::string attr_name = rf->to_string() + "_capacitance";
float cap; float cap;
bool exists; bool exists;
port_group->findAttrFloat(attr_name, cap, exists); port_group->findAttrFloat(attr_name, cap, exists);
@ -1490,7 +1490,7 @@ LibertyReader::readCapacitance(const LibertyPortSeq &ports,
} }
// rise/fall_capacitance_range(min_cap, max_cap); // rise/fall_capacitance_range(min_cap, max_cap);
attr_name = rf->to_string_long() + "_capacitance_range"; attr_name = rf->to_string() + "_capacitance_range";
const LibertyComplexAttrSeq &range_attrs = port_group->findComplexAttrs(attr_name); const LibertyComplexAttrSeq &range_attrs = port_group->findComplexAttrs(attr_name);
if (!range_attrs.empty()) { if (!range_attrs.empty()) {
const LibertyComplexAttr *attr = range_attrs[0]; const LibertyComplexAttr *attr = range_attrs[0];
@ -1894,8 +1894,8 @@ LibertyReader::makeTimingArcs(LibertyCell *cell,
LibertyPort *related_output_port = findLibertyPort(cell, timing_group, LibertyPort *related_output_port = findLibertyPort(cell, timing_group,
"related_output_pin"); "related_output_pin");
StdStringSeq related_port_names = findAttributStrings(timing_group, "related_pin"); StringSeq related_port_names = findAttributStrings(timing_group, "related_pin");
StdStringSeq related_bus_names=findAttributStrings(timing_group,"related_bus_pins"); StringSeq related_bus_names=findAttributStrings(timing_group,"related_bus_pins");
TimingType timing_type = timing_attrs->timingType(); TimingType timing_type = timing_attrs->timingType();
for (LibertyPort *to_port : ports) { for (LibertyPort *to_port : ports) {
@ -2081,7 +2081,7 @@ LibertyReader::makeLinearModels(LibertyCell *cell,
{ {
LibertyLibrary *library = cell->libertyLibrary(); LibertyLibrary *library = cell->libertyLibrary();
for (const RiseFall *rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
std::string intr_attr_name = "intrinsic_" + rf->to_string_long(); std::string intr_attr_name = "intrinsic_" + rf->to_string();
float intr = 0.0; float intr = 0.0;
bool intr_exists; bool intr_exists;
timing_group->findAttrFloat(intr_attr_name, intr, intr_exists); timing_group->findAttrFloat(intr_attr_name, intr, intr_exists);
@ -2094,7 +2094,7 @@ LibertyReader::makeLinearModels(LibertyCell *cell,
if (timingTypeIsCheck(timing_attrs->timingType())) if (timingTypeIsCheck(timing_attrs->timingType()))
model = new CheckLinearModel(cell, intr); model = new CheckLinearModel(cell, intr);
else { else {
std::string res_attr_name = rf->to_string_long() + "_resistance"; std::string res_attr_name = rf->to_string() + "_resistance";
float res = 0.0; float res = 0.0;
bool res_exists; bool res_exists;
timing_group->findAttrFloat(res_attr_name, res, res_exists); timing_group->findAttrFloat(res_attr_name, res, res_exists);
@ -2117,18 +2117,18 @@ LibertyReader::makeTableModels(LibertyCell *cell,
{ {
bool found_model = false; bool found_model = false;
for (const RiseFall *rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
std::string delay_attr_name = "cell_" + rf->to_string_long(); std::string delay_attr_name = "cell_" + rf->to_string();
TableModel *delay = readGateTableModel(timing_group, delay_attr_name.c_str(), rf, TableModel *delay = readGateTableModel(timing_group, delay_attr_name.c_str(), rf,
TableTemplateType::delay, time_scale_, TableTemplateType::delay, time_scale_,
ScaleFactorType::cell); ScaleFactorType::cell);
std::string transition_attr_name = rf->to_string_long() + "_transition"; std::string transition_attr_name = rf->to_string() + "_transition";
TableModel *transition = readGateTableModel(timing_group, TableModel *transition = readGateTableModel(timing_group,
transition_attr_name.c_str(), transition_attr_name.c_str(),
rf, TableTemplateType::delay, rf, TableTemplateType::delay,
time_scale_, time_scale_,
ScaleFactorType::transition); ScaleFactorType::transition);
if (delay || transition) { if (delay || transition) {
std::string delay_sigma_attr_name = "ocv_sigma_cell_" + rf->to_string_long(); std::string delay_sigma_attr_name = "ocv_sigma_cell_" + rf->to_string();
TableModelsEarlyLate delay_sigmas = TableModelsEarlyLate delay_sigmas =
readEarlyLateTableModels(timing_group, readEarlyLateTableModels(timing_group,
delay_sigma_attr_name.c_str(), delay_sigma_attr_name.c_str(),
@ -2136,7 +2136,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
time_scale_, time_scale_,
ScaleFactorType::unknown); ScaleFactorType::unknown);
std::string slew_sigma_attr_name = "ocv_sigma_" + rf->to_string_long() std::string slew_sigma_attr_name = "ocv_sigma_" + rf->to_string()
+ "_transition"; + "_transition";
TableModelsEarlyLate slew_sigmas = TableModelsEarlyLate slew_sigmas =
readEarlyLateTableModels(timing_group, readEarlyLateTableModels(timing_group,
@ -2164,7 +2164,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
found_model = true; found_model = true;
} }
else { else {
std::string constraint_attr_name = rf->to_string_long() + "_constraint"; std::string constraint_attr_name = rf->to_string() + "_constraint";
ScaleFactorType scale_factor_type = ScaleFactorType scale_factor_type =
timingTypeScaleFactorType(timing_attrs->timingType()); timingTypeScaleFactorType(timing_attrs->timingType());
TableModel *constraint = readCheckTableModel(timing_group, TableModel *constraint = readCheckTableModel(timing_group,
@ -2172,7 +2172,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
rf, TableTemplateType::delay, rf, TableTemplateType::delay,
time_scale_, scale_factor_type); time_scale_, scale_factor_type);
if (constraint) { if (constraint) {
std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string_long() std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string()
+ "_constraint"; + "_constraint";
TableModelsEarlyLate constraint_sigmas = TableModelsEarlyLate constraint_sigmas =
readEarlyLateTableModels(timing_group, readEarlyLateTableModels(timing_group,
@ -2298,7 +2298,7 @@ LibertyReader::readReceiverCapacitance(const LibertyGroup *timing_group,
ReceiverModelPtr &receiver_model) ReceiverModelPtr &receiver_model)
{ {
std::string cap_group_name1 = cap_group_name; std::string cap_group_name1 = cap_group_name;
cap_group_name1 += "_" + rf->to_string_long(); cap_group_name1 += "_" + rf->to_string();
const LibertyGroup *cap_group = timing_group->findSubgroup(cap_group_name1); const LibertyGroup *cap_group = timing_group->findSubgroup(cap_group_name1);
if (cap_group) { if (cap_group) {
const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment"); const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment");
@ -2328,7 +2328,7 @@ OutputWaveforms *
LibertyReader::readOutputWaveforms(const LibertyGroup *timing_group, LibertyReader::readOutputWaveforms(const LibertyGroup *timing_group,
const RiseFall *rf) const RiseFall *rf)
{ {
const std::string current_group_name = "output_current_" + rf->to_string_long(); const std::string current_group_name = "output_current_" + rf->to_string();
const LibertyGroup *current_group = timing_group->findSubgroup(current_group_name); const LibertyGroup *current_group = timing_group->findSubgroup(current_group_name);
if (current_group) { if (current_group) {
OutputWaveformSeq output_currents; OutputWaveformSeq output_currents;
@ -2680,7 +2680,7 @@ LibertyReader::readInternalPowerGroups(LibertyCell *cell,
InternalPowerModels models; InternalPowerModels models;
// rise/fall_power group // rise/fall_power group
for (const RiseFall *rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
std::string pwr_attr_name = rf->to_string_long() + "_power"; std::string pwr_attr_name = rf->to_string() + "_power";
const LibertyGroup *pwr_group = ipwr_group->findSubgroup(pwr_attr_name); const LibertyGroup *pwr_group = ipwr_group->findSubgroup(pwr_attr_name);
if (pwr_group) { if (pwr_group) {
TableModel *model = readTableModel(pwr_group, rf, TableTemplateType::power, TableModel *model = readTableModel(pwr_group, rf, TableTemplateType::power,
@ -2743,7 +2743,7 @@ LibertyReader::findLibertyPort(LibertyCell *cell,
return nullptr; return nullptr;
} }
StdStringSeq StringSeq
LibertyReader::findAttributStrings(const LibertyGroup *group, LibertyReader::findAttributStrings(const LibertyGroup *group,
const char *name_attr) const char *name_attr)
{ {
@ -2754,7 +2754,7 @@ LibertyReader::findAttributStrings(const LibertyGroup *group,
return parseTokens(*strings, ' '); return parseTokens(*strings, ' ');
} }
} }
return StdStringSeq(); return StringSeq();
} }
LibertyPortSeq LibertyPortSeq
@ -2763,7 +2763,7 @@ LibertyReader::findLibertyPorts(LibertyCell *cell,
const char *port_name_attr) const char *port_name_attr)
{ {
LibertyPortSeq ports; LibertyPortSeq ports;
StdStringSeq port_names = findAttributStrings(group, port_name_attr); StringSeq port_names = findAttributStrings(group, port_name_attr);
for (const std::string &port_name : port_names) { for (const std::string &port_name : port_names) {
LibertyPort *port = findPort(cell, port_name.c_str()); LibertyPort *port = findPort(cell, port_name.c_str());
if (port) if (port)
@ -2915,40 +2915,40 @@ LibertyReader::readStatetable(LibertyCell *cell,
const char *input_ports_arg = statetable_group->firstName(); const char *input_ports_arg = statetable_group->firstName();
const char *internal_ports_arg = statetable_group->params().size() >= 2 const char *internal_ports_arg = statetable_group->params().size() >= 2
? statetable_group->secondName() : nullptr; ? statetable_group->secondName() : nullptr;
StdStringSeq input_ports; StringSeq input_ports;
if (input_ports_arg) if (input_ports_arg)
input_ports = parseTokens(input_ports_arg, ' '); input_ports = parseTokens(input_ports_arg, ' ');
StdStringSeq internal_ports; StringSeq internal_ports;
if (internal_ports_arg) if (internal_ports_arg)
internal_ports = parseTokens(internal_ports_arg, ' '); internal_ports = parseTokens(internal_ports_arg, ' ');
const LibertySimpleAttr *table_attr = statetable_group->findSimpleAttr("table"); const LibertySimpleAttr *table_attr = statetable_group->findSimpleAttr("table");
if (table_attr) { if (table_attr) {
const std::string *table_str = table_attr->stringValue(); const std::string *table_str = table_attr->stringValue();
StdStringSeq table_rows = parseTokens(table_str->c_str(), ','); StringSeq table_rows = parseTokens(table_str->c_str(), ',');
size_t input_count = input_ports.size(); size_t input_count = input_ports.size();
size_t internal_count = internal_ports.size(); size_t internal_count = internal_ports.size();
StatetableRows table; StatetableRows table;
for (const std::string &row : table_rows) { for (const std::string &row : table_rows) {
const StdStringSeq row_groups = parseTokens(row, ':'); const StringSeq row_groups = parseTokens(row, ':');
if (row_groups.size() != 3) { if (row_groups.size() != 3) {
libWarn(1300, table_attr, "table row must have 3 groups separated by ':'."); libWarn(1300, table_attr, "table row must have 3 groups separated by ':'.");
break; break;
} }
StdStringSeq inputs = parseTokens(row_groups[0], ' '); StringSeq inputs = parseTokens(row_groups[0], ' ');
if (inputs.size() != input_count) { if (inputs.size() != input_count) {
libWarn(1301,table_attr,"table row has %zu input values but %zu are required.", libWarn(1301,table_attr,"table row has %zu input values but %zu are required.",
inputs.size(), input_count); inputs.size(), input_count);
break; break;
} }
StdStringSeq currents = parseTokens(row_groups[1], ' '); StringSeq currents = parseTokens(row_groups[1], ' ');
if (currents.size() != internal_count) { if (currents.size() != internal_count) {
libWarn(1302,table_attr, libWarn(1302,table_attr,
"table row has %zu current values but %zu are required.", "table row has %zu current values but %zu are required.",
currents.size(), internal_count); currents.size(), internal_count);
break; break;
} }
StdStringSeq nexts = parseTokens(row_groups[2], ' '); StringSeq nexts = parseTokens(row_groups[2], ' ');
if (nexts.size() != internal_count) { if (nexts.size() != internal_count) {
libWarn(1303, table_attr, "table row has %zu next values but %zu are required.", libWarn(1303, table_attr, "table row has %zu next values but %zu are required.",
nexts.size(), internal_count); nexts.size(), internal_count);
@ -3087,7 +3087,7 @@ static EnumNameMap<StateInternalValue> state_internal_value_name_map =
}; };
StateInputValues StateInputValues
LibertyReader::parseStateInputValues(StdStringSeq &inputs, LibertyReader::parseStateInputValues(StringSeq &inputs,
const LibertySimpleAttr *attr) const LibertySimpleAttr *attr)
{ {
StateInputValues input_values; StateInputValues input_values;
@ -3106,7 +3106,7 @@ LibertyReader::parseStateInputValues(StdStringSeq &inputs,
} }
StateInternalValues StateInternalValues
LibertyReader::parseStateInternalValues(StdStringSeq &states, LibertyReader::parseStateInternalValues(StringSeq &states,
const LibertySimpleAttr *attr) const LibertySimpleAttr *attr)
{ {
StateInternalValues state_values; StateInternalValues state_values;
@ -3458,37 +3458,37 @@ LibertyReader::variableValue(const char *var,
void void
LibertyReader::libWarn(int id, LibertyReader::libWarn(int id,
const LibertyGroup *obj, const LibertyGroup *group,
const char *fmt, const char *fmt,
...) ...) const
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
report_->vfileWarn(id, filename_, obj->line(), fmt, args); report_->vfileWarn(id, filename_, group->line(), fmt, args);
va_end(args); va_end(args);
} }
void void
LibertyReader::libWarn(int id, LibertyReader::libWarn(int id,
const LibertySimpleAttr *obj, const LibertySimpleAttr *attr,
const char *fmt, const char *fmt,
...) ...) const
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
report_->vfileWarn(id, filename_, obj->line(), fmt, args); report_->vfileWarn(id, filename_, attr->line(), fmt, args);
va_end(args); va_end(args);
} }
void void
LibertyReader::libWarn(int id, LibertyReader::libWarn(int id,
const LibertyComplexAttr *obj, const LibertyComplexAttr *attr,
const char *fmt, const char *fmt,
...) ...) const
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
report_->vfileWarn(id, filename_, obj->line(), fmt, args); report_->vfileWarn(id, filename_, attr->line(), fmt, args);
va_end(args); va_end(args);
} }
@ -3496,7 +3496,7 @@ void
LibertyReader::libWarn(int id, LibertyReader::libWarn(int id,
int line, int line,
const char *fmt, const char *fmt,
...) ...) const
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -3506,37 +3506,37 @@ LibertyReader::libWarn(int id,
void void
LibertyReader::libError(int id, LibertyReader::libError(int id,
const LibertyGroup *obj, const LibertyGroup *group,
const char *fmt, const char *fmt,
...) ...) const
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
report_->vfileError(id, filename_, obj->line(), fmt, args); report_->vfileError(id, filename_, group->line(), fmt, args);
va_end(args); va_end(args);
} }
void void
LibertyReader::libError(int id, LibertyReader::libError(int id,
const LibertySimpleAttr *obj, const LibertySimpleAttr *attr,
const char *fmt, const char *fmt,
...) ...) const
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
report_->vfileError(id, filename_, obj->line(), fmt, args); report_->vfileError(id, filename_, attr->line(), fmt, args);
va_end(args); va_end(args);
} }
void void
LibertyReader::libError(int id, LibertyReader::libError(int id,
const LibertyComplexAttr *obj, const LibertyComplexAttr *attr,
const char *fmt, const char *fmt,
...) ...) const
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
report_->vfileError(id, filename_, obj->line(), fmt, args); report_->vfileError(id, filename_, attr->line(), fmt, args);
va_end(args); va_end(args);
} }

View File

@ -24,13 +24,13 @@
#pragma once #pragma once
#include <cstdarg>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <array> #include <array>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include "StringSeq.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "MinMax.hh" #include "MinMax.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
@ -101,7 +101,7 @@ public:
LibertyPort *findPort(LibertyCell *cell, LibertyPort *findPort(LibertyCell *cell,
const char *port_name); const char *port_name);
StdStringSeq findAttributStrings(const LibertyGroup *group, StringSeq findAttributStrings(const LibertyGroup *group,
const char *name_attr); const char *name_attr);
protected: protected:
@ -132,6 +132,7 @@ protected:
const char *group_name, const char *group_name,
TableTemplateType type); TableTemplateType type);
void readThresholds(const LibertyGroup *library_group); void readThresholds(const LibertyGroup *library_group);
void checkThresholds(const LibertyGroup *library_group) const;
TableAxisPtr makeTableTemplateAxis(const LibertyGroup *template_group, TableAxisPtr makeTableTemplateAxis(const LibertyGroup *template_group,
int axis_index); int axis_index);
void readVoltateMaps(const LibertyGroup *library_group); void readVoltateMaps(const LibertyGroup *library_group);
@ -401,9 +402,9 @@ protected:
float defaultCap(LibertyPort *port); float defaultCap(LibertyPort *port);
void visitPorts(std::function<void (LibertyPort *port)> func); void visitPorts(std::function<void (LibertyPort *port)> func);
StateInputValues parseStateInputValues(StdStringSeq &inputs, StateInputValues parseStateInputValues(StringSeq &inputs,
const LibertySimpleAttr *attr); const LibertySimpleAttr *attr);
StateInternalValues parseStateInternalValues(StdStringSeq &states, StateInternalValues parseStateInternalValues(StringSeq &states,
const LibertySimpleAttr *attr); const LibertySimpleAttr *attr);
void getAttrInt(const LibertySimpleAttr *attr, void getAttrInt(const LibertySimpleAttr *attr,
@ -445,36 +446,36 @@ protected:
const LibertyCell *cell, const LibertyCell *cell,
int line); int line);
void libWarn(int id, void libWarn(int id,
const LibertyGroup *obj, const LibertyGroup *group,
const char *fmt, const char *fmt,
...) ...) const
__attribute__((format (printf, 4, 5))); __attribute__((format (printf, 4, 5)));
void libWarn(int id, void libWarn(int id,
const LibertySimpleAttr *obj, const LibertySimpleAttr *attr,
const char *fmt, const char *fmt,
...) ...) const
__attribute__((format (printf, 4, 5))); __attribute__((format (printf, 4, 5)));
void libWarn(int id, void libWarn(int id,
const LibertyComplexAttr *obj, const LibertyComplexAttr *attr,
const char *fmt, const char *fmt,
...) ...) const
__attribute__((format (printf, 4, 5))); __attribute__((format (printf, 4, 5)));
void libWarn(int id, void libWarn(int id,
int line, int line,
const char *fmt, const char *fmt,
...) ...) const
__attribute__((format (printf, 4, 5))); __attribute__((format (printf, 4, 5)));
void libError(int id, void libError(int id,
const LibertyGroup *obj, const LibertyGroup *group,
const char *fmt, ...) const char *fmt, ...) const
__attribute__((format (printf, 4, 5))); __attribute__((format (printf, 4, 5)));
void libError(int id, void libError(int id,
const LibertySimpleAttr *obj, const LibertySimpleAttr *attr,
const char *fmt, ...) const char *fmt, ...) const
__attribute__((format (printf, 4, 5))); __attribute__((format (printf, 4, 5)));
void libError(int id, void libError(int id,
const LibertyComplexAttr *obj, const LibertyComplexAttr *attr,
const char *fmt, ...) const char *fmt, ...) const
__attribute__((format (printf, 4, 5))); __attribute__((format (printf, 4, 5)));
const char *filename_; const char *filename_;
@ -485,7 +486,6 @@ protected:
LibertyBuilder builder_; LibertyBuilder builder_;
LibertyVariableMap var_map_; LibertyVariableMap var_map_;
LibertyLibrary *library_; LibertyLibrary *library_;
bool first_cell_;
LibraryGroupVisitorMap group_begin_map_; LibraryGroupVisitorMap group_begin_map_;
LibraryGroupVisitorMap group_end_map_; LibraryGroupVisitorMap group_end_map_;
@ -516,8 +516,8 @@ public:
LibertyReader *visitor, LibertyReader *visitor,
int line); int line);
~PortNameBitIterator(); ~PortNameBitIterator();
virtual bool hasNext(); bool hasNext() override;
virtual LibertyPort *next(); LibertyPort *next() override;
unsigned size() const { return size_; } unsigned size() const { return size_; }
protected: protected:

View File

@ -62,8 +62,8 @@ class ConcreteInstanceChildIterator : public InstanceChildIterator
{ {
public: public:
ConcreteInstanceChildIterator(ConcreteInstanceChildMap *map); ConcreteInstanceChildIterator(ConcreteInstanceChildMap *map);
bool hasNext(); bool hasNext() override;
Instance *next(); Instance *next() override;
private: private:
ConcreteInstanceChildMap *map_; ConcreteInstanceChildMap *map_;
@ -96,8 +96,8 @@ class ConcreteInstanceNetIterator : public InstanceNetIterator
{ {
public: public:
ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets); ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets);
bool hasNext(); bool hasNext() override;
Net *next(); Net *next() override;
private: private:
void findNext(); void findNext();
@ -152,8 +152,8 @@ class ConcreteInstancePinIterator : public InstancePinIterator
public: public:
ConcreteInstancePinIterator(const ConcreteInstance *inst, ConcreteInstancePinIterator(const ConcreteInstance *inst,
int pin_count); int pin_count);
bool hasNext(); bool hasNext() override;
Pin *next(); Pin *next() override;
private: private:
void findNext(); void findNext();
@ -206,8 +206,8 @@ class ConcreteNetPinIterator : public NetPinIterator
{ {
public: public:
ConcreteNetPinIterator(const ConcreteNet *net); ConcreteNetPinIterator(const ConcreteNet *net);
bool hasNext(); bool hasNext() override;
Pin *next(); Pin *next() override;
private: private:
ConcretePin *next_; ConcretePin *next_;
@ -238,8 +238,8 @@ class ConcreteNetTermIterator : public NetTermIterator
{ {
public: public:
ConcreteNetTermIterator(const ConcreteNet *net); ConcreteNetTermIterator(const ConcreteNet *net);
bool hasNext(); bool hasNext() override;
Term *next(); Term *next() override;
private: private:
ConcreteTerm *next_; ConcreteTerm *next_;
@ -322,8 +322,8 @@ class ConcreteLibraryIterator1 : public Iterator<Library*>
{ {
public: public:
ConcreteLibraryIterator1(const ConcreteLibrarySeq &libs); ConcreteLibraryIterator1(const ConcreteLibrarySeq &libs);
virtual bool hasNext(); bool hasNext() override;
virtual Library *next(); Library *next() override;
private: private:
const ConcreteLibrarySeq &libs_; const ConcreteLibrarySeq &libs_;
@ -361,8 +361,8 @@ class ConcreteLibertyLibraryIterator : public Iterator<LibertyLibrary*>
public: public:
ConcreteLibertyLibraryIterator(const ConcreteNetwork *network); ConcreteLibertyLibraryIterator(const ConcreteNetwork *network);
virtual ~ConcreteLibertyLibraryIterator(); virtual ~ConcreteLibertyLibraryIterator();
virtual bool hasNext(); bool hasNext() override;
virtual LibertyLibrary *next(); LibertyLibrary *next() override;
private: private:
void findNext(); void findNext();
@ -719,8 +719,8 @@ class ConcreteCellPortIterator1 : public CellPortIterator
public: public:
ConcreteCellPortIterator1(const ConcreteCell *cell); ConcreteCellPortIterator1(const ConcreteCell *cell);
~ConcreteCellPortIterator1(); ~ConcreteCellPortIterator1();
virtual bool hasNext() { return iter_->hasNext(); } bool hasNext() override { return iter_->hasNext(); }
virtual Port *next(); Port *next() override;
private: private:
ConcreteCellPortIterator *iter_; ConcreteCellPortIterator *iter_;
@ -756,8 +756,8 @@ class ConcreteCellPortBitIterator1 : public CellPortIterator
public: public:
ConcreteCellPortBitIterator1(const ConcreteCell *cell); ConcreteCellPortBitIterator1(const ConcreteCell *cell);
~ConcreteCellPortBitIterator1(); ~ConcreteCellPortBitIterator1();
virtual bool hasNext() { return iter_->hasNext(); } bool hasNext() override { return iter_->hasNext(); }
virtual Port *next(); Port *next() override;
private: private:
ConcreteCellPortBitIterator *iter_; ConcreteCellPortBitIterator *iter_;
@ -903,8 +903,8 @@ class ConcretePortMemberIterator1 : public PortMemberIterator
public: public:
ConcretePortMemberIterator1(const ConcretePort *port); ConcretePortMemberIterator1(const ConcretePort *port);
~ConcretePortMemberIterator1(); ~ConcretePortMemberIterator1();
virtual bool hasNext(); bool hasNext() override;
virtual Port *next(); Port *next() override;
private: private:
ConcretePortMemberIterator *iter_; ConcretePortMemberIterator *iter_;

View File

@ -1221,8 +1221,8 @@ class LeafInstanceIterator1 : public LeafInstanceIterator
public: public:
LeafInstanceIterator1(const Instance *inst, LeafInstanceIterator1(const Instance *inst,
const Network *network); const Network *network);
bool hasNext() { return next_; } bool hasNext() override { return next_; }
Instance *next(); Instance *next() override;
private: private:
void nextInst(); void nextInst();
@ -1366,8 +1366,8 @@ class ConnectedPinIterator1 : public ConnectedPinIterator
public: public:
ConnectedPinIterator1(PinSet *pins); ConnectedPinIterator1(PinSet *pins);
virtual ~ConnectedPinIterator1(); virtual ~ConnectedPinIterator1();
virtual bool hasNext(); bool hasNext() override;
virtual const Pin *next(); const Pin *next() override;
protected: protected:
PinSet *pins_; PinSet *pins_;

View File

@ -638,13 +638,16 @@ InstancePinIterator *
pin_iterator() { return Sta::sta()->ensureLinked()->pinIterator(self); } pin_iterator() { return Sta::sta()->ensureLinked()->pinIterator(self); }
InstanceNetIterator * InstanceNetIterator *
net_iterator() { return Sta::sta()->ensureLinked()->netIterator(self); } net_iterator() { return Sta::sta()->ensureLinked()->netIterator(self); }
Pin * Pin *
find_pin(const char *name) find_pin(const char *name)
{ {
return Sta::sta()->ensureLinked()->findPin(self, name); return Sta::sta()->ensureLinked()->findPin(self, name);
} }
std::string std::string
get_attribute(const char *key) { get_attribute(const char *key)
{
return Sta::sta()->ensureLinked()->getAttribute(self, key); return Sta::sta()->ensureLinked()->getAttribute(self, key);
} }

View File

@ -311,7 +311,7 @@ reduceToPiElmore(const Parasitic *parasitic_network,
if (drvr_node) { if (drvr_node) {
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s", debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s",
sta->network()->pathName(drvr_pin), sta->network()->pathName(drvr_pin),
rf->to_string().c_str(), rf->shortName(),
min_max->to_string().c_str()); min_max->to_string().c_str());
ReduceToPiElmore reducer(sta); ReduceToPiElmore reducer(sta);
return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node, return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,

View File

@ -27,7 +27,7 @@
#include "Report.hh" #include "Report.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "StringSeq.hh" #include "StringUtil.hh"
#include "parasitics/SpefReaderPvt.hh" #include "parasitics/SpefReaderPvt.hh"
#include "parasitics/SpefScanner.hh" #include "parasitics/SpefScanner.hh"
@ -62,7 +62,7 @@ sta::SpefParse::error(const location_type &loc,
char *string; char *string;
int integer; int integer;
float number; float number;
sta::StringSeq *string_seq; sta::StringSeq *std_string_seq;
sta::PortDirection *port_dir; sta::PortDirection *port_dir;
sta::SpefRspfPi *pi; sta::SpefRspfPi *pi;
sta::SpefTriple *triple; sta::SpefTriple *triple;
@ -105,7 +105,7 @@ sta::SpefParse::error(const location_type &loc,
%type <ch> hchar suffix_bus_delim prefix_bus_delim %type <ch> hchar suffix_bus_delim prefix_bus_delim
%type <string_seq> qstrings %type <std_string_seq> qstrings
%type<port_dir> direction %type<port_dir> direction
%type<triple> par_value total_cap %type<triple> par_value total_cap
@ -222,9 +222,12 @@ qstrings:
QSTRING QSTRING
{ $$ = new sta::StringSeq; { $$ = new sta::StringSeq;
$$->push_back($1); $$->push_back($1);
sta::stringDelete($1);
} }
| qstrings QSTRING | qstrings QSTRING
{ $$->push_back($2); } { $$->push_back($2);
sta::stringDelete($2);
}
; ;
hierarchy_div_def: hierarchy_div_def:

View File

@ -92,7 +92,6 @@ SpefReader::SpefReader(const std::string &filename,
cap_scale_(1.0), cap_scale_(1.0),
res_scale_(1.0), res_scale_(1.0),
induct_scale_(1.0), induct_scale_(1.0),
design_flow_(nullptr),
parasitics_(parasitics), parasitics_(parasitics),
parasitic_(nullptr) parasitic_(nullptr)
{ {
@ -101,11 +100,6 @@ SpefReader::SpefReader(const std::string &filename,
SpefReader::~SpefReader() SpefReader::~SpefReader()
{ {
if (design_flow_) {
deleteContents(design_flow_);
delete design_flow_;
design_flow_ = nullptr;
}
} }
bool bool
@ -299,7 +293,8 @@ SpefReader::portDirection(char *spef_dir)
void void
SpefReader::setDesignFlow(StringSeq *flow) SpefReader::setDesignFlow(StringSeq *flow)
{ {
design_flow_ = flow; design_flow_ = std::move(*flow);
delete flow;
} }
Pin * Pin *

View File

@ -27,7 +27,7 @@
#include <map> #include <map>
#include "Zlib.hh" #include "Zlib.hh"
#include "StringSeq.hh" #include "StringUtil.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "ParasiticsClass.hh" #include "ParasiticsClass.hh"
#include "StaState.hh" #include "StaState.hh"
@ -139,7 +139,7 @@ private:
float res_scale_; float res_scale_;
float induct_scale_; float induct_scale_;
SpefNameMap name_map_; SpefNameMap name_map_;
StringSeq *design_flow_; StringSeq design_flow_;
Parasitics *parasitics_; Parasitics *parasitics_;
Parasitic *parasitic_; Parasitic *parasitic_;
}; };

View File

@ -86,7 +86,6 @@ static EnumNameMap<PwrActivityOrigin> pwr_activity_origin_map =
{PwrActivityOrigin::propagated, "propagated"}, {PwrActivityOrigin::propagated, "propagated"},
{PwrActivityOrigin::clock, "clock"}, {PwrActivityOrigin::clock, "clock"},
{PwrActivityOrigin::constant, "constant"}, {PwrActivityOrigin::constant, "constant"},
{PwrActivityOrigin::defaulted, "defaulted"},
{PwrActivityOrigin::unknown, "unknown"}}; {PwrActivityOrigin::unknown, "unknown"}};
Power::Power(StaState *sta) : Power::Power(StaState *sta) :

View File

@ -531,7 +531,7 @@ ClockEdge::ClockEdge(Clock *clock,
const RiseFall *rf) : const RiseFall *rf) :
clock_(clock), clock_(clock),
rf_(rf), rf_(rf),
name_(stringPrint("%s %s", clock_->name(), rf_->to_string().c_str())), name_(stringPrint("%s %s", clock_->name(), rf_->shortName())),
time_(0.0), time_(0.0),
index_(clock_->index() * RiseFall::index_count + rf_->index()) index_(clock_->index() * RiseFall::index_count + rf_->index())
{ {

View File

@ -96,18 +96,15 @@ DisabledPorts::setDisabledFromTo(LibertyPort *from,
{ {
if (from_to_ == nullptr) if (from_to_ == nullptr)
from_to_ = new LibertyPortPairSet; from_to_ = new LibertyPortPairSet;
LibertyPortPair pair(from, to); from_to_->insert({from, to});
from_to_->insert(pair);
} }
void void
DisabledPorts::removeDisabledFromTo(LibertyPort *from, DisabledPorts::removeDisabledFromTo(LibertyPort *from,
LibertyPort *to) LibertyPort *to)
{ {
if (from_to_) { if (from_to_)
LibertyPortPair from_to(from, to); from_to_->erase({from, to});
from_to_->erase(from_to);
}
} }
bool bool
@ -115,12 +112,11 @@ DisabledPorts::isDisabled(LibertyPort *from,
LibertyPort *to, LibertyPort *to,
const TimingRole *role) const TimingRole *role)
{ {
LibertyPortPair from_to(from, to);
// set_disable_timing instance does not disable timing checks. // set_disable_timing instance does not disable timing checks.
return (all_ && !role->isTimingCheck()) return (all_ && !role->isTimingCheck())
|| (from_ && from_->contains(from)) || (from_ && from_->contains(from))
|| (to_ && to_->contains(to)) || (to_ && to_->contains(to))
|| (from_to_ && from_to_->contains(from_to)); || (from_to_ && from_to_->contains({from, to}));
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -2427,8 +2427,7 @@ void
InsertPinPairsThru::visit(const Pin *drvr, InsertPinPairsThru::visit(const Pin *drvr,
const Pin *load) const Pin *load)
{ {
PinPair pair(drvr, load); pairs_->insert({drvr, load});
pairs_->insert(pair);
} }
static void static void
@ -2475,8 +2474,7 @@ void
DeletePinPairsThru::visit(const Pin *drvr, DeletePinPairsThru::visit(const Pin *drvr,
const Pin *load) const Pin *load)
{ {
PinPair pair(drvr, load); pairs_->erase({drvr, load});
pairs_->erase(pair);
} }
static void static void

View File

@ -101,6 +101,7 @@ Sdc::Sdc(Mode *mode,
clk_hpin_disables_(network_), clk_hpin_disables_(network_),
propagated_clk_pins_(network_), propagated_clk_pins_(network_),
clk_latencies_(network_), clk_latencies_(network_),
clk_latency_pins_(network_),
edge_clk_latency_map_(network_), edge_clk_latency_map_(network_),
clk_insertions_(network_), clk_insertions_(network_),
clk_sense_map_(network_), clk_sense_map_(network_),
@ -169,6 +170,7 @@ Sdc::clear()
clock_pin_map_.clear(); clock_pin_map_.clear();
clock_leaf_pin_map_.clear(); clock_leaf_pin_map_.clear();
clk_latencies_.clear(); clk_latencies_.clear();
clk_latency_pins_.clear();
edge_clk_latency_map_.clear(); edge_clk_latency_map_.clear();
clk_insertions_.clear(); clk_insertions_.clear();
@ -1344,8 +1346,7 @@ bool
FindClkHpinDisables::drvrLoadExists(const Pin *drvr, FindClkHpinDisables::drvrLoadExists(const Pin *drvr,
const Pin *load) const Pin *load)
{ {
PinPair probe(drvr, load); return drvr_loads_.contains({drvr, load});
return drvr_loads_.contains(probe);
} }
void void
@ -1508,6 +1509,8 @@ Sdc::setClockLatency(Clock *clk,
} }
} }
latency->setDelay(rf, min_max, delay); latency->setDelay(rf, min_max, delay);
if (pin)
clk_latency_pins_.insert(pin);
// set_clock_latency removes set_propagated_clock on the same object. // set_clock_latency removes set_propagated_clock on the same object.
if (clk && pin == nullptr) if (clk && pin == nullptr)
@ -1580,8 +1583,7 @@ Sdc::deleteClockLatenciesReferencing(Clock *clk)
bool bool
Sdc::hasClockLatency(const Pin *pin) const Sdc::hasClockLatency(const Pin *pin) const
{ {
ClockLatency probe(nullptr, pin); return clk_latency_pins_.contains(pin);
return clk_latencies_.contains(&probe);
} }
void void
@ -3503,24 +3505,21 @@ void
Sdc::disableWire(const Pin *from, Sdc::disableWire(const Pin *from,
const Pin *to) const Pin *to)
{ {
PinPair pair(from, to); disabled_wire_edges_.insert({from, to});
disabled_wire_edges_.insert(pair);
} }
void void
Sdc::removeDisableWire(Pin *from, Sdc::removeDisableWire(Pin *from,
Pin *to) Pin *to)
{ {
PinPair probe(from, to); disabled_wire_edges_.erase({from, to});
disabled_wire_edges_.erase(probe);
} }
bool bool
Sdc::isDisabledWire(const Pin *from, Sdc::isDisabledWire(const Pin *from,
const Pin *to) const const Pin *to) const
{ {
PinPair pair(from, to); return disabled_wire_edges_.contains({from, to});
return disabled_wire_edges_.contains(pair);
} }
void void
@ -3580,8 +3579,7 @@ void
DisableEdgesThruHierPin::visit(const Pin *drvr, DisableEdgesThruHierPin::visit(const Pin *drvr,
const Pin *load) const Pin *load)
{ {
PinPair pair(drvr, load); pairs_->insert({drvr, load});
pairs_->insert(pair);
} }
void void
@ -3622,8 +3620,7 @@ void
RemoveDisableEdgesThruHierPin::visit(const Pin *drvr, RemoveDisableEdgesThruHierPin::visit(const Pin *drvr,
const Pin *load) const Pin *load)
{ {
PinPair pair(drvr, load); pairs_->erase({drvr, load});
pairs_->erase(pair);
} }
void void
@ -3656,8 +3653,7 @@ Sdc::isDisabled(const Instance *inst,
{ {
if (role == TimingRole::wire()) { if (role == TimingRole::wire()) {
// Hierarchical thru pin disables. // Hierarchical thru pin disables.
PinPair pair(from_pin, to_pin); return disabled_wire_edges_.contains({from_pin, to_pin});
return disabled_wire_edges_.contains(pair);
} }
else { else {
LibertyCell *cell = network_->libertyCell(inst); LibertyCell *cell = network_->libertyCell(inst);

View File

@ -1654,6 +1654,14 @@ set_propagate_all_clocks(bool prop)
Sta::sta()->setPropagateAllClocks(prop); Sta::sta()->setPropagateAllClocks(prop);
} }
bool
pin_is_constrained(const Pin *pin)
{
Sta *sta = Sta::sta();
Sdc *sdc = sta->cmdSdc();
return sdc->isConstrained(pin);
}
%} // inline %} // inline
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,6 @@
#include "CheckTiming.hh" #include "CheckTiming.hh"
#include "ContainerHelpers.hh"
#include "Error.hh" #include "Error.hh"
#include "TimingRole.hh" #include "TimingRole.hh"
#include "Network.hh" #include "Network.hh"
@ -64,7 +63,6 @@ void
CheckTiming::deleteErrors() CheckTiming::deleteErrors()
{ {
for (CheckError *error : errors_) { for (CheckError *error : errors_) {
deleteContents(error);
delete error; delete error;
} }
} }
@ -204,25 +202,23 @@ CheckTiming::checkLoops()
errorMsgSubst("Warning: There %is %d combinational loop%s in the design.", errorMsgSubst("Warning: There %is %d combinational loop%s in the design.",
loop_count, error_msg); loop_count, error_msg);
CheckError *error = new CheckError; CheckError *error = new CheckError;
error->push_back(stringCopy(error_msg.c_str())); error->push_back(error_msg);
for (GraphLoop *loop : loops) { for (GraphLoop *loop : loops) {
if (loop->isCombinational()) { if (loop->isCombinational()) {
Edge *last_edge = nullptr; Edge *last_edge = nullptr;
for (Edge *edge : *loop->edges()) { for (Edge *edge : *loop->edges()) {
Pin *pin = edge->from(graph_)->pin(); Pin *pin = edge->from(graph_)->pin();
const char *pin_name = stringCopy(sdc_network_->pathName(pin)); error->push_back(sdc_network_->pathName(pin));
error->push_back(pin_name);
last_edge = edge; last_edge = edge;
} }
if (last_edge) { if (last_edge) {
error->push_back(stringCopy("| loop cut point")); error->push_back("| loop cut point");
const Pin *pin = last_edge->to(graph_)->pin(); const Pin *pin = last_edge->to(graph_)->pin();
const char *pin_name = stringCopy(sdc_network_->pathName(pin)); error->push_back(sdc_network_->pathName(pin));
error->push_back(pin_name);
// Separator between loops. // Separator between loops.
error->push_back(stringCopy("--------------------------------")); error->push_back("--------------------------------");
} }
} }
} }
@ -362,15 +358,12 @@ CheckTiming::pushPinErrors(const char *msg,
CheckError *error = new CheckError; CheckError *error = new CheckError;
std::string error_msg; std::string error_msg;
errorMsgSubst(msg, pins.size(), error_msg); errorMsgSubst(msg, pins.size(), error_msg);
// Copy the error strings because the error deletes them when it error->push_back(error_msg);
// is deleted.
error->push_back(stringCopy(error_msg.c_str()));
// Sort the error pins so the output is independent of the order // Sort the error pins so the output is independent of the order
// the the errors are discovered. // the the errors are discovered.
PinSeq pins1 = sortByPathName(&pins, network_); PinSeq pins1 = sortByPathName(&pins, network_);
for (const Pin *pin : pins1) { for (const Pin *pin : pins1) {
const char *pin_name = stringCopy(sdc_network_->pathName(pin)); error->push_back(sdc_network_->pathName(pin));
error->push_back(pin_name);
} }
errors_.push_back(error); errors_.push_back(error);
} }
@ -384,15 +377,12 @@ CheckTiming::pushClkErrors(const char *msg,
CheckError *error = new CheckError; CheckError *error = new CheckError;
std::string error_msg; std::string error_msg;
errorMsgSubst(msg, clks.size(), error_msg); errorMsgSubst(msg, clks.size(), error_msg);
// Copy the error strings because the error deletes them when it error->push_back(error_msg);
// is deleted.
error->push_back(stringCopy(error_msg.c_str()));
// Sort the error clks so the output is independent of the order // Sort the error clks so the output is independent of the order
// the the errors are discovered. // the the errors are discovered.
ClockSeq clks1 = sortByName(&clks); ClockSeq clks1 = sortByName(&clks);
for (const Clock *clk : clks1) { for (const Clock *clk : clks1) {
const char *clk_name = stringCopy(clk->name()); error->push_back(clk->name());
error->push_back(clk_name);
} }
errors_.push_back(error); errors_.push_back(error);
} }

View File

@ -26,7 +26,7 @@
#include <vector> #include <vector>
#include "StringSeq.hh" #include "StringUtil.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "GraphClass.hh" #include "GraphClass.hh"
#include "SdcClass.hh" #include "SdcClass.hh"

View File

@ -106,7 +106,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
report_->reportLine("%7s source latency %s %s", report_->reportLine("%7s source latency %s %s",
time_unit->asString(src_latency, digits), time_unit->asString(src_latency, digits),
sdc_network_->pathName(src_path->pin(this)), sdc_network_->pathName(src_path->pin(this)),
src_path->transition(this)->to_string().c_str()); src_path->transition(this)->shortName());
if (src_internal_clk_latency != 0.0) if (src_internal_clk_latency != 0.0)
report_->reportLine("%7s source internal clock delay", report_->reportLine("%7s source internal clock delay",
time_unit->asString(src_internal_clk_latency, digits)); time_unit->asString(src_internal_clk_latency, digits));
@ -116,7 +116,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
report_->reportLine("%7s target latency %s %s", report_->reportLine("%7s target latency %s %s",
time_unit->asString(-tgt_latency, digits), time_unit->asString(-tgt_latency, digits),
sdc_network_->pathName(tgt_path->pin(this)), sdc_network_->pathName(tgt_path->pin(this)),
tgt_path->transition(this)->to_string().c_str()); tgt_path->transition(this)->shortName());
if (tgt_internal_clk_latency != 0.0) if (tgt_internal_clk_latency != 0.0)
report_->reportLine("%7s target internal clock delay", report_->reportLine("%7s target internal clock delay",
time_unit->asString(-tgt_internal_clk_latency, digits)); time_unit->asString(-tgt_internal_clk_latency, digits));
@ -315,10 +315,10 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
debugPrint(debug_, "clk_skew", 2, debugPrint(debug_, "clk_skew", 2,
"%s %s %s -> %s %s %s crpr = %s skew = %s", "%s %s %s -> %s %s %s crpr = %s skew = %s",
network_->pathName(src_path->pin(this)), network_->pathName(src_path->pin(this)),
src_path->transition(this)->to_string().c_str(), src_path->transition(this)->shortName(),
time_unit->asString(probe.srcLatency(this)), time_unit->asString(probe.srcLatency(this)),
network_->pathName(tgt_path->pin(this)), network_->pathName(tgt_path->pin(this)),
tgt_path->transition(this)->to_string().c_str(), tgt_path->transition(this)->shortName(),
time_unit->asString(probe.tgtLatency(this)), time_unit->asString(probe.tgtLatency(this)),
delayAsString(probe.crpr(this), this), delayAsString(probe.crpr(this), this),
time_unit->asString(probe.skew())); time_unit->asString(probe.skew()));

View File

@ -878,7 +878,7 @@ Genclks::recordSrcPaths(Clock *gclk)
debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s", debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s",
network_->pathName(gclk_pin), network_->pathName(gclk_pin),
early_late->to_string().c_str(), early_late->to_string().c_str(),
rf->to_string().c_str(), rf->shortName(),
delayAsString(path->arrival(), this)); delayAsString(path->arrival(), this));
src_path = *path; src_path = *path;
} }

View File

@ -323,6 +323,10 @@ Latches::latchOutArrival(const Path *data_path,
ArcDelay &arc_delay, ArcDelay &arc_delay,
Arrival &q_arrival) Arrival &q_arrival)
{ {
q_tag = nullptr;
arc_delay = 0.0;
q_arrival = 0.0;
Scene *scene = data_path->scene(this); Scene *scene = data_path->scene(this);
Sdc *sdc = scene->sdc(); Sdc *sdc = scene->sdc();
const Mode *mode = scene->mode(); const Mode *mode = scene->mode();
@ -337,83 +341,110 @@ Latches::latchOutArrival(const Path *data_path,
// Latch enable may be missing if library is malformed. // Latch enable may be missing if library is malformed.
switch (state) { switch (state) {
case LatchEnableState::closed: case LatchEnableState::closed:
// Latch is disabled by constant enable. // Latch is always closed because enable is constant.
break; break;
case LatchEnableState::open: { case LatchEnableState::open: {
// Latch is always open because enable is constant.
ExceptionPath *excpt = exceptionTo(data_path, nullptr); ExceptionPath *excpt = exceptionTo(data_path, nullptr);
if (!(excpt && excpt->isFalse())) { if (!(excpt && excpt->isFalse())) {
arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge, arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge,
false, min_max, dcalc_ap, sdc); false, min_max, dcalc_ap, sdc);
q_arrival = data_path->arrival() + arc_delay; q_arrival = data_path->arrival() + arc_delay;
q_tag = data_path->tag(this); // Copy the data tag but remove the drprClkPath.
// Levelization does not traverse latch D->Q edges, so in some cases
// level(Q) < level(D)
// Note that
// level(crprClkPath(data)) < level(D)
// The danger is that
// level(crprClkPath(data)) == level(Q)
// or some other downstream vertex.
// This can lead to data races when finding arrivals at the same level
// use multiple threads.
// Kill the crprClklPath to be safe.
const ClkInfo *data_clk_info = data_path->clkInfo(this);
const ClkInfo *q_clk_info =
search_->findClkInfo(scene,
data_clk_info->clkEdge(),
data_clk_info->clkSrc(),
data_clk_info->isPropagated(),
data_clk_info->genClkSrc(),
data_clk_info->isGenClkSrcPath(),
data_clk_info->pulseClkSense(),
data_clk_info->insertion(),
data_clk_info->latency(),
data_clk_info->uncertainties(),
min_max, nullptr);
q_tag = search_->findTag(scene, d_q_arc->toEdge()->asRiseFall(),
min_max, q_clk_info, false,
nullptr, false, data_path->tag(this)->states(),
false, nullptr);
} }
}
break; break;
}
case LatchEnableState::enabled: { case LatchEnableState::enabled: {
const MinMax *tgt_min_max = data_path->tgtClkMinMax(this); const MinMax *tgt_min_max = data_path->tgtClkMinMax(this);
VertexPathIterator enable_iter(enable_vertex, scene, tgt_min_max, VertexPathIterator enable_iter(enable_vertex, scene, tgt_min_max,
enable_rf, this); enable_rf, this);
while (enable_iter.hasNext()) { while (enable_iter.hasNext()) {
Path *enable_path = enable_iter.next(); Path *enable_path = enable_iter.next();
const 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(); const ClockEdge *en_clk_edge = en_clk_info->clkEdge();
if (enable_path->isClock(this)) { if (enable_path->isClock(this)) {
ExceptionPath *excpt = exceptionTo(data_path, en_clk_edge); ExceptionPath *excpt = exceptionTo(data_path, en_clk_edge);
// D->Q is disabled when if there is a path delay -to D or EN clk. // D->Q is disabled when if there is a path delay -to D or EN clk.
if (!(excpt && (excpt->isFalse() if (!(excpt && (excpt->isFalse()
|| excpt->isPathDelay()))) { || excpt->isPathDelay()))) {
Path *disable_path = latchEnableOtherPath(enable_path); Path *disable_path = latchEnableOtherPath(enable_path);
Delay borrow, time_given_to_startpoint; Delay borrow, time_given_to_startpoint;
Arrival adjusted_data_arrival; Arrival adjusted_data_arrival;
Required required; Required required;
latchRequired(data_path, enable_path, disable_path, latchRequired(data_path, enable_path, disable_path,
required, borrow, adjusted_data_arrival, required, borrow, adjusted_data_arrival,
time_given_to_startpoint); time_given_to_startpoint);
if (delayGreater(borrow, 0.0, this)) { if (delayGreater(borrow, 0.0, this)) {
// Latch is transparent when data arrives. // Latch is transparent when data arrives.
arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge, arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge,
false, min_max, dcalc_ap, sdc); false, min_max, dcalc_ap, sdc);
q_arrival = adjusted_data_arrival + arc_delay; q_arrival = adjusted_data_arrival + arc_delay;
// Tag switcheroo - data passing thru gets latch enable tag. // Tag switcheroo - data passing thru gets latch enable tag.
// States and path ap come from Q, everything else from enable. // States and path ap come from Q, everything else from enable.
Path *crpr_clk_path = crprActive(mode) ? enable_path : nullptr; Path *crpr_clk_path = crprActive(mode) ? enable_path : nullptr;
const ClkInfo *q_clk_info = const ClkInfo *q_clk_info =
search_->findClkInfo(en_clk_info->scene(), search_->findClkInfo(scene,
en_clk_edge, en_clk_edge,
en_clk_info->clkSrc(), en_clk_info->clkSrc(),
en_clk_info->isPropagated(), en_clk_info->isPropagated(),
en_clk_info->genClkSrc(), en_clk_info->genClkSrc(),
en_clk_info->isGenClkSrcPath(), en_clk_info->isGenClkSrcPath(),
en_clk_info->pulseClkSense(), en_clk_info->pulseClkSense(),
en_clk_info->insertion(), en_clk_info->insertion(),
en_clk_info->latency(), en_clk_info->latency(),
en_clk_info->uncertainties(), en_clk_info->uncertainties(),
min_max, crpr_clk_path); min_max, crpr_clk_path);
const RiseFall *q_rf = d_q_arc->toEdge()->asRiseFall(); ExceptionStateSet *states = nullptr;
ExceptionStateSet *states = nullptr; // Latch data pin is a valid exception -from pin.
// Latch data pin is a valid exception -from pin. if (sdc->exceptionFromStates(data_path->pin(this),
if (sdc->exceptionFromStates(data_path->pin(this), data_path->transition(this),
data_path->transition(this), nullptr, nullptr, // clk below
nullptr, nullptr, // clk below MinMax::max(), states)
MinMax::max(), states) // -from enable non-filter exceptions apply.
// -from enable non-filter exceptions apply. && sdc->exceptionFromStates(enable_vertex->pin(),
&& sdc->exceptionFromStates(enable_vertex->pin(), enable_rf,
enable_rf, en_clk_edge->clock(),
en_clk_edge->clock(), en_clk_edge->transition(),
en_clk_edge->transition(), MinMax::max(), false, states))
MinMax::max(), false, states)) q_tag = search_->findTag(scene, d_q_arc->toEdge()->asRiseFall(),
q_tag = search_->findTag(enable_path->tag(this)->scene(), MinMax::max(), q_clk_info, false,
q_rf, MinMax::max(), q_clk_info, false, nullptr, false, states, true, nullptr);
nullptr, false, states, true, nullptr); }
} return;
return; }
} }
}
} }
// No enable path found. // No enable path found.
}
break; break;
} }
}
} }
ExceptionPath * ExceptionPath *

View File

@ -105,7 +105,7 @@ Mode::makePathGroups(int group_path_count,
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
StdStringSeq &group_names, StringSeq &group_names,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,

View File

@ -201,7 +201,7 @@ Path::to_string(const StaState *sta) const
else else
return stringPrintTmp("%s %s %s/%s %d", return stringPrintTmp("%s %s %s/%s %d",
vertex(sta)->to_string(sta).c_str(), vertex(sta)->to_string(sta).c_str(),
transition(sta)->to_string().c_str(), transition(sta)->shortName(),
scene(sta)->name().c_str(), scene(sta)->name().c_str(),
minMax(sta)->to_string().c_str(), minMax(sta)->to_string().c_str(),
tagIndex(sta)); tagIndex(sta));

View File

@ -2030,32 +2030,22 @@ PathEndPathDelay::exceptPathCmp(const PathEnd *path_end,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathEndLess::PathEndLess(const StaState *sta) :
sta_(sta)
{
}
bool
PathEndLess::operator()(const PathEnd *path_end1,
const PathEnd *path_end2) const
{
return PathEnd::less(path_end1, path_end2, sta_);
}
bool bool
PathEnd::less(const PathEnd *path_end1, PathEnd::less(const PathEnd *path_end1,
const PathEnd *path_end2, const PathEnd *path_end2,
bool cmp_slack,
const StaState *sta) const StaState *sta)
{ {
return cmp(path_end1, path_end2, sta) < 0; return cmp(path_end1, path_end2, cmp_slack, sta) < 0;
} }
int int
PathEnd::cmp(const PathEnd *path_end1, PathEnd::cmp(const PathEnd *path_end1,
const PathEnd *path_end2, const PathEnd *path_end2,
bool cmp_slack,
const StaState *sta) const StaState *sta)
{ {
int cmp = path_end1->isUnconstrained() int cmp = !cmp_slack || path_end1->isUnconstrained()
? -cmpArrival(path_end1, path_end2, sta) ? -cmpArrival(path_end1, path_end2, sta)
: cmpSlack(path_end1, path_end2, sta); : cmpSlack(path_end1, path_end2, sta);
if (cmp == 0) { if (cmp == 0) {
@ -2139,7 +2129,25 @@ PathEnd::cmpNoCrpr(const PathEnd *path_end1,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathEndSlackLess::PathEndSlackLess(const StaState *sta) : PathEndLess::PathEndLess(bool cmp_slack,
const StaState *sta) :
cmp_slack_(cmp_slack),
sta_(sta)
{
}
bool
PathEndLess::operator()(const PathEnd *path_end1,
const PathEnd *path_end2) const
{
return PathEnd::less(path_end1, path_end2, cmp_slack_, sta_);
}
////////////////////////////////////////////////////////////////
PathEndSlackLess::PathEndSlackLess(bool cmp_slack,
const StaState *sta) :
cmp_slack_(cmp_slack),
sta_(sta) sta_(sta)
{ {
} }

View File

@ -91,7 +91,7 @@ DiversionGreater::operator()(Diversion *div1,
{ {
PathEnd *path_end1 = div1->pathEnd(); PathEnd *path_end1 = div1->pathEnd();
PathEnd *path_end2 = div2->pathEnd(); PathEnd *path_end2 = div2->pathEnd();
return PathEnd::cmp(path_end1, path_end2, sta_) > 0; return PathEnd::cmp(path_end1, path_end2, true, sta_) > 0;
} }
static void static void
@ -426,7 +426,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s", debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
from_path->to_string(this).c_str(), from_path->to_string(this).c_str(),
to_vertex->to_string(this).c_str(), to_vertex->to_string(this).c_str(),
to_rf->to_string().c_str(), to_rf->shortName(),
delayAsString(search_->deratedDelay(from_vertex, arc, edge, delayAsString(search_->deratedDelay(from_vertex, arc, edge,
false, from_path->minMax(this), false, from_path->minMax(this),
from_path->dcalcAnalysisPtIndex(this), from_path->dcalcAnalysisPtIndex(this),

View File

@ -68,8 +68,8 @@ public:
// Insert path ends that are enumerated in slack/arrival order. // Insert path ends that are enumerated in slack/arrival order.
void insert(PathEnd *path_end); void insert(PathEnd *path_end);
virtual ~PathEnum(); virtual ~PathEnum();
virtual bool hasNext(); bool hasNext() override;
virtual PathEnd *next(); PathEnd *next() override;
private: private:
void makeDiversions(PathEnd *path_end, void makeDiversions(PathEnd *path_end,

View File

@ -50,7 +50,7 @@
namespace sta { namespace sta {
size_t PathGroup::group_path_count_max = std::numeric_limits<size_t>::max(); int PathGroup::group_path_count_max = std::numeric_limits<int>::max();
PathGroup * PathGroup *
PathGroup::makePathGroupSlack(const char *name, PathGroup::makePathGroupSlack(const char *name,
@ -82,8 +82,8 @@ PathGroup::makePathGroupArrival(const char *name,
} }
PathGroup::PathGroup(const char *name, PathGroup::PathGroup(const char *name,
size_t group_path_count, int group_path_count,
size_t endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
@ -99,43 +99,36 @@ PathGroup::PathGroup(const char *name,
slack_min_(slack_min), slack_min_(slack_min),
slack_max_(slack_max), slack_max_(slack_max),
min_max_(min_max), min_max_(min_max),
compare_slack_(cmp_slack), cmp_slack_(cmp_slack),
threshold_(min_max->initValue()), heap_(group_path_count, PathEndLess(cmp_slack, sta)),
sta_(sta) sta_(sta)
{ {
} }
PathGroup::~PathGroup() PathEndSeq
PathGroup::pathEnds() const
{ {
deleteContents(path_ends_); return heap_.contents();
} }
bool bool
PathGroup::saveable(PathEnd *path_end) PathGroup::saveable(PathEnd *path_end)
{ {
float threshold; if (cmp_slack_) {
{
LockGuard lock(lock_);
threshold = threshold_;
}
if (compare_slack_) {
// Crpr increases the slack, so check the slack // Crpr increases the slack, so check the slack
// without crpr first because it is expensive to find. // without crpr first because it is expensive to find.
Slack slack = path_end->slackNoCrpr(sta_); Slack slack = path_end->slackNoCrpr(sta_);
if (!delayIsInitValue(slack, min_max_) if (!delayIsInitValue(slack, min_max_)
&& delayLessEqual(slack, threshold, sta_)
&& delayLessEqual(slack, slack_max_, sta_)) { && delayLessEqual(slack, slack_max_, sta_)) {
// Now check with crpr. // Now check with crpr.
slack = path_end->slack(sta_); slack = path_end->slack(sta_);
return delayLessEqual(slack, threshold, sta_) return delayLessEqual(slack, slack_max_, sta_)
&& delayLessEqual(slack, slack_max_, sta_)
&& delayGreaterEqual(slack, slack_min_, sta_); && delayGreaterEqual(slack, slack_min_, sta_);
} }
} }
else { else {
const Arrival &arrival = path_end->dataArrivalTime(sta_); const Arrival &arrival = path_end->dataArrivalTime(sta_);
return !delayIsInitValue(arrival, min_max_) return !delayIsInitValue(arrival, min_max_);
&& delayGreaterEqual(arrival, threshold, min_max_, sta_);
} }
return false; return false;
} }
@ -148,7 +141,7 @@ PathGroup::saveable(PathEnd *path_end)
bool bool
PathGroup::enumMinSlackUnderMin(PathEnd *path_end) PathGroup::enumMinSlackUnderMin(PathEnd *path_end)
{ {
if (compare_slack_ if (cmp_slack_
&& endpoint_path_count_ > 1 && endpoint_path_count_ > 1
&& slack_min_ > -INF) { && slack_min_ > -INF) {
const Path *path = path_end->path(); const Path *path = path_end->path();
@ -177,72 +170,28 @@ void
PathGroup::insert(PathEnd *path_end) PathGroup::insert(PathEnd *path_end)
{ {
LockGuard lock(lock_); LockGuard lock(lock_);
path_ends_.push_back(path_end); heap_.insert(path_end);
path_end->setPathGroup(this); path_end->setPathGroup(this);
if (group_path_count_ != group_path_count_max
&& path_ends_.size() > group_path_count_ * 2)
prune();
}
void
PathGroup::prune()
{
sort();
VertexPathCountMap path_counts;
size_t end_count = 0;
for (unsigned i = 0; i < path_ends_.size(); i++) {
PathEnd *path_end = path_ends_[i];
Vertex *vertex = path_end->vertex(sta_);
// Squish up to endpoint_path_count path ends per vertex
// up to the front of path_ends_.
if (end_count < group_path_count_
&& path_counts[vertex] < endpoint_path_count_) {
path_ends_[end_count++] = path_end;
path_counts[vertex]++;
}
else
delete path_end;
}
path_ends_.resize(end_count);
// Set a threshold to the bottom of the sorted list that future
// inserts need to beat.
PathEnd *last_end = path_ends_[end_count - 1];
if (compare_slack_)
threshold_ = delayAsFloat(last_end->slack(sta_));
else
threshold_ = delayAsFloat(last_end->dataArrivalTime(sta_));
} }
void void
PathGroup::pushEnds(PathEndSeq &path_ends) PathGroup::pushEnds(PathEndSeq &path_ends)
{ {
ensureSortedMaxPaths(); if (!heap_.empty()) {
for (PathEnd *path_end : path_ends_) PathEndSeq ends = heap_.extract();
path_ends.push_back(path_end); path_ends.reserve(path_ends.size() + ends.size());
} // Append heap path ends to path_ends.
path_ends.insert(path_ends.end(),
void std::make_move_iterator(ends.begin()),
PathGroup::ensureSortedMaxPaths() std::make_move_iterator(ends.end()));
{ }
if (path_ends_.size() > group_path_count_)
prune();
else
sort();
}
void
PathGroup::sort()
{
sta::sort(path_ends_, PathEndLess(sta_));
} }
void void
PathGroup::clear() PathGroup::clear()
{ {
LockGuard lock(lock_); LockGuard lock(lock_);
threshold_ = min_max_->initValue(); heap_.clear();
path_ends_.clear();
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -258,7 +207,7 @@ PathGroups::PathGroups(int group_path_count,
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
StdStringSeq &group_names, StringSeq &group_names,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,
@ -276,7 +225,7 @@ PathGroups::PathGroups(int group_path_count,
slack_min_(slack_min), slack_min_(slack_min),
slack_max_(slack_max) slack_max_(slack_max)
{ {
StdStringSet groups; StringSet groups;
for (std::string &group_name : group_names) for (std::string &group_name : group_names)
groups.insert(group_name); groups.insert(group_name);
@ -297,7 +246,7 @@ PathGroups::makeGroups(int group_path_count,
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
StdStringSet &group_names, StringSet &group_names,
bool setup_hold, bool setup_hold,
bool async, bool async,
bool gated_clk, bool gated_clk,
@ -417,7 +366,7 @@ PathGroups::findPathGroup(const Clock *clock,
bool bool
PathGroups::reportGroup(const char *group_name, PathGroups::reportGroup(const char *group_name,
StdStringSet &group_names) const StringSet &group_names) const
{ {
return group_names.empty() return group_names.empty()
|| group_names.contains(group_name); || group_names.contains(group_name);
@ -479,11 +428,11 @@ PathGroups::pathGroups(const PathEnd *path_end) const
} }
// Mirrors PathGroups::pathGroup. // Mirrors PathGroups::pathGroup.
StdStringSeq StringSeq
PathGroups::pathGroupNames(const PathEnd *path_end, PathGroups::pathGroupNames(const PathEnd *path_end,
const StaState *sta) const StaState *sta)
{ {
StdStringSeq group_names; StringSeq group_names;
const char *group_name = nullptr; const char *group_name = nullptr;
const Search *search = sta->search(); const Search *search = sta->search();
ExceptionPathSeq group_paths = search->groupPathsTo(path_end); ExceptionPathSeq group_paths = search->groupPathsTo(path_end);
@ -576,14 +525,14 @@ PathGroups::pushEnds(PathEndSeq &path_ends)
} }
} }
StdStringSeq StringSeq
PathGroups::pathGroupNames() PathGroups::pathGroupNames()
{ {
std::set<std::string> group_names1; std::set<std::string> group_names1;
const Sdc *sdc = mode_->sdc(); const Sdc *sdc = mode_->sdc();
for (const auto& [name, group] : sdc->groupPaths()) for (const auto& [name, group] : sdc->groupPaths())
group_names1.insert(name); group_names1.insert(name);
StdStringSeq group_names2; StringSeq group_names2;
for (const std::string &name : group_names1) for (const std::string &name : group_names1)
group_names2.push_back(name); group_names2.push_back(name);
sort(group_names2); sort(group_names2);
@ -632,9 +581,8 @@ PathGroups::makePathEnds(ExceptionTo *to,
unique_pins_, unique_edges_, scenes, min_max); unique_pins_, unique_edges_, scenes, min_max);
pushEnds(path_ends); pushEnds(path_ends);
if (sort_by_slack) { if (sort_by_slack)
sort(path_ends, PathEndLess(this)); sort(path_ends, PathEndLess(true, this));
}
if (unconstrained_paths if (unconstrained_paths
&& path_ends.empty()) && path_ends.empty())
@ -663,12 +611,12 @@ private:
PathGroups *path_groups_; PathGroups *path_groups_;
PathGroupEndMap ends_; PathGroupEndMap ends_;
PathEndLess cmp_; PathEndLess less_;
}; };
MakePathEnds1::MakePathEnds1(PathGroups *path_groups) : MakePathEnds1::MakePathEnds1(PathGroups *path_groups) :
path_groups_(path_groups), path_groups_(path_groups),
cmp_(path_groups) less_(true, path_groups)
{ {
} }
@ -693,7 +641,7 @@ MakePathEnds1::visitPathEnd(PathEnd *path_end,
// Only keep the path end with the smallest slack/latest arrival. // Only keep the path end with the smallest slack/latest arrival.
PathEnd *worst_end = findKey(ends_, group); PathEnd *worst_end = findKey(ends_, group);
if (worst_end) { if (worst_end) {
if (cmp_(path_end, worst_end)) { if (less_(path_end, worst_end)) {
ends_[group] = path_end->copy(); ends_[group] = path_end->copy();
delete worst_end; delete worst_end;
} }
@ -741,8 +689,8 @@ private:
PathGroups *path_groups_; PathGroups *path_groups_;
const StaState *sta_; const StaState *sta_;
PathGroupEndsMap ends_; PathGroupEndsMap ends_;
PathEndSlackLess slack_cmp_; PathEndSlackLess less_;
PathEndNoCrprLess path_no_crpr_cmp_; PathEndNoCrprLess path_no_crpr_less_;
}; };
MakePathEndsAll::MakePathEndsAll(int endpoint_path_count, MakePathEndsAll::MakePathEndsAll(int endpoint_path_count,
@ -750,8 +698,8 @@ MakePathEndsAll::MakePathEndsAll(int endpoint_path_count,
endpoint_path_count_(endpoint_path_count), endpoint_path_count_(endpoint_path_count),
path_groups_(path_groups), path_groups_(path_groups),
sta_(path_groups), sta_(path_groups),
slack_cmp_(path_groups), less_(true, path_groups),
path_no_crpr_cmp_(path_groups) path_no_crpr_less_(path_groups)
{ {
} }
@ -792,8 +740,8 @@ MakePathEndsAll::vertexEnd(Vertex *)
Debug *debug = sta_->debug(); Debug *debug = sta_->debug();
for (auto [group, ends] : ends_) { for (auto [group, ends] : ends_) {
if (ends) { if (ends) {
sort(ends, slack_cmp_); sort(ends, less_);
PathEndNoCrprSet unique_ends(path_no_crpr_cmp_); PathEndNoCrprSet unique_ends(path_no_crpr_less_);
auto end_iter = ends->begin(); auto end_iter = ends->begin();
int n = 0; int n = 0;
while (end_iter != ends->end() while (end_iter != ends->end()
@ -805,7 +753,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
debugPrint(debug, "path_group", 2, "insert %s %s %s %d", debugPrint(debug, "path_group", 2, "insert %s %s %s %d",
path_end->vertex(sta_)->to_string(sta_).c_str(), path_end->vertex(sta_)->to_string(sta_).c_str(),
path_end->typeName(), path_end->typeName(),
path_end->transition(sta_)->to_string().c_str(), path_end->transition(sta_)->shortName(),
path_end->path()->tag(sta_)->index()); path_end->path()->tag(sta_)->index());
// Give the group a copy of the path end because // Give the group a copy of the path end because
// it may delete it during pruning. // it may delete it during pruning.
@ -820,7 +768,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
debugPrint(debug, "path_group", 3, "prune %s %s %s %d", debugPrint(debug, "path_group", 3, "prune %s %s %s %d",
path_end->vertex(sta_)->to_string(sta_).c_str(), path_end->vertex(sta_)->to_string(sta_).c_str(),
path_end->typeName(), path_end->typeName(),
path_end->transition(sta_)->to_string().c_str(), path_end->transition(sta_)->shortName(),
path_end->path()->tag(sta_)->index()); path_end->path()->tag(sta_)->index());
} }
// Clear ends for next vertex. // Clear ends for next vertex.
@ -898,11 +846,8 @@ PathGroups::enumPathEnds(PathGroup *group,
// enumerator. // enumerator.
PathEnum path_enum(group_path_count, endpoint_path_count, PathEnum path_enum(group_path_count, endpoint_path_count,
unique_pins, unique_edges, cmp_slack, this); unique_pins, unique_edges, cmp_slack, this);
for (PathEnd *end : group->pathEnds()) { for (PathEnd *end : group->pathEnds())
if (group->saveable(end) path_enum.insert(end);
|| group->enumMinSlackUnderMin(end))
path_enum.insert(end);
}
group->clear(); group->clear();
// Parallel path enumeratation to find the endpoint_path_count/max path ends. // Parallel path enumeratation to find the endpoint_path_count/max path ends.

View File

@ -211,15 +211,15 @@ ReportPath::findField(const char *name) const
} }
void void
ReportPath::setReportFieldOrder(StringSeq *field_names) ReportPath::setReportFieldOrder(const StringSeq &field_names)
{ {
// Disable all fields. // Disable all fields.
for (ReportField *field : fields_) for (ReportField *field : fields_)
field->setEnabled(false); field->setEnabled(false);
ReportFieldSeq next_fields; ReportFieldSeq next_fields;
for (const char *field_name : *field_names) { for (const std::string &field_name : field_names) {
ReportField *field = findField(field_name); ReportField *field = findField(field_name.c_str());
if (field) { if (field) {
next_fields.push_back(field); next_fields.push_back(field);
field->setEnabled(true); field->setEnabled(true);
@ -406,7 +406,7 @@ ReportPath::reportEndpointHeader(const PathEnd *end,
: "max_delay/setup"; : "max_delay/setup";
report_->reportLine("%s group %s", report_->reportLine("%s group %s",
setup_hold, setup_hold,
group->name()); group->name().c_str());
reportBlankLine(); reportBlankLine();
reportEndHeader(); reportEndHeader();
} }
@ -1079,11 +1079,17 @@ ReportPath::reportJson(const PathEnd *end,
{ {
std::string result; std::string result;
result += "{\n"; result += "{\n";
stringAppend(result, " \"type\": \"%s\",\n", end->typeName()); result += " \"type\": \"";
stringAppend(result, " \"path_group\": \"%s\",\n", result += end->typeName();
end->pathGroup()->name()); result += "\",\n";
stringAppend(result, " \"path_type\": \"%s\",\n",
end->minMax(this)->to_string().c_str()); result += " \"path_group\": \"";
result += end->pathGroup()->name();
result += "\",\n";
result += " \"path_type\": \"";
result += end->minMax(this)->to_string();
result += "\",\n";
PathExpanded expanded(end->path(), this); PathExpanded expanded(end->path(), this);
const Pin *startpoint = expanded.startPath()->vertex(this)->pin(); const Pin *startpoint = expanded.startPath()->vertex(this)->pin();
@ -1269,7 +1275,7 @@ ReportPath::reportSlackOnly(const PathEnd *end) const
{ {
std::string line; std::string line;
const EarlyLate *early_late = end->pathEarlyLate(this); const EarlyLate *early_late = end->pathEarlyLate(this);
reportDescription(end->pathGroup()->name(), line); reportDescription(end->pathGroup()->name().c_str(), line);
if (end->isUnconstrained()) if (end->isUnconstrained())
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, line); reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, line);
else else

View File

@ -27,7 +27,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "StringSeq.hh" #include "StringUtil.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
#include "CheckMinPulseWidths.hh" #include "CheckMinPulseWidths.hh"
@ -49,7 +49,7 @@ public:
virtual ~ReportPath(); virtual ~ReportPath();
ReportPathFormat pathFormat() const { return format_; } ReportPathFormat pathFormat() const { return format_; }
void setPathFormat(ReportPathFormat format); void setPathFormat(ReportPathFormat format);
void setReportFieldOrder(StringSeq *field_names); void setReportFieldOrder(const StringSeq &field_names);
void setReportFields(bool report_input_pin, void setReportFields(bool report_input_pin,
bool report_hier_pins, bool report_hier_pins,
bool report_net, bool report_net,

View File

@ -497,14 +497,14 @@ Search::findPathEnds(ExceptionFrom *from,
bool unconstrained, bool unconstrained,
const SceneSeq &scenes, const SceneSeq &scenes,
const MinMaxAll *min_max, const MinMaxAll *min_max,
size_t group_path_count, int group_path_count,
size_t endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges, bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
StdStringSeq &group_names, StringSeq &group_names,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,
@ -1365,8 +1365,8 @@ ArrivalVisitor::visitFromToPath(const Pin * /* from_pin */,
debugPrint(debug_, "search", 3, " %s", debugPrint(debug_, "search", 3, " %s",
from_vertex->to_string(this).c_str()); from_vertex->to_string(this).c_str());
debugPrint(debug_, "search", 3, " %s -> %s %s", debugPrint(debug_, "search", 3, " %s -> %s %s",
from_rf->to_string().c_str(), from_rf->shortName(),
to_rf->to_string().c_str(), to_rf->shortName(),
min_max->to_string().c_str()); min_max->to_string().c_str());
debugPrint(debug_, "search", 3, " from tag: %s", debugPrint(debug_, "search", 3, " from tag: %s",
from_tag->to_string(this).c_str()); from_tag->to_string(this).c_str());
@ -2919,7 +2919,7 @@ Search::reportArrivals(Vertex *vertex,
prev_str += "NULL"; prev_str += "NULL";
} }
report_->reportLine(" %s %s %s / %s %s%s", report_->reportLine(" %s %s %s / %s %s%s",
rf->to_string().c_str(), rf->shortName(),
path->minMax(this)->to_string().c_str(), path->minMax(this)->to_string().c_str(),
delayAsString(path->arrival(), this), delayAsString(path->arrival(), this),
req, req,
@ -3654,10 +3654,10 @@ RequiredVisitor::visitFromToPath(const Pin *,
const MinMax *min_max) const MinMax *min_max)
{ {
// Don't propagate required times through latch D->Q edges. // Don't propagate required times through latch D->Q edges.
if (edge->role() != TimingRole::latchDtoQ()) { if (!edge->role()->isLatchDtoQ()) {
debugPrint(debug_, "search", 3, " %s -> %s %s", debugPrint(debug_, "search", 3, " %s -> %s %s",
from_rf->to_string().c_str(), from_rf->shortName(),
to_rf->to_string().c_str(), to_rf->shortName(),
min_max->to_string().c_str()); min_max->to_string().c_str());
debugPrint(debug_, "search", 3, " from tag %2u: %s", debugPrint(debug_, "search", 3, " from tag %2u: %s",
from_tag->index(), from_tag->index(),

View File

@ -242,7 +242,7 @@ endpoint_slack(const Pin *pin,
} }
} }
StdStringSeq StringSeq
path_group_names() path_group_names()
{ {
Sta *sta = Sta::sta(); Sta *sta = Sta::sta();
@ -359,7 +359,7 @@ find_path_ends(ExceptionFrom *from,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
StdStringSeq path_groups, StringSeq path_groups,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,
@ -395,10 +395,9 @@ set_report_path_format(ReportPathFormat format)
} }
void void
set_report_path_field_order(StringSeq *field_names) set_report_path_field_order(const StringSeq &field_names)
{ {
Sta::sta()->setReportPathFieldOrder(field_names); Sta::sta()->setReportPathFieldOrder(field_names);
delete field_names;
} }
void void
@ -741,8 +740,8 @@ write_timing_model_cmd(const char *lib_name,
void void
define_scene_cmd(const char *name, define_scene_cmd(const char *name,
const char *mode_name, const char *mode_name,
const StdStringSeq liberty_min_files, const StringSeq liberty_min_files,
const StdStringSeq liberty_max_files, const StringSeq liberty_max_files,
const char *spef_min_file, const char *spef_min_file,
const char *spef_max_file) const char *spef_max_file)
{ {
@ -753,11 +752,10 @@ define_scene_cmd(const char *name,
} }
void void
define_scenes_cmd(StringSeq *scene_names) define_scenes_cmd(const StringSeq &scene_names)
{ {
Sta *sta = Sta::sta(); Sta *sta = Sta::sta();
sta->makeScenes(scene_names); sta->makeScenes(scene_names);
delete scene_names;
} }
Scene * Scene *

View File

@ -52,7 +52,7 @@
#include "Sdc.hh" #include "Sdc.hh"
#include "Mode.hh" #include "Mode.hh"
#include "Variables.hh" #include "Variables.hh"
#include "WriteSdc.hh" #include "sdc/WriteSdc.hh"
#include "ExceptionPath.hh" #include "ExceptionPath.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "parasitics/SpefReader.hh" #include "parasitics/SpefReader.hh"
@ -299,6 +299,7 @@ Sta::makeComponents()
makeReportPath(); makeReportPath();
makePower(); makePower();
makeClkSkews(); makeClkSkews();
makeCheckTiming();
setCmdNamespace1(CmdNamespace::sdc); setCmdNamespace1(CmdNamespace::sdc);
setThreadCount1(defaultThreadCount()); setThreadCount1(defaultThreadCount());
@ -355,8 +356,7 @@ Sta::updateComponentsState()
latches_->copyState(this); latches_->copyState(this);
graph_delay_calc_->copyState(this); graph_delay_calc_->copyState(this);
report_path_->copyState(this); report_path_->copyState(this);
if (check_timing_) check_timing_->copyState(this);
check_timing_->copyState(this);
clk_skews_->copyState(this); clk_skews_->copyState(this);
if (power_) if (power_)
@ -2075,10 +2075,10 @@ Sta::isPathGroupName(const char *group_name,
|| stringEq(group_name, PathGroups::unconstrainedGroupName()); || stringEq(group_name, PathGroups::unconstrainedGroupName());
} }
StdStringSeq StringSeq
Sta::pathGroupNames(const Sdc *sdc) const Sta::pathGroupNames(const Sdc *sdc) const
{ {
StdStringSeq names; StringSeq names;
for (const Clock *clk : sdc->clocks()) for (const Clock *clk : sdc->clocks())
names.push_back(clk->name()); names.push_back(clk->name());
@ -2214,8 +2214,8 @@ Sta::checkTiming(const Mode *mode,
bool generated_clks) bool generated_clks)
{ {
if (unconstrained_endpoints) { if (unconstrained_endpoints) {
// Only arrivals to find unconstrained_endpoints. // Only need non-clock arrivals to find unconstrained_endpoints.
searchPreamble(); searchPreamble();
search_->findAllArrivals(); search_->findAllArrivals();
} }
else { else {
@ -2224,8 +2224,6 @@ Sta::checkTiming(const Mode *mode,
mode->sim()->ensureConstantsPropagated(); mode->sim()->ensureConstantsPropagated();
mode->clkNetwork()->ensureClkNetwork(); mode->clkNetwork()->ensureClkNetwork();
} }
if (check_timing_ == nullptr)
makeCheckTiming();
return check_timing_->check(mode, no_input_delay, no_output_delay, return check_timing_->check(mode, no_input_delay, no_output_delay,
reg_multiple_clks, reg_no_clks, reg_multiple_clks, reg_no_clks,
unconstrained_endpoints, unconstrained_endpoints,
@ -2468,9 +2466,9 @@ Sta::makeDefaultScene()
// define_corners (before read_liberty). // define_corners (before read_liberty).
void void
Sta::makeScenes(StringSeq *scene_names) Sta::makeScenes(const StringSeq &scene_names)
{ {
if (scene_names->size() > scene_count_max) if (scene_names.size() > scene_count_max)
report_->error(1553, "maximum scene count exceeded"); report_->error(1553, "maximum scene count exceeded");
Parasitics *parasitics = findParasitics("default"); Parasitics *parasitics = findParasitics("default");
Mode *mode = modes_[0]; Mode *mode = modes_[0];
@ -2478,7 +2476,7 @@ Sta::makeScenes(StringSeq *scene_names)
mode->clear(); mode->clear();
deleteScenes(); deleteScenes();
for (const char *name : *scene_names) for (const std::string &name : scene_names)
makeScene(name, mode, parasitics); makeScene(name, mode, parasitics);
cmd_scene_ = scenes_[0]; cmd_scene_ = scenes_[0];
@ -2490,8 +2488,8 @@ Sta::makeScenes(StringSeq *scene_names)
void void
Sta::makeScene(const std::string &name, Sta::makeScene(const std::string &name,
const std::string &mode_name, const std::string &mode_name,
const StdStringSeq &liberty_min_files, const StringSeq &liberty_min_files,
const StdStringSeq &liberty_max_files, const StringSeq &liberty_max_files,
const std::string &spef_min_file, const std::string &spef_min_file,
const std::string &spef_max_file) const std::string &spef_max_file)
{ {
@ -2598,12 +2596,12 @@ Sta::findScenes(const std::string &name,
void void
Sta::updateSceneLiberty(Scene *scene, Sta::updateSceneLiberty(Scene *scene,
const StdStringSeq &liberty_min_files, const StringSeq &liberty_min_files,
const StdStringSeq &liberty_max_files) const StringSeq &liberty_max_files)
{ {
StdStringSet warned_files; StringSet warned_files;
for (const MinMax *min_max : MinMax::range()) { for (const MinMax *min_max : MinMax::range()) {
const StdStringSeq &liberty_files = min_max == MinMax::min() const StringSeq &liberty_files = min_max == MinMax::min()
? liberty_min_files ? liberty_min_files
: liberty_max_files; : liberty_max_files;
for (const std::string &lib_file : liberty_files) { for (const std::string &lib_file : liberty_files) {
@ -2678,7 +2676,7 @@ Sta::findPathEnds(ExceptionFrom *from,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
StdStringSeq &group_names, StringSeq &group_names,
bool setup, bool setup,
bool hold, bool hold,
bool recovery, bool recovery,
@ -2729,7 +2727,7 @@ Sta::setReportPathFormat(ReportPathFormat format)
} }
void void
Sta::setReportPathFieldOrder(StringSeq *field_names) Sta::setReportPathFieldOrder(const StringSeq &field_names)
{ {
report_path_->setReportFieldOrder(field_names); report_path_->setReportFieldOrder(field_names);
} }
@ -3239,7 +3237,7 @@ void
EndpointPathEndVisitor::visit(PathEnd *path_end) EndpointPathEndVisitor::visit(PathEnd *path_end)
{ {
if (path_end->minMax(sta_) == min_max_) { if (path_end->minMax(sta_) == min_max_) {
StdStringSeq group_names = PathGroups::pathGroupNames(path_end, sta_); StringSeq group_names = PathGroups::pathGroupNames(path_end, sta_);
for (std::string &group_name : group_names) { for (std::string &group_name : group_names) {
if (group_name == path_group_name_) { if (group_name == path_group_name_) {
Slack end_slack = path_end->slack(sta_); Slack end_slack = path_end->slack(sta_);
@ -6037,7 +6035,7 @@ Sta::activity(const Pin *pin,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void
Sta::writePathSpice(Path *path, Sta::writePathSpice(const Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,

View File

@ -104,8 +104,7 @@ Tag::to_string(bool report_index,
if (report_rf_min_max) { if (report_rf_min_max) {
const RiseFall *rf = transition(); const RiseFall *rf = transition();
const MinMax *min_max = minMax(); const MinMax *min_max = minMax();
result += rf->to_string(); result += rf->shortName();
result += " ";
result += min_max->to_string(); result += min_max->to_string();
result += " "; result += " ";
} }

View File

@ -57,7 +57,7 @@ typedef int Stage;
class WritePathSpice : public WriteSpice class WritePathSpice : public WriteSpice
{ {
public: public:
WritePathSpice(Path *path, WritePathSpice(const Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,
@ -80,8 +80,8 @@ private:
void writeGateStage(Stage stage); void writeGateStage(Stage stage);
void writeStageParasitics(Stage stage); void writeStageParasitics(Stage stage);
void writeSubckts(); void writeSubckts();
StdStringSet findPathCellNames(); StringSet findPathCellNames();
void findPathCellSubckts(StdStringSet &path_cell_names); void findPathCellSubckts(StringSet &path_cell_names);
float maxTime(); float maxTime();
float pathMaxTime(); float pathMaxTime();
void writeMeasureDelayStmt(Stage stage, void writeMeasureDelayStmt(Stage stage,
@ -116,24 +116,24 @@ private:
const Path *stageLoadPath(Stage stage); const Path *stageLoadPath(Stage stage);
const TimingArc *stageGateArc(Stage stage); const TimingArc *stageGateArc(Stage stage);
const TimingArc *stageWireArc(Stage stage); const TimingArc *stageWireArc(Stage stage);
Edge *stageGateEdge(Stage stage); const Edge *stageGateEdge(Stage stage);
Edge *stageWireEdge(Stage stage); const Edge *stageWireEdge(Stage stage);
Pin *stageGateInputPin(Stage stage); const Pin *stageGateInputPin(Stage stage);
Pin *stageDrvrPin(Stage stage); const Pin *stageDrvrPin(Stage stage);
LibertyPort *stageGateInputPort(Stage stage); const LibertyPort *stageGateInputPort(Stage stage);
LibertyPort *stageDrvrPort(Stage stage); const LibertyPort *stageDrvrPort(Stage stage);
Pin *stageLoadPin(Stage stage); const Pin *stageLoadPin(Stage stage);
const char *stageGateInputPinName(Stage stage); const char *stageGateInputPinName(Stage stage);
const char *stageDrvrPinName(Stage stage); const char *stageDrvrPinName(Stage stage);
const char *stageLoadPinName(Stage stage); const char *stageLoadPinName(Stage stage);
LibertyCell *stageLibertyCell(Stage stage); const LibertyCell *stageLibertyCell(Stage stage);
Instance *stageInstance(Stage stage); const Instance *stageInstance(Stage stage);
float findSlew(const Path *path); float findSlew(const Path *path);
float findSlew(const Path *path, float findSlew(const Path *path,
const RiseFall *rf, const RiseFall *rf,
const TimingArc *next_arc); const TimingArc *next_arc);
Path *path_; const Path *path_;
PathExpanded path_expanded_; PathExpanded path_expanded_;
// Input clock waveform cycles. // Input clock waveform cycles.
int clk_cycle_count_; int clk_cycle_count_;
@ -152,7 +152,7 @@ private:
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void
writePathSpice(Path *path, writePathSpice(const Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,
@ -168,7 +168,7 @@ writePathSpice(Path *path,
writer.writeSpice(); writer.writeSpice();
} }
WritePathSpice::WritePathSpice(Path *path, WritePathSpice::WritePathSpice(const Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,
@ -215,10 +215,10 @@ WritePathSpice::writeHeader()
{ {
const Path *start_path = path_expanded_.startPath(); const Path *start_path = path_expanded_.startPath();
std::string title = stdstrPrint("Path from %s %s to %s %s", std::string title = stdstrPrint("Path from %s %s to %s %s",
network_->pathName(start_path->pin(this)), network_->pathName(start_path->pin(this)),
start_path->transition(this)->to_string().c_str(), start_path->transition(this)->shortName(),
network_->pathName(path_->pin(this)), network_->pathName(path_->pin(this)),
path_->transition(this)->to_string().c_str()); path_->transition(this)->shortName());
float max_time = maxTime(); float max_time = maxTime();
float time_step = 1e-13; float time_step = 1e-13;
writeHeader(title, max_time, time_step); writeHeader(title, max_time, time_step);
@ -227,7 +227,7 @@ WritePathSpice::writeHeader()
void void
WritePathSpice::writePrintStmt() WritePathSpice::writePrintStmt()
{ {
StdStringSeq node_names; StringSeq node_names;
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
node_names.push_back(stageDrvrPinName(stage)); node_names.push_back(stageDrvrPinName(stage));
node_names.push_back(stageLoadPinName(stage)); node_names.push_back(stageLoadPinName(stage));
@ -497,8 +497,8 @@ WritePathSpice::writeGateStage(Stage stage)
std::string subckt_name = "stage" + std::to_string(stage); std::string subckt_name = "stage" + std::to_string(stage);
const Instance *inst = stageInstance(stage); const Instance *inst = stageInstance(stage);
LibertyPort *input_port = stageGateInputPort(stage); const LibertyPort *input_port = stageGateInputPort(stage);
LibertyPort *drvr_port = stageDrvrPort(stage); const LibertyPort *drvr_port = stageDrvrPort(stage);
streamPrint(spice_stream_, ".subckt %s %s %s %s\n", streamPrint(spice_stream_, ".subckt %s %s %s %s\n",
subckt_name.c_str(), subckt_name.c_str(),
@ -515,7 +515,7 @@ WritePathSpice::writeGateStage(Stage stage)
const Path *drvr_path = stageDrvrPath(stage); const Path *drvr_path = stageDrvrPath(stage);
const RiseFall *drvr_rf = drvr_path->transition(this); const RiseFall *drvr_rf = drvr_path->transition(this);
Edge *gate_edge = stageGateEdge(stage); const Edge *gate_edge = stageGateEdge(stage);
LibertyPortLogicValues port_values; LibertyPortLogicValues port_values;
bool is_clked; bool is_clked;
@ -562,14 +562,14 @@ WritePathSpice::writeStageParasitics(Stage stage)
void void
WritePathSpice::writeSubckts() WritePathSpice::writeSubckts()
{ {
StdStringSet cell_names = findPathCellNames(); StringSet cell_names = findPathCellNames();
writeSubckts(cell_names); writeSubckts(cell_names);
} }
StdStringSet StringSet
WritePathSpice::findPathCellNames() WritePathSpice::findPathCellNames()
{ {
StdStringSet path_cell_names; StringSet path_cell_names;
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
const TimingArc *arc = stageGateArc(stage); const TimingArc *arc = stageGateArc(stage);
if (arc) { if (arc) {
@ -579,7 +579,7 @@ WritePathSpice::findPathCellNames()
path_cell_names.insert(cell->name()); path_cell_names.insert(cell->name());
} }
// Include side receivers. // Include side receivers.
Pin *drvr_pin = stageDrvrPin(stage); const Pin *drvr_pin = stageDrvrPin(stage);
auto pin_iter = network_->connectedPinIterator(drvr_pin); auto pin_iter = network_->connectedPinIterator(drvr_pin);
while (pin_iter->hasNext()) { while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next(); const Pin *pin = pin_iter->next();
@ -673,49 +673,49 @@ WritePathSpice::stageWireArc(Stage stage)
return path_expanded_.path(path_index)->prevArc(this); return path_expanded_.path(path_index)->prevArc(this);
} }
Edge * const Edge *
WritePathSpice::stageGateEdge(Stage stage) WritePathSpice::stageGateEdge(Stage stage)
{ {
const Path *path = stageDrvrPath(stage); const Path *path = stageDrvrPath(stage);
return path->prevEdge(this); return path->prevEdge(this);
} }
Edge * const Edge *
WritePathSpice::stageWireEdge(Stage stage) WritePathSpice::stageWireEdge(Stage stage)
{ {
const Path *path = stageLoadPath(stage); const Path *path = stageLoadPath(stage);
return path->prevEdge(this); return path->prevEdge(this);
} }
Pin * const Pin *
WritePathSpice::stageGateInputPin(Stage stage) WritePathSpice::stageGateInputPin(Stage stage)
{ {
const Path *path = stageGateInputPath(stage); const Path *path = stageGateInputPath(stage);
return path->pin(this); return path->pin(this);
} }
LibertyPort * const LibertyPort *
WritePathSpice::stageGateInputPort(Stage stage) WritePathSpice::stageGateInputPort(Stage stage)
{ {
Pin *pin = stageGateInputPin(stage); const Pin *pin = stageGateInputPin(stage);
return network_->libertyPort(pin); return network_->libertyPort(pin);
} }
Pin * const Pin *
WritePathSpice::stageDrvrPin(Stage stage) WritePathSpice::stageDrvrPin(Stage stage)
{ {
const Path *path = stageDrvrPath(stage); const Path *path = stageDrvrPath(stage);
return path->pin(this); return path->pin(this);
} }
LibertyPort * const LibertyPort *
WritePathSpice::stageDrvrPort(Stage stage) WritePathSpice::stageDrvrPort(Stage stage)
{ {
Pin *pin = stageDrvrPin(stage); const Pin *pin = stageDrvrPin(stage);
return network_->libertyPort(pin); return network_->libertyPort(pin);
} }
Pin * const Pin *
WritePathSpice::stageLoadPin(Stage stage) WritePathSpice::stageLoadPin(Stage stage)
{ {
const Path *path = stageLoadPath(stage); const Path *path = stageLoadPath(stage);
@ -725,35 +725,35 @@ WritePathSpice::stageLoadPin(Stage stage)
const char * const char *
WritePathSpice::stageGateInputPinName(Stage stage) WritePathSpice::stageGateInputPinName(Stage stage)
{ {
Pin *pin = stageGateInputPin(stage); const Pin *pin = stageGateInputPin(stage);
return network_->pathName(pin); return network_->pathName(pin);
} }
const char * const char *
WritePathSpice::stageDrvrPinName(Stage stage) WritePathSpice::stageDrvrPinName(Stage stage)
{ {
Pin *pin = stageDrvrPin(stage); const Pin *pin = stageDrvrPin(stage);
return network_->pathName(pin); return network_->pathName(pin);
} }
const char * const char *
WritePathSpice::stageLoadPinName(Stage stage) WritePathSpice::stageLoadPinName(Stage stage)
{ {
Pin *pin = stageLoadPin(stage); const Pin *pin = stageLoadPin(stage);
return network_->pathName(pin); return network_->pathName(pin);
} }
Instance * const Instance *
WritePathSpice::stageInstance(Stage stage) WritePathSpice::stageInstance(Stage stage)
{ {
Pin *pin = stageDrvrPin(stage); const Pin *pin = stageDrvrPin(stage);
return network_->instance(pin); return network_->instance(pin);
} }
LibertyCell * const LibertyCell *
WritePathSpice::stageLibertyCell(Stage stage) WritePathSpice::stageLibertyCell(Stage stage)
{ {
Pin *pin = stageDrvrPin(stage); const Pin *pin = stageDrvrPin(stage);
return network_->libertyPort(pin)->libertyCell(); return network_->libertyPort(pin)->libertyCell();
} }

View File

@ -24,7 +24,6 @@
#pragma once #pragma once
#include "StringSet.hh"
#include "CircuitSim.hh" #include "CircuitSim.hh"
namespace sta { namespace sta {
@ -35,7 +34,7 @@ class StaState;
// Write a spice deck for path. // Write a spice deck for path.
// Throws FileNotReadable, FileNotWritable, SubcktEndsMissing // Throws FileNotReadable, FileNotWritable, SubcktEndsMissing
void void
writePathSpice(Path *path, writePathSpice(const Path *path,
// Spice file written for path. // Spice file written for path.
const char *spice_filename, const char *spice_filename,
// Subckts used by path included in spice file. // Subckts used by path included in spice file.

View File

@ -151,7 +151,7 @@ WriteSpice::writeHeader(std::string &title,
} }
void void
WriteSpice::writePrintStmt(StdStringSeq &node_names) WriteSpice::writePrintStmt(StringSeq &node_names)
{ {
streamPrint(spice_stream_, ".print tran"); streamPrint(spice_stream_, ".print tran");
if (ckt_sim_ == CircuitSim::xyce) { if (ckt_sim_ == CircuitSim::xyce) {
@ -176,7 +176,7 @@ WriteSpice::replaceFileExt(std::string filename,
// Write gnuplot command file for use with xyce csv file. // Write gnuplot command file for use with xyce csv file.
void void
WriteSpice::writeGnuplotFile(StdStringSeq &node_nanes) WriteSpice::writeGnuplotFile(StringSeq &node_nanes)
{ {
std::string gnuplot_filename = replaceFileExt(spice_filename_, "gnuplot"); std::string gnuplot_filename = replaceFileExt(spice_filename_, "gnuplot");
std::string csv_filename = replaceFileExt(spice_filename_, "csv"); std::string csv_filename = replaceFileExt(spice_filename_, "csv");
@ -199,7 +199,7 @@ WriteSpice::writeGnuplotFile(StdStringSeq &node_nanes)
} }
void void
WriteSpice::writeSubckts(StdStringSet &cell_names) WriteSpice::writeSubckts(StringSet &cell_names)
{ {
findCellSubckts(cell_names); findCellSubckts(cell_names);
std::ifstream lib_subckts_stream(lib_subckt_filename_); std::ifstream lib_subckts_stream(lib_subckt_filename_);
@ -209,7 +209,7 @@ WriteSpice::writeSubckts(StdStringSet &cell_names)
std::string line; std::string line;
while (std::getline(lib_subckts_stream, line)) { while (std::getline(lib_subckts_stream, line)) {
// .subckt <cell_name> [args..] // .subckt <cell_name> [args..]
StdStringSeq tokens = parseTokens(line, ' '); StringSeq tokens = parseTokens(line, ' ');
if (tokens.size() >= 2 if (tokens.size() >= 2
&& stringEqual(tokens[0].c_str(), ".subckt")) { && stringEqual(tokens[0].c_str(), ".subckt")) {
const char *cell_name = tokens[1].c_str(); const char *cell_name = tokens[1].c_str();
@ -256,11 +256,11 @@ WriteSpice::writeSubckts(StdStringSet &cell_names)
void void
WriteSpice::recordSpicePortNames(const char *cell_name, WriteSpice::recordSpicePortNames(const char *cell_name,
StdStringSeq &tokens) StringSeq &tokens)
{ {
LibertyCell *cell = network_->findLibertyCell(cell_name); LibertyCell *cell = network_->findLibertyCell(cell_name);
if (cell) { if (cell) {
StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name]; StringSeq &spice_port_names = cell_spice_port_names_[cell_name];
for (size_t i = 2; i < tokens.size(); i++) { for (size_t i = 2; i < tokens.size(); i++) {
const char *port_name = tokens[i].c_str(); const char *port_name = tokens[i].c_str();
LibertyPort *port = cell->findLibertyPort(port_name); LibertyPort *port = cell->findLibertyPort(port_name);
@ -278,14 +278,14 @@ WriteSpice::recordSpicePortNames(const char *cell_name,
// Subckts can call subckts (asap7). // Subckts can call subckts (asap7).
void void
WriteSpice::findCellSubckts(StdStringSet &cell_names) WriteSpice::findCellSubckts(StringSet &cell_names)
{ {
std::ifstream lib_subckts_stream(lib_subckt_filename_); std::ifstream lib_subckts_stream(lib_subckt_filename_);
if (lib_subckts_stream.is_open()) { if (lib_subckts_stream.is_open()) {
std::string line; std::string line;
while (std::getline(lib_subckts_stream, line)) { while (std::getline(lib_subckts_stream, line)) {
// .subckt <cell_name> [args..] // .subckt <cell_name> [args..]
StdStringSeq tokens = parseTokens(line, ' '); StringSeq tokens = parseTokens(line, ' ');
if (tokens.size() >= 2 if (tokens.size() >= 2
&& stringEqual(tokens[0].c_str(), ".subckt")) { && stringEqual(tokens[0].c_str(), ".subckt")) {
const char *cell_name = tokens[1].c_str(); const char *cell_name = tokens[1].c_str();
@ -298,7 +298,7 @@ WriteSpice::findCellSubckts(StdStringSet &cell_names)
else { else {
// Process previous statement. // Process previous statement.
if (tolower(stmt[0]) == 'x') { if (tolower(stmt[0]) == 'x') {
StdStringSeq tokens = parseTokens(line, ' '); StringSeq tokens = parseTokens(line, ' ');
std::string &subckt_cell = tokens[tokens.size() - 1]; std::string &subckt_cell = tokens[tokens.size() - 1];
cell_names.insert(subckt_cell); cell_names.insert(subckt_cell);
} }
@ -323,7 +323,7 @@ WriteSpice::writeSubcktInst(const Instance *inst)
const char *inst_name = network_->pathName(inst); const char *inst_name = network_->pathName(inst);
LibertyCell *cell = network_->libertyCell(inst); LibertyCell *cell = network_->libertyCell(inst);
const char *cell_name = cell->name(); const char *cell_name = cell->name();
StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name]; StringSeq &spice_port_names = cell_spice_port_names_[cell_name];
streamPrint(spice_stream_, "x%s", inst_name); streamPrint(spice_stream_, "x%s", inst_name);
for (std::string subckt_port_name : spice_port_names) { for (std::string subckt_port_name : spice_port_names) {
const char *subckt_port_cname = subckt_port_name.c_str(); const char *subckt_port_cname = subckt_port_name.c_str();
@ -351,7 +351,7 @@ WriteSpice::writeSubcktInstVoltSrcs(const Instance *inst,
{ {
LibertyCell *cell = network_->libertyCell(inst); LibertyCell *cell = network_->libertyCell(inst);
const char *cell_name = cell->name(); const char *cell_name = cell->name();
StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name]; StringSeq &spice_port_names = cell_spice_port_names_[cell_name];
const char *inst_name = network_->pathName(inst); const char *inst_name = network_->pathName(inst);
debugPrint(debug_, "write_spice", 2, "subckt %s", cell->name()); debugPrint(debug_, "write_spice", 2, "subckt %s", cell->name());
@ -825,7 +825,7 @@ WriteSpice::railToRailSlew(float slew,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Find the logic values for expression inputs to enable paths from input_port. // Find the logic values for expression inputs to sensitize the path from input_port.
void void
WriteSpice::gatePortValues(const Pin *input_pin, WriteSpice::gatePortValues(const Pin *input_pin,
const Pin *drvr_pin, const Pin *drvr_pin,

View File

@ -30,7 +30,6 @@
#include <vector> #include <vector>
#include "StaState.hh" #include "StaState.hh"
#include "StringSet.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "GraphClass.hh" #include "GraphClass.hh"
@ -41,7 +40,7 @@
namespace sta { namespace sta {
using ParasiticNodeMap = std::map<const ParasiticNode*, int>; using ParasiticNodeMap = std::map<const ParasiticNode*, int>;
using CellSpicePortNames = std::map<std::string, StdStringSeq>; using CellSpicePortNames = std::map<std::string, StringSeq>;
using LibertyPortLogicValues = std::map<const LibertyPort*, LogicValue>; using LibertyPortLogicValues = std::map<const LibertyPort*, LogicValue>;
// Utilities for writing a spice deck. // Utilities for writing a spice deck.
@ -64,12 +63,12 @@ protected:
void writeHeader(std::string &title, void writeHeader(std::string &title,
float max_time, float max_time,
float time_step); float time_step);
void writePrintStmt(StdStringSeq &node_names); void writePrintStmt(StringSeq &node_names);
void writeGnuplotFile(StdStringSeq &node_nanes); void writeGnuplotFile(StringSeq &node_nanes);
void writeSubckts(StdStringSet &cell_names); void writeSubckts(StringSet &cell_names);
void findCellSubckts(StdStringSet &cell_names); void findCellSubckts(StringSet &cell_names);
void recordSpicePortNames(const char *cell_name, void recordSpicePortNames(const char *cell_name,
StdStringSeq &tokens); StringSeq &tokens);
void writeSubcktInst(const Instance *inst); void writeSubcktInst(const Instance *inst);
void writeSubcktInstVoltSrcs(const Instance *inst, void writeSubcktInstVoltSrcs(const Instance *inst,
LibertyPortLogicValues &port_values, LibertyPortLogicValues &port_values,

View File

@ -33,7 +33,7 @@
%inline %{ %inline %{
void void
write_path_spice_cmd(Path *path, write_path_spice_cmd(const Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
const char *lib_subckt_filename, const char *lib_subckt_filename,

View File

@ -37,7 +37,7 @@ namespace sta {
void void
readXyceCsv(const char *csv_filename, readXyceCsv(const char *csv_filename,
// Return values. // Return values.
StdStringSeq &titles, StringSeq &titles,
WaveformSeq &waveforms) WaveformSeq &waveforms)
{ {
std::ifstream file(csv_filename); std::ifstream file(csv_filename);

View File

@ -37,7 +37,7 @@ using WaveformSeq = std::vector<Table>;
void void
readXyceCsv(const char *csv_filename, readXyceCsv(const char *csv_filename,
// Return values. // Return values.
StdStringSeq &titles, StringSeq &titles,
WaveformSeq &waveforms); WaveformSeq &waveforms);
} // namespace } // namespace

View File

@ -27,8 +27,6 @@
#include "Machine.hh" #include "Machine.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "StringSet.hh"
#include "StringSeq.hh"
#include "PatternMatch.hh" #include "PatternMatch.hh"
#include "Network.hh" #include "Network.hh"
#include "Liberty.hh" #include "Liberty.hh"
@ -53,7 +51,6 @@
namespace sta { namespace sta {
typedef MinMaxAll MinMaxAllNull; typedef MinMaxAll MinMaxAllNull;
typedef std::vector<std::string> StdStringSeq;
#if TCL_MAJOR_VERSION < 9 #if TCL_MAJOR_VERSION < 9
typedef int Tcl_Size; typedef int Tcl_Size;
@ -293,53 +290,34 @@ using namespace sta;
Tcl_SetResult(interp, nullptr, TCL_STATIC); Tcl_SetResult(interp, nullptr, TCL_STATIC);
} }
%typemap(in) StringSeq* { %typemap(in) StringSet* {
$1 = tclListSeqConstChar($input, interp);
}
%typemap(in) StdStringSet* {
$1 = tclListSetStdString($input, interp); $1 = tclListSetStdString($input, interp);
} }
%typemap(in) StdStringSeq { %typemap(in) StringSeq {
$1 = tclListSeqStdString($input, interp); $1 = tclListSeqStdString($input, interp);
} }
%typemap(in) StdStringSeq* { %typemap(in) const StringSeq & (StringSeq seq) {
$1 = tclListSeqStdString($input, interp); seq = tclListSeqStdString($input, interp);
$1 = &seq;
} }
%typemap(out) StringSeq* { %typemap(in) StringSeq* {
StringSeq *strs = $1; $1 = tclListSeqStdStringPtr($input, interp);
Tcl_Obj *list = Tcl_NewListObj(0, nullptr); }
for (const char *str : *strs) {
Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str)); %typemap(in) StringSet* {
Tcl_ListObjAppendElement(interp, list, obj); $1 = tclListSetStdString($input, interp);
} }
Tcl_SetObjResult(interp, list);
%typemap(in) StringSeq {
$1 = tclListSeqStdString($input, interp);
} }
%typemap(out) StringSeq { %typemap(out) StringSeq {
StringSeq &strs = $1; StringSeq &strs = $1;
Tcl_Obj *list = Tcl_NewListObj(0, nullptr); Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const char *str : strs) {
Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str));
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(in) StdStringSet* {
$1 = tclListSetStdString($input, interp);
}
%typemap(in) StdStringSeq {
$1 = tclListSeqStdString($input, interp);
}
%typemap(out) StdStringSeq {
StdStringSeq &strs = $1;
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const std::string &str : strs) { for (const std::string &str : strs) {
Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(), str.size()); Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(), str.size());
Tcl_ListObjAppendElement(interp, list, obj); Tcl_ListObjAppendElement(interp, list, obj);
@ -497,7 +475,7 @@ using namespace sta;
const RiseFall *rf = $1; const RiseFall *rf = $1;
const char *str = ""; const char *str = "";
if (rf) if (rf)
str = rf->to_string().c_str(); str = rf->shortName();
Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC); Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
} }
@ -517,7 +495,7 @@ using namespace sta;
RiseFallBoth *tr = $1; RiseFallBoth *tr = $1;
const char *str = ""; const char *str = "";
if (tr) if (tr)
str = tr->asString(); str = tr->shortName();
Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC); Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
} }
@ -1137,10 +1115,9 @@ using namespace sta;
CheckErrorSeq *check_errors = $1; CheckErrorSeq *check_errors = $1;
for (CheckError *error : *check_errors) { for (CheckError *error : *check_errors) {
Tcl_Obj *string_list = Tcl_NewListObj(0, nullptr); Tcl_Obj *string_list = Tcl_NewListObj(0, nullptr);
for (const char *str : *error) { for (const std::string &str : *error) {
size_t str_len = strlen(str); Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(),
Tcl_Obj *obj = Tcl_NewStringObj(const_cast<char*>(str), static_cast<int>(str.size()));
static_cast<int>(str_len));
Tcl_ListObjAppendElement(interp, string_list, obj); Tcl_ListObjAppendElement(interp, string_list, obj);
} }
Tcl_ListObjAppendElement(interp, error_list, string_list); Tcl_ListObjAppendElement(interp, error_list, string_list);
@ -1249,10 +1226,6 @@ using namespace sta;
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
} }
%typemap(in) StringSet* {
$1 = tclListSetConstChar($input, interp);
}
%typemap(out) Mode* { %typemap(out) Mode* {
const Mode *mode = $1; const Mode *mode = $1;
if (mode) if (mode)

View File

@ -30,29 +30,27 @@
namespace sta { namespace sta {
StringSet * StringSeq
tclListSetConstChar(Tcl_Obj *const source, tclListSeqStdString(Tcl_Obj *const source,
Tcl_Interp *interp) Tcl_Interp *interp)
{ {
Tcl_Size argc; Tcl_Size argc;
Tcl_Obj **argv; Tcl_Obj **argv;
StringSeq seq;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) { if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StringSet *set = new StringSet;
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
int length; int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length); const char *str = Tcl_GetStringFromObj(argv[i], &length);
set->insert(str); seq.push_back(str);
} }
return set;
} }
else return seq;
return nullptr;
} }
StringSeq * StringSeq *
tclListSeqConstChar(Tcl_Obj *const source, tclListSeqStdStringPtr(Tcl_Obj *const source,
Tcl_Interp *interp) Tcl_Interp *interp)
{ {
Tcl_Size argc; Tcl_Size argc;
Tcl_Obj **argv; Tcl_Obj **argv;
@ -70,45 +68,7 @@ tclListSeqConstChar(Tcl_Obj *const source,
return nullptr; return nullptr;
} }
StdStringSeq StringSet *
tclListSeqStdString(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
StdStringSeq seq;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
seq.push_back(str);
}
}
return seq;
}
StdStringSeq *
tclListSeqStdStringPtr(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StdStringSeq *seq = new StdStringSeq;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
seq->push_back(str);
}
return seq;
}
else
return nullptr;
}
StdStringSet *
tclListSetStdString(Tcl_Obj *const source, tclListSetStdString(Tcl_Obj *const source,
Tcl_Interp *interp) Tcl_Interp *interp)
{ {
@ -116,7 +76,7 @@ tclListSetStdString(Tcl_Obj *const source,
Tcl_Obj **argv; Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) { if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StdStringSet *set = new StdStringSet; StringSet *set = new StringSet;
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
int length; int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length); const char *str = Tcl_GetStringFromObj(argv[i], &length);

View File

@ -1,36 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, 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 "StringSeq.hh"
namespace sta {
void
deleteContents(StringSeq *strings)
{
for (const char *string : *strings)
stringDelete(string);
}
} // namespace

View File

@ -1,36 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, 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 "StringSet.hh"
namespace sta {
void
deleteContents(StringSet *strings)
{
for (const char *string : *strings)
stringDelete(string);
}
} // namespace

View File

@ -265,11 +265,11 @@ trimRight(std::string &str)
str.erase(str.find_last_not_of(" ") + 1); str.erase(str.find_last_not_of(" ") + 1);
} }
StdStringSeq StringSeq
split(const std::string &text, split(const std::string &text,
const std::string &delims) const std::string &delims)
{ {
StdStringSeq tokens; StringSeq tokens;
auto start = text.find_first_not_of(delims); auto start = text.find_first_not_of(delims);
auto end = text.find_first_of(delims, start); auto end = text.find_first_of(delims, start);
while (end != std::string::npos) { while (end != std::string::npos) {
@ -283,11 +283,11 @@ split(const std::string &text,
} }
// Parse space separated tokens. // Parse space separated tokens.
StdStringSeq StringSeq
parseTokens(const std::string &s, parseTokens(const std::string &s,
const char delimiter) const char delimiter)
{ {
StdStringSeq tokens; StringSeq tokens;
size_t i = 0; size_t i = 0;
while (i < s.size()) { while (i < s.size()) {
while (i < s.size() && std::isspace(s[i])) while (i < s.size() && std::isspace(s[i]))

View File

@ -44,6 +44,15 @@ RiseFall::RiseFall(const char *name,
{ {
} }
const std::string &
RiseFall::to_string(bool use_short) const
{
if (use_short)
return short_name_;
else
return name_;
}
const RiseFall * const RiseFall *
RiseFall::opposite() const RiseFall::opposite() const
{ {
@ -134,6 +143,15 @@ RiseFallBoth::RiseFallBoth(const char *name,
{ {
} }
const std::string &
RiseFallBoth::to_string(bool use_short) const
{
if (use_short)
return short_name_;
else
return name_;
}
const RiseFallBoth * const RiseFallBoth *
RiseFallBoth::find(const char *tr_str) RiseFallBoth::find(const char *tr_str)
{ {

View File

@ -285,7 +285,7 @@ VerilogReader::makeCellPorts(Cell *cell,
VerilogModule *module, VerilogModule *module,
VerilogNetSeq *ports) VerilogNetSeq *ports)
{ {
StdStringSet port_names; StringSet port_names;
for (VerilogNet *mod_port : *ports) { for (VerilogNet *mod_port : *ports) {
const std::string &port_name = mod_port->name(); const std::string &port_name = mod_port->name();
if (!port_names.contains(port_name)) { if (!port_names.contains(port_name)) {
@ -335,7 +335,7 @@ void
VerilogReader::makeNamedPortRefCellPorts(Cell *cell, VerilogReader::makeNamedPortRefCellPorts(Cell *cell,
VerilogModule *module, VerilogModule *module,
VerilogNet *mod_port, VerilogNet *mod_port,
StdStringSet &port_names) StringSet &port_names)
{ {
PortSeq *member_ports = new PortSeq; PortSeq *member_ports = new PortSeq;
VerilogNetNameIterator *net_name_iter = mod_port->nameIterator(module,this); VerilogNetNameIterator *net_name_iter = mod_port->nameIterator(module,this);
@ -535,7 +535,7 @@ VerilogReader::makeModuleInst(const std::string *module_vname,
if (liberty_cell if (liberty_cell
&& hasScalarNamedPortRefs(liberty_cell, pins)) { && hasScalarNamedPortRefs(liberty_cell, pins)) {
const int port_count = liberty_cell->portBitCount(); const int port_count = liberty_cell->portBitCount();
StdStringSeq net_names(port_count); StringSeq net_names(port_count);
for (VerilogNet *vnet : *pins) { for (VerilogNet *vnet : *pins) {
VerilogNetPortRefScalarNet *vpin = VerilogNetPortRefScalarNet *vpin =
dynamic_cast<VerilogNetPortRefScalarNet*>(vnet); dynamic_cast<VerilogNetPortRefScalarNet*>(vnet);
@ -805,7 +805,7 @@ VerilogModule::~VerilogModule()
void void
VerilogModule::parseStmts(VerilogReader *reader) VerilogModule::parseStmts(VerilogReader *reader)
{ {
StdStringSet inst_names; StringSet inst_names;
for (VerilogStmt *stmt : *stmts_) { for (VerilogStmt *stmt : *stmts_) {
if (stmt->isDeclaration()) if (stmt->isDeclaration())
parseDcl(dynamic_cast<VerilogDcl*>(stmt), reader); parseDcl(dynamic_cast<VerilogDcl*>(stmt), reader);
@ -861,7 +861,7 @@ VerilogModule::parseDcl(VerilogDcl *dcl,
// expansion so errors are only reported once. // expansion so errors are only reported once.
void void
VerilogModule::checkInstanceName(VerilogInst *inst, VerilogModule::checkInstanceName(VerilogInst *inst,
StdStringSet &inst_names, StringSet &inst_names,
VerilogReader *reader) VerilogReader *reader)
{ {
std::string inst_name = inst->instanceName(); std::string inst_name = inst->instanceName();
@ -953,7 +953,7 @@ VerilogModuleInst::namedPins()
VerilogLibertyInst::VerilogLibertyInst(LibertyCell *cell, VerilogLibertyInst::VerilogLibertyInst(LibertyCell *cell,
const std::string &inst_name, const std::string &inst_name,
const StdStringSeq &net_names, const StringSeq &net_names,
VerilogAttrStmtSeq *attr_stmts, VerilogAttrStmtSeq *attr_stmts,
const int line) : const int line) :
VerilogInst(inst_name, attr_stmts, line), VerilogInst(inst_name, attr_stmts, line),
@ -1080,8 +1080,8 @@ VerilogAssign::~VerilogAssign()
class VerilogNullNetNameIterator : public VerilogNetNameIterator class VerilogNullNetNameIterator : public VerilogNetNameIterator
{ {
public: public:
virtual bool hasNext() { return false; } bool hasNext() override { return false; }
virtual const std::string &next(); const std::string &next() override;
}; };
const std::string & const std::string &
@ -1095,8 +1095,8 @@ class VerilogOneNetNameIterator : public VerilogNetNameIterator
{ {
public: public:
VerilogOneNetNameIterator(const std::string &name); VerilogOneNetNameIterator(const std::string &name);
virtual bool hasNext(); bool hasNext() override;
virtual const std::string &next(); const std::string &next() override;
protected: protected:
std::string name_; std::string name_;
@ -1128,8 +1128,8 @@ public:
VerilogBusNetNameIterator(const std::string bus_name, VerilogBusNetNameIterator(const std::string bus_name,
int from_index, int from_index,
int to_index); int to_index);
virtual bool hasNext(); bool hasNext() override;
virtual const std::string &next(); const std::string &next() override;
protected: protected:
const std::string bus_name_; const std::string bus_name_;
@ -1182,8 +1182,8 @@ public:
VerilogConstantNetNameIterator(VerilogConstantValue *value, VerilogConstantNetNameIterator(VerilogConstantValue *value,
const std::string &zero, const std::string &zero,
const std::string &one); const std::string &one);
virtual bool hasNext(); bool hasNext() override;
virtual const std::string &next(); const std::string &next() override;
private: private:
VerilogConstantValue *value_; VerilogConstantValue *value_;
@ -1222,8 +1222,8 @@ public:
VerilogModule *module, VerilogModule *module,
VerilogReader *reader); VerilogReader *reader);
virtual ~VerilogNetConcatNameIterator(); virtual ~VerilogNetConcatNameIterator();
virtual bool hasNext(); bool hasNext() override;
virtual const std::string &next(); const std::string &next() override;
private: private:
VerilogModule *module_; VerilogModule *module_;
@ -2008,7 +2008,7 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
network_->setAttribute(inst, entry->key(), entry->value()); network_->setAttribute(inst, entry->key(), entry->value());
} }
} }
const StdStringSeq &net_names = lib_inst->netNames(); const StringSeq &net_names = lib_inst->netNames();
LibertyCellPortBitIterator port_iter(lib_cell); LibertyCellPortBitIterator port_iter(lib_cell);
while (port_iter.hasNext()) { while (port_iter.hasNext()) {
LibertyPort *port = port_iter.next(); LibertyPort *port = port_iter.next();

View File

@ -28,7 +28,6 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include "StringSeq.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
namespace sta { namespace sta {
@ -76,7 +75,7 @@ public:
private: private:
void parseStmts(VerilogReader *reader); void parseStmts(VerilogReader *reader);
void checkInstanceName(VerilogInst *inst, void checkInstanceName(VerilogInst *inst,
StdStringSet &inst_names, StringSet &inst_names,
VerilogReader *reader); VerilogReader *reader);
std::string name_; std::string name_;
@ -217,16 +216,16 @@ class VerilogLibertyInst : public VerilogInst
public: public:
VerilogLibertyInst(LibertyCell *cell, VerilogLibertyInst(LibertyCell *cell,
const std::string &inst_name, const std::string &inst_name,
const StdStringSeq &net_names, const StringSeq &net_names,
VerilogAttrStmtSeq *attr_stmts, VerilogAttrStmtSeq *attr_stmts,
const int line); const int line);
virtual bool isLibertyInst() const { return true; } virtual bool isLibertyInst() const { return true; }
LibertyCell *cell() const { return cell_; } LibertyCell *cell() const { return cell_; }
const StdStringSeq &netNames() const { return net_names_; } const StringSeq &netNames() const { return net_names_; }
private: private:
LibertyCell *cell_; LibertyCell *cell_;
StdStringSeq net_names_; StringSeq net_names_;
}; };
// Abstract base class for nets. // Abstract base class for nets.