Merge pull request #307 from The-OpenROAD-Project-staging/upstream
Upstream
This commit is contained in:
commit
a0b629462d
|
|
@ -241,8 +241,6 @@ set(STA_SOURCE
|
||||||
util/RiseFallMinMaxDelay.cc
|
util/RiseFallMinMaxDelay.cc
|
||||||
util/RiseFallValues.cc
|
util/RiseFallValues.cc
|
||||||
util/Stats.cc
|
util/Stats.cc
|
||||||
util/StringSeq.cc
|
|
||||||
util/StringSet.cc
|
|
||||||
util/StringUtil.cc
|
util/StringUtil.cc
|
||||||
util/Transition.cc
|
util/Transition.cc
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
ref_time_ = output_waveforms_->referenceTime(in_slew_);
|
ref_time_ = output_waveforms_->referenceTime(in_slew_);
|
||||||
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
|
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
|
||||||
drvr_cell->name(),
|
drvr_cell->name(),
|
||||||
drvr_rf_->to_string().c_str());
|
drvr_rf_->shortName());
|
||||||
ArcDelay gate_delay;
|
ArcDelay gate_delay;
|
||||||
Slew drvr_slew;
|
Slew drvr_slew;
|
||||||
gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew);
|
gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "DelayCalc.hh"
|
#include "DelayCalc.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "ContainerHelpers.hh"
|
#include "ContainerHelpers.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
|
|
@ -37,9 +38,9 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef std::map<const char*, MakeArcDelayCalc, CharPtrLess> DelayCalcMap;
|
typedef std::map<std::string, MakeArcDelayCalc> DelayCalcMap;
|
||||||
|
|
||||||
static DelayCalcMap *delay_calcs = nullptr;
|
static DelayCalcMap delay_calcs;
|
||||||
|
|
||||||
void
|
void
|
||||||
registerDelayCalcs()
|
registerDelayCalcs()
|
||||||
|
|
@ -54,26 +55,23 @@ registerDelayCalcs()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
registerDelayCalc(const char *name,
|
registerDelayCalc(const std::string &name,
|
||||||
MakeArcDelayCalc maker)
|
MakeArcDelayCalc maker)
|
||||||
{
|
{
|
||||||
if (delay_calcs == nullptr)
|
delay_calcs[name] = maker;
|
||||||
delay_calcs = new DelayCalcMap;
|
|
||||||
(*delay_calcs)[name] = maker;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
deleteDelayCalcs()
|
deleteDelayCalcs()
|
||||||
{
|
{
|
||||||
delete delay_calcs;
|
delay_calcs.clear();
|
||||||
delay_calcs = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArcDelayCalc *
|
ArcDelayCalc *
|
||||||
makeDelayCalc(const char *name,
|
makeDelayCalc(const std::string &name,
|
||||||
StaState *sta)
|
StaState *sta)
|
||||||
{
|
{
|
||||||
MakeArcDelayCalc maker = findKey(delay_calcs, name);
|
MakeArcDelayCalc maker = findKey(&delay_calcs, name);
|
||||||
if (maker)
|
if (maker)
|
||||||
return maker(sta);
|
return maker(sta);
|
||||||
else
|
else
|
||||||
|
|
@ -81,16 +79,16 @@ makeDelayCalc(const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isDelayCalcName(const char *name)
|
isDelayCalcName(const std::string &name)
|
||||||
{
|
{
|
||||||
return delay_calcs->contains(name);
|
return delay_calcs.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSeq
|
StringSeq
|
||||||
delayCalcNames()
|
delayCalcNames()
|
||||||
{
|
{
|
||||||
StringSeq names;
|
StringSeq names;
|
||||||
for (const auto [name, make_dcalc] : *delay_calcs)
|
for (const auto &[name, make_dcalc] : delay_calcs)
|
||||||
names.push_back(name);
|
names.push_back(name);
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ class DmpAlg : public StaState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DmpAlg(int nr_order, StaState *sta);
|
DmpAlg(int nr_order, StaState *sta);
|
||||||
virtual ~DmpAlg();
|
~DmpAlg() override = default;
|
||||||
virtual const char *name() = 0;
|
virtual const char *name() = 0;
|
||||||
// Set driver model and pi model parameters for delay calculation.
|
// Set driver model and pi model parameters for delay calculation.
|
||||||
virtual void init(const LibertyLibrary *library,
|
virtual void init(const LibertyLibrary *library,
|
||||||
|
|
@ -156,7 +156,7 @@ public:
|
||||||
// Return values.
|
// Return values.
|
||||||
double &vo,
|
double &vo,
|
||||||
double &dol_dt);
|
double &dol_dt);
|
||||||
// Load responce to driver waveform.
|
// Load response to driver waveform.
|
||||||
void Vl(double t,
|
void Vl(double t,
|
||||||
// Return values.
|
// Return values.
|
||||||
double &vl,
|
double &vl,
|
||||||
|
|
@ -288,8 +288,6 @@ DmpAlg::DmpAlg(int nr_order,
|
||||||
fjac_[i] = fjac_storage_ + i * max_nr_order_;
|
fjac_[i] = fjac_storage_ + i * max_nr_order_;
|
||||||
}
|
}
|
||||||
|
|
||||||
DmpAlg::~DmpAlg() = default;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DmpAlg::init(const LibertyLibrary *drvr_library,
|
DmpAlg::init(const LibertyLibrary *drvr_library,
|
||||||
const LibertyCell *drvr_cell,
|
const LibertyCell *drvr_cell,
|
||||||
|
|
@ -1645,7 +1643,8 @@ gateModelRd(const LibertyCell *cell,
|
||||||
gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1);
|
gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1);
|
||||||
gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2);
|
gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2);
|
||||||
double vth = cell->libertyLibrary()->outputThreshold(rf);
|
double vth = cell->libertyLibrary()->outputThreshold(rf);
|
||||||
float rd = -std::log(vth) * std::abs(delayAsFloat(d1) - delayAsFloat(d2)) / (cap2 - cap1);
|
float rd = -std::log(vth) * std::abs(delayAsFloat(d1) - delayAsFloat(d2))
|
||||||
|
/ (cap2 - cap1);
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -604,7 +604,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
|
||||||
{
|
{
|
||||||
debugPrint(debug_, "delay_calc", 2, " driver cell %s %s",
|
debugPrint(debug_, "delay_calc", 2, " driver cell %s %s",
|
||||||
drvr_cell->name(),
|
drvr_cell->name(),
|
||||||
rf->to_string().c_str());
|
rf->shortName());
|
||||||
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) {
|
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) {
|
||||||
for (TimingArc *arc : arc_set->arcs()) {
|
for (TimingArc *arc : arc_set->arcs()) {
|
||||||
if (arc->toEdge()->asRiseFall() == rf) {
|
if (arc->toEdge()->asRiseFall() == rf) {
|
||||||
|
|
@ -1114,8 +1114,7 @@ GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
|
||||||
const Pin *from_pin = from_vertex->pin();
|
const Pin *from_pin = from_vertex->pin();
|
||||||
const RiseFall *from_rf = arc1->fromEdge()->asRiseFall();
|
const RiseFall *from_rf = arc1->fromEdge()->asRiseFall();
|
||||||
const RiseFall *drvr_rf = arc1->toEdge()->asRiseFall();
|
const RiseFall *drvr_rf = arc1->toEdge()->asRiseFall();
|
||||||
Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
|
const Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
|
||||||
in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
|
|
||||||
|
|
||||||
const Pin *drvr_pin1 = drvr_vertex1->pin();
|
const Pin *drvr_pin1 = drvr_vertex1->pin();
|
||||||
float load_cap;
|
float load_cap;
|
||||||
|
|
@ -1694,7 +1693,7 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
|
||||||
related_out_cap, scene, min_max, digits);
|
related_out_cap, scene, min_max, digits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const Slew &from_slew = edgeFromSlew(from_vertex, from_rf, edge, scene, min_max);
|
const Slew from_slew = edgeFromSlew(from_vertex, from_rf, edge, scene, min_max);
|
||||||
const Parasitic *to_parasitic;
|
const Parasitic *to_parasitic;
|
||||||
float load_cap;
|
float load_cap;
|
||||||
parasiticLoad(to_pin, to_rf, scene, min_max, nullptr, arc_delay_calc_,
|
parasiticLoad(to_pin, to_rf, scene, min_max, nullptr, arc_delay_calc_,
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||||
output_waveforms_[drvr_idx] = output_waveforms;
|
output_waveforms_[drvr_idx] = output_waveforms;
|
||||||
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
|
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
|
||||||
dcalc_arg.drvrCell()->name(),
|
dcalc_arg.drvrCell()->name(),
|
||||||
drvr_rf_->to_string().c_str());
|
drvr_rf_->shortName());
|
||||||
LibertyCell *drvr_cell = dcalc_arg.drvrCell();
|
LibertyCell *drvr_cell = dcalc_arg.drvrCell();
|
||||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||||
bool vdd_exists;
|
bool vdd_exists;
|
||||||
|
|
@ -744,7 +744,7 @@ PrimaDelayCalc::dcalcResults()
|
||||||
debugPrint(debug_, "ccs_dcalc", 2,
|
debugPrint(debug_, "ccs_dcalc", 2,
|
||||||
"load %s %s delay %s slew %s",
|
"load %s %s delay %s slew %s",
|
||||||
network_->pathName(load_pin),
|
network_->pathName(load_pin),
|
||||||
drvr_rf_->to_string().c_str(),
|
drvr_rf_->shortName(),
|
||||||
delayAsString(wire_delay, this),
|
delayAsString(wire_delay, this),
|
||||||
delayAsString(load_slew, this));
|
delayAsString(load_slew, this));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ StaState::clk_network__ moved to Mode
|
||||||
StaState::parasitics_ moved to Scene
|
StaState::parasitics_ moved to Scene
|
||||||
|
|
||||||
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
||||||
to StdStringSeq&.
|
to StringSeq&.
|
||||||
|
|
||||||
Sta::isClock has been removed. Use mode->clkNetwork()->isClock instead.
|
Sta::isClock has been removed. Use mode->clkNetwork()->isClock instead.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ OpenSTA Timing Analyzer Release Notes
|
||||||
|
|
||||||
This file summarizes user visible changes for each release.
|
This file summarizes user visible changes for each release.
|
||||||
|
|
||||||
2025/02/24
|
2026/02/24
|
||||||
----------
|
----------
|
||||||
|
|
||||||
The define_scene -library argument now takes a the library name or a
|
The define_scene -library argument now takes a the library name or a
|
||||||
|
|
@ -201,7 +201,7 @@ to remove paths through identical pins and rise/fall edges.
|
||||||
Instances now have pins for verilog netlist power/ground connections,
|
Instances now have pins for verilog netlist power/ground connections,
|
||||||
|
|
||||||
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
||||||
to StdStringSeq&.
|
to StringSeq&.
|
||||||
|
|
||||||
Release 2.6.1 2025/03/30
|
Release 2.6.1 2025/03/30
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
|
||||||
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)
|
if (enable_port)
|
||||||
return stringPrintTmp("%s %s",
|
return stringPrintTmp("%s %s",
|
||||||
enable_port->name(),
|
enable_port->name(),
|
||||||
enable_rf->to_string().c_str());
|
enable_rf->shortName());
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,9 @@ public:
|
||||||
void remove(Vertex *vertex);
|
void remove(Vertex *vertex);
|
||||||
void reportEntries() const;
|
void reportEntries() const;
|
||||||
|
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
bool hasNext(Level to_level);
|
bool hasNext(Level to_level);
|
||||||
virtual Vertex *next();
|
Vertex *next() override;
|
||||||
|
|
||||||
// Apply visitor to all vertices in the queue in level order.
|
// Apply visitor to all vertices in the queue in level order.
|
||||||
// Returns the number of vertices that are visited.
|
// Returns the number of vertices that are visited.
|
||||||
|
|
@ -131,19 +131,19 @@ public:
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
StaState *sta);
|
StaState *sta);
|
||||||
virtual ~BfsFwdIterator();
|
virtual ~BfsFwdIterator();
|
||||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred);
|
SearchPred *search_pred) override;
|
||||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
const Mode *mode);
|
const Mode *mode) override;
|
||||||
using BfsIterator::enqueueAdjacentVertices;
|
using BfsIterator::enqueueAdjacentVertices;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool levelLessOrEqual(Level level1,
|
bool levelLessOrEqual(Level level1,
|
||||||
Level level2) const;
|
Level level2) const override;
|
||||||
virtual bool levelLess(Level level1,
|
bool levelLess(Level level1,
|
||||||
Level level2) const;
|
Level level2) const override;
|
||||||
virtual void incrLevel(Level &level) const;
|
void incrLevel(Level &level) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfsBkwdIterator : public BfsIterator
|
class BfsBkwdIterator : public BfsIterator
|
||||||
|
|
@ -153,19 +153,19 @@ public:
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
StaState *sta);
|
StaState *sta);
|
||||||
virtual ~BfsBkwdIterator();
|
virtual ~BfsBkwdIterator();
|
||||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred);
|
SearchPred *search_pred) override;
|
||||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
const Mode *mode);
|
const Mode *mode) override;
|
||||||
using BfsIterator::enqueueAdjacentVertices;
|
using BfsIterator::enqueueAdjacentVertices;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool levelLessOrEqual(Level level1,
|
bool levelLessOrEqual(Level level1,
|
||||||
Level level2) const;
|
Level level2) const override;
|
||||||
virtual bool levelLess(Level level1,
|
bool levelLess(Level level1,
|
||||||
Level level2) const;
|
Level level2) const override;
|
||||||
virtual void incrLevel(Level &level) const;
|
void incrLevel(Level &level) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ public:
|
||||||
comp_(comp),
|
comp_(comp),
|
||||||
min_heap_comp_(comp)
|
min_heap_comp_(comp)
|
||||||
{
|
{
|
||||||
heap_.reserve(max_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy constructor
|
// Copy constructor
|
||||||
|
|
@ -107,7 +106,12 @@ public:
|
||||||
setMaxSize(size_t max_size)
|
setMaxSize(size_t max_size)
|
||||||
{
|
{
|
||||||
max_size_ = max_size;
|
max_size_ = max_size;
|
||||||
heap_.reserve(max_size);
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reserve(size_t size)
|
||||||
|
{
|
||||||
|
heap_.reserve(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert an element into the heap.
|
// Insert an element into the heap.
|
||||||
|
|
@ -172,8 +176,6 @@ public:
|
||||||
{
|
{
|
||||||
// Convert heap to sorted vector (best to worst)
|
// Convert heap to sorted vector (best to worst)
|
||||||
std::sort_heap(heap_.begin(), heap_.end(), min_heap_comp_);
|
std::sort_heap(heap_.begin(), heap_.end(), min_heap_comp_);
|
||||||
// Reverse to get best first (according to user's comparison)
|
|
||||||
std::reverse(heap_.begin(), heap_.end());
|
|
||||||
std::vector<T> result = std::move(heap_);
|
std::vector<T> result = std::move(heap_);
|
||||||
heap_.clear();
|
heap_.clear();
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -181,11 +183,10 @@ public:
|
||||||
|
|
||||||
// Extract all elements sorted from best to worst (const version).
|
// Extract all elements sorted from best to worst (const version).
|
||||||
// Creates a copy since we can't modify the heap.
|
// Creates a copy since we can't modify the heap.
|
||||||
std::vector<T> extract() const
|
std::vector<T> contents() const
|
||||||
{
|
{
|
||||||
std::vector<T> temp_heap = heap_;
|
std::vector<T> temp_heap = heap_;
|
||||||
std::sort_heap(temp_heap.begin(), temp_heap.end(), min_heap_comp_);
|
std::sort_heap(temp_heap.begin(), temp_heap.end(), min_heap_comp_);
|
||||||
std::reverse(temp_heap.begin(), temp_heap.end());
|
|
||||||
return temp_heap;
|
return temp_heap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,7 +246,7 @@ private:
|
||||||
Compare comp_;
|
Compare comp_;
|
||||||
explicit MinHeapCompare(const Compare& c) : comp_(c) {}
|
explicit MinHeapCompare(const Compare& c) : comp_(c) {}
|
||||||
bool operator()(const T& a, const T& b) const {
|
bool operator()(const T& a, const T& b) const {
|
||||||
return comp_(b, a); // Inverted: worst is at root
|
return comp_(a, b); // comp = less puts largest at root (worst)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,8 +264,8 @@ class ConcreteCellPortBitIterator : public Iterator<ConcretePort*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual ConcretePort *next();
|
ConcretePort *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void findNext();
|
void findNext();
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "StringSeq.hh"
|
#include <string>
|
||||||
|
|
||||||
|
#include "StringUtil.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -38,10 +40,10 @@ void
|
||||||
registerDelayCalcs();
|
registerDelayCalcs();
|
||||||
// Register a delay calculator for the set_delay_calc command.
|
// Register a delay calculator for the set_delay_calc command.
|
||||||
void
|
void
|
||||||
registerDelayCalc(const char *name,
|
registerDelayCalc(const std::string &name,
|
||||||
MakeArcDelayCalc maker);
|
MakeArcDelayCalc maker);
|
||||||
bool
|
bool
|
||||||
isDelayCalcName(const char *name);
|
isDelayCalcName(const std::string &name);
|
||||||
StringSeq
|
StringSeq
|
||||||
delayCalcNames();
|
delayCalcNames();
|
||||||
void
|
void
|
||||||
|
|
@ -49,7 +51,7 @@ deleteDelayCalcs();
|
||||||
|
|
||||||
// Make a registered delay calculator by name.
|
// Make a registered delay calculator by name.
|
||||||
ArcDelayCalc *
|
ArcDelayCalc *
|
||||||
makeDelayCalc(const char *name,
|
makeDelayCalc(const std::string &name,
|
||||||
StaState *sta);
|
StaState *sta);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -427,8 +427,8 @@ class VertexIterator : public Iterator<Vertex*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VertexIterator(Graph *graph);
|
VertexIterator(Graph *graph);
|
||||||
virtual bool hasNext() { return vertex_ || bidir_vertex_; }
|
bool hasNext() override { return vertex_ || bidir_vertex_; }
|
||||||
virtual Vertex *next();
|
Vertex *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool findNextPin();
|
bool findNextPin();
|
||||||
|
|
@ -450,8 +450,8 @@ public:
|
||||||
const Graph *graph);
|
const Graph *graph);
|
||||||
VertexInEdgeIterator(VertexId vertex_id,
|
VertexInEdgeIterator(VertexId vertex_id,
|
||||||
const Graph *graph);
|
const Graph *graph);
|
||||||
bool hasNext() { return (next_ != nullptr); }
|
bool hasNext() override { return (next_ != nullptr); }
|
||||||
Edge *next();
|
Edge *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Edge *next_;
|
Edge *next_;
|
||||||
|
|
@ -463,8 +463,8 @@ class VertexOutEdgeIterator : public VertexEdgeIterator
|
||||||
public:
|
public:
|
||||||
VertexOutEdgeIterator(Vertex *vertex,
|
VertexOutEdgeIterator(Vertex *vertex,
|
||||||
const Graph *graph);
|
const Graph *graph);
|
||||||
bool hasNext() { return (next_ != nullptr); }
|
bool hasNext() override { return (next_ != nullptr); }
|
||||||
Edge *next();
|
Edge *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Edge *next_;
|
Edge *next_;
|
||||||
|
|
@ -478,8 +478,8 @@ public:
|
||||||
EdgesThruHierPinIterator(const Pin *hpin,
|
EdgesThruHierPinIterator(const Pin *hpin,
|
||||||
Network *network,
|
Network *network,
|
||||||
Graph *graph);
|
Graph *graph);
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual Edge *next();
|
Edge *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EdgeSet edges_;
|
EdgeSet edges_;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNext() { return seq_ && itr_ != seq_->end(); }
|
bool hasNext() override { return seq_ && itr_ != seq_->end(); }
|
||||||
OBJ_TYPE next() { return *itr_++; }
|
OBJ_TYPE next() override { return *itr_++; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const VECTOR_TYPE *seq_;
|
const VECTOR_TYPE *seq_;
|
||||||
|
|
@ -80,8 +80,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNext() { return map_ && itr_ != map_->end(); }
|
bool hasNext() override { return map_ && itr_ != map_->end(); }
|
||||||
OBJ_TYPE next() {
|
OBJ_TYPE next() override {
|
||||||
OBJ_TYPE next = itr_->second;
|
OBJ_TYPE next = itr_->second;
|
||||||
itr_++;
|
itr_++;
|
||||||
return next;
|
return next;
|
||||||
|
|
@ -108,8 +108,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNext() { return set_ && itr_ != set_->end(); }
|
bool hasNext() override { return set_ && itr_ != set_->end(); }
|
||||||
OBJ_TYPE next() { return *itr_++; }
|
OBJ_TYPE next() override { return *itr_++; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const SET_TYPE *set_;
|
const SET_TYPE *set_;
|
||||||
|
|
|
||||||
|
|
@ -458,8 +458,8 @@ class LibertyCellIterator : public Iterator<LibertyCell*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LibertyCellIterator(const LibertyLibrary *library);
|
LibertyCellIterator(const LibertyLibrary *library);
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
LibertyCell *next();
|
LibertyCell *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteLibraryCellIterator iter_;
|
ConcreteLibraryCellIterator iter_;
|
||||||
|
|
@ -715,8 +715,8 @@ class LibertyCellPortIterator : public Iterator<LibertyPort*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LibertyCellPortIterator(const LibertyCell *cell);
|
LibertyCellPortIterator(const LibertyCell *cell);
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
LibertyPort *next();
|
LibertyPort *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteCellPortIterator iter_;
|
ConcreteCellPortIterator iter_;
|
||||||
|
|
@ -727,8 +727,8 @@ class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
|
||||||
public:
|
public:
|
||||||
LibertyCellPortBitIterator(const LibertyCell *cell);
|
LibertyCellPortBitIterator(const LibertyCell *cell);
|
||||||
virtual ~LibertyCellPortBitIterator();
|
virtual ~LibertyCellPortBitIterator();
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
LibertyPort *next();
|
LibertyPort *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteCellPortBitIterator *iter_;
|
ConcreteCellPortBitIterator *iter_;
|
||||||
|
|
@ -980,8 +980,8 @@ class LibertyPortMemberIterator : public Iterator<LibertyPort*>
|
||||||
public:
|
public:
|
||||||
LibertyPortMemberIterator(const LibertyPort *port);
|
LibertyPortMemberIterator(const LibertyPort *port);
|
||||||
virtual ~LibertyPortMemberIterator();
|
virtual ~LibertyPortMemberIterator();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual LibertyPort *next();
|
LibertyPort *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcretePortMemberIterator *iter_;
|
ConcretePortMemberIterator *iter_;
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ public:
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float min_slack,
|
float min_slack,
|
||||||
float max_slack,
|
float max_slack,
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
|
||||||
|
|
@ -204,8 +204,8 @@ public:
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
virtual ~VertexPathIterator();
|
virtual ~VertexPathIterator();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual Path *next();
|
Path *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void findNext();
|
void findNext();
|
||||||
|
|
|
||||||
|
|
@ -153,9 +153,13 @@ public:
|
||||||
|
|
||||||
static bool less(const PathEnd *path_end1,
|
static bool less(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2,
|
const PathEnd *path_end2,
|
||||||
|
// Compare slack (if constrained), or arrival when false.
|
||||||
|
bool cmp_slack,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
static int cmp(const PathEnd *path_end1,
|
static int cmp(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2,
|
const PathEnd *path_end2,
|
||||||
|
// Compare slack (if constrained), or arrival when false.
|
||||||
|
bool cmp_slack,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
static int cmpSlack(const PathEnd *path_end1,
|
static int cmpSlack(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2,
|
const PathEnd *path_end2,
|
||||||
|
|
@ -611,11 +615,13 @@ protected:
|
||||||
class PathEndLess
|
class PathEndLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PathEndLess(const StaState *sta);
|
PathEndLess(bool cmp_slack,
|
||||||
|
const StaState *sta);
|
||||||
bool operator()(const PathEnd *path_end1,
|
bool operator()(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2) const;
|
const PathEnd *path_end2) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool cmp_slack_;
|
||||||
const StaState *sta_;
|
const StaState *sta_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -623,11 +629,13 @@ protected:
|
||||||
class PathEndSlackLess
|
class PathEndSlackLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PathEndSlackLess(const StaState *sta);
|
PathEndSlackLess(bool cmp_slack,
|
||||||
|
const StaState *sta);
|
||||||
bool operator()(const PathEnd *path_end1,
|
bool operator()(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2) const;
|
const PathEnd *path_end2) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool cmp_slack_;
|
||||||
const StaState *sta_;
|
const StaState *sta_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,12 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "BoundedHeap.hh"
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
|
#include "PathEnd.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -48,7 +50,6 @@ using PathGroupSeq = std::vector<PathGroup*>;
|
||||||
class PathGroup
|
class PathGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~PathGroup();
|
|
||||||
// Path group that compares compare slacks.
|
// Path group that compares compare slacks.
|
||||||
static PathGroup *makePathGroupArrival(const char *name,
|
static PathGroup *makePathGroupArrival(const char *name,
|
||||||
int group_path_count,
|
int group_path_count,
|
||||||
|
|
@ -66,9 +67,9 @@ public:
|
||||||
float min_slack,
|
float min_slack,
|
||||||
float max_slack,
|
float max_slack,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
const char *name() const { return name_.c_str(); }
|
const std::string &name() const { return name_; }
|
||||||
const MinMax *minMax() const { return min_max_;}
|
const MinMax *minMax() const { return min_max_;}
|
||||||
const PathEndSeq &pathEnds() const { return path_ends_; }
|
PathEndSeq pathEnds() const;
|
||||||
void insert(PathEnd *path_end);
|
void insert(PathEnd *path_end);
|
||||||
// Push group_path_count into path_ends.
|
// Push group_path_count into path_ends.
|
||||||
void pushEnds(PathEndSeq &path_ends);
|
void pushEnds(PathEndSeq &path_ends);
|
||||||
|
|
@ -76,15 +77,14 @@ public:
|
||||||
bool saveable(PathEnd *path_end);
|
bool saveable(PathEnd *path_end);
|
||||||
bool enumMinSlackUnderMin(PathEnd *path_end);
|
bool enumMinSlackUnderMin(PathEnd *path_end);
|
||||||
int maxPaths() const { return group_path_count_; }
|
int maxPaths() const { return group_path_count_; }
|
||||||
PathEndSeq &pathEnds() { return path_ends_; }
|
|
||||||
// This does NOT delete the path ends.
|
// This does NOT delete the path ends.
|
||||||
void clear();
|
void clear();
|
||||||
static size_t group_path_count_max;
|
static int group_path_count_max;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PathGroup(const char *name,
|
PathGroup(const char *name,
|
||||||
size_t group_path_count,
|
int group_path_count,
|
||||||
size_t endpoint_path_count,
|
int endpoint_path_count,
|
||||||
bool unique_pins,
|
bool unique_pins,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float min_slack,
|
float min_slack,
|
||||||
|
|
@ -92,21 +92,17 @@ protected:
|
||||||
bool cmp_slack,
|
bool cmp_slack,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
void ensureSortedMaxPaths();
|
|
||||||
void prune();
|
|
||||||
void sort();
|
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
size_t group_path_count_;
|
int group_path_count_;
|
||||||
size_t endpoint_path_count_;
|
int endpoint_path_count_;
|
||||||
bool unique_pins_;
|
bool unique_pins_;
|
||||||
bool unique_edges_;
|
bool unique_edges_;
|
||||||
float slack_min_;
|
float slack_min_;
|
||||||
float slack_max_;
|
float slack_max_;
|
||||||
PathEndSeq path_ends_;
|
|
||||||
const MinMax *min_max_;
|
const MinMax *min_max_;
|
||||||
bool compare_slack_;
|
bool cmp_slack_;
|
||||||
float threshold_;
|
BoundedHeap<PathEnd*, PathEndLess> heap_;
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
const StaState *sta_;
|
const StaState *sta_;
|
||||||
};
|
};
|
||||||
|
|
@ -120,7 +116,7 @@ public:
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
@ -144,7 +140,7 @@ public:
|
||||||
PathGroup *findPathGroup(const Clock *clock,
|
PathGroup *findPathGroup(const Clock *clock,
|
||||||
const MinMax *min_max) const;
|
const MinMax *min_max) const;
|
||||||
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
||||||
static StdStringSeq pathGroupNames(const PathEnd *path_end,
|
static StringSeq pathGroupNames(const PathEnd *path_end,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
static const char *asyncPathGroupName() { return async_group_name_; }
|
static const char *asyncPathGroupName() { return async_group_name_; }
|
||||||
static const char *pathDelayGroupName() { return path_delay_group_name_; }
|
static const char *pathDelayGroupName() { return path_delay_group_name_; }
|
||||||
|
|
@ -184,17 +180,17 @@ protected:
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
StdStringSet &group_names,
|
StringSet &group_names,
|
||||||
bool setup_hold,
|
bool setup_hold,
|
||||||
bool async,
|
bool async,
|
||||||
bool gated_clk,
|
bool gated_clk,
|
||||||
bool unconstrained,
|
bool unconstrained,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
bool reportGroup(const char *group_name,
|
bool reportGroup(const char *group_name,
|
||||||
StdStringSet &group_names) const;
|
StringSet &group_names) const;
|
||||||
static GroupPath *groupPathTo(const PathEnd *path_end,
|
static GroupPath *groupPathTo(const PathEnd *path_end,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
StdStringSeq pathGroupNames();
|
StringSeq pathGroupNames();
|
||||||
|
|
||||||
const Mode *mode_;
|
const Mode *mode_;
|
||||||
int group_path_count_;
|
int group_path_count_;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ enum class PwrActivityOrigin
|
||||||
propagated,
|
propagated,
|
||||||
clock,
|
clock,
|
||||||
constant,
|
constant,
|
||||||
defaulted,
|
|
||||||
unknown
|
unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "StringSeq.hh"
|
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "MinMax.hh"
|
#include "MinMax.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
@ -149,7 +148,7 @@ using ExceptionPathPtHash = std::map<size_t, ExceptionPathSet>;
|
||||||
using ClockLatencies = std::set<ClockLatency*, ClockLatencyLess>;
|
using ClockLatencies = std::set<ClockLatency*, ClockLatencyLess>;
|
||||||
using EdgeClockLatencyMap = std::map<PinPair, ClockLatency*, PinPairLess>;
|
using EdgeClockLatencyMap = std::map<PinPair, ClockLatency*, PinPairLess>;
|
||||||
using PinClockUncertaintyMap = std::map<const Pin*, ClockUncertainties*>;
|
using PinClockUncertaintyMap = std::map<const Pin*, ClockUncertainties*>;
|
||||||
using InterClockUncertaintySet = std::set<InterClockUncertainty*, InterClockUncertaintyLess>;
|
using InterClockUncertaintySet=std::set<InterClockUncertainty*,InterClockUncertaintyLess>;
|
||||||
using ClockGatingCheckMap = std::map<const Clock*, ClockGatingCheck*>;
|
using ClockGatingCheckMap = std::map<const Clock*, ClockGatingCheck*>;
|
||||||
using InstanceClockGatingCheckMap = std::map<const Instance*, ClockGatingCheck*>;
|
using InstanceClockGatingCheckMap = std::map<const Instance*, ClockGatingCheck*>;
|
||||||
using PinClockGatingCheckMap = std::map<const Pin*, ClockGatingCheck*>;
|
using PinClockGatingCheckMap = std::map<const Pin*, ClockGatingCheck*>;
|
||||||
|
|
@ -1306,6 +1305,7 @@ protected:
|
||||||
bool clk_hpin_disables_valid_;
|
bool clk_hpin_disables_valid_;
|
||||||
PinSet propagated_clk_pins_;
|
PinSet propagated_clk_pins_;
|
||||||
ClockLatencies clk_latencies_;
|
ClockLatencies clk_latencies_;
|
||||||
|
PinSet clk_latency_pins_;
|
||||||
EdgeClockLatencyMap edge_clk_latency_map_;
|
EdgeClockLatencyMap edge_clk_latency_map_;
|
||||||
ClockInsertions clk_insertions_;
|
ClockInsertions clk_insertions_;
|
||||||
PinClockUncertaintyMap pin_clk_uncertainty_map_;
|
PinClockUncertaintyMap pin_clk_uncertainty_map_;
|
||||||
|
|
|
||||||
|
|
@ -100,14 +100,14 @@ public:
|
||||||
bool unconstrained,
|
bool unconstrained,
|
||||||
const SceneSeq &scenes,
|
const SceneSeq &scenes,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
size_t group_path_count,
|
int group_path_count,
|
||||||
size_t endpoint_path_count,
|
int endpoint_path_count,
|
||||||
bool unique_pins,
|
bool unique_pins,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
bool sort_by_slack,
|
bool sort_by_slack,
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "VectorMap.hh"
|
#include "VectorMap.hh"
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "MinMaxValues.hh"
|
#include "MinMaxValues.hh"
|
||||||
#include "Delay.hh"
|
#include "Delay.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "StringSeq.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
@ -126,11 +125,11 @@ public:
|
||||||
void setThreadCount(int thread_count);
|
void setThreadCount(int thread_count);
|
||||||
|
|
||||||
// define_corners compatibility.
|
// define_corners compatibility.
|
||||||
void makeScenes(StringSeq *scene_names);
|
void makeScenes(const StringSeq &scene_names);
|
||||||
void makeScene(const std::string &name,
|
void makeScene(const std::string &name,
|
||||||
const std::string &mode_name,
|
const std::string &mode_name,
|
||||||
const StdStringSeq &liberty_min_files,
|
const StringSeq &liberty_min_files,
|
||||||
const StdStringSeq &liberty_max_files,
|
const StringSeq &liberty_max_files,
|
||||||
const std::string &spef_min_file,
|
const std::string &spef_min_file,
|
||||||
const std::string &spef_max_file);
|
const std::string &spef_max_file);
|
||||||
Scene *findScene(const std::string &name) const;
|
Scene *findScene(const std::string &name) const;
|
||||||
|
|
@ -653,7 +652,7 @@ public:
|
||||||
const Sdc *sdc) __attribute__ ((deprecated));
|
const Sdc *sdc) __attribute__ ((deprecated));
|
||||||
bool isPathGroupName(const char *group_name,
|
bool isPathGroupName(const char *group_name,
|
||||||
const Sdc *sdc) const;
|
const Sdc *sdc) const;
|
||||||
StdStringSeq pathGroupNames(const Sdc *sdc) const;
|
StringSeq pathGroupNames(const Sdc *sdc) const;
|
||||||
void resetPath(ExceptionFrom *from,
|
void resetPath(ExceptionFrom *from,
|
||||||
ExceptionThruSeq *thrus,
|
ExceptionThruSeq *thrus,
|
||||||
ExceptionTo *to,
|
ExceptionTo *to,
|
||||||
|
|
@ -966,7 +965,7 @@ public:
|
||||||
bool sort_by_slack,
|
bool sort_by_slack,
|
||||||
// Path groups to report.
|
// Path groups to report.
|
||||||
// Empty list reports all groups.
|
// Empty list reports all groups.
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
// Predicates to filter the type of path
|
// Predicates to filter the type of path
|
||||||
// ends returned.
|
// ends returned.
|
||||||
bool setup,
|
bool setup,
|
||||||
|
|
@ -976,7 +975,7 @@ public:
|
||||||
bool clk_gating_setup,
|
bool clk_gating_setup,
|
||||||
bool clk_gating_hold);
|
bool clk_gating_hold);
|
||||||
void setReportPathFormat(ReportPathFormat format);
|
void setReportPathFormat(ReportPathFormat format);
|
||||||
void setReportPathFieldOrder(StringSeq *field_names);
|
void setReportPathFieldOrder(const StringSeq &field_names);
|
||||||
void setReportPathFields(bool report_input_pin,
|
void setReportPathFields(bool report_input_pin,
|
||||||
bool report_hier_pins,
|
bool report_hier_pins,
|
||||||
bool report_net,
|
bool report_net,
|
||||||
|
|
@ -1388,7 +1387,7 @@ public:
|
||||||
LibertyLibrarySeq *map_libs);
|
LibertyLibrarySeq *map_libs);
|
||||||
LibertyCellSeq *equivCells(LibertyCell *cell);
|
LibertyCellSeq *equivCells(LibertyCell *cell);
|
||||||
|
|
||||||
void writePathSpice(Path *path,
|
void writePathSpice(const Path *path,
|
||||||
const char *spice_filename,
|
const char *spice_filename,
|
||||||
const char *subckt_filename,
|
const char *subckt_filename,
|
||||||
const char *lib_subckt_filename,
|
const char *lib_subckt_filename,
|
||||||
|
|
@ -1588,8 +1587,8 @@ protected:
|
||||||
void setThreadCount1(int thread_count);
|
void setThreadCount1(int thread_count);
|
||||||
void updateLibertyScenes();
|
void updateLibertyScenes();
|
||||||
void updateSceneLiberty(Scene *scene,
|
void updateSceneLiberty(Scene *scene,
|
||||||
const StdStringSeq &liberty_min_files,
|
const StringSeq &liberty_min_files,
|
||||||
const StdStringSeq &liberty_max_files);
|
const StringSeq &liberty_max_files);
|
||||||
|
|
||||||
Scene *makeScene(const std::string &name,
|
Scene *makeScene(const std::string &name,
|
||||||
Mode *mode,
|
Mode *mode,
|
||||||
|
|
|
||||||
|
|
@ -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 <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "Machine.hh" // __attribute__
|
#include "Machine.hh" // __attribute__
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
using StdStringSeq = std::vector<std::string>;
|
using StringSeq = std::vector<std::string>;
|
||||||
|
using StringSet = std::set<std::string>;
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
stringEq(const char *str1,
|
stringEq(const char *str1,
|
||||||
|
|
@ -204,7 +206,7 @@ void
|
||||||
trimRight(std::string &str);
|
trimRight(std::string &str);
|
||||||
|
|
||||||
// Spit text into delimiter separated tokens and skip whitepace.
|
// Spit text into delimiter separated tokens and skip whitepace.
|
||||||
StdStringSeq
|
StringSeq
|
||||||
parseTokens(const std::string &s,
|
parseTokens(const std::string &s,
|
||||||
const char delimiter);
|
const char delimiter);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,33 +22,24 @@
|
||||||
//
|
//
|
||||||
// This notice may not be removed or altered from any source distribution.
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
#include "ArcDelayCalc.hh"
|
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "StringSeq.hh"
|
|
||||||
|
|
||||||
#include <tcl.h>
|
#include <tcl.h>
|
||||||
|
|
||||||
|
#include "ArcDelayCalc.hh"
|
||||||
|
#include "StringUtil.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
#if TCL_MAJOR_VERSION < 9
|
#if TCL_MAJOR_VERSION < 9
|
||||||
typedef int Tcl_Size;
|
typedef int Tcl_Size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
StringSet *
|
StringSeq
|
||||||
tclListSetConstChar(Tcl_Obj *const source,
|
|
||||||
Tcl_Interp *interp);
|
|
||||||
|
|
||||||
StringSeq *
|
|
||||||
tclListSeqConstChar(Tcl_Obj *const source,
|
|
||||||
Tcl_Interp *interp);
|
|
||||||
|
|
||||||
StdStringSeq
|
|
||||||
tclListSeqStdString(Tcl_Obj *const source,
|
tclListSeqStdString(Tcl_Obj *const source,
|
||||||
Tcl_Interp *interp);
|
Tcl_Interp *interp);
|
||||||
StdStringSeq *
|
StringSeq *
|
||||||
tclListSeqStdStringPtr(Tcl_Obj *const source,
|
tclListSeqStdStringPtr(Tcl_Obj *const source,
|
||||||
Tcl_Interp *interp);
|
Tcl_Interp *interp);
|
||||||
StdStringSet *
|
StringSet *
|
||||||
tclListSetStdString(Tcl_Obj *const source,
|
tclListSetStdString(Tcl_Obj *const source,
|
||||||
Tcl_Interp *interp);
|
Tcl_Interp *interp);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,7 @@ public:
|
||||||
static const RiseFall *fall() { return &fall_; }
|
static const RiseFall *fall() { return &fall_; }
|
||||||
static int riseIndex() { return rise_.sdf_triple_index_; }
|
static int riseIndex() { return rise_.sdf_triple_index_; }
|
||||||
static int fallIndex() { return fall_.sdf_triple_index_; }
|
static int fallIndex() { return fall_.sdf_triple_index_; }
|
||||||
const std::string &to_string_long() const { return name_; }
|
const std::string &to_string(bool use_short = false) const;
|
||||||
const std::string &to_string() const { return short_name_; }
|
|
||||||
const char *name() const { return name_.c_str(); }
|
const char *name() const { return name_.c_str(); }
|
||||||
const char *shortName() const { return short_name_.c_str(); }
|
const char *shortName() const { return short_name_.c_str(); }
|
||||||
int index() const { return sdf_triple_index_; }
|
int index() const { return sdf_triple_index_; }
|
||||||
|
|
@ -94,7 +93,7 @@ public:
|
||||||
static const RiseFallBoth *rise() { return &rise_; }
|
static const RiseFallBoth *rise() { return &rise_; }
|
||||||
static const RiseFallBoth *fall() { return &fall_; }
|
static const RiseFallBoth *fall() { return &fall_; }
|
||||||
static const RiseFallBoth *riseFall() { return &rise_fall_; }
|
static const RiseFallBoth *riseFall() { return &rise_fall_; }
|
||||||
const std::string &to_string() const { return short_name_; }
|
const std::string &to_string(bool use_short = false) const;
|
||||||
const char *name() const { return name_.c_str(); }
|
const char *name() const { return name_.c_str(); }
|
||||||
const char *shortName() const { return short_name_.c_str(); }
|
const char *shortName() const { return short_name_.c_str(); }
|
||||||
int index() const { return sdf_triple_index_; }
|
int index() const { return sdf_triple_index_; }
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "StringSet.hh"
|
#include "StringUtil.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -173,7 +173,7 @@ protected:
|
||||||
void makeNamedPortRefCellPorts(Cell *cell,
|
void makeNamedPortRefCellPorts(Cell *cell,
|
||||||
VerilogModule *module,
|
VerilogModule *module,
|
||||||
VerilogNet *mod_port,
|
VerilogNet *mod_port,
|
||||||
StdStringSet &port_names);
|
StringSet &port_names);
|
||||||
void checkModuleDcls(VerilogModule *module,
|
void checkModuleDcls(VerilogModule *module,
|
||||||
std::set<std::string> &port_names);
|
std::set<std::string> &port_names);
|
||||||
void makeModuleInstBody(VerilogModule *module,
|
void makeModuleInstBody(VerilogModule *module,
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
#include "Debug.hh"
|
#include "Debug.hh"
|
||||||
#include "Error.hh"
|
#include "Error.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "PatternMatch.hh"
|
#include "PatternMatch.hh"
|
||||||
#include "Units.hh"
|
#include "Units.hh"
|
||||||
#include "Transition.hh"
|
#include "Transition.hh"
|
||||||
|
|
@ -1367,17 +1366,14 @@ LibertyCell::makeTimingArcPortMaps()
|
||||||
LibertyPort *from = arc_set->from();
|
LibertyPort *from = arc_set->from();
|
||||||
LibertyPort *to = arc_set->to();
|
LibertyPort *to = arc_set->to();
|
||||||
if (from && to) {
|
if (from && to) {
|
||||||
LibertyPortPair from_to_pair(from, to);
|
TimingArcSetSeq &sets = port_timing_arc_set_map_[{from, to}];
|
||||||
TimingArcSetSeq &sets = port_timing_arc_set_map_[from_to_pair];
|
|
||||||
sets.push_back(arc_set);
|
sets.push_back(arc_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
LibertyPortPair from_pair(from, nullptr);
|
TimingArcSetSeq &from_sets = port_timing_arc_set_map_[{from, nullptr}];
|
||||||
TimingArcSetSeq &from_sets = port_timing_arc_set_map_[from_pair];
|
|
||||||
from_sets.push_back(arc_set);
|
from_sets.push_back(arc_set);
|
||||||
|
|
||||||
LibertyPortPair to_pair(nullptr, to);
|
TimingArcSetSeq &to_sets = port_timing_arc_set_map_[{nullptr, to}];
|
||||||
TimingArcSetSeq &to_sets = port_timing_arc_set_map_[to_pair];
|
|
||||||
to_sets.push_back(arc_set);
|
to_sets.push_back(arc_set);
|
||||||
|
|
||||||
const TimingRole *role = arc_set->role();
|
const TimingRole *role = arc_set->role();
|
||||||
|
|
@ -1411,8 +1407,7 @@ LibertyCell::timingArcSets(const LibertyPort *from,
|
||||||
const LibertyPort *to) const
|
const LibertyPort *to) const
|
||||||
{
|
{
|
||||||
static const TimingArcSetSeq null_set;
|
static const TimingArcSetSeq null_set;
|
||||||
const LibertyPortPair port_pair(from, to);
|
auto itr = port_timing_arc_set_map_.find({from, to});
|
||||||
auto itr = port_timing_arc_set_map_.find(port_pair);
|
|
||||||
return (itr == port_timing_arc_set_map_.end()) ? null_set : itr->second;
|
return (itr == port_timing_arc_set_map_.end()) ? null_set : itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1437,8 +1432,8 @@ LibertyCell::timingArcSetCount() const
|
||||||
bool
|
bool
|
||||||
LibertyCell::hasTimingArcs(LibertyPort *port) const
|
LibertyCell::hasTimingArcs(LibertyPort *port) const
|
||||||
{
|
{
|
||||||
return port_timing_arc_set_map_.contains(LibertyPortPair(port, nullptr))
|
return port_timing_arc_set_map_.contains({port, nullptr})
|
||||||
|| port_timing_arc_set_map_.contains(LibertyPortPair(nullptr, port));
|
|| port_timing_arc_set_map_.contains({nullptr, port});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,7 @@ LibertyReader::LibertyReader(const char *filename,
|
||||||
debug_(network->debug()),
|
debug_(network->debug()),
|
||||||
network_(network),
|
network_(network),
|
||||||
builder_(debug_, report_),
|
builder_(debug_, report_),
|
||||||
library_(nullptr),
|
library_(nullptr)
|
||||||
first_cell_(true)
|
|
||||||
{
|
{
|
||||||
defineVisitors();
|
defineVisitors();
|
||||||
}
|
}
|
||||||
|
|
@ -148,13 +147,13 @@ LibertyReader::beginLibrary(const LibertyGroup *library_group,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyReader::endLibrary(const LibertyGroup *group,
|
LibertyReader::endLibrary(const LibertyGroup *library_group,
|
||||||
LibertyGroup *)
|
LibertyGroup *)
|
||||||
{
|
{
|
||||||
// If a library hasno cells endCell is not called.
|
// If a library has no cells endCell is not called.
|
||||||
if (first_cell_)
|
readLibraryAttributes(library_group);
|
||||||
readLibraryAttributes(group);
|
checkThresholds(library_group);
|
||||||
delete group;
|
delete library_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -167,12 +166,7 @@ LibertyReader::endCell(const LibertyGroup *cell_group,
|
||||||
// Normally they are all defined by the first cell, but there
|
// Normally they are all defined by the first cell, but there
|
||||||
// are libraries that define table templates and bus tyupes
|
// are libraries that define table templates and bus tyupes
|
||||||
// between cells.
|
// between cells.
|
||||||
if (first_cell_)
|
readLibraryAttributes(library_group);
|
||||||
readLibraryAttributes(library_group);
|
|
||||||
else {
|
|
||||||
readTableTemplates(library_group);
|
|
||||||
readBusTypes(nullptr, library_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *name = cell_group->firstName();
|
const char *name = cell_group->firstName();
|
||||||
if (name) {
|
if (name) {
|
||||||
|
|
@ -182,8 +176,10 @@ LibertyReader::endCell(const LibertyGroup *cell_group,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
libWarn(1193, cell_group, "cell missing name.");
|
libWarn(1193, cell_group, "cell missing name.");
|
||||||
|
|
||||||
|
// Delete the cell group and preceding library attributes
|
||||||
|
// and groups so they are not revisited and reduce memory peak.
|
||||||
library_group->clear();
|
library_group->clear();
|
||||||
first_cell_ = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -524,24 +520,28 @@ void
|
||||||
LibertyReader::readThresholds(const LibertyGroup *library_group)
|
LibertyReader::readThresholds(const LibertyGroup *library_group)
|
||||||
{
|
{
|
||||||
for (const RiseFall *rf : RiseFall::range()) {
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
std::string suffix = rf->to_string_long();
|
std::string suffix = rf->to_string();
|
||||||
readLibAttrFloat(library_group, ("input_threshold_pct_" + suffix).c_str(),
|
readLibAttrFloat(library_group, ("input_threshold_pct_" + suffix).c_str(),
|
||||||
&LibertyLibrary::setInputThreshold, rf, 0.01F);
|
&LibertyLibrary::setInputThreshold, rf, 0.01F);
|
||||||
if (library_->inputThreshold(rf) == 0.0)
|
|
||||||
libWarn(1145, library_group, "input_threshold_pct_%s not found.", rf->name());
|
|
||||||
|
|
||||||
readLibAttrFloat(library_group, ("output_threshold_pct_" + suffix).c_str(),
|
readLibAttrFloat(library_group, ("output_threshold_pct_" + suffix).c_str(),
|
||||||
&LibertyLibrary::setOutputThreshold, rf, 0.01F);
|
&LibertyLibrary::setOutputThreshold, rf, 0.01F);
|
||||||
if (library_->outputThreshold(rf) == 0.0)
|
|
||||||
libWarn(1146, library_group, "output_threshold_pct_%s not found.", rf->name());
|
|
||||||
|
|
||||||
readLibAttrFloat(library_group, ("slew_lower_threshold_pct_" + suffix).c_str(),
|
readLibAttrFloat(library_group, ("slew_lower_threshold_pct_" + suffix).c_str(),
|
||||||
&LibertyLibrary::setSlewLowerThreshold, rf, 0.01F);
|
&LibertyLibrary::setSlewLowerThreshold, rf, 0.01F);
|
||||||
if (library_->slewLowerThreshold(rf) == 0.0)
|
|
||||||
libWarn(1147, library_group, "slew_lower_threshold_pct_%s not found.", rf->name());
|
|
||||||
|
|
||||||
readLibAttrFloat(library_group, ("slew_upper_threshold_pct_" + suffix).c_str(),
|
readLibAttrFloat(library_group, ("slew_upper_threshold_pct_" + suffix).c_str(),
|
||||||
&LibertyLibrary::setSlewUpperThreshold, rf, 0.01F);
|
&LibertyLibrary::setSlewUpperThreshold, rf, 0.01F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibertyReader::checkThresholds(const LibertyGroup *library_group) const
|
||||||
|
{
|
||||||
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
|
if (library_->inputThreshold(rf) == 0.0)
|
||||||
|
libWarn(1145, library_group, "input_threshold_pct_%s not found.", rf->name());
|
||||||
|
if (library_->outputThreshold(rf) == 0.0)
|
||||||
|
libWarn(1146, library_group, "output_threshold_pct_%s not found.", rf->name());
|
||||||
|
if (library_->slewLowerThreshold(rf) == 0.0)
|
||||||
|
libWarn(1147, library_group, "slew_lower_threshold_pct_%s not found.", rf->name());
|
||||||
if (library_->slewUpperThreshold(rf) == 0.0)
|
if (library_->slewUpperThreshold(rf) == 0.0)
|
||||||
libWarn(1148, library_group, "slew_upper_threshold_pct_%s not found.", rf->name());
|
libWarn(1148, library_group, "slew_upper_threshold_pct_%s not found.", rf->name());
|
||||||
}
|
}
|
||||||
|
|
@ -907,7 +907,7 @@ void
|
||||||
LibertyReader::readSlewDegradations(const LibertyGroup *library_group)
|
LibertyReader::readSlewDegradations(const LibertyGroup *library_group)
|
||||||
{
|
{
|
||||||
for (const RiseFall *rf : RiseFall::range()) {
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
const std::string group_name = rf->to_string_long() + "_transition_degradation";
|
const std::string group_name = rf->to_string() + "_transition_degradation";
|
||||||
const LibertyGroup *degradation_group =
|
const LibertyGroup *degradation_group =
|
||||||
library_group->findSubgroup(group_name.c_str());
|
library_group->findSubgroup(group_name.c_str());
|
||||||
if (degradation_group) {
|
if (degradation_group) {
|
||||||
|
|
@ -1480,7 +1480,7 @@ LibertyReader::readCapacitance(const LibertyPortSeq &ports,
|
||||||
for (LibertyPort *port : ports) {
|
for (LibertyPort *port : ports) {
|
||||||
// rise/fall_capacitance
|
// rise/fall_capacitance
|
||||||
for (const RiseFall *rf : RiseFall::range()) {
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
std::string attr_name = rf->to_string_long() + "_capacitance";
|
std::string attr_name = rf->to_string() + "_capacitance";
|
||||||
float cap;
|
float cap;
|
||||||
bool exists;
|
bool exists;
|
||||||
port_group->findAttrFloat(attr_name, cap, exists);
|
port_group->findAttrFloat(attr_name, cap, exists);
|
||||||
|
|
@ -1490,7 +1490,7 @@ LibertyReader::readCapacitance(const LibertyPortSeq &ports,
|
||||||
}
|
}
|
||||||
|
|
||||||
// rise/fall_capacitance_range(min_cap, max_cap);
|
// rise/fall_capacitance_range(min_cap, max_cap);
|
||||||
attr_name = rf->to_string_long() + "_capacitance_range";
|
attr_name = rf->to_string() + "_capacitance_range";
|
||||||
const LibertyComplexAttrSeq &range_attrs = port_group->findComplexAttrs(attr_name);
|
const LibertyComplexAttrSeq &range_attrs = port_group->findComplexAttrs(attr_name);
|
||||||
if (!range_attrs.empty()) {
|
if (!range_attrs.empty()) {
|
||||||
const LibertyComplexAttr *attr = range_attrs[0];
|
const LibertyComplexAttr *attr = range_attrs[0];
|
||||||
|
|
@ -1894,8 +1894,8 @@ LibertyReader::makeTimingArcs(LibertyCell *cell,
|
||||||
|
|
||||||
LibertyPort *related_output_port = findLibertyPort(cell, timing_group,
|
LibertyPort *related_output_port = findLibertyPort(cell, timing_group,
|
||||||
"related_output_pin");
|
"related_output_pin");
|
||||||
StdStringSeq related_port_names = findAttributStrings(timing_group, "related_pin");
|
StringSeq related_port_names = findAttributStrings(timing_group, "related_pin");
|
||||||
StdStringSeq related_bus_names=findAttributStrings(timing_group,"related_bus_pins");
|
StringSeq related_bus_names=findAttributStrings(timing_group,"related_bus_pins");
|
||||||
TimingType timing_type = timing_attrs->timingType();
|
TimingType timing_type = timing_attrs->timingType();
|
||||||
|
|
||||||
for (LibertyPort *to_port : ports) {
|
for (LibertyPort *to_port : ports) {
|
||||||
|
|
@ -2081,7 +2081,7 @@ LibertyReader::makeLinearModels(LibertyCell *cell,
|
||||||
{
|
{
|
||||||
LibertyLibrary *library = cell->libertyLibrary();
|
LibertyLibrary *library = cell->libertyLibrary();
|
||||||
for (const RiseFall *rf : RiseFall::range()) {
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
std::string intr_attr_name = "intrinsic_" + rf->to_string_long();
|
std::string intr_attr_name = "intrinsic_" + rf->to_string();
|
||||||
float intr = 0.0;
|
float intr = 0.0;
|
||||||
bool intr_exists;
|
bool intr_exists;
|
||||||
timing_group->findAttrFloat(intr_attr_name, intr, intr_exists);
|
timing_group->findAttrFloat(intr_attr_name, intr, intr_exists);
|
||||||
|
|
@ -2094,7 +2094,7 @@ LibertyReader::makeLinearModels(LibertyCell *cell,
|
||||||
if (timingTypeIsCheck(timing_attrs->timingType()))
|
if (timingTypeIsCheck(timing_attrs->timingType()))
|
||||||
model = new CheckLinearModel(cell, intr);
|
model = new CheckLinearModel(cell, intr);
|
||||||
else {
|
else {
|
||||||
std::string res_attr_name = rf->to_string_long() + "_resistance";
|
std::string res_attr_name = rf->to_string() + "_resistance";
|
||||||
float res = 0.0;
|
float res = 0.0;
|
||||||
bool res_exists;
|
bool res_exists;
|
||||||
timing_group->findAttrFloat(res_attr_name, res, res_exists);
|
timing_group->findAttrFloat(res_attr_name, res, res_exists);
|
||||||
|
|
@ -2117,18 +2117,18 @@ LibertyReader::makeTableModels(LibertyCell *cell,
|
||||||
{
|
{
|
||||||
bool found_model = false;
|
bool found_model = false;
|
||||||
for (const RiseFall *rf : RiseFall::range()) {
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
std::string delay_attr_name = "cell_" + rf->to_string_long();
|
std::string delay_attr_name = "cell_" + rf->to_string();
|
||||||
TableModel *delay = readGateTableModel(timing_group, delay_attr_name.c_str(), rf,
|
TableModel *delay = readGateTableModel(timing_group, delay_attr_name.c_str(), rf,
|
||||||
TableTemplateType::delay, time_scale_,
|
TableTemplateType::delay, time_scale_,
|
||||||
ScaleFactorType::cell);
|
ScaleFactorType::cell);
|
||||||
std::string transition_attr_name = rf->to_string_long() + "_transition";
|
std::string transition_attr_name = rf->to_string() + "_transition";
|
||||||
TableModel *transition = readGateTableModel(timing_group,
|
TableModel *transition = readGateTableModel(timing_group,
|
||||||
transition_attr_name.c_str(),
|
transition_attr_name.c_str(),
|
||||||
rf, TableTemplateType::delay,
|
rf, TableTemplateType::delay,
|
||||||
time_scale_,
|
time_scale_,
|
||||||
ScaleFactorType::transition);
|
ScaleFactorType::transition);
|
||||||
if (delay || transition) {
|
if (delay || transition) {
|
||||||
std::string delay_sigma_attr_name = "ocv_sigma_cell_" + rf->to_string_long();
|
std::string delay_sigma_attr_name = "ocv_sigma_cell_" + rf->to_string();
|
||||||
TableModelsEarlyLate delay_sigmas =
|
TableModelsEarlyLate delay_sigmas =
|
||||||
readEarlyLateTableModels(timing_group,
|
readEarlyLateTableModels(timing_group,
|
||||||
delay_sigma_attr_name.c_str(),
|
delay_sigma_attr_name.c_str(),
|
||||||
|
|
@ -2136,7 +2136,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
|
||||||
time_scale_,
|
time_scale_,
|
||||||
ScaleFactorType::unknown);
|
ScaleFactorType::unknown);
|
||||||
|
|
||||||
std::string slew_sigma_attr_name = "ocv_sigma_" + rf->to_string_long()
|
std::string slew_sigma_attr_name = "ocv_sigma_" + rf->to_string()
|
||||||
+ "_transition";
|
+ "_transition";
|
||||||
TableModelsEarlyLate slew_sigmas =
|
TableModelsEarlyLate slew_sigmas =
|
||||||
readEarlyLateTableModels(timing_group,
|
readEarlyLateTableModels(timing_group,
|
||||||
|
|
@ -2164,7 +2164,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
|
||||||
found_model = true;
|
found_model = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::string constraint_attr_name = rf->to_string_long() + "_constraint";
|
std::string constraint_attr_name = rf->to_string() + "_constraint";
|
||||||
ScaleFactorType scale_factor_type =
|
ScaleFactorType scale_factor_type =
|
||||||
timingTypeScaleFactorType(timing_attrs->timingType());
|
timingTypeScaleFactorType(timing_attrs->timingType());
|
||||||
TableModel *constraint = readCheckTableModel(timing_group,
|
TableModel *constraint = readCheckTableModel(timing_group,
|
||||||
|
|
@ -2172,7 +2172,7 @@ LibertyReader::makeTableModels(LibertyCell *cell,
|
||||||
rf, TableTemplateType::delay,
|
rf, TableTemplateType::delay,
|
||||||
time_scale_, scale_factor_type);
|
time_scale_, scale_factor_type);
|
||||||
if (constraint) {
|
if (constraint) {
|
||||||
std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string_long()
|
std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string()
|
||||||
+ "_constraint";
|
+ "_constraint";
|
||||||
TableModelsEarlyLate constraint_sigmas =
|
TableModelsEarlyLate constraint_sigmas =
|
||||||
readEarlyLateTableModels(timing_group,
|
readEarlyLateTableModels(timing_group,
|
||||||
|
|
@ -2298,7 +2298,7 @@ LibertyReader::readReceiverCapacitance(const LibertyGroup *timing_group,
|
||||||
ReceiverModelPtr &receiver_model)
|
ReceiverModelPtr &receiver_model)
|
||||||
{
|
{
|
||||||
std::string cap_group_name1 = cap_group_name;
|
std::string cap_group_name1 = cap_group_name;
|
||||||
cap_group_name1 += "_" + rf->to_string_long();
|
cap_group_name1 += "_" + rf->to_string();
|
||||||
const LibertyGroup *cap_group = timing_group->findSubgroup(cap_group_name1);
|
const LibertyGroup *cap_group = timing_group->findSubgroup(cap_group_name1);
|
||||||
if (cap_group) {
|
if (cap_group) {
|
||||||
const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment");
|
const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment");
|
||||||
|
|
@ -2328,7 +2328,7 @@ OutputWaveforms *
|
||||||
LibertyReader::readOutputWaveforms(const LibertyGroup *timing_group,
|
LibertyReader::readOutputWaveforms(const LibertyGroup *timing_group,
|
||||||
const RiseFall *rf)
|
const RiseFall *rf)
|
||||||
{
|
{
|
||||||
const std::string current_group_name = "output_current_" + rf->to_string_long();
|
const std::string current_group_name = "output_current_" + rf->to_string();
|
||||||
const LibertyGroup *current_group = timing_group->findSubgroup(current_group_name);
|
const LibertyGroup *current_group = timing_group->findSubgroup(current_group_name);
|
||||||
if (current_group) {
|
if (current_group) {
|
||||||
OutputWaveformSeq output_currents;
|
OutputWaveformSeq output_currents;
|
||||||
|
|
@ -2680,7 +2680,7 @@ LibertyReader::readInternalPowerGroups(LibertyCell *cell,
|
||||||
InternalPowerModels models;
|
InternalPowerModels models;
|
||||||
// rise/fall_power group
|
// rise/fall_power group
|
||||||
for (const RiseFall *rf : RiseFall::range()) {
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
std::string pwr_attr_name = rf->to_string_long() + "_power";
|
std::string pwr_attr_name = rf->to_string() + "_power";
|
||||||
const LibertyGroup *pwr_group = ipwr_group->findSubgroup(pwr_attr_name);
|
const LibertyGroup *pwr_group = ipwr_group->findSubgroup(pwr_attr_name);
|
||||||
if (pwr_group) {
|
if (pwr_group) {
|
||||||
TableModel *model = readTableModel(pwr_group, rf, TableTemplateType::power,
|
TableModel *model = readTableModel(pwr_group, rf, TableTemplateType::power,
|
||||||
|
|
@ -2743,7 +2743,7 @@ LibertyReader::findLibertyPort(LibertyCell *cell,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStringSeq
|
StringSeq
|
||||||
LibertyReader::findAttributStrings(const LibertyGroup *group,
|
LibertyReader::findAttributStrings(const LibertyGroup *group,
|
||||||
const char *name_attr)
|
const char *name_attr)
|
||||||
{
|
{
|
||||||
|
|
@ -2754,7 +2754,7 @@ LibertyReader::findAttributStrings(const LibertyGroup *group,
|
||||||
return parseTokens(*strings, ' ');
|
return parseTokens(*strings, ' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return StdStringSeq();
|
return StringSeq();
|
||||||
}
|
}
|
||||||
|
|
||||||
LibertyPortSeq
|
LibertyPortSeq
|
||||||
|
|
@ -2763,7 +2763,7 @@ LibertyReader::findLibertyPorts(LibertyCell *cell,
|
||||||
const char *port_name_attr)
|
const char *port_name_attr)
|
||||||
{
|
{
|
||||||
LibertyPortSeq ports;
|
LibertyPortSeq ports;
|
||||||
StdStringSeq port_names = findAttributStrings(group, port_name_attr);
|
StringSeq port_names = findAttributStrings(group, port_name_attr);
|
||||||
for (const std::string &port_name : port_names) {
|
for (const std::string &port_name : port_names) {
|
||||||
LibertyPort *port = findPort(cell, port_name.c_str());
|
LibertyPort *port = findPort(cell, port_name.c_str());
|
||||||
if (port)
|
if (port)
|
||||||
|
|
@ -2915,40 +2915,40 @@ LibertyReader::readStatetable(LibertyCell *cell,
|
||||||
const char *input_ports_arg = statetable_group->firstName();
|
const char *input_ports_arg = statetable_group->firstName();
|
||||||
const char *internal_ports_arg = statetable_group->params().size() >= 2
|
const char *internal_ports_arg = statetable_group->params().size() >= 2
|
||||||
? statetable_group->secondName() : nullptr;
|
? statetable_group->secondName() : nullptr;
|
||||||
StdStringSeq input_ports;
|
StringSeq input_ports;
|
||||||
if (input_ports_arg)
|
if (input_ports_arg)
|
||||||
input_ports = parseTokens(input_ports_arg, ' ');
|
input_ports = parseTokens(input_ports_arg, ' ');
|
||||||
StdStringSeq internal_ports;
|
StringSeq internal_ports;
|
||||||
if (internal_ports_arg)
|
if (internal_ports_arg)
|
||||||
internal_ports = parseTokens(internal_ports_arg, ' ');
|
internal_ports = parseTokens(internal_ports_arg, ' ');
|
||||||
|
|
||||||
const LibertySimpleAttr *table_attr = statetable_group->findSimpleAttr("table");
|
const LibertySimpleAttr *table_attr = statetable_group->findSimpleAttr("table");
|
||||||
if (table_attr) {
|
if (table_attr) {
|
||||||
const std::string *table_str = table_attr->stringValue();
|
const std::string *table_str = table_attr->stringValue();
|
||||||
StdStringSeq table_rows = parseTokens(table_str->c_str(), ',');
|
StringSeq table_rows = parseTokens(table_str->c_str(), ',');
|
||||||
size_t input_count = input_ports.size();
|
size_t input_count = input_ports.size();
|
||||||
size_t internal_count = internal_ports.size();
|
size_t internal_count = internal_ports.size();
|
||||||
StatetableRows table;
|
StatetableRows table;
|
||||||
for (const std::string &row : table_rows) {
|
for (const std::string &row : table_rows) {
|
||||||
const StdStringSeq row_groups = parseTokens(row, ':');
|
const StringSeq row_groups = parseTokens(row, ':');
|
||||||
if (row_groups.size() != 3) {
|
if (row_groups.size() != 3) {
|
||||||
libWarn(1300, table_attr, "table row must have 3 groups separated by ':'.");
|
libWarn(1300, table_attr, "table row must have 3 groups separated by ':'.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
StdStringSeq inputs = parseTokens(row_groups[0], ' ');
|
StringSeq inputs = parseTokens(row_groups[0], ' ');
|
||||||
if (inputs.size() != input_count) {
|
if (inputs.size() != input_count) {
|
||||||
libWarn(1301,table_attr,"table row has %zu input values but %zu are required.",
|
libWarn(1301,table_attr,"table row has %zu input values but %zu are required.",
|
||||||
inputs.size(), input_count);
|
inputs.size(), input_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
StdStringSeq currents = parseTokens(row_groups[1], ' ');
|
StringSeq currents = parseTokens(row_groups[1], ' ');
|
||||||
if (currents.size() != internal_count) {
|
if (currents.size() != internal_count) {
|
||||||
libWarn(1302,table_attr,
|
libWarn(1302,table_attr,
|
||||||
"table row has %zu current values but %zu are required.",
|
"table row has %zu current values but %zu are required.",
|
||||||
currents.size(), internal_count);
|
currents.size(), internal_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
StdStringSeq nexts = parseTokens(row_groups[2], ' ');
|
StringSeq nexts = parseTokens(row_groups[2], ' ');
|
||||||
if (nexts.size() != internal_count) {
|
if (nexts.size() != internal_count) {
|
||||||
libWarn(1303, table_attr, "table row has %zu next values but %zu are required.",
|
libWarn(1303, table_attr, "table row has %zu next values but %zu are required.",
|
||||||
nexts.size(), internal_count);
|
nexts.size(), internal_count);
|
||||||
|
|
@ -3087,7 +3087,7 @@ static EnumNameMap<StateInternalValue> state_internal_value_name_map =
|
||||||
};
|
};
|
||||||
|
|
||||||
StateInputValues
|
StateInputValues
|
||||||
LibertyReader::parseStateInputValues(StdStringSeq &inputs,
|
LibertyReader::parseStateInputValues(StringSeq &inputs,
|
||||||
const LibertySimpleAttr *attr)
|
const LibertySimpleAttr *attr)
|
||||||
{
|
{
|
||||||
StateInputValues input_values;
|
StateInputValues input_values;
|
||||||
|
|
@ -3106,7 +3106,7 @@ LibertyReader::parseStateInputValues(StdStringSeq &inputs,
|
||||||
}
|
}
|
||||||
|
|
||||||
StateInternalValues
|
StateInternalValues
|
||||||
LibertyReader::parseStateInternalValues(StdStringSeq &states,
|
LibertyReader::parseStateInternalValues(StringSeq &states,
|
||||||
const LibertySimpleAttr *attr)
|
const LibertySimpleAttr *attr)
|
||||||
{
|
{
|
||||||
StateInternalValues state_values;
|
StateInternalValues state_values;
|
||||||
|
|
@ -3458,37 +3458,37 @@ LibertyReader::variableValue(const char *var,
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyReader::libWarn(int id,
|
LibertyReader::libWarn(int id,
|
||||||
const LibertyGroup *obj,
|
const LibertyGroup *group,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
report_->vfileWarn(id, filename_, obj->line(), fmt, args);
|
report_->vfileWarn(id, filename_, group->line(), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyReader::libWarn(int id,
|
LibertyReader::libWarn(int id,
|
||||||
const LibertySimpleAttr *obj,
|
const LibertySimpleAttr *attr,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
report_->vfileWarn(id, filename_, obj->line(), fmt, args);
|
report_->vfileWarn(id, filename_, attr->line(), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyReader::libWarn(int id,
|
LibertyReader::libWarn(int id,
|
||||||
const LibertyComplexAttr *obj,
|
const LibertyComplexAttr *attr,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
report_->vfileWarn(id, filename_, obj->line(), fmt, args);
|
report_->vfileWarn(id, filename_, attr->line(), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3496,7 +3496,7 @@ void
|
||||||
LibertyReader::libWarn(int id,
|
LibertyReader::libWarn(int id,
|
||||||
int line,
|
int line,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|
@ -3506,37 +3506,37 @@ LibertyReader::libWarn(int id,
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyReader::libError(int id,
|
LibertyReader::libError(int id,
|
||||||
const LibertyGroup *obj,
|
const LibertyGroup *group,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
report_->vfileError(id, filename_, obj->line(), fmt, args);
|
report_->vfileError(id, filename_, group->line(), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyReader::libError(int id,
|
LibertyReader::libError(int id,
|
||||||
const LibertySimpleAttr *obj,
|
const LibertySimpleAttr *attr,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
report_->vfileError(id, filename_, obj->line(), fmt, args);
|
report_->vfileError(id, filename_, attr->line(), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyReader::libError(int id,
|
LibertyReader::libError(int id,
|
||||||
const LibertyComplexAttr *obj,
|
const LibertyComplexAttr *attr,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
report_->vfileError(id, filename_, obj->line(), fmt, args);
|
report_->vfileError(id, filename_, attr->line(), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdarg>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "StringSeq.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "MinMax.hh"
|
#include "MinMax.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
@ -101,7 +101,7 @@ public:
|
||||||
|
|
||||||
LibertyPort *findPort(LibertyCell *cell,
|
LibertyPort *findPort(LibertyCell *cell,
|
||||||
const char *port_name);
|
const char *port_name);
|
||||||
StdStringSeq findAttributStrings(const LibertyGroup *group,
|
StringSeq findAttributStrings(const LibertyGroup *group,
|
||||||
const char *name_attr);
|
const char *name_attr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -132,6 +132,7 @@ protected:
|
||||||
const char *group_name,
|
const char *group_name,
|
||||||
TableTemplateType type);
|
TableTemplateType type);
|
||||||
void readThresholds(const LibertyGroup *library_group);
|
void readThresholds(const LibertyGroup *library_group);
|
||||||
|
void checkThresholds(const LibertyGroup *library_group) const;
|
||||||
TableAxisPtr makeTableTemplateAxis(const LibertyGroup *template_group,
|
TableAxisPtr makeTableTemplateAxis(const LibertyGroup *template_group,
|
||||||
int axis_index);
|
int axis_index);
|
||||||
void readVoltateMaps(const LibertyGroup *library_group);
|
void readVoltateMaps(const LibertyGroup *library_group);
|
||||||
|
|
@ -401,9 +402,9 @@ protected:
|
||||||
|
|
||||||
float defaultCap(LibertyPort *port);
|
float defaultCap(LibertyPort *port);
|
||||||
void visitPorts(std::function<void (LibertyPort *port)> func);
|
void visitPorts(std::function<void (LibertyPort *port)> func);
|
||||||
StateInputValues parseStateInputValues(StdStringSeq &inputs,
|
StateInputValues parseStateInputValues(StringSeq &inputs,
|
||||||
const LibertySimpleAttr *attr);
|
const LibertySimpleAttr *attr);
|
||||||
StateInternalValues parseStateInternalValues(StdStringSeq &states,
|
StateInternalValues parseStateInternalValues(StringSeq &states,
|
||||||
const LibertySimpleAttr *attr);
|
const LibertySimpleAttr *attr);
|
||||||
|
|
||||||
void getAttrInt(const LibertySimpleAttr *attr,
|
void getAttrInt(const LibertySimpleAttr *attr,
|
||||||
|
|
@ -445,36 +446,36 @@ protected:
|
||||||
const LibertyCell *cell,
|
const LibertyCell *cell,
|
||||||
int line);
|
int line);
|
||||||
void libWarn(int id,
|
void libWarn(int id,
|
||||||
const LibertyGroup *obj,
|
const LibertyGroup *group,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
__attribute__((format (printf, 4, 5)));
|
__attribute__((format (printf, 4, 5)));
|
||||||
void libWarn(int id,
|
void libWarn(int id,
|
||||||
const LibertySimpleAttr *obj,
|
const LibertySimpleAttr *attr,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
__attribute__((format (printf, 4, 5)));
|
__attribute__((format (printf, 4, 5)));
|
||||||
void libWarn(int id,
|
void libWarn(int id,
|
||||||
const LibertyComplexAttr *obj,
|
const LibertyComplexAttr *attr,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
__attribute__((format (printf, 4, 5)));
|
__attribute__((format (printf, 4, 5)));
|
||||||
void libWarn(int id,
|
void libWarn(int id,
|
||||||
int line,
|
int line,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...)
|
...) const
|
||||||
__attribute__((format (printf, 4, 5)));
|
__attribute__((format (printf, 4, 5)));
|
||||||
void libError(int id,
|
void libError(int id,
|
||||||
const LibertyGroup *obj,
|
const LibertyGroup *group,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...) const
|
||||||
__attribute__((format (printf, 4, 5)));
|
__attribute__((format (printf, 4, 5)));
|
||||||
void libError(int id,
|
void libError(int id,
|
||||||
const LibertySimpleAttr *obj,
|
const LibertySimpleAttr *attr,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...) const
|
||||||
__attribute__((format (printf, 4, 5)));
|
__attribute__((format (printf, 4, 5)));
|
||||||
void libError(int id,
|
void libError(int id,
|
||||||
const LibertyComplexAttr *obj,
|
const LibertyComplexAttr *attr,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...) const
|
||||||
__attribute__((format (printf, 4, 5)));
|
__attribute__((format (printf, 4, 5)));
|
||||||
|
|
||||||
const char *filename_;
|
const char *filename_;
|
||||||
|
|
@ -485,7 +486,6 @@ protected:
|
||||||
LibertyBuilder builder_;
|
LibertyBuilder builder_;
|
||||||
LibertyVariableMap var_map_;
|
LibertyVariableMap var_map_;
|
||||||
LibertyLibrary *library_;
|
LibertyLibrary *library_;
|
||||||
bool first_cell_;
|
|
||||||
LibraryGroupVisitorMap group_begin_map_;
|
LibraryGroupVisitorMap group_begin_map_;
|
||||||
LibraryGroupVisitorMap group_end_map_;
|
LibraryGroupVisitorMap group_end_map_;
|
||||||
|
|
||||||
|
|
@ -516,8 +516,8 @@ public:
|
||||||
LibertyReader *visitor,
|
LibertyReader *visitor,
|
||||||
int line);
|
int line);
|
||||||
~PortNameBitIterator();
|
~PortNameBitIterator();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual LibertyPort *next();
|
LibertyPort *next() override;
|
||||||
unsigned size() const { return size_; }
|
unsigned size() const { return size_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ class ConcreteInstanceChildIterator : public InstanceChildIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConcreteInstanceChildIterator(ConcreteInstanceChildMap *map);
|
ConcreteInstanceChildIterator(ConcreteInstanceChildMap *map);
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
Instance *next();
|
Instance *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteInstanceChildMap *map_;
|
ConcreteInstanceChildMap *map_;
|
||||||
|
|
@ -96,8 +96,8 @@ class ConcreteInstanceNetIterator : public InstanceNetIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets);
|
ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets);
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
Net *next();
|
Net *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void findNext();
|
void findNext();
|
||||||
|
|
@ -152,8 +152,8 @@ class ConcreteInstancePinIterator : public InstancePinIterator
|
||||||
public:
|
public:
|
||||||
ConcreteInstancePinIterator(const ConcreteInstance *inst,
|
ConcreteInstancePinIterator(const ConcreteInstance *inst,
|
||||||
int pin_count);
|
int pin_count);
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
Pin *next();
|
Pin *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void findNext();
|
void findNext();
|
||||||
|
|
@ -206,8 +206,8 @@ class ConcreteNetPinIterator : public NetPinIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConcreteNetPinIterator(const ConcreteNet *net);
|
ConcreteNetPinIterator(const ConcreteNet *net);
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
Pin *next();
|
Pin *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcretePin *next_;
|
ConcretePin *next_;
|
||||||
|
|
@ -238,8 +238,8 @@ class ConcreteNetTermIterator : public NetTermIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConcreteNetTermIterator(const ConcreteNet *net);
|
ConcreteNetTermIterator(const ConcreteNet *net);
|
||||||
bool hasNext();
|
bool hasNext() override;
|
||||||
Term *next();
|
Term *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteTerm *next_;
|
ConcreteTerm *next_;
|
||||||
|
|
@ -322,8 +322,8 @@ class ConcreteLibraryIterator1 : public Iterator<Library*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConcreteLibraryIterator1(const ConcreteLibrarySeq &libs);
|
ConcreteLibraryIterator1(const ConcreteLibrarySeq &libs);
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual Library *next();
|
Library *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ConcreteLibrarySeq &libs_;
|
const ConcreteLibrarySeq &libs_;
|
||||||
|
|
@ -361,8 +361,8 @@ class ConcreteLibertyLibraryIterator : public Iterator<LibertyLibrary*>
|
||||||
public:
|
public:
|
||||||
ConcreteLibertyLibraryIterator(const ConcreteNetwork *network);
|
ConcreteLibertyLibraryIterator(const ConcreteNetwork *network);
|
||||||
virtual ~ConcreteLibertyLibraryIterator();
|
virtual ~ConcreteLibertyLibraryIterator();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual LibertyLibrary *next();
|
LibertyLibrary *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void findNext();
|
void findNext();
|
||||||
|
|
@ -719,8 +719,8 @@ class ConcreteCellPortIterator1 : public CellPortIterator
|
||||||
public:
|
public:
|
||||||
ConcreteCellPortIterator1(const ConcreteCell *cell);
|
ConcreteCellPortIterator1(const ConcreteCell *cell);
|
||||||
~ConcreteCellPortIterator1();
|
~ConcreteCellPortIterator1();
|
||||||
virtual bool hasNext() { return iter_->hasNext(); }
|
bool hasNext() override { return iter_->hasNext(); }
|
||||||
virtual Port *next();
|
Port *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteCellPortIterator *iter_;
|
ConcreteCellPortIterator *iter_;
|
||||||
|
|
@ -756,8 +756,8 @@ class ConcreteCellPortBitIterator1 : public CellPortIterator
|
||||||
public:
|
public:
|
||||||
ConcreteCellPortBitIterator1(const ConcreteCell *cell);
|
ConcreteCellPortBitIterator1(const ConcreteCell *cell);
|
||||||
~ConcreteCellPortBitIterator1();
|
~ConcreteCellPortBitIterator1();
|
||||||
virtual bool hasNext() { return iter_->hasNext(); }
|
bool hasNext() override { return iter_->hasNext(); }
|
||||||
virtual Port *next();
|
Port *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteCellPortBitIterator *iter_;
|
ConcreteCellPortBitIterator *iter_;
|
||||||
|
|
@ -903,8 +903,8 @@ class ConcretePortMemberIterator1 : public PortMemberIterator
|
||||||
public:
|
public:
|
||||||
ConcretePortMemberIterator1(const ConcretePort *port);
|
ConcretePortMemberIterator1(const ConcretePort *port);
|
||||||
~ConcretePortMemberIterator1();
|
~ConcretePortMemberIterator1();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual Port *next();
|
Port *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcretePortMemberIterator *iter_;
|
ConcretePortMemberIterator *iter_;
|
||||||
|
|
|
||||||
|
|
@ -1221,8 +1221,8 @@ class LeafInstanceIterator1 : public LeafInstanceIterator
|
||||||
public:
|
public:
|
||||||
LeafInstanceIterator1(const Instance *inst,
|
LeafInstanceIterator1(const Instance *inst,
|
||||||
const Network *network);
|
const Network *network);
|
||||||
bool hasNext() { return next_; }
|
bool hasNext() override { return next_; }
|
||||||
Instance *next();
|
Instance *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void nextInst();
|
void nextInst();
|
||||||
|
|
@ -1366,8 +1366,8 @@ class ConnectedPinIterator1 : public ConnectedPinIterator
|
||||||
public:
|
public:
|
||||||
ConnectedPinIterator1(PinSet *pins);
|
ConnectedPinIterator1(PinSet *pins);
|
||||||
virtual ~ConnectedPinIterator1();
|
virtual ~ConnectedPinIterator1();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual const Pin *next();
|
const Pin *next() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PinSet *pins_;
|
PinSet *pins_;
|
||||||
|
|
|
||||||
|
|
@ -638,13 +638,16 @@ InstancePinIterator *
|
||||||
pin_iterator() { return Sta::sta()->ensureLinked()->pinIterator(self); }
|
pin_iterator() { return Sta::sta()->ensureLinked()->pinIterator(self); }
|
||||||
InstanceNetIterator *
|
InstanceNetIterator *
|
||||||
net_iterator() { return Sta::sta()->ensureLinked()->netIterator(self); }
|
net_iterator() { return Sta::sta()->ensureLinked()->netIterator(self); }
|
||||||
|
|
||||||
Pin *
|
Pin *
|
||||||
find_pin(const char *name)
|
find_pin(const char *name)
|
||||||
{
|
{
|
||||||
return Sta::sta()->ensureLinked()->findPin(self, name);
|
return Sta::sta()->ensureLinked()->findPin(self, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
get_attribute(const char *key) {
|
get_attribute(const char *key)
|
||||||
|
{
|
||||||
return Sta::sta()->ensureLinked()->getAttribute(self, key);
|
return Sta::sta()->ensureLinked()->getAttribute(self, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ reduceToPiElmore(const Parasitic *parasitic_network,
|
||||||
if (drvr_node) {
|
if (drvr_node) {
|
||||||
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s",
|
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s",
|
||||||
sta->network()->pathName(drvr_pin),
|
sta->network()->pathName(drvr_pin),
|
||||||
rf->to_string().c_str(),
|
rf->shortName(),
|
||||||
min_max->to_string().c_str());
|
min_max->to_string().c_str());
|
||||||
ReduceToPiElmore reducer(sta);
|
ReduceToPiElmore reducer(sta);
|
||||||
return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
|
return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include "Report.hh"
|
#include "Report.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "StringSeq.hh"
|
#include "StringUtil.hh"
|
||||||
#include "parasitics/SpefReaderPvt.hh"
|
#include "parasitics/SpefReaderPvt.hh"
|
||||||
#include "parasitics/SpefScanner.hh"
|
#include "parasitics/SpefScanner.hh"
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ sta::SpefParse::error(const location_type &loc,
|
||||||
char *string;
|
char *string;
|
||||||
int integer;
|
int integer;
|
||||||
float number;
|
float number;
|
||||||
sta::StringSeq *string_seq;
|
sta::StringSeq *std_string_seq;
|
||||||
sta::PortDirection *port_dir;
|
sta::PortDirection *port_dir;
|
||||||
sta::SpefRspfPi *pi;
|
sta::SpefRspfPi *pi;
|
||||||
sta::SpefTriple *triple;
|
sta::SpefTriple *triple;
|
||||||
|
|
@ -105,7 +105,7 @@ sta::SpefParse::error(const location_type &loc,
|
||||||
|
|
||||||
%type <ch> hchar suffix_bus_delim prefix_bus_delim
|
%type <ch> hchar suffix_bus_delim prefix_bus_delim
|
||||||
|
|
||||||
%type <string_seq> qstrings
|
%type <std_string_seq> qstrings
|
||||||
%type<port_dir> direction
|
%type<port_dir> direction
|
||||||
|
|
||||||
%type<triple> par_value total_cap
|
%type<triple> par_value total_cap
|
||||||
|
|
@ -222,9 +222,12 @@ qstrings:
|
||||||
QSTRING
|
QSTRING
|
||||||
{ $$ = new sta::StringSeq;
|
{ $$ = new sta::StringSeq;
|
||||||
$$->push_back($1);
|
$$->push_back($1);
|
||||||
|
sta::stringDelete($1);
|
||||||
}
|
}
|
||||||
| qstrings QSTRING
|
| qstrings QSTRING
|
||||||
{ $$->push_back($2); }
|
{ $$->push_back($2);
|
||||||
|
sta::stringDelete($2);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
hierarchy_div_def:
|
hierarchy_div_def:
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ SpefReader::SpefReader(const std::string &filename,
|
||||||
cap_scale_(1.0),
|
cap_scale_(1.0),
|
||||||
res_scale_(1.0),
|
res_scale_(1.0),
|
||||||
induct_scale_(1.0),
|
induct_scale_(1.0),
|
||||||
design_flow_(nullptr),
|
|
||||||
parasitics_(parasitics),
|
parasitics_(parasitics),
|
||||||
parasitic_(nullptr)
|
parasitic_(nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -101,11 +100,6 @@ SpefReader::SpefReader(const std::string &filename,
|
||||||
|
|
||||||
SpefReader::~SpefReader()
|
SpefReader::~SpefReader()
|
||||||
{
|
{
|
||||||
if (design_flow_) {
|
|
||||||
deleteContents(design_flow_);
|
|
||||||
delete design_flow_;
|
|
||||||
design_flow_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -299,7 +293,8 @@ SpefReader::portDirection(char *spef_dir)
|
||||||
void
|
void
|
||||||
SpefReader::setDesignFlow(StringSeq *flow)
|
SpefReader::setDesignFlow(StringSeq *flow)
|
||||||
{
|
{
|
||||||
design_flow_ = flow;
|
design_flow_ = std::move(*flow);
|
||||||
|
delete flow;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pin *
|
Pin *
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "Zlib.hh"
|
#include "Zlib.hh"
|
||||||
#include "StringSeq.hh"
|
#include "StringUtil.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "ParasiticsClass.hh"
|
#include "ParasiticsClass.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
|
|
@ -139,7 +139,7 @@ private:
|
||||||
float res_scale_;
|
float res_scale_;
|
||||||
float induct_scale_;
|
float induct_scale_;
|
||||||
SpefNameMap name_map_;
|
SpefNameMap name_map_;
|
||||||
StringSeq *design_flow_;
|
StringSeq design_flow_;
|
||||||
Parasitics *parasitics_;
|
Parasitics *parasitics_;
|
||||||
Parasitic *parasitic_;
|
Parasitic *parasitic_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,6 @@ static EnumNameMap<PwrActivityOrigin> pwr_activity_origin_map =
|
||||||
{PwrActivityOrigin::propagated, "propagated"},
|
{PwrActivityOrigin::propagated, "propagated"},
|
||||||
{PwrActivityOrigin::clock, "clock"},
|
{PwrActivityOrigin::clock, "clock"},
|
||||||
{PwrActivityOrigin::constant, "constant"},
|
{PwrActivityOrigin::constant, "constant"},
|
||||||
{PwrActivityOrigin::defaulted, "defaulted"},
|
|
||||||
{PwrActivityOrigin::unknown, "unknown"}};
|
{PwrActivityOrigin::unknown, "unknown"}};
|
||||||
|
|
||||||
Power::Power(StaState *sta) :
|
Power::Power(StaState *sta) :
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ ClockEdge::ClockEdge(Clock *clock,
|
||||||
const RiseFall *rf) :
|
const RiseFall *rf) :
|
||||||
clock_(clock),
|
clock_(clock),
|
||||||
rf_(rf),
|
rf_(rf),
|
||||||
name_(stringPrint("%s %s", clock_->name(), rf_->to_string().c_str())),
|
name_(stringPrint("%s %s", clock_->name(), rf_->shortName())),
|
||||||
time_(0.0),
|
time_(0.0),
|
||||||
index_(clock_->index() * RiseFall::index_count + rf_->index())
|
index_(clock_->index() * RiseFall::index_count + rf_->index())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -96,18 +96,15 @@ DisabledPorts::setDisabledFromTo(LibertyPort *from,
|
||||||
{
|
{
|
||||||
if (from_to_ == nullptr)
|
if (from_to_ == nullptr)
|
||||||
from_to_ = new LibertyPortPairSet;
|
from_to_ = new LibertyPortPairSet;
|
||||||
LibertyPortPair pair(from, to);
|
from_to_->insert({from, to});
|
||||||
from_to_->insert(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DisabledPorts::removeDisabledFromTo(LibertyPort *from,
|
DisabledPorts::removeDisabledFromTo(LibertyPort *from,
|
||||||
LibertyPort *to)
|
LibertyPort *to)
|
||||||
{
|
{
|
||||||
if (from_to_) {
|
if (from_to_)
|
||||||
LibertyPortPair from_to(from, to);
|
from_to_->erase({from, to});
|
||||||
from_to_->erase(from_to);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -115,12 +112,11 @@ DisabledPorts::isDisabled(LibertyPort *from,
|
||||||
LibertyPort *to,
|
LibertyPort *to,
|
||||||
const TimingRole *role)
|
const TimingRole *role)
|
||||||
{
|
{
|
||||||
LibertyPortPair from_to(from, to);
|
|
||||||
// set_disable_timing instance does not disable timing checks.
|
// set_disable_timing instance does not disable timing checks.
|
||||||
return (all_ && !role->isTimingCheck())
|
return (all_ && !role->isTimingCheck())
|
||||||
|| (from_ && from_->contains(from))
|
|| (from_ && from_->contains(from))
|
||||||
|| (to_ && to_->contains(to))
|
|| (to_ && to_->contains(to))
|
||||||
|| (from_to_ && from_to_->contains(from_to));
|
|| (from_to_ && from_to_->contains({from, to}));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -2427,8 +2427,7 @@ void
|
||||||
InsertPinPairsThru::visit(const Pin *drvr,
|
InsertPinPairsThru::visit(const Pin *drvr,
|
||||||
const Pin *load)
|
const Pin *load)
|
||||||
{
|
{
|
||||||
PinPair pair(drvr, load);
|
pairs_->insert({drvr, load});
|
||||||
pairs_->insert(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2475,8 +2474,7 @@ void
|
||||||
DeletePinPairsThru::visit(const Pin *drvr,
|
DeletePinPairsThru::visit(const Pin *drvr,
|
||||||
const Pin *load)
|
const Pin *load)
|
||||||
{
|
{
|
||||||
PinPair pair(drvr, load);
|
pairs_->erase({drvr, load});
|
||||||
pairs_->erase(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
28
sdc/Sdc.cc
28
sdc/Sdc.cc
|
|
@ -101,6 +101,7 @@ Sdc::Sdc(Mode *mode,
|
||||||
clk_hpin_disables_(network_),
|
clk_hpin_disables_(network_),
|
||||||
propagated_clk_pins_(network_),
|
propagated_clk_pins_(network_),
|
||||||
clk_latencies_(network_),
|
clk_latencies_(network_),
|
||||||
|
clk_latency_pins_(network_),
|
||||||
edge_clk_latency_map_(network_),
|
edge_clk_latency_map_(network_),
|
||||||
clk_insertions_(network_),
|
clk_insertions_(network_),
|
||||||
clk_sense_map_(network_),
|
clk_sense_map_(network_),
|
||||||
|
|
@ -169,6 +170,7 @@ Sdc::clear()
|
||||||
clock_pin_map_.clear();
|
clock_pin_map_.clear();
|
||||||
clock_leaf_pin_map_.clear();
|
clock_leaf_pin_map_.clear();
|
||||||
clk_latencies_.clear();
|
clk_latencies_.clear();
|
||||||
|
clk_latency_pins_.clear();
|
||||||
edge_clk_latency_map_.clear();
|
edge_clk_latency_map_.clear();
|
||||||
clk_insertions_.clear();
|
clk_insertions_.clear();
|
||||||
|
|
||||||
|
|
@ -1344,8 +1346,7 @@ bool
|
||||||
FindClkHpinDisables::drvrLoadExists(const Pin *drvr,
|
FindClkHpinDisables::drvrLoadExists(const Pin *drvr,
|
||||||
const Pin *load)
|
const Pin *load)
|
||||||
{
|
{
|
||||||
PinPair probe(drvr, load);
|
return drvr_loads_.contains({drvr, load});
|
||||||
return drvr_loads_.contains(probe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1508,6 +1509,8 @@ Sdc::setClockLatency(Clock *clk,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
latency->setDelay(rf, min_max, delay);
|
latency->setDelay(rf, min_max, delay);
|
||||||
|
if (pin)
|
||||||
|
clk_latency_pins_.insert(pin);
|
||||||
|
|
||||||
// set_clock_latency removes set_propagated_clock on the same object.
|
// set_clock_latency removes set_propagated_clock on the same object.
|
||||||
if (clk && pin == nullptr)
|
if (clk && pin == nullptr)
|
||||||
|
|
@ -1580,8 +1583,7 @@ Sdc::deleteClockLatenciesReferencing(Clock *clk)
|
||||||
bool
|
bool
|
||||||
Sdc::hasClockLatency(const Pin *pin) const
|
Sdc::hasClockLatency(const Pin *pin) const
|
||||||
{
|
{
|
||||||
ClockLatency probe(nullptr, pin);
|
return clk_latency_pins_.contains(pin);
|
||||||
return clk_latencies_.contains(&probe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3503,24 +3505,21 @@ void
|
||||||
Sdc::disableWire(const Pin *from,
|
Sdc::disableWire(const Pin *from,
|
||||||
const Pin *to)
|
const Pin *to)
|
||||||
{
|
{
|
||||||
PinPair pair(from, to);
|
disabled_wire_edges_.insert({from, to});
|
||||||
disabled_wire_edges_.insert(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Sdc::removeDisableWire(Pin *from,
|
Sdc::removeDisableWire(Pin *from,
|
||||||
Pin *to)
|
Pin *to)
|
||||||
{
|
{
|
||||||
PinPair probe(from, to);
|
disabled_wire_edges_.erase({from, to});
|
||||||
disabled_wire_edges_.erase(probe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Sdc::isDisabledWire(const Pin *from,
|
Sdc::isDisabledWire(const Pin *from,
|
||||||
const Pin *to) const
|
const Pin *to) const
|
||||||
{
|
{
|
||||||
PinPair pair(from, to);
|
return disabled_wire_edges_.contains({from, to});
|
||||||
return disabled_wire_edges_.contains(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3580,8 +3579,7 @@ void
|
||||||
DisableEdgesThruHierPin::visit(const Pin *drvr,
|
DisableEdgesThruHierPin::visit(const Pin *drvr,
|
||||||
const Pin *load)
|
const Pin *load)
|
||||||
{
|
{
|
||||||
PinPair pair(drvr, load);
|
pairs_->insert({drvr, load});
|
||||||
pairs_->insert(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3622,8 +3620,7 @@ void
|
||||||
RemoveDisableEdgesThruHierPin::visit(const Pin *drvr,
|
RemoveDisableEdgesThruHierPin::visit(const Pin *drvr,
|
||||||
const Pin *load)
|
const Pin *load)
|
||||||
{
|
{
|
||||||
PinPair pair(drvr, load);
|
pairs_->erase({drvr, load});
|
||||||
pairs_->erase(pair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3656,8 +3653,7 @@ Sdc::isDisabled(const Instance *inst,
|
||||||
{
|
{
|
||||||
if (role == TimingRole::wire()) {
|
if (role == TimingRole::wire()) {
|
||||||
// Hierarchical thru pin disables.
|
// Hierarchical thru pin disables.
|
||||||
PinPair pair(from_pin, to_pin);
|
return disabled_wire_edges_.contains({from_pin, to_pin});
|
||||||
return disabled_wire_edges_.contains(pair);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LibertyCell *cell = network_->libertyCell(inst);
|
LibertyCell *cell = network_->libertyCell(inst);
|
||||||
|
|
|
||||||
|
|
@ -1654,6 +1654,14 @@ set_propagate_all_clocks(bool prop)
|
||||||
Sta::sta()->setPropagateAllClocks(prop);
|
Sta::sta()->setPropagateAllClocks(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pin_is_constrained(const Pin *pin)
|
||||||
|
{
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
Sdc *sdc = sta->cmdSdc();
|
||||||
|
return sdc->isConstrained(pin);
|
||||||
|
}
|
||||||
|
|
||||||
%} // inline
|
%} // inline
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include "CheckTiming.hh"
|
#include "CheckTiming.hh"
|
||||||
|
|
||||||
#include "ContainerHelpers.hh"
|
|
||||||
#include "Error.hh"
|
#include "Error.hh"
|
||||||
#include "TimingRole.hh"
|
#include "TimingRole.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
|
|
@ -64,7 +63,6 @@ void
|
||||||
CheckTiming::deleteErrors()
|
CheckTiming::deleteErrors()
|
||||||
{
|
{
|
||||||
for (CheckError *error : errors_) {
|
for (CheckError *error : errors_) {
|
||||||
deleteContents(error);
|
|
||||||
delete error;
|
delete error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -204,25 +202,23 @@ CheckTiming::checkLoops()
|
||||||
errorMsgSubst("Warning: There %is %d combinational loop%s in the design.",
|
errorMsgSubst("Warning: There %is %d combinational loop%s in the design.",
|
||||||
loop_count, error_msg);
|
loop_count, error_msg);
|
||||||
CheckError *error = new CheckError;
|
CheckError *error = new CheckError;
|
||||||
error->push_back(stringCopy(error_msg.c_str()));
|
error->push_back(error_msg);
|
||||||
|
|
||||||
for (GraphLoop *loop : loops) {
|
for (GraphLoop *loop : loops) {
|
||||||
if (loop->isCombinational()) {
|
if (loop->isCombinational()) {
|
||||||
Edge *last_edge = nullptr;
|
Edge *last_edge = nullptr;
|
||||||
for (Edge *edge : *loop->edges()) {
|
for (Edge *edge : *loop->edges()) {
|
||||||
Pin *pin = edge->from(graph_)->pin();
|
Pin *pin = edge->from(graph_)->pin();
|
||||||
const char *pin_name = stringCopy(sdc_network_->pathName(pin));
|
error->push_back(sdc_network_->pathName(pin));
|
||||||
error->push_back(pin_name);
|
|
||||||
last_edge = edge;
|
last_edge = edge;
|
||||||
}
|
}
|
||||||
if (last_edge) {
|
if (last_edge) {
|
||||||
error->push_back(stringCopy("| loop cut point"));
|
error->push_back("| loop cut point");
|
||||||
const Pin *pin = last_edge->to(graph_)->pin();
|
const Pin *pin = last_edge->to(graph_)->pin();
|
||||||
const char *pin_name = stringCopy(sdc_network_->pathName(pin));
|
error->push_back(sdc_network_->pathName(pin));
|
||||||
error->push_back(pin_name);
|
|
||||||
|
|
||||||
// Separator between loops.
|
// Separator between loops.
|
||||||
error->push_back(stringCopy("--------------------------------"));
|
error->push_back("--------------------------------");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -362,15 +358,12 @@ CheckTiming::pushPinErrors(const char *msg,
|
||||||
CheckError *error = new CheckError;
|
CheckError *error = new CheckError;
|
||||||
std::string error_msg;
|
std::string error_msg;
|
||||||
errorMsgSubst(msg, pins.size(), error_msg);
|
errorMsgSubst(msg, pins.size(), error_msg);
|
||||||
// Copy the error strings because the error deletes them when it
|
error->push_back(error_msg);
|
||||||
// is deleted.
|
|
||||||
error->push_back(stringCopy(error_msg.c_str()));
|
|
||||||
// Sort the error pins so the output is independent of the order
|
// Sort the error pins so the output is independent of the order
|
||||||
// the the errors are discovered.
|
// the the errors are discovered.
|
||||||
PinSeq pins1 = sortByPathName(&pins, network_);
|
PinSeq pins1 = sortByPathName(&pins, network_);
|
||||||
for (const Pin *pin : pins1) {
|
for (const Pin *pin : pins1) {
|
||||||
const char *pin_name = stringCopy(sdc_network_->pathName(pin));
|
error->push_back(sdc_network_->pathName(pin));
|
||||||
error->push_back(pin_name);
|
|
||||||
}
|
}
|
||||||
errors_.push_back(error);
|
errors_.push_back(error);
|
||||||
}
|
}
|
||||||
|
|
@ -384,15 +377,12 @@ CheckTiming::pushClkErrors(const char *msg,
|
||||||
CheckError *error = new CheckError;
|
CheckError *error = new CheckError;
|
||||||
std::string error_msg;
|
std::string error_msg;
|
||||||
errorMsgSubst(msg, clks.size(), error_msg);
|
errorMsgSubst(msg, clks.size(), error_msg);
|
||||||
// Copy the error strings because the error deletes them when it
|
error->push_back(error_msg);
|
||||||
// is deleted.
|
|
||||||
error->push_back(stringCopy(error_msg.c_str()));
|
|
||||||
// Sort the error clks so the output is independent of the order
|
// Sort the error clks so the output is independent of the order
|
||||||
// the the errors are discovered.
|
// the the errors are discovered.
|
||||||
ClockSeq clks1 = sortByName(&clks);
|
ClockSeq clks1 = sortByName(&clks);
|
||||||
for (const Clock *clk : clks1) {
|
for (const Clock *clk : clks1) {
|
||||||
const char *clk_name = stringCopy(clk->name());
|
error->push_back(clk->name());
|
||||||
error->push_back(clk_name);
|
|
||||||
}
|
}
|
||||||
errors_.push_back(error);
|
errors_.push_back(error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "StringSeq.hh"
|
#include "StringUtil.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
|
||||||
report_->reportLine("%7s source latency %s %s",
|
report_->reportLine("%7s source latency %s %s",
|
||||||
time_unit->asString(src_latency, digits),
|
time_unit->asString(src_latency, digits),
|
||||||
sdc_network_->pathName(src_path->pin(this)),
|
sdc_network_->pathName(src_path->pin(this)),
|
||||||
src_path->transition(this)->to_string().c_str());
|
src_path->transition(this)->shortName());
|
||||||
if (src_internal_clk_latency != 0.0)
|
if (src_internal_clk_latency != 0.0)
|
||||||
report_->reportLine("%7s source internal clock delay",
|
report_->reportLine("%7s source internal clock delay",
|
||||||
time_unit->asString(src_internal_clk_latency, digits));
|
time_unit->asString(src_internal_clk_latency, digits));
|
||||||
|
|
@ -116,7 +116,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
|
||||||
report_->reportLine("%7s target latency %s %s",
|
report_->reportLine("%7s target latency %s %s",
|
||||||
time_unit->asString(-tgt_latency, digits),
|
time_unit->asString(-tgt_latency, digits),
|
||||||
sdc_network_->pathName(tgt_path->pin(this)),
|
sdc_network_->pathName(tgt_path->pin(this)),
|
||||||
tgt_path->transition(this)->to_string().c_str());
|
tgt_path->transition(this)->shortName());
|
||||||
if (tgt_internal_clk_latency != 0.0)
|
if (tgt_internal_clk_latency != 0.0)
|
||||||
report_->reportLine("%7s target internal clock delay",
|
report_->reportLine("%7s target internal clock delay",
|
||||||
time_unit->asString(-tgt_internal_clk_latency, digits));
|
time_unit->asString(-tgt_internal_clk_latency, digits));
|
||||||
|
|
@ -315,10 +315,10 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
|
||||||
debugPrint(debug_, "clk_skew", 2,
|
debugPrint(debug_, "clk_skew", 2,
|
||||||
"%s %s %s -> %s %s %s crpr = %s skew = %s",
|
"%s %s %s -> %s %s %s crpr = %s skew = %s",
|
||||||
network_->pathName(src_path->pin(this)),
|
network_->pathName(src_path->pin(this)),
|
||||||
src_path->transition(this)->to_string().c_str(),
|
src_path->transition(this)->shortName(),
|
||||||
time_unit->asString(probe.srcLatency(this)),
|
time_unit->asString(probe.srcLatency(this)),
|
||||||
network_->pathName(tgt_path->pin(this)),
|
network_->pathName(tgt_path->pin(this)),
|
||||||
tgt_path->transition(this)->to_string().c_str(),
|
tgt_path->transition(this)->shortName(),
|
||||||
time_unit->asString(probe.tgtLatency(this)),
|
time_unit->asString(probe.tgtLatency(this)),
|
||||||
delayAsString(probe.crpr(this), this),
|
delayAsString(probe.crpr(this), this),
|
||||||
time_unit->asString(probe.skew()));
|
time_unit->asString(probe.skew()));
|
||||||
|
|
|
||||||
|
|
@ -878,7 +878,7 @@ Genclks::recordSrcPaths(Clock *gclk)
|
||||||
debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s",
|
debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s",
|
||||||
network_->pathName(gclk_pin),
|
network_->pathName(gclk_pin),
|
||||||
early_late->to_string().c_str(),
|
early_late->to_string().c_str(),
|
||||||
rf->to_string().c_str(),
|
rf->shortName(),
|
||||||
delayAsString(path->arrival(), this));
|
delayAsString(path->arrival(), this));
|
||||||
src_path = *path;
|
src_path = *path;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,10 @@ Latches::latchOutArrival(const Path *data_path,
|
||||||
ArcDelay &arc_delay,
|
ArcDelay &arc_delay,
|
||||||
Arrival &q_arrival)
|
Arrival &q_arrival)
|
||||||
{
|
{
|
||||||
|
q_tag = nullptr;
|
||||||
|
arc_delay = 0.0;
|
||||||
|
q_arrival = 0.0;
|
||||||
|
|
||||||
Scene *scene = data_path->scene(this);
|
Scene *scene = data_path->scene(this);
|
||||||
Sdc *sdc = scene->sdc();
|
Sdc *sdc = scene->sdc();
|
||||||
const Mode *mode = scene->mode();
|
const Mode *mode = scene->mode();
|
||||||
|
|
@ -337,83 +341,110 @@ Latches::latchOutArrival(const Path *data_path,
|
||||||
// Latch enable may be missing if library is malformed.
|
// Latch enable may be missing if library is malformed.
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case LatchEnableState::closed:
|
case LatchEnableState::closed:
|
||||||
// Latch is disabled by constant enable.
|
// Latch is always closed because enable is constant.
|
||||||
break;
|
break;
|
||||||
case LatchEnableState::open: {
|
case LatchEnableState::open: {
|
||||||
|
// Latch is always open because enable is constant.
|
||||||
ExceptionPath *excpt = exceptionTo(data_path, nullptr);
|
ExceptionPath *excpt = exceptionTo(data_path, nullptr);
|
||||||
if (!(excpt && excpt->isFalse())) {
|
if (!(excpt && excpt->isFalse())) {
|
||||||
arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge,
|
arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge,
|
||||||
false, min_max, dcalc_ap, sdc);
|
false, min_max, dcalc_ap, sdc);
|
||||||
q_arrival = data_path->arrival() + arc_delay;
|
q_arrival = data_path->arrival() + arc_delay;
|
||||||
q_tag = data_path->tag(this);
|
// Copy the data tag but remove the drprClkPath.
|
||||||
|
// Levelization does not traverse latch D->Q edges, so in some cases
|
||||||
|
// level(Q) < level(D)
|
||||||
|
// Note that
|
||||||
|
// level(crprClkPath(data)) < level(D)
|
||||||
|
// The danger is that
|
||||||
|
// level(crprClkPath(data)) == level(Q)
|
||||||
|
// or some other downstream vertex.
|
||||||
|
// This can lead to data races when finding arrivals at the same level
|
||||||
|
// use multiple threads.
|
||||||
|
// Kill the crprClklPath to be safe.
|
||||||
|
const ClkInfo *data_clk_info = data_path->clkInfo(this);
|
||||||
|
const ClkInfo *q_clk_info =
|
||||||
|
search_->findClkInfo(scene,
|
||||||
|
data_clk_info->clkEdge(),
|
||||||
|
data_clk_info->clkSrc(),
|
||||||
|
data_clk_info->isPropagated(),
|
||||||
|
data_clk_info->genClkSrc(),
|
||||||
|
data_clk_info->isGenClkSrcPath(),
|
||||||
|
data_clk_info->pulseClkSense(),
|
||||||
|
data_clk_info->insertion(),
|
||||||
|
data_clk_info->latency(),
|
||||||
|
data_clk_info->uncertainties(),
|
||||||
|
min_max, nullptr);
|
||||||
|
q_tag = search_->findTag(scene, d_q_arc->toEdge()->asRiseFall(),
|
||||||
|
min_max, q_clk_info, false,
|
||||||
|
nullptr, false, data_path->tag(this)->states(),
|
||||||
|
false, nullptr);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case LatchEnableState::enabled: {
|
case LatchEnableState::enabled: {
|
||||||
const MinMax *tgt_min_max = data_path->tgtClkMinMax(this);
|
const MinMax *tgt_min_max = data_path->tgtClkMinMax(this);
|
||||||
VertexPathIterator enable_iter(enable_vertex, scene, tgt_min_max,
|
VertexPathIterator enable_iter(enable_vertex, scene, tgt_min_max,
|
||||||
enable_rf, this);
|
enable_rf, this);
|
||||||
while (enable_iter.hasNext()) {
|
while (enable_iter.hasNext()) {
|
||||||
Path *enable_path = enable_iter.next();
|
Path *enable_path = enable_iter.next();
|
||||||
const ClkInfo *en_clk_info = enable_path->clkInfo(this);
|
const ClkInfo *en_clk_info = enable_path->clkInfo(this);
|
||||||
const ClockEdge *en_clk_edge = en_clk_info->clkEdge();
|
const ClockEdge *en_clk_edge = en_clk_info->clkEdge();
|
||||||
if (enable_path->isClock(this)) {
|
if (enable_path->isClock(this)) {
|
||||||
ExceptionPath *excpt = exceptionTo(data_path, en_clk_edge);
|
ExceptionPath *excpt = exceptionTo(data_path, en_clk_edge);
|
||||||
// D->Q is disabled when if there is a path delay -to D or EN clk.
|
// D->Q is disabled when if there is a path delay -to D or EN clk.
|
||||||
if (!(excpt && (excpt->isFalse()
|
if (!(excpt && (excpt->isFalse()
|
||||||
|| excpt->isPathDelay()))) {
|
|| excpt->isPathDelay()))) {
|
||||||
Path *disable_path = latchEnableOtherPath(enable_path);
|
Path *disable_path = latchEnableOtherPath(enable_path);
|
||||||
Delay borrow, time_given_to_startpoint;
|
Delay borrow, time_given_to_startpoint;
|
||||||
Arrival adjusted_data_arrival;
|
Arrival adjusted_data_arrival;
|
||||||
Required required;
|
Required required;
|
||||||
latchRequired(data_path, enable_path, disable_path,
|
latchRequired(data_path, enable_path, disable_path,
|
||||||
required, borrow, adjusted_data_arrival,
|
required, borrow, adjusted_data_arrival,
|
||||||
time_given_to_startpoint);
|
time_given_to_startpoint);
|
||||||
if (delayGreater(borrow, 0.0, this)) {
|
if (delayGreater(borrow, 0.0, this)) {
|
||||||
// Latch is transparent when data arrives.
|
// Latch is transparent when data arrives.
|
||||||
arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge,
|
arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge,
|
||||||
false, min_max, dcalc_ap, sdc);
|
false, min_max, dcalc_ap, sdc);
|
||||||
q_arrival = adjusted_data_arrival + arc_delay;
|
q_arrival = adjusted_data_arrival + arc_delay;
|
||||||
// Tag switcheroo - data passing thru gets latch enable tag.
|
// Tag switcheroo - data passing thru gets latch enable tag.
|
||||||
// States and path ap come from Q, everything else from enable.
|
// States and path ap come from Q, everything else from enable.
|
||||||
Path *crpr_clk_path = crprActive(mode) ? enable_path : nullptr;
|
Path *crpr_clk_path = crprActive(mode) ? enable_path : nullptr;
|
||||||
const ClkInfo *q_clk_info =
|
const ClkInfo *q_clk_info =
|
||||||
search_->findClkInfo(en_clk_info->scene(),
|
search_->findClkInfo(scene,
|
||||||
en_clk_edge,
|
en_clk_edge,
|
||||||
en_clk_info->clkSrc(),
|
en_clk_info->clkSrc(),
|
||||||
en_clk_info->isPropagated(),
|
en_clk_info->isPropagated(),
|
||||||
en_clk_info->genClkSrc(),
|
en_clk_info->genClkSrc(),
|
||||||
en_clk_info->isGenClkSrcPath(),
|
en_clk_info->isGenClkSrcPath(),
|
||||||
en_clk_info->pulseClkSense(),
|
en_clk_info->pulseClkSense(),
|
||||||
en_clk_info->insertion(),
|
en_clk_info->insertion(),
|
||||||
en_clk_info->latency(),
|
en_clk_info->latency(),
|
||||||
en_clk_info->uncertainties(),
|
en_clk_info->uncertainties(),
|
||||||
min_max, crpr_clk_path);
|
min_max, crpr_clk_path);
|
||||||
const RiseFall *q_rf = d_q_arc->toEdge()->asRiseFall();
|
ExceptionStateSet *states = nullptr;
|
||||||
ExceptionStateSet *states = nullptr;
|
// Latch data pin is a valid exception -from pin.
|
||||||
// Latch data pin is a valid exception -from pin.
|
if (sdc->exceptionFromStates(data_path->pin(this),
|
||||||
if (sdc->exceptionFromStates(data_path->pin(this),
|
data_path->transition(this),
|
||||||
data_path->transition(this),
|
nullptr, nullptr, // clk below
|
||||||
nullptr, nullptr, // clk below
|
MinMax::max(), states)
|
||||||
MinMax::max(), states)
|
// -from enable non-filter exceptions apply.
|
||||||
// -from enable non-filter exceptions apply.
|
&& sdc->exceptionFromStates(enable_vertex->pin(),
|
||||||
&& sdc->exceptionFromStates(enable_vertex->pin(),
|
enable_rf,
|
||||||
enable_rf,
|
en_clk_edge->clock(),
|
||||||
en_clk_edge->clock(),
|
en_clk_edge->transition(),
|
||||||
en_clk_edge->transition(),
|
MinMax::max(), false, states))
|
||||||
MinMax::max(), false, states))
|
q_tag = search_->findTag(scene, d_q_arc->toEdge()->asRiseFall(),
|
||||||
q_tag = search_->findTag(enable_path->tag(this)->scene(),
|
MinMax::max(), q_clk_info, false,
|
||||||
q_rf, MinMax::max(), q_clk_info, false,
|
nullptr, false, states, true, nullptr);
|
||||||
nullptr, false, states, true, nullptr);
|
}
|
||||||
}
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// No enable path found.
|
// No enable path found.
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExceptionPath *
|
ExceptionPath *
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ Mode::makePathGroups(int group_path_count,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ Path::to_string(const StaState *sta) const
|
||||||
else
|
else
|
||||||
return stringPrintTmp("%s %s %s/%s %d",
|
return stringPrintTmp("%s %s %s/%s %d",
|
||||||
vertex(sta)->to_string(sta).c_str(),
|
vertex(sta)->to_string(sta).c_str(),
|
||||||
transition(sta)->to_string().c_str(),
|
transition(sta)->shortName(),
|
||||||
scene(sta)->name().c_str(),
|
scene(sta)->name().c_str(),
|
||||||
minMax(sta)->to_string().c_str(),
|
minMax(sta)->to_string().c_str(),
|
||||||
tagIndex(sta));
|
tagIndex(sta));
|
||||||
|
|
|
||||||
|
|
@ -2030,32 +2030,22 @@ PathEndPathDelay::exceptPathCmp(const PathEnd *path_end,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PathEndLess::PathEndLess(const StaState *sta) :
|
|
||||||
sta_(sta)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PathEndLess::operator()(const PathEnd *path_end1,
|
|
||||||
const PathEnd *path_end2) const
|
|
||||||
{
|
|
||||||
return PathEnd::less(path_end1, path_end2, sta_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PathEnd::less(const PathEnd *path_end1,
|
PathEnd::less(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2,
|
const PathEnd *path_end2,
|
||||||
|
bool cmp_slack,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
return cmp(path_end1, path_end2, sta) < 0;
|
return cmp(path_end1, path_end2, cmp_slack, sta) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PathEnd::cmp(const PathEnd *path_end1,
|
PathEnd::cmp(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2,
|
const PathEnd *path_end2,
|
||||||
|
bool cmp_slack,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
int cmp = path_end1->isUnconstrained()
|
int cmp = !cmp_slack || path_end1->isUnconstrained()
|
||||||
? -cmpArrival(path_end1, path_end2, sta)
|
? -cmpArrival(path_end1, path_end2, sta)
|
||||||
: cmpSlack(path_end1, path_end2, sta);
|
: cmpSlack(path_end1, path_end2, sta);
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
|
|
@ -2139,7 +2129,25 @@ PathEnd::cmpNoCrpr(const PathEnd *path_end1,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PathEndSlackLess::PathEndSlackLess(const StaState *sta) :
|
PathEndLess::PathEndLess(bool cmp_slack,
|
||||||
|
const StaState *sta) :
|
||||||
|
cmp_slack_(cmp_slack),
|
||||||
|
sta_(sta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathEndLess::operator()(const PathEnd *path_end1,
|
||||||
|
const PathEnd *path_end2) const
|
||||||
|
{
|
||||||
|
return PathEnd::less(path_end1, path_end2, cmp_slack_, sta_);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
PathEndSlackLess::PathEndSlackLess(bool cmp_slack,
|
||||||
|
const StaState *sta) :
|
||||||
|
cmp_slack_(cmp_slack),
|
||||||
sta_(sta)
|
sta_(sta)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ DiversionGreater::operator()(Diversion *div1,
|
||||||
{
|
{
|
||||||
PathEnd *path_end1 = div1->pathEnd();
|
PathEnd *path_end1 = div1->pathEnd();
|
||||||
PathEnd *path_end2 = div2->pathEnd();
|
PathEnd *path_end2 = div2->pathEnd();
|
||||||
return PathEnd::cmp(path_end1, path_end2, sta_) > 0;
|
return PathEnd::cmp(path_end1, path_end2, true, sta_) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -426,7 +426,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
|
||||||
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
|
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
|
||||||
from_path->to_string(this).c_str(),
|
from_path->to_string(this).c_str(),
|
||||||
to_vertex->to_string(this).c_str(),
|
to_vertex->to_string(this).c_str(),
|
||||||
to_rf->to_string().c_str(),
|
to_rf->shortName(),
|
||||||
delayAsString(search_->deratedDelay(from_vertex, arc, edge,
|
delayAsString(search_->deratedDelay(from_vertex, arc, edge,
|
||||||
false, from_path->minMax(this),
|
false, from_path->minMax(this),
|
||||||
from_path->dcalcAnalysisPtIndex(this),
|
from_path->dcalcAnalysisPtIndex(this),
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,8 @@ public:
|
||||||
// Insert path ends that are enumerated in slack/arrival order.
|
// Insert path ends that are enumerated in slack/arrival order.
|
||||||
void insert(PathEnd *path_end);
|
void insert(PathEnd *path_end);
|
||||||
virtual ~PathEnum();
|
virtual ~PathEnum();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual PathEnd *next();
|
PathEnd *next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void makeDiversions(PathEnd *path_end,
|
void makeDiversions(PathEnd *path_end,
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
size_t PathGroup::group_path_count_max = std::numeric_limits<size_t>::max();
|
int PathGroup::group_path_count_max = std::numeric_limits<int>::max();
|
||||||
|
|
||||||
PathGroup *
|
PathGroup *
|
||||||
PathGroup::makePathGroupSlack(const char *name,
|
PathGroup::makePathGroupSlack(const char *name,
|
||||||
|
|
@ -82,8 +82,8 @@ PathGroup::makePathGroupArrival(const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
PathGroup::PathGroup(const char *name,
|
PathGroup::PathGroup(const char *name,
|
||||||
size_t group_path_count,
|
int group_path_count,
|
||||||
size_t endpoint_path_count,
|
int endpoint_path_count,
|
||||||
bool unique_pins,
|
bool unique_pins,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
|
|
@ -99,43 +99,36 @@ PathGroup::PathGroup(const char *name,
|
||||||
slack_min_(slack_min),
|
slack_min_(slack_min),
|
||||||
slack_max_(slack_max),
|
slack_max_(slack_max),
|
||||||
min_max_(min_max),
|
min_max_(min_max),
|
||||||
compare_slack_(cmp_slack),
|
cmp_slack_(cmp_slack),
|
||||||
threshold_(min_max->initValue()),
|
heap_(group_path_count, PathEndLess(cmp_slack, sta)),
|
||||||
sta_(sta)
|
sta_(sta)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PathGroup::~PathGroup()
|
PathEndSeq
|
||||||
|
PathGroup::pathEnds() const
|
||||||
{
|
{
|
||||||
deleteContents(path_ends_);
|
return heap_.contents();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PathGroup::saveable(PathEnd *path_end)
|
PathGroup::saveable(PathEnd *path_end)
|
||||||
{
|
{
|
||||||
float threshold;
|
if (cmp_slack_) {
|
||||||
{
|
|
||||||
LockGuard lock(lock_);
|
|
||||||
threshold = threshold_;
|
|
||||||
}
|
|
||||||
if (compare_slack_) {
|
|
||||||
// Crpr increases the slack, so check the slack
|
// Crpr increases the slack, so check the slack
|
||||||
// without crpr first because it is expensive to find.
|
// without crpr first because it is expensive to find.
|
||||||
Slack slack = path_end->slackNoCrpr(sta_);
|
Slack slack = path_end->slackNoCrpr(sta_);
|
||||||
if (!delayIsInitValue(slack, min_max_)
|
if (!delayIsInitValue(slack, min_max_)
|
||||||
&& delayLessEqual(slack, threshold, sta_)
|
|
||||||
&& delayLessEqual(slack, slack_max_, sta_)) {
|
&& delayLessEqual(slack, slack_max_, sta_)) {
|
||||||
// Now check with crpr.
|
// Now check with crpr.
|
||||||
slack = path_end->slack(sta_);
|
slack = path_end->slack(sta_);
|
||||||
return delayLessEqual(slack, threshold, sta_)
|
return delayLessEqual(slack, slack_max_, sta_)
|
||||||
&& delayLessEqual(slack, slack_max_, sta_)
|
|
||||||
&& delayGreaterEqual(slack, slack_min_, sta_);
|
&& delayGreaterEqual(slack, slack_min_, sta_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const Arrival &arrival = path_end->dataArrivalTime(sta_);
|
const Arrival &arrival = path_end->dataArrivalTime(sta_);
|
||||||
return !delayIsInitValue(arrival, min_max_)
|
return !delayIsInitValue(arrival, min_max_);
|
||||||
&& delayGreaterEqual(arrival, threshold, min_max_, sta_);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +141,7 @@ PathGroup::saveable(PathEnd *path_end)
|
||||||
bool
|
bool
|
||||||
PathGroup::enumMinSlackUnderMin(PathEnd *path_end)
|
PathGroup::enumMinSlackUnderMin(PathEnd *path_end)
|
||||||
{
|
{
|
||||||
if (compare_slack_
|
if (cmp_slack_
|
||||||
&& endpoint_path_count_ > 1
|
&& endpoint_path_count_ > 1
|
||||||
&& slack_min_ > -INF) {
|
&& slack_min_ > -INF) {
|
||||||
const Path *path = path_end->path();
|
const Path *path = path_end->path();
|
||||||
|
|
@ -177,72 +170,28 @@ void
|
||||||
PathGroup::insert(PathEnd *path_end)
|
PathGroup::insert(PathEnd *path_end)
|
||||||
{
|
{
|
||||||
LockGuard lock(lock_);
|
LockGuard lock(lock_);
|
||||||
path_ends_.push_back(path_end);
|
heap_.insert(path_end);
|
||||||
path_end->setPathGroup(this);
|
path_end->setPathGroup(this);
|
||||||
if (group_path_count_ != group_path_count_max
|
|
||||||
&& path_ends_.size() > group_path_count_ * 2)
|
|
||||||
prune();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathGroup::prune()
|
|
||||||
{
|
|
||||||
sort();
|
|
||||||
VertexPathCountMap path_counts;
|
|
||||||
size_t end_count = 0;
|
|
||||||
for (unsigned i = 0; i < path_ends_.size(); i++) {
|
|
||||||
PathEnd *path_end = path_ends_[i];
|
|
||||||
Vertex *vertex = path_end->vertex(sta_);
|
|
||||||
// Squish up to endpoint_path_count path ends per vertex
|
|
||||||
// up to the front of path_ends_.
|
|
||||||
if (end_count < group_path_count_
|
|
||||||
&& path_counts[vertex] < endpoint_path_count_) {
|
|
||||||
path_ends_[end_count++] = path_end;
|
|
||||||
path_counts[vertex]++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
delete path_end;
|
|
||||||
}
|
|
||||||
path_ends_.resize(end_count);
|
|
||||||
|
|
||||||
// Set a threshold to the bottom of the sorted list that future
|
|
||||||
// inserts need to beat.
|
|
||||||
PathEnd *last_end = path_ends_[end_count - 1];
|
|
||||||
if (compare_slack_)
|
|
||||||
threshold_ = delayAsFloat(last_end->slack(sta_));
|
|
||||||
else
|
|
||||||
threshold_ = delayAsFloat(last_end->dataArrivalTime(sta_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathGroup::pushEnds(PathEndSeq &path_ends)
|
PathGroup::pushEnds(PathEndSeq &path_ends)
|
||||||
{
|
{
|
||||||
ensureSortedMaxPaths();
|
if (!heap_.empty()) {
|
||||||
for (PathEnd *path_end : path_ends_)
|
PathEndSeq ends = heap_.extract();
|
||||||
path_ends.push_back(path_end);
|
path_ends.reserve(path_ends.size() + ends.size());
|
||||||
}
|
// Append heap path ends to path_ends.
|
||||||
|
path_ends.insert(path_ends.end(),
|
||||||
void
|
std::make_move_iterator(ends.begin()),
|
||||||
PathGroup::ensureSortedMaxPaths()
|
std::make_move_iterator(ends.end()));
|
||||||
{
|
}
|
||||||
if (path_ends_.size() > group_path_count_)
|
|
||||||
prune();
|
|
||||||
else
|
|
||||||
sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathGroup::sort()
|
|
||||||
{
|
|
||||||
sta::sort(path_ends_, PathEndLess(sta_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathGroup::clear()
|
PathGroup::clear()
|
||||||
{
|
{
|
||||||
LockGuard lock(lock_);
|
LockGuard lock(lock_);
|
||||||
threshold_ = min_max_->initValue();
|
heap_.clear();
|
||||||
path_ends_.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -258,7 +207,7 @@ PathGroups::PathGroups(int group_path_count,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
@ -276,7 +225,7 @@ PathGroups::PathGroups(int group_path_count,
|
||||||
slack_min_(slack_min),
|
slack_min_(slack_min),
|
||||||
slack_max_(slack_max)
|
slack_max_(slack_max)
|
||||||
{
|
{
|
||||||
StdStringSet groups;
|
StringSet groups;
|
||||||
for (std::string &group_name : group_names)
|
for (std::string &group_name : group_names)
|
||||||
groups.insert(group_name);
|
groups.insert(group_name);
|
||||||
|
|
||||||
|
|
@ -297,7 +246,7 @@ PathGroups::makeGroups(int group_path_count,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
StdStringSet &group_names,
|
StringSet &group_names,
|
||||||
bool setup_hold,
|
bool setup_hold,
|
||||||
bool async,
|
bool async,
|
||||||
bool gated_clk,
|
bool gated_clk,
|
||||||
|
|
@ -417,7 +366,7 @@ PathGroups::findPathGroup(const Clock *clock,
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PathGroups::reportGroup(const char *group_name,
|
PathGroups::reportGroup(const char *group_name,
|
||||||
StdStringSet &group_names) const
|
StringSet &group_names) const
|
||||||
{
|
{
|
||||||
return group_names.empty()
|
return group_names.empty()
|
||||||
|| group_names.contains(group_name);
|
|| group_names.contains(group_name);
|
||||||
|
|
@ -479,11 +428,11 @@ PathGroups::pathGroups(const PathEnd *path_end) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mirrors PathGroups::pathGroup.
|
// Mirrors PathGroups::pathGroup.
|
||||||
StdStringSeq
|
StringSeq
|
||||||
PathGroups::pathGroupNames(const PathEnd *path_end,
|
PathGroups::pathGroupNames(const PathEnd *path_end,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
StdStringSeq group_names;
|
StringSeq group_names;
|
||||||
const char *group_name = nullptr;
|
const char *group_name = nullptr;
|
||||||
const Search *search = sta->search();
|
const Search *search = sta->search();
|
||||||
ExceptionPathSeq group_paths = search->groupPathsTo(path_end);
|
ExceptionPathSeq group_paths = search->groupPathsTo(path_end);
|
||||||
|
|
@ -576,14 +525,14 @@ PathGroups::pushEnds(PathEndSeq &path_ends)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStringSeq
|
StringSeq
|
||||||
PathGroups::pathGroupNames()
|
PathGroups::pathGroupNames()
|
||||||
{
|
{
|
||||||
std::set<std::string> group_names1;
|
std::set<std::string> group_names1;
|
||||||
const Sdc *sdc = mode_->sdc();
|
const Sdc *sdc = mode_->sdc();
|
||||||
for (const auto& [name, group] : sdc->groupPaths())
|
for (const auto& [name, group] : sdc->groupPaths())
|
||||||
group_names1.insert(name);
|
group_names1.insert(name);
|
||||||
StdStringSeq group_names2;
|
StringSeq group_names2;
|
||||||
for (const std::string &name : group_names1)
|
for (const std::string &name : group_names1)
|
||||||
group_names2.push_back(name);
|
group_names2.push_back(name);
|
||||||
sort(group_names2);
|
sort(group_names2);
|
||||||
|
|
@ -632,9 +581,8 @@ PathGroups::makePathEnds(ExceptionTo *to,
|
||||||
unique_pins_, unique_edges_, scenes, min_max);
|
unique_pins_, unique_edges_, scenes, min_max);
|
||||||
|
|
||||||
pushEnds(path_ends);
|
pushEnds(path_ends);
|
||||||
if (sort_by_slack) {
|
if (sort_by_slack)
|
||||||
sort(path_ends, PathEndLess(this));
|
sort(path_ends, PathEndLess(true, this));
|
||||||
}
|
|
||||||
|
|
||||||
if (unconstrained_paths
|
if (unconstrained_paths
|
||||||
&& path_ends.empty())
|
&& path_ends.empty())
|
||||||
|
|
@ -663,12 +611,12 @@ private:
|
||||||
|
|
||||||
PathGroups *path_groups_;
|
PathGroups *path_groups_;
|
||||||
PathGroupEndMap ends_;
|
PathGroupEndMap ends_;
|
||||||
PathEndLess cmp_;
|
PathEndLess less_;
|
||||||
};
|
};
|
||||||
|
|
||||||
MakePathEnds1::MakePathEnds1(PathGroups *path_groups) :
|
MakePathEnds1::MakePathEnds1(PathGroups *path_groups) :
|
||||||
path_groups_(path_groups),
|
path_groups_(path_groups),
|
||||||
cmp_(path_groups)
|
less_(true, path_groups)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,7 +641,7 @@ MakePathEnds1::visitPathEnd(PathEnd *path_end,
|
||||||
// Only keep the path end with the smallest slack/latest arrival.
|
// Only keep the path end with the smallest slack/latest arrival.
|
||||||
PathEnd *worst_end = findKey(ends_, group);
|
PathEnd *worst_end = findKey(ends_, group);
|
||||||
if (worst_end) {
|
if (worst_end) {
|
||||||
if (cmp_(path_end, worst_end)) {
|
if (less_(path_end, worst_end)) {
|
||||||
ends_[group] = path_end->copy();
|
ends_[group] = path_end->copy();
|
||||||
delete worst_end;
|
delete worst_end;
|
||||||
}
|
}
|
||||||
|
|
@ -741,8 +689,8 @@ private:
|
||||||
PathGroups *path_groups_;
|
PathGroups *path_groups_;
|
||||||
const StaState *sta_;
|
const StaState *sta_;
|
||||||
PathGroupEndsMap ends_;
|
PathGroupEndsMap ends_;
|
||||||
PathEndSlackLess slack_cmp_;
|
PathEndSlackLess less_;
|
||||||
PathEndNoCrprLess path_no_crpr_cmp_;
|
PathEndNoCrprLess path_no_crpr_less_;
|
||||||
};
|
};
|
||||||
|
|
||||||
MakePathEndsAll::MakePathEndsAll(int endpoint_path_count,
|
MakePathEndsAll::MakePathEndsAll(int endpoint_path_count,
|
||||||
|
|
@ -750,8 +698,8 @@ MakePathEndsAll::MakePathEndsAll(int endpoint_path_count,
|
||||||
endpoint_path_count_(endpoint_path_count),
|
endpoint_path_count_(endpoint_path_count),
|
||||||
path_groups_(path_groups),
|
path_groups_(path_groups),
|
||||||
sta_(path_groups),
|
sta_(path_groups),
|
||||||
slack_cmp_(path_groups),
|
less_(true, path_groups),
|
||||||
path_no_crpr_cmp_(path_groups)
|
path_no_crpr_less_(path_groups)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -792,8 +740,8 @@ MakePathEndsAll::vertexEnd(Vertex *)
|
||||||
Debug *debug = sta_->debug();
|
Debug *debug = sta_->debug();
|
||||||
for (auto [group, ends] : ends_) {
|
for (auto [group, ends] : ends_) {
|
||||||
if (ends) {
|
if (ends) {
|
||||||
sort(ends, slack_cmp_);
|
sort(ends, less_);
|
||||||
PathEndNoCrprSet unique_ends(path_no_crpr_cmp_);
|
PathEndNoCrprSet unique_ends(path_no_crpr_less_);
|
||||||
auto end_iter = ends->begin();
|
auto end_iter = ends->begin();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
while (end_iter != ends->end()
|
while (end_iter != ends->end()
|
||||||
|
|
@ -805,7 +753,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
|
||||||
debugPrint(debug, "path_group", 2, "insert %s %s %s %d",
|
debugPrint(debug, "path_group", 2, "insert %s %s %s %d",
|
||||||
path_end->vertex(sta_)->to_string(sta_).c_str(),
|
path_end->vertex(sta_)->to_string(sta_).c_str(),
|
||||||
path_end->typeName(),
|
path_end->typeName(),
|
||||||
path_end->transition(sta_)->to_string().c_str(),
|
path_end->transition(sta_)->shortName(),
|
||||||
path_end->path()->tag(sta_)->index());
|
path_end->path()->tag(sta_)->index());
|
||||||
// Give the group a copy of the path end because
|
// Give the group a copy of the path end because
|
||||||
// it may delete it during pruning.
|
// it may delete it during pruning.
|
||||||
|
|
@ -820,7 +768,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
|
||||||
debugPrint(debug, "path_group", 3, "prune %s %s %s %d",
|
debugPrint(debug, "path_group", 3, "prune %s %s %s %d",
|
||||||
path_end->vertex(sta_)->to_string(sta_).c_str(),
|
path_end->vertex(sta_)->to_string(sta_).c_str(),
|
||||||
path_end->typeName(),
|
path_end->typeName(),
|
||||||
path_end->transition(sta_)->to_string().c_str(),
|
path_end->transition(sta_)->shortName(),
|
||||||
path_end->path()->tag(sta_)->index());
|
path_end->path()->tag(sta_)->index());
|
||||||
}
|
}
|
||||||
// Clear ends for next vertex.
|
// Clear ends for next vertex.
|
||||||
|
|
@ -898,11 +846,8 @@ PathGroups::enumPathEnds(PathGroup *group,
|
||||||
// enumerator.
|
// enumerator.
|
||||||
PathEnum path_enum(group_path_count, endpoint_path_count,
|
PathEnum path_enum(group_path_count, endpoint_path_count,
|
||||||
unique_pins, unique_edges, cmp_slack, this);
|
unique_pins, unique_edges, cmp_slack, this);
|
||||||
for (PathEnd *end : group->pathEnds()) {
|
for (PathEnd *end : group->pathEnds())
|
||||||
if (group->saveable(end)
|
path_enum.insert(end);
|
||||||
|| group->enumMinSlackUnderMin(end))
|
|
||||||
path_enum.insert(end);
|
|
||||||
}
|
|
||||||
group->clear();
|
group->clear();
|
||||||
|
|
||||||
// Parallel path enumeratation to find the endpoint_path_count/max path ends.
|
// Parallel path enumeratation to find the endpoint_path_count/max path ends.
|
||||||
|
|
|
||||||
|
|
@ -211,15 +211,15 @@ ReportPath::findField(const char *name) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ReportPath::setReportFieldOrder(StringSeq *field_names)
|
ReportPath::setReportFieldOrder(const StringSeq &field_names)
|
||||||
{
|
{
|
||||||
// Disable all fields.
|
// Disable all fields.
|
||||||
for (ReportField *field : fields_)
|
for (ReportField *field : fields_)
|
||||||
field->setEnabled(false);
|
field->setEnabled(false);
|
||||||
|
|
||||||
ReportFieldSeq next_fields;
|
ReportFieldSeq next_fields;
|
||||||
for (const char *field_name : *field_names) {
|
for (const std::string &field_name : field_names) {
|
||||||
ReportField *field = findField(field_name);
|
ReportField *field = findField(field_name.c_str());
|
||||||
if (field) {
|
if (field) {
|
||||||
next_fields.push_back(field);
|
next_fields.push_back(field);
|
||||||
field->setEnabled(true);
|
field->setEnabled(true);
|
||||||
|
|
@ -406,7 +406,7 @@ ReportPath::reportEndpointHeader(const PathEnd *end,
|
||||||
: "max_delay/setup";
|
: "max_delay/setup";
|
||||||
report_->reportLine("%s group %s",
|
report_->reportLine("%s group %s",
|
||||||
setup_hold,
|
setup_hold,
|
||||||
group->name());
|
group->name().c_str());
|
||||||
reportBlankLine();
|
reportBlankLine();
|
||||||
reportEndHeader();
|
reportEndHeader();
|
||||||
}
|
}
|
||||||
|
|
@ -1079,11 +1079,17 @@ ReportPath::reportJson(const PathEnd *end,
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
result += "{\n";
|
result += "{\n";
|
||||||
stringAppend(result, " \"type\": \"%s\",\n", end->typeName());
|
result += " \"type\": \"";
|
||||||
stringAppend(result, " \"path_group\": \"%s\",\n",
|
result += end->typeName();
|
||||||
end->pathGroup()->name());
|
result += "\",\n";
|
||||||
stringAppend(result, " \"path_type\": \"%s\",\n",
|
|
||||||
end->minMax(this)->to_string().c_str());
|
result += " \"path_group\": \"";
|
||||||
|
result += end->pathGroup()->name();
|
||||||
|
result += "\",\n";
|
||||||
|
|
||||||
|
result += " \"path_type\": \"";
|
||||||
|
result += end->minMax(this)->to_string();
|
||||||
|
result += "\",\n";
|
||||||
|
|
||||||
PathExpanded expanded(end->path(), this);
|
PathExpanded expanded(end->path(), this);
|
||||||
const Pin *startpoint = expanded.startPath()->vertex(this)->pin();
|
const Pin *startpoint = expanded.startPath()->vertex(this)->pin();
|
||||||
|
|
@ -1269,7 +1275,7 @@ ReportPath::reportSlackOnly(const PathEnd *end) const
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
const EarlyLate *early_late = end->pathEarlyLate(this);
|
const EarlyLate *early_late = end->pathEarlyLate(this);
|
||||||
reportDescription(end->pathGroup()->name(), line);
|
reportDescription(end->pathGroup()->name().c_str(), line);
|
||||||
if (end->isUnconstrained())
|
if (end->isUnconstrained())
|
||||||
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, line);
|
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, line);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "StringSeq.hh"
|
#include "StringUtil.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
#include "PathEnd.hh"
|
#include "PathEnd.hh"
|
||||||
#include "CheckMinPulseWidths.hh"
|
#include "CheckMinPulseWidths.hh"
|
||||||
|
|
@ -49,7 +49,7 @@ public:
|
||||||
virtual ~ReportPath();
|
virtual ~ReportPath();
|
||||||
ReportPathFormat pathFormat() const { return format_; }
|
ReportPathFormat pathFormat() const { return format_; }
|
||||||
void setPathFormat(ReportPathFormat format);
|
void setPathFormat(ReportPathFormat format);
|
||||||
void setReportFieldOrder(StringSeq *field_names);
|
void setReportFieldOrder(const StringSeq &field_names);
|
||||||
void setReportFields(bool report_input_pin,
|
void setReportFields(bool report_input_pin,
|
||||||
bool report_hier_pins,
|
bool report_hier_pins,
|
||||||
bool report_net,
|
bool report_net,
|
||||||
|
|
|
||||||
|
|
@ -497,14 +497,14 @@ Search::findPathEnds(ExceptionFrom *from,
|
||||||
bool unconstrained,
|
bool unconstrained,
|
||||||
const SceneSeq &scenes,
|
const SceneSeq &scenes,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
size_t group_path_count,
|
int group_path_count,
|
||||||
size_t endpoint_path_count,
|
int endpoint_path_count,
|
||||||
bool unique_pins,
|
bool unique_pins,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
bool sort_by_slack,
|
bool sort_by_slack,
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
@ -1365,8 +1365,8 @@ ArrivalVisitor::visitFromToPath(const Pin * /* from_pin */,
|
||||||
debugPrint(debug_, "search", 3, " %s",
|
debugPrint(debug_, "search", 3, " %s",
|
||||||
from_vertex->to_string(this).c_str());
|
from_vertex->to_string(this).c_str());
|
||||||
debugPrint(debug_, "search", 3, " %s -> %s %s",
|
debugPrint(debug_, "search", 3, " %s -> %s %s",
|
||||||
from_rf->to_string().c_str(),
|
from_rf->shortName(),
|
||||||
to_rf->to_string().c_str(),
|
to_rf->shortName(),
|
||||||
min_max->to_string().c_str());
|
min_max->to_string().c_str());
|
||||||
debugPrint(debug_, "search", 3, " from tag: %s",
|
debugPrint(debug_, "search", 3, " from tag: %s",
|
||||||
from_tag->to_string(this).c_str());
|
from_tag->to_string(this).c_str());
|
||||||
|
|
@ -2919,7 +2919,7 @@ Search::reportArrivals(Vertex *vertex,
|
||||||
prev_str += "NULL";
|
prev_str += "NULL";
|
||||||
}
|
}
|
||||||
report_->reportLine(" %s %s %s / %s %s%s",
|
report_->reportLine(" %s %s %s / %s %s%s",
|
||||||
rf->to_string().c_str(),
|
rf->shortName(),
|
||||||
path->minMax(this)->to_string().c_str(),
|
path->minMax(this)->to_string().c_str(),
|
||||||
delayAsString(path->arrival(), this),
|
delayAsString(path->arrival(), this),
|
||||||
req,
|
req,
|
||||||
|
|
@ -3654,10 +3654,10 @@ RequiredVisitor::visitFromToPath(const Pin *,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
// Don't propagate required times through latch D->Q edges.
|
// Don't propagate required times through latch D->Q edges.
|
||||||
if (edge->role() != TimingRole::latchDtoQ()) {
|
if (!edge->role()->isLatchDtoQ()) {
|
||||||
debugPrint(debug_, "search", 3, " %s -> %s %s",
|
debugPrint(debug_, "search", 3, " %s -> %s %s",
|
||||||
from_rf->to_string().c_str(),
|
from_rf->shortName(),
|
||||||
to_rf->to_string().c_str(),
|
to_rf->shortName(),
|
||||||
min_max->to_string().c_str());
|
min_max->to_string().c_str());
|
||||||
debugPrint(debug_, "search", 3, " from tag %2u: %s",
|
debugPrint(debug_, "search", 3, " from tag %2u: %s",
|
||||||
from_tag->index(),
|
from_tag->index(),
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ endpoint_slack(const Pin *pin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStringSeq
|
StringSeq
|
||||||
path_group_names()
|
path_group_names()
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
|
|
@ -359,7 +359,7 @@ find_path_ends(ExceptionFrom *from,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
bool sort_by_slack,
|
bool sort_by_slack,
|
||||||
StdStringSeq path_groups,
|
StringSeq path_groups,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
@ -395,10 +395,9 @@ set_report_path_format(ReportPathFormat format)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_report_path_field_order(StringSeq *field_names)
|
set_report_path_field_order(const StringSeq &field_names)
|
||||||
{
|
{
|
||||||
Sta::sta()->setReportPathFieldOrder(field_names);
|
Sta::sta()->setReportPathFieldOrder(field_names);
|
||||||
delete field_names;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -741,8 +740,8 @@ write_timing_model_cmd(const char *lib_name,
|
||||||
void
|
void
|
||||||
define_scene_cmd(const char *name,
|
define_scene_cmd(const char *name,
|
||||||
const char *mode_name,
|
const char *mode_name,
|
||||||
const StdStringSeq liberty_min_files,
|
const StringSeq liberty_min_files,
|
||||||
const StdStringSeq liberty_max_files,
|
const StringSeq liberty_max_files,
|
||||||
const char *spef_min_file,
|
const char *spef_min_file,
|
||||||
const char *spef_max_file)
|
const char *spef_max_file)
|
||||||
{
|
{
|
||||||
|
|
@ -753,11 +752,10 @@ define_scene_cmd(const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
define_scenes_cmd(StringSeq *scene_names)
|
define_scenes_cmd(const StringSeq &scene_names)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
sta->makeScenes(scene_names);
|
sta->makeScenes(scene_names);
|
||||||
delete scene_names;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene *
|
Scene *
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "Mode.hh"
|
#include "Mode.hh"
|
||||||
#include "Variables.hh"
|
#include "Variables.hh"
|
||||||
#include "WriteSdc.hh"
|
#include "sdc/WriteSdc.hh"
|
||||||
#include "ExceptionPath.hh"
|
#include "ExceptionPath.hh"
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "parasitics/SpefReader.hh"
|
#include "parasitics/SpefReader.hh"
|
||||||
|
|
@ -299,6 +299,7 @@ Sta::makeComponents()
|
||||||
makeReportPath();
|
makeReportPath();
|
||||||
makePower();
|
makePower();
|
||||||
makeClkSkews();
|
makeClkSkews();
|
||||||
|
makeCheckTiming();
|
||||||
|
|
||||||
setCmdNamespace1(CmdNamespace::sdc);
|
setCmdNamespace1(CmdNamespace::sdc);
|
||||||
setThreadCount1(defaultThreadCount());
|
setThreadCount1(defaultThreadCount());
|
||||||
|
|
@ -355,8 +356,7 @@ Sta::updateComponentsState()
|
||||||
latches_->copyState(this);
|
latches_->copyState(this);
|
||||||
graph_delay_calc_->copyState(this);
|
graph_delay_calc_->copyState(this);
|
||||||
report_path_->copyState(this);
|
report_path_->copyState(this);
|
||||||
if (check_timing_)
|
check_timing_->copyState(this);
|
||||||
check_timing_->copyState(this);
|
|
||||||
clk_skews_->copyState(this);
|
clk_skews_->copyState(this);
|
||||||
|
|
||||||
if (power_)
|
if (power_)
|
||||||
|
|
@ -2075,10 +2075,10 @@ Sta::isPathGroupName(const char *group_name,
|
||||||
|| stringEq(group_name, PathGroups::unconstrainedGroupName());
|
|| stringEq(group_name, PathGroups::unconstrainedGroupName());
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStringSeq
|
StringSeq
|
||||||
Sta::pathGroupNames(const Sdc *sdc) const
|
Sta::pathGroupNames(const Sdc *sdc) const
|
||||||
{
|
{
|
||||||
StdStringSeq names;
|
StringSeq names;
|
||||||
for (const Clock *clk : sdc->clocks())
|
for (const Clock *clk : sdc->clocks())
|
||||||
names.push_back(clk->name());
|
names.push_back(clk->name());
|
||||||
|
|
||||||
|
|
@ -2214,8 +2214,8 @@ Sta::checkTiming(const Mode *mode,
|
||||||
bool generated_clks)
|
bool generated_clks)
|
||||||
{
|
{
|
||||||
if (unconstrained_endpoints) {
|
if (unconstrained_endpoints) {
|
||||||
// Only arrivals to find unconstrained_endpoints.
|
// Only need non-clock arrivals to find unconstrained_endpoints.
|
||||||
searchPreamble();
|
searchPreamble();
|
||||||
search_->findAllArrivals();
|
search_->findAllArrivals();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -2224,8 +2224,6 @@ Sta::checkTiming(const Mode *mode,
|
||||||
mode->sim()->ensureConstantsPropagated();
|
mode->sim()->ensureConstantsPropagated();
|
||||||
mode->clkNetwork()->ensureClkNetwork();
|
mode->clkNetwork()->ensureClkNetwork();
|
||||||
}
|
}
|
||||||
if (check_timing_ == nullptr)
|
|
||||||
makeCheckTiming();
|
|
||||||
return check_timing_->check(mode, no_input_delay, no_output_delay,
|
return check_timing_->check(mode, no_input_delay, no_output_delay,
|
||||||
reg_multiple_clks, reg_no_clks,
|
reg_multiple_clks, reg_no_clks,
|
||||||
unconstrained_endpoints,
|
unconstrained_endpoints,
|
||||||
|
|
@ -2468,9 +2466,9 @@ Sta::makeDefaultScene()
|
||||||
|
|
||||||
// define_corners (before read_liberty).
|
// define_corners (before read_liberty).
|
||||||
void
|
void
|
||||||
Sta::makeScenes(StringSeq *scene_names)
|
Sta::makeScenes(const StringSeq &scene_names)
|
||||||
{
|
{
|
||||||
if (scene_names->size() > scene_count_max)
|
if (scene_names.size() > scene_count_max)
|
||||||
report_->error(1553, "maximum scene count exceeded");
|
report_->error(1553, "maximum scene count exceeded");
|
||||||
Parasitics *parasitics = findParasitics("default");
|
Parasitics *parasitics = findParasitics("default");
|
||||||
Mode *mode = modes_[0];
|
Mode *mode = modes_[0];
|
||||||
|
|
@ -2478,7 +2476,7 @@ Sta::makeScenes(StringSeq *scene_names)
|
||||||
mode->clear();
|
mode->clear();
|
||||||
|
|
||||||
deleteScenes();
|
deleteScenes();
|
||||||
for (const char *name : *scene_names)
|
for (const std::string &name : scene_names)
|
||||||
makeScene(name, mode, parasitics);
|
makeScene(name, mode, parasitics);
|
||||||
|
|
||||||
cmd_scene_ = scenes_[0];
|
cmd_scene_ = scenes_[0];
|
||||||
|
|
@ -2490,8 +2488,8 @@ Sta::makeScenes(StringSeq *scene_names)
|
||||||
void
|
void
|
||||||
Sta::makeScene(const std::string &name,
|
Sta::makeScene(const std::string &name,
|
||||||
const std::string &mode_name,
|
const std::string &mode_name,
|
||||||
const StdStringSeq &liberty_min_files,
|
const StringSeq &liberty_min_files,
|
||||||
const StdStringSeq &liberty_max_files,
|
const StringSeq &liberty_max_files,
|
||||||
const std::string &spef_min_file,
|
const std::string &spef_min_file,
|
||||||
const std::string &spef_max_file)
|
const std::string &spef_max_file)
|
||||||
{
|
{
|
||||||
|
|
@ -2598,12 +2596,12 @@ Sta::findScenes(const std::string &name,
|
||||||
|
|
||||||
void
|
void
|
||||||
Sta::updateSceneLiberty(Scene *scene,
|
Sta::updateSceneLiberty(Scene *scene,
|
||||||
const StdStringSeq &liberty_min_files,
|
const StringSeq &liberty_min_files,
|
||||||
const StdStringSeq &liberty_max_files)
|
const StringSeq &liberty_max_files)
|
||||||
{
|
{
|
||||||
StdStringSet warned_files;
|
StringSet warned_files;
|
||||||
for (const MinMax *min_max : MinMax::range()) {
|
for (const MinMax *min_max : MinMax::range()) {
|
||||||
const StdStringSeq &liberty_files = min_max == MinMax::min()
|
const StringSeq &liberty_files = min_max == MinMax::min()
|
||||||
? liberty_min_files
|
? liberty_min_files
|
||||||
: liberty_max_files;
|
: liberty_max_files;
|
||||||
for (const std::string &lib_file : liberty_files) {
|
for (const std::string &lib_file : liberty_files) {
|
||||||
|
|
@ -2678,7 +2676,7 @@ Sta::findPathEnds(ExceptionFrom *from,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
bool sort_by_slack,
|
bool sort_by_slack,
|
||||||
StdStringSeq &group_names,
|
StringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
@ -2729,7 +2727,7 @@ Sta::setReportPathFormat(ReportPathFormat format)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Sta::setReportPathFieldOrder(StringSeq *field_names)
|
Sta::setReportPathFieldOrder(const StringSeq &field_names)
|
||||||
{
|
{
|
||||||
report_path_->setReportFieldOrder(field_names);
|
report_path_->setReportFieldOrder(field_names);
|
||||||
}
|
}
|
||||||
|
|
@ -3239,7 +3237,7 @@ void
|
||||||
EndpointPathEndVisitor::visit(PathEnd *path_end)
|
EndpointPathEndVisitor::visit(PathEnd *path_end)
|
||||||
{
|
{
|
||||||
if (path_end->minMax(sta_) == min_max_) {
|
if (path_end->minMax(sta_) == min_max_) {
|
||||||
StdStringSeq group_names = PathGroups::pathGroupNames(path_end, sta_);
|
StringSeq group_names = PathGroups::pathGroupNames(path_end, sta_);
|
||||||
for (std::string &group_name : group_names) {
|
for (std::string &group_name : group_names) {
|
||||||
if (group_name == path_group_name_) {
|
if (group_name == path_group_name_) {
|
||||||
Slack end_slack = path_end->slack(sta_);
|
Slack end_slack = path_end->slack(sta_);
|
||||||
|
|
@ -6037,7 +6035,7 @@ Sta::activity(const Pin *pin,
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
Sta::writePathSpice(Path *path,
|
Sta::writePathSpice(const Path *path,
|
||||||
const char *spice_filename,
|
const char *spice_filename,
|
||||||
const char *subckt_filename,
|
const char *subckt_filename,
|
||||||
const char *lib_subckt_filename,
|
const char *lib_subckt_filename,
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,7 @@ Tag::to_string(bool report_index,
|
||||||
if (report_rf_min_max) {
|
if (report_rf_min_max) {
|
||||||
const RiseFall *rf = transition();
|
const RiseFall *rf = transition();
|
||||||
const MinMax *min_max = minMax();
|
const MinMax *min_max = minMax();
|
||||||
result += rf->to_string();
|
result += rf->shortName();
|
||||||
result += " ";
|
|
||||||
result += min_max->to_string();
|
result += min_max->to_string();
|
||||||
result += " ";
|
result += " ";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ typedef int Stage;
|
||||||
class WritePathSpice : public WriteSpice
|
class WritePathSpice : public WriteSpice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WritePathSpice(Path *path,
|
WritePathSpice(const Path *path,
|
||||||
const char *spice_filename,
|
const char *spice_filename,
|
||||||
const char *subckt_filename,
|
const char *subckt_filename,
|
||||||
const char *lib_subckt_filename,
|
const char *lib_subckt_filename,
|
||||||
|
|
@ -80,8 +80,8 @@ private:
|
||||||
void writeGateStage(Stage stage);
|
void writeGateStage(Stage stage);
|
||||||
void writeStageParasitics(Stage stage);
|
void writeStageParasitics(Stage stage);
|
||||||
void writeSubckts();
|
void writeSubckts();
|
||||||
StdStringSet findPathCellNames();
|
StringSet findPathCellNames();
|
||||||
void findPathCellSubckts(StdStringSet &path_cell_names);
|
void findPathCellSubckts(StringSet &path_cell_names);
|
||||||
float maxTime();
|
float maxTime();
|
||||||
float pathMaxTime();
|
float pathMaxTime();
|
||||||
void writeMeasureDelayStmt(Stage stage,
|
void writeMeasureDelayStmt(Stage stage,
|
||||||
|
|
@ -116,24 +116,24 @@ private:
|
||||||
const Path *stageLoadPath(Stage stage);
|
const Path *stageLoadPath(Stage stage);
|
||||||
const TimingArc *stageGateArc(Stage stage);
|
const TimingArc *stageGateArc(Stage stage);
|
||||||
const TimingArc *stageWireArc(Stage stage);
|
const TimingArc *stageWireArc(Stage stage);
|
||||||
Edge *stageGateEdge(Stage stage);
|
const Edge *stageGateEdge(Stage stage);
|
||||||
Edge *stageWireEdge(Stage stage);
|
const Edge *stageWireEdge(Stage stage);
|
||||||
Pin *stageGateInputPin(Stage stage);
|
const Pin *stageGateInputPin(Stage stage);
|
||||||
Pin *stageDrvrPin(Stage stage);
|
const Pin *stageDrvrPin(Stage stage);
|
||||||
LibertyPort *stageGateInputPort(Stage stage);
|
const LibertyPort *stageGateInputPort(Stage stage);
|
||||||
LibertyPort *stageDrvrPort(Stage stage);
|
const LibertyPort *stageDrvrPort(Stage stage);
|
||||||
Pin *stageLoadPin(Stage stage);
|
const Pin *stageLoadPin(Stage stage);
|
||||||
const char *stageGateInputPinName(Stage stage);
|
const char *stageGateInputPinName(Stage stage);
|
||||||
const char *stageDrvrPinName(Stage stage);
|
const char *stageDrvrPinName(Stage stage);
|
||||||
const char *stageLoadPinName(Stage stage);
|
const char *stageLoadPinName(Stage stage);
|
||||||
LibertyCell *stageLibertyCell(Stage stage);
|
const LibertyCell *stageLibertyCell(Stage stage);
|
||||||
Instance *stageInstance(Stage stage);
|
const Instance *stageInstance(Stage stage);
|
||||||
|
|
||||||
float findSlew(const Path *path);
|
float findSlew(const Path *path);
|
||||||
float findSlew(const Path *path,
|
float findSlew(const Path *path,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const TimingArc *next_arc);
|
const TimingArc *next_arc);
|
||||||
Path *path_;
|
const Path *path_;
|
||||||
PathExpanded path_expanded_;
|
PathExpanded path_expanded_;
|
||||||
// Input clock waveform cycles.
|
// Input clock waveform cycles.
|
||||||
int clk_cycle_count_;
|
int clk_cycle_count_;
|
||||||
|
|
@ -152,7 +152,7 @@ private:
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
writePathSpice(Path *path,
|
writePathSpice(const Path *path,
|
||||||
const char *spice_filename,
|
const char *spice_filename,
|
||||||
const char *subckt_filename,
|
const char *subckt_filename,
|
||||||
const char *lib_subckt_filename,
|
const char *lib_subckt_filename,
|
||||||
|
|
@ -168,7 +168,7 @@ writePathSpice(Path *path,
|
||||||
writer.writeSpice();
|
writer.writeSpice();
|
||||||
}
|
}
|
||||||
|
|
||||||
WritePathSpice::WritePathSpice(Path *path,
|
WritePathSpice::WritePathSpice(const Path *path,
|
||||||
const char *spice_filename,
|
const char *spice_filename,
|
||||||
const char *subckt_filename,
|
const char *subckt_filename,
|
||||||
const char *lib_subckt_filename,
|
const char *lib_subckt_filename,
|
||||||
|
|
@ -215,10 +215,10 @@ WritePathSpice::writeHeader()
|
||||||
{
|
{
|
||||||
const Path *start_path = path_expanded_.startPath();
|
const Path *start_path = path_expanded_.startPath();
|
||||||
std::string title = stdstrPrint("Path from %s %s to %s %s",
|
std::string title = stdstrPrint("Path from %s %s to %s %s",
|
||||||
network_->pathName(start_path->pin(this)),
|
network_->pathName(start_path->pin(this)),
|
||||||
start_path->transition(this)->to_string().c_str(),
|
start_path->transition(this)->shortName(),
|
||||||
network_->pathName(path_->pin(this)),
|
network_->pathName(path_->pin(this)),
|
||||||
path_->transition(this)->to_string().c_str());
|
path_->transition(this)->shortName());
|
||||||
float max_time = maxTime();
|
float max_time = maxTime();
|
||||||
float time_step = 1e-13;
|
float time_step = 1e-13;
|
||||||
writeHeader(title, max_time, time_step);
|
writeHeader(title, max_time, time_step);
|
||||||
|
|
@ -227,7 +227,7 @@ WritePathSpice::writeHeader()
|
||||||
void
|
void
|
||||||
WritePathSpice::writePrintStmt()
|
WritePathSpice::writePrintStmt()
|
||||||
{
|
{
|
||||||
StdStringSeq node_names;
|
StringSeq node_names;
|
||||||
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
|
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
|
||||||
node_names.push_back(stageDrvrPinName(stage));
|
node_names.push_back(stageDrvrPinName(stage));
|
||||||
node_names.push_back(stageLoadPinName(stage));
|
node_names.push_back(stageLoadPinName(stage));
|
||||||
|
|
@ -497,8 +497,8 @@ WritePathSpice::writeGateStage(Stage stage)
|
||||||
std::string subckt_name = "stage" + std::to_string(stage);
|
std::string subckt_name = "stage" + std::to_string(stage);
|
||||||
|
|
||||||
const Instance *inst = stageInstance(stage);
|
const Instance *inst = stageInstance(stage);
|
||||||
LibertyPort *input_port = stageGateInputPort(stage);
|
const LibertyPort *input_port = stageGateInputPort(stage);
|
||||||
LibertyPort *drvr_port = stageDrvrPort(stage);
|
const LibertyPort *drvr_port = stageDrvrPort(stage);
|
||||||
|
|
||||||
streamPrint(spice_stream_, ".subckt %s %s %s %s\n",
|
streamPrint(spice_stream_, ".subckt %s %s %s %s\n",
|
||||||
subckt_name.c_str(),
|
subckt_name.c_str(),
|
||||||
|
|
@ -515,7 +515,7 @@ WritePathSpice::writeGateStage(Stage stage)
|
||||||
|
|
||||||
const Path *drvr_path = stageDrvrPath(stage);
|
const Path *drvr_path = stageDrvrPath(stage);
|
||||||
const RiseFall *drvr_rf = drvr_path->transition(this);
|
const RiseFall *drvr_rf = drvr_path->transition(this);
|
||||||
Edge *gate_edge = stageGateEdge(stage);
|
const Edge *gate_edge = stageGateEdge(stage);
|
||||||
|
|
||||||
LibertyPortLogicValues port_values;
|
LibertyPortLogicValues port_values;
|
||||||
bool is_clked;
|
bool is_clked;
|
||||||
|
|
@ -562,14 +562,14 @@ WritePathSpice::writeStageParasitics(Stage stage)
|
||||||
void
|
void
|
||||||
WritePathSpice::writeSubckts()
|
WritePathSpice::writeSubckts()
|
||||||
{
|
{
|
||||||
StdStringSet cell_names = findPathCellNames();
|
StringSet cell_names = findPathCellNames();
|
||||||
writeSubckts(cell_names);
|
writeSubckts(cell_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStringSet
|
StringSet
|
||||||
WritePathSpice::findPathCellNames()
|
WritePathSpice::findPathCellNames()
|
||||||
{
|
{
|
||||||
StdStringSet path_cell_names;
|
StringSet path_cell_names;
|
||||||
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
|
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
|
||||||
const TimingArc *arc = stageGateArc(stage);
|
const TimingArc *arc = stageGateArc(stage);
|
||||||
if (arc) {
|
if (arc) {
|
||||||
|
|
@ -579,7 +579,7 @@ WritePathSpice::findPathCellNames()
|
||||||
path_cell_names.insert(cell->name());
|
path_cell_names.insert(cell->name());
|
||||||
}
|
}
|
||||||
// Include side receivers.
|
// Include side receivers.
|
||||||
Pin *drvr_pin = stageDrvrPin(stage);
|
const Pin *drvr_pin = stageDrvrPin(stage);
|
||||||
auto pin_iter = network_->connectedPinIterator(drvr_pin);
|
auto pin_iter = network_->connectedPinIterator(drvr_pin);
|
||||||
while (pin_iter->hasNext()) {
|
while (pin_iter->hasNext()) {
|
||||||
const Pin *pin = pin_iter->next();
|
const Pin *pin = pin_iter->next();
|
||||||
|
|
@ -673,49 +673,49 @@ WritePathSpice::stageWireArc(Stage stage)
|
||||||
return path_expanded_.path(path_index)->prevArc(this);
|
return path_expanded_.path(path_index)->prevArc(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Edge *
|
const Edge *
|
||||||
WritePathSpice::stageGateEdge(Stage stage)
|
WritePathSpice::stageGateEdge(Stage stage)
|
||||||
{
|
{
|
||||||
const Path *path = stageDrvrPath(stage);
|
const Path *path = stageDrvrPath(stage);
|
||||||
return path->prevEdge(this);
|
return path->prevEdge(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Edge *
|
const Edge *
|
||||||
WritePathSpice::stageWireEdge(Stage stage)
|
WritePathSpice::stageWireEdge(Stage stage)
|
||||||
{
|
{
|
||||||
const Path *path = stageLoadPath(stage);
|
const Path *path = stageLoadPath(stage);
|
||||||
return path->prevEdge(this);
|
return path->prevEdge(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pin *
|
const Pin *
|
||||||
WritePathSpice::stageGateInputPin(Stage stage)
|
WritePathSpice::stageGateInputPin(Stage stage)
|
||||||
{
|
{
|
||||||
const Path *path = stageGateInputPath(stage);
|
const Path *path = stageGateInputPath(stage);
|
||||||
return path->pin(this);
|
return path->pin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
LibertyPort *
|
const LibertyPort *
|
||||||
WritePathSpice::stageGateInputPort(Stage stage)
|
WritePathSpice::stageGateInputPort(Stage stage)
|
||||||
{
|
{
|
||||||
Pin *pin = stageGateInputPin(stage);
|
const Pin *pin = stageGateInputPin(stage);
|
||||||
return network_->libertyPort(pin);
|
return network_->libertyPort(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pin *
|
const Pin *
|
||||||
WritePathSpice::stageDrvrPin(Stage stage)
|
WritePathSpice::stageDrvrPin(Stage stage)
|
||||||
{
|
{
|
||||||
const Path *path = stageDrvrPath(stage);
|
const Path *path = stageDrvrPath(stage);
|
||||||
return path->pin(this);
|
return path->pin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
LibertyPort *
|
const LibertyPort *
|
||||||
WritePathSpice::stageDrvrPort(Stage stage)
|
WritePathSpice::stageDrvrPort(Stage stage)
|
||||||
{
|
{
|
||||||
Pin *pin = stageDrvrPin(stage);
|
const Pin *pin = stageDrvrPin(stage);
|
||||||
return network_->libertyPort(pin);
|
return network_->libertyPort(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pin *
|
const Pin *
|
||||||
WritePathSpice::stageLoadPin(Stage stage)
|
WritePathSpice::stageLoadPin(Stage stage)
|
||||||
{
|
{
|
||||||
const Path *path = stageLoadPath(stage);
|
const Path *path = stageLoadPath(stage);
|
||||||
|
|
@ -725,35 +725,35 @@ WritePathSpice::stageLoadPin(Stage stage)
|
||||||
const char *
|
const char *
|
||||||
WritePathSpice::stageGateInputPinName(Stage stage)
|
WritePathSpice::stageGateInputPinName(Stage stage)
|
||||||
{
|
{
|
||||||
Pin *pin = stageGateInputPin(stage);
|
const Pin *pin = stageGateInputPin(stage);
|
||||||
return network_->pathName(pin);
|
return network_->pathName(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
WritePathSpice::stageDrvrPinName(Stage stage)
|
WritePathSpice::stageDrvrPinName(Stage stage)
|
||||||
{
|
{
|
||||||
Pin *pin = stageDrvrPin(stage);
|
const Pin *pin = stageDrvrPin(stage);
|
||||||
return network_->pathName(pin);
|
return network_->pathName(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
WritePathSpice::stageLoadPinName(Stage stage)
|
WritePathSpice::stageLoadPinName(Stage stage)
|
||||||
{
|
{
|
||||||
Pin *pin = stageLoadPin(stage);
|
const Pin *pin = stageLoadPin(stage);
|
||||||
return network_->pathName(pin);
|
return network_->pathName(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance *
|
const Instance *
|
||||||
WritePathSpice::stageInstance(Stage stage)
|
WritePathSpice::stageInstance(Stage stage)
|
||||||
{
|
{
|
||||||
Pin *pin = stageDrvrPin(stage);
|
const Pin *pin = stageDrvrPin(stage);
|
||||||
return network_->instance(pin);
|
return network_->instance(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
LibertyCell *
|
const LibertyCell *
|
||||||
WritePathSpice::stageLibertyCell(Stage stage)
|
WritePathSpice::stageLibertyCell(Stage stage)
|
||||||
{
|
{
|
||||||
Pin *pin = stageDrvrPin(stage);
|
const Pin *pin = stageDrvrPin(stage);
|
||||||
return network_->libertyPort(pin)->libertyCell();
|
return network_->libertyPort(pin)->libertyCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "CircuitSim.hh"
|
#include "CircuitSim.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -35,7 +34,7 @@ class StaState;
|
||||||
// Write a spice deck for path.
|
// Write a spice deck for path.
|
||||||
// Throws FileNotReadable, FileNotWritable, SubcktEndsMissing
|
// Throws FileNotReadable, FileNotWritable, SubcktEndsMissing
|
||||||
void
|
void
|
||||||
writePathSpice(Path *path,
|
writePathSpice(const Path *path,
|
||||||
// Spice file written for path.
|
// Spice file written for path.
|
||||||
const char *spice_filename,
|
const char *spice_filename,
|
||||||
// Subckts used by path included in spice file.
|
// Subckts used by path included in spice file.
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ WriteSpice::writeHeader(std::string &title,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WriteSpice::writePrintStmt(StdStringSeq &node_names)
|
WriteSpice::writePrintStmt(StringSeq &node_names)
|
||||||
{
|
{
|
||||||
streamPrint(spice_stream_, ".print tran");
|
streamPrint(spice_stream_, ".print tran");
|
||||||
if (ckt_sim_ == CircuitSim::xyce) {
|
if (ckt_sim_ == CircuitSim::xyce) {
|
||||||
|
|
@ -176,7 +176,7 @@ WriteSpice::replaceFileExt(std::string filename,
|
||||||
|
|
||||||
// Write gnuplot command file for use with xyce csv file.
|
// Write gnuplot command file for use with xyce csv file.
|
||||||
void
|
void
|
||||||
WriteSpice::writeGnuplotFile(StdStringSeq &node_nanes)
|
WriteSpice::writeGnuplotFile(StringSeq &node_nanes)
|
||||||
{
|
{
|
||||||
std::string gnuplot_filename = replaceFileExt(spice_filename_, "gnuplot");
|
std::string gnuplot_filename = replaceFileExt(spice_filename_, "gnuplot");
|
||||||
std::string csv_filename = replaceFileExt(spice_filename_, "csv");
|
std::string csv_filename = replaceFileExt(spice_filename_, "csv");
|
||||||
|
|
@ -199,7 +199,7 @@ WriteSpice::writeGnuplotFile(StdStringSeq &node_nanes)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WriteSpice::writeSubckts(StdStringSet &cell_names)
|
WriteSpice::writeSubckts(StringSet &cell_names)
|
||||||
{
|
{
|
||||||
findCellSubckts(cell_names);
|
findCellSubckts(cell_names);
|
||||||
std::ifstream lib_subckts_stream(lib_subckt_filename_);
|
std::ifstream lib_subckts_stream(lib_subckt_filename_);
|
||||||
|
|
@ -209,7 +209,7 @@ WriteSpice::writeSubckts(StdStringSet &cell_names)
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(lib_subckts_stream, line)) {
|
while (std::getline(lib_subckts_stream, line)) {
|
||||||
// .subckt <cell_name> [args..]
|
// .subckt <cell_name> [args..]
|
||||||
StdStringSeq tokens = parseTokens(line, ' ');
|
StringSeq tokens = parseTokens(line, ' ');
|
||||||
if (tokens.size() >= 2
|
if (tokens.size() >= 2
|
||||||
&& stringEqual(tokens[0].c_str(), ".subckt")) {
|
&& stringEqual(tokens[0].c_str(), ".subckt")) {
|
||||||
const char *cell_name = tokens[1].c_str();
|
const char *cell_name = tokens[1].c_str();
|
||||||
|
|
@ -256,11 +256,11 @@ WriteSpice::writeSubckts(StdStringSet &cell_names)
|
||||||
|
|
||||||
void
|
void
|
||||||
WriteSpice::recordSpicePortNames(const char *cell_name,
|
WriteSpice::recordSpicePortNames(const char *cell_name,
|
||||||
StdStringSeq &tokens)
|
StringSeq &tokens)
|
||||||
{
|
{
|
||||||
LibertyCell *cell = network_->findLibertyCell(cell_name);
|
LibertyCell *cell = network_->findLibertyCell(cell_name);
|
||||||
if (cell) {
|
if (cell) {
|
||||||
StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name];
|
StringSeq &spice_port_names = cell_spice_port_names_[cell_name];
|
||||||
for (size_t i = 2; i < tokens.size(); i++) {
|
for (size_t i = 2; i < tokens.size(); i++) {
|
||||||
const char *port_name = tokens[i].c_str();
|
const char *port_name = tokens[i].c_str();
|
||||||
LibertyPort *port = cell->findLibertyPort(port_name);
|
LibertyPort *port = cell->findLibertyPort(port_name);
|
||||||
|
|
@ -278,14 +278,14 @@ WriteSpice::recordSpicePortNames(const char *cell_name,
|
||||||
|
|
||||||
// Subckts can call subckts (asap7).
|
// Subckts can call subckts (asap7).
|
||||||
void
|
void
|
||||||
WriteSpice::findCellSubckts(StdStringSet &cell_names)
|
WriteSpice::findCellSubckts(StringSet &cell_names)
|
||||||
{
|
{
|
||||||
std::ifstream lib_subckts_stream(lib_subckt_filename_);
|
std::ifstream lib_subckts_stream(lib_subckt_filename_);
|
||||||
if (lib_subckts_stream.is_open()) {
|
if (lib_subckts_stream.is_open()) {
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(lib_subckts_stream, line)) {
|
while (std::getline(lib_subckts_stream, line)) {
|
||||||
// .subckt <cell_name> [args..]
|
// .subckt <cell_name> [args..]
|
||||||
StdStringSeq tokens = parseTokens(line, ' ');
|
StringSeq tokens = parseTokens(line, ' ');
|
||||||
if (tokens.size() >= 2
|
if (tokens.size() >= 2
|
||||||
&& stringEqual(tokens[0].c_str(), ".subckt")) {
|
&& stringEqual(tokens[0].c_str(), ".subckt")) {
|
||||||
const char *cell_name = tokens[1].c_str();
|
const char *cell_name = tokens[1].c_str();
|
||||||
|
|
@ -298,7 +298,7 @@ WriteSpice::findCellSubckts(StdStringSet &cell_names)
|
||||||
else {
|
else {
|
||||||
// Process previous statement.
|
// Process previous statement.
|
||||||
if (tolower(stmt[0]) == 'x') {
|
if (tolower(stmt[0]) == 'x') {
|
||||||
StdStringSeq tokens = parseTokens(line, ' ');
|
StringSeq tokens = parseTokens(line, ' ');
|
||||||
std::string &subckt_cell = tokens[tokens.size() - 1];
|
std::string &subckt_cell = tokens[tokens.size() - 1];
|
||||||
cell_names.insert(subckt_cell);
|
cell_names.insert(subckt_cell);
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +323,7 @@ WriteSpice::writeSubcktInst(const Instance *inst)
|
||||||
const char *inst_name = network_->pathName(inst);
|
const char *inst_name = network_->pathName(inst);
|
||||||
LibertyCell *cell = network_->libertyCell(inst);
|
LibertyCell *cell = network_->libertyCell(inst);
|
||||||
const char *cell_name = cell->name();
|
const char *cell_name = cell->name();
|
||||||
StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name];
|
StringSeq &spice_port_names = cell_spice_port_names_[cell_name];
|
||||||
streamPrint(spice_stream_, "x%s", inst_name);
|
streamPrint(spice_stream_, "x%s", inst_name);
|
||||||
for (std::string subckt_port_name : spice_port_names) {
|
for (std::string subckt_port_name : spice_port_names) {
|
||||||
const char *subckt_port_cname = subckt_port_name.c_str();
|
const char *subckt_port_cname = subckt_port_name.c_str();
|
||||||
|
|
@ -351,7 +351,7 @@ WriteSpice::writeSubcktInstVoltSrcs(const Instance *inst,
|
||||||
{
|
{
|
||||||
LibertyCell *cell = network_->libertyCell(inst);
|
LibertyCell *cell = network_->libertyCell(inst);
|
||||||
const char *cell_name = cell->name();
|
const char *cell_name = cell->name();
|
||||||
StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name];
|
StringSeq &spice_port_names = cell_spice_port_names_[cell_name];
|
||||||
const char *inst_name = network_->pathName(inst);
|
const char *inst_name = network_->pathName(inst);
|
||||||
|
|
||||||
debugPrint(debug_, "write_spice", 2, "subckt %s", cell->name());
|
debugPrint(debug_, "write_spice", 2, "subckt %s", cell->name());
|
||||||
|
|
@ -825,7 +825,7 @@ WriteSpice::railToRailSlew(float slew,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Find the logic values for expression inputs to enable paths from input_port.
|
// Find the logic values for expression inputs to sensitize the path from input_port.
|
||||||
void
|
void
|
||||||
WriteSpice::gatePortValues(const Pin *input_pin,
|
WriteSpice::gatePortValues(const Pin *input_pin,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "Liberty.hh"
|
#include "Liberty.hh"
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
|
|
@ -41,7 +40,7 @@
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
using ParasiticNodeMap = std::map<const ParasiticNode*, int>;
|
using ParasiticNodeMap = std::map<const ParasiticNode*, int>;
|
||||||
using CellSpicePortNames = std::map<std::string, StdStringSeq>;
|
using CellSpicePortNames = std::map<std::string, StringSeq>;
|
||||||
using LibertyPortLogicValues = std::map<const LibertyPort*, LogicValue>;
|
using LibertyPortLogicValues = std::map<const LibertyPort*, LogicValue>;
|
||||||
|
|
||||||
// Utilities for writing a spice deck.
|
// Utilities for writing a spice deck.
|
||||||
|
|
@ -64,12 +63,12 @@ protected:
|
||||||
void writeHeader(std::string &title,
|
void writeHeader(std::string &title,
|
||||||
float max_time,
|
float max_time,
|
||||||
float time_step);
|
float time_step);
|
||||||
void writePrintStmt(StdStringSeq &node_names);
|
void writePrintStmt(StringSeq &node_names);
|
||||||
void writeGnuplotFile(StdStringSeq &node_nanes);
|
void writeGnuplotFile(StringSeq &node_nanes);
|
||||||
void writeSubckts(StdStringSet &cell_names);
|
void writeSubckts(StringSet &cell_names);
|
||||||
void findCellSubckts(StdStringSet &cell_names);
|
void findCellSubckts(StringSet &cell_names);
|
||||||
void recordSpicePortNames(const char *cell_name,
|
void recordSpicePortNames(const char *cell_name,
|
||||||
StdStringSeq &tokens);
|
StringSeq &tokens);
|
||||||
void writeSubcktInst(const Instance *inst);
|
void writeSubcktInst(const Instance *inst);
|
||||||
void writeSubcktInstVoltSrcs(const Instance *inst,
|
void writeSubcktInstVoltSrcs(const Instance *inst,
|
||||||
LibertyPortLogicValues &port_values,
|
LibertyPortLogicValues &port_values,
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
%inline %{
|
%inline %{
|
||||||
|
|
||||||
void
|
void
|
||||||
write_path_spice_cmd(Path *path,
|
write_path_spice_cmd(const Path *path,
|
||||||
const char *spice_filename,
|
const char *spice_filename,
|
||||||
const char *subckt_filename,
|
const char *subckt_filename,
|
||||||
const char *lib_subckt_filename,
|
const char *lib_subckt_filename,
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ namespace sta {
|
||||||
void
|
void
|
||||||
readXyceCsv(const char *csv_filename,
|
readXyceCsv(const char *csv_filename,
|
||||||
// Return values.
|
// Return values.
|
||||||
StdStringSeq &titles,
|
StringSeq &titles,
|
||||||
WaveformSeq &waveforms)
|
WaveformSeq &waveforms)
|
||||||
{
|
{
|
||||||
std::ifstream file(csv_filename);
|
std::ifstream file(csv_filename);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ using WaveformSeq = std::vector<Table>;
|
||||||
void
|
void
|
||||||
readXyceCsv(const char *csv_filename,
|
readXyceCsv(const char *csv_filename,
|
||||||
// Return values.
|
// Return values.
|
||||||
StdStringSeq &titles,
|
StringSeq &titles,
|
||||||
WaveformSeq &waveforms);
|
WaveformSeq &waveforms);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,6 @@
|
||||||
|
|
||||||
#include "Machine.hh"
|
#include "Machine.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "StringSeq.hh"
|
|
||||||
#include "PatternMatch.hh"
|
#include "PatternMatch.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Liberty.hh"
|
#include "Liberty.hh"
|
||||||
|
|
@ -53,7 +51,6 @@
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef MinMaxAll MinMaxAllNull;
|
typedef MinMaxAll MinMaxAllNull;
|
||||||
typedef std::vector<std::string> StdStringSeq;
|
|
||||||
|
|
||||||
#if TCL_MAJOR_VERSION < 9
|
#if TCL_MAJOR_VERSION < 9
|
||||||
typedef int Tcl_Size;
|
typedef int Tcl_Size;
|
||||||
|
|
@ -293,53 +290,34 @@ using namespace sta;
|
||||||
Tcl_SetResult(interp, nullptr, TCL_STATIC);
|
Tcl_SetResult(interp, nullptr, TCL_STATIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(in) StringSeq* {
|
%typemap(in) StringSet* {
|
||||||
$1 = tclListSeqConstChar($input, interp);
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(in) StdStringSet* {
|
|
||||||
$1 = tclListSetStdString($input, interp);
|
$1 = tclListSetStdString($input, interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(in) StdStringSeq {
|
%typemap(in) StringSeq {
|
||||||
$1 = tclListSeqStdString($input, interp);
|
$1 = tclListSeqStdString($input, interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(in) StdStringSeq* {
|
%typemap(in) const StringSeq & (StringSeq seq) {
|
||||||
$1 = tclListSeqStdString($input, interp);
|
seq = tclListSeqStdString($input, interp);
|
||||||
|
$1 = &seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(out) StringSeq* {
|
%typemap(in) StringSeq* {
|
||||||
StringSeq *strs = $1;
|
$1 = tclListSeqStdStringPtr($input, interp);
|
||||||
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
|
}
|
||||||
for (const char *str : *strs) {
|
|
||||||
Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str));
|
%typemap(in) StringSet* {
|
||||||
Tcl_ListObjAppendElement(interp, list, obj);
|
$1 = tclListSetStdString($input, interp);
|
||||||
}
|
}
|
||||||
Tcl_SetObjResult(interp, list);
|
|
||||||
|
%typemap(in) StringSeq {
|
||||||
|
$1 = tclListSeqStdString($input, interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(out) StringSeq {
|
%typemap(out) StringSeq {
|
||||||
StringSeq &strs = $1;
|
StringSeq &strs = $1;
|
||||||
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
|
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
|
||||||
for (const char *str : strs) {
|
|
||||||
Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str));
|
|
||||||
Tcl_ListObjAppendElement(interp, list, obj);
|
|
||||||
}
|
|
||||||
Tcl_SetObjResult(interp, list);
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(in) StdStringSet* {
|
|
||||||
$1 = tclListSetStdString($input, interp);
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(in) StdStringSeq {
|
|
||||||
$1 = tclListSeqStdString($input, interp);
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(out) StdStringSeq {
|
|
||||||
StdStringSeq &strs = $1;
|
|
||||||
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
|
|
||||||
for (const std::string &str : strs) {
|
for (const std::string &str : strs) {
|
||||||
Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(), str.size());
|
Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(), str.size());
|
||||||
Tcl_ListObjAppendElement(interp, list, obj);
|
Tcl_ListObjAppendElement(interp, list, obj);
|
||||||
|
|
@ -497,7 +475,7 @@ using namespace sta;
|
||||||
const RiseFall *rf = $1;
|
const RiseFall *rf = $1;
|
||||||
const char *str = "";
|
const char *str = "";
|
||||||
if (rf)
|
if (rf)
|
||||||
str = rf->to_string().c_str();
|
str = rf->shortName();
|
||||||
Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
|
Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -517,7 +495,7 @@ using namespace sta;
|
||||||
RiseFallBoth *tr = $1;
|
RiseFallBoth *tr = $1;
|
||||||
const char *str = "";
|
const char *str = "";
|
||||||
if (tr)
|
if (tr)
|
||||||
str = tr->asString();
|
str = tr->shortName();
|
||||||
Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
|
Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1137,10 +1115,9 @@ using namespace sta;
|
||||||
CheckErrorSeq *check_errors = $1;
|
CheckErrorSeq *check_errors = $1;
|
||||||
for (CheckError *error : *check_errors) {
|
for (CheckError *error : *check_errors) {
|
||||||
Tcl_Obj *string_list = Tcl_NewListObj(0, nullptr);
|
Tcl_Obj *string_list = Tcl_NewListObj(0, nullptr);
|
||||||
for (const char *str : *error) {
|
for (const std::string &str : *error) {
|
||||||
size_t str_len = strlen(str);
|
Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(),
|
||||||
Tcl_Obj *obj = Tcl_NewStringObj(const_cast<char*>(str),
|
static_cast<int>(str.size()));
|
||||||
static_cast<int>(str_len));
|
|
||||||
Tcl_ListObjAppendElement(interp, string_list, obj);
|
Tcl_ListObjAppendElement(interp, string_list, obj);
|
||||||
}
|
}
|
||||||
Tcl_ListObjAppendElement(interp, error_list, string_list);
|
Tcl_ListObjAppendElement(interp, error_list, string_list);
|
||||||
|
|
@ -1249,10 +1226,6 @@ using namespace sta;
|
||||||
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
|
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(in) StringSet* {
|
|
||||||
$1 = tclListSetConstChar($input, interp);
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(out) Mode* {
|
%typemap(out) Mode* {
|
||||||
const Mode *mode = $1;
|
const Mode *mode = $1;
|
||||||
if (mode)
|
if (mode)
|
||||||
|
|
|
||||||
|
|
@ -30,29 +30,27 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
StringSet *
|
StringSeq
|
||||||
tclListSetConstChar(Tcl_Obj *const source,
|
tclListSeqStdString(Tcl_Obj *const source,
|
||||||
Tcl_Interp *interp)
|
Tcl_Interp *interp)
|
||||||
{
|
{
|
||||||
Tcl_Size argc;
|
Tcl_Size argc;
|
||||||
Tcl_Obj **argv;
|
Tcl_Obj **argv;
|
||||||
|
|
||||||
|
StringSeq seq;
|
||||||
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
|
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
|
||||||
StringSet *set = new StringSet;
|
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
int length;
|
int length;
|
||||||
const char *str = Tcl_GetStringFromObj(argv[i], &length);
|
const char *str = Tcl_GetStringFromObj(argv[i], &length);
|
||||||
set->insert(str);
|
seq.push_back(str);
|
||||||
}
|
}
|
||||||
return set;
|
|
||||||
}
|
}
|
||||||
else
|
return seq;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSeq *
|
StringSeq *
|
||||||
tclListSeqConstChar(Tcl_Obj *const source,
|
tclListSeqStdStringPtr(Tcl_Obj *const source,
|
||||||
Tcl_Interp *interp)
|
Tcl_Interp *interp)
|
||||||
{
|
{
|
||||||
Tcl_Size argc;
|
Tcl_Size argc;
|
||||||
Tcl_Obj **argv;
|
Tcl_Obj **argv;
|
||||||
|
|
@ -70,45 +68,7 @@ tclListSeqConstChar(Tcl_Obj *const source,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStringSeq
|
StringSet *
|
||||||
tclListSeqStdString(Tcl_Obj *const source,
|
|
||||||
Tcl_Interp *interp)
|
|
||||||
{
|
|
||||||
Tcl_Size argc;
|
|
||||||
Tcl_Obj **argv;
|
|
||||||
|
|
||||||
StdStringSeq seq;
|
|
||||||
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
int length;
|
|
||||||
const char *str = Tcl_GetStringFromObj(argv[i], &length);
|
|
||||||
seq.push_back(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return seq;
|
|
||||||
}
|
|
||||||
|
|
||||||
StdStringSeq *
|
|
||||||
tclListSeqStdStringPtr(Tcl_Obj *const source,
|
|
||||||
Tcl_Interp *interp)
|
|
||||||
{
|
|
||||||
Tcl_Size argc;
|
|
||||||
Tcl_Obj **argv;
|
|
||||||
|
|
||||||
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
|
|
||||||
StdStringSeq *seq = new StdStringSeq;
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
int length;
|
|
||||||
const char *str = Tcl_GetStringFromObj(argv[i], &length);
|
|
||||||
seq->push_back(str);
|
|
||||||
}
|
|
||||||
return seq;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
StdStringSet *
|
|
||||||
tclListSetStdString(Tcl_Obj *const source,
|
tclListSetStdString(Tcl_Obj *const source,
|
||||||
Tcl_Interp *interp)
|
Tcl_Interp *interp)
|
||||||
{
|
{
|
||||||
|
|
@ -116,7 +76,7 @@ tclListSetStdString(Tcl_Obj *const source,
|
||||||
Tcl_Obj **argv;
|
Tcl_Obj **argv;
|
||||||
|
|
||||||
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
|
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
|
||||||
StdStringSet *set = new StdStringSet;
|
StringSet *set = new StringSet;
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
int length;
|
int length;
|
||||||
const char *str = Tcl_GetStringFromObj(argv[i], &length);
|
const char *str = Tcl_GetStringFromObj(argv[i], &length);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
str.erase(str.find_last_not_of(" ") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStringSeq
|
StringSeq
|
||||||
split(const std::string &text,
|
split(const std::string &text,
|
||||||
const std::string &delims)
|
const std::string &delims)
|
||||||
{
|
{
|
||||||
StdStringSeq tokens;
|
StringSeq tokens;
|
||||||
auto start = text.find_first_not_of(delims);
|
auto start = text.find_first_not_of(delims);
|
||||||
auto end = text.find_first_of(delims, start);
|
auto end = text.find_first_of(delims, start);
|
||||||
while (end != std::string::npos) {
|
while (end != std::string::npos) {
|
||||||
|
|
@ -283,11 +283,11 @@ split(const std::string &text,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse space separated tokens.
|
// Parse space separated tokens.
|
||||||
StdStringSeq
|
StringSeq
|
||||||
parseTokens(const std::string &s,
|
parseTokens(const std::string &s,
|
||||||
const char delimiter)
|
const char delimiter)
|
||||||
{
|
{
|
||||||
StdStringSeq tokens;
|
StringSeq tokens;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < s.size()) {
|
while (i < s.size()) {
|
||||||
while (i < s.size() && std::isspace(s[i]))
|
while (i < s.size() && std::isspace(s[i]))
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,15 @@ RiseFall::RiseFall(const char *name,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &
|
||||||
|
RiseFall::to_string(bool use_short) const
|
||||||
|
{
|
||||||
|
if (use_short)
|
||||||
|
return short_name_;
|
||||||
|
else
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
|
||||||
const RiseFall *
|
const RiseFall *
|
||||||
RiseFall::opposite() const
|
RiseFall::opposite() const
|
||||||
{
|
{
|
||||||
|
|
@ -134,6 +143,15 @@ RiseFallBoth::RiseFallBoth(const char *name,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &
|
||||||
|
RiseFallBoth::to_string(bool use_short) const
|
||||||
|
{
|
||||||
|
if (use_short)
|
||||||
|
return short_name_;
|
||||||
|
else
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
|
||||||
const RiseFallBoth *
|
const RiseFallBoth *
|
||||||
RiseFallBoth::find(const char *tr_str)
|
RiseFallBoth::find(const char *tr_str)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ VerilogReader::makeCellPorts(Cell *cell,
|
||||||
VerilogModule *module,
|
VerilogModule *module,
|
||||||
VerilogNetSeq *ports)
|
VerilogNetSeq *ports)
|
||||||
{
|
{
|
||||||
StdStringSet port_names;
|
StringSet port_names;
|
||||||
for (VerilogNet *mod_port : *ports) {
|
for (VerilogNet *mod_port : *ports) {
|
||||||
const std::string &port_name = mod_port->name();
|
const std::string &port_name = mod_port->name();
|
||||||
if (!port_names.contains(port_name)) {
|
if (!port_names.contains(port_name)) {
|
||||||
|
|
@ -335,7 +335,7 @@ void
|
||||||
VerilogReader::makeNamedPortRefCellPorts(Cell *cell,
|
VerilogReader::makeNamedPortRefCellPorts(Cell *cell,
|
||||||
VerilogModule *module,
|
VerilogModule *module,
|
||||||
VerilogNet *mod_port,
|
VerilogNet *mod_port,
|
||||||
StdStringSet &port_names)
|
StringSet &port_names)
|
||||||
{
|
{
|
||||||
PortSeq *member_ports = new PortSeq;
|
PortSeq *member_ports = new PortSeq;
|
||||||
VerilogNetNameIterator *net_name_iter = mod_port->nameIterator(module,this);
|
VerilogNetNameIterator *net_name_iter = mod_port->nameIterator(module,this);
|
||||||
|
|
@ -535,7 +535,7 @@ VerilogReader::makeModuleInst(const std::string *module_vname,
|
||||||
if (liberty_cell
|
if (liberty_cell
|
||||||
&& hasScalarNamedPortRefs(liberty_cell, pins)) {
|
&& hasScalarNamedPortRefs(liberty_cell, pins)) {
|
||||||
const int port_count = liberty_cell->portBitCount();
|
const int port_count = liberty_cell->portBitCount();
|
||||||
StdStringSeq net_names(port_count);
|
StringSeq net_names(port_count);
|
||||||
for (VerilogNet *vnet : *pins) {
|
for (VerilogNet *vnet : *pins) {
|
||||||
VerilogNetPortRefScalarNet *vpin =
|
VerilogNetPortRefScalarNet *vpin =
|
||||||
dynamic_cast<VerilogNetPortRefScalarNet*>(vnet);
|
dynamic_cast<VerilogNetPortRefScalarNet*>(vnet);
|
||||||
|
|
@ -805,7 +805,7 @@ VerilogModule::~VerilogModule()
|
||||||
void
|
void
|
||||||
VerilogModule::parseStmts(VerilogReader *reader)
|
VerilogModule::parseStmts(VerilogReader *reader)
|
||||||
{
|
{
|
||||||
StdStringSet inst_names;
|
StringSet inst_names;
|
||||||
for (VerilogStmt *stmt : *stmts_) {
|
for (VerilogStmt *stmt : *stmts_) {
|
||||||
if (stmt->isDeclaration())
|
if (stmt->isDeclaration())
|
||||||
parseDcl(dynamic_cast<VerilogDcl*>(stmt), reader);
|
parseDcl(dynamic_cast<VerilogDcl*>(stmt), reader);
|
||||||
|
|
@ -861,7 +861,7 @@ VerilogModule::parseDcl(VerilogDcl *dcl,
|
||||||
// expansion so errors are only reported once.
|
// expansion so errors are only reported once.
|
||||||
void
|
void
|
||||||
VerilogModule::checkInstanceName(VerilogInst *inst,
|
VerilogModule::checkInstanceName(VerilogInst *inst,
|
||||||
StdStringSet &inst_names,
|
StringSet &inst_names,
|
||||||
VerilogReader *reader)
|
VerilogReader *reader)
|
||||||
{
|
{
|
||||||
std::string inst_name = inst->instanceName();
|
std::string inst_name = inst->instanceName();
|
||||||
|
|
@ -953,7 +953,7 @@ VerilogModuleInst::namedPins()
|
||||||
|
|
||||||
VerilogLibertyInst::VerilogLibertyInst(LibertyCell *cell,
|
VerilogLibertyInst::VerilogLibertyInst(LibertyCell *cell,
|
||||||
const std::string &inst_name,
|
const std::string &inst_name,
|
||||||
const StdStringSeq &net_names,
|
const StringSeq &net_names,
|
||||||
VerilogAttrStmtSeq *attr_stmts,
|
VerilogAttrStmtSeq *attr_stmts,
|
||||||
const int line) :
|
const int line) :
|
||||||
VerilogInst(inst_name, attr_stmts, line),
|
VerilogInst(inst_name, attr_stmts, line),
|
||||||
|
|
@ -1080,8 +1080,8 @@ VerilogAssign::~VerilogAssign()
|
||||||
class VerilogNullNetNameIterator : public VerilogNetNameIterator
|
class VerilogNullNetNameIterator : public VerilogNetNameIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool hasNext() { return false; }
|
bool hasNext() override { return false; }
|
||||||
virtual const std::string &next();
|
const std::string &next() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string &
|
const std::string &
|
||||||
|
|
@ -1095,8 +1095,8 @@ class VerilogOneNetNameIterator : public VerilogNetNameIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VerilogOneNetNameIterator(const std::string &name);
|
VerilogOneNetNameIterator(const std::string &name);
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual const std::string &next();
|
const std::string &next() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
|
@ -1128,8 +1128,8 @@ public:
|
||||||
VerilogBusNetNameIterator(const std::string bus_name,
|
VerilogBusNetNameIterator(const std::string bus_name,
|
||||||
int from_index,
|
int from_index,
|
||||||
int to_index);
|
int to_index);
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual const std::string &next();
|
const std::string &next() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const std::string bus_name_;
|
const std::string bus_name_;
|
||||||
|
|
@ -1182,8 +1182,8 @@ public:
|
||||||
VerilogConstantNetNameIterator(VerilogConstantValue *value,
|
VerilogConstantNetNameIterator(VerilogConstantValue *value,
|
||||||
const std::string &zero,
|
const std::string &zero,
|
||||||
const std::string &one);
|
const std::string &one);
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual const std::string &next();
|
const std::string &next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VerilogConstantValue *value_;
|
VerilogConstantValue *value_;
|
||||||
|
|
@ -1222,8 +1222,8 @@ public:
|
||||||
VerilogModule *module,
|
VerilogModule *module,
|
||||||
VerilogReader *reader);
|
VerilogReader *reader);
|
||||||
virtual ~VerilogNetConcatNameIterator();
|
virtual ~VerilogNetConcatNameIterator();
|
||||||
virtual bool hasNext();
|
bool hasNext() override;
|
||||||
virtual const std::string &next();
|
const std::string &next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VerilogModule *module_;
|
VerilogModule *module_;
|
||||||
|
|
@ -2008,7 +2008,7 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
|
||||||
network_->setAttribute(inst, entry->key(), entry->value());
|
network_->setAttribute(inst, entry->key(), entry->value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const StdStringSeq &net_names = lib_inst->netNames();
|
const StringSeq &net_names = lib_inst->netNames();
|
||||||
LibertyCellPortBitIterator port_iter(lib_cell);
|
LibertyCellPortBitIterator port_iter(lib_cell);
|
||||||
while (port_iter.hasNext()) {
|
while (port_iter.hasNext()) {
|
||||||
LibertyPort *port = port_iter.next();
|
LibertyPort *port = port_iter.next();
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "StringSeq.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -76,7 +75,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void parseStmts(VerilogReader *reader);
|
void parseStmts(VerilogReader *reader);
|
||||||
void checkInstanceName(VerilogInst *inst,
|
void checkInstanceName(VerilogInst *inst,
|
||||||
StdStringSet &inst_names,
|
StringSet &inst_names,
|
||||||
VerilogReader *reader);
|
VerilogReader *reader);
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
|
@ -217,16 +216,16 @@ class VerilogLibertyInst : public VerilogInst
|
||||||
public:
|
public:
|
||||||
VerilogLibertyInst(LibertyCell *cell,
|
VerilogLibertyInst(LibertyCell *cell,
|
||||||
const std::string &inst_name,
|
const std::string &inst_name,
|
||||||
const StdStringSeq &net_names,
|
const StringSeq &net_names,
|
||||||
VerilogAttrStmtSeq *attr_stmts,
|
VerilogAttrStmtSeq *attr_stmts,
|
||||||
const int line);
|
const int line);
|
||||||
virtual bool isLibertyInst() const { return true; }
|
virtual bool isLibertyInst() const { return true; }
|
||||||
LibertyCell *cell() const { return cell_; }
|
LibertyCell *cell() const { return cell_; }
|
||||||
const StdStringSeq &netNames() const { return net_names_; }
|
const StringSeq &netNames() const { return net_names_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LibertyCell *cell_;
|
LibertyCell *cell_;
|
||||||
StdStringSeq net_names_;
|
StringSeq net_names_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract base class for nets.
|
// Abstract base class for nets.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue