+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
+ |
+# ==================================================================================================================== #
+# __ ___ _ ____ _ __ __ _ _ #
+# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
+# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
+# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
+# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
+# |_| |___/ #
+# ==================================================================================================================== #
+# Authors: #
+# Patrick Lehmann #
+# #
+# License: #
+# ==================================================================================================================== #
+# Copyright 2017-2024 Patrick Lehmann - Boetzingen, Germany #
+# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+# #
+# SPDX-License-Identifier: Apache-2.0 #
+# ==================================================================================================================== #
+#
+"""
+**An abstract VHDL language model.**
+
+This package provides a unified abstract language model for VHDL. Projects reading from source files can derive own
+classes and implement additional logic to create a concrete language model for their tools.
+
+Projects consuming pre-processed VHDL data (parsed, analyzed or elaborated) can build higher level features and services
+on such a model, while supporting multiple frontends.
+
+.. admonition:: Copyright Information
+
+ :copyright: Copyright 2017-2024 Patrick Lehmann - Bötzingen, Germany
+ :copyright: Copyright 2016-2017 Patrick Lehmann - Dresden, Germany
+ :license: Apache License, Version 2.0
+"""
+__author__ = "Patrick Lehmann"
+__email__ = "Paebbels@gmail.com"
+__copyright__ = "2016-2024, Patrick Lehmann"
+__license__ = "Apache License, Version 2.0"
+__version__ = "0.29.0"
+
+
+from enum import unique, Enum, Flag, auto
+from pathlib import Path
+from sys import version_info
+
+from typing import Union, Dict, cast, List, Generator, Optional as Nullable
+
+from pyTooling.Common import getFullyQualifiedName
+from pyTooling.Decorators import export, readonly
+from pyTooling.Graph import Graph, Vertex, Edge
+
+from pyVHDLModel.Exception import VHDLModelException
+from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError
+from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError
+from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError
+from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin
+from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression
+from pyVHDLModel.Namespace import Namespace
+from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant
+from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol
+from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation
+from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package
+from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode
+from pyVHDLModel.Instantiation import PackageInstantiation
+from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType
+
+
+@export
+@unique
+class VHDLVersion(Enum):
+ """
+ An enumeration for all possible version numbers for VHDL and VHDL-AMS.
+
+ A version can be given as integer or string and is represented as a unified
+ enumeration value.
+
+ This enumeration supports compare operators.
+ """
+
+ Any = -1 #: Any
+ VHDL87 = 87 #: VHDL-1987
+ VHDL93 = 93 #: VHDL-1993
+ AMS93 = 1993 #: VHDL-AMS-1993
+ AMS99 = 1999 #: VHDL-AMS-1999
+ VHDL2000 = 2000 #: VHDL-2000
+ VHDL2002 = 2002 #: VHDL-2002
+ VHDL2008 = 2008 #: VHDL-2008
+ AMS2017 = 2017 #: VHDL-AMS-2017
+ VHDL2019 = 2019 #: VHDL-2019
+ Latest = 10000 #: Latest VHDL (2019)
+
+ __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = {
+ -1: Any,
+ 87: VHDL87,
+ 93: VHDL93,
+ # 93: AMS93,
+ 99: AMS99,
+ 0: VHDL2000,
+ 2: VHDL2002,
+ 8: VHDL2008,
+ 17: AMS2017,
+ 19: VHDL2019,
+ 1987: VHDL87,
+ # 1993: VHDL93,
+ 1993: AMS93,
+ 1999: AMS99,
+ 2000: VHDL2000,
+ 2002: VHDL2002,
+ 2008: VHDL2008,
+ 2017: AMS2017,
+ 2019: VHDL2019,
+ 10000: Latest,
+ "Any": Any,
+ "87": VHDL87,
+ "93": VHDL93,
+ # "93": AMS93,
+ "99": AMS99,
+ "00": VHDL2000,
+ "02": VHDL2002,
+ "08": VHDL2008,
+ "17": AMS2017,
+ "19": VHDL2019,
+ "1987": VHDL87,
+ # "1993": VHDL93,
+ "1993": AMS93,
+ "1999": AMS99,
+ "2000": VHDL2000,
+ "2002": VHDL2002,
+ "2008": VHDL2008,
+ "2017": AMS2017,
+ "2019": VHDL2019,
+ "Latest": Latest,
+ } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values.
+
+ def __init__(self, *_) -> None:
+ """Patch the embedded MAP dictionary"""
+ for k, v in self.__class__.__VERSION_MAPPINGS__.items():
+ if (not isinstance(v, self.__class__)) and (v == self.value):
+ self.__class__.__VERSION_MAPPINGS__[k] = self
+
+ @classmethod
+ def Parse(cls, value: Union[int, str]) -> "VHDLVersion":
+ """
+ Parses a VHDL or VHDL-AMS year code as integer or string to an enum value.
+
+ :param value: VHDL/VHDL-AMS year code.
+ :returns: Enumeration value.
+ :raises ValueError: If the year code is not recognized.
+ """
+ try:
+ return cls.__VERSION_MAPPINGS__[value]
+ except KeyError:
+ raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.")
+
+ def __lt__(self, other: Any) -> bool:
+ """
+ Compare two VHDL/VHDL-AMS versions if the version is less than the second operand.
+
+ :param other: Parameter to compare against.
+ :returns: True if version is less than the second operand.
+ :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
+ """
+ if isinstance(other, VHDLVersion):
+ return self.value < other.value
+ else:
+ raise TypeError("Second operand is not of type 'VHDLVersion'.")
+
+ def __le__(self, other: Any) -> bool:
+ """
+ Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand.
+
+ :param other: Parameter to compare against.
+ :returns: True if version is less or equal than the second operand.
+ :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
+ """
+ if isinstance(other, VHDLVersion):
+ return self.value <= other.value
+ else:
+ raise TypeError("Second operand is not of type 'VHDLVersion'.")
+
+ def __gt__(self, other: Any) -> bool:
+ """
+ Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand.
+
+ :param other: Parameter to compare against.
+ :returns: True if version is greater than the second operand.
+ :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
+ """
+ if isinstance(other, VHDLVersion):
+ return self.value > other.value
+ else:
+ raise TypeError("Second operand is not of type 'VHDLVersion'.")
+
+ def __ge__(self, other: Any) -> bool:
+ """
+ Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand.
+
+ :param other: Parameter to compare against.
+ :returns: True if version is greater or equal than the second operand.
+ :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
+ """
+ if isinstance(other, VHDLVersion):
+ return self.value >= other.value
+ else:
+ raise TypeError("Second operand is not of type 'VHDLVersion'.")
+
+ def __ne__(self, other: Any) -> bool:
+ """
+ Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand.
+
+ :param other: Parameter to compare against.
+ :returns: True if version is unequal to the second operand.
+ :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
+ """
+ if isinstance(other, VHDLVersion):
+ return self.value != other.value
+ else:
+ raise TypeError("Second operand is not of type 'VHDLVersion'.")
+
+ def __eq__(self, other: Any) -> bool:
+ """
+ Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand.
+
+ :param other: Parameter to compare against.
+ :returns: True if version is equal to the second operand.
+ :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
+ """
+ if isinstance(other, VHDLVersion):
+ if (self is self.__class__.Any) or (other is self.__class__.Any):
+ return True
+ else:
+ return self.value == other.value
+ else:
+ raise TypeError("Second operand is not of type 'VHDLVersion'.")
+
+ @readonly
+ def IsVHDL(self) -> bool:
+ """
+ Checks if the version is a VHDL (not VHDL-AMS) version.
+
+ :returns: True if version is a VHDL version.
+ """
+ return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019)
+
+ @readonly
+ def IsAMS(self) -> bool:
+ """
+ Checks if the version is a VHDL-AMS (not VHDL) version.
+
+ :returns: True if version is a VHDL-AMS version.
+ """
+ return self in (self.AMS93, self.AMS99, self.AMS2017)
+
+ def __str__(self) -> str:
+ """
+ Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``.
+
+ :return: Formatted VHDL/VHDL-AMS version.
+ """
+ if self.value == self.Any.value:
+ return "VHDL'Any"
+ elif self.value == self.Latest.value:
+ return "VHDL'Latest"
+
+ year = str(self.value)[-2:]
+ if self.IsVHDL:
+ return f"VHDL'{year}"
+ else:
+ return f"VHDL-AMS'{year}"
+
+ def __repr__(self) -> str:
+ """
+ Formats the VHDL/VHDL-AMS version to pattern ``xxxx``.
+
+ :return: Formatted VHDL/VHDL-AMS version.
+ """
+ if self.value == self.Any.value:
+ return "Any"
+ elif self.value == self.Latest.value:
+ return "Latest"
+ else:
+ return str(self.value)
+
+
+@export
+@unique
+class ObjectClass(Enum):
+ """
+ An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...).
+
+ In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context.
+ """
+
+ Default = 0 #: Object class not defined, thus it's context dependent.
+ Constant = 1 #: Constant
+ Variable = 2 #: Variable
+ Signal = 3 #: Signal
+ File = 4 #: File
+ Type = 5 #: Type
+ # FIXME: Package?
+ Procedure = 6 #: Procedure
+ Function = 7 #: Function
+
+ def __str__(self) -> str:
+ """
+ Formats the object class.
+
+ :return: Formatted object class.
+ """
+ return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance
+
+
+@export
+@unique
+class DesignUnitKind(Flag):
+ """
+ A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...).
+
+ """
+ Context = auto() #: Context
+ Package = auto() #: Package
+ PackageBody = auto() #: Package Body
+ Entity = auto() #: Entity
+ Architecture = auto() #: Architecture
+ Configuration = auto() #: Configuration
+
+ Primary = Context | Configuration | Entity | Package #: List of primary design units.
+ Secondary = PackageBody | Architecture #: List of secondary design units.
+ WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context.
+ WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region.
+
+ All = Primary | Secondary #: List of all design units.
+
+
+@export
+@unique
+class DependencyGraphVertexKind(Flag):
+ """
+ A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph.
+ """
+ Document = auto() #: A document (VHDL source file).
+ Library = auto() #: A VHDL library.
+
+ Context = auto() #: A context design unit.
+ Package = auto() #: A package design unit.
+ PackageBody = auto() #: A package body design unit.
+ Entity = auto() #: A entity design unit.
+ Architecture = auto() #: A architecture design unit.
+ Component = auto() #: A VHDL component.
+ Configuration = auto() #: A configuration design unit.
+
+
+@export
+@unique
+class DependencyGraphEdgeKind(Flag):
+ """
+ A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph.
+ """
+ Document = auto()
+ Library = auto()
+ Context = auto()
+ Package = auto()
+ Entity = auto()
+ # Architecture = auto()
+ Configuration = auto()
+ Component = auto()
+
+ DeclaredIn = auto()
+ Order = auto()
+ Reference = auto()
+ Implementation = auto()
+ Instantiation = auto()
+
+ SourceFile = Document | DeclaredIn
+ CompileOrder = Document | Order
+
+ LibraryClause = Library | Reference
+ UseClause = Package | Reference
+ ContextReference = Context | Reference
+
+ EntityImplementation = Entity | Implementation
+ PackageImplementation = Package | Implementation
+
+ EntityInstantiation = Entity | Instantiation
+ ComponentInstantiation = Component | Instantiation
+ ConfigurationInstantiation = Configuration | Instantiation
+
+
+@export
+@unique
+class ObjectGraphVertexKind(Flag):
+ """
+ A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph.
+ """
+ Type = auto()
+ Subtype = auto()
+
+ Constant = auto()
+ DeferredConstant = auto()
+ Variable = auto()
+ Signal = auto()
+ File = auto()
+
+ Alias = auto()
+
+
+@export
+@unique
+class ObjectGraphEdgeKind(Flag):
+ """
+ A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph.
+ """
+ BaseType = auto()
+ Subtype = auto()
+
+ ReferenceInExpression = auto()
+
+
+@export
+class Design(ModelEntity):
+ """
+ A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`).
+
+ It's the root of this code document-object-model (CodeDOM). It contains at least one VHDL library (see :class:`~pyVHDLModel.Library`). When the design is
+ analysed (see :meth:`Analyze`), multiple graph data structures will be created and populated with vertices and edges. As a first result, the design's compile
+ order and hierarchy can be iterated. As a second result, the design's *top-level* is identified and referenced from the design (see :attr:`TopLevel`).
+
+ The *design* contains references to the following graphs:
+
+ * :attr:`DependencyGraph`
+ * :attr:`CompileOrderGraph`
+ * :attr:`HierarchyGraph`
+ * :attr:`ObjectGraph`
+ """
+ _name: Nullable[str] #: Name of the design
+ _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design.
+ _documents: List['Document'] #: List of all documents loaded for a design.
+ _dependencyGraph: Graph[None, None, None, None, None, None, None, None, str, DesignUnit, None, None, None, None, None, None, None, None, None, None, None, None, None] #: The graph of all dependencies in the designs.
+ _compileOrderGraph: Graph[None, None, None, None, None, None, None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: A graph derived from dependency graph containing the order of documents for compilation.
+ _hierarchyGraph: Graph[None, None, None, None, None, None, None, None, str, DesignUnit, None, None, None, None, None, None, None, None, None, None, None, None, None] #: A graph derived from dependency graph containing the design hierarchy.
+ _objectGraph: Graph[None, None, None, None, None, None, None, None, str, Obj, None, None, None, None, None, None, None, None, None, None, None, None, None] #: The graph of all types and objects in the design.
+ _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field.
+
+ def __init__(self, name: Nullable[str] = None) -> None:
+ """
+ Initializes a VHDL design.
+
+ :param name: Name of the design.
+ """
+ super().__init__()
+
+ self._name = name
+ self._libraries = {}
+ self._documents = []
+
+ self._compileOrderGraph = Graph()
+ self._dependencyGraph = Graph()
+ self._hierarchyGraph = Graph()
+ self._objectGraph = Graph()
+ self._toplevel = None
+
+ @readonly
+ def Libraries(self) -> Dict[str, 'Library']:
+ """
+ Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`).
+
+ :returns: A dictionary of library names and VHDL libraries.
+ """
+ return self._libraries
+
+ @readonly
+ def Documents(self) -> List['Document']:
+ """
+ Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`).
+
+ :returns: A list of all documents.
+ """
+ return self._documents
+
+ @readonly
+ def CompileOrderGraph(self) -> Graph:
+ """
+ Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`).
+
+ :returns: Reference to the compile-order graph.
+ """
+ return self._compileOrderGraph
+
+ @readonly
+ def DependencyGraph(self) -> Graph:
+ """
+ Read-only property to access the dependency graph (:attr:`_dependencyGraph`).
+
+ :returns: Reference to the dependency graph.
+ """
+ return self._dependencyGraph
+
+ @readonly
+ def HierarchyGraph(self) -> Graph:
+ """
+ Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`).
+
+ :returns: Reference to the hierarchy graph.
+ """
+ return self._hierarchyGraph
+
+ @readonly
+ def ObjectGraph(self) -> Graph:
+ """
+ Read-only property to access the object graph (:attr:`_objectGraph`).
+
+ :returns: Reference to the object graph.
+ """
+ return self._objectGraph
+
+ @readonly
+ def TopLevel(self) -> Union[Entity, Configuration]:
+ """
+ Read-only property to access the design's *top-level* (:attr:`_toplevel`).
+
+ When called the first time, the hierarchy graph is checked for its root elements. When there is only one root element in the graph, a new field ``toplevel``
+ is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`.
+
+ :returns: Reference to the design's *top-level*.
+ :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph.
+ :raises VHDLModelException: If there is more than one *top-level*.
+ """
+ # Check for cached result
+ if self._toplevel is not None:
+ return self._toplevel
+
+ if self._hierarchyGraph.EdgeCount == 0:
+ raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.")
+
+ roots = tuple(self._hierarchyGraph.IterateRoots())
+ if len(roots) == 1:
+ toplevel = roots[0]
+ self._hierarchyGraph["toplevel"] = toplevel
+ self._toplevel = toplevel.Value
+
+ return toplevel.Value
+ else:
+ raise VHDLModelException(f"Found more than one toplevel: {', '.join(roots)}")
+
+ def LoadStdLibrary(self) -> 'Library':
+ """
+ Load the predefined VHDL library ``std`` into the design.
+
+ This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file.
+
+ :returns: The library object of library ``std``.
+ """
+ from pyVHDLModel.STD import Std
+
+ doc = Document(Path("std.vhdl"), parent=self)
+
+ library = Std()
+ for designUnit in library.IterateDesignUnits():
+ doc._AddDesignUnit(designUnit)
+
+ self.AddLibrary(library)
+
+ return library
+
+ def LoadIEEELibrary(self) -> 'Library':
+ """
+ Load the predefined VHDL library ``ieee`` into the design.
+
+ This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file.
+
+ :returns: The library object of library ``ieee``.
+ """
+ from pyVHDLModel.IEEE import Ieee
+
+ doc = Document(Path("ieee.vhdl"), parent=self)
+
+ library = Ieee()
+ for designUnit in library.IterateDesignUnits():
+ doc._AddDesignUnit(designUnit)
+
+ self.AddLibrary(library)
+
+ return library
+
+ def AddLibrary(self, library: 'Library') -> None:
+ """
+ Add a VHDL library to the design.
+
+ Ensure the libraries name doesn't collide with existing libraries in the design. |br|
+ If ok, set the libraries parent reference to the design.
+
+ :param library: Library object to loaded.
+ :raises LibraryExistsInDesignError: If the library already exists in the design.
+ :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design.
+ """
+ libraryIdentifier = library.NormalizedIdentifier
+ if libraryIdentifier in self._libraries:
+ raise LibraryExistsInDesignError(library)
+
+ if library._parent is not None:
+ raise LibraryRegisteredToForeignDesignError(library)
+
+ self._libraries[libraryIdentifier] = library
+ library._parent = self
+
+ def GetLibrary(self, libraryName: str) -> 'Library':
+ """
+ Return an (existing) VHDL library object of name ``libraryName``.
+
+ If the requested VHDL library doesn't exist, a new VHDL library with that name will be created.
+
+ :param libraryName: Name of the requested VHDL library.
+ :returns: The VHDL library object.
+ """
+ libraryIdentifier = libraryName.lower()
+ try:
+ return self._libraries[libraryIdentifier]
+ except KeyError:
+ lib = Library(libraryName, parent=self)
+ self._libraries[libraryIdentifier] = lib
+ lib._parent = self
+ return lib
+
+ # TODO: allow overloaded parameter library to be str?
+ def AddDocument(self, document: 'Document', library: 'Library') -> None:
+ """
+ Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all entities in the document
+
+ 1. Check if entity name might exist in target library.
+ 2. Add entity to library and update library membership.
+
+ 2. Iterate all architectures in the document
+
+ 1. Check if architecture name might exist in target library.
+ 2. Add architecture to library and update library membership.
+
+ 3. Iterate all packages in the document
+
+ 1. Check if package name might exist in target library.
+ 2. Add package to library and update library membership.
+
+ 4. Iterate all package bodies in the document
+
+ 1. Check if package body name might exist in target library.
+ 2. Add package body to library and update library membership.
+
+ 5. Iterate all configurations in the document
+
+ 1. Check if configuration name might exist in target library.
+ 2. Add configuration to library and update library membership.
+
+ 6. Iterate all contexts in the document
+
+ 1. Check if context name might exist in target library.
+ 2. Add context to library and update library membership.
+
+ :param document: The VHDL source code file.
+ :param library: The VHDL library used to register the embedded design units to.
+ :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design.
+ :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library.
+ :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library.
+ :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library.
+ :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library.
+ :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library.
+ :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library.
+ """
+ # FIXME: this checks for the library name, but not the object
+ # should the libraries parent be checked too?
+ if library._normalizedIdentifier not in self._libraries:
+ raise LibraryNotRegisteredError(library)
+
+ self._documents.append(document)
+ document._parent = self
+
+ for entityIdentifier, entity in document._entities.items():
+ if entityIdentifier in library._entities:
+ raise EntityExistsInLibraryError(entity, library)
+
+ library._entities[entityIdentifier] = entity
+ entity.Library = library
+
+ for entityIdentifier, architectures in document._architectures.items():
+ try:
+ architecturesPerEntity = library._architectures[entityIdentifier]
+ for architectureIdentifier, architecture in architectures.items():
+ if architectureIdentifier in architecturesPerEntity:
+ raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library)
+
+ architecturesPerEntity[architectureIdentifier] = architecture
+ architecture.Library = library
+ except KeyError:
+ architecturesPerEntity = document._architectures[entityIdentifier].copy()
+ library._architectures[entityIdentifier] = architecturesPerEntity
+
+ for architecture in architecturesPerEntity.values():
+ architecture.Library = library
+
+ for packageIdentifier, package in document._packages.items():
+ if packageIdentifier in library._packages:
+ raise PackageExistsInLibraryError(package, library)
+
+ library._packages[packageIdentifier] = package
+ package.Library = library
+
+ for packageBodyIdentifier, packageBody in document._packageBodies.items():
+ if packageBodyIdentifier in library._packageBodies:
+ raise PackageBodyExistsError(packageBody, library)
+
+ library._packageBodies[packageBodyIdentifier] = packageBody
+ packageBody.Library = library
+
+ for configurationIdentifier, configuration in document._configurations.items():
+ if configurationIdentifier in library._configurations:
+ raise ConfigurationExistsInLibraryError(configuration, library)
+
+ library._configurations[configurationIdentifier] = configuration
+ configuration.Library = library
+
+ for contextIdentifier, context in document._contexts.items():
+ if contextIdentifier in library._contexts:
+ raise ContextExistsInLibraryError(context, library)
+
+ library._contexts[contextIdentifier] = context
+ context.Library = library
+
+ def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
+ """
+ Iterate all design units in the design.
+
+ A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all VHDL libraries.
+
+ 1. Iterate all contexts in that library.
+ 2. Iterate all packages in that library.
+ 3. Iterate all package bodies in that library.
+ 4. Iterate all entites in that library.
+ 5. Iterate all architectures in that library.
+ 6. Iterate all configurations in that library.
+
+ :param filter: An enumeration with possibly multiple flags to filter the returned design units.
+ :returns: A generator to iterate all matched design units in the design.
+
+ .. seealso::
+
+ :meth:`pyVHDLModel.Library.IterateDesignUnits`
+ Iterate all design units in the library.
+ :meth:`pyVHDLModel.Document.IterateDesignUnits`
+ Iterate all design units in the document.
+ """
+ for library in self._libraries.values():
+ yield from library.IterateDesignUnits(filter)
+
+ def Analyze(self) -> None:
+ """
+ Analyze the whole design.
+
+ .. rubric:: Algorithm
+
+ 1. Analyze dependencies of design units. |br|
+ This will also yield the design hierarchy and the compiler order.
+ 2. Analyze dependencies of types and objects.
+
+ .. seealso::
+
+ :meth:`AnalyzeDependencies`
+ Analyze the dependencies of design units.
+
+ :meth:`AnalyzeObjects`
+ Analyze the dependencies of types and objects.
+ """
+ self.AnalyzeDependencies()
+ self.AnalyzeObjects()
+
+ def AnalyzeDependencies(self) -> None:
+ """
+ Analyze the dependencies of design units.
+
+ .. rubric:: Algorithm
+
+ 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br|
+ |rarr| :meth:`CreateDependencyGraph`
+ 2. Create the compile order graph. |br|
+ |rarr| :meth:`CreateCompileOrderGraph`
+ 3. Index all packages. |br|
+ |rarr| :meth:`IndexPackages`
+ 4. Index all architectures. |br|
+ |rarr| :meth:`IndexArchitectures`
+ 5. Link all contexts |br|
+ |rarr| :meth:`LinkContexts`
+ 6. Link all architectures. |br|
+ |rarr| :meth:`LinkArchitectures`
+ 7. Link all package bodies. |br|
+ |rarr| :meth:`LinkPackageBodies`
+ 8. Link all library references. |br|
+ |rarr| :meth:`LinkLibraryReferences`
+ 9. Link all package references. |br|
+ |rarr| :meth:`LinkPackageReferences`
+ 10. Link all context references. |br|
+ |rarr| :meth:`LinkContextReferences`
+ 11. Link all components. |br|
+ |rarr| :meth:`LinkComponents`
+ 12. Link all instantiations. |br|
+ |rarr| :meth:`LinkInstantiations`
+ 13. Create the hierarchy graph. |br|
+ |rarr| :meth:`CreateHierarchyGraph`
+ 14. Compute the compile order. |br|
+ |rarr| :meth:`ComputeCompileOrder`
+ """
+ self.CreateDependencyGraph()
+ self.CreateCompileOrderGraph()
+
+ self.IndexPackages()
+ self.IndexArchitectures()
+
+ self.LinkContexts()
+ self.LinkArchitectures()
+ self.LinkPackageBodies()
+ self.LinkLibraryReferences()
+ self.LinkPackageReferences()
+ self.LinkContextReferences()
+
+ self.LinkComponents()
+ self.LinkInstantiations()
+ self.CreateHierarchyGraph()
+ self.ComputeCompileOrder()
+
+ def AnalyzeObjects(self) -> None:
+ """
+ Analyze the dependencies of types and objects.
+
+ .. rubric:: Algorithm
+
+ 1. Index all entities. |br|
+ |rarr| :meth:`IndexEntities`
+ 2. Index all package bodies. |br|
+ |rarr| :meth:`IndexPackageBodies`
+ 3. Import objects. |br|
+ |rarr| :meth:`ImportObjects`
+ 4. Create the type and object graph. |br|
+ |rarr| :meth:`CreateTypeAndObjectGraph`
+ """
+ self.IndexEntities()
+ self.IndexPackageBodies()
+
+ self.ImportObjects()
+ self.CreateTypeAndObjectGraph()
+
+ def CreateDependencyGraph(self) -> None:
+ """
+ Create all vertices of the dependency graph by iterating all design units in all libraries.
+
+ This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br|
+ See :meth:`AnalyzeDependencies` for these methods and their algorithmic order.
+
+ Each vertex has the following properties:
+
+ * The vertex' ID is the design unit's identifier.
+ * The vertex' value references the design unit.
+ * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
+ * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all libraries in the design.
+
+ * Create a vertex for that library and reference the library by the vertex' value field. |br|
+ In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex.
+
+ 1. Iterate all contexts in that library.
+
+ * Create a vertex for that context and reference the context by the vertex' value field. |br|
+ In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex.
+
+ 2. Iterate all packages in that library.
+
+ * Create a vertex for that package and reference the package by the vertex' value field. |br|
+ In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex.
+
+ 3. Iterate all package bodies in that library.
+
+ * Create a vertex for that package body and reference the package body by the vertex' value field. |br|
+ In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex.
+
+ 4. Iterate all entities in that library.
+
+ * Create a vertex for that entity and reference the entity by the vertex' value field. |br|
+ In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex.
+
+ 5. Iterate all architectures in that library.
+
+ * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br|
+ In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex.
+
+ 6. Iterate all configurations in that library.
+
+ * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br|
+ In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex.
+ """
+ predefinedLibraries = ("std", "ieee")
+
+ for libraryIdentifier, library in self._libraries.items():
+ dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.Library
+ dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries
+ library._dependencyVertex = dependencyVertex
+
+ for contextIdentifier, context in library._contexts.items():
+ dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.Context
+ dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries
+ context._dependencyVertex = dependencyVertex
+
+ for packageIdentifier, package in library._packages.items():
+ dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.Package
+ dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries
+ package._dependencyVertex = dependencyVertex
+
+ for packageBodyIdentifier, packageBody in library._packageBodies.items():
+ dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody
+ dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries
+ packageBody._dependencyVertex = dependencyVertex
+
+ for entityIdentifier, entity in library._entities.items():
+ dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.Entity
+ dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries
+ entity._dependencyVertex = dependencyVertex
+
+ for entityIdentifier, architectures in library._architectures.items():
+ for architectureIdentifier, architecture in architectures.items():
+ dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture
+ dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries
+ architecture._dependencyVertex = dependencyVertex
+
+ for configurationIdentifier, configuration in library._configurations.items():
+ dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration
+ dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries
+ configuration._dependencyVertex = dependencyVertex
+
+ def CreateCompileOrderGraph(self) -> None:
+ """
+ Create a compile-order graph with bidirectional references to the dependency graph.
+
+ Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order
+ graph and bidirectionally referenced.
+
+ In addition, each vertex of a corresponding design unit in a document is linked to the vertex representing that document to express the design unit in
+ document relationship.
+
+ Each added vertex has the following properties:
+
+ * The vertex' ID is the document's filename.
+ * The vertex' value references the document.
+ * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
+ * A key-value-pair called ``predefined`` does not exist.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all documents in the design.
+
+ * Create a vertex for that document and reference the document by the vertex' value field. |br|
+ In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex.
+ * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br|
+ In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex.
+
+ * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex.
+ * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex.
+
+ 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding
+ dependency vertex. This expresses a "design unit is located in document" relation.
+
+ * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`.
+ """
+ for document in self._documents:
+ dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph)
+ dependencyVertex["kind"] = DependencyGraphVertexKind.Document
+ document._dependencyVertex = dependencyVertex
+
+ compilerOrderVertex = dependencyVertex.Copy(
+ self._compileOrderGraph,
+ copyDict=True,
+ linkingKeyToOriginalVertex="dependencyVertex",
+ linkingKeyFromOriginalVertex="compileOrderVertex"
+ )
+ document._compileOrderVertex = compilerOrderVertex
+
+ for designUnit in document._designUnits:
+ edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex)
+ edge["kind"] = DependencyGraphEdgeKind.SourceFile
+
+ def ImportObjects(self) -> None:
+ def _ImportObjects(package: Package) -> None:
+ for referencedLibrary in package._referencedPackages.values():
+ for referencedPackage in referencedLibrary.values():
+ for declaredItem in referencedPackage._declaredItems:
+ if isinstance(declaredItem, MultipleNamedEntityMixin):
+ for normalizedIdentifier in declaredItem._normalizedIdentifiers:
+ package._namespace._elements[normalizedIdentifier] = declaredItem
+ elif isinstance(declaredItem, NamedEntityMixin):
+ package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem
+ else:
+ raise VHDLModelException(f"Unexpected declared item.")
+
+ for libraryName in ("std", "ieee"):
+ for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
+ _ImportObjects(package)
+
+ for document in self.IterateDocumentsInCompileOrder():
+ for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
+ _ImportObjects(package)
+
+ def CreateTypeAndObjectGraph(self) -> None:
+ def _HandlePackage(package) -> None:
+ packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}"
+
+ for deferredConstant in package._deferredConstants.values():
+ print(f"Deferred Constant: {deferredConstant}")
+ deferredConstantVertex = Vertex(
+ vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}",
+ value=deferredConstant,
+ graph=self._objectGraph
+ )
+ deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant
+ deferredConstant._objectVertex = deferredConstantVertex
+
+ for constant in package._constants.values():
+ print(f"Constant: {constant}")
+ constantVertex = Vertex(
+ vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}",
+ value=constant,
+ graph=self._objectGraph
+ )
+ constantVertex["kind"] = ObjectGraphVertexKind.Constant
+ constant._objectVertex = constantVertex
+
+ for type in package._types.values():
+ print(f"Type: {type}")
+ typeVertex = Vertex(
+ vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}",
+ value=type,
+ graph=self._objectGraph
+ )
+ typeVertex["kind"] = ObjectGraphVertexKind.Type
+ type._objectVertex = typeVertex
+
+ for subtype in package._subtypes.values():
+ print(f"Subtype: {subtype}")
+ subtypeVertex = Vertex(
+ vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}",
+ value=subtype,
+ graph=self._objectGraph
+ )
+ subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype
+ subtype._objectVertex = subtypeVertex
+
+ for function in package._functions.values():
+ print(f"Function: {function}")
+ functionVertex = Vertex(
+ vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}",
+ value=function,
+ graph=self._objectGraph
+ )
+ functionVertex["kind"] = ObjectGraphVertexKind.Function
+ function._objectVertex = functionVertex
+
+ for procedure in package._procedures.values():
+ print(f"Procedure: {procedure}")
+ procedureVertex = Vertex(
+ vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}",
+ value=procedure,
+ graph=self._objectGraph
+ )
+ procedureVertex["kind"] = ObjectGraphVertexKind.Function
+ procedure._objectVertex = procedureVertex
+
+ for signal in package._signals.values():
+ print(f"Signal: {signal}")
+ signalVertex = Vertex(
+ vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}",
+ value=signal,
+ graph=self._objectGraph
+ )
+ signalVertex["kind"] = ObjectGraphVertexKind.Signal
+ signal._objectVertex = signalVertex
+
+ def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex):
+ if isinstance(expression, UnaryExpression):
+ _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex)
+ elif isinstance(expression, BinaryExpression):
+ _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex)
+ _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex)
+ elif isinstance(expression, TernaryExpression):
+ pass
+ elif isinstance(expression, SimpleObjectOrFunctionCallSymbol):
+ obj = namespace.FindObject(expression)
+ expression._reference = obj
+
+ edge = obj._objectVertex.EdgeToVertex(typeVertex)
+ edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression
+ else:
+ pass
+
+ def _LinkItems(package: Package):
+ for item in package._declaredItems:
+ if isinstance(item, Constant):
+ print(f"constant: {item}")
+ elif isinstance(item, DeferredConstant):
+ print(f"deferred constant: {item}")
+ elif isinstance(item, Signal):
+ print(f"signal: {item}")
+ elif isinstance(item, IntegerType):
+ typeNode = item._objectVertex
+
+ _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
+ _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
+ # elif isinstance(item, FloatingType):
+ # print(f"signal: {item}")
+ elif isinstance(item, PhysicalType):
+ typeNode = item._objectVertex
+
+ _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
+ _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
+ elif isinstance(item, ArrayType):
+ # Resolve dimensions
+ for dimension in item._dimensions:
+ subtype = package._namespace.FindSubtype(dimension)
+ dimension._reference = subtype
+
+ edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
+ edge["kind"] = ObjectGraphEdgeKind.Subtype
+
+ # Resolve element subtype
+ subtype = package._namespace.FindSubtype(item._elementType)
+ item._elementType._reference = subtype
+
+ edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
+ edge["kind"] = ObjectGraphEdgeKind.Subtype
+ elif isinstance(item, RecordType):
+ # Resolve each elements subtype
+ for element in item._elements:
+ subtype = package._namespace.FindSubtype(element._subtype)
+ element._subtype._reference = subtype
+
+ edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
+ edge["kind"] = ObjectGraphEdgeKind.Subtype
+ else:
+ print(f"not handled: {item}")
+
+ for libraryName in ("std", "ieee"):
+ for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
+ _HandlePackage(package)
+ _LinkItems(package)
+
+ for document in self.IterateDocumentsInCompileOrder():
+ for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
+ _HandlePackage(package)
+ _LinkItems(package)
+
+ def LinkContexts(self) -> None:
+ """
+ Resolves and links all items (library clauses, use clauses and nested context references) in contexts.
+
+ It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By
+ default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty
+ dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library.
+
+ At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each
+ referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in
+ :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the
+ dependency graph is added for that relationship.
+
+ At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each
+ referenced package,
+ """
+ for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context
+ # Create entries in _referenced*** for the current working library under its real name.
+ workingLibrary: Library = context.Library
+ libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier
+
+ context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier]
+ context._referencedPackages[libraryNormalizedIdentifier] = {}
+ context._referencedContexts[libraryNormalizedIdentifier] = {}
+
+ # Process all library clauses
+ for libraryReference in context._libraryReferences:
+ # A library clause can have multiple comma-separated references
+ for libraryName in libraryReference.Symbols:
+ libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier
+ try:
+ library = self._libraries[libraryNormalizedIdentifier]
+ except KeyError:
+ raise ReferencedLibraryNotExistingError(context, libraryName)
+ # TODO: add position to these messages
+
+ libraryName.Library = library
+
+ context._referencedLibraries[libraryNormalizedIdentifier] = library
+ context._referencedPackages[libraryNormalizedIdentifier] = {}
+ context._referencedContexts[libraryNormalizedIdentifier] = {}
+ # TODO: warn duplicate library reference
+
+ dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
+ dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
+
+ # Process all use clauses
+ for packageReference in context.PackageReferences:
+ # A use clause can have multiple comma-separated references
+ for symbol in packageReference.Symbols: # type: PackageReferenceSymbol
+ packageName = symbol.Name.Prefix
+ libraryName = packageName.Prefix
+
+ libraryNormalizedIdentifier = libraryName._normalizedIdentifier
+ packageNormalizedIdentifier = packageName._normalizedIdentifier
+
+ # In case work is used, resolve to the real library name.
+ if libraryNormalizedIdentifier == "work":
+ library: Library = context._parent
+ libraryNormalizedIdentifier = library._normalizedIdentifier
+ elif libraryNormalizedIdentifier not in context._referencedLibraries:
+ # TODO: This check doesn't trigger if it's the working library.
+ raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.")
+ else:
+ library = self._libraries[libraryNormalizedIdentifier]
+
+ try:
+ package = library._packages[packageNormalizedIdentifier]
+ except KeyError:
+ raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.")
+
+ symbol.Package = package
+
+ # TODO: warn duplicate package reference
+ context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package
+
+ dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
+ dependency["kind"] = DependencyGraphEdgeKind.UseClause
+
+ # TODO: update the namespace with visible members
+ if isinstance(symbol, AllPackageMembersReferenceSymbol):
+ pass
+
+ elif isinstance(symbol, PackageMemberReferenceSymbol):
+ raise NotImplementedError()
+ else:
+ raise VHDLModelException()
+
+ def LinkArchitectures(self) -> None:
+ """
+ Link all architectures to corresponding entities in all libraries.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all libraries:
+
+ 1. Iterate all architecture groups (grouped per entity symbol's name).
+ |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures`
+
+ * Check if entity symbol's name exists as an entity in this library.
+
+ 1. For each architecture in the same architecture group:
+
+ * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
+ * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
+ * Set parent namespace of architecture's namespace to the entitie's namespace.
+ * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
+
+ .. seealso::
+
+ :meth:`LinkPackageBodies`
+ Link all package bodies to corresponding packages in all libraries.
+ """
+ for library in self._libraries.values():
+ library.LinkArchitectures()
+
+ def LinkPackageBodies(self) -> None:
+ """
+ Link all package bodies to corresponding packages in all libraries.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all libraries:
+
+ 1. Iterate all package bodies.
+ |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies`
+
+ * Check if package body symbol's name exists as a package in this library.
+ * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
+ * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
+ * Set parent namespace of package body's namespace to the package's namespace.
+ * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
+
+ .. seealso::
+
+ :meth:`LinkArchitectures`
+ Link all architectures to corresponding entities in all libraries.
+ """
+ for library in self._libraries.values():
+ library.LinkPackageBodies()
+
+ def LinkLibraryReferences(self) -> None:
+ DEFAULT_LIBRARIES = ("std",)
+
+ for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
+ # All primary units supporting a context, have at least one library implicitly referenced
+ if isinstance(designUnit, PrimaryUnit):
+ for libraryIdentifier in DEFAULT_LIBRARIES:
+ referencedLibrary = self._libraries[libraryIdentifier]
+ designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
+ designUnit._referencedPackages[libraryIdentifier] = {}
+ designUnit._referencedContexts[libraryIdentifier] = {}
+ # TODO: catch KeyError on self._libraries[libName]
+ # TODO: warn duplicate library reference
+
+ dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
+ dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
+
+ workingLibrary: Library = designUnit.Library
+ libraryIdentifier = workingLibrary.NormalizedIdentifier
+ referencedLibrary = self._libraries[libraryIdentifier]
+
+
+ designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
+ designUnit._referencedPackages[libraryIdentifier] = {}
+ designUnit._referencedContexts[libraryIdentifier] = {}
+
+ dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
+ dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
+
+ # All secondary units inherit referenced libraries from their primary units.
+ else:
+ if isinstance(designUnit, Architecture):
+ referencedLibraries = designUnit.Entity.Entity._referencedLibraries
+ elif isinstance(designUnit, PackageBody):
+ referencedLibraries = designUnit.Package.Package._referencedLibraries
+ else:
+ raise VHDLModelException()
+
+ for libraryIdentifier, library in referencedLibraries.items():
+ designUnit._referencedLibraries[libraryIdentifier] = library
+
+ for libraryReference in designUnit._libraryReferences:
+ # A library clause can have multiple comma-separated references
+ for librarySymbol in libraryReference.Symbols:
+ libraryIdentifier = librarySymbol.Name.NormalizedIdentifier
+ try:
+ library = self._libraries[libraryIdentifier]
+ except KeyError:
+ ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.")
+ ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""")
+ raise ex
+
+ librarySymbol.Library = library
+ designUnit._referencedLibraries[libraryIdentifier] = library
+ designUnit._referencedPackages[libraryIdentifier] = {}
+ designUnit._referencedContexts[libraryIdentifier] = {}
+ # TODO: warn duplicate library reference
+
+ dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
+ dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
+
+ def LinkPackageReferences(self) -> None:
+ DEFAULT_PACKAGES = (
+ ("std", ("standard",)),
+ )
+
+ for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
+ # All primary units supporting a context, have at least one package implicitly referenced
+ if isinstance(designUnit, PrimaryUnit):
+ if designUnit.Library.NormalizedIdentifier != "std" and \
+ designUnit.NormalizedIdentifier != "standard":
+ for lib in DEFAULT_PACKAGES:
+ if lib[0] not in designUnit._referencedLibraries:
+ raise VHDLModelException()
+ for pack in lib[1]:
+ referencedPackage = self._libraries[lib[0]]._packages[pack]
+ designUnit._referencedPackages[lib[0]][pack] = referencedPackage
+ # TODO: catch KeyError on self._libraries[lib[0]]._packages[pack]
+ # TODO: warn duplicate package reference
+
+ dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex)
+ dependency["kind"] = DependencyGraphEdgeKind.UseClause
+
+ # All secondary units inherit referenced packages from their primary units.
+ else:
+ if isinstance(designUnit, Architecture):
+ referencedPackages = designUnit.Entity.Entity._referencedPackages
+ elif isinstance(designUnit, PackageBody):
+ referencedPackages = designUnit.Package.Package._referencedPackages
+ else:
+ raise VHDLModelException()
+
+ for packageIdentifier, package in referencedPackages.items():
+ designUnit._referencedPackages[packageIdentifier] = package
+
+ for packageReference in designUnit.PackageReferences:
+ # A use clause can have multiple comma-separated references
+ for packageMemberSymbol in packageReference.Symbols:
+ packageName = packageMemberSymbol.Name.Prefix
+ libraryName = packageName.Prefix
+
+ libraryIdentifier = libraryName.NormalizedIdentifier
+ packageIdentifier = packageName.NormalizedIdentifier
+
+ # In case work is used, resolve to the real library name.
+ if libraryIdentifier == "work":
+ library: Library = designUnit.Library
+ libraryIdentifier = library.NormalizedIdentifier
+ elif libraryIdentifier not in designUnit._referencedLibraries:
+ # TODO: This check doesn't trigger if it's the working library.
+ raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.")
+ else:
+ library = self._libraries[libraryIdentifier]
+
+ try:
+ package = library._packages[packageIdentifier]
+ except KeyError:
+ ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
+ ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.")
+ raise ex
+
+ packageMemberSymbol.Package = package
+
+ # TODO: warn duplicate package reference
+ designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
+
+ dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
+ dependency["kind"] = DependencyGraphEdgeKind.UseClause
+
+ # TODO: update the namespace with visible members
+ if isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol):
+ for componentIdentifier, component in package._components.items():
+ designUnit._namespace._elements[componentIdentifier] = component
+
+ elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol):
+ raise NotImplementedError()
+ else:
+ raise VHDLModelException()
+
+ def LinkContextReferences(self) -> None:
+ for designUnit in self.IterateDesignUnits():
+ for contextReference in designUnit._contextReferences:
+ # A context reference can have multiple comma-separated references
+ for contextSymbol in contextReference.Symbols:
+ libraryName = contextSymbol.Name.Prefix
+
+ libraryIdentifier = libraryName.NormalizedIdentifier
+ contextIdentifier = contextSymbol.Name.NormalizedIdentifier
+
+ # In case work is used, resolve to the real library name.
+ if libraryIdentifier == "work":
+ referencedLibrary = designUnit.Library
+ libraryIdentifier = referencedLibrary.NormalizedIdentifier
+ elif libraryIdentifier not in designUnit._referencedLibraries:
+ # TODO: This check doesn't trigger if it's the working library.
+ raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.")
+ else:
+ referencedLibrary = self._libraries[libraryIdentifier]
+
+ try:
+ referencedContext = referencedLibrary._contexts[contextIdentifier]
+ except KeyError:
+ raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.")
+
+ contextSymbol.Package = referencedContext
+
+ # TODO: warn duplicate referencedContext reference
+ designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext
+
+ dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference)
+ dependency["kind"] = DependencyGraphEdgeKind.ContextReference
+
+ for vertex in self._dependencyGraph.IterateTopologically():
+ if vertex["kind"] is DependencyGraphVertexKind.Context:
+ context: Context = vertex.Value
+ for designUnitVertex in vertex.IteratePredecessorVertices():
+ designUnit: DesignUnit = designUnitVertex.Value
+ for libraryIdentifier, library in context._referencedLibraries.items():
+ # if libraryIdentifier in designUnit._referencedLibraries:
+ # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
+
+ designUnit._referencedLibraries[libraryIdentifier] = library
+ designUnit._referencedPackages[libraryIdentifier] = {}
+
+ for libraryIdentifier, packages in context._referencedPackages.items():
+ for packageIdentifier, package in packages.items():
+ if packageIdentifier in designUnit._referencedPackages:
+ raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
+
+ designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
+
+ def LinkComponents(self) -> None:
+ for package in self.IterateDesignUnits(DesignUnitKind.Package): # type: Package
+ library = package._parent
+ for component in package._components.values():
+ try:
+ entity = library._entities[component.NormalizedIdentifier]
+ except KeyError:
+ print(f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.")
+
+ component.Entity = entity
+
+ # QUESTION: Add link in dependency graph as dashed line from component to entity?
+ # Currently, component has no _dependencyVertex field
+
+ def LinkInstantiations(self) -> None:
+ for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture
+ for instance in architecture.IterateInstantiations():
+ if isinstance(instance, EntityInstantiation):
+ libraryName = instance.Entity.Name.Prefix
+ libraryIdentifier = libraryName.Identifier
+ normalizedLibraryIdentifier = libraryName.NormalizedIdentifier
+ if normalizedLibraryIdentifier == "work":
+ libraryIdentifier = architecture.Library.Identifier
+ normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier
+ elif normalizedLibraryIdentifier not in architecture._referencedLibraries:
+ ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in architecture '{architecture!r}'.")
+ ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.")
+ raise ex
+
+ try:
+ library = self._libraries[normalizedLibraryIdentifier]
+ except KeyError:
+ ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.")
+ ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.")
+ raise ex
+
+ try:
+ entity = library._entities[instance.Entity.Name.NormalizedIdentifier]
+ except KeyError:
+ ex = VHDLModelException(f"Referenced entity '{instance.Entity.Name.Identifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Name.Prefix.Identifier}.{instance.Entity.Name.Identifier}' not found in {'working ' if instance.Entity.Name.Prefix.NormalizedIdentifier == 'work' else ''}library '{libraryIdentifier}'.")
+ libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier]
+ if libs:
+ ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}")
+ raise ex
+
+ instance.Entity.Entity = entity
+
+ dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance)
+ dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation
+
+ elif isinstance(instance, ComponentInstantiation):
+ component = architecture._namespace.FindComponent(instance.Component)
+
+ instance.Component.Component = component
+
+ dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance)
+ dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation
+
+ elif isinstance(instance, ConfigurationInstantiation):
+ # pass
+ print(instance.Label, instance.Configuration)
+
+ def IndexPackages(self) -> None:
+ """
+ Index all declared items in all packages in all libraries.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all libraries:
+
+ 1. Iterate all packages |br|
+ |rarr| :meth:`pyVHDLModel.Library.IndexPackages`
+
+ * Index all declared items in that package. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackageBodies`
+ Index all declared items in all package bodies in all libraries.
+ :meth:`IndexEntities`
+ Index all declared items in all entities in all libraries.
+ :meth:`IndexArchitectures`
+ Index all declared items in all architectures in all libraries.
+ """
+ for library in self._libraries.values():
+ library.IndexPackages()
+
+ def IndexPackageBodies(self) -> None:
+ """
+ Index all declared items in all packages in all libraries.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all libraries:
+
+ 1. Iterate all packages |br|
+ |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies`
+
+ * Index all declared items in that package body. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackages`
+ Index all declared items in all packages in all libraries.
+ :meth:`IndexEntities`
+ Index all declared items in all entities in all libraries.
+ :meth:`IndexArchitectures`
+ Index all declared items in all architectures in all libraries.
+ """
+ for library in self._libraries.values():
+ library.IndexPackageBodies()
+
+ def IndexEntities(self) -> None:
+ """
+ Index all declared items in all packages in all libraries.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all libraries:
+
+ 1. Iterate all packages |br|
+ |rarr| :meth:`pyVHDLModel.Library.IndexEntities`
+
+ * Index all declared items in that entity. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackages`
+ Index all declared items in all packages in all libraries.
+ :meth:`IndexPackageBodies`
+ Index all declared items in all package bodies in all libraries.
+ :meth:`IndexArchitectures`
+ Index all declared items in all architectures in all libraries.
+ """
+ for library in self._libraries.values():
+ library.IndexEntities()
+
+ def IndexArchitectures(self) -> None:
+ """
+ Index all declared items in all packages in all libraries.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all libraries:
+
+ 1. Iterate all packages |br|
+ |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures`
+
+ * Index all declared items in that architecture. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackages`
+ Index all declared items in all packages in all libraries.
+ :meth:`IndexPackageBodies`
+ Index all declared items in all package bodies in all libraries.
+ :meth:`IndexEntities`
+ Index all declared items in all entities in all libraries.
+ """
+ for library in self._libraries.values():
+ library.IndexArchitectures()
+
+ def CreateHierarchyGraph(self) -> None:
+ """
+ Create the hierarchy graph from dependency graph.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all vertices corresponding to entities and architectures in the dependency graph:
+
+ * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br|
+ In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex.
+
+ * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex.
+ * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex.
+
+ 2. Iterate all architectures ...
+
+ .. todo:: Design::CreateHierarchyGraph describe algorithm
+
+ 1. Iterate all outbound edges
+
+ .. todo:: Design::CreateHierarchyGraph describe algorithm
+ """
+ # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them
+ entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture
+ for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter):
+ hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex")
+ vertex.Value._hierarchyVertex = hierarchyVertex
+
+ # Copy implementation edges from
+ for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture):
+ for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges():
+ kind: DependencyGraphEdgeKind = dependencyEdge["kind"]
+ if DependencyGraphEdgeKind.Implementation in kind:
+ hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
+ newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex)
+ elif DependencyGraphEdgeKind.Instantiation in kind:
+ hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
+
+ # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks)
+ if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex):
+ continue
+
+ newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex)
+ else:
+ continue
+
+ newEdge["kind"] = kind
+
+ def ComputeCompileOrder(self) -> None:
+ def predicate(edge: Edge) -> bool:
+ return (
+ DependencyGraphEdgeKind.Implementation in edge["kind"] or
+ DependencyGraphEdgeKind.Instantiation in edge["kind"] or
+ DependencyGraphEdgeKind.UseClause in edge["kind"] or
+ DependencyGraphEdgeKind.ContextReference in edge["kind"]
+ ) and edge.Destination["predefined"] is False
+
+ for edge in self._dependencyGraph.IterateEdges(predicate=predicate):
+ sourceDocument: Document = edge.Source.Value.Document
+ destinationDocument: Document = edge.Destination.Value.Document
+
+ sourceVertex = sourceDocument._compileOrderVertex
+ destinationVertex = destinationDocument._compileOrderVertex
+
+ # Don't add self-edges
+ if sourceVertex is destinationVertex:
+ continue
+ # Don't add parallel edges
+ elif sourceVertex.HasEdgeToDestination(destinationVertex):
+ continue
+
+ e = sourceVertex.EdgeToVertex(destinationVertex)
+ e["kind"] = DependencyGraphEdgeKind.CompileOrder
+
+ e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"])
+ e["kind"] = DependencyGraphEdgeKind.CompileOrder
+
+ def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]:
+ """
+ Iterate all document in compile-order.
+
+ .. rubric:: Algorithm
+
+ * Check if compile-order graph was populated with vertices and its vertices are linked by edges.
+
+ 1. Iterate compile-order graph in topological order. |br|
+ :meth:`pyTooling.Graph.Graph.IterateTopologically`
+
+ * yield the compiler-order vertex' referenced document.
+
+ :returns: A generator to iterate all documents in compile-order in the design.
+ :raises VHDLModelException: If compile-order was not computed.
+
+ .. seealso::
+
+ .. todo:: missing text
+
+ :meth:`pyVHDLModel.Design.ComputeCompileOrder`
+
+ """
+ if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1:
+ raise VHDLModelException(f"Compile order is not yet computed from dependency graph.")
+
+ for compileOrderNode in self._compileOrderGraph.IterateTopologically():
+ yield compileOrderNode.Value
+
+ def GetUnusedDesignUnits(self) -> List[DesignUnit]:
+ raise NotImplementedError()
+
+ def __repr__(self) -> str:
+ """
+ Formats a representation of the design.
+
+ **Format:** ``Document: 'my_design'``
+
+ :returns: String representation of the design.
+ """
+ return f"Design: {self._name}"
+
+ __str__ = __repr__
+
+
+@export
+class Library(ModelEntity, NamedEntityMixin):
+ """A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units."""
+
+ _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library.
+ _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library.
+ _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library.
+ _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library.
+ _packages: Dict[str, Package] #: Dictionary of all packages defined in a library.
+ _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library.
+
+ _dependencyVertex: Vertex[None, None, str, Union['Library', DesignUnit], None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the dependency graph representing the library. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateDependencyGraph`.
+
+ def __init__(self, identifier: str, parent: ModelEntity = None) -> None:
+ super().__init__(parent)
+ NamedEntityMixin.__init__(self, identifier)
+
+ self._contexts = {}
+ self._configurations = {}
+ self._entities = {}
+ self._architectures = {}
+ self._packages = {}
+ self._packageBodies = {}
+
+ self._dependencyVertex = None
+
+ @readonly
+ def Contexts(self) -> Dict[str, Context]:
+ """Returns a list of all context declarations declared in this library."""
+ return self._contexts
+
+ @readonly
+ def Configurations(self) -> Dict[str, Configuration]:
+ """Returns a list of all configuration declarations declared in this library."""
+ return self._configurations
+
+ @readonly
+ def Entities(self) -> Dict[str, Entity]:
+ """Returns a list of all entity declarations declared in this library."""
+ return self._entities
+
+ @readonly
+ def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
+ """Returns a list of all architectures declarations declared in this library."""
+ return self._architectures
+
+ @readonly
+ def Packages(self) -> Dict[str, Package]:
+ """Returns a list of all package declarations declared in this library."""
+ return self._packages
+
+ @readonly
+ def PackageBodies(self) -> Dict[str, PackageBody]:
+ """Returns a list of all package body declarations declared in this library."""
+ return self._packageBodies
+
+ @readonly
+ def DependencyVertex(self) -> Vertex:
+ """
+ Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`).
+
+ The dependency vertex references this library by its value field.
+
+ :returns: The corresponding dependency vertex.
+ """
+ return self._dependencyVertex
+
+ def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
+ """
+ Iterate all design units in the library.
+
+ A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all contexts in that library.
+ 2. Iterate all packages in that library.
+ 3. Iterate all package bodies in that library.
+ 4. Iterate all entites in that library.
+ 5. Iterate all architectures in that library.
+ 6. Iterate all configurations in that library.
+
+ :param filter: An enumeration with possibly multiple flags to filter the returned design units.
+ :returns: A generator to iterate all matched design units in the library.
+
+ .. seealso::
+
+ :meth:`pyVHDLModel.Design.IterateDesignUnits`
+ Iterate all design units in the design.
+ :meth:`pyVHDLModel.Document.IterateDesignUnits`
+ Iterate all design units in the document.
+ """
+ if DesignUnitKind.Context in filter:
+ for context in self._contexts.values():
+ yield context
+
+ if DesignUnitKind.Package in filter:
+ for package in self._packages.values():
+ yield package
+
+ if DesignUnitKind.PackageBody in filter:
+ for packageBody in self._packageBodies.values():
+ yield packageBody
+
+ if DesignUnitKind.Entity in filter:
+ for entity in self._entities.values():
+ yield entity
+
+ if DesignUnitKind.Architecture in filter:
+ for architectures in self._architectures.values():
+ for architecture in architectures.values():
+ yield architecture
+
+ if DesignUnitKind.Configuration in filter:
+ for configuration in self._configurations.values():
+ yield configuration
+
+ # for verificationProperty in self._verificationUnits.values():
+ # yield verificationProperty
+ # for verificationUnit in self._verificationProperties.values():
+ # yield entity
+ # for verificationMode in self._verificationModes.values():
+ # yield verificationMode
+
+ def LinkArchitectures(self) -> None:
+ """
+ Link all architectures to corresponding entities.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all architecture groups (grouped per entity symbol's name).
+
+ * Check if entity symbol's name exists as an entity in this library.
+
+ 1. For each architecture in the same architecture group:
+
+ * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
+ * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
+ * Set parent namespace of architecture's namespace to the entitie's namespace.
+ * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
+
+ :raises VHDLModelException: If entity name doesn't exist.
+ :raises VHDLModelException: If architecture name already exists for entity.
+
+ .. seealso::
+
+ :meth:`LinkPackageBodies`
+ Link all package bodies to corresponding packages.
+ """
+ for entityName, architecturesPerEntity in self._architectures.items():
+ if entityName not in self._entities:
+ architectureNames = "', '".join(architecturesPerEntity.keys())
+ raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.")
+ # TODO: search in other libraries to find that entity.
+ # TODO: add code position
+
+ entity = self._entities[entityName]
+ for architecture in architecturesPerEntity.values():
+ if architecture._normalizedIdentifier in entity._architectures:
+ raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.")
+ # TODO: add code position of existing and current
+
+ entity._architectures[architecture._normalizedIdentifier] = architecture
+ architecture._entity.Entity = entity
+ architecture._namespace._parentNamespace = entity._namespace
+
+ # add "architecture -> entity" relation in dependency graph
+ dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex)
+ dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation
+
+ def LinkPackageBodies(self) -> None:
+ """
+ Link all package bodies to corresponding packages.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all package bodies.
+
+ * Check if package body symbol's name exists as a package in this library.
+ * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
+ * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
+ * Set parent namespace of package body's namespace to the package's namespace.
+ * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
+
+ :raises VHDLModelException: If package name doesn't exist.
+
+ .. seealso::
+
+ :meth:`LinkArchitectures`
+ Link all architectures to corresponding entities.
+ """
+ for packageBodyName, packageBody in self._packageBodies.items():
+ if packageBodyName not in self._packages:
+ raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.")
+
+ package = self._packages[packageBodyName]
+ package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced
+ packageBody._package.Package = package
+ packageBody._namespace._parentNamespace = package._namespace
+
+ # add "package body -> package" relation in dependency graph
+ dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex)
+ dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation
+
+ def IndexPackages(self) -> None:
+ """
+ Index declared items in all packages.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all packages:
+
+ * Index all declared items. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackageBodies`
+ Index all declared items in a package body.
+ :meth:`IndexEntities`
+ Index all declared items in an entity.
+ :meth:`IndexArchitectures`
+ Index all declared items in an architecture.
+ """
+ for package in self._packages.values():
+ if isinstance(package, Package):
+ package.IndexDeclaredItems()
+
+ def IndexPackageBodies(self) -> None:
+ """
+ Index declared items in all package bodies.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all package bodies:
+
+ * Index all declared items. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackages`
+ Index all declared items in a package.
+ :meth:`IndexEntities`
+ Index all declared items in an entity.
+ :meth:`IndexArchitectures`
+ Index all declared items in an architecture.
+ """
+ for packageBody in self._packageBodies.values():
+ packageBody.IndexDeclaredItems()
+
+ def IndexEntities(self) -> None:
+ """
+ Index declared items in all entities.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all entities:
+
+ * Index all declared items. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackages`
+ Index all declared items in a package.
+ :meth:`IndexPackageBodies`
+ Index all declared items in a package body.
+ :meth:`IndexArchitectures`
+ Index all declared items in an architecture.
+ """
+ for entity in self._entities.values():
+ entity.IndexDeclaredItems()
+
+ def IndexArchitectures(self) -> None:
+ """
+ Index declared items in all architectures.
+
+ .. rubric:: Algorithm
+
+ 1. Iterate all architectures:
+
+ * Index all declared items. |br|
+ |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
+
+ .. seealso::
+
+ :meth:`IndexPackages`
+ Index all declared items in a package.
+ :meth:`IndexPackageBodies`
+ Index all declared items in a package body.
+ :meth:`IndexEntities`
+ Index all declared items in an entity.
+ """
+ for architectures in self._architectures.values():
+ for architecture in architectures.values():
+ architecture.IndexDeclaredItems()
+ architecture.IndexStatements()
+
+ def __repr__(self) -> str:
+ """
+ Formats a representation of the library.
+
+ **Format:** ``Library: 'my_library'``
+
+ :returns: String representation of the library.
+ """
+ return f"Library: '{self._identifier}'"
+
+ __str__ = __repr__
+
+
+@export
+class Document(ModelEntity, DocumentedEntityMixin):
+ """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units."""
+
+ _path: Path #: path to the document. ``None`` if virtual document.
+ _designUnits: List[DesignUnit] #: List of all design units defined in a document.
+ _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document.
+ _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document.
+ _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document.
+ _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document.
+ _packages: Dict[str, Package] #: Dictionary of all packages defined in a document.
+ _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document.
+ _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document.
+ _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document.
+ _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document.
+
+ _dependencyVertex: Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the dependency graph representing the document. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateCompileOrderGraph`.
+ _compileOrderVertex: Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the compile-order graph representing the document. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateCompileOrderGraph`.
+
+ def __init__(self, path: Path, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None:
+ super().__init__(parent)
+ DocumentedEntityMixin.__init__(self, documentation)
+
+ self._path = path
+ self._designUnits = []
+ self._contexts = {}
+ self._configurations = {}
+ self._entities = {}
+ self._architectures = {}
+ self._packages = {}
+ self._packageBodies = {}
+ self._verificationUnits = {}
+ self._verificationProperties = {}
+ self._verificationModes = {}
+
+ self._dependencyVertex = None
+ self._compileOrderVertex = None
+
+ def _AddEntity(self, item: Entity) -> None:
+ """
+ Add an entity to the document's lists of design units.
+
+ :param item: Entity object to be added to the document.
+ :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Entity`.
+ :raises VHDLModelException: If entity name already exists in document.
+ """
+ if not isinstance(item, Entity):
+ ex = TypeError(f"Parameter 'item' is not of type 'Entity'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item._normalizedIdentifier
+ if identifier in self._entities:
+ # TODO: use a more specific exception
+ raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.")
+
+ self._entities[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddArchitecture(self, item: Architecture) -> None:
+ """
+ Add an architecture to the document's lists of design units.
+
+ :param item: Architecture object to be added to the document.
+ :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Architecture`.
+ :raises VHDLModelException: If architecture name already exists for the referenced entity name in document.
+ """
+ if not isinstance(item, Architecture):
+ ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ entity = item._entity.Name
+ entityIdentifier = entity._normalizedIdentifier
+ try:
+ architectures = self._architectures[entityIdentifier]
+ if item._normalizedIdentifier in architectures:
+ # TODO: use a more specific exception
+ # FIXME: this is allowed and should be a warning or a strict mode.
+ raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.")
+
+ architectures[item.Identifier] = item
+ except KeyError:
+ self._architectures[entityIdentifier] = {item._identifier: item}
+
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddPackage(self, item: Package) -> None:
+ """
+ Add a package to the document's lists of design units.
+
+ :param item: Package object to be added to the document.
+ :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Package`.
+ :raises VHDLModelException: If package name already exists in document.
+ """
+ if not isinstance(item, (Package, PackageInstantiation)):
+ ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item._normalizedIdentifier
+ if identifier in self._packages:
+ # TODO: use a more specific exception
+ raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.")
+
+ self._packages[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddPackageBody(self, item: PackageBody) -> None:
+ """
+ Add a package body to the document's lists of design units.
+
+ :param item: Package body object to be added to the document.
+ :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.PackageBody`.
+ :raises VHDLModelException: If package body name already exists in document.
+ """
+ if not isinstance(item, PackageBody):
+ ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item._normalizedIdentifier
+ if identifier in self._packageBodies:
+ # TODO: use a more specific exception
+ raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.")
+
+ self._packageBodies[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddContext(self, item: Context) -> None:
+ """
+ Add a context to the document's lists of design units.
+
+ :param item: Context object to be added to the document.
+ :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Context`.
+ :raises VHDLModelException: If context name already exists in document.
+ """
+ if not isinstance(item, Context):
+ ex = TypeError(f"Parameter 'item' is not of type 'Context'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item._normalizedIdentifier
+ if identifier in self._contexts:
+ # TODO: use a more specific exception
+ raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.")
+
+ self._contexts[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddConfiguration(self, item: Configuration) -> None:
+ """
+ Add a configuration to the document's lists of design units.
+
+ :param item: Configuration object to be added to the document.
+ :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Configuration`.
+ :raises VHDLModelException: If configuration name already exists in document.
+ """
+ if not isinstance(item, Configuration):
+ ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item._normalizedIdentifier
+ if identifier in self._configurations:
+ # TODO: use a more specific exception
+ raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.")
+
+ self._configurations[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddVerificationUnit(self, item: VerificationUnit) -> None:
+ if not isinstance(item, VerificationUnit):
+ ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item._normalizedIdentifier
+ if identifier in self._verificationUnits:
+ raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.")
+
+ self._verificationUnits[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddVerificationProperty(self, item: VerificationProperty) -> None:
+ if not isinstance(item, VerificationProperty):
+ ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item.NormalizedIdentifier
+ if identifier in self._verificationProperties:
+ raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.")
+
+ self._verificationProperties[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddVerificationMode(self, item: VerificationMode) -> None:
+ if not isinstance(item, VerificationMode):
+ ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ identifier = item.NormalizedIdentifier
+ if identifier in self._verificationModes:
+ raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.")
+
+ self._verificationModes[identifier] = item
+ self._designUnits.append(item)
+ item._document = self
+
+ def _AddDesignUnit(self, item: DesignUnit) -> None:
+ """
+ Add a design unit to the document's lists of design units.
+
+ :param item: Configuration object to be added to the document.
+ :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
+ :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
+ :raises VHDLModelException: If configuration name already exists in document.
+ """
+ if not isinstance(item, DesignUnit):
+ ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ if isinstance(item, Entity):
+ self._AddEntity(item)
+ elif isinstance(item, Architecture):
+ self._AddArchitecture(item)
+ elif isinstance(item, Package):
+ self._AddPackage(item)
+ elif isinstance(item, PackageBody):
+ self._AddPackageBody(item)
+ elif isinstance(item, Context):
+ self._AddContext(item)
+ elif isinstance(item, Configuration):
+ self._AddConfiguration(item)
+ elif isinstance(item, VerificationUnit):
+ self._AddVerificationUnit(item)
+ elif isinstance(item, VerificationProperty):
+ self._AddVerificationProperty(item)
+ elif isinstance(item, VerificationMode):
+ self._AddVerificationMode(item)
+ else:
+ ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.")
+ if version_info >= (3, 11): # pragma: no cover
+ ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
+ raise ex
+
+ @readonly
+ def Path(self) -> Path:
+ """
+ Read-only property to access the document's path (:attr:`_path`).
+
+ :returns: The path of this document.
+ """
+ return self._path
+
+ @readonly
+ def DesignUnits(self) -> List[DesignUnit]:
+ """
+ Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`).
+
+ :returns: List of all design units.
+ """
+ return self._designUnits
+
+ @readonly
+ def Contexts(self) -> Dict[str, Context]:
+ """
+ Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`).
+
+ :returns: List of all contexts.
+ """
+ return self._contexts
+
+ @readonly
+ def Configurations(self) -> Dict[str, Configuration]:
+ """
+ Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`).
+
+ :returns: List of all configurations.
+ """
+ return self._configurations
+
+ @readonly
+ def Entities(self) -> Dict[str, Entity]:
+ """
+ Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`).
+
+ :returns: List of all entities.
+ """
+ return self._entities
+
+ @readonly
+ def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
+ """
+ Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`).
+
+ :returns: List of all architectures.
+ """
+ return self._architectures
+
+ @readonly
+ def Packages(self) -> Dict[str, Package]:
+ """
+ Read-only property to access a list of all package declarations found in this document (:attr:`_packages`).
+
+ :returns: List of all packages.
+ """
+ return self._packages
+
+ @readonly
+ def PackageBodies(self) -> Dict[str, PackageBody]:
+ """
+ Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`).
+
+ :returns: List of all package bodies.
+ """
+ return self._packageBodies
+
+ @readonly
+ def VerificationUnits(self) -> Dict[str, VerificationUnit]:
+ """
+ Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`).
+
+ :returns: List of all verification units.
+ """
+ return self._verificationUnits
+
+ @readonly
+ def VerificationProperties(self) -> Dict[str, VerificationProperty]:
+ """
+ Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`).
+
+ :returns: List of all verification properties.
+ """
+ return self._verificationProperties
+
+ @readonly
+ def VerificationModes(self) -> Dict[str, VerificationMode]:
+ """
+ Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`).
+
+ :returns: List of all verification modes.
+ """
+ return self._verificationModes
+
+ @readonly
+ def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]:
+ """
+ Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`).
+
+ The compile-order vertex references this document by its value field.
+
+ :returns: The corresponding compile-order vertex.
+ """
+ return self._compileOrderVertex
+
+ def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
+ """
+ Iterate all design units in the document.
+
+ A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
+
+ .. rubric:: Algorithm
+
+ * If contexts are selected in the filter:
+
+ 1. Iterate all contexts in that library.
+
+ * If packages are selected in the filter:
+
+ 1. Iterate all packages in that library.
+
+ * If package bodies are selected in the filter:
+
+ 1. Iterate all package bodies in that library.
+
+ * If entites are selected in the filter:
+
+ 1. Iterate all entites in that library.
+
+ * If architectures are selected in the filter:
+
+ 1. Iterate all architectures in that library.
+
+ * If configurations are selected in the filter:
+
+ 1. Iterate all configurations in that library.
+
+ :param filter: An enumeration with possibly multiple flags to filter the returned design units.
+ :returns: A generator to iterate all matched design units in the document.
+
+ .. seealso::
+
+ :meth:`pyVHDLModel.Design.IterateDesignUnits`
+ Iterate all design units in the design.
+ :meth:`pyVHDLModel.Library.IterateDesignUnits`
+ Iterate all design units in the library.
+ """
+ if DesignUnitKind.Context in filter:
+ for context in self._contexts.values():
+ yield context
+
+ if DesignUnitKind.Package in filter:
+ for package in self._packages.values():
+ yield package
+
+ if DesignUnitKind.PackageBody in filter:
+ for packageBody in self._packageBodies.values():
+ yield packageBody
+
+ if DesignUnitKind.Entity in filter:
+ for entity in self._entities.values():
+ yield entity
+
+ if DesignUnitKind.Architecture in filter:
+ for architectures in self._architectures.values():
+ for architecture in architectures.values():
+ yield architecture
+
+ if DesignUnitKind.Configuration in filter:
+ for configuration in self._configurations.values():
+ yield configuration
+
+ # for verificationProperty in self._verificationUnits.values():
+ # yield verificationProperty
+ # for verificationUnit in self._verificationProperties.values():
+ # yield entity
+ # for verificationMode in self._verificationModes.values():
+ # yield verificationMode
+
+ def __repr__(self) -> str:
+ """
+ Formats a representation of the document.
+
+ **Format:** ``Document: 'path/to/file.vhdl'``
+
+ :returns: String representation of the document.
+ """
+ return f"Document: '{self._path}'"
+
+ __str__ = __repr__
+ |
+