liberty reader rewrite
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
a47a8dd831
commit
c010a0f99e
|
|
@ -17,4 +17,3 @@ define_scene ff -liberty NangateOpenCellLibrary_fast
|
|||
report_checks -path_delay min_max
|
||||
# report typical scene
|
||||
report_checks -scene tt
|
||||
|
||||
|
|
|
|||
|
|
@ -1236,6 +1236,8 @@ Edge::to_string(const StaState *sta) const
|
|||
string str = from(graph)->to_string(sta);
|
||||
str += " -> ";
|
||||
str += to(graph)->to_string(sta);
|
||||
str += " ";
|
||||
str += role()->to_string();
|
||||
FuncExpr *when = arc_set_->cond();
|
||||
if (when) {
|
||||
str += " ";
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ path_iterator(const RiseFall *rf,
|
|||
} // Vertex methods
|
||||
|
||||
%extend Edge {
|
||||
std::string to_string() { return self->to_string(Sta::sta()); };
|
||||
Vertex *from() { return self->from(Sta::sta()->graph()); }
|
||||
Vertex *to() { return self->to(Sta::sta()->graph()); }
|
||||
Pin *from_pin() { return self->from(Sta::sta()->graph())->pin(); }
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ public:
|
|||
float wire_delay) const;
|
||||
// Check for supported axis variables.
|
||||
// Return true if axes are supported.
|
||||
static bool checkSlewDegradationAxes(const TablePtr &table);
|
||||
static bool checkSlewDegradationAxes(const TableModel *table_model);
|
||||
|
||||
float defaultInputPinCap() const { return default_input_pin_cap_; }
|
||||
void setDefaultInputPinCap(float cap);
|
||||
|
|
@ -1051,7 +1051,7 @@ public:
|
|||
void setScale(ScaleFactorType type,
|
||||
ScaleFactorPvt pvt,
|
||||
float scale);
|
||||
void print();
|
||||
void report(Report *report);
|
||||
|
||||
protected:
|
||||
std::string name_;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ using FloatTable = std::vector<FloatSeq>;
|
|||
// Sequence of 1D tables (order 1).
|
||||
using Table1Seq = std::vector<Table*>;
|
||||
using Waveform = Table;
|
||||
using TableModelsEarlyLate = std::array<TableModel*, EarlyLate::index_count>;
|
||||
|
||||
TableAxisVariable
|
||||
stringTableAxisVariable(const char *variable);
|
||||
|
|
@ -63,11 +64,14 @@ class GateTableModel : public GateTimingModel
|
|||
public:
|
||||
GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *delay_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate delay_sigma_models,
|
||||
TableModel *slew_model,
|
||||
TableModel *slew_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate slew_sigma_models,
|
||||
ReceiverModelPtr receiver_model,
|
||||
OutputWaveforms *output_waveforms);
|
||||
GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *slew_model);
|
||||
~GateTableModel() override;
|
||||
void gateDelay(const Pvt *pvt,
|
||||
float in_slew,
|
||||
|
|
@ -100,7 +104,7 @@ public:
|
|||
OutputWaveforms *outputWaveforms() const { return output_waveforms_.get(); }
|
||||
// Check the axes before making the model.
|
||||
// Return true if the model axes are supported.
|
||||
static bool checkAxes(const TablePtr &table);
|
||||
static bool checkAxes(const TableModel *table);
|
||||
|
||||
protected:
|
||||
void maxCapSlew(float in_slew,
|
||||
|
|
@ -135,9 +139,9 @@ protected:
|
|||
static bool checkAxis(const TableAxis *axis);
|
||||
|
||||
std::unique_ptr<TableModel> delay_model_;
|
||||
std::array<std::unique_ptr<TableModel>, EarlyLate::index_count> delay_sigma_models_;
|
||||
TableModelsEarlyLate delay_sigma_models_;
|
||||
std::unique_ptr<TableModel> slew_model_;
|
||||
std::array<std::unique_ptr<TableModel>, EarlyLate::index_count> slew_sigma_models_;
|
||||
TableModelsEarlyLate slew_sigma_models_;
|
||||
ReceiverModelPtr receiver_model_;
|
||||
std::unique_ptr<OutputWaveforms> output_waveforms_;
|
||||
};
|
||||
|
|
@ -147,7 +151,9 @@ class CheckTableModel : public CheckTimingModel
|
|||
public:
|
||||
CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model,
|
||||
TableModel *sigma_models[EarlyLate::index_count]);
|
||||
TableModelsEarlyLate sigma_models);
|
||||
CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model);
|
||||
~CheckTableModel() override;
|
||||
ArcDelay checkDelay(const Pvt *pvt,
|
||||
float from_slew,
|
||||
|
|
@ -166,7 +172,7 @@ public:
|
|||
|
||||
// Check the axes before making the model.
|
||||
// Return true if the model axes are supported.
|
||||
static bool checkAxes(const TablePtr table);
|
||||
static bool checkAxes(const TableModel *table);
|
||||
|
||||
protected:
|
||||
void setIsScaled(bool is_scaled) override;
|
||||
|
|
@ -197,7 +203,7 @@ protected:
|
|||
static bool checkAxis(const TableAxis *axis);
|
||||
|
||||
std::unique_ptr<TableModel> model_;
|
||||
std::array<std::unique_ptr<TableModel>, EarlyLate::index_count> sigma_models_;
|
||||
TableModelsEarlyLate sigma_models_;
|
||||
};
|
||||
|
||||
class TableAxis
|
||||
|
|
@ -254,6 +260,8 @@ public:
|
|||
const TableAxis *axis2() const { return axis2_.get(); }
|
||||
const TableAxis *axis3() const { return axis3_.get(); }
|
||||
const TableAxisPtr axis1ptr() const { return axis1_; }
|
||||
const TableAxisPtr axis2ptr() const { return axis2_; }
|
||||
const TableAxisPtr axis3ptr() const { return axis3_; }
|
||||
void setIsScaled(bool is_scaled);
|
||||
|
||||
float value(size_t axis_idx1,
|
||||
|
|
@ -409,7 +417,7 @@ public:
|
|||
void setCapacitanceModel(TableModel table_model,
|
||||
size_t segment,
|
||||
const RiseFall *rf);
|
||||
static bool checkAxes(TablePtr table);
|
||||
static bool checkAxes(const TableModel *table);
|
||||
|
||||
private:
|
||||
std::vector<TableModel> capacitance_models_;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ class TimingArcAttrs
|
|||
public:
|
||||
TimingArcAttrs();
|
||||
TimingArcAttrs(TimingSense sense);
|
||||
virtual ~TimingArcAttrs();
|
||||
~TimingArcAttrs();
|
||||
TimingType timingType() const { return timing_type_; }
|
||||
void setTimingType(TimingType type);
|
||||
TimingSense timingSense() const { return timing_sense_; }
|
||||
|
|
@ -145,7 +145,8 @@ class TimingArcSet
|
|||
friend class LibertyCell;
|
||||
|
||||
public:
|
||||
virtual ~TimingArcSet();
|
||||
~TimingArcSet();
|
||||
std::string to_string();
|
||||
LibertyCell *libertyCell() const;
|
||||
LibertyPort *from() const { return from_; }
|
||||
LibertyPort *to() const { return to_; }
|
||||
|
|
@ -249,7 +250,7 @@ public:
|
|||
TimingArcSet *set() const { return set_; }
|
||||
TimingSense sense() const;
|
||||
// Index in TimingArcSet.
|
||||
unsigned index() const { return index_; }
|
||||
size_t index() const { return index_; }
|
||||
TimingModel *model() const { return model_; }
|
||||
GateTimingModel *gateModel(const Scene *scene,
|
||||
const MinMax *min_max) const;
|
||||
|
|
@ -270,7 +271,7 @@ public:
|
|||
protected:
|
||||
TimingModel *model(const Scene *scene,
|
||||
const MinMax *min_max) const;
|
||||
void setIndex(unsigned index);
|
||||
void setIndex(size_t index);
|
||||
void addScaledModel(const OperatingConditions *op_cond,
|
||||
TimingModel *scaled_model);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace sta {
|
||||
|
||||
using StdStringSeq = std::vector<std::string>;
|
||||
|
||||
// Iterate over the tokens in str separated by character sep.
|
||||
// Similar in functionality to strtok, but does not leave the string
|
||||
// side-effected. This is preferable to using strtok because it leaves
|
||||
|
|
@ -49,4 +54,9 @@ private:
|
|||
bool first_;
|
||||
};
|
||||
|
||||
// Parse delimiter separated tokens and skipp spaces.
|
||||
StdStringSeq
|
||||
parseTokens(const std::string &s,
|
||||
const char delimiter);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ public:
|
|||
static const RiseFall *fall() { return &fall_; }
|
||||
static int riseIndex() { return rise_.sdf_triple_index_; }
|
||||
static int fallIndex() { return fall_.sdf_triple_index_; }
|
||||
const std::string &to_string_long() const { return name_; }
|
||||
const std::string &to_string() const { return short_name_; }
|
||||
const char *name() const { return name_.c_str(); }
|
||||
const char *shortName() const { return short_name_.c_str(); }
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace sta {
|
|||
|
||||
FuncExpr *
|
||||
parseFuncExpr(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report)
|
||||
{
|
||||
|
|
@ -56,7 +56,7 @@ parseFuncExpr(const char *func,
|
|||
}
|
||||
|
||||
LibExprReader::LibExprReader(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report) :
|
||||
func_(func),
|
||||
|
|
@ -69,7 +69,7 @@ LibExprReader::LibExprReader(const char *func,
|
|||
|
||||
// defined in LibertyReader.cc
|
||||
LibertyPort *
|
||||
libertyReaderFindPort(LibertyCell *cell,
|
||||
libertyReaderFindPort(const LibertyCell *cell,
|
||||
const char *port_name);
|
||||
|
||||
FuncExpr *
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class LibertyCell;
|
|||
|
||||
FuncExpr *
|
||||
parseFuncExpr(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class LibExprReader
|
|||
{
|
||||
public:
|
||||
LibExprReader(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report);
|
||||
FuncExpr *makeFuncExprPort(const char *port_name);
|
||||
|
|
@ -55,7 +55,7 @@ public:
|
|||
|
||||
private:
|
||||
const char *func_;
|
||||
LibertyCell *cell_;
|
||||
const LibertyCell *cell_;
|
||||
const char *error_msg_;
|
||||
Report *report_;
|
||||
FuncExpr *result_;
|
||||
|
|
|
|||
|
|
@ -111,8 +111,6 @@ LibertyLibrary::LibertyLibrary(const char *name,
|
|||
|
||||
LibertyLibrary::~LibertyLibrary()
|
||||
{
|
||||
delete scale_factors_;
|
||||
|
||||
for (auto rf_index : RiseFall::rangeIndex()) {
|
||||
TableModel *model = wire_slew_degradation_tbls_[rf_index];
|
||||
delete model;
|
||||
|
|
@ -271,14 +269,14 @@ LibertyLibrary::setScaleFactors(ScaleFactors *scales)
|
|||
ScaleFactors *
|
||||
LibertyLibrary::makeScaleFactors(const char *name)
|
||||
{
|
||||
auto [it, inserted] = scale_factors_map_.emplace(std::string(name), name);
|
||||
auto [it, inserted] = scale_factors_map_.emplace(name, name);
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
ScaleFactors *
|
||||
LibertyLibrary::findScaleFactors(const char *name)
|
||||
{
|
||||
return findKeyValuePtr(scale_factors_map_, std::string(name));
|
||||
return findKeyValuePtr(scale_factors_map_, name);
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -400,20 +398,20 @@ LibertyLibrary::degradeWireSlew(const TableModel *model,
|
|||
// Check for supported axis variables.
|
||||
// Return true if axes are supported.
|
||||
bool
|
||||
LibertyLibrary::checkSlewDegradationAxes(const TablePtr &table)
|
||||
LibertyLibrary::checkSlewDegradationAxes(const TableModel *table_model)
|
||||
{
|
||||
switch (table->order()) {
|
||||
switch (table_model->order()) {
|
||||
case 0:
|
||||
return true;
|
||||
case 1: {
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis1 = table_model->axis1();
|
||||
TableAxisVariable var1 = axis1->variable();
|
||||
return var1 == TableAxisVariable::output_pin_transition
|
||||
|| var1 == TableAxisVariable::connect_delay;
|
||||
}
|
||||
case 2: {
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
const TableAxis *axis1 = table_model->axis1();
|
||||
const TableAxis *axis2 = table_model->axis2();
|
||||
TableAxisVariable var1 = axis1->variable();
|
||||
TableAxisVariable var2 = axis2->variable();
|
||||
return (var1 == TableAxisVariable::output_pin_transition
|
||||
|
|
@ -1269,8 +1267,7 @@ LibertyCell::makeInternalPower(LibertyPort *port,
|
|||
const std::shared_ptr<FuncExpr> &when,
|
||||
InternalPowerModels &models)
|
||||
{
|
||||
internal_powers_.emplace_back(port, related_port, related_pg_pin,
|
||||
when, models);
|
||||
internal_powers_.emplace_back(port, related_port, related_pg_pin, when, models);
|
||||
port_internal_powers_[port].push_back(internal_powers_.size() - 1);
|
||||
}
|
||||
|
||||
|
|
@ -1485,6 +1482,10 @@ LibertyCell::makeSequential(int size,
|
|||
port_to_seq_map_[sequentials_.back().output()] = idx;
|
||||
port_to_seq_map_[sequentials_.back().outputInv()] = idx;
|
||||
}
|
||||
delete clk;
|
||||
delete data;
|
||||
delete clear;
|
||||
delete preset;
|
||||
}
|
||||
|
||||
Sequential *
|
||||
|
|
@ -3087,7 +3088,8 @@ OperatingConditions::setWireloadTree(WireloadTree tree)
|
|||
|
||||
static EnumNameMap<ScaleFactorType> scale_factor_type_map =
|
||||
{{ScaleFactorType::pin_cap, "pin_cap"},
|
||||
{ScaleFactorType::wire_cap, "wire_res"},
|
||||
{ScaleFactorType::wire_cap, "wire_cap"},
|
||||
{ScaleFactorType::wire_res, "wire_res"},
|
||||
{ScaleFactorType::min_period, "min_period"},
|
||||
{ScaleFactorType::cell, "cell"},
|
||||
{ScaleFactorType::hold, "hold"},
|
||||
|
|
@ -3124,7 +3126,9 @@ scaleFactorTypeRiseFallSuffix(ScaleFactorType type)
|
|||
|| type == ScaleFactorType::recovery
|
||||
|| type == ScaleFactorType::removal
|
||||
|| type == ScaleFactorType::nochange
|
||||
|| type == ScaleFactorType::skew;
|
||||
|| type == ScaleFactorType::skew
|
||||
|| type == ScaleFactorType::leakage_power
|
||||
|| type == ScaleFactorType::internal_power;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -3144,7 +3148,8 @@ scaleFactorTypeLowHighSuffix(ScaleFactorType type)
|
|||
EnumNameMap<ScaleFactorPvt> scale_factor_pvt_names =
|
||||
{{ScaleFactorPvt::process, "process"},
|
||||
{ScaleFactorPvt::volt, "volt"},
|
||||
{ScaleFactorPvt::temp, "temp"}
|
||||
{ScaleFactorPvt::temp, "temp"},
|
||||
{ScaleFactorPvt::unknown, "unknown"}
|
||||
};
|
||||
|
||||
ScaleFactorPvt
|
||||
|
|
@ -3214,31 +3219,32 @@ ScaleFactors::scale(ScaleFactorType type,
|
|||
}
|
||||
|
||||
void
|
||||
ScaleFactors::print()
|
||||
ScaleFactors::report(Report *report)
|
||||
{
|
||||
printf("%10s", " ");
|
||||
std::string line = " ";
|
||||
for (int pvt_index = 0; pvt_index < scale_factor_pvt_count; pvt_index++) {
|
||||
ScaleFactorPvt pvt = (ScaleFactorPvt) pvt_index;
|
||||
printf("%10s", scaleFactorPvtName(pvt));
|
||||
stringAppend(line, "%10s", scaleFactorPvtName(pvt));
|
||||
}
|
||||
printf("\n");
|
||||
report->reportLineString(line);
|
||||
|
||||
for (int type_index = 0; type_index < scale_factor_type_count; type_index++) {
|
||||
ScaleFactorType type = (ScaleFactorType) type_index;
|
||||
printf("%10s ", scaleFactorTypeName(type));
|
||||
stringPrint(line, "%10s ", scaleFactorTypeName(type));
|
||||
for (int pvt_index = 0; pvt_index < scale_factor_pvt_count; pvt_index++) {
|
||||
if (scaleFactorTypeRiseFallSuffix(type)
|
||||
|| scaleFactorTypeRiseFallPrefix(type)
|
||||
|| scaleFactorTypeLowHighSuffix(type)) {
|
||||
printf(" %.3f,%.3f",
|
||||
scales_[type_index][pvt_index][RiseFall::riseIndex()],
|
||||
scales_[type_index][pvt_index][RiseFall::fallIndex()]);
|
||||
stringAppend(line, " %.3f,%.3f",
|
||||
scales_[type_index][pvt_index][RiseFall::riseIndex()],
|
||||
scales_[type_index][pvt_index][RiseFall::fallIndex()]);
|
||||
}
|
||||
else {
|
||||
printf(" %.3f",
|
||||
scales_[type_index][pvt_index][0]);
|
||||
stringAppend(line, " %.3f",
|
||||
scales_[type_index][pvt_index][0]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
report->reportLineString(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -363,6 +363,7 @@ scan_signal_type()
|
|||
%extend TimingArcSet {
|
||||
LibertyPort *from() { return self->from(); }
|
||||
LibertyPort *to() { return self->to(); }
|
||||
std::string to_string() { return self->to_string(); }
|
||||
const TimingRole *role() { return self->role(); }
|
||||
const char *sdf_cond() { return self->sdfCond().c_str(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ proc report_lib_cell_ { cell scene } {
|
|||
if { $filename != "" } {
|
||||
report_line "File $filename"
|
||||
}
|
||||
report_lib_ports $cell $scene
|
||||
report_timing_arcs $cell
|
||||
}
|
||||
|
||||
proc report_lib_ports { cell scene } {
|
||||
set iter [$cell liberty_port_iterator]
|
||||
while {[$iter has_next]} {
|
||||
set port [$iter next]
|
||||
|
|
@ -115,5 +120,16 @@ proc report_lib_port { port scene } {
|
|||
report_line " ${indent}$port_name [liberty_port_direction $port]$enable$func[port_capacitance_str $port $scene $sta_report_default_digits]"
|
||||
}
|
||||
|
||||
proc report_timing_arcs { cell } {
|
||||
set timing_arcs [$cell timing_arc_sets]
|
||||
if { [llength $timing_arcs] > 0 } {
|
||||
puts ""
|
||||
puts "Timing arcs"
|
||||
foreach timing_arc $timing_arcs {
|
||||
puts [$timing_arc to_string]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# sta namespace end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,14 +35,11 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
void
|
||||
LibertyBuilder::init(Debug *debug,
|
||||
Report *report)
|
||||
LibertyBuilder::LibertyBuilder(Debug *debug,
|
||||
Report *report) :
|
||||
debug_(debug),
|
||||
report_(report)
|
||||
{
|
||||
debug_ = debug;
|
||||
report_ = report;
|
||||
}
|
||||
|
||||
LibertyCell *
|
||||
|
|
@ -105,7 +102,7 @@ LibertyBuilder::makeBusPortBit(ConcreteLibrary *library,
|
|||
const char *bus_name,
|
||||
int bit_index)
|
||||
{
|
||||
string bit_name;
|
||||
std::string bit_name;
|
||||
stringPrint(bit_name, "%s%c%d%c",
|
||||
bus_name,
|
||||
library->busBrktLeft(),
|
||||
|
|
@ -189,6 +186,7 @@ LibertyBuilder::makeTimingArcs(LibertyCell *cell,
|
|||
case TimingType::combinational:
|
||||
if (seq
|
||||
&& seq->isLatch()
|
||||
&& seq->data()
|
||||
&& seq->data()->hasPort(from_port))
|
||||
// Latch D->Q timing arcs.
|
||||
return makeLatchDtoQArcs(cell, from_port, to_port,
|
||||
|
|
@ -307,8 +305,9 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell,
|
|||
{
|
||||
FuncExpr *func = to_port->function();
|
||||
FuncExpr *enable = to_port->tristateEnable();
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::combinational(), attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::combinational(),
|
||||
attrs);
|
||||
TimingSense sense = attrs->timingSense();
|
||||
if (sense == TimingSense::unknown) {
|
||||
// Timing sense not specified - find it from function.
|
||||
|
|
@ -388,8 +387,9 @@ LibertyBuilder::makeLatchDtoQArcs(LibertyCell *cell,
|
|||
TimingSense sense,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::latchDtoQ(), attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::latchDtoQ(),
|
||||
attrs);
|
||||
TimingModel *model;
|
||||
const RiseFall *to_rf = RiseFall::rise();
|
||||
model = attrs->model(to_rf);
|
||||
|
|
@ -456,8 +456,8 @@ LibertyBuilder::makeFromTransitionArcs(LibertyCell *cell,
|
|||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
related_out, role, attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port,
|
||||
related_out, role, attrs);
|
||||
for (auto to_rf : RiseFall::range()) {
|
||||
TimingModel *model = attrs->model(to_rf);
|
||||
if (model)
|
||||
|
|
@ -476,8 +476,8 @@ LibertyBuilder::makePresetClrArcs(LibertyCell *cell,
|
|||
TimingArcSet *arc_set = nullptr;
|
||||
TimingModel *model = attrs->model(to_rf);
|
||||
if (model) {
|
||||
arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::regSetClr(), attrs);
|
||||
arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::regSetClr(), attrs);
|
||||
const RiseFall *opp_rf = to_rf->opposite();
|
||||
switch (attrs->timingSense()) {
|
||||
case TimingSense::positive_unate:
|
||||
|
|
@ -509,8 +509,9 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell,
|
|||
bool to_fall,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::tristateEnable(), attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::tristateEnable(),
|
||||
attrs);
|
||||
FuncExpr *tristate_enable = to_port->tristateEnable();
|
||||
TimingSense sense = attrs->timingSense();
|
||||
if (sense == TimingSense::unknown && tristate_enable)
|
||||
|
|
@ -579,9 +580,9 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
|
|||
bool to_fall,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::tristateDisable(),
|
||||
attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::tristateDisable(),
|
||||
attrs);
|
||||
TimingSense sense = attrs->timingSense();
|
||||
FuncExpr *tristate_enable = to_port->tristateEnable();
|
||||
if (sense == TimingSense::unknown && tristate_enable)
|
||||
|
|
@ -648,7 +649,8 @@ LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell,
|
|||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, nullptr, to_port, role, attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(nullptr, to_port, nullptr,
|
||||
role, attrs);
|
||||
for (const RiseFall *to_rf : RiseFall::range()) {
|
||||
TimingModel *model = attrs->model(to_rf);
|
||||
if (model) {
|
||||
|
|
@ -683,8 +685,8 @@ LibertyBuilder::makeMinPulseWidthArcs(LibertyCell *cell,
|
|||
{
|
||||
if (from_port == nullptr)
|
||||
from_port = to_port;
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port, related_out,
|
||||
role, attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, related_out,
|
||||
role, attrs);
|
||||
for (const RiseFall *from_rf : RiseFall::range()) {
|
||||
TimingModel *model = attrs->model(from_rf);
|
||||
if (model)
|
||||
|
|
@ -695,27 +697,6 @@ LibertyBuilder::makeMinPulseWidthArcs(LibertyCell *cell,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
TimingArcSet *
|
||||
LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
return cell->makeTimingArcSet(from, to, nullptr, role, attrs);
|
||||
}
|
||||
|
||||
TimingArcSet *
|
||||
LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
return cell->makeTimingArcSet(from, to, related_out, role, attrs);
|
||||
}
|
||||
|
||||
TimingArc *
|
||||
LibertyBuilder::makeTimingArc(TimingArcSet *set,
|
||||
const RiseFall *from_rf,
|
||||
|
|
|
|||
|
|
@ -38,23 +38,21 @@ class Report;
|
|||
class LibertyBuilder
|
||||
{
|
||||
public:
|
||||
LibertyBuilder() {}
|
||||
virtual ~LibertyBuilder() {}
|
||||
void init(Debug *debug,
|
||||
Report *report);
|
||||
virtual LibertyCell *makeCell(LibertyLibrary *library,
|
||||
const char *name,
|
||||
const char *filename);
|
||||
virtual LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *name);
|
||||
virtual LibertyPort *makeBusPort(LibertyCell *cell,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index,
|
||||
BusDcl *bus_dcl);
|
||||
virtual LibertyPort *makeBundlePort(LibertyCell *cell,
|
||||
const char *name,
|
||||
ConcretePortSeq *members);
|
||||
LibertyBuilder(Debug *debug,
|
||||
Report *report);
|
||||
LibertyCell *makeCell(LibertyLibrary *library,
|
||||
const char *name,
|
||||
const char *filename);
|
||||
LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *name);
|
||||
LibertyPort *makeBusPort(LibertyCell *cell,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index,
|
||||
BusDcl *bus_dcl);
|
||||
LibertyPort *makeBundlePort(LibertyCell *cell,
|
||||
const char *name,
|
||||
ConcretePortSeq *members);
|
||||
// Build timing arc sets and their arcs given a type and sense.
|
||||
// Port functions and cell latches are also used by this builder
|
||||
// to get the correct roles.
|
||||
|
|
@ -100,29 +98,18 @@ protected:
|
|||
int from_index,
|
||||
int to_index);
|
||||
// Bus port bit (internal to makeBusPortBits).
|
||||
virtual LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *bit_name,
|
||||
int bit_index);
|
||||
LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *bit_name,
|
||||
int bit_index);
|
||||
void makeBusPortBit(ConcreteLibrary *library,
|
||||
LibertyCell *cell,
|
||||
ConcretePort *bus_port,
|
||||
const char *bus_name,
|
||||
int index);
|
||||
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs);
|
||||
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs);
|
||||
virtual TimingArc *makeTimingArc(TimingArcSet *set,
|
||||
const Transition *from_rf,
|
||||
const Transition *to_rf,
|
||||
TimingModel *model);
|
||||
TimingArc *makeTimingArc(TimingArcSet *set,
|
||||
const Transition *from_rf,
|
||||
const Transition *to_rf,
|
||||
TimingModel *model);
|
||||
TimingArc *makeTimingArc(TimingArcSet *set,
|
||||
const RiseFall *from_rf,
|
||||
const RiseFall *to_rf,
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ using sta::Report;
|
|||
using sta::Debug;
|
||||
using sta::Network;
|
||||
using sta::LibertyReader;
|
||||
using sta::LibertyAttr;
|
||||
using sta::LibertyGroup;
|
||||
using sta::LibertySimpleAttr;
|
||||
using sta::TimingGroup;
|
||||
using sta::LibertyCell;
|
||||
using sta::LibertyPort;
|
||||
|
|
@ -164,13 +164,6 @@ class BigcoLibertyBuilder : public LibertyBuilder
|
|||
public:
|
||||
virtual LibertyCell *makeCell(LibertyLibrary *library, const char *name,
|
||||
const char *filename);
|
||||
|
||||
protected:
|
||||
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell, LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs) override;
|
||||
};
|
||||
|
||||
LibertyCell *
|
||||
|
|
@ -182,16 +175,6 @@ BigcoLibertyBuilder::makeCell(LibertyLibrary *library, const char *name,
|
|||
return cell;
|
||||
}
|
||||
|
||||
TimingArcSet *
|
||||
BigcoLibertyBuilder::makeTimingArcSet(LibertyCell *cell, LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
return cell->makeTimingArcSet(from, to, related_out, role, attrs);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Liberty reader to parse Bigco attributes.
|
||||
|
|
@ -201,22 +184,18 @@ public:
|
|||
BigcoLibertyReader(LibertyBuilder *builder);
|
||||
|
||||
protected:
|
||||
virtual void visitAttr1(LibertyAttr *attr);
|
||||
virtual void visitAttr2(LibertyAttr *attr);
|
||||
virtual void beginLibrary(LibertyGroup *group);
|
||||
virtual void visitAttr1(const LibertySimpleAttr *attr);
|
||||
virtual void visitAttr2(const LibertySimpleAttr *attr);
|
||||
virtual void beginLibrary(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group);
|
||||
virtual TimingGroup *makeTimingGroup(int line);
|
||||
virtual void beginCell(LibertyGroup *group);
|
||||
virtual void beginCell(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group);
|
||||
};
|
||||
|
||||
BigcoLibertyReader::BigcoLibertyReader(LibertyBuilder *builder) :
|
||||
LibertyReader(builder)
|
||||
{
|
||||
// Define a visitor for the "thingy" attribute.
|
||||
// Note that the function descriptor passed to defineAttrVisitor
|
||||
// must be defined by the LibertyVisitor class, so a number of
|
||||
// extra visitor functions are pre-defined for extensions.
|
||||
defineAttrVisitor("thingy", &LibertyReader::visitAttr1);
|
||||
defineAttrVisitor("frob", &LibertyReader::visitAttr2);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -228,12 +207,13 @@ libertyCellRequired(const char *)
|
|||
|
||||
// Prune cells from liberty file based on libertyCellRequired predicate.
|
||||
void
|
||||
BigcoLibertyReader::beginCell(LibertyGroup *group)
|
||||
BigcoLibertyReader::beginCell(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group)
|
||||
{
|
||||
const char *name = group->firstName();
|
||||
if (name
|
||||
&& libertyCellRequired(name))
|
||||
LibertyReader::beginCell(group);
|
||||
LibertyReader::beginCell(group, library_group);
|
||||
}
|
||||
|
||||
TimingGroup *
|
||||
|
|
@ -244,15 +224,16 @@ BigcoLibertyReader::makeTimingGroup(int line)
|
|||
|
||||
// Called at the beginning of a library group.
|
||||
void
|
||||
BigcoLibertyReader::beginLibrary(LibertyGroup *group)
|
||||
BigcoLibertyReader::beginLibrary(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group)
|
||||
{
|
||||
LibertyReader::beginLibrary(group);
|
||||
LibertyReader::beginLibrary(group, library_group);
|
||||
// Do Bigco stuff here.
|
||||
printf("Bigco was here.\n");
|
||||
}
|
||||
|
||||
void
|
||||
BigcoLibertyReader::visitAttr1(LibertyAttr *attr)
|
||||
BigcoLibertyReader::visitAttr1(const LibertySimpleAttr *attr)
|
||||
{
|
||||
const char *thingy = getAttrString(attr);
|
||||
if (thingy) {
|
||||
|
|
@ -263,7 +244,7 @@ BigcoLibertyReader::visitAttr1(LibertyAttr *attr)
|
|||
}
|
||||
|
||||
void
|
||||
BigcoLibertyReader::visitAttr2(LibertyAttr *attr)
|
||||
BigcoLibertyReader::visitAttr2(const LibertySimpleAttr *attr)
|
||||
{
|
||||
const char *frob = getAttrString(attr);
|
||||
if (frob) {
|
||||
|
|
|
|||
|
|
@ -87,14 +87,14 @@ EOL \r?\n
|
|||
{FLOAT}{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(yyleng - 1);
|
||||
yylval->emplace<float>(strtod(yytext, nullptr));
|
||||
yylval->emplace<float>(strtof(yytext, nullptr));
|
||||
return token::FLOAT;
|
||||
}
|
||||
|
||||
{ALPHA}({ALPHA}|_|{DIGIT})*{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(yyleng - 1);
|
||||
yylval->emplace<std::string>(yytext);
|
||||
yylval->emplace<std::string>(yytext, yyleng);
|
||||
return token::KEYWORD;
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ EOL \r?\n
|
|||
{TOKEN}{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(yyleng - 1);
|
||||
yylval->emplace<std::string>(yytext);
|
||||
yylval->emplace<std::string>(yytext, yyleng);
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ EOL \r?\n
|
|||
<qstring>{EOL} {
|
||||
error("unterminated string constant");
|
||||
BEGIN(INITIAL);
|
||||
yylval->emplace<std::string>(token_);
|
||||
yylval->emplace<std::string>(token_);
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ sta::LibertyParse::error(const location_type &loc,
|
|||
|
||||
%require "3.2"
|
||||
%skeleton "lalr1.cc"
|
||||
%debug
|
||||
//%debug
|
||||
%define api.namespace {sta}
|
||||
%locations
|
||||
%define api.location.file "LibertyLocation.hh"
|
||||
|
|
@ -72,7 +72,7 @@ sta::LibertyParse::error(const location_type &loc,
|
|||
%left '^'
|
||||
%left '!'
|
||||
|
||||
%type <sta::LibertyStmt *> statement complex_attr simple_attr variable group file
|
||||
%type <void *> statement complex_attr simple_attr variable group file
|
||||
%type <sta::LibertyAttrValueSeq *> attr_values
|
||||
%type <sta::LibertyAttrValue *> attr_value
|
||||
%type <std::string> string expr expr_term expr_term1 volt_expr
|
||||
|
|
@ -158,11 +158,11 @@ string:
|
|||
|
||||
attr_value:
|
||||
FLOAT
|
||||
{ $$ = reader->makeFloatAttrValue($1); }
|
||||
{ $$ = reader->makeAttrValueFloat($1); }
|
||||
| expr
|
||||
{ $$ = reader->makeStringAttrValue(std::move($1)); }
|
||||
{ $$ = reader->makeAttrValueString(std::move($1)); }
|
||||
| volt_expr
|
||||
{ $$ = reader->makeStringAttrValue(std::move($1)); }
|
||||
{ $$ = reader->makeAttrValueString(std::move($1)); }
|
||||
;
|
||||
|
||||
/* Voltage expressions are ignored. */
|
||||
|
|
|
|||
|
|
@ -70,21 +70,23 @@ LibertyParser::setFilename(const string &filename)
|
|||
filename_ = filename;
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeDefine(LibertyAttrValueSeq *values,
|
||||
LibertyDefine *
|
||||
LibertyParser::makeDefine(const LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
LibertyDefine *define = nullptr;
|
||||
if (values->size() == 3) {
|
||||
std::string define_name = (*values)[0]->stringValue();
|
||||
const std::string &define_name = (*values)[0]->stringValue();
|
||||
const std::string &group_type_name = (*values)[1]->stringValue();
|
||||
const std::string &value_type_name = (*values)[2]->stringValue();
|
||||
LibertyAttrType value_type = attrValueType(value_type_name.c_str());
|
||||
LibertyGroupType group_type = groupType(group_type_name.c_str());
|
||||
define = new LibertyDefine(std::move(define_name), group_type,
|
||||
value_type, line);
|
||||
LibertyAttrType value_type = attrValueType(value_type_name);
|
||||
LibertyGroupType group_type = groupType(group_type_name);
|
||||
define = new LibertyDefine(std::move(define_name), group_type, value_type, line);
|
||||
LibertyGroup *group = this->group();
|
||||
group->addStmt(define);
|
||||
group->addDefine(define);
|
||||
for (auto value : *values)
|
||||
delete value;
|
||||
delete values;
|
||||
}
|
||||
else
|
||||
report_->fileWarn(24, filename_.c_str(), line,
|
||||
|
|
@ -96,42 +98,47 @@ LibertyParser::makeDefine(LibertyAttrValueSeq *values,
|
|||
// used to define valid attribute types. Beyond "string" these are
|
||||
// guesses.
|
||||
LibertyAttrType
|
||||
LibertyParser::attrValueType(const char *value_type_name)
|
||||
LibertyParser::attrValueType(const std::string &value_type_name)
|
||||
{
|
||||
if (stringEq(value_type_name, "string"))
|
||||
if (value_type_name == "string")
|
||||
return LibertyAttrType::attr_string;
|
||||
else if (stringEq(value_type_name, "integer"))
|
||||
else if (value_type_name == "integer")
|
||||
return LibertyAttrType::attr_int;
|
||||
else if (stringEq(value_type_name, "float"))
|
||||
else if (value_type_name == "float")
|
||||
return LibertyAttrType::attr_double;
|
||||
else if (stringEq(value_type_name, "boolean"))
|
||||
else if (value_type_name == "boolean")
|
||||
return LibertyAttrType::attr_boolean;
|
||||
else
|
||||
return LibertyAttrType::attr_unknown;
|
||||
}
|
||||
|
||||
LibertyGroupType
|
||||
LibertyParser::groupType(const char *group_type_name)
|
||||
LibertyParser::groupType(const std::string &group_type_name)
|
||||
{
|
||||
if (stringEq(group_type_name, "library"))
|
||||
if (group_type_name == "library")
|
||||
return LibertyGroupType::library;
|
||||
else if (stringEq(group_type_name, "cell"))
|
||||
else if (group_type_name == "cell")
|
||||
return LibertyGroupType::cell;
|
||||
else if (stringEq(group_type_name, "pin"))
|
||||
else if (group_type_name == "pin")
|
||||
return LibertyGroupType::pin;
|
||||
else if (stringEq(group_type_name, "timing"))
|
||||
else if (group_type_name == "timing")
|
||||
return LibertyGroupType::timing;
|
||||
else
|
||||
return LibertyGroupType::unknown;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyParser::groupBegin(std::string type,
|
||||
LibertyParser::groupBegin(const std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line)
|
||||
{
|
||||
LibertyGroup *group = new LibertyGroup(std::move(type), params, line);
|
||||
group_visitor_->begin(group);
|
||||
LibertyGroup *group =
|
||||
new LibertyGroup(std::move(type),
|
||||
params ? std::move(*params) : LibertyAttrValueSeq(),
|
||||
line);
|
||||
delete params;
|
||||
LibertyGroup *parent_group = group_stack_.empty() ? nullptr : group_stack_.back();
|
||||
group_visitor_->begin(group, parent_group);
|
||||
group_stack_.push_back(group);
|
||||
}
|
||||
|
||||
|
|
@ -139,20 +146,13 @@ LibertyGroup *
|
|||
LibertyParser::groupEnd()
|
||||
{
|
||||
LibertyGroup *group = this->group();
|
||||
group_visitor_->end(group);
|
||||
group_stack_.pop_back();
|
||||
LibertyGroup *parent =
|
||||
group_stack_.empty() ? nullptr : group_stack_.back();
|
||||
if (parent && group_visitor_->save(group)) {
|
||||
parent->addStmt(group);
|
||||
return group;
|
||||
}
|
||||
else if (group_visitor_->save(group))
|
||||
return group;
|
||||
else {
|
||||
delete group;
|
||||
return nullptr;
|
||||
}
|
||||
if (parent)
|
||||
parent->addSubgroup(group);
|
||||
group_visitor_->end(group, parent);
|
||||
return group;
|
||||
}
|
||||
|
||||
LibertyGroup *
|
||||
|
|
@ -167,240 +167,65 @@ LibertyParser::deleteGroups()
|
|||
deleteContents(group_stack_);
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeSimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
LibertySimpleAttr *
|
||||
LibertyParser::makeSimpleAttr(const std::string name,
|
||||
const LibertyAttrValue *value,
|
||||
int line)
|
||||
{
|
||||
LibertyAttr *attr = new LibertySimpleAttr(std::move(name), value, line);
|
||||
group_visitor_->visitAttr(attr);
|
||||
LibertySimpleAttr *attr = new LibertySimpleAttr(std::move(name),
|
||||
std::move(*value), line);
|
||||
delete value;
|
||||
LibertyGroup *group = this->group();
|
||||
if (group && group_visitor_->save(attr)) {
|
||||
group->addStmt(attr);
|
||||
return attr;
|
||||
}
|
||||
else {
|
||||
delete attr;
|
||||
return nullptr;
|
||||
}
|
||||
group->addAttr(attr);
|
||||
group_visitor_->visitAttr(attr);
|
||||
return attr;
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
LibertyComplexAttr *
|
||||
LibertyParser::makeComplexAttr(const std::string name,
|
||||
const LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
// Defines have the same syntax as complex attributes.
|
||||
// Detect and convert them.
|
||||
if (name == "define") {
|
||||
LibertyStmt *define = makeDefine(values, line);
|
||||
deleteContents(values);
|
||||
delete values;
|
||||
return define;
|
||||
makeDefine(values, line);
|
||||
return nullptr; // Define is not a complex attr; already added to group
|
||||
}
|
||||
else {
|
||||
LibertyAttr *attr = new LibertyComplexAttr(std::move(name), values, line);
|
||||
LibertyComplexAttr *attr = new LibertyComplexAttr(std::move(name),
|
||||
std::move(*values),
|
||||
line);
|
||||
delete values;
|
||||
LibertyGroup *group = this->group();
|
||||
group->addAttr(attr);
|
||||
group_visitor_->visitAttr(attr);
|
||||
if (group_visitor_->save(attr)) {
|
||||
LibertyGroup *group = this->group();
|
||||
group->addStmt(attr);
|
||||
return attr;
|
||||
}
|
||||
delete attr;
|
||||
return nullptr;
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeVariable(std::string var,
|
||||
LibertyVariable *
|
||||
LibertyParser::makeVariable(const std::string var,
|
||||
float value,
|
||||
int line)
|
||||
{
|
||||
LibertyVariable *variable = new LibertyVariable(std::move(var), value, line);
|
||||
LibertyGroup *group = this->group();
|
||||
group->addVariable(variable);
|
||||
group_visitor_->visitVariable(variable);
|
||||
if (group_visitor_->save(variable))
|
||||
return variable;
|
||||
else {
|
||||
delete variable;
|
||||
return nullptr;
|
||||
}
|
||||
return variable;
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyParser::makeStringAttrValue(std::string value)
|
||||
LibertyParser::makeAttrValueString(std::string value)
|
||||
{
|
||||
return new LibertyStringAttrValue(std::move(value));
|
||||
return new LibertyAttrValue(std::move(value));
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyParser::makeFloatAttrValue(float value)
|
||||
{
|
||||
return new LibertyFloatAttrValue(value);
|
||||
}
|
||||
|
||||
const std::string &
|
||||
LibertyFloatAttrValue::stringValue() const
|
||||
{
|
||||
criticalError(1127, "LibertyStringAttrValue called for float value");
|
||||
static std::string null;
|
||||
return null;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyStmt::LibertyStmt(int line) :
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyGroup::LibertyGroup(std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
type_(std::move(type)),
|
||||
params_(params),
|
||||
stmts_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addStmt(LibertyStmt *stmt)
|
||||
{
|
||||
if (stmts_ == nullptr)
|
||||
stmts_ = new LibertyStmtSeq;
|
||||
stmts_->push_back(stmt);
|
||||
}
|
||||
|
||||
LibertyGroup::~LibertyGroup()
|
||||
{
|
||||
if (params_) {
|
||||
deleteContents(params_);
|
||||
delete params_;
|
||||
}
|
||||
if (stmts_) {
|
||||
deleteContents(stmts_);
|
||||
delete stmts_;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::firstName()
|
||||
{
|
||||
if (params_ && params_->size() > 0) {
|
||||
LibertyAttrValue *value = (*params_)[0];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::secondName()
|
||||
{
|
||||
if (params_ && params_->size() > 1) {
|
||||
LibertyAttrValue *value = (*params_)[1];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyAttr::LibertyAttr(std::string name,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
name_(std::move(name))
|
||||
{
|
||||
}
|
||||
|
||||
LibertySimpleAttr::LibertySimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
int line) :
|
||||
LibertyAttr(std::move(name), line),
|
||||
value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
LibertySimpleAttr::~LibertySimpleAttr()
|
||||
{
|
||||
delete value_;
|
||||
}
|
||||
|
||||
LibertyAttrValueSeq *
|
||||
LibertySimpleAttr::values() const
|
||||
{
|
||||
criticalError(1125, "valueIterator called for LibertySimpleAttribute");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyComplexAttr::LibertyComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line) :
|
||||
LibertyAttr(std::move(name), line),
|
||||
values_(values)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyComplexAttr::~LibertyComplexAttr()
|
||||
{
|
||||
if (values_) {
|
||||
deleteContents(values_);
|
||||
delete values_;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyComplexAttr::firstValue()
|
||||
{
|
||||
if (values_ && values_->size() > 0)
|
||||
return (*values_)[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LibertyStringAttrValue::LibertyStringAttrValue(std::string value) :
|
||||
LibertyAttrValue(),
|
||||
value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
float
|
||||
LibertyStringAttrValue::floatValue() const
|
||||
{
|
||||
criticalError(1126, "LibertyStringAttrValue called for float value");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
LibertyFloatAttrValue::LibertyFloatAttrValue(float value) :
|
||||
value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyDefine::LibertyDefine(std::string name,
|
||||
LibertyGroupType group_type,
|
||||
LibertyAttrType value_type,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
name_(std::move(name)),
|
||||
group_type_(group_type),
|
||||
value_type_(value_type)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyVariable::LibertyVariable(std::string var,
|
||||
float value,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
var_(std::move(var)),
|
||||
value_(value)
|
||||
LibertyParser::makeAttrValueFloat(float value)
|
||||
{
|
||||
return new LibertyAttrValue(value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -425,13 +250,13 @@ LibertyScanner::includeBegin()
|
|||
error("nested include_file's are not supported");
|
||||
else {
|
||||
// include_file(filename);
|
||||
std::regex include_regexp("include_file *\\( *([^)]+) *\\) *;?");
|
||||
static const std::regex include_regexp("include_file *\\( *([^)]+) *\\) *;?");
|
||||
std::cmatch matches;
|
||||
if (std::regex_match(yytext, matches, include_regexp)) {
|
||||
string filename = matches[1].str();
|
||||
gzstream::igzstream *stream = new gzstream::igzstream(filename.c_str());
|
||||
if (stream->is_open()) {
|
||||
yypush_buffer_state(yy_create_buffer(stream, 256));
|
||||
yypush_buffer_state(yy_create_buffer(stream, 16384));
|
||||
|
||||
filename_prev_ = filename_;
|
||||
stream_prev_ = stream_;
|
||||
|
|
@ -471,4 +296,323 @@ LibertyScanner::error(const char *msg)
|
|||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyGroup::LibertyGroup(std::string type,
|
||||
LibertyAttrValueSeq params,
|
||||
int line) :
|
||||
type_(std::move(type)),
|
||||
params_(std::move(params)),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyGroup::~LibertyGroup()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::clear()
|
||||
{
|
||||
deleteContents(params_);
|
||||
deleteContents(simple_attr_map_);
|
||||
for (auto &attr : complex_attr_map_)
|
||||
deleteContents(attr.second);
|
||||
complex_attr_map_.clear();
|
||||
deleteContents(subgroups_);
|
||||
subgroup_map_.clear();
|
||||
deleteContents(define_map_);
|
||||
deleteContents(variables_);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addSubgroup(LibertyGroup *subgroup)
|
||||
{
|
||||
subgroups_.push_back(subgroup);
|
||||
subgroup_map_[subgroup->type()].push_back(subgroup);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::deleteSubgroup(const LibertyGroup *subgroup)
|
||||
{
|
||||
if (subgroup == subgroups_.back()) {
|
||||
subgroups_.pop_back();
|
||||
subgroup_map_[subgroup->type()].pop_back();
|
||||
delete subgroup;
|
||||
}
|
||||
else
|
||||
criticalError(1128, "LibertyAttrValue::floatValue() called on string");
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addDefine(LibertyDefine *define)
|
||||
{
|
||||
const string &define_name = define->name();
|
||||
LibertyDefine *prev_define = findKey(define_map_, define_name);
|
||||
if (prev_define) {
|
||||
define_map_.erase(define_name);
|
||||
delete prev_define;
|
||||
}
|
||||
define_map_[define_name] = define;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addAttr(LibertySimpleAttr *attr)
|
||||
{
|
||||
// Only keep the most recent simple attribute value.
|
||||
const auto &itr = simple_attr_map_.find(attr->name());
|
||||
if (itr != simple_attr_map_.end())
|
||||
delete itr->second;
|
||||
simple_attr_map_[attr->name()] = attr;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addAttr(LibertyComplexAttr *attr)
|
||||
{
|
||||
complex_attr_map_[attr->name()].push_back(attr);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addVariable(LibertyVariable *var)
|
||||
{
|
||||
variables_.push_back(var);
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::firstName() const
|
||||
{
|
||||
if (params_.size() >= 1) {
|
||||
LibertyAttrValue *value = params_[0];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::secondName() const
|
||||
{
|
||||
LibertyAttrValue *value = params_[1];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const LibertyGroupSeq &
|
||||
LibertyGroup::findSubgroups(const std::string type) const
|
||||
{
|
||||
return findKeyValue(subgroup_map_, type);
|
||||
}
|
||||
|
||||
const LibertyGroup *
|
||||
LibertyGroup::findSubgroup(const std::string type) const
|
||||
{
|
||||
const LibertyGroupSeq &groups = findKeyValue(subgroup_map_, type);
|
||||
if (groups.size() >= 1)
|
||||
return groups[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const LibertySimpleAttr *
|
||||
LibertyGroup::findSimpleAttr(const std::string attr_name) const
|
||||
{
|
||||
return findKeyValue(simple_attr_map_, attr_name);
|
||||
}
|
||||
|
||||
const LibertyComplexAttrSeq &
|
||||
LibertyGroup::findComplexAttrs(const std::string attr_name) const
|
||||
{
|
||||
return findKeyValue(complex_attr_map_, attr_name);
|
||||
}
|
||||
|
||||
const LibertyComplexAttr *
|
||||
LibertyGroup::findComplexAttr(const std::string attr_name) const
|
||||
{
|
||||
const LibertyComplexAttrSeq &attrs = findKeyValue(complex_attr_map_, attr_name);
|
||||
if (attrs.size() >= 1)
|
||||
return attrs[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string *
|
||||
LibertyGroup::findAttrString(const std::string attr_name) const
|
||||
{
|
||||
const LibertySimpleAttr *attr = findSimpleAttr(attr_name);
|
||||
if (attr)
|
||||
return &attr->value().stringValue();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::findAttrFloat(const std::string attr_name,
|
||||
// Return values.
|
||||
float &value,
|
||||
bool &exists) const
|
||||
{
|
||||
const LibertySimpleAttr *attr = findSimpleAttr(attr_name);
|
||||
if (attr) {
|
||||
const LibertyAttrValue &attr_value = attr->value();
|
||||
if (attr_value.isFloat()) {
|
||||
value = attr_value.floatValue();
|
||||
exists = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// Possibly quoted string float.
|
||||
const std::string &float_str = attr_value.stringValue();
|
||||
char *end = nullptr;
|
||||
value = std::strtof(float_str.c_str(), &end);
|
||||
if (end) {
|
||||
exists = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
exists = false;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::findAttrInt(const std::string attr_name,
|
||||
// Return values.
|
||||
int &value,
|
||||
bool &exists) const
|
||||
{
|
||||
const LibertySimpleAttr *attr = findSimpleAttr(attr_name);
|
||||
if (attr) {
|
||||
const LibertyAttrValue &attr_value = attr->value();
|
||||
if (attr_value.isFloat()) {
|
||||
value = static_cast<int>(attr_value.floatValue());
|
||||
exists = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
exists = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertySimpleAttr::LibertySimpleAttr(const std::string name,
|
||||
const LibertyAttrValue value,
|
||||
int line) :
|
||||
name_(std::move(name)),
|
||||
line_(line),
|
||||
value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
const std::string *
|
||||
LibertySimpleAttr::stringValue() const
|
||||
{
|
||||
return &value().stringValue();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyComplexAttr::LibertyComplexAttr(std::string name,
|
||||
const LibertyAttrValueSeq values,
|
||||
int line) :
|
||||
name_(std::move(name)),
|
||||
values_(std::move(values)),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyComplexAttr::~LibertyComplexAttr()
|
||||
{
|
||||
deleteContents(values_);
|
||||
}
|
||||
|
||||
const LibertyAttrValue *
|
||||
LibertyComplexAttr::firstValue() const
|
||||
{
|
||||
if (values_.size() > 0)
|
||||
return values_[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyAttrValue::LibertyAttrValue(std::string value) :
|
||||
string_value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
LibertyAttrValue::LibertyAttrValue(float value) :
|
||||
float_value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
LibertyAttrValue::isFloat() const
|
||||
{
|
||||
return string_value_.empty();
|
||||
}
|
||||
|
||||
bool
|
||||
LibertyAttrValue::isString() const
|
||||
{
|
||||
return !string_value_.empty();
|
||||
}
|
||||
|
||||
float
|
||||
LibertyAttrValue::floatValue() const
|
||||
{
|
||||
if (!string_value_.empty())
|
||||
criticalError(1127, "LibertyAttrValue::floatValue() called on string");
|
||||
return float_value_;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyAttrValue::floatValue(// Return values.
|
||||
float &value,
|
||||
bool &valid) const
|
||||
{
|
||||
valid = false;
|
||||
if (string_value_.empty()) {
|
||||
value = float_value_;
|
||||
valid = true;
|
||||
}
|
||||
else {
|
||||
// Some floats are enclosed in quotes.
|
||||
char *end;
|
||||
value = strtof(string_value_.c_str(), &end);
|
||||
if ((*end == '\0'
|
||||
|| isspace(*end))
|
||||
// strtof support INF as a valid float.
|
||||
&& string_value_ != "inf") {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyDefine::LibertyDefine(std::string name,
|
||||
LibertyGroupType group_type,
|
||||
LibertyAttrType value_type,
|
||||
int line) :
|
||||
name_(std::move(name)),
|
||||
group_type_(group_type),
|
||||
value_type_(value_type),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyVariable::LibertyVariable(std::string var,
|
||||
float value,
|
||||
int line) :
|
||||
var_(std::move(var)),
|
||||
value_(value),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -34,20 +34,22 @@ namespace sta {
|
|||
|
||||
class Report;
|
||||
class LibertyGroupVisitor;
|
||||
class LibertyStmt;
|
||||
class LibertyGroup;
|
||||
class LibertyAttr;
|
||||
class LibertyDefine;
|
||||
class LibertySimpleAttr;
|
||||
class LibertyComplexAttr;
|
||||
class LibertyAttrValue;
|
||||
class LibertyVariable;
|
||||
class LibertyScanner;
|
||||
|
||||
using LibertyStmtSeq = std::vector<LibertyStmt*>;
|
||||
using LibertyGroupSeq = std::vector<LibertyGroup*>;
|
||||
using LibertyAttrSeq = std::vector<LibertyAttr*>;
|
||||
using LibertyAttrMap = std::map<std::string, LibertyAttr*>;
|
||||
using LibertySubGroupMap = std::map<std::string, LibertyGroupSeq>;
|
||||
using LibertySimpleAttrMap = std::map<std::string, LibertySimpleAttr*>;
|
||||
using LibertyComplexAttrSeq = std::vector<LibertyComplexAttr*>;
|
||||
using LibertyComplexAttrMap = std::map<std::string, LibertyComplexAttrSeq>;
|
||||
using LibertyDefineMap = std::map<std::string, LibertyDefine*>;
|
||||
using LibertyAttrValueSeq = std::vector<LibertyAttrValue*>;
|
||||
using LibertyVariableSeq = std::vector<LibertyVariable*>;
|
||||
using LibertyVariableMap = std::map<std::string, float>;
|
||||
using LibertyGroupVisitorMap = std::map<std::string, LibertyGroupVisitor*>;
|
||||
|
||||
|
|
@ -65,27 +67,27 @@ public:
|
|||
const std::string &filename() const { return filename_; }
|
||||
void setFilename(const std::string &filename);
|
||||
Report *report() const { return report_; }
|
||||
LibertyStmt *makeDefine(LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrType attrValueType(const char *value_type_name);
|
||||
LibertyGroupType groupType(const char *group_type_name);
|
||||
void groupBegin(std::string type,
|
||||
LibertyDefine *makeDefine(const LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrType attrValueType(const std::string &value_type_name);
|
||||
LibertyGroupType groupType(const std::string &group_type_name);
|
||||
void groupBegin(const std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line);
|
||||
LibertyGroup *groupEnd();
|
||||
LibertyGroup *group();
|
||||
void deleteGroups();
|
||||
LibertyStmt *makeSimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
int line);
|
||||
LibertyStmt *makeComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrValue *makeStringAttrValue(std::string value);
|
||||
LibertyAttrValue *makeFloatAttrValue(float value);
|
||||
LibertyStmt *makeVariable(std::string var,
|
||||
float value,
|
||||
int line);
|
||||
LibertySimpleAttr *makeSimpleAttr(const std::string name,
|
||||
const LibertyAttrValue *value,
|
||||
int line);
|
||||
LibertyComplexAttr *makeComplexAttr(const std::string name,
|
||||
const LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrValue *makeAttrValueString(const std::string value);
|
||||
LibertyAttrValue *makeAttrValueFloat(float value);
|
||||
LibertyVariable *makeVariable(const std::string var,
|
||||
float value,
|
||||
int line);
|
||||
|
||||
private:
|
||||
std::string filename_;
|
||||
|
|
@ -94,178 +96,171 @@ private:
|
|||
LibertyGroupSeq group_stack_;
|
||||
};
|
||||
|
||||
// Abstract base class for liberty statements.
|
||||
class LibertyStmt
|
||||
{
|
||||
public:
|
||||
LibertyStmt(int line);
|
||||
virtual ~LibertyStmt() {}
|
||||
int line() const { return line_; }
|
||||
virtual bool isGroup() const { return false; }
|
||||
virtual bool isAttribute() const { return false; }
|
||||
virtual bool isSimpleAttr() const { return false; }
|
||||
virtual bool isComplexAttr() const { return false; }
|
||||
virtual bool isDefine() const { return false; }
|
||||
virtual bool isVariable() const { return false; }
|
||||
|
||||
protected:
|
||||
int line_;
|
||||
};
|
||||
|
||||
// Groups are a type keyword with a set of parameters and statements
|
||||
// enclosed in brackets.
|
||||
// type([param1][, param2]...) { stmts.. }
|
||||
class LibertyGroup : public LibertyStmt
|
||||
{
|
||||
public:
|
||||
LibertyGroup(std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line);
|
||||
virtual ~LibertyGroup();
|
||||
virtual bool isGroup() const { return true; }
|
||||
const std::string &type() const { return type_; }
|
||||
LibertyAttrValueSeq *params() const { return params_; }
|
||||
// First param as a string.
|
||||
const char *firstName();
|
||||
// Second param as a string.
|
||||
const char *secondName();
|
||||
void addStmt(LibertyStmt *stmt);
|
||||
LibertyStmtSeq *stmts() const { return stmts_; }
|
||||
|
||||
protected:
|
||||
void parseNames(LibertyAttrValueSeq *values);
|
||||
|
||||
std::string type_;
|
||||
LibertyAttrValueSeq *params_;
|
||||
LibertyStmtSeq *stmts_;
|
||||
};
|
||||
|
||||
// Abstract base class for attributes.
|
||||
class LibertyAttr : public LibertyStmt
|
||||
{
|
||||
public:
|
||||
LibertyAttr(std::string name,
|
||||
int line);
|
||||
const std::string &name() const { return name_; }
|
||||
virtual LibertyAttrValueSeq *values() const = 0;
|
||||
virtual LibertyAttrValue *firstValue() = 0;
|
||||
|
||||
protected:
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
// Abstract base class for simple attributes.
|
||||
// name : value;
|
||||
class LibertySimpleAttr : public LibertyAttr
|
||||
{
|
||||
public:
|
||||
LibertySimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
int line);
|
||||
virtual ~LibertySimpleAttr();
|
||||
bool isSimpleAttr() const override { return true; };
|
||||
LibertyAttrValue *firstValue() override { return value_; };
|
||||
LibertyAttrValueSeq *values() const override;
|
||||
|
||||
private:
|
||||
LibertyAttrValue *value_;
|
||||
};
|
||||
|
||||
// Complex attributes have multiple values.
|
||||
// name(attr_value1[, attr_value2]...);
|
||||
class LibertyComplexAttr : public LibertyAttr
|
||||
{
|
||||
public:
|
||||
LibertyComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
virtual ~LibertyComplexAttr();
|
||||
bool isComplexAttr() const override { return true; };
|
||||
LibertyAttrValue *firstValue() override ;
|
||||
LibertyAttrValueSeq *values() const override { return values_; }
|
||||
|
||||
private:
|
||||
LibertyAttrValueSeq *values_;
|
||||
};
|
||||
|
||||
// Attribute values are a string or float.
|
||||
class LibertyAttrValue
|
||||
{
|
||||
public:
|
||||
LibertyAttrValue() {}
|
||||
virtual ~LibertyAttrValue() {}
|
||||
virtual bool isString() const = 0;
|
||||
virtual bool isFloat() const = 0;
|
||||
virtual float floatValue() const = 0;
|
||||
virtual const std::string &stringValue() const = 0;
|
||||
};
|
||||
|
||||
class LibertyStringAttrValue : public LibertyAttrValue
|
||||
{
|
||||
public:
|
||||
LibertyStringAttrValue(std::string value);
|
||||
virtual ~LibertyStringAttrValue() {}
|
||||
bool isFloat() const override { return false; }
|
||||
bool isString() const override { return true; }
|
||||
float floatValue() const override ;
|
||||
const std::string &stringValue() const override { return value_; }
|
||||
LibertyAttrValue(float value);
|
||||
LibertyAttrValue(std::string value);
|
||||
bool isString() const;
|
||||
bool isFloat() const;
|
||||
float floatValue() const;
|
||||
void floatValue(// Return values.
|
||||
float &value,
|
||||
bool &valid) const;
|
||||
const std::string &stringValue() const { return string_value_; }
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
float float_value_;
|
||||
std::string string_value_;
|
||||
};
|
||||
|
||||
class LibertyFloatAttrValue : public LibertyAttrValue
|
||||
// Groups are a type keyword with a set of parameters and statements
|
||||
// enclosed in brackets.
|
||||
// type([param1][, param2]...) { stmts.. }
|
||||
class LibertyGroup
|
||||
{
|
||||
public:
|
||||
LibertyFloatAttrValue(float value);
|
||||
virtual ~LibertyFloatAttrValue() {}
|
||||
bool isString() const override { return false; }
|
||||
bool isFloat() const override { return true; }
|
||||
float floatValue() const override { return value_; }
|
||||
const std::string &stringValue() const override;
|
||||
LibertyGroup(const std::string type,
|
||||
const LibertyAttrValueSeq params,
|
||||
int line);
|
||||
~LibertyGroup();
|
||||
void clear();
|
||||
const std::string &type() const { return type_; }
|
||||
const LibertyAttrValueSeq ¶ms() const { return params_; }
|
||||
// First param as a string.
|
||||
const char *firstName() const;
|
||||
// Second param as a string.
|
||||
const char *secondName() const;
|
||||
int line() const { return line_; }
|
||||
|
||||
const LibertyGroupSeq &findSubgroups(const std::string type) const;
|
||||
const LibertyGroup *findSubgroup(const std::string type) const;
|
||||
const LibertySimpleAttr *findSimpleAttr(const std::string attr_name) const;
|
||||
const LibertyComplexAttrSeq &findComplexAttrs(const std::string attr_name) const;
|
||||
const LibertyComplexAttr *findComplexAttr(const std::string attr_name) const;
|
||||
const std::string *findAttrString(const std::string attr_name) const;
|
||||
void findAttrFloat(const std::string attr_name,
|
||||
// Return values.
|
||||
float &value,
|
||||
bool &exists) const;
|
||||
void findAttrInt(const std::string attr_name,
|
||||
// Return values.
|
||||
int &value,
|
||||
bool &exists) const;
|
||||
|
||||
const LibertyGroupSeq &subgroups() const { return subgroups_; }
|
||||
const LibertyDefineMap &defineMap() const { return define_map_; }
|
||||
|
||||
void addSubgroup(LibertyGroup *subgroup);
|
||||
void deleteSubgroup(const LibertyGroup *subgroup);
|
||||
void addAttr(LibertySimpleAttr *attr);
|
||||
void addAttr(LibertyComplexAttr *attr);
|
||||
void addDefine(LibertyDefine *define);
|
||||
void addVariable(LibertyVariable *var);
|
||||
|
||||
protected:
|
||||
std::string type_;
|
||||
LibertyAttrValueSeq params_;
|
||||
int line_;
|
||||
|
||||
LibertySimpleAttrMap simple_attr_map_;
|
||||
LibertyComplexAttrMap complex_attr_map_;
|
||||
LibertyGroupSeq subgroups_;
|
||||
LibertySubGroupMap subgroup_map_;
|
||||
LibertyDefineMap define_map_;
|
||||
LibertyVariableSeq variables_;
|
||||
};
|
||||
|
||||
class LibertyGroupLineLess
|
||||
{
|
||||
public:
|
||||
bool
|
||||
operator()(const LibertyGroup *group1,
|
||||
const LibertyGroup *group2) const {
|
||||
return group1->line() < group2->line();
|
||||
}
|
||||
};
|
||||
|
||||
// Simple attributes: name : value;
|
||||
class LibertySimpleAttr
|
||||
{
|
||||
public:
|
||||
LibertySimpleAttr(const std::string name,
|
||||
const LibertyAttrValue value,
|
||||
int line);
|
||||
const std::string &name() const { return name_; }
|
||||
const LibertyAttrValue &value() const { return value_; };
|
||||
const std::string *stringValue() const;
|
||||
int line() const { return line_; }
|
||||
|
||||
private:
|
||||
float value_;
|
||||
std::string name_;
|
||||
int line_;
|
||||
LibertyAttrValue value_;
|
||||
};
|
||||
|
||||
// Complex attributes have multiple values.
|
||||
// name(attr_value1[, attr_value2]...);
|
||||
class LibertyComplexAttr
|
||||
{
|
||||
public:
|
||||
LibertyComplexAttr(const std::string name,
|
||||
const LibertyAttrValueSeq values,
|
||||
int line);
|
||||
~LibertyComplexAttr();
|
||||
const std::string &name() const { return name_; }
|
||||
const LibertyAttrValue *firstValue() const;
|
||||
const LibertyAttrValueSeq &values() const { return values_; }
|
||||
int line() const { return line_; }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
LibertyAttrValueSeq values_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
// Define statements define new simple attributes.
|
||||
// define(attribute_name, group_name, attribute_type);
|
||||
// attribute_type is string|integer|float.
|
||||
class LibertyDefine : public LibertyStmt
|
||||
class LibertyDefine
|
||||
{
|
||||
public:
|
||||
LibertyDefine(std::string name,
|
||||
LibertyGroupType group_type,
|
||||
LibertyAttrType value_type,
|
||||
int line);
|
||||
virtual bool isDefine() const { return true; }
|
||||
const std::string &name() const { return name_; }
|
||||
LibertyGroupType groupType() const { return group_type_; }
|
||||
LibertyAttrType valueType() const { return value_type_; }
|
||||
int line() const { return line_; }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
LibertyGroupType group_type_;
|
||||
LibertyAttrType value_type_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
// The Liberty User Guide Version 2003.12 fails to document variables.
|
||||
// var = value;
|
||||
// The only example I have only uses float values, so I am assuming
|
||||
// that is all that is supported (which is probably wrong).
|
||||
class LibertyVariable : public LibertyStmt
|
||||
class LibertyVariable
|
||||
{
|
||||
public:
|
||||
LibertyVariable(std::string var,
|
||||
float value,
|
||||
int line);
|
||||
bool isVariable() const override { return true; }
|
||||
int line() const { return line_; }
|
||||
const std::string &variable() const { return var_; }
|
||||
float value() const { return value_; }
|
||||
|
||||
private:
|
||||
std::string var_;
|
||||
float value_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
class LibertyGroupVisitor
|
||||
|
|
@ -273,14 +268,13 @@ class LibertyGroupVisitor
|
|||
public:
|
||||
LibertyGroupVisitor() {}
|
||||
virtual ~LibertyGroupVisitor() {}
|
||||
virtual void begin(LibertyGroup *group) = 0;
|
||||
virtual void end(LibertyGroup *group) = 0;
|
||||
virtual void visitAttr(LibertyAttr *attr) = 0;
|
||||
virtual void begin(const LibertyGroup *group,
|
||||
LibertyGroup *parent_group) = 0;
|
||||
virtual void end(const LibertyGroup *group,
|
||||
LibertyGroup *parent_group) = 0;
|
||||
virtual void visitAttr(const LibertySimpleAttr *attr) = 0;
|
||||
virtual void visitAttr(const LibertyComplexAttr *attr) = 0;
|
||||
virtual void visitVariable(LibertyVariable *variable) = 0;
|
||||
// Predicates to save parse structure after visits.
|
||||
virtual bool save(LibertyGroup *group) = 0;
|
||||
virtual bool save(LibertyAttr *attr) = 0;
|
||||
virtual bool save(LibertyVariable *variable) = 0;
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -45,9 +45,7 @@ size_t
|
|||
findValueIndex(float value,
|
||||
const FloatSeq *values);
|
||||
static void
|
||||
sigmaModelsMvOwner(TableModel *models[EarlyLate::index_count],
|
||||
std::array<std::unique_ptr<TableModel>,
|
||||
EarlyLate::index_count> &out);
|
||||
sigmaModelsDelete(TableModelsEarlyLate &models);
|
||||
static string
|
||||
reportPvt(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
|
|
@ -63,40 +61,50 @@ TimingModel::TimingModel(LibertyCell *cell) :
|
|||
|
||||
GateTableModel::GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *delay_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate delay_sigma_models,
|
||||
TableModel *slew_model,
|
||||
TableModel *slew_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate slew_sigma_models,
|
||||
ReceiverModelPtr receiver_model,
|
||||
OutputWaveforms *output_waveforms) :
|
||||
GateTimingModel(cell),
|
||||
delay_model_(delay_model),
|
||||
delay_sigma_models_(std::move(delay_sigma_models)),
|
||||
slew_model_(slew_model),
|
||||
slew_sigma_models_(std::move(slew_sigma_models)),
|
||||
receiver_model_(receiver_model),
|
||||
output_waveforms_(output_waveforms)
|
||||
{
|
||||
sigmaModelsMvOwner(delay_sigma_models, delay_sigma_models_);
|
||||
sigmaModelsMvOwner(slew_sigma_models, slew_sigma_models_);
|
||||
}
|
||||
|
||||
GateTableModel::~GateTableModel() = default;
|
||||
GateTableModel::GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *slew_model) :
|
||||
GateTimingModel(cell),
|
||||
delay_model_(delay_model),
|
||||
delay_sigma_models_{},
|
||||
slew_model_(slew_model),
|
||||
slew_sigma_models_{},
|
||||
receiver_model_(nullptr),
|
||||
output_waveforms_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
GateTableModel::~GateTableModel()
|
||||
{
|
||||
sigmaModelsDelete(slew_sigma_models_);
|
||||
sigmaModelsDelete(delay_sigma_models_);
|
||||
}
|
||||
|
||||
static void
|
||||
sigmaModelsMvOwner(TableModel *models[EarlyLate::index_count],
|
||||
std::array<std::unique_ptr<TableModel>,
|
||||
EarlyLate::index_count> &out)
|
||||
sigmaModelsDelete(TableModelsEarlyLate &models)
|
||||
{
|
||||
TableModel *early_model = models ? models[EarlyLate::earlyIndex()] : nullptr;
|
||||
TableModel *late_model = models ? models[EarlyLate::lateIndex()] : nullptr;
|
||||
if (early_model) {
|
||||
out[EarlyLate::earlyIndex()].reset(early_model);
|
||||
if (late_model && late_model != early_model) {
|
||||
out[EarlyLate::lateIndex()].reset(late_model);
|
||||
} else if (late_model == early_model) {
|
||||
out[EarlyLate::lateIndex()] =
|
||||
std::make_unique<TableModel>(*out[EarlyLate::earlyIndex()]);
|
||||
}
|
||||
} else if (late_model) {
|
||||
out[EarlyLate::lateIndex()].reset(late_model);
|
||||
TableModel *early_model = models[EarlyLate::earlyIndex()];
|
||||
TableModel *late_model = models[EarlyLate::lateIndex()];
|
||||
if (early_model == late_model)
|
||||
delete early_model;
|
||||
else {
|
||||
delete early_model;
|
||||
delete late_model;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,19 +130,19 @@ GateTableModel::gateDelay(const Pvt *pvt,
|
|||
float sigma_early = 0.0;
|
||||
float sigma_late = 0.0;
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(pvt, delay_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_early = findValue(pvt, delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(pvt, delay_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_late = findValue(pvt, delay_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
gate_delay = makeDelay(delay, sigma_early, sigma_late);
|
||||
|
||||
float slew = findValue(pvt, slew_model_.get(), in_slew, load_cap, 0.0);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(pvt, slew_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_early = findValue(pvt, slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(pvt, slew_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_late = findValue(pvt, slew_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
// Clip negative slews to zero.
|
||||
if (slew < 0.0)
|
||||
|
|
@ -166,22 +174,22 @@ GateTableModel::reportGateDelay(const Pvt *pvt,
|
|||
load_cap, 0.0, digits);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
result += reportTableLookup("Delay sigma(early)", pvt,
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
result += reportTableLookup("Delay sigma(late)", pvt,
|
||||
delay_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
delay_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
result += '\n';
|
||||
result += reportTableLookup("Slew", pvt, slew_model_.get(), in_slew,
|
||||
load_cap, 9.0, digits);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
result += reportTableLookup("Slew sigma(early)", pvt,
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
result += reportTableLookup("Slew sigma(late)", pvt,
|
||||
slew_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
slew_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
float drvr_slew = findValue(pvt, slew_model_.get(), in_slew, load_cap, 0.0);
|
||||
if (drvr_slew < 0.0)
|
||||
|
|
@ -285,13 +293,13 @@ GateTableModel::driveResistance(const Pvt *pvt) const
|
|||
const TableModel *
|
||||
GateTableModel::delaySigmaModel(const EarlyLate *el) const
|
||||
{
|
||||
return delay_sigma_models_[el->index()].get();
|
||||
return delay_sigma_models_[el->index()];
|
||||
}
|
||||
|
||||
const TableModel *
|
||||
GateTableModel::slewSigmaModel(const EarlyLate *el) const
|
||||
{
|
||||
return slew_sigma_models_[el->index()].get();
|
||||
return slew_sigma_models_[el->index()];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -354,7 +362,7 @@ GateTableModel::axisValue(const TableAxis *axis,
|
|||
}
|
||||
|
||||
bool
|
||||
GateTableModel::checkAxes(const TablePtr &table)
|
||||
GateTableModel::checkAxes(const TableModel *table)
|
||||
{
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
|
|
@ -395,7 +403,7 @@ ReceiverModel::setCapacitanceModel(TableModel table_model,
|
|||
}
|
||||
|
||||
bool
|
||||
ReceiverModel::checkAxes(TablePtr table)
|
||||
ReceiverModel::checkAxes(const TableModel *table)
|
||||
{
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
|
|
@ -415,14 +423,25 @@ ReceiverModel::checkAxes(TablePtr table)
|
|||
|
||||
CheckTableModel::CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model,
|
||||
TableModel *sigma_models[EarlyLate::index_count]) :
|
||||
TableModelsEarlyLate sigma_models) :
|
||||
CheckTimingModel(cell),
|
||||
model_(model)
|
||||
model_(model),
|
||||
sigma_models_(std::move(sigma_models))
|
||||
{
|
||||
sigmaModelsMvOwner(sigma_models, sigma_models_);
|
||||
}
|
||||
|
||||
CheckTableModel::~CheckTableModel() = default;
|
||||
CheckTableModel::CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model) :
|
||||
CheckTimingModel(cell),
|
||||
model_(model),
|
||||
sigma_models_{}
|
||||
{
|
||||
}
|
||||
|
||||
CheckTableModel::~CheckTableModel()
|
||||
{
|
||||
sigmaModelsDelete(sigma_models_);
|
||||
}
|
||||
|
||||
void
|
||||
CheckTableModel::setIsScaled(bool is_scaled)
|
||||
|
|
@ -434,7 +453,7 @@ CheckTableModel::setIsScaled(bool is_scaled)
|
|||
const TableModel *
|
||||
CheckTableModel::sigmaModel(const EarlyLate *el) const
|
||||
{
|
||||
return sigma_models_[el->index()].get();
|
||||
return sigma_models_[el->index()];
|
||||
}
|
||||
|
||||
ArcDelay
|
||||
|
|
@ -449,10 +468,10 @@ CheckTableModel::checkDelay(const Pvt *pvt,
|
|||
float sigma_early = 0.0;
|
||||
float sigma_late = 0.0;
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(pvt, sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_early = findValue(pvt, sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, to_slew, related_out_cap);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(pvt, sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_late = findValue(pvt, sigma_models_[EarlyLate::lateIndex()],
|
||||
from_slew, to_slew, related_out_cap);
|
||||
return makeDelay(mean, sigma_early, sigma_late);
|
||||
}
|
||||
|
|
@ -491,12 +510,12 @@ CheckTableModel::reportCheckDelay(const Pvt *pvt,
|
|||
related_out_cap, digits);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()])
|
||||
result += reportTableDelay("Check sigma early", pvt,
|
||||
sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()])
|
||||
result += reportTableDelay("Check sigma late", pvt,
|
||||
sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_models_[EarlyLate::lateIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
return result;
|
||||
|
|
@ -587,7 +606,7 @@ CheckTableModel::axisValue(const TableAxis *axis,
|
|||
}
|
||||
|
||||
bool
|
||||
CheckTableModel::checkAxes(const TablePtr table)
|
||||
CheckTableModel::checkAxes(const TableModel *table)
|
||||
{
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
|
|
|
|||
|
|
@ -204,6 +204,16 @@ TimingArcSet::TimingArcSet(const TimingRole *role,
|
|||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
TimingArcSet::to_string()
|
||||
{
|
||||
std::string str = from_->name();
|
||||
str += " -> ";
|
||||
str += to_->name();
|
||||
str += " " + role()->to_string();
|
||||
return str;
|
||||
}
|
||||
|
||||
TimingArcSet::~TimingArcSet()
|
||||
{
|
||||
deleteContents(arcs_);
|
||||
|
|
@ -622,7 +632,7 @@ TimingArc::equiv(const TimingArc *arc1,
|
|||
}
|
||||
|
||||
void
|
||||
TimingArc::setIndex(unsigned index)
|
||||
TimingArc::setIndex(size_t index)
|
||||
{
|
||||
index_ = index;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ Power::reportDesign(const Scene *scene,
|
|||
PowerResult total, sequential, combinational, clock, macro, pad;
|
||||
power(scene, total, sequential, combinational, clock, macro, pad);
|
||||
ReportPower report_power(this);
|
||||
report_power.reportDesign(total, sequential, combinational, clock, macro, pad, digits);
|
||||
report_power.reportDesign(total, sequential, combinational, clock, macro, pad, digits);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ MakeTimingModel::MakeTimingModel(const char *lib_name,
|
|||
scene_(scene),
|
||||
cell_(nullptr),
|
||||
min_max_(MinMax::max()),
|
||||
lib_builder_(new LibertyBuilder),
|
||||
lib_builder_(new LibertyBuilder(debug_, report_)),
|
||||
tbl_template_index_(1),
|
||||
sdc_(scene->sdc()),
|
||||
sdc_backup_(nullptr),
|
||||
|
|
@ -611,7 +611,7 @@ MakeTimingModel::makeScalarCheckModel(float value,
|
|||
library_->findTableTemplate("scalar", TableTemplateType::delay);
|
||||
TableModel *table_model = new TableModel(table, tbl_template,
|
||||
scale_factor_type, rf);
|
||||
CheckTableModel *check_model = new CheckTableModel(cell_, table_model, nullptr);
|
||||
CheckTableModel *check_model = new CheckTableModel(cell_, table_model);
|
||||
return check_model;
|
||||
}
|
||||
|
||||
|
|
@ -628,9 +628,7 @@ MakeTimingModel::makeGateModelScalar(Delay delay,
|
|||
ScaleFactorType::cell, rf);
|
||||
TableModel *slew_model = new TableModel(slew_table, tbl_template,
|
||||
ScaleFactorType::cell, rf);
|
||||
GateTableModel *gate_model = new GateTableModel(cell_, delay_model, nullptr,
|
||||
slew_model, nullptr,
|
||||
nullptr, nullptr);
|
||||
GateTableModel *gate_model = new GateTableModel(cell_, delay_model, slew_model);
|
||||
return gate_model;
|
||||
}
|
||||
|
||||
|
|
@ -643,9 +641,7 @@ MakeTimingModel::makeGateModelScalar(Delay delay,
|
|||
library_->findTableTemplate("scalar", TableTemplateType::delay);
|
||||
TableModel *delay_model = new TableModel(delay_table, tbl_template,
|
||||
ScaleFactorType::cell, rf);
|
||||
GateTableModel *gate_model = new GateTableModel(cell_, delay_model, nullptr,
|
||||
nullptr, nullptr,
|
||||
nullptr, nullptr);
|
||||
GateTableModel *gate_model = new GateTableModel(cell_, delay_model, nullptr);
|
||||
return gate_model;
|
||||
}
|
||||
|
||||
|
|
@ -721,10 +717,8 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin,
|
|||
ScaleFactorType::cell, rf);
|
||||
TableModel *slew_model = new TableModel(slew_table, model_template,
|
||||
ScaleFactorType::cell, rf);
|
||||
GateTableModel *gate_model = new GateTableModel(cell_,
|
||||
delay_model, nullptr,
|
||||
slew_model, nullptr,
|
||||
nullptr, nullptr);
|
||||
GateTableModel *gate_model = new GateTableModel(cell_, delay_model,
|
||||
slew_model);
|
||||
return gate_model;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1178,7 +1178,7 @@ PathEndLatchCheck::sourceClkOffset(const StaState *sta) const
|
|||
const TimingRole *
|
||||
PathEndLatchCheck::checkRole(const StaState *sta) const
|
||||
{
|
||||
if (clk_path_->clkInfo(sta)->isPulseClk())
|
||||
if (clk_path_ && clk_path_->clkInfo(sta)->isPulseClk())
|
||||
// Pulse latches use register cycle accounting.
|
||||
return TimingRole::setup();
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Tests whether the is_memory attribute works for cells and libcells
|
||||
# Tests whether the is_memory attribute works for instances and cells
|
||||
read_liberty gf180mcu_sram.lib.gz
|
||||
read_liberty asap7_small.lib.gz
|
||||
read_verilog get_is_memory.v
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,3 +1,4 @@
|
|||
Warning 1195: liberty_arcs_one2one_1.lib line 45, port Y function size does not match port size.
|
||||
Warning 1216: liberty_arcs_one2one_1.lib line 48, timing port A and related port Y are different sizes.
|
||||
report_edges -from partial_wide_inv_cell/A[0]
|
||||
A[0] -> Y[0] combinational
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
Warning 1195: liberty_arcs_one2one_2.lib line 45, port Y function size does not match port size.
|
||||
Warning 1216: liberty_arcs_one2one_2.lib line 48, timing port A and related port Y are different sizes.
|
||||
report_edges -to partial_wide_inv_cell/Y[0]
|
||||
A[0] -> Y[0] combinational
|
||||
|
|
|
|||
|
|
@ -87,4 +87,27 @@ TokenParser::next()
|
|||
return token_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Parse space separated tokens.
|
||||
StdStringSeq
|
||||
parseTokens(const std::string &s,
|
||||
const char delimiter)
|
||||
{
|
||||
StdStringSeq tokens;
|
||||
size_t i = 0;
|
||||
while (i < s.size()) {
|
||||
while (i < s.size() && std::isspace(s[i]))
|
||||
++i;
|
||||
size_t start = i;
|
||||
while (i < s.size() && s[i] != delimiter)
|
||||
++i;
|
||||
if (start < i) {
|
||||
tokens.emplace_back(s, start, i - start);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
Loading…
Reference in New Issue