1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #include "lefout.h"
34 
35 #include <stdio.h>
36 
37 #include <algorithm>
38 #include <unordered_map>
39 
40 #include "db.h"
41 #include "dbTransform.h"
42 
43 using namespace odb;
44 
writeBoxes(void * boxes,const char * indent)45 void lefout::writeBoxes(void* boxes, const char* indent)
46 {
47   dbSet<dbBox>* geoms = (dbSet<dbBox>*) boxes;
48   dbSet<dbBox>::iterator bitr;
49   dbTechLayer* cur_layer = NULL;
50 
51   for (bitr = geoms->begin(); bitr != geoms->end(); ++bitr) {
52     dbBox* box = *bitr;
53     dbTechLayer* layer = box->getTechLayer();
54 
55     if (box->isVia()) {
56       dbTechVia* via = box->getTechVia();
57       assert(via);
58       int x, y;
59       box->getViaXY(x, y);
60       std::string n = via->getName();
61       fprintf(_out,
62               "%sVIA %g %g %s ;\n",
63               indent,
64               lefdist(x),
65               lefdist(y),
66               n.c_str());
67       cur_layer = NULL;
68     } else {
69       int x1 = box->xMin();
70       int y1 = box->yMin();
71       int x2 = box->xMax();
72       int y2 = box->yMax();
73 
74       std::string n;
75       if (_use_alias && layer->hasAlias())
76         n = layer->getAlias();
77       else
78         n = layer->getName();
79 
80       if (cur_layer != layer) {
81         std::string n;
82 
83         if (_use_alias && layer->hasAlias())
84           n = layer->getAlias();
85         else
86           n = layer->getName();
87 
88         fprintf(_out, "%sLAYER %s ;\n", indent, n.c_str());
89         cur_layer = layer;
90       }
91 
92       fprintf(_out,
93               "%s  RECT  %g %g %g %g ;\n",
94               indent,
95               lefdist(x1),
96               lefdist(y1),
97               lefdist(x2),
98               lefdist(y2));
99     }
100   }
101 }
102 
writeHeader(dbLib * lib)103 void lefout::writeHeader(dbLib* lib)
104 {
105   dbTech* tech = lib->getDb()->getTech();
106 
107   char left_bus_delimeter;
108   char right_bus_delimeter;
109   lib->getBusDelimeters(left_bus_delimeter, right_bus_delimeter);
110 
111   if (left_bus_delimeter == 0)
112     left_bus_delimeter = '[';
113 
114   if (right_bus_delimeter == 0)
115     right_bus_delimeter = ']';
116 
117   char hier_delimeter = lib->getHierarchyDelimeter();
118 
119   if (hier_delimeter == 0)
120     hier_delimeter = '|';
121 
122   fprintf(_out, "VERSION %s ;\n", tech->getLefVersionStr());
123   fprintf(_out,
124           "NAMESCASESENSITIVE %s ;\n",
125           tech->getNamesCaseSensitive().getString());
126   fprintf(_out,
127           "BUSBITCHARS \"%c%c\" ;\n",
128           left_bus_delimeter,
129           right_bus_delimeter);
130   fprintf(_out, "DIVIDERCHAR \"%c\" ;\n", hier_delimeter);
131   writePropertyDefinitions(lib);
132 
133   if (lib->getLefUnits()) {
134     fprintf(_out, "UNITS\n");
135     fprintf(_out, "    DATABASE MICRONS %d ;\n", lib->getLefUnits());
136     fprintf(_out, "END UNITS\n");
137   }
138 }
139 
writeTech(dbTech * tech)140 void lefout::writeTech(dbTech* tech)
141 {
142   assert(tech);
143 
144   if (tech->hasNoWireExtAtPin())
145     fprintf(_out,
146             "NOWIREEXTENSIONATPIN %s ;\n",
147             tech->getNoWireExtAtPin().getString());
148 
149   if (tech->hasClearanceMeasure())
150     fprintf(_out,
151             "CLEARANCEMEASURE %s ;\n",
152             tech->getClearanceMeasure().getString());
153 
154   if (tech->hasUseMinSpacingObs())
155     fprintf(_out,
156             "USEMINSPACING OBS %s ;\n",
157             tech->getUseMinSpacingObs().getString());
158 
159   if (tech->hasUseMinSpacingPin())
160     fprintf(_out,
161             "USEMINSPACING PIN %s ;\n",
162             tech->getUseMinSpacingPin().getString());
163 
164   if (tech->hasManufacturingGrid())
165     fprintf(_out,
166             "MANUFACTURINGGRID %.4g ;\n",
167             lefdist(tech->getManufacturingGrid()));
168 
169   dbSet<dbTechLayer> layers = tech->getLayers();
170   dbSet<dbTechLayer>::iterator litr;
171 
172   for (litr = layers.begin(); litr != layers.end(); ++litr) {
173     dbTechLayer* layer = *litr;
174     writeLayer(layer);
175   }
176 
177   // VIA's not using generate rule and not default
178   dbSet<dbTechVia> vias = tech->getVias();
179   dbSet<dbTechVia>::iterator vitr;
180 
181   for (vitr = vias.begin(); vitr != vias.end(); ++vitr) {
182     dbTechVia* via = *vitr;
183 
184     if (via->getNonDefaultRule() == NULL)
185       if (via->getViaGenerateRule() == NULL)
186         writeVia(via);
187   }
188 
189   dbSet<dbTechViaRule> via_rules = tech->getViaRules();
190   dbSet<dbTechViaRule>::iterator vritr;
191 
192   for (vritr = via_rules.begin(); vritr != via_rules.end(); ++vritr) {
193     dbTechViaRule* rule = *vritr;
194     writeTechViaRule(rule);
195   }
196 
197   dbSet<dbTechViaGenerateRule> via_gen_rules = tech->getViaGenerateRules();
198   dbSet<dbTechViaGenerateRule>::iterator vgritr;
199 
200   for (vgritr = via_gen_rules.begin(); vgritr != via_gen_rules.end();
201        ++vgritr) {
202     dbTechViaGenerateRule* rule = *vgritr;
203     writeTechViaGenerateRule(rule);
204   }
205 
206   // VIA's using generate rule
207   vias = tech->getVias();
208 
209   for (vitr = vias.begin(); vitr != vias.end(); ++vitr) {
210     dbTechVia* via = *vitr;
211 
212     if (via->getNonDefaultRule() == NULL)
213       if (via->getViaGenerateRule() != NULL)
214         writeVia(via);
215   }
216 
217   std::vector<dbTechSameNetRule*> srules;
218   tech->getSameNetRules(srules);
219 
220   if (srules.begin() != srules.end()) {
221     fprintf(_out, "\nSPACING\n");
222 
223     std::vector<dbTechSameNetRule*>::iterator sritr;
224     for (sritr = srules.begin(); sritr != srules.end(); ++sritr)
225       writeSameNetRule(*sritr);
226 
227     fprintf(_out, "\nEND SPACING\n");
228   }
229 
230   dbSet<dbTechNonDefaultRule> rules = tech->getNonDefaultRules();
231   dbSet<dbTechNonDefaultRule>::iterator ritr;
232 
233   for (ritr = rules.begin(); ritr != rules.end(); ++ritr) {
234     dbTechNonDefaultRule* rule = *ritr;
235     writeNonDefaultRule(tech, rule);
236   }
237 }
238 
writeNonDefaultRule(dbTech * tech,dbTechNonDefaultRule * rule)239 void lefout::writeNonDefaultRule(dbTech* tech, dbTechNonDefaultRule* rule)
240 {
241   std::string name = rule->getName();
242   fprintf(_out, "\nNONDEFAULTRULE %s\n", name.c_str());
243 
244   if (rule->getHardSpacing())
245     fprintf(_out, "HARDSPACING ;\n");
246 
247   std::vector<dbTechLayerRule*> layer_rules;
248   rule->getLayerRules(layer_rules);
249 
250   std::vector<dbTechLayerRule*>::iterator litr;
251   for (litr = layer_rules.begin(); litr != layer_rules.end(); ++litr)
252     writeLayerRule(*litr);
253 
254   std::vector<dbTechVia*> vias;
255   rule->getVias(vias);
256 
257   std::vector<dbTechVia*>::iterator vitr;
258   for (vitr = vias.begin(); vitr != vias.end(); ++vitr)
259     writeVia(*vitr);
260 
261   std::vector<dbTechSameNetRule*> srules;
262   rule->getSameNetRules(srules);
263 
264   if (srules.begin() != srules.end()) {
265     fprintf(_out, "\nSPACING\n");
266 
267     std::vector<dbTechSameNetRule*>::iterator sritr;
268     for (sritr = srules.begin(); sritr != srules.end(); ++sritr)
269       writeSameNetRule(*sritr);
270 
271     fprintf(_out, "\nEND SPACING\n");
272   }
273 
274   std::vector<dbTechVia*> use_vias;
275   rule->getUseVias(use_vias);
276 
277   std::vector<dbTechVia*>::iterator uvitr;
278   for (uvitr = use_vias.begin(); uvitr != use_vias.end(); ++uvitr) {
279     dbTechVia* via = *uvitr;
280     std::string vname = via->getName();
281     fprintf(_out, "USEVIA %s ;\n", vname.c_str());
282   }
283 
284   std::vector<dbTechViaGenerateRule*> use_rules;
285   rule->getUseViaRules(use_rules);
286 
287   std::vector<dbTechViaGenerateRule*>::iterator uvritr;
288   for (uvritr = use_rules.begin(); uvritr != use_rules.end(); ++uvritr) {
289     dbTechViaGenerateRule* rule = *uvritr;
290     std::string rname = rule->getName();
291     fprintf(_out, "USEVIARULE %s ;\n", rname.c_str());
292   }
293 
294   dbSet<dbTechLayer> layers = tech->getLayers();
295   dbSet<dbTechLayer>::iterator layitr;
296 
297   for (layitr = layers.begin(); layitr != layers.end(); ++layitr) {
298     dbTechLayer* layer = *layitr;
299     int count;
300 
301     if (rule->getMinCuts(layer, count)) {
302       std::string lname = layer->getName();
303       fprintf(_out, "MINCUTS %s %d ;\n", lname.c_str(), count);
304     }
305   }
306 
307   fprintf(_out, "\nEND %s\n", name.c_str());
308 }
309 
writeLayerRule(dbTechLayerRule * rule)310 void lefout::writeLayerRule(dbTechLayerRule* rule)
311 {
312   dbTechLayer* layer = rule->getLayer();
313   std::string name;
314   if (_use_alias && layer->hasAlias())
315     name = layer->getAlias();
316   else
317     name = layer->getName();
318   fprintf(_out, "\nLAYER %s\n", name.c_str());
319 
320   if (rule->getWidth())
321     fprintf(_out, "    WIDTH %g ;\n", lefdist(rule->getWidth()));
322 
323   if (rule->getSpacing())
324     fprintf(_out, "    SPACING %g ;\n", lefdist(rule->getSpacing()));
325 
326   if (rule->getWireExtension() != 0.0)
327     fprintf(
328         _out, "    WIREEXTENSION %g ;\n", lefdist(rule->getWireExtension()));
329 
330   if (rule->getResistance() != 0.0)
331     fprintf(_out, "    RESISTANCE RPERSQ %g ;\n", rule->getResistance());
332 
333   if (rule->getCapacitance() != 0.0)
334     fprintf(_out, "    CAPACITANCE CPERSQDIST %g ;\n", rule->getCapacitance());
335 
336   if (rule->getEdgeCapacitance() != 0.0)
337     fprintf(_out, "      EDGECAPACITANCE %g ;\n", rule->getEdgeCapacitance());
338 
339   fprintf(_out, "END %s\n", name.c_str());
340 }
341 
writeTechViaRule(dbTechViaRule * rule)342 void lefout::writeTechViaRule(dbTechViaRule* rule)
343 {
344   std::string name = rule->getName();
345   fprintf(_out, "\nVIARULE %s\n", name.c_str());
346 
347   uint idx;
348 
349   for (idx = 0; idx < rule->getViaLayerRuleCount(); ++idx) {
350     dbTechViaLayerRule* layrule = rule->getViaLayerRule(idx);
351     dbTechLayer* layer = layrule->getLayer();
352     std::string lname = layer->getName();
353     fprintf(_out, "    LAYER %s ;\n", lname.c_str());
354 
355     if (layrule->getDirection() == dbTechLayerDir::VERTICAL)
356       fprintf(_out, "      DIRECTION VERTICAL ;\n");
357     else if (layrule->getDirection() == dbTechLayerDir::HORIZONTAL)
358       fprintf(_out, "      DIRECTION HORIZONTAL ;\n");
359 
360     if (layrule->hasWidth()) {
361       int minW, maxW;
362       layrule->getWidth(minW, maxW);
363       fprintf(_out, "      WIDTH %g TO %g ;\n", lefdist(minW), lefdist(maxW));
364     }
365   }
366 
367   for (idx = 0; idx < rule->getViaCount(); ++idx) {
368     dbTechVia* via = rule->getVia(idx);
369     std::string vname = via->getName();
370     fprintf(_out, "    VIA %s ;\n", vname.c_str());
371   }
372 
373   fprintf(_out, "END %s\n", name.c_str());
374 }
375 
writeTechViaGenerateRule(dbTechViaGenerateRule * rule)376 void lefout::writeTechViaGenerateRule(dbTechViaGenerateRule* rule)
377 {
378   std::string name = rule->getName();
379 
380   if (rule->isDefault())
381     fprintf(_out, "\nVIARULE %s GENERATE DEFAULT\n", name.c_str());
382   else
383     fprintf(_out, "\nVIARULE %s GENERATE \n", name.c_str());
384 
385   uint idx;
386 
387   for (idx = 0; idx < rule->getViaLayerRuleCount(); ++idx) {
388     dbTechViaLayerRule* layrule = rule->getViaLayerRule(idx);
389     dbTechLayer* layer = layrule->getLayer();
390     std::string lname = layer->getName();
391     fprintf(_out, "    LAYER %s ;\n", lname.c_str());
392 
393     if (layrule->getDirection() == dbTechLayerDir::VERTICAL)
394       fprintf(_out, "      DIRECTION VERTICAL ;\n");
395     else if (layrule->getDirection() == dbTechLayerDir::HORIZONTAL)
396       fprintf(_out, "      DIRECTION HORIZONTAL ;\n");
397 
398     if (layrule->hasOverhang())
399       fprintf(_out, "      OVERHANG %g ;\n", lefdist(layrule->getOverhang()));
400 
401     if (layrule->hasMetalOverhang())
402       fprintf(_out,
403               "      METALOVERHANG %g ;\n",
404               lefdist(layrule->getMetalOverhang()));
405 
406     if (layrule->hasEnclosure()) {
407       int overhang1, overhang2;
408       layrule->getEnclosure(overhang1, overhang2);
409       fprintf(_out,
410               "      ENCLOSURE %g %g ;\n",
411               lefdist(overhang1),
412               lefdist(overhang2));
413     }
414 
415     if (layrule->hasWidth()) {
416       int minW, maxW;
417       layrule->getWidth(minW, maxW);
418       fprintf(_out, "      WIDTH %g TO %g ;\n", lefdist(minW), lefdist(maxW));
419     }
420 
421     if (layrule->hasRect()) {
422       Rect r;
423       layrule->getRect(r);
424       fprintf(_out,
425               "      RECT  %g %g  %g %g  ;\n",
426               lefdist(r.xMin()),
427               lefdist(r.yMin()),
428               lefdist(r.xMax()),
429               lefdist(r.yMax()));
430     }
431 
432     if (layrule->hasSpacing()) {
433       int spacing_x, spacing_y;
434       layrule->getSpacing(spacing_x, spacing_y);
435       fprintf(_out,
436               "      SPACING %g BY %g ;\n",
437               lefdist(spacing_x),
438               lefdist(spacing_y));
439     }
440 
441     if (layrule->hasResistance())
442       fprintf(_out, "      RESISTANCE %g ;\n", layrule->getResistance());
443   }
444 
445   fprintf(_out, "END %s\n", name.c_str());
446 }
447 
writeSameNetRule(dbTechSameNetRule * rule)448 void lefout::writeSameNetRule(dbTechSameNetRule* rule)
449 {
450   dbTechLayer* l1 = rule->getLayer1();
451   dbTechLayer* l2 = rule->getLayer2();
452 
453   std::string n1;
454   if (_use_alias && l1->hasAlias())
455     n1 = l1->getAlias();
456   else
457     n1 = l1->getName();
458 
459   std::string n2;
460   if (_use_alias && l2->hasAlias())
461     n2 = l2->getAlias();
462   else
463     n2 = l2->getName();
464 
465   if (rule->getAllowStackedVias())
466     fprintf(_out,
467             "  SAMENET %s %s %g STACK ;\n",
468             n1.c_str(),
469             n2.c_str(),
470             lefdist(rule->getSpacing()));
471   else
472     fprintf(_out,
473             "  SAMENET %s %s %g ;\n",
474             n1.c_str(),
475             n2.c_str(),
476             lefdist(rule->getSpacing()));
477 }
478 
writeLayer(dbTechLayer * layer)479 void lefout::writeLayer(dbTechLayer* layer)
480 {
481   std::string name;
482   if (_use_alias && layer->hasAlias())
483     name = layer->getAlias();
484   else
485     name = layer->getName();
486 
487   fprintf(_out, "\nLAYER %s\n", name.c_str());
488   fprintf(_out, "    TYPE %s ;\n", layer->getType().getString());
489 
490   if (layer->getNumMasks() > 1)
491     fprintf(_out, "    MASK %u ;\n", layer->getNumMasks());
492 
493   if (layer->getPitch())
494     fprintf(_out, "    PITCH %g ;\n", lefdist(layer->getPitch()));
495 
496   if (layer->getWidth())
497     fprintf(_out, "    WIDTH %g ;\n", lefdist(layer->getWidth()));
498 
499   if (layer->getWireExtension() != 0.0)
500     fprintf(
501         _out, "    WIREEXTENSION %g ;\n", lefdist(layer->getWireExtension()));
502 
503   if (layer->hasArea())
504     fprintf(_out, "    AREA %g ;\n", layer->getArea());
505 
506   uint thickness;
507   if (layer->getThickness(thickness))
508     fprintf(_out, "    THICKNESS %.3f ;\n", lefdist(thickness));
509 
510   if (layer->hasMaxWidth())
511     fprintf(_out, "    MAXWIDTH %.3f ;\n", lefdist(layer->getMaxWidth()));
512 
513   if (layer->hasMinStep())
514     fprintf(_out, "    MINSTEP %.3f ;\n", lefdist(layer->getMinStep()));
515 
516   if (layer->hasProtrusion())
517     fprintf(_out,
518             "    PROTRUSIONWIDTH %.3f  LENGTH %.3f  WIDTH %.3f ;\n",
519             lefdist(layer->getProtrusionWidth()),
520             lefdist(layer->getProtrusionLength()),
521             lefdist(layer->getProtrusionFromWidth()));
522 
523   dbSet<dbTechLayerSpacingRule> v54_rules;
524   dbSet<dbTechLayerSpacingRule>::iterator ritr;
525 
526   std::vector<dbTechV55InfluenceEntry*> inf_rules;
527   std::vector<dbTechV55InfluenceEntry*>::const_iterator infitr;
528 
529   if (layer->getV54SpacingRules(v54_rules)) {
530     for (ritr = v54_rules.begin(); ritr != v54_rules.end(); ++ritr)
531       (*ritr)->writeLef(*this);
532   }
533 
534   if (layer->hasV55SpacingRules()) {
535     layer->printV55SpacingRules(*this);
536     if (layer->getV55InfluenceRules(inf_rules)) {
537       fprintf(_out, "SPACINGTABLE INFLUENCE");
538       for (infitr = inf_rules.begin(); infitr != inf_rules.end(); ++infitr)
539         (*infitr)->writeLef(*this);
540       fprintf(_out, " ;\n");
541     }
542   }
543 
544   std::vector<dbTechMinCutRule*> cut_rules;
545   std::vector<dbTechMinCutRule*>::const_iterator citr;
546   if (layer->getMinimumCutRules(cut_rules)) {
547     for (citr = cut_rules.begin(); citr != cut_rules.end(); citr++)
548       (*citr)->writeLef(*this);
549   }
550 
551   std::vector<dbTechMinEncRule*> enc_rules;
552   std::vector<dbTechMinEncRule*>::const_iterator eitr;
553   if (layer->getMinEnclosureRules(enc_rules)) {
554     for (eitr = enc_rules.begin(); eitr != enc_rules.end(); eitr++)
555       (*eitr)->writeLef(*this);
556   }
557 
558   layer->writeAntennaRulesLef(*this);
559 
560   if (layer->getDirection() != dbTechLayerDir::NONE)
561     fprintf(_out, "    DIRECTION %s ;\n", layer->getDirection().getString());
562 
563   if (layer->getResistance() != 0.0)
564     fprintf(_out, "    RESISTANCE RPERSQ %g ;\n", layer->getResistance());
565 
566   if (layer->getCapacitance() != 0.0)
567     fprintf(_out, "    CAPACITANCE CPERSQDIST %g ;\n", layer->getCapacitance());
568 
569   if (layer->getEdgeCapacitance() != 0.0)
570     fprintf(_out, "    EDGECAPACITANCE %g ;\n", layer->getEdgeCapacitance());
571 
572   dbProperty::writeProperties(layer, _out);
573 
574   fprintf(_out, "END %s\n", name.c_str());
575 }
576 
writeVia(dbTechVia * via)577 void lefout::writeVia(dbTechVia* via)
578 {
579   std::string name = via->getName();
580 
581   if (via->isDefault())
582     fprintf(_out, "\nVIA %s DEFAULT\n", name.c_str());
583   else
584     fprintf(_out, "\nVIA %s\n", name.c_str());
585 
586   if (via->isTopOfStack())
587     fprintf(_out, "    TOPOFSTACKONLY\n");
588 
589   if (via->getResistance() != 0.0)
590     fprintf(_out, "    RESISTANCE %g ;\n", via->getResistance());
591 
592   dbTechViaGenerateRule* rule = via->getViaGenerateRule();
593 
594   if (rule == NULL) {
595     dbSet<dbBox> boxes = via->getBoxes();
596     writeBoxes(&boxes, "    ");
597   } else {
598     std::string rname = rule->getName();
599     fprintf(_out, "\n    VIARULE %s \n", rname.c_str());
600 
601     dbViaParams P;
602     via->getViaParams(P);
603 
604     fprintf(_out,
605             " + CUTSIZE %g %g ",
606             lefdist(P.getXCutSize()),
607             lefdist(P.getYCutSize()));
608     std::string top = P.getTopLayer()->getName();
609     std::string bot = P.getBottomLayer()->getName();
610     std::string cut = P.getCutLayer()->getName();
611     fprintf(_out, " + LAYERS %s %s %s ", bot.c_str(), cut.c_str(), top.c_str());
612     fprintf(_out,
613             " + CUTSPACING %g %g ",
614             lefdist(P.getXCutSpacing()),
615             lefdist(P.getYCutSpacing()));
616     fprintf(_out,
617             " + ENCLOSURE %g %g %g %g ",
618             lefdist(P.getXBottomEnclosure()),
619             lefdist(P.getYBottomEnclosure()),
620             lefdist(P.getXTopEnclosure()),
621             lefdist(P.getYTopEnclosure()));
622 
623     if ((P.getNumCutRows() != 1) || (P.getNumCutCols() != 1))
624       fprintf(_out, " + ROWCOL %d %d ", P.getNumCutRows(), P.getNumCutCols());
625 
626     if ((P.getXOrigin() != 0) || (P.getYOrigin() != 0))
627       fprintf(_out,
628               " + ORIGIN %g %g ",
629               lefdist(P.getXOrigin()),
630               lefdist(P.getYOrigin()));
631 
632     if ((P.getXTopOffset() != 0) || (P.getYTopOffset() != 0)
633         || (P.getXBottomOffset() != 0) || (P.getYBottomOffset() != 0))
634       fprintf(_out,
635               " + OFFSET %g %g %g %g ",
636               lefdist(P.getXBottomOffset()),
637               lefdist(P.getYBottomOffset()),
638               lefdist(P.getXTopOffset()),
639               lefdist(P.getYTopOffset()));
640 
641     std::string pname = via->getPattern();
642     if (strcmp(pname.c_str(), "") != 0)
643       fprintf(_out, " + PATTERNNAME %s", pname.c_str());
644   }
645 
646   fprintf(_out, "END %s\n", name.c_str());
647 }
648 
writeLib(dbLib * lib)649 void lefout::writeLib(dbLib* lib)
650 {
651   dbSet<dbSite> sites = lib->getSites();
652   dbSet<dbSite>::iterator site_itr;
653 
654   for (site_itr = sites.begin(); site_itr != sites.end(); ++site_itr) {
655     dbSite* site = *site_itr;
656     writeSite(site);
657   }
658 
659   dbSet<dbMaster> masters = lib->getMasters();
660   dbSet<dbMaster>::iterator master_itr;
661 
662   for (master_itr = masters.begin(); master_itr != masters.end();
663        ++master_itr) {
664     dbMaster* master = *master_itr;
665     if (_write_marked_masters && !master->isMarked())
666       continue;
667     writeMaster(master);
668   }
669 }
670 
writeSite(dbSite * site)671 void lefout::writeSite(dbSite* site)
672 {
673   std::string n = site->getName();
674 
675   fprintf(_out, "SITE %s\n", n.c_str());
676   dbSiteClass sclass = site->getClass();
677   fprintf(_out, "    CLASS %s ;\n", sclass.getString());
678 
679   if (site->getSymmetryX() || site->getSymmetryY() || site->getSymmetryR90()) {
680     fprintf(_out, "    SYMMETRY");
681 
682     if (site->getSymmetryX())
683       fprintf(_out, " X");
684 
685     if (site->getSymmetryY())
686       fprintf(_out, " Y");
687 
688     if (site->getSymmetryR90())
689       fprintf(_out, " R90");
690 
691     fprintf(_out, " ;\n");
692   }
693 
694   if (site->getWidth() || site->getHeight())
695     fprintf(_out,
696             "    SIZE %g BY %g ;\n",
697             lefdist(site->getWidth()),
698             lefdist(site->getHeight()));
699 
700   fprintf(_out, "END %s\n", n.c_str());
701 }
702 
writeMaster(dbMaster * master)703 void lefout::writeMaster(dbMaster* master)
704 {
705   std::string name = master->getName();
706 
707   if (_use_master_ids)
708     fprintf(_out, "\nMACRO M%u\n", master->getMasterId());
709   else
710     fprintf(_out, "\nMACRO %s\n", name.c_str());
711 
712   if (master->getType() != dbMasterType::NONE)
713     fprintf(_out, "    CLASS %s ;\n", master->getType().getString());
714 
715   int x, y;
716   master->getOrigin(x, y);
717 
718   if ((x != 0) || (y != 0))
719     fprintf(_out, "    ORIGIN %g %g ;\n", lefdist(x), lefdist(y));
720 
721   if (master->getEEQ()) {
722     std::string eeq = master->getEEQ()->getName();
723     if (_use_master_ids)
724       fprintf(_out, "    EEQ M%u ;\n", master->getEEQ()->getMasterId());
725     else
726       fprintf(_out, "    EEQ %s ;\n", eeq.c_str());
727   }
728 
729   if (master->getLEQ()) {
730     std::string leq = master->getLEQ()->getName();
731     if (_use_master_ids)
732       fprintf(_out, "    LEQ M%u ;\n", master->getLEQ()->getMasterId());
733     else
734       fprintf(_out, "    LEQ %s ;\n", leq.c_str());
735   }
736 
737   int w = master->getWidth();
738   int h = master->getHeight();
739 
740   if ((w != 0) || (h != 0))
741     fprintf(_out, "    SIZE %g BY %g ;\n", lefdist(w), lefdist(h));
742 
743   if (master->getSymmetryX() || master->getSymmetryY()
744       || master->getSymmetryR90()) {
745     fprintf(_out, "    SYMMETRY");
746 
747     if (master->getSymmetryX())
748       fprintf(_out, " X");
749 
750     if (master->getSymmetryY())
751       fprintf(_out, " Y");
752 
753     if (master->getSymmetryR90())
754       fprintf(_out, " R90");
755 
756     fprintf(_out, " ;\n");
757   }
758 
759   if ((x != 0) || (y != 0)) {
760     dbTransform t(Point(-x, -y));
761     master->transform(t);
762   }
763 
764   if (master->getSite()) {
765     std::string site = master->getSite()->getName();
766     fprintf(_out, "    SITE %s ;\n", site.c_str());
767   }
768 
769   dbSet<dbMTerm> mterms = master->getMTerms();
770   dbSet<dbMTerm>::iterator mitr;
771 
772   for (mitr = mterms.begin(); mitr != mterms.end(); ++mitr) {
773     dbMTerm* mterm = *mitr;
774     writeMTerm(mterm);
775   }
776 
777   dbSet<dbBox> obs = master->getObstructions();
778 
779   if (obs.begin() != obs.end()) {
780     fprintf(_out, "    OBS\n");
781     writeBoxes(&obs, "      ");
782     fprintf(_out, "    END\n");
783   }
784 
785   if ((x != 0) || (y != 0)) {
786     dbTransform t(Point(x, y));
787     master->transform(t);
788   }
789 
790   if (_use_master_ids)
791     fprintf(_out, "END M%u\n", master->getMasterId());
792   else
793     fprintf(_out, "END %s\n", name.c_str());
794 }
795 
writeMTerm(dbMTerm * mterm)796 void lefout::writeMTerm(dbMTerm* mterm)
797 {
798   std::string name = mterm->getName();
799 
800   fprintf(_out, "    PIN %s\n", name.c_str());
801   fprintf(_out, "        DIRECTION %s ; \n", mterm->getIoType().getString());
802   fprintf(_out, "        USE %s ; \n", mterm->getSigType().getString());
803 
804   mterm->writeAntennaLef(*this);
805   dbSet<dbMPin> pins = mterm->getMPins();
806   dbSet<dbMPin>::iterator pitr;
807 
808   for (pitr = pins.begin(); pitr != pins.end(); ++pitr) {
809     dbMPin* pin = *pitr;
810 
811     dbSet<dbBox> geoms = pin->getGeometry();
812 
813     if (geoms.begin() != geoms.end()) {
814       fprintf(_out, "        PORT\n");
815       writeBoxes(&geoms, "            ");
816       fprintf(_out, "        END\n");
817     }
818   }
819 
820   fprintf(_out, "    END %s\n", name.c_str());
821 }
822 
writePropertyDefinition(dbProperty * prop)823 void lefout::writePropertyDefinition(dbProperty* prop)
824 {
825   std::string propName = prop->getName();
826   dbObjectType owner_type = prop->getPropOwner()->getObjectType();
827   dbProperty::Type prop_type = prop->getType();
828   std::string objectType, propType, value;
829   switch (owner_type) {
830     case dbTechLayerObj:
831       objectType = "LAYER";
832       break;
833     case dbLibObj:
834       objectType = "LIBRARY";
835       break;
836     case dbMasterObj:
837       objectType = "MACRO";
838       break;
839     case dbMPinObj:
840       objectType = "PIN";
841       break;
842     case dbTechViaObj:
843       objectType = "VIA";
844       break;
845     case dbTechViaRuleObj:
846       objectType = "VIARULE";
847       break;
848     case dbTechNonDefaultRuleObj:
849       objectType = "NONDEFAULTRULE";
850       break;
851     default:
852       return;
853   }
854 
855   switch (prop_type) {
856     case dbProperty::INT_PROP:
857     case dbProperty::BOOL_PROP:
858       propType = "INTEGER";
859       break;
860     case dbProperty::DOUBLE_PROP:
861       propType = "REAL";
862       break;
863     case dbProperty::STRING_PROP:
864       propType = "STRING";
865       break;
866     default:
867       return;
868   }
869   fprintf(_out,
870           "    %s %s %s ",
871           objectType.c_str(),
872           propName.c_str(),
873           propType.c_str());
874   if (owner_type == dbLibObj) {
875     fprintf(_out, "\n        ");
876     prop->writePropValue(prop, _out);
877     fprintf(_out, "\n    ");
878   }
879 
880   fprintf(_out, ";\n");
881 }
882 
writeObjectPropertyDefinitions(dbObject * obj,std::unordered_map<std::string,short> & propertiesMap)883 inline void lefout::writeObjectPropertyDefinitions(
884     dbObject* obj,
885     std::unordered_map<std::string, short>& propertiesMap)
886 {
887   int bitNumber;
888   switch (obj->getObjectType()) {
889     case dbTechLayerObj:
890       bitNumber = 0;
891       break;
892     case dbLibObj:
893       bitNumber = 1;
894       break;
895     case dbMasterObj:
896       bitNumber = 2;
897       break;
898     case dbMPinObj:
899       bitNumber = 3;
900       break;
901     case dbTechViaObj:
902       bitNumber = 4;
903       break;
904     case dbTechViaRuleObj:
905       bitNumber = 5;
906       break;
907     case dbTechNonDefaultRuleObj:
908       bitNumber = 6;
909       break;
910     default:
911       return;
912   }
913   dbSet<dbProperty> properties = dbProperty::getProperties(obj);
914   dbSet<dbProperty>::iterator pitr;
915   for (pitr = properties.begin(); pitr != properties.end(); ++pitr) {
916     dbProperty* prop = *pitr;
917     if (propertiesMap[prop->getName()] & 0x1 << bitNumber)
918       continue;
919     propertiesMap[prop->getName()] |= 0x1 << bitNumber;
920     writePropertyDefinition(prop);
921   }
922 }
923 
writePropertyDefinitions(dbLib * lib)924 void lefout::writePropertyDefinitions(dbLib* lib)
925 {
926   std::unordered_map<std::string, short> propertiesMap;
927   dbTech* tech = lib->getDb()->getTech();
928 
929   fprintf(_out, "\nPROPERTYDEFINITIONS\n");
930 
931   // writing property definitions of objectType LAYER
932   for (dbTechLayer* layer : tech->getLayers())
933     writeObjectPropertyDefinitions(layer, propertiesMap);
934 
935   // writing property definitions of objectType LIBRARY
936   writeObjectPropertyDefinitions(lib, propertiesMap);
937 
938   // writing property definitions of objectType MACRO
939   for (dbMaster* master : lib->getMasters()) {
940     writeObjectPropertyDefinitions(master, propertiesMap);
941     for (dbMTerm* term : master->getMTerms())
942       for (dbMPin* pin : term->getMPins())
943         writeObjectPropertyDefinitions(pin, propertiesMap);
944   }
945 
946   // writing property definitions of objectType VIA
947   for (dbTechVia* via : tech->getVias())
948     writeObjectPropertyDefinitions(via, propertiesMap);
949 
950   // writing property definitions of objectType VIARULE
951   for (dbTechViaRule* vrule : tech->getViaRules())
952     writeObjectPropertyDefinitions(vrule, propertiesMap);
953 
954   // writing property definitions of objectType NONDEFAULTRULE
955   for (dbTechNonDefaultRule* nrule : tech->getNonDefaultRules())
956     writeObjectPropertyDefinitions(nrule, propertiesMap);
957 
958   fprintf(_out, "END PROPERTYDEFINITIONS\n\n");
959 }
960 
writeTech(dbTech * tech,const char * lef_file)961 bool lefout::writeTech(dbTech* tech, const char* lef_file)
962 {
963   _out = fopen(lef_file, "w");
964 
965   if (_out == NULL) {
966     fprintf(stderr, "Cannot open LEF file %s\n", lef_file);
967     return false;
968   }
969 
970   _dist_factor = 1.0 / (double) tech->getDbUnitsPerMicron();
971   _area_factor = _dist_factor * _dist_factor;
972   writeTech(tech);
973 
974   fprintf(_out, "END LIBRARY\n");
975   fclose(_out);
976   return true;
977 }
978 
writeLib(dbLib * lib,const char * lef_file)979 bool lefout::writeLib(dbLib* lib, const char* lef_file)
980 {
981   _out = fopen(lef_file, "w");
982 
983   if (_out == NULL) {
984     fprintf(stderr, "Cannot open LEF file %s\n", lef_file);
985     return false;
986   }
987 
988   _dist_factor = 1.0 / (double) lib->getDbUnitsPerMicron();
989   _area_factor = _dist_factor * _dist_factor;
990   writeHeader(lib);
991   writeLib(lib);
992   fprintf(_out, "END LIBRARY\n");
993   fclose(_out);
994   return true;
995 }
996 
writeTechAndLib(dbLib * lib,const char * lef_file)997 bool lefout::writeTechAndLib(dbLib* lib, const char* lef_file)
998 {
999   _out = fopen(lef_file, "w");
1000 
1001   if (_out == NULL) {
1002     fprintf(stderr, "Cannot open LEF file %s\n", lef_file);
1003     return false;
1004   }
1005 
1006   _dist_factor = 1.0 / (double) lib->getDbUnitsPerMicron();
1007   _area_factor = _dist_factor * _dist_factor;
1008   dbTech* tech = lib->getDb()->getTech();
1009   writeHeader(lib);
1010   writeTech(tech);
1011   writeLib(lib);
1012   fprintf(_out, "END LIBRARY\n");
1013   fclose(_out);
1014 
1015   return true;
1016 }
1017