// OpenSTA, Static Timing Analyzer // Copyright (c) 2021, 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 . // This file illustratates how to customize the liberty file reader to // read attributes that are not used by the STA. In this example: // * code is called at the beginning of a library definition // * a string attribute named "thingy" is parsed #include #include "Machine.hh" #include "StringUtil.hh" #include "LibertyReader.hh" #include "LibertyReaderPvt.hh" #include "LibertyBuilder.hh" #include "Network.hh" #include "ConcreteNetwork.hh" #include "Sta.hh" // Import symbols from sta package (this example is in the global package). using sta::Report; using sta::Debug; using sta::Network; using sta::LibertyReader; using sta::LibertyAttr; using sta::LibertyGroup; using sta::TimingGroup; using sta::LibertyCell; using sta::LibertyPort; using sta::LibertyLibrary; using sta::TimingArcSet; using sta::LibertyBuilder; using sta::TimingRole; using sta::TimingArcAttrs; using sta::Sta; using sta::stringCopy; // LibertyCell with Bigco thingy variable. class BigcoCell : public LibertyCell { public: BigcoCell(LibertyLibrary *library, const char *name, const char *filename); void setThingy(const char *thingy); protected: const char *thingy_; }; BigcoCell::BigcoCell(LibertyLibrary *library, const char *name, const char *filename) : LibertyCell(library, name, filename), thingy_(0) { } void BigcoCell::setThingy(const char *thingy) { thingy_ = thingy; } //////////////////////////////////////////////////////////////// class BigcoTimingGroup : public TimingGroup { public: BigcoTimingGroup(int line); const char *frob() const { return frob_; } void setFrob(const char *frob); protected: const char *frob_; }; BigcoTimingGroup::BigcoTimingGroup(int line) : TimingGroup(line), frob_(0) { } void BigcoTimingGroup::setFrob(const char *frob) { frob_ = frob; } //////////////////////////////////////////////////////////////// class BigcoTimingArcSet : public TimingArcSet { public: BigcoTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, LibertyPort *related_out, TimingRole *role, TimingArcAttrs *attrs); protected: const char *frob_; }; BigcoTimingArcSet::BigcoTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, LibertyPort *related_out, TimingRole *role, TimingArcAttrs *attrs) : TimingArcSet(cell, from, to, related_out, role, attrs) { const char *frob = static_cast(attrs)->frob(); if (frob) frob_ = stringCopy(frob); } //////////////////////////////////////////////////////////////// // Make Bigco objects instead of Liberty objects. 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, TimingRole *role, TimingArcAttrs *attrs); }; LibertyCell * BigcoLibertyBuilder::makeCell(LibertyLibrary *library, const char *name, const char *filename) { LibertyCell *cell = new BigcoCell(library, name, filename); library->addCell(cell); return cell; } TimingArcSet * BigcoLibertyBuilder::makeTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, LibertyPort *related_out, TimingRole *role, TimingArcAttrs *attrs) { return new BigcoTimingArcSet(cell, from, to, related_out, role, attrs); } //////////////////////////////////////////////////////////////// // Liberty reader to parse Bigco attributes. class BigcoLibertyReader : public LibertyReader { public: BigcoLibertyReader(LibertyBuilder *builder); protected: virtual void visitAttr1(LibertyAttr *attr); virtual void visitAttr2(LibertyAttr *attr); virtual void beginLibrary(LibertyGroup *group); virtual TimingGroup *makeTimingGroup(int line); virtual void beginCell(LibertyGroup *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 libertyCellRequired(const char *) { // Predicate for cell names. return true; } // Prune cells from liberty file based on libertyCellRequired predicate. void BigcoLibertyReader::beginCell(LibertyGroup *group) { const char *name = group->firstName(); if (name && libertyCellRequired(name)) LibertyReader::beginCell(group); } TimingGroup * BigcoLibertyReader::makeTimingGroup(int line) { return new BigcoTimingGroup(line); } // Called at the beginning of a library group. void BigcoLibertyReader::beginLibrary(LibertyGroup *group) { LibertyReader::beginLibrary(group); // Do Bigco stuff here. printf("Bigco was here.\n"); } void BigcoLibertyReader::visitAttr1(LibertyAttr *attr) { const char *thingy = getAttrString(attr); if (thingy) { printf("Bigco thingy attribute value is %s.\n", thingy); if (cell_) static_cast(cell_)->setThingy(thingy); } } void BigcoLibertyReader::visitAttr2(LibertyAttr *attr) { const char *frob = getAttrString(attr); if (frob) { if (timing_) static_cast(timing_)->setFrob(frob); } } //////////////////////////////////////////////////////////////// // Define a BigcoSta class derived from the Sta class to install the // new liberty reader/visitor in BigcoSta::makeLibertyReader. class BigcoSta : public Sta { public: BigcoSta(); protected: virtual LibertyLibrary *readLibertyFile(const char *filename, bool infer_latches, Network *network); }; BigcoSta::BigcoSta() : Sta() { } // Replace Sta liberty file reader with Bigco's very own. LibertyLibrary * Sta::readLibertyFile(const char *filename, bool infer_latches, Network *network) { BigcoLibertyBuilder builder; BigcoLibertyReader reader(&builder); return reader.readLibertyFile(filename, infer_latches, network); }