Merge remote-tracking branch 'upstream/master' into upstream

This commit is contained in:
Matt Liberty 2026-03-09 17:58:52 +00:00
commit 38f7af09cc
83 changed files with 2443 additions and 2657 deletions

View File

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

View File

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

View File

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

View File

@ -125,7 +125,7 @@ class DmpAlg : public StaState
{
public:
DmpAlg(int nr_order, StaState *sta);
virtual ~DmpAlg();
~DmpAlg() override = default;
virtual const char *name() = 0;
// Set driver model and pi model parameters for delay calculation.
virtual void init(const LibertyLibrary *library,
@ -156,7 +156,7 @@ public:
// Return values.
double &vo,
double &dol_dt);
// Load responce to driver waveform.
// Load response to driver waveform.
void Vl(double t,
// Return values.
double &vl,
@ -288,8 +288,6 @@ DmpAlg::DmpAlg(int nr_order,
fjac_[i] = fjac_storage_ + i * max_nr_order_;
}
DmpAlg::~DmpAlg() = default;
void
DmpAlg::init(const LibertyLibrary *drvr_library,
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, cap2, pocv_enabled, d2, s2);
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;
}

View File

@ -604,7 +604,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
{
debugPrint(debug_, "delay_calc", 2, " driver cell %s %s",
drvr_cell->name(),
rf->to_string().c_str());
rf->shortName());
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) {
for (TimingArc *arc : arc_set->arcs()) {
if (arc->toEdge()->asRiseFall() == rf) {
@ -1114,8 +1114,7 @@ GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
const Pin *from_pin = from_vertex->pin();
const RiseFall *from_rf = arc1->fromEdge()->asRiseFall();
const RiseFall *drvr_rf = arc1->toEdge()->asRiseFall();
Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
const Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
const Pin *drvr_pin1 = drvr_vertex1->pin();
float load_cap;
@ -1694,7 +1693,7 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
related_out_cap, scene, min_max, digits);
}
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;
float load_cap;
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;
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
dcalc_arg.drvrCell()->name(),
drvr_rf_->to_string().c_str());
drvr_rf_->shortName());
LibertyCell *drvr_cell = dcalc_arg.drvrCell();
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
bool vdd_exists;
@ -744,7 +744,7 @@ PrimaDelayCalc::dcalcResults()
debugPrint(debug_, "ccs_dcalc", 2,
"load %s %s delay %s slew %s",
network_->pathName(load_pin),
drvr_rf_->to_string().c_str(),
drvr_rf_->shortName(),
delayAsString(wire_delay, this),
delayAsString(load_slew, this));

View File

@ -40,7 +40,7 @@ StaState::clk_network__ moved to Mode
StaState::parasitics_ moved to Scene
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
to StdStringSeq&.
to StringSeq&.
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.
2025/02/24
2026/02/24
----------
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,
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
to StdStringSeq&.
to StringSeq&.
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)
return stringPrintTmp("%s %s",
enable_port->name(),
enable_rf->to_string().c_str());
enable_rf->shortName());
}
return "";
}

View File

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

View File

@ -60,7 +60,6 @@ public:
comp_(comp),
min_heap_comp_(comp)
{
heap_.reserve(max_size);
}
// Copy constructor
@ -107,7 +106,12 @@ public:
setMaxSize(size_t max_size)
{
max_size_ = max_size;
heap_.reserve(max_size);
}
void
reserve(size_t size)
{
heap_.reserve(size);
}
// Insert an element into the heap.
@ -172,8 +176,6 @@ public:
{
// Convert heap to sorted vector (best to worst)
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_);
heap_.clear();
return result;
@ -181,11 +183,10 @@ public:
// Extract all elements sorted from best to worst (const version).
// 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::sort_heap(temp_heap.begin(), temp_heap.end(), min_heap_comp_);
std::reverse(temp_heap.begin(), temp_heap.end());
return temp_heap;
}
@ -245,7 +246,7 @@ private:
Compare comp_;
explicit MinHeapCompare(const Compare& c) : comp_(c) {}
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:
ConcreteCellPortBitIterator(const ConcreteCell *cell);
virtual bool hasNext();
virtual ConcretePort *next();
bool hasNext() override;
ConcretePort *next() override;
private:
void findNext();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,6 @@
#include <string_view>
#include <functional>
#include "StringSeq.hh"
#include "StringUtil.hh"
#include "LibertyClass.hh"
#include "NetworkClass.hh"
@ -126,11 +125,11 @@ public:
void setThreadCount(int thread_count);
// define_corners compatibility.
void makeScenes(StringSeq *scene_names);
void makeScenes(const StringSeq &scene_names);
void makeScene(const std::string &name,
const std::string &mode_name,
const StdStringSeq &liberty_min_files,
const StdStringSeq &liberty_max_files,
const StringSeq &liberty_min_files,
const StringSeq &liberty_max_files,
const std::string &spef_min_file,
const std::string &spef_max_file);
Scene *findScene(const std::string &name) const;
@ -653,7 +652,7 @@ public:
const Sdc *sdc) __attribute__ ((deprecated));
bool isPathGroupName(const char *group_name,
const Sdc *sdc) const;
StdStringSeq pathGroupNames(const Sdc *sdc) const;
StringSeq pathGroupNames(const Sdc *sdc) const;
void resetPath(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
@ -966,7 +965,7 @@ public:
bool sort_by_slack,
// Path groups to report.
// Empty list reports all groups.
StdStringSeq &group_names,
StringSeq &group_names,
// Predicates to filter the type of path
// ends returned.
bool setup,
@ -976,7 +975,7 @@ public:
bool clk_gating_setup,
bool clk_gating_hold);
void setReportPathFormat(ReportPathFormat format);
void setReportPathFieldOrder(StringSeq *field_names);
void setReportPathFieldOrder(const StringSeq &field_names);
void setReportPathFields(bool report_input_pin,
bool report_hier_pins,
bool report_net,
@ -1388,7 +1387,7 @@ public:
LibertyLibrarySeq *map_libs);
LibertyCellSeq *equivCells(LibertyCell *cell);
void writePathSpice(Path *path,
void writePathSpice(const Path *path,
const char *spice_filename,
const char *subckt_filename,
const char *lib_subckt_filename,
@ -1588,8 +1587,8 @@ protected:
void setThreadCount1(int thread_count);
void updateLibertyScenes();
void updateSceneLiberty(Scene *scene,
const StdStringSeq &liberty_min_files,
const StdStringSeq &liberty_max_files);
const StringSeq &liberty_min_files,
const StringSeq &liberty_max_files);
Scene *makeScene(const std::string &name,
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 <string>
#include <vector>
#include <set>
#include "Machine.hh" // __attribute__
namespace sta {
using StdStringSeq = std::vector<std::string>;
using StringSeq = std::vector<std::string>;
using StringSet = std::set<std::string>;
inline bool
stringEq(const char *str1,
@ -204,7 +206,7 @@ void
trimRight(std::string &str);
// Spit text into delimiter separated tokens and skip whitepace.
StdStringSeq
StringSeq
parseTokens(const std::string &s,
const char delimiter);

View File

@ -22,33 +22,24 @@
//
// 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 "ArcDelayCalc.hh"
#include "StringUtil.hh"
namespace sta {
#if TCL_MAJOR_VERSION < 9
typedef int Tcl_Size;
#endif
StringSet *
tclListSetConstChar(Tcl_Obj *const source,
Tcl_Interp *interp);
StringSeq *
tclListSeqConstChar(Tcl_Obj *const source,
Tcl_Interp *interp);
StdStringSeq
StringSeq
tclListSeqStdString(Tcl_Obj *const source,
Tcl_Interp *interp);
StdStringSeq *
StringSeq *
tclListSeqStdStringPtr(Tcl_Obj *const source,
Tcl_Interp *interp);
StdStringSet *
StringSet *
tclListSetStdString(Tcl_Obj *const source,
Tcl_Interp *interp);

View File

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

View File

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

View File

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

View File

@ -78,8 +78,7 @@ LibertyReader::LibertyReader(const char *filename,
debug_(network->debug()),
network_(network),
builder_(debug_, report_),
library_(nullptr),
first_cell_(true)
library_(nullptr)
{
defineVisitors();
}
@ -148,13 +147,13 @@ LibertyReader::beginLibrary(const LibertyGroup *library_group,
}
void
LibertyReader::endLibrary(const LibertyGroup *group,
LibertyReader::endLibrary(const LibertyGroup *library_group,
LibertyGroup *)
{
// If a library hasno cells endCell is not called.
if (first_cell_)
readLibraryAttributes(group);
delete group;
// If a library has no cells endCell is not called.
readLibraryAttributes(library_group);
checkThresholds(library_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
// are libraries that define table templates and bus tyupes
// between cells.
if (first_cell_)
readLibraryAttributes(library_group);
else {
readTableTemplates(library_group);
readBusTypes(nullptr, library_group);
}
readLibraryAttributes(library_group);
const char *name = cell_group->firstName();
if (name) {
@ -182,8 +176,10 @@ LibertyReader::endCell(const LibertyGroup *cell_group,
}
else
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();
first_cell_ = false;
}
void
@ -524,24 +520,28 @@ void
LibertyReader::readThresholds(const LibertyGroup *library_group)
{
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(),
&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(),
&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(),
&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(),
&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)
libWarn(1148, library_group, "slew_upper_threshold_pct_%s not found.", rf->name());
}
@ -907,7 +907,7 @@ void
LibertyReader::readSlewDegradations(const LibertyGroup *library_group)
{
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 =
library_group->findSubgroup(group_name.c_str());
if (degradation_group) {
@ -1480,7 +1480,7 @@ LibertyReader::readCapacitance(const LibertyPortSeq &ports,
for (LibertyPort *port : ports) {
// rise/fall_capacitance
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;
bool 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);
attr_name = rf->to_string_long() + "_capacitance_range";
attr_name = rf->to_string() + "_capacitance_range";
const LibertyComplexAttrSeq &range_attrs = port_group->findComplexAttrs(attr_name);
if (!range_attrs.empty()) {
const LibertyComplexAttr *attr = range_attrs[0];
@ -1894,8 +1894,8 @@ LibertyReader::makeTimingArcs(LibertyCell *cell,
LibertyPort *related_output_port = findLibertyPort(cell, timing_group,
"related_output_pin");
StdStringSeq related_port_names = findAttributStrings(timing_group, "related_pin");
StdStringSeq related_bus_names=findAttributStrings(timing_group,"related_bus_pins");
StringSeq related_port_names = findAttributStrings(timing_group, "related_pin");
StringSeq related_bus_names=findAttributStrings(timing_group,"related_bus_pins");
TimingType timing_type = timing_attrs->timingType();
for (LibertyPort *to_port : ports) {
@ -2081,7 +2081,7 @@ LibertyReader::makeLinearModels(LibertyCell *cell,
{
LibertyLibrary *library = cell->libertyLibrary();
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;
bool intr_exists;
timing_group->findAttrFloat(intr_attr_name, intr, intr_exists);
@ -2094,7 +2094,7 @@ LibertyReader::makeLinearModels(LibertyCell *cell,
if (timingTypeIsCheck(timing_attrs->timingType()))
model = new CheckLinearModel(cell, intr);
else {
std::string res_attr_name = rf->to_string_long() + "_resistance";
std::string res_attr_name = rf->to_string() + "_resistance";
float res = 0.0;
bool res_exists;
timing_group->findAttrFloat(res_attr_name, res, res_exists);
@ -2117,18 +2117,18 @@ LibertyReader::makeTableModels(LibertyCell *cell,
{
bool found_model = false;
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,
TableTemplateType::delay, time_scale_,
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,
transition_attr_name.c_str(),
rf, TableTemplateType::delay,
time_scale_,
ScaleFactorType::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 =
readEarlyLateTableModels(timing_group,
delay_sigma_attr_name.c_str(),
@ -2136,7 +2136,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
time_scale_,
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";
TableModelsEarlyLate slew_sigmas =
readEarlyLateTableModels(timing_group,
@ -2164,7 +2164,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
found_model = true;
}
else {
std::string constraint_attr_name = rf->to_string_long() + "_constraint";
std::string constraint_attr_name = rf->to_string() + "_constraint";
ScaleFactorType scale_factor_type =
timingTypeScaleFactorType(timing_attrs->timingType());
TableModel *constraint = readCheckTableModel(timing_group,
@ -2172,7 +2172,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
rf, TableTemplateType::delay,
time_scale_, scale_factor_type);
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";
TableModelsEarlyLate constraint_sigmas =
readEarlyLateTableModels(timing_group,
@ -2298,7 +2298,7 @@ LibertyReader::readReceiverCapacitance(const LibertyGroup *timing_group,
ReceiverModelPtr &receiver_model)
{
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);
if (cap_group) {
const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment");
@ -2328,7 +2328,7 @@ OutputWaveforms *
LibertyReader::readOutputWaveforms(const LibertyGroup *timing_group,
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);
if (current_group) {
OutputWaveformSeq output_currents;
@ -2680,7 +2680,7 @@ LibertyReader::readInternalPowerGroups(LibertyCell *cell,
InternalPowerModels models;
// rise/fall_power group
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);
if (pwr_group) {
TableModel *model = readTableModel(pwr_group, rf, TableTemplateType::power,
@ -2743,7 +2743,7 @@ LibertyReader::findLibertyPort(LibertyCell *cell,
return nullptr;
}
StdStringSeq
StringSeq
LibertyReader::findAttributStrings(const LibertyGroup *group,
const char *name_attr)
{
@ -2754,7 +2754,7 @@ LibertyReader::findAttributStrings(const LibertyGroup *group,
return parseTokens(*strings, ' ');
}
}
return StdStringSeq();
return StringSeq();
}
LibertyPortSeq
@ -2763,7 +2763,7 @@ LibertyReader::findLibertyPorts(LibertyCell *cell,
const char *port_name_attr)
{
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) {
LibertyPort *port = findPort(cell, port_name.c_str());
if (port)
@ -2915,40 +2915,40 @@ LibertyReader::readStatetable(LibertyCell *cell,
const char *input_ports_arg = statetable_group->firstName();
const char *internal_ports_arg = statetable_group->params().size() >= 2
? statetable_group->secondName() : nullptr;
StdStringSeq input_ports;
StringSeq input_ports;
if (input_ports_arg)
input_ports = parseTokens(input_ports_arg, ' ');
StdStringSeq internal_ports;
StringSeq internal_ports;
if (internal_ports_arg)
internal_ports = parseTokens(internal_ports_arg, ' ');
const LibertySimpleAttr *table_attr = statetable_group->findSimpleAttr("table");
if (table_attr) {
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 internal_count = internal_ports.size();
StatetableRows table;
for (const std::string &row : table_rows) {
const StdStringSeq row_groups = parseTokens(row, ':');
const StringSeq row_groups = parseTokens(row, ':');
if (row_groups.size() != 3) {
libWarn(1300, table_attr, "table row must have 3 groups separated by ':'.");
break;
}
StdStringSeq inputs = parseTokens(row_groups[0], ' ');
StringSeq inputs = parseTokens(row_groups[0], ' ');
if (inputs.size() != input_count) {
libWarn(1301,table_attr,"table row has %zu input values but %zu are required.",
inputs.size(), input_count);
break;
}
StdStringSeq currents = parseTokens(row_groups[1], ' ');
StringSeq currents = parseTokens(row_groups[1], ' ');
if (currents.size() != internal_count) {
libWarn(1302,table_attr,
"table row has %zu current values but %zu are required.",
currents.size(), internal_count);
break;
}
StdStringSeq nexts = parseTokens(row_groups[2], ' ');
StringSeq nexts = parseTokens(row_groups[2], ' ');
if (nexts.size() != internal_count) {
libWarn(1303, table_attr, "table row has %zu next values but %zu are required.",
nexts.size(), internal_count);
@ -3087,7 +3087,7 @@ static EnumNameMap<StateInternalValue> state_internal_value_name_map =
};
StateInputValues
LibertyReader::parseStateInputValues(StdStringSeq &inputs,
LibertyReader::parseStateInputValues(StringSeq &inputs,
const LibertySimpleAttr *attr)
{
StateInputValues input_values;
@ -3106,7 +3106,7 @@ LibertyReader::parseStateInputValues(StdStringSeq &inputs,
}
StateInternalValues
LibertyReader::parseStateInternalValues(StdStringSeq &states,
LibertyReader::parseStateInternalValues(StringSeq &states,
const LibertySimpleAttr *attr)
{
StateInternalValues state_values;
@ -3458,37 +3458,37 @@ LibertyReader::variableValue(const char *var,
void
LibertyReader::libWarn(int id,
const LibertyGroup *obj,
const LibertyGroup *group,
const char *fmt,
...)
...) const
{
va_list args;
va_start(args, fmt);
report_->vfileWarn(id, filename_, obj->line(), fmt, args);
report_->vfileWarn(id, filename_, group->line(), fmt, args);
va_end(args);
}
void
LibertyReader::libWarn(int id,
const LibertySimpleAttr *obj,
const LibertySimpleAttr *attr,
const char *fmt,
...)
...) const
{
va_list args;
va_start(args, fmt);
report_->vfileWarn(id, filename_, obj->line(), fmt, args);
report_->vfileWarn(id, filename_, attr->line(), fmt, args);
va_end(args);
}
void
LibertyReader::libWarn(int id,
const LibertyComplexAttr *obj,
const LibertyComplexAttr *attr,
const char *fmt,
...)
...) const
{
va_list args;
va_start(args, fmt);
report_->vfileWarn(id, filename_, obj->line(), fmt, args);
report_->vfileWarn(id, filename_, attr->line(), fmt, args);
va_end(args);
}
@ -3496,7 +3496,7 @@ void
LibertyReader::libWarn(int id,
int line,
const char *fmt,
...)
...) const
{
va_list args;
va_start(args, fmt);
@ -3506,37 +3506,37 @@ LibertyReader::libWarn(int id,
void
LibertyReader::libError(int id,
const LibertyGroup *obj,
const LibertyGroup *group,
const char *fmt,
...)
...) const
{
va_list args;
va_start(args, fmt);
report_->vfileError(id, filename_, obj->line(), fmt, args);
report_->vfileError(id, filename_, group->line(), fmt, args);
va_end(args);
}
void
LibertyReader::libError(int id,
const LibertySimpleAttr *obj,
const LibertySimpleAttr *attr,
const char *fmt,
...)
...) const
{
va_list args;
va_start(args, fmt);
report_->vfileError(id, filename_, obj->line(), fmt, args);
report_->vfileError(id, filename_, attr->line(), fmt, args);
va_end(args);
}
void
LibertyReader::libError(int id,
const LibertyComplexAttr *obj,
const LibertyComplexAttr *attr,
const char *fmt,
...)
...) const
{
va_list args;
va_start(args, fmt);
report_->vfileError(id, filename_, obj->line(), fmt, args);
report_->vfileError(id, filename_, attr->line(), fmt, args);
va_end(args);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -96,18 +96,15 @@ DisabledPorts::setDisabledFromTo(LibertyPort *from,
{
if (from_to_ == nullptr)
from_to_ = new LibertyPortPairSet;
LibertyPortPair pair(from, to);
from_to_->insert(pair);
from_to_->insert({from, to});
}
void
DisabledPorts::removeDisabledFromTo(LibertyPort *from,
LibertyPort *to)
{
if (from_to_) {
LibertyPortPair from_to(from, to);
from_to_->erase(from_to);
}
if (from_to_)
from_to_->erase({from, to});
}
bool
@ -115,12 +112,11 @@ DisabledPorts::isDisabled(LibertyPort *from,
LibertyPort *to,
const TimingRole *role)
{
LibertyPortPair from_to(from, to);
// set_disable_timing instance does not disable timing checks.
return (all_ && !role->isTimingCheck())
|| (from_ && from_->contains(from))
|| (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,
const Pin *load)
{
PinPair pair(drvr, load);
pairs_->insert(pair);
pairs_->insert({drvr, load});
}
static void
@ -2475,8 +2474,7 @@ void
DeletePinPairsThru::visit(const Pin *drvr,
const Pin *load)
{
PinPair pair(drvr, load);
pairs_->erase(pair);
pairs_->erase({drvr, load});
}
static void

View File

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

View File

@ -1654,6 +1654,14 @@ set_propagate_all_clocks(bool 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
////////////////////////////////////////////////////////////////

View File

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

View File

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

View File

@ -106,7 +106,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
report_->reportLine("%7s source latency %s %s",
time_unit->asString(src_latency, digits),
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)
report_->reportLine("%7s source internal clock delay",
time_unit->asString(src_internal_clk_latency, digits));
@ -116,7 +116,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
report_->reportLine("%7s target latency %s %s",
time_unit->asString(-tgt_latency, digits),
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)
report_->reportLine("%7s target internal clock delay",
time_unit->asString(-tgt_internal_clk_latency, digits));
@ -315,10 +315,10 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
debugPrint(debug_, "clk_skew", 2,
"%s %s %s -> %s %s %s crpr = %s skew = %s",
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)),
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)),
delayAsString(probe.crpr(this), this),
time_unit->asString(probe.skew()));

View File

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

View File

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

View File

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

View File

@ -201,7 +201,7 @@ Path::to_string(const StaState *sta) const
else
return stringPrintTmp("%s %s %s/%s %d",
vertex(sta)->to_string(sta).c_str(),
transition(sta)->to_string().c_str(),
transition(sta)->shortName(),
scene(sta)->name().c_str(),
minMax(sta)->to_string().c_str(),
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
PathEnd::less(const PathEnd *path_end1,
const PathEnd *path_end2,
bool cmp_slack,
const StaState *sta)
{
return cmp(path_end1, path_end2, sta) < 0;
return cmp(path_end1, path_end2, cmp_slack, sta) < 0;
}
int
PathEnd::cmp(const PathEnd *path_end1,
const PathEnd *path_end2,
bool cmp_slack,
const StaState *sta)
{
int cmp = path_end1->isUnconstrained()
int cmp = !cmp_slack || path_end1->isUnconstrained()
? -cmpArrival(path_end1, path_end2, sta)
: cmpSlack(path_end1, path_end2, sta);
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)
{
}

View File

@ -91,7 +91,7 @@ DiversionGreater::operator()(Diversion *div1,
{
PathEnd *path_end1 = div1->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
@ -426,7 +426,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
from_path->to_string(this).c_str(),
to_vertex->to_string(this).c_str(),
to_rf->to_string().c_str(),
to_rf->shortName(),
delayAsString(search_->deratedDelay(from_vertex, arc, edge,
false, from_path->minMax(this),
from_path->dcalcAnalysisPtIndex(this),

View File

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

View File

@ -50,7 +50,7 @@
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::makePathGroupSlack(const char *name,
@ -82,8 +82,8 @@ PathGroup::makePathGroupArrival(const char *name,
}
PathGroup::PathGroup(const char *name,
size_t group_path_count,
size_t endpoint_path_count,
int group_path_count,
int endpoint_path_count,
bool unique_pins,
bool unique_edges,
float slack_min,
@ -99,43 +99,36 @@ PathGroup::PathGroup(const char *name,
slack_min_(slack_min),
slack_max_(slack_max),
min_max_(min_max),
compare_slack_(cmp_slack),
threshold_(min_max->initValue()),
cmp_slack_(cmp_slack),
heap_(group_path_count, PathEndLess(cmp_slack, sta)),
sta_(sta)
{
}
PathGroup::~PathGroup()
PathEndSeq
PathGroup::pathEnds() const
{
deleteContents(path_ends_);
return heap_.contents();
}
bool
PathGroup::saveable(PathEnd *path_end)
{
float threshold;
{
LockGuard lock(lock_);
threshold = threshold_;
}
if (compare_slack_) {
if (cmp_slack_) {
// Crpr increases the slack, so check the slack
// without crpr first because it is expensive to find.
Slack slack = path_end->slackNoCrpr(sta_);
if (!delayIsInitValue(slack, min_max_)
&& delayLessEqual(slack, threshold, sta_)
&& delayLessEqual(slack, slack_max_, sta_)) {
// Now check with crpr.
slack = path_end->slack(sta_);
return delayLessEqual(slack, threshold, sta_)
&& delayLessEqual(slack, slack_max_, sta_)
return delayLessEqual(slack, slack_max_, sta_)
&& delayGreaterEqual(slack, slack_min_, sta_);
}
}
else {
const Arrival &arrival = path_end->dataArrivalTime(sta_);
return !delayIsInitValue(arrival, min_max_)
&& delayGreaterEqual(arrival, threshold, min_max_, sta_);
return !delayIsInitValue(arrival, min_max_);
}
return false;
}
@ -148,7 +141,7 @@ PathGroup::saveable(PathEnd *path_end)
bool
PathGroup::enumMinSlackUnderMin(PathEnd *path_end)
{
if (compare_slack_
if (cmp_slack_
&& endpoint_path_count_ > 1
&& slack_min_ > -INF) {
const Path *path = path_end->path();
@ -177,72 +170,28 @@ void
PathGroup::insert(PathEnd *path_end)
{
LockGuard lock(lock_);
path_ends_.push_back(path_end);
heap_.insert(path_end);
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
PathGroup::pushEnds(PathEndSeq &path_ends)
{
ensureSortedMaxPaths();
for (PathEnd *path_end : path_ends_)
path_ends.push_back(path_end);
}
void
PathGroup::ensureSortedMaxPaths()
{
if (path_ends_.size() > group_path_count_)
prune();
else
sort();
}
void
PathGroup::sort()
{
sta::sort(path_ends_, PathEndLess(sta_));
if (!heap_.empty()) {
PathEndSeq ends = heap_.extract();
path_ends.reserve(path_ends.size() + ends.size());
// Append heap path ends to path_ends.
path_ends.insert(path_ends.end(),
std::make_move_iterator(ends.begin()),
std::make_move_iterator(ends.end()));
}
}
void
PathGroup::clear()
{
LockGuard lock(lock_);
threshold_ = min_max_->initValue();
path_ends_.clear();
heap_.clear();
}
////////////////////////////////////////////////////////////////
@ -258,7 +207,7 @@ PathGroups::PathGroups(int group_path_count,
bool unique_edges,
float slack_min,
float slack_max,
StdStringSeq &group_names,
StringSeq &group_names,
bool setup,
bool hold,
bool recovery,
@ -276,7 +225,7 @@ PathGroups::PathGroups(int group_path_count,
slack_min_(slack_min),
slack_max_(slack_max)
{
StdStringSet groups;
StringSet groups;
for (std::string &group_name : group_names)
groups.insert(group_name);
@ -297,7 +246,7 @@ PathGroups::makeGroups(int group_path_count,
bool unique_edges,
float slack_min,
float slack_max,
StdStringSet &group_names,
StringSet &group_names,
bool setup_hold,
bool async,
bool gated_clk,
@ -417,7 +366,7 @@ PathGroups::findPathGroup(const Clock *clock,
bool
PathGroups::reportGroup(const char *group_name,
StdStringSet &group_names) const
StringSet &group_names) const
{
return group_names.empty()
|| group_names.contains(group_name);
@ -479,11 +428,11 @@ PathGroups::pathGroups(const PathEnd *path_end) const
}
// Mirrors PathGroups::pathGroup.
StdStringSeq
StringSeq
PathGroups::pathGroupNames(const PathEnd *path_end,
const StaState *sta)
{
StdStringSeq group_names;
StringSeq group_names;
const char *group_name = nullptr;
const Search *search = sta->search();
ExceptionPathSeq group_paths = search->groupPathsTo(path_end);
@ -576,14 +525,14 @@ PathGroups::pushEnds(PathEndSeq &path_ends)
}
}
StdStringSeq
StringSeq
PathGroups::pathGroupNames()
{
std::set<std::string> group_names1;
const Sdc *sdc = mode_->sdc();
for (const auto& [name, group] : sdc->groupPaths())
group_names1.insert(name);
StdStringSeq group_names2;
StringSeq group_names2;
for (const std::string &name : group_names1)
group_names2.push_back(name);
sort(group_names2);
@ -632,9 +581,8 @@ PathGroups::makePathEnds(ExceptionTo *to,
unique_pins_, unique_edges_, scenes, min_max);
pushEnds(path_ends);
if (sort_by_slack) {
sort(path_ends, PathEndLess(this));
}
if (sort_by_slack)
sort(path_ends, PathEndLess(true, this));
if (unconstrained_paths
&& path_ends.empty())
@ -663,12 +611,12 @@ private:
PathGroups *path_groups_;
PathGroupEndMap ends_;
PathEndLess cmp_;
PathEndLess less_;
};
MakePathEnds1::MakePathEnds1(PathGroups *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.
PathEnd *worst_end = findKey(ends_, group);
if (worst_end) {
if (cmp_(path_end, worst_end)) {
if (less_(path_end, worst_end)) {
ends_[group] = path_end->copy();
delete worst_end;
}
@ -741,8 +689,8 @@ private:
PathGroups *path_groups_;
const StaState *sta_;
PathGroupEndsMap ends_;
PathEndSlackLess slack_cmp_;
PathEndNoCrprLess path_no_crpr_cmp_;
PathEndSlackLess less_;
PathEndNoCrprLess path_no_crpr_less_;
};
MakePathEndsAll::MakePathEndsAll(int endpoint_path_count,
@ -750,8 +698,8 @@ MakePathEndsAll::MakePathEndsAll(int endpoint_path_count,
endpoint_path_count_(endpoint_path_count),
path_groups_(path_groups),
sta_(path_groups),
slack_cmp_(path_groups),
path_no_crpr_cmp_(path_groups)
less_(true, path_groups),
path_no_crpr_less_(path_groups)
{
}
@ -792,8 +740,8 @@ MakePathEndsAll::vertexEnd(Vertex *)
Debug *debug = sta_->debug();
for (auto [group, ends] : ends_) {
if (ends) {
sort(ends, slack_cmp_);
PathEndNoCrprSet unique_ends(path_no_crpr_cmp_);
sort(ends, less_);
PathEndNoCrprSet unique_ends(path_no_crpr_less_);
auto end_iter = ends->begin();
int n = 0;
while (end_iter != ends->end()
@ -805,7 +753,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
debugPrint(debug, "path_group", 2, "insert %s %s %s %d",
path_end->vertex(sta_)->to_string(sta_).c_str(),
path_end->typeName(),
path_end->transition(sta_)->to_string().c_str(),
path_end->transition(sta_)->shortName(),
path_end->path()->tag(sta_)->index());
// Give the group a copy of the path end because
// it may delete it during pruning.
@ -820,7 +768,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
debugPrint(debug, "path_group", 3, "prune %s %s %s %d",
path_end->vertex(sta_)->to_string(sta_).c_str(),
path_end->typeName(),
path_end->transition(sta_)->to_string().c_str(),
path_end->transition(sta_)->shortName(),
path_end->path()->tag(sta_)->index());
}
// Clear ends for next vertex.
@ -898,11 +846,8 @@ PathGroups::enumPathEnds(PathGroup *group,
// enumerator.
PathEnum path_enum(group_path_count, endpoint_path_count,
unique_pins, unique_edges, cmp_slack, this);
for (PathEnd *end : group->pathEnds()) {
if (group->saveable(end)
|| group->enumMinSlackUnderMin(end))
path_enum.insert(end);
}
for (PathEnd *end : group->pathEnds())
path_enum.insert(end);
group->clear();
// 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
ReportPath::setReportFieldOrder(StringSeq *field_names)
ReportPath::setReportFieldOrder(const StringSeq &field_names)
{
// Disable all fields.
for (ReportField *field : fields_)
field->setEnabled(false);
ReportFieldSeq next_fields;
for (const char *field_name : *field_names) {
ReportField *field = findField(field_name);
for (const std::string &field_name : field_names) {
ReportField *field = findField(field_name.c_str());
if (field) {
next_fields.push_back(field);
field->setEnabled(true);
@ -406,7 +406,7 @@ ReportPath::reportEndpointHeader(const PathEnd *end,
: "max_delay/setup";
report_->reportLine("%s group %s",
setup_hold,
group->name());
group->name().c_str());
reportBlankLine();
reportEndHeader();
}
@ -1079,11 +1079,17 @@ ReportPath::reportJson(const PathEnd *end,
{
std::string result;
result += "{\n";
stringAppend(result, " \"type\": \"%s\",\n", end->typeName());
stringAppend(result, " \"path_group\": \"%s\",\n",
end->pathGroup()->name());
stringAppend(result, " \"path_type\": \"%s\",\n",
end->minMax(this)->to_string().c_str());
result += " \"type\": \"";
result += end->typeName();
result += "\",\n";
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);
const Pin *startpoint = expanded.startPath()->vertex(this)->pin();
@ -1269,7 +1275,7 @@ ReportPath::reportSlackOnly(const PathEnd *end) const
{
std::string line;
const EarlyLate *early_late = end->pathEarlyLate(this);
reportDescription(end->pathGroup()->name(), line);
reportDescription(end->pathGroup()->name().c_str(), line);
if (end->isUnconstrained())
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, line);
else

View File

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

View File

@ -497,14 +497,14 @@ Search::findPathEnds(ExceptionFrom *from,
bool unconstrained,
const SceneSeq &scenes,
const MinMaxAll *min_max,
size_t group_path_count,
size_t endpoint_path_count,
int group_path_count,
int endpoint_path_count,
bool unique_pins,
bool unique_edges,
float slack_min,
float slack_max,
bool sort_by_slack,
StdStringSeq &group_names,
StringSeq &group_names,
bool setup,
bool hold,
bool recovery,
@ -1365,8 +1365,8 @@ ArrivalVisitor::visitFromToPath(const Pin * /* from_pin */,
debugPrint(debug_, "search", 3, " %s",
from_vertex->to_string(this).c_str());
debugPrint(debug_, "search", 3, " %s -> %s %s",
from_rf->to_string().c_str(),
to_rf->to_string().c_str(),
from_rf->shortName(),
to_rf->shortName(),
min_max->to_string().c_str());
debugPrint(debug_, "search", 3, " from tag: %s",
from_tag->to_string(this).c_str());
@ -2919,7 +2919,7 @@ Search::reportArrivals(Vertex *vertex,
prev_str += "NULL";
}
report_->reportLine(" %s %s %s / %s %s%s",
rf->to_string().c_str(),
rf->shortName(),
path->minMax(this)->to_string().c_str(),
delayAsString(path->arrival(), this),
req,
@ -3654,10 +3654,10 @@ RequiredVisitor::visitFromToPath(const Pin *,
const MinMax *min_max)
{
// 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",
from_rf->to_string().c_str(),
to_rf->to_string().c_str(),
from_rf->shortName(),
to_rf->shortName(),
min_max->to_string().c_str());
debugPrint(debug_, "search", 3, " from tag %2u: %s",
from_tag->index(),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,29 +30,27 @@
namespace sta {
StringSet *
tclListSetConstChar(Tcl_Obj *const source,
StringSeq
tclListSeqStdString(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
StringSeq seq;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StringSet *set = new StringSet;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
set->insert(str);
seq.push_back(str);
}
return set;
}
else
return nullptr;
return seq;
}
StringSeq *
tclListSeqConstChar(Tcl_Obj *const source,
Tcl_Interp *interp)
tclListSeqStdStringPtr(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
@ -70,45 +68,7 @@ tclListSeqConstChar(Tcl_Obj *const source,
return nullptr;
}
StdStringSeq
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 *
StringSet *
tclListSetStdString(Tcl_Obj *const source,
Tcl_Interp *interp)
{
@ -116,7 +76,7 @@ tclListSetStdString(Tcl_Obj *const source,
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StdStringSet *set = new StdStringSet;
StringSet *set = new StringSet;
for (int i = 0; i < argc; i++) {
int 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);
}
StdStringSeq
StringSeq
split(const std::string &text,
const std::string &delims)
{
StdStringSeq tokens;
StringSeq tokens;
auto start = text.find_first_not_of(delims);
auto end = text.find_first_of(delims, start);
while (end != std::string::npos) {
@ -283,11 +283,11 @@ split(const std::string &text,
}
// Parse space separated tokens.
StdStringSeq
StringSeq
parseTokens(const std::string &s,
const char delimiter)
{
StdStringSeq tokens;
StringSeq tokens;
size_t i = 0;
while (i < s.size()) {
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 *
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 *
RiseFallBoth::find(const char *tr_str)
{

View File

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

View File

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