1 // OpenSTA, Static Timing Analyzer
2 // Copyright (c) 2021, Parallax Software, Inc.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17 // This file illustratates how to customize the liberty file reader to
18 // read attributes that are not used by the STA. In this example:
19 // * code is called at the beginning of a library definition
20 // * a string attribute named "thingy" is parsed
21
22 #include <stdio.h>
23 #include "Machine.hh"
24 #include "StringUtil.hh"
25 #include "LibertyReader.hh"
26 #include "LibertyReaderPvt.hh"
27 #include "LibertyBuilder.hh"
28 #include "Network.hh"
29 #include "ConcreteNetwork.hh"
30 #include "Sta.hh"
31
32 // Import symbols from sta package (this example is in the global package).
33 using sta::Report;
34 using sta::Debug;
35 using sta::Network;
36 using sta::LibertyReader;
37 using sta::LibertyAttr;
38 using sta::LibertyGroup;
39 using sta::TimingGroup;
40 using sta::LibertyCell;
41 using sta::LibertyPort;
42 using sta::LibertyLibrary;
43 using sta::TimingArcSet;
44 using sta::LibertyBuilder;
45 using sta::TimingRole;
46 using sta::TimingArcAttrs;
47 using sta::Sta;
48 using sta::stringCopy;
49
50 // LibertyCell with Bigco thingy variable.
51 class BigcoCell : public LibertyCell
52 {
53 public:
54 BigcoCell(LibertyLibrary *library, const char *name, const char *filename);
55 void setThingy(const char *thingy);
56
57 protected:
58 const char *thingy_;
59 };
60
BigcoCell(LibertyLibrary * library,const char * name,const char * filename)61 BigcoCell::BigcoCell(LibertyLibrary *library, const char *name,
62 const char *filename) :
63 LibertyCell(library, name, filename),
64 thingy_(0)
65 {
66 }
67
68 void
setThingy(const char * thingy)69 BigcoCell::setThingy(const char *thingy)
70 {
71 thingy_ = thingy;
72 }
73
74 ////////////////////////////////////////////////////////////////
75
76 class BigcoTimingGroup : public TimingGroup
77 {
78 public:
79 BigcoTimingGroup(int line);
frob() const80 const char *frob() const { return frob_; }
81 void setFrob(const char *frob);
82
83 protected:
84 const char *frob_;
85 };
86
BigcoTimingGroup(int line)87 BigcoTimingGroup::BigcoTimingGroup(int line) :
88 TimingGroup(line),
89 frob_(0)
90 {
91 }
92
93 void
setFrob(const char * frob)94 BigcoTimingGroup::setFrob(const char *frob)
95 {
96 frob_ = frob;
97 }
98
99 ////////////////////////////////////////////////////////////////
100
101 class BigcoTimingArcSet : public TimingArcSet
102 {
103 public:
104 BigcoTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to,
105 LibertyPort *related_out, TimingRole *role,
106 TimingArcAttrs *attrs);
107
108 protected:
109 const char *frob_;
110 };
111
BigcoTimingArcSet(LibertyCell * cell,LibertyPort * from,LibertyPort * to,LibertyPort * related_out,TimingRole * role,TimingArcAttrs * attrs)112 BigcoTimingArcSet::BigcoTimingArcSet(LibertyCell *cell, LibertyPort *from,
113 LibertyPort *to,
114 LibertyPort *related_out, TimingRole *role,
115 TimingArcAttrs *attrs) :
116 TimingArcSet(cell, from, to, related_out, role, attrs)
117 {
118 const char *frob = static_cast<BigcoTimingGroup*>(attrs)->frob();
119 if (frob)
120 frob_ = stringCopy(frob);
121 }
122
123 ////////////////////////////////////////////////////////////////
124
125 // Make Bigco objects instead of Liberty objects.
126 class BigcoLibertyBuilder : public LibertyBuilder
127 {
128 public:
129 virtual LibertyCell *makeCell(LibertyLibrary *library, const char *name,
130 const char *filename);
131
132 protected:
133 virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell, LibertyPort *from,
134 LibertyPort *to,
135 LibertyPort *related_out,
136 TimingRole *role,
137 TimingArcAttrs *attrs);
138 };
139
140 LibertyCell *
makeCell(LibertyLibrary * library,const char * name,const char * filename)141 BigcoLibertyBuilder::makeCell(LibertyLibrary *library, const char *name,
142 const char *filename)
143 {
144 LibertyCell *cell = new BigcoCell(library, name, filename);
145 library->addCell(cell);
146 return cell;
147 }
148
149 TimingArcSet *
makeTimingArcSet(LibertyCell * cell,LibertyPort * from,LibertyPort * to,LibertyPort * related_out,TimingRole * role,TimingArcAttrs * attrs)150 BigcoLibertyBuilder::makeTimingArcSet(LibertyCell *cell, LibertyPort *from,
151 LibertyPort *to,
152 LibertyPort *related_out,
153 TimingRole *role,
154 TimingArcAttrs *attrs)
155 {
156 return new BigcoTimingArcSet(cell, from, to, related_out, role, attrs);
157 }
158
159 ////////////////////////////////////////////////////////////////
160
161 // Liberty reader to parse Bigco attributes.
162 class BigcoLibertyReader : public LibertyReader
163 {
164 public:
165 BigcoLibertyReader(LibertyBuilder *builder);
166
167 protected:
168 virtual void visitAttr1(LibertyAttr *attr);
169 virtual void visitAttr2(LibertyAttr *attr);
170 virtual void beginLibrary(LibertyGroup *group);
171 virtual TimingGroup *makeTimingGroup(int line);
172 virtual void beginCell(LibertyGroup *group);
173 };
174
BigcoLibertyReader(LibertyBuilder * builder)175 BigcoLibertyReader::BigcoLibertyReader(LibertyBuilder *builder) :
176 LibertyReader(builder)
177 {
178 // Define a visitor for the "thingy" attribute.
179 // Note that the function descriptor passed to defineAttrVisitor
180 // must be defined by the LibertyVisitor class, so a number of
181 // extra visitor functions are pre-defined for extensions.
182 defineAttrVisitor("thingy", &LibertyReader::visitAttr1);
183 defineAttrVisitor("frob", &LibertyReader::visitAttr2);
184 }
185
186 bool
libertyCellRequired(const char *)187 libertyCellRequired(const char *)
188 {
189 // Predicate for cell names.
190 return true;
191 }
192
193 // Prune cells from liberty file based on libertyCellRequired predicate.
194 void
beginCell(LibertyGroup * group)195 BigcoLibertyReader::beginCell(LibertyGroup *group)
196 {
197 const char *name = group->firstName();
198 if (name
199 && libertyCellRequired(name))
200 LibertyReader::beginCell(group);
201 }
202
203 TimingGroup *
makeTimingGroup(int line)204 BigcoLibertyReader::makeTimingGroup(int line)
205 {
206 return new BigcoTimingGroup(line);
207 }
208
209 // Called at the beginning of a library group.
210 void
beginLibrary(LibertyGroup * group)211 BigcoLibertyReader::beginLibrary(LibertyGroup *group)
212 {
213 LibertyReader::beginLibrary(group);
214 // Do Bigco stuff here.
215 printf("Bigco was here.\n");
216 }
217
218 void
visitAttr1(LibertyAttr * attr)219 BigcoLibertyReader::visitAttr1(LibertyAttr *attr)
220 {
221 const char *thingy = getAttrString(attr);
222 if (thingy) {
223 printf("Bigco thingy attribute value is %s.\n", thingy);
224 if (cell_)
225 static_cast<BigcoCell*>(cell_)->setThingy(thingy);
226 }
227 }
228
229 void
visitAttr2(LibertyAttr * attr)230 BigcoLibertyReader::visitAttr2(LibertyAttr *attr)
231 {
232 const char *frob = getAttrString(attr);
233 if (frob) {
234 if (timing_)
235 static_cast<BigcoTimingGroup*>(timing_)->setFrob(frob);
236 }
237 }
238
239 ////////////////////////////////////////////////////////////////
240
241 // Define a BigcoSta class derived from the Sta class to install the
242 // new liberty reader/visitor in BigcoSta::makeLibertyReader.
243 class BigcoSta : public Sta
244 {
245 public:
246 BigcoSta();
247
248 protected:
249 virtual LibertyLibrary *readLibertyFile(const char *filename,
250 bool infer_latches,
251 Network *network);
252 };
253
BigcoSta()254 BigcoSta::BigcoSta() :
255 Sta()
256 {
257 }
258
259 // Replace Sta liberty file reader with Bigco's very own.
260 LibertyLibrary *
readLibertyFile(const char * filename,bool infer_latches,Network * network)261 Sta::readLibertyFile(const char *filename,
262 bool infer_latches,
263 Network *network)
264 {
265 BigcoLibertyBuilder builder;
266 BigcoLibertyReader reader(&builder);
267 return reader.readLibertyFile(filename, infer_latches, network);
268 }
269