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 }