From f0c9971015015fa9cded7d2c1427bee55718ddfb Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 26 Feb 2026 05:13:51 +1300 Subject: [PATCH 01/22] Expose 'TimingType' from `TimingArc`. (#380) When using the OpenSTA Liberty file parser as a general-purpose Liberty reader, it's useful to be able to extract the original `TimingType` for a timing arc, and trivial to support. --- include/sta/TimingArc.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index 347e37f1..caccedf1 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -170,6 +170,7 @@ public: void deleteTimingArc(TimingArc *arc); TimingArc *findTimingArc(unsigned arc_index); void setRole(const TimingRole *role); + TimingType timingType() const { return attrs_->timingType(); } FuncExpr *cond() const { return attrs_->cond(); } // Cond default is the timing arcs with no condition when there are // other conditional timing arcs between the same pins. From a2cd40f57c53d4a6a6a71d5fa3df400b877334f1 Mon Sep 17 00:00:00 2001 From: Kazuto Iris <78157415+kazutoiris@users.noreply.github.com> Date: Thu, 26 Feb 2026 10:08:47 +0800 Subject: [PATCH 02/22] fix: Revert "Expose 'TimingType' from `TimingArc`. (#380)" (#390) Now the `TimingArcSet` class in `TimingArc.hh` has two identical declarations of the `timingType()` member function with the same signature, return type and implementation, which causes an overload conflict error during the build process. This reverts commit f0c9971015015fa9cded7d2c1427bee55718ddfb. --- include/sta/TimingArc.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index caccedf1..347e37f1 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -170,7 +170,6 @@ public: void deleteTimingArc(TimingArc *arc); TimingArc *findTimingArc(unsigned arc_index); void setRole(const TimingRole *role); - TimingType timingType() const { return attrs_->timingType(); } FuncExpr *cond() const { return attrs_->cond(); } // Cond default is the timing arcs with no condition when there are // other conditional timing arcs between the same pins. From 95d5ebb47cda31c6f4fe360fe4f29becc623ada8 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 26 Feb 2026 09:32:20 -0800 Subject: [PATCH 03/22] test/helpers.tcl Signed-off-by: James Cherry --- test/helpers.tcl | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/helpers.tcl diff --git a/test/helpers.tcl b/test/helpers.tcl new file mode 100644 index 00000000..46eb84c9 --- /dev/null +++ b/test/helpers.tcl @@ -0,0 +1,41 @@ +# Helper functions common to multiple regressions. + +set test_dir [file dirname [file normalize [info script]]] +set result_dir [file join $test_dir "results"] + +# puts [exec cat $file] without forking. +proc report_file { file } { + set stream [open $file r] + if { [file extension $file] == ".gz" } { + zlib push gunzip $stream + } + gets $stream line + while { ![eof $stream] } { + puts $line + gets $stream line + } + close $stream +} + +proc report_file_filter { file filter } { + set stream [open $file r] + gets $stream line + while { ![eof $stream] } { + set index [string first $filter $line] + if { $index != -1 } { + set line [string replace $line $index [expr $index + [string length $filter] - 1]] + } + puts $line + gets $stream line + } + close $stream +} + +proc make_result_file { filename } { + variable result_dir + return [file join $result_dir $filename] +} + +proc sort_objects { objects } { + return [sta::sort_by_full_name $objects] +} From a47a8dd8315f6e8d55a90c3f55d4c433e55bff7d Mon Sep 17 00:00:00 2001 From: Kazuto Iris <78157415+kazutoiris@users.noreply.github.com> Date: Sat, 28 Feb 2026 05:51:28 +0800 Subject: [PATCH 04/22] Add GitHub Action for CI and fix broken testcases (#391) * feat(ci): add GitHub Action for push and pull request * fix(ci): fix broken testcases * chore: add CODEOWNERS for ci * ci: bump actions/upload-artifact from 6 to 7 --- .github/dependabot.yml | 6 +++++ .github/workflows/ci.yml | 54 ++++++++++++++++++++++++++++++++++++++++ CODEOWNERS | 2 ++ test/get_filter.ok | 2 +- test/report_json1.ok | 10 ++++---- test/suppress_msg.ok | 8 +++--- 6 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 CODEOWNERS diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..c7fc735e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..74255543 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +name: CI + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + submodules: true + + - name: Set up dependencies + run: | + sudo apt-get update && sudo apt-get install -y flex libfl-dev bison tcl-dev tcl-tclreadline libeigen3-dev ninja-build + + - name: Set up cudd-3.0.0 + run: | + wget https://github.com/oscc-ip/artifact/releases/download/cudd-3.0.0/build.tar.gz + mkdir -p cudd + tar -zxvf build.tar.gz -Ccudd + + - name: Build + run: | + mkdir build + cd build + cmake .. -G Ninja -DCUDD_DIR=$(pwd)/../cudd -DCMAKE_INSTALL_PREFIX=$(pwd)/install -DCMAKE_BUILD_TYPE=Release + cmake --build . --target all -- -j $(nproc) + cmake --install . + tar -zcvf build.tar.gz -Cinstall . + + - name: Test + run: | + cd test + ./regression + + - name: Upload Artifacts + uses: actions/upload-artifact@v7 + if: ${{ !cancelled() }} + with: + name: artifact + path: | + build/install/* + + - name: Upload Test Result + uses: actions/upload-artifact@v7 + if: ${{ !cancelled() }} + with: + name: result + path: | + test/results/* diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..c6c2b793 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,2 @@ +# For CI/CD issues +/.github/ @kazutoiris diff --git a/test/get_filter.ok b/test/get_filter.ok index deaa54f3..b66978cd 100644 --- a/test/get_filter.ok +++ b/test/get_filter.ok @@ -53,4 +53,4 @@ in2 [get_ports -filter direction==output *] out [get_cells -filter {name ~= *r1*} *] -Error: get_filter.tcl line 48, unknown filter operand. +Error 336: get_filter.tcl line 48, unknown filter operand. diff --git a/test/report_json1.ok b/test/report_json1.ok index 7f70fbf7..51e8ae79 100644 --- a/test/report_json1.ok +++ b/test/report_json1.ok @@ -36,7 +36,7 @@ "net": "mid", "arrival": 3.296e-10, "capacitance": 1.949e-15, - "slew": 4.035e-11 + "slew": 3.612e-11 }, { "instance": "_1416_[0]", @@ -45,7 +45,7 @@ "pin": "_1416_[0]/D", "net": "mid", "arrival": 3.296e-10, - "slew": 4.035e-11 + "slew": 3.612e-11 } ], "target_clock": "clk", @@ -72,9 +72,9 @@ ], "data_arrival_time": 3.296e-10, "crpr": 0.000e+00, - "margin": 1.225e-10, - "required_time": 9.877e-09, - "slack": 9.548e-09 + "margin": 1.207e-10, + "required_time": 9.879e-09, + "slack": 9.550e-09 } ] } diff --git a/test/suppress_msg.ok b/test/suppress_msg.ok index 0fd4d548..2673ab25 100644 --- a/test/suppress_msg.ok +++ b/test/suppress_msg.ok @@ -1,12 +1,12 @@ Warning 1: suppress_msg.tcl line 18, cmd warn 1 -caught Error: suppress_msg.tcl line 18, cmd error 1 +caught Error 2: suppress_msg.tcl line 18, cmd error 1 Warning 1: cmd warn 2 -caught Error: 2cmd error 2 +caught Error: 2 cmd error 2 after error caught caught after error Warning 1: suppress_msg.tcl line 51, cmd warn 7 -caught Error: suppress_msg.tcl line 51, cmd error 7 +caught Error 2: suppress_msg.tcl line 51, cmd error 7 Warning 1: cmd warn 8 -caught Error: 2cmd error 8 +caught Error: 2 cmd error 8 From c010a0f99e10d4bfb39849a6c964e6ded7b5cbda Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 27 Feb 2026 16:57:08 -0800 Subject: [PATCH 05/22] liberty reader rewrite Signed-off-by: James Cherry --- examples/multi_corner.tcl | 1 - graph/Graph.cc | 2 + graph/Graph.i | 1 + include/sta/Liberty.hh | 4 +- include/sta/TableModel.hh | 26 +- include/sta/TimingArc.hh | 9 +- include/sta/TokenParser.hh | 10 + include/sta/Transition.hh | 1 + liberty/LibExprReader.cc | 6 +- liberty/LibExprReader.hh | 2 +- liberty/LibExprReaderPvt.hh | 4 +- liberty/Liberty.cc | 56 +- liberty/Liberty.i | 1 + liberty/Liberty.tcl | 16 + liberty/LibertyBuilder.cc | 71 +- liberty/LibertyBuilder.hh | 57 +- liberty/LibertyExt.cc | 49 +- liberty/LibertyLex.ll | 8 +- liberty/LibertyParse.yy | 10 +- liberty/LibertyParser.cc | 622 ++- liberty/LibertyParser.hh | 296 +- liberty/LibertyReader.cc | 8365 +++++++++++--------------------- liberty/LibertyReaderPvt.hh | 1152 ++--- liberty/TableModel.cc | 109 +- liberty/TimingArc.cc | 12 +- power/Power.cc | 2 +- search/MakeTimingModel.cc | 18 +- search/PathEnd.cc | 2 +- test/get_is_memory.tcl | 2 +- test/gf180mcu_sram.lib.gz | Bin 7015 -> 6997 bytes test/liberty_arcs_one2one_1.ok | 1 + test/liberty_arcs_one2one_2.ok | 1 + util/TokenParser.cc | 23 + 33 files changed, 4109 insertions(+), 6830 deletions(-) diff --git a/examples/multi_corner.tcl b/examples/multi_corner.tcl index 4900d867..fa5fab18 100644 --- a/examples/multi_corner.tcl +++ b/examples/multi_corner.tcl @@ -17,4 +17,3 @@ define_scene ff -liberty NangateOpenCellLibrary_fast report_checks -path_delay min_max # report typical scene report_checks -scene tt - diff --git a/graph/Graph.cc b/graph/Graph.cc index 2fe4d934..9e0b189d 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -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 += " "; diff --git a/graph/Graph.i b/graph/Graph.i index ed9ad710..b6f3c3c5 100644 --- a/graph/Graph.i +++ b/graph/Graph.i @@ -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(); } diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 68d43bb3..02769b84 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -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_; diff --git a/include/sta/TableModel.hh b/include/sta/TableModel.hh index 1d08d751..1e88faf6 100644 --- a/include/sta/TableModel.hh +++ b/include/sta/TableModel.hh @@ -49,6 +49,7 @@ using FloatTable = std::vector; // Sequence of 1D tables (order 1). using Table1Seq = std::vector; using Waveform = Table; +using TableModelsEarlyLate = std::array; 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 delay_model_; - std::array, EarlyLate::index_count> delay_sigma_models_; + TableModelsEarlyLate delay_sigma_models_; std::unique_ptr slew_model_; - std::array, EarlyLate::index_count> slew_sigma_models_; + TableModelsEarlyLate slew_sigma_models_; ReceiverModelPtr receiver_model_; std::unique_ptr 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 model_; - std::array, 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 capacitance_models_; diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index 347e37f1..63c04d49 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -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); diff --git a/include/sta/TokenParser.hh b/include/sta/TokenParser.hh index a339a6a8..27db37f9 100644 --- a/include/sta/TokenParser.hh +++ b/include/sta/TokenParser.hh @@ -24,8 +24,13 @@ #pragma once +#include +#include + namespace sta { +using StdStringSeq = std::vector; + // 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 diff --git a/include/sta/Transition.hh b/include/sta/Transition.hh index 39190c6c..3f3e03c6 100644 --- a/include/sta/Transition.hh +++ b/include/sta/Transition.hh @@ -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(); } diff --git a/liberty/LibExprReader.cc b/liberty/LibExprReader.cc index c9bc84bc..dfb2d679 100644 --- a/liberty/LibExprReader.cc +++ b/liberty/LibExprReader.cc @@ -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 * diff --git a/liberty/LibExprReader.hh b/liberty/LibExprReader.hh index 79d6d35f..fa36aaa3 100644 --- a/liberty/LibExprReader.hh +++ b/liberty/LibExprReader.hh @@ -32,7 +32,7 @@ class LibertyCell; FuncExpr * parseFuncExpr(const char *func, - LibertyCell *cell, + const LibertyCell *cell, const char *error_msg, Report *report); diff --git a/liberty/LibExprReaderPvt.hh b/liberty/LibExprReaderPvt.hh index 4532b2e8..06a65ea2 100644 --- a/liberty/LibExprReaderPvt.hh +++ b/liberty/LibExprReaderPvt.hh @@ -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_; diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index d83d06b7..5df31143 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -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 &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 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 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); } } diff --git a/liberty/Liberty.i b/liberty/Liberty.i index 96223170..2257b2eb 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -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(); } diff --git a/liberty/Liberty.tcl b/liberty/Liberty.tcl index 672e876f..fd75a8bf 100644 --- a/liberty/Liberty.tcl +++ b/liberty/Liberty.tcl @@ -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 } diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index b20d8c62..988c32e9 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -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, diff --git a/liberty/LibertyBuilder.hh b/liberty/LibertyBuilder.hh index dacbbb41..06538687 100644 --- a/liberty/LibertyBuilder.hh +++ b/liberty/LibertyBuilder.hh @@ -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, diff --git a/liberty/LibertyExt.cc b/liberty/LibertyExt.cc index d45a7420..32c10b5e 100644 --- a/liberty/LibertyExt.cc +++ b/liberty/LibertyExt.cc @@ -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) { diff --git a/liberty/LibertyLex.ll b/liberty/LibertyLex.ll index 6df7d07b..22edd696 100644 --- a/liberty/LibertyLex.ll +++ b/liberty/LibertyLex.ll @@ -87,14 +87,14 @@ EOL \r?\n {FLOAT}{TOKEN_END} { /* Push back the TOKEN_END character. */ yyless(yyleng - 1); - yylval->emplace(strtod(yytext, nullptr)); + yylval->emplace(strtof(yytext, nullptr)); return token::FLOAT; } {ALPHA}({ALPHA}|_|{DIGIT})*{TOKEN_END} { /* Push back the TOKEN_END character. */ yyless(yyleng - 1); - yylval->emplace(yytext); + yylval->emplace(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(yytext); + yylval->emplace(yytext, yyleng); return token::STRING; } @@ -141,7 +141,7 @@ EOL \r?\n {EOL} { error("unterminated string constant"); BEGIN(INITIAL); - yylval->emplace(token_); + yylval->emplace(token_); return token::STRING; } diff --git a/liberty/LibertyParse.yy b/liberty/LibertyParse.yy index 7423c4fe..a3d4b715 100644 --- a/liberty/LibertyParse.yy +++ b/liberty/LibertyParse.yy @@ -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 statement complex_attr simple_attr variable group file +%type statement complex_attr simple_attr variable group file %type attr_values %type attr_value %type 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. */ diff --git a/liberty/LibertyParser.cc b/liberty/LibertyParser.cc index 9cf52702..4660aa42 100644 --- a/liberty/LibertyParser.cc +++ b/liberty/LibertyParser.cc @@ -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(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 diff --git a/liberty/LibertyParser.hh b/liberty/LibertyParser.hh index e27d859a..2f533c36 100644 --- a/liberty/LibertyParser.hh +++ b/liberty/LibertyParser.hh @@ -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; using LibertyGroupSeq = std::vector; -using LibertyAttrSeq = std::vector; -using LibertyAttrMap = std::map; +using LibertySubGroupMap = std::map; +using LibertySimpleAttrMap = std::map; +using LibertyComplexAttrSeq = std::vector; +using LibertyComplexAttrMap = std::map; using LibertyDefineMap = std::map; using LibertyAttrValueSeq = std::vector; +using LibertyVariableSeq = std::vector; using LibertyVariableMap = std::map; using LibertyGroupVisitorMap = std::map; @@ -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 diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index edcde894..974ab7ec 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -26,6 +26,7 @@ #include #include +#include #include #include "ContainerHelpers.hh" @@ -55,9 +56,6 @@ extern int LibertyParse_debug; namespace sta { -using std::make_shared; -using std::string; - static void scaleFloats(FloatSeq &floats, float scale); @@ -74,76 +72,19 @@ readLibertyFile(const char *filename, LibertyReader::LibertyReader(const char *filename, bool infer_latches, Network *network) : - LibertyGroupVisitor() + LibertyGroupVisitor(), + filename_(filename), + infer_latches_(infer_latches), + report_(network->report()), + debug_(network->debug()), + network_(network), + builder_(debug_, report_), + library_(nullptr), + first_cell_(true) { - init(filename, infer_latches, network); defineVisitors(); } -void -LibertyReader::init(const char *filename, - bool infer_latches, - Network *network) -{ - filename_ = filename; - infer_latches_ = infer_latches; - report_ = network->report(); - debug_ = network->debug(); - network_ = network; - var_map_ = nullptr; - library_ = nullptr; - wireload_ = nullptr; - wireload_selection_ = nullptr; - default_wireload_ = nullptr; - default_wireload_selection_ = nullptr; - scale_factors_ = nullptr; - save_scale_factors_ = nullptr; - tbl_template_ = nullptr; - cell_ = nullptr; - save_cell_ = nullptr; - scaled_cell_owner_ = nullptr; - test_cell_ = nullptr; - ocv_derate_name_ = nullptr; - op_cond_ = nullptr; - ports_ = nullptr; - port_group_ = nullptr; - saved_ports_ = nullptr; - saved_port_group_ = nullptr; - in_bus_ = false; - in_bundle_ = false; - in_ccsn_ = false; - in_ecsm_waveform_ = false; - sequential_ = nullptr; - statetable_ = nullptr; - timing_ = nullptr; - internal_power_ = nullptr; - leakage_power_ = nullptr; - table_ = nullptr; - rf_ = nullptr; - index_ = 0; - table_model_scale_ = 1.0; - mode_def_ = nullptr; - mode_value_ = nullptr; - ocv_derate_ = nullptr; - pg_port_ = nullptr; - default_operating_condition_ = nullptr; - receiver_model_ = nullptr; - - builder_.init(debug_, report_); - - for (auto rf_index : RiseFall::rangeIndex()) { - have_input_threshold_[rf_index] = false; - have_output_threshold_[rf_index] = false; - have_slew_lower_threshold_[rf_index] = false; - have_slew_upper_threshold_[rf_index] = false; - } -} - -LibertyReader::~LibertyReader() -{ - delete var_map_; -} - LibertyLibrary * LibertyReader::readLibertyFile(const char *filename) { @@ -157,498 +98,179 @@ LibertyReader::defineGroupVisitor(const char *type, LibraryGroupVisitor begin_visitor, LibraryGroupVisitor end_visitor) { - group_begin_map_[type] = begin_visitor; - group_end_map_[type] = end_visitor; -} - -void -LibertyReader::defineAttrVisitor(const char *attr_name, - LibraryAttrVisitor visitor) -{ - attr_visitor_map_[attr_name] = visitor; + if (begin_visitor) + group_begin_map_[type] = begin_visitor; + if (end_visitor) + group_end_map_[type] = end_visitor; } void LibertyReader::defineVisitors() { - // Library defineGroupVisitor("library", &LibertyReader::beginLibrary, &LibertyReader::endLibrary); - defineAttrVisitor("time_unit", &LibertyReader::visitTimeUnit); - defineAttrVisitor("pulling_resistance_unit", - &LibertyReader::visitPullingResistanceUnit); - defineAttrVisitor("resistance_unit", &LibertyReader::visitResistanceUnit); - defineAttrVisitor("capacitive_load_unit", - &LibertyReader::visitCapacitiveLoadUnit); - defineAttrVisitor("voltage_unit", &LibertyReader::visitVoltageUnit); - defineAttrVisitor("current_unit", &LibertyReader::visitCurrentUnit); - defineAttrVisitor("leakage_power_unit", &LibertyReader::visitPowerUnit); - defineAttrVisitor("distance_unit", &LibertyReader::visitDistanceUnit); - defineAttrVisitor("delay_model", &LibertyReader::visitDelayModel); - defineAttrVisitor("bus_naming_style", &LibertyReader::visitBusStyle); - defineAttrVisitor("voltage_map", &LibertyReader::visitVoltageMap); - defineAttrVisitor("nom_temperature", &LibertyReader::visitNomTemp); - defineAttrVisitor("nom_voltage", &LibertyReader::visitNomVolt); - defineAttrVisitor("nom_process", &LibertyReader::visitNomProc); - defineAttrVisitor("default_inout_pin_cap", - &LibertyReader::visitDefaultInoutPinCap); - defineAttrVisitor("default_input_pin_cap", - &LibertyReader::visitDefaultInputPinCap); - defineAttrVisitor("default_output_pin_cap", - &LibertyReader::visitDefaultOutputPinCap); - defineAttrVisitor("default_max_transition", - &LibertyReader::visitDefaultMaxTransition); - defineAttrVisitor("default_max_fanout", - &LibertyReader::visitDefaultMaxFanout); - defineAttrVisitor("default_intrinsic_rise", - &LibertyReader::visitDefaultIntrinsicRise); - defineAttrVisitor("default_intrinsic_fall", - &LibertyReader::visitDefaultIntrinsicFall); - defineAttrVisitor("default_inout_pin_rise_res", - &LibertyReader::visitDefaultInoutPinRiseRes); - defineAttrVisitor("default_inout_pin_fall_res", - &LibertyReader::visitDefaultInoutPinFallRes); - defineAttrVisitor("default_output_pin_rise_res", - &LibertyReader::visitDefaultOutputPinRiseRes); - defineAttrVisitor("default_output_pin_fall_res", - &LibertyReader::visitDefaultOutputPinFallRes); - defineAttrVisitor("default_fanout_load", - &LibertyReader::visitDefaultFanoutLoad); - defineAttrVisitor("default_wire_load", - &LibertyReader::visitDefaultWireLoad); - defineAttrVisitor("default_wire_load_mode", - &LibertyReader::visitDefaultWireLoadMode); - defineAttrVisitor("default_wire_load_selection", - &LibertyReader::visitDefaultWireLoadSelection); - defineAttrVisitor("default_operating_conditions", - &LibertyReader::visitDefaultOperatingConditions); - defineAttrVisitor("input_threshold_pct_fall", - &LibertyReader::visitInputThresholdPctFall); - defineAttrVisitor("input_threshold_pct_rise", - &LibertyReader::visitInputThresholdPctRise); - defineAttrVisitor("output_threshold_pct_fall", - &LibertyReader::visitOutputThresholdPctFall); - defineAttrVisitor("output_threshold_pct_rise", - &LibertyReader::visitOutputThresholdPctRise); - defineAttrVisitor("slew_lower_threshold_pct_fall", - &LibertyReader::visitSlewLowerThresholdPctFall); - defineAttrVisitor("slew_lower_threshold_pct_rise", - &LibertyReader::visitSlewLowerThresholdPctRise); - defineAttrVisitor("slew_upper_threshold_pct_fall", - &LibertyReader::visitSlewUpperThresholdPctFall); - defineAttrVisitor("slew_upper_threshold_pct_rise", - &LibertyReader::visitSlewUpperThresholdPctRise); - defineAttrVisitor("slew_derate_from_library", - &LibertyReader::visitSlewDerateFromLibrary); - - defineGroupVisitor("lu_table_template", - &LibertyReader::beginTableTemplateDelay, - &LibertyReader::endTableTemplate); - defineGroupVisitor("output_current_template", - &LibertyReader::beginTableTemplateOutputCurrent, - &LibertyReader::endTableTemplate); - defineAttrVisitor("variable_1", &LibertyReader::visitVariable1); - defineAttrVisitor("variable_2", &LibertyReader::visitVariable2); - defineAttrVisitor("variable_3", &LibertyReader::visitVariable3); - defineAttrVisitor("index_1", &LibertyReader::visitIndex1); - defineAttrVisitor("index_2", &LibertyReader::visitIndex2); - defineAttrVisitor("index_3", &LibertyReader::visitIndex3); - - defineGroupVisitor("technology", - &LibertyReader::beginTechnology, - &LibertyReader::endTechnology); - defineGroupVisitor("rise_transition_degradation", - &LibertyReader::beginRiseTransitionDegredation, - &LibertyReader::endRiseFallTransitionDegredation); - defineGroupVisitor("fall_transition_degradation", - &LibertyReader::beginFallTransitionDegredation, - &LibertyReader::endRiseFallTransitionDegredation); - - defineGroupVisitor("type", &LibertyReader::beginType, - &LibertyReader::endType); - defineAttrVisitor("bit_from", &LibertyReader::visitBitFrom); - defineAttrVisitor("bit_to", &LibertyReader::visitBitTo); - - defineGroupVisitor("scaling_factors", &LibertyReader::beginScalingFactors, - &LibertyReader::endScalingFactors); - defineScalingFactorVisitors(); - - defineGroupVisitor("operating_conditions", &LibertyReader::beginOpCond, - &LibertyReader::endOpCond); - defineAttrVisitor("process", &LibertyReader::visitProc); - defineAttrVisitor("voltage", &LibertyReader::visitVolt); - defineAttrVisitor("temperature", &LibertyReader::visitTemp); - defineAttrVisitor("tree_type", &LibertyReader::visitTreeType); - - defineGroupVisitor("wire_load", &LibertyReader::beginWireload, - &LibertyReader::endWireload); - defineAttrVisitor("resistance", &LibertyReader::visitResistance); - defineAttrVisitor("slope", &LibertyReader::visitSlope); - defineAttrVisitor("fanout_length", &LibertyReader::visitFanoutLength); - - defineGroupVisitor("wire_load_selection", - &LibertyReader::beginWireloadSelection, - &LibertyReader::endWireloadSelection); - defineAttrVisitor("wire_load_from_area", - &LibertyReader::visitWireloadFromArea); - - // Cells - defineGroupVisitor("cell", &LibertyReader::beginCell, - &LibertyReader::endCell); - defineGroupVisitor("scaled_cell", &LibertyReader::beginScaledCell, - &LibertyReader::endScaledCell); - defineAttrVisitor("clock_gating_integrated_cell", - &LibertyReader::visitClockGatingIntegratedCell); - defineAttrVisitor("area", &LibertyReader::visitArea); - defineAttrVisitor("dont_use", &LibertyReader::visitDontUse); - defineAttrVisitor("is_macro_cell", &LibertyReader::visitIsMacro); - defineAttrVisitor("is_memory", &LibertyReader::visitIsMemory); - defineAttrVisitor("pad_cell", &LibertyReader::visitIsPadCell); - defineAttrVisitor("is_pad", &LibertyReader::visitIsPad); - defineAttrVisitor("is_clock_cell", &LibertyReader::visitIsClockCell); - defineAttrVisitor("is_level_shifter", &LibertyReader::visitIsLevelShifter); - defineAttrVisitor("level_shifter_type", &LibertyReader::visitLevelShifterType); - defineAttrVisitor("is_isolation_cell", &LibertyReader::visitIsIsolationCell); - defineAttrVisitor("always_on", &LibertyReader::visitAlwaysOn); - defineAttrVisitor("switch_cell_type", &LibertyReader::visitSwitchCellType); - defineAttrVisitor("interface_timing", &LibertyReader::visitInterfaceTiming); - defineAttrVisitor("scaling_factors", &LibertyReader::visitScalingFactors); - defineAttrVisitor("cell_footprint", &LibertyReader::visitCellFootprint); - defineAttrVisitor("user_function_class", - &LibertyReader::visitCellUserFunctionClass); - - // Pins - defineGroupVisitor("pin", &LibertyReader::beginPin,&LibertyReader::endPin); - defineGroupVisitor("bus", &LibertyReader::beginBus,&LibertyReader::endBus); - defineGroupVisitor("bundle", &LibertyReader::beginBundle, - &LibertyReader::endBundle); - defineAttrVisitor("direction", &LibertyReader::visitDirection); - defineAttrVisitor("clock", &LibertyReader::visitClock); - defineAttrVisitor("bus_type", &LibertyReader::visitBusType); - defineAttrVisitor("members", &LibertyReader::visitMembers); - defineAttrVisitor("function", &LibertyReader::visitFunction); - defineAttrVisitor("three_state", &LibertyReader::visitThreeState); - defineAttrVisitor("capacitance", &LibertyReader::visitCapacitance); - defineAttrVisitor("rise_capacitance", &LibertyReader::visitRiseCap); - defineAttrVisitor("fall_capacitance", &LibertyReader::visitFallCap); - defineAttrVisitor("rise_capacitance_range", - &LibertyReader::visitRiseCapRange); - defineAttrVisitor("fall_capacitance_range", - &LibertyReader::visitFallCapRange); - defineAttrVisitor("fanout_load", &LibertyReader::visitFanoutLoad); - defineAttrVisitor("max_fanout", &LibertyReader::visitMaxFanout); - defineAttrVisitor("min_fanout", &LibertyReader::visitMinFanout); - defineAttrVisitor("max_transition", &LibertyReader::visitMaxTransition); - defineAttrVisitor("min_transition", &LibertyReader::visitMinTransition); - defineAttrVisitor("max_capacitance", &LibertyReader::visitMaxCapacitance); - defineAttrVisitor("min_capacitance", &LibertyReader::visitMinCapacitance); - defineAttrVisitor("min_period", &LibertyReader::visitMinPeriod); - defineAttrVisitor("min_pulse_width_low", - &LibertyReader::visitMinPulseWidthLow); - defineAttrVisitor("min_pulse_width_high", - &LibertyReader::visitMinPulseWidthHigh); - defineAttrVisitor("pulse_clock", - &LibertyReader::visitPulseClock); - defineAttrVisitor("clock_gate_clock_pin", - &LibertyReader::visitClockGateClockPin); - defineAttrVisitor("clock_gate_enable_pin", - &LibertyReader::visitClockGateEnablePin); - defineAttrVisitor("clock_gate_out_pin", - &LibertyReader::visitClockGateOutPin); - defineAttrVisitor("is_pll_feedback_pin", - &LibertyReader::visitIsPllFeedbackPin); - defineAttrVisitor("signal_type", &LibertyReader::visitSignalType); - - defineAttrVisitor("isolation_cell_data_pin", - &LibertyReader::visitIsolationCellDataPin); - defineAttrVisitor("isolation_cell_enable_pin", - &LibertyReader::visitIsolationCellEnablePin); - defineAttrVisitor("level_shifter_data_pin", - &LibertyReader::visitLevelShifterDataPin); - defineAttrVisitor("switch_pin", &LibertyReader::visitSwitchPin); - - // Memory - defineGroupVisitor("memory", &LibertyReader::beginMemory, - &LibertyReader::endMemory); - - // Register/latch - defineGroupVisitor("ff", &LibertyReader::beginFF, &LibertyReader::endFF); - defineGroupVisitor("ff_bank", &LibertyReader::beginFFBank, - &LibertyReader::endFFBank); - defineGroupVisitor("latch", &LibertyReader::beginLatch, - &LibertyReader::endLatch); - defineGroupVisitor("latch_bank", &LibertyReader::beginLatchBank, - &LibertyReader::endLatchBank); - defineAttrVisitor("clocked_on", &LibertyReader::visitClockedOn); - defineAttrVisitor("enable", &LibertyReader::visitClockedOn); - defineAttrVisitor("data_in", &LibertyReader::visitDataIn); - defineAttrVisitor("next_state", &LibertyReader::visitDataIn); - defineAttrVisitor("clear", &LibertyReader::visitClear); - defineAttrVisitor("preset", &LibertyReader::visitPreset); - defineAttrVisitor("clear_preset_var1", &LibertyReader::visitClrPresetVar1); - defineAttrVisitor("clear_preset_var2", &LibertyReader::visitClrPresetVar2); - - // Statetable - defineGroupVisitor("statetable", &LibertyReader::beginStatetable, - &LibertyReader::endStatetable); - defineAttrVisitor("table", &LibertyReader::visitTable); - - defineGroupVisitor("timing", &LibertyReader::beginTiming, - &LibertyReader::endTiming); - defineAttrVisitor("related_pin", &LibertyReader::visitRelatedPin); - defineAttrVisitor("related_bus_pins", &LibertyReader::visitRelatedBusPins); - defineAttrVisitor("related_output_pin", - &LibertyReader::visitRelatedOutputPin); - defineAttrVisitor("timing_type", &LibertyReader::visitTimingType); - defineAttrVisitor("timing_sense", &LibertyReader::visitTimingSense); - defineAttrVisitor("sdf_cond_start", &LibertyReader::visitSdfCondStart); - defineAttrVisitor("sdf_cond_end", &LibertyReader::visitSdfCondEnd); - defineAttrVisitor("mode", &LibertyReader::visitMode); - defineAttrVisitor("intrinsic_rise", &LibertyReader::visitIntrinsicRise); - defineAttrVisitor("intrinsic_fall", &LibertyReader::visitIntrinsicFall); - defineAttrVisitor("rise_resistance", &LibertyReader::visitRiseResistance); - defineAttrVisitor("fall_resistance", &LibertyReader::visitFallResistance); - defineGroupVisitor("cell_rise", &LibertyReader::beginCellRise, - &LibertyReader::endCellRiseFall); - defineGroupVisitor("cell_fall", &LibertyReader::beginCellFall, - &LibertyReader::endCellRiseFall); - defineGroupVisitor("rise_transition", &LibertyReader::beginRiseTransition, - &LibertyReader::endRiseFallTransition); - defineGroupVisitor("fall_transition", &LibertyReader::beginFallTransition, - &LibertyReader::endRiseFallTransition); - defineGroupVisitor("rise_constraint", &LibertyReader::beginRiseConstraint, - &LibertyReader::endRiseFallConstraint); - defineGroupVisitor("fall_constraint", &LibertyReader::beginFallConstraint, - &LibertyReader::endRiseFallConstraint); - defineAttrVisitor("value", &LibertyReader::visitValue); - defineAttrVisitor("values", &LibertyReader::visitValues); - - defineGroupVisitor("lut", &LibertyReader::beginLut,&LibertyReader::endLut); - - defineGroupVisitor("test_cell", &LibertyReader::beginTestCell, - &LibertyReader::endTestCell); - - defineGroupVisitor("mode_definition", &LibertyReader::beginModeDef, - &LibertyReader::endModeDef); - defineGroupVisitor("mode_value", &LibertyReader::beginModeValue, - &LibertyReader::endModeValue); - defineAttrVisitor("when", &LibertyReader::visitWhen); - defineAttrVisitor("sdf_cond", &LibertyReader::visitSdfCond); - - // Power attributes. - defineGroupVisitor("power_lut_template", - &LibertyReader::beginTableTemplatePower, - &LibertyReader::endTableTemplate); - defineGroupVisitor("leakage_power", &LibertyReader::beginLeakagePower, - &LibertyReader::endLeakagePower); - defineGroupVisitor("internal_power", &LibertyReader::beginInternalPower, - &LibertyReader::endInternalPower); - // power group for both rise/fall - defineGroupVisitor("power", &LibertyReader::beginRisePower, - &LibertyReader::endPower); - defineGroupVisitor("fall_power", &LibertyReader::beginFallPower, - &LibertyReader::endRiseFallPower); - defineGroupVisitor("rise_power", &LibertyReader::beginRisePower, - &LibertyReader::endRiseFallPower); - defineAttrVisitor("related_ground_pin",&LibertyReader::visitRelatedGroundPin); - defineAttrVisitor("related_power_pin", &LibertyReader::visitRelatedPowerPin); - defineAttrVisitor("related_pg_pin", &LibertyReader::visitRelatedPgPin); - - // AOCV attributes. - defineAttrVisitor("ocv_arc_depth", &LibertyReader::visitOcvArcDepth); - defineAttrVisitor("default_ocv_derate_group", - &LibertyReader::visitDefaultOcvDerateGroup); - defineAttrVisitor("ocv_derate_group", &LibertyReader::visitOcvDerateGroup); - defineGroupVisitor("ocv_table_template", - &LibertyReader::beginTableTemplateOcv, - &LibertyReader::endTableTemplate); - defineGroupVisitor("ocv_derate", - &LibertyReader::beginOcvDerate, - &LibertyReader::endOcvDerate); - defineGroupVisitor("ocv_derate_factors", - &LibertyReader::beginOcvDerateFactors, - &LibertyReader::endOcvDerateFactors); - defineAttrVisitor("rf_type", &LibertyReader::visitRfType); - defineAttrVisitor("derate_type", &LibertyReader::visitDerateType); - defineAttrVisitor("path_type", &LibertyReader::visitPathType); - - // POCV attributes. - defineGroupVisitor("ocv_sigma_cell_rise", &LibertyReader::beginOcvSigmaCellRise, - &LibertyReader::endOcvSigmaCell); - defineGroupVisitor("ocv_sigma_cell_fall", &LibertyReader::beginOcvSigmaCellFall, - &LibertyReader::endOcvSigmaCell); - defineGroupVisitor("ocv_sigma_rise_transition", - &LibertyReader::beginOcvSigmaRiseTransition, - &LibertyReader::endOcvSigmaTransition); - defineGroupVisitor("ocv_sigma_fall_transition", - &LibertyReader::beginOcvSigmaFallTransition, - &LibertyReader::endOcvSigmaTransition); - defineGroupVisitor("ocv_sigma_rise_constraint", - &LibertyReader::beginOcvSigmaRiseConstraint, - &LibertyReader::endOcvSigmaConstraint); - defineGroupVisitor("ocv_sigma_fall_constraint", - &LibertyReader::beginOcvSigmaFallConstraint, - &LibertyReader::endOcvSigmaConstraint); - defineAttrVisitor("sigma_type", &LibertyReader::visitSigmaType); - defineAttrVisitor("cell_leakage_power", &LibertyReader::visitCellLeakagePower); - - defineGroupVisitor("pg_pin", &LibertyReader::beginPgPin, - &LibertyReader::endPgPin); - defineAttrVisitor("pg_type", &LibertyReader::visitPgType); - defineAttrVisitor("voltage_name", &LibertyReader::visitVoltageName); - - // ccs receiver capacitance - defineGroupVisitor("receiver_capacitance", - &LibertyReader::beginReceiverCapacitance, - &LibertyReader::endReceiverCapacitance); - - defineGroupVisitor("receiver_capacitance_rise", - &LibertyReader::beginReceiverCapacitance1Rise, - &LibertyReader::endReceiverCapacitanceRiseFall); - defineGroupVisitor("receiver_capacitance_fall", - &LibertyReader::beginReceiverCapacitance1Fall, - &LibertyReader::endReceiverCapacitanceRiseFall); - defineAttrVisitor("segment", &LibertyReader::visitSegement); - - defineGroupVisitor("receiver_capacitance1_rise", - &LibertyReader::beginReceiverCapacitance1Rise, - &LibertyReader::endReceiverCapacitanceRiseFall); - defineGroupVisitor("receiver_capacitance1_fall", - &LibertyReader::beginReceiverCapacitance1Fall, - &LibertyReader::endReceiverCapacitanceRiseFall); - defineGroupVisitor("receiver_capacitance2_rise", - &LibertyReader::beginReceiverCapacitance2Rise, - &LibertyReader::endReceiverCapacitanceRiseFall); - defineGroupVisitor("receiver_capacitance2_fall", - &LibertyReader::beginReceiverCapacitance2Fall, - &LibertyReader::endReceiverCapacitanceRiseFall); - // ccs - defineGroupVisitor("output_current_rise", - &LibertyReader::beginOutputCurrentRise, - &LibertyReader::endOutputCurrentRiseFall); - defineGroupVisitor("output_current_fall", - &LibertyReader::beginOutputCurrentFall, - &LibertyReader::endOutputCurrentRiseFall); - defineGroupVisitor("vector", &LibertyReader::beginVector, &LibertyReader::endVector); - defineAttrVisitor("reference_time", &LibertyReader::visitReferenceTime); - defineGroupVisitor("normalized_driver_waveform", - &LibertyReader::beginNormalizedDriverWaveform, - &LibertyReader::endNormalizedDriverWaveform); - defineAttrVisitor("driver_waveform_name", &LibertyReader::visitDriverWaveformName); - defineAttrVisitor("driver_waveform_rise", &LibertyReader::visitDriverWaveformRise); - defineAttrVisitor("driver_waveform_fall", &LibertyReader::visitDriverWaveformFall); - - // ccsn (not implemented, this is needed to properly ignore ccsn groups) - defineGroupVisitor("ccsn_first_stage", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - defineGroupVisitor("ccsn_last_stage", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - defineGroupVisitor("output_voltage_rise", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - defineGroupVisitor("output_voltage_fall", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - defineGroupVisitor("propagated_noise_low", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - defineGroupVisitor("propagated_noise_high", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - defineGroupVisitor("input_ccb", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - defineGroupVisitor("output_ccb", &LibertyReader::beginCcsn, - &LibertyReader::endCcsn); - - defineGroupVisitor("ecsm_waveform", &LibertyReader::beginEcsmWaveform, - &LibertyReader::endEcsmWaveform); - defineGroupVisitor("ecsm_waveform_set", &LibertyReader::beginEcsmWaveform, - &LibertyReader::endEcsmWaveform); - defineGroupVisitor("ecsm_capacitance", &LibertyReader::beginEcsmWaveform, - &LibertyReader::endEcsmWaveform); + defineGroupVisitor("cell", nullptr, &LibertyReader::endCell); + defineGroupVisitor("scaled_cell", nullptr, &LibertyReader::endScaledCell); } void -LibertyReader::defineScalingFactorVisitors() +LibertyReader::visitAttr(const LibertySimpleAttr *) { - for (int type_index = 0; type_index < scale_factor_type_count; type_index++) { - ScaleFactorType type = static_cast(type_index); - const char *type_name = scaleFactorTypeName(type); - for (int pvt_index = 0; pvt_index < scale_factor_pvt_count; pvt_index++) { - ScaleFactorPvt pvt = static_cast(pvt_index); - const char *pvt_name = scaleFactorPvtName(pvt); - if (scaleFactorTypeRiseFallSuffix(type)) { - for (auto tr : RiseFall::range()) { - const char *tr_name = (tr == RiseFall::rise()) ? "rise":"fall"; - string attr_name; - stringPrint(attr_name, "k_%s_%s_%s", - pvt_name, - type_name, - tr_name); - defineAttrVisitor(attr_name.c_str() ,&LibertyReader::visitScaleFactorSuffix); - } - } - else if (scaleFactorTypeRiseFallPrefix(type)) { - for (auto tr : RiseFall::range()) { - const char *tr_name = (tr == RiseFall::rise()) ? "rise":"fall"; - string attr_name; - stringPrint(attr_name, "k_%s_%s_%s", - pvt_name, - tr_name, - type_name); - defineAttrVisitor(attr_name.c_str(),&LibertyReader::visitScaleFactorPrefix); - } - } - else if (scaleFactorTypeLowHighSuffix(type)) { - for (auto tr : RiseFall::range()) { - const char *tr_name = (tr == RiseFall::rise()) ? "high":"low"; - string attr_name; - stringPrint(attr_name, "k_%s_%s_%s", - pvt_name, - type_name, - tr_name); - defineAttrVisitor(attr_name.c_str(),&LibertyReader::visitScaleFactorHiLow); - } - } - else { - string attr_name; - stringPrint(attr_name, "k_%s_%s", - pvt_name, - type_name); - defineAttrVisitor(attr_name.c_str(),&LibertyReader::visitScaleFactor); - } - } - } } void -LibertyReader::visitAttr(LibertyAttr *attr) +LibertyReader::visitAttr(const LibertyComplexAttr *) { - LibraryAttrVisitor *visitor = findKeyValuePtr(attr_visitor_map_, attr->name()); - if (visitor) - (this->**visitor)(attr); } void -LibertyReader::begin(LibertyGroup *group) +LibertyReader::begin(const LibertyGroup *group, + LibertyGroup *parent_group) { LibraryGroupVisitor *visitor = findKeyValuePtr(group_begin_map_, group->type()); if (visitor) - (this->**visitor)(group); + (this->**visitor)(group, parent_group); } void -LibertyReader::end(LibertyGroup *group) +LibertyReader::end(const LibertyGroup *group, + LibertyGroup *parent_group) { LibraryGroupVisitor *visitor = findKeyValuePtr(group_end_map_, group->type()); if (visitor) - (this->**visitor)(group); + (this->**visitor)(group, parent_group); } void -LibertyReader::beginLibrary(LibertyGroup *group) +LibertyReader::beginLibrary(const LibertyGroup *library_group, + LibertyGroup *) { - const char *name = group->firstName(); + makeLibrary(library_group); +} + +void +LibertyReader::endLibrary(const LibertyGroup *group, + LibertyGroup *) +{ + // If a library hasno cells endCell is not called. + if (first_cell_) + readLibraryAttributes(group); + delete group; +} + +//////////////////////////////////////////////////////////////// + +void +LibertyReader::endCell(const LibertyGroup *cell_group, + LibertyGroup *library_group) +{ + // Read library groups defined since the last cell was read. + // Normally they are all defined by the first cell, but there + // are libraries that define table templates and bus tyupes + // between cells. + if (first_cell_) + readLibraryAttributes(library_group); + else { + readTableTemplates(library_group); + readBusTypes(nullptr, library_group); + } + + const char *name = cell_group->firstName(); + if (name) { + debugPrint(debug_, "liberty", 1, "cell %s", name); + LibertyCell *cell = builder_.makeCell(library_, name, filename_); + readCell(cell, cell_group); + } + else + libWarn(1193, cell_group, "cell missing name."); + library_group->clear(); + first_cell_ = false; +} + +void +LibertyReader::endScaledCell(const LibertyGroup *scaled_cell_group, + LibertyGroup *library_group) +{ + readLibraryAttributes(library_group); + readScaledCell(scaled_cell_group); + library_group->deleteSubgroup(scaled_cell_group); +} + +//////////////////////////////////////////////////////////////// + +void +LibertyReader::readLibraryAttributes(const LibertyGroup *library_group) +{ + readTechnology(library_group); + readLibraryUnits(library_group); + readThresholds(library_group); + readDelayModel(library_group); + readBusStyle(library_group); + readBusTypes(nullptr, library_group); + readTableTemplates(library_group); + readVoltateMaps(library_group); + readWireloads(library_group); + readWireloadSelection(library_group); + readDefaultWireLoad(library_group); + readDefaultWireLoadMode(library_group); + readDefaultWireLoadSelection(library_group); + readOperatingConds(library_group); + readScaleFactors(library_group); + readOcvDerateFactors(nullptr, library_group); + readDefaultOcvDerateGroup(library_group); + readGroupAttrFloat("ocv_arc_depth", library_group, + [this](float v) { library_->setOcvArcDepth(v); }); + readNormalizedDriverWaveform(library_group); + readSlewDegradations(library_group); + + readLibAttrFloat(library_group, "nom_temperature", + &LibertyLibrary::setNominalTemperature, 1.0F); + readLibAttrFloat(library_group, "nom_voltage", &LibertyLibrary::setNominalVoltage, + volt_scale_); + readLibAttrFloat(library_group, "nom_process", + &LibertyLibrary::setNominalProcess, 1.0F); + readLibAttrFloat(library_group, "default_inout_pin_cap", + &LibertyLibrary::setDefaultBidirectPinCap, cap_scale_); + readLibAttrFloat(library_group, "default_input_pin_cap", + &LibertyLibrary::setDefaultInputPinCap, cap_scale_); + readLibAttrFloat(library_group, "default_output_pin_cap", + &LibertyLibrary::setDefaultOutputPinCap, cap_scale_); + readLibAttrFloatWarnZero(library_group, "default_max_transition", + &LibertyLibrary::setDefaultMaxSlew, time_scale_); + readLibAttrFloatWarnZero(library_group, "default_max_fanout", + &LibertyLibrary::setDefaultMaxFanout, 1.0F); + readLibAttrFloat(library_group, "default_intrinsic_rise", + &LibertyLibrary::setDefaultIntrinsic, RiseFall::rise(), + time_scale_); + readLibAttrFloat(library_group, "default_intrinsic_fall", + &LibertyLibrary::setDefaultIntrinsic, RiseFall::fall(), + time_scale_); + readLibAttrFloat(library_group, "default_inout_pin_rise_res", + &LibertyLibrary::setDefaultBidirectPinRes, RiseFall::rise(), + res_scale_); + readLibAttrFloat(library_group, "default_inout_pin_fall_res", + &LibertyLibrary::setDefaultBidirectPinRes, RiseFall::fall(), + res_scale_); + readLibAttrFloat(library_group, "default_output_pin_rise_res", + &LibertyLibrary::setDefaultOutputPinRes, RiseFall::rise(), + res_scale_); + readLibAttrFloat(library_group, "default_output_pin_fall_res", + &LibertyLibrary::setDefaultOutputPinRes, RiseFall::fall(), + res_scale_); + readLibAttrFloatWarnZero(library_group, "default_fanout_load", + &LibertyLibrary::setDefaultFanoutLoad, 1.0F); + readLibAttrFloat(library_group, "slew_derate_from_library", + &LibertyLibrary::setSlewDerateFromLibrary, 1.0F); +} + +void +LibertyReader::makeLibrary(const LibertyGroup *libary_group) +{ + const char *name = libary_group->firstName(); if (name) { LibertyLibrary *library = network_->findLiberty(name); if (library) - libWarn(1140, group, "library %s already exists.", name); + libWarn(1140, libary_group, "library %s already exists.", name); // Make a new library even if a library with the same name exists. // Both libraries may be accessed by min/max analysis points. library_ = network_->makeLibertyLibrary(name, filename_); @@ -664,8 +286,6 @@ LibertyReader::beginLibrary(LibertyGroup *group) current_scale_ = 1E-3F; // Default is 1; power_scale_ = 1; - // Default is fJ. - setEnergyScale(); // Default is 1 micron. distance_scale_ = 1e-6; @@ -677,802 +297,326 @@ LibertyReader::beginLibrary(LibertyGroup *group) library_->units()->distanceUnit()->setScale(distance_scale_); library_->setDelayModelType(DelayModelType::cmos_linear); - scale_factors_ = new ScaleFactors(""); - library_->setScaleFactors(scale_factors_); } else - libError(1141, group, "library missing name."); + libError(1141, libary_group, "library missing name."); } -// Energy scale is derived. -void -LibertyReader::setEnergyScale() +// Energy scale is derived from other units. +float +LibertyReader::energyScale() { - energy_scale_ = volt_scale_ * volt_scale_ * cap_scale_; + return volt_scale_ * volt_scale_ * cap_scale_; } void -LibertyReader::endLibrary(LibertyGroup *group) +LibertyReader::readTechnology(const LibertyGroup *library_group) { - endLibraryAttrs(group); -} - -void -LibertyReader::endLibraryAttrs(LibertyGroup *group) -{ - // These attributes reference named groups in the library so - // wait until the end of the library to resolve them. - if (default_wireload_) { - const Wireload *wireload = library_->findWireload(default_wireload_); - if (wireload) - library_->setDefaultWireload(wireload); - else - libWarn(1142, group, "default_wire_load %s not found.", default_wireload_); - stringDelete(default_wireload_); - default_wireload_ = nullptr; - } - - if (default_wireload_selection_) { - const WireloadSelection *selection = - library_->findWireloadSelection(default_wireload_selection_); - if (selection) - library_->setDefaultWireloadSelection(selection); - else - libWarn(1143, group, "default_wire_selection %s not found.", - default_wireload_selection_); - stringDelete(default_wireload_selection_); - default_wireload_selection_ = nullptr; - } - - if (default_operating_condition_) { - OperatingConditions *op_cond = - library_->findOperatingConditions(default_operating_condition_); - if (op_cond) - library_->setDefaultOperatingConditions(op_cond); - else - libWarn(1144, group, "default_operating_condition %s not found.", - default_operating_condition_); - stringDelete(default_operating_condition_); - default_operating_condition_ = nullptr; - } - - bool missing_threshold = false; - for (auto rf : RiseFall::range()) { - int rf_index = rf->index(); - if (!have_input_threshold_[rf_index]) { - libWarn(1145, group, "input_threshold_pct_%s not found.", rf->name()); - missing_threshold = true; - } - if (!have_output_threshold_[rf_index]) { - libWarn(1146, group, "output_threshold_pct_%s not found.", rf->name()); - missing_threshold = true; - } - if (!have_slew_lower_threshold_[rf_index]) { - libWarn(1147, group, "slew_lower_threshold_pct_%s not found.", rf->name()); - missing_threshold = true; - } - if (!have_slew_upper_threshold_[rf_index]) { - libWarn(1148, group, "slew_upper_threshold_pct_%s not found.", rf->name()); - missing_threshold = true; + const LibertyComplexAttr *tech_attr = library_group->findComplexAttr("technology"); + if (tech_attr) { + const LibertyAttrValue *tech_value = tech_attr->firstValue(); + if (tech_value) { + const std::string &tech = tech_value->stringValue(); + if (tech == "fpga") + library_->setDelayModelType(DelayModelType::cmos_linear); } } - if (missing_threshold) - libError(1149, group, "Library %s is missing one or more thresholds.", - library_->name()); } void -LibertyReader::visitTimeUnit(LibertyAttr *attr) +LibertyReader::readLibraryUnits(const LibertyGroup *library_group) { - if (library_) - parseUnits(attr, "s", time_scale_, library_->units()->timeUnit()); -} + readUnit("time_unit", "s", time_scale_, library_->units()->timeUnit(), library_group); + readUnit("pulling_resistance_unit", "ohm", res_scale_, + library_->units()->resistanceUnit(), library_group); + readUnit("voltage_unit", "V", volt_scale_, library_->units()->voltageUnit(), + library_group); + readUnit("current_unit", "A", current_scale_, library_->units()->currentUnit(), + library_group); + readUnit("leakage_power_unit", "W", power_scale_, library_->units()->powerUnit(), + library_group); + readUnit("distance_unit", "m", distance_scale_, library_->units()->distanceUnit(), + library_group); -void -LibertyReader::visitPullingResistanceUnit(LibertyAttr *attr) -{ - if (library_) - parseUnits(attr, "ohm", res_scale_, - library_->units()->resistanceUnit()); -} - -void -LibertyReader::visitResistanceUnit(LibertyAttr *attr) -{ - if (library_) - parseUnits(attr, "ohm", res_scale_, library_->units()->resistanceUnit()); -} - -void -LibertyReader::visitCurrentUnit(LibertyAttr *attr) -{ - if (library_) - parseUnits(attr, "A", current_scale_, library_->units()->currentUnit()); -} - -void -LibertyReader::visitVoltageUnit(LibertyAttr *attr) -{ - if (library_) - parseUnits(attr, "V", volt_scale_, library_->units()->voltageUnit()); - setEnergyScale(); -} - -void -LibertyReader::visitPowerUnit(LibertyAttr *attr) -{ - if (library_) - parseUnits(attr, "W", power_scale_, library_->units()->powerUnit()); -} - -void -LibertyReader::visitDistanceUnit(LibertyAttr *attr) -{ - if (library_) - parseUnits(attr, "m", distance_scale_, library_->units()->distanceUnit()); -} - -void -LibertyReader::parseUnits(LibertyAttr *attr, - const char *unit_suffix, - float &scale_var, - Unit *unit) -{ - const char *units = getAttrString(attr); - if (units) { - // Unit format is . - // Find the multiplier digits. - string units1 = units; - size_t mult_end = units1.find_first_not_of("0123456789"); - float mult = 1.0F; - string scale_suffix; - if (mult_end != units1.npos) { - string unit_mult = units1.substr(0, mult_end); - scale_suffix = units1.substr(mult_end); - if (unit_mult == "1") - mult = 1.0F; - else if (unit_mult == "10") - mult = 10.0F; - else if (unit_mult == "100") - mult = 100.0F; - else - libWarn(1150, attr, "unknown unit multiplier %s.", unit_mult.c_str()); - } - else - scale_suffix = units; - - float scale_mult = 1.0F; - if (scale_suffix.size() == strlen(unit_suffix) + 1) { - string suffix = scale_suffix.substr(1); - if (stringEqual(suffix.c_str(), unit_suffix)) { - char scale_char = tolower(scale_suffix[0]); - if (scale_char == 'k') - scale_mult = 1E+3F; - else if (scale_char == 'm') - scale_mult = 1E-3F; - else if (scale_char == 'u') - scale_mult = 1E-6F; - else if (scale_char == 'n') - scale_mult = 1E-9F; - else if (scale_char == 'p') - scale_mult = 1E-12F; - else if (scale_char == 'f') - scale_mult = 1E-15F; - else - libWarn(1151, attr, "unknown unit scale %c.", scale_char); + const LibertyComplexAttr *cap_attr = + library_group->findComplexAttr("capacitive_load_unit"); + if (cap_attr) { + const LibertyAttrValueSeq &values = cap_attr->values(); + if (values.size() == 2) { + LibertyAttrValue *value = values[0]; + bool valid = false; + float scale; + if (value->isFloat()) { + scale = value->floatValue(); + valid = true; } - else - libWarn(1152, attr, "unknown unit suffix %s.", suffix.c_str()); - } - else if (!stringEqual(scale_suffix.c_str(), unit_suffix)) - libWarn(1153, attr, "unknown unit suffix %s.", scale_suffix.c_str()); - scale_var = scale_mult * mult; - unit->setScale(scale_var); - } -} - -void -LibertyReader::visitCapacitiveLoadUnit(LibertyAttr *attr) -{ - if (library_) { - if (attr->isComplexAttr()) { - LibertyAttrValueSeq *values = attr->values(); - if (values->size() == 2) { - LibertyAttrValue *value = (*values)[0]; - bool valid = false; - float scale; - if (value->isFloat()) { - scale = value->floatValue(); + else if (value->isString()) { + try { + scale = std::stof(value->stringValue()); valid = true; } - else if (value->isString()) { - try { - scale = std::stof(value->stringValue()); - valid = true; - } - catch (...) { - valid = false; - } + catch (...) { + valid = false; } + } - if (valid) { - value = (*values)[1]; - if (value->isString()) { - const std::string suffix = value->stringValue(); - if (stringEqual(suffix.c_str(), "ff")) - cap_scale_ = scale * 1E-15F; - else if (stringEqual(suffix.c_str(), "pf")) - cap_scale_ = scale * 1E-12F; - else - libWarn(1154, attr, "capacitive_load_units are not ff or pf."); - } - else - libWarn(1155, attr, "capacitive_load_units are not a string."); - } - else - libWarn(1157, attr, "capacitive_load_units scale is not a float."); - } - else if (values->size() == 1) - libWarn(1156, attr, "capacitive_load_units missing suffix."); - else - libWarn(1158, attr, "capacitive_load_units missing scale and suffix."); - } - else - libWarn(1159, attr, "capacitive_load_unit missing values suffix."); - library_->units()->capacitanceUnit()->setScale(cap_scale_); - setEnergyScale(); - } -} - -void -LibertyReader::visitDelayModel(LibertyAttr *attr) -{ - if (library_) { - const char *type_name = getAttrString(attr); - if (type_name) { - if (stringEq(type_name, "table_lookup")) - library_->setDelayModelType(DelayModelType::table); - else if (stringEq(type_name, "generic_cmos")) - library_->setDelayModelType(DelayModelType::cmos_linear); - else if (stringEq(type_name, "piecewise_cmos")) { - library_->setDelayModelType(DelayModelType::cmos_pwl); - libWarn(1160, attr, "delay_model %s not supported.", type_name); - } - else if (stringEq(type_name, "cmos2")) { - library_->setDelayModelType(DelayModelType::cmos2); - libWarn(1161, attr, "delay_model %s not supported.", type_name); - } - else if (stringEq(type_name, "polynomial")) { - library_->setDelayModelType(DelayModelType::polynomial); - libWarn(1162, attr, "delay_model %s not supported.", type_name); - } - // Evil IBM garbage. - else if (stringEq(type_name, "dcm")) { - library_->setDelayModelType(DelayModelType::dcm); - libWarn(1163, attr, "delay_model %s not supported..", type_name); - } - else - libWarn(1164, attr, "unknown delay_model %s.", type_name); - } - } -} - -void -LibertyReader::visitBusStyle(LibertyAttr *attr) -{ - if (library_) { - const char *bus_style = getAttrString(attr); - // Assume bus style is of the form "%s[%d]". - if (bus_style - && strlen(bus_style) == 6 - && bus_style[0] == '%' - && bus_style[1] == 's' - && bus_style[3] == '%' - && bus_style[4] == 'd') - library_->setBusBrkts(bus_style[2], bus_style[5]); - else - libWarn(1165, attr, "unknown bus_naming_style format."); - } -} - -void -LibertyReader::visitVoltageMap(LibertyAttr *attr) -{ - if (library_) { - if (attr->isComplexAttr()) { - LibertyAttrValueSeq *values = attr->values(); - if (values->size() >= 1) { - LibertyAttrValue *value = (*values)[0]; + if (valid) { + value = values[1]; if (value->isString()) { - const std::string &supply_name = value->stringValue(); - if (values->size() == 2) { - value = (*values)[1]; - bool valid = false; - float voltage; - if (value->isFloat()) { - voltage = value->floatValue(); - valid = true; - } - else if (value->isString()) { - try { - voltage = std::stof(value->stringValue()); - valid = true; - } - catch (...) { - valid = false; - } - } - - if (valid) - library_->addSupplyVoltage(supply_name.c_str(), voltage); - else - libWarn(1166, attr, "voltage_map voltage is not a float."); - } + const std::string suffix = value->stringValue(); + if (stringEqual(suffix.c_str(), "ff")) + cap_scale_ = scale * 1E-15F; + else if (stringEqual(suffix.c_str(), "pf")) + cap_scale_ = scale * 1E-12F; else - libWarn(1167, attr, "voltage_map missing voltage."); + libWarn(1154, cap_attr, "capacitive_load_units are not ff or pf."); } else - libWarn(1168, attr, "voltage_map supply name is not a string."); + libWarn(1155, cap_attr, "capacitive_load_units are not a string."); } else - libWarn(1169, attr, "voltage_map missing supply name and voltage."); + libWarn(1157, cap_attr, "capacitive_load_units scale is not a float."); + } + else if (values.size() == 1) + libWarn(1156, cap_attr, "capacitive_load_units missing suffix."); + else + libWarn(1158, cap_attr, "capacitive_load_units missing scale and suffix."); + library_->units()->capacitanceUnit()->setScale(cap_scale_); + } +} + +void +LibertyReader::readUnit(const char *unit_attr_name, + const char *unit_suffix, + float &scale_var, + Unit *unit, + const LibertyGroup *library_group) +{ + const LibertySimpleAttr *unit_attr = library_group->findSimpleAttr(unit_attr_name); + if (unit_attr) { + const std::string *units = unit_attr->stringValue(); + if (units) { + // Unit format is . + // Find the multiplier digits. + std::string units1 = *units; + size_t mult_end = units1.find_first_not_of("0123456789"); + float mult = 1.0F; + std::string scale_suffix; + if (mult_end != units1.npos) { + std::string unit_mult = units1.substr(0, mult_end); + scale_suffix = units1.substr(mult_end); + if (unit_mult == "1") + mult = 1.0F; + else if (unit_mult == "10") + mult = 10.0F; + else if (unit_mult == "100") + mult = 100.0F; + else + libWarn(1150, unit_attr, "unknown unit multiplier %s.", unit_mult.c_str()); + } + else + scale_suffix = *units; + + float scale_mult = 1.0F; + if (scale_suffix.size() == strlen(unit_suffix) + 1) { + std::string suffix = scale_suffix.substr(1); + if (stringEqual(suffix.c_str(), unit_suffix)) { + char scale_char = tolower(scale_suffix[0]); + if (scale_char == 'k') + scale_mult = 1E+3F; + else if (scale_char == 'm') + scale_mult = 1E-3F; + else if (scale_char == 'u') + scale_mult = 1E-6F; + else if (scale_char == 'n') + scale_mult = 1E-9F; + else if (scale_char == 'p') + scale_mult = 1E-12F; + else if (scale_char == 'f') + scale_mult = 1E-15F; + else + libWarn(1151, unit_attr, "unknown unit scale %c.", scale_char); + } + else + libWarn(1152, unit_attr, "unknown unit suffix %s.", suffix.c_str()); + } + else if (!stringEqual(scale_suffix.c_str(), unit_suffix)) + libWarn(1153, unit_attr, "unknown unit suffix %s.", scale_suffix.c_str()); + scale_var = scale_mult * mult; + unit->setScale(scale_var); + } + } +} + +void +LibertyReader::readDelayModel(const LibertyGroup *library_group) +{ + const std::string *type_name = library_group->findAttrString("delay_model"); + if (type_name) { + if (*type_name == "table_lookup") + library_->setDelayModelType(DelayModelType::table); + else if (*type_name == "generic_cmos") + library_->setDelayModelType(DelayModelType::cmos_linear); + else if (*type_name == "piecewise_cmos") { + library_->setDelayModelType(DelayModelType::cmos_pwl); + libWarn(1160, library_group, "delay_model %s not supported.", type_name->c_str()); + } + else if (*type_name == "cmos2") { + library_->setDelayModelType(DelayModelType::cmos2); + libWarn(1161, library_group, "delay_model %s not supported.", type_name->c_str()); + } + else if (*type_name == "polynomial") { + library_->setDelayModelType(DelayModelType::polynomial); + libWarn(1162, library_group, "delay_model %s not supported.", type_name->c_str()); + } + // Evil IBM garbage. + else if (*type_name == "dcm") { + library_->setDelayModelType(DelayModelType::dcm); + libWarn(1163, library_group, "delay_model %s not supported..", type_name->c_str()); } else - libWarn(1170, attr, "voltage_map missing values suffix."); + libWarn(1164, library_group, "unknown delay_model %s.", type_name->c_str()); } } void -LibertyReader::visitNomTemp(LibertyAttr *attr) +LibertyReader::readBusStyle(const LibertyGroup *library_group) { - if (library_) { - float value; - bool valid; - getAttrFloat(attr, value, valid); - if (valid) - library_->setNominalTemperature(value); + const std::string *bus_style = library_group->findAttrString("bus_naming_style"); + if (bus_style) { + // Assume bus style is of the form "%s[%d]". + if (bus_style->size() == 6 + && (*bus_style)[0] == '%' + && (*bus_style)[1] == 's' + && (*bus_style)[3] == '%' + && (*bus_style)[4] == 'd') + library_->setBusBrkts((*bus_style)[2], (*bus_style)[5]); + else + libWarn(1165, library_group, "unknown bus_naming_style format."); } } void -LibertyReader::visitNomProc(LibertyAttr *attr) +LibertyReader::readBusTypes(LibertyCell *cell, + const LibertyGroup *group) { - if (library_) { - float value; - bool valid; - getAttrFloat(attr, value, valid); - if (valid) - library_->setNominalProcess(value); - } -} - -void -LibertyReader::visitNomVolt(LibertyAttr *attr) -{ - if (library_) { - float value; - bool valid; - getAttrFloat(attr, value, valid); - if (valid) - library_->setNominalVoltage(value); - } -} - -void -LibertyReader::visitDefaultInoutPinCap(LibertyAttr *attr) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setDefaultBidirectPinCap(value * cap_scale_); - } -} - -void -LibertyReader::visitDefaultInputPinCap(LibertyAttr *attr) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setDefaultInputPinCap(value * cap_scale_); - } -} - -void -LibertyReader::visitDefaultOutputPinCap(LibertyAttr *attr) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setDefaultOutputPinCap(value * cap_scale_); - } -} - -void -LibertyReader::visitDefaultMaxTransition(LibertyAttr *attr) -{ - if (library_){ - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - if (value == 0.0) - libWarn(1171, attr, "default_max_transition is 0.0."); - library_->setDefaultMaxSlew(value * time_scale_); + for (const LibertyGroup *type_group : group->findSubgroups("type")) { + const char *name = type_group->firstName(); + if (name) { + int from, to; + bool from_exists, to_exists; + type_group->findAttrInt("bit_from", from, from_exists); + type_group->findAttrInt("bit_to", to, to_exists); + if (from_exists && to_exists) { + if (cell) + cell->makeBusDcl(name, from, to); + else + library_->makeBusDcl(name, from, to); + } + else if (!from_exists) + libWarn(1179, type_group, "bus type missing bit_from."); + else if (!to_exists) + libWarn(1180, type_group, "bus type missing bit_to."); } } } void -LibertyReader::visitDefaultMaxFanout(LibertyAttr *attr) +LibertyReader::readThresholds(const LibertyGroup *library_group) { - if (library_){ - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - if (value == 0.0) - libWarn(1172, attr, "default_max_fanout is 0.0."); - library_->setDefaultMaxFanout(value); - } + for (const RiseFall *rf : RiseFall::range()) { + std::string suffix = rf->to_string_long(); + readLibAttrFloat(library_group, ("input_threshold_pct_" + suffix).c_str(), + &LibertyLibrary::setInputThreshold, rf, 0.01F); + if (library_->inputThreshold(rf) == 0.0) + libWarn(1145, library_group, "input_threshold_pct_%s not found.", rf->name()); + + readLibAttrFloat(library_group, ("output_threshold_pct_" + suffix).c_str(), + &LibertyLibrary::setOutputThreshold, rf, 0.01F); + if (library_->outputThreshold(rf) == 0.0) + libWarn(1146, library_group, "output_threshold_pct_%s not found.", rf->name()); + + readLibAttrFloat(library_group, ("slew_lower_threshold_pct_" + suffix).c_str(), + &LibertyLibrary::setSlewLowerThreshold, rf, 0.01F); + if (library_->slewLowerThreshold(rf) == 0.0) + libWarn(1147, library_group, "slew_lower_threshold_pct_%s not found.", rf->name()); + + readLibAttrFloat(library_group, ("slew_upper_threshold_pct_" + suffix).c_str(), + &LibertyLibrary::setSlewUpperThreshold, rf, 0.01F); + if (library_->slewUpperThreshold(rf) == 0.0) + libWarn(1148, library_group, "slew_upper_threshold_pct_%s not found.", rf->name()); } } void -LibertyReader::visitDefaultIntrinsicRise(LibertyAttr *attr) +LibertyReader::readTableTemplates(const LibertyGroup *library_group) { - visitDefaultIntrinsic(attr, RiseFall::rise()); + readTableTemplates(library_group, "lu_table_template", TableTemplateType::delay); + readTableTemplates(library_group, "output_current_template", + TableTemplateType::output_current); + readTableTemplates(library_group, "power_lut_template", TableTemplateType::power); + readTableTemplates(library_group, "ocv_table_template", TableTemplateType::ocv); } void -LibertyReader::visitDefaultIntrinsicFall(LibertyAttr *attr) -{ - visitDefaultIntrinsic(attr, RiseFall::fall()); -} - -void -LibertyReader::visitDefaultIntrinsic(LibertyAttr *attr, - const RiseFall *rf) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setDefaultIntrinsic(rf, value * time_scale_); - } -} - -void -LibertyReader::visitDefaultInoutPinRiseRes(LibertyAttr *attr) -{ - visitDefaultInoutPinRes(attr, RiseFall::rise()); -} - -void -LibertyReader::visitDefaultInoutPinFallRes(LibertyAttr *attr) -{ - visitDefaultInoutPinRes(attr, RiseFall::fall()); -} - -void -LibertyReader::visitDefaultInoutPinRes(LibertyAttr *attr, - const RiseFall *rf) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setDefaultBidirectPinRes(rf, value * res_scale_); - } -} - -void -LibertyReader::visitDefaultOutputPinRiseRes(LibertyAttr *attr) -{ - visitDefaultOutputPinRes(attr, RiseFall::rise()); -} - -void -LibertyReader::visitDefaultOutputPinFallRes(LibertyAttr *attr) -{ - visitDefaultOutputPinRes(attr, RiseFall::fall()); -} - -void -LibertyReader::visitDefaultOutputPinRes(LibertyAttr *attr, - const RiseFall *rf) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setDefaultOutputPinRes(rf, value * res_scale_); - } -} - -void -LibertyReader::visitDefaultFanoutLoad(LibertyAttr *attr) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - if (value == 0.0) - libWarn(1173, attr, "default_fanout_load is 0.0."); - library_->setDefaultFanoutLoad(value); - } - } -} - -void -LibertyReader::visitDefaultWireLoad(LibertyAttr *attr) -{ - if (library_) { - const char *value = getAttrString(attr); - if (value) { - stringDelete(default_wireload_); - default_wireload_ = stringCopy(value); - } - } -} - -void -LibertyReader::visitDefaultWireLoadMode(LibertyAttr *attr) -{ - if (library_) { - const char *wire_load_mode = getAttrString(attr); - if (wire_load_mode) { - WireloadMode mode = stringWireloadMode(wire_load_mode); - if (mode != WireloadMode::unknown) - library_->setDefaultWireloadMode(mode); - else - libWarn(1174, attr, "default_wire_load_mode %s not found.", - wire_load_mode); - } - } -} - -void -LibertyReader::visitDefaultWireLoadSelection(LibertyAttr *attr) -{ - if (library_) { - const char *value = getAttrString(attr); - if (value) { - stringDelete(default_wireload_selection_); - default_wireload_selection_ = stringCopy(value); - } - } -} - -void -LibertyReader::visitDefaultOperatingConditions(LibertyAttr *attr) -{ - if (library_) { - const char *value = getAttrString(attr); - if (value) { - stringDelete(default_operating_condition_); - default_operating_condition_ = stringCopy(value); - } - } -} - -void -LibertyReader::visitInputThresholdPctFall(LibertyAttr *attr) -{ - visitInputThresholdPct(attr, RiseFall::fall()); -} - -void -LibertyReader::visitInputThresholdPctRise(LibertyAttr *attr) -{ - visitInputThresholdPct(attr, RiseFall::rise()); -} - -void -LibertyReader::visitInputThresholdPct(LibertyAttr *attr, - const RiseFall *rf) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setInputThreshold(rf, value / 100.0F); - } - have_input_threshold_[rf->index()] = true; -} - -void -LibertyReader::visitOutputThresholdPctFall(LibertyAttr *attr) -{ - visitOutputThresholdPct(attr, RiseFall::fall()); -} - -void -LibertyReader::visitOutputThresholdPctRise(LibertyAttr *attr) -{ - visitOutputThresholdPct(attr, RiseFall::rise()); -} - -void -LibertyReader::visitOutputThresholdPct(LibertyAttr *attr, - const RiseFall *rf) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setOutputThreshold(rf, value / 100.0F); - } - have_output_threshold_[rf->index()] = true; -} - -void -LibertyReader::visitSlewLowerThresholdPctFall(LibertyAttr *attr) -{ - visitSlewLowerThresholdPct(attr, RiseFall::fall()); -} - -void -LibertyReader::visitSlewLowerThresholdPctRise(LibertyAttr *attr) -{ - visitSlewLowerThresholdPct(attr, RiseFall::rise()); -} - -void -LibertyReader::visitSlewLowerThresholdPct(LibertyAttr *attr, - const RiseFall *rf) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setSlewLowerThreshold(rf, value / 100.0F); - } - have_slew_lower_threshold_[rf->index()] = true; -} - -void -LibertyReader::visitSlewUpperThresholdPctFall(LibertyAttr *attr) -{ - visitSlewUpperThresholdPct(attr, RiseFall::fall()); -} - -void -LibertyReader::visitSlewUpperThresholdPctRise(LibertyAttr *attr) -{ - visitSlewUpperThresholdPct(attr, RiseFall::rise()); -} - -void -LibertyReader::visitSlewUpperThresholdPct(LibertyAttr *attr, - const RiseFall *rf) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setSlewUpperThreshold(rf, value / 100.0F); - } - have_slew_upper_threshold_[rf->index()] = true; -} - -void -LibertyReader::visitSlewDerateFromLibrary(LibertyAttr *attr) -{ - if (library_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - library_->setSlewDerateFromLibrary(value); - } -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginTechnology(LibertyGroup *group) -{ - if (library_) { - const char *tech = group->firstName(); - if (stringEq(tech, "fpga")) - library_->setDelayModelType(DelayModelType::cmos_linear); - } -} - -void -LibertyReader::endTechnology(LibertyGroup *) -{ -} - -void -LibertyReader::beginTableTemplateDelay(LibertyGroup *group) -{ - beginTableTemplate(group, TableTemplateType::delay); -} - -void -LibertyReader::beginTableTemplateOutputCurrent(LibertyGroup *group) -{ - beginTableTemplate(group, TableTemplateType::output_current); -} - -void -LibertyReader::beginTableTemplate(LibertyGroup *group, +LibertyReader::readTableTemplates(const LibertyGroup *library_group, + const char *group_name, TableTemplateType type) { - if (library_) { - const char *name = group->firstName(); + for (const LibertyGroup *template_group : library_group->findSubgroups(group_name)) { + const char *name = template_group->firstName(); if (name) { - tbl_template_ = library_->makeTableTemplate(name, type); + TableTemplate *tbl_template = library_->makeTableTemplate(name, type); + TableAxisPtr axis1 = makeTableTemplateAxis(template_group, 1); + if (axis1) + tbl_template->setAxis1(axis1); + TableAxisPtr axis2 = makeTableTemplateAxis(template_group, 2); + if (axis2) + tbl_template->setAxis2(axis2); + TableAxisPtr axis3 = makeTableTemplateAxis(template_group, 3); + if (axis3) + tbl_template->setAxis3(axis3); } else - libWarn(1175, group, "table template missing name."); - axis_var_[0] = axis_var_[1] = axis_var_[2] = TableAxisVariable::unknown; - clearAxisValues(); - } -} - -void -LibertyReader::clearAxisValues() -{ - axis_values_[0].clear(); - axis_values_[1].clear(); - axis_values_[2].clear(); -} - -void -LibertyReader::endTableTemplate(LibertyGroup *group) -{ - if (tbl_template_) { - TableAxisPtr axis1 = makeAxis(0, group); - if (axis1) - tbl_template_->setAxis1(axis1); - TableAxisPtr axis2 = makeAxis(1, group); - if (axis2) - tbl_template_->setAxis2(axis2); - TableAxisPtr axis3 = makeAxis(2, group); - if (axis3) - tbl_template_->setAxis3(axis3); - tbl_template_ = nullptr; - axis_var_[0] = axis_var_[1] = axis_var_[2] = TableAxisVariable::unknown; + libWarn(1175, template_group, "table template missing name."); } } TableAxisPtr -LibertyReader::makeAxis(int index, - LibertyGroup *group) +LibertyReader::makeTableTemplateAxis(const LibertyGroup *template_group, + int axis_index) { - TableAxisVariable axis_var = axis_var_[index]; - if (axis_var != TableAxisVariable::unknown) { - FloatSeq values; - if (!axis_values_[index].empty()) { + std::string var_attr_name = "variable_" + std::to_string(axis_index); + const std::string *var_name = template_group->findAttrString(var_attr_name); + if (var_name) { + TableAxisVariable axis_var = stringTableAxisVariable(var_name->c_str()); + if (axis_var == TableAxisVariable::unknown) + libWarn(1297, template_group, "axis type %s not supported.", var_name->c_str()); + else { + std::string index_attr_name = "index_" + std::to_string(axis_index); + const LibertyComplexAttr *index_attr = + template_group->findComplexAttr(index_attr_name); + FloatSeq axis_values; + if (index_attr) { + axis_values = readFloatSeq(index_attr, 1.0F); + if (!axis_values.empty()) { + float prev = axis_values[0]; + for (size_t i = 1; i < axis_values.size(); i++) { + float value = axis_values[i]; + if (value <= prev) { + libWarn(1178, template_group, "non-increasing table index values."); + break; + } + prev = value; + } + } + } const Units *units = library_->units(); float scale = tableVariableUnit(axis_var, units)->scale(); - values = std::move(axis_values_[index]); - scaleFloats(values, scale); + scaleFloats(axis_values, scale); + return make_shared(axis_var, std::move(axis_values)); } - return make_shared(axis_var, std::move(values)); } - else if (!axis_values_[index].empty()) { - libWarn(1176, group, "missing variable_%d attribute.", index + 1); - axis_values_[index].clear(); - } - // No warning for missing index_xx attributes because they are not required. return nullptr; } @@ -1486,695 +630,2163 @@ scaleFloats(FloatSeq &floats, } void -LibertyReader::visitVariable1(LibertyAttr *attr) +LibertyReader::readVoltateMaps(const LibertyGroup *library_group) { - visitVariable(0, attr); -} - -void -LibertyReader::visitVariable2(LibertyAttr *attr) -{ - visitVariable(1, attr); -} - -void -LibertyReader::visitVariable3(LibertyAttr *attr) -{ - visitVariable(2, attr); -} - -void -LibertyReader::visitVariable(int index, - LibertyAttr *attr) -{ - if (tbl_template_) { - const char *type = getAttrString(attr); - TableAxisVariable var = stringTableAxisVariable(type); - if (var == TableAxisVariable::unknown) - libWarn(1297, attr, "axis type %s not supported.", type); - else - axis_var_[index] = var; + for (const LibertyComplexAttr *volt_attr : + library_group->findComplexAttrs("voltage_map")) { + const LibertyAttrValueSeq &values = volt_attr->values(); + if (values.size() == 2) { + const std::string &volt_name = values[0]->stringValue(); + float volt; + bool valid; + values[1]->floatValue(volt, valid); + if (valid) + library_->addSupplyVoltage(volt_name.c_str(), volt); + else + libWarn(1166, volt_attr, "voltage_map voltage is not a float."); + } } } void -LibertyReader::visitIndex1(LibertyAttr *attr) +LibertyReader::readOperatingConds(const LibertyGroup *library_group) { - visitIndex(0, attr); + for (const LibertyGroup *opcond_group : + library_group->findSubgroups("operating_conditions")) { + const char *name = opcond_group->firstName(); + if (name) { + OperatingConditions *op_cond = library_->makeOperatingConditions(name); + float value; + bool exists; + opcond_group->findAttrFloat("process", value, exists); + if (exists) + op_cond->setProcess(value); + opcond_group->findAttrFloat("temperature", value, exists); + if (exists) + op_cond->setTemperature(value); + opcond_group->findAttrFloat("voltage", value, exists); + if (exists) + op_cond->setVoltage(value); + const std::string *tree_type = opcond_group->findAttrString("tree_type"); + if (tree_type) { + WireloadTree wireload_tree = stringWireloadTree(tree_type->c_str()); + op_cond->setWireloadTree(wireload_tree); + } + } + } + + const std::string *default_op_cond = + library_group->findAttrString("default_operating_conditions"); + if (default_op_cond) { + OperatingConditions *op_cond = + library_->findOperatingConditions(default_op_cond->c_str()); + if (op_cond) + library_->setDefaultOperatingConditions(op_cond); + else + libWarn(1144, library_group, "default_operating_condition %s not found.", + default_op_cond->c_str()); + } } void -LibertyReader::visitIndex2(LibertyAttr *attr) +LibertyReader::readScaleFactors(const LibertyGroup *library_group) { - visitIndex(1, attr); + // Top level scale factors. + ScaleFactors *scale_factors = library_->makeScaleFactors(""); + library_->setScaleFactors(scale_factors); + readScaleFactors(library_group, scale_factors); + + // Named scale factors. + for (const LibertyGroup *scale_group : library_group->findSubgroups("scaling_factors")){ + const char *name = scale_group->firstName(); + if (name) { + ScaleFactors *scale_factors = library_->makeScaleFactors(name); + readScaleFactors(scale_group, scale_factors); + } + } } void -LibertyReader::visitIndex3(LibertyAttr *attr) +LibertyReader::readScaleFactors(const LibertyGroup *scale_group, + ScaleFactors *scale_factors) { - visitIndex(2, attr); + // Skip unknown type. + for (int type_index = 0; type_index < scale_factor_type_count - 1; type_index++) { + ScaleFactorType type = static_cast(type_index); + const char *type_name = scaleFactorTypeName(type); + // Skip unknown pvt. + for (int pvt_index = 0; pvt_index < scale_factor_pvt_count - 1; pvt_index++) { + ScaleFactorPvt pvt = static_cast(pvt_index); + const std::string pvt_name = scaleFactorPvtName(pvt); + std::string attr_name; + for (const RiseFall *rf : RiseFall::range()) { + if (scaleFactorTypeRiseFallSuffix(type)) { + const std::string rf_name = (rf == RiseFall::rise()) ? "rise" : "fall"; + attr_name = "k_" + pvt_name + "_" + type_name + "_" + rf_name; + } + else if (scaleFactorTypeRiseFallPrefix(type)) { + const char *rf_name = (rf == RiseFall::rise()) ? "rise" : "fall"; + attr_name = "k_" + pvt_name + "_" + rf_name + "_" + type_name; + } + else if (scaleFactorTypeLowHighSuffix(type)) { + const char *rf_name = (rf == RiseFall::rise()) ? "high":"low"; + attr_name = "k_" + pvt_name + "_" + type_name + "_" + rf_name; + } + else + attr_name = "k_" + pvt_name + "_" + type_name; + float value; + bool exists; + scale_group->findAttrFloat(attr_name, value, exists); + if (exists) + scale_factors->setScale(type, pvt, rf, value); + } + } + } } void -LibertyReader::visitIndex(int index, - LibertyAttr *attr) +LibertyReader::readWireloads(const LibertyGroup *library_group) { - if (tbl_template_ - // Ignore index_* in ecsm_waveform groups. - && !in_ecsm_waveform_) { - FloatSeq axis_values = readFloatSeq(attr, 1.0F); + for (const LibertyGroup *wl_group : library_group->findSubgroups("wire_load")) { + const char *name = wl_group->firstName(); + if (name) { + Wireload *wireload = library_->makeWireload(name); + float value; + bool exists; + wl_group->findAttrFloat("resistance", value, exists); + if (exists) + wireload->setResistance(value * res_scale_); + + wl_group->findAttrFloat("capacitance", value, exists); + if (exists) + wireload->setCapacitance(value * cap_scale_); + + wl_group->findAttrFloat("slope", value, exists); + if (exists) + wireload->setSlope(value); + + for (const LibertyComplexAttr *fanout_attr : + wl_group->findComplexAttrs("fanout_length")) { + float fanout, length; + bool exists; + getAttrFloat2(fanout_attr, fanout, length, exists); + if (exists) + wireload->addFanoutLength(fanout, length); + else + libWarn(1185, fanout_attr, "fanout_length is missing length and fanout."); + } + } + else + libWarn(1184, wl_group, "wire_load missing name."); + } +} + +void +LibertyReader::readWireloadSelection(const LibertyGroup *library_group) +{ + const LibertyGroup *sel_group = library_group->findSubgroup("wire_load_selection"); + if (sel_group) { + const char *name = sel_group->firstName(); + if (name == nullptr) + name = ""; + WireloadSelection *wireload_selection = library_->makeWireloadSelection(name); + for (const LibertyComplexAttr *area_attr : + sel_group->findComplexAttrs("wire_load_from_area")) { + const LibertyAttrValueSeq &values = area_attr->values(); + if (values.size() == 3) { + LibertyAttrValue *value = values[0]; + if (value->isFloat()) { + float min_area = value->floatValue(); + value = values[1]; + if (value->isFloat()) { + float max_area = value->floatValue(); + value = values[2]; + if (value->isString()) { + const std::string &wireload_name = value->stringValue(); + const Wireload *wireload = + library_->findWireload(wireload_name.c_str()); + if (wireload) + wireload_selection->addWireloadFromArea(min_area, max_area, + wireload); + else + libWarn(1187, area_attr, "wireload %s not found.", wireload_name.c_str()); + } + else + libWarn(1188, area_attr, + "wire_load_from_area wireload name not a string."); + } + else + libWarn(1189, area_attr, "wire_load_from_area min not a float."); + } + else + libWarn(1190, area_attr, "wire_load_from_area max not a float."); + } + else + libWarn(1191, area_attr, "wire_load_from_area missing parameters."); + } + } +} + +void +LibertyReader::readDefaultWireLoad(const LibertyGroup *library_group) +{ + const std::string *wireload_name = library_group->findAttrString("default_wire_load"); + if (wireload_name) { + const Wireload *wireload = library_->findWireload(wireload_name->c_str()); + if (wireload) + library_->setDefaultWireload(wireload); + else + libWarn(1142, library_group, "default_wire_load %s not found.", + wireload_name->c_str()); + } +} + +void +LibertyReader::readDefaultWireLoadMode(const LibertyGroup *library_group) +{ + const std::string *wire_load_mode = + library_group->findAttrString("default_wire_load_mode"); + if (wire_load_mode) { + WireloadMode mode = stringWireloadMode(wire_load_mode->c_str()); + if (mode != WireloadMode::unknown) + library_->setDefaultWireloadMode(mode); + else + libWarn(1174, library_group, "default_wire_load_mode %s not found.", + wire_load_mode->c_str()); + } +} + +void +LibertyReader::readDefaultWireLoadSelection(const LibertyGroup *library_group) +{ + const std::string *selection_name = + library_group->findAttrString("default_wire_load_selection"); + if (selection_name) { + const WireloadSelection *selection = + library_->findWireloadSelection(selection_name->c_str()); + if (selection) + library_->setDefaultWireloadSelection(selection); + else + libWarn(1143, library_group, "default_wire_selection %s not found.", + selection_name->c_str()); + } +} + +void +LibertyReader::readModeDefs(LibertyCell *cell, + const LibertyGroup *cell_group) +{ + for (const LibertyGroup *mode_group : cell_group->findSubgroups("mode_definition")) { + const char *name = mode_group->firstName(); + if (name) { + ModeDef *mode_def = cell->makeModeDef(name); + for (const LibertyGroup *value_group : mode_group->findSubgroups("mode_value")) { + const char *value_name = value_group->firstName(); + if (value_name) { + ModeValueDef *mode_value = mode_def->defineValue(value_name, nullptr, nullptr); + const std::string *sdf_cond = value_group->findAttrString("sdf_cond"); + if (sdf_cond) + mode_value->setSdfCond(sdf_cond->c_str()); + const std::string *when = value_group->findAttrString("when"); + if (when) { + // line + FuncExpr *when_expr = parseFunc(when->c_str(), "when", cell, + value_group->line()); + mode_value->setCond(when_expr); + } + } + else + libWarn(1264, value_group, "mode value missing name."); + } + } + else + libWarn(1263, mode_group, "mode definition missing name."); + } +} + +void +LibertyReader::readSlewDegradations(const LibertyGroup *library_group) +{ + for (const RiseFall *rf : RiseFall::range()) { + const std::string group_name = rf->to_string_long() + "_transition_degradation"; + const LibertyGroup *degradation_group = + library_group->findSubgroup(group_name.c_str()); + if (degradation_group) { + TableModel *table_model = readTableModel(degradation_group, rf, + TableTemplateType::delay, + time_scale_, + ScaleFactorType::transition); + if (LibertyLibrary::checkSlewDegradationAxes(table_model)) + library_->setWireSlewDegradationTable(table_model, rf); + else + libWarn(1254, degradation_group, "unsupported model axis."); + } + } +} + +void +LibertyReader::readLibAttrFloat(const LibertyGroup *library_group, + const char *attr_name, + void (LibertyLibrary::*set_func)(float value), + float scale) +{ + float value; + bool exists; + library_group->findAttrFloat(attr_name, value, exists); + if (exists) + (library_->*set_func)(value * scale); +} + +void +LibertyReader::readLibAttrFloat(const LibertyGroup *library_group, + const char *attr_name, + void (LibertyLibrary::*set_func)(const RiseFall *rf, + float value), + const RiseFall *rf, + float scale) +{ + float value; + bool exists; + library_group->findAttrFloat(attr_name, value, exists); + if (exists) + (library_->*set_func)(rf, value * scale); +} + +void +LibertyReader::readLibAttrFloatWarnZero(const LibertyGroup *library_group, + const char *attr_name, + void (LibertyLibrary::*set_func)(float value), + float scale) +{ + float value; + bool exists; + library_group->findAttrFloat(attr_name, value, exists); + if (exists) { + if (value == 0.0F) { + const LibertySimpleAttr *attr = library_group->findSimpleAttr(attr_name); + if (attr) + libWarn(1171, attr, "%s is 0.0.", attr_name); + else + libWarn(1172, library_group, "%s is 0.0.", attr_name); + } + (library_->*set_func)(value * scale); + } +} + +//////////////////////////////////////////////////////////////// + +void +LibertyReader::readCell(LibertyCell *cell, + const LibertyGroup *cell_group) +{ + readBusTypes(cell, cell_group); + // Make ports first because they are referenced by functions, timing arcs, etc. + LibertyPortGroupMap port_group_map = makeCellPorts(cell, cell_group); + + // Make ff/latch output ports. + makeSequentials(cell, cell_group); + + readCellAttributes(cell, cell_group); + + // Set port directions before making timing arcs etc. + for (auto const &[port_group, ports] : port_group_map) + readPortDir(ports, port_group); + + for (auto const &[port_group, ports] : port_group_map) { + readPortAttributes(cell, ports, port_group); + makePortFuncs(cell, ports, port_group); + makeTimingArcs(cell, ports, port_group); + readInternalPowerGroups(cell, ports, port_group); + } + + readTestCell(cell, cell_group); + + cell->finish(infer_latches_, report_, debug_); +} + +void +LibertyReader::readScaledCell(const LibertyGroup *scaled_cell_group) +{ + const char *name = scaled_cell_group->firstName(); + if (name) { + LibertyCell *owner = library_->findLibertyCell(name); + if (owner) { + const char *op_cond_name = scaled_cell_group->secondName(); + if (op_cond_name) { + OperatingConditions *op_cond = library_->findOperatingConditions(op_cond_name); + if (op_cond) { + debugPrint(debug_, "liberty", 1, "scaled cell %s %s", + name, op_cond_name); + LibertyCell *scaled_cell = library_->makeScaledCell(name, filename_); + readCell(scaled_cell, scaled_cell_group); + checkScaledCell(scaled_cell, owner, scaled_cell_group, op_cond_name); + // Add scaled cell AFTER ports and timing arcs are defined. + owner->addScaledCell(op_cond, scaled_cell); + } + else + libWarn(1202, scaled_cell_group, "operating conditions %s not found.", + op_cond_name); + } + else + libWarn(1203, scaled_cell_group, "scaled_cell missing operating condition."); + } + else + libWarn(1204, scaled_cell_group, "scaled_cell cell %s has not been defined.", name); + } + else + libWarn(1205, scaled_cell_group, "scaled_cell missing name."); +} + +// Minimal check that is not very specific about where the discrepancies are. +void +LibertyReader::checkScaledCell(LibertyCell *scaled_cell, + LibertyCell *owner, + const LibertyGroup *scaled_cell_group, + const char *op_cond_name) +{ + if (equivCellPorts(scaled_cell, owner)) { + if (!equivCellPorts(scaled_cell, owner)) + libWarn(1206, scaled_cell_group, "scaled_cell %s, %s ports do not match cell ports", + scaled_cell->name(), + op_cond_name); + if (!equivCellFuncs(scaled_cell, owner)) + libWarn(1206, scaled_cell_group, + "scaled_cell %s, %s port functions do not match cell port functions.", + scaled_cell->name(), + op_cond_name); + } + else + libWarn(1207, scaled_cell_group, "scaled_cell ports do not match cell ports."); + if (!equivCellTimingArcSets(scaled_cell, owner)) + libWarn(1208, scaled_cell_group, + "scaled_cell %s, %s timing does not match cell timing.", + scaled_cell->name(), + op_cond_name); +} + +LibertyPortGroupMap +LibertyReader::makeCellPorts(LibertyCell *cell, + const LibertyGroup *cell_group) +{ + LibertyPortGroupMap port_group_map; + for (const LibertyGroup *subgroup : cell_group->subgroups()) { + const std::string &type = subgroup->type(); + if (type == "pin") + makePinPort(cell, subgroup, port_group_map); + else if (type == "bus") + makeBusPort(cell, subgroup, port_group_map); + else if (type == "bundle") + makeBundlePort(cell, subgroup, port_group_map); + else if (type == "pg_pin") + makePgPinPort(cell, subgroup); + } + return port_group_map; +} + +void +LibertyReader::makePinPort(LibertyCell *cell, + const LibertyGroup *pin_group, + LibertyPortGroupMap &port_group_map) +{ + for (const LibertyAttrValue *port_value : pin_group->params()) { + const std::string &port_name = port_value->stringValue(); + LibertyPort *port = makePort(cell, port_name.c_str()); + port_group_map[pin_group].push_back(port); + } +} + +void +LibertyReader::makeBusPort(LibertyCell *cell, + const LibertyGroup *bus_group, + LibertyPortGroupMap &port_group_map) +{ + for (const LibertyAttrValue *port_value : bus_group->params()) { + const std::string &port_name = port_value->stringValue(); + const LibertySimpleAttr *bus_type_attr = bus_group->findSimpleAttr("bus_type"); + if (bus_type_attr) { + const std::string *bus_type = bus_type_attr->stringValue(); + if (bus_type) { + // Look for bus dcl local to cell first. + BusDcl *bus_dcl = cell->findBusDcl(bus_type->c_str()); + if (bus_dcl == nullptr) + bus_dcl = library_->findBusDcl(bus_type->c_str()); + if (bus_dcl) { + debugPrint(debug_, "liberty", 1, " bus %s", port_name.c_str()); + LibertyPort *bus_port = makeBusPort(cell, port_name.c_str(), + bus_dcl->from(), bus_dcl->to(), + bus_dcl); + port_group_map[bus_group].push_back(bus_port); + // Make ports for pin groups inside the bus group. + makeBusPinPorts(cell, bus_group, port_group_map); + } + else + libWarn(1235, bus_type_attr, "bus_type %s not found.", bus_type->c_str()); + } + } + else + libWarn(1236, bus_type_attr, "bus_type not found."); + } +} + +void +LibertyReader::makeBusPinPorts(LibertyCell *cell, + const LibertyGroup *bus_group, + LibertyPortGroupMap &port_group_map) +{ + for (const LibertyGroup *pin_group : bus_group->findSubgroups("pin")) { + for (const LibertyAttrValue *param : pin_group->params()) { + if (param->isString()) { + const std::string pin_name = param->stringValue(); + debugPrint(debug_, "liberty", 1, " bus pin port %s", pin_name.c_str()); + // Expand foo[3:0] port names. + PortNameBitIterator name_iter(cell, pin_name.c_str(), this, pin_group->line()); + while (name_iter.hasNext()) { + LibertyPort *pin_port = name_iter.next(); + if (pin_port) { + port_group_map[pin_group].push_back(pin_port); + } + else + libWarn(1232, pin_group, "pin %s not found.", pin_name.c_str()); + } + } + else + libWarn(1233, pin_group, "pin name is not a string."); + } + } +} + +void +LibertyReader::makeBundlePort(LibertyCell *cell, + const LibertyGroup *bundle_group, + LibertyPortGroupMap &port_group_map) +{ + const std::string &bundle_name = bundle_group->firstName(); + debugPrint(debug_, "liberty", 1, " bundle %s", bundle_name.c_str()); + + const LibertyComplexAttr *member_attr = bundle_group->findComplexAttr("members"); + ConcretePortSeq *members = new ConcretePortSeq; + for (const LibertyAttrValue *member_value : member_attr->values()) { + if (member_value->isString()) { + const char *member_name = member_value->stringValue().c_str(); + LibertyPort *member = cell->findLibertyPort(member_name); + if (member == nullptr) + member = makePort(cell, member_name); + members->push_back(member); + } + } + LibertyPort *bundle_port = builder_.makeBundlePort(cell, bundle_name.c_str(), + members); + port_group_map[bundle_group].push_back(bundle_port); + // Make ports for pin groups inside the bundle group. + makeBundlePinPorts(cell, bundle_group, port_group_map); +} + +void +LibertyReader::makeBundlePinPorts(LibertyCell *cell, + const LibertyGroup *bundle_group, + LibertyPortGroupMap &port_group_map) +{ + for (const LibertyGroup *pin_group : bundle_group->findSubgroups("pin")) { + for (LibertyAttrValue *param : pin_group->params()) { + if (param->isString()) { + const std::string pin_name = param->stringValue(); + debugPrint(debug_, "liberty", 1, " bundle pin port %s", pin_name.c_str()); + LibertyPort *pin_port = cell->findLibertyPort(pin_name.c_str()); + if (pin_port == nullptr) + pin_port = makePort(cell, pin_name.c_str()); + port_group_map[pin_group].push_back(pin_port); + } + else + libWarn(1234, pin_group, "pin name is not a string."); + } + } +} + +void +LibertyReader::makePgPinPort(LibertyCell *cell, + const LibertyGroup *pg_pin_group) +{ + const std::string &port_name = pg_pin_group->firstName(); + LibertyPort *pg_port = makePort(cell, port_name.c_str()); + + const std::string *type_name = pg_pin_group->findAttrString("pg_type"); + if (type_name) { + PwrGndType type = findPwrGndType(type_name->c_str()); + PortDirection *dir = PortDirection::unknown(); + switch (type) { + case PwrGndType::primary_ground: + case PwrGndType::backup_ground: + case PwrGndType::internal_ground: + dir = PortDirection::ground(); + break; + case PwrGndType::primary_power: + case PwrGndType::backup_power: + case PwrGndType::internal_power: + dir = PortDirection::power(); + break; + case PwrGndType::none: + libError(1291, pg_pin_group, "unknown pg_type."); + break; + default: + break; + } + pg_port->setPwrGndType(type); + pg_port->setDirection(dir); + } + + const std::string *voltate_name = pg_pin_group->findAttrString("voltage_name"); + if (voltate_name) + pg_port->setVoltageName(voltate_name->c_str()); +} + +//////////////////////////////////////////////////////////////// + +void +LibertyReader::readPortAttributes(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + readCapacitance(ports, port_group); + readMinPulseWidth(cell, ports, port_group); + readPortAttrFloat("min_period", &LibertyPort::setMinPeriod, ports, + port_group, time_scale_); + readPortAttrBool("clock", &LibertyPort::setIsClock, ports, port_group); + readPortAttrFloat("fanout_load", &LibertyPort::setFanoutLoad, ports, + port_group, 1.0F); + readPortAttrFloatMinMax("max_fanout", &LibertyPort::setFanoutLimit, ports, + port_group, MinMax::max(), 1.0F); + readPortAttrFloatMinMax("min_fanout", &LibertyPort::setFanoutLimit, ports, + port_group, MinMax::min(), 1.0F); + readPulseClock(ports, port_group); + readPortAttrBool("clock_gate_clock_pin", &LibertyPort::setIsClockGateClock, + ports, port_group); + readPortAttrBool("clock_gate_enable_pin", &LibertyPort::setIsClockGateEnable, + ports, port_group); + readPortAttrBool("clock_gate_out_pin", &LibertyPort::setIsClockGateOut, + ports, port_group); + readPortAttrBool("is_pll_feedback_pin", &LibertyPort::setIsPllFeedback, + ports, port_group); + readSignalType(cell, ports, port_group); + readPortAttrBool("isolation_cell_data_pin", + &LibertyPort::setIsolationCellData, ports, port_group); + readPortAttrBool("isolation_cell_enable_pin", + &LibertyPort::setIsolationCellEnable, ports, port_group); + readPortAttrBool("level_shifter_data_pin", + &LibertyPort::setLevelShifterData, ports, port_group); + readPortAttrBool("switch_pin", &LibertyPort::setIsSwitch, ports, port_group); + readPortAttrString("related_ground_pin", &LibertyPort::setRelatedGroundPin, + ports, port_group); + readPortAttrString("related_power_pin", &LibertyPort::setRelatedPowerPin, + ports, port_group); + readDriverWaveform(ports, port_group); +} + +void +LibertyReader::readDriverWaveform(const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + for (const RiseFall *rf : RiseFall::range()) { + const char *attr_name = rf == RiseFall::rise() + ? "driver_waveform_rise" : "driver_waveform_fall"; + const std::string *name = port_group->findAttrString(attr_name); + if (name) { + DriverWaveform *waveform = library_->findDriverWaveform(name->c_str()); + if (waveform) { + for (LibertyPort *port : ports) + port->setDriverWaveform(waveform, rf); + } + } + } +} + +void +LibertyReader::readPortAttrString(const char *attr_name, + void (LibertyPort::*set_func)(const char *value), + const LibertyPortSeq &ports, + const LibertyGroup *group) +{ + const std::string *value = group->findAttrString(attr_name); + if (value) { + for (LibertyPort *port : ports) + (port->*set_func)(value->c_str()); + } +} + +void +LibertyReader::readPortAttrFloat(const char *attr_name, + void (LibertyPort::*set_func)(float value), + const LibertyPortSeq &ports, + const LibertyGroup *group, + float scale) +{ + float value; + bool exists; + group->findAttrFloat(attr_name, value, exists); + if (exists) { + for (LibertyPort *port : ports) + (port->*set_func)(value * scale); + } +} + +void +LibertyReader::readPortAttrBool(const char *attr_name, + void (LibertyPort::*set_func)(bool value), + const LibertyPortSeq &ports, + const LibertyGroup *group) +{ + const LibertySimpleAttr *attr = group->findSimpleAttr(attr_name); + if (attr) { + const LibertyAttrValue &attr_value = attr->value(); + if (attr_value.isString()) { + const std::string &value = attr_value.stringValue(); + if (stringEqual(value.c_str(), "true")) { + for (LibertyPort *port : ports) + (port->*set_func)(true); + } + else if (stringEqual(value.c_str(), "false")) { + for (LibertyPort *port : ports) + (port->*set_func)(false); + } + else + libWarn(1238, attr, "%s attribute is not boolean.", attr_name); + } + else + libWarn(1239, attr, "%s attribute is not boolean.", attr_name); + } +} + +void +LibertyReader::readPortAttrFloatMinMax(const char *attr_name, + void (LibertyPort::*set_func)(float value, + const MinMax *min_max), + const LibertyPortSeq &ports, + const LibertyGroup *group, + const MinMax *min_max, + float scale) +{ + float value; + bool exists; + group->findAttrFloat(attr_name, value, exists); + if (exists) { + for (LibertyPort *port : ports) + (port->*set_func)(value * scale, min_max); + } +} + +void +LibertyReader::readPulseClock(const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + const std::string *pulse_clk = port_group->findAttrString("pulse_clock"); + if (pulse_clk) { + const RiseFall *trigger = nullptr; + const RiseFall *sense = nullptr; + if (*pulse_clk == "rise_triggered_high_pulse") { + trigger = RiseFall::rise(); + sense = RiseFall::rise(); + } + else if (*pulse_clk == "rise_triggered_low_pulse") { + trigger = RiseFall::rise(); + sense = RiseFall::fall(); + } + else if (*pulse_clk == "fall_triggered_high_pulse") { + trigger = RiseFall::fall(); + sense = RiseFall::rise(); + } + else if (*pulse_clk == "fall_triggered_low_pulse") { + trigger = RiseFall::fall(); + sense = RiseFall::fall(); + } + else + libWarn(1242, port_group, "pulse_latch unknown pulse type."); + if (trigger) { + for (LibertyPort *port : ports) + port->setPulseClk(trigger, sense); + } + } +} + +void +LibertyReader::readSignalType(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + if (!dynamic_cast(cell)) + return; + const std::string *type = port_group->findAttrString("signal_type"); + if (!type) + return; + ScanSignalType signal_type = ScanSignalType::none; + if (*type == "test_scan_enable") + signal_type = ScanSignalType::enable; + else if (*type == "test_scan_enable_inverted") + signal_type = ScanSignalType::enable_inverted; + else if (*type == "test_scan_clock") + signal_type = ScanSignalType::clock; + else if (*type == "test_scan_clock_a") + signal_type = ScanSignalType::clock_a; + else if (*type == "test_scan_clock_b") + signal_type = ScanSignalType::clock_b; + else if (*type == "test_scan_in") + signal_type = ScanSignalType::input; + else if (*type == "test_scan_in_inverted") + signal_type = ScanSignalType::input_inverted; + else if (*type == "test_scan_out") + signal_type = ScanSignalType::output; + else if (*type == "test_scan_out_inverted") + signal_type = ScanSignalType::output_inverted; + else { + libWarn(1299, port_group, "unknown signal_type %s.", type->c_str()); + return; + } + for (LibertyPort *port : ports) + port->setScanSignalType(signal_type); +} + +void +LibertyReader::readPortDir(const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + const LibertySimpleAttr *dir_attr = port_group->findSimpleAttr("direction"); + // Note missing direction attribute is not an error because a bus group + // can have pin groups for the bus bits that have direcitons. + if (dir_attr) { + const std::string *dir = dir_attr->stringValue(); + if (dir) { + PortDirection *port_dir = PortDirection::unknown(); + if (*dir == "input") + port_dir = PortDirection::input(); + else if (*dir == "output") + port_dir = PortDirection::output(); + else if (*dir == "inout") + port_dir = PortDirection::bidirect(); + else if (*dir == "internal") + port_dir = PortDirection::internal(); + else + libWarn(1240, dir_attr, "unknown port direction."); + for (LibertyPort *port : ports) + port->setDirection(port_dir); + } + } +} + +void +LibertyReader::readCapacitance(const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + // capacitance + readPortAttrFloat("capacitance", &LibertyPort::setCapacitance, ports, + port_group, cap_scale_); + + for (LibertyPort *port : ports) { + // rise/fall_capacitance + for (const RiseFall *rf : RiseFall::range()) { + std::string attr_name = rf->to_string_long() + "_capacitance"; + float cap; + bool exists; + port_group->findAttrFloat(attr_name, cap, exists); + if (exists) { + for (const MinMax *min_max : MinMax::range()) + port->setCapacitance(rf, min_max, cap * cap_scale_); + } + + // rise/fall_capacitance_range(min_cap, max_cap); + attr_name = rf->to_string_long() + "_capacitance_range"; + const LibertyComplexAttrSeq &range_attrs = port_group->findComplexAttrs(attr_name); + if (!range_attrs.empty()) { + const LibertyComplexAttr *attr = range_attrs[0]; + const LibertyAttrValueSeq &values = attr->values(); + if (values.size() == 2) { + float cap_min = values[0]->floatValue(); + float cap_max = values[1]->floatValue(); + port->setCapacitance(rf, MinMax::min(), cap_min * cap_scale_); + port->setCapacitance(rf, MinMax::max(), cap_max * cap_scale_); + } + } + } + if (!(port->isBus() || port->isBundle())) + setPortCapDefault(port); + + for (const MinMax *min_max : MinMax::range()) { + // min/max_capacitance + std::string attr_name = min_max->to_string() + "_capacitance"; + float limit; + bool exists; + port_group->findAttrFloat(attr_name, limit, exists); + if (exists) + port->setCapacitanceLimit(limit * cap_scale_, min_max); + + // min/max_transition + attr_name = min_max->to_string() + "_transition"; + port_group->findAttrFloat(attr_name, limit, exists); + if (exists) + port->setSlewLimit(limit * time_scale_, min_max); + } + + // Default capacitance. + if (port->isBus() || port->isBundle()) { + // Do not clobber member port capacitances by setting the capacitance + // on a bus or bundle. + LibertyPortMemberIterator member_iter(port); + while (member_iter.hasNext()) { + LibertyPort *member = member_iter.next(); + setPortCapDefault(member); + } + } + else + setPortCapDefault(port); + } +} + +void +LibertyReader::setPortCapDefault(LibertyPort *port) +{ + for (const MinMax *min_max : MinMax::range()) { + for (const RiseFall *rf : RiseFall::range()) { + float cap; + bool exists; + port->capacitance(rf, min_max, cap, exists); + if (!exists) + port->setCapacitance(rf, min_max, defaultCap(port)); + } + } +} + +void +LibertyReader::readMinPulseWidth(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + for (LibertyPort *port : ports) { + TimingArcAttrsPtr timing_attrs = nullptr; + for (const RiseFall *rf : RiseFall::range()) { + const char *mpw_attr_name = rf == RiseFall::rise() + ? "min_pulse_width_high" + : "min_pulse_width_low"; + float mpw; + bool exists; + port_group->findAttrFloat(mpw_attr_name, mpw, exists); + if (exists) { + mpw *= time_scale_; + port->setMinPulseWidth(rf, mpw); + + // Make timing arcs for the port min_pulse_width_low/high attributes. + // This is redundant but makes sdf annotation consistent. + if (timing_attrs == nullptr) { + timing_attrs = std::make_shared(); + timing_attrs->setTimingType(TimingType::min_pulse_width); + } + TimingModel *check_model = + makeScalarCheckModel(cell, mpw, ScaleFactorType::min_pulse_width, rf); + timing_attrs->setModel(rf, check_model); + } + } + if (timing_attrs) + builder_.makeTimingArcs(cell, port, port, nullptr, timing_attrs, + port_group->line()); + } +} + +void +LibertyReader::makePortFuncs(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + const LibertySimpleAttr *func_attr = port_group->findSimpleAttr("function"); + if (func_attr) { + const std::string *func = func_attr->stringValue(); + if (func) { + FuncExpr *func_expr = parseFunc(func->c_str(), "function", cell, func_attr->line()); + for (LibertyPort *port : ports) { + port->setFunction(func_expr); + if (func_expr->checkSize(port)) { + libWarn(1195, func_attr->line(), + "port %s function size does not match port size.", + port->name()); + } + } + } + } + + const LibertySimpleAttr *tri_attr = port_group->findSimpleAttr("three_state"); + if (tri_attr) { + const std::string *tri_disable = tri_attr->stringValue(); + if (tri_disable) { + FuncExpr *tri_disable_expr = parseFunc(tri_disable->c_str(), + "three_state", cell, + tri_attr->line()); + FuncExpr *tri_enable_expr = tri_disable_expr->invert(); + for (LibertyPort *port : ports) { + port->setTristateEnable(tri_enable_expr); + if (port->direction() == PortDirection::output()) + port->setDirection(PortDirection::tristate()); + } + } + } +} + +//////////////////////////////////////////////////////////////// + +void +LibertyReader::makeSequentials(LibertyCell *cell, + const LibertyGroup *cell_group) +{ + makeSequentials(cell, cell_group, true, "ff", "clocked_on", "next_state"); + makeSequentials(cell, cell_group, true, "ff_bank", "clocked_on", "next_state"); + makeSequentials(cell, cell_group, false, "latch", "enable", "data_in"); + makeSequentials(cell, cell_group, false, "latch_bank", "enable", "data_in"); + + const LibertyGroup *lut_group = cell_group->findSubgroup("lut");; + if (lut_group) { + LibertyPort *out_port = nullptr; + LibertyPort *out_port_inv = nullptr; + size_t size; + makeSeqPorts(cell, lut_group, out_port, out_port_inv, size); + } +} + +void +LibertyReader::makeSequentials(LibertyCell *cell, + const LibertyGroup *cell_group, + bool is_register, + const char *seq_group_name, + const char *clk_attr_name, + const char *data_attr_name) +{ + for (const LibertyGroup *seq_group : cell_group->findSubgroups(seq_group_name)) { + LibertyPort *out_port = nullptr; + LibertyPort *out_port_inv = nullptr; + size_t size; + makeSeqPorts(cell, seq_group, out_port, out_port_inv, size); + FuncExpr *clk_expr = makeSeqFunc(cell, seq_group, clk_attr_name, size); + FuncExpr *data_expr = makeSeqFunc(cell, seq_group, data_attr_name, size); + FuncExpr *clr_expr = makeSeqFunc(cell, seq_group, "clear", size); + FuncExpr *preset_expr = makeSeqFunc(cell, seq_group, "preset", size); + + LogicValue clr_preset_var1 = LogicValue::unknown; + const LibertySimpleAttr *var1 = seq_group->findSimpleAttr("clear_preset_var1"); + if (var1) + clr_preset_var1 = getAttrLogicValue(var1); + + LogicValue clr_preset_var2 = LogicValue::unknown; + const LibertySimpleAttr *var2 = seq_group->findSimpleAttr("clear_preset_var2"); + if (var2) + clr_preset_var2 = getAttrLogicValue(var2); + + cell->makeSequential(size, is_register, clk_expr, data_expr, clr_expr, + preset_expr, clr_preset_var1, clr_preset_var2, + out_port, out_port_inv); + } +} + +FuncExpr * +LibertyReader::makeSeqFunc(LibertyCell *cell, + const LibertyGroup *seq_group, + const char *attr_name, + int size) +{ + FuncExpr *expr = nullptr; + const std::string *attr = seq_group->findAttrString(attr_name); + if (attr) { + expr = parseFunc(attr->c_str(), attr_name, cell, seq_group->line()); + if (expr && expr->checkSize(size)) { + libWarn(1196, seq_group, "%s %s bus width mismatch.", + seq_group->type().c_str(), attr_name); + delete expr; + expr = nullptr; + } + } + return expr; +} + +void +LibertyReader::makeSeqPorts(LibertyCell *cell, + const LibertyGroup *seq_group, + // Return values. + LibertyPort *&out_port, + LibertyPort *&out_port_inv, + size_t &size) +{ + const char *out_name, *out_inv_name; + bool has_size; + seqPortNames(seq_group, out_name, out_inv_name, has_size, size); + if (out_name) { + if (has_size) + out_port = makeBusPort(cell, out_name, size - 1, 0, nullptr); + else + out_port = makePort(cell, out_name); + out_port->setDirection(PortDirection::internal()); + } + if (out_inv_name) { + if (has_size) + out_port_inv = makeBusPort(cell, out_inv_name, size - 1, 0, nullptr); + else + out_port_inv = makePort(cell, out_inv_name); + out_port_inv->setDirection(PortDirection::internal()); + } +} + +void +LibertyReader::seqPortNames(const LibertyGroup *group, + const char *&out_name, + const char *&out_inv_name, + bool &has_size, + size_t &size) +{ + out_name = nullptr; + out_inv_name = nullptr; + if (group->params().size() == 1) { + // out_port + out_name = group->firstName(); + size = 1; + has_size = false; + } + if (group->params().size() == 2) { + // out_port, out_port_inv + out_name = group->firstName(); + out_inv_name = group->secondName(); + size = 1; + has_size = false; + } + else if (group->params().size() == 3) { + LibertyAttrValue *third_value = group->params()[2]; + if (third_value->isFloat()) { + // out_port, out_port_inv, bus_size + out_name = group->firstName(); + out_inv_name = group->secondName(); + size = static_cast(third_value->floatValue()); + has_size = true; + } + else { + // in_port (ignored), out_port, out_port_inv + out_name = group->secondName(); + out_inv_name = third_value->stringValue().c_str(); + has_size = true; + size = 1; + } + } +} + +//////////////////////////////////////////////////////////////// + +void +LibertyReader::readCellAttributes(LibertyCell *cell, + const LibertyGroup *cell_group) +{ + readCellAttrFloat("area", &LibertyCell::setArea, cell, cell_group, 1.0); + readCellAttrString("cell_footprint", &LibertyCell::setFootprint, cell, cell_group); + readCellAttrBool("dont_use", &LibertyCell::setDontUse, cell, cell_group); + readCellAttrBool("is_macro_cell", &LibertyCell::setIsMacro, cell, cell_group); + readCellAttrBool("is_pad", &LibertyCell::setIsPad, cell, cell_group); + readCellAttrBool("is_level_shifter", &LibertyCell::setIsLevelShifter, cell, cell_group); + readCellAttrBool("is_clock_cell", &LibertyCell::setIsClockCell, cell, cell_group); + readCellAttrBool("is_isolation_cell", &LibertyCell::setIsIsolationCell,cell,cell_group); + readCellAttrBool("always_on", &LibertyCell::setAlwaysOn,cell,cell_group); + readCellAttrBool("interface_timing", &LibertyCell::setInterfaceTiming,cell,cell_group); + readCellAttrFloat("cell_leakage_power", &LibertyCell::setLeakagePower, cell, + cell_group, power_scale_); + + readCellAttrBool("is_memory", &LibertyCell::setIsMemory, cell, cell_group); + if (cell_group->findSubgroup("memory")) + cell->setIsMemory(true); + + readCellAttrBool("pad_cell", &LibertyCell::setIsPad, cell, cell_group); + readLevelShifterType(cell, cell_group); + readSwitchCellType(cell, cell_group); + readCellAttrString("user_function_class", &LibertyCell::setUserFunctionClass, + cell, cell_group); + + readOcvDerateFactors(cell, cell_group); + readCellOcvDerateGroup(cell, cell_group); + readGroupAttrFloat("ocv_arc_depth", cell_group, + [cell](float v) { cell->setOcvArcDepth(v); }); + + const std::string *clock_gate_type = + cell_group->findAttrString("clock_gating_integrated_cell"); + if (clock_gate_type) { + if (stringBeginEqual(clock_gate_type->c_str(), "latch_posedge")) + cell->setClockGateType(ClockGateType::latch_posedge); + else if (stringBeginEqual(clock_gate_type->c_str(), "latch_negedge")) + cell->setClockGateType(ClockGateType::latch_negedge); + else + cell->setClockGateType(ClockGateType::other); + } + + readScaleFactors(cell, cell_group); + readLeagageGrouops(cell, cell_group); + readStatetable(cell, cell_group); + readModeDefs(cell, cell_group); +} + +void +LibertyReader::readScaleFactors(LibertyCell *cell, + const LibertyGroup *cell_group) +{ + const std::string *scale_factors_name = cell_group->findAttrString("scaling_factors"); + if (scale_factors_name) { + ScaleFactors *scale_factors = library_->findScaleFactors(scale_factors_name->c_str()); + if (scale_factors) + cell->setScaleFactors(scale_factors); + else + libWarn(1230, cell_group, "scaling_factors %s not found.", + scale_factors_name->c_str()); + } +} + +void +LibertyReader::readCellAttrString(const char *attr_name, + void (LibertyCell::*set_func)(const char *value), + LibertyCell *cell, + const LibertyGroup *group) +{ + const std::string *value = group->findAttrString(attr_name); + if (value) + (cell->*set_func)(value->c_str()); +} + +void +LibertyReader::readCellAttrFloat(const char *attr_name, + void (LibertyCell::*set_func)(float value), + LibertyCell *cell, + const LibertyGroup *group, + float scale) +{ + float value; + bool exists; + group->findAttrFloat(attr_name, value, exists); + if (exists) + (cell->*set_func)(value * scale); +} + +void +LibertyReader::readCellAttrBool(const char *attr_name, + void (LibertyCell::*set_func)(bool value), + LibertyCell *cell, + const LibertyGroup *group) +{ + const LibertySimpleAttr *attr = group->findSimpleAttr(attr_name); + if (attr) { + const LibertyAttrValue &attr_value = attr->value(); + if (attr_value.isString()) { + const std::string &value = attr_value.stringValue(); + if (stringEqual(value.c_str(), "true")) + (cell->*set_func)(true); + else if (stringEqual(value.c_str(), "false")) + (cell->*set_func)(false); + else + libWarn(1279, attr, "%s attribute is not boolean.", attr_name); + } + else + libWarn(1280, attr, "%s attribute is not boolean.", attr_name); + } +} + +//////////////////////////////////////////////////////////////// + +void +LibertyReader::makeTimingArcs(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + for (const LibertyGroup *timing_group : port_group->findSubgroups("timing")) { + TimingArcAttrsPtr timing_attrs = std::make_shared(); + readTimingArcAttrs(cell, timing_group, timing_attrs); + makeTimingModels(cell, timing_group, timing_attrs); + + LibertyPort *related_output_port = findLibertyPort(cell, timing_group, + "related_output_pin"); + StdStringSeq related_port_names = findAttributStrings(timing_group, "related_pin"); + StdStringSeq related_bus_names=findAttributStrings(timing_group,"related_bus_pins"); + TimingType timing_type = timing_attrs->timingType(); + + for (LibertyPort *to_port : ports) { + if (timing_type == TimingType::combinational && + to_port->direction()->isInput()) + libWarn(1209, timing_group, "combinational timing to an input port."); + + if (related_port_names.size() || related_bus_names.size()) { + for (const std::string &from_port_name : related_port_names) { + debugPrint(debug_, "liberty", 2, " timing %s -> %s", + from_port_name.c_str(), to_port->name()); + makeTimingArcs(cell, from_port_name, to_port, related_output_port, true, + timing_attrs, timing_group->line()); + } + for (const std::string &from_port_name : related_bus_names) { + debugPrint(debug_, "liberty", 2, " timing %s -> %s", + from_port_name.c_str(), to_port->name()); + makeTimingArcs(cell, from_port_name, to_port, related_output_port, false, + timing_attrs, timing_group->line()); + } + } + else if (!(timing_type == TimingType::min_pulse_width + || timing_type == TimingType::minimum_period + || timing_type == TimingType::min_clock_tree_path + || timing_type == TimingType::max_clock_tree_path)) + libWarn(1243, timing_group, "timing group missing related_pin/related_bus_pin."); + else + makeTimingArcs(cell, to_port, related_output_port, + timing_attrs, timing_group->line()); + } + } +} + +void +LibertyReader::readTimingArcAttrs(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + readTimingSense(timing_group, timing_attrs); + readTimingType(timing_group, timing_attrs); + readTimingWhen(cell, timing_group, timing_attrs); + readTimingMode(timing_group, timing_attrs); + readGroupAttrFloat("ocv_arc_depth", timing_group, + [timing_attrs](float v) { timing_attrs->setOcvArcDepth(v); }); +} + +void +LibertyReader::readGroupAttrFloat(const char *attr_name, + const LibertyGroup *group, + const std::function &set_func, + float scale) +{ + float value; + bool exists; + group->findAttrFloat(attr_name, value, exists); + if (exists) + set_func(value * scale); +} + +void +LibertyReader::readTimingSense(const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + const LibertySimpleAttr *sense_attr = timing_group->findSimpleAttr("timing_sense"); + if (sense_attr) { + const std::string *sense_name = sense_attr->stringValue(); + if (sense_name) { + if (*sense_name == "non_unate") + timing_attrs->setTimingSense(TimingSense::non_unate); + else if (*sense_name == "positive_unate") + timing_attrs->setTimingSense(TimingSense::positive_unate); + else if (*sense_name == "negative_unate") + timing_attrs->setTimingSense(TimingSense::negative_unate); + else + libWarn(1245, timing_group, "unknown timing_sense %s.", sense_name->c_str()); + } + } +} + +void +LibertyReader::readTimingType(const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + TimingType type = TimingType::combinational; + const LibertySimpleAttr *type_attr = timing_group->findSimpleAttr("timing_type"); + if (type_attr) { + const std::string *type_name = type_attr->stringValue(); + if (type_name) { + type = findTimingType(type_name->c_str()); + if (type == TimingType::unknown) { + libWarn(1244, type_attr, "unknown timing_type %s.", type_name->c_str()); + type = TimingType::combinational; + } + } + } + timing_attrs->setTimingType(type); +} + +void +LibertyReader::readTimingWhen(const LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + const LibertySimpleAttr *when_attr = timing_group->findSimpleAttr("when"); + if (when_attr) { + const std::string *when = when_attr->stringValue(); + if (when) { + FuncExpr *when_expr = parseFunc(when->c_str(), "when", cell, when_attr->line()); + timing_attrs->setCond(when_expr); + } + } + + const LibertySimpleAttr *cond_attr = timing_group->findSimpleAttr("sdf_cond"); + if (cond_attr) { + const std::string *cond = cond_attr->stringValue(); + if (cond) + timing_attrs->setSdfCond(cond->c_str()); + } + cond_attr = timing_group->findSimpleAttr("sdf_cond_start"); + if (cond_attr) { + const std::string *cond = cond_attr->stringValue(); + if (cond) + timing_attrs->setSdfCondStart(cond->c_str()); + } + cond_attr = timing_group->findSimpleAttr("sdf_cond_end"); + if (cond_attr) { + const std::string *cond = cond_attr->stringValue(); + if (cond) + timing_attrs->setSdfCondEnd(cond->c_str()); + } +} + +void +LibertyReader::readTimingMode(const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + const LibertyComplexAttrSeq &mode_attrs = timing_group->findComplexAttrs("mode"); + if (!mode_attrs.empty()) { + const LibertyComplexAttr *mode_attr = mode_attrs[0]; + const LibertyAttrValueSeq &mode_values = mode_attr->values(); + if (mode_values.size() == 2) { + LibertyAttrValue *value = mode_values[0]; + if (value->isString()) + timing_attrs->setModeName(value->stringValue()); + else + libWarn(1248, mode_attr, "mode name is not a string."); + + value = mode_values[1]; + if (value->isString()) + timing_attrs->setModeValue(value->stringValue()); + else + libWarn(1246, mode_attr, "mode value is not a string."); + } + else + libWarn(1249, mode_attr, "mode requirees 2 values."); + } +} + +void +LibertyReader::makeTimingModels(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + switch (cell->libertyLibrary()->delayModelType()) { + case DelayModelType::cmos_linear: + makeLinearModels(cell, timing_group, timing_attrs); + break; + case DelayModelType::table: + makeTableModels(cell, timing_group, timing_attrs); + break; + case DelayModelType::cmos_pwl: + case DelayModelType::cmos2: + case DelayModelType::polynomial: + case DelayModelType::dcm: + break; + } +} + +void +LibertyReader::makeLinearModels(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + LibertyLibrary *library = cell->libertyLibrary(); + for (const RiseFall *rf : RiseFall::range()) { + std::string intr_attr_name = "intrinsic_" + rf->to_string_long(); + float intr = 0.0; + bool intr_exists; + timing_group->findAttrFloat(intr_attr_name, intr, intr_exists); + if (intr_exists) + intr *= time_scale_; + else + library->defaultIntrinsic(rf, intr, intr_exists); + TimingModel *model = nullptr; + if (intr_exists) { + if (timingTypeIsCheck(timing_attrs->timingType())) + model = new CheckLinearModel(cell, intr); + else { + std::string res_attr_name = rf->to_string_long() + "_resistance"; + float res = 0.0; + bool res_exists; + timing_group->findAttrFloat(res_attr_name, res, res_exists); + if (res_exists) + res *= res_scale_; + else + library->defaultPinResistance(rf, PortDirection::output(), + res, res_exists); + model = new GateLinearModel(cell, intr, res); + } + timing_attrs->setModel(rf, model); + } + } +} + +void +LibertyReader::makeTableModels(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs) +{ + for (const RiseFall *rf : RiseFall::range()) { + std::string delay_attr_name = "cell_" + rf->to_string_long(); + TableModel *delay = readGateTableModel(timing_group, delay_attr_name.c_str(), rf, + TableTemplateType::delay, time_scale_, + ScaleFactorType::cell); + std::string transition_attr_name = rf->to_string_long() + "_transition"; + TableModel *transition = readGateTableModel(timing_group, + transition_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::transition); + if (delay || transition) { + std::string delay_sigma_attr_name = "ocv_sigma_cell_" + rf->to_string_long(); + TableModelsEarlyLate delay_sigmas = + readEarlyLateTableModels(timing_group, + delay_sigma_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::unknown); + + std::string slew_sigma_attr_name = "ocv_sigma_" + rf->to_string_long() + + "_transition"; + TableModelsEarlyLate slew_sigmas = + readEarlyLateTableModels(timing_group, + slew_sigma_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::unknown); + + ReceiverModelPtr receiver_model = readReceiverCapacitance(timing_group, rf); + OutputWaveforms *output_waveforms = readOutputWaveforms(timing_group, rf); + + timing_attrs->setModel(rf, new GateTableModel(cell, delay, + std::move(delay_sigmas), + transition, + std::move(slew_sigmas), + receiver_model, + output_waveforms)); + TimingType timing_type = timing_attrs->timingType(); + if (isGateTimingType(timing_type)) { + if (transition == nullptr) + libWarn(1210, timing_group, "missing %s_transition.", rf->name()); + if (delay == nullptr) + libWarn(1211, timing_group, "missing cell_%s.", rf->name()); + } + } + + std::string constraint_attr_name = rf->to_string_long() + "_constraint"; + ScaleFactorType scale_factor_type = + timingTypeScaleFactorType(timing_attrs->timingType()); + TableModel *constraint = readCheckTableModel(timing_group, + constraint_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, scale_factor_type); + if (constraint) { + std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string_long() + + "_constraint"; + TableModelsEarlyLate constraint_sigmas = + readEarlyLateTableModels(timing_group, + constraint_sigma_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::unknown); + timing_attrs->setModel(rf, new CheckTableModel(cell, constraint, + std::move(constraint_sigmas))); + } + } +} + +bool +LibertyReader::isGateTimingType(TimingType timing_type) +{ + return timing_type == TimingType::clear + || timing_type == TimingType::combinational + || timing_type == TimingType::combinational_fall + || timing_type == TimingType::combinational_rise + || timing_type == TimingType::falling_edge + || timing_type == TimingType::preset + || timing_type == TimingType::rising_edge + || timing_type == TimingType::three_state_disable + || timing_type == TimingType::three_state_disable_rise + || timing_type == TimingType::three_state_disable_fall + || timing_type == TimingType::three_state_enable + || timing_type == TimingType::three_state_enable_fall + || timing_type == TimingType::three_state_enable_rise; +} + +TableModel * +LibertyReader::readGateTableModel(const LibertyGroup *timing_group, + const char *table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type) +{ + const LibertyGroup *table_group = timing_group->findSubgroup(table_group_name); + if (table_group) { + TableModel *model = readTableModel(table_group, rf, template_type, scale, + scale_factor_type); + if (model && !GateTableModel::checkAxes(model)) + libWarn(1251, table_group, "unsupported model axis."); + return model; + } + return nullptr; +} + +TableModel * +LibertyReader::readCheckTableModel(const LibertyGroup *timing_group, + const char *table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type) +{ + const LibertyGroup *table_group = timing_group->findSubgroup(table_group_name); + if (table_group) { + TableModel *model = readTableModel(table_group, rf, template_type, scale, + scale_factor_type); + if (model && !CheckTableModel::checkAxes(model)) + libWarn(1252, table_group, "unsupported model axis."); + return model; + } + return nullptr; +} + +TableModelsEarlyLate +LibertyReader::readEarlyLateTableModels(const LibertyGroup *timing_group, + const char *table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type) +{ + TableModelsEarlyLate models{}; + for (const LibertyGroup *table_group : timing_group->findSubgroups(table_group_name)) { + TableModel *model = readTableModel(table_group, rf, template_type, scale, + scale_factor_type); + const std::string *early_late = table_group->findAttrString("sigma_type"); + if (early_late == nullptr + || *early_late == "early_and_late") { + models[EarlyLate::early()->index()] = model; + models[EarlyLate::late()->index()] = model; + } + else if (*early_late == "early") + models[EarlyLate::early()->index()] = model; + else if (*early_late == "late") + models[EarlyLate::late()->index()] = model; + + //if (model && !GateTableModel::checkAxes(model)) + // libWarn(1182, table_group, "unsupported model axis."); + } + return models; +} + +ReceiverModelPtr +LibertyReader::readReceiverCapacitance(const LibertyGroup *timing_group, + const RiseFall *rf) +{ + ReceiverModelPtr receiver_model = nullptr; + readReceiverCapacitance(timing_group, "receiver_capacitance", 0, rf, + receiver_model); + readReceiverCapacitance(timing_group, "receiver_capacitance1", 0, rf, + receiver_model); + readReceiverCapacitance(timing_group, "receiver_capacitance2", 1, rf, + receiver_model); + return receiver_model; +} + +void +LibertyReader::readReceiverCapacitance(const LibertyGroup *timing_group, + const char *cap_group_name, + int index, + const RiseFall *rf, + ReceiverModelPtr &receiver_model) +{ + std::string cap_group_name1 = cap_group_name; + cap_group_name1 += "_" + rf->to_string_long(); + const LibertyGroup *cap_group = timing_group->findSubgroup(cap_group_name1); + if (cap_group) { + const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment"); + if (segment_attr) { + // For receiver_capacitance groups with mulitiple segments this + // overrides the index passed in beginReceiverCapacitance1Rise/Fall. + int segment; + bool exists; + getAttrInt(segment_attr, segment, exists); + if (exists) + index = segment; + } + TableModel *model = readTableModel(cap_group, rf, TableTemplateType::delay, + cap_scale_, ScaleFactorType::pin_cap); + if (ReceiverModel::checkAxes(model)) { + if (receiver_model == nullptr) + receiver_model = std::make_shared(); + receiver_model->setCapacitanceModel(std::move(*model), index, rf); + } + else + libWarn(1219, cap_group, "unsupported model axis."); + delete model; + } +} + +OutputWaveforms * +LibertyReader::readOutputWaveforms(const LibertyGroup *timing_group, + const RiseFall *rf) +{ + const std::string current_group_name = "output_current_" + rf->to_string_long(); + const LibertyGroup *current_group = timing_group->findSubgroup(current_group_name); + if (current_group) { + OutputWaveformSeq output_currents; + for (const LibertyGroup *vector_group : current_group->findSubgroups("vector")) { + float ref_time; + bool ref_time_exists; + vector_group->findAttrFloat("reference_time", ref_time, ref_time_exists); + if (ref_time_exists) { + ref_time *= time_scale_; + TableModel *table = readTableModel(vector_group, rf, + TableTemplateType::output_current, + current_scale_, ScaleFactorType::unknown); + if (table) { + TableTemplate *tbl_template = table->tblTemplate(); + const TableAxis *slew_axis, *cap_axis; + // Canonicalize axis order. + if (tbl_template->axis1()->variable()==TableAxisVariable::input_net_transition){ + slew_axis = table->axis1(); + cap_axis = table->axis2(); + } + else { + slew_axis = table->axis2(); + cap_axis = table->axis1(); + } + + if (slew_axis->size() == 1 && cap_axis->size() == 1) { + // Convert 1x1xN Table (order 3) to 1D Table. + float slew = slew_axis->axisValue(0); + float cap = cap_axis->axisValue(0); + TablePtr table_ptr = table->table(); + FloatTable *values3 = table_ptr->values3(); + FloatSeq row = std::move((*values3)[0]); + values3->erase(values3->begin()); + Table *table1 = new Table(std::move(row), table->table()->axis3ptr()); + output_currents.emplace_back(slew, cap, table1, ref_time); + } + else + libWarn(1223, vector_group, + "vector index_1 and index_2 must have exactly one value."); + } + delete table; + } + else + libWarn(1224, vector_group, "vector reference_time not found."); + } + if (!output_currents.empty()) + return makeOutputWaveforms(current_group, output_currents, rf); + } + return nullptr; +} + +OutputWaveforms * +LibertyReader::makeOutputWaveforms(const LibertyGroup *current_group, + OutputWaveformSeq &output_currents, + const RiseFall *rf) +{ + std::set slew_set, cap_set; + FloatSeq slew_values; + FloatSeq cap_values; + for (const OutputWaveform &waveform : output_currents) { + float slew = waveform.slew(); + // Filter duplilcate slews and capacitances. + if (!slew_set.contains(slew)) { + slew_set.insert(slew); + slew_values.push_back(slew); + } + float cap = waveform.cap(); + if (!cap_set.contains(cap)) { + cap_set.insert(cap); + cap_values.push_back(cap); + } + } + sort(slew_values, std::less()); + sort(cap_values, std::less()); + size_t slew_size = slew_values.size(); + size_t cap_size = cap_values.size(); + TableAxisPtr slew_axis = + make_shared(TableAxisVariable::input_net_transition, + std::move(slew_values)); + TableAxisPtr cap_axis = + make_shared(TableAxisVariable::total_output_net_capacitance, + std::move(cap_values)); + FloatSeq ref_times(slew_size); + Table1Seq current_waveforms(slew_size * cap_size); + for (OutputWaveform &waveform : output_currents) { + size_t slew_index, cap_index; + bool slew_exists, cap_exists; + slew_axis->findAxisIndex(waveform.slew(), slew_index, slew_exists); + cap_axis->findAxisIndex(waveform.cap(), cap_index, cap_exists); + if (slew_exists && cap_exists) { + size_t index = slew_index * cap_axis->size() + cap_index; + current_waveforms[index] = waveform.releaseCurrents(); + ref_times[slew_index] = waveform.referenceTime(); + } + else + libWarn(1221, current_group, "output current waveform %.2e %.2e not found.", + waveform.slew(), + waveform.cap()); + } + Table ref_time_tbl(std::move(ref_times), slew_axis); + OutputWaveforms *output_current = new OutputWaveforms(slew_axis, cap_axis, rf, + current_waveforms, + std::move(ref_time_tbl)); + return output_current; +} + +TableModel * +LibertyReader::readTableModel(const LibertyGroup *table_group, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type) +{ + const char *template_name = table_group->firstName(); + if (library_ && template_name) { + TableTemplate *tbl_template = library_->findTableTemplate(template_name, + template_type); + if (tbl_template) { + TablePtr table = readTableModel(table_group, tbl_template, scale); + if (table) { + TableModel *table_model = new TableModel(table, tbl_template, + scale_factor_type, rf); + return table_model; + } + } + else + libWarn(1253, table_group, "table template %s not found.", template_name); + } + return nullptr; +} + +TablePtr +LibertyReader::readTableModel(const LibertyGroup *table_group, + const TableTemplate *tbl_template, + float scale) +{ + const LibertyComplexAttr *values_attr = table_group->findComplexAttr("values"); + if (values_attr) { + TableAxisPtr axis1 = makeTableAxis(table_group, "index_1", tbl_template->axis1ptr()); + TableAxisPtr axis2 = makeTableAxis(table_group, "index_2", tbl_template->axis2ptr()); + TableAxisPtr axis3 = makeTableAxis(table_group, "index_3", tbl_template->axis3ptr()); + if (axis1 && axis2 && axis3) { + // 3D table + FloatTable float_table = makeFloatTable(values_attr, table_group, + axis1->size() * axis2->size(), + axis3->size(), scale); + return make_shared(std::move(float_table), axis1, axis2, axis3); + } + else if (axis1 && axis2) { + FloatTable float_table = makeFloatTable(values_attr, table_group, + axis1->size(), axis2->size(), scale); + return make_shared
(std::move(float_table), axis1, axis2); + } + else if (axis1) { + FloatTable table = makeFloatTable(values_attr, table_group, 1, + axis1->size(), scale); + return make_shared
(std::move(table[0]), axis1); + } + else if (axis1 == nullptr && axis2 == nullptr && axis3 == nullptr) { + FloatTable table = makeFloatTable(values_attr, table_group, 1, 1, scale); + float value = table[0][0]; + return std::make_shared
(value); + } + } + else + libWarn(1257, table_group, "%s is missing values.", table_group->type().c_str()); + return nullptr; +} + +TableAxisPtr +LibertyReader::makeTableAxis(const LibertyGroup *table_group, + const char *index_attr_name, + TableAxisPtr template_axis) +{ + const LibertyComplexAttr *index_attr = table_group->findComplexAttr(index_attr_name); + if (index_attr) { + FloatSeq axis_values = readFloatSeq(index_attr, 1.0F); if (axis_values.empty()) - libWarn(1177, attr, "missing table index values."); + libWarn(1177, index_attr, "missing table index values."); else { // Check monotonicity of the values. float prev = axis_values[0]; for (size_t i = 1; i < axis_values.size(); i++) { float value = axis_values[i]; if (value <= prev) - libWarn(1178, attr, "non-increasing table index values."); + libWarn(1173, index_attr, "non-increasing table index values."); prev = value; } - axis_values_[index] = std::move(axis_values); + + TableAxisVariable axis_var = template_axis->variable(); + const Units *units = library_->units(); + float scale = tableVariableUnit(axis_var, units)->scale(); + scaleFloats(axis_values, scale); + return make_shared(axis_var, std::move(axis_values)); } } + return template_axis; } //////////////////////////////////////////////////////////////// void -LibertyReader::beginType(LibertyGroup *) +LibertyReader::makeTimingArcs(LibertyCell *cell, + const std::string &from_port_name, + LibertyPort *to_port, + LibertyPort *related_out_port, + bool one_to_one, + TimingArcAttrsPtr timing_attrs, + int timing_line) { - type_bit_from_exists_ = false; - type_bit_to_exists_ = false; -} - -void -LibertyReader::endType(LibertyGroup *group) -{ - const char *name = group->firstName(); - if (name) { - if (type_bit_from_exists_ && type_bit_to_exists_) { - if (cell_) - cell_->makeBusDcl(name, type_bit_from_, type_bit_to_); - else if (library_) - library_->makeBusDcl(name, type_bit_from_, type_bit_to_); + PortNameBitIterator from_port_iter(cell, from_port_name.c_str(), this, timing_line); + if (from_port_iter.size() == 1 && !to_port->hasMembers()) { + // one -> one + if (from_port_iter.hasNext()) { + LibertyPort *from_port = from_port_iter.next(); + if (from_port->direction()->isOutput()) + libWarn(1212, timing_line, "timing group from output port."); + builder_.makeTimingArcs(cell, from_port, to_port, related_out_port, + timing_attrs, timing_line); + } + } + else if (from_port_iter.size() > 1 && !to_port->hasMembers()) { + // bus -> one + while (from_port_iter.hasNext()) { + LibertyPort *from_port = from_port_iter.next(); + if (from_port->direction()->isOutput()) + libWarn(1213, timing_line, "timing group from output port."); + builder_.makeTimingArcs(cell, from_port, to_port, related_out_port, + timing_attrs, timing_line); + } + } + else if (from_port_iter.size() == 1 && to_port->hasMembers()) { + // one -> bus + if (from_port_iter.hasNext()) { + LibertyPort *from_port = from_port_iter.next(); + if (from_port->direction()->isOutput()) + libWarn(1214, timing_line, "timing group from output port."); + LibertyPortMemberIterator bit_iter(to_port); + while (bit_iter.hasNext()) { + LibertyPort *to_port_bit = bit_iter.next(); + builder_.makeTimingArcs(cell, from_port, to_port_bit, related_out_port, + timing_attrs, timing_line); + } + } + } + else { + // bus -> bus + if (one_to_one) { + int from_size = from_port_iter.size(); + int to_size = to_port->size(); + LibertyPortMemberIterator to_port_iter(to_port); + // warn about different sizes + if (from_size != to_size) + libWarn(1216, timing_line, + "timing port %s and related port %s are different sizes.", + from_port_name.c_str(), + to_port->name()); + // align to/from iterators for one-to-one mapping + while (from_size > to_size) { + from_size--; + from_port_iter.next(); + } + while (to_size > from_size) { + to_size--; + to_port_iter.next(); + } + // make timing arcs + while (from_port_iter.hasNext() && to_port_iter.hasNext()) { + LibertyPort *from_port_bit = from_port_iter.next(); + LibertyPort *to_port_bit = to_port_iter.next(); + if (from_port_bit->direction()->isOutput()) + libWarn(1215, timing_line, "timing group from output port."); + builder_.makeTimingArcs(cell, from_port_bit, to_port_bit, + related_out_port, timing_attrs, + timing_line); + } } else { - if (!type_bit_from_exists_) - libWarn(1179, group, "bus type %s missing bit_from.", name); - if (!type_bit_to_exists_) - libWarn(1180, group, "bus type %s missing bit_to.", name); - } - } - else - libWarn(1181, group, "type missing name."); -} - -void -LibertyReader::visitBitFrom(LibertyAttr *attr) -{ - getAttrInt(attr, type_bit_from_, type_bit_from_exists_); -} - -void -LibertyReader::visitBitTo(LibertyAttr *attr) -{ - getAttrInt(attr, type_bit_to_, type_bit_to_exists_); -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginScalingFactors(LibertyGroup *group) -{ - const char *name = group->firstName(); - if (name) { - save_scale_factors_ = scale_factors_; - scale_factors_ = library_->makeScaleFactors(name); - } - else - libWarn(1182, group, "scaling_factors do not have a name."); -} - -void -LibertyReader::endScalingFactors(LibertyGroup *) -{ - scale_factors_ = save_scale_factors_; -} - -void -LibertyReader::visitScaleFactorSuffix(LibertyAttr *attr) -{ - if (scale_factors_) { - ScaleFactorPvt pvt = ScaleFactorPvt::unknown; - ScaleFactorType type = ScaleFactorType::unknown; - const RiseFall *rf = nullptr; - // Parse the attribute name. - TokenParser parser(attr->name().c_str(), "_"); - if (parser.hasNext()) - parser.next(); - if (parser.hasNext()) { - const char *pvt_name = parser.next(); - pvt = findScaleFactorPvt(pvt_name); - } - if (parser.hasNext()) { - const char *type_name = parser.next(); - type = findScaleFactorType(type_name); - } - if (parser.hasNext()) { - const char *tr_name = parser.next(); - if (stringEq(tr_name, "rise")) - rf = RiseFall::rise(); - else if (stringEq(tr_name, "fall")) - rf = RiseFall::fall(); - } - if (pvt != ScaleFactorPvt::unknown - && type != ScaleFactorType::unknown - && rf) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - scale_factors_->setScale(type, pvt, rf, value); - } - } -} - -void -LibertyReader::visitScaleFactorPrefix(LibertyAttr *attr) -{ - if (scale_factors_) { - ScaleFactorPvt pvt = ScaleFactorPvt::unknown; - ScaleFactorType type = ScaleFactorType::unknown; - const RiseFall *rf = nullptr; - // Parse the attribute name. - TokenParser parser(attr->name().c_str(), "_"); - if (parser.hasNext()) - parser.next(); - if (parser.hasNext()) { - const char *pvt_name = parser.next(); - pvt = findScaleFactorPvt(pvt_name); - } - if (parser.hasNext()) { - const char *tr_name = parser.next(); - if (stringEq(tr_name, "rise")) - rf = RiseFall::rise(); - else if (stringEq(tr_name, "fall")) - rf = RiseFall::fall(); - } - if (parser.hasNext()) { - const char *type_name = parser.next(); - type = findScaleFactorType(type_name); - } - if (pvt != ScaleFactorPvt::unknown - && type != ScaleFactorType::unknown - && rf) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - scale_factors_->setScale(type, pvt, rf, value); - } - } -} - -void -LibertyReader::visitScaleFactorHiLow(LibertyAttr *attr) -{ - if (scale_factors_) { - ScaleFactorPvt pvt = ScaleFactorPvt::unknown; - ScaleFactorType type = ScaleFactorType::unknown; - const RiseFall *rf = nullptr; - const char *pvt_name = nullptr; - const char *type_name = nullptr; - const char *tr_name = nullptr; - // Parse the attribute name. - TokenParser parser(attr->name().c_str(), "_"); - if (parser.hasNext()) - parser.next(); - if (parser.hasNext()) { - pvt_name = parser.next(); - pvt = findScaleFactorPvt(pvt_name); - } - if (parser.hasNext()) { - type_name = parser.next(); - type = findScaleFactorType(type_name); - } - if (parser.hasNext()) { - tr_name = parser.next(); - if (stringEq(tr_name, "high")) - rf = RiseFall::rise(); - else if (stringEq(tr_name, "low")) - rf = RiseFall::fall(); - } - if (pvt != ScaleFactorPvt::unknown - && type != ScaleFactorType::unknown - && rf) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - scale_factors_->setScale(type, pvt, rf, value); - } - } -} - -void -LibertyReader::visitScaleFactor(LibertyAttr *attr) -{ - if (scale_factors_) { - ScaleFactorPvt pvt = ScaleFactorPvt::unknown; - ScaleFactorType type = ScaleFactorType::unknown; - const char *pvt_name = nullptr; - const char *type_name = nullptr; - // Parse the attribute name. - TokenParser parser(attr->name().c_str(), " "); - if (parser.hasNext()) - parser.next(); - if (parser.hasNext()) { - pvt_name = parser.next(); - pvt = findScaleFactorPvt(pvt_name); - } - if (parser.hasNext()) { - type_name = parser.next(); - type = findScaleFactorType(type_name); - } - if (pvt != ScaleFactorPvt::unknown - && type != ScaleFactorType::unknown) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - scale_factors_->setScale(type, pvt, value); - } - } -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginOpCond(LibertyGroup *group) -{ - if (library_) { - const char *name = group->firstName(); - if (name) - op_cond_ = library_->makeOperatingConditions(name); - else - libWarn(1183, group, "operating_conditions missing name."); - } -} - -void -LibertyReader::visitProc(LibertyAttr *attr) -{ - if (op_cond_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - op_cond_->setProcess(value); - } -} - -void -LibertyReader::visitVolt(LibertyAttr *attr) -{ - if (op_cond_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - op_cond_->setVoltage(value * volt_scale_); - } -} - -void -LibertyReader::visitTemp(LibertyAttr *attr) -{ - if (op_cond_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - op_cond_->setTemperature(value); - } -} - -void -LibertyReader::visitTreeType(LibertyAttr *attr) -{ - if (op_cond_) { - const char *tree_type = getAttrString(attr); - if (tree_type) { - WireloadTree wire_load_tree = stringWireloadTree(tree_type); - op_cond_->setWireloadTree(wire_load_tree); - } - } -} - -void -LibertyReader::endOpCond(LibertyGroup *) -{ - op_cond_ = nullptr; -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginWireload(LibertyGroup *group) -{ - if (library_) { - const char *name = group->firstName(); - if (name) - wireload_ = library_->makeWireload(name); - } - else - libWarn(1184, group, "wire_load missing name."); -} - -void -LibertyReader::endWireload(LibertyGroup *) -{ - wireload_ = nullptr; -} - -void -LibertyReader::visitResistance(LibertyAttr *attr) -{ - if (wireload_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - wireload_->setResistance(value * res_scale_); - } -} - -void -LibertyReader::visitSlope(LibertyAttr *attr) -{ - if (wireload_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - wireload_->setSlope(value); - } -} - -void -LibertyReader::visitFanoutLength(LibertyAttr *attr) -{ - if (wireload_) { - float fanout, length; - bool exists; - getAttrFloat2(attr, fanout, length, exists); - if (exists) - wireload_->addFanoutLength(fanout, length); - else - libWarn(1185, attr, "fanout_length is missing length and fanout."); - } -} - -void -LibertyReader::beginWireloadSelection(LibertyGroup *group) -{ - if (library_) { - const char *name = group->firstName(); - if (name) - wireload_selection_ = library_->makeWireloadSelection(name); - } - else - libWarn(1186, group, "wire_load_selection missing name."); -} - -void -LibertyReader::endWireloadSelection(LibertyGroup *) -{ - wireload_selection_ = nullptr; -} - -void -LibertyReader::visitWireloadFromArea(LibertyAttr *attr) -{ - if (wireload_selection_) { - if (attr->isComplexAttr()) { - LibertyAttrValueSeq *values = attr->values(); - if (values->size() == 3) { - LibertyAttrValue *value = (*values)[0]; - if (value->isFloat()) { - float min_area = value->floatValue(); - value = (*values)[1]; - if (value->isFloat()) { - float max_area = value->floatValue(); - - value = (*values)[2]; - if (value->isString()) { - const std::string &wireload_name = value->stringValue(); - const Wireload *wireload = - library_->findWireload(wireload_name.c_str()); - if (wireload) - wireload_selection_->addWireloadFromArea(min_area, max_area, - wireload); - else - libWarn(1187, attr, "wireload %s not found.", wireload_name.c_str()); - } - else - libWarn(1188, attr, - "wire_load_from_area wireload name not a string."); - } - else - libWarn(1189, attr, "wire_load_from_area min not a float."); + // cross product + while (from_port_iter.hasNext()) { + LibertyPort *from_port_bit = from_port_iter.next(); + LibertyPortMemberIterator to_port_iter(to_port); + while (to_port_iter.hasNext()) { + LibertyPort *to_port_bit = to_port_iter.next(); + builder_.makeTimingArcs(cell, from_port_bit, to_port_bit, + related_out_port, timing_attrs, + timing_line); } - else - libWarn(1190, attr, "wire_load_from_area max not a float."); } - else - libWarn(1191, attr, "wire_load_from_area missing parameters."); } - else - libWarn(1192, attr, "wire_load_from_area missing parameters."); } } +void +LibertyReader::makeTimingArcs(LibertyCell *cell, + LibertyPort *to_port, + LibertyPort *related_out_port, + TimingArcAttrsPtr timing_attrs, + int timing_line) +{ + if (to_port->hasMembers()) { + LibertyPortMemberIterator bit_iter(to_port); + while (bit_iter.hasNext()) { + LibertyPort *to_port_bit = bit_iter.next(); + builder_.makeTimingArcs(cell, nullptr, to_port_bit, + related_out_port, timing_attrs, + timing_line); + } + } + else + builder_.makeTimingArcs(cell, nullptr, to_port, + related_out_port, timing_attrs, + timing_line); +} + //////////////////////////////////////////////////////////////// void -LibertyReader::beginCell(LibertyGroup *group) +LibertyReader::readLeagageGrouops(LibertyCell *cell, + const LibertyGroup *cell_group) { - const char *name = group->firstName(); - if (name) { - debugPrint(debug_, "liberty", 1, "cell %s", name); - if (library_) { - cell_ = builder_.makeCell(library_, name, filename_); - in_bus_ = false; - in_bundle_ = false; - } - } - else - libWarn(1193, group, "cell missing name."); -} - -void -LibertyReader::endCell(LibertyGroup *group) -{ - if (cell_) { - // Sequentials and leakage powers reference expressions outside of port definitions - // so they do not require LibertyFunc's. - makeCellSequentials(); - makeStatetable(); - // Parse functions defined inside of port groups that reference other ports - // and replace the references with the parsed expressions. - parseCellFuncs(); - makeLeakagePowers(); - finishPortGroups(); - - if (ocv_derate_name_) { - OcvDerate *derate = cell_->findOcvDerate(ocv_derate_name_); - if (derate == nullptr) - derate = library_->findOcvDerate(ocv_derate_name_); - if (derate) - cell_->setOcvDerate(derate); - else - libWarn(1194, group, "cell %s ocv_derate_group %s not found.", - cell_->name(), ocv_derate_name_); - stringDelete(ocv_derate_name_); - ocv_derate_name_ = nullptr; - } - cell_->finish(infer_latches_, report_, debug_); - cell_ = nullptr; - } -} - -void -LibertyReader::finishPortGroups() -{ - for (PortGroup *port_group : cell_port_groups_) { - int line = port_group->line(); - for (LibertyPort *port : *port_group->ports()) { - checkPort(port, line); - makeMinPulseWidthArcs(port, line); - } - makeTimingArcs(port_group); - makeInternalPowers(port_group); - delete port_group; - } - cell_port_groups_.clear(); -} - -void -LibertyReader::checkPort(LibertyPort *port, - int line) -{ - FuncExpr *func_expr = port->function(); - if (func_expr) { - if (func_expr->checkSize(port)) { - libWarn(1195, line, "port %s function size does not match port size.", - port->name()); - } - } - if (port->tristateEnable() - && port->direction() == PortDirection::output()) - port->setDirection(PortDirection::tristate()); -} - -// Make timing arcs for the port min_pulse_width_low/high attributes. -// This is redundant but makes sdf annotation consistent. -void -LibertyReader::makeMinPulseWidthArcs(LibertyPort *port, - int line) -{ - TimingArcAttrsPtr attrs = nullptr; - for (auto hi_low : RiseFall::range()) { - float min_width; + for (const LibertyGroup *leak_group : cell_group->findSubgroups("leakage_power")) { + FuncExpr *when = readFuncExpr(cell, leak_group, "when"); + float power; bool exists; - port->minPulseWidth(hi_low, min_width, exists); + leak_group->findAttrFloat("value", power, exists); if (exists) { - if (attrs == nullptr) { - attrs = make_shared(); - attrs->setTimingType(TimingType::min_pulse_width); + LibertyPort *related_pg_port = findLibertyPort(cell, leak_group, "related_pg_pin"); + cell->makeLeakagePower(related_pg_port, when, power * power_scale_); + } + else + libWarn(1307, leak_group, "leakage_power missing value."); + } +} + +void +LibertyReader::readInternalPowerGroups(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group) +{ + for (LibertyPort *port : ports) { + for (const LibertyGroup *ipwr_group : port_group->findSubgroups("internal_power")) { + LibertyPortSeq related_ports = findLibertyPorts(cell, ipwr_group, "related_pin"); + LibertyPort *related_pg_port = findLibertyPort(cell, ipwr_group, "related_pg_pin"); + std::shared_ptr when; + FuncExpr *when1 = readFuncExpr(cell, ipwr_group, "when"); + if (when1) + when = std::shared_ptr(when1); + InternalPowerModels models; + // rise/fall_power group + for (const RiseFall *rf : RiseFall::range()) { + std::string pwr_attr_name = rf->to_string_long() + "_power"; + const LibertyGroup *pwr_group = ipwr_group->findSubgroup(pwr_attr_name); + if (pwr_group) { + TableModel *model = readTableModel(pwr_group, rf, TableTemplateType::power, + energyScale(), + ScaleFactorType::internal_power); + models[rf->index()] = std::make_shared(model); + } + } + // power group (rise/fall power are the same) + const LibertyGroup *pwr_group = ipwr_group->findSubgroup("power"); + if (pwr_group) { + TableModel *model = readTableModel(pwr_group, RiseFall::rise(), + TableTemplateType::power, + energyScale(), + ScaleFactorType::internal_power); + auto pwr_model = std::make_shared(model); + for (const RiseFall *rf : RiseFall::range()) + models[rf->index()] = pwr_model; + } + if (related_ports.empty()) + cell->makeInternalPower(port, nullptr, related_pg_port, when, models); + else { + for (LibertyPort *related_port : related_ports) + cell->makeInternalPower(port, related_port, related_pg_port, when, models); } - // rise/fall_constraint model is on the leading edge of the pulse. - const RiseFall *model_rf = hi_low; - TimingModel *check_model = - makeScalarCheckModel(min_width, ScaleFactorType::min_pulse_width, model_rf); - attrs->setModel(model_rf, check_model); } } - if (attrs) - builder_.makeTimingArcs(cell_, port, port, nullptr, attrs, line); } +//////////////////////////////////////////////////////////////// + +FuncExpr * +LibertyReader::readFuncExpr(LibertyCell *cell, + const LibertyGroup *group, + const char *attr_name) +{ + const std::string *attr = group->findAttrString(attr_name); + if (attr) + return parseFunc(attr->c_str(), attr_name, cell, group->line()); + else + return nullptr; +} + +LibertyPort * +LibertyReader::findLibertyPort(LibertyCell *cell, + const LibertyGroup *group, + const char *port_name_attr) +{ + const LibertySimpleAttr *attr = group->findSimpleAttr(port_name_attr); + if (attr) { + const std::string *port_name = attr->stringValue(); + if (port_name) { + LibertyPort *port = cell->findLibertyPort(port_name->c_str()); + if (port) + return port; + else + libWarn(1290, attr, "port %s not found.", port_name->c_str()); + } + } + return nullptr; +} + +StdStringSeq +LibertyReader::findAttributStrings(const LibertyGroup *group, + const char *name_attr) +{ + const LibertySimpleAttr *attr = group->findSimpleAttr(name_attr); + if (attr) { + const std::string *strings = attr->stringValue(); + if (strings) { + return parseTokens(*strings, ' '); + } + } + return StdStringSeq(); +} + +LibertyPortSeq +LibertyReader::findLibertyPorts(LibertyCell *cell, + const LibertyGroup *group, + const char *port_name_attr) +{ + LibertyPortSeq ports; + StdStringSeq port_names = findAttributStrings(group, port_name_attr); + for (const std::string &port_name : port_names) { + LibertyPort *port = findPort(cell, port_name.c_str()); + if (port) + ports.push_back(port); + else + libWarn(1306, group, "port %s not found.", port_name.c_str()); + } + return ports; +} + +//////////////////////////////////////////////////////////////// + TimingModel * -LibertyReader::makeScalarCheckModel(float value, +LibertyReader::makeScalarCheckModel(LibertyCell *cell, + float value, ScaleFactorType scale_factor_type, const RiseFall *rf) { - TablePtr table = make_shared
(value); + TablePtr table = std::make_shared
(value); TableTemplate *tbl_template = 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); + TableModelsEarlyLate sigmas{}; + CheckTableModel *check_model = new CheckTableModel(cell, table_model, + std::move(sigmas)); return check_model; } -void -LibertyReader::makeTimingArcs(PortGroup *port_group) -{ - for (TimingGroup *timing : port_group->timingGroups()) { - timing->makeTimingModels(cell_, this); - - for (LibertyPort *port : *port_group->ports()) - makeTimingArcs(port, timing); - } -} - -void -LibertyReader::makeInternalPowers(PortGroup *port_group) -{ - for (InternalPowerGroup *power_group : port_group->internalPowerGroups()) { - for (LibertyPort *port : *port_group->ports()) - makeInternalPowers(port, power_group); - } -} - -void -LibertyReader::makeCellSequentials() -{ - for (SequentialGroup *seq : cell_sequentials_) { - makeCellSequential(seq); - delete seq; - } - cell_sequentials_.clear(); -} - -void -LibertyReader::makeCellSequential(SequentialGroup *seq) -{ - int line = seq->line(); - int size = seq->size(); - bool is_register = seq->isRegister(); - bool is_bank = seq->isBank(); - const char *type = is_register - ? (is_bank ? "ff_bank" : "ff") - : (is_bank ? "latch_bank" : "latch"); - const char *clk = seq->clock(); - FuncExpr *clk_expr = nullptr; - if (clk) { - const char *clk_attr = is_register ? "clocked_on" : "enable"; - clk_expr = parseFunc(clk, clk_attr, line); - if (clk_expr && clk_expr->checkSize(size)) { - libWarn(1196, line, "%s %s bus width mismatch.", type, clk_attr); - delete clk_expr; - clk_expr = nullptr; - } - } - const char *data = seq->data(); - FuncExpr *data_expr = nullptr; - if (data) { - const char *data_attr = is_register ? "next_state" : "data_in"; - data_expr = parseFunc(data, data_attr, line); - if (data_expr && data_expr->checkSize(size)) { - libWarn(1197, line, "%s %s bus width mismatch.", type, data_attr); - delete data_expr; - data_expr = nullptr; - } - } - const char *clr = seq->clear(); - FuncExpr *clr_expr = nullptr; - if (clr) { - clr_expr = parseFunc(clr, "clear", line); - if (clr_expr && clr_expr->checkSize(size)) { - libWarn(1198, line, "%s %s bus width mismatch.", type, "clear"); - delete clr_expr; - clr_expr = nullptr; - } - } - const char *preset = seq->preset(); - FuncExpr *preset_expr = nullptr; - if (preset) { - preset_expr = parseFunc(preset, "preset", line); - if (preset_expr && preset_expr->checkSize(size)) { - libWarn(1199, line, "%s %s bus width mismatch.", type, "preset"); - delete preset_expr; - preset_expr = nullptr; - } - } - cell_->makeSequential(size, is_register, clk_expr, data_expr, clr_expr, - preset_expr, seq->clrPresetVar1(), - seq->clrPresetVar2(), - seq->outPort(), seq->outInvPort()); - if (!is_register) - checkLatchEnableSense(clk_expr, line); - - // The expressions used in the sequentials are copied by bitSubExpr. - delete clk_expr; - delete data_expr; - delete clr_expr; - delete preset_expr; -} - void LibertyReader::checkLatchEnableSense(FuncExpr *enable_func, int line) @@ -2202,1029 +2814,194 @@ LibertyReader::checkLatchEnableSense(FuncExpr *enable_func, //////////////////////////////////////////////////////////////// void -LibertyReader::makeStatetable() +LibertyReader::readNormalizedDriverWaveform(const LibertyGroup *library_group) { - if (statetable_) { - LibertyPortSeq input_ports; - for (const string &input : statetable_->inputPorts()) { - LibertyPort *port = cell_->findLibertyPort(input.c_str()); - if (port) - input_ports.push_back(port); - else - libWarn(1298, statetable_->line(), "statetable input port %s not found.", - input.c_str()); + for (const LibertyGroup *waveform_group : + library_group->findSubgroups("normalized_driver_waveform")) { + const char *template_name = waveform_group->firstName(); + if (template_name) { + TableTemplate *tbl_template = library_->findTableTemplate(template_name, + TableTemplateType::delay); + if (!tbl_template) { + libWarn(1256, waveform_group, "table template %s not found.", template_name); + continue; + } + TablePtr table = readTableModel(waveform_group, tbl_template, time_scale_); + if (!table) + continue; + if (table->axis1()->variable() != TableAxisVariable::input_net_transition) { + libWarn(1265, waveform_group, + "normalized_driver_waveform variable_1 must be input_net_transition"); + continue; + } + if (table->axis2()->variable() != TableAxisVariable::normalized_voltage) { + libWarn(1225, waveform_group, + "normalized_driver_waveform variable_2 must be normalized_voltage"); + continue; + } + std::string driver_waveform_name; + const std::string *name_attr = waveform_group->findAttrString("driver_waveform_name"); + if (name_attr) + driver_waveform_name = *name_attr; + library_->makeDriverWaveform(driver_waveform_name, table); } - LibertyPortSeq internal_ports; - for (const string &internal : statetable_->internalPorts()) { - LibertyPort *port = cell_->findLibertyPort(internal.c_str()); - if (port == nullptr) - port = makePort(cell_, internal.c_str()); - internal_ports.push_back(port); - } - cell_->makeStatetable(input_ports, internal_ports, statetable_->table()); - delete statetable_; - statetable_ = nullptr; + else + libWarn(1227, waveform_group, "normalized_driver_waveform missing template."); } } //////////////////////////////////////////////////////////////// void -LibertyReader::makeLeakagePowers() +LibertyReader::readLevelShifterType(LibertyCell *cell, + const LibertyGroup *cell_group) { - for (LeakagePowerGroup *power_group : leakage_powers_) { - LibertyPort *related_pg_pin = - cell_->findLibertyPort(power_group->relatedPgPin().c_str()); - cell_->makeLeakagePower(related_pg_pin, power_group->when(), power_group->power()); - delete power_group; + const std::string *level_shifter_type = cell_group->findAttrString("level_shifter_type"); + if (level_shifter_type) { + if (*level_shifter_type == "HL") + cell->setLevelShifterType(LevelShifterType::HL); + else if (*level_shifter_type == "LH") + cell->setLevelShifterType(LevelShifterType::LH); + else if (*level_shifter_type == "HL_LH") + cell->setLevelShifterType(LevelShifterType::HL_LH); + else + libWarn(1228, cell_group, "level_shifter_type must be HL, LH, or HL_LH"); } - leakage_powers_.clear(); -} - -// Record a reference to a function that will be parsed at the end of -// the cell definition when all of the ports are defined. -void -LibertyReader::makeLibertyFunc(const char *expr, - LibertySetFunc set_func, - bool invert, - const char *attr_name, - LibertyStmt *stmt) -{ - LibertyFunc *func = new LibertyFunc(expr, set_func, - invert, attr_name, stmt->line()); - cell_funcs_.push_back(func); } void -LibertyReader::parseCellFuncs() +LibertyReader::readSwitchCellType(LibertyCell *cell, + const LibertyGroup *cell_group) { - for (LibertyFunc *func : cell_funcs_) { - FuncExpr *expr = parseFunc(func->expr(), func->attrName(), func->line()); - if (func->invert() && expr) - expr = expr->invert(); - if (expr) - func->setFunc()(expr); - delete func; + const std::string *switch_cell_type = cell_group->findAttrString("switch_cell_type"); + if (switch_cell_type) { + if (*switch_cell_type == "coarse_grain") + cell->setSwitchCellType(SwitchCellType::coarse_grain); + else if (*switch_cell_type == "fine_grain") + cell->setSwitchCellType(SwitchCellType::fine_grain); + else + libWarn(1229, cell_group, "switch_cell_type must be coarse_grain or fine_grain"); } - cell_funcs_.clear(); } void -LibertyReader::beginScaledCell(LibertyGroup *group) +LibertyReader::readCellOcvDerateGroup(LibertyCell *cell, + const LibertyGroup *cell_group) { - const char *name = group->firstName(); - if (name) { - scaled_cell_owner_ = library_->findLibertyCell(name); - if (scaled_cell_owner_) { - const char *op_cond_name = group->secondName(); - if (op_cond_name) { - op_cond_ = library_->findOperatingConditions(op_cond_name); - if (op_cond_) { - debugPrint(debug_, "liberty", 1, "scaled cell %s %s", - name, op_cond_name); - cell_ = library_->makeScaledCell(name, filename_); + const std::string *derate_name = cell_group->findAttrString("ocv_derate_group"); + if (derate_name) { + OcvDerate *derate = cell->findOcvDerate(derate_name->c_str()); + if (derate == nullptr) + derate = library_->findOcvDerate(derate_name->c_str()); + if (derate) + cell->setOcvDerate(derate); + else + libWarn(1237, cell_group, "OCV derate group named %s not found.", + derate_name->c_str()); + } +} + +void +LibertyReader::readStatetable(LibertyCell *cell, + const LibertyGroup *cell_group) +{ + for (const LibertyGroup *statetable_group : cell_group->findSubgroups("statetable")) { + const char *input_ports_arg = statetable_group->firstName(); + const char *internal_ports_arg = statetable_group->params().size() >= 2 + ? statetable_group->secondName() : nullptr; + StdStringSeq input_ports; + if (input_ports_arg) + input_ports = parseTokens(input_ports_arg, ' '); + StdStringSeq internal_ports; + if (internal_ports_arg) + internal_ports = parseTokens(internal_ports_arg, ' '); + + const LibertySimpleAttr *table_attr = statetable_group->findSimpleAttr("table"); + if (table_attr) { + const std::string *table_str = table_attr->stringValue(); + StdStringSeq table_rows = parseTokens(table_str->c_str(), ','); + size_t input_count = input_ports.size(); + size_t internal_count = internal_ports.size(); + StatetableRows table; + for (const std::string &row : table_rows) { + const StdStringSeq row_groups = parseTokens(row, ':'); + if (row_groups.size() != 3) { + libWarn(1300, table_attr, "table row must have 3 groups separated by ':'."); + break; } + StdStringSeq inputs = parseTokens(row_groups[0], ' '); + if (inputs.size() != input_count) { + libWarn(1301,table_attr,"table row has %zu input values but %zu are required.", + inputs.size(), input_count); + break; + } + StdStringSeq currents = parseTokens(row_groups[1], ' '); + if (currents.size() != internal_count) { + libWarn(1302,table_attr, + "table row has %zu current values but %zu are required.", + currents.size(), internal_count); + break; + } + StdStringSeq nexts = parseTokens(row_groups[2], ' '); + if (nexts.size() != internal_count) { + libWarn(1303, table_attr, "table row has %zu next values but %zu are required.", + nexts.size(), internal_count); + break; + } + + StateInputValues input_values = parseStateInputValues(inputs, table_attr); + StateInternalValues current_values=parseStateInternalValues(currents,table_attr); + StateInternalValues next_values = parseStateInternalValues(nexts, table_attr); + table.emplace_back(input_values, current_values, next_values); + } + + LibertyPortSeq input_port_ptrs; + for (const std::string &input : input_ports) { + LibertyPort *port = cell->findLibertyPort(input.c_str()); + if (port) + input_port_ptrs.push_back(port); else - libWarn(1202, group, "operating conditions %s not found.", op_cond_name); + libWarn(1298, statetable_group, "statetable input port %s not found.", + input.c_str()); } - else - libWarn(1203, group, "scaled_cell missing operating condition."); - } - else - libWarn(1204, group, "scaled_cell cell %s has not been defined.", name); - } - else - libWarn(1205, group, "scaled_cell missing name."); -} - -void -LibertyReader::endScaledCell(LibertyGroup *group) -{ - if (cell_) { - makeCellSequentials(); - parseCellFuncs(); - finishPortGroups(); - cell_->finish(infer_latches_, report_, debug_); - checkScaledCell(group); - // Add scaled cell AFTER ports and timing arcs are defined. - scaled_cell_owner_->addScaledCell(op_cond_, cell_); - cell_ = nullptr; - scaled_cell_owner_ = nullptr; - op_cond_ = nullptr; - } -} - -// Minimal check that is not very specific about where the discrepancies are. -void -LibertyReader::checkScaledCell(LibertyGroup *group) -{ - if (equivCellPorts(cell_, scaled_cell_owner_)) { - if (!equivCellPorts(cell_, scaled_cell_owner_)) - libWarn(1206, group, "scaled_cell %s, %s ports do not match cell ports", - cell_->name(), - op_cond_->name()); - if (!equivCellFuncs(cell_, scaled_cell_owner_)) - libWarn(1206, group, - "scaled_cell %s, %s port functions do not match cell port functions.", - cell_->name(), - op_cond_->name()); - } - else - libWarn(1207, group, "scaled_cell ports do not match cell ports."); - if (!equivCellTimingArcSets(cell_, scaled_cell_owner_)) - libWarn(1208, group, "scaled_cell %s, %s timing does not match cell timing.", - cell_->name(), - op_cond_->name()); -} - -void -LibertyReader::makeTimingArcs(LibertyPort *to_port, - TimingGroup *timing) -{ - LibertyPort *related_out_port = nullptr; - const char *related_out_port_name = timing->relatedOutputPortName(); - if (related_out_port_name) - related_out_port = findPort(related_out_port_name); - int line = timing->line(); - PortDirection *to_port_dir = to_port->direction(); - // Checks should be more comprehensive (timing checks on inputs, etc). - TimingType type = timing->attrs()->timingType(); - if (type == TimingType::combinational && - to_port_dir->isInput()) - libWarn(1209, line, "combinational timing to an input port."); - if (timing->relatedPortNames()) { - for (const char *from_port_name : *timing->relatedPortNames()) { - PortNameBitIterator from_port_iter(cell_, from_port_name, this, line); - if (from_port_iter.hasNext()) { - debugPrint(debug_, "liberty", 2, " timing %s -> %s", - from_port_name, to_port->name()); - makeTimingArcs(from_port_name, from_port_iter, to_port, - related_out_port, timing); + LibertyPortSeq internal_port_ptrs; + for (const std::string &internal : internal_ports) { + LibertyPort *port = cell->findLibertyPort(internal.c_str()); + if (port == nullptr) + port = makePort(cell, internal.c_str()); + internal_port_ptrs.push_back(port); } + cell->makeStatetable(input_port_ptrs, internal_port_ptrs, table); } } - else - makeTimingArcs(to_port, related_out_port, timing); -} - -void -TimingGroup::makeTimingModels(LibertyCell *cell, - LibertyReader *visitor) -{ - switch (cell->libertyLibrary()->delayModelType()) { - case DelayModelType::cmos_linear: - makeLinearModels(cell); - break; - case DelayModelType::table: - makeTableModels(cell, visitor); - break; - case DelayModelType::cmos_pwl: - case DelayModelType::cmos2: - case DelayModelType::polynomial: - case DelayModelType::dcm: - break; - } } void -TimingGroup::makeLinearModels(LibertyCell *cell) +LibertyReader::readTestCell(LibertyCell *cell, + const LibertyGroup *cell_group) { - LibertyLibrary *library = cell->libertyLibrary(); - for (auto rf : RiseFall::range()) { - int rf_index = rf->index(); - float intr = intrinsic_[rf_index]; - bool intr_exists = intrinsic_exists_[rf_index]; - if (!intr_exists) - library->defaultIntrinsic(rf, intr, intr_exists); - TimingModel *model = nullptr; - if (timingTypeIsCheck(attrs_->timingType())) { - if (intr_exists) - model = new CheckLinearModel(cell, intr); - } + const LibertyGroup *test_cell_group = cell_group->findSubgroup("test_cell"); + if (test_cell_group) { + if (cell->testCell()) + libWarn(1262, test_cell_group, "cell %s test_cell redefinition.", cell->name()); else { - float res = resistance_[rf_index]; - bool res_exists = resistance_exists_[rf_index]; - if (!res_exists) - library->defaultPinResistance(rf, PortDirection::output(), - res, res_exists); - if (!res_exists) - res = 0.0F; - if (intr_exists) - model = new GateLinearModel(cell, intr, res); - } - attrs_->setModel(rf, model); - } -} - -void -TimingGroup::makeTableModels(LibertyCell *cell, - LibertyReader *reader) -{ - for (const RiseFall *rf : RiseFall::range()) { - int rf_index = rf->index(); - TableModel *delay = cell_[rf_index]; - TableModel *transition = transition_[rf_index]; - TableModel *constraint = constraint_[rf_index]; - if (delay || transition) { - attrs_->setModel(rf, new GateTableModel(cell, delay, delay_sigma_[rf_index], - transition, - slew_sigma_[rf_index], - receiver_model_, - output_waveforms_[rf_index])); - TimingType timing_type = attrs_->timingType(); - if (timing_type == TimingType::clear - || timing_type == TimingType::combinational - || timing_type == TimingType::combinational_fall - || timing_type == TimingType::combinational_rise - || timing_type == TimingType::falling_edge - || timing_type == TimingType::preset - || timing_type == TimingType::rising_edge - || timing_type == TimingType::three_state_disable - || timing_type == TimingType::three_state_disable_rise - || timing_type == TimingType::three_state_disable_fall - || timing_type == TimingType::three_state_enable - || timing_type == TimingType::three_state_enable_fall - || timing_type == TimingType::three_state_enable_rise) { - if (transition == nullptr) - reader->libWarn(1210, line_, "missing %s_transition.", rf->name()); - if (delay == nullptr) - reader->libWarn(1211, line_, "missing cell_%s.", rf->name()); - } - } - else if (constraint) - attrs_->setModel(rf, new CheckTableModel(cell, constraint, - constraint_sigma_[rf_index])); - cell_[rf_index] = nullptr; - transition_[rf_index] = nullptr; - constraint_[rf_index] = nullptr; - } -} - -void -LibertyReader::makeTimingArcs(const char *from_port_name, - PortNameBitIterator &from_port_iter, - LibertyPort *to_port, - LibertyPort *related_out_port, - TimingGroup *timing) -{ - if (from_port_iter.size() == 1 && !to_port->hasMembers()) { - // one -> one - if (from_port_iter.hasNext()) { - LibertyPort *from_port = from_port_iter.next(); - if (from_port->direction()->isOutput()) - libWarn(1212, timing->line(), "timing group from output port."); - builder_.makeTimingArcs(cell_, from_port, to_port, related_out_port, - timing->attrs(), timing->line()); - } - } - else if (from_port_iter.size() > 1 && !to_port->hasMembers()) { - // bus -> one - while (from_port_iter.hasNext()) { - LibertyPort *from_port = from_port_iter.next(); - if (from_port->direction()->isOutput()) - libWarn(1213, timing->line(), "timing group from output port."); - builder_.makeTimingArcs(cell_, from_port, to_port, related_out_port, - timing->attrs(), timing->line()); - } - } - else if (from_port_iter.size() == 1 && to_port->hasMembers()) { - // one -> bus - if (from_port_iter.hasNext()) { - LibertyPort *from_port = from_port_iter.next(); - if (from_port->direction()->isOutput()) - libWarn(1214, timing->line(), "timing group from output port."); - LibertyPortMemberIterator bit_iter(to_port); - while (bit_iter.hasNext()) { - LibertyPort *to_port_bit = bit_iter.next(); - builder_.makeTimingArcs(cell_, from_port, to_port_bit, related_out_port, - timing->attrs(), timing->line()); - } - } - } - else { - // bus -> bus - if (timing->isOneToOne()) { - int from_size = from_port_iter.size(); - int to_size = to_port->size(); - LibertyPortMemberIterator to_port_iter(to_port); - // warn about different sizes - if (from_size != to_size) - libWarn(1216, timing->line(), - "timing port %s and related port %s are different sizes.", - from_port_name, - to_port->name()); - // align to/from iterators for one-to-one mapping - while (from_size > to_size) { - from_size--; - from_port_iter.next(); - } - while (to_size > from_size) { - to_size--; - to_port_iter.next(); - } - // make timing arcs - while (from_port_iter.hasNext() && to_port_iter.hasNext()) { - LibertyPort *from_port_bit = from_port_iter.next(); - LibertyPort *to_port_bit = to_port_iter.next(); - if (from_port_bit->direction()->isOutput()) - libWarn(1215, timing->line(), "timing group from output port."); - builder_.makeTimingArcs(cell_, from_port_bit, to_port_bit, - related_out_port, timing->attrs(), - timing->line()); - } - } - else { - while (from_port_iter.hasNext()) { - LibertyPort *from_port_bit = from_port_iter.next(); - if (from_port_bit->direction()->isOutput()) - libWarn(1217, timing->line(), "timing group from output port."); - LibertyPortMemberIterator to_iter(to_port); - while (to_iter.hasNext()) { - LibertyPort *to_port_bit = to_iter.next(); - builder_.makeTimingArcs(cell_, from_port_bit, to_port_bit, - related_out_port, timing->attrs(), - timing->line()); - } - } - } - } -} - -void -LibertyReader::makeTimingArcs(LibertyPort *to_port, - LibertyPort *related_out_port, - TimingGroup *timing) -{ - if (to_port->hasMembers()) { - LibertyPortMemberIterator bit_iter(to_port); - while (bit_iter.hasNext()) { - LibertyPort *to_port_bit = bit_iter.next(); - builder_.makeTimingArcs(cell_, nullptr, to_port_bit, - related_out_port, timing->attrs(), - timing->line()); - } - } - else - builder_.makeTimingArcs(cell_, nullptr, to_port, - related_out_port, timing->attrs(), - timing->line()); -} - -//////////////////////////////////////////////////////////////// - -// Group that encloses receiver_capacitance1/2 etc groups. -void -LibertyReader::beginReceiverCapacitance(LibertyGroup *) -{ - receiver_model_ = make_shared(); -} - -void -LibertyReader::endReceiverCapacitance(LibertyGroup *) -{ - if (ports_) { - for (LibertyPort *port : *ports_) - port->setReceiverModel(receiver_model_); - } - receiver_model_ = nullptr; -} - -// For receiver_capacitance groups with mulitiple segments this -// overrides the index passed in beginReceiverCapacitance1Rise/Fall. -void -LibertyReader::visitSegement(LibertyAttr *attr) -{ - if (receiver_model_) { - int segment; - bool exists; - getAttrInt(attr, segment, exists); - if (exists) - index_ = segment; - } -} - -void -LibertyReader::beginReceiverCapacitance1Rise(LibertyGroup *group) -{ - beginReceiverCapacitance(group, 0, RiseFall::rise()); -} - -void -LibertyReader::beginReceiverCapacitance1Fall(LibertyGroup *group) -{ - beginReceiverCapacitance(group, 0, RiseFall::fall()); -} - -void -LibertyReader::beginReceiverCapacitance2Rise(LibertyGroup *group) -{ - beginReceiverCapacitance(group, 1, RiseFall::rise()); -} - -void -LibertyReader::beginReceiverCapacitance2Fall(LibertyGroup *group) -{ - beginReceiverCapacitance(group, 1, RiseFall::fall()); -} - -void -LibertyReader::beginReceiverCapacitance(LibertyGroup *group, - int index, - const RiseFall *rf) -{ - if (timing_ || ports_) { - beginTableModel(group, TableTemplateType::delay, rf, 1.0, - ScaleFactorType::pin_cap); - index_ = index; - } - else - libWarn(1218, group, "receiver_capacitance group not in timing or pin group."); -} - -void -LibertyReader::endReceiverCapacitanceRiseFall(LibertyGroup *group) -{ - if (table_) { - if (ReceiverModel::checkAxes(table_)) { - if (receiver_model_ == nullptr) { - receiver_model_ = make_shared(); - if (timing_) - timing_->setReceiverModel(receiver_model_); - } - receiver_model_->setCapacitanceModel(TableModel(table_, tbl_template_, - scale_factor_type_, rf_), - index_, rf_); - } - else - libWarn(1219, group, "unsupported model axis."); - endTableModel(); - } -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginOutputCurrentRise(LibertyGroup *group) -{ - beginOutputCurrent(RiseFall::rise(), group); -} - -void -LibertyReader::beginOutputCurrentFall(LibertyGroup *group) -{ - beginOutputCurrent(RiseFall::fall(), group); -} - -void -LibertyReader::beginOutputCurrent(const RiseFall *rf, - LibertyGroup *group) -{ - if (timing_) { - rf_ = rf; - output_currents_.clear(); - } - else - libWarn(1220, group, "output_current_%s group not in timing group.", - rf->name()); -} - -void -LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group) -{ - if (timing_) { - std::set slew_set, cap_set; - FloatSeq slew_values; - FloatSeq cap_values; - for (OutputWaveform *waveform : output_currents_) { - float slew = waveform->slew(); - if (!slew_set.contains(slew)) { - slew_set.insert(slew); - slew_values.push_back(slew); - } - float cap = waveform->cap(); - if (!cap_set.contains(cap)) { - cap_set.insert(cap); - cap_values.push_back(cap); - } - } - sort(slew_values, std::less()); - sort(cap_values, std::less()); - size_t slew_size = slew_values.size(); - size_t cap_size = cap_values.size(); - TableAxisPtr slew_axis=make_shared(TableAxisVariable::input_net_transition, - std::move(slew_values)); - TableAxisPtr cap_axis = - make_shared(TableAxisVariable::total_output_net_capacitance, - std::move(cap_values)); - FloatSeq ref_times(slew_size); - Table1Seq current_waveforms(slew_size * cap_size); - for (OutputWaveform *waveform : output_currents_) { - size_t slew_index, cap_index; - bool slew_exists, cap_exists; - slew_axis->findAxisIndex(waveform->slew(), slew_index, slew_exists); - cap_axis->findAxisIndex(waveform->cap(), cap_index, cap_exists); - if (slew_exists && cap_exists) { - size_t index = slew_index * cap_axis->size() + cap_index; - current_waveforms[index] = waveform->stealCurrents(); - ref_times[slew_index] = waveform->referenceTime(); - } - else - libWarn(1221, group, "output current waveform %.2e %.2e not found.", - waveform->slew(), - waveform->cap()); - } - Table ref_time_tbl(std::move(ref_times), slew_axis); - OutputWaveforms *output_current = new OutputWaveforms(slew_axis, cap_axis, rf_, - current_waveforms, - std::move(ref_time_tbl)); - timing_->setOutputWaveforms(rf_, output_current); - deleteContents(output_currents_); - } -} - -void -LibertyReader::beginVector(LibertyGroup *group) -{ - if (timing_ && !in_ccsn_) { - beginTable(group, TableTemplateType::output_current, current_scale_); - scale_factor_type_ = ScaleFactorType::unknown; - reference_time_exists_ = false; - if (tbl_template_ && !OutputWaveforms::checkAxes(tbl_template_)) - libWarn(1222, group, "unsupported model axis."); - } -} - -void -LibertyReader::visitReferenceTime(LibertyAttr *attr) -{ - getAttrFloat(attr, reference_time_, reference_time_exists_); - if (reference_time_exists_) - reference_time_ *= time_scale_; -} - -void -LibertyReader::endVector(LibertyGroup *group) -{ - if (timing_ && tbl_template_) { - TableAxisPtr slew_axis, cap_axis; - // Canonicalize axis order. - if (tbl_template_->axis1()->variable() == TableAxisVariable::input_net_transition) { - slew_axis = axis_[0]; - cap_axis = axis_[1]; - } - else { - slew_axis = axis_[1]; - cap_axis = axis_[0]; - } - - if (slew_axis->size() == 1 && cap_axis->size() == 1) { - // Convert 1x1xN Table (order 3) to 1D Table. - float slew = slew_axis->axisValue(0); - float cap = cap_axis->axisValue(0); - Table *table_ptr = table_.get(); - FloatTable *values3 = table_ptr->values3(); - FloatSeq row = std::move((*values3)[0]); - values3->erase(values3->begin()); - Table *table1 = new Table(std::move(row), axis_[2]); - OutputWaveform *waveform = new OutputWaveform(slew, cap, table1, reference_time_); - output_currents_.push_back(waveform); - } - else - libWarn(1223,group->line(), "vector index_1 and index_2 must have exactly one value."); - if (!reference_time_exists_) - libWarn(1224, group->line(), "vector reference_time not found."); - reference_time_exists_ = false; - tbl_template_ = nullptr; - } -} - -/////////////////////////////////////////////////////////////// - -void -LibertyReader::beginNormalizedDriverWaveform(LibertyGroup *group) -{ - beginTable(group, TableTemplateType::delay, time_scale_); - driver_waveform_name_.clear(); -} - -void -LibertyReader::visitDriverWaveformName(LibertyAttr *attr) -{ - driver_waveform_name_ = getAttrString(attr); -} - -void -LibertyReader::endNormalizedDriverWaveform(LibertyGroup *group) -{ - if (table_) { - if (table_->axis1()->variable() == TableAxisVariable::input_net_transition) { - if (table_->axis2()->variable() == TableAxisVariable::normalized_voltage) { - // Null driver_waveform_name_ means it is the default unnamed waveform. - library_->makeDriverWaveform(driver_waveform_name_, table_); - - } - else - libWarn(1225, group, "normalized_driver_waveform variable_2 must be normalized_voltage"); - } - else - libWarn(1226, group, "normalized_driver_waveform variable_1 must be input_net_transition"); - } - endTableModel(); -} - -void -LibertyReader::visitDriverWaveformRise(LibertyAttr *attr) -{ - visitDriverWaveformRiseFall(attr, RiseFall::rise()); -} - -void -LibertyReader::visitDriverWaveformFall(LibertyAttr *attr) -{ - visitDriverWaveformRiseFall(attr, RiseFall::fall()); -} - -void -LibertyReader::visitDriverWaveformRiseFall(LibertyAttr *attr, - const RiseFall *rf) -{ - if (ports_) { - const char *driver_waveform_name = getAttrString(attr); - DriverWaveform *driver_waveform = library_->findDriverWaveform(driver_waveform_name); - if (driver_waveform) { - for (LibertyPort *port : *ports_) - port->setDriverWaveform(driver_waveform, rf); - } - } -} - -/////////////////////////////////////////////////////////////// - -void -LibertyReader::makeInternalPowers(LibertyPort *port, - InternalPowerGroup *power_group) -{ - int line = power_group->line(); - const std::string &related_pg_pin_name = power_group->relatedPgPin(); - LibertyPort *related_pg_pin = cell_->findLibertyPort(related_pg_pin_name.c_str()); - - StringSeq *related_port_names = power_group->relatedPortNames(); - if (related_port_names) { - for (const char *related_port_name : *related_port_names) { - PortNameBitIterator related_port_iter(cell_, related_port_name, this, line); - if (related_port_iter.hasNext()) { - debugPrint(debug_, "liberty", 2, " power %s -> %s", - related_port_name, port->name()); - makeInternalPowers(port, related_port_name, related_port_iter, - related_pg_pin, power_group); - } - } - } - else { - if (port->hasMembers()) { - LibertyPortMemberIterator bit_iter(port); - while (bit_iter.hasNext()) { - LibertyPort *port_bit = bit_iter.next(); - cell_->makeInternalPower(port_bit, nullptr, related_pg_pin, - power_group->when(), power_group->models()); - } - } - else - cell_->makeInternalPower(port, nullptr, related_pg_pin, power_group->when(), - power_group->models()); - } -} - -void -LibertyReader::makeInternalPowers(LibertyPort *port, - const char *related_port_name, - PortNameBitIterator &related_port_iter, - LibertyPort *related_pg_pin, - InternalPowerGroup *power_group) -{ - const auto &when = power_group->when(); - InternalPowerModels &models = power_group->models(); - if (related_port_iter.size() == 1 && !port->hasMembers()) { - // one -> one - if (related_port_iter.hasNext()) { - LibertyPort *related_port = related_port_iter.next(); - cell_->makeInternalPower(port, related_port, related_pg_pin, when, models); - } - } - else if (related_port_iter.size() > 1 && !port->hasMembers()) { - // bus -> one - while (related_port_iter.hasNext()) { - LibertyPort *related_port = related_port_iter.next(); - cell_->makeInternalPower(port, related_port, related_pg_pin, when, models); - } - } - else if (related_port_iter.size() == 1 && port->hasMembers()) { - // one -> bus - if (related_port_iter.hasNext()) { - LibertyPort *related_port = related_port_iter.next(); - LibertyPortMemberIterator bit_iter(port); - while (bit_iter.hasNext()) { - LibertyPort *port_bit = bit_iter.next(); - cell_->makeInternalPower(port_bit, related_port, related_pg_pin, when, models); - } - } - } - else { - // bus -> bus - if (power_group->isOneToOne()) { - if (static_cast(related_port_iter.size()) == port->size()) { - LibertyPortMemberIterator to_iter(port); - while (related_port_iter.hasNext() && to_iter.hasNext()) { - LibertyPort *related_port_bit = related_port_iter.next(); - LibertyPort *port_bit = to_iter.next(); - cell_->makeInternalPower(port_bit, related_port_bit, related_pg_pin, - when, models); - } - } - else - libWarn(1227, power_group->line(), - "internal_power port %s and related port %s are different sizes.", - related_port_name, - port->name()); - } - else { - while (related_port_iter.hasNext()) { - LibertyPort *related_port_bit = related_port_iter.next(); - LibertyPortMemberIterator to_iter(port); - while (to_iter.hasNext()) { - LibertyPort *port_bit = to_iter.next(); - cell_->makeInternalPower(port_bit, related_port_bit, related_pg_pin, - when, models); - } - } + std::string test_cell_name = std::string(cell->name()) + "/test_cell"; + TestCell *test_cell = new TestCell(cell->libertyLibrary(), + std::move(test_cell_name), + cell->filename()); + cell->setTestCell(test_cell); + readCell(test_cell, test_cell_group); } } } //////////////////////////////////////////////////////////////// -void -LibertyReader::visitArea(LibertyAttr *attr) -{ - if (cell_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - cell_->setArea(value); - } - if (wireload_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - wireload_->setArea(value); - } -} - -void -LibertyReader::visitDontUse(LibertyAttr *attr) -{ - if (cell_) { - bool dont_use, exists; - getAttrBool(attr, dont_use, exists); - if (exists) - cell_->setDontUse(dont_use); - } -} - -void -LibertyReader::visitIsMacro(LibertyAttr *attr) -{ - if (cell_) { - bool is_macro, exists; - getAttrBool(attr, is_macro, exists); - if (exists) - cell_->setIsMacro(is_macro); - } -} - -void -LibertyReader::visitIsMemory(LibertyAttr *attr) -{ - if (cell_) { - bool is_memory, exists; - getAttrBool(attr, is_memory, exists); - if (exists) - cell_->setIsMemory(is_memory); - } -} - -void -LibertyReader::visitIsPadCell(LibertyAttr *attr) -{ - if (cell_) { - bool pad_cell, exists; - getAttrBool(attr, pad_cell, exists); - if (exists) - cell_->setIsPad(pad_cell); - } -} - -void -LibertyReader::visitIsClockCell(LibertyAttr *attr) -{ - if (cell_) { - bool is_clock_cell, exists; - getAttrBool(attr, is_clock_cell, exists); - if (exists) - cell_->setIsClockCell(is_clock_cell); - } -} - -void -LibertyReader::visitIsLevelShifter(LibertyAttr *attr) -{ - if (cell_) { - bool is_level_shifter, exists; - getAttrBool(attr, is_level_shifter, exists); - if (exists) - cell_->setIsLevelShifter(is_level_shifter); - } -} - -void -LibertyReader::visitLevelShifterType(LibertyAttr *attr) -{ - if (cell_) { - const char *level_shifter_type = getAttrString(attr); - if (stringEq(level_shifter_type, "HL")) - cell_->setLevelShifterType(LevelShifterType::HL); - else if (stringEq(level_shifter_type, "LH")) - cell_->setLevelShifterType(LevelShifterType::LH); - else if (stringEq(level_shifter_type, "HL_LH")) - cell_->setLevelShifterType(LevelShifterType::HL_LH); - else - libWarn(1228, attr, "level_shifter_type must be HL, LH, or HL_LH"); - } -} - -void -LibertyReader::visitIsIsolationCell(LibertyAttr *attr) -{ - if (cell_) { - bool is_isolation_cell, exists; - getAttrBool(attr, is_isolation_cell, exists); - if (exists) - cell_->setIsIsolationCell(is_isolation_cell); - } -} - -void -LibertyReader::visitAlwaysOn(LibertyAttr *attr) -{ - if (cell_) { - bool always_on, exists; - getAttrBool(attr, always_on, exists); - if (exists) - cell_->setAlwaysOn(always_on); - } -} - -void -LibertyReader::visitSwitchCellType(LibertyAttr *attr) -{ - if (cell_) { - const char *switch_cell_type = getAttrString(attr); - if (stringEq(switch_cell_type, "coarse_grain")) - cell_->setSwitchCellType(SwitchCellType::coarse_grain); - else if (stringEq(switch_cell_type, "fine_grain")) - cell_->setSwitchCellType(SwitchCellType::fine_grain); - else - libWarn(1229, attr, "switch_cell_type must be coarse_grain or fine_grain"); - } -} - -void -LibertyReader::visitInterfaceTiming(LibertyAttr *attr) -{ - if (cell_) { - bool value, exists; - getAttrBool(attr, value, exists); - if (exists) - cell_->setInterfaceTiming(value); - } -} - -void -LibertyReader::visitScalingFactors(LibertyAttr *attr) -{ - if (cell_) { - const char *scale_factors_name = getAttrString(attr); - ScaleFactors *scales = library_->findScaleFactors(scale_factors_name); - if (scales) - cell_->setScaleFactors(scales); - else - libWarn(1230, attr, "scaling_factors %s not found.", scale_factors_name); - } -} - -void -LibertyReader::visitClockGatingIntegratedCell(LibertyAttr *attr) -{ - if (cell_) { - const char *clock_gate_type = getAttrString(attr); - if (clock_gate_type) { - if (stringBeginEqual(clock_gate_type, "latch_posedge")) - cell_->setClockGateType(ClockGateType::latch_posedge); - else if (stringBeginEqual(clock_gate_type, "latch_negedge")) - cell_->setClockGateType(ClockGateType::latch_negedge); - else - cell_->setClockGateType(ClockGateType::other); - } - } -} - -void -LibertyReader::visitCellFootprint(LibertyAttr *attr) -{ - if (cell_) { - const char *footprint = getAttrString(attr); - if (footprint) - cell_->setFootprint(footprint); - } -} - -void -LibertyReader::visitCellUserFunctionClass(LibertyAttr *attr) -{ - if (cell_) { - const char *user_function_class = getAttrString(attr); - if (user_function_class) - cell_->setUserFunctionClass(user_function_class); - } -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginPin(LibertyGroup *group) -{ - if (cell_) { - if (in_bus_) { - saved_ports_ = ports_; - saved_port_group_ = port_group_; - ports_ = new LibertyPortSeq; - for (LibertyAttrValue *param : *group->params()) { - if (param->isString()) { - const std::string &port_name = param->stringValue(); - debugPrint(debug_, "liberty", 1, " port %s", port_name.c_str()); - PortNameBitIterator port_iter(cell_, port_name.c_str(), this, group->line()); - while (port_iter.hasNext()) { - LibertyPort *port = port_iter.next(); - ports_->push_back(port); - } - } - else - libWarn(1231, group, "pin name is not a string."); - } - } - else if (in_bundle_) { - saved_ports_ = ports_; - saved_port_group_ = port_group_; - ports_ = new LibertyPortSeq; - for (LibertyAttrValue *param : *group->params()) { - if (param->isString()) { - const char *name = param->stringValue().c_str(); - debugPrint(debug_, "liberty", 1, " port %s", name); - LibertyPort *port = findPort(name); - if (port == nullptr) - port = makePort(cell_, name); - ports_->push_back(port); - } - else - libWarn(1232, group, "pin name is not a string."); - } - } - else { - ports_ = new LibertyPortSeq; - // Multiple port names can share group def. - for (LibertyAttrValue *param : *group->params()) { - if (param->isString()) { - const char *name = param->stringValue().c_str(); - debugPrint(debug_, "liberty", 1, " port %s", name); - LibertyPort *port = makePort(cell_, name); - ports_->push_back(port); - } - else - libWarn(1233, group, "pin name is not a string."); - } - } - port_group_ = new PortGroup(ports_, group->line()); - cell_port_groups_.push_back(port_group_); - } -} - LibertyPort * LibertyReader::makePort(LibertyCell *cell, const char *port_name) { - string sta_name = portLibertyToSta(port_name); + std::string sta_name = portLibertyToSta(port_name); return builder_.makePort(cell, sta_name.c_str()); } @@ -3235,189 +3012,13 @@ LibertyReader::makeBusPort(LibertyCell *cell, int to_index, BusDcl *bus_dcl) { - string sta_name = portLibertyToSta(bus_name); + std::string sta_name = portLibertyToSta(bus_name); return builder_.makeBusPort(cell, bus_name, from_index, to_index, bus_dcl); } -void -LibertyReader::endPin(LibertyGroup *) -{ - if (cell_) { - endPorts(); - if (in_bus_ || in_bundle_) { - ports_ = saved_ports_; - port_group_ = saved_port_group_; - } - } -} - -void -LibertyReader::endPorts() -{ - // Capacitances default based on direction so wait until the end - // of the pin group to set them. - if (ports_) { - for (LibertyPort *port : *ports_) { - if (in_bus_ || in_bundle_) { - // Do not clobber member port capacitances by setting the capacitance - // on a bus or bundle. - LibertyPortMemberIterator member_iter(port); - while (member_iter.hasNext()) { - LibertyPort *member = member_iter.next(); - setPortCapDefault(member); - } - } - else - setPortCapDefault(port); - } - ports_ = nullptr; - port_group_ = nullptr; - } -} - -void -LibertyReader::setPortCapDefault(LibertyPort *port) -{ - for (auto min_max : MinMax::range()) { - for (auto tr : RiseFall::range()) { - float cap; - bool exists; - port->capacitance(tr, min_max, cap, exists); - if (!exists) - port->setCapacitance(tr, min_max, defaultCap(port)); - } - } -} - -void -LibertyReader::beginBus(LibertyGroup *group) -{ - if (cell_) { - beginBusOrBundle(group); - in_bus_ = true; - } -} - -void -LibertyReader::endBus(LibertyGroup *group) -{ - if (cell_) { - if (ports_->empty()) - libWarn(1234, group, "bus %s bus_type not found.", group->firstName()); - endBusOrBundle(); - in_bus_ = false; - } -} - -void -LibertyReader::beginBusOrBundle(LibertyGroup *group) -{ - // Multiple port names can share group def. - for (LibertyAttrValue *param : *group->params()) { - if (param->isString()) { - const string &name = param->stringValue(); - bus_names_.push_back(stringCopy(name.c_str())); - } - } - ports_ = new LibertyPortSeq; - port_group_ = new PortGroup(ports_, group->line()); - cell_port_groups_.push_back(port_group_); -} - -void -LibertyReader::endBusOrBundle() -{ - endPorts(); - deleteContents(&bus_names_); - bus_names_.clear(); - ports_ = nullptr; - port_group_ = nullptr; -} - -// Bus port are not made until the bus_type is specified. -void -LibertyReader::visitBusType(LibertyAttr *attr) -{ - if (cell_) { - const char *bus_type = getAttrString(attr); - if (bus_type) { - // Look for bus dcl local to cell first. - BusDcl *bus_dcl = cell_->findBusDcl(bus_type); - if (bus_dcl == nullptr) - bus_dcl = library_->findBusDcl(bus_type); - if (bus_dcl) { - for (const char *name : bus_names_) { - debugPrint(debug_, "liberty", 1, " bus %s", name); - LibertyPort *port = makeBusPort(cell_, name, bus_dcl->from(), - bus_dcl->to(), bus_dcl); - ports_->push_back(port); - } - } - else - libWarn(1235, attr, "bus_type %s not found.", bus_type); - } - else - libWarn(1236, attr, "bus_type is not a string."); - } -} - -void -LibertyReader::beginBundle(LibertyGroup *group) -{ - if (cell_) { - beginBusOrBundle(group); - in_bundle_ = true; - } -} - -void -LibertyReader::endBundle(LibertyGroup *group) -{ - if (cell_) { - if (ports_ && ports_->empty()) - libWarn(1237, group, "bundle %s member not found.", group->firstName()); - endBusOrBundle(); - in_bundle_ = false; - } -} - -void -LibertyReader::visitMembers(LibertyAttr *attr) -{ - if (cell_) { - if (attr->isComplexAttr()) { - for (const char *name : bus_names_) { - debugPrint(debug_, "liberty", 1, " bundle %s", name); - ConcretePortSeq *members = new ConcretePortSeq; - for (LibertyAttrValue *value : *attr->values()) { - if (value->isString()) { - const char *port_name = value->stringValue().c_str(); - LibertyPort *port = findPort(port_name); - if (port == nullptr) - port = makePort(cell_, port_name); - members->push_back(port); - } - else - libWarn(1238, attr, "member is not a string."); - } - LibertyPort *port = builder_.makeBundlePort(cell_, name, members); - ports_->push_back(port); - } - } - else - libWarn(1239, attr,"members attribute is missing values."); - } -} - -LibertyPort * -LibertyReader::findPort(const char *port_name) -{ - return findPort(cell_, port_name); -} - // Also used by LibExprParser::makeFuncExprPort. LibertyPort * -libertyReaderFindPort(LibertyCell *cell, +libertyReaderFindPort(const LibertyCell *cell, const char *port_name) { LibertyPort *port = cell->findLibertyPort(port_name); @@ -3427,7 +3028,7 @@ libertyReaderFindPort(LibertyCell *cell, char brkt_right = library->busBrktRight(); const char escape = '\\'; // Pins at top level with bus names have escaped brackets. - string escaped_port_name = escapeChars(port_name, brkt_left, brkt_right, escape); + std::string escaped_port_name = escapeChars(port_name, brkt_left, brkt_right, escape); port = cell->findLibertyPort(escaped_port_name.c_str()); } return port; @@ -3440,193 +3041,6 @@ LibertyReader::findPort(LibertyCell *cell, return libertyReaderFindPort(cell, port_name); } -void -LibertyReader::visitDirection(LibertyAttr *attr) -{ - if (ports_) { - const char *dir = getAttrString(attr); - if (dir) { - PortDirection *port_dir = PortDirection::unknown(); - if (stringEq(dir, "input")) - port_dir = PortDirection::input(); - else if (stringEq(dir, "output")) - port_dir = PortDirection::output(); - else if (stringEq(dir, "inout")) - port_dir = PortDirection::bidirect(); - else if (stringEq(dir, "internal")) - port_dir = PortDirection::internal(); - else - libWarn(1240, attr, "unknown port direction."); - - for (LibertyPort *port : *ports_) { - // Tristate enable function sets direction to tristate; don't - // clobber it. - if (!port->direction()->isTristate()) - port->setDirection(port_dir); - } - } - } -} - -void -LibertyReader::visitFunction(LibertyAttr *attr) -{ - if (ports_) { - const char *func = getAttrString(attr); - if (func) { - for (LibertyPort *port : *ports_) - makeLibertyFunc(func, - [port] (FuncExpr *expr) { port->setFunction(expr); }, - false, "function", attr); - } - } -} - -void -LibertyReader::visitThreeState(LibertyAttr *attr) -{ - if (ports_) { - const char *three_state = getAttrString(attr); - if (three_state) { - for (LibertyPort *port : *ports_) - makeLibertyFunc(three_state, - [port] (FuncExpr *expr) { port->setTristateEnable(expr); }, - true, "three_state", attr); - } - } -} - -void -LibertyReader::visitPorts(std::function func) -{ - for (LibertyPort *port : *ports_) { - func(port); - LibertyPortMemberIterator member_iter(port); - while (member_iter.hasNext()) { - LibertyPort *member = member_iter.next(); - func(member); - } - } -} - -void -LibertyReader::visitClock(LibertyAttr *attr) -{ - if (ports_) { - bool is_clk, exists; - getAttrBool(attr, is_clk, exists); - if (exists) { - for (LibertyPort *port : *ports_) - port->setIsClock(is_clk); - } - } -} - -void -LibertyReader::visitIsPad(LibertyAttr *attr) -{ - if (ports_) { - bool is_pad, exists; - getAttrBool(attr, is_pad, exists); - if (exists) { - for (LibertyPort *port : *ports_) - port->setIsPad(is_pad); - } - } -} - -void -LibertyReader::visitCapacitance(LibertyAttr *attr) -{ - if (ports_) { - float cap; - bool exists; - getAttrFloat(attr, cap, exists); - if (exists) { - cap *= cap_scale_; - for (LibertyPort *port : *ports_) - port->setCapacitance(cap); - } - } - if (wireload_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - wireload_->setCapacitance(value * cap_scale_); - } -} - -void -LibertyReader::visitRiseCap(LibertyAttr *attr) -{ - if (ports_) { - float cap; - bool exists; - getAttrFloat(attr, cap, exists); - if (exists) { - cap *= cap_scale_; - for (LibertyPort *port : *ports_) { - port->setCapacitance(RiseFall::rise(), MinMax::min(), cap); - port->setCapacitance(RiseFall::rise(), MinMax::max(), cap); - } - } - } -} - -void -LibertyReader::visitFallCap(LibertyAttr *attr) -{ - if (ports_) { - float cap; - bool exists; - getAttrFloat(attr, cap, exists); - if (exists) { - cap *= cap_scale_; - for (LibertyPort *port : *ports_) { - port->setCapacitance(RiseFall::fall(), MinMax::min(), cap); - port->setCapacitance(RiseFall::fall(), MinMax::max(), cap); - } - } - } -} - -void -LibertyReader::visitRiseCapRange(LibertyAttr *attr) -{ - if (ports_) { - bool exists; - float min, max; - getAttrFloat2(attr, min, max, exists); - if (exists) { - min *= cap_scale_; - max *= cap_scale_; - for (LibertyPort *port : *ports_) { - port->setCapacitance(RiseFall::rise(), MinMax::min(), min); - port->setCapacitance(RiseFall::rise(), MinMax::max(), max); - } - } - } -} - -void -LibertyReader::visitFallCapRange(LibertyAttr *attr) -{ - if (ports_) { - bool exists; - float min, max; - getAttrFloat2(attr, min, max, exists); - if (exists) { - min *= cap_scale_; - max *= cap_scale_; - for (LibertyPort *port : *ports_) { - port->setCapacitance(RiseFall::fall(), MinMax::min(), min); - port->setCapacitance(RiseFall::fall(), MinMax::max(), max); - } - } - } -} - float LibertyReader::defaultCap(LibertyPort *port) { @@ -3642,535 +3056,8 @@ LibertyReader::defaultCap(LibertyPort *port) return cap; } -void -LibertyReader::visitFanoutLoad(LibertyAttr *attr) -{ - if (ports_) { - float fanout; - bool exists; - getAttrFloat(attr, fanout, exists); - if (exists) { - visitPorts([&] (LibertyPort *port) { - port->setFanoutLoad(fanout); - }); - } - } -} - -void -LibertyReader::visitMaxFanout(LibertyAttr *attr) -{ - visitFanout(attr, MinMax::max()); -} - -void -LibertyReader::visitMinFanout(LibertyAttr *attr) -{ - visitFanout(attr, MinMax::min()); -} - -void -LibertyReader::visitFanout(LibertyAttr *attr, - const MinMax *min_max) -{ - if (ports_) { - float fanout; - bool exists; - getAttrFloat(attr, fanout, exists); - if (exists) { - visitPorts([&] (LibertyPort *port) { - port->setFanoutLimit(fanout, min_max); - }); - } - } -} - -void -LibertyReader::visitMaxTransition(LibertyAttr *attr) -{ - visitMinMaxTransition(attr, MinMax::max()); -} - -void -LibertyReader::visitMinTransition(LibertyAttr *attr) -{ - visitMinMaxTransition(attr, MinMax::min()); -} - -void -LibertyReader::visitMinMaxTransition(LibertyAttr *attr, - const MinMax *min_max) -{ - if (cell_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - if (min_max == MinMax::max() && value == 0.0) - libWarn(1241, attr, "max_transition is 0.0."); - value *= time_scale_; - visitPorts([&] (LibertyPort *port) { - port->setSlewLimit(value, min_max); - }); - } - } -} - -void -LibertyReader::visitMaxCapacitance(LibertyAttr *attr) -{ - visitMinMaxCapacitance(attr, MinMax::max()); -} - -void -LibertyReader::visitMinCapacitance(LibertyAttr *attr) -{ - visitMinMaxCapacitance(attr, MinMax::min()); -} - -void -LibertyReader::visitMinMaxCapacitance(LibertyAttr *attr, - const MinMax *min_max) -{ - if (cell_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - value *= cap_scale_; - visitPorts([&] (LibertyPort *port) { - port->setCapacitanceLimit(value, min_max); - }); - } - } -} - -void -LibertyReader::visitMinPeriod(LibertyAttr *attr) -{ - if (cell_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - for (LibertyPort *port : *ports_) - port->setMinPeriod(value * time_scale_); - } - } -} - -void -LibertyReader::visitMinPulseWidthLow(LibertyAttr *attr) -{ - visitMinPulseWidth(attr, RiseFall::fall()); -} - -void -LibertyReader::visitMinPulseWidthHigh(LibertyAttr *attr) -{ - visitMinPulseWidth(attr, RiseFall::rise()); -} - -void -LibertyReader::visitMinPulseWidth(LibertyAttr *attr, - const RiseFall *rf) -{ - if (cell_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - value *= time_scale_; - for (LibertyPort *port : *ports_) - port->setMinPulseWidth(rf, value); - } - } -} - -void -LibertyReader::visitPulseClock(LibertyAttr *attr) -{ - if (cell_) { - const char *pulse_clk = getAttrString(attr); - if (pulse_clk) { - const RiseFall *trigger = nullptr; - const RiseFall *sense = nullptr; - if (stringEq(pulse_clk, "rise_triggered_high_pulse")) { - trigger = RiseFall::rise(); - sense = RiseFall::rise(); - } - else if (stringEq(pulse_clk, "rise_triggered_low_pulse")) { - trigger = RiseFall::rise(); - sense = RiseFall::fall(); - } - else if (stringEq(pulse_clk, "fall_triggered_high_pulse")) { - trigger = RiseFall::fall(); - sense = RiseFall::rise(); - } - else if (stringEq(pulse_clk, "fall_triggered_low_pulse")) { - trigger = RiseFall::fall(); - sense = RiseFall::fall(); - } - else - libWarn(1242,attr, "pulse_latch unknown pulse type."); - if (trigger) { - for (LibertyPort *port : *ports_) - port->setPulseClk(trigger, sense); - } - } - } -} - -void -LibertyReader::visitClockGateClockPin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setIsClockGateClock); -} - -void -LibertyReader::visitClockGateEnablePin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setIsClockGateEnable); -} - -void -LibertyReader::visitClockGateOutPin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setIsClockGateOut); -} - -void -LibertyReader::visitIsPllFeedbackPin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setIsPllFeedback); -} - -void -LibertyReader::visitSignalType(LibertyAttr *attr) -{ - if (test_cell_ && ports_) { - const char *type = getAttrString(attr); - if (type) { - ScanSignalType signal_type = ScanSignalType::none; - if (stringEq(type, "test_scan_enable")) - signal_type = ScanSignalType::enable; - else if (stringEq(type, "test_scan_enable_inverted")) - signal_type = ScanSignalType::enable_inverted; - else if (stringEq(type, "test_scan_clock")) - signal_type = ScanSignalType::clock; - else if (stringEq(type, "test_scan_clock_a")) - signal_type = ScanSignalType::clock_a; - else if (stringEq(type, "test_scan_clock_b")) - signal_type = ScanSignalType::clock_b; - else if (stringEq(type, "test_scan_in")) - signal_type = ScanSignalType::input; - else if (stringEq(type, "test_scan_in_inverted")) - signal_type = ScanSignalType::input_inverted; - else if (stringEq(type, "test_scan_out")) - signal_type = ScanSignalType::output; - else if (stringEq(type, "test_scan_out_inverted")) - signal_type = ScanSignalType::output_inverted; - else { - libWarn(1299, attr, "unknown signal_type %s.", type); - return; - } - for (LibertyPort *port : *ports_) - port->setScanSignalType(signal_type); - } - } -} - -void -LibertyReader::visitIsolationCellDataPin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setIsolationCellData); -} - -void -LibertyReader::visitIsolationCellEnablePin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setIsolationCellEnable); -} - -void -LibertyReader::visitLevelShifterDataPin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setLevelShifterData); -} - -void -LibertyReader::visitSwitchPin(LibertyAttr *attr) -{ - visitPortBoolAttr(attr, &LibertyPort::setIsSwitch); -} - -void -LibertyReader::visitPortBoolAttr(LibertyAttr *attr, - LibertyPortBoolSetter setter) -{ - if (cell_) { - bool value, exists; - getAttrBool(attr, value, exists); - if (exists) { - for (LibertyPort *port : *ports_) - (port->*setter)(value); - } - } -} - //////////////////////////////////////////////////////////////// -void -LibertyReader::beginMemory(LibertyGroup *) -{ - if (cell_) { - cell_->setIsMemory(true); - } -} - -void -LibertyReader::endMemory(LibertyGroup *) -{ -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginFF(LibertyGroup *group) -{ - beginSequential(group, true, false); -} - -void -LibertyReader::endFF(LibertyGroup *) -{ - sequential_ = nullptr; -} - -void -LibertyReader::beginFFBank(LibertyGroup *group) -{ - beginSequential(group, true, true); -} - -void -LibertyReader::endFFBank(LibertyGroup *) -{ - sequential_ = nullptr; -} - -void -LibertyReader::beginLatch(LibertyGroup *group) -{ - beginSequential(group, false, false); -} - -void -LibertyReader::endLatch(LibertyGroup *) -{ - sequential_ = nullptr; -} - -void -LibertyReader::beginLatchBank(LibertyGroup *group) -{ - beginSequential(group, false, true); -} - -void -LibertyReader::endLatchBank(LibertyGroup *) -{ - sequential_ = nullptr; -} - -void -LibertyReader::beginSequential(LibertyGroup *group, - bool is_register, - bool is_bank) -{ - if (cell_) { - // Define ff/latch state variables as internal ports. - const char *out_name, *out_inv_name; - int size; - bool has_size; - seqPortNames(group, out_name, out_inv_name, has_size, size); - LibertyPort *out_port = nullptr; - LibertyPort *out_port_inv = nullptr; - if (out_name) { - if (has_size) - out_port = makeBusPort(cell_, out_name, size - 1, 0, nullptr); - else - out_port = makePort(cell_, out_name); - out_port->setDirection(PortDirection::internal()); - } - if (out_inv_name) { - if (has_size) - out_port_inv = makeBusPort(cell_, out_inv_name, size - 1, 0, nullptr); - else - out_port_inv = makePort(cell_, out_inv_name); - out_port_inv->setDirection(PortDirection::internal()); - } - sequential_ = new SequentialGroup(is_register, is_bank, - out_port, out_port_inv, size, - group->line()); - cell_sequentials_.push_back(sequential_); - } -} - -void -LibertyReader::seqPortNames(LibertyGroup *group, - const char *&out_name, - const char *&out_inv_name, - bool &has_size, - int &size) -{ - out_name = nullptr; - out_inv_name = nullptr; - size = 1; - has_size = false; - if (group->params()->size() == 2) { - // out_port, out_port_inv - out_name = group->firstName(); - out_inv_name = group->secondName(); - } - else if (group->params()->size() == 3) { - LibertyAttrValue *third_value = (*group->params())[2]; - if (third_value->isFloat()) { - // out_port, out_port_inv, bus_size - out_name = group->firstName(); - out_inv_name = group->secondName(); - size = static_cast(third_value->floatValue()); - has_size = true; - } - else { - // in_port (ignored), out_port, out_port_inv - out_name = group->secondName(); - out_inv_name = third_value->stringValue().c_str(); - } - } -} - -void -LibertyReader::visitClockedOn(LibertyAttr *attr) -{ - if (sequential_) { - const char *func = getAttrString(attr); - if (func) - sequential_->setClock(stringCopy(func)); - } -} - -void -LibertyReader::visitDataIn(LibertyAttr *attr) -{ - if (sequential_) { - const char *func = getAttrString(attr); - if (func) - sequential_->setData(stringCopy(func)); - } -} - -void -LibertyReader::visitClear(LibertyAttr *attr) -{ - if (sequential_) { - const char *func = getAttrString(attr); - if (func) - sequential_->setClear(stringCopy(func)); - } -} - -void -LibertyReader::visitPreset(LibertyAttr *attr) -{ - if (sequential_) { - const char *func = getAttrString(attr); - if (func) - sequential_->setPreset(stringCopy(func)); - } -} - -void -LibertyReader::visitClrPresetVar1(LibertyAttr *attr) -{ - if (sequential_) { - LogicValue var = getAttrLogicValue(attr); - sequential_->setClrPresetVar1(var); - } -} - -void -LibertyReader::visitClrPresetVar2(LibertyAttr *attr) -{ - if (sequential_) { - LogicValue var = getAttrLogicValue(attr); - sequential_->setClrPresetVar2(var); - } -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginStatetable(LibertyGroup *group) -{ - if (cell_) { - const char *input_ports_arg = group->firstName(); - StdStringSeq input_ports; - if (input_ports_arg) - input_ports = parseTokenList(input_ports_arg, ' '); - - const char *internal_ports_arg = group->secondName(); - StdStringSeq internal_ports; - if (internal_ports_arg) - internal_ports = parseTokenList(internal_ports_arg, ' '); - statetable_ = new StatetableGroup(input_ports, internal_ports, group->line()); - } -} - -void -LibertyReader::visitTable(LibertyAttr *attr) -{ - if (statetable_) { - const char *table_str = getAttrString(attr); - StdStringSeq table_rows = parseTokenList(table_str, ','); - size_t input_count = statetable_->inputPorts().size(); - size_t internal_count = statetable_->internalPorts().size(); - for (string row : table_rows) { - StdStringSeq row_groups = parseTokenList(row.c_str(), ':'); - if (row_groups.size() != 3) { - libWarn(1300, attr, "table row must have 3 groups separated by ':'."); - break; - } - StdStringSeq inputs = parseTokenList(row_groups[0].c_str(), ' '); - if (inputs.size() != input_count) { - libWarn(1301, attr, "table row has %zu input values but %zu are required.", - inputs.size(), - input_count); - break; - } - StdStringSeq currents = parseTokenList(row_groups[1].c_str(), ' '); - if (currents.size() != internal_count) { - libWarn(1302, attr, "table row has %zu current values but %zu are required.", - currents.size(), - internal_count); - break; - } - StdStringSeq nexts = parseTokenList(row_groups[2].c_str(), ' '); - if (nexts.size() != internal_count) { - libWarn(1303, attr, "table row has %zu next values but %zu are required.", - nexts.size(), - internal_count); - break; - } - - StateInputValues input_values = parseStateInputValues(inputs, attr); - StateInternalValues current_values=parseStateInternalValues(currents,attr); - StateInternalValues next_values = parseStateInternalValues(nexts, attr); - statetable_->addRow(input_values, current_values, next_values); - } - } -} - static EnumNameMap state_input_value_name_map = {{StateInputValue::low, "L"}, {StateInputValue::high, "H"}, @@ -4195,10 +3082,10 @@ static EnumNameMap state_internal_value_name_map = StateInputValues LibertyReader::parseStateInputValues(StdStringSeq &inputs, - LibertyAttr *attr) + const LibertySimpleAttr *attr) { StateInputValues input_values; - for (string input : inputs) { + for (std::string input : inputs) { bool exists; StateInputValue value; state_input_value_name_map.find(input.c_str(), value, exists); @@ -4214,10 +3101,10 @@ LibertyReader::parseStateInputValues(StdStringSeq &inputs, StateInternalValues LibertyReader::parseStateInternalValues(StdStringSeq &states, - LibertyAttr *attr) + const LibertySimpleAttr *attr) { StateInternalValues state_values; - for (string state : states) { + for (std::string state : states) { bool exists; StateInternalValue value; state_internal_value_name_map.find(state.c_str(), value, exists); @@ -4231,530 +3118,30 @@ LibertyReader::parseStateInternalValues(StdStringSeq &states, return state_values; } -void -LibertyReader::endStatetable(LibertyGroup *) -{ -} - //////////////////////////////////////////////////////////////// -void -LibertyReader::beginTiming(LibertyGroup *group) -{ - if (port_group_) { - timing_ = new TimingGroup(group->line()); - port_group_->addTimingGroup(timing_); - } -} - -void -LibertyReader::endTiming(LibertyGroup *group) -{ - if (timing_) { - // Set scale factor type in constraint tables. - for (auto rf : RiseFall::range()) { - TableModel *model = timing_->constraint(rf); - if (model) { - ScaleFactorType type=timingTypeScaleFactorType(timing_->attrs()->timingType()); - model->setScaleFactorType(type); - } - } - TimingType timing_type = timing_->attrs()->timingType(); - if (timing_->relatedPortNames() == nullptr - && !(timing_type == TimingType::min_pulse_width - || timing_type == TimingType::minimum_period - || timing_type == TimingType::min_clock_tree_path - || timing_type == TimingType::max_clock_tree_path)) - libWarn(1243, group, "timing group missing related_pin/related_bus_pin."); - } - timing_ = nullptr; - receiver_model_ = nullptr; -} - -void -LibertyReader::visitRelatedPin(LibertyAttr *attr) -{ - if (timing_) - visitRelatedPin(attr, timing_); - if (internal_power_) - visitRelatedPin(attr, internal_power_); -} - -void -LibertyReader::visitRelatedPin(LibertyAttr *attr, - RelatedPortGroup *group) -{ - const char *port_names = getAttrString(attr); - if (port_names) { - group->setRelatedPortNames(parseNameList(port_names)); - group->setIsOneToOne(true); - } -} - -StringSeq * -LibertyReader::parseNameList(const char *name_list) -{ - StringSeq *names = new StringSeq; - // Parse space separated list of names. - TokenParser parser(name_list, " "); - while (parser.hasNext()) { - char *token = parser.next(); - // Skip extra spaces. - if (token[0] != '\0') { - const char *name = token; - names->push_back(stringCopy(name)); - } - } - return names; -} - -StdStringSeq -LibertyReader::parseTokenList(const char *token_str, - const char separator) -{ - StdStringSeq tokens; - // Parse space separated list of names. - char separators[2] = {separator, '\0'}; - TokenParser parser(token_str, separators); - while (parser.hasNext()) { - char *token = parser.next(); - // Skip extra spaces. - if (token[0] != '\0') { - tokens.push_back(token); - } - } - return tokens; -} - -void -LibertyReader::visitRelatedBusPins(LibertyAttr *attr) -{ - if (timing_) - visitRelatedBusPins(attr, timing_); - if (internal_power_) - visitRelatedBusPins(attr, internal_power_); -} - -void -LibertyReader::visitRelatedBusPins(LibertyAttr *attr, - RelatedPortGroup *group) -{ - const char *port_names = getAttrString(attr); - if (port_names) { - group->setRelatedPortNames(parseNameList(port_names)); - group->setIsOneToOne(false); - } -} - -void -LibertyReader::visitRelatedOutputPin(LibertyAttr *attr) -{ - if (timing_) { - const char *pin_name = getAttrString(attr); - if (pin_name) - timing_->setRelatedOutputPortName(pin_name); - } -} - -void -LibertyReader::visitTimingType(LibertyAttr *attr) -{ - if (timing_) { - const char *type_name = getAttrString(attr); - if (type_name) { - TimingType type = findTimingType(type_name); - if (type == TimingType::unknown) - libWarn(1244, attr, "unknown timing_type %s.", type_name); - else - timing_->attrs()->setTimingType(type); - } - } -} - -void -LibertyReader::visitTimingSense(LibertyAttr *attr) -{ - if (timing_) { - const char *sense_name = getAttrString(attr); - if (sense_name) { - if (stringEq(sense_name, "non_unate")) - timing_->attrs()->setTimingSense(TimingSense::non_unate); - else if (stringEq(sense_name, "positive_unate")) - timing_->attrs()->setTimingSense(TimingSense::positive_unate); - else if (stringEq(sense_name, "negative_unate")) - timing_->attrs()->setTimingSense(TimingSense::negative_unate); - else - libWarn(1245, attr, "unknown timing_sense %s.", sense_name); - } - } -} - -void -LibertyReader::visitSdfCondStart(LibertyAttr *attr) -{ - if (timing_) { - const char *cond = getAttrString(attr); - if (cond) - timing_->attrs()->setSdfCondStart(cond); - } -} - -void -LibertyReader::visitSdfCondEnd(LibertyAttr *attr) -{ - if (timing_) { - const char *cond = getAttrString(attr); - if (cond) - timing_->attrs()->setSdfCondEnd(cond); - } -} - -void -LibertyReader::visitMode(LibertyAttr *attr) -{ - if (timing_) { - if (attr->isComplexAttr()) { - LibertyAttrValueSeq *values = attr->values(); - if (values->size() == 2) { - LibertyAttrValue *value = (*values)[0]; - if (value->isString()) - timing_->attrs()->setModeName(value->stringValue()); - else - libWarn(1248, attr, "mode name is not a string."); - - value = (*values)[1]; - if (value->isString()) - timing_->attrs()->setModeValue(value->stringValue()); - else - libWarn(1246, attr, "mode value is not a string."); - } - else - libWarn(1249, attr, "mode requirees 2 values."); - } - else - libWarn(1250, attr, "mode missing mode name and value."); - } -} - -void -LibertyReader::visitIntrinsicRise(LibertyAttr *attr) -{ - visitIntrinsic(attr, RiseFall::rise()); -} - -void -LibertyReader::visitIntrinsicFall(LibertyAttr *attr) -{ - visitIntrinsic(attr, RiseFall::fall()); -} - -void -LibertyReader::visitIntrinsic(LibertyAttr *attr, - const RiseFall *rf) -{ - if (timing_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - timing_->setIntrinsic(rf, value * time_scale_); - } -} - -void -LibertyReader::visitRiseResistance(LibertyAttr *attr) -{ - visitRiseFallResistance(attr, RiseFall::rise()); -} - -void -LibertyReader::visitFallResistance(LibertyAttr *attr) -{ - visitRiseFallResistance(attr, RiseFall::fall()); -} - -void -LibertyReader::visitRiseFallResistance(LibertyAttr *attr, - const RiseFall *rf) -{ - if (timing_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - timing_->setResistance(rf, value * res_scale_); - } -} - -void -LibertyReader::beginCellRise(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::rise(), ScaleFactorType::cell); -} - -void -LibertyReader::beginCellFall(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::fall(), ScaleFactorType::cell); -} - -void -LibertyReader::endCellRiseFall(LibertyGroup *group) -{ - if (table_) { - if (GateTableModel::checkAxes(table_)) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - timing_->setCell(rf_, table_model); - } - else - libWarn(1251, group, "unsupported model axis."); - } - endTableModel(); -} - -void -LibertyReader::beginRiseTransition(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::rise(), ScaleFactorType::transition); -} - -void -LibertyReader::beginFallTransition(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::fall(), ScaleFactorType::transition); -} - -void -LibertyReader::endRiseFallTransition(LibertyGroup *group) -{ - if (table_) { - if (GateTableModel::checkAxes(table_)) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - timing_->setTransition(rf_, table_model); - } - else - libWarn(1252, group, "unsupported model axis."); - } - endTableModel(); -} - -void -LibertyReader::beginRiseConstraint(LibertyGroup *group) -{ - // Scale factor depends on timing_type, which may follow this stmt. - beginTimingTableModel(group, RiseFall::rise(), ScaleFactorType::unknown); -} - -void -LibertyReader::beginFallConstraint(LibertyGroup *group) -{ - // Scale factor depends on timing_type, which may follow this stmt. - beginTimingTableModel(group, RiseFall::fall(), ScaleFactorType::unknown); -} - -void -LibertyReader::endRiseFallConstraint(LibertyGroup *group) -{ - if (table_) { - if (CheckTableModel::checkAxes(table_)) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - timing_->setConstraint(rf_, table_model); - } - else - libWarn(1253, group, "unsupported model axis."); - } - endTableModel(); -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginRiseTransitionDegredation(LibertyGroup *group) -{ - if (library_) - beginTableModel(group, TableTemplateType::delay, - RiseFall::rise(), time_scale_, - ScaleFactorType::transition); -} - -void -LibertyReader::beginFallTransitionDegredation(LibertyGroup *group) -{ - if (library_) - beginTableModel(group, TableTemplateType::delay, - RiseFall::fall(), time_scale_, - ScaleFactorType::transition); -} - -void -LibertyReader::endRiseFallTransitionDegredation(LibertyGroup *group) -{ - if (table_) { - if (LibertyLibrary::checkSlewDegradationAxes(table_)) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - library_->setWireSlewDegradationTable(table_model, rf_); - } - else - libWarn(1254, group, "unsupported model axis."); - } - endTableModel(); -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginTimingTableModel(LibertyGroup *group, - const RiseFall *rf, - ScaleFactorType scale_factor_type) -{ - if (timing_) - beginTableModel(group, TableTemplateType::delay, rf, - time_scale_, scale_factor_type); - else - libWarn(1255, group, "%s group not in timing group.", group->type().c_str()); -} - -void -LibertyReader::beginTableModel(LibertyGroup *group, - TableTemplateType type, - const RiseFall *rf, - float scale, - ScaleFactorType scale_factor_type) -{ - beginTable(group, type, scale); - rf_ = rf; - scale_factor_type_ = scale_factor_type; - sigma_type_ = EarlyLateAll::all(); -} - -void -LibertyReader::endTableModel() -{ - endTable(); - scale_factor_type_ = ScaleFactorType::unknown; - sigma_type_ = nullptr; - index_ = 0; -} - -void -LibertyReader::beginTable(LibertyGroup *group, - TableTemplateType type, - float scale) -{ - const char *template_name = group->firstName(); - if (library_ && template_name) { - tbl_template_ = library_->findTableTemplate(template_name, type); - if (tbl_template_) { - axis_[0] = tbl_template_->axis1ptr(); - axis_[1] = tbl_template_->axis2ptr(); - axis_[2] = tbl_template_->axis3ptr(); - } - else { - libWarn(1256, group, "table template %s not found.", template_name); - axis_[0] = nullptr; - axis_[1] = nullptr; - axis_[2] = nullptr; - } - clearAxisValues(); - table_ = nullptr; - table_model_scale_ = scale; - } -} - -void -LibertyReader::endTable() -{ - table_ = nullptr; - tbl_template_ = nullptr; - axis_[0] = nullptr; - axis_[1] = nullptr; - axis_[2] = nullptr; -} - -void -LibertyReader::visitValue(LibertyAttr *attr) -{ - if (leakage_power_) { - float value; - bool valid; - getAttrFloat(attr, value, valid); - if (valid) - leakage_power_->setPower(value * power_scale_); - } -} - -void -LibertyReader::visitValues(LibertyAttr *attr) -{ - if (tbl_template_ - // Ignore values in ecsm_waveform groups. - && !in_ecsm_waveform_) - makeTable(attr, table_model_scale_); -} - -void -LibertyReader::makeTable(LibertyAttr *attr, - float scale) -{ - if (attr->isComplexAttr()) { - makeTableAxis(0, attr); - makeTableAxis(1, attr); - makeTableAxis(2, attr); - if (axis_[0] && axis_[1] && axis_[2]) { - // 3D table - // Column index1*size(index2) + index2 - // Row index3 - table_ = make_shared
(makeFloatTable(attr, - axis_[0]->size() * axis_[1]->size(), - axis_[2]->size(), scale), - axis_[0], axis_[1], axis_[2]); - } - else if (axis_[0] && axis_[1]) { - // 2D table - // Row variable1/axis[0] - // Column variable2/axis[1] - table_ = make_shared
(makeFloatTable(attr, axis_[0]->size(), - axis_[1]->size(), scale), - axis_[0], axis_[1]); - } - else if (axis_[0]) { - // 1D table - FloatTable table = makeFloatTable(attr, 1, axis_[0]->size(), scale); - table_ = make_shared
(std::move(table[0]), axis_[0]); - } - else if (axis_[0] == nullptr && axis_[1] == nullptr && axis_[2] == nullptr) { - // scalar - FloatTable table = makeFloatTable(attr, 1, 1, scale); - float value = table[0][0]; - table_ = make_shared
(value); - } - } - else - libWarn(1257, attr, "%s is missing values.", attr->name().c_str()); -} - FloatTable -LibertyReader::makeFloatTable(LibertyAttr *attr, +LibertyReader::makeFloatTable(const LibertyComplexAttr *values_attr, + const LibertyGroup *table_group, size_t rows, size_t cols, float scale) { FloatTable table; table.reserve(rows); - for (LibertyAttrValue *value : *attr->values()) { + for (const LibertyAttrValue *value : values_attr->values()) { FloatSeq row; + row.reserve(cols); if (value->isString()) - row = parseStringFloatList(value->stringValue(), scale, attr); + row = parseStringFloatList(value->stringValue(), scale, values_attr); else if (value->isFloat()) row.push_back(value->floatValue() * scale); else - libWarn(1258, attr, "%s is not a list of floats.", attr->name().c_str()); + libWarn(1258, values_attr, "%s is not a list of floats.", + values_attr->name().c_str()); if (row.size() != cols) { - libWarn(1259, attr, "table row has %zu columns but axis has %zu.", + libWarn(1259, values_attr, "%s row has %zu columns but axis has %zu.", + table_group->type().c_str(), row.size(), cols); for (size_t c = row.size(); c < cols; c++) @@ -4763,9 +3150,14 @@ LibertyReader::makeFloatTable(LibertyAttr *attr, table.push_back(std::move(row)); } if (table.size() != rows) { - libWarn(1260, attr, "table has %zu rows but axis has %zu.", - table.size(), - rows); + if (rows == 0) + libWarn(1260, values_attr, "%s missing axis values.", + table_group->type().c_str()); + else + libWarn(1261, values_attr, "%s has %zu rows but axis has %zu.", + table_group->type().c_str(), + table.size(), + rows); for (size_t r = table.size(); r < rows; r++) { FloatSeq row(cols, 0.0); table.push_back(std::move(row)); @@ -4774,254 +3166,55 @@ LibertyReader::makeFloatTable(LibertyAttr *attr, return table; } -void -LibertyReader::makeTableAxis(int index, - LibertyAttr *attr) -{ - if (axis_[index] && !axis_values_[index].empty()) { - TableAxisVariable var = axis_[index]->variable(); - const Units *units = library_->units(); - float scale = tableVariableUnit(var, units)->scale(); - FloatSeq values = std::move(axis_values_[index]); - scaleFloats(values, scale); - axis_[index] = make_shared(var, std::move(values)); - } - else if (axis_[index] && axis_[index]->values().empty()) { - libWarn(1344, attr, "Table axis and template missing values."); - axis_[index] = nullptr; - axis_values_[index].clear(); - } -} - -//////////////////////////////////////////////////////////////// - -// Define lut output variables as internal ports. -// I can't find any documentation for this group. -void -LibertyReader::beginLut(LibertyGroup *group) -{ - if (cell_) { - for (LibertyAttrValue *param : *group->params()) { - if (param->isString()) { - const std::string &names = param->stringValue(); - // Parse space separated list of related port names. - TokenParser parser(names.c_str(), " "); - while (parser.hasNext()) { - char *name = parser.next(); - if (name[0] != '\0') { - LibertyPort *port = makePort(cell_, name); - port->setDirection(PortDirection::internal()); - } - } - } - else - libWarn(1261, group, "lut output is not a string."); - } - } -} - -void -LibertyReader::endLut(LibertyGroup *) -{ -} - //////////////////////////////////////////////////////////////// void -LibertyReader::beginTestCell(LibertyGroup *group) -{ - if (cell_ && cell_->testCell()) - libWarn(1262, group, "cell %s test_cell redefinition.", cell_->name()); - else { - string name = cell_->name(); - name += "/test_cell"; - test_cell_ = new TestCell(cell_->libertyLibrary(), std::move(name), - cell_->filename()); - cell_->setTestCell(test_cell_); - - // Do a recursive parse of cell into the test_cell because it has - // pins, buses, bundles, and sequentials just like a cell. - save_cell_ = cell_; - save_cell_port_groups_ = std::move(cell_port_groups_); - save_statetable_ = statetable_; - statetable_ = nullptr; - save_cell_sequentials_ = std::move(cell_sequentials_); - save_cell_funcs_ = std::move(cell_funcs_); - cell_ = test_cell_; - } -} - -void -LibertyReader::endTestCell(LibertyGroup *) -{ - makeCellSequentials(); - makeStatetable(); - parseCellFuncs(); - finishPortGroups(); - - // Restore reader state to enclosing cell. - cell_port_groups_ = std::move(save_cell_port_groups_); - statetable_ = save_statetable_; - cell_sequentials_ = std::move(save_cell_sequentials_); - cell_funcs_= std::move(save_cell_funcs_); - cell_ = save_cell_; - - test_cell_ = nullptr; - save_statetable_ = nullptr; -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginModeDef(LibertyGroup *group) -{ - const char *name = group->firstName(); - if (name) - mode_def_ = cell_->makeModeDef(name); - else - libWarn(1263, group, "mode definition missing name."); -} - -void -LibertyReader::endModeDef(LibertyGroup *) -{ - mode_def_ = nullptr; -} - -void -LibertyReader::beginModeValue(LibertyGroup *group) -{ - if (mode_def_) { - const char *name = group->firstName(); - if (name) - mode_value_ = mode_def_->defineValue(name, nullptr, nullptr); - else - libWarn(1264, group, "mode value missing name."); - } -} - -void - LibertyReader::endModeValue(LibertyGroup *) -{ - mode_value_ = nullptr; -} - -void -LibertyReader::visitWhen(LibertyAttr *attr) -{ - if (tbl_template_) - libWarn(1265, attr, "when attribute inside table model."); - if (mode_value_) { - const char *func = getAttrString(attr); - if (func) { - ModeValueDef *mode_value = mode_value_; - makeLibertyFunc(func, - [mode_value] (FuncExpr *expr) {mode_value->setCond(expr);}, - false, "when", attr); - } - } - if (timing_ && !in_ccsn_) { - const char *func = getAttrString(attr); - if (func) { - TimingArcAttrs *attrs = timing_->attrs().get(); - makeLibertyFunc(func, - [attrs] (FuncExpr *expr) { attrs->setCond(expr);}, - false, "when", attr); - } - } - if (internal_power_) { - const char *func = getAttrString(attr); - if (func) { - InternalPowerGroup *internal_pwr = internal_power_; - makeLibertyFunc(func, - [internal_pwr] (FuncExpr *expr) { - internal_pwr->setWhen(std::shared_ptr(expr)); - }, - false, "when", attr); - } - } - if (leakage_power_) { - const char *func = getAttrString(attr); - if (func) { - LeakagePowerGroup *leakage_pwr = leakage_power_; - makeLibertyFunc(func, - [leakage_pwr] (FuncExpr *expr) { leakage_pwr->setWhen(expr);}, - false, "when", attr); - } - } -} - -void -LibertyReader::visitSdfCond(LibertyAttr *attr) -{ - if (mode_value_) { - const char *cond = getAttrString(attr); - if (cond) - mode_value_->setSdfCond(cond); - } - else if (timing_) { - const char *cond = getAttrString(attr); - if (cond) - timing_->attrs()->setSdfCond(cond); - } - // sdf_cond can also appear inside minimum_period groups. -} - -//////////////////////////////////////////////////////////////// - -const char * -LibertyReader::getAttrString(LibertyAttr *attr) -{ - if (attr->isSimpleAttr()) { - LibertyAttrValue *value = attr->firstValue(); - if (value->isString()) - return value->stringValue().c_str(); - else - libWarn(1266, attr, "%s attribute is not a string.", attr->name().c_str()); - } - else - libWarn(1267, attr, "%s is not a simple attribute.", attr->name().c_str()); - return nullptr; -} - -void -LibertyReader::getAttrInt(LibertyAttr *attr, +LibertyReader::getAttrInt(const LibertySimpleAttr *attr, // Return values. int &value, bool &exists) { value = 0; exists = false; - if (attr->isSimpleAttr()) { - LibertyAttrValue *attr_value = attr->firstValue(); - if (attr_value->isFloat()) { - float float_val = attr_value->floatValue(); - value = static_cast(float_val); - exists = true; - } - else - libWarn(1268, attr, "%s attribute is not an integer.",attr->name().c_str()); + const LibertyAttrValue &attr_value = attr->value(); + if (attr_value.isFloat()) { + float float_val = attr_value.floatValue(); + value = static_cast(float_val); + exists = true; } else - libWarn(1269, attr, "%s is not a simple attribute.", attr->name().c_str()); + libWarn(1268, attr, "%s attribute is not an integer.",attr->name().c_str()); } +// Get two floats in a complex attribute. +// attr(float1, float2); void -LibertyReader::getAttrFloat(LibertyAttr *attr, - // Return values. - float &value, - bool &valid) +LibertyReader::getAttrFloat2(const LibertyComplexAttr *attr, + // Return values. + float &value1, + float &value2, + bool &exists) { - valid = false; - if (attr->isSimpleAttr()) - getAttrFloat(attr, attr->firstValue(), value, valid); + exists = false; + const LibertyAttrValueSeq &values = attr->values(); + if (values.size() == 2) { + LibertyAttrValue *value = values[0]; + getAttrFloat(attr, value, value1, exists); + if (!exists) + libWarn(1272, attr, "%s is not a float.", attr->name().c_str()); + + value = values[1]; + getAttrFloat(attr, value, value2, exists); + if (!exists) + libWarn(1273, attr, "%s is not a float.", attr->name().c_str()); + } else - libWarn(1270, attr, "%s is not a simple attribute.", attr->name().c_str()); + libWarn(1274, attr, "%s requires 2 valules.", attr->name().c_str()); } void -LibertyReader::getAttrFloat(LibertyAttr *attr, - LibertyAttrValue *attr_value, +LibertyReader::getAttrFloat(const LibertyComplexAttr *attr, + const LibertyAttrValue *attr_value, // Return values. float &value, bool &valid) @@ -5032,17 +3225,13 @@ LibertyReader::getAttrFloat(LibertyAttr *attr, } else if (attr_value->isString()) { const std::string &str = attr_value->stringValue(); - // See if attribute string is a variable. variableValue(str.c_str(), value, valid); if (!valid) { - // For some reason area attributes for pads are quoted floats. - // Check that the string is a valid double. char *end; value = strtof(str.c_str(), &end); if ((*end && !isspace(*end)) - // strtof support INF as a valid float. || str == "inf") - libWarn(1271, attr, "%s value %s is not a float.", + libWarn(1183, attr->line(), "%s value %s is not a float.", attr->name().c_str(), str.c_str()); valid = true; @@ -5050,48 +3239,56 @@ LibertyReader::getAttrFloat(LibertyAttr *attr, } } -// Get two floats in a complex attribute. -// attr(float1, float2); -void -LibertyReader::getAttrFloat2(LibertyAttr *attr, - // Return values. - float &value1, - float &value2, - bool &exists) -{ - exists = false; - if (attr->isComplexAttr()) { - LibertyAttrValueSeq *values = attr->values(); - if (values->size() == 2) { - LibertyAttrValue *value = (*values)[0]; - getAttrFloat(attr, value, value1, exists); - if (!exists) - libWarn(1272, attr, "%s is not a float.", attr->name().c_str()); - - value = (*values)[1]; - getAttrFloat(attr, value, value2, exists); - if (!exists) - libWarn(1273, attr, "%s is not a float.", attr->name().c_str()); - } - else - libWarn(1274, attr, "%s requires 2 valules.", attr->name().c_str()); - } - else - libWarn(1345, attr, "%s requires 2 valules.", attr->name().c_str()); -} - // Parse string of comma separated floats. // Note that some brain damaged vendors (that used to "Think") are not // consistent about including the delimiters. FloatSeq LibertyReader::parseStringFloatList(const std::string &float_list, float scale, - LibertyAttr *attr) + const LibertySimpleAttr *attr) { FloatSeq values; + values.reserve(std::max(10, float_list.size() / 5)); const char *token = float_list.c_str(); while (*token != '\0') { // Some (brain dead) libraries enclose floats in brackets. + if (*token == '{') + token++; + char *end; + float value = strtof(token, &end) * scale; + if (end == token + || !(*end == '\0' + || isspace(*end) + || *end == ',' + || *end == '}')) { + std::string token_end = token; + if (end != token) { + token_end.clear(); + for (const char *t = token; t <= end; t++) + token_end += *t; + } + libWarn(1310, attr, "%s is not a float.", token_end.c_str()); + token += token_end.size(); + } + else { + values.push_back(value); + token = end; + } + while (*token == ',' || *token == ' ' || *token == '}') + token++; + } + return values; +} + +FloatSeq +LibertyReader::parseStringFloatList(const std::string &float_list, + float scale, + const LibertyComplexAttr *attr) +{ + FloatSeq values; + values.reserve(std::max(10, float_list.size() / 5)); + const char *token = float_list.c_str(); + while (*token != '\0') { if (*token == '{') token++; char *end; @@ -5121,108 +3318,93 @@ LibertyReader::parseStringFloatList(const std::string &float_list, } FloatSeq -LibertyReader::readFloatSeq(LibertyAttr *attr, +LibertyReader::readFloatSeq(const LibertyComplexAttr *attr, float scale) { FloatSeq values; - if (attr->isComplexAttr()) { - LibertyAttrValueSeq *attr_values = attr->values(); - if (attr_values->size() == 1) { - LibertyAttrValue *value = (*attr_values)[0]; - if (value->isString()) { - values = parseStringFloatList(value->stringValue(), scale, attr); - } - else if (value->isFloat()) { - values.push_back(value->floatValue()); - } - else - libWarn(1276, attr, "%s is missing values.", attr->name().c_str()); - } - else - libWarn(1277, attr, "%s has more than one string.", attr->name().c_str()); - } - else { - LibertyAttrValue *value = attr->firstValue(); + const LibertyAttrValueSeq &attr_values = attr->values(); + if (attr_values.size() == 1) { + LibertyAttrValue *value = attr_values[0]; if (value->isString()) { values = parseStringFloatList(value->stringValue(), scale, attr); } + else if (value->isFloat()) { + values.push_back(value->floatValue() * scale); + } else - libWarn(1278, attr, "%s is missing values.", attr->name().c_str()); + libWarn(1276, attr, "%s is missing values.", attr->name().c_str()); } + else if (attr_values.size() > 1) { + for (LibertyAttrValue *val : attr_values) { + if (val->isFloat()) + values.push_back(val->floatValue() * scale); + else if (val->isString()) { + FloatSeq parsed = parseStringFloatList(val->stringValue(), scale, attr); + values.insert(values.end(), parsed.begin(), parsed.end()); + } + } + } + else + libWarn(1277, attr, "%s has no values.", attr->name().c_str()); return values; } +//////////////////////////////////////////////////////////////// + void -LibertyReader::getAttrBool(LibertyAttr *attr, +LibertyReader::getAttrBool(const LibertySimpleAttr *attr, // Return values. bool &value, bool &exists) { exists = false; - if (attr->isSimpleAttr()) { - LibertyAttrValue *val = attr->firstValue(); - if (val->isString()) { - const std::string &str = val->stringValue(); - if (stringEqual(str.c_str(), "true")) { - value = true; - exists = true; - } - else if (stringEqual(str.c_str(), "false")) { - value = false; - exists = true; - } - else - libWarn(1279, attr, "%s attribute is not boolean.", attr->name().c_str()); + const LibertyAttrValue &val = attr->value(); + if (val.isString()) { + const std::string &str = val.stringValue(); + if (stringEqual(str.c_str(), "true")) { + value = true; + exists = true; + } + else if (stringEqual(str.c_str(), "false")) { + value = false; + exists = true; } else - libWarn(1280, attr, "%s attribute is not boolean.", attr->name().c_str()); + libWarn(1288, attr, "%s attribute is not boolean.", attr->name().c_str()); } else - libWarn(1281, attr, "%s is not a simple attribute.", attr->name().c_str()); + libWarn(1289, attr, "%s attribute is not boolean.", attr->name().c_str()); } // Read L/H/X string attribute values as bool. LogicValue -LibertyReader::getAttrLogicValue(LibertyAttr *attr) +LibertyReader::getAttrLogicValue(const LibertySimpleAttr *attr) { - const char *str = getAttrString(attr); + const std::string *str = attr->stringValue(); if (str) { - if (stringEq(str, "L")) + if (*str == "L") return LogicValue::zero; - else if (stringEq(str, "H")) + else if (*str == "H") return LogicValue::one; - else if (stringEq(str, "X")) + else if (*str == "X") return LogicValue::unknown; else libWarn(1282, attr, "attribute %s value %s not recognized.", - attr->name().c_str(), str); + attr->name().c_str(), str->c_str()); // fall thru } return LogicValue::unknown; } -FuncExpr * -LibertyReader::parseFunc(const char *func, - const char *attr_name, - int line) -{ - string error_msg; - stringPrint(error_msg, "%s, line %d %s", - filename_, - line, - attr_name); - return parseFuncExpr(func, cell_, error_msg.c_str(), report_); -} - const EarlyLateAll * -LibertyReader::getAttrEarlyLate(LibertyAttr *attr) +LibertyReader::getAttrEarlyLate(const LibertySimpleAttr *attr) { - const char *value = getAttrString(attr); - if (stringEq(value, "early")) + const std::string *value = attr->stringValue(); + if (*value == "early") return EarlyLateAll::early(); - else if (stringEq(value, "late")) + else if (*value == "late") return EarlyLateAll::late(); - else if (stringEq(value, "early_and_late")) + else if (*value == "early_and_late") return EarlyLateAll::all(); else { libWarn(1283, attr, "unknown early/late value."); @@ -5232,16 +3414,30 @@ LibertyReader::getAttrEarlyLate(LibertyAttr *attr) //////////////////////////////////////////////////////////////// +FuncExpr * +LibertyReader::parseFunc(const char *func, + const char *attr_name, + const LibertyCell *cell, + int line) +{ + std::string error_msg; + stringPrint(error_msg, "%s, line %d %s", + filename_, + line, + attr_name); + return parseFuncExpr(func, cell, error_msg.c_str(), report_); +} + +//////////////////////////////////////////////////////////////// + void LibertyReader::visitVariable(LibertyVariable *var) { - if (var_map_ == nullptr) - var_map_ = new LibertyVariableMap; - const string &var_name = var->variable(); + const std::string &var_name = var->variable(); float value; bool exists; findKeyValue(var_map_, var_name, value, exists); - (*var_map_)[var_name] = var->value(); + var_map_[var_name] = var->value(); } void @@ -5249,23 +3445,44 @@ LibertyReader::variableValue(const char *var, float &value, bool &exists) { - if (var_map_) - findKeyValue(var_map_, var, value, exists); - else - exists = false; + findKeyValue(var_map_, var, value, exists); } //////////////////////////////////////////////////////////////// void LibertyReader::libWarn(int id, - LibertyStmt *stmt, + const LibertyGroup *obj, const char *fmt, ...) { va_list args; va_start(args, fmt); - report_->vfileWarn(id, filename_, stmt->line(), fmt, args); + report_->vfileWarn(id, filename_, obj->line(), fmt, args); + va_end(args); +} + +void +LibertyReader::libWarn(int id, + const LibertySimpleAttr *obj, + const char *fmt, + ...) +{ + va_list args; + va_start(args, fmt); + report_->vfileWarn(id, filename_, obj->line(), fmt, args); + va_end(args); +} + +void +LibertyReader::libWarn(int id, + const LibertyComplexAttr *obj, + const char *fmt, + ...) +{ + va_list args; + va_start(args, fmt); + report_->vfileWarn(id, filename_, obj->line(), fmt, args); va_end(args); } @@ -5283,821 +3500,138 @@ LibertyReader::libWarn(int id, void LibertyReader::libError(int id, - LibertyStmt *stmt, + const LibertyGroup *obj, const char *fmt, ...) { va_list args; va_start(args, fmt); - report_->vfileError(id, filename_, stmt->line(), fmt, args); + report_->vfileError(id, filename_, obj->line(), fmt, args); + va_end(args); +} + +void +LibertyReader::libError(int id, + const LibertySimpleAttr *obj, + const char *fmt, + ...) +{ + va_list args; + va_start(args, fmt); + report_->vfileError(id, filename_, obj->line(), fmt, args); + va_end(args); +} + +void +LibertyReader::libError(int id, + const LibertyComplexAttr *obj, + const char *fmt, + ...) +{ + va_list args; + va_start(args, fmt); + report_->vfileError(id, filename_, obj->line(), fmt, args); va_end(args); } //////////////////////////////////////////////////////////////// void -LibertyReader::beginTableTemplatePower(LibertyGroup *group) +LibertyReader::readDefaultOcvDerateGroup(const LibertyGroup *library_group) { - beginTableTemplate(group, TableTemplateType::power); -} - -void -LibertyReader::beginLeakagePower(LibertyGroup *group) -{ - if (cell_) { - leakage_power_ = new LeakagePowerGroup(group->line()); - leakage_powers_.push_back(leakage_power_); - } -} - -void -LibertyReader::endLeakagePower(LibertyGroup *) -{ - leakage_power_ = nullptr; -} - -void -LibertyReader::beginInternalPower(LibertyGroup *group) -{ - if (port_group_) { - internal_power_ = new InternalPowerGroup(group->line()); - port_group_->addInternalPowerGroup(internal_power_); - } -} - -void -LibertyReader::endInternalPower(LibertyGroup *) -{ - internal_power_ = nullptr; -} - -void -LibertyReader::beginFallPower(LibertyGroup *group) -{ - if (internal_power_) - beginTableModel(group, TableTemplateType::power, - RiseFall::fall(), energy_scale_, - ScaleFactorType::internal_power); -} - -void -LibertyReader::beginRisePower(LibertyGroup *group) -{ - if (internal_power_) - beginTableModel(group, TableTemplateType::power, - RiseFall::rise(), energy_scale_, - ScaleFactorType::internal_power); -} - -void -LibertyReader::endRiseFallPower(LibertyGroup *) -{ - if (table_) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - internal_power_->setModel(rf_, std::make_shared(table_model)); - } - endTableModel(); -} - -void -LibertyReader::endPower(LibertyGroup *) -{ - if (table_) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - // Share the model for rise/fall. - auto power_model = std::make_shared(table_model); - internal_power_->setModel(RiseFall::rise(), power_model); - internal_power_->setModel(RiseFall::fall(), power_model); - } - endTableModel(); -} - -void -LibertyReader::visitRelatedGroundPin(LibertyAttr *attr) -{ - if (ports_) { - const char *related_ground_pin = getAttrString(attr); - for (LibertyPort *port : *ports_) - port->setRelatedGroundPin(related_ground_pin); - } -} - -void -LibertyReader::visitRelatedPowerPin(LibertyAttr *attr) -{ - if (ports_) { - const char *related_power_pin = getAttrString(attr); - for (LibertyPort *port : *ports_) - port->setRelatedPowerPin(related_power_pin); - } -} - -void -LibertyReader::visitRelatedPgPin(LibertyAttr *attr) -{ - if (internal_power_) - internal_power_->setRelatedPgPin(getAttrString(attr)); - else if (leakage_power_) - leakage_power_->setRelatedPgPin(getAttrString(attr)); -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginTableTemplateOcv(LibertyGroup *group) -{ - beginTableTemplate(group, TableTemplateType::ocv); -} - -void -LibertyReader::visitOcvArcDepth(LibertyAttr *attr) -{ - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) { - if (timing_) - timing_->attrs()->setOcvArcDepth(value); - else if (cell_) - cell_->setOcvArcDepth(value); + const std::string *derate_name = + library_group->findAttrString("default_ocv_derate_group"); + if (derate_name) { + OcvDerate *derate = library_->findOcvDerate(derate_name->c_str()); + if (derate) + library_->setDefaultOcvDerate(derate); else - library_->setOcvArcDepth(value); + libWarn(1284, library_group, "OCV derate group named %s not found.", + derate_name->c_str()); } } +// Read cell or library level ocv_derate groups. void -LibertyReader::visitDefaultOcvDerateGroup(LibertyAttr *attr) +LibertyReader::readOcvDerateFactors(LibertyCell *cell, + const LibertyGroup *parent_group) { - const char *derate_name = getAttrString(attr); - OcvDerate *derate = library_->findOcvDerate(derate_name); - if (derate) - library_->setDefaultOcvDerate(derate); - else - libWarn(1284, attr, "OCV derate group named %s not found.", derate_name); -} - -void -LibertyReader::visitOcvDerateGroup(LibertyAttr *attr) -{ - ocv_derate_name_ = stringCopy(getAttrString(attr)); -} - -void -LibertyReader::beginOcvDerate(LibertyGroup *group) -{ - const char *name = group->firstName(); - if (name) - ocv_derate_ = library_->makeOcvDerate(name); - else - libWarn(1285, group, "ocv_derate missing name."); -} - -void -LibertyReader::endOcvDerate(LibertyGroup *) -{ - ocv_derate_ = nullptr; -} - -void -LibertyReader::beginOcvDerateFactors(LibertyGroup *group) -{ - if (ocv_derate_) { - rf_type_ = RiseFallBoth::riseFall(); - derate_type_ = EarlyLateAll::all(); - path_type_ = PathType::clk_and_data; - beginTable(group, TableTemplateType::ocv, 1.0); - } -} - -void -LibertyReader::endOcvDerateFactors(LibertyGroup *) -{ - if (ocv_derate_) { - for (auto early_late : derate_type_->range()) { - for (auto rf : rf_type_->range()) { - if (path_type_ == PathType::clk_and_data) { - ocv_derate_->setDerateTable(rf, early_late, PathType::clk, table_); - ocv_derate_->setDerateTable(rf, early_late, PathType::data, table_); + for (const LibertyGroup *ocv_derate_group : + parent_group->findSubgroups("ocv_derate")) { + const char *name = ocv_derate_group->firstName(); + if (name) { + OcvDerate *ocv_derate = cell + ? cell->makeOcvDerate(name) + : library_->makeOcvDerate(name); + for (const LibertyGroup *factors_group : + ocv_derate_group->findSubgroups("ocv_derate_factors")) { + const RiseFallBoth *rf_type = RiseFallBoth::riseFall(); + const std::string *rf_attr = factors_group->findAttrString("rf_type"); + if (rf_attr) { + if (*rf_attr == "rise") + rf_type = RiseFallBoth::rise(); + else if (*rf_attr == "fall") + rf_type = RiseFallBoth::fall(); + else if (*rf_attr == "rise_and_fall") + rf_type = RiseFallBoth::riseFall(); + else + libError(1286, factors_group, "unknown rise/fall."); + } + + const EarlyLateAll *derate_type = EarlyLateAll::all(); + const std::string *derate_attr = factors_group->findAttrString("derate_type"); + if (derate_attr) { + if (*derate_attr == "early") + derate_type = EarlyLateAll::early(); + else if (*derate_attr == "late") + derate_type = EarlyLateAll::late(); + else if (*derate_attr == "early_and_late") + derate_type = EarlyLateAll::all(); + else { + libWarn(1309, factors_group, "unknown early/late value."); + } + } + + PathType path_type = PathType::clk_and_data; + const std::string *path_attr = factors_group->findAttrString("path_type"); + if (path_attr) { + if (*path_attr == "clock") + path_type = PathType::clk; + else if (*path_attr == "data") + path_type = PathType::data; + else if (*path_attr == "clock_and_data") + path_type = PathType::clk_and_data; + else + libWarn(1287, factors_group, "unknown derate type."); + } + + const char *template_name = factors_group->firstName(); + if (template_name) { + TableTemplate *tbl_template = + library_->findTableTemplate(template_name, TableTemplateType::ocv); + if (tbl_template) { + TablePtr table = readTableModel(factors_group, tbl_template, 1.0F); + if (table) { + for (const EarlyLate *early_late : derate_type->range()) { + for (const RiseFall *rf : rf_type->range()) { + if (path_type == PathType::clk_and_data) { + ocv_derate->setDerateTable(rf, early_late, PathType::clk, table); + ocv_derate->setDerateTable(rf, early_late, PathType::data, table); + } + else + ocv_derate->setDerateTable(rf, early_late, path_type, table); + } + } + } + } + else + libWarn(1308, factors_group, "table template %s not found.", template_name); } - else - ocv_derate_->setDerateTable(rf, early_late, path_type_, table_); } } - } - endTable(); -} - -void -LibertyReader::visitRfType(LibertyAttr *attr) -{ - const char *rf_name = getAttrString(attr); - if (stringEq(rf_name, "rise")) - rf_type_ = RiseFallBoth::rise(); - else if (stringEq(rf_name, "fall")) - rf_type_ = RiseFallBoth::fall(); - else if (stringEq(rf_name, "rise_and_fall")) - rf_type_ = RiseFallBoth::riseFall(); - else - libError(1286, attr, "unknown rise/fall."); -} - -void -LibertyReader::visitDerateType(LibertyAttr *attr) -{ - derate_type_ = getAttrEarlyLate(attr); -} - -void -LibertyReader::visitPathType(LibertyAttr *attr) -{ - const char *path_type = getAttrString(attr); - if (stringEq(path_type, "clock")) - path_type_ = PathType::clk; - else if (stringEq(path_type, "data")) - path_type_ = PathType::data; - else if (stringEq(path_type, "clock_and_data")) - path_type_ = PathType::clk_and_data; - else - libWarn(1287, attr, "unknown derate type."); -} - -//////////////////////////////////////////////////////////////// - -void -LibertyReader::beginOcvSigmaCellRise(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::rise(), ScaleFactorType::unknown); -} - -void -LibertyReader::beginOcvSigmaCellFall(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::fall(), ScaleFactorType::unknown); -} - -void -LibertyReader::endOcvSigmaCell(LibertyGroup *group) -{ - if (table_) { - if (GateTableModel::checkAxes(table_)) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - if (sigma_type_ == EarlyLateAll::all()) { - timing_->setDelaySigma(rf_, EarlyLate::min(), table_model); - timing_->setDelaySigma(rf_, EarlyLate::max(), table_model); - } - else - timing_->setDelaySigma(rf_, sigma_type_->asMinMax(), table_model); - } else - libWarn(1288, group, "unsupported model axis."); + libWarn(1285, ocv_derate_group, "ocv_derate missing name."); } - endTableModel(); -} - -void -LibertyReader::beginOcvSigmaRiseTransition(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::rise(), ScaleFactorType::unknown); -} - -void -LibertyReader::beginOcvSigmaFallTransition(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::fall(), ScaleFactorType::unknown); -} - -void -LibertyReader::endOcvSigmaTransition(LibertyGroup *group) -{ - if (table_) { - if (GateTableModel::checkAxes(table_)) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - if (sigma_type_ == EarlyLateAll::all()) { - timing_->setSlewSigma(rf_, EarlyLate::min(), table_model); - timing_->setSlewSigma(rf_, EarlyLate::max(), table_model); - } - else - timing_->setSlewSigma(rf_, sigma_type_->asMinMax(), table_model); - } - else - libWarn(1289, group, "unsupported model axis."); - } - endTableModel(); -} - -void -LibertyReader::beginOcvSigmaRiseConstraint(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::rise(), ScaleFactorType::unknown); -} - -void -LibertyReader::beginOcvSigmaFallConstraint(LibertyGroup *group) -{ - beginTimingTableModel(group, RiseFall::fall(), ScaleFactorType::unknown); -} - -void -LibertyReader::endOcvSigmaConstraint(LibertyGroup *group) -{ - if (table_) { - if (CheckTableModel::checkAxes(table_)) { - TableModel *table_model = new TableModel(table_, tbl_template_, - scale_factor_type_, rf_); - if (sigma_type_ == EarlyLateAll::all()) { - timing_->setConstraintSigma(rf_, EarlyLate::min(), table_model); - timing_->setConstraintSigma(rf_, EarlyLate::max(), table_model); - } - else - timing_->setConstraintSigma(rf_, sigma_type_->asMinMax(), table_model); - } - else - libWarn(1290, group, "unsupported model axis."); - } - endTableModel(); -} - -void -LibertyReader::visitSigmaType(LibertyAttr *attr) -{ - sigma_type_ = getAttrEarlyLate(attr); -} - -void -LibertyReader::visitCellLeakagePower(LibertyAttr *attr) -{ - if (cell_) { - float value; - bool exists; - getAttrFloat(attr, value, exists); - if (exists) - cell_->setLeakagePower(value * power_scale_); - } -} - -void -LibertyReader::beginPgPin(LibertyGroup *group) -{ - if (cell_) { - const char *name = group->firstName(); - pg_port_ = builder_.makePort(cell_, name); - } -} - -void -LibertyReader::endPgPin(LibertyGroup *) -{ - pg_port_ = nullptr; -} - -void -LibertyReader::visitPgType(LibertyAttr *attr) -{ - if (pg_port_) { - const char *type_name = getAttrString(attr); - PwrGndType type = findPwrGndType(type_name); - PortDirection *dir = PortDirection::unknown(); - switch (type) { - case PwrGndType::primary_ground: - case PwrGndType::backup_ground: - case PwrGndType::internal_ground: - dir = PortDirection::ground(); - break; - case PwrGndType::primary_power: - case PwrGndType::backup_power: - case PwrGndType::internal_power: - dir = PortDirection::power(); - break; - case PwrGndType::none: - libError(1291, attr, "unknown pg_type."); - break; - default: - break; - } - pg_port_->setPwrGndType(type); - pg_port_->setDirection(dir); - } -} - -void -LibertyReader::visitVoltageName(LibertyAttr *attr) -{ - if (pg_port_) { - const char *voltage_name = getAttrString(attr); - pg_port_->setVoltageName(voltage_name); - } -} - -// Contents Ignored. -void -LibertyReader::beginCcsn(LibertyGroup *) -{ - in_ccsn_ = true; -} - -void -LibertyReader::endCcsn(LibertyGroup *) -{ - in_ccsn_ = false; -} - -// Contents Ignored. -void -LibertyReader::beginEcsmWaveform(LibertyGroup *) -{ - in_ecsm_waveform_ = true; -} - -void -LibertyReader::endEcsmWaveform(LibertyGroup *) -{ - in_ecsm_waveform_ = false; -} - -//////////////////////////////////////////////////////////////// - -LibertyFunc::LibertyFunc(const char *expr, - LibertySetFunc set_func, - bool invert, - const char *attr_name, - int line) : - expr_(stringCopy(expr)), - set_func_(set_func), - invert_(invert), - attr_name_(stringCopy(attr_name)), - line_(line) -{ -} - -LibertyFunc::~LibertyFunc() -{ - stringDelete(expr_); - stringDelete(attr_name_); -} - -//////////////////////////////////////////////////////////////// - -PortGroup::PortGroup(LibertyPortSeq *ports, - int line) : - ports_(ports), - line_(line) -{ -} - -PortGroup::~PortGroup() -{ - deleteContents(timings_); - delete ports_; - deleteContents(internal_power_groups_); -} - -void -PortGroup::addTimingGroup(TimingGroup *timing) -{ - timings_.push_back(timing); -} - -void -PortGroup::addInternalPowerGroup(InternalPowerGroup *internal_power) -{ - internal_power_groups_.push_back(internal_power); -} - -//////////////////////////////////////////////////////////////// - -SequentialGroup::SequentialGroup(bool is_register, - bool is_bank, - LibertyPort *out_port, - LibertyPort *out_inv_port, - int size, - int line) : - is_register_(is_register), - is_bank_(is_bank), - out_port_(out_port), - out_inv_port_(out_inv_port), - size_(size), - clk_(nullptr), - data_(nullptr), - preset_(nullptr), - clear_(nullptr), - clr_preset_var1_(LogicValue::unknown), - clr_preset_var2_(LogicValue::unknown), - line_(line) -{ -} - -SequentialGroup::~SequentialGroup() -{ - if (clk_) - stringDelete(clk_); - if (data_) - stringDelete(data_); - if (preset_) - stringDelete(preset_); - if (clear_) - stringDelete(clear_); -} - -void -SequentialGroup::setClock(const char *clk) -{ - clk_ = clk; -} - -void -SequentialGroup::setData(const char *data) -{ - data_ = data; -} - -void -SequentialGroup::setClear(const char *clr) -{ - clear_ = clr; -} - -void -SequentialGroup::setPreset(const char *preset) -{ - preset_ = preset; -} - -void -SequentialGroup::setClrPresetVar1(LogicValue var) -{ - clr_preset_var1_ = var; -} - -void -SequentialGroup::setClrPresetVar2(LogicValue var) -{ - clr_preset_var2_ = var; -} - -//////////////////////////////////////////////////////////////// - -StatetableGroup::StatetableGroup(StdStringSeq &input_ports, - StdStringSeq &internal_ports, - int line) : - input_ports_(input_ports), - internal_ports_(internal_ports), - line_(line) -{ -} - -void -StatetableGroup::addRow(StateInputValues &input_values, - StateInternalValues ¤t_values, - StateInternalValues &next_values) -{ - table_.emplace_back(input_values, current_values, next_values); -} - -//////////////////////////////////////////////////////////////// - -RelatedPortGroup::RelatedPortGroup(int line) : - related_port_names_(nullptr), - line_(line) -{ -} - -RelatedPortGroup::~RelatedPortGroup() -{ - if (related_port_names_) { - deleteContents(related_port_names_); - delete related_port_names_; - } -} - -void -RelatedPortGroup::setRelatedPortNames(StringSeq *names) -{ - related_port_names_ = names; -} - -void -RelatedPortGroup::setIsOneToOne(bool one) -{ - is_one_to_one_ = one; -} - -//////////////////////////////////////////////////////////////// - -TimingGroup::TimingGroup(int line) : - RelatedPortGroup(line), - attrs_(make_shared()), - related_output_port_name_(nullptr), - receiver_model_(nullptr) -{ - for (auto rf_index : RiseFall::rangeIndex()) { - cell_[rf_index] = nullptr; - constraint_[rf_index] = nullptr; - transition_[rf_index] = nullptr; - intrinsic_[rf_index] = 0.0F; - intrinsic_exists_[rf_index] = false; - resistance_[rf_index] = 0.0F; - resistance_exists_[rf_index] = false; - output_waveforms_[rf_index] = nullptr; - - for (auto el_index : EarlyLate::rangeIndex()) { - delay_sigma_[rf_index][el_index] = nullptr; - slew_sigma_[rf_index][el_index] = nullptr; - constraint_sigma_[rf_index][el_index] = nullptr; - } - } -} - -TimingGroup::~TimingGroup() -{ - if (related_output_port_name_) - stringDelete(related_output_port_name_); -} - -void -TimingGroup::setRelatedOutputPortName(const char *name) -{ - related_output_port_name_ = stringCopy(name); -} - -void -TimingGroup::setIntrinsic(const RiseFall *rf, - float value) -{ - int rf_index = rf->index(); - intrinsic_[rf_index] = value; - intrinsic_exists_[rf_index] = true; -} - -void -TimingGroup::intrinsic(const RiseFall *rf, - // Return values. - float &value, - bool &exists) -{ - int rf_index = rf->index(); - value = intrinsic_[rf_index]; - exists = intrinsic_exists_[rf_index]; -} - -void -TimingGroup::setResistance(const RiseFall *rf, - float value) -{ - int rf_index = rf->index(); - resistance_[rf_index] = value; - resistance_exists_[rf_index] = true; -} - -void -TimingGroup::resistance(const RiseFall *rf, - // Return values. - float &value, - bool &exists) -{ - int rf_index = rf->index(); - value = resistance_[rf_index]; - exists = resistance_exists_[rf_index]; -} - -TableModel * -TimingGroup::cell(const RiseFall *rf) -{ - return cell_[rf->index()]; -} - -void -TimingGroup::setCell(const RiseFall *rf, - TableModel *model) -{ - cell_[rf->index()] = model; -} - -TableModel * -TimingGroup::constraint(const RiseFall *rf) -{ - return constraint_[rf->index()]; -} - -void -TimingGroup::setConstraint(const RiseFall *rf, - TableModel *model) -{ - constraint_[rf->index()] = model; -} - -TableModel * -TimingGroup::transition(const RiseFall *rf) -{ - return transition_[rf->index()]; -} - -void -TimingGroup::setTransition(const RiseFall *rf, - TableModel *model) -{ - transition_[rf->index()] = model; -} - -void -TimingGroup::setDelaySigma(const RiseFall *rf, - const EarlyLate *early_late, - TableModel *model) -{ - delay_sigma_[rf->index()][early_late->index()] = model; -} - -void -TimingGroup::setSlewSigma(const RiseFall *rf, - const EarlyLate *early_late, - TableModel *model) -{ - slew_sigma_[rf->index()][early_late->index()] = model; -} - -void -TimingGroup::setConstraintSigma(const RiseFall *rf, - const EarlyLate *early_late, - TableModel *model) -{ - constraint_sigma_[rf->index()][early_late->index()] = model; -} - -void -TimingGroup::setReceiverModel(ReceiverModelPtr receiver_model) -{ - receiver_model_ = receiver_model; -} - -OutputWaveforms * -TimingGroup::outputWaveforms(const RiseFall *rf) -{ - return output_waveforms_[rf->index()]; -} - -void -TimingGroup::setOutputWaveforms(const RiseFall *rf, - OutputWaveforms *output_waveforms) -{ - output_waveforms_[rf->index()] = output_waveforms; -} - -//////////////////////////////////////////////////////////////// - -InternalPowerGroup::InternalPowerGroup(int line) : - RelatedPortGroup(line), - when_(), - models_{} -{ -} - -void -InternalPowerGroup::setWhen(std::shared_ptr when) -{ - when_ = std::move(when); -} - -void -InternalPowerGroup::setModel(const RiseFall *rf, - std::shared_ptr model) -{ - models_[rf->index()] = std::move(model); -} - -void -InternalPowerGroup::setRelatedPgPin(std::string related_pg_pin) -{ - related_pg_pin_ = std::move(related_pg_pin); -} - -//////////////////////////////////////////////////////////////// - -LeakagePowerGroup::LeakagePowerGroup(int line) : - when_(nullptr), - power_(0.0), - line_(line) -{ -} - -void -LeakagePowerGroup::setRelatedPgPin(std::string pin_name) -{ - related_pg_pin_ = std::move(pin_name); -} - -void -LeakagePowerGroup::setWhen(FuncExpr *when) -{ - when_ = when; -} - -void -LeakagePowerGroup::setPower(float power) -{ - power_ = power; } //////////////////////////////////////////////////////////////// @@ -6121,7 +3655,7 @@ PortNameBitIterator::PortNameBitIterator(LibertyCell *cell, void PortNameBitIterator::init(const char *port_name) { - LibertyPort *port = visitor_->findPort(port_name); + LibertyPort *port = visitor_->findPort(cell_, port_name); if (port) { if (port->isBus()) bit_iterator_ = new LibertyPortMemberIterator(port); @@ -6133,13 +3667,13 @@ PortNameBitIterator::init(const char *port_name) // Check for bus range. LibertyLibrary *library = visitor_->library(); bool is_bus, is_range, subscript_wild; - string bus_name; + std::string bus_name; int from, to; parseBusName(port_name, library->busBrktLeft(), library->busBrktRight(), '\\', is_bus, is_range, bus_name, from, to, subscript_wild); if (is_range) { - port = visitor_->findPort(port_name); + port = visitor_->findPort(cell_, port_name); if (port) { if (port->isBus()) { if (port->busIndexInRange(from) @@ -6224,13 +3758,9 @@ PortNameBitIterator::findRangeBusNameNext() ? range_bit_ >= range_to_ : range_bit_ <= range_to_) { LibertyLibrary *library = visitor_->library(); - string bus_bit_name; - stringPrint(bus_bit_name, "%s%c%d%c", - range_bus_name_.c_str(), - library->busBrktLeft(), - range_bit_, - library->busBrktRight()); - range_name_next_ = visitor_->findPort(bus_bit_name.c_str()); + std::string bus_bit_name = range_bus_name_ + library->busBrktLeft() + + std::to_string(range_bit_) + library->busBrktRight(); + range_name_next_ = visitor_->findPort(cell_, bus_bit_name.c_str()); if (range_name_next_) { if (range_from_ > range_to_) range_bit_--; @@ -6257,17 +3787,10 @@ OutputWaveform::OutputWaveform(float slew, { } -OutputWaveform::~OutputWaveform() -{ - delete currents_; -} - Table * -OutputWaveform::stealCurrents() +OutputWaveform::releaseCurrents() { - Table *currents = currents_; - currents_ = nullptr; - return currents; + return currents_.release(); } } // namespace diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index b4a8e604..91fdf260 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -47,33 +48,17 @@ namespace sta { class LibertyBuilder; class LibertyReader; -class LibertyFunc; -class PortGroup; -class SequentialGroup; -class StatetableGroup; -class RelatedPortGroup; -class TimingGroup; -class InternalPowerGroup; -class LeakagePowerGroup; class PortNameBitIterator; class TimingArcBuilder; -class LibertyAttr; class OutputWaveform; -using LibraryAttrVisitor = void (LibertyReader::*)(LibertyAttr *attr); -using LibraryGroupVisitor = void (LibertyReader::*)(LibertyGroup *group); -using LibraryAttrMap = std::unordered_map; -using LibraryGroupMap = std::unordered_map; -using PortGroupSeq = std::vector; -using SequentialGroupSeq = std::vector; -using LibertyFuncSeq = std::vector; -using TimingGroupSeq = std::vector; -using InternalPowerGroupSeq = std::vector; -using LeakagePowerGroupSeq = std::vector; -using LibertyPortBoolSetter = void (LibertyPort::*)(bool value); -using OutputWaveformSeq = std::vector; +using LibraryGroupVisitor = void (LibertyReader::*)(const LibertyGroup *group, + LibertyGroup *parent_group); +using LibraryGroupVisitorMap = std::unordered_map; using StdStringSeq = std::vector; -using LibertySetFunc = std::function; +using LibertyPortGroupMap = std::map; +using OutputWaveformSeq = std::vector; class LibertyReader : public LibertyGroupVisitor { @@ -81,428 +66,124 @@ public: LibertyReader(const char *filename, bool infer_latches, Network *network); - virtual ~LibertyReader(); virtual LibertyLibrary *readLibertyFile(const char *filename); LibertyLibrary *library() { return library_; } const LibertyLibrary *library() const { return library_; } - virtual void init(const char *filename, - bool infer_latches, - Network *network); - virtual bool save(LibertyGroup *) { return false; } - virtual bool save(LibertyAttr *) { return false; } - virtual bool save(LibertyVariable *) { return false; } + virtual void beginLibrary(const LibertyGroup *group, + LibertyGroup *library_group); + virtual void endLibrary(const LibertyGroup *group, + LibertyGroup *null_group); + virtual void visitAttr(const LibertySimpleAttr *attr); + virtual void visitAttr(const LibertyComplexAttr *attr); + virtual void visitVariable(LibertyVariable *var); + // Extension points for custom attributes (e.g. LibertyExt). + virtual void visitAttr1(const LibertySimpleAttr *) {} + virtual void visitAttr2(const LibertySimpleAttr *) {} - virtual void beginLibrary(LibertyGroup *group); - virtual void endLibrary(LibertyGroup *group); - virtual void endLibraryAttrs(LibertyGroup *group); - virtual void visitAttr(LibertyAttr *attr); - virtual void visitTimeUnit(LibertyAttr *attr); - virtual void visitCapacitiveLoadUnit(LibertyAttr *attr); - virtual void visitResistanceUnit(LibertyAttr *attr); - virtual void visitPullingResistanceUnit(LibertyAttr *attr); - virtual void visitVoltageUnit(LibertyAttr *attr); - virtual void visitCurrentUnit(LibertyAttr *attr); - virtual void visitPowerUnit(LibertyAttr *attr); - virtual void visitDistanceUnit(LibertyAttr *attr); - virtual void parseUnits(LibertyAttr *attr, - const char *suffix, - float &scale_var, - Unit *unit_suffix); - virtual void visitDelayModel(LibertyAttr *attr); - virtual void visitVoltageMap(LibertyAttr *attr); - virtual void visitBusStyle(LibertyAttr *attr); - virtual void visitNomTemp(LibertyAttr *attr); - virtual void visitNomVolt(LibertyAttr *attr); - virtual void visitNomProc(LibertyAttr *attr); - virtual void visitDefaultInoutPinCap(LibertyAttr *attr); - virtual void visitDefaultInputPinCap(LibertyAttr *attr); - virtual void visitDefaultOutputPinCap(LibertyAttr *attr); - virtual void visitDefaultMaxTransition(LibertyAttr *attr); - virtual void visitDefaultMaxFanout(LibertyAttr *attr); - virtual void visitDefaultIntrinsicRise(LibertyAttr *attr); - virtual void visitDefaultIntrinsicFall(LibertyAttr *attr); - virtual void visitDefaultIntrinsic(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitDefaultInoutPinRiseRes(LibertyAttr *attr); - virtual void visitDefaultInoutPinFallRes(LibertyAttr *attr); - virtual void visitDefaultInoutPinRes(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitDefaultOutputPinRiseRes(LibertyAttr *attr); - virtual void visitDefaultOutputPinFallRes(LibertyAttr *attr); - virtual void visitDefaultOutputPinRes(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitDefaultFanoutLoad(LibertyAttr *attr); - virtual void visitDefaultWireLoad(LibertyAttr *attr); - virtual void visitDefaultWireLoadMode(LibertyAttr *attr); - virtual void visitDefaultWireLoadSelection(LibertyAttr *attr); - virtual void visitDefaultOperatingConditions(LibertyAttr *attr); - virtual void visitInputThresholdPctFall(LibertyAttr *attr); - virtual void visitInputThresholdPctRise(LibertyAttr *attr); - virtual void visitInputThresholdPct(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitOutputThresholdPctFall(LibertyAttr *attr); - virtual void visitOutputThresholdPctRise(LibertyAttr *attr); - virtual void visitOutputThresholdPct(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitSlewLowerThresholdPctFall(LibertyAttr *attr); - virtual void visitSlewLowerThresholdPctRise(LibertyAttr *attr); - virtual void visitSlewLowerThresholdPct(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitSlewUpperThresholdPctFall(LibertyAttr *attr); - virtual void visitSlewUpperThresholdPctRise(LibertyAttr *attr); - virtual void visitSlewUpperThresholdPct(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitSlewDerateFromLibrary(LibertyAttr *attr); + void endCell(const LibertyGroup *group, + LibertyGroup *library_group); + void endScaledCell(const LibertyGroup *group, + LibertyGroup *library_group); + void checkScaledCell(LibertyCell *scaled_cell, + LibertyCell *owner, + const LibertyGroup *scaled_cell_group, + const char *op_cond_name); - virtual void beginTechnology(LibertyGroup *group); - virtual void endTechnology(LibertyGroup *group); - virtual void beginTableTemplateDelay(LibertyGroup *group); - virtual void beginTableTemplateOutputCurrent(LibertyGroup *group); - virtual void beginTableTemplate(LibertyGroup *group, - TableTemplateType type); - virtual void endTableTemplate(LibertyGroup *group); - virtual void visitVariable1(LibertyAttr *attr); - virtual void visitVariable2(LibertyAttr *attr); - virtual void visitVariable3(LibertyAttr *attr); - virtual void visitIndex1(LibertyAttr *attr); - virtual void visitIndex2(LibertyAttr *attr); - virtual void visitIndex3(LibertyAttr *attr); + void setPortCapDefault(LibertyPort *port); + void checkLatchEnableSense(FuncExpr *enable_func, + int line); + FloatTable makeFloatTable(const LibertyComplexAttr *attr, + const LibertyGroup *table_group, + size_t rows, + size_t cols, + float scale); - virtual void beginType(LibertyGroup *group); - virtual void endType(LibertyGroup *group); - virtual void visitBitFrom(LibertyAttr *attr); - virtual void visitBitTo(LibertyAttr *attr); - - virtual void beginCell(LibertyGroup *group); - virtual void endCell(LibertyGroup *group); - virtual void beginScaledCell(LibertyGroup *group); - virtual void endScaledCell(LibertyGroup *group); - virtual void checkScaledCell(LibertyGroup *group); - virtual void finishPortGroups(); - virtual void checkPort(LibertyPort *port, - int line); - virtual void makeTimingArcs(PortGroup *port_group); - virtual void makeInternalPowers(PortGroup *port_group); - virtual void makeCellSequentials(); - virtual void makeCellSequential(SequentialGroup *seq); - virtual void makeStatetable(); - virtual void makeLeakagePowers(); - virtual void parseCellFuncs(); - virtual void makeLibertyFunc(const char *expr, - LibertySetFunc set_func, - bool invert, - const char *attr_name, - LibertyStmt *stmt); - virtual void makeTimingArcs(LibertyPort *to_port, - TimingGroup *timing); - virtual void makeTimingArcs(const char *from_port_name, - PortNameBitIterator &from_port_iter, - LibertyPort *to_port, - LibertyPort *related_out_port, - TimingGroup *timing); - virtual void makeTimingArcs(LibertyPort *to_port, - LibertyPort *related_out_port, - TimingGroup *timing); - - virtual void visitClockGatingIntegratedCell(LibertyAttr *attr); - virtual void visitArea(LibertyAttr *attr); - virtual void visitDontUse(LibertyAttr *attr); - virtual void visitIsMacro(LibertyAttr *attr); - virtual void visitIsMemory(LibertyAttr *attr); - virtual void visitIsPadCell(LibertyAttr *attr); - virtual void visitIsPad(LibertyAttr *attr); - virtual void visitIsClockCell(LibertyAttr *attr); - virtual void visitIsLevelShifter(LibertyAttr *attr); - virtual void visitLevelShifterType(LibertyAttr *attr); - virtual void visitIsIsolationCell(LibertyAttr *attr); - virtual void visitAlwaysOn(LibertyAttr *attr); - virtual void visitSwitchCellType(LibertyAttr *attr); - virtual void visitInterfaceTiming(LibertyAttr *attr); - virtual void visitScalingFactors(LibertyAttr *attr); - virtual void visitCellLeakagePower(LibertyAttr *attr); - virtual void visitCellFootprint(LibertyAttr *attr); - virtual void visitCellUserFunctionClass(LibertyAttr *attr); - - virtual void beginPin(LibertyGroup *group); - virtual void endPin(LibertyGroup *group); - virtual void beginBus(LibertyGroup *group); - virtual void endBus(LibertyGroup *group); - virtual void beginBundle(LibertyGroup *group); - virtual void endBundle(LibertyGroup *group); - virtual void beginBusOrBundle(LibertyGroup *group); - virtual void endBusOrBundle(); - virtual void endPorts(); - virtual void setPortCapDefault(LibertyPort *port); - virtual void visitMembers(LibertyAttr *attr); - virtual void visitDirection(LibertyAttr *attr); - virtual void visitFunction(LibertyAttr *attr); - virtual void visitThreeState(LibertyAttr *attr); - virtual void visitBusType(LibertyAttr *attr); - virtual void visitCapacitance(LibertyAttr *attr); - virtual void visitRiseCap(LibertyAttr *attr); - virtual void visitFallCap(LibertyAttr *attr); - virtual void visitRiseCapRange(LibertyAttr *attr); - virtual void visitFallCapRange(LibertyAttr *attr); - virtual void visitFanoutLoad(LibertyAttr *attr); - virtual void visitMaxFanout(LibertyAttr *attr); - virtual void visitMinFanout(LibertyAttr *attr); - virtual void visitFanout(LibertyAttr *attr, - const MinMax *min_max); - virtual void visitMaxTransition(LibertyAttr *attr); - virtual void visitMinTransition(LibertyAttr *attr); - virtual void visitMinMaxTransition(LibertyAttr *attr, - const MinMax *min_max); - virtual void visitMaxCapacitance(LibertyAttr *attr); - virtual void visitMinCapacitance(LibertyAttr *attr); - virtual void visitMinMaxCapacitance(LibertyAttr *attr, - const MinMax *min_max); - virtual void visitMinPeriod(LibertyAttr *attr); - virtual void visitMinPulseWidthLow(LibertyAttr *attr); - virtual void visitMinPulseWidthHigh(LibertyAttr *attr); - virtual void visitMinPulseWidth(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitPulseClock(LibertyAttr *attr); - virtual void visitClockGateClockPin(LibertyAttr *attr); - virtual void visitClockGateEnablePin(LibertyAttr *attr); - virtual void visitClockGateOutPin(LibertyAttr *attr); - void visitIsPllFeedbackPin(LibertyAttr *attr); - virtual void visitSignalType(LibertyAttr *attr); - const EarlyLateAll *getAttrEarlyLate(LibertyAttr *attr); - virtual void visitClock(LibertyAttr *attr); - virtual void visitIsolationCellDataPin(LibertyAttr *attr); - virtual void visitIsolationCellEnablePin(LibertyAttr *attr); - virtual void visitLevelShifterDataPin(LibertyAttr *attr); - virtual void visitSwitchPin(LibertyAttr *attr); - void visitPortBoolAttr(LibertyAttr *attr, - LibertyPortBoolSetter setter); - - virtual void beginScalingFactors(LibertyGroup *group); - virtual void endScalingFactors(LibertyGroup *group); - virtual void defineScalingFactorVisitors(); - virtual void visitScaleFactorSuffix(LibertyAttr *attr); - virtual void visitScaleFactorPrefix(LibertyAttr *attr); - virtual void visitScaleFactorHiLow(LibertyAttr *attr); - virtual void visitScaleFactor(LibertyAttr *attr); - - virtual void beginOpCond(LibertyGroup *group); - virtual void endOpCond(LibertyGroup *group); - virtual void visitProc(LibertyAttr *attr); - virtual void visitVolt(LibertyAttr *attr); - virtual void visitTemp(LibertyAttr *attr); - virtual void visitTreeType(LibertyAttr *attr); - - virtual void beginWireload(LibertyGroup *group); - virtual void endWireload(LibertyGroup *group); - virtual void visitResistance(LibertyAttr *attr); - virtual void visitSlope(LibertyAttr *attr); - virtual void visitFanoutLength(LibertyAttr *attr); - - virtual void beginWireloadSelection(LibertyGroup *group); - virtual void endWireloadSelection(LibertyGroup *group); - virtual void visitWireloadFromArea(LibertyAttr *attr); - - virtual void beginMemory(LibertyGroup *group); - virtual void endMemory(LibertyGroup *group); - - virtual void beginFF(LibertyGroup *group); - virtual void endFF(LibertyGroup *group); - virtual void beginFFBank(LibertyGroup *group); - virtual void endFFBank(LibertyGroup *group); - virtual void beginLatch(LibertyGroup *group); - virtual void endLatch(LibertyGroup *group); - virtual void beginLatchBank(LibertyGroup *group); - virtual void endLatchBank(LibertyGroup *group); - virtual void beginSequential(LibertyGroup *group, - bool is_register, - bool is_bank); - virtual void seqPortNames(LibertyGroup *group, - const char *&out_name, - const char *&out_inv_name, - bool &has_size, - int &size); - virtual void checkLatchEnableSense(FuncExpr *enable_func, - int line); - virtual void visitClockedOn(LibertyAttr *attr); - virtual void visitDataIn(LibertyAttr *attr); - virtual void visitClear(LibertyAttr *attr); - virtual void visitPreset(LibertyAttr *attr); - virtual void visitClrPresetVar1(LibertyAttr *attr); - virtual void visitClrPresetVar2(LibertyAttr *attr); - - virtual void beginStatetable(LibertyGroup *group); - virtual void endStatetable(LibertyGroup *group); - virtual void visitTable(LibertyAttr *attr); - - virtual void beginTiming(LibertyGroup *group); - virtual void endTiming(LibertyGroup *group); - virtual void visitRelatedPin(LibertyAttr *attr); - virtual void visitRelatedPin(LibertyAttr *attr, - RelatedPortGroup *group); - virtual void visitRelatedBusPins(LibertyAttr *attr); - virtual void visitRelatedBusPins(LibertyAttr *attr, - RelatedPortGroup *group); - virtual void visitRelatedOutputPin(LibertyAttr *attr); - virtual void visitTimingType(LibertyAttr *attr); - virtual void visitTimingSense(LibertyAttr *attr); - virtual void visitSdfCondStart(LibertyAttr *attr); - virtual void visitSdfCondEnd(LibertyAttr *attr); - virtual void visitMode(LibertyAttr *attr); - virtual void visitIntrinsicRise(LibertyAttr *attr); - virtual void visitIntrinsicFall(LibertyAttr *attr); - virtual void visitIntrinsic(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitRiseResistance(LibertyAttr *attr); - virtual void visitFallResistance(LibertyAttr *attr); - virtual void visitRiseFallResistance(LibertyAttr *attr, - const RiseFall *rf); - virtual void visitValue(LibertyAttr *attr); - virtual void visitValues(LibertyAttr *attr); - virtual void beginCellRise(LibertyGroup *group); - virtual void beginCellFall(LibertyGroup *group); - virtual void endCellRiseFall(LibertyGroup *group); - virtual void beginRiseTransition(LibertyGroup *group); - virtual void endRiseFallTransition(LibertyGroup *group); - virtual void beginFallTransition(LibertyGroup *group); - virtual void beginRiseConstraint(LibertyGroup *group); - virtual void endRiseFallConstraint(LibertyGroup *group); - virtual void beginFallConstraint(LibertyGroup *group); - - virtual void beginRiseTransitionDegredation(LibertyGroup *group); - virtual void beginFallTransitionDegredation(LibertyGroup *group); - virtual void endRiseFallTransitionDegredation(LibertyGroup *group); - - virtual void beginTableModel(LibertyGroup *group, - TableTemplateType type, - const RiseFall *rf, - float scale, - ScaleFactorType scale_factor_type); - virtual void endTableModel(); - virtual void beginTimingTableModel(LibertyGroup *group, - const RiseFall *rf, - ScaleFactorType scale_factor_type); - virtual void beginTable(LibertyGroup *group, - TableTemplateType type, - float scale); - virtual void endTable(); - virtual void makeTable(LibertyAttr *attr, - float scale); - virtual FloatTable makeFloatTable(LibertyAttr *attr, - size_t rows, - size_t cols, - float scale); - - virtual void beginLut(LibertyGroup *group); - virtual void endLut(LibertyGroup *group); - - virtual void beginTestCell(LibertyGroup *group); - virtual void endTestCell(LibertyGroup *group); - - virtual void beginModeDef(LibertyGroup *group); - virtual void endModeDef(LibertyGroup *group); - virtual void beginModeValue(LibertyGroup *group); - virtual void endModeValue(LibertyGroup *group); - virtual void visitWhen(LibertyAttr *attr); - virtual void visitSdfCond(LibertyAttr *attr); - - // Power attributes. - virtual void beginTableTemplatePower(LibertyGroup *group); - virtual void beginLeakagePower(LibertyGroup *group); - virtual void endLeakagePower(LibertyGroup *group); - virtual void beginInternalPower(LibertyGroup *group); - virtual void endInternalPower(LibertyGroup *group); - virtual void beginFallPower(LibertyGroup *group); - virtual void beginRisePower(LibertyGroup *group); - virtual void endRiseFallPower(LibertyGroup *group); - virtual void endPower(LibertyGroup *group); - virtual void visitRelatedGroundPin(LibertyAttr *attr); - virtual void visitRelatedPowerPin(LibertyAttr *attr); - virtual void visitRelatedPgPin(LibertyAttr *attr); - virtual void makeInternalPowers(LibertyPort *port, - InternalPowerGroup *power_group); - virtual void makeInternalPowers(LibertyPort *port, - const char *related_port_name, - PortNameBitIterator &related_port_iter, - LibertyPort *related_pg_pin, - InternalPowerGroup *power_group); - - // AOCV attributes. - virtual void beginTableTemplateOcv(LibertyGroup *group); - virtual void visitOcvArcDepth(LibertyAttr *attr); - virtual void visitDefaultOcvDerateGroup(LibertyAttr *attr); - virtual void visitOcvDerateGroup(LibertyAttr *attr); - virtual void beginOcvDerate(LibertyGroup *group); - virtual void endOcvDerate(LibertyGroup *group); - virtual void beginOcvDerateFactors(LibertyGroup *group); - virtual void endOcvDerateFactors(LibertyGroup *group); - virtual void visitRfType(LibertyAttr *attr); - virtual void visitDerateType(LibertyAttr *attr); - virtual void visitPathType(LibertyAttr *attr); - - // POCV attributes. - virtual void beginOcvSigmaCellRise(LibertyGroup *group); - virtual void beginOcvSigmaCellFall(LibertyGroup *group); - virtual void endOcvSigmaCell(LibertyGroup *group); - virtual void beginOcvSigmaRiseTransition(LibertyGroup *group); - virtual void beginOcvSigmaFallTransition(LibertyGroup *group); - virtual void endOcvSigmaTransition(LibertyGroup *group); - virtual void beginOcvSigmaRiseConstraint(LibertyGroup *group); - virtual void beginOcvSigmaFallConstraint(LibertyGroup *group); - virtual void endOcvSigmaConstraint(LibertyGroup *group); - virtual void visitSigmaType(LibertyAttr *attr); - - // PgPin group. - virtual void beginPgPin(LibertyGroup *group); - virtual void endPgPin(LibertyGroup *group); - virtual void visitPgType(LibertyAttr *attr); - virtual void visitVoltageName(LibertyAttr *attr); - - // ccs receiver capacitance - virtual void beginReceiverCapacitance(LibertyGroup *group); - virtual void endReceiverCapacitance(LibertyGroup *group); - - virtual void visitSegement(LibertyAttr *attr); - - virtual void beginReceiverCapacitance1Rise(LibertyGroup *group); - virtual void endReceiverCapacitanceRiseFall(LibertyGroup *group); - virtual void beginReceiverCapacitance1Fall(LibertyGroup *group); - virtual void beginReceiverCapacitance2Rise(LibertyGroup *group); - virtual void beginReceiverCapacitance2Fall(LibertyGroup *group); - void beginReceiverCapacitance(LibertyGroup *group, - int index, - const RiseFall *rf); - void endReceiverCapacitance(LibertyGroup *group, - int index, - const RiseFall *rf); - // ccs - void beginOutputCurrentRise(LibertyGroup *group); - void beginOutputCurrentFall(LibertyGroup *group); - void beginOutputCurrent(const RiseFall *rf, - LibertyGroup *group); - void endOutputCurrentRiseFall(LibertyGroup *group); - void beginVector(LibertyGroup *group); - void endVector(LibertyGroup *group); - void visitReferenceTime(LibertyAttr *attr); - - void beginNormalizedDriverWaveform(LibertyGroup *group); - void endNormalizedDriverWaveform(LibertyGroup *group); - void visitDriverWaveformName(LibertyAttr *attr); - - void visitDriverWaveformRise(LibertyAttr *attr); - void visitDriverWaveformFall(LibertyAttr *attr); - void visitDriverWaveformRiseFall(LibertyAttr *attr, - const RiseFall *rf); - - void beginCcsn(LibertyGroup *group); - void endCcsn(LibertyGroup *group); - void beginEcsmWaveform(LibertyGroup *group); - void endEcsmWaveform(LibertyGroup *group); LibertyPort *findPort(LibertyCell *cell, const char *port_name); - virtual void begin(LibertyGroup *group); - virtual void end(LibertyGroup *group); + StdStringSeq findAttributStrings(const LibertyGroup *group, + const char *name_attr); protected: + virtual void begin(const LibertyGroup *group, + LibertyGroup *library_group); + virtual void end(const LibertyGroup *group, + LibertyGroup *library_group); + + // Library gruops. + void makeLibrary(const LibertyGroup *libary_group); + void readLibraryAttributes(const LibertyGroup *library_group); + void readLibraryUnits(const LibertyGroup *library_group); + void readDelayModel(const LibertyGroup *library_group); + void readBusStyle(const LibertyGroup *library_group); + void readDefaultWireLoad(const LibertyGroup *library_group); + void readDefaultWireLoadMode(const LibertyGroup *library_group); + void readTechnology(const LibertyGroup *library_group); + void readDefaultWireLoadSelection(const LibertyGroup *library_group); + void readUnit(const char *unit_attr_name, + const char *unit_suffix, + float &scale_var, + Unit *unit, + const LibertyGroup *library_group); + void readBusTypes(LibertyCell *cell, + const LibertyGroup *type_group); + void readTableTemplates(const LibertyGroup *library_group); + void readTableTemplates(const LibertyGroup *library_group, + const char *group_name, + TableTemplateType type); + void readThresholds(const LibertyGroup *library_group); + TableAxisPtr makeTableTemplateAxis(const LibertyGroup *template_group, + int axis_index); + void readVoltateMaps(const LibertyGroup *library_group); + void readWireloads(const LibertyGroup *library_group); + void readWireloadSelection(const LibertyGroup *library_group); + void readOperatingConds(const LibertyGroup *library_group); + void readScaleFactors(const LibertyGroup *library_group); + void readScaleFactors(const LibertyGroup *scale_group, + ScaleFactors *scale_factors); + void readOcvDerateFactors(LibertyCell *cell, + const LibertyGroup *library_group); + void readDefaultOcvDerateGroup(const LibertyGroup *library_group); + void readNormalizedDriverWaveform(const LibertyGroup *library_group); + void readSlewDegradations(const LibertyGroup *library_group); + void readLibAttrFloat(const LibertyGroup *library_group, + const char *attr_name, + void (LibertyLibrary::*set_func)(float value), + float scale); + void readLibAttrFloat(const LibertyGroup *library_group, + const char *attr_name, + void (LibertyLibrary::*set_func)(const RiseFall *rf, + float value), + const RiseFall *rf, + float scale); + void readLibAttrFloatWarnZero(const LibertyGroup *library_group, + const char *attr_name, + void (LibertyLibrary::*set_func)(float value), + float scale); + + // Cell groups. + void readCell(LibertyCell *cell, + const LibertyGroup *cell_group); + void readScaledCell(const LibertyGroup *scaled_cell_group); + LibertyPortGroupMap makeCellPorts(LibertyCell *cell, + const LibertyGroup *cell_group); + void makePinPort(LibertyCell *cell, + const LibertyGroup *pin_group, + LibertyPortGroupMap &port_group_map); + void makeBusPort(LibertyCell *cell, + const LibertyGroup *bus_group, + LibertyPortGroupMap &port_group_map); + void makeBusPinPorts(LibertyCell *cell, + const LibertyGroup *bus_group, + LibertyPortGroupMap &port_group_map); + void makeBundlePort(LibertyCell *cell, + const LibertyGroup *bundle_group, + LibertyPortGroupMap &port_group_map); + void makeBundlePinPorts(LibertyCell *cell, + const LibertyGroup *bundle_group, + LibertyPortGroupMap &port_group_map); + void makePgPinPort(LibertyCell *cell, + const LibertyGroup *pg_pin_group); LibertyPort *makePort(LibertyCell *cell, const char *port_name); LibertyPort *makeBusPort(LibertyCell *cell, @@ -511,78 +192,270 @@ protected: int to_index, BusDcl *bus_dcl); - TimingModel *makeScalarCheckModel(float value, + void readPortAttributes(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void readPortAttrString(const char *attr_name, + void (LibertyPort::*set_func)(const char *value), + const LibertyPortSeq &ports, + const LibertyGroup *group); + void readPortAttrFloat(const char *attr_name, + void (LibertyPort::*set_func)(float value), + const LibertyPortSeq &ports, + const LibertyGroup *group, + float scale); + void readPortAttrBool(const char *attr_name, + void (LibertyPort::*set_func)(bool value), + const LibertyPortSeq &ports, + const LibertyGroup *group); + void readDriverWaveform(const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void readPortAttrFloatMinMax(const char *attr_name, + void (LibertyPort::*set_func)(float value, + const MinMax *min_max), + const LibertyPortSeq &ports, + const LibertyGroup *group, + const MinMax *min_max, + float scale); + void readPulseClock(const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void readSignalType(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void readMinPulseWidth(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void readModeDefs(LibertyCell *cell, + const LibertyGroup *cell_group); + void makeTimingArcs(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group); + bool isGateTimingType(TimingType timing_type); + TableModel *readGateTableModel(const LibertyGroup *timing_group, + const char *table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type); + TableModelsEarlyLate + readEarlyLateTableModels(const LibertyGroup *timing_group, + const char *table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type); + TableModel *readCheckTableModel(const LibertyGroup *timing_group, + const char *table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type); + ReceiverModelPtr readReceiverCapacitance(const LibertyGroup *timing_group, + const RiseFall *rf); + void readReceiverCapacitance(const LibertyGroup *timing_group, + const char *cap_group_name, + int index, + const RiseFall *rf, + ReceiverModelPtr &receiver_model); + OutputWaveforms *readOutputWaveforms(const LibertyGroup *timing_group, + const RiseFall *rf); + OutputWaveforms *makeOutputWaveforms(const LibertyGroup *current_group, + OutputWaveformSeq &output_currents, + const RiseFall *rf); + + TableModel *readTableModel(const LibertyGroup *table_group, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type); + TablePtr readTableModel(const LibertyGroup *table_group, + const TableTemplate *tbl_template, + float scale); + void makeTimingModels(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + void makeLinearModels(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + void makeTableModels(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + + TableAxisPtr makeTableAxis(const LibertyGroup *table_group, + const char *index_attr_name, + TableAxisPtr template_axis); + void readGroupAttrFloat(const char *attr_name, + const LibertyGroup *group, + const std::function &set_func, + float scale = 1.0F); + void readTimingArcAttrs(LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + void readTimingSense(const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + void readTimingType(const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + void readTimingWhen(const LibertyCell *cell, + const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + void readTimingMode(const LibertyGroup *timing_group, + TimingArcAttrsPtr timing_attrs); + void makePortFuncs(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group); + + void makeSequentials(LibertyCell *cell, + const LibertyGroup *cell_group); + void makeSequentials(LibertyCell *cell, + const LibertyGroup *cell_group, + bool is_register, + const char *seq_group_name, + const char *clk_attr_name, + const char *data_attr_name); + FuncExpr *makeSeqFunc(LibertyCell *cell, + const LibertyGroup *seq_group, + const char *attr_name, + int size); + void makeSeqPorts(LibertyCell *cell, + const LibertyGroup *seq_group, + // Return values. + LibertyPort *&out_port, + LibertyPort *&out_port_inv, + size_t &size); + void seqPortNames(const LibertyGroup *group, + const char *&out_name, + const char *&out_inv_name, + bool &has_size, + size_t &size); + TimingModel *makeScalarCheckModel(LibertyCell *cell, + float value, ScaleFactorType scale_factor_type, const RiseFall *rf); - void makeMinPulseWidthArcs(LibertyPort *port, - int line); - void setEnergyScale(); + void readPortDir(const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void readCapacitance(const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void makeTimingArcs(LibertyCell *cell, + const std::string &from_port_name, + LibertyPort *to_port, + LibertyPort *related_out_port, + bool one_to_one, + TimingArcAttrsPtr timing_attrs, + int timing_line); + void makeTimingArcs(LibertyCell *cell, + LibertyPort *to_port, + LibertyPort *related_out_port, + TimingArcAttrsPtr timing_attrs, + int timing_line); + + void readInternalPowerGroups(LibertyCell *cell, + const LibertyPortSeq &ports, + const LibertyGroup *port_group); + void readLeagageGrouops(LibertyCell *cell, + const LibertyGroup *port_group); + + void readCellAttributes(LibertyCell *cell, + const LibertyGroup *cell_group); + void readScaleFactors(LibertyCell *cell, + const LibertyGroup *cell_group); + void readCellAttrString(const char *attr_name, + void (LibertyCell::*set_func)(const char *value), + LibertyCell *cell, + const LibertyGroup *group); + void readCellAttrFloat(const char *attr_name, + void (LibertyCell::*set_func)(float value), + LibertyCell *cell, + const LibertyGroup *group, + float scale); + void readCellAttrBool(const char *attr_name, + void (LibertyCell::*set_func)(bool value), + LibertyCell *cell, + const LibertyGroup *group); + void readLevelShifterType(LibertyCell *cell, + const LibertyGroup *cell_group); + void readSwitchCellType(LibertyCell *cell, + const LibertyGroup *cell_group); + void readCellOcvDerateGroup(LibertyCell *cell, + const LibertyGroup *cell_group); + void readStatetable(LibertyCell *cell, + const LibertyGroup *cell_group); + void readTestCell(LibertyCell *cell, + const LibertyGroup *cell_group); + + FuncExpr *readFuncExpr(LibertyCell *cell, + const LibertyGroup *group, + const char *attr_name); + LibertyPort *findLibertyPort(LibertyCell *cell, + const LibertyGroup *group, + const char *port_name_attr); + LibertyPortSeq findLibertyPorts(LibertyCell *cell, + const LibertyGroup *group, + const char *port_name_attr); + + float energyScale(); void defineVisitors(); + void defineGroupVisitor(const char *type, LibraryGroupVisitor begin_visitor, LibraryGroupVisitor end_visitor); - void defineAttrVisitor(const char *attr_name, - LibraryAttrVisitor visitor); - void parseNames(const char *name_str); - void clearAxisValues(); - void makeTableAxis(int index, - LibertyAttr *attr); - StringSeq *parseNameList(const char *name_list); - StdStringSeq parseTokenList(const char *token_str, - const char separator); - LibertyPort *findPort(const char *port_name); float defaultCap(LibertyPort *port); - virtual void visitVariable(LibertyVariable *var); void visitPorts(std::function func); StateInputValues parseStateInputValues(StdStringSeq &inputs, - LibertyAttr *attr); + const LibertySimpleAttr *attr); StateInternalValues parseStateInternalValues(StdStringSeq &states, - LibertyAttr *attr); + const LibertySimpleAttr *attr); - const char *getAttrString(LibertyAttr *attr); - void getAttrInt(LibertyAttr *attr, + void getAttrInt(const LibertySimpleAttr *attr, // Return values. int &value, bool &exists); - void getAttrFloat(LibertyAttr *attr, - // Return values. - float &value, - bool &valid); - void getAttrFloat(LibertyAttr *attr, - LibertyAttrValue *attr_value, - // Return values. - float &value, - bool &valid); - void getAttrFloat2(LibertyAttr *attr, + void getAttrFloat2(const LibertyComplexAttr *attr, // Return values. float &value1, float &value2, bool &exists); - FloatSeq parseStringFloatList(const std::string &float_list, - float scale, - LibertyAttr *attr); - LogicValue getAttrLogicValue(LibertyAttr *attr); - void getAttrBool(LibertyAttr *attr, + void getAttrFloat(const LibertyComplexAttr *attr, + const LibertyAttrValue *attr_value, + // Return values. + float &value, + bool &valid); + LogicValue getAttrLogicValue(const LibertySimpleAttr *attr); + void getAttrBool(const LibertySimpleAttr *attr, // Return values. bool &value, bool &exists); - void visitVariable(int index, - LibertyAttr *attr); - void visitIndex(int index, - LibertyAttr *attr); + const EarlyLateAll *getAttrEarlyLate(const LibertySimpleAttr *attr); + + FloatSeq parseStringFloatList(const std::string &float_list, + float scale, + const LibertySimpleAttr *attr); + FloatSeq parseStringFloatList(const std::string &float_list, + float scale, + const LibertyComplexAttr *attr); TableAxisPtr makeAxis(int index, - LibertyGroup *group); - FloatSeq readFloatSeq(LibertyAttr *attr, + const LibertyGroup *group); + FloatSeq readFloatSeq(const LibertyComplexAttr *attr, float scale); void variableValue(const char *var, float &value, bool &exists); FuncExpr *parseFunc(const char *func, const char *attr_name, + const LibertyCell *cell, int line); void libWarn(int id, - LibertyStmt *stmt, + const LibertyGroup *obj, + const char *fmt, + ...) + __attribute__((format (printf, 4, 5))); + void libWarn(int id, + const LibertySimpleAttr *obj, + const char *fmt, + ...) + __attribute__((format (printf, 4, 5))); + void libWarn(int id, + const LibertyComplexAttr *obj, const char *fmt, ...) __attribute__((format (printf, 4, 5))); @@ -592,7 +465,15 @@ protected: ...) __attribute__((format (printf, 4, 5))); void libError(int id, - LibertyStmt *stmt, + const LibertyGroup *obj, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); + void libError(int id, + const LibertySimpleAttr *obj, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); + void libError(int id, + const LibertyComplexAttr *obj, const char *fmt, ...) __attribute__((format (printf, 4, 5))); @@ -602,64 +483,12 @@ protected: Debug *debug_; Network *network_; LibertyBuilder builder_; - LibertyVariableMap *var_map_; + LibertyVariableMap var_map_; LibertyLibrary *library_; - LibraryGroupMap group_begin_map_; - LibraryGroupMap group_end_map_; - LibraryAttrMap attr_visitor_map_; - Wireload *wireload_; - WireloadSelection *wireload_selection_; - const char *default_wireload_; - const char *default_wireload_selection_; - ScaleFactors *scale_factors_; - ScaleFactors *save_scale_factors_; - bool have_input_threshold_[RiseFall::index_count]; - bool have_output_threshold_[RiseFall::index_count]; - bool have_slew_lower_threshold_[RiseFall::index_count]; - bool have_slew_upper_threshold_[RiseFall::index_count]; - TableTemplate *tbl_template_; - LibertyCell *cell_; - LibertyCell *scaled_cell_owner_; - const char *ocv_derate_name_; - PortGroupSeq cell_port_groups_; - OperatingConditions *op_cond_; - LibertyPortSeq *ports_; - PortGroup *port_group_; - LibertyPortSeq *saved_ports_; - PortGroup *saved_port_group_; - StringSeq bus_names_; - bool in_bus_; - bool in_bundle_; - bool in_ccsn_; - bool in_ecsm_waveform_; - TableAxisVariable axis_var_[3]; - FloatSeq axis_values_[3]; - int type_bit_from_; - bool type_bit_from_exists_; - int type_bit_to_; - bool type_bit_to_exists_; - SequentialGroup *sequential_; - SequentialGroupSeq cell_sequentials_; - StatetableGroup *statetable_; - TimingGroup *timing_; - InternalPowerGroup *internal_power_; - LeakagePowerGroup *leakage_power_; - LeakagePowerGroupSeq leakage_powers_; - const RiseFall *rf_; - int index_; - OcvDerate *ocv_derate_; - const RiseFallBoth *rf_type_; - const EarlyLateAll *derate_type_; - const EarlyLateAll *sigma_type_; - PathType path_type_; - LibertyPort *pg_port_; - ScaleFactorType scale_factor_type_; - TableAxisPtr axis_[3]; - TablePtr table_; - float table_model_scale_; - ModeDef *mode_def_; - ModeValueDef *mode_value_; - LibertyFuncSeq cell_funcs_; + bool first_cell_; + LibraryGroupVisitorMap group_begin_map_; + LibraryGroupVisitorMap group_end_map_; + float time_scale_; float cap_scale_; float res_scale_; @@ -668,263 +497,11 @@ protected: float power_scale_; float energy_scale_; float distance_scale_; - const char *default_operating_condition_; - ReceiverModelPtr receiver_model_; - OutputWaveformSeq output_currents_; - OutputWaveforms *output_waveforms_; - float reference_time_; - bool reference_time_exists_; - std::string driver_waveform_name_; - - TestCell *test_cell_; - // Saved state while parsing test_cell. - LibertyCell *save_cell_; - PortGroupSeq save_cell_port_groups_; - StatetableGroup *save_statetable_; - SequentialGroupSeq save_cell_sequentials_; - LibertyFuncSeq save_cell_funcs_; static constexpr char escape_ = '\\'; private: friend class PortNameBitIterator; - friend class TimingGroup; -}; - -// Reference to a function that will be parsed at the end of the cell -// definition when all of the ports are defined. -class LibertyFunc -{ -public: - LibertyFunc(const char *expr, - LibertySetFunc set_func, - bool invert, - const char *attr_name, - int line); - ~LibertyFunc(); - const char *expr() const { return expr_; } - LibertySetFunc setFunc() const { return set_func_; } - bool invert() const { return invert_; } - const char *attrName() const { return attr_name_; } - int line() const { return line_; } - -protected: - const char *expr_; - LibertySetFunc set_func_; - bool invert_; - const char *attr_name_; - int line_; -}; - -// Port attributes that refer to other ports cannot be parsed -// until all of the ports are defined. This class saves them -// so they can be parsed at the end of the cell. -class PortGroup -{ -public: - PortGroup(LibertyPortSeq *ports, - int line); - ~PortGroup(); - LibertyPortSeq *ports() const { return ports_; } - TimingGroupSeq &timingGroups() { return timings_; } - void addTimingGroup(TimingGroup *timing); - InternalPowerGroupSeq &internalPowerGroups() { return internal_power_groups_; } - void addInternalPowerGroup(InternalPowerGroup *internal_power); - ReceiverModel *receiverModel() const { return receiver_model_; } - void setReceiverModel(ReceiverModelPtr receiver_model); - int line() const { return line_; } - -private: - LibertyPortSeq *ports_; - TimingGroupSeq timings_; - InternalPowerGroupSeq internal_power_groups_; - ReceiverModel *receiver_model_; - int line_; -}; - -// Liberty group with related_pins group attribute. -class RelatedPortGroup -{ -public: - RelatedPortGroup(int line); - virtual ~RelatedPortGroup(); - int line() const { return line_; } - StringSeq *relatedPortNames() const { return related_port_names_; } - void setRelatedPortNames(StringSeq *names); - bool isOneToOne() const { return is_one_to_one_; } - void setIsOneToOne(bool one); - -protected: - StringSeq *related_port_names_; - bool is_one_to_one_; - int line_; -}; - -class SequentialGroup -{ -public: - SequentialGroup(bool is_register, - bool is_bank, - LibertyPort *out_port, - LibertyPort *out_inv_port, - int size, - int line); - ~SequentialGroup(); - LibertyPort *outPort() const { return out_port_; } - LibertyPort *outInvPort() const { return out_inv_port_; } - int size() const { return size_; } - bool isRegister() const { return is_register_; } - bool isBank() const { return is_bank_; } - const char *clock() const { return clk_; } - void setClock(const char *clk); - const char *data() const { return data_; } - void setData(const char *data); - const char *clear() const { return clear_; } - void setClear(const char *clr); - const char *preset() const { return preset_; } - void setPreset(const char *preset); - LogicValue clrPresetVar1() const { return clr_preset_var1_; } - void setClrPresetVar1(LogicValue var); - LogicValue clrPresetVar2() const { return clr_preset_var2_; } - void setClrPresetVar2(LogicValue var); - int line() const { return line_; } - -protected: - bool is_register_; - bool is_bank_; - LibertyPort *out_port_; - LibertyPort *out_inv_port_; - int size_; - const char *clk_; - const char *data_; - const char *preset_; - const char *clear_; - LogicValue clr_preset_var1_; - LogicValue clr_preset_var2_; - int line_; -}; - -class StatetableGroup -{ -public: - StatetableGroup(StdStringSeq &input_ports, - StdStringSeq &internal_ports, - int line); - const StdStringSeq &inputPorts() const { return input_ports_; } - const StdStringSeq &internalPorts() const { return internal_ports_; } - void addRow(StateInputValues &input_values, - StateInternalValues ¤t_values, - StateInternalValues &next_values); - StatetableRows &table() { return table_; } - int line() const { return line_; } - -private: - StdStringSeq input_ports_; - StdStringSeq internal_ports_; - StatetableRows table_; - int line_; -}; - -class TimingGroup : public RelatedPortGroup -{ -public: - TimingGroup(int line); - virtual ~TimingGroup(); - TimingArcAttrsPtr attrs() { return attrs_; } - const char *relatedOutputPortName()const {return related_output_port_name_;} - void setRelatedOutputPortName(const char *name); - void intrinsic(const RiseFall *rf, - // Return values. - float &value, - bool &exists); - void setIntrinsic(const RiseFall *rf, - float value); - void resistance(const RiseFall *rf, - // Return values. - float &value, - bool &exists); - void setResistance(const RiseFall *rf, - float value); - TableModel *cell(const RiseFall *rf); - void setCell(const RiseFall *rf, - TableModel *model); - TableModel *constraint(const RiseFall *rf); - void setConstraint(const RiseFall *rf, - TableModel *model); - TableModel *transition(const RiseFall *rf); - void setTransition(const RiseFall *rf, - TableModel *model); - void makeTimingModels(LibertyCell *cell, - LibertyReader *visitor); - void setDelaySigma(const RiseFall *rf, - const EarlyLate *early_late, - TableModel *model); - void setSlewSigma(const RiseFall *rf, - const EarlyLate *early_late, - TableModel *model); - void setConstraintSigma(const RiseFall *rf, - const EarlyLate *early_late, - TableModel *model); - void setReceiverModel(ReceiverModelPtr receiver_model); - OutputWaveforms *outputWaveforms(const RiseFall *rf); - void setOutputWaveforms(const RiseFall *rf, - OutputWaveforms *output_current); - -protected: - void makeLinearModels(LibertyCell *cell); - void makeTableModels(LibertyCell *cell, - LibertyReader *reader); - - TimingArcAttrsPtr attrs_; - const char *related_output_port_name_; - float intrinsic_[RiseFall::index_count]; - bool intrinsic_exists_[RiseFall::index_count]; - float resistance_[RiseFall::index_count]; - bool resistance_exists_[RiseFall::index_count]; - TableModel *cell_[RiseFall::index_count]; - TableModel *constraint_[RiseFall::index_count]; - TableModel *constraint_sigma_[RiseFall::index_count][EarlyLate::index_count]; - TableModel *transition_[RiseFall::index_count]; - TableModel *delay_sigma_[RiseFall::index_count][EarlyLate::index_count]; - TableModel *slew_sigma_[RiseFall::index_count][EarlyLate::index_count]; - OutputWaveforms *output_waveforms_[RiseFall::index_count]; - ReceiverModelPtr receiver_model_; -}; - -class InternalPowerGroup : public RelatedPortGroup -{ -public: - InternalPowerGroup(int line); - const std::string &relatedPgPin() const { return related_pg_pin_; } - void setRelatedPgPin(std::string related_pg_pin); - const std::shared_ptr &when() const { return when_; } - void setWhen(std::shared_ptr when); - void setModel(const RiseFall *rf, - std::shared_ptr model); - InternalPowerModels &models() { return models_; } - -private: - std::string related_pg_pin_; - std::shared_ptr when_; - InternalPowerModels models_; -}; - -class LeakagePowerGroup -{ -public: - LeakagePowerGroup(int line); - const std::string &relatedPgPin() const { return related_pg_pin_; } - void setRelatedPgPin(std::string pin_name); - FuncExpr *when() const { return when_; } - void setWhen(FuncExpr *when); - float power() const { return power_; } - void setPower(float power); - -protected: - std::string related_pg_pin_; - FuncExpr *when_; - float power_; - int line_; }; // Named port iterator. Port name can be: @@ -968,17 +545,16 @@ public: float axis_value2, Table *currents, float reference_time); - ~OutputWaveform(); float slew() const { return slew_; } float cap() const { return cap_; } - Table *currents() const { return currents_; } - Table *stealCurrents(); + Table *releaseCurrents(); + float referenceTime() { return reference_time_; } private: float slew_; float cap_; - Table *currents_; + std::unique_ptr
currents_; float reference_time_; }; diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index 27512dc5..977c9b08 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -45,9 +45,7 @@ size_t findValueIndex(float value, const FloatSeq *values); static void -sigmaModelsMvOwner(TableModel *models[EarlyLate::index_count], - std::array, - 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, - 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(*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(); diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 347c56fe..1f1ea2c1 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -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; } diff --git a/power/Power.cc b/power/Power.cc index db3ef053..4319de04 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -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 diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index 7e3f89b8..1c605a26 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -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; } } diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 2a7af024..7e72e6fb 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -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 diff --git a/test/get_is_memory.tcl b/test/get_is_memory.tcl index 23080a99..61d9d461 100644 --- a/test/get_is_memory.tcl +++ b/test/get_is_memory.tcl @@ -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 diff --git a/test/gf180mcu_sram.lib.gz b/test/gf180mcu_sram.lib.gz index b4ab4b9fd42edea2bb0ab58aa96dee052d029a6f..84279e4699285d224a3d74decd2db47e3a0f682c 100644 GIT binary patch delta 19 acmaEEcGZkazMF%g-hX-~1M@~1Z)pHSYz656 delta 37 scmca=_S{THzMF$X_>O5h19N(sp@l(ia%p^VQDUxMPG%CrMlNq@0O!;T&;S4c diff --git a/test/liberty_arcs_one2one_1.ok b/test/liberty_arcs_one2one_1.ok index dc99d32b..eac1a900 100644 --- a/test/liberty_arcs_one2one_1.ok +++ b/test/liberty_arcs_one2one_1.ok @@ -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 diff --git a/test/liberty_arcs_one2one_2.ok b/test/liberty_arcs_one2one_2.ok index 323145d3..0dbc0a3a 100644 --- a/test/liberty_arcs_one2one_2.ok +++ b/test/liberty_arcs_one2one_2.ok @@ -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 diff --git a/util/TokenParser.cc b/util/TokenParser.cc index e048cecf..d0a44859 100644 --- a/util/TokenParser.cc +++ b/util/TokenParser.cc @@ -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 From d31372ef9ac381db8e0105c91e461230e68e8d77 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 27 Feb 2026 17:54:32 -0800 Subject: [PATCH 06/22] regression sta_dir Signed-off-by: James Cherry --- test/regression | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/regression b/test/regression index a64ac704..2d6aa6ce 100755 --- a/test/regression +++ b/test/regression @@ -31,7 +31,7 @@ exec tclsh $0 ${1+"$@"} # Directory containing tests. set test_dir [file dirname [file normalize [info script]]] -set sta_dir [file normalize [file join $test_dir ".."]] +set sta_dir [file dirname $test_dir] source [file join $test_dir regression_vars.tcl] source [file join $test_dir regression.tcl] From a6425a3364b790a04f2cf8f85a1fc07fb6dab9f2 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 28 Feb 2026 14:51:09 -0800 Subject: [PATCH 07/22] FindMessages criticalError Signed-off-by: James Cherry --- dcalc/ArnoldiDelayCalc.cc | 3 ++- etc/FindMessages.tcl | 2 +- power/Power.cc | 2 +- search/Levelize.cc | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dcalc/ArnoldiDelayCalc.cc b/dcalc/ArnoldiDelayCalc.cc index ac6705d8..162c4d3e 100644 --- a/dcalc/ArnoldiDelayCalc.cc +++ b/dcalc/ArnoldiDelayCalc.cc @@ -610,7 +610,8 @@ delay_work_get_residues(delay_work *D,int term_index) // calculate_poles_res // -void arnoldi1::calculate_poles_res(delay_work *D,double rdrive) +void arnoldi1::calculate_poles_res(delay_work *D, + double rdrive) { if (n > D->nmax) delay_work_alloc(D,n); double *p = D->poles; diff --git a/etc/FindMessages.tcl b/etc/FindMessages.tcl index bf60754b..c5fad936 100755 --- a/etc/FindMessages.tcl +++ b/etc/FindMessages.tcl @@ -61,7 +61,7 @@ foreach subdir $subdirs { set files [glob -nocomplain [file join $subdir "*.{cc,hh,yy,ll,i}"]] set files_c [concat $files_c $files] } -set warn_regexp_c {(?:(?:->critical|->warn|->fileWarn|->error|->fileError|libWarn|libError| warn)\(|tclArgError\(interp,\s*)([0-9]+),.*(".+")} +set warn_regexp_c {(?:(?:->critical|->warn|->fileWarn|->error|->fileError|criticalError|libWarn|libError)\(|tclArgError\(interp,\s*)([0-9]+),.*(".+")} set files_tcl {} foreach subdir $subdirs { diff --git a/power/Power.cc b/power/Power.cc index 4319de04..2faaef23 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -842,7 +842,7 @@ Power::evalBddDuty(DdNode *bdd, else if (bdd == Cudd_ReadLogicZero(bdd_.cuddMgr())) return 0.0; else - criticalError(1100, "unknown cudd constant"); + criticalError(2400, "unknown cudd constant"); } else { float duty0 = evalBddDuty(Cudd_E(bdd), inst); diff --git a/search/Levelize.cc b/search/Levelize.cc index 02ef86e5..df6c983d 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -678,7 +678,7 @@ Levelize::setLevelIncr(Vertex *vertex, } max_level_ = max(level, max_level_); if (level >= Graph::vertex_level_max) - criticalError(617, "maximum logic level exceeded"); + criticalError(618, "maximum logic level exceeded"); } void From cd21c43693fd1a83b5b58015a2ddc808b60588ea Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 28 Feb 2026 14:57:00 -0800 Subject: [PATCH 08/22] rm LibertyPort::clkTreeDelays, clockTreePathDelays Signed-off-by: James Cherry --- include/sta/Liberty.hh | 5 ----- liberty/Liberty.cc | 27 --------------------------- 2 files changed, 32 deletions(-) diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 02769b84..3f096a81 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -892,10 +892,6 @@ public: float clkTreeDelay(float in_slew, const RiseFall *from_rf, const MinMax *min_max) const; - // deprecated 2024-06-22 - RiseFallMinMax clkTreeDelays() const __attribute__ ((deprecated)); - // deprecated 2024-02-27 - RiseFallMinMax clockTreePathDelays() const __attribute__ ((deprecated)); static bool equiv(const LibertyPort *port1, const LibertyPort *port2); @@ -916,7 +912,6 @@ protected: void setMinPort(LibertyPort *min); void addScaledPort(OperatingConditions *op_cond, LibertyPort *scaled_port); - RiseFallMinMax clkTreeDelays1() const; void setMemberFlag(bool value, const std::function &setter); void setMemberFloat(float value, diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 5df31143..7510fdcb 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -2736,33 +2736,6 @@ LibertyPort::setDriverWaveform(DriverWaveform *driver_waveform, //////////////////////////////////////////////////////////////// -RiseFallMinMax -LibertyPort::clockTreePathDelays() const -{ - return clkTreeDelays1(); -} - -RiseFallMinMax -LibertyPort::clkTreeDelays() const -{ - return clkTreeDelays1(); -} - -RiseFallMinMax -LibertyPort::clkTreeDelays1() const -{ - RiseFallMinMax delays; - for (const RiseFall *from_rf : RiseFall::range()) { - for (const RiseFall *to_rf : RiseFall::range()) { - for (const MinMax *min_max : MinMax::range()) { - float delay = clkTreeDelay(0.0, from_rf, to_rf, min_max); - delays.setValue(from_rf, min_max, delay); - } - } - } - return delays; -} - float LibertyPort::clkTreeDelay(float in_slew, const RiseFall *rf, From e76f54a068ddcd5821ea554b2ff06ae6a3fc9e2e Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 28 Feb 2026 15:45:34 -0800 Subject: [PATCH 09/22] rm TokenParser Signed-off-by: James Cherry --- CMakeLists.txt | 1 - include/sta/StringUtil.hh | 13 ++--- include/sta/TokenParser.hh | 62 -------------------- liberty/LibertyReader.cc | 1 - spice/WriteSpice.cc | 16 +++--- spice/WriteSpice.hh | 6 +- util/StringUtil.cc | 29 ++++++++-- util/TokenParser.cc | 113 ------------------------------------- 8 files changed, 41 insertions(+), 200 deletions(-) delete mode 100644 include/sta/TokenParser.hh delete mode 100644 util/TokenParser.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 60932b82..973cfb0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -237,7 +237,6 @@ set(STA_SOURCE util/StringSeq.cc util/StringSet.cc util/StringUtil.cc - util/TokenParser.cc util/Transition.cc verilog/VerilogReader.cc diff --git a/include/sta/StringUtil.hh b/include/sta/StringUtil.hh index c222d53b..cdb9b1b7 100644 --- a/include/sta/StringUtil.hh +++ b/include/sta/StringUtil.hh @@ -33,6 +33,8 @@ namespace sta { +using StdStringSeq = std::vector; + inline bool stringEq(const char *str1, const char *str2) @@ -201,12 +203,9 @@ deleteTmpStrings(); void trimRight(std::string &str); -using StringVector = std::vector; - -void -split(const std::string &text, - const std::string &delims, - // Return values. - StringVector &tokens); +// Spit text into delimiter separated tokens and skip whitepace. +StdStringSeq +parseTokens(const std::string &s, + const char delimiter); } // namespace diff --git a/include/sta/TokenParser.hh b/include/sta/TokenParser.hh deleted file mode 100644 index 27db37f9..00000000 --- a/include/sta/TokenParser.hh +++ /dev/null @@ -1,62 +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 . -// -// 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 -#include - -namespace sta { - -using StdStringSeq = std::vector; - -// 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 -// string terminators where the separators were. -// Using STL string functions to parse tokens is messy and extremely slow -// on the RogueWave/Solaris implementation, apparently because of mutexes -// on temporary strings. -class TokenParser -{ -public: - TokenParser(const char *str, - const char *delimiters); - bool hasNext(); - char *next(); - -private: - const char *delimiters_; - char *token_; - char *token_end_; - char token_delimiter_; - bool first_; -}; - -// Parse delimiter separated tokens and skipp spaces. -StdStringSeq -parseTokens(const std::string &s, - const char delimiter); - -} // namespace diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 974ab7ec..c070e3dd 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -33,7 +33,6 @@ #include "EnumNameMap.hh" #include "Report.hh" #include "Debug.hh" -#include "TokenParser.hh" #include "Units.hh" #include "Transition.hh" #include "FuncExpr.hh" diff --git a/spice/WriteSpice.cc b/spice/WriteSpice.cc index cce1989b..8d55d8c7 100644 --- a/spice/WriteSpice.cc +++ b/spice/WriteSpice.cc @@ -213,8 +213,7 @@ WriteSpice::writeSubckts(StdStringSet &cell_names) string line; while (getline(lib_subckts_stream, line)) { // .subckt [args..] - StringVector tokens; - split(line, " \t", tokens); + StdStringSeq tokens = parseTokens(line, ' '); if (tokens.size() >= 2 && stringEqual(tokens[0].c_str(), ".subckt")) { const char *cell_name = tokens[1].c_str(); @@ -261,11 +260,11 @@ WriteSpice::writeSubckts(StdStringSet &cell_names) void WriteSpice::recordSpicePortNames(const char *cell_name, - StringVector &tokens) + StdStringSeq &tokens) { LibertyCell *cell = network_->findLibertyCell(cell_name); if (cell) { - StringVector &spice_port_names = cell_spice_port_names_[cell_name]; + StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name]; for (size_t i = 2; i < tokens.size(); i++) { const char *port_name = tokens[i].c_str(); LibertyPort *port = cell->findLibertyPort(port_name); @@ -290,8 +289,7 @@ WriteSpice::findCellSubckts(StdStringSet &cell_names) string line; while (getline(lib_subckts_stream, line)) { // .subckt [args..] - StringVector tokens; - split(line, " \t", tokens); + StdStringSeq tokens = parseTokens(line, ' '); if (tokens.size() >= 2 && stringEqual(tokens[0].c_str(), ".subckt")) { const char *cell_name = tokens[1].c_str(); @@ -304,7 +302,7 @@ WriteSpice::findCellSubckts(StdStringSet &cell_names) else { // Process previous statement. if (tolower(stmt[0]) == 'x') { - split(stmt, " \t", tokens); + StdStringSeq tokens = parseTokens(line, ' '); string &subckt_cell = tokens[tokens.size() - 1]; cell_names.insert(subckt_cell); } @@ -329,7 +327,7 @@ WriteSpice::writeSubcktInst(const Instance *inst) const char *inst_name = network_->pathName(inst); LibertyCell *cell = network_->libertyCell(inst); const char *cell_name = cell->name(); - StringVector &spice_port_names = cell_spice_port_names_[cell_name]; + StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name]; streamPrint(spice_stream_, "x%s", inst_name); for (string subckt_port_name : spice_port_names) { const char *subckt_port_cname = subckt_port_name.c_str(); @@ -357,7 +355,7 @@ WriteSpice::writeSubcktInstVoltSrcs(const Instance *inst, { LibertyCell *cell = network_->libertyCell(inst); const char *cell_name = cell->name(); - StringVector &spice_port_names = cell_spice_port_names_[cell_name]; + StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name]; const char *inst_name = network_->pathName(inst); debugPrint(debug_, "write_spice", 2, "subckt %s", cell->name()); diff --git a/spice/WriteSpice.hh b/spice/WriteSpice.hh index 3e55e294..aee55dfe 100644 --- a/spice/WriteSpice.hh +++ b/spice/WriteSpice.hh @@ -40,9 +40,9 @@ namespace sta { using ParasiticNodeMap = std::map; -using CellSpicePortNames = std::map; -using LibertyPortLogicValues = std::map; using StdStringSeq = std::vector; +using CellSpicePortNames = std::map; +using LibertyPortLogicValues = std::map; // Utilities for writing a spice deck. class WriteSpice : public StaState @@ -69,7 +69,7 @@ protected: void writeSubckts(StdStringSet &cell_names); void findCellSubckts(StdStringSet &cell_names); void recordSpicePortNames(const char *cell_name, - StringVector &tokens); + StdStringSeq &tokens); void writeSubcktInst(const Instance *inst); void writeSubcktInstVoltSrcs(const Instance *inst, LibertyPortLogicValues &port_values, diff --git a/util/StringUtil.cc b/util/StringUtil.cc index a0b8c154..6a8680e4 100644 --- a/util/StringUtil.cc +++ b/util/StringUtil.cc @@ -269,12 +269,11 @@ trimRight(string &str) str.erase(str.find_last_not_of(" ") + 1); } -void +StdStringSeq split(const string &text, - const string &delims, - // Return values. - StringVector &tokens) + const string &delims) { + StdStringSeq tokens; auto start = text.find_first_not_of(delims); auto end = text.find_first_of(delims, start); while (end != string::npos) { @@ -284,6 +283,28 @@ split(const string &text, } if (start != string::npos) tokens.push_back(text.substr(start)); + return tokens; +} + +// 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 diff --git a/util/TokenParser.cc b/util/TokenParser.cc deleted file mode 100644 index d0a44859..00000000 --- a/util/TokenParser.cc +++ /dev/null @@ -1,113 +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 . -// -// 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 "TokenParser.hh" - -#include -#include - -namespace sta { - -TokenParser::TokenParser(const char *str, - const char *delimiters) : - delimiters_(delimiters), - token_(const_cast(str)), - token_delimiter_('\0'), - first_(true) -{ - // Skip leading spaces. - while (*token_ != '\0' && isspace(*token_)) - token_++; - token_end_ = strpbrk(token_, delimiters_); - if (token_end_) { - // Save the delimiter. - token_delimiter_ = *token_end_; - // Replace the separator with a terminator. - *token_end_ = '\0'; - } -} - -bool -TokenParser::hasNext() -{ - if (!first_) { - // Replace the previous separator. - if (token_end_) { - *token_end_ = token_delimiter_; - token_ = token_end_ + 1; - // Skip spaces. - while (*token_ != '\0' && isspace(*token_)) - token_++; - // Skip delimiters. - while (*token_ != '\0' && strchr(delimiters_,*token_) != nullptr) - token_++; - if (*token_ == '\0') - token_ = nullptr; - else { - token_end_ = strpbrk(token_, delimiters_); - if (token_end_) { - // Save the delimiter. - token_delimiter_ = *token_end_; - // Replace the separator with a terminator. - *token_end_ = '\0'; - } - } - } - else - token_ = nullptr; - } - return token_ != nullptr; -} - -char * -TokenParser::next() -{ - first_ = false; - 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 From 0f8d7cffd3f8190c269b83c20708e1423ac50429 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 28 Feb 2026 15:53:23 -0800 Subject: [PATCH 10/22] mv StdStringSeq defs to StringUtil.hh Signed-off-by: James Cherry --- include/sta/PathGroup.hh | 2 +- include/sta/Search.hh | 2 +- include/sta/Sta.hh | 2 +- include/sta/StringSeq.hh | 1 - include/sta/StringSet.hh | 1 - liberty/LibertyReaderPvt.hh | 2 +- spice/WriteSpice.hh | 2 +- spice/Xyce.hh | 2 +- verilog/VerilogReaderPvt.hh | 2 +- 9 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/sta/PathGroup.hh b/include/sta/PathGroup.hh index a3bd6ee3..836804f7 100644 --- a/include/sta/PathGroup.hh +++ b/include/sta/PathGroup.hh @@ -32,6 +32,7 @@ #include "SdcClass.hh" #include "StaState.hh" #include "SearchClass.hh" +#include "StringUtil.hh" namespace sta { @@ -42,7 +43,6 @@ using PathGroupIterator = PathEndSeq::iterator; using PathGroupClkMap = std::map; using PathGroupNamedMap = std::map; using PathGroupSeq = std::vector; -using StdStringSeq = std::vector; // A collection of PathEnds grouped and sorted for reporting. class PathGroup diff --git a/include/sta/Search.hh b/include/sta/Search.hh index 09bc1687..4c98845c 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -40,6 +40,7 @@ #include "SearchPred.hh" #include "VertexVisitor.hh" #include "Path.hh" +#include "StringUtil.hh" namespace sta { @@ -70,7 +71,6 @@ using VertexSlackMapSeq = std::vector; using WorstSlacksSeq = std::vector; using DelayDblSeq = std::vector; using ExceptionPathSeq = std::vector; -using StdStringSeq = std::vector; class Search : public StaState { diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 15df9a85..ddb2f7d7 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -30,6 +30,7 @@ #include #include "StringSeq.hh" +#include "StringUtil.hh" #include "LibertyClass.hh" #include "NetworkClass.hh" #include "SdcClass.hh" @@ -80,7 +81,6 @@ using SceneNameMap = std::map; using SlowDrvrIterator = Iterator; using CheckError = StringSeq; using CheckErrorSeq = std::vector; -using StdStringSeq = std::vector; enum class CmdNamespace { sta, sdc }; using ParasiticsNameMap = std::map; // Path::slack/arrival/required function. diff --git a/include/sta/StringSeq.hh b/include/sta/StringSeq.hh index ca7c304f..9821b7b2 100644 --- a/include/sta/StringSeq.hh +++ b/include/sta/StringSeq.hh @@ -31,7 +31,6 @@ namespace sta { using StringSeq = std::vector; -using StdStringSeq = std::vector; void deleteContents(StringSeq *strings); diff --git a/include/sta/StringSet.hh b/include/sta/StringSet.hh index 36fa7e67..fc3d0d2b 100644 --- a/include/sta/StringSet.hh +++ b/include/sta/StringSet.hh @@ -31,7 +31,6 @@ namespace sta { using StringSet = std::set; using StdStringSet = std::set; -using StdStringSeq = std::vector; void deleteContents(StringSet *strings); diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 91fdf260..c17cdeb8 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -31,6 +31,7 @@ #include #include "StringSeq.hh" +#include "StringUtil.hh" #include "MinMax.hh" #include "NetworkClass.hh" #include "Transition.hh" @@ -55,7 +56,6 @@ class OutputWaveform; using LibraryGroupVisitor = void (LibertyReader::*)(const LibertyGroup *group, LibertyGroup *parent_group); using LibraryGroupVisitorMap = std::unordered_map; -using StdStringSeq = std::vector; using LibertyPortGroupMap = std::map; using OutputWaveformSeq = std::vector; diff --git a/spice/WriteSpice.hh b/spice/WriteSpice.hh index aee55dfe..81bd15b7 100644 --- a/spice/WriteSpice.hh +++ b/spice/WriteSpice.hh @@ -31,6 +31,7 @@ #include "StaState.hh" #include "StringSet.hh" +#include "StringUtil.hh" #include "Liberty.hh" #include "GraphClass.hh" #include "Parasitics.hh" @@ -40,7 +41,6 @@ namespace sta { using ParasiticNodeMap = std::map; -using StdStringSeq = std::vector; using CellSpicePortNames = std::map; using LibertyPortLogicValues = std::map; diff --git a/spice/Xyce.hh b/spice/Xyce.hh index 1c27cb4e..ce8e5e6c 100644 --- a/spice/Xyce.hh +++ b/spice/Xyce.hh @@ -27,11 +27,11 @@ #include #include +#include "StringUtil.hh" #include "TableModel.hh" namespace sta { -using StdStringSeq = std::vector; using WaveformSeq = std::vector
; void diff --git a/verilog/VerilogReaderPvt.hh b/verilog/VerilogReaderPvt.hh index 60498c7d..6bbe8288 100644 --- a/verilog/VerilogReaderPvt.hh +++ b/verilog/VerilogReaderPvt.hh @@ -29,12 +29,12 @@ #include #include "StringSeq.hh" +#include "StringUtil.hh" namespace sta { using VerilogDclMap = std::map; using VerilogConstantValue = std::vector; -using StdStringSeq = std::vector; class VerilogStmt { From 94b8fd8f374e377c10d74b265c9f90d7526ccd60 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sun, 1 Mar 2026 17:33:20 -0800 Subject: [PATCH 11/22] dcalc threshold adjustment Signed-off-by: James Cherry --- dcalc/LumpedCapDelayCalc.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index 948e277f..c3f6a5a0 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -170,9 +170,10 @@ LumpedCapDelayCalc::makeResult(const LibertyLibrary *drvr_library, for (const auto [load_pin, load_idx] : load_pin_index_map) { ArcDelay wire_delay = 0.0; + Slew load_slew = drvr_slew; thresholdAdjust(load_pin, drvr_library, rf, wire_delay, drvr_slew); dcalc_result.setWireDelay(load_idx, wire_delay); - dcalc_result.setLoadSlew(load_idx, drvr_slew); + dcalc_result.setLoadSlew(load_idx, load_slew); } return dcalc_result; } From 741bf4d561679a6ef36619cc514df29be89b8156 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 2 Mar 2026 12:13:13 -0800 Subject: [PATCH 12/22] rm using std:: Signed-off-by: James Cherry --- app/Main.cc | 3 +- dcalc/ArcDcalcWaveforms.cc | 6 +- dcalc/ArnoldiDelayCalc.cc | 46 +++--- dcalc/ArnoldiReduce.cc | 4 +- dcalc/CcsCeffDelayCalc.cc | 30 ++-- dcalc/DelayCalcBase.cc | 11 +- dcalc/DmpCeff.cc | 38 ++--- dcalc/FindRoot.cc | 8 +- dcalc/GraphDelayCalc.cc | 18 +-- dcalc/LumpedCapDelayCalc.cc | 7 +- dcalc/ParallelDelayCalc.cc | 6 +- dcalc/PrimaDelayCalc.cc | 15 +- dcalc/UnitDelayCalc.cc | 8 +- graph/Graph.cc | 12 +- liberty/EquivCells.cc | 2 - liberty/FuncExpr.cc | 14 +- liberty/Liberty.cc | 6 +- liberty/LibertyParser.cc | 8 +- liberty/LibertyWriter.cc | 6 +- liberty/LinearModel.cc | 10 +- liberty/TableModel.cc | 66 ++++---- liberty/TimingArc.cc | 11 +- liberty/Units.cc | 7 +- network/ConcreteLibrary.cc | 30 ++-- network/ConcreteNetwork.cc | 26 ++-- network/Network.cc | 8 +- network/ParseBus.cc | 14 +- network/SdcNetwork.cc | 89 ++++++----- network/VerilogNamespace.cc | 60 ++++---- parasitics/ConcreteParasitics.cc | 4 +- parasitics/ReduceParasitics.cc | 5 +- parasitics/SpefReader.cc | 4 +- power/Power.cc | 13 +- power/SaifReader.cc | 16 +- power/VcdParse.cc | 52 +++---- power/VcdReader.cc | 77 +++++----- sdc/ExceptionPath.cc | 10 +- sdc/Sdc.cc | 36 +++-- sdc/WriteSdc.cc | 5 +- sdf/SdfReader.cc | 100 ++++++------ sdf/SdfWriter.cc | 50 +++--- search/CheckTiming.cc | 10 +- search/ClkSkew.cc | 10 +- search/Crpr.cc | 20 +-- search/Genclks.cc | 6 +- search/Levelize.cc | 15 +- search/MakeTimingModel.cc | 22 ++- search/Property.cc | 30 ++-- search/ReportPath.cc | 163 ++++++++++---------- search/Search.cc | 7 +- search/Sta.cc | 46 +++--- search/WorstSlack.cc | 6 +- spice/WritePathSpice.cc | 23 ++- spice/WriteSpice.cc | 76 +++++---- spice/Xyce.cc | 34 ++--- util/Fuzzy.cc | 11 +- util/PatternMatch.cc | 8 +- util/Report.cc | 8 +- util/StringUtil.cc | 28 ++-- util/Transition.cc | 6 +- verilog/VerilogReader.cc | 255 +++++++++++++++---------------- verilog/VerilogWriter.cc | 27 ++-- 62 files changed, 794 insertions(+), 958 deletions(-) diff --git a/app/Main.cc b/app/Main.cc index baa1c0ea..aa28aed8 100644 --- a/app/Main.cc +++ b/app/Main.cc @@ -39,7 +39,6 @@ namespace sta { extern const char *tcl_inits[]; } -using std::string; using sta::stringEq; using sta::findCmdLineFlag; using sta::Sta; @@ -129,7 +128,7 @@ staTclAppInit(int argc, if (!findCmdLineFlag(argc, argv, "-no_init")) { const char *home = getenv("HOME"); if (home) { - string init_path = home; + std::string init_path = home; init_path += "/"; init_path += init_filename; if (std::filesystem::is_regular_file(init_path.c_str())) diff --git a/dcalc/ArcDcalcWaveforms.cc b/dcalc/ArcDcalcWaveforms.cc index b927bf1a..c718e8b9 100644 --- a/dcalc/ArcDcalcWaveforms.cc +++ b/dcalc/ArcDcalcWaveforms.cc @@ -35,8 +35,6 @@ namespace sta { -using std::make_shared; - Waveform ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg, const Scene *scene, @@ -68,8 +66,8 @@ ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg, FloatSeq time_values; for (float time : in_waveform.axis1()->values()) time_values.push_back(time + dcalc_arg.inputDelay()); - TableAxisPtr time_axis = make_shared(TableAxisVariable::time, - std::move(time_values)); + TableAxisPtr time_axis = std::make_shared(TableAxisVariable::time, + std::move(time_values)); // Scale the waveform from 0:vdd. FloatSeq *scaled_values = new FloatSeq; for (float value : *in_waveform.values()) { diff --git a/dcalc/ArnoldiDelayCalc.cc b/dcalc/ArnoldiDelayCalc.cc index 162c4d3e..bb1d1702 100644 --- a/dcalc/ArnoldiDelayCalc.cc +++ b/dcalc/ArnoldiDelayCalc.cc @@ -63,10 +63,6 @@ namespace sta { // ra_get_r // ra_get_s -using std::string; -using std::abs; -using std::vector; - struct delay_work; struct delay_c; @@ -151,15 +147,15 @@ public: const LoadPinIndexMap &load_pin_index_map, const Scene *scene, const MinMax *min_max) override; - string reportGateDelay(const Pin *drvr_pin, - const TimingArc *arc, - const Slew &in_slew, - float load_cap, - const Parasitic *parasitic, - const LoadPinIndexMap &load_pin_index_map, - const Scene *scene, - const MinMax *min_max, - int digits) override; + std::string reportGateDelay(const Pin *drvr_pin, + const TimingArc *arc, + const Slew &in_slew, + float load_cap, + const Parasitic *parasitic, + const LoadPinIndexMap &load_pin_index_map, + const Scene *scene, + const MinMax *min_max, + int digits) override; void finishDrvrPin() override; void delay_work_set_thresholds(delay_work *D, double lo, @@ -240,7 +236,7 @@ private: int pin_n_; ArnoldiReduce *reduce_; delay_work *delay_work_; - vector unsaved_parasitics_; + std::vector unsaved_parasitics_; bool pocv_enabled_; }; @@ -469,7 +465,7 @@ ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell, return dcalc_result; } -string +std::string ArnoldiDelayCalc::reportGateDelay(const Pin *drvr_pin, const TimingArc *arc, const Slew &in_slew, @@ -690,7 +686,7 @@ tridiagEV(int n,double *din,double *ein,double *d,double **v) e[0] = 0.0; for (h=n-1;h>=1;h--) { iter = 0; - while (abs(e[h])>1e-18) { // 1e-6ps + while (std::abs(e[h])>1e-18) { // 1e-6ps m=0; if (m != h) { if (iter++ == 20) @@ -820,14 +816,14 @@ solve_t_bracketed(double s,int order,double *p,double *rr, if (0.0= 0.0) - || (abs(2.0*f) > abs(dxold*df))) { + || (std::abs(2.0*f) > std::abs(dxold*df))) { dxold = dx; dx = 0.5*(xh-xl); if (flast*f >0.0) { @@ -851,7 +847,7 @@ solve_t_bracketed(double s,int order,double *p,double *rr, return rts; } } - if (abs(dx) < xacc) { + if (std::abs(dx) < xacc) { return rts; } get_dv(rts,s,order,p,rr,&f,&df); f -= val; @@ -860,7 +856,7 @@ solve_t_bracketed(double s,int order,double *p,double *rr, else xh = rts; } - if (abs(f)<1e-6) // 1uV + if (std::abs(f)<1e-6) // 1uV return rts; return 0.5*(xl+xh); } @@ -1266,28 +1262,28 @@ ArnoldiDelayCalc::ra_solve_for_s(delay_work *D, f = (ptlo-pthi)/p - tlohi; df = dlo-dhi; s = s - f/df; - if (abs(f)<.001e-12) return; // .001ps + if (std::abs(f)<.001e-12) return; // .001ps ra_solve_for_pt(p*s,vlo,&ptlo,&dlo); ra_solve_for_pt(p*s,vhi,&pthi,&dhi); f = (ptlo-pthi)/p - tlohi; df = dlo-dhi; s = s - f/df; - if (abs(f)<.001e-12) return; // .001ps + if (std::abs(f)<.001e-12) return; // .001ps ra_solve_for_pt(p*s,vlo,&ptlo,&dlo); ra_solve_for_pt(p*s,vhi,&pthi,&dhi); f = (ptlo-pthi)/p - tlohi; df = dlo-dhi; s = s - f/df; - if (abs(f)<.001e-12) return; // .001ps + if (std::abs(f)<.001e-12) return; // .001ps ra_solve_for_pt(p*s,vlo,&ptlo,&dlo); ra_solve_for_pt(p*s,vhi,&pthi,&dhi); f = (ptlo-pthi)/p - tlohi; df = dlo-dhi; s = s - f/df; - if (abs(f)<.001e-12) return; // .001ps + if (std::abs(f)<.001e-12) return; // .001ps ra_solve_for_pt(p*s,vlo,&ptlo,&dlo); ra_solve_for_pt(p*s,vhi,&pthi,&dhi); @@ -1295,7 +1291,7 @@ ArnoldiDelayCalc::ra_solve_for_s(delay_work *D, df = dlo-dhi; s = s - f/df; - if (abs(f)>.5e-12) // .5ps + if (std::abs(f)>.5e-12) // .5ps debugPrint(debug_, "arnoldi", 1, "ra_solve_for_s p %g tlohi %s err %s", p, units_->timeUnit()->asString(tlohi), diff --git a/dcalc/ArnoldiReduce.cc b/dcalc/ArnoldiReduce.cc index f05f8abc..ac8095e2 100644 --- a/dcalc/ArnoldiReduce.cc +++ b/dcalc/ArnoldiReduce.cc @@ -38,8 +38,6 @@ namespace sta { -using std::string; - rcmodel::rcmodel() : pinV(nullptr) { @@ -621,7 +619,7 @@ ArnoldiReduce::makeRcmodelFromTs() report_->reportLine(" d[%d] %s", h, units_->timeUnit()->asString(d[h])); - string line = stdstrPrint("U[%d]",h); + std::string line = stdstrPrint("U[%d]",h); for (i=0;ireportLineString(line); diff --git a/dcalc/CcsCeffDelayCalc.cc b/dcalc/CcsCeffDelayCalc.cc index 14b3e639..3f460d08 100644 --- a/dcalc/CcsCeffDelayCalc.cc +++ b/dcalc/CcsCeffDelayCalc.cc @@ -24,6 +24,8 @@ #include "CcsCeffDelayCalc.hh" +#include + #include "Debug.hh" #include "Units.hh" #include "Liberty.hh" @@ -38,17 +40,11 @@ namespace sta { -using std::string; - // Implementaion based on: // "Gate Delay Estimation with Library Compatible Current Source Models // and Effective Capacitance", D. Garyfallou et al, // IEEE Transactions on Very Large Scale Integration (VLSI) Systems, March 2021 -using std::abs; -using std::exp; -using std::make_shared; - ArcDelayCalc * makeCcsCeffDelayCalc(StaState *sta) { @@ -144,7 +140,7 @@ CcsCeffDelayCalc::gateDelaySlew(const LibertyLibrary *drvr_library, findCsmWaveform(); ref_time_ = output_waveforms_->referenceTime(in_slew_); gate_delay = region_times_[region_vth_idx_] - ref_time_; - drvr_slew = abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]); + drvr_slew = std::abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]); debugPrint(debug_, "ccs_dcalc", 2, "gate_delay %s drvr_slew %s (initial)", delayAsString(gate_delay, this), @@ -184,12 +180,12 @@ CcsCeffDelayCalc::gateDelaySlew(const LibertyLibrary *drvr_library, } findCsmWaveform(); gate_delay = region_times_[region_vth_idx_] - ref_time_; - drvr_slew = abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]); + drvr_slew = std::abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]); debugPrint(debug_, "ccs_dcalc", 2, "gate_delay %s drvr_slew %s", delayAsString(gate_delay, this), delayAsString(drvr_slew, this)); - if (abs(delayAsFloat(drvr_slew) - prev_drvr_slew) < .01 * prev_drvr_slew) + if (std::abs(delayAsFloat(drvr_slew) - prev_drvr_slew) < .01 * prev_drvr_slew) break; prev_drvr_slew = delayAsFloat(drvr_slew); } @@ -529,8 +525,8 @@ CcsCeffDelayCalc::drvrWaveform() drvr_volts->push_back(v); } } - TableAxisPtr drvr_time_axis = make_shared(TableAxisVariable::time, - std::move(*drvr_times)); + TableAxisPtr drvr_time_axis = std::make_shared(TableAxisVariable::time, + std::move(*drvr_times)); delete drvr_times; Table drvr_table(drvr_volts, drvr_time_axis); return drvr_table; @@ -561,8 +557,8 @@ CcsCeffDelayCalc::loadWaveform(const Pin *load_pin) double v1 = (drvr_rf_ == RiseFall::rise()) ? v : vdd_ - v; load_volts->push_back(v1); } - TableAxisPtr load_time_axis = make_shared(TableAxisVariable::time, - std::move(*load_times)); + TableAxisPtr load_time_axis = std::make_shared(TableAxisVariable::time, + std::move(*load_times)); delete load_times; Table load_table(load_volts, load_time_axis); return load_table; @@ -606,8 +602,8 @@ CcsCeffDelayCalc::drvrRampWaveform(const Pin *in_pin, double v1 = (drvr_rf == RiseFall::rise()) ? v : vdd_ - v; load_volts->push_back(v1); } - TableAxisPtr load_time_axis = make_shared(TableAxisVariable::time, - std::move(*load_times)); + TableAxisPtr load_time_axis = std::make_shared(TableAxisVariable::time, + std::move(*load_times)); delete load_times; Table load_table(load_volts, load_time_axis); return load_table; @@ -663,7 +659,7 @@ CcsCeffDelayCalc::makeWaveformPreamble(const Pin *in_pin, //////////////////////////////////////////////////////////////// -string +std::string CcsCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, const TimingArc *arc, const Slew &in_slew, @@ -680,7 +676,7 @@ CcsCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, pi_elmore = parasitics_->reduceToPiElmore(parasitic, drvr_pin_, rf, scene, min_max); } - string report = table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap, + std::string report = table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap, pi_elmore, load_pin_index_map, scene, min_max, digits); parasitics_->deleteDrvrReducedParasitics(drvr_pin); diff --git a/dcalc/DelayCalcBase.cc b/dcalc/DelayCalcBase.cc index ecaa16d4..5d201987 100644 --- a/dcalc/DelayCalcBase.cc +++ b/dcalc/DelayCalcBase.cc @@ -38,9 +38,6 @@ namespace sta { -using std::string; -using std::log; - DelayCalcBase::DelayCalcBase(StaState *sta) : ArcDelayCalc(sta) { @@ -101,9 +98,9 @@ DelayCalcBase::dspfWireDelaySlew(const Pin *load_pin, vh = load_library->slewUpperThreshold(rf); slew_derate = load_library->slewDerateFromLibrary(); } - wire_delay = -elmore * log(1.0 - vth); - load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate; - load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate; + wire_delay = -elmore * std::log(1.0 - vth); + load_slew = drvr_slew + elmore * std::log((1.0 - vl) / (1.0 - vh)) / slew_derate; + load_slew = drvr_slew + elmore * std::log((1.0 - vl) / (1.0 - vh)) / slew_derate; } void @@ -173,7 +170,7 @@ DelayCalcBase::checkDelay(const Pin *check_pin, return delay_zero; } -string +std::string DelayCalcBase::reportCheckDelay(const Pin *check_pin, const TimingArc *arc, const Slew &from_slew, diff --git a/dcalc/DmpCeff.cc b/dcalc/DmpCeff.cc index d759fc40..dd9b6721 100644 --- a/dcalc/DmpCeff.cc +++ b/dcalc/DmpCeff.cc @@ -32,8 +32,9 @@ #include "DmpCeff.hh" -#include // abs, min -#include // sqrt, log +#include +#include +#include #include "Report.hh" #include "Debug.hh" @@ -50,15 +51,6 @@ namespace sta { -using std::string; -using std::abs; -using std::min; -using std::max; -using std::sqrt; -using std::log; -using std::isnan; -using std::function; - // Tolerance (as a scale of value) for driver parameters (Ceff, delta t, t0). static const double driver_param_tol = .01; // Waveform threshold crossing time tolerance (1.0 = 100%). @@ -107,7 +99,7 @@ newtonRaphson(const int max_iter, const int n, const double x_tol, // eval(state) is called to fill fvec and fjac. - function eval, + std::function eval, // Temporaries supplied by caller. double *fvec, double **fjac, @@ -337,7 +329,7 @@ DmpAlg::findDriverParams(double ceff) gateDelays(ceff, t_vth, t_vl, slew); // Scale slew to 0-100% double dt = slew / (vh_ - vl_); - double t0 = t_vth + log(1.0 - vth_) * rd_ * ceff - vth_ * dt; + double t0 = t_vth + std::log(1.0 - vth_) * rd_ * ceff - vth_ * dt; x_[DmpParam::dt] = dt; x_[DmpParam::t0] = t0; newtonRaphson(100, x_, nr_order_, driver_param_tol, @@ -461,7 +453,7 @@ DmpAlg::showFvec() void DmpAlg::showJacobian() { - string line = " "; + std::string line = " "; for (int j = 0; j < nr_order_; j++) line += stdstrPrint("%12s", dmp_param_index_strings[j]); report_->reportLineString(line); @@ -894,7 +886,7 @@ DmpPi::init(const LibertyLibrary *drvr_library, k0_ = 1.0 / (rd_ * c2_); double a = rpi_ * rd_ * c1_ * c2_; double b = rd_ * (c1_ + c2_) + rpi_ * c1_; - double sqrt_ = sqrt(b * b - 4 * a); + double sqrt_ = std::sqrt(b * b - 4 * a); p1_ = (b + sqrt_) / (2 * a); p2_ = (b - sqrt_) / (2 * a); @@ -1282,7 +1274,7 @@ newtonRaphson(const int max_iter, double x[], const int size, const double x_tol, - function eval, + std::function eval, // Temporaries supplied by caller. double *fvec, double **fjac, @@ -1300,7 +1292,7 @@ newtonRaphson(const int max_iter, bool all_under_x_tol = true; for (int i = 0; i < size; i++) { - if (abs(p[i]) > abs(x[i]) * x_tol) + if (std::abs(p[i]) > std::abs(x[i]) * x_tol) all_under_x_tol = false; x[i] += p[i]; } @@ -1334,7 +1326,7 @@ luDecomp(double **a, for (int i = 0; i < size; i++) { double big = 0.0; for (int j = 0; j < size; j++) { - double temp = abs(a[i][j]); + double temp = std::abs(a[i][j]); if (temp > big) big = temp; } @@ -1363,7 +1355,7 @@ luDecomp(double **a, for (int k = 0; k < j; k++) sum -= a[i][k] * a[k][j]; a[i][j] = sum; - double dum = scale[i] * abs(sum); + double dum = scale[i] * std::abs(sum); if (dum >= big) { big = dum; imax = i; @@ -1507,7 +1499,7 @@ DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin, float in_slew1 = delayAsFloat(in_slew); float c2, rpi, c1; parasitics_->piModel(parasitic, c2, rpi, c1); - if (isnan(c2) || isnan(c1) || isnan(rpi)) + if (std::isnan(c2) || std::isnan(c1) || std::isnan(rpi)) report_->error(1040, "parasitic Pi model has NaNs."); setCeffAlgorithm(drvr_library, drvr_cell, pinPvt(drvr_pin, scene, min_max), table_model, rf, in_slew1, c2, rpi, c1); @@ -1583,7 +1575,7 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library, dmp_alg_->name()); } -string +std::string DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, const TimingArc *arc, const Slew &in_slew, @@ -1598,7 +1590,7 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, parasitic, load_pin_index_map, scene, min_max); GateTableModel *model = arc->gateTableModel(scene, min_max); float c_eff = 0.0; - string result; + std::string result; const LibertyCell *drvr_cell = arc->to()->libertyCell(); const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary(); const Units *units = drvr_library->units(); @@ -1653,7 +1645,7 @@ gateModelRd(const LibertyCell *cell, gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1); gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2); double vth = cell->libertyLibrary()->outputThreshold(rf); - float rd = -log(vth) * abs(delayAsFloat(d1) - delayAsFloat(d2)) / (cap2 - cap1); + float rd = -std::log(vth) * std::abs(delayAsFloat(d1) - delayAsFloat(d2)) / (cap2 - cap1); return rd; } diff --git a/dcalc/FindRoot.cc b/dcalc/FindRoot.cc index b74d7d16..2b0e9665 100644 --- a/dcalc/FindRoot.cc +++ b/dcalc/FindRoot.cc @@ -28,8 +28,6 @@ namespace sta { -using std::abs; - double findRoot(FindRootFunc func, double x1, @@ -76,7 +74,7 @@ findRoot(FindRootFunc func, // Swap x1/x2 so func(x1) < 0. std::swap(x1, x2); double root = (x1 + x2) * 0.5; - double dx_prev = abs(x2 - x1); + double dx_prev = std::abs(x2 - x1); double dx = dx_prev; double y, dy; func(root, y, dy); @@ -84,7 +82,7 @@ findRoot(FindRootFunc func, // Newton/raphson out of range. if ((((root - x2) * dy - y) * ((root - x1) * dy - y) > 0.0) // Not decreasing fast enough. - || (abs(2.0 * y) > abs(dx_prev * dy))) { + || (std::abs(2.0 * y) > std::abs(dx_prev * dy))) { // Bisect x1/x2 interval. dx_prev = dx; dx = (x2 - x1) * 0.5; @@ -95,7 +93,7 @@ findRoot(FindRootFunc func, dx = y / dy; root -= dx; } - if (abs(dx) <= x_tol * abs(root)) { + if (std::abs(dx) <= x_tol * std::abs(root)) { // Converged. fail = false; return root; diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index e94b3c8b..5fdf9587 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -24,6 +24,8 @@ #include "GraphDelayCalc.hh" +#include +#include #include #include "ContainerHelpers.hh" @@ -53,10 +55,6 @@ namespace sta { -using std::string; -using std::abs; -using std::array; - static const Slew default_slew = 0.0; static bool @@ -941,7 +939,7 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex, initSlew(drvr_vertex); initWireDelays(drvr_vertex); bool delay_changed = false; - array delay_exists = {false, false}; + std::array delay_exists = {false, false}; VertexInEdgeIterator edge_iter(drvr_vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); @@ -983,7 +981,7 @@ GraphDelayCalc::findLatchEdgeDelays(Edge *edge) Instance *drvr_inst = network_->instance(drvr_pin); debugPrint(debug_, "delay_calc", 2, "find latch D->Q %s", sdc_network_->pathName(drvr_inst)); - array delay_exists = {false, false}; + std::array delay_exists = {false, false}; LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); bool delay_changed = findDriverEdgeDelays(drvr_vertex, nullptr, edge, arc_delay_calc_, load_pin_index_map, @@ -999,7 +997,7 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex, ArcDelayCalc *arc_delay_calc, LoadPinIndexMap &load_pin_index_map, // Return value. - array &delay_exists) + std::array &delay_exists) { Vertex *from_vertex = edge->from(graph_); const TimingArcSet *arc_set = edge->timingArcSet(); @@ -1231,7 +1229,7 @@ GraphDelayCalc::annotateDelaySlew(Edge *edge, float gate_delay1 = delayAsFloat(gate_delay); float prev_gate_delay1 = delayAsFloat(prev_gate_delay); if (prev_gate_delay1 == 0.0 - || (abs(gate_delay1 - prev_gate_delay1) / prev_gate_delay1 + || (std::abs(gate_delay1 - prev_gate_delay1) / prev_gate_delay1 > incremental_delay_tolerance_)) delay_changed = true; graph_->setArcDelay(edge, arc, ap_index, gate_delay); @@ -1660,7 +1658,7 @@ GraphDelayCalc::checkEdgeClkSlew(const Vertex *from_vertex, //////////////////////////////////////////////////////////////// -string +std::string GraphDelayCalc::reportDelayCalc(const Edge *edge, const TimingArc *arc, const Scene *scene, @@ -1673,7 +1671,7 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge, const TimingRole *role = arc->role(); const Instance *inst = network_->instance(to_pin); const TimingArcSet *arc_set = edge->timingArcSet(); - string result; + std::string result; const RiseFall *from_rf = arc->fromEdge()->asRiseFall(); const RiseFall *to_rf = arc->toEdge()->asRiseFall(); if (from_rf && to_rf) { diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index c3f6a5a0..c9f2985c 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -40,9 +40,6 @@ namespace sta { -using std::string; -using std::isnan; - ArcDelayCalc * makeLumpedCapDelayCalc(StaState *sta) { @@ -146,7 +143,7 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin, Slew drvr_slew; float in_slew1 = delayAsFloat(in_slew); // NaNs cause seg faults during table lookup. - if (isnan(load_cap) || isnan(delayAsFloat(in_slew))) + if (std::isnan(load_cap) || std::isnan(delayAsFloat(in_slew))) report_->error(1350, "gate delay input variable is NaN"); model->gateDelay(pinPvt(drvr_pin, scene, min_max), in_slew1, load_cap, variables_->pocvEnabled(), @@ -178,7 +175,7 @@ LumpedCapDelayCalc::makeResult(const LibertyLibrary *drvr_library, return dcalc_result; } -string +std::string LumpedCapDelayCalc::reportGateDelay(const Pin *check_pin, const TimingArc *arc, const Slew &in_slew, diff --git a/dcalc/ParallelDelayCalc.cc b/dcalc/ParallelDelayCalc.cc index f18c785d..d4ead20f 100644 --- a/dcalc/ParallelDelayCalc.cc +++ b/dcalc/ParallelDelayCalc.cc @@ -34,8 +34,6 @@ namespace sta { -using std::vector; - ParallelDelayCalc::ParallelDelayCalc(StaState *sta): DelayCalcBase(sta) { @@ -71,8 +69,8 @@ ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args, ArcDcalcResultSeq dcalc_results(drvr_count); Slew slew_sum = 0.0; ArcDelay load_delay_sum = 0.0; - vector intrinsic_delays(dcalc_args.size()); - vector load_delays(dcalc_args.size()); + std::vector intrinsic_delays(dcalc_args.size()); + std::vector load_delays(dcalc_args.size()); for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) { ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx]; ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx]; diff --git a/dcalc/PrimaDelayCalc.cc b/dcalc/PrimaDelayCalc.cc index 835d02c6..85175777 100644 --- a/dcalc/PrimaDelayCalc.cc +++ b/dcalc/PrimaDelayCalc.cc @@ -44,9 +44,6 @@ namespace sta { -using std::string; -using std::abs; -using std::make_shared; using Eigen::SparseLU; using Eigen::HouseholderQR; using Eigen::ColPivHouseholderQR; @@ -726,7 +723,7 @@ PrimaDelayCalc::dcalcResults() ThresholdTimes &drvr_times = threshold_times_[drvr_node]; float ref_time = output_waveforms_[drvr_idx]->referenceTime(dcalc_arg.inSlewFlt()); ArcDelay gate_delay = drvr_times[threshold_vth] - ref_time; - Slew drvr_slew = abs(drvr_times[threshold_vh] - drvr_times[threshold_vl]); + Slew drvr_slew = std::abs(drvr_times[threshold_vh] - drvr_times[threshold_vl]); dcalc_result.setGateDelay(gate_delay); dcalc_result.setDrvrSlew(drvr_slew); debugPrint(debug_, "ccs_dcalc", 2, @@ -743,7 +740,7 @@ PrimaDelayCalc::dcalcResults() ThresholdTimes &wire_times = threshold_times_[load_node]; ThresholdTimes &drvr_times = threshold_times_[drvr_node]; ArcDelay wire_delay = wire_times[threshold_vth] - drvr_times[threshold_vth]; - Slew load_slew = abs(wire_times[threshold_vh] - wire_times[threshold_vl]); + Slew load_slew = std::abs(wire_times[threshold_vh] - wire_times[threshold_vl]); debugPrint(debug_, "ccs_dcalc", 2, "load %s %s delay %s slew %s", network_->pathName(load_pin), @@ -908,7 +905,7 @@ PrimaDelayCalc::recordWaveformStep(double time) //////////////////////////////////////////////////////////////// -string +std::string PrimaDelayCalc::reportGateDelay(const Pin *drvr_pin, const TimingArc *arc, const Slew &in_slew, @@ -959,8 +956,8 @@ Waveform PrimaDelayCalc::watchWaveform(const Pin *pin) { FloatSeq &voltages = watch_pin_values_[pin]; - TableAxisPtr time_axis = make_shared(TableAxisVariable::time, - FloatSeq(times_)); + TableAxisPtr time_axis = std::make_shared(TableAxisVariable::time, + FloatSeq(times_)); Table waveform(new FloatSeq(voltages), time_axis); return waveform; } @@ -1003,7 +1000,7 @@ void PrimaDelayCalc::reportMatrix(MatrixSd &matrix) { for (Eigen::Index i = 0; i < matrix.rows(); i++) { - string line = "| "; + std::string line = "| "; for (Eigen::Index j = 0; j < matrix.cols(); j++) { std::string entry = stdstrPrint("%10.3e", matrix.coeff(i, j)); line += entry; diff --git a/dcalc/UnitDelayCalc.cc b/dcalc/UnitDelayCalc.cc index c32197fb..cafcf426 100644 --- a/dcalc/UnitDelayCalc.cc +++ b/dcalc/UnitDelayCalc.cc @@ -28,8 +28,6 @@ namespace sta { -using std::string; - ArcDelayCalc * makeUnitDelayCalc(StaState *sta) { @@ -142,7 +140,7 @@ UnitDelayCalc::unitDelayResult(const LoadPinIndexMap &load_pin_index_map) return dcalc_result; } -string +std::string UnitDelayCalc::reportGateDelay(const Pin *, const TimingArc *, const Slew &, @@ -153,7 +151,7 @@ UnitDelayCalc::reportGateDelay(const Pin *, const MinMax *, int) { - string result("Delay = 1.0\n"); + std::string result("Delay = 1.0\n"); result += "Slew = 0.0\n"; return result; } @@ -170,7 +168,7 @@ UnitDelayCalc::checkDelay(const Pin *, return units_->timeUnit()->scale(); } -string +std::string UnitDelayCalc::reportCheckDelay(const Pin *, const TimingArc *, const Slew &, diff --git a/graph/Graph.cc b/graph/Graph.cc index 9e0b189d..f56a02a7 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -39,8 +39,6 @@ namespace sta { -using std::string; - //////////////////////////////////////////////////////////////// // // Graph @@ -985,12 +983,12 @@ Vertex::setObjectIdx(ObjectIdx idx) object_idx_ = idx; } -string +std::string Vertex::to_string(const StaState *sta) const { const Network *network = sta->sdcNetwork(); if (network->direction(pin_)->isBidirect()) { - string str = network->pathName(pin_); + std::string str = network->pathName(pin_); str += ' '; str += is_bidirect_drvr_ ? "driver" : "load"; return str; @@ -1002,7 +1000,7 @@ Vertex::to_string(const StaState *sta) const const char * Vertex::name(const Network *network) const { - string name = to_string(network); + std::string name = to_string(network); return makeTmpString(name); } @@ -1229,11 +1227,11 @@ Edge::setObjectIdx(ObjectIdx idx) object_idx_ = idx; } -string +std::string Edge::to_string(const StaState *sta) const { const Graph *graph = sta->graph(); - string str = from(graph)->to_string(sta); + std::string str = from(graph)->to_string(sta); str += " -> "; str += to(graph)->to_string(sta); str += " "; diff --git a/liberty/EquivCells.cc b/liberty/EquivCells.cc index f081435b..af81a35e 100644 --- a/liberty/EquivCells.cc +++ b/liberty/EquivCells.cc @@ -38,8 +38,6 @@ namespace sta { -using std::max; - static unsigned hashCell(const LibertyCell *cell); static unsigned diff --git a/liberty/FuncExpr.cc b/liberty/FuncExpr.cc index 38f3faea..0d422d1a 100644 --- a/liberty/FuncExpr.cc +++ b/liberty/FuncExpr.cc @@ -30,8 +30,6 @@ namespace sta { -using std::string; - FuncExpr * FuncExpr::makePort(LibertyPort *port) { @@ -199,20 +197,20 @@ FuncExpr::portTimingSense(const LibertyPort *port) const return TimingSense::unknown; } -string +std::string FuncExpr::to_string() const { return to_string(false); } -string +std::string FuncExpr::to_string(bool with_parens) const { switch (op_) { case Op::port: return port_->name(); case Op::not_: { - string result = "!"; + std::string result = "!"; result += left_ ? left_->to_string(true) : "?"; return result; } @@ -231,12 +229,12 @@ FuncExpr::to_string(bool with_parens) const } } -string +std::string FuncExpr::to_string(bool with_parens, char op) const { - string right = right_->to_string(true); - string result; + std::string right = right_->to_string(true); + std::string result; if (with_parens) result += '('; result += left_ ? left_->to_string(true) : "?"; diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 7510fdcb..130af802 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -50,8 +50,6 @@ namespace sta { -using std::string; - void initLiberty() { @@ -2704,13 +2702,13 @@ LibertyPort::setReceiverModel(ReceiverModelPtr receiver_model) receiver_model_ = receiver_model; } -string +std::string portLibertyToSta(const char *port_name) { constexpr char bus_brkt_left = '['; constexpr char bus_brkt_right = ']'; size_t name_length = strlen(port_name); - string sta_name; + std::string sta_name; for (size_t i = 0; i < name_length; i++) { char ch = port_name[i]; if (ch == bus_brkt_left diff --git a/liberty/LibertyParser.cc b/liberty/LibertyParser.cc index 4660aa42..d85911b7 100644 --- a/liberty/LibertyParser.cc +++ b/liberty/LibertyParser.cc @@ -37,8 +37,6 @@ namespace sta { -using std::string; - void parseLibertyFile(const char *filename, LibertyGroupVisitor *library_visitor, @@ -65,7 +63,7 @@ LibertyParser::LibertyParser(const char *filename, } void -LibertyParser::setFilename(const string &filename) +LibertyParser::setFilename(const std::string &filename) { filename_ = filename; } @@ -253,7 +251,7 @@ LibertyScanner::includeBegin() static const std::regex include_regexp("include_file *\\( *([^)]+) *\\) *;?"); std::cmatch matches; if (std::regex_match(yytext, matches, include_regexp)) { - string filename = matches[1].str(); + std::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, 16384)); @@ -348,7 +346,7 @@ LibertyGroup::deleteSubgroup(const LibertyGroup *subgroup) void LibertyGroup::addDefine(LibertyDefine *define) { - const string &define_name = define->name(); + const std::string &define_name = define->name(); LibertyDefine *prev_define = findKey(define_map_, define_name); if (prev_define) { define_map_.erase(define_name); diff --git a/liberty/LibertyWriter.cc b/liberty/LibertyWriter.cc index 6c4b757f..2622b1ba 100644 --- a/liberty/LibertyWriter.cc +++ b/liberty/LibertyWriter.cc @@ -25,7 +25,7 @@ #include "LibertyWriter.hh" #include -#include +#include #include "Units.hh" #include "FuncExpr.hh" @@ -39,8 +39,6 @@ namespace sta { -using std::abs; - class LibertyWriter { public: @@ -271,7 +269,7 @@ LibertyWriter::writeBusDcls() fprintf(stream_, " type (\"%s\") {\n", dcl->name().c_str()); fprintf(stream_, " base_type : array;\n"); fprintf(stream_, " data_type : bit;\n"); - fprintf(stream_, " bit_width : %d;\n", abs(dcl->from() - dcl->to() + 1)); + fprintf(stream_, " bit_width : %d;\n", std::abs(dcl->from() - dcl->to() + 1)); fprintf(stream_, " bit_from : %d;\n", dcl->from()); fprintf(stream_, " bit_to : %d;\n", dcl->to()); fprintf(stream_, " }\n"); diff --git a/liberty/LinearModel.cc b/liberty/LinearModel.cc index 1001e74b..552533e6 100644 --- a/liberty/LinearModel.cc +++ b/liberty/LinearModel.cc @@ -29,8 +29,6 @@ namespace sta { -using std::string; - GateLinearModel::GateLinearModel(LibertyCell *cell, float intrinsic, float resistance) : @@ -53,7 +51,7 @@ GateLinearModel::gateDelay(const Pvt *, drvr_slew = 0.0; } -string +std::string GateLinearModel::reportGateDelay(const Pvt *, float, float load_cap, @@ -65,7 +63,7 @@ GateLinearModel::reportGateDelay(const Pvt *, const Unit *time_unit = units->timeUnit(); const Unit *res_unit = units->resistanceUnit(); const Unit *cap_unit = units->capacitanceUnit(); - string result = "Delay = "; + std::string result = "Delay = "; result += time_unit->asString(intrinsic_, digits); result += " + "; result += res_unit->asString(resistance_, digits); @@ -105,7 +103,7 @@ CheckLinearModel::checkDelay(const Pvt *, return intrinsic_; } -string +std::string CheckLinearModel::reportCheckDelay(const Pvt *, float, const char *, @@ -117,7 +115,7 @@ CheckLinearModel::reportCheckDelay(const Pvt *, const LibertyLibrary *library = cell_->libertyLibrary(); const Units *units = library->units(); const Unit *time_unit = units->timeUnit(); - string result = "Check = "; + std::string result = "Check = "; result += time_unit->asString(intrinsic_, digits); return result; } diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index 977c9b08..b7677e16 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -35,23 +35,17 @@ namespace sta { -using std::string; -using std::min; -using std::max; -using std::abs; -using std::make_shared; - size_t findValueIndex(float value, const FloatSeq *values); static void sigmaModelsDelete(TableModelsEarlyLate &models); -static string +static std::string reportPvt(const LibertyCell *cell, const Pvt *pvt, int digits); static void -appendSpaces(string &result, +appendSpaces(std::string &result, int count); TimingModel::TimingModel(LibertyCell *cell) : @@ -162,14 +156,14 @@ GateTableModel::gateDelay(const Pvt *pvt, gateDelay(pvt, in_slew, load_cap, pocv_enabled, gate_delay, drvr_slew); } -string +std::string GateTableModel::reportGateDelay(const Pvt *pvt, float in_slew, float load_cap, bool pocv_enabled, int digits) const { - string result = reportPvt(cell_, pvt, digits); + std::string result = reportPvt(cell_, pvt, digits); result += reportTableLookup("Delay", pvt, delay_model_.get(), in_slew, load_cap, 0.0, digits); if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()]) @@ -197,7 +191,7 @@ GateTableModel::reportGateDelay(const Pvt *pvt, return result; } -string +std::string GateTableModel::reportTableLookup(const char *result_name, const Pvt *pvt, const TableModel *model, @@ -496,7 +490,7 @@ CheckTableModel::findValue(const Pvt *pvt, return 0.0; } -string +std::string CheckTableModel::reportCheckDelay(const Pvt *pvt, float from_slew, const char *from_slew_annotation, @@ -505,7 +499,7 @@ CheckTableModel::reportCheckDelay(const Pvt *pvt, bool pocv_enabled, int digits) const { - string result = reportTableDelay("Check", pvt, model_.get(), + std::string result = reportTableDelay("Check", pvt, model_.get(), from_slew, from_slew_annotation, to_slew, related_out_cap, digits); if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()]) @@ -521,7 +515,7 @@ CheckTableModel::reportCheckDelay(const Pvt *pvt, return result; } -string +std::string CheckTableModel::reportTableDelay(const char *result_name, const Pvt *pvt, const TableModel *model, @@ -535,7 +529,7 @@ CheckTableModel::reportTableDelay(const char *result_name, float axis_value1, axis_value2, axis_value3; findAxisValues(from_slew, to_slew, related_out_cap, axis_value1, axis_value2, axis_value3); - string result = reportPvt(cell_, pvt, digits); + std::string result = reportPvt(cell_, pvt, digits); result += model_->reportValue(result_name, cell_, pvt, axis_value1, from_slew_annotation, axis_value2, axis_value3, @@ -735,7 +729,7 @@ TableModel::scaleFactor(const LibertyCell *cell, rf_index_, cell, pvt); } -string +std::string TableModel::reportValue(const char *result_name, const LibertyCell *cell, const Pvt *pvt, @@ -746,7 +740,7 @@ TableModel::reportValue(const char *result_name, const Unit *table_unit, int digits) const { - string result = table_->reportValue("Table value", cell, pvt, value1, + std::string result = table_->reportValue("Table value", cell, pvt, value1, comment1, value2, value3, table_unit, digits); result += reportPvtScaleFactor(cell, pvt, digits); @@ -758,7 +752,7 @@ TableModel::reportValue(const char *result_name, return result; } -static string +static std::string reportPvt(const LibertyCell *cell, const Pvt *pvt, int digits) @@ -767,7 +761,7 @@ reportPvt(const LibertyCell *cell, if (pvt == nullptr) pvt = library->defaultOperatingConditions(); if (pvt) { - string result; + std::string result; stringPrint(result, "P = %.*f V = %.*f T = %.*f\n", digits, pvt->process(), digits, pvt->voltage(), @@ -777,7 +771,7 @@ reportPvt(const LibertyCell *cell, return ""; } -string +std::string TableModel::reportPvtScaleFactor(const LibertyCell *cell, const Pvt *pvt, int digits) const @@ -785,7 +779,7 @@ TableModel::reportPvtScaleFactor(const LibertyCell *cell, if (pvt == nullptr) pvt = cell->libertyLibrary()->defaultOperatingConditions(); if (pvt) { - string result; + std::string result; stringPrint(result, "PVT scale factor = %.*f\n", digits, scaleFactor(cell, pvt)); @@ -1166,7 +1160,7 @@ Table::reportValueOrder0(const char *result_name, const Unit *table_unit, int digits) const { - string result = result_name; + std::string result = result_name; result += " constant = "; result += table_unit->asString(value_, digits); if (comment1) @@ -1187,7 +1181,7 @@ Table::reportValueOrder1(const char *result_name, { const Units *units = cell->libertyLibrary()->units(); const Unit *unit1 = axis1_->unit(units); - string result = "Table is indexed by\n "; + std::string result = "Table is indexed by\n "; result += axis1_->variableString(); result += " = "; result += unit1->asString(value1, digits); @@ -1228,7 +1222,7 @@ Table::reportValueOrder2(const char *result_name, const Units *units = cell->libertyLibrary()->units(); const Unit *unit1 = axis1_->unit(units); const Unit *unit2 = axis2_->unit(units); - string result = "------- "; + std::string result = "------- "; result += axis1_->variableString(); result += " = "; result += unit1->asString(value1, digits); @@ -1289,7 +1283,7 @@ Table::reportValueOrder3(const char *result_name, const Unit *unit1 = axis1_->unit(units); const Unit *unit2 = axis2_->unit(units); const Unit *unit3 = axis3_->unit(units); - string result = " --------- "; + std::string result = " --------- "; result += axis1_->variableString(); result += " = "; result += unit1->asString(value1, digits); @@ -1391,7 +1385,7 @@ Table::report(const Units *units, const Unit *unit1 = axis1_->unit(units); report->reportLine("%s", tableVariableString(axis1_->variable())); report->reportLine("------------------------------"); - string line; + std::string line; for (size_t index1 = 0; index1 < axis1_->size(); index1++) { line += unit1->asString(axis1_->axisValue(index1), digits); line += " "; @@ -1410,7 +1404,7 @@ Table::report(const Units *units, const Unit *unit2 = axis2_->unit(units); report->reportLine("%s", tableVariableString(axis2_->variable())); report->reportLine(" ------------------------------"); - string line = " "; + std::string line = " "; for (size_t index2 = 0; index2 < axis2_->size(); index2++) { line += unit2->asString(axis2_->axisValue(index2), digits); line += " "; @@ -1436,7 +1430,7 @@ Table::report(const Units *units, unit1->asString(axis1_->axisValue(axis_index1), digits)); report->reportLine("%s", tableVariableString(axis3_->variable())); report->reportLine(" ------------------------------"); - string line = " "; + std::string line = " "; for (size_t axis_index3 = 0; axis_index3 < axis3_->size(); axis_index3++) { line += unit3->asString(axis3_->axisValue(axis_index3), digits); line += " "; @@ -1455,7 +1449,7 @@ Table::report(const Units *units, } static void -appendSpaces(string &result, +appendSpaces(std::string &result, int count) { while (count--) @@ -1755,7 +1749,7 @@ OutputWaveforms::findVoltages(size_t wave_index, // Make voltage -> current table. FloatSeq axis_volts = volts; TableAxisPtr volt_axis = - make_shared(TableAxisVariable::input_voltage, std::move(axis_volts)); + std::make_shared(TableAxisVariable::input_voltage, std::move(axis_volts)); FloatSeq *currents1 = new FloatSeq(*currents->values()); Table *volt_currents = new Table(currents1, volt_axis); voltage_currents_[wave_index] = volt_currents; @@ -1774,7 +1768,7 @@ OutputWaveforms::currentWaveform(float slew, times->push_back(time); currents->push_back(current); } - TableAxisPtr time_axis = make_shared(TableAxisVariable::time, std::move(*times)); + TableAxisPtr time_axis = std::make_shared(TableAxisVariable::time, std::move(*times)); delete times; return Table(currents, time_axis); } @@ -1951,7 +1945,7 @@ OutputWaveforms::voltageWaveform(float slew, times.push_back(time); volts.push_back(volt); } - TableAxisPtr time_axis = make_shared(TableAxisVariable::time, + TableAxisPtr time_axis = std::make_shared(TableAxisVariable::time, std::move(times)); return Table(std::move(volts), time_axis); } @@ -2076,7 +2070,7 @@ OutputWaveforms::voltageCurrentWaveform(float slew, currents->push_back(current); } TableAxisPtr volt_axis = - make_shared(TableAxisVariable::input_voltage, std::move(*volts)); + std::make_shared(TableAxisVariable::input_voltage, std::move(*volts)); delete volts; return Table(currents, volt_axis); } @@ -2095,12 +2089,12 @@ OutputWaveforms::finalResistance() const FloatSeq &voltages = voltage_currents->axis1()->values(); FloatSeq *currents = voltage_currents->values(); size_t idx_last1 = voltages.size() - 2; - return (vdd_ - voltages[idx_last1]) / abs((*currents)[idx_last1]); + return (vdd_ - voltages[idx_last1]) / std::abs((*currents)[idx_last1]); } //////////////////////////////////////////////////////////////// -DriverWaveform::DriverWaveform(const string &name, +DriverWaveform::DriverWaveform(const std::string &name, TablePtr waveforms) : name_(name), waveforms_(waveforms) @@ -2118,7 +2112,7 @@ DriverWaveform::waveform(float slew) time_values->push_back(time); volt_values->push_back(volt); } - TableAxisPtr time_axis = make_shared(TableAxisVariable::time, + TableAxisPtr time_axis = std::make_shared(TableAxisVariable::time, std::move(*time_values)); delete time_values; Table waveform(volt_values, time_axis); diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 1f1ea2c1..7bc324a6 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -35,9 +35,6 @@ namespace sta { -using std::string; -using std::make_shared; - static bool timingArcsEquiv(const TimingArcSet *set1, const TimingArcSet *set2); @@ -511,7 +508,7 @@ TimingArcSet::wireArcIndex(const RiseFall *rf) void TimingArcSet::init() { - wire_timing_arc_attrs_ = make_shared(TimingSense::positive_unate); + wire_timing_arc_attrs_ = std::make_shared(TimingSense::positive_unate); wire_timing_arc_set_ = new TimingArcSet(TimingRole::wire(), wire_timing_arc_attrs_); new TimingArc(wire_timing_arc_set_, Transition::rise(), Transition::rise(), nullptr); @@ -549,18 +546,18 @@ TimingArc::~TimingArc() delete scaled_models_; } -string +std::string TimingArc::to_string() const { if (set_->role()->isWire()) { - string str = "wire "; + std::string str = "wire "; str += from_rf_->to_string(); str += " -> "; str += to_rf_->to_string(); return str; } else { - string str = set_->from()->name(); + std::string str = set_->from()->name(); str += " "; str += from_rf_->to_string(); str += " -> "; diff --git a/liberty/Units.cc b/liberty/Units.cc index 97e33309..9cbb4631 100644 --- a/liberty/Units.cc +++ b/liberty/Units.cc @@ -32,9 +32,6 @@ namespace sta { -using std::abs; - - Unit::Unit(const char *suffix) : scale_(1.0), suffix_(suffix), @@ -175,12 +172,12 @@ Unit::asString(float value, int digits) const { // Special case INF because it blows up otherwise. - if (abs(value) >= INF * .1) + if (std::abs(value) >= INF * .1) return (value > 0.0) ? "INF" : "-INF"; else { float scaled_value = value / scale_; // prevent "-0.00" on slowaris - if (abs(scaled_value) < 1E-6) + if (std::abs(scaled_value) < 1E-6) scaled_value = 0.0; return stringPrintTmp("%.*f", digits, scaled_value); } diff --git a/network/ConcreteLibrary.cc b/network/ConcreteLibrary.cc index 0ecba436..a1fb2b50 100644 --- a/network/ConcreteLibrary.cc +++ b/network/ConcreteLibrary.cc @@ -24,6 +24,7 @@ #include "ConcreteLibrary.hh" +#include #include #include @@ -35,13 +36,6 @@ namespace sta { -using std::string; -using std::map; -using std::min; -using std::max; -using std::abs; -using std::swap; - static constexpr char escape_ = '\\'; ConcreteLibrary::ConcreteLibrary(const char *name, @@ -228,7 +222,7 @@ ConcreteCell::makeBusPortBit(ConcretePort *bus_port, 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(), @@ -272,14 +266,14 @@ ConcreteCell::setIsLeaf(bool is_leaf) } void -ConcreteCell::setAttribute(const string &key, - const string &value) +ConcreteCell::setAttribute(const std::string &key, + const std::string &value) { attribute_map_[key] = value; } -string -ConcreteCell::getAttribute(const string &key) const +std::string +ConcreteCell::getAttribute(const std::string &key) const { const auto &itr = attribute_map_.find(key); if (itr != attribute_map_.end()) @@ -350,8 +344,8 @@ void BusPort::addBusBit(ConcretePort *port, int index) { - from_ = min(from_, index); - to_ = max(to_, index); + from_ = std::min(from_, index); + to_ = std::max(to_, index); members_.push_back(port); } @@ -362,7 +356,7 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left, { const char bus_brkts_left[2]{bus_brkt_left, '\0'}; const char bus_brkts_right[2]{bus_brkt_right, '\0'}; - map bus_map; + std::map bus_map; // Find ungrouped bus ports. // Remove bus bit ports from the ports_ vector during the scan by // keeping an index to the next insertion index and skipping over @@ -372,7 +366,7 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left, for (ConcretePort *port : ports) { const char *port_name = port->name(); bool is_bus; - string bus_name; + std::string bus_name; int index; parseBusName(port_name, bus_brkts_left, bus_brkts_right, escape_, is_bus, bus_name, index); @@ -402,7 +396,7 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left, (*members)[member_index] = bus_bit; } if (msb_first) - swap(from, to); + std::swap(from, to); ConcretePort *port = makeBusPort(bus_name.c_str(), from, to, members); port->setDirection(bus_port.direction()); } @@ -505,7 +499,7 @@ int ConcretePort::size() const { if (is_bus_) - return abs(to_index_ - from_index_) + 1; + return std::abs(to_index_ - from_index_) + 1; else if (is_bundle_) return static_cast(member_ports_->size()); else diff --git a/network/ConcreteNetwork.cc b/network/ConcreteNetwork.cc index 57c419b9..22fd122d 100644 --- a/network/ConcreteNetwork.cc +++ b/network/ConcreteNetwork.cc @@ -35,8 +35,6 @@ namespace sta { -using std::string; - static void makeChildNetwork(Instance *proto, Instance *parent, @@ -581,8 +579,8 @@ ConcreteNetwork::setIsLeaf(Cell *cell, void ConcreteNetwork::setAttribute(Cell *cell, - const string &key, - const string &value) + const std::string &key, + const std::string &value) { ConcreteCell *ccell = reinterpret_cast(cell); ccell->setAttribute(key, value); @@ -628,9 +626,9 @@ ConcreteNetwork::filename(const Cell *cell) return ccell->filename(); } -string +std::string ConcreteNetwork::getAttribute(const Cell *cell, - const string &key) const + const std::string &key) const { const ConcreteCell *ccell = reinterpret_cast(cell); return ccell->getAttribute(key); @@ -967,9 +965,9 @@ ConcreteNetwork::id(const Instance *instance) const return inst->id(); } -string +std::string ConcreteNetwork::getAttribute(const Instance *inst, - const string &key) const + const std::string &key) const { const ConcreteInstance *cinst = reinterpret_cast(inst); return cinst->getAttribute(key); @@ -1389,8 +1387,8 @@ ConcreteNetwork::connect(Instance *inst, void ConcreteNetwork::setAttribute(Instance *inst, - const string &key, - const string &value) + const std::string &key, + const std::string &value) { ConcreteInstance *cinst = reinterpret_cast(inst); cinst->setAttribute(key, value); @@ -1718,14 +1716,14 @@ ConcreteInstance::childIterator() const } void -ConcreteInstance::setAttribute(const string &key, - const string &value) +ConcreteInstance::setAttribute(const std::string &key, + const std::string &value) { attribute_map_[key] = value; } -string -ConcreteInstance::getAttribute(const string &key) const +std::string +ConcreteInstance::getAttribute(const std::string &key) const { const auto &itr = attribute_map_.find(key); if (itr != attribute_map_.end()) diff --git a/network/Network.cc b/network/Network.cc index 3b6bad62..78e13b1e 100644 --- a/network/Network.cc +++ b/network/Network.cc @@ -37,8 +37,6 @@ namespace sta { -using std::string; - Network::Network() : default_liberty_(nullptr), divider_('/'), @@ -76,7 +74,7 @@ Network::findPortsMatching(const Cell *cell, { PortSeq matches; bool is_bus, is_range, subscript_wild; - string bus_name; + std::string bus_name; int from, to; parseBusName(pattern->pattern(), '[', ']', '\\', is_bus, is_range, bus_name, from, to, subscript_wild); @@ -1043,12 +1041,12 @@ Network::findInstPinsHierMatching(const Instance *instance, // Return value. PinSeq &matches) const { - string inst_name = name(instance); + std::string inst_name = name(instance); InstancePinIterator *pin_iter = pinIterator(instance); while (pin_iter->hasNext()) { const Pin *pin = pin_iter->next(); const char *port_name = name(port(pin)); - string pin_name = inst_name + divider_ + port_name; + std::string pin_name = inst_name + divider_ + port_name; if (pattern->match(pin_name.c_str())) matches.push_back(pin); } diff --git a/network/ParseBus.cc b/network/ParseBus.cc index 17108412..c3dae9e5 100644 --- a/network/ParseBus.cc +++ b/network/ParseBus.cc @@ -32,8 +32,6 @@ namespace sta { -using std::string; - bool isBusName(const char *name, const char brkt_left, @@ -60,7 +58,7 @@ parseBusName(const char *name, const char escape, // Return values. bool &is_bus, - string &bus_name, + std::string &bus_name, int &index) { const char brkts_left[2] = {brkt_left, '\0'}; @@ -76,7 +74,7 @@ parseBusName(const char *name, char escape, // Return values. bool &is_bus, - string &bus_name, + std::string &bus_name, int &index) { is_bus = false; @@ -110,7 +108,7 @@ parseBusName(const char *name, // Return values. bool &is_bus, bool &is_range, - string &bus_name, + std::string &bus_name, int &from, int &to, bool &subscript_wild) @@ -129,7 +127,7 @@ parseBusName(const char *name, // Return values. bool &is_bus, bool &is_range, - string &bus_name, + std::string &bus_name, int &from, int &to, bool &subscript_wild) @@ -173,13 +171,13 @@ parseBusName(const char *name, } } -string +std::string escapeChars(const char *token, const char ch1, const char ch2, const char escape) { - string escaped; + std::string escaped; for (const char *s = token; *s; s++) { char ch = *s; if (ch == escape) { diff --git a/network/SdcNetwork.cc b/network/SdcNetwork.cc index 29a0037e..0495f943 100644 --- a/network/SdcNetwork.cc +++ b/network/SdcNetwork.cc @@ -30,13 +30,10 @@ namespace sta { -using std::string; -using std::to_string; - -static string +static std::string escapeDividers(const char *token, const Network *network); -static string +static std::string escapeBrackets(const char *token, const Network *network); @@ -137,9 +134,9 @@ NetworkNameAdapter::id(const Cell *cell) const return network_->id(cell); } -string +std::string NetworkNameAdapter::getAttribute(const Cell *cell, - const string &key) const + const std::string &key) const { return network_->getAttribute(cell, key); } @@ -355,9 +352,9 @@ NetworkNameAdapter::cell(const Instance *instance) const return network_->cell(instance); } -string +std::string NetworkNameAdapter::getAttribute(const Instance *inst, - const string &key) const + const std::string &key) const { return network_->getAttribute(inst, key); } @@ -675,16 +672,16 @@ SdcNetwork::findPort(const Cell *cell, if (port == nullptr) { // Look for matches after escaping brackets. bool is_bus; - string bus_name; + std::string bus_name; int index; parseBusName(name, '[', ']', pathEscape(), is_bus, bus_name, index); if (is_bus) { - string escaped1 = escapeBrackets(name, this); + std::string escaped1 = escapeBrackets(name, this); port = network_->findPort(cell, escaped1.c_str()); if (port == nullptr) { // Try escaping base foo\[0\][1] - string escaped2; - string escaped_bus_name = escapeBrackets(bus_name.c_str(), this); + std::string escaped2; + std::string escaped_bus_name = escapeBrackets(bus_name.c_str(), this); stringPrint(escaped2, "%s[%d]", escaped_bus_name.c_str(), index); @@ -693,7 +690,7 @@ SdcNetwork::findPort(const Cell *cell, } else { // Try escaping brackets foo\[0\].bar - string escaped = escapeBrackets(name, this); + std::string escaped = escapeBrackets(name, this); port = network_->findPort(cell, escaped.c_str()); } } @@ -708,19 +705,19 @@ SdcNetwork::findPortsMatching(const Cell *cell, if (matches.empty()) { // Look for matches after escaping brackets. bool is_bus; - string bus_name; + std::string bus_name; int index; parseBusName(pattern->pattern(), '[', ']', pathEscape(), is_bus, bus_name, index); if (is_bus) { - string escaped1 = escapeBrackets(pattern->pattern(), this); + std::string escaped1 = escapeBrackets(pattern->pattern(), this); PatternMatch escaped_pattern1(escaped1.c_str(), pattern); matches = network_->findPortsMatching(cell, &escaped_pattern1); if (matches.empty()) { // Try escaping base foo\[0\][1] - string escaped_name = escapeBrackets(bus_name.c_str(), this); + std::string escaped_name = escapeBrackets(bus_name.c_str(), this); escaped_name += '['; - escaped_name += to_string(index); + escaped_name += std::to_string(index); escaped_name += ']'; PatternMatch escaped_pattern2(escaped_name.c_str(), pattern); matches = network_->findPortsMatching(cell, &escaped_pattern2); @@ -728,7 +725,7 @@ SdcNetwork::findPortsMatching(const Cell *cell, } else { // Try escaping brackets foo\[0\].bar - string escaped = escapeBrackets(pattern->pattern(), this); + std::string escaped = escapeBrackets(pattern->pattern(), this); PatternMatch escaped_pattern(escaped.c_str(), pattern); matches = network_->findPortsMatching(cell, &escaped_pattern); } @@ -796,7 +793,7 @@ SdcNetwork::findInstance(const char *path_name) const parent = network_->topInstance(); Instance *child = findChild(parent, child_name); if (child == nullptr) { - string escaped_name = escapeDividers(child_name, this); + std::string escaped_name = escapeDividers(child_name, this); child = findChild(parent, escaped_name.c_str()); } return child; @@ -808,10 +805,10 @@ SdcNetwork::findInstanceRelative(const Instance *inst, { Instance *inst1 = network_->findInstanceRelative(inst, path_name); if (inst1 == nullptr) { - string path_name1 = escapeBrackets(path_name, this); + std::string path_name1 = escapeBrackets(path_name, this); inst1 = network_->findInstanceRelative(inst, path_name1.c_str()); if (inst1 == nullptr) { - string path_name2 = escapeDividers(path_name1.c_str(), network_); + std::string path_name2 = escapeDividers(path_name1.c_str(), network_); inst1 = network_->findInstanceRelative(inst, path_name2.c_str()); } } @@ -848,7 +845,7 @@ SdcNetwork::findChild(const Instance *parent, { Instance *child = network_->findChild(parent, name); if (child == nullptr) { - string escaped = escapeBrackets(name, this); + std::string escaped = escapeBrackets(name, this); child = network_->findChild(parent, escaped.c_str()); } return child; @@ -873,8 +870,8 @@ SdcNetwork::findNet(const Instance *instance, { Net *net = network_->findNet(instance, net_name); if (net == nullptr) { - string net_name1 = escapeBrackets(net_name, this); - string net_name2 = escapeDividers(net_name1.c_str(), network_); + std::string net_name1 = escapeBrackets(net_name, this); + std::string net_name2 = escapeDividers(net_name1.c_str(), network_); net = network_->findNet(instance, net_name2.c_str()); } return net; @@ -886,15 +883,15 @@ SdcNetwork::findNetRelative(const Instance *inst, { Net *net = network_->findNetRelative(inst, path_name); if (net == nullptr) { - string path_name1 = escapeDividers(path_name, network_); + std::string path_name1 = escapeDividers(path_name, network_); net = network_->findNetRelative(inst, path_name1.c_str()); if (net == nullptr) { - string path_name2 = escapeBrackets(path_name, network_); + std::string path_name2 = escapeBrackets(path_name, network_); net = network_->findNetRelative(inst, path_name2.c_str()); if (net == nullptr) { - string path_name3 = escapeDividers(path_name2.c_str(), network_); + std::string path_name3 = escapeDividers(path_name2.c_str(), network_); net = network_->findNetRelative(inst, path_name3.c_str()); } } @@ -926,12 +923,12 @@ SdcNetwork::findInstNetsMatching(const Instance *instance, network_->findInstNetsMatching(instance, pattern, matches); if (matches.empty()) { // Look for matches after escaping path dividers. - string escaped_pattern = escapeDividers(pattern->pattern(), this); + std::string escaped_pattern = escapeDividers(pattern->pattern(), this); const PatternMatch escaped_dividers(escaped_pattern.c_str(), pattern); network_->findInstNetsMatching(instance, &escaped_dividers, matches); if (matches.empty()) { // Look for matches after escaping brackets. - string escaped_pattern2 = escapeBrackets(pattern->pattern(),this); + std::string escaped_pattern2 = escapeBrackets(pattern->pattern(),this); const PatternMatch escaped_brkts(escaped_pattern2.c_str(), pattern); network_->findInstNetsMatching(instance, &escaped_brkts, matches); } @@ -959,24 +956,24 @@ SdcNetwork::findPin(const Instance *instance, if (pin == nullptr) { // Look for match after escaping brackets. bool is_bus; - string bus_name; + std::string bus_name; int index; parseBusName(port_name, '[', ']', pathEscape(), is_bus, bus_name, index); if (is_bus) { - string escaped1 = escapeBrackets(port_name, this); + std::string escaped1 = escapeBrackets(port_name, this); pin = network_->findPin(instance, escaped1.c_str()); if (pin == nullptr) { // Try escaping base foo\[0\][1] - string escaped_bus_name = escapeBrackets(bus_name.c_str(), this); - string escaped2; + std::string escaped_bus_name = escapeBrackets(bus_name.c_str(), this); + std::string escaped2; stringPrint(escaped2, "%s[%d]", escaped_bus_name.c_str(), index); pin = network_->findPin(instance, escaped2.c_str()); } } else { // Try escaping port brackets foo\[0\].bar - string escaped = escapeBrackets(port_name, this); + std::string escaped = escapeBrackets(port_name, this); pin = network_->findPin(instance, escaped.c_str()); } } @@ -1028,7 +1025,7 @@ SdcNetwork::visitPinTail(const Instance *instance, if (network_->hasMembers(port)) { bool bus_matches = tail->match(port_name); if (!bus_matches) { - string escaped_name = escapeDividers(port_name, network_); + std::string escaped_name = escapeDividers(port_name, network_); bus_matches = tail->match(escaped_name); } PortMemberIterator *member_iter = network_->memberIterator(port); @@ -1044,7 +1041,7 @@ SdcNetwork::visitPinTail(const Instance *instance, const char *member_name = network_->name(member_port); bool member_matches = tail->match(member_name); if (!member_matches) { - string escaped_name = escapeDividers(member_name, network_); + std::string escaped_name = escapeDividers(member_name, network_); member_matches = tail->match(escaped_name); } if (member_matches) { @@ -1059,7 +1056,7 @@ SdcNetwork::visitPinTail(const Instance *instance, else { bool port_matches = tail->match(port_name); if (!port_matches) { - string escaped_name = escapeDividers(port_name, network_); + std::string escaped_name = escapeDividers(port_name, network_); port_matches = tail->match(escaped_name); } if (port_matches) { @@ -1081,7 +1078,7 @@ SdcNetwork::makeInstance(LibertyCell *cell, const char *name, Instance *parent) { - string escaped_name = escapeDividers(name, this); + std::string escaped_name = escapeDividers(name, this); return network_edit_->makeInstance(cell, escaped_name.c_str(), parent); } @@ -1089,7 +1086,7 @@ Net * SdcNetwork::makeNet(const char *name, Instance *parent) { - string escaped_name = escapeDividers(name, this); + std::string escaped_name = escapeDividers(name, this); return network_edit_->makeNet(escaped_name.c_str(), parent); } @@ -1188,7 +1185,7 @@ SdcNetwork::parsePath(const char *path, else *p++ = ch; if (p - inst_path + 1 > inst_path_length) - report_->critical(1500, "inst path string lenth estimate busted"); + report_->critical(1500, "inst path std::string lenth estimate busted"); } *p = '\0'; stringDelete(inst_path); @@ -1235,7 +1232,7 @@ SdcNetwork::visitMatches(const Instance *parent, network_->findChildrenMatching(parent, &matcher, matches); if (has_brkts && matches.empty()) { // Look for matches after escaping brackets. - string escaped_brkts = escapeBrackets(inst_path, this); + std::string escaped_brkts = escapeBrackets(inst_path, this); const PatternMatch escaped_pattern(escaped_brkts, pattern); network_->findChildrenMatching(parent, &escaped_pattern, matches); } @@ -1257,7 +1254,7 @@ SdcNetwork::visitMatches(const Instance *parent, *p++ = ch; } if (p - inst_path + 1 > inst_path_length) - report_->critical(1501, "inst path string lenth estimate exceeded"); + report_->critical(1501, "inst path std::string lenth estimate exceeded"); } *p = '\0'; if (!found_match) { @@ -1265,7 +1262,7 @@ SdcNetwork::visitMatches(const Instance *parent, found_match |= visit_tail(parent, &tail_pattern); if (!found_match && has_brkts) { // Look for matches after escaping brackets. - string escaped_path = escapeBrackets(inst_path, this); + std::string escaped_path = escapeBrackets(inst_path, this); const PatternMatch escaped_tail(escaped_path, pattern); found_match |= visit_tail(parent, &escaped_tail); } @@ -1276,7 +1273,7 @@ SdcNetwork::visitMatches(const Instance *parent, //////////////////////////////////////////////////////////////// -static string +static std::string escapeDividers(const char *token, const Network *network) { @@ -1284,7 +1281,7 @@ escapeDividers(const char *token, network->pathEscape()); } -static string +static std::string escapeBrackets(const char *token, const Network *network) { diff --git a/network/VerilogNamespace.cc b/network/VerilogNamespace.cc index 5a1dc8e0..5362d115 100644 --- a/network/VerilogNamespace.cc +++ b/network/VerilogNamespace.cc @@ -31,39 +31,37 @@ namespace sta { -using std::string; - constexpr char verilog_escape = '\\'; -static string +static std::string staToVerilog(const char *sta_name); -static string +static std::string staToVerilog2(const char *sta_name); -static string -verilogToSta(const string *verilog_name); +static std::string +verilogToSta(const std::string *verilog_name); -string +std::string cellVerilogName(const char *sta_name) { return staToVerilog(sta_name); } -string +std::string instanceVerilogName(const char *sta_name) { return staToVerilog(sta_name); } -string +std::string netVerilogName(const char *sta_name) { bool is_bus; - string bus_name; + std::string bus_name; int index; parseBusName(sta_name, '[', ']', verilog_escape, is_bus, bus_name, index); if (is_bus) { - string bus_vname = staToVerilog(bus_name.c_str()); - string vname; + std::string bus_vname = staToVerilog(bus_name.c_str()); + std::string vname; stringPrint(vname, "%s[%d]", bus_vname.c_str(), index); return vname; } @@ -71,19 +69,19 @@ netVerilogName(const char *sta_name) return staToVerilog2(sta_name); } -string +std::string portVerilogName(const char *sta_name) { return staToVerilog2(sta_name); } -static string +static std::string staToVerilog(const char *sta_name) { // Leave room for leading escape and trailing space if the name // needs to be escaped. // Assume the name has to be escaped and start copying while scanning. - string escaped_name = "\\"; + std::string escaped_name = "\\"; bool escaped = false; for (const char *s = sta_name; *s ; s++) { char ch = s[0]; @@ -110,17 +108,17 @@ staToVerilog(const char *sta_name) return escaped_name; } else - return string(sta_name); + return std::string(sta_name); } -static string +static std::string staToVerilog2(const char *sta_name) { constexpr char bus_brkt_left = '['; constexpr char bus_brkt_right = ']'; // Leave room for leading escape and trailing space if the name // needs to be escaped. - string escaped_name = "\\"; + std::string escaped_name = "\\"; // Assume the name has to be escaped and start copying while scanning. bool escaped = false; for (const char *s = sta_name; *s ; s++) { @@ -150,37 +148,37 @@ staToVerilog2(const char *sta_name) return escaped_name; } else - return string(sta_name); + return std::string(sta_name); } //////////////////////////////////////////////////////////////// -string -moduleVerilogToSta(const string *module_name) +std::string +moduleVerilogToSta(const std::string *module_name) { return verilogToSta(module_name); } -string -instanceVerilogToSta(const string *inst_name) +std::string +instanceVerilogToSta(const std::string *inst_name) { return verilogToSta(inst_name); } -string -netVerilogToSta(const string *net_name) +std::string +netVerilogToSta(const std::string *net_name) { return verilogToSta(net_name); } -string -portVerilogToSta(const string *port_name) +std::string +portVerilogToSta(const std::string *port_name) { return verilogToSta(port_name); } -static string -verilogToSta(const string *verilog_name) +static std::string +verilogToSta(const std::string *verilog_name) { if (verilog_name->front() == '\\') { constexpr char divider = '/'; @@ -190,7 +188,7 @@ verilogToSta(const string *verilog_name) size_t verilog_name_length = verilog_name->size(); if (isspace(verilog_name->back())) verilog_name_length--; - string sta_name; + std::string sta_name; // Ignore leading '\'. for (size_t i = 1; i < verilog_name_length; i++) { char ch = verilog_name->at(i); @@ -205,7 +203,7 @@ verilogToSta(const string *verilog_name) return sta_name; } else - return string(*verilog_name); + return std::string(*verilog_name); } } // namespace diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc index dd866664..f6a156ff 100644 --- a/parasitics/ConcreteParasitics.cc +++ b/parasitics/ConcreteParasitics.cc @@ -45,8 +45,6 @@ namespace sta { -using std::max; - ConcreteParasitic::~ConcreteParasitic() { } @@ -620,7 +618,7 @@ ConcreteParasiticNetwork::ensureParasiticNode(const Net *net, node = new ConcreteParasiticNode(net, id, network->highestNetAbove(net1) != net_); sub_nodes_[net_id] = node; if (net == net_) - max_node_id_ = max((int) max_node_id_, id); + max_node_id_ = std::max((int) max_node_id_, id); } else node = id_node->second; diff --git a/parasitics/ReduceParasitics.cc b/parasitics/ReduceParasitics.cc index 1650f8e3..311ef35c 100644 --- a/parasitics/ReduceParasitics.cc +++ b/parasitics/ReduceParasitics.cc @@ -24,6 +24,7 @@ #include "ReduceParasitics.hh" +#include #include #include @@ -38,8 +39,6 @@ namespace sta { -using std::max; - typedef std::map ParasiticNodeValueMap; typedef std::map ResistorCurrentMap; typedef std::set ParasiticResistorSet; @@ -174,7 +173,7 @@ ReduceToPi::reducePiDfs(const Pin *drvr_pin, + pinCapacitance(node); y1 = dwn_cap; y2 = y3 = 0.0; - max_resistance = max(max_resistance, src_resistance); + max_resistance = std::max(max_resistance, src_resistance); visit(node); ParasiticResistorSeq &resistors = resistor_map_[node]; diff --git a/parasitics/SpefReader.cc b/parasitics/SpefReader.cc index b27efe6c..7d0751f8 100644 --- a/parasitics/SpefReader.cc +++ b/parasitics/SpefReader.cc @@ -43,8 +43,6 @@ namespace sta { -using std::string; - bool readSpefFile(const std::string &filename, Instance *instance, @@ -616,7 +614,7 @@ SpefTriple::value(int index) const //////////////////////////////////////////////////////////////// SpefScanner::SpefScanner(std::istream *stream, - const string &filename, + const std::string &filename, SpefReader *reader, Report *report) : yyFlexLexer(stream), diff --git a/power/Power.cc b/power/Power.cc index 2faaef23..f0b590fa 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -72,13 +72,6 @@ namespace sta { -using std::abs; -using std::max; -using std::min; -using std::isnormal; -using std::vector; -using std::map; - static bool isPositiveUnate(const LibertyCell *cell, const LibertyPort *from, @@ -734,7 +727,7 @@ percentChange(float value, return 1.0; } else - return abs(value - prev) / prev; + return std::abs(value - prev) / prev; } // Return true if the activity changed. @@ -1837,7 +1830,7 @@ Power::clockMinPeriod(const Sdc *sdc) if (!clks.empty()) { float min_period = INF; for (const Clock *clk : clks) - min_period = min(min_period, clk->period()); + min_period = std::min(min_period, clk->period()); return min_period; } else @@ -1963,7 +1956,7 @@ PwrActivity::check() // Densities can get very small from multiplying probabilities // through deep chains of logic. Clip them to prevent floating // point anomalies. - if (abs(density_) < min_density) + if (std::abs(density_) < min_density) density_ = 0.0; } diff --git a/power/SaifReader.cc b/power/SaifReader.cc index 3a758ba2..bd62602a 100644 --- a/power/SaifReader.cc +++ b/power/SaifReader.cc @@ -26,6 +26,7 @@ #include #include +#include #include "Error.hh" #include "Debug.hh" @@ -42,9 +43,6 @@ namespace sta { -using std::string; -using std::min; - bool readSaif(const char *filename, const char *scope, @@ -129,9 +127,9 @@ SaifReader::instancePush(const char *instance_name) // Check for a match to the annotation scope. saif_scope_.push_back(instance_name); - string saif_scope; + std::string saif_scope; bool first = true; - for (string &inst : saif_scope_) { + for (std::string &inst : saif_scope_) { if (!first) saif_scope += sdc_network_->pathDivider(); saif_scope += inst; @@ -167,7 +165,7 @@ SaifReader::setNetDurations(const char *net_name, if (in_scope_level_ > 0) { Instance *parent = path_.empty() ? sdc_network_->topInstance() : path_.back(); if (parent) { - string unescaped_name = unescaped(net_name); + std::string unescaped_name = unescaped(net_name); const Pin *pin = sdc_network_->findPin(parent, unescaped_name.c_str()); LibertyPort *liberty_port = pin ? sdc_network_->libertyPort(pin) : nullptr; if (pin @@ -194,10 +192,10 @@ SaifReader::setNetDurations(const char *net_name, stringDelete(net_name); } -string +std::string SaifReader::unescaped(const char *token) { - string unescaped; + std::string unescaped; for (const char *t = token; *t; t++) { char ch = *t; if (ch != escape_) @@ -211,7 +209,7 @@ SaifReader::unescaped(const char *token) //////////////////////////////////////////////////////////////// SaifScanner::SaifScanner(std::istream *stream, - const string &filename, + const std::string &filename, SaifReader *reader, Report *report) : yyFlexLexer(stream), diff --git a/power/VcdParse.cc b/power/VcdParse.cc index 93d6625c..83e171cf 100644 --- a/power/VcdParse.cc +++ b/power/VcdParse.cc @@ -35,10 +35,6 @@ namespace sta { -using std::vector; -using std::string; -using std::isspace; - // Very imprecise syntax definition // https://en.wikipedia.org/wiki/Value_change_dump#Structure.2FSyntax // Much better syntax definition @@ -125,7 +121,7 @@ VcdParse::VcdParse(Report *report, void VcdParse::parseTimescale() { - vector tokens = readStmtTokens(); + std::vector tokens = readStmtTokens(); if (tokens.size() == 1) { size_t last; double time_scale = std::stod(tokens[0], &last); @@ -140,7 +136,7 @@ VcdParse::parseTimescale() } void -VcdParse::setTimeUnit(const string &time_unit, +VcdParse::setTimeUnit(const std::string &time_unit, double time_scale) { double time_unit_scale = 1.0; @@ -177,19 +173,19 @@ static EnumNameMap vcd_var_type_map = void VcdParse::parseVar() { - vector tokens = readStmtTokens(); + std::vector tokens = readStmtTokens(); if (tokens.size() == 4 || tokens.size() == 5) { - string type_name = tokens[0]; + std::string type_name = tokens[0]; VcdVarType type = vcd_var_type_map.find(type_name, VcdVarType::unknown); if (type == VcdVarType::unknown) report_->fileWarn(1370, filename_, file_line_, "Unknown variable type %s.", type_name.c_str()); else { - size_t width = stoi(tokens[1]); - string &id = tokens[2]; - string name = tokens[3]; + size_t width = std::stoi(tokens[1]); + std::string &id = tokens[2]; + std::string name = tokens[3]; // iverilog separates bus base name from bit range. if (tokens.size() == 5) { // Preserve space after esacaped name. @@ -208,8 +204,8 @@ VcdParse::parseVar() void VcdParse::parseScope() { - vector tokens = readStmtTokens(); - string &scope = tokens[1]; + std::vector tokens = readStmtTokens(); + std::string &scope = tokens[1]; scope_.push_back(scope); } @@ -223,11 +219,11 @@ VcdParse::parseUpscope() void VcdParse::parseVarValues() { - string token = getToken(); + std::string token = getToken(); while (!token.empty()) { char char0 = toupper(token[0]); if (char0 == '#' && token.size() > 1) { - VcdTime time = stoll(token.substr(1)); + VcdTime time = std::stoll(token.substr(1)); prev_time_ = time_; time_ = time; if (time_ > prev_time_) @@ -238,15 +234,15 @@ VcdParse::parseVarValues() || char0 == 'X' || char0 == 'U' || char0 == 'Z') { - string id = token.substr(1); + std::string id = token.substr(1); if (!reader_->varIdValid(id)) report_->fileError(805, filename_, file_line_, "unknown variable %s", id.c_str()); reader_->varAppendValue(id, time_, char0); } else if (char0 == 'B') { - string bus_value = token.substr(1); - string id = getToken(); + std::string bus_value = token.substr(1); + std::string id = getToken(); if (!reader_->varIdValid(id)) report_->fileError(807, filename_, file_line_, "unknown variable %s", id.c_str()); @@ -261,12 +257,12 @@ VcdParse::parseVarValues() reader_->setTimeMax(time_); } -string +std::string VcdParse::readStmtString() { stmt_line_ = file_line_; - string line; - string token = getToken(); + std::string line; + std::string token = getToken(); while (!token.empty() && token != "$end") { if (!line.empty()) line += " "; @@ -276,12 +272,12 @@ VcdParse::readStmtString() return line; } -vector +std::vector VcdParse::readStmtTokens() { stmt_line_ = file_line_; - vector tokens; - string token = getToken(); + std::vector tokens; + std::string token = getToken(); while (!token.empty() && token != "$end") { tokens.push_back(token); token = getToken(); @@ -289,18 +285,18 @@ VcdParse::readStmtTokens() return tokens; } -string +std::string VcdParse::getToken() { - string token; + std::string token; int ch = gzgetc(stream_); // skip whitespace - while (ch != EOF && isspace(ch)) { + while (ch != EOF && std::isspace(ch)) { if (ch == '\n') file_line_++; ch = gzgetc(stream_); } - while (ch != EOF && !isspace(ch)) { + while (ch != EOF && !std::isspace(ch)) { token.push_back(ch); ch = gzgetc(stream_); } diff --git a/power/VcdReader.cc b/power/VcdReader.cc index 30b0078e..5e624273 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -24,8 +24,10 @@ #include "VcdReader.hh" +#include #include #include +#include #include "VcdParse.hh" #include "Debug.hh" @@ -41,13 +43,6 @@ namespace sta { -using std::string; -using std::abs; -using std::min; -using std::to_string; -using std::vector; -using std::unordered_map; - // Transition count and high time for duty cycle for a group of pins // for one bit of vcd ID. class VcdCount @@ -117,9 +112,9 @@ VcdCount::highTime(VcdTime time_max) const //////////////////////////////////////////////////////////////// // VcdCount[bit] -typedef vector VcdCounts; +using VcdCounts = std::vector; // ID -> VcdCount[bit] -typedef unordered_map VcdIdCountsMap; +using VcdIdCountsMap = std::unordered_map; class VcdCountReader : public VcdReader { @@ -134,31 +129,31 @@ public: double timeScale() const { return time_scale_; } // VcdParse callbacks. - void setDate(const string &) override {} - void setComment(const string &) override {} - void setVersion(const string &) override {} - void setTimeUnit(const string &time_unit, + void setDate(const std::string &) override {} + void setComment(const std::string &) override {} + void setVersion(const std::string &) override {} + void setTimeUnit(const std::string &time_unit, double time_unit_scale, double time_scale) override; void setTimeMin(VcdTime time) override; void setTimeMax(VcdTime time) override; void varMinDeltaTime(VcdTime) override {} - bool varIdValid(const string &id) override; + bool varIdValid(const std::string &id) override; void makeVar(const VcdScope &scope, - const string &name, + const std::string &name, VcdVarType type, size_t width, - const string &id) override; - void varAppendValue(const string &id, + const std::string &id) override; + void varAppendValue(const std::string &id, VcdTime time, char value) override; - void varAppendBusValue(const string &id, + void varAppendBusValue(const std::string &id, VcdTime time, - const string &bus_value) override; + const std::string &bus_value) override; private: - void addVarPin(const string &pin_name, - const string &id, + void addVarPin(const std::string &pin_name, + const std::string &id, size_t width, size_t bit_idx); @@ -189,7 +184,7 @@ VcdCountReader::VcdCountReader(const std::string &scope, } void -VcdCountReader::setTimeUnit(const string &, +VcdCountReader::setTimeUnit(const std::string &, double time_unit_scale, double time_scale) { @@ -209,23 +204,23 @@ VcdCountReader::setTimeMax(VcdTime time) } bool -VcdCountReader::varIdValid(const string &) +VcdCountReader::varIdValid(const std::string &) { return true; } void VcdCountReader::makeVar(const VcdScope &scope, - const string &name, + const std::string &name, VcdVarType type, size_t width, - const string &id) + const std::string &id) { if (type == VcdVarType::wire || type == VcdVarType::reg) { - string path_name; + std::string path_name; bool first = true; - for (const string &context : scope) { + for (const std::string &context : scope) { if (!first) path_name += '/'; path_name += context; @@ -238,25 +233,25 @@ VcdCountReader::makeVar(const VcdScope &scope, path_name += '/'; path_name += name; // Strip the scope from the name. - string var_scoped = path_name.substr(scope_length + 1); + std::string var_scoped = path_name.substr(scope_length + 1); if (width == 1) { - string pin_name = netVerilogToSta(&var_scoped); + std::string pin_name = netVerilogToSta(&var_scoped); addVarPin(pin_name, id, width, 0); } else { bool is_bus, is_range, subscript_wild; - string bus_name; + std::string bus_name; int from, to; parseBusName(var_scoped.c_str(), '[', ']', '\\', is_bus, is_range, bus_name, from, to, subscript_wild); if (is_bus) { - string sta_bus_name = netVerilogToSta(&bus_name); + std::string sta_bus_name = netVerilogToSta(&bus_name); int bit_idx = 0; if (to < from) { for (int bus_bit = to; bus_bit <= from; bus_bit++) { - string pin_name = sta_bus_name; + std::string pin_name = sta_bus_name; pin_name += '['; - pin_name += to_string(bus_bit); + pin_name += std::to_string(bus_bit); pin_name += ']'; addVarPin(pin_name, id, width, bit_idx); bit_idx++; @@ -264,9 +259,9 @@ VcdCountReader::makeVar(const VcdScope &scope, } else { for (int bus_bit = to; bus_bit >= from; bus_bit--) { - string pin_name = sta_bus_name; + std::string pin_name = sta_bus_name; pin_name += '['; - pin_name += to_string(bus_bit); + pin_name += std::to_string(bus_bit); pin_name += ']'; addVarPin(pin_name, id, width, bit_idx); bit_idx++; @@ -281,8 +276,8 @@ VcdCountReader::makeVar(const VcdScope &scope, } void -VcdCountReader::addVarPin(const string &pin_name, - const string &id, +VcdCountReader::addVarPin(const std::string &pin_name, + const std::string &id, size_t width, size_t bit_idx) { @@ -303,7 +298,7 @@ VcdCountReader::addVarPin(const string &pin_name, } void -VcdCountReader::varAppendValue(const string &id, +VcdCountReader::varAppendValue(const std::string &id, VcdTime time, char value) { @@ -329,9 +324,9 @@ VcdCountReader::varAppendValue(const string &id, } void -VcdCountReader::varAppendBusValue(const string &id, +VcdCountReader::varAppendBusValue(const std::string &id, VcdTime time, - const string &bus_value) + const std::string &bus_value) { const auto &itr = vcd_count_map_.find(id); if (itr != vcd_count_map_.end()) { @@ -476,7 +471,7 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin, sdc_network_->pathName(pin)); else { double clk_period = clk->period(); - if (abs((clk_period - sim_period) / clk_period) > sim_clk_period_tolerance_) + if (std::abs((clk_period - sim_period) / clk_period) > sim_clk_period_tolerance_) // Warn if sim clock period differs from SDC by more than 10%. report_->warn(1452, "clock %s vcd period %s differs from SDC clock period %s", clk->name(), diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index 70d131c9..25ba0d78 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -38,8 +38,6 @@ namespace sta { -using std::string; - static bool thrusIntersectPts(ExceptionThruSeq *thrus1, ExceptionThruSeq *thrus2, @@ -326,7 +324,7 @@ ExceptionPath::intersectsPts(ExceptionPath *exception, const char * ExceptionPath::fromThruToString(const Network *network) const { - string str; + std::string str; if (min_max_ != MinMaxAll::all()) { str += " -"; str += min_max_->to_string(); @@ -1186,7 +1184,7 @@ ExceptionFromTo::deletePinBefore(const Pin *pin, const char * ExceptionFromTo::asString(const Network *network) const { - string str; + std::string str; str += " "; str += cmdKeyword(); str += " {"; @@ -1360,7 +1358,7 @@ ExceptionTo::clone(const Network *network) const char * ExceptionTo::asString(const Network *network) const { - string str; + std::string str; if (hasObjects()) str += ExceptionFromTo::asString(network); @@ -1679,7 +1677,7 @@ ExceptionThru::~ExceptionThru() const char * ExceptionThru::asString(const Network *network) const { - string str; + std::string str; bool first = true; int obj_count = 0; if (pins_) { diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 85ee1950..001d7567 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -62,8 +62,6 @@ namespace sta { -using std::swap; - bool ClockPairLess::operator()(const ClockPair &pair1, const ClockPair &pair2) const @@ -693,10 +691,10 @@ void Sdc::swapDeratingFactors(Sdc *sdc1, Sdc *sdc2) { - swap(sdc1->derating_factors_, sdc2->derating_factors_); - swap(sdc1->net_derating_factors_, sdc2->net_derating_factors_); - swap(sdc1->inst_derating_factors_, sdc2->inst_derating_factors_); - swap(sdc1->cell_derating_factors_, sdc2->cell_derating_factors_); + std::swap(sdc1->derating_factors_, sdc2->derating_factors_); + std::swap(sdc1->net_derating_factors_, sdc2->net_derating_factors_); + std::swap(sdc1->inst_derating_factors_, sdc2->inst_derating_factors_); + std::swap(sdc1->cell_derating_factors_, sdc2->cell_derating_factors_); } void @@ -1818,7 +1816,7 @@ void Sdc::swapClockInsertions(Sdc *sdc1, Sdc *sdc2) { - swap(sdc1->clk_insertions_, sdc2->clk_insertions_); + std::swap(sdc1->clk_insertions_, sdc2->clk_insertions_); } void @@ -2825,17 +2823,17 @@ void Sdc::swapPortDelays(Sdc *sdc1, Sdc *sdc2) { - swap(sdc1->input_delays_, sdc2->input_delays_); - swap(sdc1->input_delay_pin_map_, sdc2->input_delay_pin_map_); - swap(sdc1->input_delay_ref_pin_map_, sdc2->input_delay_ref_pin_map_); - swap(sdc1->input_delay_leaf_pin_map_, sdc2->input_delay_leaf_pin_map_); - swap(sdc1->input_delay_internal_pin_map_, sdc2->input_delay_internal_pin_map_); - swap(sdc1->input_delay_index_, sdc2->input_delay_index_); + std::swap(sdc1->input_delays_, sdc2->input_delays_); + std::swap(sdc1->input_delay_pin_map_, sdc2->input_delay_pin_map_); + std::swap(sdc1->input_delay_ref_pin_map_, sdc2->input_delay_ref_pin_map_); + std::swap(sdc1->input_delay_leaf_pin_map_, sdc2->input_delay_leaf_pin_map_); + std::swap(sdc1->input_delay_internal_pin_map_, sdc2->input_delay_internal_pin_map_); + std::swap(sdc1->input_delay_index_, sdc2->input_delay_index_); - swap(sdc1->output_delays_, sdc2->output_delays_); - swap(sdc1->output_delay_pin_map_, sdc2->output_delay_pin_map_); - swap(sdc1->output_delay_ref_pin_map_, sdc2->output_delay_ref_pin_map_); - swap(sdc1->output_delay_leaf_pin_map_, sdc2->output_delay_leaf_pin_map_); + std::swap(sdc1->output_delays_, sdc2->output_delays_); + std::swap(sdc1->output_delay_pin_map_, sdc2->output_delay_pin_map_); + std::swap(sdc1->output_delay_ref_pin_map_, sdc2->output_delay_ref_pin_map_); + std::swap(sdc1->output_delay_leaf_pin_map_, sdc2->output_delay_leaf_pin_map_); } //////////////////////////////////////////////////////////////// @@ -3374,8 +3372,8 @@ void Sdc::swapPortExtCaps(Sdc *sdc1, Sdc *sdc2) { - swap(sdc1->port_ext_cap_map_, sdc2->port_ext_cap_map_); - swap(sdc1->net_wire_cap_map_, sdc2->net_wire_cap_map_); + std::swap(sdc1->port_ext_cap_map_, sdc2->port_ext_cap_map_); + std::swap(sdc1->net_wire_cap_map_, sdc2->net_wire_cap_map_); } //////////////////////////////////////////////////////////////// diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc index e317a8a4..9ca25826 100644 --- a/sdc/WriteSdc.cc +++ b/sdc/WriteSdc.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include "ContainerHelpers.hh" #include "Zlib.hh" @@ -63,8 +64,6 @@ namespace sta { -using std::string; - typedef std::set ClockSenseSet; typedef std::vector ClockSenseSeq; @@ -1167,7 +1166,7 @@ WriteSdc::writeDisabledEdgeSense(Edge *edge) const { gzprintf(stream_, "set_disable_timing "); const char *sense = to_string(edge->sense()); - string filter; + std::string filter; stringPrint(filter, "sense == %s", sense); writeGetTimingArcs(edge, filter.c_str()); gzprintf(stream_, "\n"); diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc index 9e945130..59beb9f9 100644 --- a/sdf/SdfReader.cc +++ b/sdf/SdfReader.cc @@ -26,6 +26,7 @@ #include #include +#include #include "ContainerHelpers.hh" #include "Zlib.hh" @@ -45,9 +46,6 @@ namespace sta { -using std::string; -using std::to_string; - class SdfTriple { public: @@ -69,14 +67,14 @@ public: const std::string *port, const std::string *cond); ~SdfPortSpec(); - const string *port() const { return port_; } + const std::string *port() const { return port_; } const Transition *transition() const { return tr_; } - const string *cond() const { return cond_; } + const std::string *cond() const { return cond_; } private: const Transition *tr_; - const string *port_; - const string *cond_; // timing checks only + const std::string *port_; + const std::string *cond_; // timing checks only }; bool @@ -162,7 +160,7 @@ SdfReader::setDivider(char divider) void SdfReader::setTimescale(float multiplier, - const string *units) + const std::string *units) { if (multiplier == 1.0 || multiplier == 10.0 @@ -182,8 +180,8 @@ SdfReader::setTimescale(float multiplier, } void -SdfReader::interconnect(const string *from_pin_name, - const string *to_pin_name, +SdfReader::interconnect(const std::string *from_pin_name, + const std::string *to_pin_name, SdfTripleSeq *triples) { // Ignore non-incremental annotations in incremental only mode. @@ -225,7 +223,7 @@ SdfReader::interconnect(const string *from_pin_name, } void -SdfReader::port(const string *to_pin_name, +SdfReader::port(const std::string *to_pin_name, SdfTripleSeq *triples) { // Ignore non-incremental annotations in incremental only mode. @@ -296,13 +294,13 @@ SdfReader::setEdgeDelays(Edge *edge, } void -SdfReader::setCell(const string *cell_name) +SdfReader::setCell(const std::string *cell_name) { cell_name_ = cell_name; } void -SdfReader::setInstance(const string *instance_name) +SdfReader::setInstance(const std::string *instance_name) { if (instance_name) { if (*instance_name == "*") { @@ -344,13 +342,13 @@ SdfReader::cellFinish() void SdfReader::iopath(SdfPortSpec *from_edge, - const string *to_port_name, + const std::string *to_port_name, SdfTripleSeq *triples, - const string *cond, + const std::string *cond, bool condelse) { if (instance_) { - const string *from_port_name = from_edge->port(); + const std::string *from_port_name = from_edge->port(); Cell *cell = network_->cell(instance_); Port *from_port = findPort(cell, from_port_name); Port *to_port = findPort(cell, to_port_name); @@ -420,7 +418,7 @@ SdfReader::iopath(SdfPortSpec *from_edge, Port * SdfReader::findPort(const Cell *cell, - const string *port_name) + const std::string *port_name) { Port *port = network_->findPort(cell, port_name->c_str()); if (port == nullptr) @@ -437,8 +435,8 @@ SdfReader::timingCheck(const TimingRole *role, SdfTriple *triple) { if (instance_) { - const string *data_port_name = data_edge->port(); - const string *clk_port_name = clk_edge->port(); + const std::string *data_port_name = data_edge->port(); + const std::string *clk_port_name = clk_edge->port(); Cell *cell = network_->cell(instance_); Port *data_port = findPort(cell, data_port_name); Port *clk_port = findPort(cell, clk_port_name); @@ -515,8 +513,8 @@ SdfReader::annotateCheckEdges(Pin *data_pin, bool match_generic) { bool matched = false; - const string *cond_start = data_edge->cond(); - const string *cond_end = clk_edge->cond(); + const std::string *cond_start = data_edge->cond(); + const std::string *cond_end = clk_edge->cond(); // Timing check graph edges from clk to data. Vertex *to_vertex = graph_->pinLoadVertex(data_pin); // Fanin < fanout, so search for driver from load. @@ -557,7 +555,7 @@ SdfReader::timingCheckWidth(SdfPortSpec *edge, // Ignore non-incremental annotations in incremental only mode. if (!(is_incremental_only_ && !in_incremental_) && instance_) { - const string *port_name = edge->port(); + const std::string *port_name = edge->port(); Cell *cell = network_->cell(instance_); Port *port = findPort(cell, port_name); if (port) { @@ -604,8 +602,8 @@ SdfReader::timingCheckSetupHold1(SdfPortSpec *data_edge, const TimingRole *setup_role, const TimingRole *hold_role) { - const string *data_port_name = data_edge->port(); - const string *clk_port_name = clk_edge->port(); + const std::string *data_port_name = data_edge->port(); + const std::string *clk_port_name = clk_edge->port(); Cell *cell = network_->cell(instance_); Port *data_port = findPort(cell, data_port_name); Port *clk_port = findPort(cell, clk_port_name); @@ -626,7 +624,7 @@ SdfReader::timingCheckPeriod(SdfPortSpec *edge, // Ignore non-incremental annotations in incremental only mode. if (!(is_incremental_only_ && !in_incremental_) && instance_) { - const string *port_name = edge->port(); + const std::string *port_name = edge->port(); Cell *cell = network_->cell(instance_); Port *port = findPort(cell, port_name); if (port) { @@ -683,7 +681,7 @@ SdfReader::device(SdfTripleSeq *triples) } void -SdfReader::device(const string *to_port_name, +SdfReader::device(const std::string *to_port_name, SdfTripleSeq *triples) { // Ignore non-incremental annotations in incremental only mode. @@ -799,7 +797,7 @@ SdfReader::setEdgeArcDelaysCondUse(Edge *edge, } bool -SdfReader::condMatch(const string *sdf_cond, +SdfReader::condMatch(const std::string *sdf_cond, const std::string &lib_cond) { // If the sdf is not conditional it matches any library condition. @@ -828,24 +826,24 @@ SdfReader::condMatch(const string *sdf_cond, SdfPortSpec * SdfReader::makePortSpec(const Transition *tr, - const string *port, - const string *cond) + const std::string *port, + const std::string *cond) { return new SdfPortSpec(tr, port, cond); } SdfPortSpec * -SdfReader::makeCondPortSpec(const string *cond_port) +SdfReader::makeCondPortSpec(const std::string *cond_port) { // Search from end to find port name because condition may contain spaces. - string cond_port1(*cond_port); + std::string cond_port1(*cond_port); trimRight(cond_port1); auto port_idx = cond_port1.find_last_of(" "); if (port_idx != cond_port1.npos) { - string *port1 = new string(cond_port1.substr(port_idx + 1)); + std::string *port1 = new std::string(cond_port1.substr(port_idx + 1)); auto cond_end = cond_port1.find_last_not_of(" ", port_idx); if (cond_end != cond_port1.npos) { - string *cond1 = new string(cond_port1.substr(0, cond_end + 1)); + std::string *cond1 = new std::string(cond_port1.substr(0, cond_end + 1)); SdfPortSpec *port_spec = new SdfPortSpec(Transition::riseFall(), port1, cond1); @@ -913,13 +911,13 @@ SdfReader::setInIncremental(bool incr) in_incremental_ = incr; } -string * -SdfReader::unescaped(const string *token) +std::string * +SdfReader::unescaped(const std::string *token) { char path_escape = network_->pathEscape(); char path_divider = network_->pathDivider(); size_t token_length = token->size(); - string *unescaped = new string; + std::string *unescaped = new std::string; for (size_t i = 0; i < token_length; i++) { char ch = (*token)[i]; if (ch == escape_) { @@ -955,11 +953,11 @@ SdfReader::unescaped(const string *token) return unescaped; } -string * -SdfReader::makePath(const string *head, - const string *tail) +std::string * +SdfReader::makePath(const std::string *head, + const std::string *tail) { - string *path = new string(*head); + std::string *path = new std::string(*head); *path += network_->pathDivider(); *path += *tail; delete head; @@ -967,13 +965,13 @@ SdfReader::makePath(const string *head, return path; } -string * -SdfReader::makeBusName(string *base_name, +std::string * +SdfReader::makeBusName(std::string *base_name, int index) { - string *bus_name = unescaped(base_name); + std::string *bus_name = unescaped(base_name); *bus_name += '['; - *bus_name += to_string(index); + *bus_name += std::to_string(index); *bus_name += ']'; delete base_name; return bus_name; @@ -1006,10 +1004,10 @@ SdfReader::sdfError(int id, } Pin * -SdfReader::findPin(const string *name) +SdfReader::findPin(const std::string *name) { if (path_) { - string path_name(path_); + std::string path_name(path_); path_name += divider_; path_name += *name; Pin *pin = network_->findPin(path_name.c_str()); @@ -1020,9 +1018,9 @@ SdfReader::findPin(const string *name) } Instance * -SdfReader::findInstance(const string *name) +SdfReader::findInstance(const std::string *name) { - string inst_name; + std::string inst_name; if (path_) { inst_name = path_; inst_name += divider_; @@ -1039,8 +1037,8 @@ SdfReader::findInstance(const string *name) //////////////////////////////////////////////////////////////// SdfPortSpec::SdfPortSpec(const Transition *tr, - const string *port, - const string *cond) : + const std::string *port, + const std::string *cond) : tr_(tr), port_(port), cond_(cond) @@ -1084,7 +1082,7 @@ SdfTriple::hasValue() const //////////////////////////////////////////////////////////////// SdfScanner::SdfScanner(std::istream *stream, - const string &filename, + const std::string &filename, SdfReader *reader, Report *report) : yyFlexLexer(stream), diff --git a/sdf/SdfWriter.cc b/sdf/SdfWriter.cc index f0095017..f42d54a9 100644 --- a/sdf/SdfWriter.cc +++ b/sdf/SdfWriter.cc @@ -45,8 +45,6 @@ namespace sta { -using std::string; - class SdfWriter : public StaState { public: @@ -108,10 +106,10 @@ protected: void writeSdfTriple(float min, float max); void writeSdfDelay(double delay); - string sdfPortName(const Pin *pin); - string sdfPathName(const Pin *pin); - string sdfPathName(const Instance *inst); - string sdfName(const Instance *inst); + std::string sdfPortName(const Pin *pin); + std::string sdfPathName(const Pin *pin); + std::string sdfPathName(const Instance *inst); + std::string sdfName(const Instance *inst); private: char sdf_divider_; @@ -315,8 +313,8 @@ SdfWriter::writeInterconnectFromPin(Pin *drvr_pin) Edge *edge = edge_iter.next(); if (edge->isWire()) { Pin *load_pin = edge->to(graph_)->pin(); - string drvr_pin_name = sdfPathName(drvr_pin); - string load_pin_name = sdfPathName(load_pin); + std::string drvr_pin_name = sdfPathName(drvr_pin); + std::string load_pin_name = sdfPathName(load_pin); gzprintf(stream_, " (INTERCONNECT %s %s ", drvr_pin_name.c_str(), load_pin_name.c_str()); @@ -347,7 +345,7 @@ SdfWriter::writeInstHeader(const Instance *inst) { gzprintf(stream_, " (CELL\n"); gzprintf(stream_, " (CELLTYPE \"%s\")\n", network_->cellName(inst)); - string inst_name = sdfPathName(inst); + std::string inst_name = sdfPathName(inst); gzprintf(stream_, " (INSTANCE %s)\n", inst_name.c_str()); } @@ -392,8 +390,8 @@ SdfWriter::writeIopaths(const Instance *inst, gzprintf(stream_, " (COND %s\n", sdf_cond.c_str()); gzprintf(stream_, " "); } - string from_pin_name = sdfPortName(from_pin); - string to_pin_name = sdfPortName(to_pin); + std::string from_pin_name = sdfPortName(from_pin); + std::string to_pin_name = sdfPortName(to_pin); gzprintf(stream_, " (IOPATH %s %s ", from_pin_name.c_str(), to_pin_name.c_str()); @@ -661,7 +659,7 @@ SdfWriter::writeCheck(Edge *edge, if (!sdf_cond_start.empty()) gzprintf(stream_, "(COND %s ", sdf_cond_start.c_str()); - string to_pin_name = sdfPortName(to_pin); + std::string to_pin_name = sdfPortName(to_pin); if (use_data_edge) { gzprintf(stream_, "(%s %s)", sdfEdge(arc->toEdge()), @@ -678,7 +676,7 @@ SdfWriter::writeCheck(Edge *edge, if (!sdf_cond_end.empty()) gzprintf(stream_, "(COND %s ", sdf_cond_end.c_str()); - string from_pin_name = sdfPortName(from_pin); + std::string from_pin_name = sdfPortName(from_pin); if (use_clk_edge) gzprintf(stream_, "(%s %s)", sdfEdge(arc->fromEdge()), @@ -704,7 +702,7 @@ SdfWriter::writeWidthCheck(const Pin *pin, float min_width, float max_width) { - string pin_name = sdfPortName(pin); + std::string pin_name = sdfPortName(pin); gzprintf(stream_, " (WIDTH (%s %s) ", sdfEdge(hi_low->asTransition()), pin_name.c_str()); @@ -716,7 +714,7 @@ void SdfWriter::writePeriodCheck(const Pin *pin, float min_period) { - string pin_name = sdfPortName(pin); + std::string pin_name = sdfPortName(pin); gzprintf(stream_, " (PERIOD %s ", pin_name.c_str()); writeSdfTriple(min_period, min_period); gzprintf(stream_, ")\n"); @@ -734,16 +732,16 @@ SdfWriter::sdfEdge(const Transition *tr) //////////////////////////////////////////////////////////////// -string +std::string SdfWriter::sdfPathName(const Pin *pin) { Instance *inst = network_->instance(pin); if (network_->isTopInstance(inst)) return sdfPortName(pin); else { - string inst_path = sdfPathName(inst); - string port_name = sdfPortName(pin); - string sdf_name = inst_path; + std::string inst_path = sdfPathName(inst); + std::string port_name = sdfPortName(pin); + std::string sdf_name = inst_path; sdf_name += sdf_divider_; sdf_name += port_name; return sdf_name; @@ -751,15 +749,15 @@ SdfWriter::sdfPathName(const Pin *pin) } // Based on Network::pathName. -string +std::string SdfWriter::sdfPathName(const Instance *instance) { InstanceSeq inst_path; network_->path(instance, inst_path); - string path_name; + std::string path_name; while (!inst_path.empty()) { const Instance *inst = inst_path.back(); - string inst_name = sdfName(inst); + std::string inst_name = sdfName(inst); path_name += inst_name; inst_path.pop_back(); if (!inst_path.empty()) @@ -769,11 +767,11 @@ SdfWriter::sdfPathName(const Instance *instance) } // Escape for non-alpha numeric characters. -string +std::string SdfWriter::sdfName(const Instance *inst) { const char *name = network_->name(inst); - string sdf_name; + std::string sdf_name; const char *p = name; while (*p) { char ch = *p; @@ -789,12 +787,12 @@ SdfWriter::sdfName(const Instance *inst) return sdf_name; } -string +std::string SdfWriter::sdfPortName(const Pin *pin) { const char *name = network_->portName(pin); size_t name_length = strlen(name); - string sdf_name; + std::string sdf_name; constexpr char bus_brkt_left = '['; constexpr char bus_brkt_right = ']'; diff --git a/search/CheckTiming.cc b/search/CheckTiming.cc index 9c692fba..f05de24e 100644 --- a/search/CheckTiming.cc +++ b/search/CheckTiming.cc @@ -46,8 +46,6 @@ namespace sta { -using std::string; - CheckTiming::CheckTiming(StaState *sta) : StaState(sta), mode_(nullptr), @@ -202,7 +200,7 @@ CheckTiming::checkLoops() loop_count++; } if (loop_count > 0) { - string error_msg; + std::string error_msg; errorMsgSubst("Warning: There %is %d combinational loop%s in the design.", loop_count, error_msg); CheckError *error = new CheckError; @@ -362,7 +360,7 @@ CheckTiming::pushPinErrors(const char *msg, { if (!pins.empty()) { CheckError *error = new CheckError; - string error_msg; + std::string error_msg; errorMsgSubst(msg, pins.size(), error_msg); // Copy the error strings because the error deletes them when it // is deleted. @@ -384,7 +382,7 @@ CheckTiming::pushClkErrors(const char *msg, { if (!clks.empty()) { CheckError *error = new CheckError; - string error_msg; + std::string error_msg; errorMsgSubst(msg, clks.size(), error_msg); // Copy the error strings because the error deletes them when it // is deleted. @@ -404,7 +402,7 @@ CheckTiming::pushClkErrors(const char *msg, void CheckTiming::errorMsgSubst(const char *msg, int obj_count, - string &error_msg) + std::string &error_msg) { for (const char *s = msg; *s; s++) { char ch = *s; diff --git a/search/ClkSkew.cc b/search/ClkSkew.cc index 9a34fe5e..09cdf204 100644 --- a/search/ClkSkew.cc +++ b/search/ClkSkew.cc @@ -49,8 +49,6 @@ namespace sta { -using std::abs; - ClkSkews::ClkSkews(StaState *sta) : StaState(sta), include_internal_latency_(true), @@ -148,7 +146,7 @@ ClkSkews::findWorstClkSkew(const SceneSeq &scenes, float worst_skew = 0.0; for (const auto& [clk, clk_skews] : skews_) { float skew = clk_skews[setup_hold->index()].skew(); - if (abs(skew) > abs(worst_skew)) + if (std::abs(skew) > std::abs(worst_skew)) worst_skew = skew; } return worst_skew; @@ -210,8 +208,8 @@ ClkSkews::findClkSkew(ConstClockSeq &clks, ClkSkew &partial_skew_val = partial_skew[setup_hold_idx]; float partial_skew1 = partial_skew_val.skew(); float final_skew1 = final_skew.skew(); - if (abs(partial_skew1) > abs(final_skew1) - || (fuzzyEqual(abs(partial_skew1), abs(final_skew1)) + if (std::abs(partial_skew1) > std::abs(final_skew1) + || (fuzzyEqual(std::abs(partial_skew1), std::abs(final_skew1)) // Break ties based on source/target path names. && ClkSkew::srcTgtPathNameLess(partial_skew_val, final_skew, this))) final_skew = partial_skew_val; @@ -325,7 +323,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex, delayAsString(probe.crpr(this), this), time_unit->asString(probe.skew())); if (clk_skew.srcPath() == nullptr - || abs(probe.skew()) > abs(clk_skew.skew())) + || std::abs(probe.skew()) > std::abs(clk_skew.skew())) clk_skew = probe; } } diff --git a/search/Crpr.cc b/search/Crpr.cc index c2226541..e782aef0 100644 --- a/search/Crpr.cc +++ b/search/Crpr.cc @@ -24,8 +24,8 @@ #include "Crpr.hh" +#include #include // abs -#include #include "Debug.hh" #include "Network.hh" @@ -44,9 +44,6 @@ namespace sta { -using std::min; -using std::abs; - CheckCrpr::CheckCrpr(StaState *sta) : StaState(sta) { @@ -60,11 +57,10 @@ CheckCrpr::maxCrpr(const ClkInfo *clk_info) const Path *crpr_clk_path = clk_info->crprClkPath(this); if (crpr_clk_path) { Arrival other_arrival = otherMinMaxArrival(crpr_clk_path); - float crpr_diff = abs(delayAsFloat(crpr_clk_path->arrival(), - EarlyLate::late(), - this) - - delayAsFloat(other_arrival, EarlyLate::early(), - this)); + float crpr_diff = std::abs(delayAsFloat(crpr_clk_path->arrival(), + EarlyLate::late(), this) + - delayAsFloat(other_arrival, EarlyLate::early(), + this)); return crpr_diff; } return 0.0F; @@ -284,7 +280,7 @@ CheckCrpr::findCrpr1(const Path *src_clk_path, Arrival tgt_arrival = tgt_clk_path->arrival(); float src_clk_time = src_clk_path->clkEdge(this)->time(); float tgt_clk_time = tgt_clk_path->clkEdge(this)->time(); - float crpr_mean = abs(delayAsFloat(src_arrival) - src_clk_time + float crpr_mean = std::abs(delayAsFloat(src_arrival) - src_clk_time - (delayAsFloat(tgt_arrival) - tgt_clk_time)); // Remove the sigma from both source and target path arrivals. float crpr_sigma2 = delaySigma2(src_arrival, src_el) @@ -300,7 +296,7 @@ CheckCrpr::findCrpr1(const Path *src_clk_path, delayAsString(src_delta, this)); debugPrint(debug_, "crpr", 2, " tgt delta %s", delayAsString(tgt_delta, this)); - float common_delay = min(src_delta, tgt_delta); + float common_delay = std::min(src_delta, tgt_delta); debugPrint(debug_, "crpr", 2, " %s delta %s", network_->pathName(src_clk_path->pin(this)), delayAsString(common_delay, this)); @@ -312,7 +308,7 @@ float CheckCrpr::crprArrivalDiff(const Path *path) { Arrival other_arrival = otherMinMaxArrival(path); - float crpr_diff = abs(delayAsFloat(path->arrival()) + float crpr_diff = std::abs(delayAsFloat(path->arrival()) - delayAsFloat(other_arrival)); return crpr_diff; } diff --git a/search/Genclks.cc b/search/Genclks.cc index 66b8cd14..bbb26621 100644 --- a/search/Genclks.cc +++ b/search/Genclks.cc @@ -24,6 +24,8 @@ #include "Genclks.hh" +#include + #include "ContainerHelpers.hh" #include "Stats.hh" #include "Debug.hh" @@ -47,8 +49,6 @@ namespace sta { -using std::max; - class GenclkInfo { public: @@ -151,7 +151,7 @@ Genclks::clkPinMaxLevel(const Clock *clk) const Level max_level = 0; for (const Pin *pin : clk->leafPins()) { Vertex *vertex = srcPath(pin); - max_level = max(max_level, vertex->level()); + max_level = std::max(max_level, vertex->level()); } return max_level; } diff --git a/search/Levelize.cc b/search/Levelize.cc index df6c983d..d04891bf 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -25,6 +25,7 @@ #include "Levelize.hh" #include +#include #include #include "ContainerHelpers.hh" @@ -43,8 +44,6 @@ namespace sta { -using std::max; - Levelize::Levelize(StaState *sta) : StaState(sta), levelized_(false), @@ -500,16 +499,16 @@ Levelize::assignLevels(VertexSeq &topo_sorted) Edge *edge = edge_iter.next(); Vertex *to_vertex = edge->to(graph_); if (searchThru(edge)) - setLevel(to_vertex, max(to_vertex->level(), - vertex->level() + level_space_)); + setLevel(to_vertex, std::max(to_vertex->level(), + vertex->level() + level_space_)); } // Levelize bidirect driver as if it was a fanout of the bidirect load. const Pin *pin = vertex->pin(); if (graph_delay_calc_->bidirectDrvrSlewFromLoad(pin) && !vertex->isBidirectDriver()) { Vertex *to_vertex = graph_->pinDrvrVertex(pin); - setLevel(to_vertex, max(to_vertex->level(), - vertex->level() + level_space_)); + setLevel(to_vertex, std::max(to_vertex->level(), + vertex->level() + level_space_)); } } } @@ -541,7 +540,7 @@ Levelize::setLevel(Vertex *vertex, vertex->to_string(this).c_str(), level); vertex->setLevel(level); - max_level_ = max(level, max_level_); + max_level_ = std::max(level, max_level_); if (level >= Graph::vertex_level_max) report_->critical(616, "maximum logic level exceeded"); } @@ -676,7 +675,7 @@ Levelize::setLevelIncr(Vertex *vertex, observer_->levelChangedBefore(vertex); vertex->setLevel(level); } - max_level_ = max(level, max_level_); + max_level_ = std::max(level, max_level_); if (level >= Graph::vertex_level_max) criticalError(618, "maximum logic level exceeded"); } diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index 1c605a26..d709f477 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -26,6 +26,7 @@ #include "MakeTimingModelPvt.hh" #include +#include #include #include "Debug.hh" @@ -51,11 +52,6 @@ namespace sta { -using std::string; -using std::min; -using std::max; -using std::make_shared; - LibertyLibrary * makeTimingModel(const char *lib_name, const char *cell_name, @@ -305,7 +301,7 @@ MakeEndTimingArcs::visit(PathEnd *path_end) margins.value(input_rf_, min_max, max_margin, max_exists); // Always max margin, even for min/hold checks. margins.setValue(input_rf_, min_max, - max_exists ? max(max_margin, delay1) : delay1); + max_exists ? std::max(max_margin, delay1) : delay1); } } @@ -606,7 +602,7 @@ MakeTimingModel::makeScalarCheckModel(float value, ScaleFactorType scale_factor_type, const RiseFall *rf) { - TablePtr table = make_shared
(value); + TablePtr table = std::make_shared
(value); TableTemplate *tbl_template = library_->findTableTemplate("scalar", TableTemplateType::delay); TableModel *table_model = new TableModel(table, tbl_template, @@ -620,8 +616,8 @@ MakeTimingModel::makeGateModelScalar(Delay delay, Slew slew, const RiseFall *rf) { - TablePtr delay_table = make_shared
(delayAsFloat(delay)); - TablePtr slew_table = make_shared
(delayAsFloat(slew)); + TablePtr delay_table = std::make_shared
(delayAsFloat(delay)); + TablePtr slew_table = std::make_shared
(delayAsFloat(slew)); TableTemplate *tbl_template = library_->findTableTemplate("scalar", TableTemplateType::delay); TableModel *delay_model = new TableModel(delay_table, tbl_template, @@ -636,7 +632,7 @@ TimingModel * MakeTimingModel::makeGateModelScalar(Delay delay, const RiseFall *rf) { - TablePtr delay_table = make_shared
(delayAsFloat(delay)); + TablePtr delay_table = std::make_shared
(delayAsFloat(delay)); TableTemplate *tbl_template = library_->findTableTemplate("scalar", TableTemplateType::delay); TableModel *delay_model = new TableModel(delay_table, tbl_template, @@ -708,8 +704,8 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin, std::make_shared(TableAxisVariable::total_output_net_capacitance, std::move(axis_values)); - TablePtr delay_table = make_shared
(load_values, load_axis); - TablePtr slew_table = make_shared
(slew_values, load_axis); + TablePtr delay_table = std::make_shared
(load_values, load_axis); + TablePtr slew_table = std::make_shared
(slew_values, load_axis); TableTemplate *model_template = ensureTableTemplate(drvr_template, load_axis); @@ -738,7 +734,7 @@ MakeTimingModel::ensureTableTemplate(const TableTemplate *drvr_template, { TableTemplate *model_template = findKey(template_map_, drvr_template); if (model_template == nullptr) { - string template_name = "template_"; + std::string template_name = "template_"; template_name += std::to_string(tbl_template_index_++); model_template = library_->makeTableTemplate(template_name, diff --git a/search/Property.cc b/search/Property.cc index 07eddc0a..ba12610a 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -24,6 +24,9 @@ #include "Property.hh" +#include +#include + #include "StringUtil.hh" #include "MinMax.hh" #include "Transition.hh" @@ -43,22 +46,19 @@ namespace sta { -using std::string; -using std::max; - class PropertyUnknown : public Exception { public: PropertyUnknown(const char *type, const char *property); PropertyUnknown(const char *type, - const string property); + const std::string property); virtual ~PropertyUnknown() {} virtual const char *what() const noexcept; private: const char *type_; - const string property_; + const std::string property_; }; PropertyUnknown::PropertyUnknown(const char *type, @@ -70,7 +70,7 @@ PropertyUnknown::PropertyUnknown(const char *type, } PropertyUnknown::PropertyUnknown(const char *type, - const string property) : + const std::string property) : Exception(), type_(type), property_(property) @@ -556,7 +556,7 @@ PropertyValue::operator=(PropertyValue &&value) noexcept return *this; } -string +std::string PropertyValue::to_string(const Network *network) const { switch (type_) { @@ -683,9 +683,9 @@ Properties::getProperty(const Cell *cell, return PropertyValue(network->name(cell)); else if (property == "full_name") { Library *lib = network->library(cell); - string lib_name = network->name(lib); - string cell_name = network->name(cell); - string full_name = lib_name + network->pathDivider() + cell_name; + std::string lib_name = network->name(lib); + std::string cell_name = network->name(cell); + std::string full_name = lib_name + network->pathDivider() + cell_name; return PropertyValue(full_name); } else if (property == "library") @@ -714,9 +714,9 @@ Properties::getProperty(const LibertyCell *cell, else if (property == "full_name") { Network *network = sta_->cmdNetwork(); LibertyLibrary *lib = cell->libertyLibrary(); - string lib_name = lib->name(); - string cell_name = cell->name(); - string full_name = lib_name + network->pathDivider() + cell_name; + std::string lib_name = lib->name(); + std::string cell_name = cell->name(); + std::string full_name = lib_name + network->pathDivider() + cell_name; return PropertyValue(full_name); } else if (property == "filename") @@ -1099,7 +1099,7 @@ Properties::getProperty(Edge *edge, const std::string &property) { if (property == "full_name") { - string full_name = edge->to_string(sta_); + std::string full_name = edge->to_string(sta_); return PropertyValue(full_name); } if (property == "delay_min_fall") @@ -1159,7 +1159,7 @@ Properties::getProperty(TimingArcSet *arc_set, const char *from = arc_set->from()->name(); const char *to = arc_set->to()->name(); const char *cell_name = arc_set->libertyCell()->name(); - string name; + std::string name; stringPrint(name, "%s %s -> %s", cell_name, from, to); return PropertyValue(name); } diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 9122a805..ad9b9f11 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -23,6 +23,7 @@ // This notice may not be removed or altered from any source distribution. #include // reverse +#include #include "ReportPath.hh" @@ -63,8 +64,6 @@ namespace sta { -using std::string; - static void hierPinsAbove(const Net *net, const Network *network, @@ -373,7 +372,7 @@ ReportPath::reportPathEndHeader() const void ReportPath::reportPathEndFooter() const { - string header; + std::string header; switch (format_) { case ReportPathFormat::full: case ReportPathFormat::full_clock: @@ -474,7 +473,7 @@ ReportPath::reportFull(const PathEndCheck *end) const reportSlack(end); } -string +std::string ReportPath::checkRoleString(const PathEnd *end) const { return stdstrPrint("library %s time", @@ -486,7 +485,7 @@ ReportPath::reportEndpoint(const PathEndCheck *end) const { Instance *inst = network_->instance(end->vertex(this)->pin()); const char *inst_name = cmd_network_->pathName(inst); - string clk_name = tgtClkName(end); + std::string clk_name = tgtClkName(end); const char *rise_fall = asRisingFalling(end->targetClkEndTrans(this)); const TimingRole *check_role = end->checkRole(this); const TimingRole *check_generic_role = check_role->genericRole(); @@ -593,7 +592,7 @@ ReportPath::reportEndpoint(const PathEndLatchCheck *end) const { Instance *inst = network_->instance(end->vertex(this)->pin()); const char *inst_name = cmd_network_->pathName(inst); - string clk_name = tgtClkName(end); + std::string clk_name = tgtClkName(end); const char *reg_desc = latchDesc(end); auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str()); reportEndpoint(inst_name, reason); @@ -625,7 +624,7 @@ ReportPath::reportBorrowing(const PathEndLatchCheck *end, if (borrow_limit_exists) reportLineTotal("user max time borrow", max_borrow, early_late); else { - string tgt_clk_name = tgtClkName(end); + std::string tgt_clk_name = tgtClkName(end); Arrival tgt_clk_width = end->targetClkWidth(this); const Path *tgt_clk_path = end->targetClkPath(); if (tgt_clk_path->clkInfo(search_)->isPropagated()) { @@ -691,7 +690,7 @@ ReportPath::reportEndpoint(const PathEndPathDelay *end) const else { Instance *inst = network_->instance(end->vertex(this)->pin()); const char *inst_name = cmd_network_->pathName(inst); - string clk_name = tgtClkName(end); + std::string clk_name = tgtClkName(end); const char *reg_desc = clkRegLatchDesc(end); auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str()); reportEndpoint(inst_name, reason); @@ -723,7 +722,7 @@ ReportPath::reportFull(const PathEndPathDelay *end) const if (min_max == MinMax::max()) margin = -margin; - string delay_msg = min_max->to_string() + "_delay"; + std::string delay_msg = min_max->to_string() + "_delay"; float delay = path_delay->delay(); reportLine(delay_msg.c_str(), delay, delay, early_late); if (!path_delay->ignoreClkLatency()) { @@ -821,7 +820,7 @@ ReportPath::reportEndpointOutputDelay(const PathEndClkConstrained *end) const if (network_->isTopLevelPort(pin)) { // Pin direction is "output" even for bidirects. if (tgt_clk) { - string clk_name = tgtClkName(end); + std::string clk_name = tgtClkName(end); auto reason = stdstrPrint("output port clocked by %s", clk_name.c_str()); reportEndpoint(pin_name, reason); } @@ -830,7 +829,7 @@ ReportPath::reportEndpointOutputDelay(const PathEndClkConstrained *end) const } else { if (tgt_clk) { - string clk_name = tgtClkName(end); + std::string clk_name = tgtClkName(end); auto reason = stdstrPrint("internal path endpoint clocked by %s", clk_name.c_str()); @@ -875,7 +874,7 @@ ReportPath::reportEndpoint(const PathEndGatedClock *end) const { Instance *inst = network_->instance(end->vertex(this)->pin()); const char *inst_name = cmd_network_->pathName(inst); - string clk_name = tgtClkName(end); + std::string clk_name = tgtClkName(end); const RiseFall *clk_end_rf = end->targetClkEndTrans(this); const RiseFall *clk_rf = (end->minMax(this) == MinMax::max()) ? clk_end_rf : clk_end_rf->opposite(); @@ -955,7 +954,7 @@ ReportPath::reportEndpoint(const PathEndDataCheck *end) const void ReportPath::reportEndHeader() const { - string line; + std::string line; // Line one. reportDescription("", line); line += ' '; @@ -981,8 +980,8 @@ ReportPath::reportEndHeader() const void ReportPath::reportEndLine(const PathEnd *end) const { - string line; - string endpoint = pathEndpoint(end); + std::string line; + std::string endpoint = pathEndpoint(end); reportDescription(endpoint.c_str(), line); const EarlyLate *early_late = end->pathEarlyLate(this); reportSpaceFieldDelay(end->requiredTimeOffset(this), early_late, line); @@ -996,7 +995,7 @@ ReportPath::reportEndLine(const PathEnd *end) const void ReportPath::reportSummaryHeader() const { - string line; + std::string line; reportDescription("Startpoint", line); line += ' '; reportDescription("Endpoint", line); @@ -1010,7 +1009,7 @@ ReportPath::reportSummaryHeader() const void ReportPath::reportSummaryLine(const PathEnd *end) const { - string line; + std::string line; PathExpanded expanded(end->path(), this); const EarlyLate *early_late = end->pathEarlyLate(this); auto startpoint = pathStartpoint(end, expanded); @@ -1025,7 +1024,7 @@ ReportPath::reportSummaryLine(const PathEnd *end) const report_->reportLineString(line); } -string +std::string ReportPath::pathStartpoint(const PathEnd *end, const PathExpanded &expanded) const { @@ -1043,7 +1042,7 @@ ReportPath::pathStartpoint(const PathEnd *end, } } -string +std::string ReportPath::pathEndpoint(const PathEnd *end) const { Pin *pin = end->vertex(this)->pin(); @@ -1078,7 +1077,7 @@ void ReportPath::reportJson(const PathEnd *end, bool last) const { - string result; + std::string result; result += "{\n"; stringAppend(result, " \"type\": \"%s\",\n", end->typeName()); stringAppend(result, " \"path_group\": \"%s\",\n", @@ -1149,7 +1148,7 @@ ReportPath::reportJson(const PathEnd *end, void ReportPath::reportJson(const Path *path) const { - string result; + std::string result; result += "{\n"; reportJson(path, "path", 0, false, result); result += "}\n"; @@ -1161,7 +1160,7 @@ ReportPath::reportJson(const Path *path, const char *path_name, int indent, bool trailing_comma, - string &result) const + std::string &result) const { PathExpanded expanded(path, this); reportJson(expanded, path_name, indent, trailing_comma, result); @@ -1172,7 +1171,7 @@ ReportPath::reportJson(const PathExpanded &expanded, const char *path_name, int indent, bool trailing_comma, - string &result) const + std::string &result) const { stringAppend(result, "%*s\"%s\": [\n", indent, "", path_name); for (size_t i = expanded.startIndex(); i < expanded.size(); i++) { @@ -1256,7 +1255,7 @@ ReportPath::reportJson(const PathExpanded &expanded, void ReportPath::reportSlackOnlyHeader() const { - string line; + std::string line; reportDescription("Group", line); line += ' '; reportField("Slack", field_total_, line); @@ -1268,7 +1267,7 @@ ReportPath::reportSlackOnlyHeader() const void ReportPath::reportSlackOnly(const PathEnd *end) const { - string line; + std::string line; const EarlyLate *early_late = end->pathEarlyLate(this); reportDescription(end->pathGroup()->name(), line); if (end->isUnconstrained()) @@ -1318,7 +1317,7 @@ ReportPath::reportMpwChecks(const MinPulseWidthCheckSeq &checks, void ReportPath::reportMpwHeaderShort() const { - string line; + std::string line; reportDescription("", line); line += ' '; reportField("Required", field_total_, line); @@ -1342,7 +1341,7 @@ ReportPath::reportMpwHeaderShort() const void ReportPath::reportShort(const MinPulseWidthCheck &check) const { - string line; + std::string line; const char *pin_name = cmd_network_->pathName(check.pin(this)); const char *hi_low = mpwCheckHiLow(check); auto what = stdstrPrint("%s (%s)", pin_name, hi_low); @@ -1356,7 +1355,7 @@ ReportPath::reportShort(const MinPulseWidthCheck &check) const void ReportPath::reportVerbose(const MinPulseWidthCheck &check) const { - string line; + std::string line; const char *pin_name = cmd_network_->pathName(check.pin(this)); line += "Pin: "; line += pin_name; @@ -1462,7 +1461,7 @@ ReportPath::reportChecks(const MinPeriodCheckSeq &checks, void ReportPath::reportPeriodHeaderShort() const { - string line; + std::string line; reportDescription("", line); line += ' '; reportField("", field_total_, line); @@ -1488,7 +1487,7 @@ ReportPath::reportPeriodHeaderShort() const void ReportPath::reportShort(const MinPeriodCheck &check) const { - string line; + std::string line; const char *pin_name = cmd_network_->pathName(check.pin()); reportDescription(pin_name, line); reportSpaceFieldDelay(check.period(), EarlyLate::early(), line); @@ -1500,7 +1499,7 @@ ReportPath::reportShort(const MinPeriodCheck &check) const void ReportPath::reportVerbose(const MinPeriodCheck &check) const { - string line; + std::string line; const char *pin_name = cmd_network_->pathName(check.pin()); line += "Pin: "; line += pin_name; @@ -1536,7 +1535,7 @@ ReportPath::reportChecks(const MaxSkewCheckSeq &checks, void ReportPath::reportMaxSkewHeaderShort() const { - string line; + std::string line; reportDescription("", line); line += ' '; reportField("Required", field_total_, line); @@ -1562,7 +1561,7 @@ ReportPath::reportMaxSkewHeaderShort() const void ReportPath::reportShort(const MaxSkewCheck &check) const { - string line; + std::string line; Pin *clk_pin = check.clkPin(this); const char *clk_pin_name = network_->pathName(clk_pin); TimingArc *check_arc = check.checkArc(); @@ -1581,7 +1580,7 @@ ReportPath::reportShort(const MaxSkewCheck &check) const void ReportPath::reportVerbose(const MaxSkewCheck &check) const { - string line; + std::string line; const char *clk_pin_name = cmd_network_->pathName(check.clkPin(this)); line += "Constrained Pin: "; line += clk_pin_name; @@ -1617,7 +1616,7 @@ ReportPath::reportSkewClkPath(const char *arrival_msg, const EarlyLate *early_late = clk_path->minMax(this); const RiseFall *clk_rf = clk_edge->transition(); const RiseFall *clk_end_rf = clk_path->transition(this); - string clk_name = clkName(clk, clk_end_rf != clk_rf); + std::string clk_name = clkName(clk, clk_end_rf != clk_rf); float clk_time = clk_edge->time(); const Arrival &clk_arrival = search_->clkPathArrival(clk_path); Arrival clk_delay = clk_arrival - clk_time; @@ -1656,7 +1655,7 @@ ReportPath::reportSkewClkPath(const char *arrival_msg, void ReportPath::reportLimitShortHeader(const ReportField *field) const { - string line; + std::string line; reportDescription("Pin", line); line += ' '; reportField("Limit", field, line); @@ -1676,7 +1675,7 @@ ReportPath::reportLimitShort(const ReportField *field, float limit, float slack) const { - string line; + std::string line; const char *pin_name = cmd_network_->pathName(pin); reportDescription(pin_name, line); line += ' '; @@ -1701,7 +1700,7 @@ ReportPath::reportLimitVerbose(const ReportField *field, const Scene *scene, const MinMax *min_max) const { - string line; + std::string line; line += "Pin "; line += cmd_network_->pathName(pin); line += ' '; @@ -1781,7 +1780,7 @@ ReportPath::reportStartpoint(const PathEnd *end, const Path *clk_path = expanded.clkPath(); bool clk_inverted = clk_path && clk_rf != clk_path->transition(this); - string clk_name = clkName(clk, clk_inverted); + std::string clk_name = clkName(clk, clk_inverted); const char *reg_desc = edgeRegLatchDesc(prev_edge, prev_arc); auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str()); reportStartpoint(inst_name, reason); @@ -1829,7 +1828,7 @@ ReportPath::pathFromClkPin(const Path *path, void ReportPath::reportStartpoint(const char *start, - const string reason) const + const std::string reason) const { reportStartEndPoint(start, reason, "Startpoint"); } @@ -1878,17 +1877,17 @@ ReportPath::reportUnclockedEndpoint(const PathEnd *end, void ReportPath::reportEndpoint(const char *end, - const string reason) const + const std::string reason) const { reportStartEndPoint(end, reason, "Endpoint"); } void ReportPath::reportStartEndPoint(const char *pt, - string reason, + std::string reason, const char *key) const { - string line; + std::string line; // Account for punctuation in the line. int line_len = strlen(key) + 2 + strlen(pt) + 2 + reason.size() + 1; if (!no_split_ @@ -1921,7 +1920,7 @@ ReportPath::reportStartEndPoint(const char *pt, void ReportPath::reportGroup(const PathEnd *end) const { - string line; + std::string line; line = "Path Group: "; PathGroup *group = end->pathGroup(); line += group ? group->name() : "(none)"; @@ -1946,13 +1945,13 @@ ReportPath::reportGroup(const PathEnd *end) const //////////////////////////////////////////////////////////////// -string +std::string ReportPath::checkRoleReason(const PathEnd *end) const { return stdstrPrint("%s time", end->checkRole(this)->to_string().c_str()); } -string +std::string ReportPath::tgtClkName(const PathEnd *end) const { const ClockEdge *tgt_clk_edge = end->targetClkEdge(this); @@ -1962,11 +1961,11 @@ ReportPath::tgtClkName(const PathEnd *end) const return clkName(tgt_clk, clk_end_rf != clk_rf); } -string +std::string ReportPath::clkName(const Clock *clk, bool inverted) const { - string name = clk->name(); + std::string name = clk->name(); if (inverted) name += '\''; return name; @@ -2088,7 +2087,7 @@ ReportPath::reportSrcClkAndPath(const Path *path, } } } - string clk_name = clkName(clk, clk_rf != clk_end_rf); + std::string clk_name = clkName(clk, clk_rf != clk_end_rf); bool clk_used_as_data = pathFromClkPin(expanded); bool is_prop = isPropagated(path); @@ -2185,7 +2184,7 @@ ReportPath::reportTgtClk(const PathEnd *end, Clock *clk = clk_edge->clock(); const RiseFall *clk_rf = clk_edge->transition(); const RiseFall *clk_end_rf = end->targetClkEndTrans(this); - string clk_name = clkName(clk, clk_end_rf != clk_rf); + std::string clk_name = clkName(clk, clk_end_rf != clk_rf); float clk_time = prev_time + end->targetClkTime(this) + end->targetClkMcpAdjustment(this) @@ -2439,7 +2438,7 @@ ReportPath::reportPathLine(const Path *path, { Vertex *vertex = path->vertex(this); Pin *pin = vertex->pin(); - const string what = descriptionField(vertex); + const std::string what = descriptionField(vertex); const RiseFall *rf = path->transition(this); bool is_driver = network_->isDriver(pin); const EarlyLate *early_late = path->minMax(this); @@ -2449,7 +2448,7 @@ ReportPath::reportPathLine(const Path *path, Slew slew = graph_->slew(vertex, rf, slew_index); float cap = field_blank_; Instance *inst = network_->instance(pin); - string src_attr = ""; + std::string src_attr = ""; if (inst) src_attr = network_->getAttribute(inst, "src"); // Don't show capacitance field for input pins. @@ -2462,7 +2461,7 @@ ReportPath::reportPathLine(const Path *path, void ReportPath::reportRequired(const PathEnd *end, - string margin_msg) const + std::string margin_msg) const { Required req_time = end->requiredTimeOffset(this); const EarlyLate *early_late = end->clkEarlyLate(this); @@ -2503,7 +2502,7 @@ ReportPath::reportSlack(Slack slack) const void ReportPath::reportSpaceSlack(const PathEnd *end, - string &result) const + std::string &result) const { Slack slack = end->slack(this); reportSpaceSlack(slack, result); @@ -2511,7 +2510,7 @@ ReportPath::reportSpaceSlack(const PathEnd *end, void ReportPath::reportSpaceSlack(Slack slack, - string &result) const + std::string &result) const { const EarlyLate *early_late = EarlyLate::early(); reportSpaceFieldDelay(slack, early_late, result); @@ -2718,7 +2717,7 @@ ReportPath::reportPath6(const Path *path, bool is_clk_start = path1->vertex(this) == clk_start; bool is_clk = path1->isClock(search_); Instance *inst = network_->instance(pin); - string src_attr = ""; + std::string src_attr = ""; if (inst) src_attr = network_->getAttribute(inst, "src"); // Always show the search start point (register clk pin). @@ -2804,13 +2803,13 @@ ReportPath::reportPath6(const Path *path, cap = graph_delay_calc_->loadCap(pin, rf, scene, min_max); if (field_fanout_->enabled()) fanout = drvrFanout(vertex, scene, min_max); - const string what = descriptionField(vertex); + const std::string what = descriptionField(vertex); reportLine(what.c_str(), cap, slew, fanout, incr, time, false, min_max, rf, src_attr, line_case); if (report_net_) { - const string what2 = descriptionNet(pin); + const std::string what2 = descriptionNet(pin); reportLine(what2.c_str(), field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, false, min_max, nullptr, src_attr, ""); @@ -2823,7 +2822,7 @@ ReportPath::reportPath6(const Path *path, || (i == 0) || (i == path_last_index) || is_clk_start) { - const string what = descriptionField(vertex); + const std::string what = descriptionField(vertex); reportLine(what.c_str(), field_blank_, slew, field_blank_, incr, time, false, min_max, rf, src_attr, line_case); @@ -2843,7 +2842,7 @@ ReportPath::reportHierPinsThru(const Path *path) const const Edge *prev_edge = path->prevEdge(this); if (prev_edge && prev_edge->isWire()) { for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) { - const string what = descriptionField(hpin); + const std::string what = descriptionField(hpin); reportLine(what.c_str(), field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, false, path->minMax(this), nullptr, "", ""); @@ -2874,13 +2873,13 @@ ReportPath::nextArcAnnotated(const Path *next_path, return graph_->arcDelayAnnotated(edge, arc, ap_index); } -string +std::string ReportPath::descriptionField(const Vertex *vertex) const { return descriptionField(vertex->pin()); } -string +std::string ReportPath::descriptionField(const Pin *pin) const { const char *pin_name = cmd_network_->pathName(pin); @@ -2906,7 +2905,7 @@ ReportPath::descriptionField(const Pin *pin) const return stdstrPrint("%s (%s)", pin_name, name2); } -string +std::string ReportPath::descriptionNet(const Pin *pin) const { if (network_->isTopLevelPort(pin)) { @@ -3028,7 +3027,7 @@ ReportPath::pathInputDelayRefPath(const Path *path, void ReportPath::reportPathHeader() const { - string line; + std::string line; bool first_field = true; for (const ReportField *field : fields_) { if (field->enabled()) { @@ -3125,10 +3124,10 @@ ReportPath::reportLine(const char *what, bool total_with_minus, const EarlyLate *early_late, const RiseFall *rf, - string src_attr, + std::string src_attr, const char *line_case) const { - string line; + std::string line; size_t field_index = 0; bool first_field = true; for (const ReportField *field : fields_) { @@ -3180,7 +3179,7 @@ ReportPath::reportLine(const char *what, field_index++; } // Trim trailing spaces and report the line. - string line_stdstr = line; + std::string line_stdstr = line; trimRight(line_stdstr); report_->reportLineString(line_stdstr.c_str()); } @@ -3211,7 +3210,7 @@ ReportPath::reportLineTotal1(const char *what, bool incr_with_minus, const EarlyLate *early_late) const { - string line; + std::string line; reportDescription(what, line); line += ' '; if (incr_with_minus) @@ -3231,7 +3230,7 @@ ReportPath::reportDashLineTotal() const void ReportPath::reportDescription(const char *what, - string &line) const + std::string &line) const { reportDescription(what, false, false, line); } @@ -3240,7 +3239,7 @@ void ReportPath::reportDescription(const char *what, bool first_field, bool last_field, - string &line) const + std::string &line) const { line += what; int length = strlen(what); @@ -3260,7 +3259,7 @@ ReportPath::reportDescription(const char *what, void ReportPath::reportFieldTime(float value, ReportField *field, - string &line) const + std::string &line) const { if (delayAsFloat(value) == field_blank_) reportFieldBlank(field, line); @@ -3275,7 +3274,7 @@ ReportPath::reportFieldTime(float value, void ReportPath::reportSpaceFieldTime(float value, - string &line) const + std::string &line) const { line += ' '; reportFieldTime(value, field_total_, line); @@ -3284,7 +3283,7 @@ ReportPath::reportSpaceFieldTime(float value, void ReportPath::reportSpaceFieldDelay(Delay value, const EarlyLate *early_late, - string &line) const + std::string &line) const { line += ' '; reportTotalDelay(value, early_late, line); @@ -3293,7 +3292,7 @@ ReportPath::reportSpaceFieldDelay(Delay value, void ReportPath::reportTotalDelay(Delay value, const EarlyLate *early_late, - string &line) const + std::string &line) const { const char *str = delayAsString(value, early_late, this, digits_); if (stringEq(str, minus_zero_)) @@ -3307,7 +3306,7 @@ void ReportPath::reportFieldDelayMinus(Delay value, const EarlyLate *early_late, const ReportField *field, - string &line) const + std::string &line) const { if (delayAsFloat(value) == field_blank_) reportFieldBlank(field, line); @@ -3327,7 +3326,7 @@ void ReportPath::reportFieldDelay(Delay value, const EarlyLate *early_late, const ReportField *field, - string &line) const + std::string &line) const { if (delayAsFloat(value) == field_blank_) reportFieldBlank(field, line); @@ -3345,7 +3344,7 @@ ReportPath::reportFieldDelay(Delay value, void ReportPath::reportField(float value, const ReportField *field, - string &line) const + std::string &line) const { if (value == field_blank_) reportFieldBlank(field, line); @@ -3357,7 +3356,7 @@ ReportPath::reportField(float value, } else { // fanout - string value_str; + std::string value_str; stringPrint(value_str, "%.0f", value); reportField(value_str.c_str(), field, line); } @@ -3367,7 +3366,7 @@ ReportPath::reportField(float value, void ReportPath::reportField(const char *value, const ReportField *field, - string &line) const + std::string &line) const { if (field->leftJustify()) line += value; @@ -3379,7 +3378,7 @@ ReportPath::reportField(const char *value, void ReportPath::reportFieldBlank(const ReportField *field, - string &line) const + std::string &line) const { line += field->blank(); } @@ -3387,7 +3386,7 @@ ReportPath::reportFieldBlank(const ReportField *field, void ReportPath::reportDashLine() const { - string line; + std::string line; for (const ReportField *field : fields_) { if (field->enabled()) { for (int i = 0; i < field->width(); i++) @@ -3401,7 +3400,7 @@ ReportPath::reportDashLine() const void ReportPath::reportDashLine(int line_width) const { - string line; + std::string line; for (int i = 0; i < line_width; i++) line += '-'; report_->reportLineString(line); diff --git a/search/Search.cc b/search/Search.cc index 248477d4..25683114 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -24,8 +24,7 @@ #include "Search.hh" -#include -#include // abs +#include #include "ContainerHelpers.hh" #include "Mutex.hh" @@ -70,10 +69,6 @@ namespace sta { -using std::min; -using std::max; -using std::abs; - //////////////////////////////////////////////////////////////// EvalPred::EvalPred(const StaState *sta) : diff --git a/search/Sta.cc b/search/Sta.cc index baa4ab07..5c096867 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -24,7 +24,9 @@ #include "Sta.hh" +#include #include +#include #include "Machine.hh" #include "ContainerHelpers.hh" @@ -88,10 +90,6 @@ namespace sta { -using std::string; -using std::min; -using std::max; - static bool libertyPortCapsEqual(const LibertyPort *port1, const LibertyPort *port2); @@ -576,7 +574,7 @@ Sta::cmdSdc() const } void -Sta::setCmdMode(const string &mode_name) +Sta::setCmdMode(const std::string &mode_name) { if (!mode_name.empty()) { if (!mode_name_map_.contains(mode_name)) { @@ -3203,8 +3201,8 @@ class EndpointPathEndVisitor : public PathEndVisitor { public: EndpointPathEndVisitor(const std::string &path_group_name, - const MinMax *min_max, - const StaState *sta); + const MinMax *min_max, + const StaState *sta); PathEndVisitor *copy() const; void visit(PathEnd *path_end); Slack slack() const { return slack_; } @@ -3217,8 +3215,8 @@ private: }; EndpointPathEndVisitor::EndpointPathEndVisitor(const std::string &path_group_name, - const MinMax *min_max, - const StaState *sta) : + const MinMax *min_max, + const StaState *sta) : path_group_name_(path_group_name), min_max_(min_max), slack_(MinMax::min()->initValue()), @@ -3249,8 +3247,8 @@ EndpointPathEndVisitor::visit(PathEnd *path_end) Slack Sta::endpointSlack(const Pin *pin, - const std::string &path_group_name, - const MinMax *min_max) + const std::string &path_group_name, + const MinMax *min_max) { ensureGraph(); Vertex *vertex = graph_->pinLoadVertex(pin); @@ -3458,7 +3456,7 @@ MinPeriodEndVisitor::visit(PathEnd *path_end) || pathIsFromInputPort(path_end)))) { Slack slack = path_end->slack(sta_); float period = clk_->period() - delayAsFloat(slack); - min_period_ = max(min_period_, period); + min_period_ = std::max(min_period_, period); } } @@ -3551,12 +3549,12 @@ Sta::worstSlack(const Scene *scene, //////////////////////////////////////////////////////////////// -string +std::string Sta::reportDelayCalc(Edge *edge, - TimingArc *arc, + TimingArc *arc, const Scene *scene, - const MinMax *min_max, - int digits) + const MinMax *min_max, + int digits) { findDelays(); return graph_delay_calc_->reportDelayCalc(edge, arc, scene, min_max, digits); @@ -4097,13 +4095,13 @@ Sta::setResistance(const Net *net, bool Sta::readSpef(const std::string &name, const std::string &filename, - Instance *instance, + Instance *instance, Scene *scene, // -scene deprecated 11/20/2025 - const MinMaxAll *min_max, - bool pin_cap_included, - bool keep_coupling_caps, - float coupling_cap_factor, - bool reduce) + const MinMaxAll *min_max, + bool pin_cap_included, + bool keep_coupling_caps, + float coupling_cap_factor, + bool reduce) { ensureLibLinked(); Parasitics *parasitics = nullptr; @@ -4137,7 +4135,7 @@ Sta::readSpef(const std::string &name, } bool success = readSpefFile(filename.c_str(), instance, - pin_cap_included, keep_coupling_caps, + pin_cap_included, keep_coupling_caps, coupling_cap_factor, reduce, scene, min_max, parasitics, this); delaysInvalid(); @@ -4151,7 +4149,7 @@ Sta::findParasitics(const std::string &name) } void -Sta::reportParasiticAnnotation(const string &spef_name, +Sta::reportParasiticAnnotation(const std::string &spef_name, bool report_unannotated) { ensureLibLinked(); diff --git a/search/WorstSlack.cc b/search/WorstSlack.cc index cad69282..9eae159b 100644 --- a/search/WorstSlack.cc +++ b/search/WorstSlack.cc @@ -24,6 +24,8 @@ #include "WorstSlack.hh" +#include + #include "ContainerHelpers.hh" #include "Debug.hh" #include "Report.hh" @@ -34,8 +36,6 @@ namespace sta { -using std::min; - WorstSlacks::WorstSlacks(StaState *sta) : worst_slacks_(sta->scenePathCount(), sta), sta_(sta) @@ -195,7 +195,7 @@ WorstSlack::sortQueue(PathAPIndex path_ap_index) sort(vertices, slack_less); int vertex_count = vertices.size(); - int threshold_index = min(min_queue_size_, vertex_count - 1); + int threshold_index = std::min(min_queue_size_, vertex_count - 1); Vertex *threshold_vertex = vertices[threshold_index]; slack_threshold_ = search_->wnsSlack(threshold_vertex, path_ap_index); debugPrint(debug_, "wns", 3, "threshold %s", diff --git a/spice/WritePathSpice.cc b/spice/WritePathSpice.cc index 694ba7b3..1368cd51 100644 --- a/spice/WritePathSpice.cc +++ b/spice/WritePathSpice.cc @@ -24,8 +24,8 @@ #include "WritePathSpice.hh" -#include #include +#include #include "Debug.hh" #include "Error.hh" @@ -50,11 +50,6 @@ namespace sta { -using std::string; -using std::ofstream; -using std::ifstream; -using std::max; - typedef int Stage; //////////////////////////////////////////////////////////////// @@ -112,7 +107,7 @@ private: // Stage stageFirst(); Stage stageLast(); - string stageName(Stage stage); + std::string stageName(Stage stage); int stageGateInputPathIndex(Stage stage); int stageDrvrPathIndex(Stage stage); int stageLoadPathIndex(Stage stage); @@ -219,7 +214,7 @@ void WritePathSpice::writeHeader() { const Path *start_path = path_expanded_.startPath(); - 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)), start_path->transition(this)->to_string().c_str(), network_->pathName(path_->pin(this)), @@ -291,7 +286,7 @@ WritePathSpice::writeStageInstances() streamPrint(spice_stream_, "*****************\n\n"); for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { - string stage_name = stageName(stage); + std::string stage_name = stageName(stage); const char *stage_cname = stage_name.c_str(); if (stage == stageFirst()) streamPrint(spice_stream_, "x%s %s %s %s\n", @@ -450,7 +445,7 @@ WritePathSpice::writeMeasureSlewStmt(Stage stage, { const Pin *pin = path->pin(this); const RiseFall *rf = path->transition(this); - string prefix = stageName(stage); + std::string prefix = stageName(stage); writeMeasureSlewStmt(pin, rf, prefix); } @@ -480,7 +475,7 @@ WritePathSpice::writeInputStage(Stage stage) // External driver not handled. const char *drvr_pin_name = stageDrvrPinName(stage); const char *load_pin_name = stageLoadPinName(stage); - string prefix = stageName(stage); + std::string prefix = stageName(stage); streamPrint(spice_stream_, ".subckt %s %s %s\n", prefix.c_str(), drvr_pin_name, @@ -499,7 +494,7 @@ WritePathSpice::writeGateStage(Stage stage) const char *drvr_pin_name = stageDrvrPinName(stage); const Pin *load_pin = stageLoadPin(stage); const char *load_pin_name = stageLoadPinName(stage); - string subckt_name = "stage" + std::to_string(stage); + std::string subckt_name = "stage" + std::to_string(stage); const Instance *inst = stageInstance(stage); LibertyPort *input_port = stageGateInputPort(stage); @@ -614,10 +609,10 @@ WritePathSpice::stageLast() return (path_expanded_.size() + 1) / 2; } -string +std::string WritePathSpice::stageName(Stage stage) { - string name; + std::string name; stringPrint(name, "stage%d", stage); return name; } diff --git a/spice/WriteSpice.cc b/spice/WriteSpice.cc index 8d55d8c7..9b1bf2c3 100644 --- a/spice/WriteSpice.cc +++ b/spice/WriteSpice.cc @@ -26,6 +26,8 @@ #include // swap #include +#include +#include #include "cudd.h" @@ -50,12 +52,6 @@ namespace sta { -using std::string; -using std::ifstream; -using std::ofstream; -using std::swap; -using std::set; - Net * pinNet(const Pin *pin, const Network *network); @@ -68,7 +64,7 @@ public: const char *what() const noexcept; protected: - string what_; + std::string what_; }; SubcktEndsMissing::SubcktEndsMissing(const char *cell_name, @@ -137,7 +133,7 @@ WriteSpice::initPowerGnd() } void -WriteSpice::writeHeader(string &title, +WriteSpice::writeHeader(std::string &title, float max_time, float time_step) { @@ -159,21 +155,21 @@ WriteSpice::writePrintStmt(StdStringSeq &node_names) { streamPrint(spice_stream_, ".print tran"); if (ckt_sim_ == CircuitSim::xyce) { - string csv_filename = replaceFileExt(spice_filename_, "csv"); + std::string csv_filename = replaceFileExt(spice_filename_, "csv"); streamPrint(spice_stream_, " format=csv file=%s", csv_filename.c_str()); writeGnuplotFile(node_names); } - for (string &name : node_names) + for (std::string &name : node_names) streamPrint(spice_stream_, " v(%s)", name.c_str()); streamPrint(spice_stream_, "\n\n"); } -string -WriteSpice::replaceFileExt(string filename, +std::string +WriteSpice::replaceFileExt(std::string filename, const char *ext) { size_t dot = filename.rfind('.'); - string ext_filename = filename.substr(0, dot + 1); + std::string ext_filename = filename.substr(0, dot + 1); ext_filename += ext; return ext_filename; } @@ -184,7 +180,7 @@ WriteSpice::writeGnuplotFile(StdStringSeq &node_nanes) { std::string gnuplot_filename = replaceFileExt(spice_filename_, "gnuplot"); std::string csv_filename = replaceFileExt(spice_filename_, "csv"); - ofstream gnuplot_stream; + std::ofstream gnuplot_stream; gnuplot_stream.open(gnuplot_filename); if (gnuplot_stream.is_open()) { streamPrint(gnuplot_stream, "set datafile separator ','\n"); @@ -206,12 +202,12 @@ void WriteSpice::writeSubckts(StdStringSet &cell_names) { findCellSubckts(cell_names); - ifstream lib_subckts_stream(lib_subckt_filename_); + std::ifstream lib_subckts_stream(lib_subckt_filename_); if (lib_subckts_stream.is_open()) { - ofstream subckts_stream(subckt_filename_); + std::ofstream subckts_stream(subckt_filename_); if (subckts_stream.is_open()) { - string line; - while (getline(lib_subckts_stream, line)) { + std::string line; + while (std::getline(lib_subckts_stream, line)) { // .subckt [args..] StdStringSeq tokens = parseTokens(line, ' '); if (tokens.size() >= 2 @@ -220,7 +216,7 @@ WriteSpice::writeSubckts(StdStringSet &cell_names) if (cell_names.contains(cell_name)) { subckts_stream << line << "\n"; bool found_ends = false; - while (getline(lib_subckts_stream, line)) { + while (std::getline(lib_subckts_stream, line)) { subckts_stream << line << "\n"; if (stringBeginEqual(line.c_str(), ".ends")) { subckts_stream << "\n"; @@ -239,13 +235,13 @@ WriteSpice::writeSubckts(StdStringSet &cell_names) lib_subckts_stream.close(); if (!cell_names.empty()) { - string missing_cells; - for (const string &cell_name : cell_names) { - missing_cells += "\n"; - missing_cells += cell_name; + std::string missing_cells; + for (const std::string &cell_name : cell_names) { + missing_cells += "\n"; + missing_cells += cell_name; } - report_->error(1605, "The subkct file %s is missing definitions for %s", - lib_subckt_filename_, + report_->error(1605, "The subkct file %s is missing definitions for %s", + lib_subckt_filename_, missing_cells.c_str()); } } @@ -284,10 +280,10 @@ WriteSpice::recordSpicePortNames(const char *cell_name, void WriteSpice::findCellSubckts(StdStringSet &cell_names) { - ifstream lib_subckts_stream(lib_subckt_filename_); + std::ifstream lib_subckts_stream(lib_subckt_filename_); if (lib_subckts_stream.is_open()) { - string line; - while (getline(lib_subckts_stream, line)) { + std::string line; + while (std::getline(lib_subckts_stream, line)) { // .subckt [args..] StdStringSeq tokens = parseTokens(line, ' '); if (tokens.size() >= 2 @@ -295,15 +291,15 @@ WriteSpice::findCellSubckts(StdStringSet &cell_names) const char *cell_name = tokens[1].c_str(); if (cell_names.contains(cell_name)) { // Scan the subckt definition for subckt calls. - string stmt; - while (getline(lib_subckts_stream, line)) { + std::string stmt; + while (std::getline(lib_subckts_stream, line)) { if (line[0] == '+') stmt += line.substr(1); else { // Process previous statement. if (tolower(stmt[0]) == 'x') { StdStringSeq tokens = parseTokens(line, ' '); - string &subckt_cell = tokens[tokens.size() - 1]; + std::string &subckt_cell = tokens[tokens.size() - 1]; cell_names.insert(subckt_cell); } stmt = line; @@ -329,7 +325,7 @@ WriteSpice::writeSubcktInst(const Instance *inst) const char *cell_name = cell->name(); StdStringSeq &spice_port_names = cell_spice_port_names_[cell_name]; streamPrint(spice_stream_, "x%s", inst_name); - for (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(); Pin *pin = network_->findPin(inst, subckt_port_cname); LibertyPort *pg_port = cell->findLibertyPort(subckt_port_cname); @@ -359,7 +355,7 @@ WriteSpice::writeSubcktInstVoltSrcs(const Instance *inst, const char *inst_name = network_->pathName(inst); debugPrint(debug_, "write_spice", 2, "subckt %s", cell->name()); - for (string subckt_port_sname : spice_port_names) { + for (std::string subckt_port_sname : spice_port_names) { const char *subckt_port_name = subckt_port_sname.c_str(); LibertyPort *port = cell->findLibertyPort(subckt_port_name); const Pin *pin = port ? network_->findPin(inst, port) : nullptr; @@ -412,7 +408,7 @@ WriteSpice::writeVoltageSource(const char *inst_name, const char *port_name, float voltage) { - string node_name = inst_name; + std::string node_name = inst_name; node_name += '/'; node_name += port_name; writeVoltageSource(node_name.c_str(), voltage); @@ -536,7 +532,7 @@ WriteSpice::writeParasiticNetwork(const Pin *drvr_pin, const Parasitic *parasitic, const NetSet &coupling_nets) { - set reachable_pins; + std::set reachable_pins; // Sort resistors for consistent regression results. ParasiticResistorSeq resistors = parasitics_->resistors(parasitic); sort(resistors, [this] (const ParasiticResistor *r1, @@ -614,8 +610,8 @@ WriteSpice::writeParasiticNetwork(const Pin *drvr_pin, const Net *net1 = node1 ? parasitics_->net(node1, network_) : nullptr; const Net *net2 = node2 ? parasitics_->net(node2, network_) : nullptr; if (net2 == net) { - swap(net1, net2); - swap(node1, node2); + std::swap(net1, net2); + std::swap(node1, node2); } if (net2 && coupling_nets.contains(net2)) // Write half the capacitance because the coupled net will do the same. @@ -1036,7 +1032,7 @@ WriteSpice::writeMeasureDelayStmt(const Pin *from_pin, const RiseFall *from_rf, const Pin *to_pin, const RiseFall *to_rf, - string prefix) + std::string prefix) { const char *from_pin_name = network_->pathName(from_pin); float from_threshold = power_voltage_ * default_library_->inputThreshold(from_rf); @@ -1062,7 +1058,7 @@ WriteSpice::writeMeasureDelayStmt(const Pin *from_pin, void WriteSpice::writeMeasureSlewStmt(const Pin *pin, const RiseFall *rf, - string prefix) + std::string prefix) { const char *pin_name = network_->pathName(pin); const char *spice_rf = spiceTrans(rf); @@ -1108,7 +1104,7 @@ WriteSpice::spiceTrans(const RiseFall *rf) // fprintf for c++ streams. // Yes, I hate formatted output to ostream THAT much. void -streamPrint(ofstream &stream, +streamPrint(std::ofstream &stream, const char *fmt, ...) { diff --git a/spice/Xyce.cc b/spice/Xyce.cc index f198df70..a4a0f3b6 100644 --- a/spice/Xyce.cc +++ b/spice/Xyce.cc @@ -26,55 +26,49 @@ #include "Xyce.hh" #include -#include #include +#include +#include #include "Error.hh" namespace sta { -using std::string; -using std::ifstream; -using std::getline; -using std::stringstream; -using std::vector; -using std::make_shared; - void readXyceCsv(const char *csv_filename, // Return values. StdStringSeq &titles, WaveformSeq &waveforms) { - ifstream file(csv_filename); + std::ifstream file(csv_filename); if (file.is_open()) { - string line; + std::string line; // Read the header line. - getline(file, line); - stringstream ss(line); - string field; + std::getline(file, line); + std::stringstream ss(line); + std::string field; size_t col = 0; - while (getline(ss, field, ',')) { + while (std::getline(ss, field, ',')) { // Skip TIME title. if (col > 0) titles.push_back(field); col++; } - vector values(titles.size() + 1); - while (getline(file, line)) { - stringstream ss(line); + std::vector values(titles.size() + 1); + while (std::getline(file, line)) { + std::stringstream ss(line); size_t col = 0; - while (getline(ss, field, ',')) { + while (std::getline(ss, field, ',')) { float value = std::stof(field); values[col].push_back(value); col++; } } file.close(); - TableAxisPtr time_axis = make_shared(TableAxisVariable::time, - std::move(values[0])); + TableAxisPtr time_axis = std::make_shared(TableAxisVariable::time, + std::move(values[0])); for (size_t var = 1; var < values.size(); var++) waveforms.emplace_back(new FloatSeq(values[var]), time_axis); } diff --git a/util/Fuzzy.cc b/util/Fuzzy.cc index f7158366..bd055f1d 100644 --- a/util/Fuzzy.cc +++ b/util/Fuzzy.cc @@ -31,9 +31,6 @@ namespace sta { -using std::max; -using std::abs; - constexpr static float float_equal_tolerance = 1E-15F; bool @@ -43,18 +40,18 @@ fuzzyEqual(float v1, if (v1 == v2) return true; else if (v1 == 0.0) - return abs(v2) < float_equal_tolerance; + return std::abs(v2) < float_equal_tolerance; else if (v2 == 0.0) - return abs(v1) < float_equal_tolerance; + return std::abs(v1) < float_equal_tolerance; else - return abs(v1 - v2) < 1E-6F * max(abs(v1), abs(v2)); + return std::abs(v1 - v2) < 1E-6F * std::max(std::abs(v1), std::abs(v2)); } bool fuzzyZero(float v) { return v == 0.0 - || abs(v) < float_equal_tolerance; + || std::abs(v) < float_equal_tolerance; } bool diff --git a/util/PatternMatch.cc b/util/PatternMatch.cc index 8b1e49e8..7e814258 100644 --- a/util/PatternMatch.cc +++ b/util/PatternMatch.cc @@ -28,8 +28,6 @@ namespace sta { -using std::string; - PatternMatch::PatternMatch(const char *pattern, bool is_regexp, bool nocase, @@ -65,7 +63,7 @@ PatternMatch::PatternMatch(const char *pattern, compileRegexp(); } -PatternMatch::PatternMatch(const string &pattern, +PatternMatch::PatternMatch(const std::string &pattern, const PatternMatch *inherit_from) : pattern_(pattern.c_str()), is_regexp_(inherit_from->is_regexp_), @@ -83,7 +81,7 @@ PatternMatch::compileRegexp() int flags = TCL_REG_ADVANCED; if (nocase_) flags |= TCL_REG_NOCASE; - string anchored_pattern; + std::string anchored_pattern; anchored_pattern += '^'; anchored_pattern += pattern_; anchored_pattern += '$'; @@ -112,7 +110,7 @@ PatternMatch::hasWildcards() const } bool -PatternMatch::match(const string &str) const +PatternMatch::match(const std::string &str) const { return match(str.c_str()); } diff --git a/util/Report.cc b/util/Report.cc index 5f6b885b..6772484e 100644 --- a/util/Report.cc +++ b/util/Report.cc @@ -33,8 +33,6 @@ namespace sta { -using std::min; - Report *Report::default_ = nullptr; Report::Report() : @@ -78,11 +76,11 @@ Report::printString(const char *buffer, redirectStringPrint(buffer, length); else { if (redirect_stream_) - ret = min(ret, fwrite(buffer, sizeof(char), length, redirect_stream_)); + ret = std::min(ret, fwrite(buffer, sizeof(char), length, redirect_stream_)); else - ret = min(ret, printConsole(buffer, length)); + ret = std::min(ret, printConsole(buffer, length)); if (log_stream_) - ret = min(ret, fwrite(buffer, sizeof(char), length, log_stream_)); + ret = std::min(ret, fwrite(buffer, sizeof(char), length, log_stream_)); } return ret; } diff --git a/util/StringUtil.cc b/util/StringUtil.cc index 6a8680e4..991d25db 100644 --- a/util/StringUtil.cc +++ b/util/StringUtil.cc @@ -24,21 +24,17 @@ #include "StringUtil.hh" -#include +#include +#include #include #include #include // exit -#include -#include #include "Machine.hh" #include "Mutex.hh" namespace sta { -using std::max; -using std::string; - static void stringPrintTmp(const char *fmt, va_list args, @@ -76,7 +72,7 @@ isDigits(const char *str) // print for c++ strings. void -stringPrint(string &str, +stringPrint(std::string &str, const char *fmt, ...) { @@ -90,7 +86,7 @@ stringPrint(string &str, } void -stringAppend(string &str, +stringAppend(std::string &str, const char *fmt, ...) { @@ -103,7 +99,7 @@ stringAppend(string &str, str += tmp; } -string +std::string stdstrPrint(const char *fmt, ...) { @@ -223,7 +219,7 @@ makeTmpString(size_t length) if (tmp_length < length) { // String isn't long enough. Make a new one. delete [] tmp_str; - tmp_length = max(tmp_string_initial_length, length); + tmp_length = std::max(tmp_string_initial_length, length); tmp_str = new char[tmp_length]; tmp_strings[tmp_string_next] = tmp_str; tmp_string_lengths[tmp_string_next] = tmp_length; @@ -233,7 +229,7 @@ makeTmpString(size_t length) } char * -makeTmpString(string &str) +makeTmpString(std::string &str) { char *tmp = makeTmpString(str.length() + 1); strcpy(tmp, str.c_str()); @@ -264,24 +260,24 @@ isTmpString(const char *str) //////////////////////////////////////////////////////////////// void -trimRight(string &str) +trimRight(std::string &str) { str.erase(str.find_last_not_of(" ") + 1); } StdStringSeq -split(const string &text, - const string &delims) +split(const std::string &text, + const std::string &delims) { StdStringSeq tokens; auto start = text.find_first_not_of(delims); auto end = text.find_first_of(delims, start); - while (end != string::npos) { + while (end != std::string::npos) { tokens.push_back(text.substr(start, end - start)); start = text.find_first_not_of(delims, end); end = text.find_first_of(delims, start); } - if (start != string::npos) + if (start != std::string::npos) tokens.push_back(text.substr(start)); return tokens; } diff --git a/util/Transition.cc b/util/Transition.cc index a77a898b..0e09243c 100644 --- a/util/Transition.cc +++ b/util/Transition.cc @@ -24,12 +24,12 @@ #include "Transition.hh" +#include + #include "ContainerHelpers.hh" namespace sta { -using std::max; - const RiseFall RiseFall::rise_("rise", "^", 0); const RiseFall RiseFall::fall_("fall", "v", 1); const std::array RiseFall::range_{&rise_, &fall_}; @@ -195,7 +195,7 @@ Transition::Transition(const char *name, { transition_map_[name_] = this; transition_map_[init_final_] = this; - max_index_ = max(sdf_triple_index, max_index_); + max_index_ = std::max(sdf_triple_index, max_index_); } bool diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc index e7ac21d3..e101d0f9 100644 --- a/verilog/VerilogReader.cc +++ b/verilog/VerilogReader.cc @@ -25,6 +25,7 @@ #include "VerilogReader.hh" #include +#include #include "ContainerHelpers.hh" #include "Zlib.hh" @@ -42,12 +43,10 @@ namespace sta { -using std::string; - using VerilogConstant10 = unsigned long long; -static string -verilogBusBitName(const string &bus_name, +static std::string +verilogBusBitName(const std::string &bus_name, int index); static int hierarchyLevel(Net *net, @@ -227,13 +226,13 @@ VerilogReader::module(Cell *cell) } void -VerilogReader::makeModule(const string *module_vname, +VerilogReader::makeModule(const std::string *module_vname, VerilogNetSeq *ports, VerilogStmtSeq *stmts, VerilogAttrStmtSeq *attr_stmts, int line) { - const string module_name = moduleVerilogToSta(module_vname); + const std::string module_name = moduleVerilogToSta(module_vname); Cell *cell = network_->findCell(library_, module_name.c_str()); if (cell) { VerilogModule *module = module_map_[cell]; @@ -258,7 +257,7 @@ VerilogReader::makeModule(const string *module_vname, } void -VerilogReader::makeModule(const string *module_name, +VerilogReader::makeModule(const std::string *module_name, VerilogStmtSeq *port_dcls, VerilogStmtSeq *stmts, VerilogAttrStmtSeq *attr_stmts, @@ -288,7 +287,7 @@ VerilogReader::makeCellPorts(Cell *cell, { StdStringSet port_names; for (VerilogNet *mod_port : *ports) { - const string &port_name = mod_port->name(); + const std::string &port_name = mod_port->name(); if (!port_names.contains(port_name)) { port_names.insert(port_name); if (mod_port->isNamed()) { @@ -310,7 +309,7 @@ VerilogReader::makeCellPorts(Cell *cell, Port * VerilogReader::makeCellPort(Cell *cell, VerilogModule *module, - const string &port_name) + const std::string &port_name) { VerilogDcl *dcl = module->declaration(port_name.c_str()); if (dcl) { @@ -341,7 +340,7 @@ VerilogReader::makeNamedPortRefCellPorts(Cell *cell, PortSeq *member_ports = new PortSeq; VerilogNetNameIterator *net_name_iter = mod_port->nameIterator(module,this); while (net_name_iter->hasNext()) { - const string &net_name = net_name_iter->next(); + const std::string &net_name = net_name_iter->next(); port_names.insert(net_name); Port *port = makeCellPort(cell, module, net_name); member_ports->push_back(port); @@ -354,7 +353,7 @@ VerilogReader::makeNamedPortRefCellPorts(Cell *cell, // Make sure each declaration appears in the module port list. void VerilogReader::checkModuleDcls(VerilogModule *module, - std::set &port_names) + std::set &port_names) { for (auto const & [port_name, dcl] : *module->declarationMap()) { PortDirection *dir = dcl->direction(); @@ -444,10 +443,10 @@ VerilogReader::makeDclBus(PortDirection *dir, } VerilogDclArg * -VerilogReader::makeDclArg(const string *net_vname) +VerilogReader::makeDclArg(const std::string *net_vname) { dcl_arg_count_++; - const string net_name = netVerilogToSta(net_vname); + const std::string net_name = netVerilogToSta(net_vname); VerilogDclArg *dcl =new VerilogDclArg(net_name); delete net_vname; return dcl; @@ -461,14 +460,14 @@ VerilogReader::makeDclArg(VerilogAssign *assign) } VerilogNetPartSelect * -VerilogReader::makeNetPartSelect(const string *net_vname, +VerilogReader::makeNetPartSelect(const std::string *net_vname, int from_index, int to_index) { net_part_select_count_++; if (report_stmt_stats_) net_bus_names_ += net_vname->size() + 1; - const string net_name = netVerilogToSta(net_vname); + const std::string net_name = netVerilogToSta(net_vname); VerilogNetPartSelect *select = new VerilogNetPartSelect(net_name, from_index, to_index); @@ -477,7 +476,7 @@ VerilogReader::makeNetPartSelect(const string *net_vname, } VerilogNetConstant * -VerilogReader::makeNetConstant(const string *constant, +VerilogReader::makeNetConstant(const std::string *constant, int line) { net_constant_count_++; @@ -485,25 +484,25 @@ VerilogReader::makeNetConstant(const string *constant, } VerilogNetScalar * -VerilogReader::makeNetScalar(const string *net_vname) +VerilogReader::makeNetScalar(const std::string *net_vname) { net_scalar_count_++; if (report_stmt_stats_) net_scalar_names_ += net_vname->size() + 1; - const string net_name = netVerilogToSta(net_vname); + const std::string net_name = netVerilogToSta(net_vname); VerilogNetScalar *scalar = new VerilogNetScalar(net_name); delete net_vname; return scalar; } VerilogNetBitSelect * -VerilogReader::makeNetBitSelect(const string *net_vname, +VerilogReader::makeNetBitSelect(const std::string *net_vname, int index) { net_bit_select_count_++; if (report_stmt_stats_) net_bus_names_ += net_vname->size() + 1; - const string net_name = netVerilogToSta(net_vname); + const std::string net_name = netVerilogToSta(net_vname); VerilogNetBitSelect *select = new VerilogNetBitSelect(net_name, index); delete net_vname; return select; @@ -519,14 +518,14 @@ VerilogReader::makeAssign(VerilogNet *lhs, } VerilogInst * -VerilogReader::makeModuleInst(const string *module_vname, - const string *inst_vname, +VerilogReader::makeModuleInst(const std::string *module_vname, + const std::string *inst_vname, VerilogNetSeq *pins, VerilogAttrStmtSeq *attr_stmts, const int line) { - const string module_name = moduleVerilogToSta(module_vname); - const string inst_name = instanceVerilogToSta(inst_vname); + const std::string module_name = moduleVerilogToSta(module_vname); + const std::string inst_name = instanceVerilogToSta(inst_vname); Cell *cell = network_->findAnyCell(module_name.c_str()); LibertyCell *liberty_cell = nullptr; if (cell) @@ -541,7 +540,7 @@ VerilogReader::makeModuleInst(const string *module_vname, VerilogNetPortRefScalarNet *vpin = dynamic_cast(vnet); const char *port_name = vpin->name().c_str(); - const string &net_name = vpin->netName(); + const std::string &net_name = vpin->netName(); Port *port = network_->findPort(cell, port_name); LibertyPort *lport = network_->libertyPort(port); if (lport->isBus()) { @@ -607,20 +606,20 @@ VerilogReader::hasScalarNamedPortRefs(LibertyCell *liberty_cell, } VerilogNetPortRef * -VerilogReader::makeNetNamedPortRefScalarNet(const string *port_vname) +VerilogReader::makeNetNamedPortRefScalarNet(const std::string *port_vname) { net_port_ref_scalar_net_count_++; if (report_stmt_stats_) port_names_ += port_vname->size() + 1; - const string port_name = portVerilogToSta(port_vname); + const std::string port_name = portVerilogToSta(port_vname); VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name.c_str()); delete port_vname; return ref; } VerilogNetPortRef * -VerilogReader::makeNetNamedPortRefScalarNet(const string *port_vname, - const string *net_vname) +VerilogReader::makeNetNamedPortRefScalarNet(const std::string *port_vname, + const std::string *net_vname) { net_port_ref_scalar_net_count_++; if (report_stmt_stats_) { @@ -628,8 +627,8 @@ VerilogReader::makeNetNamedPortRefScalarNet(const string *port_vname, net_scalar_names_ += net_vname->size() + 1; port_names_ += port_vname->size() + 1; } - const string port_name = portVerilogToSta(port_vname); - const string net_name = netVerilogToSta(net_vname); + const std::string port_name = portVerilogToSta(port_vname); + const std::string net_name = netVerilogToSta(net_vname); VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name.c_str(), net_name.c_str()); delete port_vname; @@ -638,18 +637,18 @@ VerilogReader::makeNetNamedPortRefScalarNet(const string *port_vname, } VerilogNetPortRef * -VerilogReader::makeNetNamedPortRefBitSelect(const string *port_vname, - const string *bus_vname, +VerilogReader::makeNetNamedPortRefBitSelect(const std::string *port_vname, + const std::string *bus_vname, int index) { net_port_ref_scalar_net_count_++; - const string bus_name = portVerilogToSta(bus_vname); - const string net_name = verilogBusBitName(bus_name, index); + const std::string bus_name = portVerilogToSta(bus_vname); + const std::string net_name = verilogBusBitName(bus_name, index); if (report_stmt_stats_) { net_scalar_names_ += net_name.length() + 1; port_names_ += port_vname->size() + 1; } - const string port_name = portVerilogToSta(port_vname); + const std::string port_name = portVerilogToSta(port_vname); VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name.c_str(), net_name.c_str()); delete port_vname; @@ -658,25 +657,25 @@ VerilogReader::makeNetNamedPortRefBitSelect(const string *port_vname, } VerilogNetPortRef * -VerilogReader::makeNetNamedPortRefScalar(const string *port_vname, +VerilogReader::makeNetNamedPortRefScalar(const std::string *port_vname, VerilogNet *net) { net_port_ref_scalar_count_++; if (report_stmt_stats_) port_names_ += port_vname->size() + 1; - const string port_name = portVerilogToSta(port_vname); + const std::string port_name = portVerilogToSta(port_vname); VerilogNetPortRef *ref = new VerilogNetPortRefScalar(port_name.c_str(), net); delete port_vname; return ref; } VerilogNetPortRef * -VerilogReader::makeNetNamedPortRefBit(const string *port_vname, +VerilogReader::makeNetNamedPortRefBit(const std::string *port_vname, int index, VerilogNet *net) { net_port_ref_bit_count_++; - const string port_name = portVerilogToSta(port_vname); + const std::string port_name = portVerilogToSta(port_vname); VerilogNetPortRef *ref = new VerilogNetPortRefBit(port_name.c_str(), index, net); delete port_vname; @@ -684,13 +683,13 @@ VerilogReader::makeNetNamedPortRefBit(const string *port_vname, } VerilogNetPortRef * -VerilogReader::makeNetNamedPortRefPart(const string *port_vname, +VerilogReader::makeNetNamedPortRefPart(const std::string *port_vname, int from_index, int to_index, VerilogNet *net) { net_port_ref_part_count_++; - const string port_name = portVerilogToSta(port_vname); + const std::string port_name = portVerilogToSta(port_vname); VerilogNetPortRef *ref = new VerilogNetPortRefPart(port_name, from_index, to_index, net); @@ -776,11 +775,11 @@ VerilogReader::warn(int id, //////////////////////////////////////////////////////////////// -VerilogModule::VerilogModule(const string &name, +VerilogModule::VerilogModule(const std::string &name, VerilogNetSeq *ports, VerilogStmtSeq *stmts, VerilogAttrStmtSeq *attr_stmts, - const string &filename, + const std::string &filename, int line, VerilogReader *reader) : VerilogStmt(line), @@ -822,7 +821,7 @@ VerilogModule::parseDcl(VerilogDcl *dcl, { for (VerilogDclArg *arg : *dcl->args()) { if (arg->isNamed()) { - const string &net_name = arg->netName(); + const std::string &net_name = arg->netName(); VerilogDcl *existing_dcl = dcl_map_[net_name.c_str()]; if (existing_dcl) { PortDirection *existing_dir = existing_dcl->direction(); @@ -845,7 +844,7 @@ VerilogModule::parseDcl(VerilogDcl *dcl, // input/output/inout dcls. dcl_map_[net_name.c_str()] = dcl; else if (!dcl->direction()->isInternal()) { - string net_vname = netVerilogName(net_name.c_str()); + std::string net_vname = netVerilogName(net_name.c_str()); reader->warn(1395, filename_.c_str(), dcl->line(), "signal %s previously declared on line %d.", net_vname.c_str(), @@ -865,14 +864,14 @@ VerilogModule::checkInstanceName(VerilogInst *inst, StdStringSet &inst_names, VerilogReader *reader) { - string inst_name = inst->instanceName(); + std::string inst_name = inst->instanceName(); if (inst_names.contains(inst_name)) { int i = 1; - string replacement_name; + std::string replacement_name; do { replacement_name = stdstrPrint("%s_%d", inst_name.c_str(), i++); } while (inst_names.contains(replacement_name)); - string inst_vname = instanceVerilogName(inst_name.c_str()); + std::string inst_vname = instanceVerilogName(inst_name.c_str()); reader->warn(1396, filename_.c_str(), inst->line(), "instance name %s duplicated - renamed to %s.", inst_vname.c_str(), @@ -884,7 +883,7 @@ VerilogModule::checkInstanceName(VerilogInst *inst, } VerilogDcl * -VerilogModule::declaration(const string &net_name) +VerilogModule::declaration(const std::string &net_name) { return findKey(dcl_map_, net_name.c_str()); } @@ -896,7 +895,7 @@ VerilogStmt::VerilogStmt(int line) : { } -VerilogInst::VerilogInst(const string &inst_name, +VerilogInst::VerilogInst(const std::string &inst_name, VerilogAttrStmtSeq *attr_stmts, const int line) : VerilogStmt(line), @@ -912,13 +911,13 @@ VerilogInst::~VerilogInst() } void -VerilogInst::setInstanceName(const string &inst_name) +VerilogInst::setInstanceName(const std::string &inst_name) { inst_name_ = inst_name; } -VerilogModuleInst::VerilogModuleInst(const string &module_name, - const string &inst_name, +VerilogModuleInst::VerilogModuleInst(const std::string &module_name, + const std::string &inst_name, VerilogNetSeq *pins, VerilogAttrStmtSeq *attr_stmts, int line) : @@ -953,7 +952,7 @@ VerilogModuleInst::namedPins() } VerilogLibertyInst::VerilogLibertyInst(LibertyCell *cell, - const string &inst_name, + const std::string &inst_name, const StdStringSeq &net_names, VerilogAttrStmtSeq *attr_stmts, const int line) : @@ -1000,7 +999,7 @@ VerilogDcl::appendArg(VerilogDclArg *arg) args_->push_back(arg); } -const string & +const std::string & VerilogDcl::portName() { return (*args_)[0]->netName(); @@ -1036,7 +1035,7 @@ VerilogDclBus::size() const return abs(to_index_ - from_index_) + 1; } -VerilogDclArg::VerilogDclArg(const string &net_name) : +VerilogDclArg::VerilogDclArg(const std::string &net_name) : net_name_(net_name), assign_(nullptr) { @@ -1052,7 +1051,7 @@ VerilogDclArg::~VerilogDclArg() delete assign_; } -const string & +const std::string & VerilogDclArg::netName() { if (assign_) @@ -1082,29 +1081,29 @@ class VerilogNullNetNameIterator : public VerilogNetNameIterator { public: virtual bool hasNext() { return false; } - virtual const string &next(); + virtual const std::string &next(); }; -const string & +const std::string & VerilogNullNetNameIterator::next() { - static const string null; + static const std::string null; return null; } class VerilogOneNetNameIterator : public VerilogNetNameIterator { public: - VerilogOneNetNameIterator(const string &name); + VerilogOneNetNameIterator(const std::string &name); virtual bool hasNext(); - virtual const string &next(); + virtual const std::string &next(); protected: - string name_; + std::string name_; bool has_next_; }; -VerilogOneNetNameIterator::VerilogOneNetNameIterator(const string &name) : +VerilogOneNetNameIterator::VerilogOneNetNameIterator(const std::string &name) : name_(name), has_next_(true) { @@ -1116,7 +1115,7 @@ VerilogOneNetNameIterator::hasNext() return has_next_; } -const string & +const std::string & VerilogOneNetNameIterator::next() { has_next_ = false; @@ -1126,21 +1125,21 @@ VerilogOneNetNameIterator::next() class VerilogBusNetNameIterator : public VerilogNetNameIterator { public: - VerilogBusNetNameIterator(const string bus_name, + VerilogBusNetNameIterator(const std::string bus_name, int from_index, int to_index); virtual bool hasNext(); - virtual const string &next(); + virtual const std::string &next(); protected: - const string bus_name_; + const std::string bus_name_; int from_index_; int to_index_; int index_; - string bit_name_; + std::string bit_name_; }; -VerilogBusNetNameIterator::VerilogBusNetNameIterator(const string bus_name, +VerilogBusNetNameIterator::VerilogBusNetNameIterator(const std::string bus_name, int from_index, int to_index) : bus_name_(bus_name), @@ -1159,7 +1158,7 @@ VerilogBusNetNameIterator::hasNext() && index_ >= to_index_); } -const string & +const std::string & VerilogBusNetNameIterator::next() { bit_name_ = verilogBusBitName(bus_name_, index_); @@ -1170,8 +1169,8 @@ VerilogBusNetNameIterator::next() return bit_name_; } -static string -verilogBusBitName(const string &bus_name, +static std::string +verilogBusBitName(const std::string &bus_name, int index) { return stdstrPrint("%s[%d]", bus_name.c_str(), index); @@ -1181,22 +1180,22 @@ class VerilogConstantNetNameIterator : public VerilogNetNameIterator { public: VerilogConstantNetNameIterator(VerilogConstantValue *value, - const string &zero, - const string &one); + const std::string &zero, + const std::string &one); virtual bool hasNext(); - virtual const string &next(); + virtual const std::string &next(); private: VerilogConstantValue *value_; - const string &zero_; - const string &one_; + const std::string &zero_; + const std::string &one_; int bit_index_; }; VerilogConstantNetNameIterator:: VerilogConstantNetNameIterator(VerilogConstantValue *value, - const string &zero, - const string &one) : + const std::string &zero, + const std::string &one) : value_(value), zero_(zero), one_(one), @@ -1210,7 +1209,7 @@ VerilogConstantNetNameIterator::hasNext() return bit_index_ >= 0; } -const string & +const std::string & VerilogConstantNetNameIterator::next() { return (*value_)[bit_index_--] ? one_ : zero_; @@ -1224,7 +1223,7 @@ public: VerilogReader *reader); virtual ~VerilogNetConcatNameIterator(); virtual bool hasNext(); - virtual const string &next(); + virtual const std::string &next(); private: VerilogModule *module_; @@ -1262,7 +1261,7 @@ VerilogNetConcatNameIterator::hasNext() || net_iter_ != nets_->end(); } -const string & +const std::string & VerilogNetConcatNameIterator::next() { if (net_name_iter_ && net_name_iter_->hasNext()) @@ -1276,15 +1275,15 @@ VerilogNetConcatNameIterator::next() return net_name_iter_->next(); } } - static const string null; + static const std::string null; return null; } //////////////////////////////////////////////////////////////// -const string VerilogNetUnnamed::null_; +const std::string VerilogNetUnnamed::null_; -VerilogNetNamed::VerilogNetNamed(const string &name) : +VerilogNetNamed::VerilogNetNamed(const std::string &name) : VerilogNet(), name_(name) { @@ -1294,7 +1293,7 @@ VerilogNetNamed::~VerilogNetNamed() { } -VerilogNetScalar::VerilogNetScalar(const string &name) : +VerilogNetScalar::VerilogNetScalar(const std::string &name) : VerilogNetNamed(name) { } @@ -1318,7 +1317,7 @@ VerilogNetScalar::size(VerilogModule *module) } static VerilogNetNameIterator * -verilogNetScalarNameIterator(const string &name, +verilogNetScalarNameIterator(const std::string &name, VerilogModule *module) { if (!name.empty()) { @@ -1339,7 +1338,7 @@ VerilogNetScalar::nameIterator(VerilogModule *module, return verilogNetScalarNameIterator(name_.c_str(), module); } -VerilogNetBitSelect::VerilogNetBitSelect(const string &name, +VerilogNetBitSelect::VerilogNetBitSelect(const std::string &name, int index) : VerilogNetNamed(verilogBusBitName(name, index)), index_(index) @@ -1359,7 +1358,7 @@ VerilogNetBitSelect::nameIterator(VerilogModule *, return new VerilogOneNetNameIterator(name_); } -VerilogNetPartSelect::VerilogNetPartSelect(const string &name, +VerilogNetPartSelect::VerilogNetPartSelect(const std::string &name, int from_index, int to_index): VerilogNetNamed(name), @@ -1384,7 +1383,7 @@ VerilogNetPartSelect::nameIterator(VerilogModule *, return new VerilogBusNetNameIterator(name_.c_str(), from_index_, to_index_); } -VerilogNetConstant::VerilogNetConstant(const string *constant, +VerilogNetConstant::VerilogNetConstant(const std::string *constant, VerilogReader *reader, int line) { @@ -1392,13 +1391,13 @@ VerilogNetConstant::VerilogNetConstant(const string *constant, } void -VerilogNetConstant::parseConstant(const string *constant, +VerilogNetConstant::parseConstant(const std::string *constant, VerilogReader *reader, int line) { // Find constant size. size_t csize_end = constant->find('\''); - string csize = constant->substr(0, csize_end); + std::string csize = constant->substr(0, csize_end); // Read the constant size. size_t size = std::stol(csize); @@ -1434,7 +1433,7 @@ VerilogNetConstant::parseConstant(const string *constant, } void -VerilogNetConstant::parseConstant(const string *constant, +VerilogNetConstant::parseConstant(const std::string *constant, size_t base_idx, int base, int digit_bit_count) @@ -1463,13 +1462,13 @@ VerilogNetConstant::parseConstant(const string *constant, } void -VerilogNetConstant::parseConstant10(const string *constant, +VerilogNetConstant::parseConstant10(const std::string *constant, size_t base_idx, VerilogReader *reader, int line) { // Copy the constant skipping underscores. - string tmp; + std::string tmp; for (size_t i = base_idx + 1; i < constant->size(); i++) { char ch = constant->at(i); if (ch != '_') @@ -1478,7 +1477,7 @@ VerilogNetConstant::parseConstant10(const string *constant, size_t size = value_->size(); size_t length = tmp.size(); - const string &constant10_max = reader->constant10Max(); + const std::string &constant10_max = reader->constant10Max(); size_t max_length = constant10_max.size(); if (length > max_length || (length == max_length @@ -1546,18 +1545,18 @@ VerilogNetConcat::nameIterator(VerilogModule *module, return new VerilogNetConcatNameIterator(nets_, module, reader); } -VerilogNetPortRef::VerilogNetPortRef(const string &name) : +VerilogNetPortRef::VerilogNetPortRef(const std::string &name) : VerilogNetScalar(name) { } -VerilogNetPortRefScalarNet::VerilogNetPortRefScalarNet(const string &name) : +VerilogNetPortRefScalarNet::VerilogNetPortRefScalarNet(const std::string &name) : VerilogNetPortRef(name) { } -VerilogNetPortRefScalarNet::VerilogNetPortRefScalarNet(const string &name, - const string &net_name) : +VerilogNetPortRefScalarNet::VerilogNetPortRefScalarNet(const std::string &name, + const std::string &net_name) : VerilogNetPortRef(name), net_name_(net_name) { @@ -1584,7 +1583,7 @@ VerilogNetPortRefScalarNet::nameIterator(VerilogModule *module, return verilogNetScalarNameIterator(net_name_, module); } -VerilogNetPortRefScalar::VerilogNetPortRefScalar(const string &name, +VerilogNetPortRefScalar::VerilogNetPortRefScalar(const std::string &name, VerilogNet *net) : VerilogNetPortRef(name), net_(net) @@ -1615,7 +1614,7 @@ VerilogNetPortRefScalar::nameIterator(VerilogModule *module, return new VerilogNullNetNameIterator(); } -VerilogNetPortRefBit::VerilogNetPortRefBit(const string &name, +VerilogNetPortRefBit::VerilogNetPortRefBit(const std::string &name, int index, VerilogNet *net) : VerilogNetPortRefScalar(name, net), @@ -1623,7 +1622,7 @@ VerilogNetPortRefBit::VerilogNetPortRefBit(const string &name, { } -VerilogNetPortRefPart::VerilogNetPortRefPart(const string &name, +VerilogNetPortRefPart::VerilogNetPortRefPart(const std::string &name, int from_index, int to_index, VerilogNet *net) : @@ -1632,26 +1631,26 @@ VerilogNetPortRefPart::VerilogNetPortRefPart(const string &name, { } -const string & +const std::string & VerilogNetPortRefPart::name() const { return name_; } -VerilogAttrEntry::VerilogAttrEntry(const string &key, - const string &value) : +VerilogAttrEntry::VerilogAttrEntry(const std::string &key, + const std::string &value) : key_(key), value_(value) { } -string +std::string VerilogAttrEntry::key() { return key_; } -string +std::string VerilogAttrEntry::value() { return value_; @@ -1687,8 +1686,8 @@ using BindingMap = std::map; class VerilogBindingTbl { public: - VerilogBindingTbl(const string &zero_net_name_, - const string &one_net_name_); + VerilogBindingTbl(const std::string &zero_net_name_, + const std::string &one_net_name_); Net *ensureNetBinding(const char *net_name, Instance *inst, NetworkReader *network); @@ -1698,8 +1697,8 @@ public: Net *net); private: - const string &zero_net_name_; - const string &one_net_name_; + const std::string &zero_net_name_; + const std::string &one_net_name_; BindingMap map_; }; @@ -1719,7 +1718,7 @@ VerilogReader::linkNetwork(const char *top_cell_name, VerilogNetNameIterator *net_name_iter = mod_port->nameIterator(module, this); while (net_name_iter->hasNext()) { - const string &net_name = net_name_iter->next(); + const std::string &net_name = net_name_iter->next(); Port *port = network_->findPort(top_cell, net_name.c_str()); Net *net = bindings.ensureNetBinding(net_name.c_str(), top_instance, network_); // Guard against repeated port name. @@ -1795,10 +1794,10 @@ VerilogReader::makeModuleInstNetwork(VerilogModuleInst *mod_inst, VerilogBindingTbl *parent_bindings, bool make_black_boxes) { - const string &module_name = mod_inst->moduleName(); + const std::string &module_name = mod_inst->moduleName(); Cell *cell = network_->findAnyCell(module_name.c_str()); if (cell == nullptr) { - string inst_vname = instanceVerilogName(mod_inst->instanceName().c_str()); + std::string inst_vname = instanceVerilogName(mod_inst->instanceName().c_str()); if (make_black_boxes) { cell = makeBlackBox(mod_inst, parent_module); linkWarn(198, parent_module->filename(), mod_inst->line(), @@ -1861,7 +1860,7 @@ VerilogReader::makeNamedInstPins(Cell *cell, VerilogBindingTbl *parent_bindings, bool is_leaf) { - string inst_vname = instanceVerilogName(mod_inst->instanceName().c_str()); + std::string inst_vname = instanceVerilogName(mod_inst->instanceName().c_str()); for (auto mpin : *mod_inst->pins()) { VerilogNetPortRef *vpin = dynamic_cast(mpin); const char *port_name = vpin->name().c_str(); @@ -1921,7 +1920,7 @@ VerilogReader::makeOrderedInstPins(Cell *cell, VerilogNet *net = *pin_iter++; Port *port = port_iter->next(); if (network_->size(port) != net->size(parent_module)) { - string inst_vname = instanceVerilogName(mod_inst->instanceName().c_str()); + std::string inst_vname = instanceVerilogName(mod_inst->instanceName().c_str()); linkWarn(202, parent_module->filename(), mod_inst->line(), "instance %s port %s size %d does not match net size %d.", inst_vname.c_str(), @@ -1959,7 +1958,7 @@ VerilogReader::makeInstPin(Instance *inst, VerilogBindingTbl *parent_bindings, bool is_leaf) { - string net_name; + std::string net_name; if (net_name_iter->hasNext()) net_name = net_name_iter->next(); makeInstPin(inst, port, net_name, bindings, parent, parent_bindings, @@ -1969,7 +1968,7 @@ VerilogReader::makeInstPin(Instance *inst, void VerilogReader::makeInstPin(Instance *inst, Port *port, - const string &net_name, + const std::string &net_name, VerilogBindingTbl *bindings, Instance *parent, VerilogBindingTbl *parent_bindings, @@ -2013,7 +2012,7 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst, LibertyCellPortBitIterator port_iter(lib_cell); while (port_iter.hasNext()) { LibertyPort *port = port_iter.next(); - const string &net_name = net_names[port->pinIndex()]; + const std::string &net_name = net_names[port->pinIndex()]; // net_name may be the name of a single bit bus. if (!net_name.empty()) { Net *net = nullptr; @@ -2023,7 +2022,7 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst, if (dcl && dcl->isBus()) { VerilogDclBus *dcl_bus = dynamic_cast(dcl); // Bus is only 1 bit wide. - string bus_name = verilogBusBitName(net_name, dcl_bus->fromIndex()); + std::string bus_name = verilogBusBitName(net_name, dcl_bus->fromIndex()); net = parent_bindings->ensureNetBinding(bus_name.c_str(), parent, network_); } else @@ -2042,7 +2041,7 @@ Cell * VerilogReader::makeBlackBox(VerilogModuleInst *mod_inst, VerilogModule *parent_module) { - const string &module_name = mod_inst->moduleName(); + const std::string &module_name = mod_inst->moduleName(); Cell *cell = network_->makeCell(library_, module_name.c_str(), true, parent_module->filename()); if (mod_inst->namedPins()) @@ -2109,8 +2108,8 @@ VerilogReader::mergeAssignNet(VerilogAssign *assign, VerilogNetNameIterator *lhs_iter = lhs->nameIterator(module, this); VerilogNetNameIterator *rhs_iter = rhs->nameIterator(module, this); while (lhs_iter->hasNext() && rhs_iter->hasNext()) { - const string &lhs_name = lhs_iter->next(); - const string &rhs_name = rhs_iter->next(); + const std::string &lhs_name = lhs_iter->next(); + const std::string &rhs_name = rhs_iter->next(); Net *lhs_net = bindings->ensureNetBinding(lhs_name.c_str(), inst, network_); Net *rhs_net = bindings->ensureNetBinding(rhs_name.c_str(), inst, network_); // Merge lower level net into higher level net so that deleting @@ -2148,8 +2147,8 @@ hierarchyLevel(Net *net, //////////////////////////////////////////////////////////////// -VerilogBindingTbl::VerilogBindingTbl(const string &zero_net_name, - const string &one_net_name) : +VerilogBindingTbl::VerilogBindingTbl(const std::string &zero_net_name, + const std::string &one_net_name) : zero_net_name_(zero_net_name), one_net_name_(one_net_name) { diff --git a/verilog/VerilogWriter.cc b/verilog/VerilogWriter.cc index 3ba02ba9..a38e44b9 100644 --- a/verilog/VerilogWriter.cc +++ b/verilog/VerilogWriter.cc @@ -24,9 +24,10 @@ #include "VerilogWriter.hh" -#include #include +#include #include +#include #include "Error.hh" #include "Liberty.hh" @@ -38,10 +39,6 @@ namespace sta { -using std::min; -using std::max; -using std::string; - class VerilogWriter { public: @@ -284,8 +281,8 @@ VerilogWriter::writeWireDcls(const Instance *inst) int index; parseBusName(net_name, '[', ']', escape, is_bus, bus_name, index); BusIndexRange &range = bus_ranges[bus_name]; - range.first = max(range.first, index); - range.second = min(range.second, index); + range.first = std::max(range.first, index); + range.second = std::min(range.second, index); } else { std::string net_vname = netVerilogName(net_name); @@ -337,8 +334,8 @@ VerilogWriter::writeChild(const Instance *child) Cell *child_cell = network_->cell(child); if (!remove_cells_.contains(child_cell)) { const char *child_name = network_->name(child); - string child_vname = instanceVerilogName(child_name); - string child_cell_vname = cellVerilogName(network_->name(child_cell)); + std::string child_vname = instanceVerilogName(child_name); + std::string child_cell_vname = cellVerilogName(network_->name(child_cell)); fprintf(stream_, " %s %s (", child_cell_vname.c_str(), child_vname.c_str()); @@ -369,10 +366,10 @@ VerilogWriter::writeInstPin(const Instance *inst, Net *net = network_->net(pin); if (net) { const char *net_name = network_->name(net); - string net_vname = netVerilogName(net_name); + std::string net_vname = netVerilogName(net_name); if (!first_port) fprintf(stream_, ",\n "); - string port_vname = portVerilogName(network_->name(port)); + std::string port_vname = portVerilogName(network_->name(port)); fprintf(stream_, ".%s(%s)", port_vname.c_str(), net_vname.c_str()); @@ -422,13 +419,13 @@ VerilogWriter::writeInstBusPinBit(const Instance *inst, { Pin *pin = network_->findPin(inst, port); Net *net = pin ? network_->net(pin) : nullptr; - string net_name; + std::string net_name; if (net) net_name = network_->name(net); else // There is no verilog syntax to "skip" a bit in the concatentation. stringPrint(net_name, "_NC%d", unconnected_net_index_++); - string net_vname = netVerilogName(net_name.c_str()); + std::string net_vname = netVerilogName(net_name.c_str()); if (!first_member) fprintf(stream_, ",\n "); fprintf(stream_, "%s", net_vname.c_str()); @@ -455,8 +452,8 @@ VerilogWriter::writeAssigns(const Instance *inst) || (include_pwr_gnd_ && network_->direction(port)->isPowerGround())) && !stringEqual(network_->name(port), network_->name(net))) { // Port name is different from net name. - string port_vname = netVerilogName(network_->name(port)); - string net_vname = netVerilogName(network_->name(net)); + std::string port_vname = netVerilogName(network_->name(port)); + std::string net_vname = netVerilogName(network_->name(net)); fprintf(stream_, " assign %s = %s;\n", port_vname.c_str(), net_vname.c_str()); From e054499e4592cd07c0b5fed2e4d7c413d0b4906d Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 2 Mar 2026 13:22:13 -0800 Subject: [PATCH 13/22] report_arrival requires not needed Signed-off-by: James Cherry --- include/sta/Sta.hh | 2 ++ search/Sta.cc | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index ddb2f7d7..ed1c6c47 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1517,10 +1517,12 @@ protected: void reportDelaysWrtClks(const Pin *pin, const Scene *scene, int digits, + bool find_required, PathDelayFunc get_path_delay); void reportDelaysWrtClks(Vertex *vertex, const Scene *scene, int digits, + bool find_required, PathDelayFunc get_path_delay); void reportDelaysWrtClks(Vertex *vertex, const ClockEdge *clk_edge, diff --git a/search/Sta.cc b/search/Sta.cc index 5c096867..fa1c3bb4 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -3270,7 +3270,8 @@ Sta::reportArrivalWrtClks(const Pin *pin, const Scene *scene, int digits) { - reportDelaysWrtClks(pin, scene, digits, + searchPreamble(); + reportDelaysWrtClks(pin, scene, digits, false, [] (const Path *path) { return path->arrival(); }); @@ -3281,7 +3282,7 @@ Sta::reportRequiredWrtClks(const Pin *pin, const Scene *scene, int digits) { - reportDelaysWrtClks(pin, scene, digits, + reportDelaysWrtClks(pin, scene, digits, true, [] (const Path *path) { return path->required(); }); @@ -3292,7 +3293,7 @@ Sta::reportSlackWrtClks(const Pin *pin, const Scene *scene, int digits) { - reportDelaysWrtClks(pin, scene, digits, + reportDelaysWrtClks(pin, scene, digits, true, [this] (const Path *path) { return path->slack(this); }); @@ -3302,24 +3303,29 @@ void Sta::reportDelaysWrtClks(const Pin *pin, const Scene *scene, int digits, + bool find_required, PathDelayFunc get_path_delay) { ensureGraph(); Vertex *vertex, *bidir_vertex; graph_->pinVertices(pin, vertex, bidir_vertex); if (vertex) - reportDelaysWrtClks(vertex, scene, digits, get_path_delay); + reportDelaysWrtClks(vertex, scene, digits, find_required, get_path_delay); if (bidir_vertex) - reportDelaysWrtClks(vertex, scene, digits, get_path_delay); + reportDelaysWrtClks(vertex, scene, digits, find_required, get_path_delay); } void Sta::reportDelaysWrtClks(Vertex *vertex, const Scene *scene, int digits, + bool find_required, PathDelayFunc get_path_delay) { - findRequired(vertex); + if (find_required) + findRequired(vertex); + else + search_->findArrivals(vertex->level()); const Sdc *sdc = scene->sdc(); reportDelaysWrtClks(vertex, nullptr, scene, digits, get_path_delay); const ClockEdge *default_clk_edge = sdc->defaultArrivalClock()->edge(RiseFall::rise()); From f89fcbfa115e74add71487218ff3b76e30023288 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 2 Mar 2026 16:26:14 -0800 Subject: [PATCH 14/22] tcl sta::is_ideal_clock Signed-off-by: James Cherry --- include/sta/Sta.hh | 8 ++++---- search/Search.i | 9 +++++++++ search/Sta.cc | 13 +++++++++---- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index ed1c6c47..718f97ae 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1297,13 +1297,13 @@ public: void clkPinsInvalid(const Mode *mode); // The following functions assume ensureClkNetwork() has been called. bool isClock(const Pin *pin, - const Mode *mode) const; + const Mode *mode); bool isClock(const Net *net, - const Mode *mode) const; + const Mode *mode); bool isIdealClock(const Pin *pin, - const Mode *mode) const; + const Mode *mode); bool isPropagatedClock(const Pin *pin, - const Mode *mode) const; + const Mode *mode); const PinSet *pins(const Clock *clk, const Mode *mode); diff --git a/search/Search.i b/search/Search.i index 8978d530..67d84876 100644 --- a/search/Search.i +++ b/search/Search.i @@ -335,6 +335,15 @@ slow_drivers(int count) return Sta::sta()->slowDrivers(count); } +bool +is_ideal_clock(const Pin *pin) +{ + Sta *sta = Sta::sta(); + const Mode *mode = sta->cmdMode(); + sta->ensureClkNetwork(); + return sta->isIdealClock(pin, mode); +} + //////////////////////////////////////////////////////////////// PathEndSeq diff --git a/search/Sta.cc b/search/Sta.cc index fa1c3bb4..2d91a4f4 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -6054,28 +6054,31 @@ Sta::ensureClkNetwork(const Mode *mode) bool Sta::isClock(const Pin *pin, - const Mode *mode) const + const Mode *mode) { + ensureClkNetwork(mode); return mode->clkNetwork()->isClock(pin); } bool Sta::isClock(const Net *net, - const Mode *mode) const + const Mode *mode) { + ensureClkNetwork(mode); return mode->clkNetwork()->isClock(net); } bool Sta::isIdealClock(const Pin *pin, - const Mode *mode) const + const Mode *mode) { + ensureClkNetwork(mode); return mode->clkNetwork()->isIdealClock(pin); } bool Sta::isPropagatedClock(const Pin *pin, - const Mode *mode) const + const Mode *mode) { return mode->clkNetwork()->isPropagatedClock(pin); } @@ -6084,12 +6087,14 @@ const PinSet * Sta::pins(const Clock *clk, const Mode *mode) { + ensureClkNetwork(mode); return mode->clkNetwork()->pins(clk); } void Sta::clkPinsInvalid(const Mode *mode) { + ensureClkNetwork(mode); mode->clkNetwork()->clkPinsInvalid(); } From 6f4cdcfea8efa9bb277b6d09909a5fba8bbf5a49 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 2 Mar 2026 16:41:35 -0800 Subject: [PATCH 15/22] tcl sta::is_ideal_clock Signed-off-by: James Cherry --- search/Search.i | 1 - 1 file changed, 1 deletion(-) diff --git a/search/Search.i b/search/Search.i index 67d84876..550f1b00 100644 --- a/search/Search.i +++ b/search/Search.i @@ -340,7 +340,6 @@ is_ideal_clock(const Pin *pin) { Sta *sta = Sta::sta(); const Mode *mode = sta->cmdMode(); - sta->ensureClkNetwork(); return sta->isIdealClock(pin, mode); } From 73e1a392c5998e3e15b5942f5c1b8b22ec7abb08 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 2 Mar 2026 16:47:40 -0800 Subject: [PATCH 16/22] rm unused Sta::report functions Signed-off-by: James Cherry --- include/sta/Sta.hh | 10 ---------- search/Search.i | 20 -------------------- search/Sta.cc | 20 -------------------- 3 files changed, 50 deletions(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 718f97ae..5bc48f70 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -988,16 +988,6 @@ public: void setReportPathDigits(int digits); void setReportPathNoSplit(bool no_split); void setReportPathSigmas(bool report_sigmas); - // Header above reportPathEnd results. - void reportPathEndHeader(); - // Footer below reportPathEnd results. - void reportPathEndFooter(); - // Format report_path_endpoint only: - // Previous path end is used to detect path group changes - // so headers are reported by group. - void reportPathEnd(PathEnd *end, - PathEnd *prev_end, - bool last); void reportPathEnd(PathEnd *end); void reportPathEnds(PathEndSeq *ends); ReportPath *reportPath() { return report_path_; } diff --git a/search/Search.i b/search/Search.i index 550f1b00..8ffff0ff 100644 --- a/search/Search.i +++ b/search/Search.i @@ -382,32 +382,12 @@ find_path_ends(ExceptionFrom *from, //////////////////////////////////////////////////////////////// -void -report_path_end_header() -{ - Sta::sta()->reportPathEndHeader(); -} - -void -report_path_end_footer() -{ - Sta::sta()->reportPathEndFooter(); -} - void report_path_end(PathEnd *end) { Sta::sta()->reportPathEnd(end); } -void -report_path_end2(PathEnd *end, - PathEnd *prev_end, - bool last) -{ - Sta::sta()->reportPathEnd(end, prev_end, last); -} - void set_report_path_format(ReportPathFormat format) { diff --git a/search/Sta.cc b/search/Sta.cc index 2d91a4f4..7899a110 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2772,32 +2772,12 @@ Sta::setReportPathSigmas(bool report_sigmas) report_path_->setReportSigmas(report_sigmas); } -void -Sta::reportPathEndHeader() -{ - report_path_->reportPathEndHeader(); -} - -void -Sta::reportPathEndFooter() -{ - report_path_->reportPathEndFooter(); -} - void Sta::reportPathEnd(PathEnd *end) { report_path_->reportPathEnd(end); } -void -Sta::reportPathEnd(PathEnd *end, - PathEnd *prev_end, - bool last) -{ - report_path_->reportPathEnd(end, prev_end, last); -} - void Sta::reportPathEnds(PathEndSeq *ends) { From eb0446d4e20679fcacd85d941069fbe83b4d7d87 Mon Sep 17 00:00:00 2001 From: Deepashree Sengupta Date: Tue, 3 Mar 2026 00:48:15 +0000 Subject: [PATCH 17/22] Write verilog escape (#394) * Fir for write_verilog issue 3826 Signed-off-by: dsengupta0628 * staToVerilog2 remove escaped_name+=ch Signed-off-by: dsengupta0628 * updated regression to remove \ from module name Signed-off-by: dsengupta0628 * Using helpers.tcl function to redirect results Signed-off-by: dsengupta0628 * add std::string and remove trailing space, update regression name Signed-off-by: dsengupta0628 * update regression to reflect correct output verilog name Signed-off-by: dsengupta0628 --------- Signed-off-by: dsengupta0628 --- network/VerilogNamespace.cc | 10 ++-------- test/regression_vars.tcl | 1 + test/verilog_write_escape.ok | 18 ++++++++++++++++++ test/verilog_write_escape.tcl | 10 ++++++++++ test/verilog_write_escape.v | 13 +++++++++++++ verilog/VerilogWriter.cc | 3 ++- 6 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 test/verilog_write_escape.ok create mode 100644 test/verilog_write_escape.tcl create mode 100644 test/verilog_write_escape.v diff --git a/network/VerilogNamespace.cc b/network/VerilogNamespace.cc index 5362d115..1d0231d9 100644 --- a/network/VerilogNamespace.cc +++ b/network/VerilogNamespace.cc @@ -86,15 +86,12 @@ staToVerilog(const char *sta_name) for (const char *s = sta_name; *s ; s++) { char ch = s[0]; if (ch == verilog_escape) { + escaped = true; char next_ch = s[1]; if (next_ch == verilog_escape) { - escaped_name += ch; escaped_name += next_ch; s++; } - else - // Skip escape. - escaped = true; } else { if ((!(isalnum(ch) || ch == '_'))) @@ -124,15 +121,12 @@ staToVerilog2(const char *sta_name) for (const char *s = sta_name; *s ; s++) { char ch = s[0]; if (ch == verilog_escape) { + escaped = true; char next_ch = s[1]; if (next_ch == verilog_escape) { - escaped_name += ch; escaped_name += next_ch; s++; } - else - // Skip escape. - escaped = true; } else { bool is_brkt = (ch == bus_brkt_left || ch == bus_brkt_right); diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index c1ed29ea..ab1f6c62 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -165,6 +165,7 @@ record_public_tests { suppress_msg verilog_attribute verilog_specify + verilog_write_escape } define_test_group fast [group_tests all] diff --git a/test/verilog_write_escape.ok b/test/verilog_write_escape.ok new file mode 100644 index 00000000..4906a851 --- /dev/null +++ b/test/verilog_write_escape.ok @@ -0,0 +1,18 @@ +module multi_sink (clk); + input clk; + + wire \alu_adder_result_ex[0] ; + + hier_block \h1\x (.childclk(clk), + .\Y[2:1] ({\alu_adder_result_ex[0] , + \alu_adder_result_ex[0] })); +endmodule +module hier_block (childclk, + \Y[2:1] ); + input childclk; + output [1:0] \Y[2:1] ; + + + BUFx2_ASAP7_75t_R \abuf_$100 (.A(childclk)); + BUFx2_ASAP7_75t_R \ff0/name (.A(childclk)); +endmodule diff --git a/test/verilog_write_escape.tcl b/test/verilog_write_escape.tcl new file mode 100644 index 00000000..29e78590 --- /dev/null +++ b/test/verilog_write_escape.tcl @@ -0,0 +1,10 @@ +# Check if "h1\x" and \Y[2:1] are correctly processed from input to output of Verilog +source helpers.tcl +read_liberty gf180mcu_sram.lib.gz +read_liberty asap7_small.lib.gz +read_verilog verilog_write_escape.v +link_design multi_sink +set verilog_file [make_result_file "verilog_write_escape.v"] +write_verilog $verilog_file +report_file $verilog_file +read_verilog $verilog_file diff --git a/test/verilog_write_escape.v b/test/verilog_write_escape.v new file mode 100644 index 00000000..e0c43c3e --- /dev/null +++ b/test/verilog_write_escape.v @@ -0,0 +1,13 @@ +module multi_sink (clk); + input clk; + wire \alu_adder_result_ex[0] ; + \hier_block \h1\x (.childclk(clk), .\Y[2:1] ({ \alu_adder_result_ex[0] , \alu_adder_result_ex[0] }) ); +endmodule // multi_sink + +module hier_block (childclk, \Y[2:1] ); + input childclk; + output [1:0] \Y[2:1] ; + wire [1:0] \Y[2:1] ; + BUFx2_ASAP7_75t_R \abuf_$100 (.A(childclk)); + BUFx2_ASAP7_75t_R \ff0/name (.A(childclk)); +endmodule // hier_block1 diff --git a/verilog/VerilogWriter.cc b/verilog/VerilogWriter.cc index a38e44b9..3d6e274c 100644 --- a/verilog/VerilogWriter.cc +++ b/verilog/VerilogWriter.cc @@ -386,7 +386,8 @@ VerilogWriter::writeInstBusPin(const Instance *inst, if (!first_port) fprintf(stream_, ",\n "); - fprintf(stream_, ".%s({", network_->name(port)); + std::string port_vname = portVerilogName(network_->name(port)); + fprintf(stream_, ".%s({", port_vname.c_str()); first_port = false; bool first_member = true; From 62cd210a8aff98cb8bf795e7b70c610faf5deebb Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 3 Mar 2026 07:59:09 -0800 Subject: [PATCH 18/22] back edge->to is a root resolves #395 Signed-off-by: James Cherry --- search/Levelize.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/Levelize.cc b/search/Levelize.cc index d04891bf..5a0127b0 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -323,7 +323,7 @@ Levelize::findCycleBackEdges() stack.emplace(vertex, new VertexOutEdgeIterator(vertex, graph_)); EdgeSet back_edges = findBackEdges(path, stack); for (Edge *back_edge : back_edges) - roots_.insert(back_edge->from(graph_)); + roots_.insert(back_edge->to(graph_)); back_edge_count += back_edges.size(); } } From 8ed837d74b6c341f574284024de1343127014692 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 5 Mar 2026 13:33:58 -0800 Subject: [PATCH 19/22] relevelize latch EN->Q Signed-off-by: James Cherry --- Dockerfile.ubuntu22.04 | 2 ++ include/sta/TimingRole.hh | 1 + liberty/TimingRole.cc | 6 ++++++ search/Levelize.cc | 29 ++++++++++++++++++++++++----- search/Sta.cc | 28 ++++++++++++++++------------ 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/Dockerfile.ubuntu22.04 b/Dockerfile.ubuntu22.04 index 9a803c8f..e636fc21 100644 --- a/Dockerfile.ubuntu22.04 +++ b/Dockerfile.ubuntu22.04 @@ -6,9 +6,11 @@ LABEL maintainer="James Cherry " ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get install -y \ + git \ wget \ cmake \ gcc \ + gdb \ tcl-dev \ tcl-tclreadline \ libeigen3-dev \ diff --git a/include/sta/TimingRole.hh b/include/sta/TimingRole.hh index 3621f63c..d77a8454 100644 --- a/include/sta/TimingRole.hh +++ b/include/sta/TimingRole.hh @@ -78,6 +78,7 @@ public: [[nodiscard]] bool isNonSeqTimingCheck() const { return is_non_seq_check_; } [[nodiscard]] bool isDataCheck() const; [[nodiscard]] bool isLatchDtoQ() const; + [[nodiscard]] bool isLatchEnToQ() const; const TimingRole *genericRole() const; const TimingRole *sdfRole() const; // Timing check data path min/max. diff --git a/liberty/TimingRole.cc b/liberty/TimingRole.cc index 1839e52f..e772d1bc 100644 --- a/liberty/TimingRole.cc +++ b/liberty/TimingRole.cc @@ -163,6 +163,12 @@ TimingRole::isLatchDtoQ() const return this == &latch_d_q_; } +bool +TimingRole::isLatchEnToQ() const +{ + return this == &latch_en_q_; +} + bool TimingRole::isTimingCheckBetween() const { diff --git a/search/Levelize.cc b/search/Levelize.cc index 5a0127b0..a53f8f7e 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -526,8 +526,16 @@ Levelize::ensureLatchLevels() for (Edge *edge : latch_d_to_q_edges_) { Vertex *from = edge->from(graph_); Vertex *to = edge->to(graph_); - if (from->level() == to->level()) - setLevel(from, from->level() + level_space_); + if (from->level() == to->level()) { + Level adjusted_level = from->level() + level_space_; + debugPrint(debug_, "levelize", 2, "latch %s %d (adjusted %d) -> %s %d", + from->to_string(this).c_str(), + from->level(), + adjusted_level, + to->to_string(this).c_str(), + to->level()); + setLevel(from, adjusted_level); + } } latch_d_to_q_edges_.clear(); } @@ -536,7 +544,7 @@ void Levelize::setLevel(Vertex *vertex, Level level) { - debugPrint(debug_, "levelize", 2, "set level %s %d", + debugPrint(debug_, "levelize", 3, "set level %s %d", vertex->to_string(this).c_str(), level); vertex->setLevel(level); @@ -602,7 +610,7 @@ void Levelize::relevelize() { for (Vertex *vertex : relevelize_from_) { - debugPrint(debug_, "levelize", 1, "relevelize from %s", + debugPrint(debug_, "levelize", 2, "relevelize from %s", vertex->to_string(this).c_str()); if (isRoot(vertex)) roots_.insert(vertex); @@ -641,9 +649,20 @@ Levelize::visit(Vertex *vertex, visit(to_vertex, edge, level+level_space, level_space, path_vertices, path); } - if (edge->role() == TimingRole::latchDtoQ()) + + const TimingRole *role = edge->role(); + if (role->isLatchDtoQ()) latch_d_to_q_edges_.insert(edge); + if (role->isLatchEnToQ()) { + VertexInEdgeIterator edge_iter2(to_vertex, graph_); + while (edge_iter2.hasNext()) { + Edge *edge2 = edge_iter2.next(); + if (edge2->role()->isLatchDtoQ()) + latch_d_to_q_edges_.insert(edge2); + } + } } + // Levelize bidirect driver as if it was a fanout of the bidirect load. if (graph_delay_calc_->bidirectDrvrSlewFromLoad(from_pin) && !vertex->isBidirectDriver()) { diff --git a/search/Sta.cc b/search/Sta.cc index 7899a110..527e8ee1 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -4671,12 +4671,14 @@ Sta::connectLoadPinAfter(Vertex *vertex) VertexInEdgeIterator edge_iter(vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - Vertex *from_vertex = edge->from(graph_); - graph_delay_calc_->delayInvalid(from_vertex); - search_->requiredInvalid(from_vertex); - for (Mode *mode : modes_) - mode->sdc()->clkHpinDisablesChanged(from_vertex->pin()); - levelize_->relevelizeFrom(from_vertex); + if (!edge->role()->isTimingCheck()) { + Vertex *from_vertex = edge->from(graph_); + graph_delay_calc_->delayInvalid(from_vertex); + search_->requiredInvalid(from_vertex); + levelize_->relevelizeFrom(from_vertex); + for (Mode *mode : modes_) + mode->sdc()->clkHpinDisablesChanged(from_vertex->pin()); + } } Pin *pin = vertex->pin(); for (Mode *mode : modes_) { @@ -4754,12 +4756,14 @@ Sta::deleteEdge(Edge *edge) edge->from(graph_)->name(sdc_network_), edge->to(graph_)->name(sdc_network_)); Vertex *to = edge->to(graph_); - search_->deleteEdgeBefore(edge); - graph_delay_calc_->delayInvalid(to); - levelize_->relevelizeFrom(to); - levelize_->deleteEdgeBefore(edge); - for (Mode *mode : modes_) - mode->sdc()->clkHpinDisablesChanged(edge->from(graph_)->pin()); + if (!edge->role()->isTimingCheck()) { + search_->deleteEdgeBefore(edge); + graph_delay_calc_->delayInvalid(to); + levelize_->relevelizeFrom(to); + levelize_->deleteEdgeBefore(edge); + for (Mode *mode : modes_) + mode->sdc()->clkHpinDisablesChanged(edge->from(graph_)->pin()); + } graph_->deleteEdge(edge); } From f1e5587fef8115ccdb32a57d0196d22be348e11c Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 5 Mar 2026 18:41:25 -0700 Subject: [PATCH 20/22] rapidus liberty latch D->Q/EN->Q matching Signed-off-by: James Cherry --- include/sta/TimingArc.hh | 1 + liberty/Liberty.cc | 88 +++++++++++++++++++++++----------------- liberty/Liberty.i | 10 +++++ liberty/Liberty.tcl | 10 ++++- liberty/LibertyReader.cc | 47 ++++++++++++--------- liberty/TimingArc.cc | 3 +- 6 files changed, 98 insertions(+), 61 deletions(-) diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index 63c04d49..257e446d 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -176,6 +176,7 @@ public: // other conditional timing arcs between the same pins. bool isCondDefault() const { return is_cond_default_; } void setIsCondDefault(bool is_default); + const FuncExpr *when() const { return attrs_->cond(); } // SDF IOPATHs match sdfCond. // sdfCond (IOPATH) reuses sdfCondStart (timing check) variable. const std::string &sdfCond() const { return attrs_->sdfCondStart(); } diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 130af802..181b0e42 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -1679,45 +1679,58 @@ LibertyCell::makeLatchEnables(Report *report, { if (hasSequentials() || hasInferedRegTimingArcs()) { - for (auto en_to_q : timing_arc_sets_) { - if (en_to_q->role() == TimingRole::latchEnToQ()) { - LibertyPort *en = en_to_q->from(); - LibertyPort *q = en_to_q->to(); - for (TimingArcSet *d_to_q : timingArcSetsTo(q)) { - if (d_to_q->role() == TimingRole::latchDtoQ() - && condMatch(en_to_q, d_to_q)) { - LibertyPort *d = d_to_q->from(); - const RiseFall *en_rf = en_to_q->isRisingFallingEdge(); - if (en_rf) { - TimingArcSet *setup_check = findLatchSetup(d, en, en_rf, q, d_to_q, - report); - LatchEnable *latch_enable = makeLatchEnable(d, en, en_rf, q, d_to_q, - en_to_q, - setup_check, - debug); - FuncExpr *en_func = latch_enable->enableFunc(); - if (en_func) { - TimingSense en_sense = en_func->portTimingSense(en); - if (en_sense == TimingSense::positive_unate - && en_rf != RiseFall::rise()) - report->warn(1114, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.", - library_->name(), - name(), - en->name(), - q->name(), - en_rf == RiseFall::rise()?"rising":"falling"); - else if (en_sense == TimingSense::negative_unate - && en_rf != RiseFall::fall()) - report->warn(1115, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.", - library_->name(), - name(), - en->name(), - q->name(), - en_rf == RiseFall::rise()?"rising":"falling"); - } + for (TimingArcSet *d_to_q : timing_arc_sets_) { + if (d_to_q->role() == TimingRole::latchDtoQ()) { + LibertyPort *d = d_to_q->from(); + LibertyPort *q = d_to_q->to(); + TimingArcSet *en_to_q = nullptr; + TimingArcSet *en_to_q_when = nullptr; + // Prefer en_to_q with matching when. + for (TimingArcSet *arc_to_q : timingArcSetsTo(q)) { + if (arc_to_q->role() == TimingRole::latchEnToQ()) { + if (condMatch(arc_to_q, d_to_q)) + en_to_q_when = arc_to_q; + else + en_to_q = arc_to_q; + } + } + if (en_to_q_when) + en_to_q = en_to_q_when; + if (en_to_q) { + LibertyPort *en = en_to_q->from(); + const RiseFall *en_rf = en_to_q->isRisingFallingEdge(); + if (en_rf) { + TimingArcSet *setup_check = findLatchSetup(d, en, en_rf, q, d_to_q, report); + LatchEnable *latch_enable = makeLatchEnable(d, en, en_rf, q, d_to_q, + en_to_q, setup_check, debug); + FuncExpr *en_func = latch_enable->enableFunc(); + if (en_func) { + TimingSense en_sense = en_func->portTimingSense(en); + if (en_sense == TimingSense::positive_unate + && en_rf != RiseFall::rise()) + report->warn(1114, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.", + library_->name(), + name(), + en->name(), + q->name(), + en_rf == RiseFall::rise()?"rising":"falling"); + else if (en_sense == TimingSense::negative_unate + && en_rf != RiseFall::fall()) + report->warn(1115, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.", + library_->name(), + name(), + en->name(), + q->name(), + en_rf == RiseFall::rise()?"rising":"falling"); } } } + else + report->warn(1121, "cell %s/%s no latch enable found for %s -> %s.", + library_->name(), + name(), + d->name(), + q->name()); } } } @@ -1810,8 +1823,7 @@ LibertyCell::makeLatchEnable(LibertyPort *d, Debug *debug) { FuncExpr *en_func = findLatchEnableFunc(d, en, en_rf); - latch_enables_.emplace_back(d, en, en_rf, en_func, q, d_to_q, en_to_q, - setup_check); + latch_enables_.emplace_back(d, en, en_rf, en_func, q, d_to_q, en_to_q, setup_check); size_t idx = latch_enables_.size() - 1; latch_d_to_q_map_[d_to_q] = idx; latch_check_map_[setup_check] = idx; diff --git a/liberty/Liberty.i b/liberty/Liberty.i index 2257b2eb..d2856e68 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -379,6 +379,16 @@ full_name() to); } +const std::string +when() +{ + const FuncExpr *when = self->when(); + if (when) + return when->to_string(); + else + return ""; +} + TimingArcSeq & timing_arcs() { return self->arcs(); } diff --git a/liberty/Liberty.tcl b/liberty/Liberty.tcl index fd75a8bf..6d93601d 100644 --- a/liberty/Liberty.tcl +++ b/liberty/Liberty.tcl @@ -126,7 +126,15 @@ proc report_timing_arcs { cell } { puts "" puts "Timing arcs" foreach timing_arc $timing_arcs { - puts [$timing_arc to_string] + puts " [$timing_arc to_string]" + puts " [$timing_arc role]" + set when [$timing_arc when] + if { $when != "" } { + puts " when $when" + } + foreach arc [$timing_arc timing_arcs] { + puts " [$arc from_edge] -> [$arc to_edge]" + } } } } diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index c070e3dd..6851b501 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -2059,7 +2059,7 @@ LibertyReader::makeTimingModels(LibertyCell *cell, const LibertyGroup *timing_group, TimingArcAttrsPtr timing_attrs) { - switch (cell->libertyLibrary()->delayModelType()) { + switch (cell->libertyLibrary()->delayModelType()) { case DelayModelType::cmos_linear: makeLinearModels(cell, timing_group, timing_attrs); break; @@ -2115,6 +2115,7 @@ LibertyReader::makeTableModels(LibertyCell *cell, const LibertyGroup *timing_group, TimingArcAttrsPtr timing_attrs) { + bool found_model = false; for (const RiseFall *rf : RiseFall::range()) { std::string delay_attr_name = "cell_" + rf->to_string_long(); TableModel *delay = readGateTableModel(timing_group, delay_attr_name.c_str(), rf, @@ -2160,30 +2161,36 @@ LibertyReader::makeTableModels(LibertyCell *cell, if (delay == nullptr) libWarn(1211, timing_group, "missing cell_%s.", rf->name()); } + found_model = true; } - - std::string constraint_attr_name = rf->to_string_long() + "_constraint"; - ScaleFactorType scale_factor_type = - timingTypeScaleFactorType(timing_attrs->timingType()); - TableModel *constraint = readCheckTableModel(timing_group, - constraint_attr_name.c_str(), - rf, TableTemplateType::delay, - time_scale_, scale_factor_type); - if (constraint) { - std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string_long() - + "_constraint"; - TableModelsEarlyLate constraint_sigmas = - readEarlyLateTableModels(timing_group, - constraint_sigma_attr_name.c_str(), - rf, TableTemplateType::delay, - time_scale_, - ScaleFactorType::unknown); - timing_attrs->setModel(rf, new CheckTableModel(cell, constraint, - std::move(constraint_sigmas))); + else { + std::string constraint_attr_name = rf->to_string_long() + "_constraint"; + ScaleFactorType scale_factor_type = + timingTypeScaleFactorType(timing_attrs->timingType()); + TableModel *constraint = readCheckTableModel(timing_group, + constraint_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, scale_factor_type); + if (constraint) { + std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string_long() + + "_constraint"; + TableModelsEarlyLate constraint_sigmas = + readEarlyLateTableModels(timing_group, + constraint_sigma_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::unknown); + timing_attrs->setModel(rf, new CheckTableModel(cell, constraint, + std::move(constraint_sigmas))); + found_model = true; + } } } + if (!found_model) + libWarn(1311, timing_group, "no table models found in timing group."); } + bool LibertyReader::isGateTimingType(TimingType timing_type) { diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 7bc324a6..ba5f086b 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -207,7 +207,6 @@ TimingArcSet::to_string() std::string str = from_->name(); str += " -> "; str += to_->name(); - str += " " + role()->to_string(); return str; } @@ -333,7 +332,7 @@ TimingArcSet::isRisingFallingEdge() const if (from_rf1 == from_rf2) return from_rf1; } - if (arcs_.size() == 1) + if (arc_count == 1) return arcs_[0]->fromEdge()->asRiseFall(); else return nullptr; From 6653d6c253e13452229016474658b7071584127e Mon Sep 17 00:00:00 2001 From: Matt Liberty Date: Sat, 7 Mar 2026 21:49:34 +0000 Subject: [PATCH 21/22] skip ci in the private org Signed-off-by: Matt Liberty --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74255543..e8eda3c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ on: jobs: build: + if: github.repository_owner != 'The-OpenROAD-Project-private' runs-on: ubuntu-latest steps: - name: Checkout From 2b9035c573c195e3240695a42ff2af450c301b6c Mon Sep 17 00:00:00 2001 From: Matt Liberty Date: Sat, 7 Mar 2026 21:52:35 +0000 Subject: [PATCH 22/22] remove CODEOWNERS, not relevant here Signed-off-by: Matt Liberty --- CODEOWNERS | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index c6c2b793..00000000 --- a/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -# For CI/CD issues -/.github/ @kazutoiris