Merge remote-tracking branch 'upstream/master' into upstream
This commit is contained in:
commit
38f7af09cc
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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_,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
-------------------------
|
||||
|
|
|
|||
3507
doc/OpenSTA.fodt
3507
doc/OpenSTA.fodt
File diff suppressed because it is too large
Load Diff
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -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 "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ enum class PwrActivityOrigin
|
|||
propagated,
|
||||
clock,
|
||||
constant,
|
||||
defaulted,
|
||||
unknown
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "StringSeq.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "SearchClass.hh"
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <map>
|
||||
|
||||
#include "VectorMap.hh"
|
||||
#include "StringSet.hh"
|
||||
#include "MinMaxValues.hh"
|
||||
#include "Delay.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) :
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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}));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
28
sdc/Sdc.cc
28
sdc/Sdc.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "StringSeq.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "SdcClass.hh"
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 += " ";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ using WaveformSeq = std::vector<Table>;
|
|||
void
|
||||
readXyceCsv(const char *csv_filename,
|
||||
// Return values.
|
||||
StdStringSeq &titles,
|
||||
StringSeq &titles,
|
||||
WaveformSeq &waveforms);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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]))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue