1 /*
2     SCPLACER -- a standard cell placer for ASICs.
3 
4     Copyright (c) 2019, Niels Moseley <niels@symbioticeda.com>
5 
6     Permission to use, copy, modify, and/or distribute this software for any
7     purpose with or without fee is hereby granted, provided that the above
8     copyright notice and this permission notice appear in all copies.
9 
10     THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11     WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12     MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13     ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18 */
19 
20 #include "lefreader.h"
21 
isWhitespace(char c) const22 bool LEFReader::isWhitespace(char c) const
23 {
24     return ((c==' ') || (c == '\t'));
25 }
26 
isAlpha(char c) const27 bool LEFReader::isAlpha(char c) const
28 {
29     if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))
30         return true;
31 
32     if ((c == '_') || (c == '!'))
33         return true;
34 
35     return false;
36 }
37 
isDigit(char c) const38 bool LEFReader::isDigit(char c) const
39 {
40     return ((c >= '0') && (c <= '9'));
41 }
42 
isAlphaNumeric(char c) const43 bool LEFReader::isAlphaNumeric(char c) const
44 {
45     return (isAlpha(c) || isDigit(c));
46 }
47 
48 
tokenize(std::string & tokstr)49 LEFReader::token_t LEFReader::tokenize(std::string &tokstr)
50 {
51     tokstr.clear();
52 
53     while(isWhitespace(m_tokchar) && !m_is->eof())
54     {
55         m_tokchar = m_is->get();
56     }
57 
58     if (m_is->eof())
59     {
60         return TOK_EOF;
61     }
62 
63     if ((m_tokchar==10) || (m_tokchar==13))
64     {
65         m_tokchar = m_is->get();
66         m_lineNum++;
67         return TOK_EOL;
68     }
69 
70     if (m_tokchar=='#')
71     {
72         m_tokchar = m_is->get();
73         return TOK_HASH;
74     }
75 
76     if (m_tokchar==';')
77     {
78         m_tokchar = m_is->get();
79         return TOK_SEMICOL;
80     }
81 
82     if (m_tokchar=='(')
83     {
84         m_tokchar = m_is->get();
85         return TOK_LPAREN;
86     }
87 
88     if (m_tokchar==')')
89     {
90         m_tokchar = m_is->get();
91         return TOK_RPAREN;
92     }
93 
94     if (m_tokchar=='[')
95     {
96         m_tokchar = m_is->get();
97         return TOK_LBRACKET;
98     }
99 
100     if (m_tokchar==']')
101     {
102         m_tokchar = m_is->get();
103         return TOK_RBRACKET;
104     }
105 
106     if (m_tokchar=='-')
107     {
108         // could be the start of a number
109         tokstr = m_tokchar;
110         m_tokchar = m_is->get();
111         if (isDigit(m_tokchar))
112         {
113             // it is indeed a number!
114             while(isDigit(m_tokchar) || (m_tokchar == '.') || (m_tokchar == 'e'))
115             {
116                 tokstr += m_tokchar;
117                 m_tokchar = m_is->get();
118             }
119             return TOK_NUMBER;
120         }
121         return TOK_MINUS;
122     }
123 
124     if (isAlpha(m_tokchar))
125     {
126         tokstr = m_tokchar;
127         m_tokchar = m_is->get();
128         while(isAlphaNumeric(m_tokchar))
129         {
130             tokstr += m_tokchar;
131             m_tokchar = m_is->get();
132         }
133         return TOK_IDENT;
134     }
135 
136     if (m_tokchar=='"')
137     {
138         m_tokchar = m_is->get();
139         while((m_tokchar != '"') && (m_tokchar != 10) && (m_tokchar != 13))
140         {
141             tokstr += m_tokchar;
142             m_tokchar = m_is->get();
143         }
144 
145         // skip closing quotes
146         if (m_tokchar == '"')
147         {
148             m_tokchar = m_is->get();
149         }
150 
151         // error on newline
152         if ((m_tokchar == 10) || (m_tokchar == 13))
153         {
154             // TODO: error, string cannot continue after newline!
155         }
156         return TOK_STRING;
157     }
158 
159     if (isDigit(m_tokchar))
160     {
161         tokstr = m_tokchar;
162         m_tokchar = m_is->get();
163         while(isDigit(m_tokchar) || (m_tokchar == '.') || (m_tokchar == 'e'))
164         {
165             tokstr += m_tokchar;
166             m_tokchar = m_is->get();
167         }
168         return TOK_NUMBER;
169     }
170 
171     m_tokchar = m_is->get();
172     return TOK_ERR;
173 }
174 
parse(std::istream & lefstream)175 void LEFReader::parse(std::istream &lefstream)
176 {
177     m_lineNum = 1;
178 
179     if (!lefstream.good())
180     {
181         error("LEFReader: input stream is faulty\n");
182         return;
183     }
184 
185     m_is = &lefstream;
186 
187     m_tokchar = m_is->get();
188 
189     bool m_inComment = false;
190 
191     m_curtok = TOK_EOF;
192     do
193     {
194         m_curtok = tokenize(m_tokstr);
195         if (!m_inComment)
196         {
197             switch(m_curtok)
198             {
199             case TOK_ERR:
200                 error("LEF parse error\n");
201                 break;
202             case TOK_HASH:  // line comment
203                 m_inComment = true;
204                 break;
205             case TOK_IDENT:
206                 if (m_tokstr == "MACRO")
207                 {
208                     parseMacro();
209                 }
210                 else if (m_tokstr == "LAYER")
211                 {
212                     parseLayer();
213                 }
214                 else if (m_tokstr == "VIA")
215                 {
216                     parseVia();
217                 }
218                 else if (m_tokstr == "VIARULE")
219                 {
220                     parseViaRule();
221                 }
222                 else if (m_tokstr == "UNITS")
223                 {
224                     parseUnits();
225                 }
226                 else if (m_tokstr == "PROPERTYDEFINITIONS")
227                 {
228                     parsePropertyDefintions();
229                 }
230                 break;
231             default:
232                 ;
233             }
234         }
235         else
236         {
237             if (m_curtok == TOK_EOL)
238             {
239                 m_inComment = false;
240             }
241         }
242     } while(m_curtok != TOK_EOF);
243 
244     onEndParse();
245 }
246 
error(const std::string & errstr)247 void LEFReader::error(const std::string &errstr)
248 {
249     std::cerr << "Line " << m_lineNum << " : " << errstr;
250 }
251 
parseMacro()252 bool LEFReader::parseMacro()
253 {
254     std::string name;
255 
256 
257     // macro name
258     m_curtok = tokenize(name);
259     if (m_curtok != TOK_IDENT)
260     {
261         error("Expected a macro name\n");
262         return false;
263     }
264 
265     //std::cout << "MACRO " << name << "\n";
266 
267     // expect EOL
268     m_curtok = tokenize(m_tokstr);
269     if (m_curtok != TOK_EOL)
270     {
271         error("Expected EOL\n");
272         return false;
273     }
274 
275     onMacro(name);
276 
277     // wait for 'END macroname'
278     bool endFound = false;
279     while(true)
280     {
281         m_curtok = tokenize(m_tokstr);
282 
283         if (m_curtok == TOK_IDENT)
284         {
285             if (m_tokstr == "PIN")
286             {
287                 parsePin();
288             }
289             else if (m_tokstr == "CLASS")
290             {
291                 parseClass();
292             }
293             else if (m_tokstr == "ORIGIN")
294             {
295                 parseOrigin();
296             }
297             else if (m_tokstr == "FOREIGN")
298             {
299                 parseForeign();
300             }
301             else if (m_tokstr == "SIZE")
302             {
303                 parseSize();
304             }
305             else if (m_tokstr == "SYMMETRY")
306             {
307                 parseSymmetry();
308             }
309             else if (m_tokstr == "SITE")
310             {
311                 parseSite();
312             }
313             //else if (m_tokstr == "LAYER")
314             //{
315             //    parseLayer();   // TECH LEF layer, not a port LAYER!
316             //}
317         }
318 
319         if (endFound)
320         {
321             if ((m_curtok == TOK_IDENT) && (m_tokstr == name))
322             {
323                 //cout << "END " << name << "\n";
324                 return true;
325             }
326         }
327         else if ((m_curtok == TOK_IDENT) && (m_tokstr == "END"))
328         {
329             endFound = true;
330         }
331         else
332         {
333             endFound = false;
334         }
335 
336         if (m_is->eof())
337         {
338             error("Unexpected end of file\n");
339             return false;
340         }
341     }
342 }
343 
parsePin()344 bool LEFReader::parsePin()
345 {
346     std::string name;
347 
348 
349     // pin name
350     m_curtok = tokenize(name);
351     if (m_curtok != TOK_IDENT)
352     {
353         error("Expected a pin name\n");
354         return false;
355     }
356 
357     //std::cout << "  PIN " << name << "\n";
358 
359     // expect EOL
360     m_curtok = tokenize(m_tokstr);
361     if (m_curtok != TOK_EOL)
362     {
363         error("Expected EOL\n");
364         return false;
365     }
366 
367     onPin(name);
368 
369     // wait for 'END macroname'
370     bool endFound = false;
371     while(true)
372     {
373         m_curtok = tokenize(m_tokstr);
374 
375         if (m_curtok == TOK_IDENT)
376         {
377             if (m_tokstr == "DIRECTION")
378             {
379                 parseDirection();
380             }
381             else if (m_tokstr == "USE")
382             {
383                 parseUse();
384             }
385             else if (m_tokstr == "PORT")
386             {
387                 parsePort();
388             }
389         }
390 
391         if (endFound)
392         {
393             if ((m_curtok == TOK_IDENT) && (m_tokstr == name))
394             {
395                 //std::cout << "  END " << name << "\n";
396                 return true;
397             }
398         }
399         else if ((m_curtok == TOK_IDENT) && (m_tokstr == "END"))
400         {
401             endFound = true;
402         }
403         else
404         {
405             endFound = false;
406         }
407 
408         if (m_is->eof())
409         {
410             error("Unexpected end of file\n");
411             return false;
412         }
413     }
414 }
415 
416 
parseClass()417 bool LEFReader::parseClass()
418 {
419     // CLASS name <optional name> ';'
420 
421     std::string className;
422 
423 
424     // read in all the classes
425     bool foundOne = false;
426     m_curtok = tokenize(m_tokstr);
427     while(m_curtok == TOK_IDENT)
428     {
429         foundOne = true;
430         className += m_tokstr;
431         className += " ";
432         m_curtok = tokenize(m_tokstr);
433     }
434     if (!foundOne)
435     {
436         error("Expected at least one class\n");
437         return false;
438     }
439 
440     if (m_curtok != TOK_SEMICOL)
441     {
442         error("Expected a semicolon\n");
443         return false;
444     }
445 
446     onClass(className);
447 
448     return true;
449 };
450 
parseOrigin()451 bool LEFReader::parseOrigin()
452 {
453     // ORIGIN <number> <number> ;
454 
455 
456     std::string xnum;
457     std::string ynum;
458 
459     m_curtok = tokenize(xnum);
460     if (m_curtok != TOK_NUMBER)
461     {
462         error("Expected a number\n");
463         return false;
464     }
465 
466     m_curtok = tokenize(ynum);
467     if (m_curtok != TOK_NUMBER)
468     {
469         error("Expected a number\n");
470         return false;
471     }
472 
473     m_curtok = tokenize(m_tokstr);
474     if (m_curtok != TOK_SEMICOL)
475     {
476         error("Expected a semicolon\n");
477         return false;
478     }
479 
480     double xnumd, ynumd;
481     try
482     {
483         xnumd = std::stod(xnum);
484         ynumd = std::stod(ynum);
485     }
486     catch(const std::invalid_argument& ia)
487     {
488         error(ia.what());
489     }
490 
491     onOrigin(xnumd, ynumd);
492 
493     //std::cout << "  ORIGIN " << xnum << " " << ynum << "\n";
494 
495     return true;
496 };
497 
parseSite()498 bool LEFReader::parseSite()
499 {
500     // SITE name ';'
501 
502     std::string siteName;
503 
504 
505     m_curtok = tokenize(siteName);
506     if (m_curtok != TOK_IDENT)
507     {
508         error("Expected an identifier\n");
509         return false;
510     }
511 
512     m_curtok = tokenize(m_tokstr);
513     if (m_curtok != TOK_SEMICOL)
514     {
515         error("Expected a semicolon\n");
516         return false;
517     }
518 
519     onSite(siteName);
520 
521     //std::cout << "  SITE " << siteName << "\n";
522 
523     return true;
524 };
525 
parseSize()526 bool LEFReader::parseSize()
527 {
528     // SIZE <number> BY <number> ';'
529 
530 
531     std::string xnum;
532     std::string ynum;
533 
534     m_curtok = tokenize(xnum);
535     if (m_curtok != TOK_NUMBER)
536     {
537         error("Expected a number\n");
538         return false;
539     }
540 
541     m_curtok = tokenize(m_tokstr);
542     if ((m_curtok != TOK_IDENT) && (m_tokstr != "BY"))
543     {
544         error("Expected 'BY'\n");
545         return false;
546     }
547 
548     m_curtok = tokenize(ynum);
549     if (m_curtok != TOK_NUMBER)
550     {
551         error("Expected a number\n");
552         return false;
553     }
554 
555     m_curtok = tokenize(m_tokstr);
556     if (m_curtok != TOK_SEMICOL)
557     {
558         error("Expected a semicolon\n");
559         return false;
560     }
561 
562     double xnumd, ynumd;
563     try
564     {
565         xnumd = std::stod(xnum);
566         ynumd = std::stod(ynum);
567     }
568     catch(const std::invalid_argument& ia)
569     {
570         error(ia.what());
571     }
572 
573     onSize(xnumd, ynumd);
574 
575     //std::cout << "  SIZE " << xnum << " " << ynum << "\n";
576 
577     return true;
578 };
579 
parseSymmetry()580 bool LEFReader::parseSymmetry()
581 {
582     // SYMMETRY (X|Y|R90)+ ';'
583 
584 
585     std::string symmetry;
586 
587     // read options until we get to the semicolon.
588     m_curtok = tokenize(m_tokstr);
589     while(m_curtok!= TOK_SEMICOL)
590     {
591         symmetry += m_tokstr;
592         symmetry += " ";
593         m_curtok = tokenize(m_tokstr);
594     }
595 
596     //std::cout << "  SYMMETRY " << symmetry << "\n";
597 
598     return true;
599 };
600 
parseForeign()601 bool LEFReader::parseForeign()
602 {
603     // FOREIGN <cellname> <number> <number> ;
604 
605     std::string cellname;
606     std::string xnum;
607     std::string ynum;
608 
609     m_curtok = tokenize(cellname);
610     if (m_curtok != TOK_IDENT)
611     {
612         error("Expected the cell name\n");
613         return false;
614     }
615 
616     m_curtok = tokenize(xnum);
617     if (m_curtok != TOK_NUMBER)
618     {
619         error("Expected a number\n");
620         return false;
621     }
622 
623     m_curtok = tokenize(ynum);
624     if (m_curtok != TOK_NUMBER)
625     {
626         error("Expected a number\n");
627         return false;
628     }
629 
630     m_curtok = tokenize(m_tokstr);
631     if (m_curtok != TOK_SEMICOL)
632     {
633         error("Expected a semicolon\n");
634         return false;
635     }
636 
637     double xnumd, ynumd;
638     try
639     {
640         xnumd = std::stod(xnum);
641         ynumd = std::stod(ynum);
642     }
643     catch(const std::invalid_argument& ia)
644     {
645         error(ia.what());
646     }
647 
648     onForeign(cellname, xnumd, ynumd);
649 
650     return true;
651 };
652 
653 
parseDirection()654 bool LEFReader::parseDirection()
655 {
656     // DIRECTION OUTPUT/INPUT/INOUT etc.
657     std::string direction;
658 
659     // read options until we get to the semicolon.
660     m_curtok = tokenize(direction);
661     if (m_curtok != TOK_IDENT)
662     {
663         error("Expected direction\n");
664         return false;
665     }
666 
667     m_curtok = tokenize(m_tokstr);
668     if ((direction == "OUTPUT") && (m_tokstr == "TRISTATE"))
669     {
670         // OUTPUT can be followed by TRISTATE
671         // FIXME: use enum.
672         direction += " TRISTATE";
673         m_curtok = tokenize(m_tokstr);
674     }
675 
676     if (m_curtok != TOK_SEMICOL)
677     {
678         error("Expected a semicolon\n");
679         return false;
680     }
681 
682     onPinDirection(direction);
683 
684     return true;
685 };
686 
parseUse()687 bool LEFReader::parseUse()
688 {
689     // USE OUTPUT/INPUT/INOUT etc.
690 
691     std::string use;
692 
693     m_curtok = tokenize(use);
694     if (m_curtok != TOK_IDENT)
695     {
696         error("Expected use\n");
697         return false;
698     }
699 
700     m_curtok = tokenize(m_tokstr);
701     if (m_curtok != TOK_SEMICOL)
702     {
703         error("Expected a semicolon\n");
704         return false;
705     }
706 
707     onPinUse(use);
708 
709     return true;
710 };
711 
parsePort()712 bool LEFReader::parsePort()
713 {
714     std::string name;
715 
716 
717     m_curtok = tokenize(m_tokstr);
718     if (m_curtok != TOK_EOL)
719     {
720         error("Expected EOL\n");
721         return false;
722     }
723 
724     // expect LAYER
725     m_curtok = tokenize(m_tokstr);
726     while (m_curtok == TOK_IDENT)
727     {
728         if (m_tokstr == "LAYER")
729         {
730             parsePortLayer();
731         }
732         else if (m_tokstr == "END")
733         {
734             break;
735         }
736         else
737         {
738             // eat until ;
739             do
740             {
741                 m_curtok = tokenize(m_tokstr);
742             } while(m_curtok != TOK_SEMICOL);
743 
744             // eat newline
745             m_curtok = tokenize(m_tokstr);
746             if (m_curtok != TOK_EOL)
747             {
748                 error("Expected EOL");
749                 return false;
750             }
751         }
752 
753         if (m_is->eof())
754         {
755             error("Unexpected end of file\n");
756             return false;
757         }
758     }
759     return true;
760 }
761 
parsePortLayer()762 bool LEFReader::parsePortLayer()
763 {
764     // LAYER <name> ';'
765     std::string name;
766 
767     m_curtok = tokenize(name);
768     if (m_curtok != TOK_IDENT)
769     {
770         error("Expected layer name\n");
771         return false;
772     }
773 
774     m_curtok = tokenize(m_tokstr);
775     if (m_curtok != TOK_SEMICOL)
776     {
777         error("Expected a semicolon\n");
778         return false;
779     }
780 
781     m_curtok = tokenize(m_tokstr);
782     if (m_curtok != TOK_EOL)
783     {
784         error("Expected an EOL\n");
785         return false;
786     }
787 
788     //std::cout << "    LAYER " << name << "\n";
789 
790     do
791     {
792         if (!parsePortLayerItem())
793         {
794             return false;
795         }
796     } while(m_tokstr != "END");
797 
798     return true;
799 }
800 
parsePortLayerItem()801 bool LEFReader::parsePortLayerItem()
802 {
803     m_curtok = tokenize(m_tokstr);
804     if (m_curtok != TOK_IDENT)
805     {
806         error("Expected RECT or END\n");
807         return false;
808     }
809 
810     while(1)
811     {
812         if (m_tokstr == "END")
813         {
814             return true;
815         }
816         else if (m_tokstr == "RECT")
817         {
818             parseRect();
819         }
820         m_curtok = tokenize(m_tokstr);
821     }
822 }
823 
parseRect()824 bool LEFReader::parseRect()
825 {
826 
827     std::string coords;
828 
829     for(uint32_t i=0; i<4; i++)
830     {
831         m_curtok = tokenize(m_tokstr);
832         if (m_curtok != TOK_NUMBER)
833         {
834             error("Expected number in RECT\n");
835             return false;
836         }
837         coords += m_tokstr;
838         coords += " ";
839     }
840 
841     // expect ;
842     m_curtok = tokenize(m_tokstr);
843     if (m_curtok != TOK_SEMICOL)
844     {
845         error("Expected a semicolon in RECT\n");
846         return false;
847     }
848 
849     // expect EOL
850     m_curtok = tokenize(m_tokstr);
851     if (m_curtok != TOK_EOL)
852     {
853         error("Expected an EOL in RECT\n");
854         return false;
855     }
856 
857     //std::cout << "      RECT " << coords << "\n";
858 
859     return true;
860 }
861 
parseLayer()862 bool LEFReader::parseLayer()
863 {
864     m_curtok = tokenize(m_tokstr);
865     std::string layerName = m_tokstr;
866 
867     if (m_curtok != TOK_IDENT)
868     {
869         error("Expected a layer name\n");
870         return false;
871     }
872 
873     // expect EOL
874     m_curtok = tokenize(m_tokstr);
875     if (m_curtok != TOK_EOL)
876     {
877         error("Expected EOL in LAYER\n");
878         return false;
879     }
880 
881     onLayer(layerName);
882 
883     // parse all the layer items
884     do
885     {
886         if (!parseLayerItem())
887         {
888             return false;
889         }
890     } while(m_tokstr != "END");
891 
892     // expect END <layername> EOL
893 
894     m_curtok = tokenize(m_tokstr);
895     if (m_curtok != TOK_IDENT)
896     {
897         error("Expected END <layername>\n");
898         return false;
899     }
900     if (m_tokstr != layerName)
901     {
902         error("Expected END <layername> : name does not match\n");
903         return false;
904     }
905     m_curtok = tokenize(m_tokstr);
906     if (m_curtok != TOK_EOL)
907     {
908         error("Expected EOL\n");
909         return false;
910     }
911 
912     return true;
913 }
914 
parseLayerItem()915 bool LEFReader::parseLayerItem()
916 {
917     m_curtok = tokenize(m_tokstr);
918     if (m_curtok != TOK_IDENT)
919     {
920         error("Expected identifier in layer item\n");
921         return false;
922     }
923     if (m_tokstr == "PITCH")
924     {
925         return parseLayerPitch();
926     }
927     else if (m_tokstr == "OFFSET")
928     {
929         return parseLayerOffset();
930     }
931     else if (m_tokstr == "TYPE")
932     {
933         return parseLayerType();
934     }
935     else if (m_tokstr == "DIRECTION")
936     {
937         return parseLayerDirection();
938     }
939     else if (m_tokstr == "WIDTH")
940     {
941         return parseLayerWidth();
942     }
943     else if (m_tokstr == "MAXWIDTH")
944     {
945         return parseLayerMaxWidth();
946     }
947     else if (m_tokstr == "END")
948     {
949         return true;
950     }
951     else
952     {
953         // eat everything on the line
954         while((m_curtok != TOK_EOL) && (m_curtok != TOK_EOF))
955         {
956             m_curtok = tokenize(m_tokstr);
957         }
958         if (m_curtok == TOK_EOF)
959         {
960             error("Unexpected end of file");
961             return false;
962         }
963     }
964 
965     return true;
966 }
967 
parseLayerPitch()968 bool LEFReader::parseLayerPitch()
969 {
970     std::string pitch;
971     m_curtok = tokenize(m_tokstr);
972     if (m_curtok != TOK_NUMBER)
973     {
974         error("Expected a number in layer pitch\n");
975         return false;
976     }
977 
978     pitch = m_tokstr;
979 
980     // expect ;
981     m_curtok = tokenize(m_tokstr);
982     if (m_curtok != TOK_SEMICOL)
983     {
984         error("Expected a semicolon in layer pitch\n");
985         return false;
986     }
987 
988     // expect EOL
989     m_curtok = tokenize(m_tokstr);
990     if (m_curtok != TOK_EOL)
991     {
992         error("Expected an EOL\n");
993         return false;
994     }
995 
996     double pitchd;
997     try
998     {
999         pitchd = std::stod(pitch);
1000     }
1001     catch(const std::invalid_argument& ia)
1002     {
1003         error(ia.what());
1004     }
1005 
1006     onLayerPitch(pitchd);
1007 
1008     return true;
1009 }
1010 
parseLayerOffset()1011 bool LEFReader::parseLayerOffset()
1012 {
1013     std::string offset;
1014     m_curtok = tokenize(m_tokstr);
1015     if (m_curtok != TOK_NUMBER)
1016     {
1017         error("Expected a number in layer offset\n");
1018         return false;
1019     }
1020 
1021     offset = m_tokstr;
1022 
1023     // expect ;
1024     m_curtok = tokenize(m_tokstr);
1025     if (m_curtok != TOK_SEMICOL)
1026     {
1027         error("Expected a semicolon in layer offset\n");
1028         return false;
1029     }
1030 
1031     // expect EOL
1032     m_curtok = tokenize(m_tokstr);
1033     if (m_curtok != TOK_EOL)
1034     {
1035         error("Expected an EOL\n");
1036         return false;
1037     }
1038 
1039     double offsetd;
1040     try
1041     {
1042         offsetd = std::stod(offset);
1043     }
1044     catch(const std::invalid_argument& ia)
1045     {
1046         error(ia.what());
1047     }
1048 
1049     onLayerOffset(offsetd);
1050 
1051     return true;
1052 }
1053 
parseLayerType()1054 bool LEFReader::parseLayerType()
1055 {
1056     std::string layerType;
1057     m_curtok = tokenize(m_tokstr);
1058     if (m_curtok != TOK_IDENT)
1059     {
1060         error("Expected a string in layer type\n");
1061         return false;
1062     }
1063 
1064     layerType = m_tokstr;
1065 
1066     // expect ;
1067     m_curtok = tokenize(m_tokstr);
1068     if (m_curtok != TOK_SEMICOL)
1069     {
1070         error("Expected a semicolon in layer type\n");
1071         return false;
1072     }
1073 
1074     // expect EOL
1075     m_curtok = tokenize(m_tokstr);
1076     if (m_curtok != TOK_EOL)
1077     {
1078         error("Expected an EOL\n");
1079         return false;
1080     }
1081 
1082     onLayerType(layerType);
1083 
1084     return true;
1085 }
1086 
parseLayerWidth()1087 bool LEFReader::parseLayerWidth()
1088 {
1089     std::string width;
1090     m_curtok = tokenize(m_tokstr);
1091     if (m_curtok != TOK_NUMBER)
1092     {
1093         error("Expected a number in layer width\n");
1094         return false;
1095     }
1096 
1097     width = m_tokstr;
1098 
1099     // expect ;
1100     m_curtok = tokenize(m_tokstr);
1101     if (m_curtok != TOK_SEMICOL)
1102     {
1103         error("Expected a semicolon in layer width\n");
1104         return false;
1105     }
1106 
1107     // expect EOL
1108     m_curtok = tokenize(m_tokstr);
1109     if (m_curtok != TOK_EOL)
1110     {
1111         error("Expected an EOL\n");
1112         return false;
1113     }
1114 
1115     double widthd;
1116     try
1117     {
1118         widthd = std::stod(width);
1119     }
1120     catch(const std::invalid_argument& ia)
1121     {
1122         error(ia.what());
1123     }
1124 
1125     onLayerWidth(widthd);
1126 
1127     return true;
1128 }
1129 
parseLayerMaxWidth()1130 bool LEFReader::parseLayerMaxWidth()
1131 {
1132     std::string maxwidth;
1133     m_curtok = tokenize(m_tokstr);
1134     if (m_curtok != TOK_NUMBER)
1135     {
1136         error("Expected a number in layer max width\n");
1137         return false;
1138     }
1139 
1140     maxwidth = m_tokstr;
1141 
1142     // expect ;
1143     m_curtok = tokenize(m_tokstr);
1144     if (m_curtok != TOK_SEMICOL)
1145     {
1146         error("Expected a semicolon in layer max width\n");
1147         return false;
1148     }
1149 
1150     // expect EOL
1151     m_curtok = tokenize(m_tokstr);
1152     if (m_curtok != TOK_EOL)
1153     {
1154         error("Expected an EOL\n");
1155         return false;
1156     }
1157 
1158     double maxwidthd;
1159     try
1160     {
1161         maxwidthd = std::stod(maxwidth);
1162     }
1163     catch(const std::invalid_argument& ia)
1164     {
1165         error(ia.what());
1166     }
1167 
1168     onLayerMaxWidth(maxwidthd);
1169 
1170     return true;
1171 }
1172 
parseLayerDirection()1173 bool LEFReader::parseLayerDirection()
1174 {
1175     std::string direction;
1176     m_curtok = tokenize(m_tokstr);
1177     if (m_curtok != TOK_IDENT)
1178     {
1179         error("Expected a string in layer direction\n");
1180         return false;
1181     }
1182 
1183     direction = m_tokstr;
1184 
1185     // expect ;
1186     m_curtok = tokenize(m_tokstr);
1187     if (m_curtok != TOK_SEMICOL)
1188     {
1189         error("Expected a semicolon in layer direction\n");
1190         return false;
1191     }
1192 
1193     // expect EOL
1194     m_curtok = tokenize(m_tokstr);
1195     if (m_curtok != TOK_EOL)
1196     {
1197         error("Expected an EOL\n");
1198         return false;
1199     }
1200 
1201     onLayerDirection(direction);
1202 
1203     return true;
1204 }
1205 
parseVia()1206 bool LEFReader::parseVia()
1207 {
1208     // VIA <vianame> ...
1209     // keep on reading tokens until we
1210     // find END <vianame>
1211 
1212     m_curtok = tokenize(m_tokstr);
1213     std::string viaName;
1214 
1215     if (m_curtok != TOK_IDENT)
1216     {
1217         error("Expected identifier in via name\n");
1218         return false;
1219     }
1220 
1221     viaName = m_tokstr;
1222 
1223     // read until we get END <vianame>
1224     do
1225     {
1226         m_curtok = tokenize(m_tokstr);
1227         while(m_tokstr != "END")
1228         {
1229             m_curtok = tokenize(m_tokstr);
1230         }
1231 
1232         // read via name
1233         m_curtok = tokenize(m_tokstr);
1234         if (m_curtok != TOK_IDENT)
1235         {
1236             error("Expected via name after END\n");
1237             return false;
1238         }
1239     } while(m_tokstr == viaName);
1240 
1241     m_curtok = tokenize(m_tokstr);
1242     if (m_curtok != TOK_EOL)
1243     {
1244         error("Expected EOL after END <vianame>\n");
1245         return false;
1246     }
1247 
1248     return true;
1249 }
1250 
parseViaRule()1251 bool LEFReader::parseViaRule()
1252 {
1253     // VIARULE <vianame> ...
1254     // keep on reading tokens until we
1255     // find END <vianame>
1256 
1257     m_curtok = tokenize(m_tokstr);
1258     std::string viaRuleName;
1259 
1260     if (m_curtok != TOK_IDENT)
1261     {
1262         error("Expected identifier in viarule name\n");
1263         return false;
1264     }
1265 
1266     viaRuleName = m_tokstr;
1267 
1268     // read until we get END <vianame>
1269     do
1270     {
1271         m_curtok = tokenize(m_tokstr);
1272         while(m_tokstr != "END")
1273         {
1274             m_curtok = tokenize(m_tokstr);
1275         }
1276 
1277         // read via name
1278         m_curtok = tokenize(m_tokstr);
1279         if (m_curtok != TOK_IDENT)
1280         {
1281             error("Expected viarule name after END\n");
1282             return false;
1283         }
1284     } while(m_tokstr == viaRuleName);
1285 
1286     m_curtok = tokenize(m_tokstr);
1287     if (m_curtok != TOK_EOL)
1288     {
1289         error("Expected EOL after END <viarule name>\n");
1290         return false;
1291     }
1292 
1293     return true;
1294 }
1295 
parseUnits()1296 bool LEFReader::parseUnits()
1297 {
1298     // UNITS
1299     //   DATABASE MICRONS ;
1300     //   ...
1301     // END UNITS
1302 
1303     // expect EOL after UNITS
1304 
1305     m_curtok = tokenize(m_tokstr);
1306     if (m_curtok != TOK_EOL)
1307     {
1308         error("Expected EOL after UNITS\n");
1309         return false;
1310     }
1311 
1312     while(1)
1313     {
1314         m_curtok = tokenize(m_tokstr);
1315 
1316         if (m_curtok != TOK_IDENT)
1317         {
1318             error("Expected string in units block\n");
1319             return false;
1320         }
1321 
1322         if (m_tokstr == "DATABASE")
1323         {
1324             m_curtok = tokenize(m_tokstr);
1325             if ((m_curtok == TOK_IDENT) && (m_tokstr == "MICRONS"))
1326             {
1327                 m_curtok = tokenize(m_tokstr);
1328                 if (m_curtok == TOK_NUMBER)
1329                 {
1330                     double micronsd;
1331                     try
1332                     {
1333                         micronsd = std::stod(m_tokstr);
1334                     }
1335                     catch(const std::invalid_argument& ia)
1336                     {
1337                         error(ia.what());
1338                         return false;
1339                     }
1340 
1341                     // expect ; and EOL
1342                     m_curtok = tokenize(m_tokstr);
1343                     if (m_curtok != TOK_SEMICOL)
1344                     {
1345                         error("Expected ; after DATABASE MICRONS <number>\n");
1346                         return false;
1347                     }
1348 
1349                     m_curtok = tokenize(m_tokstr);
1350                     if (m_curtok != TOK_EOL)
1351                     {
1352                         error("Expected EOL after DATABASE MICRONS <number> ;\n");
1353                         return false;
1354                     }
1355 
1356                     onDatabaseUnitsMicrons(micronsd);
1357                 }
1358                 else
1359                 {
1360                     error("Expected a number after DATABASE MICRONS\n");
1361                     return false;
1362                 }
1363             }
1364             else
1365             {
1366                 error("Expects MICRONS keywords after DATABASE\n");
1367                 return false;
1368             }
1369         }
1370         else if (m_tokstr == "END")
1371         {
1372             // check for units
1373             m_curtok = tokenize(m_tokstr);
1374             if ((m_curtok == TOK_IDENT) && (m_tokstr == "UNITS"))
1375             {
1376                 return true;
1377             }
1378             else
1379             {
1380                 // read until EOL
1381                 while ((m_curtok != TOK_EOL) && (m_curtok != TOK_EOF))
1382                 {
1383                     m_curtok = tokenize(m_tokstr);
1384                 }
1385             }
1386         }
1387         else
1388         {
1389             // got something other than DATABASE or END
1390             // read until EOL
1391             while ((m_curtok != TOK_EOL) && (m_curtok != TOK_EOF))
1392             {
1393                 m_curtok = tokenize(m_tokstr);
1394             }
1395         }
1396     }
1397 }
1398 
parsePropertyDefintions()1399 bool LEFReader::parsePropertyDefintions()
1400 {
1401     // basically, eat everything until
1402     // we encounter END PROPERTYDEFINTIONS EOL
1403 
1404     while(1)
1405     {
1406         m_curtok = tokenize(m_tokstr);
1407         if ((m_curtok == TOK_IDENT) && (m_tokstr == "END"))
1408         {
1409             m_curtok = tokenize(m_tokstr);
1410             if ((m_curtok == TOK_IDENT) && (m_tokstr == "PROPERTYDEFINITIONS"))
1411             {
1412                 m_curtok = tokenize(m_tokstr);
1413                 if (m_curtok == TOK_EOL)
1414                 {
1415                     return true;
1416                 }
1417                 else if (m_curtok == TOK_EOF)
1418                 {
1419                     error("Unexpected end of liberty file\n");
1420                     return false;
1421                 }
1422             }
1423             else if (m_curtok == TOK_EOF)
1424             {
1425                 error("Unexpected end of liberty file\n");
1426                 return false;
1427             }
1428         }
1429         else if (m_curtok == TOK_EOF)
1430         {
1431             error("Unexpected end of liberty file\n");
1432             return false;
1433         }
1434     }
1435 }