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