// OpenSTA, Static Timing Analyzer // Copyright (c) 2020, 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 . #pragma once #include "DisallowCopyAssign.hh" #include "Vector.hh" #include "Map.hh" #include "Set.hh" #include "StringUtil.hh" namespace sta { class Report; class LibertyGroupVisitor; class LibertyAttrVisitor; class LibertyStmt; class LibertyGroup; class LibertyAttr; class LibertyDefine; class LibertyAttrValue; class LibertyVariable; class LibertySubgroupIterator; class LibertyAttrIterator; typedef Vector LibertyStmtSeq; typedef Vector LibertyGroupSeq; typedef Vector LibertyAttrSeq; typedef Map LibertyAttrMap; typedef Map LibertyDefineMap; typedef Vector LibertyAttrValueSeq; typedef Map LibertyVariableMap; typedef MapLibertyGroupVisitorMap; typedef LibertyAttrValueSeq::Iterator LibertyAttrValueIterator; enum class LibertyAttrType { attr_string, attr_int, attr_double, attr_boolean, attr_unknown }; enum class LibertyGroupType { library, cell, pin, timing, unknown }; // Abstract base class for liberty statements. class LibertyStmt { public: explicit LibertyStmt(int line); virtual ~LibertyStmt() {} int line() const { return line_; } virtual bool isGroup() const { return false; } virtual bool isAttribute() const { return false; } virtual bool isDefine() const { return false; } virtual bool isVariable() const { return false; } protected: int line_; private: DISALLOW_COPY_AND_ASSIGN(LibertyStmt); }; // 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(const char *type, LibertyAttrValueSeq *params, int line); virtual ~LibertyGroup(); virtual bool isGroup() const { return true; } const char *type() const { return type_; } // First param as a string. const char *firstName(); // Second param as a string. const char *secondName(); LibertyAttr *findAttr(const char *name); void addSubgroup(LibertyGroup *subgroup); void addDefine(LibertyDefine *define); void addAttribute(LibertyAttr *attr); void addVariable(LibertyVariable *var); LibertyGroupSeq *subgroups() const { return subgroups_; } LibertyAttrSeq *attrs() const { return attrs_; } LibertyAttrValueSeq *params() const { return params_; } protected: void parseNames(LibertyAttrValueSeq *values); const char *type_; LibertyAttrValueSeq *params_; LibertyAttrSeq *attrs_; LibertyAttrMap *attr_map_; LibertyGroupSeq *subgroups_; LibertyDefineMap *define_map_; private: DISALLOW_COPY_AND_ASSIGN(LibertyGroup); }; class LibertySubgroupIterator : public LibertyGroupSeq::Iterator { public: explicit LibertySubgroupIterator(LibertyGroup *group); private: DISALLOW_COPY_AND_ASSIGN(LibertySubgroupIterator); }; class LibertyAttrIterator : public LibertyAttrSeq::Iterator { public: explicit LibertyAttrIterator(LibertyGroup *group); private: DISALLOW_COPY_AND_ASSIGN(LibertyAttrIterator); }; // Abstract base class for attributes. class LibertyAttr : public LibertyStmt { public: LibertyAttr(const char *name, int line); virtual ~LibertyAttr(); const char *name() const { return name_; } virtual bool isAttribute() const { return true; } virtual bool isSimple() const = 0; virtual bool isComplex() const = 0; virtual LibertyAttrValueSeq *values() const = 0; virtual LibertyAttrValue *firstValue() = 0; protected: const char *name_; private: DISALLOW_COPY_AND_ASSIGN(LibertyAttr); }; // Abstract base class for simple attributes. // name : value; class LibertySimpleAttr : public LibertyAttr { public: LibertySimpleAttr(const char *name, LibertyAttrValue *value, int line); virtual ~LibertySimpleAttr(); virtual bool isSimple() const { return true; } virtual bool isComplex() const { return false; } virtual LibertyAttrValue *firstValue() { return value_; } virtual LibertyAttrValueSeq *values() const; private: DISALLOW_COPY_AND_ASSIGN(LibertySimpleAttr); LibertyAttrValue *value_; }; // Complex attributes have multiple values. // name(attr_value1[, attr_value2]...); class LibertyComplexAttr : public LibertyAttr { public: LibertyComplexAttr(const char *name, LibertyAttrValueSeq *values, int line); virtual ~LibertyComplexAttr(); virtual bool isSimple() const { return false; } virtual bool isComplex() const { return true; } virtual LibertyAttrValue *firstValue(); virtual LibertyAttrValueSeq *values() const { return values_; } private: DISALLOW_COPY_AND_ASSIGN(LibertyComplexAttr); LibertyAttrValueSeq *values_; }; // Attribute values are a string or float. class LibertyAttrValue { public: LibertyAttrValue() {} virtual ~LibertyAttrValue() {} virtual bool isString() = 0; virtual bool isFloat() = 0; virtual float floatValue() = 0; virtual const char *stringValue() = 0; private: DISALLOW_COPY_AND_ASSIGN(LibertyAttrValue); }; class LibertyStringAttrValue : public LibertyAttrValue { public: explicit LibertyStringAttrValue(const char *value); virtual ~LibertyStringAttrValue(); virtual bool isFloat() { return false; } virtual bool isString() { return true; } virtual float floatValue(); virtual const char *stringValue(); private: DISALLOW_COPY_AND_ASSIGN(LibertyStringAttrValue); const char *value_; }; class LibertyFloatAttrValue : public LibertyAttrValue { public: explicit LibertyFloatAttrValue(float value); virtual bool isString() { return false; } virtual bool isFloat() { return true; } virtual float floatValue(); virtual const char *stringValue(); private: DISALLOW_COPY_AND_ASSIGN(LibertyFloatAttrValue); float value_; }; // Define statements define new simple attributes. // define(attribute_name, group_name, attribute_type); // attribute_type is string|integer|float. class LibertyDefine : public LibertyStmt { public: LibertyDefine(const char *name, LibertyGroupType group_type, LibertyAttrType value_type, int line); virtual ~LibertyDefine(); virtual bool isDefine() const { return true; } const char *name() const { return name_; } LibertyGroupType groupType() const { return group_type_; } LibertyAttrType valueType() const { return value_type_; } private: DISALLOW_COPY_AND_ASSIGN(LibertyDefine); const char *name_; LibertyGroupType group_type_; LibertyAttrType value_type_; }; // 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 { public: LibertyVariable(const char *var, float value, int line); // var_ is NOT deleted by ~LibertyVariable because the group // variable map ref's it. virtual ~LibertyVariable(); virtual bool isVariable() const { return true; } const char *variable() const { return var_; } float value() const { return value_; } private: DISALLOW_COPY_AND_ASSIGN(LibertyVariable); const char *var_; float value_; }; 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 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; private: DISALLOW_COPY_AND_ASSIGN(LibertyGroupVisitor); }; FILE * libertyIncludeBegin(const char *filename); void libertyIncludeEnd(); bool libertyInInclude(); void libertyIncrLine(); void libertyParseError(const char *fmt, ...); int libertyLine(); void parseLibertyFile(const char *filename, LibertyGroupVisitor *library_visitor, Report *report); void libertyGroupBegin(const char *type, LibertyAttrValueSeq *params, int line); LibertyGroup * libertyGroupEnd(); LibertyGroup * libertyGroup(); LibertyStmt * makeLibertyComplexAttr(const char *name, LibertyAttrValueSeq *values, int line); LibertyStmt * makeLibertySimpleAttr(const char *name, LibertyAttrValue *value, int line); LibertyAttrValue * makeLibertyFloatAttrValue(float value); LibertyAttrValue * makeLibertyStringAttrValue(char *value); LibertyStmt * makeLibertyVariable(char *var, float value, int line); } // namespace // Global namespace. int LibertyParse_error(const char *msg);