1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977
|
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilog-Perl bison parser
//
// This file is part of Verilog-Perl.
//
// Author: Wilson Snyder <wsnyder@wsnyder.org>
//
// Code available from: http://www.veripool.org/systemperl
//
//*************************************************************************
//
// Copyright 2001-2019 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
%{
#include <cstdio>
#include <fstream>
#include <stack>
#include <vector>
#include <map>
#include <deque>
#include <cassert>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <climits>
#include "VParse.h"
#include "VParseGrammar.h"
#define YYERROR_VERBOSE 1
#define YYINITDEPTH 5000 // Large as the stack won't grow, since YYSTYPE_IS_TRIVIAL isn't defined
#define YYMAXDEPTH 5000
// See VParseGrammar.h for the C++ interface to this parser
// Include that instead of VParseBison.h
//*************************************************************************
#define GRAMMARP VParseGrammar::staticGrammarp()
#define PARSEP VParseGrammar::staticParsep()
#define NEWSTRING(text) (string((text)))
#define SPACED(a,b) ((a)+(((a)=="" || (b)=="")?"":" ")+(b))
#define VARRESET_LIST(decl) { GRAMMARP->pinNum(1); VARRESET(); VARDECL(decl); } // Start of pinlist
#define VARRESET_NONLIST(decl) { GRAMMARP->pinNum(0); VARRESET(); VARDECL(decl); } // Not in a pinlist
#define VARRESET() { VARDECL(""); VARIO(""); VARNET(""); VARDTYPE(""); } // Start of one variable decl
// VARDECL("") indicates inside a port list or IO list and we shouldn't declare the variable
#define VARDECL(type) { GRAMMARP->m_varDecl = (type); } // genvar, parameter, localparam
#define VARIO(type) { GRAMMARP->m_varIO = (type); } // input, output, inout, ref, const ref
#define VARNET(type) { GRAMMARP->m_varNet = (type); } // supply*,wire,tri
#define VARDTYPE(type) { GRAMMARP->m_varDType = (type); } // "signed", "int", etc
#define PINNUMINC() { GRAMMARP->pinNumInc(); }
#define INSTPREP(cellmod,cellparam,withinInst) { GRAMMARP->pinNum(1); GRAMMARP->m_cellMod=(cellmod); GRAMMARP->m_cellParam=(cellparam); GRAMMARP->m_withinInst = 1; }
#define INSTDONE() { GRAMMARP->m_withinInst = 0; }
enum net_idx {NI_NETNAME = 0, NI_MSB, NI_LSB};
static void VARDONE(VFileLine* fl, const string& name, const string& array, const string& value) {
if (GRAMMARP->m_varIO!="" && GRAMMARP->m_varDecl=="") GRAMMARP->m_varDecl="port";
if (GRAMMARP->m_varDecl!="") {
PARSEP->varCb(fl, GRAMMARP->m_varDecl, name, PARSEP->symObjofUpward(), GRAMMARP->m_varNet,
GRAMMARP->m_varDType, array, value);
}
if (GRAMMARP->m_varIO!="" || GRAMMARP->pinNum()) {
PARSEP->portCb(fl, name, PARSEP->symObjofUpward(),
GRAMMARP->m_varIO, GRAMMARP->m_varDType, array, GRAMMARP->pinNum());
}
if (GRAMMARP->m_varDType == "type") {
PARSEP->syms().replaceInsert(VAstType::TYPE,name);
}
}
static void VARDONETYPEDEF(VFileLine* fl, const string& name, const string& type, const string& array) {
VARRESET(); VARDECL("typedef"); VARDTYPE(type);
VARDONE(fl,name,array,"");
// TYPE shouldn't override a more specific node type, as often is forward reference
PARSEP->syms().replaceInsert(VAstType::TYPE,name);
}
static void parse_net_constants(VFileLine* fl, VParseHashElem nets[][3]) {
VParseHashElem (*net)[3] = &nets[0];
VParseHashElem* nhp = net[0];
std::deque<VParseNet>::iterator it = GRAMMARP->m_portStack.begin();
while (it != GRAMMARP->m_portStack.end()) {
// Default net name is simply the complete token
const char* netnamep = it->m_name.c_str();
size_t delim = it->m_name.find_first_of("'");
if (it->m_name[0] != '\\' && it->m_msb.empty()
&& delim != string::npos && it->m_name[delim] == '\'') {
// Handle sized integer constants (e.g., 7'b0) specifically but ignore replications (e.g., {4{w}})
if (delim != 0 && netnamep[0] != '{') {
// Handle the first part that indicates the width for sized constants (guaranteed to be a decimal)
char* endp;
errno = 0;
long l = strtol(netnamep, &endp, 10);
if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX || l <= 0) {
fl->error((string)"Unexpected length in size of integer constant: \""+netnamep+"\".");
return;
}
// Skip whitespace
while (endp < netnamep + delim && isspace(*endp)) {
endp++;
}
if (endp != netnamep + delim) {
fl->error((string)"Could not convert size of integer constant: \""+netnamep+"\".");
return;
}
int count = l;
// Skip characters up to the delimiter ' to determine new netnamep
netnamep += delim;
// Test for legal base specifiers:
// d, D, h, H, o, O , b, or B for the decimal, hexadecimal, octal, and binary bases, respectively
char base = netnamep[1];
// 's' indicates a signed constant, is followed by the actual base; currently ignored
if (base == 's' || base == 'S') {
base = netnamep[2];
}
if (strchr("dDhHoObB", base) == NULL) {
fl->error((string)"Base specifier \""+base+"\" is not valid in integer constant \""+it->m_name.c_str()+"\".");
return;
}
// These assignments could be prettified with C++11
nhp[NI_MSB].keyp = "msb";
nhp[NI_MSB].val_type = VParseHashElem::ELEM_INT;
nhp[NI_MSB].val_int = count - 1;
nhp[NI_LSB].keyp = "lsb";
nhp[NI_LSB].val_type = VParseHashElem::ELEM_INT;
nhp[NI_LSB].val_int = 0;
} else {
// fl->error increases the error count which would create regressions for no good reasons.
// There is no ->warn or similar though but we could print, e.g., to stderr in these cases
//fl->error((string)"Neither unsized integer constant nor replications are not fully supported in nets (\""+netnamep+"\").");
//fprintf(stderr, "Neither unsized integer constant nor replications are not fully supported in nets (\"%s\").\n", netnamep);
}
} else {
// Ordinary net names might have a range attached or not.
// If it does then parse its bounds into proper integers.
const char *msbstr = it->m_msb.c_str();
if (msbstr[0] != '\0') {
{ // Parse NI_MSB
char* endp;
errno = 0;
long l = strtol(msbstr, &endp, 10);
// Test for range within int, and proper parsing
if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX || l < 0
|| (endp && l == 0 && errno == ERANGE)) {
fl->error((string)"Unexpected length in msb specification of \""+netnamep+"\" (endp="+endp+", errno="+strerror(errno)+").");
return;
}
nhp[NI_MSB].keyp = "msb";
nhp[NI_MSB].val_type = VParseHashElem::ELEM_INT;
nhp[NI_MSB].val_int = (int)l;
}
{ // Parse NI_LSB
char* endp;
errno = 0;
long l = strtol(it->m_lsb.c_str(), &endp, 10);
if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX || l < 0
|| (endp && l == 0 && errno == ERANGE)) {
fl->error((string)"Unexpected length in lsb specification of \""+netnamep+"\".");
return;
}
nhp[NI_LSB].keyp = "lsb";
nhp[NI_LSB].val_type = VParseHashElem::ELEM_INT;
nhp[NI_LSB].val_int = (int)l;
}
} else {
nhp[NI_MSB].keyp = NULL;
nhp[NI_LSB].keyp = NULL;
}
}
nhp[NI_NETNAME].keyp = "netname";
nhp[NI_NETNAME].val_type = VParseHashElem::ELEM_STR;
nhp[NI_NETNAME].val_str = netnamep;
*it++;
nhp += 3; // We operate on three elements in each iteration
}
}
static void PINDONE(VFileLine* fl, const string& name, const string& expr) {
if (GRAMMARP->m_cellParam) {
// Stack them until we create the instance itself
GRAMMARP->m_pinStack.push_back(VParseGPin(fl, name, expr, GRAMMARP->pinNum()));
} else {
PARSEP->pinCb(fl, name, expr, GRAMMARP->pinNum());
if (PARSEP->usePinSelects()) {
if (GRAMMARP->m_portStack.empty()) {
string netname;
if (GRAMMARP->m_portNextNetName.empty()) {
netname = expr;
} else {
netname = GRAMMARP->m_portNextNetName;
}
size_t elem_cnt = GRAMMARP->m_portNextNetMsb.empty() ? 1 : 3;
VParseHashElem nets[elem_cnt];
// These assignments could be prettified with C++11
nets[NI_NETNAME].keyp = "netname";
nets[NI_NETNAME].val_type = VParseHashElem::ELEM_STR;
nets[NI_NETNAME].val_str = netname;
if (elem_cnt > 1) {
nets[NI_MSB].keyp = "msb";
nets[NI_MSB].val_type = VParseHashElem::ELEM_STR;
nets[NI_MSB].val_str = GRAMMARP->m_portNextNetMsb;
nets[NI_LSB].keyp = "lsb";
nets[NI_LSB].val_type = VParseHashElem::ELEM_STR;
nets[NI_LSB].val_str = GRAMMARP->m_portNextNetLsb;
}
PARSEP->pinselectsCb(fl, name, 1, elem_cnt, &nets[0], GRAMMARP->pinNum());
} else {
// Connection with multiple pins was parsed completely.
// There might be one net left in the pipe...
if (GRAMMARP->m_portNextNetValid) {
GRAMMARP->m_portStack.push_front(VParseNet(GRAMMARP->m_portNextNetName, GRAMMARP->m_portNextNetMsb, GRAMMARP->m_portNextNetLsb));
}
unsigned int arraycnt = GRAMMARP->m_portStack.size();
VParseHashElem nets[arraycnt][3];
parse_net_constants(fl, nets);
PARSEP->pinselectsCb(fl, name, arraycnt, 3, &nets[0][0], GRAMMARP->pinNum());
}
// Clear all pin-related fields
GRAMMARP->m_portNextNetValid = false;
GRAMMARP->m_portNextNetName.clear();
GRAMMARP->m_portStack.clear();
GRAMMARP->m_portNextNetMsb.clear();
GRAMMARP->m_portNextNetLsb.clear();
}
}
}
static void PINPARAMS() {
// Throw out all the "pins" we found before we could do instanceCb
while (!GRAMMARP->m_pinStack.empty()) {
VParseGPin& pinr = GRAMMARP->m_pinStack.front();
PARSEP->parampinCb(pinr.m_fl, pinr.m_name, pinr.m_conn, pinr.m_number);
GRAMMARP->m_pinStack.pop_front();
}
GRAMMARP->m_withinPin = true;
}
static void PORTNET(VFileLine* fl, const string& name) {
if (!GRAMMARP->m_withinInst) {
return;
}
GRAMMARP->m_portNextNetValid = true;
GRAMMARP->m_portNextNetName = name;
GRAMMARP->m_portNextNetMsb.clear();
GRAMMARP->m_portNextNetLsb.clear();
}
static void PORTRANGE(const string& msb, const string& lsb) {
if (!GRAMMARP->m_withinInst) {
return;
}
GRAMMARP->m_portNextNetMsb = msb;
GRAMMARP->m_portNextNetLsb = lsb;
}
static void PIN_CONCAT_APPEND(const string& expr) {
if (!GRAMMARP->m_withinPin) {
return;
}
if (!GRAMMARP->m_portNextNetValid) {
// Only while not within a valid net term the expression is part
// of a replication constant. If that's detected ignore the
// previous expression (that is actually just the contained
// concatenation) in favor of the full replication expression.
if (expr[0] == '{') {
if (expr.find_first_of("{", 1) != string::npos) {
// fprintf(stderr, "%d: ignoring \"%s\" in favor of \"%s\".\n", __LINE__, GRAMMARP->m_portStack.front().m_name.c_str(), expr.c_str());
GRAMMARP->m_portStack.pop_front();
GRAMMARP->m_portStack.push_front(VParseNet(expr));
}
} else {
GRAMMARP->m_portStack.push_front(VParseNet(expr));
}
} else {
GRAMMARP->m_portStack.push_front(VParseNet(GRAMMARP->m_portNextNetName, GRAMMARP->m_portNextNetMsb, GRAMMARP->m_portNextNetLsb));
}
GRAMMARP->m_portNextNetValid = false;
}
/* Yacc */
static int VParseBisonlex(VParseBisonYYSType* yylvalp) { return PARSEP->lexToBison(yylvalp); }
static void VParseBisonerror(const char *s) { VParseGrammar::bisonError(s); }
static void ERRSVKWD(VFileLine* fileline, const string& tokname) {
static int toldonce = 0;
fileline->error((string)"Unexpected \""+tokname+"\": \""+tokname+"\" is a SystemVerilog keyword misused as an identifier.");
if (!toldonce++) fileline->error("Modify the Verilog-2001 code to avoid SV keywords, or use `begin_keywords or --language.");
}
static void NEED_S09(VFileLine*, const string&) {
//Let lint tools worry about it
//fileline->error((string)"Advanced feature: \""+tokname+"\" is a 1800-2009 construct, but used under --language 1800-2005 or earlier.");
}
%}
BISONPRE_VERSION(0.0, 2.999, %pure_parser)
BISONPRE_VERSION(3.0, %pure-parser)
BISONPRE_VERSION(0.0, 2.999, %token_table)
BISONPRE_VERSION(3.0, %token-table)
BISONPRE_VERSION(2.4, 2.999, %define lr.keep_unreachable_states)
BISONPRE_VERSION(3.0, %define lr.keep-unreachable-state)
// When writing Bison patterns we use yTOKEN instead of "token",
// so Bison will error out on unknown "token"s.
// Generic lexer tokens, for example a number
// IEEE: real_number
%token<str> yaFLOATNUM "FLOATING-POINT NUMBER"
// IEEE: identifier, class_identifier, class_variable_identifier,
// covergroup_variable_identifier, dynamic_array_variable_identifier,
// enum_identifier, interface_identifier, interface_instance_identifier,
// package_identifier, type_identifier, variable_identifier,
%token<str> yaID__ETC "IDENTIFIER"
%token<str> yaID__LEX "IDENTIFIER-in-lex"
%token<str> yaID__aPACKAGE "PACKAGE-IDENTIFIER"
%token<str> yaID__aTYPE "TYPE-IDENTIFIER"
// aCOVERGROUP is same as aTYPE
// Can't predecode aFUNCTION, can declare after use
// Can't predecode aINTERFACE, can declare after use
// Can't predecode aTASK, can declare after use
// IEEE: integral_number
%token<str> yaINTNUM "INTEGER NUMBER"
// IEEE: time_literal + time_unit
%token<str> yaTIMENUM "TIME NUMBER"
// IEEE: string_literal
%token<str> yaSTRING "STRING"
%token<str> yaSTRING__IGNORE "STRING-ignored" // Used when expr:string not allowed
%token<str> yaTIMINGSPEC "TIMING SPEC ELEMENT"
%token<str> ygenGATE "GATE keyword"
%token<str> ygenCONFIGKEYWORD "CONFIG keyword (cell/use/design/etc)"
%token<str> ygenOPERATOR "OPERATOR"
%token<str> ygenSTRENGTH "STRENGTH keyword (strong1/etc)"
%token<str> ygenSYSCALL "SYSCALL"
%token<str> '!'
%token<str> '#'
%token<str> '%'
%token<str> '&'
%token<str> '('
%token<str> ')'
%token<str> '*'
%token<str> '+'
%token<str> ','
%token<str> '-'
%token<str> '.'
%token<str> '/'
%token<str> ':'
%token<str> ';'
%token<str> '<'
%token<str> '='
%token<str> '>'
%token<str> '?'
%token<str> '@'
%token<str> '['
%token<str> ']'
%token<str> '^'
%token<str> '{'
%token<str> '|'
%token<str> '}'
%token<str> '~'
// Specific keywords
// yKEYWORD means match "keyword"
// Other cases are yXX_KEYWORD where XX makes it unique,
// for example yP_ for punctuation based operators.
// Double underscores "yX__Y" means token X followed by Y,
// and "yX__ETC" means X folled by everything but Y(s).
%token<str> yACCEPT_ON "accept_on"
%token<str> yALIAS "alias"
%token<str> yALWAYS "always"
%token<str> yAND "and"
%token<str> yASSERT "assert"
%token<str> yASSIGN "assign"
%token<str> yASSUME "assume"
%token<str> yAUTOMATIC "automatic"
%token<str> yBEFORE "before"
%token<str> yBEGIN "begin"
%token<str> yBIND "bind"
%token<str> yBINS "bins"
%token<str> yBINSOF "binsof"
%token<str> yBIT "bit"
%token<str> yBREAK "break"
%token<str> yBUF "buf"
%token<str> yBYTE "byte"
%token<str> yCASE "case"
%token<str> yCASEX "casex"
%token<str> yCASEZ "casez"
%token<str> yCHANDLE "chandle"
%token<str> yCHECKER "checker"
%token<str> yCLASS "class"
%token<str> yCLOCK "clock"
%token<str> yCLOCKING "clocking"
%token<str> yCONSTRAINT "constraint"
%token<str> yCONST__ETC "const"
%token<str> yCONST__LEX "const-in-lex"
%token<str> yCONST__LOCAL "const-then-local"
%token<str> yCONST__REF "const-then-ref"
%token<str> yCONTEXT "context"
%token<str> yCONTINUE "continue"
%token<str> yCOVER "cover"
%token<str> yCOVERGROUP "covergroup"
%token<str> yCOVERPOINT "coverpoint"
%token<str> yCROSS "cross"
%token<str> yDEASSIGN "deassign"
%token<str> yDEFAULT "default"
%token<str> yDEFPARAM "defparam"
%token<str> yDISABLE "disable"
%token<str> yDIST "dist"
%token<str> yDO "do"
%token<str> yEDGE "edge"
%token<str> yELSE "else"
%token<str> yEND "end"
%token<str> yENDCASE "endcase"
%token<str> yENDCHECKER "endchecker"
%token<str> yENDCLASS "endclass"
%token<str> yENDCLOCKING "endclocking"
%token<str> yENDFUNCTION "endfunction"
%token<str> yENDGENERATE "endgenerate"
%token<str> yENDGROUP "endgroup"
%token<str> yENDINTERFACE "endinterface"
%token<str> yENDMODULE "endmodule"
%token<str> yENDPACKAGE "endpackage"
%token<str> yENDPROGRAM "endprogram"
%token<str> yENDPROPERTY "endproperty"
%token<str> yENDSEQUENCE "endsequence"
%token<str> yENDSPECIFY "endspecify"
%token<str> yENDTABLE "endtable"
%token<str> yENDTASK "endtask"
%token<str> yENUM "enum"
%token<str> yEVENT "event"
%token<str> yEVENTUALLY "eventually"
%token<str> yEXPECT "expect"
%token<str> yEXPORT "export"
%token<str> yEXTENDS "extends"
%token<str> yEXTERN "extern"
%token<str> yFINAL "final"
%token<str> yFIRST_MATCH "first_match"
%token<str> yFOR "for"
%token<str> yFORCE "force"
%token<str> yFOREACH "foreach"
%token<str> yFOREVER "forever"
%token<str> yFORK "fork"
%token<str> yFORKJOIN "forkjoin"
%token<str> yFUNCTION__ETC "function"
%token<str> yFUNCTION__LEX "function-in-lex"
%token<str> yFUNCTION__aPUREV "function-is-pure-virtual"
%token<str> yGENERATE "generate"
%token<str> yGENVAR "genvar"
%token<str> yGLOBAL__CLOCKING "global-then-clocking"
%token<str> yGLOBAL__LEX "global-in-lex"
%token<str> yIF "if"
%token<str> yIFF "iff"
%token<str> yIGNORE_BINS "ignore_bins"
%token<str> yILLEGAL_BINS "illegal_bins"
%token<str> yIMPLEMENTS "implements"
%token<str> yIMPLIES "implies"
%token<str> yIMPORT "import"
%token<str> yINITIAL "initial"
%token<str> yINOUT "inout"
%token<str> yINPUT "input"
%token<str> yINSIDE "inside"
%token<str> yINT "int"
%token<str> yINTEGER "integer"
%token<str> yINTERCONNECT "interconnect"
%token<str> yINTERFACE "interface"
%token<str> yINTERSECT "intersect"
%token<str> yJOIN "join"
%token<str> yLET "let"
%token<str> yLOCALPARAM "localparam"
%token<str> yLOCAL__COLONCOLON "local-then-::"
%token<str> yLOCAL__ETC "local"
%token<str> yLOCAL__LEX "local-in-lex"
%token<str> yLOGIC "logic"
%token<str> yLONGINT "longint"
%token<str> yMATCHES "matches"
%token<str> yMODPORT "modport"
%token<str> yMODULE "module"
%token<str> yNAND "nand"
%token<str> yNEGEDGE "negedge"
%token<str> yNETTYPE "nettype"
%token<str> yNEW__ETC "new"
%token<str> yNEW__LEX "new-in-lex"
%token<str> yNEW__PAREN "new-then-paren"
%token<str> yNEXTTIME "nexttime"
%token<str> yNOR "nor"
%token<str> yNOT "not"
%token<str> yNULL "null"
%token<str> yOR "or"
%token<str> yOUTPUT "output"
%token<str> yPACKAGE "package"
%token<str> yPACKED "packed"
%token<str> yPARAMETER "parameter"
%token<str> yPOSEDGE "posedge"
%token<str> yPRIORITY "priority"
%token<str> yPROGRAM "program"
%token<str> yPROPERTY "property"
%token<str> yPROTECTED "protected"
%token<str> yPURE "pure"
%token<str> yRAND "rand"
%token<str> yRANDC "randc"
%token<str> yRANDCASE "randcase"
%token<str> yRANDSEQUENCE "randsequence"
%token<str> yREAL "real"
%token<str> yREALTIME "realtime"
%token<str> yREF "ref"
%token<str> yREG "reg"
%token<str> yREJECT_ON "reject_on"
%token<str> yRELEASE "release"
%token<str> yREPEAT "repeat"
%token<str> yRESTRICT "restrict"
%token<str> yRETURN "return"
%token<str> ySCALARED "scalared"
%token<str> ySEQUENCE "sequence"
%token<str> ySHORTINT "shortint"
%token<str> ySHORTREAL "shortreal"
%token<str> ySIGNED "signed"
%token<str> ySOFT "soft"
%token<str> ySOLVE "solve"
%token<str> ySPECIFY "specify"
%token<str> ySPECPARAM "specparam"
%token<str> ySTATIC__CONSTRAINT "static-then-constraint"
%token<str> ySTATIC__ETC "static"
%token<str> ySTATIC__LEX "static-in-lex"
%token<str> ySTRING "string"
%token<str> ySTRONG "strong"
%token<str> ySTRUCT "struct"
%token<str> ySUPER "super"
%token<str> ySUPPLY0 "supply0"
%token<str> ySUPPLY1 "supply1"
%token<str> ySYNC_ACCEPT_ON "sync_accept_on"
%token<str> ySYNC_REJECT_ON "sync_reject_on"
%token<str> yS_ALWAYS "s_always"
%token<str> yS_EVENTUALLY "s_eventually"
%token<str> yS_NEXTTIME "s_nexttime"
%token<str> yS_UNTIL "s_until"
%token<str> yS_UNTIL_WITH "s_until_with"
%token<str> yTABLE "table"
%token<str> yTAGGED "tagged"
%token<str> yTASK__ETC "task"
%token<str> yTASK__LEX "task-in-lex"
%token<str> yTASK__aPUREV "task-is-pure-virtual"
%token<str> yTHIS "this"
%token<str> yTHROUGHOUT "throughout"
%token<str> yTIME "time"
%token<str> yTIMEPRECISION "timeprecision"
%token<str> yTIMEUNIT "timeunit"
%token<str> yTRI "tri"
%token<str> yTRI0 "tri0"
%token<str> yTRI1 "tri1"
%token<str> yTRIAND "triand"
%token<str> yTRIOR "trior"
%token<str> yTRIREG "trireg"
%token<str> yTYPE "type"
%token<str> yTYPEDEF "typedef"
%token<str> yUNION "union"
%token<str> yUNIQUE "unique"
%token<str> yUNIQUE0 "unique0"
%token<str> yUNSIGNED "unsigned"
%token<str> yUNTIL "until"
%token<str> yUNTIL_WITH "until_with"
%token<str> yUNTYPED "untyped"
%token<str> yVAR "var"
%token<str> yVECTORED "vectored"
%token<str> yVIRTUAL__CLASS "virtual-then-class"
%token<str> yVIRTUAL__ETC "virtual"
%token<str> yVIRTUAL__INTERFACE "virtual-then-interface"
%token<str> yVIRTUAL__LEX "virtual-in-lex"
%token<str> yVIRTUAL__anyID "virtual-then-identifier"
%token<str> yVOID "void"
%token<str> yWAIT "wait"
%token<str> yWAIT_ORDER "wait_order"
%token<str> yWAND "wand"
%token<str> yWEAK "weak"
%token<str> yWHILE "while"
%token<str> yWILDCARD "wildcard"
%token<str> yWIRE "wire"
%token<str> yWITHIN "within"
%token<str> yWITH__BRA "with-then-["
%token<str> yWITH__CUR "with-then-{"
%token<str> yWITH__ETC "with"
%token<str> yWITH__LEX "with-in-lex"
%token<str> yWITH__PAREN "with-then-("
%token<str> yWOR "wor"
%token<str> yXNOR "xnor"
%token<str> yXOR "xor"
%token<str> yD_ERROR "$error"
%token<str> yD_FATAL "$fatal"
%token<str> yD_INFO "$info"
%token<str> yD_ROOT "$root"
%token<str> yD_UNIT "$unit"
%token<str> yD_WARNING "$warning"
%token<str> yP_TICK "'"
%token<str> yP_TICKBRA "'{"
%token<str> yP_OROR "||"
%token<str> yP_ANDAND "&&"
%token<str> yP_NOR "~|"
%token<str> yP_XNOR "^~"
%token<str> yP_NAND "~&"
%token<str> yP_EQUAL "=="
%token<str> yP_NOTEQUAL "!="
%token<str> yP_CASEEQUAL "==="
%token<str> yP_CASENOTEQUAL "!=="
%token<str> yP_WILDEQUAL "==?"
%token<str> yP_WILDNOTEQUAL "!=?"
%token<str> yP_GTE ">="
%token<str> yP_LTE "<="
%token<str> yP_LTE__IGNORE "<=-ignored" // Used when expr:<= means assignment
%token<str> yP_SLEFT "<<"
%token<str> yP_SRIGHT ">>"
%token<str> yP_SSRIGHT ">>>"
%token<str> yP_POW "**"
%token<str> yP_PAR__IGNORE "(-ignored" // Used when sequence_expr:expr:( is ignored
%token<str> yP_PAR__STRENGTH "(-for-strength"
%token<str> yP_LTMINUSGT "<->"
%token<str> yP_PLUSCOLON "+:"
%token<str> yP_MINUSCOLON "-:"
%token<str> yP_MINUSGT "->"
%token<str> yP_MINUSGTGT "->>"
%token<str> yP_EQGT "=>"
%token<str> yP_ASTGT "*>"
%token<str> yP_ANDANDAND "&&&"
%token<str> yP_POUNDPOUND "##"
%token<str> yP_POUNDMINUSPD "#-#"
%token<str> yP_POUNDEQPD "#=#"
%token<str> yP_DOTSTAR ".*"
%token<str> yP_ATAT "@@"
%token<str> yP_COLONCOLON "::"
%token<str> yP_COLONEQ ":="
%token<str> yP_COLONDIV ":/"
%token<str> yP_ORMINUSGT "|->"
%token<str> yP_OREQGT "|=>"
%token<str> yP_BRASTAR "[*"
%token<str> yP_BRAEQ "[="
%token<str> yP_BRAMINUSGT "[->"
%token<str> yP_BRAPLUSKET "[+]"
%token<str> yP_PLUSPLUS "++"
%token<str> yP_MINUSMINUS "--"
%token<str> yP_PLUSEQ "+="
%token<str> yP_MINUSEQ "-="
%token<str> yP_TIMESEQ "*="
%token<str> yP_DIVEQ "/="
%token<str> yP_MODEQ "%="
%token<str> yP_ANDEQ "&="
%token<str> yP_OREQ "|="
%token<str> yP_XOREQ "^="
%token<str> yP_SLEFTEQ "<<="
%token<str> yP_SRIGHTEQ ">>="
%token<str> yP_SSRIGHTEQ ">>>="
// '( is not a operator, as "' (" is legal
//********************
// Verilog op precedence
%token<str> prUNARYARITH
%token<str> prREDUCTION
%token<str> prNEGATION
%token<str> prEVENTBEGIN
%token<str> prTAGGED
// These prevent other conflicts
%left yP_ANDANDAND
%left yMATCHES
%left prTAGGED
%left prSEQ_CLOCKING
// Lowest precedence
// These are in IEEE 17.7.1
%nonassoc yALWAYS yS_ALWAYS yEVENTUALLY yS_EVENTUALLY yACCEPT_ON yREJECT_ON ySYNC_ACCEPT_ON ySYNC_REJECT_ON
%right yP_ORMINUSGT yP_OREQGT yP_POUNDMINUSPD yP_POUNDEQPD
%right yUNTIL yS_UNTIL yUNTIL_WITH yS_UNTIL_WITH yIMPLIES
%right yIFF
%left yOR
%left yAND
%nonassoc yNOT yNEXTTIME yS_NEXTTIME
%left yINTERSECT
%left yWITHIN
%right yTHROUGHOUT
%left prPOUNDPOUND_MULTI
%left yP_POUNDPOUND
%left yP_BRASTAR yP_BRAEQ yP_BRAMINUSGT yP_BRAPLUSKET
// Not specified, but needed higher than yOR, lower than normal non-pexpr expressions
%left yPOSEDGE yNEGEDGE yEDGE
%left '{' '}'
//%nonassoc '=' yP_PLUSEQ yP_MINUSEQ yP_TIMESEQ yP_DIVEQ yP_MODEQ yP_ANDEQ yP_OREQ yP_XOREQ yP_SLEFTEQ yP_SRIGHTEQ yP_SSRIGHTEQ yP_COLONEQ yP_COLONDIV yP_LTE
%right yP_MINUSGT yP_LTMINUSGT
%right '?' ':'
%left yP_OROR
%left yP_ANDAND
%left '|' yP_NOR
%left '^' yP_XNOR
%left '&' yP_NAND
%left yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL
%left '>' '<' yP_GTE yP_LTE yP_LTE__IGNORE yINSIDE yDIST
%left yP_SLEFT yP_SRIGHT yP_SSRIGHT
%left '+' '-'
%left '*' '/' '%'
%left yP_POW
%left prUNARYARITH yP_MINUSMINUS yP_PLUSPLUS prREDUCTION prNEGATION
%left '.'
// Not in IEEE, but need to avoid conflicts; TICK should bind tightly just lower than COLONCOLON
%left yP_TICK
//%left '(' ')' '[' ']' yP_COLONCOLON '.'
%nonassoc prLOWER_THAN_ELSE
%nonassoc yELSE
//BISONPRE_TYPES
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
%start source_text
%%
//**********************************************************************
// Feedback to the Lexer
// Note we read a parenthesis ahead, so this may not change the lexer at the right point.
statePushVlg: // For PSL lexing, escape current state into Verilog state
/* empty */ { }
;
statePop: // Return to previous lexing state
/* empty */ { }
;
//**********************************************************************
// Files
source_text: // ==IEEE: source_text
/* empty */ { }
// // timeunits_declaration moved into description:package_item
| descriptionList { }
;
descriptionList: // IEEE: part of source_text
description { }
| descriptionList description { }
;
description: // ==IEEE: description
module_declaration { }
// // udp_declaration moved into module_declaration
| interface_declaration { }
| program_declaration { }
| package_declaration { }
| package_item { }
| bind_directive { }
// unsupported // IEEE: config_declaration
| error { }
;
timeunits_declaration: // ==IEEE: timeunits_declaration
yTIMEUNIT yaTIMENUM ';' { }
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';' { NEED_S09($<fl>1,"timeunit /"); }
| yTIMEPRECISION yaTIMENUM ';' { }
;
//**********************************************************************
// Packages
package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE
{ PARSEP->endpackageCb($<fl>3,$3);
PARSEP->symPopScope(VAstType::PACKAGE); }
;
packageFront:
// // Lifetime is 1800-2009
yPACKAGE lifetimeE idAny ';'
{ PARSEP->symPushNew(VAstType::PACKAGE, $3);
PARSEP->packageCb($<fl>1,$1, $3); }
;
package_itemListE: // IEEE: [{ package_item }]
/* empty */ { }
| package_itemList { }
;
package_itemList: // IEEE: { package_item }
package_item { }
| package_itemList package_item { }
;
package_item: // ==IEEE: package_item
package_or_generate_item_declaration { }
| anonymous_program { }
| package_export_declaration { }
| timeunits_declaration { }
;
package_or_generate_item_declaration: // ==IEEE: package_or_generate_item_declaration
net_declaration { }
| data_declaration { }
| task_declaration { }
| function_declaration { }
| checker_declaration { }
| dpi_import_export { }
| extern_constraint_declaration { }
| class_declaration { }
// // class_constructor_declaration is part of function_declaration
| local_parameter_declaration ';' { }
| parameter_declaration ';' { }
| covergroup_declaration { }
| overload_declaration { }
| assertion_item_declaration { }
| ';' { }
;
package_import_declarationList:
package_import_declaration { }
| package_import_declarationList package_import_declaration { }
;
package_import_declaration: // ==IEEE: package_import_declaration
yIMPORT package_import_itemList ';' { }
;
package_import_itemList:
package_import_item { }
| package_import_itemList ',' package_import_item { }
;
package_import_item: // ==IEEE: package_import_item
yaID__aPACKAGE yP_COLONCOLON package_import_itemObj
{ PARSEP->syms().import($<fl>1,$1,$3);
PARSEP->importCb($<fl>1,$1,$3); }
;
package_import_itemObj<str>: // IEEE: part of package_import_item
idAny { $<fl>$=$<fl>1; $$=$1; }
| '*' { $<fl>$=$<fl>1; $$=$1; }
;
package_export_declaration<str>: // IEEE: package_export_declaration
yEXPORT '*' yP_COLONCOLON '*' ';' { }
| yEXPORT package_import_itemList ';' { }
;
//**********************************************************************
// Module headers
module_declaration: // ==IEEE: module_declaration
// // timeunits_declaration instead in module_item
// // IEEE: module_nonansi_header + module_ansi_header
modFront importsAndParametersE portsStarE ';'
module_itemListE yENDMODULE endLabelE
{ PARSEP->endmoduleCb($<fl>6,$6);
PARSEP->symPopScope(VAstType::MODULE); }
//
| yEXTERN modFront importsAndParametersE portsStarE ';'
{ PARSEP->symPopScope(VAstType::MODULE); }
;
modFront:
// // General note: all *Front functions must call symPushNew before
// // any formal arguments, as the arguments must land in the new scope.
yMODULE lifetimeE idAny
{ PARSEP->symPushNew(VAstType::MODULE, $3);
PARSEP->moduleCb($<fl>1,$1,$3,false,PARSEP->inCellDefine()); }
;
importsAndParametersE: // IEEE: common part of module_declaration, interface_declaration, program_declaration
// // { package_import_declaration } [ parameter_port_list ]
parameter_port_listE { }
| package_import_declarationList parameter_port_listE { }
;
parameter_value_assignmentE: // IEEE: [ parameter_value_assignment ]
/* empty */ { }
| '#' '(' cellpinList ')' { }
// // Side effect of combining *_instantiations
| '#' delay_value { }
;
parameter_port_listE: // IEEE: parameter_port_list + empty == parameter_value_assignment
/* empty */ { }
| '#' '(' ')' { }
// // IEEE: '#' '(' list_of_param_assignments { ',' parameter_port_declaration } ')'
// // IEEE: '#' '(' parameter_port_declaration { ',' parameter_port_declaration } ')'
// // Can't just do that as "," conflicts with between vars and between stmts, so
// // split into pre-comma and post-comma parts
| '#' '(' {VARRESET_LIST("parameter");} paramPortDeclOrArgList ')' { VARRESET_NONLIST(""); }
// // Note legal to start with "a=b" with no parameter statement
;
paramPortDeclOrArgList: // IEEE: list_of_param_assignments + { parameter_port_declaration }
paramPortDeclOrArg { }
| paramPortDeclOrArgList ',' paramPortDeclOrArg { }
;
paramPortDeclOrArg: // IEEE: param_assignment + parameter_port_declaration
// // We combine the two as we can't tell which follows a comma
param_assignment { }
| parameter_port_declarationFront param_assignment { }
;
portsStarE: // IEEE: .* + list_of_ports + list_of_port_declarations + empty
/* empty */ { }
// // .* expanded from module_declaration
// // '(' ')' handled by list_of_ports:portE
| '(' yP_DOTSTAR ')' { }
| '(' {VARRESET_LIST("");} list_of_portsE ')' { VARRESET_NONLIST(""); }
;
list_of_portsE: // IEEE: list_of_ports + list_of_port_declarations
portE { }
| list_of_portsE ',' portE { }
;
portE: // ==IEEE: [ port ]
// // Though not type for interfaces, we factor out the port direction and type
// // so we can simply handle it in one place
//
// // IEEE: interface_port_header port_identifier { unpacked_dimension }
// // Expanded interface_port_header
// // We use instantCb here because the non-port form looks just like a module instantiation
/* empty */ { }
| portDirNetE id/*interface*/ idAny/*port*/ variable_dimensionListE sigAttrListE
{ VARDTYPE($2); VARIO("interface"); VARDONE($<fl>2, $3, $4, ""); PINNUMINC();
PARSEP->instantCb($<fl>2, $2, $3, $4); PARSEP->endcellCb($<fl>2,""); }
| portDirNetE yINTERFACE idAny/*port*/ variable_dimensionListE sigAttrListE
{ VARDTYPE($2); VARIO("interface"); VARDONE($<fl>2, $3, $4, ""); PINNUMINC(); }
| portDirNetE id/*interface*/ '.' idAny/*modport*/ idAny/*port*/ variable_dimensionListE sigAttrListE
{ VARDTYPE($2+"."+$4); VARIO("interface"); VARDONE($<fl>2, $5, $6, ""); PINNUMINC();
PARSEP->instantCb($<fl>2, $2, $5, $6); PARSEP->endcellCb($<fl>2,""); }
| portDirNetE yINTERFACE '.' idAny/*modport*/ idAny/*port*/ variable_dimensionListE sigAttrListE
{ VARDTYPE($2+"."+$4); VARIO("interface"); VARDONE($<fl>2, $5, $6, ""); PINNUMINC(); }
//
// // IEEE: ansi_port_declaration, with [port_direction] removed
// // IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension } [ '=' constant_expression ]
// // IEEE: [ net_port_header | variable_port_header ] '.' port_identifier '(' [ expression ] ')'
// // IEEE: [ variable_port_header ] port_identifier { variable_dimension } [ '=' constant_expression ]
// // Substitute net_port_header = [ port_direction ] net_port_type
// // Substitute variable_port_header = [ port_direction ] variable_port_type
// // Substitute net_port_type = [ net_type ] data_type_or_implicit
// // Substitute variable_port_type = var_data_type
// // [ [ port_direction ] net_port_type | interface_port_header ] port_identifier { unpacked_dimension }
// // [ [ port_direction ] var_data_type ] port_identifier variable_dimensionListE [ '=' constant_expression ]
// // [ [ port_direction ] net_port_type | [ port_direction ] var_data_type ] '.' port_identifier '(' [ expression ] ')'
//
// // Remove optional '[...] id' is in portAssignment
// // Remove optional '[port_direction]' is in port
// // net_port_type | interface_port_header port_identifier { unpacked_dimension }
// // net_port_type | interface_port_header port_identifier { unpacked_dimension }
// // var_data_type port_identifier variable_dimensionListE [ '=' constExpr ]
// // net_port_type | [ port_direction ] var_data_type '.' port_identifier '(' [ expr ] ')'
// // Expand implicit_type
//
// // IEEE-2012: Since a net_type_identifier is a data_type, it falls into
// // the rules here without change.
//
// // variable_dimensionListE instead of rangeListE to avoid conflicts
//
// // Note implicit rules looks just line declaring additional followon port
// // No VARDECL("port") for implicit, as we don't want to declare variables for them
| portDirNetE var_data_type '.' portSig '(' portAssignExprE ')' sigAttrListE
{ VARDTYPE($2); VARDONE($<fl>4, $4, "", ""); PINNUMINC(); }
| portDirNetE signing '.' portSig '(' portAssignExprE ')' sigAttrListE
{ VARDTYPE($2); VARDONE($<fl>4, $4, "", ""); PINNUMINC(); }
| portDirNetE signingE variable_dimensionList '.' portSig '(' portAssignExprE ')' sigAttrListE
{ VARDTYPE(SPACED($2,$3)); VARDONE($<fl>5, $5, "", ""); PINNUMINC(); }
| portDirNetE yINTERCONNECT signingE variable_dimensionListE '.' portSig '(' portAssignExprE ')' sigAttrListE
{ VARDTYPE(SPACED(SPACED($2,$3),$4)); VARDONE($<fl>6, $6, "", ""); PINNUMINC(); }
| portDirNetE /*implicit*/ '.' portSig '(' portAssignExprE ')' sigAttrListE
{ /*VARDTYPE-same*/ VARDONE($<fl>3, $3, "", ""); PINNUMINC(); }
//
| portDirNetE var_data_type portSig variable_dimensionListE sigAttrListE
{ VARDTYPE($2); VARDONE($<fl>3, $3, $4, ""); PINNUMINC(); }
| portDirNetE signing portSig variable_dimensionListE sigAttrListE
{ VARDTYPE($2); VARDONE($<fl>3, $3, $4, ""); PINNUMINC(); }
| portDirNetE signingE variable_dimensionList portSig variable_dimensionListE sigAttrListE
{ VARDTYPE(SPACED($2,$3)); VARDONE($<fl>4, $4, $5, ""); PINNUMINC(); }
| portDirNetE yINTERCONNECT signingE variable_dimensionList portSig variable_dimensionListE sigAttrListE
{ VARDTYPE(SPACED(SPACED($2,$3),$4)); VARDONE($<fl>5, $5, $6, ""); PINNUMINC(); }
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE
{ /*VARDTYPE-same*/ VARDONE($<fl>2, $2, $3, ""); PINNUMINC(); }
//
| portDirNetE var_data_type portSig variable_dimensionListE sigAttrListE '=' constExpr
{ VARDTYPE($2); VARDONE($<fl>3, $3, $4, $7); PINNUMINC(); }
| portDirNetE signing portSig variable_dimensionListE sigAttrListE '=' constExpr
{ VARDTYPE($2); VARDONE($<fl>3, $3, $4, $7); PINNUMINC(); }
| portDirNetE signingE variable_dimensionList portSig variable_dimensionListE sigAttrListE '=' constExpr
{ VARDTYPE(SPACED($2,$3)); VARDONE($<fl>4, $4, $5, $8); PINNUMINC(); }
| portDirNetE yINTERCONNECT signingE variable_dimensionList portSig variable_dimensionListE sigAttrListE '=' constExpr
{ VARDTYPE(SPACED(SPACED($2,$3),$4)); VARDONE($<fl>5, $5, $6, $9); PINNUMINC(); }
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr
{ /*VARDTYPE-same*/ VARDONE($<fl>2, $2, $3, $6); PINNUMINC(); }
//
| '{' list_of_portsE '}' { }
;
portDirNetE: // IEEE: part of port, optional net type and/or direction
/* empty */ { }
// // Per spec, if direction given default the nettype.
// // The higher level rule may override this VARDTYPE with one later in the parse.
| port_direction { VARDTYPE(""/*default_nettype*/); }
| port_direction net_type { VARDTYPE(""/*default_nettype*/); } // net_type calls VARNET
| net_type { } // net_type calls VARNET
;
port_declNetE: // IEEE: part of port_declaration, optional net type
/* empty */ { }
| net_type { } // net_type calls VARNET
;
portAssignExprE: // IEEE: part of port, optional expression
/* empty */ { }
| expr { }
;
portSig<str>:
id/*port*/ { $<fl>$=$<fl>1; $$=$1; }
| idSVKwd { $<fl>$=$<fl>1; $$=$1; }
;
//**********************************************************************
// Interface headers
interface_declaration: // IEEE: interface_declaration + interface_nonansi_header + interface_ansi_header:
// // timeunits_delcarationE is instead in interface_item
intFront importsAndParametersE portsStarE ';'
interface_itemListE yENDINTERFACE endLabelE
{ PARSEP->endinterfaceCb($<fl>6, $6);
PARSEP->symPopScope(VAstType::INTERFACE); }
| yEXTERN intFront importsAndParametersE portsStarE ';' { }
;
intFront:
yINTERFACE lifetimeE idAny/*new_interface*/
{ PARSEP->symPushNew(VAstType::INTERFACE,$3);
PARSEP->interfaceCb($<fl>1,$1,$3); }
;
interface_itemListE:
/* empty */ { }
| interface_itemList { }
;
interface_itemList:
interface_item { }
| interface_itemList interface_item { }
;
interface_item: // IEEE: interface_item + non_port_interface_item
port_declaration ';' { }
// // IEEE: non_port_interface_item
| generate_region { }
| interface_or_generate_item { }
| program_declaration { }
// // IEEE 1800-2017: modport_item
// // See instead old 2012 position in interface_or_generate_item
| interface_declaration { }
| timeunits_declaration { }
// // See note in interface_or_generate item
| module_common_item { }
;
interface_or_generate_item: // ==IEEE: interface_or_generate_item
// // module_common_item in interface_item, as otherwise duplicated
// // with module_or_generate_item:module_common_item
// // IEEE 1800-2017 removes modport_declaration here
// // but for 2012 compatibility we retain it
modport_declaration { }
| extern_tf_declaration { }
;
//**********************************************************************
// Program headers
anonymous_program: // ==IEEE: anonymous_program
// // See the spec - this doesn't change the scope, items still go up "top"
yPROGRAM ';' anonymous_program_itemListE yENDPROGRAM { }
;
anonymous_program_itemListE: // IEEE: { anonymous_program_item }
/* empty */ { }
| anonymous_program_itemList { }
;
anonymous_program_itemList: // IEEE: { anonymous_program_item }
anonymous_program_item { }
| anonymous_program_itemList anonymous_program_item { }
;
anonymous_program_item: // ==IEEE: anonymous_program_item
task_declaration { }
| function_declaration { }
| class_declaration { }
| covergroup_declaration { }
// // class_constructor_declaration is part of function_declaration
| ';' { }
;
program_declaration: // IEEE: program_declaration + program_nonansi_header + program_ansi_header:
// // timeunits_delcarationE is instead in program_item
pgmFront importsAndParametersE portsStarE ';'
program_itemListE yENDPROGRAM endLabelE
{ PARSEP->endprogramCb($<fl>6,$6);
PARSEP->symPopScope(VAstType::PROGRAM); }
| yEXTERN pgmFront importsAndParametersE portsStarE ';'
{ PARSEP->symPopScope(VAstType::PROGRAM); }
;
pgmFront:
yPROGRAM lifetimeE idAny/*new_program*/
{ PARSEP->symPushNew(VAstType::PROGRAM,$3);
PARSEP->programCb($<fl>1,$1, $3);
}
;
program_itemListE: // ==IEEE: [{ program_item }]
/* empty */ { }
| program_itemList { }
;
program_itemList: // ==IEEE: { program_item }
program_item { }
| program_itemList program_item { }
;
program_item: // ==IEEE: program_item
port_declaration ';' { }
| non_port_program_item { }
;
non_port_program_item: // ==IEEE: non_port_program_item
continuous_assign { }
| module_or_generate_item_declaration { }
| initial_construct { }
| final_construct { }
| concurrent_assertion_item { }
| timeunits_declaration { }
| program_generate_item { }
;
program_generate_item: // ==IEEE: program_generate_item
loop_generate_construct { }
| conditional_generate_construct { }
| generate_region { }
| elaboration_system_task { }
;
extern_tf_declaration: // ==IEEE: extern_tf_declaration
yEXTERN task_prototype ';' { }
| yEXTERN function_prototype ';' { }
| yEXTERN yFORKJOIN task_prototype ';' { }
;
modport_declaration: // ==IEEE: modport_declaration
yMODPORT modport_itemList ';' { }
;
modport_itemList: // IEEE: part of modport_declaration
modport_item { }
| modport_itemList ',' modport_item { }
;
modport_item: // ==IEEE: modport_item
modport_idFront '(' {VARRESET_LIST("");} modportPortsDeclList ')'
{ VARRESET_NONLIST("");
PARSEP->endmodportCb($<fl>1, "endmodport");
PARSEP->symPopScope(VAstType::MODPORT); }
;
modport_idFront:
id/*new-modport*/
{ PARSEP->symPushNew(VAstType::MODPORT,$1);
PARSEP->modportCb($<fl>1,"modport",$1); }
;
modportPortsDeclList:
modportPortsDecl { }
| modportPortsDeclList ',' modportPortsDecl { }
;
// IEEE: modport_ports_declaration + modport_simple_ports_declaration
// + (modport_tf_ports_declaration+import_export) + modport_clocking_declaration
// We've expanded the lists each take to instead just have standalone ID ports.
// We track the type as with the V2k series of defines, then create as each ID is seen.
modportPortsDecl:
// // IEEE: modport_simple_ports_declaration
port_direction modportSimplePort { }
// // IEEE: modport_clocking_declaration
| yCLOCKING idAny/*clocking_identifier*/ { }
| yIMPORT modport_tf_port { }
| yEXPORT modport_tf_port { }
// Continuations of above after a comma.
// // IEEE: modport_simple_ports_declaration
| modportSimplePort { }
;
modportSimplePort: // IEEE: modport_simple_port or modport_tf_port, depending what keyword was earlier
// // Note 'init' field is used to say what to connect to
id { VARDONE($<fl>1,$1,"",$1); PINNUMINC(); }
| '.' idAny '(' ')' { VARDONE($<fl>1,$2,"",""); PINNUMINC(); }
| '.' idAny '(' expr ')' { VARDONE($<fl>1,$2,"",$4); PINNUMINC(); }
;
modport_tf_port: // ==IEEE: modport_tf_port
id/*tf_identifier*/ { }
| method_prototype { }
;
//************************************************
// Variable Declarations
genvar_declaration: // ==IEEE: genvar_declaration
yGENVAR list_of_genvar_identifiers ';' { }
;
list_of_genvar_identifiers: // IEEE: list_of_genvar_identifiers (for declaration)
genvar_identifierDecl { }
| list_of_genvar_identifiers ',' genvar_identifierDecl { }
;
genvar_identifierDecl: // IEEE: genvar_identifier (for declaration)
id/*new-genvar_identifier*/ sigAttrListE { VARRESET_NONLIST("genvar"); VARDONE($<fl>1, $1, "", ""); }
;
local_parameter_declaration: // IEEE: local_parameter_declaration
// // See notes in parameter_declaration
local_parameter_declarationFront list_of_param_assignments { }
;
parameter_declaration: // IEEE: parameter_declaration
// // IEEE: yPARAMETER yTYPE list_of_type_assignments ';'
// // Instead of list_of_type_assignments
// // we use list_of_param_assignments because for port handling
// // it already must accept types, so simpler to have code only one place
parameter_declarationFront list_of_param_assignments { }
;
local_parameter_declarationFront: // IEEE: local_parameter_declaration w/o assignment
varLParamReset implicit_typeE { VARRESET(); VARDECL("localparam"); VARDTYPE($2); }
| varLParamReset data_type { VARRESET(); VARDECL("localparam"); VARDTYPE($2); }
| varLParamReset yTYPE { VARRESET(); VARDECL("localparam"); VARDTYPE($2); }
;
parameter_declarationFront: // IEEE: parameter_declaration w/o assignment
varGParamReset implicit_typeE { VARRESET(); VARDECL("parameter"); VARDTYPE($2); }
| varGParamReset data_type { VARRESET(); VARDECL("parameter"); VARDTYPE($2); }
| varGParamReset yTYPE { VARRESET(); VARDECL("parameter"); VARDTYPE($2); }
;
parameter_port_declarationFront: // IEEE: parameter_port_declaration w/o assignment
// // IEEE: parameter_declaration (minus assignment)
parameter_declarationFront { }
| local_parameter_declarationFront { /*NEED_S09(CURLINE(),"port localparams");*/ }
//
| data_type { VARDTYPE($1); }
| yTYPE { VARDTYPE($1); }
;
net_declaration: // IEEE: net_declaration - excluding implict
net_declarationFront netSigList ';' { }
;
net_declarationFront: // IEEE: beginning of net_declaration
net_declRESET net_type strengthSpecE net_scalaredE net_dataType { VARDTYPE(SPACED($4,$5)); }
| net_declRESET yINTERCONNECT signingE rangeListE { VARNET($2); VARDTYPE(SPACED($3,$4)); }
;
net_declRESET:
/* empty */ { VARRESET_NONLIST("net"); }
;
net_scalaredE<str>:
/* empty */ { $$=""; }
| ySCALARED { $<fl>$=$<fl>1; $$=$1; }
| yVECTORED { $<fl>$=$<fl>1; $$=$1; }
;
net_dataType<str>:
// // If there's a SV data type there shouldn't be a delay on this wire
// // Otherwise #(...) can't be determined to be a delay or parameters
// // Submit this as a footnote to the committee
var_data_type { $<fl>$=$<fl>1; $$=$1; }
| signingE rangeList delayE { $<fl>$=$<fl>1; $$=SPACED($1,$2); }
| signing delayE { $<fl>$=$<fl>1; $$=$1; }
| /*implicit*/ delayE { $<fl>$=$<fl>1; $$=""; }
;
net_type: // ==IEEE: net_type
ySUPPLY0 { VARNET($1); }
| ySUPPLY1 { VARNET($1); }
| yTRI { VARNET($1); }
| yTRI0 { VARNET($1); }
| yTRI1 { VARNET($1); }
| yTRIAND { VARNET($1); }
| yTRIOR { VARNET($1); }
| yTRIREG { VARNET($1); }
| yWAND { VARNET($1); }
| yWIRE { VARNET($1); }
| yWOR { VARNET($1); }
;
varGParamReset:
yPARAMETER { VARRESET_NONLIST($1); }
;
varLParamReset:
yLOCALPARAM { VARRESET_NONLIST($1); }
;
port_direction: // ==IEEE: port_direction + tf_port_direction
// // IEEE 19.8 just "input" FIRST forces type to wire - we'll ignore that here
yINPUT { VARIO($1); }
| yOUTPUT { VARIO($1); }
| yINOUT { VARIO($1); }
| yREF { VARIO($1); }
| yCONST__REF yREF { VARIO($1); }
;
port_directionReset: // IEEE: port_direction that starts a port_declaraiton
// // Used only for declarations outside the port list
yINPUT { VARRESET_NONLIST(""); VARIO($1); }
| yOUTPUT { VARRESET_NONLIST(""); VARIO($1); }
| yINOUT { VARRESET_NONLIST(""); VARIO($1); }
| yREF { VARRESET_NONLIST(""); VARIO($1); }
| yCONST__REF yREF { VARRESET_NONLIST(""); VARIO($1); }
;
port_declaration: // ==IEEE: port_declaration
// // Used inside block; followed by ';'
// // SIMILAR to tf_port_declaration
//
// // IEEE: inout_declaration
// // IEEE: input_declaration
// // IEEE: output_declaration
// // IEEE: ref_declaration
port_directionReset port_declNetE var_data_type { VARDTYPE($3); } list_of_variable_decl_assignments { }
| port_directionReset port_declNetE signingE rangeList { VARDTYPE(SPACED($3,$4)); } list_of_variable_decl_assignments { }
| port_directionReset port_declNetE signing { VARDTYPE($3); } list_of_variable_decl_assignments { }
| port_directionReset port_declNetE /*implicit*/ { VARDTYPE("");/*default_nettype*/} list_of_variable_decl_assignments { }
// // IEEE: interface_declaration
// // Looks just like variable declaration unless has a period
// // See etcInst
;
tf_port_declaration: // ==IEEE: tf_port_declaration
// // Used inside function; followed by ';'
// // SIMILAR to port_declaration
//
port_directionReset var_data_type { VARDTYPE($2); } list_of_tf_variable_identifiers ';' { }
| port_directionReset implicit_typeE { VARDTYPE($2); } list_of_tf_variable_identifiers ';' { }
;
integer_atom_type<str>: // ==IEEE: integer_atom_type
yBYTE { $<fl>$=$<fl>1; $$=$1; }
| ySHORTINT { $<fl>$=$<fl>1; $$=$1; }
| yINT { $<fl>$=$<fl>1; $$=$1; }
| yLONGINT { $<fl>$=$<fl>1; $$=$1; }
| yINTEGER { $<fl>$=$<fl>1; $$=$1; }
| yTIME { $<fl>$=$<fl>1; $$=$1; }
;
integer_vector_type<str>: // ==IEEE: integer_atom_type
yBIT { $<fl>$=$<fl>1; $$=$1; }
| yLOGIC { $<fl>$=$<fl>1; $$=$1; }
| yREG { $<fl>$=$<fl>1; $$=$1; }
;
non_integer_type<str>: // ==IEEE: non_integer_type
ySHORTREAL { $<fl>$=$<fl>1; $$=$1; }
| yREAL { $<fl>$=$<fl>1; $$=$1; }
| yREALTIME { $<fl>$=$<fl>1; $$=$1; }
;
signingE<str>: // IEEE: signing - plus empty
/*empty*/ { $$=""; }
| signing { $<fl>$=$<fl>1; $$=$1; }
;
signing<str>: // ==IEEE: signing
ySIGNED { $<fl>$=$<fl>1; $$=$1; }
| yUNSIGNED { $<fl>$=$<fl>1; $$=$1; }
;
//************************************************
// Data Types
casting_type<str>: // IEEE: casting_type
simple_type { $<fl>$=$<fl>1; $$=$1; }
// // IEEE: constant_primary
// // In expr:cast this is expanded to just "expr"
//
// // IEEE: signing
| ySIGNED { $<fl>$=$<fl>1; $$=$1; }
| yUNSIGNED { $<fl>$=$<fl>1; $$=$1; }
| ySTRING { $<fl>$=$<fl>1; $$=$1; }
| yCONST__ETC/*then `*/ { $<fl>$=$<fl>1; $$=$1; }
;
simple_type<str>: // ==IEEE: simple_type
// // IEEE: integer_type
integer_atom_type { $<fl>$=$<fl>1; $$=$1; }
| integer_vector_type { $<fl>$=$<fl>1; $$=$1; }
| non_integer_type { $<fl>$=$<fl>1; $$=$1; }
// // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| package_scopeIdFollowsE yaID__aTYPE { $<fl>$=$<fl>1; $$=$1+$2; }
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
;
data_typeVar<str>: // IEEE: data_type + virtual_interface_declaration
data_type { $<fl>$=$<fl>1; $$=$1; }
// // IEEE-2009: virtual_interface_declaration
// // IEEE-2012: part of data_type
| yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ parameter_value_assignmentE '.' id/*modport*/
{ $<fl>$=$<fl>1; $$=SPACED($1,SPACED($2,$3)); }
| yVIRTUAL__anyID id/*interface*/ parameter_value_assignmentE '.' id/*modport*/
{ $<fl>$=$<fl>1; $$=SPACED($1,$2); }
;
data_type<str>: // ==IEEE: data_type, excluding class_type etc references
integer_vector_type signingE rangeListE { $<fl>$=$<fl>1; $$=SPACED($1,SPACED($2,$3)); }
| integer_atom_type signingE { $<fl>$=$<fl>1; $$=SPACED($1,$2); }
| non_integer_type { $<fl>$=$<fl>1; $$=$1; }
| ySTRUCT packedSigningE '{' { PARSEP->symPushNewAnon(VAstType::STRUCT); }
/*cont*/ struct_union_memberList '}' packed_dimensionListE
{ $<fl>$=$<fl>1; $$=$1; PARSEP->symPopScope(VAstType::STRUCT); }
| yUNION taggedE packedSigningE '{' { PARSEP->symPushNewAnon(VAstType::UNION); }
/*cont*/ struct_union_memberList '}' packed_dimensionListE
{ $<fl>$=$<fl>1; $$=$1; PARSEP->symPopScope(VAstType::UNION); }
| enumDecl { $<fl>$=$<fl>1; $$=$1; }
| ySTRING { $<fl>$=$<fl>1; $$=$1; }
| yCHANDLE { $<fl>$=$<fl>1; $$=$1; }
// // Rules overlap virtual_interface_declaration
// // Parameters here are SV2009
// // IEEE has ['.' modport] but that will conflict with port
// // declarations which decode '.' modport themselves, so
// // instead see data_typeVar
| yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ parameter_value_assignmentE
{ $<fl>$=$<fl>1; $$=SPACED($1,SPACED($2,$3)); }
| yVIRTUAL__anyID id/*interface*/ parameter_value_assignmentE
{ $<fl>$=$<fl>1; $$=SPACED($1,$2); }
//
// // IEEE: [ class_scope | package_scope ] type_identifier { packed_dimension }
// // See data_type
// // IEEE: class_type
// // See data_type
| yEVENT { $<fl>$=$<fl>1; $$=$1; }
| type_reference { $<fl>$=$<fl>1; $$=$1; }
//
//----------------------
// // REFERENCES
//
// // IEEE: [ class_scope | package_scope ] type_identifier { packed_dimension }
// // IEEE: class_type
// // IEEE: ps_covergroup_identifier
// // Don't distinguish between types and classes so all these combined
| package_scopeIdFollowsE class_typeOneList packed_dimensionListE { $<fl>$=$<fl>1; $$=$<str>1+$<str>2+$3; }
;
// IEEE: struct_union - not needed, expanded in data_type
data_type_or_void<str>: // ==IEEE: data_type_or_void
data_type { $<fl>$=$<fl>1; $$=$1; }
| yVOID { $<fl>$=$<fl>1; $$=$1; }
;
var_data_type<str>: // ==IEEE: var_data_type
data_type { $<fl>$=$<fl>1; $$=$1; }
| yVAR data_type { $<fl>$=$<fl>1; $$=$1; }
| yVAR implicit_typeE { $<fl>$=$<fl>1; $$=$1; }
;
type_reference<str>: // ==IEEE: type_reference
yTYPE '(' exprOrDataType ')' { $<fl>$=$<fl>1; $$="type("+$3+")"; }
;
struct_union_memberList: // IEEE: { struct_union_member }
struct_union_member { }
| struct_union_memberList struct_union_member { }
;
struct_union_member: // ==IEEE: struct_union_member
random_qualifierE data_type_or_void { VARRESET_NONLIST("member"); VARDTYPE(SPACED($1,$2)); }
/*cont*/ list_of_variable_decl_assignments ';' { }
;
list_of_variable_decl_assignments: // ==IEEE: list_of_variable_decl_assignments
variable_decl_assignment { }
| list_of_variable_decl_assignments ',' variable_decl_assignment { }
;
variable_decl_assignment: // ==IEEE: variable_decl_assignment
id variable_dimensionListE sigAttrListE
{ VARDONE($<fl>1, $1, $2, ""); }
| id variable_dimensionListE sigAttrListE '=' variable_declExpr
{ VARDONE($<fl>1, $1, $2, $5); }
| idSVKwd { }
//
// // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]"
// // Matches above with variable_dimensionE = "[]"
// // IEEE: "class_variable_identifier [ '=' class_new ]"
// // variable_dimensionE must be empty
// // Pushed into variable_declExpr:dynamic_array_new
//
// // IEEE: "[ covergroup_variable_identifier ] '=' class_new
// // Pushed into variable_declExpr:class_new
| '=' class_new { }
;
list_of_tf_variable_identifiers: // ==IEEE: list_of_tf_variable_identifiers
tf_variable_identifier { }
| list_of_tf_variable_identifiers ',' tf_variable_identifier { }
;
tf_variable_identifier: // IEEE: part of list_of_tf_variable_identifiers
id variable_dimensionListE sigAttrListE
{ VARDONE($<fl>1, $1, $2, ""); }
| id variable_dimensionListE sigAttrListE '=' expr
{ VARDONE($<fl>1, $1, $2, $5); }
;
variable_declExpr<str>: // IEEE: part of variable_decl_assignment - rhs of expr
expr { $<fl>$=$<fl>1; $$=$1; }
| dynamic_array_new { $<fl>$=$<fl>1; $$=$1; }
| class_new { $<fl>$=$<fl>1; $$=$1; }
;
variable_dimensionListE<str>: // IEEE: variable_dimension + empty
/*empty*/ { $$=""; }
| variable_dimensionList { $<fl>$=$<fl>1; $$=$1; }
;
variable_dimensionList<str>: // IEEE: variable_dimension + empty
variable_dimension { $<fl>$=$<fl>1; $$=$1; }
| variable_dimensionList variable_dimension { $<fl>$=$<fl>1; $$=$1+$2; }
;
variable_dimension<str>: // ==IEEE: variable_dimension
// // IEEE: unsized_dimension
'[' ']' { $<fl>$=$<fl>1; $$=""; }
// // IEEE: unpacked_dimension
| anyrange { $<fl>$=$<fl>1; $$=$1; }
| '[' constExpr ']' { $<fl>$=$<fl>1; $$="["+$2+"]"; }
// // IEEE: associative_dimension
| '[' data_type ']' { $<fl>$=$<fl>1; $$="["+$2+"]"; }
| yP_BRASTAR ']' { $<fl>$=$<fl>1; $$="[*]"; }
| '[' '*' ']' { $<fl>$=$<fl>1; $$="[*]"; }
// // IEEE: queue_dimension
// // '[' '$' ']' -- $ is part of expr
// // '[' '$' ':' expr ']' -- anyrange:expr:$
;
random_qualifierE<str>: // IEEE: random_qualifier + empty
/*empty*/ { $$=""; }
| random_qualifier { $<fl>$=$<fl>1; $$=$1; }
;
random_qualifier<str>: // ==IEEE: random_qualifier
yRAND { $<fl>$=$<fl>1; $$=$1; }
| yRANDC { $<fl>$=$<fl>1; $$=$1; }
;
taggedE:
/*empty*/ { }
| yTAGGED { }
;
packedSigningE:
/*empty*/ { }
| yPACKED signingE { }
;
//************************************************
// enum
// IEEE: part of data_type
enumDecl<str>:
yENUM enum_base_typeE '{' enum_nameList '}' rangeListE { $$=$2; }
;
enum_base_typeE<str>: // IEEE: enum_base_type
/* empty */ { $$="enum"; }
// // Not in spec, but obviously "enum [1:0]" should work
// // implicit_type expanded, without empty
| signingE rangeList { $<fl>$=$<fl>1; $$=$1+$2; }
| signing { $<fl>$=$<fl>1; $$=$1; }
//
| integer_atom_type signingE { $<fl>$=$<fl>1; $$=SPACED($1,$2); }
| integer_vector_type signingE regrangeE { $<fl>$=$<fl>1; $$=SPACED($1,SPACED($2,$3)); }
// // below can be idAny or yaID__aTYPE
// // IEEE requires a type, though no shift conflict if idAny
| idAny regrangeE { $<fl>$=$<fl>1; $$=SPACED($1,$2); }
;
enum_nameList:
enum_name_declaration { }
| enum_nameList ',' enum_name_declaration { }
;
enum_name_declaration: // ==IEEE: enum_name_declaration
idAny/*enum_identifier*/ enumNameRangeE enumNameStartE { }
;
enumNameRangeE: // IEEE: second part of enum_name_declaration
/* empty */ { }
| '[' intnumAsConst ']' { }
| '[' intnumAsConst ':' intnumAsConst ']' { }
;
enumNameStartE: // IEEE: third part of enum_name_declaration
/* empty */ { }
| '=' constExpr { }
;
intnumAsConst:
yaINTNUM { }
;
//************************************************
// Typedef
data_declaration: // ==IEEE: data_declaration
// // VARRESET can't be called here - conflicts
data_declarationVar { }
| type_declaration { }
| package_import_declaration { }
// // IEEE 2005: virtual_interface_declaration
// // IEEE 2009 removed this
// // "yVIRTUAL yID yID" looks just like a data_declaration
// // Therefore the virtual_interface_declaration term isn't used
// // 1800-2009:
| net_type_declaration { }
;
class_property: // ==IEEE: class_property, which is {property_qualifier} data_declaration
memberQualResetListE data_declarationVarClass { }
| memberQualResetListE type_declaration { }
| memberQualResetListE package_import_declaration { }
// // IEEE: virtual_interface_declaration
// // "yVIRTUAL yID yID" looks just like a data_declaration
// // Therefore the virtual_interface_declaration term isn't used
;
data_declarationVar: // IEEE: part of data_declaration
// // The first declaration has complications between assuming what's the type vs ID declaring
data_declarationVarFront list_of_variable_decl_assignments ';' { }
;
data_declarationVarClass: // IEEE: part of data_declaration (for class_property)
// // The first declaration has complications between assuming what's the type vs ID declaring
data_declarationVarFrontClass list_of_variable_decl_assignments ';' { }
;
data_declarationVarFront: // IEEE: part of data_declaration
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
constE yVAR lifetimeE data_type { VARRESET(); VARDECL("var"); VARDTYPE(SPACED($1,$4)); }
| constE yVAR lifetimeE { VARRESET(); VARDECL("var"); VARDTYPE($1); }
| constE yVAR lifetimeE signingE rangeList { VARRESET(); VARDECL("var"); VARDTYPE(SPACED($1,SPACED($4,$5))); }
//
// // Expanded: "constE lifetimeE data_type"
| /**/ data_typeVar { VARRESET(); VARDECL("var"); VARDTYPE($1); }
| /**/ lifetime data_typeVar { VARRESET(); VARDECL("var"); VARDTYPE($2); }
| yCONST__ETC lifetimeE data_typeVar { VARRESET(); VARDECL("var"); VARDTYPE(SPACED($1,$3)); }
// // = class_new is in variable_decl_assignment
//
// // IEEE: virtual_interface_declaration
// // data_type includes VIRTUAL_INTERFACE, so added to data_typeVar
;
data_declarationVarFrontClass: // IEEE: part of data_declaration (for class_property)
// // VARRESET called before this rule
// // yCONST is removed, added to memberQual rules
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
yVAR lifetimeE data_type { VARDECL("var"); VARDTYPE(SPACED(GRAMMARP->m_varDType,$3)); }
| yVAR lifetimeE { VARDECL("var"); VARDTYPE(GRAMMARP->m_varDType); }
| yVAR lifetimeE signingE rangeList { VARDECL("var"); VARDTYPE(SPACED(GRAMMARP->m_varDType,SPACED($3,$4))); }
//
// // Expanded: "constE lifetimeE data_type"
| /**/ data_typeVar { VARDECL("var"); VARDTYPE(SPACED(GRAMMARP->m_varDType,$1)); }
// // lifetime is removed, added to memberQual rules to avoid conflict
// // yCONST is removed, added to memberQual rules to avoid conflict
// // = class_new is in variable_decl_assignment
;
net_type_declaration: // IEEE: net_type_declaration
yNETTYPE data_type idAny/*net_type_identifier*/ ';' { }
// // package_scope part of data_type
| yNETTYPE data_type idAny yWITH__ETC package_scopeIdFollows id/*tf_identifier*/ ';' { }
| yNETTYPE package_scopeIdFollows id/*net_type_identifier*/ idAny/*net_type_identifier*/ ';' { }
;
constE<str>: // IEEE: part of data_declaration
/* empty */ { $$ = ""; }
| yCONST__ETC { $$ = $1; }
;
implicit_typeE<str>: // IEEE: part of *data_type_or_implicit
// // Also expanded in data_declaration
/* empty */ { $$ = ""; }
| signingE rangeList { $$ = SPACED($1,$2); }
| signing { $$ = $1; }
;
assertion_variable_declaration: // IEEE: assertion_variable_declaration
// // IEEE: var_data_type expanded
var_data_type list_of_variable_decl_assignments ';' { }
;
type_declaration: // ==IEEE: type_declaration
// // Use idAny, as we can redeclare a typedef on an existing typedef
yTYPEDEF data_type idAny variable_dimensionListE ';'
{ VARDONETYPEDEF($<fl>1,$3,$2,$4); }
| yTYPEDEF id/*interface*/ bit_selectE '.' idAny/*type*/ idAny/*type*/ ';'
{ VARDONETYPEDEF($<fl>1,$6,$2+$3+"."+$5,""); }
// // Combines into above "data_type id" rule
| yTYPEDEF id ';' { VARDONETYPEDEF($<fl>1,$2,"",""); }
| yTYPEDEF yENUM idAny ';' { PARSEP->syms().replaceInsert(VAstType::ENUM, $3); }
| yTYPEDEF ySTRUCT idAny ';' { PARSEP->syms().replaceInsert(VAstType::STRUCT, $3); }
| yTYPEDEF yUNION idAny ';' { PARSEP->syms().replaceInsert(VAstType::UNION, $3); }
| yTYPEDEF yCLASS idAny ';' { PARSEP->syms().replaceInsert(VAstType::CLASS, $3); }
| yTYPEDEF yINTERFACE yCLASS idAny ';' { PARSEP->syms().replaceInsert(VAstType::CLASS, $3); }
;
//************************************************
// Module Items
module_itemListE: // IEEE: Part of module_declaration
/* empty */ { }
| module_itemList { }
;
module_itemList: // IEEE: Part of module_declaration
module_item { }
| module_itemList module_item { }
;
module_item: // ==IEEE: module_item
port_declaration ';' { }
| non_port_module_item { }
;
non_port_module_item: // ==IEEE: non_port_module_item
generate_region { }
| module_or_generate_item { }
| specify_block { }
| specparam_declaration { }
| program_declaration { }
| module_declaration { }
| interface_declaration { }
| timeunits_declaration { }
;
module_or_generate_item: // ==IEEE: module_or_generate_item
// // IEEE: parameter_override
yDEFPARAM list_of_defparam_assignments ';' { }
// // IEEE: gate_instantiation + udp_instantiation + module_instantiation
// // not here, see etcInst in module_common_item
// // We joined udp & module definitions, so this goes here
| combinational_body { }
// // This module_common_item shared with interface_or_generate_item:module_common_item
| module_common_item { }
;
module_common_item: // ==IEEE: module_common_item
module_or_generate_item_declaration { }
// // IEEE: interface_instantiation
// // + IEEE: program_instantiation
// // + module_instantiation from module_or_generate_item
| etcInst { }
| assertion_item { }
| bind_directive { }
| continuous_assign { }
// // IEEE: net_alias
| yALIAS variable_lvalue aliasEqList ';' { }
| initial_construct { }
| final_construct { }
// // IEEE: always_construct
| yALWAYS stmtBlock { }
| loop_generate_construct { }
| conditional_generate_construct { }
| elaboration_system_task { }
//
| error ';' { }
;
continuous_assign: // IEEE: continuous_assign
yASSIGN strengthSpecE delayE assignList ';' { }
;
initial_construct: // IEEE: initial_construct
yINITIAL stmtBlock { }
;
final_construct: // IEEE: final_construct
yFINAL stmtBlock { }
;
module_or_generate_item_declaration: // ==IEEE: module_or_generate_item_declaration
package_or_generate_item_declaration { }
| genvar_declaration { }
| clocking_declaration { }
| yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { }
| yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' { }
;
aliasEqList: // IEEE: part of net_alias
'=' variable_lvalue { }
| aliasEqList '=' variable_lvalue { }
;
bind_directive: // ==IEEE: bind_directive + bind_target_scope
// // ';' - Note IEEE grammar is wrong, includes extra ';' - it's already in module_instantiation
// // We merged the rules - id may be a bind_target_instance or module_identifier or interface_identifier
yBIND bind_target_instance bind_instantiation { }
| yBIND bind_target_instance ':' bind_target_instance_list bind_instantiation { }
;
bind_target_instance_list: // ==IEEE: bind_target_instance_list
bind_target_instance { }
| bind_target_instance_list ',' bind_target_instance { }
;
bind_target_instance: // ==IEEE: bind_target_instance
hierarchical_identifierBit { }
;
bind_instantiation: // ==IEEE: bind_instantiation
// // IEEE: program_instantiation
// // IEEE: + module_instantiation
// // IEEE: + interface_instantiation
etcInst { }
;
//************************************************
// Generates
//
// Way down in generate_item is speced a difference between module,
// interface and checker generates. modules and interfaces are almost
// identical (minus DEFPARAMs) so we overlap them. Checkers are too
// different, so we copy all rules for checkers.
generate_region: // ==IEEE: generate_region
yGENERATE ~c~genItemList yENDGENERATE { }
| yGENERATE yENDGENERATE { }
;
c_generate_region: // IEEE: generate_region (for checkers)
BISONPRE_COPY(generate_region,{s/~c~/c_/g}) // {copied}
;
generate_block: // IEEE: generate_block
// // Either a single item, or a begin-end block
~c~generate_item { }
| ~c~genItemBegin { }
;
c_generate_block: // IEEE: generate_block (for checkers)
BISONPRE_COPY(generate_block,{s/~c~/c_/g}) // {copied}
;
genItemBegin: // IEEE: part of generate_block
yBEGIN ~c~genItemList yEND { }
| yBEGIN yEND { }
| id ':' yBEGIN ~c~genItemList yEND endLabelE { }
| id ':' yBEGIN yEND endLabelE { }
| yBEGIN ':' idAny ~c~genItemList yEND endLabelE { }
| yBEGIN ':' idAny yEND endLabelE { }
;
c_genItemBegin: // IEEE: part of generate_block (for checkers)
BISONPRE_COPY(genItemBegin,{s/~c~/c_/g}) // {copied}
;
genItemOrBegin: // Not in IEEE, but our begin isn't under generate_item
~c~generate_item { }
| ~c~genItemBegin { }
;
c_genItemOrBegin: // (for checkers)
BISONPRE_COPY(genItemOrBegin,{s/~c~/c_/g}) // {copied}
;
genItemList:
~c~genItemOrBegin { }
| ~c~genItemList ~c~genItemOrBegin { }
;
c_genItemList: // (for checkers)
BISONPRE_COPY(genItemList,{s/~c~/c_/g}) // {copied}
;
generate_item: // IEEE: module_or_interface_or_generate_item
// // Only legal when in a generate under a module (or interface under a module)
module_or_generate_item { }
// // Only legal when in a generate under an interface
| interface_or_generate_item { }
// // IEEE: checker_or_generate_item
// // Only legal when in a generate under a checker
// // so below in c_generate_item
;
c_generate_item: // IEEE: generate_item (for checkers)
checker_or_generate_item { }
;
conditional_generate_construct: // ==IEEE: conditional_generate_construct
// // IEEE: case_generate_construct
yCASE '(' expr ')' yENDCASE { }
| yCASE '(' expr ')' ~c~case_generate_itemList yENDCASE { }
// // IEEE: if_generate_construct
| yIF '(' expr ')' ~c~generate_block %prec prLOWER_THAN_ELSE { }
| yIF '(' expr ')' ~c~generate_block yELSE ~c~generate_block { }
;
c_conditional_generate_construct: // IEEE: conditional_generate_construct (for checkers)
BISONPRE_COPY(conditional_generate_construct,{s/~c~/c_/g}) // {copied}
;
loop_generate_construct: // ==IEEE: loop_generate_construct
yFOR '(' genvar_initialization ';' expr ';' genvar_iteration ')' ~c~generate_block
{ }
;
c_loop_generate_construct: // IEEE: loop_generate_construct (for checkers)
BISONPRE_COPY(loop_generate_construct,{s/~c~/c_/g}) // {copied}
;
genvar_initialization: // ==IEEE: genvar_initalization
id '=' constExpr { }
| yGENVAR genvar_identifierDecl '=' constExpr { }
;
genvar_iteration: // ==IEEE: genvar_iteration
// // IEEE: assignment_operator plus IDs
| id '=' expr { }
| id yP_PLUSEQ expr { }
| id yP_MINUSEQ expr { }
| id yP_TIMESEQ expr { }
| id yP_DIVEQ expr { }
| id yP_MODEQ expr { }
| id yP_ANDEQ expr { }
| id yP_OREQ expr { }
| id yP_XOREQ expr { }
| id yP_SLEFTEQ expr { }
| id yP_SRIGHTEQ expr { }
| id yP_SSRIGHTEQ expr { }
// // inc_or_dec_operator
| yP_PLUSPLUS id { }
| yP_MINUSMINUS id { }
| id yP_PLUSPLUS { }
| id yP_MINUSMINUS { }
;
case_generate_itemList: // IEEE: { case_generate_item }
~c~case_generate_item { }
| ~c~case_generate_itemList ~c~case_generate_item { }
;
c_case_generate_itemList: // IEEE: { case_generate_item } (for checkers)
BISONPRE_COPY(case_generate_itemList,{s/~c~/c_/g}) // {copied}
;
case_generate_item: // ==IEEE: case_generate_item
caseCondList ':' ~c~generate_block { }
| yDEFAULT ':' ~c~generate_block { }
| yDEFAULT ~c~generate_block { }
;
c_case_generate_item: // IEEE: case_generate_item (for checkers)
BISONPRE_COPY(case_generate_item,{s/~c~/c_/g}) // {copied}
;
//************************************************
// Assignments and register declarations
assignList:
assignOne { }
| assignList ',' assignOne { }
;
assignOne:
variable_lvalue '=' expr { PARSEP->contassignCb($<fl>2,"assign",$1,$3); }
;
delay_or_event_controlE: // IEEE: delay_or_event_control plus empty
/* empty */ { }
| delay_control { } /* ignored */
| event_control { } /* ignored */
| yREPEAT '(' expr ')' event_control { } /* ignored */
;
delayE:
/* empty */ { }
| delay_control { } /* ignored */
;
delay_control: // ==IEEE: delay_control
'#' delay_value { } /* ignored */
| '#' '(' minTypMax ')' { } /* ignored */
| '#' '(' minTypMax ',' minTypMax ')' { } /* ignored */
| '#' '(' minTypMax ',' minTypMax ',' minTypMax ')' { } /* ignored */
;
delay_value: // ==IEEE:delay_value
// // IEEE: ps_identifier
ps_id_etc { }
| yaINTNUM { }
| yaFLOATNUM { }
| yaTIMENUM { }
;
delayExpr:
expr { }
;
minTypMax: // IEEE: mintypmax_expression and constant_mintypmax_expression
delayExpr { }
| delayExpr ':' delayExpr ':' delayExpr { }
;
netSigList: // IEEE: list_of_port_identifiers
netSig { }
| netSigList ',' netSig { }
;
netSig: // IEEE: net_decl_assignment - one element from list_of_port_identifiers
netId sigAttrListE { VARDONE($<fl>1, $1, "", ""); }
| netId sigAttrListE '=' expr { VARDONE($<fl>1, $1, "", $4); }
| netId variable_dimensionList sigAttrListE { VARDONE($<fl>1, $1, $2, ""); }
;
netId<str>:
id/*new-net*/ { $<fl>$=$<fl>1; $$=$1; }
| idSVKwd { $<fl>$=$<fl>1; $$=$1; }
;
sigAttrListE:
/* empty */ { }
;
rangeListE<str>: // IEEE: [{packed_dimension}]
/* empty */ { $$=""; }
| rangeList { $<fl>$=$<fl>1; $$ = $1; }
;
rangeList<str>: // IEEE: {packed_dimension}
anyrange { $<fl>$=$<fl>1; $$ = $1; }
| rangeList anyrange { $<fl>$=$<fl>1; $$ = $1+$2; }
;
regrangeE<str>:
/* empty */ { $$=""; }
| anyrange { $<fl>$=$<fl>1; $$=$1; }
;
bit_selectE<str>: // IEEE: constant_bit_select (IEEE included empty)
/* empty */ { $$ = ""; }
| '[' constExpr ']' { $<fl>$=$<fl>1; $$ = "["+$2+"]"; }
;
// IEEE: select
// Merged into more general idArray
anyrange<str>:
'[' constExpr ':' constExpr ']' { $<fl>$=$<fl>1; $$ = "["+$2+":"+$4+"]"; }
;
packed_dimensionListE<str>: // IEEE: [{ packed_dimension }]
/* empty */ { $$=""; }
| packed_dimensionList { $<fl>$=$<fl>1; $$=$1; }
;
packed_dimensionList<str>: // IEEE: { packed_dimension }
packed_dimension { $<fl>$=$<fl>1; $$=$1; }
| packed_dimensionList packed_dimension { $<fl>$=$<fl>1; $$=$1+$2; }
;
packed_dimension<str>: // ==IEEE: packed_dimension
anyrange { $<fl>$=$<fl>1; $$=$1; }
| '[' ']' { $$="[]"; }
;
//************************************************
// Parameters
param_assignment: // ==IEEE: param_assignment
// // IEEE: constant_param_expression
// // param_expression: '$' is in expr
id/*new-parameter*/ variable_dimensionListE sigAttrListE '=' exprOrDataTypeOrMinTypMax
{ $<fl>$=$<fl>1; VARDONE($<fl>1, $1, $2, $5); }
// // only legal in port list; throws error if not set
| id/*new-parameter*/ variable_dimensionListE sigAttrListE
{ $<fl>$=$<fl>1; VARDONE($<fl>1, $1, $2, ""); NEED_S09($<fl>1,"optional parameter defaults"); }
;
list_of_param_assignments: // ==IEEE: list_of_param_assignments
param_assignment { }
| list_of_param_assignments ',' param_assignment { }
;
list_of_defparam_assignments: // ==IEEE: list_of_defparam_assignments
defparam_assignment { }
| list_of_defparam_assignments ',' defparam_assignment { }
;
defparam_assignment: // ==IEEE: defparam_assignment
hierarchical_identifier/*parameter*/ '=' expr { PARSEP->defparamCb($<fl>2,"defparam",$1,$3); }
;
//************************************************
// Instances
// We don't know identifier types, so this matches all module,udp,etc instantiation
// module_id [#(params)] name (pins) [, name ...] ; // module_instantiation
// gate (strong0) [#(delay)] [name] (pins) [, (pins)...] ; // gate_instantiation
// program_id [#(params}] name ; // program_instantiation
// interface_id [#(params}] name ; // interface_instantiation
// checker_id name (pins) ; // checker_instantiation
etcInst: // IEEE: module_instantiation + gate_instantiation + udp_instantiation
instName { INSTPREP($1,1,0); } strengthSpecE parameter_value_assignmentE { INSTPREP($1,0,1); } instnameList ';'
{ INSTDONE(); }
// // IEEE: interface_identifier' .' modport_identifier list_of_interface_identifiers
| instName { INSTPREP($1,1,0); } '.' id {INSTPREP($1,0,0);} mpInstnameList ';'
{ INSTDONE(); }
;
instName<str>:
gateKwd { $<fl>$=$<fl>1; $$=$1; }
// // id is-a: interface_identifier
// // or program_identifier
// // or udp_identifier
// // or module_identifier
| id { $<fl>$=$<fl>1; $$=$1; }
;
mpInstnameList: // Similar to instnameList, but for modport instantiations which have no parenthesis
mpInstnameParen { }
| mpInstnameList ',' mpInstnameParen { }
;
mpInstnameParen: // Similar to instnameParen, but for modport instantiations which have no parenthesis
mpInstname { PARSEP->endcellCb($<fl>1,""); }
;
mpInstname: // Similar to instname, but for modport instantiations which have no parenthesis
// // id is-a: interface_port_identifier (interface.modport)
id instRangeE { PARSEP->instantCb($<fl>1, GRAMMARP->m_cellMod, $1, $2); }
;
instnameList:
instnameParen { }
| instnameList ',' instnameParen { }
;
instnameParen:
instname cellpinList ')' { PARSEP->endcellCb($<fl>3,""); }
;
instname:
// // id is-a: hierarchical_instance (interface)
// // or instance_identifier (module)
// // or instance_identifier (program)
// // or udp_instance (udp)
id instRangeE '(' { PARSEP->instantCb($<fl>1, GRAMMARP->m_cellMod, $1, $2); PINPARAMS(); }
| instRangeE '(' { PARSEP->instantCb($<fl>2, GRAMMARP->m_cellMod, "", $1); PINPARAMS(); } // UDP
;
instRangeE<str>:
/* empty */ { $$ = ""; }
| '[' constExpr ']' { $<fl>$=$<fl>1; $$ = "["+$2+"]"; }
| '[' constExpr ':' constExpr ']' { $<fl>$=$<fl>1; $$ = "["+$2+":"+$4+"]"; }
;
cellpinList:
{ VARRESET_LIST(""); } cellpinItList { VARRESET_NONLIST(""); GRAMMARP->m_withinPin = false; }
;
cellpinItList: // IEEE: list_of_port_connections + list_of_parameter_assignmente
{ GRAMMARP->m_portNextNetName.clear(); } cellpinItemE { }
| cellpinItList ',' cellpinItemE { }
;
cellpinItemE: // IEEE: named_port_connection + named_parameter_assignment + empty
/* empty: ',,' is legal */ { PINNUMINC(); } /*PINDONE(yylval.fl,"",""); <- No, as then () implies a pin*/
| yP_DOTSTAR { PINDONE($<fl>1,"*","*");PINNUMINC(); }
| '.' idSVKwd { PINDONE($<fl>1,$2,$2); PINNUMINC(); }
| '.' idAny { PINDONE($<fl>1,$2,$2); PINNUMINC(); }
| '.' idAny '(' ')' { PINDONE($<fl>1,$2,""); PINNUMINC(); }
// // mintypmax is expanded here, as it might be a UDP or gate primitive
// // For checkers, this needs to not just expr, but include events + properties
| '.' idAny '(' pev_expr ')' { PINDONE($<fl>1,$2,$4); PINNUMINC(); }
| '.' idAny '(' pev_expr ':' expr ')' { PINDONE($<fl>1,$2,$4); PINNUMINC(); }
| '.' idAny '(' pev_expr ':' expr ':' expr ')' { PINDONE($<fl>1,$2,$4); PINNUMINC(); }
// // For parameters
| '.' idAny '(' data_type ')' { PINDONE($<fl>1,$2,$4); PINNUMINC(); }
// // For parameters
| data_type { PINDONE($<fl>1,"",$1); PINNUMINC(); }
//
| expr { PINDONE($<fl>1,"",$1); PINNUMINC(); }
| expr ':' expr { PINDONE($<fl>1,"",$1); PINNUMINC(); }
| expr ':' expr ':' expr { PINDONE($<fl>1,"",$1); PINNUMINC(); }
;
//************************************************
// EventControl lists
event_control: // ==IEEE: event_control
'@' '(' event_expression ')' { }
| '@' '*' { }
| '@' '(' '*' ')' { }
// // IEEE: hierarchical_event_identifier
| '@' idClassSel/*event_id or ps_or_hierarchical_sequence_identifier*/ { }
// // IEEE: ps_or_hierarchical_sequence_identifier
// // sequence_instance without parens matches idClassSel above.
// // Ambiguity: "'@' sequence (-for-sequence" versus expr:delay_or_event_controlE "'@' id (-for-expr
// // For now we avoid this, as it's very unlikely someone would mix
// // 1995 delay with a sequence with parameters.
// // Alternatively split this out of event_control, and delay_or_event_controlE
// // and anywhere delay_or_event_controlE is called allow two expressions
;
event_expression: // IEEE: event_expression - split over several
// // ',' rules aren't valid in port lists - ev_expr is there.
// // Also eliminates left recursion to appease conflicts
ev_expr { }
| event_expression ',' ev_expr %prec yOR { } /* Verilog 2001 */
;
senitemEdge<str>: // IEEE: part of event_expression
// // Also called by pev_expr
yPOSEDGE expr { $<fl>$=$<fl>1; $$=$1+" "+$2; }
| yPOSEDGE expr yIFF expr { $<fl>$=$<fl>1; $$=$1+" "+$2+" iff "+$4; }
| yNEGEDGE expr { $<fl>$=$<fl>1; $$=$1+" "+$2; }
| yNEGEDGE expr yIFF expr { $<fl>$=$<fl>1; $$=$1+" "+$2+" iff "+$4; }
| yEDGE expr { $<fl>$=$<fl>1; $$=$1+" "+$2; NEED_S09($<fl>1,"edge"); }
| yEDGE expr yIFF expr { $<fl>$=$<fl>1; $$=$1+" "+$2+" iff "+$4; NEED_S09($<fl>1,"edge"); }
;
//************************************************
// Statements
stmtBlock: // IEEE: statement + seq_block + par_block
stmt { }
;
seq_block: // ==IEEE: seq_block
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
seq_blockFront blockDeclStmtList yEND endLabelE { PARSEP->symPopScope(VAstType::BLOCK); }
| seq_blockFront /**/ yEND endLabelE { PARSEP->symPopScope(VAstType::BLOCK); }
;
par_block: // ==IEEE: par_block
par_blockFront blockDeclStmtList yJOIN endLabelE { PARSEP->symPopScope(VAstType::FORK); }
| par_blockFront /**/ yJOIN endLabelE { PARSEP->symPopScope(VAstType::FORK); }
;
seq_blockFront: // IEEE: part of seq_block
yBEGIN { PARSEP->symPushNewAnon(VAstType::BLOCK); }
| yBEGIN ':' idAny/*new-block_identifier*/ { PARSEP->symPushNew(VAstType::BLOCK,$1); }
;
par_blockFront: // IEEE: part of par_block
yFORK { PARSEP->symPushNewAnon(VAstType::FORK); }
| yFORK ':' idAny/*new-block_identifier*/ { PARSEP->symPushNew(VAstType::FORK,$1); }
;
blockDeclStmtList: // IEEE: { block_item_declaration } { statement or null }
// // The spec seems to suggest a empty declaration isn't ok, but most simulators take it
block_item_declarationList { }
| block_item_declarationList stmtList { }
| stmtList { }
;
block_item_declarationList: // IEEE: [ block_item_declaration ]
block_item_declaration { }
| block_item_declarationList block_item_declaration { }
;
block_item_declaration: // ==IEEE: block_item_declaration
data_declaration { }
| local_parameter_declaration ';' { }
| parameter_declaration ';' { }
| overload_declaration { }
| let_declaration { }
;
stmtList:
stmtBlock { }
| stmtList stmtBlock { }
;
stmt: // IEEE: statement_or_null == function_statement_or_null
statement_item { }
| id/*block_identifier*/ ':' statement_item { } /*S05 block creation rule*/
// // from _or_null
| ';' { }
;
statement_item: // IEEE: statement_item
// // IEEE: operator_assignment
foperator_assignment ';' { }
//
// // IEEE: blocking_assignment
// // 1800-2009 restricts LHS of assignment to new to not have a range
// // This is ignored to avoid conflicts
| fexprLvalue '=' class_new ';' { }
| fexprLvalue '=' dynamic_array_new ';' { }
//
// // IEEE: nonblocking_assignment
| fexprLvalue yP_LTE delay_or_event_controlE expr ';' { }
//
// // IEEE: procedural_continuous_assignment
| yASSIGN expr '=' delay_or_event_controlE expr ';' { }
| yDEASSIGN variable_lvalue ';' { }
| yFORCE expr '=' expr ';' { }
| yRELEASE variable_lvalue ';' { }
//
// // IEEE: case_statement
| unique_priorityE caseStart caseAttrE case_itemListE yENDCASE { }
| unique_priorityE caseStart caseAttrE yMATCHES case_patternListE yENDCASE { }
| unique_priorityE caseStart caseAttrE yINSIDE case_insideListE yENDCASE { }
//
// // IEEE: conditional_statement
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { }
| unique_priorityE yIF '(' expr ')' stmtBlock yELSE stmtBlock { }
//
| finc_or_dec_expression ';' { }
// // IEEE: inc_or_dec_expression
// // Below under expr
//
// // IEEE: subroutine_call_statement
| yVOID yP_TICK '(' function_subroutine_callNoMethod ')' ';' { }
| yVOID yP_TICK '(' expr '.' function_subroutine_callNoMethod ')' ';' { }
// // Expr included here to resolve our not knowing what is a method call
// // Expr here must result in a subroutine_call
| task_subroutine_callNoMethod ';' { }
| fexpr '.' array_methodNoRoot ';' { }
| fexpr '.' task_subroutine_callNoMethod ';' { }
| fexprScope ';' { }
// // Not here in IEEE; from class_constructor_declaration
// // Because we've joined class_constructor_declaration into generic functions
// // Way over-permissive;
// // IEEE: [ ySUPER '.' yNEW [ '(' list_of_arguments ')' ] ';' ]
| fexpr '.' class_new ';' { }
//
// // IEEE: disable_statement
| yDISABLE hierarchical_identifier/*task_or_block*/ ';' { }
| yDISABLE yFORK ';' { }
// // IEEE: event_trigger
| yP_MINUSGT hierarchical_identifier/*event*/ ';' { }
| yP_MINUSGTGT delay_or_event_controlE hierarchical_identifier/*event*/ ';' { }
// // IEEE: loop_statement
| yFOREVER stmtBlock { }
| yREPEAT '(' expr ')' stmtBlock { }
| yWHILE '(' expr ')' stmtBlock { }
// // for's first ';' is in for_initalization
| yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
{ }
| yFOR '(' for_initialization ';' for_stepE ')' stmtBlock
{ }
| yDO stmtBlock yWHILE '(' expr ')' ';' { }
// // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009
| yFOREACH '(' idClassForeach/*array_id[loop_variables]*/ ')' stmt { }
//
// // IEEE: jump_statement
| yRETURN ';' { }
| yRETURN expr ';' { }
| yBREAK ';' { }
| yCONTINUE ';' { }
//
| par_block { }
// // IEEE: procedural_timing_control_statement + procedural_timing_control
| delay_control stmtBlock { }
| event_control stmtBlock { }
| cycle_delay stmtBlock { }
//
| seq_block { }
//
// // IEEE: wait_statement
| yWAIT '(' expr ')' stmtBlock { }
| yWAIT yFORK ';' { }
| yWAIT_ORDER '(' hierarchical_identifierList ')' action_block { }
//
// // IEEE: procedural_assertion_statement
| procedural_assertion_statement { }
//
// // IEEE: clocking_drive ';'
// // clockvar_expression made to fexprLvalue to prevent reduce conflict
// // Note LTE in this context is highest precedence, so first on left wins
| fexprLvalue yP_LTE cycle_delay expr ';' { }
//
| randsequence_statement { }
//
// // IEEE: randcase_statement
| yRANDCASE case_itemList yENDCASE { }
//
| expect_property_statement { }
//
| error ';' { }
;
operator_assignment: // IEEE: operator_assignment
~f~exprLvalue '=' delay_or_event_controlE expr { }
| ~f~exprLvalue yP_PLUSEQ expr { }
| ~f~exprLvalue yP_MINUSEQ expr { }
| ~f~exprLvalue yP_TIMESEQ expr { }
| ~f~exprLvalue yP_DIVEQ expr { }
| ~f~exprLvalue yP_MODEQ expr { }
| ~f~exprLvalue yP_ANDEQ expr { }
| ~f~exprLvalue yP_OREQ expr { }
| ~f~exprLvalue yP_XOREQ expr { }
| ~f~exprLvalue yP_SLEFTEQ expr { }
| ~f~exprLvalue yP_SRIGHTEQ expr { }
| ~f~exprLvalue yP_SSRIGHTEQ expr { }
;
foperator_assignment<str>: // IEEE: operator_assignment (for first part of expression)
BISONPRE_COPY(operator_assignment,{s/~f~/f/g}) // {copied}
;
inc_or_dec_expression<str>: // ==IEEE: inc_or_dec_expression
// // Need fexprScope instead of variable_lvalue to prevent conflict
~l~exprScope yP_PLUSPLUS { $<fl>$=$<fl>1; $$ = $1+$2; }
| ~l~exprScope yP_MINUSMINUS { $<fl>$=$<fl>1; $$ = $1+$2; }
// // Need expr instead of variable_lvalue to prevent conflict
| yP_PLUSPLUS expr { $<fl>$=$<fl>1; $$ = $1+$2; }
| yP_MINUSMINUS expr { $<fl>$=$<fl>1; $$ = $1+$2; }
;
finc_or_dec_expression<str>: // IEEE: inc_or_dec_expression (for first part of expression)
BISONPRE_COPY(inc_or_dec_expression,{s/~l~/f/g}) // {copied}
;
sinc_or_dec_expression<str>: // IEEE: inc_or_dec_expression (for sequence_expression)
BISONPRE_COPY(inc_or_dec_expression,{s/~l~/s/g}) // {copied}
;
pinc_or_dec_expression<str>: // IEEE: inc_or_dec_expression (for property_expression)
BISONPRE_COPY(inc_or_dec_expression,{s/~l~/p/g}) // {copied}
;
ev_inc_or_dec_expression<str>: // IEEE: inc_or_dec_expression (for ev_expr)
BISONPRE_COPY(inc_or_dec_expression,{s/~l~/ev_/g}) // {copied}
;
pev_inc_or_dec_expression<str>: // IEEE: inc_or_dec_expression (for pev_expr)
BISONPRE_COPY(inc_or_dec_expression,{s/~l~/pev_/g}) // {copied}
;
class_new<str>: // ==IEEE: class_new
// // Special precence so (...) doesn't match expr
yNEW__ETC { $<fl>$=$<fl>1; $$ = $1; }
| yNEW__ETC expr { $<fl>$=$<fl>1; $$ = $1+" "+$2; }
// // Grammer abiguity; we assume "new (x)" the () are a argument, not expr
| yNEW__PAREN '(' list_of_argumentsE ')' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; }
;
dynamic_array_new<str>: // ==IEEE: dynamic_array_new
yNEW__ETC '[' expr ']' { $<fl>$=$<fl>1; $$=$1+"["+$3+"]"; }
| yNEW__ETC '[' expr ']' '(' expr ')' { $<fl>$=$<fl>1; $$=$1+"["+$3+"]("+$6+")"; }
;
//************************************************
// Case/If
unique_priorityE: // IEEE: unique_priority + empty
/*empty*/ { }
| yPRIORITY { }
| yUNIQUE { }
| yUNIQUE0 { NEED_S09($<fl>1, "unique0"); }
;
action_block: // ==IEEE: action_block
stmt %prec prLOWER_THAN_ELSE { }
| stmt yELSE stmt { }
| yELSE stmt { }
;
caseStart: // IEEE: part of case_statement
yCASE '(' expr ')' { }
| yCASEX '(' expr ')' { }
| yCASEZ '(' expr ')' { }
;
caseAttrE:
/*empty*/ { }
;
case_patternListE: // IEEE: case_pattern_item
// &&& is part of expr so aliases to case_itemList
case_itemListE { }
;
case_itemListE: // IEEE: [ { case_item } ]
/* empty */ { }
| case_itemList { }
;
case_insideListE: // IEEE: [ { case_inside_item } ]
/* empty */ { }
| case_inside_itemList { }
;
case_itemList: // IEEE: { case_item + ... }
caseCondList ':' stmtBlock { }
| yDEFAULT ':' stmtBlock { }
| yDEFAULT stmtBlock { }
| case_itemList caseCondList ':' stmtBlock { }
| case_itemList yDEFAULT stmtBlock { }
| case_itemList yDEFAULT ':' stmtBlock { }
;
case_inside_itemList: // IEEE: { case_inside_item + open_range_list ... }
open_range_list ':' stmtBlock { }
| yDEFAULT ':' stmtBlock { }
| yDEFAULT stmtBlock { }
| case_inside_itemList open_range_list ':' stmtBlock { }
| case_inside_itemList yDEFAULT stmtBlock { }
| case_inside_itemList yDEFAULT ':' stmtBlock { }
;
open_range_list: // ==IEEE: open_range_list + open_value_range
open_value_range { }
| open_range_list ',' open_value_range { }
;
open_value_range: // ==IEEE: open_value_range
value_range { }
;
value_range: // ==IEEE: value_range
expr { }
| '[' expr ':' expr ']' { }
;
covergroup_value_range: // ==IEEE-2012: covergroup_value_range
cgexpr { }
| '[' cgexpr ':' cgexpr ']' { }
;
caseCondList: // IEEE: part of case_item
expr { }
| caseCondList ',' expr { }
;
patternNoExpr<str>: // IEEE: pattern **Excluding Expr*
'.' id/*variable*/ { $<fl>$=$<fl>1; $$="."+$2; }
| yP_DOTSTAR { $<fl>$=$<fl>1; $$=".*"; }
// // IEEE: "expr" excluded; expand in callers
// // "yTAGGED id [expr]" Already part of expr
| yTAGGED id/*member_identifier*/ patternNoExpr { $<fl>$=$<fl>1; $$=" tagged "+$2+" "+$3; }
// // "yP_TICKBRA patternList '}'" part of expr under assignment_pattern
;
patternList<str>: // IEEE: part of pattern
patternOne { $<fl>$=$<fl>1; $$=$1; }
| patternList ',' patternOne { $<fl>$=$<fl>1; $$=$1+","+$3; }
;
patternOne<str>: // IEEE: part of pattern
expr { $<fl>$=$<fl>1; $$=$1; }
| expr '{' argsExprList '}' { $<fl>$=$<fl>1; $$=$1; }
| patternNoExpr { $<fl>$=$<fl>1; $$=$1; }
;
patternMemberList<str>: // IEEE: part of pattern and assignment_pattern
patternKey ':' expr { $<fl>$=$<fl>1; $$=$1+" : "+$2; }
| patternKey ':' patternNoExpr { $<fl>$=$<fl>1; $$=$1+" : "+$2; }
| patternMemberList ',' patternKey ':' expr { $<fl>$=$<fl>1; $$=$1+","+$3+":"+$4; }
| patternMemberList ',' patternKey ':' patternNoExpr { $<fl>$=$<fl>1; $$=$1+","+$3+":"+$4; }
;
patternKey<str>: // IEEE: merge structure_pattern_key, array_pattern_key, assignment_pattern_key
// // IEEE: structure_pattern_key
// // id/*member*/ is part of constExpr below
constExpr { $<fl>$=$<fl>1; $$=$1; }
// // IEEE: assignment_pattern_key
| yDEFAULT { $<fl>$=$<fl>1; $$=$1; }
| simple_type { $<fl>$=$<fl>1; $$=$1; }
// // simple_type reference looks like constExpr
;
assignment_pattern<str>: // ==IEEE: assignment_pattern
// This doesn't match the text of the spec. I think a : is missing, or example code needed
// yP_TICKBRA constExpr exprList '}' { $$="'{"+$2+" "+$3"}"; }
// // "'{ const_expression }" is same as patternList with one entry
// // From patternNoExpr
// // also IEEE: "''{' expression { ',' expression } '}'"
// // matches since patternList includes expr
yP_TICKBRA patternList '}' { $<fl>$=$<fl>1; $$="'{"+$2+"}"; }
// // From patternNoExpr
// // also IEEE "''{' structure_pattern_key ':' ...
// // also IEEE "''{' array_pattern_key ':' ...
| yP_TICKBRA patternMemberList '}' { $<fl>$=$<fl>1; $$="'{"+$2+"}"; }
// // IEEE: Not in grammar, but in VMM
| yP_TICKBRA '}' { $<fl>$=$<fl>1; $$="'{}"; }
;
// "datatype id = x {, id = x }" | "yaId = x {, id=x}" is legal
for_initialization: // ==IEEE: for_initialization + for_variable_declaration + extra terminating ";"
// // IEEE: for_variable_declaration
for_initializationItemList ';' { }
// // IEEE: 1800-2017 empty initialization
| ';' { }
;
for_initializationItemList: // IEEE: [for_variable_declaration...]
for_initializationItem { }
| for_initializationItemList ',' for_initializationItem { }
;
for_initializationItem: // IEEE: variable_assignment + for_variable_declaration
// // IEEE: for_variable_declaration
data_type idAny/*new*/ '=' expr { VARDTYPE($1); }
// // IEEE-2012:
| yVAR data_type idAny/*new*/ '=' expr { VARDTYPE($1); }
// // IEEE: variable_assignment
| variable_lvalue '=' expr { }
;
for_stepE: // IEEE: for_step + empty
/* empty */ { }
| for_step { }
;
for_step: // IEEE: for_step
for_step_assignment { }
| for_step ',' for_step_assignment { }
;
for_step_assignment: // ==IEEE: for_step_assignment
operator_assignment { }
//
| inc_or_dec_expression { }
// // IEEE: subroutine_call
| function_subroutine_callNoMethod { }
// // method_call:array_method requires a '.'
| expr '.' array_methodNoRoot { }
| exprScope { }
;
loop_variables<str>: // ==IEEE: loop_variables
id { $<fl>$=$<fl>1; $$=$1; }
| loop_variables ',' id { $<fl>$=$<fl>1; $$=$1+","+$3; }
;
//************************************************
// Functions/tasks
funcRef<str>: // IEEE: part of tf_call
// // package_scope/hierarchical_... is part of expr, so just need ID
// // making-a id-is-a
// // ----------------- ------------------
// // tf_call tf_identifier expr (list_of_arguments)
// // method_call(post .) function_identifier expr (list_of_arguments)
// // property_instance property_identifier property_actual_arg
// // sequence_instance sequence_identifier sequence_actual_arg
// // let_expression let_identifier let_actual_arg
//
id '(' pev_list_of_argumentsE ')' { $<fl>$=$<fl>1; $$=$1+"("+$3+")"; }
| package_scopeIdFollows id '(' pev_list_of_argumentsE ')' { $<fl>$=$<fl>2; $$=$1+$2+"("+$4+")"; }
| class_scope_id '(' pev_list_of_argumentsE ')' { $<fl>$=$<fl>1; $$=$<str>1+"("+$3+")"; }
;
task_subroutine_callNoMethod<str>: // function_subroutine_callNoMethod (as task)
// // IEEE: tf_call
funcRef { $<fl>$=$<fl>1; $$=$1; }
| funcRef yWITH__PAREN '(' expr ')' { $<fl>$=$<fl>1; $$=$1+" "+$2+$3+$4+$5; }
| system_t_call { $<fl>$=$<fl>1; $$=$1; }
// // IEEE: method_call requires a "." so is in expr
// // IEEE: ['std::'] not needed, as normal std package resolution will find it
// // IEEE: randomize_call
// // We implement randomize as a normal funcRef, since randomize isn't a keyword
// // Note yNULL is already part of expressions, so they come for free
| funcRef yWITH__CUR constraint_block { $<fl>$=$<fl>1; $$=$1+" with..."; }
;
function_subroutine_callNoMethod<str>: // IEEE: function_subroutine_call (as function)
// // IEEE: tf_call
funcRef { $<fl>$=$<fl>1; $$=$1; }
| funcRef yWITH__PAREN '(' expr ')' { $<fl>$=$<fl>1; $$=$1+" "+$2+$3+$4+$5; }
| system_f_call { $<fl>$=$<fl>1; $$=$1; }
// // IEEE: method_call requires a "." so is in expr
// // IEEE: ['std::'] not needed, as normal std package resolution will find it
// // IEEE: randomize_call
// // We implement randomize as a normal funcRef, since randomize isn't a keyword
// // Note yNULL is already part of expressions, so they come for free
| funcRef yWITH__CUR constraint_block { $<fl>$=$<fl>1; $$=$1+" with..."; }
;
system_t_call<str>: // IEEE: system_tf_call (as task)
system_f_call { $<fl>$=$<fl>1; $$ = $1; }
;
system_f_call<str>: // IEEE: system_tf_call (as func)
ygenSYSCALL parenE { $<fl>$=$<fl>1; $$ = $1; }
// // Allow list of data_type to support "x,,,y"
| ygenSYSCALL '(' exprOrDataTypeList ')' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; }
// // Standard doesn't explicity list system calls
// // But these match elaboration calls in 1800-2009
| yD_FATAL parenE { $<fl>$=$<fl>1; $$ = $1; }
| yD_FATAL '(' exprOrDataTypeList ')' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; }
| yD_ERROR parenE { $<fl>$=$<fl>1; $$ = $1; }
| yD_ERROR '(' exprOrDataTypeList ')' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; }
| yD_WARNING parenE { $<fl>$=$<fl>1; $$ = $1; }
| yD_WARNING '(' exprOrDataTypeList ')' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; }
| yD_INFO parenE { $<fl>$=$<fl>1; $$ = $1; }
| yD_INFO '(' exprOrDataTypeList ')' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; }
;
elaboration_system_task<str>: // IEEE: elaboration_system_task (1800-2009)
// // $fatal first argument is exit number, must be constant
yD_FATAL parenE ';' { $<fl>$=$<fl>1; $$ = $1; NEED_S09($<fl>1,"elaboration system tasks"); }
| yD_FATAL '(' exprOrDataTypeList ')' ';' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; NEED_S09($<fl>1,"elaboration system tasks"); }
| yD_ERROR parenE ';' { $<fl>$=$<fl>1; $$ = $1; NEED_S09($<fl>1,"elaboration system tasks"); }
| yD_ERROR '(' exprOrDataTypeList ')' ';' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; NEED_S09($<fl>1,"elaboration system tasks"); }
| yD_WARNING parenE ';' { $<fl>$=$<fl>1; $$ = $1; NEED_S09($<fl>1,"elaboration system tasks"); }
| yD_WARNING '(' exprOrDataTypeList ')' ';' {$<fl>$=$<fl>1; $$ = $1+"("+$3+")"; NEED_S09($<fl>1,"elaboration system tasks"); }
| yD_INFO parenE ';' { $<fl>$=$<fl>1; $$ = $1; NEED_S09($<fl>1,"elaboration system tasks"); }
| yD_INFO '(' exprOrDataTypeList ')' ';' { $<fl>$=$<fl>1; $$ = $1+"("+$3+")"; NEED_S09($<fl>1,"elaboration system tasks"); }
;
property_actual_arg<str>: // ==IEEE: property_actual_arg
// // IEEE: property_expr
// // IEEE: sequence_actual_arg
pev_expr { $<fl>$=$<fl>1; $$=$1; }
// // IEEE: sequence_expr
// // property_expr already includes sequence_expr
;
task<fl>:
yTASK__ETC { $<fl>$=$<fl>1; }
| yTASK__aPUREV { $<fl>$=$<fl>1; }
;
task_declaration: // IEEE: task_declaration
yTASK__ETC lifetimeE taskId tfGuts yENDTASK endLabelE
{ PARSEP->endtaskfuncCb($<fl>5,$5);
PARSEP->symPopScope(VAstType::TASK); }
| yTASK__aPUREV lifetimeE taskId tfGutsPureV
{ PARSEP->endtaskfuncCb($<fl>1,"endtask");
PARSEP->symPopScope(VAstType::TASK); }
;
task_prototype: // ==IEEE: task_prototype
// // IEEE: has '(' tf_port_list ')'
// // However the () should be optional for OVA
task taskId '(' tf_port_listE ')' { PARSEP->symPopScope(VAstType::TASK); PARSEP->endtaskfuncCb($<fl>1,"endtask"); }
| task taskId { PARSEP->symPopScope(VAstType::TASK); PARSEP->endtaskfuncCb($<fl>1,"endtask"); }
;
function<fl>:
yFUNCTION__ETC { $<fl>$=$<fl>1; }
| yFUNCTION__aPUREV { $<fl>$=$<fl>1; }
;
function_declaration: // IEEE: function_declaration + function_body_declaration
yFUNCTION__ETC lifetimeE funcId tfGuts yENDFUNCTION endLabelE
{ PARSEP->endtaskfuncCb($<fl>5,$5);
PARSEP->symPopScope(VAstType::FUNCTION); }
| yFUNCTION__ETC lifetimeE funcIdNew tfGuts yENDFUNCTION endLabelE
{ PARSEP->endtaskfuncCb($<fl>5,$5);
PARSEP->symPopScope(VAstType::FUNCTION); }
| yFUNCTION__aPUREV lifetimeE funcId tfGutsPureV
{ PARSEP->endtaskfuncCb($<fl>1,"endfunction");
PARSEP->symPopScope(VAstType::FUNCTION); }
| yFUNCTION__aPUREV lifetimeE funcIdNew tfGutsPureV
{ PARSEP->endtaskfuncCb($<fl>1,"endfunction");
PARSEP->symPopScope(VAstType::FUNCTION); }
;
function_prototype: // IEEE: function_prototype
// // IEEE: has '(' tf_port_list ')'
// // However the () should be optional for OVA
function funcId '(' tf_port_listE ')' { PARSEP->symPopScope(VAstType::FUNCTION); PARSEP->endtaskfuncCb($<fl>1,"endfunction"); }
| function funcId { PARSEP->symPopScope(VAstType::FUNCTION); PARSEP->endtaskfuncCb($<fl>1,"endfunction"); }
;
class_constructor_prototype: // ==IEEE: class_constructor_prototype
function funcIdNew '(' tf_port_listE ')' ';' { PARSEP->symPopScope(VAstType::FUNCTION); PARSEP->endtaskfuncCb($<fl>1,"endfunction"); }
| function funcIdNew ';' { PARSEP->symPopScope(VAstType::FUNCTION); PARSEP->endtaskfuncCb($<fl>1,"endfunction"); }
;
method_prototype:
task_prototype { }
| function_prototype { }
;
lifetimeE: // IEEE: [lifetime]
/* empty */ { }
| lifetime { }
;
lifetime: // ==IEEE: lifetime
// // Note lifetime used by members is instead under memberQual
ySTATIC__ETC { }
| yAUTOMATIC { }
;
taskId:
tfIdScoped
{ PARSEP->symPushNewUnder(VAstType::TASK, $<str>1, $<scp>1);
PARSEP->taskCb($<fl>1,"task",$<str>1); }
;
funcId: // IEEE: function_data_type_or_implicit + part of function_body_declaration
// // IEEE: function_data_type_or_implicit must be expanded here to prevent conflict
// // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID
/**/ tfIdScoped
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, $<str>1, $<scp>1);
PARSEP->functionCb($<fl>1,"function",$<str>1,""); }
| signingE rangeList tfIdScoped
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, $<str>3, $<scp>3);
PARSEP->functionCb($<fl>3,"function",$<str>3,SPACED($1,$2)); }
| signing tfIdScoped
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, $<str>2, $<scp>2);
PARSEP->functionCb($<fl>2,"function",$<str>2,$1); }
| yVOID tfIdScoped
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, $<str>2, $<scp>2);
PARSEP->functionCb($<fl>2,"function",$<str>2,$1); }
| data_type tfIdScoped
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, $<str>2, $<scp>2);
PARSEP->functionCb($<fl>2,"function",$<str>2,$1); }
;
funcIdNew: // IEEE: from class_constructor_declaration
yNEW__ETC
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, "new", NULL);
PARSEP->functionCb($<fl>1,"function","new",""); }
| yNEW__PAREN
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, "new", NULL);
PARSEP->functionCb($<fl>1,"function","new",""); }
| class_scopeWithoutId yNEW__PAREN
{ PARSEP->symPushNewUnder(VAstType::FUNCTION, "new", $<scp>1);
PARSEP->functionCb($<fl>2,"function","new",""); }
;
tfIdScoped<str_scp>: // IEEE: part of function_body_declaration/task_body_declaration
// // IEEE: [ interface_identifier '.' | class_scope ] function_identifier
id { $<fl>$=$<fl>1; $<scp>$=NULL; $<str>$ = $1; }
| id/*interface_identifier*/ '.' id { $<fl>$=$<fl>1; $<scp>$=NULL; $<str>$ = $1+"."+$2; }
| class_scope_id { $<fl>$=$<fl>1; $<scp>$=$<scp>1; $<str>$ = $<str>1; }
;
tfGuts:
'(' tf_port_listE ')' ';' tfBodyE { }
| ';' tfBodyE { }
;
tfGutsPureV:
'(' tf_port_listE ')' ';' { }
| ';' { }
;
tfBodyE: // IEEE: part of function_body_declaration/task_body_declaration
/* empty */ { }
| tf_item_declarationList { }
| tf_item_declarationList stmtList { }
| stmtList { }
;
function_data_type<str>: // IEEE: function_data_type
yVOID { $$ = $1; }
| data_type { $$ = $1; }
;
tf_item_declarationList:
tf_item_declaration { }
| tf_item_declarationList tf_item_declaration { }
;
tf_item_declaration: // ==IEEE: tf_item_declaration
block_item_declaration { }
| tf_port_declaration { }
;
tf_port_listE: // IEEE: tf_port_list + empty
// // Empty covered by tf_port_item
{ VARRESET_LIST(""); VARIO("input"); }
tf_port_listList { VARRESET_NONLIST(""); }
;
tf_port_listList: // IEEE: part of tf_port_list
tf_port_item { }
| tf_port_listList ',' tf_port_item { }
;
tf_port_item: // ==IEEE: tf_port_item
// // We split tf_port_item into the type and assignment as don't know what follows a comma
/* empty */ { PINNUMINC(); } // For example a ",," port
| tf_port_itemFront tf_port_itemAssignment { PINNUMINC(); }
| tf_port_itemAssignment { PINNUMINC(); }
;
tf_port_itemFront: // IEEE: part of tf_port_item, which has the data type
data_type { VARDTYPE($1); }
| signingE rangeList { VARDTYPE(SPACED($1,$2)); }
| signing { VARDTYPE($1); }
| yVAR data_type { VARDTYPE($2); }
| yVAR implicit_typeE { VARDTYPE($2); }
//
| tf_port_itemDir /*implicit*/ { VARDTYPE(""); /*default_nettype-see spec*/ }
| tf_port_itemDir data_type { VARDTYPE($2); }
| tf_port_itemDir signingE rangeList { VARDTYPE(SPACED($2,$3)); }
| tf_port_itemDir signing { VARDTYPE($2); }
| tf_port_itemDir yVAR data_type { VARDTYPE($3); }
| tf_port_itemDir yVAR implicit_typeE { VARDTYPE($3); }
;
tf_port_itemDir: // IEEE: part of tf_port_item, direction
port_direction { } // port_direction sets VARIO
;
tf_port_itemAssignment: // IEEE: part of tf_port_item, which has assignment
id variable_dimensionListE sigAttrListE
{ VARDONE($<fl>1, $1, $2, ""); }
| id variable_dimensionListE sigAttrListE '=' expr
{ VARDONE($<fl>1, $1, $2, $5); }
;
parenE:
/* empty */ { }
| '(' ')' { }
;
// method_call: // ==IEEE: method_call + method_call_body
// // IEEE: method_call_root '.' method_identifier [ '(' list_of_arguments ')' ]
// // "method_call_root '.' method_identifier" looks just like "expr '.' id"
// // "method_call_root '.' method_identifier (...)" looks just like "expr '.' tf_call"
// // IEEE: built_in_method_call
// // method_call_root not needed, part of expr resolution
// // What's left is below array_methodNoRoot
array_methodNoRoot<str>: // ==IEEE: built_in_method_call without root
// // method_call_root not needed, part of expr resolution
array_method_nameNoId method_callWithE { $<fl>$=$<fl>1; $$=$1+$2; }
| array_method_nameNoId '(' list_of_argumentsE ')' method_callWithE { $<fl>$=$<fl>1; $$=$1+$2+$3+$4+$5; }
// // "method_call_root '.' randomize_call" matches function_subroutine_call:randomize_call
;
method_callWithE<str>:
// // Code duplicated elsewhere
/* empty */ { $$=""; }
| yWITH__PAREN '(' expr ')' { $<fl>$=$<fl>1; $$=$1+$2+$3+$4; }
;
array_method_nameNoId<str>: // IEEE: array_method_name minus method_identifier
yUNIQUE { $<fl>$=$<fl>1; $$=$1; }
| yAND { $<fl>$=$<fl>1; $$=$1; }
| yOR { $<fl>$=$<fl>1; $$=$1; }
| yXOR { $<fl>$=$<fl>1; $$=$1; }
;
dpi_import_export: // ==IEEE: dpi_import_export
yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE function_prototype ';' { }
| yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE task_prototype ';' { }
| yEXPORT yaSTRING dpi_importLabelE function idAny ';' { }
| yEXPORT yaSTRING dpi_importLabelE task idAny ';' { }
;
dpi_importLabelE: // IEEE: part of dpi_import_export
/* empty */ { }
| idAny/*c_identifier*/ '=' { }
;
dpi_tf_import_propertyE: // IEEE: [ dpi_function_import_property + dpi_task_import_property ]
/* empty */ { }
| yCONTEXT { }
| yPURE { }
;
overload_declaration: // ==IEEE: overload_declaration
// // OLD: Overloads deprecated in IEEE 1800-2017
yBIND overload_operator function data_type idAny/*new-function_identifier*/
'(' overload_proto_formals ')' ';' { }
;
overload_operator<str>: // ==IEEE: overload_operator
"+" { $$="+"; }
| yP_PLUSPLUS { $$="++"; }
| "-" { $$="-"; }
| yP_MINUSMINUS { $$="--"; }
| "*" { $$="*"; }
| yP_POW { $$="**"; }
| "/" { $$="/"; }
| "%" { $$="%"; }
| yP_EQUAL { $$="=="; }
| yP_NOTEQUAL { $$="!="; }
| "<" { $$="<"; }
| yP_LTE { $$="<="; }
| ">" { $$=">"; }
| yP_GTE { $$=">="; }
| "=" { $$="="; }
;
overload_proto_formals: // ==IEEE: overload_proto_formals
data_type { }
| overload_proto_formals ',' data_type { }
;
//************************************************
// Expressions
//
// ~l~ means this is the (l)eft hand side of any operator
// it will get replaced by "", "f" or "s"equence
// ~r~ means this is a (r)ight hand later expansion in the same statement,
// not under parenthesis for <= disambiguation
// it will get replaced by "", or "f"
// ~p~ means this is a (p)arenthetized expression
// it will get replaced by "", or "s"equence
constExpr<str>:
expr { $<fl>$=$<fl>1; $$ = $1; }
;
expr<str>: // IEEE: part of expression/constant_expression/primary
// *SEE BELOW* // IEEE: primary/constant_primary
//
// // IEEE: unary_operator primary
'+' ~r~expr %prec prUNARYARITH { $<fl>$=$<fl>1; $$ = $1+$2; }
| '-' ~r~expr %prec prUNARYARITH { $<fl>$=$<fl>1; $$ = $1+$2; }
| '!' ~r~expr %prec prNEGATION { $<fl>$=$<fl>1; $$ = $1+$2; }
| '&' ~r~expr %prec prREDUCTION { $<fl>$=$<fl>1; $$ = $1+$2; }
| '~' ~r~expr %prec prNEGATION { $<fl>$=$<fl>1; $$ = $1+$2; }
| '|' ~r~expr %prec prREDUCTION { $<fl>$=$<fl>1; $$ = $1+$2; }
| '^' ~r~expr %prec prREDUCTION { $<fl>$=$<fl>1; $$ = $1+$2; }
| yP_NAND ~r~expr %prec prREDUCTION { $<fl>$=$<fl>1; $$ = $1+$2; }
| yP_NOR ~r~expr %prec prREDUCTION { $<fl>$=$<fl>1; $$ = $1+$2; }
| yP_XNOR ~r~expr %prec prREDUCTION { $<fl>$=$<fl>1; $$ = $1+$2; }
//
// // IEEE: inc_or_dec_expression
| ~l~inc_or_dec_expression { $<fl>$=$<fl>1; $$ = $1; }
//
// // IEEE: '(' operator_assignment ')'
// // Need exprScope of variable_lvalue to prevent conflict
| '(' ~p~exprScope '=' expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_PLUSEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_MINUSEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_TIMESEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_DIVEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_MODEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_ANDEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_OREQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_XOREQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_SLEFTEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_SRIGHTEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
| '(' ~p~exprScope yP_SSRIGHTEQ expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+$3+$4+")"; }
//
// // IEEE: expression binary_operator expression
| ~l~expr '+' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '-' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '*' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '/' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '%' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_EQUAL ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_NOTEQUAL ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_CASEEQUAL ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_CASENOTEQUAL ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_WILDEQUAL ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_WILDNOTEQUAL ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_ANDAND ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_OROR ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_POW ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '<' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '>' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_GTE ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '&' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '|' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr '^' ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_XNOR ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_NOR ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_NAND ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_SLEFT ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_SRIGHT ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_SSRIGHT ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| ~l~expr yP_LTMINUSGT ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
//
// // IEEE: expr yP_MINUSGT expr (1800-2009)
// // Conflicts with constraint_expression:"expr yP_MINUSGT constraint_set"
// // To duplicating expr for constraints, just allow the more general form
// // Later Ast processing must ignore constraint terms where inappropriate
| ~l~expr yP_MINUSGT constraint_set { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
//
// // <= is special, as we need to disambiguate it with <= assignment
// // We copy all of expr to fexpr and rename this token to a fake one.
| ~l~expr yP_LTE~f__IGNORE~ ~r~expr { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
//
// // IEEE: conditional_expression
| ~l~expr '?' ~r~expr ':' ~r~expr { $<fl>$=$<fl>1; $$ = $1+"?"+$3+":"+$5; }
//
// // IEEE: inside_expression
| ~l~expr yINSIDE '{' open_range_list '}' { $<fl>$=$<fl>1; $$ = $1+" inside {"+$3+"}"; }
//
// // IEEE: tagged_union_expression
| yTAGGED id/*member*/ %prec prTAGGED { $<fl>$=$<fl>1; $$ = " tagged "+$1; }
| yTAGGED id/*member*/ %prec prTAGGED expr { $<fl>$=$<fl>1; $$ = " tagged "+$1+" "+$2; }
//
//======================// IEEE: primary/constant_primary
//
// // IEEE: primary_literal (minus string, which is handled specially)
| yaINTNUM { $<fl>$=$<fl>1; $$ = $1; }
| yaFLOATNUM { $<fl>$=$<fl>1; $$ = $1; }
| yaTIMENUM { $<fl>$=$<fl>1; $$ = $1; }
| strAsInt~noStr__IGNORE~ { $<fl>$=$<fl>1; $$ = $1; }
//
// // IEEE: "... hierarchical_identifier select" see below
//
// // IEEE: empty_queue (IEEE 1800-2017 empty_unpacked_array_concatenation)
| '{' '}'
//
// // IEEE: concatenation/constant_concatenation
// // Part of exprOkLvalue below
//
// // IEEE: multiple_concatenation/constant_multiple_concatenation
| '{' constExpr '{' cateList '}' '}' { $<fl>$=$<fl>1; $$ = "{"+$2+"{"+$4+"}}"; }
// // IEEE: multiple_concatenation/constant_multiple_concatenation+ range_expression (1800-2009)
| '{' constExpr '{' cateList '}' '}' '[' expr ']'
{ $<fl>$=$<fl>1; $$ = "{"+$2+"{"+$4+"}}["+$8+"]"; NEED_S09($<fl>6,"{}[]"); }
| '{' constExpr '{' cateList '}' '}' '[' expr ':' expr ']'
{ $<fl>$=$<fl>1; $$ = "{"+$2+"{"+$4+"}}["+$8+$9+$10+"]"; NEED_S09($<fl>6,"{}[]"); }
| '{' constExpr '{' cateList '}' '}' '[' expr yP_PLUSCOLON expr ']'
{ $<fl>$=$<fl>1; $$ = "{"+$2+"{"+$4+"}}["+$8+$9+$10+"]"; NEED_S09($<fl>6,"{}[]"); }
| '{' constExpr '{' cateList '}' '}' '[' expr yP_MINUSCOLON expr ']'
{ $<fl>$=$<fl>1; $$ = "{"+$2+"{"+$4+"}}["+$8+$9+$10+"]"; NEED_S09($<fl>6,"{}[]"); }
//
| function_subroutine_callNoMethod { $$ = $1; }
// // method_call
| ~l~expr '.' function_subroutine_callNoMethod { $<fl>$=$<fl>1; $$=$1+"."+$3; }
// // method_call:array_method requires a '.'
| ~l~expr '.' array_methodNoRoot { $<fl>$=$<fl>1; $$ = $1+"."+$3; }
//
// // IEEE: let_expression
// // see funcRef
//
// // IEEE: '(' mintypmax_expression ')'
| ~noPar__IGNORE~'(' expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+")"; }
| ~noPar__IGNORE~'(' expr ':' expr ':' expr ')' { $<fl>$=$<fl>1; $$ = "("+$2+":"+$4+":"+$5+")"; }
// // PSL rule
| '_' '(' statePushVlg expr statePop ')' { $<fl>$=$<fl>1; $$ = "_("+$4+")"; } // Arbitrary Verilog inside PSL
//
// // IEEE: cast/constant_cast
| casting_type yP_TICK '(' expr ')' { $<fl>$=$<fl>1; $$ = $1+"'("+$4+")"; }
// // Spec only allows primary with addition of a type reference
// // We'll be more general, and later assert LHS was a type.
| ~l~expr yP_TICK '(' expr ')' { $<fl>$=$<fl>1; $$ = $1+"'("+$4+")"; }
//
// // IEEE: assignment_pattern_expression
// // IEEE: streaming_concatenation
// // See exprOkLvalue
//
// // IEEE: sequence_method_call
// // Indistinguishable from function_subroutine_call:method_call
//
| '$' { $<fl>$=$<fl>1; $$ = "$"; }
| yNULL { $<fl>$=$<fl>1; $$ = $1; }
// // IEEE: yTHIS
// // See exprScope
//
//----------------------
//
// // Part of expr that may also be used as lvalue
| ~l~exprOkLvalue { $<fl>$=$<fl>1; $$ = $1; }
//
//----------------------
//
// // IEEE: cond_predicate - here to avoid reduce problems
// // Note expr includes cond_pattern
| ~l~expr yP_ANDANDAND ~r~expr { $<fl>$=$<fl>1; $$ = $1 + "&&&" + $3; }
//
// // IEEE: cond_pattern - here to avoid reduce problems
// // "expr yMATCHES pattern"
// // IEEE: pattern - expanded here to avoid conflicts
| ~l~expr yMATCHES patternNoExpr { $<fl>$=$<fl>1; $$ = $1 + " matches " + $3; }
| ~l~expr yMATCHES ~r~expr { $<fl>$=$<fl>1; $$ = $1 + " matches " + $3; }
//
// // IEEE: expression_or_dist - here to avoid reduce problems
// // "expr yDIST '{' dist_list '}'"
| ~l~expr yDIST '{' dist_list '}' { $<fl>$=$<fl>1; $$ = $1 + " dist " + $3+"..."+$5; }
;
fexpr<str>: // For use as first part of statement (disambiguates <=)
BISONPRE_COPY(expr,{s/~l~/f/g; s/~r~/f/g; s/~f__IGNORE~/__IGNORE/g;}) // {copied}
;
ev_expr<str>: // IEEE: event_expression
// // for yOR/, see event_expression
//
// // IEEE: [ edge_identifier ] expression [ yIFF expression ]
// // expr alone see below
senitemEdge { }
| ev_expr yIFF expr { }
//
// // IEEE: sequence_instance [ yIFF expression ]
// // seq_inst is in expr, so matches senitem rule above
//
// // IEEE: event_expression yOR event_expression
| ev_expr yOR ev_expr { }
// // IEEE: event_expression ',' event_expression
// // See real event_expression rule
//
//---------------------
// // IEEE: expr
| BISONPRE_COPY(expr,{s/~l~/ev_/g; s/~r~/ev_/g; s/~p~/ev_/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g;}) // {copied}
//
// // IEEE: '(' event_expression ')'
// // expr:'(' x ')' conflicts with event_expression:'(' event_expression ')'
// // so we use a special expression class
| '(' event_expression ')' { $<fl>$=$<fl>1; $$ = "(...)"; }
// // IEEE: From normal expr: '(' expr ':' expr ':' expr ')'
// // But must avoid conflict
| '(' event_expression ':' expr ':' expr ')' { $<fl>$=$<fl>1; $$ = "(...)"; }
;
//sexpr: See elsewhere
//pexpr: See elsewhere
exprOkLvalue<str>: // expression that's also OK to use as a variable_lvalue
~l~exprScope { $<fl>$=$<fl>1; $$ = $1; }
// // IEEE: concatenation/constant_concatenation
| '{' cateList '}' { $<fl>$=$<fl>1; $$ = "{"+$2+"}"; }
// // IEEE: concatenation/constant_concatenation+ constant_range_expression (1800-2009)
| '{' cateList '}' '[' expr ']' { $<fl>$=$<fl>1; $$ = "{"+$2+"}["+$5+"]"; NEED_S09($<fl>4,"{}[]"); }
| '{' cateList '}' '[' expr ':' expr ']' { $<fl>$=$<fl>1; $$ = "{"+$2+"}["+$5+$6+$7+"]"; NEED_S09($<fl>4,"{}[]"); }
| '{' cateList '}' '[' expr yP_PLUSCOLON expr ']' { $<fl>$=$<fl>1; $$ = "{"+$2+"}["+$5+$6+$7+"]"; NEED_S09($<fl>4,"{}[]"); }
| '{' cateList '}' '[' expr yP_MINUSCOLON expr ']' { $<fl>$=$<fl>1; $$ = "{"+$2+"}["+$5+$6+$7+"]"; NEED_S09($<fl>4,"{}[]"); }
// // IEEE: assignment_pattern_expression
// // IEEE: [ assignment_pattern_expression_type ] == [ ps_type_id /ps_paremeter_id/data_type]
// // We allow more here than the spec requires
| ~l~exprScope assignment_pattern { $<fl>$=$<fl>1; $$=$1+$2; }
| data_type assignment_pattern { $<fl>$=$<fl>1; $$=$1+$2; }
| assignment_pattern { $<fl>$=$<fl>1; $$=$1; }
//
| streaming_concatenation { $<fl>$=$<fl>1; $$ = $1; }
;
fexprOkLvalue<str>: // exprOkLValue, For use as first part of statement (disambiguates <=)
BISONPRE_COPY(exprOkLvalue,{s/~l~/f/g}) // {copied}
;
sexprOkLvalue<str>: // exprOkLValue, For use by sequence_expr
BISONPRE_COPY(exprOkLvalue,{s/~l~/s/g}) // {copied}
;
pexprOkLvalue<str>: // exprOkLValue, For use by property_expr
BISONPRE_COPY(exprOkLvalue,{s/~l~/p/g}) // {copied}
;
ev_exprOkLvalue<str>: // exprOkLValue, For use by ev_expr
BISONPRE_COPY(exprOkLvalue,{s/~l~/ev_/g}) // {copied}
;
pev_exprOkLvalue<str>: // exprOkLValue, For use by ev_expr
BISONPRE_COPY(exprOkLvalue,{s/~l~/pev_/g}) // {copied}
;
exprLvalue<str>: // expression that should be a variable_lvalue
~f~exprOkLvalue { $<fl>$=$<fl>1; $$ = $1; }
;
fexprLvalue<str>: // For use as first part of statement (disambiguates <=)
BISONPRE_COPY(exprLvalue,{s/~f~/f/g}) // {copied}
;
exprScope<str>: // scope and variable for use to inside an expression
// // Here we've split method_call_root | implicit_class_handle | class_scope | package_scope
// // from the object being called and let expr's "." deal with resolving it.
// // (note method_call_root was simplified to require a primary in 1800-2009)
//
// // IEEE: [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select
// // Or method_call_body without parenthesis
// // See also varRefClassBit, which is the non-expr version of most of this
yTHIS { $<fl>$=$<fl>1; $$ = $1; }
| idArrayed { $<fl>$=$<fl>1; $$ = $1; }
| package_scopeIdFollows idArrayed { $<fl>$=$<fl>1; $$ = $1+$2; }
| class_scopeIdFollows idArrayed { $<fl>$=$<fl>1; $$ = $<str>1+$2; }
| ~l~expr '.' idArrayed { $<fl>$=$<fl>1; $$ = $1+"."+$3; PORTNET($<fl>1, $$); }
// // expr below must be a "yTHIS"
| ~l~expr '.' ySUPER { $<fl>$=$<fl>1; $$ = $1+"."+$3; }
// // Part of implicit_class_handle
| ySUPER { $<fl>$=$<fl>1; $$ = $1; }
;
fexprScope<str>: // exprScope, For use as first part of statement (disambiguates <=)
BISONPRE_COPY(exprScope,{s/~l~/f/g}) // {copied}
;
sexprScope<str>: // exprScope, For use by sequence_expr
BISONPRE_COPY(exprScope,{s/~l~/s/g}) // {copied}
;
pexprScope<str>: // exprScope, For use by property_expr
BISONPRE_COPY(exprScope,{s/~l~/p/g}) // {copied}
;
ev_exprScope<str>: // exprScope, For use by ev_expr
BISONPRE_COPY(exprScope,{s/~l~/ev_/g}) // {copied}
;
pev_exprScope<str>: // exprScope, For use by ev_expr
BISONPRE_COPY(exprScope,{s/~l~/pev_/g}) // {copied}
;
// Generic expressions
exprOrDataType<str>: // expr | data_type: combined to prevent conflicts
expr { $<fl>$=$<fl>1; $$ = $1; }
// // data_type includes id that overlaps expr, so special flavor
| data_type { $<fl>$=$<fl>1; $$ = $1; }
// // not in spec, but needed for $past(sig,1,,@(posedge clk))
| event_control { $$ = "event_control"; }
;
exprOrDataTypeOrMinTypMax<str>: // exprOrDataType or mintypmax_expression
expr { $<fl>$=$<fl>1; $$ = $1; }
| expr ':' expr ':' expr { $<fl>$=$<fl>1; $$ = $1+$2+$3+$4+$5; }
// // data_type includes id that overlaps expr, so special flavor
| data_type { $<fl>$=$<fl>1; $$ = $1; }
// // not in spec, but needed for $past(sig,1,,@(posedge clk))
| event_control { $$ = "event_control"; }
;
cateList<str>:
// // Not just 'expr' to prevent conflict via stream_concOrExprOrType
stream_expression { $<fl>$=$<fl>1; $$ = $1; PIN_CONCAT_APPEND($1); }
| cateList ',' stream_expression { $<fl>$=$<fl>1; $$ = $1+","+$3; PIN_CONCAT_APPEND($3); }
;
exprOrDataTypeList<str>:
exprOrDataType { $<fl>$=$<fl>1; $$ = $1; }
| exprOrDataTypeList ',' exprOrDataType { $<fl>$=$<fl>1; $$ = $1+","+$3; }
| exprOrDataTypeList ',' { $<fl>$=$<fl>1; $$ = $1+","; } // Verilog::Parser only: ,, is ok
;
list_of_argumentsE<str>: // IEEE: [list_of_arguments]
// // See comments under funcRef
argsDottedList { $<fl>$=$<fl>1; $$=$1; }
| argsExprListE { $<fl>$=$<fl>1; $$=$1; }
| argsExprListE ',' argsDottedList { $<fl>$=$<fl>1; $$=$1+","+$3; }
;
pev_list_of_argumentsE<str>: // IEEE: [list_of_arguments] - pev_expr at bottom
// // See comments under funcRef
pev_argsDottedList { $<fl>$=$<fl>1; $$=$1; }
| pev_argsExprListE { $<fl>$=$<fl>1; $$=$1; }
| pev_argsExprListE ',' pev_argsDottedList { $<fl>$=$<fl>1; $$=$1+","+$3; }
;
argsExprList<str>: // IEEE: part of list_of_arguments (used where ,, isn't legal)
expr { $<fl>$=$<fl>1; $$ = $1; }
| argsExprList ',' expr { $<fl>$=$<fl>1; $$ = $1+","+$3; }
;
argsExprListE<str>: // IEEE: part of list_of_arguments
argsExprOneE { $<fl>$=$<fl>1; $$ = $1; }
| argsExprListE ',' argsExprOneE { $<fl>$=$<fl>1; $$ = $1+","+$3; }
;
pev_argsExprListE<str>: // IEEE: part of list_of_arguments - pev_expr at bottom
pev_argsExprOneE { $<fl>$=$<fl>1; $$ = $1; }
| pev_argsExprListE ',' pev_argsExprOneE { $<fl>$=$<fl>1; $$ = $1+","+$3; }
;
argsExprOneE<str>: // IEEE: part of list_of_arguments
/*empty*/ { $$ = ""; } // ,, is legal in list_of_arguments
| expr { $<fl>$=$<fl>1; $$ = $1; }
;
pev_argsExprOneE<str>: // IEEE: part of list_of_arguments - pev_expr at bottom
/*empty*/ { $$ = ""; } // ,, is legal in list_of_arguments
| pev_expr { $<fl>$=$<fl>1; $$ = $1; }
;
argsDottedList<str>: // IEEE: part of list_of_arguments
argsDotted { $<fl>$=$<fl>1; $$=$1; }
| argsDottedList ',' argsDotted { $<fl>$=$<fl>1; $$=$1+","+$3; }
;
pev_argsDottedList<str>: // IEEE: part of list_of_arguments - pev_expr at bottom
pev_argsDotted { $<fl>$=$<fl>1; $$=$1; }
| pev_argsDottedList ',' pev_argsDotted { $<fl>$=$<fl>1; $$=$1+","+$3; }
;
argsDotted<str>: // IEEE: part of list_of_arguments
'.' idAny '(' ')' { $<fl>$=$<fl>1; $$=$1+$2+$3+$4; }
| '.' idAny '(' expr ')' { $<fl>$=$<fl>1; $$=$1+$2+$3+$4+$5; }
;
pev_argsDotted<str>: // IEEE: part of list_of_arguments - pev_expr at bottom
'.' idAny '(' ')' { $<fl>$=$<fl>1; $$=$1+$2+$3+$4; }
| '.' idAny '(' pev_expr ')' { $<fl>$=$<fl>1; $$=$1+$2+$3+$4+$5; }
;
streaming_concatenation<str>: // ==IEEE: streaming_concatenation
// // Need to disambiguate {<< expr-{ ... expr-} stream_concat }
// // From {<< stream-{ ... stream-} }
// // Likewise simple_type's idScoped from constExpr's idScope
// // Thus we allow always any two operations. Sorry
// // IEEE: "'{' yP_SL/R stream_concatenation '}'"
// // IEEE: "'{' yP_SL/R simple_type stream_concatenation '}'"
// // IEEE: "'{' yP_SL/R constExpr stream_concatenation '}'"
'{' yP_SLEFT stream_concOrExprOrType '}' { $<fl>$=$<fl>1; $$="{<<"+$3+"}"; }
| '{' yP_SRIGHT stream_concOrExprOrType '}' { $<fl>$=$<fl>1; $$="{>>"+$3+"}"; }
| '{' yP_SLEFT stream_concOrExprOrType stream_concatenation '}' { $<fl>$=$<fl>1; $$="{<<"+$3+" "+$4+"}"; }
| '{' yP_SRIGHT stream_concOrExprOrType stream_concatenation '}' { $<fl>$=$<fl>1; $$="{>>"+$3+" "+$4+"}"; }
;
stream_concOrExprOrType<str>: // IEEE: stream_concatenation | slice_size:simple_type | slice_size:constExpr
cateList { $<fl>$=$<fl>1; $$=$1; }
| simple_type { $<fl>$=$<fl>1; $$=$1; }
// // stream_concatenation found via cateList:stream_expr:'{-normal-concat'
// // simple_typeRef found via cateList:stream_expr:expr:id
// // constant_expression found via cateList:stream_expr:expr
;
stream_concatenation<str>: // ==IEEE: stream_concatenation
'{' stream_expressionList '}' { $<fl>$=$<fl>1; $$="{"+$2+"}"; }
;
stream_expressionList<str>: // IEEE: part of stream_concatenation
stream_expression { $<fl>$=$<fl>1; $$=$1; }
| stream_expressionList ',' stream_expression { $<fl>$=$<fl>1; $$=$1+","+$3; }
;
stream_expression<str>: // ==IEEE: stream_expression
// // IEEE: array_range_expression expanded below
expr { $<fl>$=$<fl>1; $$=$1; }
| expr yWITH__BRA '[' expr ']' { $<fl>$=$<fl>1; $$=$1; }
| expr yWITH__BRA '[' expr ':' expr ']' { $<fl>$=$<fl>1; $$=$1; }
| expr yWITH__BRA '[' expr yP_PLUSCOLON expr ']' { $<fl>$=$<fl>1; $$=$1; }
| expr yWITH__BRA '[' expr yP_MINUSCOLON expr ']' { $<fl>$=$<fl>1; $$=$1; }
;
//************************************************
// Gate declarations
// We can't tell between UDPs and modules as they aren't declared yet.
// For simplicity, assume everything is a module, perhaps nameless,
// and deal with it later.
// IEEE: cmos_switchtype + enable_gatetype + mos_switchtype
// + n_input_gatetype + n_output_gatetype + pass_en_switchtype
// + pass_switchtype
gateKwd<str>:
ygenGATE { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yAND { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yBUF { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yNAND { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yNOR { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yNOT { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yOR { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yXNOR { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
| yXOR { $<fl>$=$<fl>1; INSTPREP($1,0,0); }
;
// This list is also hardcoded in VParseLex.l
strength: // IEEE: strength0+strength1 - plus HIGHZ/SMALL/MEDIUM/LARGE
ygenSTRENGTH { }
| ySUPPLY0 { }
| ySUPPLY1 { }
;
strengthSpecE: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty
/* empty */ { }
| strengthSpec { }
;
strengthSpec: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty
yP_PAR__STRENGTH strength ')' { }
| yP_PAR__STRENGTH strength ',' strength ')' { }
;
//************************************************
// Tables
combinational_body: // IEEE: combinational_body + sequential_body
yTABLE tableJunkList yENDTABLE { }
;
tableJunkList:
tableJunk { } /* ignored */
| tableJunkList tableJunk { } /* ignored */
;
tableJunk:
BISONPRE_NOT(yTABLE,yENDTABLE) { }
| yTABLE tableJunk yENDTABLE { }
| error {}
;
//************************************************
// Specify
specify_block: // ==IEEE: specify_block
ySPECIFY specifyJunkList yENDSPECIFY { }
| ySPECIFY yENDSPECIFY { }
;
specifyJunkList:
specifyJunk { } /* ignored */
| specifyJunkList specifyJunk { } /* ignored */
;
specifyJunk:
BISONPRE_NOT(ySPECIFY,yENDSPECIFY) { }
| ySPECIFY specifyJunk yENDSPECIFY { }
| error {}
;
specparam_declaration: // ==IEEE: specparam_declaration
ySPECPARAM junkToSemiList ';' { }
;
junkToSemiList:
junkToSemi { } /* ignored */
| junkToSemiList junkToSemi { } /* ignored */
;
junkToSemi:
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { }
| error {}
;
//************************************************
// IDs
id<str>:
yaID__ETC { $<fl>$=$<fl>1; $$=$1; }
;
idAny<str>: // Any kind of identifier
yaID__aPACKAGE { $<fl>$=$<fl>1; $$=$1; }
| yaID__aTYPE { $<fl>$=$<fl>1; $$=$1; }
| yaID__ETC { $<fl>$=$<fl>1; $$=$1; }
;
idSVKwd<str>: // Warn about non-forward compatible Verilog 2001 code
// // yBIT, yBYTE won't work here as causes conflicts
yDO { $<fl>$=$<fl>1; $$=$1; ERRSVKWD($<fl>1,$$); }
| yFINAL { $<fl>$=$<fl>1; $$=$1; ERRSVKWD($<fl>1,$$); }
;
variable_lvalue<str>: // IEEE: variable_lvalue or net_lvalue
// // Note many variable_lvalue's must use exprOkLvalue when arbitrary expressions may also exist
idClassSel { $<fl>$=$<fl>1; $$ = $1; }
| '{' variable_lvalueConcList '}' { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
// // IEEE: [ assignment_pattern_expression_type ] assignment_pattern_variable_lvalue
// // We allow more assignment_pattern_expression_types then strictly required
| data_type yP_TICKBRA variable_lvalueList '}' { $<fl>$=$<fl>1; $$ = $1+" "+$2+$3+$4; }
| idClassSel yP_TICKBRA variable_lvalueList '}' { $<fl>$=$<fl>1; $$ = $1+" "+$2+$3+$4; }
| /**/ yP_TICKBRA variable_lvalueList '}' { $<fl>$=$<fl>1; $$ = $1+$2+$3; }
| streaming_concatenation { $<fl>$=$<fl>1; $$ = $1; }
;
variable_lvalueConcList<str>: // IEEE: part of variable_lvalue: '{' variable_lvalue { ',' variable_lvalue } '}'
variable_lvalue { $<fl>$=$<fl>1; $$ = $1; }
| variable_lvalueConcList ',' variable_lvalue { $<fl>$=$<fl>1; $$ = $1+","+$3; }
;
variable_lvalueList<str>: // IEEE: part of variable_lvalue: variable_lvalue { ',' variable_lvalue }
variable_lvalue { $<fl>$=$<fl>1; $$ = $1; }
| variable_lvalueList ',' variable_lvalue { $<fl>$=$<fl>1; $$ = $1+","+$3; }
;
idClassSel<str>: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged variable
idDotted { $<fl>$=$<fl>1; $$ = $1; }
// // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select
| yTHIS '.' idDotted { $<fl>$=$<fl>1; $$ = "this."+$3; }
| ySUPER '.' idDotted { $<fl>$=$<fl>1; $$ = "super."+$3; }
| yTHIS '.' ySUPER '.' idDotted { $<fl>$=$<fl>1; $$ = "this.super."+$3; }
// // Expanded: package_scope idDotted
| class_scopeIdFollows idDotted { $<fl>$=$<fl>1; $$ = $<str>1+$2; }
| package_scopeIdFollows idDotted { $<fl>$=$<fl>1; $$ = $<str>1+$2; }
;
idClassForeach<str>: // Misc Ref to dotted, and/or arrayed, no bit range for foreach statement
// // We can't just use the more general idClassSel
// // because ,'s are allowed in the []'s
idDottedForeach { $<fl>$=$<fl>1; $$ = $1; }
// // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select
| yTHIS '.' idDottedForeach { $<fl>$=$<fl>1; $$ = "this."+$3; }
| ySUPER '.' idDottedForeach { $<fl>$=$<fl>1; $$ = "super."+$3; }
| yTHIS '.' ySUPER '.' idDottedForeach { $<fl>$=$<fl>1; $$ = "this.super."+$3; }
// // Expanded: package_scope idDotted
| class_scopeIdFollows idDottedForeach { $<fl>$=$<fl>1; $$ = $<str>1+$2; }
| package_scopeIdFollows idDottedForeach { $<fl>$=$<fl>1; $$ = $<str>1+$2; }
;
hierarchical_identifierList: // IEEE: part of wait_statement
hierarchical_identifier { }
| hierarchical_identifierList ',' hierarchical_identifier { }
;
hierarchical_identifierBit: // IEEE: "hierarchical_identifier bit_select"
// // Not in grammar but "this." believed legal here
idClassSel { }
;
hierarchical_identifier<str>: // IEEE: hierarchical_identifier, including extra bit_select
// // +hierarchical_parameter_identifier
// // Not in grammar but "this." believed legal here
idClassSel { $<fl>$=$<fl>1; $$ = $1; }
;
idDotted<str>:
yD_ROOT '.' idDottedMore { $<fl>$=$<fl>1; $$ = $1+"."+$3; }
| idDottedMore { $<fl>$=$<fl>1; $$ = $1; }
;
idDottedForeach<str>:
yD_ROOT '.' idDottedForeachMore { $<fl>$=$<fl>1; $$ = $1+"."+$3; }
| idDottedForeachMore { $<fl>$=$<fl>1; $$ = $1; }
;
idDottedMore<str>:
idArrayed { $<fl>$=$<fl>1; $$ = $1; }
| idDottedMore '.' idArrayed { $<fl>$=$<fl>1; $$ = $1+"."+$3; }
;
idDottedForeachMore<str>:
idForeach { $<fl>$=$<fl>1; $$ = $1; }
| idDottedForeachMore '.' idForeach { $<fl>$=$<fl>1; $$ = $1+"."+$3; }
;
// Single component of dotted path, maybe [#].
// Due to lookahead constraints, we can't know if [:] or [+:] are valid (last dotted part),
// we'll assume so and cleanup later.
// id below includes:
// enum_identifier
idArrayed<str>: // IEEE: id + select
id { $<fl>$=$<fl>1; $$ = $1; PORTNET($<fl>1, $1);}
// // IEEE: part_select_range/constant_part_select_range
| idArrayed '[' expr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+"]"; PORTRANGE($3, $3);}
| idArrayed '[' constExpr ':' constExpr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+":"+$5+"]"; PORTRANGE($3, $5);}
// // IEEE: indexed_range/constant_indexed_range
| idArrayed '[' expr yP_PLUSCOLON constExpr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+"+:"+$5+"]"; }
| idArrayed '[' expr yP_MINUSCOLON constExpr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+"-:"+$5+"]"; }
;
idForeach<str>: // IEEE: id + select + [loop_variables]
// // Merge of foreach and idArrayed to prevent conflict
id { $<fl>$=$<fl>1; $$ = $1; }
// // IEEE: part_select_range/constant_part_select_range
| idForeach '[' expr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+"]"; }
| idForeach '[' constExpr ':' constExpr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+":"+$5+"]"; }
// // IEEE: indexed_range/constant_indexed_range
| idForeach '[' expr yP_PLUSCOLON constExpr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+"+:"+$5+"]"; }
| idForeach '[' expr yP_MINUSCOLON constExpr ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+"-:"+$5+"]"; }
// // IEEE: part of foreach: [ loop_variables ]
| idForeach '[' expr ',' loop_variables ']' { $<fl>$=$<fl>1; $$ = $1+"["+$3+","+$5+"]"; }
;
strAsInt<str>:
yaSTRING { $<fl>$=$<fl>1; $$ = $1; }
;
endLabelE:
/* empty */ { }
| ':' idAny { }
| ':' yNEW__ETC { }
;
//************************************************
// Clocking
clocking_declaration: // IEEE: clocking_declaration
clockingFront clocking_event ';'
clocking_itemListE yENDCLOCKING endLabelE { PARSEP->symPopScope(VAstType::CLOCKING); }
// // global clocking below - we allow item list, though not in grammar
;
clockingFront: // IEEE: part of class_declaration
yCLOCKING { PARSEP->symPushNewAnon(VAstType::CLOCKING); }
| yCLOCKING idAny/*clocking_identifier*/ { PARSEP->symPushNew(VAstType::CLOCKING,$2); }
| yDEFAULT yCLOCKING { PARSEP->symPushNewAnon(VAstType::CLOCKING); }
| yDEFAULT yCLOCKING idAny/*clocking_identifier*/ { PARSEP->symPushNew(VAstType::CLOCKING,$3); }
| yGLOBAL__CLOCKING yCLOCKING { PARSEP->symPushNewAnon(VAstType::CLOCKING); }
| yGLOBAL__CLOCKING yCLOCKING idAny/*clocking_identifier*/ { PARSEP->symPushNew(VAstType::CLOCKING,$3); }
;
clocking_event: // ==IEEE: clocking_event
'@' id { }
| '@' '(' event_expression ')' { }
;
clocking_itemListE:
/* empty */ { }
| clocking_itemList { }
;
clocking_itemList: // IEEE: [ clocking_item ]
clocking_item { }
| clocking_itemList clocking_item { }
;
clocking_item: // ==IEEE: clocking_item
yDEFAULT default_skew ';' { }
| clocking_direction list_of_clocking_decl_assign ';' { }
| assertion_item_declaration { }
;
default_skew: // ==IEEE: default_skew
yINPUT clocking_skew { }
| yOUTPUT clocking_skew { }
| yINPUT clocking_skew yOUTPUT clocking_skew { }
;
clocking_direction: // ==IEEE: clocking_direction
yINPUT clocking_skewE { }
| yOUTPUT clocking_skewE { }
| yINPUT clocking_skewE yOUTPUT clocking_skewE { }
| yINOUT { }
;
list_of_clocking_decl_assign: // ==IEEE: list_of_clocking_decl_assign
clocking_decl_assign { }
| list_of_clocking_decl_assign ',' clocking_decl_assign { }
;
clocking_decl_assign: // ==IEEE: clocking_decl_assign
idAny/*new-signal_identifier*/ { }
| idAny/*new-signal_identifier*/ '=' expr { }
;
clocking_skewE: // IEEE: [clocking_skew]
/* empty */ { }
| clocking_skew { }
;
clocking_skew: // ==IEEE: clocking_skew
yPOSEDGE { }
| yPOSEDGE delay_control { }
| yNEGEDGE { }
| yNEGEDGE delay_control { }
| yEDGE { NEED_S09($<fl>1,"edge"); }
| yEDGE delay_control { NEED_S09($<fl>1,"edge"); }
| delay_control { }
;
cycle_delay: // ==IEEE: cycle_delay
yP_POUNDPOUND yaINTNUM { }
| yP_POUNDPOUND id { }
| yP_POUNDPOUND '(' expr ')' { }
;
//************************************************
// Asserts
assertion_item_declaration: // ==IEEE: assertion_item_declaration
property_declaration { }
| sequence_declaration { }
| let_declaration { }
;
assertion_item: // ==IEEE: assertion_item
concurrent_assertion_item { }
| deferred_immediate_assertion_item { }
;
deferred_immediate_assertion_item: // ==IEEE: deferred_immediate_assertion_item
deferred_immediate_assertion_statement { }
| id/*block_identifier*/ ':' deferred_immediate_assertion_statement { }
;
procedural_assertion_statement: // ==IEEE: procedural_assertion_statement
concurrent_assertion_statement { }
| immediate_assertion_statement { }
// // IEEE: checker_instantiation
// // Unlike modules, checkers are the only "id id (...)" form in statements.
| checker_instantiation { }
;
immediate_assertion_statement: // ==IEEE: immediate_assertion_statement
simple_immediate_assertion_statement { }
| deferred_immediate_assertion_statement { }
;
simple_immediate_assertion_statement: // ==IEEE: simple_immediate_assertion_statement
// // IEEE: simple_immediate_assert_statement
yASSERT '(' expr ')' action_block { }
// // IEEE: simple_immediate_assume_statement
| yASSUME '(' expr ')' action_block { }
// // IEEE: simple_immediate_cover_statement
| yCOVER '(' expr ')' stmt { }
;
deferred_immediate_assertion_statement: // ==IEEE: deferred_immediate_assertion_statement
// // IEEE: deferred_immediate_assert_statement
yASSERT '#' yaINTNUM '(' expr ')' action_block { } // yaINTNUM is always a '0'
// // 1800-2012:
| yASSERT yFINAL '(' expr ')' action_block { }
// // IEEE: deferred_immediate_assume_statement
| yASSUME '#' yaINTNUM '(' expr ')' action_block { } // yaINTNUM is always a '0'
// // 1800-2012:
| yASSUME yFINAL '(' expr ')' action_block { }
// // IEEE: deferred_immediate_cover_statement
| yCOVER '#' yaINTNUM '(' expr ')' stmt { } // yaINTNUM is always a '0'
// // 1800-2012:
| yCOVER yFINAL '(' expr ')' action_block { }
;
expect_property_statement: // ==IEEE: expect_property_statement
yEXPECT '(' property_spec ')' action_block { }
;
concurrent_assertion_item: // IEEE: concurrent_assertion_item
concurrent_assertion_statement { }
| id/*block_identifier*/ ':' concurrent_assertion_statement { }
// // IEEE: checker_instantiation
// // identical to module_instantiation; see etcInst
;
concurrent_assertion_statement: // ==IEEE: concurrent_assertion_statement
// // IEEE: assert_property_statement
yASSERT yPROPERTY '(' property_spec ')' action_block { }
// // IEEE: assume_property_statement
| yASSUME yPROPERTY '(' property_spec ')' action_block { }
// // IEEE: cover_property_statement
| yCOVER yPROPERTY '(' property_spec ')' stmtBlock { }
// // IEEE: cover_sequence_statement
| yCOVER ySEQUENCE '(' sexpr ')' stmt { }
// // IEEE: yCOVER ySEQUENCE '(' clocking_event sexpr ')' stmt
// // sexpr already includes "clocking_event sexpr"
| yCOVER ySEQUENCE '(' clocking_event yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' sexpr ')' stmt { }
| yCOVER ySEQUENCE '(' yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' sexpr ')' stmt { }
// // IEEE: restrict_property_statement
| yRESTRICT yPROPERTY '(' property_spec ')' ';' { }
;
property_declaration: // ==IEEE: property_declaration
property_declarationFront property_port_listE ';' property_declarationBody
yENDPROPERTY endLabelE
{ PARSEP->symPopScope(VAstType::PROPERTY); }
;
property_declarationFront: // IEEE: part of property_declaration
yPROPERTY idAny/*property_identifier*/
{ PARSEP->symPushNew(VAstType::PROPERTY,$2); }
;
property_port_listE: // IEEE: [ ( [ property_port_list ] ) ]
/* empty */ { }
| '(' {VARRESET_LIST(""); VARIO("input"); } property_port_list ')'
{ VARRESET_NONLIST(""); }
;
property_port_list: // ==IEEE: property_port_list
property_port_item { }
| property_port_list ',' property_port_item { }
;
property_port_item: // IEEE: property_port_item/sequence_port_item
// // Merged in sequence_port_item
// // IEEE: property_lvar_port_direction ::= yINPUT
// // prop IEEE: [ yLOCAL [ yINPUT ] ] property_formal_type
// // id {variable_dimension} [ '=' property_actual_arg ]
// // seq IEEE: [ yLOCAL [ sequence_lvar_port_direction ] ] sequence_formal_type
// // id {variable_dimension} [ '=' sequence_actual_arg ]
property_port_itemFront property_port_itemAssignment { }
;
property_port_itemFront: // IEEE: part of property_port_item/sequence_port_item
//
property_port_itemDirE property_formal_typeNoDt { VARDTYPE($2); }
// // data_type_or_implicit
| property_port_itemDirE data_type { VARDTYPE($2); }
| property_port_itemDirE yVAR data_type { VARDTYPE($3); }
| property_port_itemDirE yVAR implicit_typeE { VARDTYPE($3); }
| property_port_itemDirE signingE rangeList { VARDTYPE(SPACED($2,$3)); }
| property_port_itemDirE /*implicit*/ { /*VARDTYPE-same*/ }
;
property_port_itemAssignment: // IEEE: part of property_port_item/sequence_port_item/checker_port_direction
portSig variable_dimensionListE { VARDONE($<fl>1, $1, $2, ""); PINNUMINC(); }
| portSig variable_dimensionListE '=' property_actual_arg
{ VARDONE($<fl>1, $1, $2, $4); PINNUMINC(); }
;
property_port_itemDirE:
/* empty */ { }
| yLOCAL__ETC { }
| yLOCAL__ETC port_direction { }
;
property_declarationBody: // IEEE: part of property_declaration
assertion_variable_declarationList property_statement_spec { }
// // IEEE-2012: Incorectly hasyCOVER ySEQUENCE then property_spec here.
// // Fixed in IEEE 1800-2017
| property_statement_spec { }
;
assertion_variable_declarationList: // IEEE: part of assertion_variable_declaration
assertion_variable_declaration { }
| assertion_variable_declarationList assertion_variable_declaration { }
;
sequence_declaration: // ==IEEE: sequence_declaration
sequence_declarationFront sequence_port_listE ';' sequence_declarationBody
yENDSEQUENCE endLabelE
{ PARSEP->symPopScope(VAstType::SEQUENCE); }
;
sequence_declarationFront: // IEEE: part of sequence_declaration
ySEQUENCE idAny/*new_sequence*/
{ PARSEP->symPushNew(VAstType::SEQUENCE,$2); }
;
sequence_port_listE: // IEEE: [ ( [ sequence_port_list ] ) ]
// // IEEE: sequence_lvar_port_direction ::= yINPUT | yINOUT | yOUTPUT
// // IEEE: [ yLOCAL [ sequence_lvar_port_direction ] ] sequence_formal_type
// // id {variable_dimension} [ '=' sequence_actual_arg ]
// // All this is almost identically the same as a property.
// // Difference is only yINOUT/yOUTPUT (which might be added to 1800-2012)
// // and yPROPERTY. So save some work.
property_port_listE { }
;
property_formal_typeNoDt<str>: // IEEE: property_formal_type (w/o implicit)
sequence_formal_typeNoDt { $$ = $1; }
| yPROPERTY { $$ = "property"; }
;
sequence_formal_typeNoDt<str>: // ==IEEE: sequence_formal_type (w/o data_type_or_implicit)
// // IEEE: data_type_or_implicit
// // implicit expanded where used
ySEQUENCE { $$ = "sequence"; }
// // IEEE-2009: yEVENT
// // already part of data_type. Removed in 1800-2012.
| yUNTYPED { $$ = "untyped"; }
;
sequence_declarationBody: // IEEE: part of sequence_declaration
// // 1800-2012 makes ';' optional
assertion_variable_declarationList sexpr { }
| assertion_variable_declarationList sexpr ';' { }
| sexpr { }
| sexpr ';' { }
;
property_spec: // IEEE: property_spec
// // IEEE: [clocking_event ] [ yDISABLE yIFF '(' expression_or_dist ')' ] property_expr
// // matches property_spec: "clocking_event property_expr" so we put it there
yDISABLE yIFF '(' expr ')' pexpr { }
| pexpr { }
;
property_statement_spec: // ==IEEE: property_statement_spec
// // IEEE: [ clocking_event ] [ yDISABLE yIFF '(' expression_or_dist ')' ] property_statement
property_statement { }
| yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' property_statement { }
// // IEEE: clocking_event property_statement
// // IEEE: clocking_event yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' property_statement
// // Both overlap pexpr:"clocking_event pexpr" the difference is
// // property_statement:property_statementCaseIf so replicate it
| clocking_event property_statementCaseIf { }
| clocking_event yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' property_statementCaseIf { }
;
property_statement: // ==IEEE: property_statement
// // Doesn't make sense to have "pexpr ;" in pexpr rule itself, so we split out case/if
pexpr ';' { }
// // Note this term replicated in property_statement_spec
// // If committee adds terms, they may need to be there too.
| property_statementCaseIf { }
;
property_statementCaseIf: // IEEE: property_statement - minus pexpr
yCASE '(' expr/*expression_or_dist*/ ')' property_case_itemList yENDCASE { }
| yCASE '(' expr/*expression_or_dist*/ ')' yENDCASE { }
| yIF '(' expr/*expression_or_dist*/ ')' pexpr %prec prLOWER_THAN_ELSE { }
| yIF '(' expr/*expression_or_dist*/ ')' pexpr yELSE pexpr { }
;
property_case_itemList: // IEEE: {property_case_item}
property_case_item { }
| property_case_itemList ',' property_case_item { }
;
property_case_item: // ==IEEE: property_case_item
// // IEEE: expression_or_dist { ',' expression_or_dist } ':' property_statement
// // IEEE 1800-2012 changed from property_statement to property_expr
// // IEEE 1800-2017 changed to require the semicolon
caseCondList ':' pexpr { }
| caseCondList ':' pexpr ';' { }
| yDEFAULT pexpr { }
| yDEFAULT ':' pexpr ';' { }
;
pev_expr<str>: // IEEE: property_actual_arg | expr
// // which expands to pexpr | event_expression
// // Used in port and function calls, when we can't know yet if something
// // is a function/sequence/property or instance/checker pin.
//
// // '(' pev_expr ')'
// // Already in pexpr
// // IEEE: event_expression ',' event_expression
// // ','s are legal in event_expressions, but parens required to avoid conflict with port-sep-,
// // IEEE: event_expression yOR event_expression
// // Already in pexpr - needs removal there
// // IEEE: event_expression yIFF expr
// // Already in pexpr - needs removal there
//
senitemEdge { $$=$1; }
//
//============= pexpr rules copied for pev_expr
| BISONPRE_COPY_ONCE(pexpr,{s/~o~p/pev_/g; }) // {copied}
//
//============= sexpr rules copied for pev_expr
| BISONPRE_COPY_ONCE(sexpr,{s/~p~s/pev_/g; }) // {copied}
//
//============= expr rules copied for pev_expr
| BISONPRE_COPY_ONCE(expr,{s/~l~/pev_/g; s/~p~/pev_/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g; }) // {copied}
;
pexpr<str>: // IEEE: property_expr (The name pexpr is important as regexps just add an "p" to expr.)
//
// // IEEE: sequence_expr
// // Expanded below
//
// // IEEE: '(' pexpr ')'
// // Expanded below
//
yNOT pexpr %prec prNEGATION { }
| ySTRONG '(' sexpr ')' { }
| yWEAK '(' sexpr ')' { }
// // IEEE: pexpr yOR pexpr
// // IEEE: pexpr yAND pexpr
// // Under ~p~sexpr and/or ~p~sexpr
//
// // IEEE: "sequence_expr yP_ORMINUSGT pexpr"
// // Instead we use pexpr to prevent conflicts
| ~o~pexpr yP_ORMINUSGT pexpr { }
| ~o~pexpr yP_OREQGT pexpr { }
//
// // IEEE-2009: property_statement
// // IEEE-2012: yIF and yCASE
| property_statementCaseIf { }
//
| ~o~pexpr/*sexpr*/ yP_POUNDMINUSPD pexpr { }
| ~o~pexpr/*sexpr*/ yP_POUNDEQPD pexpr { }
| yNEXTTIME pexpr { }
| yS_NEXTTIME pexpr { }
| yNEXTTIME '[' expr/*const*/ ']' pexpr %prec yNEXTTIME { }
| yS_NEXTTIME '[' expr/*const*/ ']' pexpr %prec yS_NEXTTIME { }
| yALWAYS pexpr { }
| yALWAYS '[' cycle_delay_const_range_expression ']' pexpr %prec yALWAYS { }
| yS_ALWAYS '[' constant_range ']' pexpr %prec yS_ALWAYS { }
| yS_EVENTUALLY pexpr { }
| yEVENTUALLY '[' constant_range ']' pexpr %prec yEVENTUALLY { }
| yS_EVENTUALLY '[' cycle_delay_const_range_expression ']' pexpr %prec yS_EVENTUALLY { }
| ~o~pexpr yUNTIL pexpr { }
| ~o~pexpr yS_UNTIL pexpr { }
| ~o~pexpr yUNTIL_WITH pexpr { }
| ~o~pexpr yS_UNTIL_WITH pexpr { }
| ~o~pexpr yIMPLIES pexpr { }
// // yIFF also used by event_expression
| ~o~pexpr yIFF ~o~pexpr { }
| yACCEPT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec yACCEPT_ON { }
| yREJECT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec yREJECT_ON { }
| ySYNC_ACCEPT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec ySYNC_ACCEPT_ON { }
| ySYNC_REJECT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec ySYNC_REJECT_ON { }
//
// // IEEE: "property_instance"
// // Looks just like a function/method call
//
// // Note "clocking_event pexpr" overlaps property_statement_spec: clocking_event property_statement
//
// // Include property_specDisable to match property_spec rule
| clocking_event yDISABLE yIFF '(' expr ')' pexpr %prec prSEQ_CLOCKING { }
//
//============= sexpr rules copied for property_expr
| BISONPRE_COPY_ONCE(sexpr,{s/~p~s/p/g; }) // {copied}
//
//============= expr rules copied for property_expr
| BISONPRE_COPY_ONCE(expr,{s/~l~/p/g; s/~p~/p/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g; }) // {copied}
;
sexpr<str>: // ==IEEE: sequence_expr (The name sexpr is important as regexps just add an "s" to expr.)
// // ********* RULES COPIED IN sequence_exprProp
// // For precedence, see IEEE 17.7.1
//
// // IEEE: "cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }"
// // IEEE: "sequence_expr cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }"
// // Both rules basically mean we can repeat sequences, so make it simpler:
cycle_delay_range sexpr %prec yP_POUNDPOUND { }
| ~p~sexpr cycle_delay_range sexpr %prec prPOUNDPOUND_MULTI { }
//
// // IEEE: expression_or_dist [ boolean_abbrev ]
// // Note expression_or_dist includes "expr"!
// // sexpr/*sexpression_or_dist*/ --- Hardcoded below
| ~p~sexpr/*sexpression_or_dist*/ boolean_abbrev { }
//
// // IEEE: "sequence_instance [ sequence_abbrev ]"
// // version without sequence_abbrev looks just like normal function call
// // version w/sequence_abbrev matches above; expression_or_dist:expr:func boolean_abbrev:sequence_abbrev
//
// // IEEE: '(' expression_or_dist {',' sequence_match_item } ')' [ boolean_abbrev ]
// // IEEE: '(' sexpr {',' sequence_match_item } ')' [ sequence_abbrev ]
// // As sequence_expr includes expression_or_dist, and boolean_abbrev includes sequence_abbrev:
// // '(' sequence_expr {',' sequence_match_item } ')' [ boolean_abbrev ]
// // "'(' sexpr ')' boolean_abbrev" matches "[sexpr:'(' expr ')'] boolean_abbrev" so we can simply drop it
| '(' ~p~sexpr ')' { $<fl>$=$<fl>1; $$=$1+$2+$3; }
| '(' ~p~sexpr ',' sequence_match_itemList ')' { }
//
// // AND/OR are between pexprs OR sexprs
| ~p~sexpr yAND ~p~sexpr { $<fl>$=$<fl>1; $$=$1+$2+$3; }
| ~p~sexpr yOR ~p~sexpr { $<fl>$=$<fl>1; $$=$1+$2+$3; }
// // Intersect always has an sexpr rhs
| ~p~sexpr yINTERSECT sexpr { $<fl>$=$<fl>1; $$=$1+$2+$3; }
//
| yFIRST_MATCH '(' sexpr ')' { }
| yFIRST_MATCH '(' sexpr ',' sequence_match_itemList ')' { }
| ~p~sexpr/*sexpression_or_dist*/ yTHROUGHOUT sexpr { }
// // Below pexpr's are really sequence_expr, but avoid conflict
// // IEEE: sexpr yWITHIN sexpr
| ~p~sexpr yWITHIN sexpr { $<fl>$=$<fl>1; $$=$1+$2+$3; }
// // Note concurrent_assertion had duplicate rule for below
| clocking_event ~p~sexpr %prec prSEQ_CLOCKING { }
//
//============= expr rules copied for sequence_expr
| BISONPRE_COPY_ONCE(expr,{s/~l~/s/g; s/~p~/s/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g; }) // {copied}
;
cycle_delay_range: // IEEE: ==cycle_delay_range
// // These three terms in 1800-2005 ONLY
yP_POUNDPOUND yaINTNUM { }
| yP_POUNDPOUND id { }
| yP_POUNDPOUND '(' constExpr ')' { }
// // In 1800-2009 ONLY:
// // IEEE: yP_POUNDPOUND constant_primary
// // UNSUP: This causes a big grammer ambiguity
// // as ()'s mismatch between primary and the following statement
// // the sv-ac committee has been asked to clarify (Mantis 1901)
| yP_POUNDPOUND '[' cycle_delay_const_range_expression ']' { }
| yP_POUNDPOUND yP_BRASTAR ']' { }
| yP_POUNDPOUND yP_BRAPLUSKET { }
;
sequence_match_itemList: // IEEE: [sequence_match_item] part of sequence_expr
sequence_match_item { }
| sequence_match_itemList ',' sequence_match_item { }
;
sequence_match_item: // ==IEEE: sequence_match_item
// // IEEE says: operator_assignment
// // IEEE says: inc_or_dec_expression
// // IEEE says: subroutine_call
// // This is the same list as...
for_step_assignment { }
;
boolean_abbrev: // ==IEEE: boolean_abbrev
// // IEEE: consecutive_repetition
yP_BRASTAR const_or_range_expression ']' { }
| yP_BRASTAR ']' { }
| yP_BRAPLUSKET { }
// // IEEE: non_consecutive_repetition
| yP_BRAEQ const_or_range_expression ']' { }
// // IEEE: goto_repetition
| yP_BRAMINUSGT const_or_range_expression ']' { }
;
const_or_range_expression: // ==IEEE: const_or_range_expression
constExpr { }
| cycle_delay_const_range_expression { }
;
constant_range: // ==IEEE: constant_range
constExpr ':' constExpr { }
;
cycle_delay_const_range_expression: // ==IEEE: cycle_delay_const_range_expression
// // Note '$' is part of constExpr
constExpr ':' constExpr { }
;
//************************************************
// Let
let_declaration: // ==IEEE: let_declaration
let_declarationFront let_port_listE '=' expr ';'
{ PARSEP->symPopScope(VAstType::LET); }
;
let_declarationFront: // IEEE: part of let_declaration
yLET idAny/*let_identifier*/
{ PARSEP->symPushNew(VAstType::LET,$2); }
;
let_port_listE: // ==IEEE: let_port_list
/* empty */
// // IEEE: let_port_list
// // No significant difference from task ports
| '(' tf_port_listE ')'
{ VARRESET_NONLIST(""); }
;
//************************************************
// Covergroup
covergroup_declaration: // ==IEEE: covergroup_declaration
covergroup_declarationFront coverage_eventE ';' coverage_spec_or_optionListE
yENDGROUP endLabelE
{ PARSEP->endgroupCb($<fl>5,$5);
PARSEP->symPopScope(VAstType::COVERGROUP); }
| covergroup_declarationFront '(' tf_port_listE ')' coverage_eventE ';' coverage_spec_or_optionListE
yENDGROUP endLabelE
{ PARSEP->endgroupCb($<fl>8,$8);
PARSEP->symPopScope(VAstType::COVERGROUP); }
;
covergroup_declarationFront: // IEEE: part of covergroup_declaration
yCOVERGROUP idAny
{ PARSEP->symPushNew(VAstType::COVERGROUP,$2);
PARSEP->covergroupCb($<fl>1,$1,$2); }
;
cgexpr<str>: // IEEE-2012: covergroup_expression, before that just expression
expr { $<fl>$=$<fl>1; $$ = $1; }
;
coverage_spec_or_optionListE: // IEEE: [{coverage_spec_or_option}]
/* empty */ { }
| coverage_spec_or_optionList { }
;
coverage_spec_or_optionList: // IEEE: {coverage_spec_or_option}
coverage_spec_or_option { }
| coverage_spec_or_optionList coverage_spec_or_option { }
;
coverage_spec_or_option: // ==IEEE: coverage_spec_or_option
// // IEEE: coverage_spec
cover_point { }
| cover_cross { }
| coverage_option ';' { }
| error { }
;
coverage_option: // ==IEEE: coverage_option
// // option/type_option aren't really keywords
id/*yOPTION | yTYPE_OPTION*/ '.' idAny/*member_identifier*/ '=' expr { }
;
cover_point: // ==IEEE: cover_point
/**/ yCOVERPOINT expr iffE bins_or_empty { }
// // IEEE-2012: class_scope before an ID
| /**/ /**/ /**/ id ':' yCOVERPOINT expr iffE bins_or_empty { }
| class_scope_id ':' yCOVERPOINT expr iffE bins_or_empty { }
| class_scope_id id data_type id ':' yCOVERPOINT expr iffE bins_or_empty { }
| class_scope_id id /**/ id ':' yCOVERPOINT expr iffE bins_or_empty { }
| /**/ id /**/ id ':' yCOVERPOINT expr iffE bins_or_empty { }
// // IEEE-2012:
| bins_or_empty { }
;
iffE: // IEEE: part of cover_point, others
/* empty */ { }
| yIFF '(' expr ')' { }
;
bins_or_empty: // ==IEEE: bins_or_empty
'{' bins_or_optionsList '}' { }
| '{' '}' { }
| ';' { }
;
bins_or_optionsList: // IEEE: { bins_or_options ';' }
bins_or_options ';' { }
| bins_or_optionsList bins_or_options ';' { }
;
bins_or_options: // ==IEEE: bins_or_options
// // Superset of IEEE - we allow []'s in more places
coverage_option { }
// // Can't use wildcardE as results in conflicts
| /**/ bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' iffE { }
| yWILDCARD bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' iffE { }
| /**/ bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' yWITH__CUR '{' cgexpr ')' iffE { }
| yWILDCARD bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' yWITH__CUR '{' cgexpr ')' iffE { }
//
// // cgexpr part of trans_list
//
| /**/ bins_keyword id/*bin_identifier*/ bins_orBraE '=' trans_list iffE { }
| yWILDCARD bins_keyword id/*bin_identifier*/ bins_orBraE '=' trans_list iffE { }
//
| bins_keyword id/*bin_identifier*/ bins_orBraE '=' yDEFAULT iffE { }
//
| bins_keyword id/*bin_identifier*/ bins_orBraE '=' yDEFAULT ySEQUENCE iffE { }
;
bins_orBraE: // IEEE: part of bins_or_options:
/* empty */ { }
| '[' ']' { }
| '[' cgexpr ']' { }
;
bins_keyword: // ==IEEE: bins_keyword
yBINS { }
| yILLEGAL_BINS { }
| yIGNORE_BINS { }
;
covergroup_range_list: // ==IEEE: covergroup_range_list
covergroup_value_range { }
| covergroup_range_list ',' covergroup_value_range { }
;
trans_list: // ==IEEE: trans_list
'(' trans_set ')' { }
| trans_list ',' '(' trans_set ')' { }
;
trans_set: // ==IEEE: trans_set
trans_range_list { }
// // Note the { => } in the grammer, this is really a list
| trans_set yP_EQGT trans_range_list { }
;
trans_range_list: // ==IEEE: trans_range_list
trans_item { }
| trans_item yP_BRASTAR repeat_range ']' { }
| trans_item yP_BRAMINUSGT repeat_range ']' { }
| trans_item yP_BRAEQ repeat_range ']' { }
;
trans_item: // ==IEEE: range_list
covergroup_range_list { }
;
repeat_range: // ==IEEE: repeat_range
cgexpr { }
| cgexpr ':' cgexpr { }
;
cover_cross: // ==IEEE: cover_cross
id/*cover_point_identifier*/ ':' yCROSS list_of_cross_items iffE cross_body { }
| /**/ yCROSS list_of_cross_items iffE cross_body { }
;
list_of_cross_items: // ==IEEE: list_of_cross_items
cross_item ',' cross_item { }
| cross_item ',' cross_item ',' cross_itemList { }
;
cross_itemList: // IEEE: part of list_of_cross_items
cross_item
| cross_itemList ',' cross_item { }
;
cross_item: // ==IEEE: cross_item
idAny/*cover_point_identifier or variable_identifier*/ { }
;
cross_body: // ==IEEE: cross_body
'{' '}' { }
// // IEEE-2012: No semicolon here, mistake in spec
| '{' cross_body_itemSemiList '}' { }
| ';' { }
;
cross_body_itemSemiList: // IEEE: part of cross_body
cross_body_item ';' { }
| cross_body_itemSemiList cross_body_item ';' { }
;
cross_body_item: // ==IEEE: cross_body_item
// // IEEE: our semicolon is in the list
bins_selection_or_option { }
| function_declaration { }
;
bins_selection_or_option: // ==IEEE: bins_selection_or_option
coverage_option { }
| bins_selection { }
;
bins_selection: // ==IEEE: bins_selection
bins_keyword idAny/*new-bin_identifier*/ '=' select_expression iffE { }
;
select_expression: // ==IEEE: select_expression
// // IEEE: select_condition expanded here
yBINSOF '(' bins_expression ')' { }
| yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}' { }
| yWITH__PAREN '(' cgexpr ')' { }
// // IEEE-2012: Need clarification as to precedence
//UNSUP yWITH__PAREN '(' cgexpr ')' yMATCHES cgexpr { }
| '!' yBINSOF '(' bins_expression ')' { }
| '!' yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}' { }
| '!' yWITH__PAREN '(' cgexpr ')' { }
// // IEEE-2012: Need clarification as to precedence
//UNSUP '!' yWITH__PAREN '(' cgexpr ')' yMATCHES cgexpr { }
| select_expression yP_ANDAND select_expression { }
| select_expression yP_OROR select_expression { }
| '(' select_expression ')' { }
// // IEEE-2012: cross_identifier
// // Part of covergroup_expression - generic identifier
// // IEEE-2012: Need clarification as to precedence
//UNSUP covergroup_expression [ yMATCHES covergroup_expression ]
;
bins_expression: // ==IEEE: bins_expression
// // "cover_point_identifier" and "variable_identifier" look identical
id/*variable_identifier or cover_point_identifier*/ { }
| id/*cover_point_identifier*/ '.' idAny/*bins_identifier*/ { }
;
coverage_eventE: // IEEE: [ coverage_event ]
/* empty */ { }
| clocking_event { }
| yWITH__ETC function idAny/*"sample"*/ '(' tf_port_listE ')' { }
| yP_ATAT '(' block_event_expression ')' { }
;
block_event_expression: // ==IEEE: block_event_expression
block_event_expressionTerm { }
| block_event_expression yOR block_event_expressionTerm { }
;
block_event_expressionTerm: // IEEE: part of block_event_expression
yBEGIN hierarchical_btf_identifier { }
| yEND hierarchical_btf_identifier { }
;
hierarchical_btf_identifier: // ==IEEE: hierarchical_btf_identifier
// // hierarchical_tf_identifier + hierarchical_block_identifier
hierarchical_identifier/*tf_or_block*/ { }
// // method_identifier
| hierarchical_identifier class_scope_id { }
| hierarchical_identifier id { }
;
//**********************************************************************
// Randsequence
randsequence_statement: // ==IEEE: randsequence_statement
yRANDSEQUENCE '(' ')' productionList yENDSEQUENCE { }
| yRANDSEQUENCE '(' id/*production_identifier*/ ')' productionList yENDSEQUENCE { }
;
productionList: // IEEE: production+
production { }
| productionList production { }
;
production: // ==IEEE: production
productionFront ':' rs_ruleList ';' { }
;
productionFront: // IEEE: part of production
function_data_type id/*production_identifier*/ { }
| /**/ id/*production_identifier*/ { }
| function_data_type id/*production_identifier*/ '(' tf_port_listE ')' { }
| /**/ id/*production_identifier*/ '(' tf_port_listE ')' { }
;
rs_ruleList: // IEEE: rs_rule+ part of production
rs_rule { }
| rs_ruleList '|' rs_rule { }
;
rs_rule: // ==IEEE: rs_rule
rs_production_list { }
| rs_production_list yP_COLONEQ weight_specification { }
| rs_production_list yP_COLONEQ weight_specification rs_code_block { }
;
rs_production_list: // ==IEEE: rs_production_list
rs_prodList { }
| yRAND yJOIN /**/ production_item production_itemList { }
| yRAND yJOIN '(' expr ')' production_item production_itemList { }
;
weight_specification: // ==IEEE: weight_specification
yaINTNUM { }
| idClassSel/*ps_identifier*/ { }
| '(' expr ')' { }
;
rs_code_block: // ==IEEE: rs_code_block
'{' '}' { }
| '{' rs_code_blockItemList '}' { }
;
rs_code_blockItemList: // IEEE: part of rs_code_block
rs_code_blockItem { }
| rs_code_blockItemList rs_code_blockItem { }
;
rs_code_blockItem: // IEEE: part of rs_code_block
data_declaration { }
| stmt { }
;
rs_prodList: // IEEE: rs_prod+
rs_prod { }
| rs_prodList rs_prod { }
;
rs_prod: // ==IEEE: rs_prod
production_item { }
| rs_code_block { }
// // IEEE: rs_if_else
| yIF '(' expr ')' production_item %prec prLOWER_THAN_ELSE { }
| yIF '(' expr ')' production_item yELSE production_item { }
// // IEEE: rs_repeat
| yREPEAT '(' expr ')' production_item { }
// // IEEE: rs_case
| yCASE '(' expr ')' rs_case_itemList yENDCASE { }
;
production_itemList: // IEEE: production_item+
production_item { }
| production_itemList production_item { }
;
production_item: // ==IEEE: production_item
id/*production_identifier*/ { }
| id/*production_identifier*/ '(' list_of_argumentsE ')' { }
;
rs_case_itemList: // IEEE: rs_case_item+
rs_case_item { }
| rs_case_itemList rs_case_item { }
;
rs_case_item: // ==IEEE: rs_case_item
caseCondList ':' production_item ';' { }
| yDEFAULT production_item ';' { }
| yDEFAULT ':' production_item ';' { }
;
//**********************************************************************
// Checker
checker_declaration: // ==IEEE: part of checker_declaration
checkerFront checker_port_listE ';'
checker_or_generate_itemListE yENDCHECKER endLabelE
{ PARSEP->symPopScope(VAstType::CHECKER); }
;
checkerFront: // IEEE: part of checker_declaration
yCHECKER idAny/*checker_identifier*/
{ PARSEP->symPushNew(VAstType::CHECKER, $2); }
;
checker_port_listE: // IEEE: [ ( [ checker_port_list ] ) ]
// // checker_port_item is basically the same as property_port_item, minus yLOCAL::
// // Want to bet 1800-2012 adds local to checkers?
property_port_listE { }
;
checker_or_generate_itemListE: // IEEE: [{ checker_or_generate_itemList }]
/* empty */ { }
| checker_or_generate_itemList { }
;
checker_or_generate_itemList: // IEEE: { checker_or_generate_itemList }
checker_or_generate_item { }
| checker_or_generate_itemList checker_or_generate_item { }
;
checker_or_generate_item: // ==IEEE: checker_or_generate_item
checker_or_generate_item_declaration { }
| initial_construct { }
// // IEEE: checker_construct
| yALWAYS stmtBlock { }
| final_construct { }
| assertion_item { }
| continuous_assign { }
| checker_generate_item { }
;
checker_or_generate_item_declaration: // ==IEEE: checker_or_generate_item_declaration
data_declaration { }
| yRAND data_declaration { }
| function_declaration { }
| checker_declaration { }
| assertion_item_declaration { }
| covergroup_declaration { }
| overload_declaration { }
| genvar_declaration { }
| clocking_declaration { }
| yDEFAULT yCLOCKING id/*clocking_identifier*/ ';' { }
| yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' { }
| ';' { }
;
checker_generate_item: // ==IEEE: checker_generate_item
// // Specialized for checker so need "c_" prefixes here
c_loop_generate_construct { }
| c_conditional_generate_construct { }
| c_generate_region { }
//
| elaboration_system_task { }
;
checker_instantiation:
// // Only used for procedural_assertion_item's
// // Version in concurrent_assertion_item looks like etcInst
// // Thus instead of *_checker_port_connection we can use etcInst's cellpinList
id/*checker_identifier*/ id '(' cellpinList ')' ';' { }
;
//**********************************************************************
// Class
class_declaration: // ==IEEE: part of class_declaration
// // IEEE-2012: using this also for interface_class_declaration
// // The classExtendsE rule relys on classFront having the
// // new class scope correct via classFront
classFront parameter_port_listE classExtendsE classImplementsE ';'
class_itemListE yENDCLASS endLabelE
{ PARSEP->endclassCb($<fl>7,$7);
PARSEP->symPopScope(VAstType::CLASS); }
;
classFront: // IEEE: part of class_declaration
classVirtualE yCLASS lifetimeE idAny/*class_identifier*/
{ PARSEP->symPushNew(VAstType::CLASS, $4);
PARSEP->classCb($<fl>2,$2,$4,$1); }
// // IEEE: part of interface_class_declaration
| yINTERFACE yCLASS lifetimeE idAny/*class_identifier*/
{ PARSEP->symPushNew(VAstType::CLASS, $4);
PARSEP->classCb($<fl>2,$2,$4,$1); }
;
classVirtualE<str>:
/* empty */ { $$=""; }
| yVIRTUAL__CLASS { $<fl>$=$<fl>1; $$=$1; }
;
classExtendsE: // IEEE: part of class_declaration
// // The classExtendsE rule relys on classFront having the
// // new class scope correct via classFront
/* empty */ { }
| yEXTENDS class_typeWithoutId { PARSEP->syms().import($<fl>1,$<str>2,$<scp>2,"*"); }
| yEXTENDS class_typeWithoutId '(' list_of_argumentsE ')' { PARSEP->syms().import($<fl>1,$<str>2,$<scp>2,"*"); }
;
classImplementsE: // IEEE: part of class_declaration
// // All 1800-2012
/* empty */ { }
| yIMPLEMENTS classImplementsList { PARSEP->syms().import($<fl>1,$<str>2,$<scp>2,"*"); }
;
classImplementsList: // IEEE: part of class_declaration
// // All 1800-2012
class_typeWithoutId { }
| classImplementsList ',' class_typeWithoutId { }
;
//=========
// Package scoping - to traverse the symbol table properly, the final identifer
// must be included in the rules below.
// Each of these must end with {symsPackageDone | symsClassDone}
ps_id_etc<str>: // package_scope + general id
package_scopeIdFollowsE id { $<fl>$=$<fl>1; $$=$1+$2; }
;
class_scope_id<str_scp>: // class_scope + id etc
class_scopeIdFollows id { $<fl>$=$<fl>1; $<scp>$=$<scp>1; $<str>$=$<str>1+$<str>2; }
;
//=== Below rules assume special scoping per above
class_typeWithoutId<str_scp>: // as with class_typeWithoutId but allow yaID__aTYPE
// // and we thus don't need to resolve it in specified package
package_scopeIdFollowsE class_typeOneList { $<fl>$=$<fl>2; $<scp>$=$<scp>2; $<str>$=$1+$<str>2; }
;
class_scopeWithoutId<str_scp>: // class_type standalone without following id
// // and we thus don't need to resolve it in specified package
class_scopeIdFollows { $<fl>$=$<fl>1; $<scp>$=$<scp>1; $<str>$=$<str>1; PARSEP->symTableNextId(NULL); }
;
class_scopeIdFollows<str_scp>: // IEEE: class_scope + type
// // IEEE: "class_type yP_COLONCOLON"
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // But class_type:'::' conflicts with class_scope:'::' so expand here
package_scopeIdFollowsE class_typeOneListColonIdFollows { $<fl>$=$<fl>2; $<scp>$=$<scp>2; $<str>$=$1+$<str>2; }
;
class_typeOneListColonIdFollows<str_scp>: // IEEE: class_type :: but allow yaID__aTYPE
class_typeOneList yP_COLONCOLON { $<fl>$=$<fl>1; $<scp>$=$<scp>1; $<str>$=$<str>1+$<str>2; PARSEP->symTableNextId($<scp>1); }
;
class_typeOneList<str_scp>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
// // If you follow the rules down, class_type is really a list via ps_class_identifier
// // Must propagate scp up for next id
class_typeOne { $<fl>$=$<fl>1; $<scp>$=$<scp>1; $<str>$=$<str>1; }
| class_typeOneListColonIdFollows class_typeOne { $<fl>$=$<fl>1; $<scp>$=$<scp>2; $<str>$=$<str>1+$<str>2; }
;
class_typeOne<str_scp>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
// // If you follow the rules down, class_type is really a list via ps_class_identifier
// // Not listed in IEEE, but see bug627 any parameter type maybe a class
yaID__aTYPE parameter_value_assignmentE
{ $<fl>$=$<fl>1; $<scp>$=$<scp>1; $<str>$=$<str>1; }
;
package_scopeIdFollowsE<str>: // IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
/* empty */ { $$=""; }
| package_scopeIdFollows { $<fl>$=$<fl>1; $$=$1; }
;
package_scopeIdFollows<str>: // IEEE: package_scope
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // class_qualifier := [ yLOCAL '::' ] [ implicit_class_handle '.' | class_scope ]
// //vv mid rule action needed otherwise we might not have NextId in time to parse the id token
yD_UNIT { PARSEP->symTableNextId(PARSEP->syms().netlistSymp()); }
/*cont*/ yP_COLONCOLON { $<fl>$=$<fl>1; $<str>$=$<str>1+$<str>3; }
| yaID__aPACKAGE { PARSEP->symTableNextId($<scp>1); }
/*cont*/ yP_COLONCOLON { $<fl>$=$<fl>1; $<str>$=$<str>1+$<str>3; }
| yLOCAL__COLONCOLON { PARSEP->symTableNextId($<scp>1); }
/*cont*/ yP_COLONCOLON { $<fl>$=$<fl>1; $<str>$=$<str>1+$<str>3; }
;
//^^^=========
class_itemListE:
/* empty */ { }
| class_itemList { }
;
class_itemList:
class_item { }
| class_itemList class_item { }
;
class_item: // ==IEEE: class_item
class_property { }
| class_method { }
| class_constraint { }
//
| class_declaration { }
| timeunits_declaration { }
| covergroup_declaration { }
| local_parameter_declaration ';' { } // 1800-2009
| parameter_declaration ';' { } // 1800-2009
| ';' { }
//
| error ';' { }
;
class_method: // ==IEEE: class_method
memberQualResetListE task_declaration { }
| memberQualResetListE function_declaration { }
// // 1800-2009 adds yPURE yVIRTUAL, already in memberQualResetListE
| yEXTERN memberQualResetListE method_prototype ';' { }
// // IEEE: "method_qualifierE class_constructor_declaration"
// // part of function_declaration
| yEXTERN memberQualResetListE class_constructor_prototype { }
;
// IEEE: class_constructor_prototype
// See function_declaration
class_item_qualifier<str>: // IEEE: class_item_qualifier minus ySTATIC
// // IMPORTANT: yPROTECTED | yLOCAL is in a lex rule
yPROTECTED { $<fl>$=$<fl>1; $$=$1; }
| yLOCAL__ETC { $<fl>$=$<fl>1; $$=$1; }
| ySTATIC__ETC { $<fl>$=$<fl>1; $$=$1; }
;
memberQualResetListE: // Called from class_property for all qualifiers before yVAR
// // Also before method declarations, to prevent grammar conflict
// // Thus both types of qualifiers (method/property) are here
/*empty*/ { VARRESET(); VARDTYPE(""); }
| memberQualList { VARRESET(); VARDTYPE($1); }
;
memberQualList<str>:
memberQualOne { $<fl>$=$<fl>1; $$=$1; }
| memberQualList memberQualOne { $<fl>$=$<fl>1; $$=SPACED($1,$2); }
;
memberQualOne<str>: // IEEE: property_qualifier + method_qualifier
// // Part of method_qualifier and property_qualifier
class_item_qualifier { $<fl>$=$<fl>1; $$=$1; }
// // Part of method_qualifier only
| yVIRTUAL__ETC { $<fl>$=$<fl>1; $$=$1; }
// // IMPORTANT: lexer looks for yPURE yVIRTUAL
| yPURE yVIRTUAL__ETC { $<fl>$=$<fl>1; $$=$1+" "+$2; }
// // Part of property_qualifier only
| random_qualifier { $<fl>$=$<fl>1; $$=$1; }
// // Part of lifetime, but here as ySTATIC can be in different positions
| yAUTOMATIC { $<fl>$=$<fl>1; $$=$1; }
// // Part of data_declaration, but not in data_declarationVarFrontClass
| yCONST__ETC { $<fl>$=$<fl>1; $$=$1; }
;
//**********************************************************************
// Constraints
class_constraint: // ==IEEE: class_constraint
// // IEEE: constraint_declaration
constraintStaticE yCONSTRAINT idAny constraint_block { }
// // IEEE: constraint_prototype + constraint_prototype_qualifier
| constraintStaticE yCONSTRAINT idAny ';' { }
| yEXTERN constraintStaticE yCONSTRAINT idAny ';' { }
| yPURE constraintStaticE yCONSTRAINT idAny ';' { }
;
constraint_block: // ==IEEE: constraint_block
'{' constraint_block_itemList '}' { }
;
constraint_block_itemList: // IEEE: { constraint_block_item }
constraint_block_item { }
| constraint_block_itemList constraint_block_item { }
;
constraint_block_item: // ==IEEE: constraint_block_item
ySOLVE solve_before_list yBEFORE solve_before_list ';' { }
| constraint_expression { }
;
solve_before_list: // ==IEEE: solve_before_list
constraint_primary { }
| solve_before_list ',' constraint_primary { }
;
constraint_primary: // ==IEEE: constraint_primary
// // exprScope more general than: [ implicit_class_handle '.' | class_scope ] hierarchical_identifier select
exprScope { }
;
constraint_expressionList<str>: // ==IEEE: { constraint_expression }
constraint_expression { $$=$1; }
| constraint_expressionList constraint_expression { $$=$1+" "+$2; }
;
constraint_expression<str>: // ==IEEE: constraint_expression
expr/*expression_or_dist*/ ';' { $$=$1; }
// // 1800-2012:
| ySOFT expr/*expression_or_dist*/ ';' { $$="soft "+$1; }
// // 1800-2012:
// // IEEE: uniqueness_constraint ';'
| yUNIQUE '{' open_range_list '}' { $$="unique {...}"; }
// // IEEE: expr yP_MINUSGT constraint_set
// // Conflicts with expr:"expr yP_MINUSGT expr"; rule moved there
//
| yIF '(' expr ')' constraint_set %prec prLOWER_THAN_ELSE { $$=$1; }
| yIF '(' expr ')' constraint_set yELSE constraint_set { $$=$1;}
// // IEEE says array_identifier here, but dotted accepted in VMM + 1800-2009
| yFOREACH '(' idClassForeach/*array_id[loop_variables]*/ ')' constraint_set { $$=$1; }
// // soft is 1800-2012
| yDISABLE ySOFT expr/*constraint_primary*/ ';' { $$="disable soft "+$1; }
;
constraint_set<str>: // ==IEEE: constraint_set
constraint_expression { $$=$1; }
| '{' constraint_expressionList '}' { $$=$1+$2+$3; }
;
dist_list: // ==IEEE: dist_list
dist_item { }
| dist_list ',' dist_item { }
;
dist_item: // ==IEEE: dist_item + dist_weight
value_range { }
| value_range yP_COLONEQ expr { }
| value_range yP_COLONDIV expr { }
;
extern_constraint_declaration: // ==IEEE: extern_constraint_declaration
constraintStaticE yCONSTRAINT class_scope_id constraint_block { }
;
constraintStaticE: // IEEE: part of extern_constraint_declaration
/* empty */ { }
| ySTATIC__CONSTRAINT { }
;
//**********************************************************************
%%
int VParseGrammar::parse() {
s_grammarp = this;
return VParseBisonparse();
}
void VParseGrammar::debug(int level) {
VParseBisondebug = level;
}
const char* VParseGrammar::tokenName(int token) {
#if YYDEBUG || YYERROR_VERBOSE
if (token >= 255) {
switch (token) {
/*BISONPRE_TOKEN_NAMES*/
default: return yytname[token-255];
}
} else {
static char ch[2]; ch[0]=token; ch[1]='\0';
return ch;
}
#else
return "";
#endif
}
//YACC = /kits/sources/bison-2.4.1/src/bison --report=lookahead
// --report=lookahead
// --report=itemset
// --graph
//
// Local Variables:
// compile-command: "cd .. ; make -j 8 && make test"
// End:
|