1 /* Authors: Lutong Wang and Bangqi Xu */
2 /*
3  * Copyright (c) 2019, The Regents of the University of California
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *     * Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above copyright
11  *       notice, this list of conditions and the following disclaimer in the
12  *       documentation and/or other materials provided with the distribution.
13  *     * Neither the name of the University nor the
14  *       names of its contributors may be used to endorse or promote products
15  *       derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef _FR_TECHOBJECT_H_
30 #define _FR_TECHOBJECT_H_
31 
32 #include <iostream>
33 #include <map>
34 #include <memory>
35 #include <vector>
36 
37 #include "db/obj/frVia.h"
38 #include "db/tech/frLayer.h"
39 #include "db/tech/frViaRuleGenerate.h"
40 #include "frBaseTypes.h"
41 #include "utl/Logger.h"
42 namespace fr {
43 namespace io {
44 class Parser;
45 }
46 class frTechObject
47 {
48  public:
49   // constructors
frTechObject()50   frTechObject() : dbUnit(0), manufacturingGrid(0) {}
51   // getters
getDBUPerUU()52   frUInt4 getDBUPerUU() const { return dbUnit; }
getManufacturingGrid()53   frUInt4 getManufacturingGrid() const { return manufacturingGrid; }
getLayer(const frString & name)54   frLayer* getLayer(const frString& name) const
55   {
56     if (name2layer.find(name) == name2layer.end()) {
57       // std::cout <<"Error: cannot find layer" <<std::endl;
58       // exit(1);
59       return nullptr;
60     } else {
61       return name2layer.at(name);
62     }
63   }
getLayer(frLayerNum in)64   frLayer* getLayer(frLayerNum in) const
65   {
66     if ((int) in < 0 || in >= (int) layers.size()) {
67       std::cout << "Error: cannot find layer" << std::endl;
68       exit(1);
69     } else {
70       return layers.at(in).get();
71     }
72   }
getBottomLayerNum()73   frLayerNum getBottomLayerNum() const { return 0; }
getTopLayerNum()74   frLayerNum getTopLayerNum() const
75   {
76     return (frLayerNum)((int) layers.size() - 1);
77   }
getLayers()78   const std::vector<std::unique_ptr<frLayer>>& getLayers() const
79   {
80     return layers;
81   }
82 
getVias()83   const std::vector<std::unique_ptr<frViaDef>>& getVias() const { return vias; }
getViaRuleGenerates()84   const std::vector<std::unique_ptr<frViaRuleGenerate>>& getViaRuleGenerates()
85       const
86   {
87     return viaRuleGenerates;
88   }
89   const std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>&
getVia2ViaForbiddenLen()90   getVia2ViaForbiddenLen() const
91   {
92     return via2ViaForbiddenLen;
93   }
94   const std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>&
getViaForbiddenTurnLen()95   getViaForbiddenTurnLen() const
96   {
97     return viaForbiddenTurnLen;
98   }
99   const std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>&
getViaForbiddenPlanarLen()100   getViaForbiddenPlanarLen() const
101   {
102     return viaForbiddenPlanarLen;
103   }
104 
105   // setters
setDBUPerUU(frUInt4 uIn)106   void setDBUPerUU(frUInt4 uIn) { dbUnit = uIn; }
setManufacturingGrid(frUInt4 in)107   void setManufacturingGrid(frUInt4 in) { manufacturingGrid = in; }
addLayer(std::unique_ptr<frLayer> in)108   void addLayer(std::unique_ptr<frLayer> in)
109   {
110     name2layer[in->getName()] = in.get();
111     layers.push_back(std::move(in));
112     layer2Name2CutClass.push_back(std::map<std::string, frLef58CutClass*>());
113     layerCutClass.push_back(std::vector<std::unique_ptr<frLef58CutClass>>());
114   }
addVia(std::unique_ptr<frViaDef> in)115   void addVia(std::unique_ptr<frViaDef> in)
116   {
117     if (name2via.find(in->getName()) != name2via.end()) {
118       std::cout << "Error: duplicated via definition for " << in->getName()
119                 << "\n";
120     }
121     name2via[in->getName()] = in.get();
122     vias.push_back(std::move(in));
123   }
addCutClass(frLayerNum lNum,std::unique_ptr<frLef58CutClass> in)124   void addCutClass(frLayerNum lNum, std::unique_ptr<frLef58CutClass> in)
125   {
126     auto rptr = in.get();
127     layer2Name2CutClass[lNum][in->getName()] = rptr;
128     layerCutClass[lNum].push_back(std::move(in));
129     layers[lNum]->addCutClass(rptr);
130   }
addViaRuleGenerate(std::unique_ptr<frViaRuleGenerate> in)131   void addViaRuleGenerate(std::unique_ptr<frViaRuleGenerate> in)
132   {
133     name2viaRuleGenerate[in->getName()] = in.get();
134     viaRuleGenerates.push_back(std::move(in));
135   }
addConstraint(const std::shared_ptr<frConstraint> & constraintIn)136   void addConstraint(const std::shared_ptr<frConstraint>& constraintIn)
137   {
138     constraints.push_back(constraintIn);
139   }
addUConstraint(std::unique_ptr<frConstraint> in)140   void addUConstraint(std::unique_ptr<frConstraint> in)
141   {
142     uConstraints.push_back(std::move(in));
143   }
144 
145   // forbidden length table related
146   bool isVia2ViaForbiddenLen(int tableLayerIdx,
147                              bool isPrevDown,
148                              bool isCurrDown,
149                              bool isCurrDirX,
150                              frCoord len,
151                              frNonDefaultRule* ndr = nullptr,
152                              bool isOverlap = false)
153   {
154     int tableEntryIdx = getTableEntryIdx(!isPrevDown, !isCurrDown, !isCurrDirX);
155     if (isOverlap) {
156       return isIncluded(
157           via2ViaForbiddenOverlapLen[tableLayerIdx][tableEntryIdx], len);
158     } else {
159       return isIncluded(
160           (ndr ? ndr->via2ViaForbiddenLen
161                : via2ViaForbiddenLen)[tableLayerIdx][tableEntryIdx],
162           len);
163     }
164   }
165 
166   bool isViaForbiddenTurnLen(int tableLayerIdx,
167                              bool isDown,
168                              bool isCurrDirX,
169                              frCoord len,
170                              frNonDefaultRule* ndr = nullptr)
171   {
172     int tableEntryIdx = getTableEntryIdx(!isDown, !isCurrDirX);
173     return isIncluded((ndr ? ndr->viaForbiddenTurnLen
174                            : viaForbiddenTurnLen)[tableLayerIdx][tableEntryIdx],
175                       len);
176   }
177 
isLine2LineForbiddenLen(int tableLayerIdx,bool isZShape,bool isCurrDirX,frCoord len)178   bool isLine2LineForbiddenLen(int tableLayerIdx,
179                                bool isZShape,
180                                bool isCurrDirX,
181                                frCoord len)
182   {
183     int tableEntryIdx = getTableEntryIdx(!isZShape, !isCurrDirX);
184     return isIncluded(line2LineForbiddenLen[tableLayerIdx][tableEntryIdx], len);
185   }
186 
isViaForbiddenThrough(int tableLayerIdx,bool isDown,bool isCurrDirX)187   bool isViaForbiddenThrough(int tableLayerIdx, bool isDown, bool isCurrDirX)
188   {
189     int tableEntryIdx = getTableEntryIdx(!isDown, !isCurrDirX);
190     return viaForbiddenThrough[tableLayerIdx][tableEntryIdx];
191   }
192 
getVia(frString name)193   frViaDef* getVia(frString name) const { return name2via.at(name); }
194 
getViaRule(frString name)195   frViaRuleGenerate* getViaRule(frString name) const
196   {
197     return name2viaRuleGenerate.at(name);
198   }
199 
addNDR(std::unique_ptr<frNonDefaultRule> n)200   void addNDR(std::unique_ptr<frNonDefaultRule> n)
201   {
202     nonDefaultRules.push_back(std::move(n));
203   }
204 
getNondefaultRules()205   const std::vector<std::unique_ptr<frNonDefaultRule>>& getNondefaultRules()
206       const
207   {
208     return nonDefaultRules;
209   }
210 
getNondefaultRule(string name)211   frNonDefaultRule* getNondefaultRule(string name)
212   {
213     for (std::unique_ptr<frNonDefaultRule>& nd : nonDefaultRules) {
214       if (nd->getName() == name)
215         return nd.get();
216     }
217     return nullptr;
218   }
219 
getMaxNondefaultSpacing(int z)220   frCoord getMaxNondefaultSpacing(int z)
221   {
222     frCoord spc = 0;
223     for (std::unique_ptr<frNonDefaultRule>& nd : nonDefaultRules) {
224       if (nd->getSpacing(z) > spc)
225         spc = nd->getSpacing(z);
226     }
227     return spc;
228   }
229 
getMaxNondefaultWidth(int z)230   frCoord getMaxNondefaultWidth(int z)
231   {
232     frCoord spc = 0;
233     for (std::unique_ptr<frNonDefaultRule>& nd : nonDefaultRules) {
234       if (nd->getWidth(z) > spc)
235         spc = nd->getWidth(z);
236     }
237     return spc;
238   }
239 
hasNondefaultRules()240   bool hasNondefaultRules() { return !nonDefaultRules.empty(); }
241 
242   // debug
printAllConstraints(utl::Logger * logger)243   void printAllConstraints(utl::Logger* logger)
244   {
245     logger->report("Reporting Layer Properties");
246     for (auto& layer : layers) {
247       auto type = layer->getType();
248       if (type == frLayerTypeEnum::CUT)
249         logger->report("Cut Layer {}", layer->getName());
250       else if (type == frLayerTypeEnum::ROUTING)
251         logger->report("Routing Layer {}", layer->getName());
252       layer->printAllConstraints(logger);
253     }
254   }
255 
printDefaultVias(Logger * logger)256   void printDefaultVias(Logger* logger)
257   {
258     logger->info(DRT, 167, "List of default vias:");
259     for (auto& layer : layers) {
260       if (layer->getType() == frLayerTypeEnum::CUT
261           && layer->getLayerNum() >= 2 /*BOTTOM_ROUTING_LAYER*/) {
262         logger->report("  Layer {}", layer->getName());
263         logger->report("    default via: {}",
264                        layer->getDefaultViaDef()->getName());
265       }
266     }
267   }
268 
269   friend class io::Parser;
270 
271  protected:
272   frUInt4 dbUnit;
273   frUInt4 manufacturingGrid;
274 
275   std::map<frString, frLayer*> name2layer;
276   std::vector<std::unique_ptr<frLayer>> layers;
277 
278   std::map<frString, frViaDef*> name2via;
279   std::vector<std::unique_ptr<frViaDef>> vias;
280 
281   std::vector<std::map<frString, frLef58CutClass*>> layer2Name2CutClass;
282   std::vector<std::vector<std::unique_ptr<frLef58CutClass>>> layerCutClass;
283 
284   std::map<frString, frViaRuleGenerate*> name2viaRuleGenerate;
285   std::vector<std::unique_ptr<frViaRuleGenerate>> viaRuleGenerates;
286 
287   frCollection<std::shared_ptr<frConstraint>> constraints;
288   std::vector<std::unique_ptr<frConstraint>> uConstraints;
289   std::vector<std::unique_ptr<frNonDefaultRule>> nonDefaultRules;
290 
291   // via2ViaForbiddenLen[z][0], prev via is down, curr via is down, forgidden x
292   // dist range (for non-shape-based rule) via2ViaForbiddenLen[z][1], prev via
293   // is down, curr via is down, forgidden y dist range (for non-shape-based
294   // rule) via2ViaForbiddenLen[z][2], prev via is down, curr via is up,
295   // forgidden x dist range (for non-shape-based rule)
296   // via2ViaForbiddenLen[z][3], prev via is down, curr via is up,   forgidden y
297   // dist range (for non-shape-based rule) via2ViaForbiddenLen[z][4], prev via
298   // is up,   curr via is down, forgidden x dist range (for non-shape-based
299   // rule) via2ViaForbiddenLen[z][5], prev via is up,   curr via is down,
300   // forgidden y dist range (for non-shape-based rule)
301   // via2ViaForbiddenLen[z][6], prev via is up,   curr via is up,   forgidden x
302   // dist range (for non-shape-based rule) via2ViaForbiddenLen[z][7], prev via
303   // is up,   curr via is up,   forgidden y dist range (for non-shape-based
304   // rule)
305   std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>
306       via2ViaForbiddenLen;
307 
308   // via2ViaForbiddenOverlapLen[z][0], prev via is down, curr via is down,
309   // forgidden x dist range (for shape-based rule)
310   // via2ViaForbiddenOverlapLen[z][1], prev via is down, curr via is down,
311   // forgidden y dist range (for shape-based rule)
312   // via2ViaForbiddenOverlapLen[z][2], prev via is down, curr via is up,
313   // forgidden x dist range (for shape-based rule)
314   // via2ViaForbiddenOverlapLen[z][3], prev via is down, curr via is up,
315   // forgidden y dist range (for shape-based rule)
316   // via2ViaForbiddenOverlapLen[z][4], prev via is up,   curr via is down,
317   // forgidden x dist range (for shape-based rule)
318   // via2ViaForbiddenOverlapLen[z][5], prev via is up,   curr via is down,
319   // forgidden y dist range (for shape-based rule)
320   // via2ViaForbiddenOverlapLen[z][6], prev via is up,   curr via is up,
321   // forgidden x dist range (for shape-based rule)
322   // via2ViaForbiddenOverlapLen[z][7], prev via is up,   curr via is up,
323   // forgidden y dist range (for shape-based rule)
324   std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>
325       via2ViaForbiddenOverlapLen;
326 
327   // viaForbiddenTurnLen[z][0], last via is down, forbidden x dist range before
328   // turn viaForbiddenTurnLen[z][1], last via is down, forbidden y dist range
329   // before turn viaForbiddenTurnLen[z][2], last via is up,   forbidden x dist
330   // range before turn viaForbiddenTurnLen[z][3], last via is up,   forbidden y
331   // dist range before turn
332   std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>
333       viaForbiddenTurnLen;
334 
335   // viaForbiddenPlanarLen[z][0], last via is down, forbidden x dist range
336   // viaForbiddenPlanarLen[z][1], last via is down, forbidden y dist range
337   // viaForbiddenPlanarLen[z][2], last via is up,   forbidden x dist range
338   // viaForbiddenPlanarLen[z][3], last via is up,   forbidden y dist range
339   std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>
340       viaForbiddenPlanarLen;
341 
342   // line2LineForbiddenForbiddenLen[z][0], z shape, forbidden x dist range
343   // line2LineForbiddenForbiddenLen[z][1], z shape, forbidden y dist range
344   // line2LineForbiddenForbiddenLen[z][2], u shape, forbidden x dist range
345   // line2LineForbiddenForbiddenLen[z][3], u shape, forbidden y dist range
346   std::vector<std::vector<std::vector<std::pair<frCoord, frCoord>>>>
347       line2LineForbiddenLen;
348 
349   // viaForbiddenPlanarThrough[z][0], forbidden planar through along x direction
350   // for down via viaForbiddenPlanarThrough[z][1], forbidden planar through
351   // along y direction for down via viaForbiddenPlanarThrough[z][2], forbidden
352   // planar through along x direction for up via
353   // viaForbiddenPlanarThrough[z][3], forbidden planar through along y direction
354   // for up via
355   std::vector<std::vector<bool>> viaForbiddenThrough;
356 
357   // forbidden length table related utilities
getTableEntryIdx(bool in1,bool in2)358   int getTableEntryIdx(bool in1, bool in2)
359   {
360     int retIdx = 0;
361     if (in1) {
362       retIdx += 1;
363     }
364     retIdx <<= 1;
365     if (in2) {
366       retIdx += 1;
367     }
368     return retIdx;
369   }
370 
getTableEntryIdx(bool in1,bool in2,bool in3)371   int getTableEntryIdx(bool in1, bool in2, bool in3)
372   {
373     int retIdx = 0;
374     if (in1) {
375       retIdx += 1;
376     }
377     retIdx <<= 1;
378     if (in2) {
379       retIdx += 1;
380     }
381     retIdx <<= 1;
382     if (in3) {
383       retIdx += 1;
384     }
385     return retIdx;
386   }
387 
isIncluded(const std::vector<std::pair<frCoord,frCoord>> & intervals,const frCoord len)388   bool isIncluded(const std::vector<std::pair<frCoord, frCoord>>& intervals,
389                   const frCoord len)
390   {
391     bool included = false;
392     for (auto& interval : intervals) {
393       if (interval.first <= len && interval.second >= len) {
394         included = true;
395         break;
396       }
397     }
398     return included;
399   }
400 
401   friend class FlexRP;
402 };
403 }  // namespace fr
404 
405 #endif
406