Coverage for pyVHDLModel/__init__.py: 63%

1155 statements  

« prev     ^ index     » next       coverage.py v7.15.1, created at 2026-07-13 17:58 +0000

1# ==================================================================================================================== # 

2# __ ___ _ ____ _ __ __ _ _ # 

3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | # 

4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | # 

5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | # 

6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| # 

7# |_| |___/ # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany # 

15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany # 

16# # 

17# Licensed under the Apache License, Version 2.0 (the "License"); # 

18# you may not use this file except in compliance with the License. # 

19# You may obtain a copy of the License at # 

20# # 

21# http://www.apache.org/licenses/LICENSE-2.0 # 

22# # 

23# Unless required by applicable law or agreed to in writing, software # 

24# distributed under the License is distributed on an "AS IS" BASIS, # 

25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

26# See the License for the specific language governing permissions and # 

27# limitations under the License. # 

28# # 

29# SPDX-License-Identifier: Apache-2.0 # 

30# ==================================================================================================================== # 

31# 

32""" 

33**An abstract VHDL language model.** 

34 

35This package provides a unified abstract language model for VHDL. Projects reading from source files can derive own 

36classes and implement additional logic to create a concrete language model for their tools. 

37 

38Projects consuming pre-processed VHDL data (parsed, analyzed or elaborated) can build higher level features and services 

39on such a model, while supporting multiple frontends. 

40 

41.. admonition:: Copyright Information 

42 

43 :copyright: Copyright 2017-2026 Patrick Lehmann - Bötzingen, Germany 

44 :copyright: Copyright 2016-2017 Patrick Lehmann - Dresden, Germany 

45 :license: Apache License, Version 2.0 

46""" 

47__author__ = "Patrick Lehmann" 

48__email__ = "Paebbels@gmail.com" 

49__copyright__ = "2016-2026, Patrick Lehmann" 

50__license__ = "Apache License, Version 2.0" 

51__version__ = "0.37.0" 

52# __keywords__ = [] 

53__project_url__ = "https://github.com/VHDL/pyVHDLModel" 

54__documentation_url__ = "https://vhdl.github.io/pyVHDLModel" 

55__issue_tracker_url__ = "https://GitHub.com/VHDL/pyVHDLModel/issues" 

56 

57 

58from enum import unique, Enum, Flag, auto 

59from pathlib import Path 

60from sys import version_info 

61 

62from typing import Union, Dict, cast, List, Generator, Optional as Nullable 

63 

64from pyTooling.Common import getFullyQualifiedName 

65from pyTooling.Decorators import export, readonly 

66from pyTooling.Graph import Graph, Vertex, Edge 

67from pyTooling.Warning import WarningCollector 

68 

69from pyVHDLModel.Exception import VHDLModelException, NotImplementedWarning, BlackboxWarning 

70from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError 

71from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError 

72from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError 

73from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin 

74from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression 

75from pyVHDLModel.Namespace import Namespace 

76from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant 

77from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol 

78from pyVHDLModel.Common import AllowBlackboxMixin 

79from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin 

80from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation 

81from pyVHDLModel.Concurrent import GenerateStatement, IfGenerateStatement, ForGenerateStatement, CaseGenerateStatement 

82from pyVHDLModel.Concurrent import GenerateBranch, ConcurrentStatementsMixin, ConcurrentBlockStatement 

83from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package, Component 

84from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode 

85from pyVHDLModel.Instantiation import PackageInstantiation 

86from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType 

87 

88 

89@export 

90@unique 

91class VHDLVersion(Enum): 

92 """ 

93 An enumeration for all possible version numbers for VHDL and VHDL-AMS. 

94 

95 A version can be given as integer or string and is represented as a unified 

96 enumeration value. 

97 

98 This enumeration supports compare operators. 

99 """ 

100 

101 Any = -1 #: Any 

102 VHDL87 = 87 #: VHDL-1987 

103 VHDL93 = 93 #: VHDL-1993 

104 AMS93 = 1993 #: VHDL-AMS-1993 

105 AMS99 = 1999 #: VHDL-AMS-1999 

106 VHDL2000 = 2000 #: VHDL-2000 

107 VHDL2002 = 2002 #: VHDL-2002 

108 VHDL2008 = 2008 #: VHDL-2008 

109 AMS2017 = 2017 #: VHDL-AMS-2017 

110 VHDL2019 = 2019 #: VHDL-2019 

111 Latest = 10000 #: Latest VHDL (2019) 

112 

113 __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = { 

114 -1: Any, 

115 87: VHDL87, 

116 93: VHDL93, 

117 # 93: AMS93, 

118 99: AMS99, 

119 0: VHDL2000, 

120 2: VHDL2002, 

121 8: VHDL2008, 

122 17: AMS2017, 

123 19: VHDL2019, 

124 1987: VHDL87, 

125 # 1993: VHDL93, 

126 1993: AMS93, 

127 1999: AMS99, 

128 2000: VHDL2000, 

129 2002: VHDL2002, 

130 2008: VHDL2008, 

131 2017: AMS2017, 

132 2019: VHDL2019, 

133 10000: Latest, 

134 "Any": Any, 

135 "87": VHDL87, 

136 "93": VHDL93, 

137 # "93": AMS93, 

138 "99": AMS99, 

139 "00": VHDL2000, 

140 "02": VHDL2002, 

141 "08": VHDL2008, 

142 "17": AMS2017, 

143 "19": VHDL2019, 

144 "1987": VHDL87, 

145 # "1993": VHDL93, 

146 "1993": AMS93, 

147 "1999": AMS99, 

148 "2000": VHDL2000, 

149 "2002": VHDL2002, 

150 "2008": VHDL2008, 

151 "2017": AMS2017, 

152 "2019": VHDL2019, 

153 "Latest": Latest, 

154 } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values. 

155 

156 def __init__(self, *_) -> None: 

157 """Patch the embedded MAP dictionary""" 

158 for k, v in self.__class__.__VERSION_MAPPINGS__.items(): 

159 if (not isinstance(v, self.__class__)) and (v == self.value): 

160 self.__class__.__VERSION_MAPPINGS__[k] = self 

161 

162 @classmethod 

163 def Parse(cls, value: Union[int, str]) -> "VHDLVersion": 

164 """ 

165 Parses a VHDL or VHDL-AMS year code as integer or string to an enum value. 

166 

167 :param value: VHDL/VHDL-AMS year code. 

168 :returns: Enumeration value. 

169 :raises ValueError: If the year code is not recognized. 

170 """ 

171 try: 

172 return cls.__VERSION_MAPPINGS__[value] 

173 except KeyError: 

174 raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.") 

175 

176 def __lt__(self, other: Any) -> bool: 

177 """ 

178 Compare two VHDL/VHDL-AMS versions if the version is less than the second operand. 

179 

180 :param other: Parameter to compare against. 

181 :returns: True if version is less than the second operand. 

182 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`. 

183 """ 

184 if isinstance(other, VHDLVersion): 

185 return self.value < other.value 

186 else: 

187 raise TypeError("Second operand is not of type 'VHDLVersion'.") 

188 

189 def __le__(self, other: Any) -> bool: 

190 """ 

191 Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand. 

192 

193 :param other: Parameter to compare against. 

194 :returns: True if version is less or equal than the second operand. 

195 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`. 

196 """ 

197 if isinstance(other, VHDLVersion): 

198 return self.value <= other.value 

199 else: 

200 raise TypeError("Second operand is not of type 'VHDLVersion'.") 

201 

202 def __gt__(self, other: Any) -> bool: 

203 """ 

204 Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand. 

205 

206 :param other: Parameter to compare against. 

207 :returns: True if version is greater than the second operand. 

208 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`. 

209 """ 

210 if isinstance(other, VHDLVersion): 

211 return self.value > other.value 

212 else: 

213 raise TypeError("Second operand is not of type 'VHDLVersion'.") 

214 

215 def __ge__(self, other: Any) -> bool: 

216 """ 

217 Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand. 

218 

219 :param other: Parameter to compare against. 

220 :returns: True if version is greater or equal than the second operand. 

221 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`. 

222 """ 

223 if isinstance(other, VHDLVersion): 

224 return self.value >= other.value 

225 else: 

226 raise TypeError("Second operand is not of type 'VHDLVersion'.") 

227 

228 def __ne__(self, other: Any) -> bool: 

229 """ 

230 Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand. 

231 

232 :param other: Parameter to compare against. 

233 :returns: True if version is unequal to the second operand. 

234 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`. 

235 """ 

236 if isinstance(other, VHDLVersion): 

237 return self.value != other.value 

238 else: 

239 raise TypeError("Second operand is not of type 'VHDLVersion'.") 

240 

241 def __eq__(self, other: Any) -> bool: 

242 """ 

243 Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand. 

244 

245 :param other: Parameter to compare against. 

246 :returns: True if version is equal to the second operand. 

247 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`. 

248 """ 

249 if isinstance(other, VHDLVersion): 

250 if (self is self.__class__.Any) or (other is self.__class__.Any): 

251 return True 

252 else: 

253 return self.value == other.value 

254 else: 

255 raise TypeError("Second operand is not of type 'VHDLVersion'.") 

256 

257 @readonly 

258 def IsVHDL(self) -> bool: 

259 """ 

260 Checks if the version is a VHDL (not VHDL-AMS) version. 

261 

262 :returns: True if version is a VHDL version. 

263 """ 

264 return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019) 

265 

266 @readonly 

267 def IsAMS(self) -> bool: 

268 """ 

269 Checks if the version is a VHDL-AMS (not VHDL) version. 

270 

271 :returns: True if version is a VHDL-AMS version. 

272 """ 

273 return self in (self.AMS93, self.AMS99, self.AMS2017) 

274 

275 def __str__(self) -> str: 

276 """ 

277 Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``. 

278 

279 :returns: Formatted VHDL/VHDL-AMS version. 

280 """ 

281 if self.value == self.Any.value: 

282 return "VHDL'Any" 

283 elif self.value == self.Latest.value: 

284 return "VHDL'Latest" 

285 

286 year = str(self.value)[-2:] 

287 if self.IsVHDL: 

288 return f"VHDL'{year}" 

289 else: 

290 return f"VHDL-AMS'{year}" 

291 

292 def __repr__(self) -> str: 

293 """ 

294 Formats the VHDL/VHDL-AMS version to pattern ``xxxx``. 

295 

296 :returns: Formatted VHDL/VHDL-AMS version. 

297 """ 

298 if self.value == self.Any.value: 

299 return "Any" 

300 elif self.value == self.Latest.value: 

301 return "Latest" 

302 else: 

303 return str(self.value) 

304 

305 

306@export 

307class IEEEFlavor(Flag): 

308 """ 

309 The ``IEEE`` VHDL library as a fixed set of predefined VHDL packages according to IEEE Std. 1076. 

310 

311 Nonetheless, some vendors decided to sneak in additional packages into the ``IEEE`` namespace. |br| 

312 Supported flavors are: 

313 

314 * ``Synopsys`` 

315 * ``MentorGraphics`` 

316 

317 In addition, IEEE Std. 1076.X extensions can be loaded. |br| 

318 Supported extensions are: 

319 

320 * ``WithVITAL`` - IEEE Std. 1076.4 

321 

322 """ 

323 Unknown = 0 #: Unknown IEEE flavor 

324 IEEE = 1 #: IEEE Std. 1076 compliant list of IEEE packages. 

325 Synopsys = 2 #: Additional packages created by Synopsys are visible within the IEEE library. 

326 MentorGraphics = 4 #: Additional packages created by Mentor Graphics are visible within the IEEE library. 

327 WithVITAL = 32 #: Additionally load IEEE Std 1076.4 VITAL packages. (VITAL = VHDL Initiative Towards ASIC Libraries) 

328 

329 

330@export 

331@unique 

332class ObjectClass(Enum): 

333 """ 

334 An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...). 

335 

336 In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context. 

337 """ 

338 

339 Default = 0 #: Object class not defined, thus it's context dependent. 

340 Constant = 1 #: Constant 

341 Variable = 2 #: Variable 

342 Signal = 3 #: Signal 

343 File = 4 #: File 

344 Type = 5 #: Type 

345 # FIXME: Package? 

346 Procedure = 6 #: Procedure 

347 Function = 7 #: Function 

348 

349 def __str__(self) -> str: 

350 """ 

351 Formats the object class. 

352 

353 :returns: Formatted object class. 

354 """ 

355 return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance 

356 

357 

358@export 

359@unique 

360class DesignUnitKind(Flag): 

361 """ 

362 A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...). 

363 

364 """ 

365 Context = auto() #: Context 

366 Package = auto() #: Package 

367 PackageBody = auto() #: Package Body 

368 Entity = auto() #: Entity 

369 Architecture = auto() #: Architecture 

370 Configuration = auto() #: Configuration 

371 

372 Primary = Context | Configuration | Entity | Package #: List of primary design units. 

373 Secondary = PackageBody | Architecture #: List of secondary design units. 

374 WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context. 

375 WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region. 

376 

377 All = Primary | Secondary #: List of all design units. 

378 

379 

380@export 

381@unique 

382class DependencyGraphVertexKind(Flag): 

383 """ 

384 A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph. 

385 """ 

386 Document = auto() #: A document (VHDL source file). 

387 Library = auto() #: A VHDL library. 

388 

389 Context = auto() #: A context design unit. 

390 Package = auto() #: A package design unit. 

391 PackageBody = auto() #: A package body design unit. 

392 Entity = auto() #: A entity design unit. 

393 Architecture = auto() #: A architecture design unit. 

394 Component = auto() #: A VHDL component. 

395 Configuration = auto() #: A configuration design unit. 

396 

397 

398@export 

399@unique 

400class DependencyGraphEdgeKind(Flag): 

401 """ 

402 A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph. 

403 """ 

404 Document = auto() 

405 Library = auto() 

406 Context = auto() 

407 Package = auto() 

408 Entity = auto() 

409 # Architecture = auto() 

410 Configuration = auto() 

411 Component = auto() 

412 

413 DeclaredIn = auto() 

414 Order = auto() 

415 Reference = auto() 

416 Implementation = auto() 

417 Instantiation = auto() 

418 

419 SourceFile = Document | DeclaredIn 

420 CompileOrder = Document | Order 

421 

422 LibraryClause = Library | Reference 

423 UseClause = Package | Reference 

424 ContextReference = Context | Reference 

425 

426 EntityImplementation = Entity | Implementation 

427 PackageImplementation = Package | Implementation 

428 

429 EntityInstantiation = Entity | Instantiation 

430 ComponentInstantiation = Component | Instantiation 

431 ConfigurationInstantiation = Configuration | Instantiation 

432 

433 PackageInstantiation = Package | Instantiation 

434 

435 

436@export 

437@unique 

438class ObjectGraphVertexKind(Flag): 

439 """ 

440 A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph. 

441 """ 

442 Type = auto() 

443 Subtype = auto() 

444 

445 Constant = auto() 

446 DeferredConstant = auto() 

447 Variable = auto() 

448 Signal = auto() 

449 File = auto() 

450 

451 Alias = auto() 

452 

453 

454@export 

455@unique 

456class ObjectGraphEdgeKind(Flag): 

457 """ 

458 A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph. 

459 """ 

460 BaseType = auto() 

461 Subtype = auto() 

462 

463 ReferenceInExpression = auto() 

464 

465 

466@export 

467class Design(ModelEntity, AllowBlackboxMixin): 

468 """ 

469 A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`). 

470 

471 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 

472 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 

473 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`). 

474 

475 The *design* contains references to the following graphs: 

476 

477 * :attr:`DependencyGraph` 

478 * :attr:`CompileOrderGraph` 

479 * :attr:`HierarchyGraph` 

480 * :attr:`ObjectGraph` 

481 """ 

482 _name: Nullable[str] #: Name of the design. 

483 _allowBlackbox: bool #: Allow blackboxes after linking the design. 

484 _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design. 

485 _documents: List['Document'] #: List of all documents loaded for a design. 

486 _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. 

487 _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. 

488 _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. 

489 _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. 

490 _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field. 

491 

492 def __init__( 

493 self, 

494 name: Nullable[str] = None, 

495 allowBlackbox: bool = False 

496 ) -> None: 

497 """ 

498 Initialize a VHDL design. 

499 

500 :param allowBlackbox: Specify if blackboxes are allowed in this design. 

501 :param name: Name of the design. 

502 """ 

503 super().__init__() 

504 AllowBlackboxMixin.__init__(self, allowBlackbox) 

505 

506 self._name = name 

507 

508 self._libraries = {} 

509 self._documents = [] 

510 

511 self._compileOrderGraph = Graph() 

512 self._dependencyGraph = Graph() 

513 self._hierarchyGraph = Graph() 

514 self._objectGraph = Graph() 

515 self._toplevel = None 

516 

517 @readonly 

518 def Name(self) -> Nullable[str]: 

519 """ 

520 Read-only property to access the design's name (:attr:`_name`). 

521 

522 :returns: The name of the design. 

523 """ 

524 return self._name 

525 

526 @readonly 

527 def Libraries(self) -> Dict[str, 'Library']: 

528 """ 

529 Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`). 

530 

531 :returns: A dictionary of library names and VHDL libraries. 

532 """ 

533 return self._libraries 

534 

535 @readonly 

536 def Documents(self) -> List['Document']: 

537 """ 

538 Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`). 

539 

540 :returns: A list of all documents. 

541 """ 

542 return self._documents 

543 

544 @readonly 

545 def CompileOrderGraph(self) -> Graph: 

546 """ 

547 Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`). 

548 

549 :returns: Reference to the compile-order graph. 

550 """ 

551 return self._compileOrderGraph 

552 

553 @readonly 

554 def DependencyGraph(self) -> Graph: 

555 """ 

556 Read-only property to access the dependency graph (:attr:`_dependencyGraph`). 

557 

558 :returns: Reference to the dependency graph. 

559 """ 

560 return self._dependencyGraph 

561 

562 @readonly 

563 def HierarchyGraph(self) -> Graph: 

564 """ 

565 Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`). 

566 

567 :returns: Reference to the hierarchy graph. 

568 """ 

569 return self._hierarchyGraph 

570 

571 @readonly 

572 def ObjectGraph(self) -> Graph: 

573 """ 

574 Read-only property to access the object graph (:attr:`_objectGraph`). 

575 

576 :returns: Reference to the object graph. 

577 """ 

578 return self._objectGraph 

579 

580 @readonly 

581 def TopLevel(self) -> Union[Entity, Configuration]: 

582 """ 

583 Read-only property to access the design's *top-level* (:attr:`_toplevel`). 

584 

585 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`` 

586 is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`. 

587 

588 :returns: Reference to the design's *top-level*. 

589 :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph. 

590 :raises VHDLModelException: If there is more than one *top-level*. 

591 """ 

592 # Check for cached result 

593 if self._toplevel is not None: 

594 return self._toplevel 

595 

596 if self._hierarchyGraph.EdgeCount == 0: 

597 raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.") 

598 

599 roots = tuple(self._hierarchyGraph.IterateRoots()) 

600 if len(roots) == 1: 

601 toplevel = roots[0] 

602 self._hierarchyGraph["toplevel"] = toplevel 

603 self._toplevel = toplevel.Value 

604 

605 return toplevel.Value 

606 else: 

607 raise VHDLModelException(f"Found more than one toplevel: {', '.join(str(r) for r in roots)}") 

608 

609 def LoadStdLibrary(self) -> 'Library': 

610 """ 

611 Load the predefined VHDL library ``std`` into the design. 

612 

613 This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file. 

614 

615 :returns: The library object of library ``std``. 

616 """ 

617 from pyVHDLModel.STD import Std 

618 

619 doc = Document(Path("std.vhdl"), parent=self) 

620 

621 library = Std() 

622 for designUnit in library.IterateDesignUnits(): 

623 doc._AddDesignUnit(designUnit) 

624 

625 self.AddLibrary(library) 

626 

627 return library 

628 

629 def LoadIEEELibrary(self, flavor: Nullable[IEEEFlavor] = None) -> 'Library': 

630 """ 

631 Load the predefined VHDL library ``ieee`` into the design. 

632 

633 This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file. 

634 

635 :param flavor: Select the IEEE library flavor: IEEE, Synopsys, MentorGraphics. 

636 :returns: The library object of library ``ieee``. 

637 """ 

638 from pyVHDLModel.IEEE import Ieee 

639 

640 doc = Document(Path("ieee.vhdl"), parent=self) 

641 

642 library = Ieee(flavor) 

643 for designUnit in library.IterateDesignUnits(): 

644 doc._AddDesignUnit(designUnit) 

645 

646 self.AddLibrary(library) 

647 

648 return library 

649 

650 def AddLibrary(self, library: 'Library') -> None: 

651 """ 

652 Add a VHDL library to the design. 

653 

654 Ensure the libraries name doesn't collide with existing libraries in the design. |br| 

655 If ok, set the libraries parent reference to the design. 

656 

657 :param library: Library object to loaded. 

658 :raises LibraryExistsInDesignError: If the library already exists in the design. 

659 :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design. 

660 """ 

661 libraryIdentifier = library.NormalizedIdentifier 

662 if libraryIdentifier in self._libraries: 

663 raise LibraryExistsInDesignError(library) 

664 

665 if library._parent is not None: 

666 raise LibraryRegisteredToForeignDesignError(library) 

667 

668 self._libraries[libraryIdentifier] = library 

669 library.Parent = self 

670 

671 def GetLibrary(self, libraryName: str) -> 'Library': 

672 """ 

673 Return an (existing) VHDL library object of name ``libraryName``. 

674 

675 If the requested VHDL library doesn't exist, a new VHDL library with that name will be created. 

676 

677 :param libraryName: Name of the requested VHDL library. 

678 :returns: The VHDL library object. 

679 """ 

680 libraryIdentifier = libraryName.lower() 

681 try: 

682 return self._libraries[libraryIdentifier] 

683 except KeyError: 

684 lib = Library(libraryName, parent=self) 

685 self._libraries[libraryIdentifier] = lib 

686 lib.Parent = self 

687 return lib 

688 

689 # TODO: allow overloaded parameter library to be str? 

690 def AddDocument(self, document: 'Document', library: 'Library') -> None: 

691 """ 

692 Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library. 

693 

694 .. rubric:: Algorithm 

695 

696 1. Iterate all entities in the document 

697 

698 1. Check if entity name might exist in target library. 

699 2. Add entity to library and update library membership. 

700 

701 2. Iterate all architectures in the document 

702 

703 1. Check if architecture name might exist in target library. 

704 2. Add architecture to library and update library membership. 

705 

706 3. Iterate all packages in the document 

707 

708 1. Check if package name might exist in target library. 

709 2. Add package to library and update library membership. 

710 

711 4. Iterate all package bodies in the document 

712 

713 1. Check if package body name might exist in target library. 

714 2. Add package body to library and update library membership. 

715 

716 5. Iterate all configurations in the document 

717 

718 1. Check if configuration name might exist in target library. 

719 2. Add configuration to library and update library membership. 

720 

721 6. Iterate all contexts in the document 

722 

723 1. Check if context name might exist in target library. 

724 2. Add context to library and update library membership. 

725 

726 :param document: The VHDL source code file. 

727 :param library: The VHDL library used to register the embedded design units to. 

728 :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design. 

729 :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library. 

730 :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library. 

731 :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library. 

732 :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library. 

733 :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library. 

734 :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library. 

735 """ 

736 # FIXME: this checks for the library name, but not the object 

737 # should the libraries parent be checked too? 

738 if library._normalizedIdentifier not in self._libraries: 738 ↛ 739line 738 didn't jump to line 739 because the condition on line 738 was never true

739 raise LibraryNotRegisteredError(library) 

740 

741 self._documents.append(document) 

742 document.Parent = self 

743 #document.Library = library 

744 

745 document._library = library 

746 

747 for entityIdentifier, entity in document._entities.items(): 

748 if entityIdentifier in library._entities: 748 ↛ 749line 748 didn't jump to line 749 because the condition on line 748 was never true

749 raise EntityExistsInLibraryError(entity, library) 

750 

751 library._entities[entityIdentifier] = entity 

752 entity.Library = library 

753 

754 for entityIdentifier, architectures in document._architectures.items(): 

755 try: 

756 architecturesPerEntity = library._architectures[entityIdentifier] 

757 for architectureIdentifier, architecture in architectures.items(): 

758 if architectureIdentifier in architecturesPerEntity: 

759 raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library) 

760 

761 architecturesPerEntity[architectureIdentifier] = architecture 

762 architecture.Library = library 

763 except KeyError: 

764 architecturesPerEntity = document._architectures[entityIdentifier].copy() 

765 library._architectures[entityIdentifier] = architecturesPerEntity 

766 

767 for architecture in architecturesPerEntity.values(): 

768 architecture.Library = library 

769 

770 for packageIdentifier, package in document._packages.items(): 

771 if packageIdentifier in library._packages: 771 ↛ 772line 771 didn't jump to line 772 because the condition on line 771 was never true

772 raise PackageExistsInLibraryError(package, library) 

773 

774 library._packages[packageIdentifier] = package 

775 package.Library = library 

776 

777 for packageBodyIdentifier, packageBody in document._packageBodies.items(): 

778 if packageBodyIdentifier in library._packageBodies: 778 ↛ 779line 778 didn't jump to line 779 because the condition on line 778 was never true

779 raise PackageBodyExistsError(packageBody, library) 

780 

781 library._packageBodies[packageBodyIdentifier] = packageBody 

782 packageBody.Library = library 

783 

784 for configurationIdentifier, configuration in document._configurations.items(): 

785 if configurationIdentifier in library._configurations: 785 ↛ 786line 785 didn't jump to line 786 because the condition on line 785 was never true

786 raise ConfigurationExistsInLibraryError(configuration, library) 

787 

788 library._configurations[configurationIdentifier] = configuration 

789 configuration.Library = library 

790 

791 for contextIdentifier, context in document._contexts.items(): 

792 if contextIdentifier in library._contexts: 792 ↛ 793line 792 didn't jump to line 793 because the condition on line 792 was never true

793 raise ContextExistsInLibraryError(context, library) 

794 

795 library._contexts[contextIdentifier] = context 

796 context.Library = library 

797 

798 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]: 

799 """ 

800 Iterate all design units in the design. 

801 

802 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units. 

803 

804 .. rubric:: Algorithm 

805 

806 1. Iterate all VHDL libraries. 

807 

808 1. Iterate all contexts in that library. 

809 2. Iterate all packages in that library. 

810 3. Iterate all package bodies in that library. 

811 4. Iterate all entites in that library. 

812 5. Iterate all architectures in that library. 

813 6. Iterate all configurations in that library. 

814 

815 :param filter: An enumeration with possibly multiple flags to filter the returned design units. 

816 :returns: A generator to iterate all matched design units in the design. 

817 

818 .. seealso:: 

819 

820 :meth:`pyVHDLModel.Library.IterateDesignUnits` 

821 Iterate all design units in the library. 

822 :meth:`pyVHDLModel.Document.IterateDesignUnits` 

823 Iterate all design units in the document. 

824 """ 

825 for library in self._libraries.values(): 

826 yield from library.IterateDesignUnits(filter) 

827 

828 def Analyze(self) -> None: 

829 """ 

830 Analyze the whole design. 

831 

832 .. rubric:: Algorithm 

833 

834 1. Analyze dependencies of design units. |br| 

835 This will also yield the design hierarchy and the compiler order. 

836 2. Analyze dependencies of types and objects. 

837 

838 .. seealso:: 

839 

840 :meth:`AnalyzeDependencies` 

841 Analyze the dependencies of design units. 

842 

843 :meth:`AnalyzeObjects` 

844 Analyze the dependencies of types and objects. 

845 """ 

846 self.AnalyzeDependencies() 

847 # self.AnalyzeObjects() 

848 

849 def AnalyzeDependencies(self) -> None: 

850 """ 

851 Analyze the dependencies of design units. 

852 

853 .. rubric:: Algorithm 

854 

855 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br| 

856 |rarr| :meth:`CreateDependencyGraph` 

857 2. Create the compile order graph. |br| 

858 |rarr| :meth:`CreateCompileOrderGraph` 

859 3. Index all packages. |br| 

860 |rarr| :meth:`IndexPackages` 

861 4. Index all architectures. |br| 

862 |rarr| :meth:`IndexArchitectures` 

863 5. Link all contexts |br| 

864 |rarr| :meth:`LinkContexts` 

865 6. Link all architectures. |br| 

866 |rarr| :meth:`LinkArchitectures` 

867 7. Link all package bodies. |br| 

868 |rarr| :meth:`LinkPackageBodies` 

869 8. Link all package instances. |br| 

870 |rarr| :meth:`LinkPackageInstances` 

871 9. Link all library references. |br| 

872 |rarr| :meth:`LinkLibraryReferences` 

873 10. Link all package references. |br| 

874 |rarr| :meth:`LinkPackageReferences` 

875 11. Link all context references. |br| 

876 |rarr| :meth:`LinkContextReferences` 

877 12. Link all components. |br| 

878 |rarr| :meth:`LinkComponents` 

879 13. Link all instantiations. |br| 

880 |rarr| :meth:`LinkInstantiations` 

881 14. Create the hierarchy graph. |br| 

882 |rarr| :meth:`CreateHierarchyGraph` 

883 15. Compute the compile order. |br| 

884 |rarr| :meth:`ComputeCompileOrder` 

885 """ 

886 self.CreateDependencyGraph() 

887 self.CreateCompileOrderGraph() 

888 

889 self.IndexPackages() 

890 self.IndexArchitectures() 

891 

892 self.LinkContexts() 

893 self.LinkArchitectures() 

894 self.LinkPackageBodies() 

895 self.LinkPackageInstances() 

896 self.LinkLibraryReferences() 

897 self.LinkPackageReferences() 

898 self.LinkContextReferences() 

899 

900 self.LinkComponents() 

901 self.LinkInstantiations() 

902 self.CreateHierarchyGraph() 

903 self.ComputeCompileOrder() 

904 

905 def AnalyzeObjects(self) -> None: 

906 """ 

907 Analyze the dependencies of types and objects. 

908 

909 .. rubric:: Algorithm 

910 

911 1. Index all entities. |br| 

912 |rarr| :meth:`IndexEntities` 

913 2. Index all package bodies. |br| 

914 |rarr| :meth:`IndexPackageBodies` 

915 3. Import objects. |br| 

916 |rarr| :meth:`ImportObjects` 

917 4. Create the type and object graph. |br| 

918 |rarr| :meth:`CreateTypeAndObjectGraph` 

919 """ 

920 self.IndexEntities() 

921 self.IndexPackageBodies() 

922 

923 self.ImportObjects() 

924 self.CreateTypeAndObjectGraph() 

925 

926 def CreateDependencyGraph(self) -> None: 

927 """ 

928 Create all vertices of the dependency graph by iterating all design units in all libraries. 

929 

930 This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br| 

931 See :meth:`AnalyzeDependencies` for these methods and their algorithmic order. 

932 

933 Each vertex has the following properties: 

934 

935 * The vertex' ID is the design unit's identifier. 

936 * The vertex' value references the design unit. 

937 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`. 

938 * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity. 

939 

940 .. rubric:: Algorithm 

941 

942 1. Iterate all libraries in the design. 

943 

944 * Create a vertex for that library and reference the library by the vertex' value field. |br| 

945 In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex. 

946 

947 1. Iterate all contexts in that library. 

948 

949 * Create a vertex for that context and reference the context by the vertex' value field. |br| 

950 In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex. 

951 

952 2. Iterate all packages in that library. 

953 

954 * Create a vertex for that package and reference the package by the vertex' value field. |br| 

955 In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex. 

956 

957 3. Iterate all package bodies in that library. 

958 

959 * Create a vertex for that package body and reference the package body by the vertex' value field. |br| 

960 In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex. 

961 

962 4. Iterate all entities in that library. 

963 

964 * Create a vertex for that entity and reference the entity by the vertex' value field. |br| 

965 In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex. 

966 

967 5. Iterate all architectures in that library. 

968 

969 * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br| 

970 In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex. 

971 

972 6. Iterate all configurations in that library. 

973 

974 * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br| 

975 In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex. 

976 """ 

977 predefinedLibraries = ("std", "ieee") 

978 

979 for libraryIdentifier, library in self._libraries.items(): 

980 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph) 

981 dependencyVertex["kind"] = DependencyGraphVertexKind.Library 

982 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries 

983 library._dependencyVertex = dependencyVertex 

984 

985 for contextIdentifier, context in library._contexts.items(): 

986 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph) 

987 dependencyVertex["kind"] = DependencyGraphVertexKind.Context 

988 dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries 

989 context._dependencyVertex = dependencyVertex 

990 

991 for packageIdentifier, package in library._packages.items(): 

992 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph) 

993 dependencyVertex["kind"] = DependencyGraphVertexKind.Package 

994 dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries 

995 package._dependencyVertex = dependencyVertex 

996 

997 for packageBodyIdentifier, packageBody in library._packageBodies.items(): 

998 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph) 

999 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody 

1000 dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries 

1001 packageBody._dependencyVertex = dependencyVertex 

1002 

1003 for entityIdentifier, entity in library._entities.items(): 

1004 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph) 

1005 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity 

1006 dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries 

1007 entity._dependencyVertex = dependencyVertex 

1008 

1009 for entityIdentifier, architectures in library._architectures.items(): 

1010 for architectureIdentifier, architecture in architectures.items(): 

1011 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph) 

1012 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture 

1013 dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries 

1014 architecture._dependencyVertex = dependencyVertex 

1015 

1016 for configurationIdentifier, configuration in library._configurations.items(): 

1017 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph) 

1018 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration 

1019 dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries 

1020 configuration._dependencyVertex = dependencyVertex 

1021 

1022 def CreateCompileOrderGraph(self) -> None: 

1023 """ 

1024 Create a compile-order graph with bidirectional references to the dependency graph. 

1025 

1026 Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order 

1027 graph and bidirectionally referenced. 

1028 

1029 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 

1030 document relationship. 

1031 

1032 Each added vertex has the following properties: 

1033 

1034 * The vertex' ID is the document's filename. 

1035 * The vertex' value references the document. 

1036 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`. 

1037 * A key-value-pair called ``predefined`` does not exist. 

1038 

1039 .. rubric:: Algorithm 

1040 

1041 1. Iterate all documents in the design. 

1042 

1043 * Create a vertex for that document and reference the document by the vertex' value field. |br| 

1044 In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex. 

1045 * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br| 

1046 In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex. 

1047 

1048 * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex. 

1049 * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex. 

1050 

1051 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding 

1052 dependency vertex. This expresses a "design unit is located in document" relation. 

1053 

1054 * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`. 

1055 """ 

1056 for document in self._documents: 

1057 dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph) 

1058 dependencyVertex["kind"] = DependencyGraphVertexKind.Document 

1059 document._dependencyVertex = dependencyVertex 

1060 

1061 compilerOrderVertex = dependencyVertex.Copy( 

1062 self._compileOrderGraph, 

1063 copyDict=True, 

1064 linkingKeyToOriginalVertex="dependencyVertex", 

1065 linkingKeyFromOriginalVertex="compileOrderVertex" 

1066 ) 

1067 document._compileOrderVertex = compilerOrderVertex 

1068 

1069 for designUnit in document._designUnits: 

1070 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex) 

1071 edge["kind"] = DependencyGraphEdgeKind.SourceFile 

1072 

1073 def ImportObjects(self) -> None: 

1074 def _ImportObjects(package: Package) -> None: 

1075 from pyVHDLModel.Declaration import AttributeSpecification 

1076 

1077 for referencedLibrary in package._referencedPackages.values(): 

1078 for referencedPackage in referencedLibrary.values(): 

1079 for declaredItem in referencedPackage._declaredItems: 

1080 if isinstance(declaredItem, MultipleNamedEntityMixin): 

1081 for normalizedIdentifier in declaredItem._normalizedIdentifiers: 

1082 package._namespace._elements[normalizedIdentifier] = declaredItem 

1083 elif isinstance(declaredItem, NamedEntityMixin): 

1084 package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem 

1085 elif isinstance(declaredItem, AttributeSpecification): 

1086 # FIXME: actually, this is not a declared item, but a application of an attribute to named entities 

1087 WarningCollector.Raise(NotImplementedWarning(f"Attribute specification.")) 

1088 

1089 else: 

1090 raise VHDLModelException(f"Unexpected declared item.") 

1091 

1092 for libraryName in ("std", "ieee"): 

1093 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package 

1094 _ImportObjects(package) 

1095 

1096 for document in self.IterateDocumentsInCompileOrder(): 

1097 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package 

1098 _ImportObjects(package) 

1099 

1100 def CreateTypeAndObjectGraph(self) -> None: 

1101 def _HandlePackage(package) -> None: 

1102 packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}" 

1103 

1104 for deferredConstant in package._deferredConstants.values(): 

1105 print(f"Deferred Constant: {deferredConstant}") 

1106 deferredConstantVertex = Vertex( 

1107 vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}", 

1108 value=deferredConstant, 

1109 graph=self._objectGraph 

1110 ) 

1111 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant 

1112 deferredConstant._objectVertex = deferredConstantVertex 

1113 

1114 for constant in package._constants.values(): 

1115 print(f"Constant: {constant}") 

1116 constantVertex = Vertex( 

1117 vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}", 

1118 value=constant, 

1119 graph=self._objectGraph 

1120 ) 

1121 constantVertex["kind"] = ObjectGraphVertexKind.Constant 

1122 constant._objectVertex = constantVertex 

1123 

1124 for type in package._types.values(): 

1125 print(f"Type: {type}") 

1126 typeVertex = Vertex( 

1127 vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}", 

1128 value=type, 

1129 graph=self._objectGraph 

1130 ) 

1131 typeVertex["kind"] = ObjectGraphVertexKind.Type 

1132 type._objectVertex = typeVertex 

1133 

1134 for subtype in package._subtypes.values(): 

1135 print(f"Subtype: {subtype}") 

1136 subtypeVertex = Vertex( 

1137 vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}", 

1138 value=subtype, 

1139 graph=self._objectGraph 

1140 ) 

1141 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype 

1142 subtype._objectVertex = subtypeVertex 

1143 

1144 for function in package._functions.values(): 

1145 print(f"Function: {function}") 

1146 functionVertex = Vertex( 

1147 vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}", 

1148 value=function, 

1149 graph=self._objectGraph 

1150 ) 

1151 functionVertex["kind"] = ObjectGraphVertexKind.Function 

1152 function._objectVertex = functionVertex 

1153 

1154 for procedure in package._procedures.values(): 

1155 print(f"Procedure: {procedure}") 

1156 procedureVertex = Vertex( 

1157 vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}", 

1158 value=procedure, 

1159 graph=self._objectGraph 

1160 ) 

1161 procedureVertex["kind"] = ObjectGraphVertexKind.Function 

1162 procedure._objectVertex = procedureVertex 

1163 

1164 for signal in package._signals.values(): 

1165 print(f"Signal: {signal}") 

1166 signalVertex = Vertex( 

1167 vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}", 

1168 value=signal, 

1169 graph=self._objectGraph 

1170 ) 

1171 signalVertex["kind"] = ObjectGraphVertexKind.Signal 

1172 signal._objectVertex = signalVertex 

1173 

1174 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex): 

1175 if isinstance(expression, UnaryExpression): 

1176 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex) 

1177 elif isinstance(expression, BinaryExpression): 

1178 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex) 

1179 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex) 

1180 elif isinstance(expression, TernaryExpression): 

1181 WarningCollector.Raise(NotImplementedWarning(f"Handling of ternary expression.")) 

1182 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): 

1183 obj = namespace.FindObject(expression) 

1184 expression._reference = obj 

1185 

1186 edge = obj._objectVertex.EdgeToVertex(typeVertex) 

1187 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression 

1188 else: 

1189 WarningCollector.Raise(NotImplementedWarning(f"Unhandled else-branch")) 

1190 

1191 def _LinkItems(package: Package): 

1192 for item in package._declaredItems: 

1193 if isinstance(item, Constant): 

1194 print(f"constant: {item}") 

1195 elif isinstance(item, DeferredConstant): 

1196 print(f"deferred constant: {item}") 

1197 elif isinstance(item, Signal): 

1198 print(f"signal: {item}") 

1199 elif isinstance(item, IntegerType): 

1200 typeNode = item._objectVertex 

1201 

1202 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode) 

1203 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode) 

1204 # elif isinstance(item, FloatingType): 

1205 # print(f"signal: {item}") 

1206 elif isinstance(item, PhysicalType): 

1207 typeNode = item._objectVertex 

1208 

1209 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode) 

1210 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode) 

1211 elif isinstance(item, ArrayType): 

1212 # Resolve dimensions 

1213 for dimension in item._dimensions: 

1214 subtype = package._namespace.FindSubtype(dimension) 

1215 dimension._reference = subtype 

1216 

1217 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex) 

1218 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1219 

1220 # Resolve element subtype 

1221 subtype = package._namespace.FindSubtype(item._elementType) 

1222 item._elementType._reference = subtype 

1223 

1224 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex) 

1225 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1226 elif isinstance(item, RecordType): 

1227 # Resolve each elements subtype 

1228 for element in item._elements: 

1229 subtype = package._namespace.FindSubtype(element._subtype) 

1230 element._subtype._reference = subtype 

1231 

1232 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex) 

1233 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1234 else: 

1235 print(f"not handled: {item}") 

1236 

1237 for libraryName in ("std", "ieee"): 

1238 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package 

1239 _HandlePackage(package) 

1240 _LinkItems(package) 

1241 

1242 for document in self.IterateDocumentsInCompileOrder(): 

1243 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package 

1244 _HandlePackage(package) 

1245 _LinkItems(package) 

1246 

1247 def LinkContexts(self) -> None: 

1248 """ 

1249 Resolves and links all items (library clauses, use clauses and nested context references) in contexts. 

1250 

1251 It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By 

1252 default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty 

1253 dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. 

1254 

1255 At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each 

1256 referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in 

1257 :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the 

1258 dependency graph is added for that relationship. 

1259 

1260 At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each 

1261 referenced package, 

1262 """ 

1263 for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context 

1264 # Create entries in _referenced*** for the current working library under its real name. 

1265 workingLibrary: Library = context.Library 

1266 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier 

1267 

1268 context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier] 

1269 context._referencedPackages[libraryNormalizedIdentifier] = {} 

1270 context._referencedContexts[libraryNormalizedIdentifier] = {} 

1271 

1272 # Process all library clauses 

1273 for libraryReference in context._libraryReferences: 

1274 # A library clause can have multiple comma-separated references 

1275 for libraryName in libraryReference.Symbols: 

1276 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier 

1277 try: 

1278 library = self._libraries[libraryNormalizedIdentifier] 

1279 except KeyError: 

1280 raise ReferencedLibraryNotExistingError(context, libraryName) 

1281 # TODO: add position to these messages 

1282 

1283 libraryName.Library = library 

1284 

1285 context._referencedLibraries[libraryNormalizedIdentifier] = library 

1286 context._referencedPackages[libraryNormalizedIdentifier] = {} 

1287 context._referencedContexts[libraryNormalizedIdentifier] = {} 

1288 # TODO: warn duplicate library reference 

1289 

1290 dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference) 

1291 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1292 

1293 # Process all use clauses 

1294 for packageReference in context.PackageReferences: 

1295 # A use clause can have multiple comma-separated references 

1296 for symbol in packageReference.Symbols: # type: PackageReferenceSymbol 

1297 packageName = symbol.Name.Prefix 

1298 libraryName = packageName.Prefix 

1299 

1300 libraryNormalizedIdentifier = libraryName._normalizedIdentifier 

1301 packageNormalizedIdentifier = packageName._normalizedIdentifier 

1302 

1303 # In case work is used, resolve to the real library name. 

1304 if libraryNormalizedIdentifier == "work": 1304 ↛ 1305line 1304 didn't jump to line 1305 because the condition on line 1304 was never true

1305 library: Library = context._parent 

1306 libraryNormalizedIdentifier = library._normalizedIdentifier 

1307 elif libraryNormalizedIdentifier not in context._referencedLibraries: 1307 ↛ 1309line 1307 didn't jump to line 1309 because the condition on line 1307 was never true

1308 # TODO: This check doesn't trigger if it's the working library. 

1309 raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.") 

1310 else: 

1311 library = self._libraries[libraryNormalizedIdentifier] 

1312 

1313 try: 

1314 package = library._packages[packageNormalizedIdentifier] 

1315 except KeyError: 

1316 raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.") 

1317 

1318 # FIXME: check if package isn't a generic package 

1319 symbol.Package = package 

1320 

1321 # TODO: warn duplicate package reference 

1322 context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package 

1323 

1324 dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference) 

1325 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1326 

1327 # TODO: update the namespace with visible members 

1328 if isinstance(symbol, AllPackageMembersReferenceSymbol): 1328 ↛ 1331line 1328 didn't jump to line 1331 because the condition on line 1328 was always true

1329 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'.")) 

1330 

1331 elif isinstance(symbol, PackageMemberReferenceSymbol): 

1332 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'.")) 

1333 

1334 else: 

1335 raise VHDLModelException() 

1336 

1337 def LinkArchitectures(self) -> None: 

1338 """ 

1339 Link all architectures to corresponding entities in all libraries. 

1340 

1341 .. rubric:: Algorithm 

1342 

1343 1. Iterate all libraries: 

1344 

1345 1. Iterate all architecture groups (grouped per entity symbol's name). 

1346 |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures` 

1347 

1348 * Check if entity symbol's name exists as an entity in this library. 

1349 

1350 1. For each architecture in the same architecture group: 

1351 

1352 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`. 

1353 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity` 

1354 * Set parent namespace of architecture's namespace to the entitie's namespace. 

1355 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex. 

1356 

1357 .. seealso:: 

1358 

1359 :meth:`LinkPackageBodies` 

1360 Link all package bodies to corresponding packages in all libraries. 

1361 :meth:`LinkPackageInstances` 

1362 Link all package instances to corresponding generic packages in all libraries. 

1363 """ 

1364 for library in self._libraries.values(): 

1365 library.LinkArchitectures() 

1366 

1367 def LinkPackageBodies(self) -> None: 

1368 """ 

1369 Link all package bodies to corresponding packages in all libraries. 

1370 

1371 .. rubric:: Algorithm 

1372 

1373 1. Iterate all libraries: 

1374 

1375 1. Iterate all package bodies. 

1376 |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies` 

1377 

1378 * Check if package body symbol's name exists as a package in this library. 

1379 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`. 

1380 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package` 

1381 * Set parent namespace of package body's namespace to the package's namespace. 

1382 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex. 

1383 

1384 .. seealso:: 

1385 

1386 :meth:`LinkArchitectures` 

1387 Link all architectures to corresponding entities in all libraries. 

1388 :meth:`LinkPackageInstances` 

1389 Link all package instances to corresponding generic packages in all libraries. 

1390 """ 

1391 for library in self._libraries.values(): 

1392 library.LinkPackageBodies() 

1393 

1394 def LinkPackageInstances(self) -> None: 

1395 """ 

1396 Link all package instances to corresponding generic packages in all libraries. 

1397 

1398 .. rubric:: Algorithm 

1399 

1400 1. Iterate all libraries: 

1401 

1402 1. Iterate all package instances. 

1403 |rarr| :meth:`pyVHDLModel.Library.LinkPackageInstances` 

1404 

1405 .. todo:: 

1406 

1407 * Check if package instance's symbol's name exists as a generic package in this library. 

1408 * Add generic package to package instance :attr:`pyVHDLModel.DesignUnit.Package._packageBody`. 

1409 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package` 

1410 * Set parent namespace of package body's namespace to the package's namespace. 

1411 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex. 

1412 

1413 .. seealso:: 

1414 

1415 :meth:`LinkArchitectures` 

1416 Link all architectures to corresponding entities in all libraries. 

1417 :meth:`LinkPackageBodies` 

1418 Link all package bodies to corresponding packages in all libraries. 

1419 """ 

1420 for library in self._libraries.values(): 

1421 library.LinkPackageInstances() 

1422 

1423 def LinkLibraryReferences(self) -> None: 

1424 """ 

1425 Link all library references (library clause) to the matching VHDL library. 

1426 

1427 .. rubric:: Algorithm 

1428 

1429 1. Iterate all design units with contexts: 

1430 

1431 * If the design unit is a primary unit: 

1432 

1433 1. Iterate all library identifiers in ``DEFAULT_LIBRARIES`` (``std``): 

1434 

1435 * Get the referenced library by name from the design. 

1436 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library. 

1437 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary. 

1438 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary. 

1439 * Add an edge in the dependency graph from design unit to the referenced library. 

1440 

1441 2. Get the design unit's library: 

1442 

1443 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library. 

1444 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary. 

1445 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary. 

1446 * Add an edge in the dependency graph from design unit to the referenced library. 

1447 

1448 * If the design unit is a secondary unit: 

1449 

1450 * If design unit is an architecture, get the corresponding entity's referenced libraries. 

1451 * If design unit is a package body, get the corresponding package's referenced libraries. 

1452 * Otherwise, raise an exception 

1453 

1454 For every referenced library create new dictionary entries in the design unit's ``_referencedLibraries``. 

1455 

1456 2. Iterate every library reference (library clause) in the design unit: 

1457 

1458 * Iterate every library symbol within the library reference: 

1459 

1460 * Get the library identifier from the symbol. 

1461 * Continue the inner loop, if identifier is ``work``. 

1462 * Get the referenced library from the design or raise an exception. 

1463 * Update the library symbol's target with the referenced library. 

1464 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library. 

1465 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary. 

1466 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary. 

1467 * Add an edge in the dependency graph from design unit to the referenced library. 

1468 

1469 .. seealso:: 

1470 

1471 :meth:`LinkPackageReferences` 

1472 Link *use clause*. 

1473 :meth:`LinkContextReferences` 

1474 Link *context clause*. 

1475 :meth:`AnalyzeDependencies` 

1476 Analyze dependencies and link relations. 

1477 """ 

1478 DEFAULT_LIBRARIES = ("std",) 

1479 

1480 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext): 

1481 # All primary units supporting a context, have at least one library implicitly referenced 

1482 if isinstance(designUnit, PrimaryUnit): 

1483 for libraryIdentifier in DEFAULT_LIBRARIES: 

1484 referencedLibrary = self._libraries[libraryIdentifier] 

1485 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary 

1486 designUnit._referencedPackages[libraryIdentifier] = {} 

1487 designUnit._referencedContexts[libraryIdentifier] = {} 

1488 # TODO: catch KeyError on self._libraries[libName] 

1489 # TODO: warn duplicate library reference 

1490 

1491 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex) 

1492 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1493 

1494 # TODO: this could create a duplicate linking, if primary unit is put into library 'std' 

1495 workingLibrary: Library = designUnit.Library 

1496 libraryIdentifier = workingLibrary.NormalizedIdentifier 

1497 referencedLibrary = self._libraries[libraryIdentifier] # TODO: isn't this the same as the workingLibrary from 2 lines before? 

1498 

1499 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary 

1500 designUnit._referencedPackages[libraryIdentifier] = {} 

1501 designUnit._referencedContexts[libraryIdentifier] = {} 

1502 

1503 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex) 

1504 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1505 

1506 # All secondary units inherit referenced libraries from their primary units. 

1507 else: 

1508 if isinstance(designUnit, Architecture): 

1509 referencedLibraries = designUnit.Entity.Entity._referencedLibraries 

1510 elif isinstance(designUnit, PackageBody): 1510 ↛ 1513line 1510 didn't jump to line 1513 because the condition on line 1510 was always true

1511 referencedLibraries = designUnit.Package.Package._referencedLibraries 

1512 else: 

1513 raise VHDLModelException() # FIXME: exception message 

1514 

1515 for libraryIdentifier, library in referencedLibraries.items(): 

1516 designUnit._referencedLibraries[libraryIdentifier] = library # TODO: Could we use the .update() method 

1517 

1518 for libraryReference in designUnit._libraryReferences: 

1519 # A library clause can have multiple comma-separated references 

1520 for librarySymbol in libraryReference.Symbols: 

1521 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier 

1522 if libraryIdentifier == "work": 1522 ↛ 1523line 1522 didn't jump to line 1523 because the condition on line 1522 was never true

1523 continue 

1524 

1525 try: 

1526 library = self._libraries[libraryIdentifier] 

1527 except KeyError: 

1528 ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.") 

1529 ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""") 

1530 raise ex 

1531 

1532 librarySymbol.Library = library 

1533 designUnit._referencedLibraries[libraryIdentifier] = library 

1534 designUnit._referencedPackages[libraryIdentifier] = {} 

1535 designUnit._referencedContexts[libraryIdentifier] = {} 

1536 # TODO: warn duplicate library reference 

1537 

1538 dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference) 

1539 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1540 

1541 def LinkPackageReferences(self) -> None: 

1542 """ 

1543 Link all package references (use clause) to the matching packages. 

1544 

1545 .. rubric:: Algorithm 

1546 

1547 1. Iterate all design units with contexts: 

1548 

1549 * If the design unit is a primary unit: 

1550 

1551 * If primary unit isn't package ``std.standard``: 

1552 

1553 1. Iterate all library, packages tuples in ``DEFAULT_PACKAGES`` (``std``: [``standard``]): 

1554 

1555 * Raise an exception, if library isn't listed in design unit's ``_referencedLibraries``. 

1556 * For every package in packages: 

1557 

1558 * Get the referenced package by library name and package name from the design. 

1559 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package. 

1560 * Add an edge in the dependency graph from design unit to the referenced package. 

1561 

1562 * If the design unit is a secondary unit: 

1563 

1564 * If design unit is an architecture, get the corresponding entity's referenced packages. 

1565 * If design unit is a package body, get the corresponding package's referenced packages. 

1566 * Otherwise, raise an exception 

1567 

1568 For every referenced package create new dictionary entries in the design unit's ``_referencedPackages``. 

1569 

1570 2. Iterate every package reference (use clause) in the design unit: 

1571 

1572 * Iterate every package symbol within the package reference: 

1573 

1574 1. Get the library identifier from the symbol. 

1575 2. Get the package identifier from the symbol. 

1576 3. Resolve library: 

1577 

1578 * If library name is ``work``, get library from design unit. 

1579 * If library name is not in design unit's ``_referencedLibraries``, raise an exception. 

1580 * Otherwise, lookup library by name in design. 

1581 

1582 4. Resolve package: 

1583 

1584 * Lookup package by name in library. 

1585 

1586 5. Update design unit: 

1587 

1588 * Update the package symbol's target with the referenced package. 

1589 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package. 

1590 * Add an edge in the dependency graph from design unit to the referenced package. 

1591 

1592 6. Import public package members. 

1593 

1594 * If package symbol is a ``AllPackageMembersReferenceSymbol``: 

1595 

1596 * Iterate all components within the referenced package and add entries for each component in the design unit's ``_namespace``. 

1597 

1598 .. todo:: Other elements are not implemented. 

1599 

1600 * If package symbol is a ``PackageMemberReferenceSymbol`` 

1601 

1602 .. todo:: Not implemented. 

1603 

1604 * Otherwise, raise an exception. 

1605 

1606 .. seealso:: 

1607 

1608 :meth:`LinkLibraryReferences` 

1609 Link *library clause*. 

1610 :meth:`LinkContextReferences` 

1611 Link *context clause*. 

1612 :meth:`AnalyzeDependencies` 

1613 Analyze dependencies and link relations. 

1614 """ 

1615 DEFAULT_PACKAGES = ( 

1616 ("std", ("standard",)), 

1617 ) 

1618 

1619 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext): 

1620 # All primary units supporting a context, have at least one package implicitly referenced 

1621 if isinstance(designUnit, PrimaryUnit): 

1622 if not (designUnit.Library.NormalizedIdentifier == "std" and designUnit.NormalizedIdentifier == "standard"): 

1623 for lib, packages in DEFAULT_PACKAGES: 

1624 if lib not in designUnit._referencedLibraries: 1624 ↛ 1625line 1624 didn't jump to line 1625 because the condition on line 1624 was never true

1625 raise VHDLModelException() # TODO: missing exception message 

1626 for package in packages: 

1627 referencedPackage = self._libraries[lib]._packages[package] 

1628 designUnit._referencedPackages[lib][package] = referencedPackage 

1629 # TODO: catch KeyError on self._libraries[lib[0]]._packages[package] 

1630 # TODO: warn duplicate package reference 

1631 

1632 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex) 

1633 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1634 

1635 # All secondary units inherit referenced packages from their primary units. 

1636 else: 

1637 if isinstance(designUnit, Architecture): 

1638 referencedPackages = designUnit.Entity.Entity._referencedPackages 

1639 elif isinstance(designUnit, PackageBody): 1639 ↛ 1642line 1639 didn't jump to line 1642 because the condition on line 1639 was always true

1640 referencedPackages = designUnit.Package.Package._referencedPackages 

1641 else: 

1642 raise VHDLModelException() # FIXME: exception message 

1643 

1644 for packageIdentifier, package in referencedPackages.items(): 

1645 designUnit._referencedPackages[packageIdentifier] = package 

1646 

1647 for packageReference in designUnit.PackageReferences: 

1648 # A use clause can have multiple comma-separated references 

1649 for packageMemberSymbol in packageReference.Symbols: 

1650 if isinstance(packageMemberSymbol, PackageReferenceSymbol): 1650 ↛ 1651line 1650 didn't jump to line 1651 because the condition on line 1650 was never true

1651 packageName = packageMemberSymbol.Name 

1652 elif isinstance(packageMemberSymbol, (AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol)): 1652 ↛ 1655line 1652 didn't jump to line 1655 because the condition on line 1652 was always true

1653 packageName = packageMemberSymbol.Name.Prefix 

1654 

1655 libraryName = packageName.Prefix 

1656 

1657 libraryIdentifier = libraryName.NormalizedIdentifier 

1658 packageIdentifier = packageName.NormalizedIdentifier 

1659 

1660 # In case work is used, resolve to the real library name. 

1661 if libraryIdentifier == "work": 

1662 library: Library = designUnit.Library 

1663 libraryIdentifier = library.NormalizedIdentifier 

1664 elif libraryIdentifier not in designUnit._referencedLibraries: 1664 ↛ 1666line 1664 didn't jump to line 1666 because the condition on line 1664 was never true

1665 # TODO: This check doesn't trigger if it's the working library. 

1666 raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.") 

1667 else: 

1668 library = self._libraries[libraryIdentifier] 

1669 

1670 try: 

1671 package = library._packages[packageIdentifier] 

1672 except KeyError: 

1673 ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.") 

1674 ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.") 

1675 raise ex 

1676 

1677 # FIXME: check if package isn't a generic package 

1678 packageMemberSymbol.Package = package 

1679 

1680 # TODO: warn duplicate package reference 

1681 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package 

1682 

1683 dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference) 

1684 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1685 

1686 # TODO: update the namespace with visible members 

1687 if isinstance(packageMemberSymbol, PackageReferenceSymbol): 1687 ↛ 1688line 1687 didn't jump to line 1688 because the condition on line 1687 was never true

1688 designUnit._namespace._elements[packageIdentifier] = package 

1689 

1690 elif isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1690 ↛ 1696line 1690 didn't jump to line 1696 because the condition on line 1690 was always true

1691 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'. Exception: components are handled.")) 

1692 

1693 for componentIdentifier, component in package._components.items(): 1693 ↛ 1694line 1693 didn't jump to line 1694 because the loop on line 1693 never started

1694 designUnit._namespace._elements[componentIdentifier] = component 

1695 

1696 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol): 

1697 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'.")) 

1698 

1699 else: 

1700 ex = VHDLModelException(f"Unknown package reference symbol type.") 

1701 ex.add_note(f"Got type '{getFullyQualifiedName(packageMemberSymbol)}'.") 

1702 raise ex 

1703 

1704 def LinkContextReferences(self) -> None: 

1705 """ 

1706 Link all context references (context clause) to the matching context. 

1707 

1708 .. rubric:: Algorithm 

1709 

1710 1. Iterate all design units: 

1711 

1712 * Iterate all context references in the design unit: 

1713 

1714 * Iterate each context symbol within the context reference. 

1715 

1716 1. Get the library identifier from the symbol. 

1717 2. Get the context identifier from the symbol. 

1718 3. Resolve library: 

1719 

1720 * If library name is ``work``, get library from design unit. 

1721 * If library name is not in design unit's ``_referencedLibraries``, raise an exception. 

1722 * Otherwise, lookup library by name in design. 

1723 

1724 4. Resolve context: 

1725 

1726 * Lookup context by name in library. 

1727 

1728 5. Update design unit: 

1729 

1730 * Update the context symbol's target with the referenced context. 

1731 * Add an entry in the design unit's ``_referencedContexts`` dictionary referencing the referenced context. 

1732 * Add an edge in the dependency graph from design unit to the referenced context. 

1733 

1734 2. Iterate all context vertices in the dependency graph (``_dependencyGraph``) in topological order: 

1735 

1736 * Get the context from the context vertex. 

1737 * Iterate all predecessor vertices (design unit vertices) of the context vertex: 

1738 

1739 1. Get the design unit from design unit vertex. 

1740 2. Iterate referenced libraries of the context: 

1741 

1742 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library. 

1743 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary. 

1744 

1745 3. Iterate referenced packages of the context: 

1746 

1747 * Raise an exception if package name is already listed in ``_referencedPackages``. 

1748 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package. 

1749 

1750 .. seealso:: 

1751 

1752 :meth:`LinkLibraryReferences` 

1753 Link *library clause*. 

1754 :meth:`LinkPackageReferences` 

1755 Link *use clause*. 

1756 :meth:`AnalyzeDependencies` 

1757 Analyze dependencies and link relations. 

1758 """ 

1759 for designUnit in self.IterateDesignUnits(): 

1760 for contextReference in designUnit._contextReferences: 

1761 # A context reference can have multiple comma-separated references 

1762 for contextSymbol in contextReference.Symbols: 

1763 libraryName = contextSymbol.Name.Prefix 

1764 

1765 libraryIdentifier = libraryName.NormalizedIdentifier 

1766 contextIdentifier = contextSymbol.Name.NormalizedIdentifier 

1767 

1768 # In case work is used, resolve to the real library name. 

1769 if libraryIdentifier == "work": 1769 ↛ 1772line 1769 didn't jump to line 1772 because the condition on line 1769 was always true

1770 referencedLibrary = designUnit.Library 

1771 libraryIdentifier = referencedLibrary.NormalizedIdentifier 

1772 elif libraryIdentifier not in designUnit._referencedLibraries: 

1773 # TODO: This check doesn't trigger if it's the working library. 

1774 raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.") 

1775 else: 

1776 referencedLibrary = self._libraries[libraryIdentifier] 

1777 

1778 try: 

1779 referencedContext = referencedLibrary._contexts[contextIdentifier] 

1780 except KeyError: 

1781 raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.") 

1782 

1783 contextSymbol.Package = referencedContext 

1784 

1785 # TODO: warn duplicate referencedContext reference 

1786 designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext 

1787 

1788 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference) 

1789 dependency["kind"] = DependencyGraphEdgeKind.ContextReference 

1790 

1791 for vertex in self._dependencyGraph.IterateTopologically(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Context): 

1792 context: Context = vertex.Value 

1793 for designUnitVertex in vertex.IteratePredecessorVertices(): # TODO: should this be filtered to exclude non-contexts? 

1794 designUnit: DesignUnit = designUnitVertex.Value 

1795 for libraryIdentifier, library in context._referencedLibraries.items(): 

1796 # if libraryIdentifier in designUnit._referencedLibraries: 

1797 # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.") 

1798 

1799 designUnit._referencedLibraries[libraryIdentifier] = library 

1800 designUnit._referencedPackages[libraryIdentifier] = {} 

1801 

1802 for libraryIdentifier, packages in context._referencedPackages.items(): 

1803 for packageIdentifier, package in packages.items(): 

1804 if packageIdentifier in designUnit._referencedPackages: 1804 ↛ 1805line 1804 didn't jump to line 1805 because the condition on line 1804 was never true

1805 raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.") 

1806 

1807 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package 

1808 

1809 def LinkComponents(self) -> None: 

1810 """ 

1811 Link components to matching entities found in same VHDL library. 

1812 

1813 .. rubric:: Algorithm 

1814 

1815 1. Iterate all design units with component declarations (packages and architectures): 

1816 

1817 1. Iterate all component declarations in a package or architecture: 

1818 

1819 * Check if an entity with matching name can be found in the VHDL library the package is declared within. If 

1820 found, set the component's entity reference to that entity, otherwise check if blackboxes are allowed for 

1821 that component. If so, mark the component as a blackbox, otherwise, raise an exception. 

1822 

1823 2. Iterate concurrent statements with declaration regions (block statements, generate statements) if the design 

1824 unit is an architecture: 

1825 

1826 * If the statement is an :class:`IfGenerateStatement`: 

1827 

1828 1. Iterate declared components in the :class:`IfGenerateBranch`. 

1829 2. Iterate declared components in each :class:`ElIfGenerateBranch`. 

1830 3. Iterate declared components in the :class:`ElseGenerateBranch` if it exists. 

1831 

1832 * If the statement is an :class:`ForGenerateStatement`: 

1833 

1834 1. Iterate declared components. 

1835 

1836 * If the statement is an :class:`CaseGenerateStatement`: 

1837 

1838 1. Iterate declared components. 

1839 2. Iterate 

1840 

1841 .. seealso:: 

1842 

1843 :meth:`LinkInstantiations` 

1844 Link instantiations to components and entities. 

1845 :meth:`AnalyzeDependencies` 

1846 Analyze dependencies in a design (calls this method). 

1847 """ 

1848 def linkStatements(library: Library, concurrent: ConcurrentStatementsMixin) -> None: 

1849 for statement in concurrent._statements: 

1850 if isinstance(statement, IfGenerateStatement): 1850 ↛ 1851line 1850 didn't jump to line 1851 because the condition on line 1850 was never true

1851 linkComponents(library, statement._ifBranch) 

1852 linkStatements(library, statement._ifBranch) 

1853 for branch in statement._elsifBranches: 

1854 linkComponents(library, branch) 

1855 linkStatements(library, branch) 

1856 if (branch := statement._elseBranch) is not None: 

1857 linkComponents(library, branch) 

1858 linkStatements(library, branch) 

1859 elif isinstance(statement, ForGenerateStatement): 1859 ↛ 1860line 1859 didn't jump to line 1860 because the condition on line 1859 was never true

1860 linkComponents(library, statement) 

1861 linkStatements(library, statement) 

1862 elif isinstance(statement, CaseGenerateStatement): 1862 ↛ 1863line 1862 didn't jump to line 1863 because the condition on line 1862 was never true

1863 for case in statement._cases: 

1864 linkComponents(library, case) 

1865 linkStatements(library, case) 

1866 elif isinstance(statement, ConcurrentBlockStatement): 1866 ↛ 1867line 1866 didn't jump to line 1867 because the condition on line 1866 was never true

1867 linkComponents(library, statement) 

1868 linkStatements(library, statement) 

1869 

1870 def searchEntityAndLinkComponent(library: Library, component: Component) -> None: 

1871 # QUESTION: Add link in dependency graph as dashed line from component to entity? 

1872 # Currently, component has no _dependencyVertex field 

1873 try: 

1874 entity = library._entities[component.NormalizedIdentifier] 

1875 except KeyError: 

1876 if component.AllowBlackbox: 

1877 component._isBlackBox = True 

1878 return 

1879 else: 

1880 raise VHDLModelException( 

1881 f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.") 

1882 

1883 component.Entity = entity 

1884 

1885 def linkComponents(library: Library, declarationRegion: ConcurrentDeclarationRegionMixin) -> None: 

1886 for item in declarationRegion._declaredItems: 

1887 if isinstance(item, Component): 

1888 searchEntityAndLinkComponent(library, item) 

1889 

1890 for designUnit in self.IterateDesignUnits(DesignUnitKind.Package | DesignUnitKind.Architecture): # type: Union[Package, Architecture] 

1891 library = designUnit._parent 

1892 for component in designUnit._components.values(): 1892 ↛ 1893line 1892 didn't jump to line 1893 because the loop on line 1892 never started

1893 searchEntityAndLinkComponent(library, component) 

1894 

1895 if isinstance(designUnit, Architecture): 

1896 linkStatements(library, designUnit) 

1897 

1898 def LinkInstantiations(self) -> None: 

1899 for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture 

1900 for instance in architecture.IterateInstantiations(): 

1901 if isinstance(instance, EntityInstantiation): 1901 ↛ 1934line 1901 didn't jump to line 1934 because the condition on line 1901 was always true

1902 libraryName = instance.Entity.Name.Prefix 

1903 libraryIdentifier = libraryName.Identifier 

1904 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier 

1905 if normalizedLibraryIdentifier == "work": 

1906 libraryIdentifier = architecture.Library.Identifier 

1907 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier 

1908 elif normalizedLibraryIdentifier not in architecture._referencedLibraries: 1908 ↛ 1909line 1908 didn't jump to line 1909 because the condition on line 1908 was never true

1909 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}'.") 

1910 ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.") 

1911 raise ex 

1912 

1913 try: 

1914 library = self._libraries[normalizedLibraryIdentifier] 

1915 except KeyError: 

1916 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.") 

1917 ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.") 

1918 raise ex 

1919 

1920 try: 

1921 entity = library._entities[instance.Entity.Name.NormalizedIdentifier] 

1922 except KeyError: 

1923 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}'.") 

1924 libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier] 

1925 if libs: 

1926 ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}") 

1927 raise ex 

1928 

1929 instance.Entity.Entity = entity 

1930 

1931 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance) 

1932 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation 

1933 

1934 elif isinstance(instance, ComponentInstantiation): 

1935 component = instance._parent._namespace.FindComponent(instance.Component) 

1936 

1937 instance.Component.Component = component 

1938 

1939 if not component.IsBlackbox: 

1940 dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance) 

1941 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation 

1942 else: 

1943 WarningCollector.Raise(BlackboxWarning(f"Blackbox caused by '{instance.Label}: {instance.Component.Name}'.")) 

1944 

1945 elif isinstance(instance, ConfigurationInstantiation): 

1946 WarningCollector.Raise(NotImplementedWarning(f"Configuration instantiation of '{instance.Label}: {instance.Configuration}'.")) 

1947 

1948 def IndexPackages(self) -> None: 

1949 """ 

1950 Index all declared items in all packages in all libraries. 

1951 

1952 .. rubric:: Algorithm 

1953 

1954 1. Iterate all libraries: 

1955 

1956 1. Iterate all packages |br| 

1957 |rarr| :meth:`pyVHDLModel.Library.IndexPackages` 

1958 

1959 * Index all declared items in that package. |br| 

1960 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems` 

1961 

1962 .. seealso:: 

1963 

1964 :meth:`IndexPackageBodies` 

1965 Index all declared items in all package bodies in all libraries. 

1966 :meth:`IndexEntities` 

1967 Index all declared items in all entities in all libraries. 

1968 :meth:`IndexArchitectures` 

1969 Index all declared items in all architectures in all libraries. 

1970 """ 

1971 for library in self._libraries.values(): 

1972 library.IndexPackages() 

1973 

1974 def IndexPackageBodies(self) -> None: 

1975 """ 

1976 Index all declared items in all packages in all libraries. 

1977 

1978 .. rubric:: Algorithm 

1979 

1980 1. Iterate all libraries: 

1981 

1982 1. Iterate all packages |br| 

1983 |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies` 

1984 

1985 * Index all declared items in that package body. |br| 

1986 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems` 

1987 

1988 .. seealso:: 

1989 

1990 :meth:`IndexPackages` 

1991 Index all declared items in all packages in all libraries. 

1992 :meth:`IndexEntities` 

1993 Index all declared items in all entities in all libraries. 

1994 :meth:`IndexArchitectures` 

1995 Index all declared items in all architectures in all libraries. 

1996 """ 

1997 for library in self._libraries.values(): 

1998 library.IndexPackageBodies() 

1999 

2000 def IndexEntities(self) -> None: 

2001 """ 

2002 Index all declared items in all packages in all libraries. 

2003 

2004 .. rubric:: Algorithm 

2005 

2006 1. Iterate all libraries: 

2007 

2008 1. Iterate all packages |br| 

2009 |rarr| :meth:`pyVHDLModel.Library.IndexEntities` 

2010 

2011 * Index all declared items in that entity. |br| 

2012 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems` 

2013 

2014 .. seealso:: 

2015 

2016 :meth:`IndexPackages` 

2017 Index all declared items in all packages in all libraries. 

2018 :meth:`IndexPackageBodies` 

2019 Index all declared items in all package bodies in all libraries. 

2020 :meth:`IndexArchitectures` 

2021 Index all declared items in all architectures in all libraries. 

2022 """ 

2023 for library in self._libraries.values(): 

2024 library.IndexEntities() 

2025 

2026 def IndexArchitectures(self) -> None: 

2027 """ 

2028 Index all declared items in all packages in all libraries. 

2029 

2030 .. rubric:: Algorithm 

2031 

2032 1. Iterate all libraries: 

2033 

2034 1. Iterate all packages |br| 

2035 |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures` 

2036 

2037 * Index all declared items in that architecture. |br| 

2038 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems` 

2039 

2040 .. seealso:: 

2041 

2042 :meth:`IndexPackages` 

2043 Index all declared items in all packages in all libraries. 

2044 :meth:`IndexPackageBodies` 

2045 Index all declared items in all package bodies in all libraries. 

2046 :meth:`IndexEntities` 

2047 Index all declared items in all entities in all libraries. 

2048 """ 

2049 for library in self._libraries.values(): 

2050 library.IndexArchitectures() 

2051 

2052 def CreateHierarchyGraph(self) -> None: 

2053 """ 

2054 Create the hierarchy graph from dependency graph. 

2055 

2056 .. rubric:: Algorithm 

2057 

2058 1. Iterate all vertices corresponding to entities and architectures in the dependency graph: 

2059 

2060 * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br| 

2061 In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex. 

2062 

2063 * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex. 

2064 * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex. 

2065 

2066 2. Iterate all architectures ... 

2067 

2068 .. todo:: Design::CreateHierarchyGraph describe algorithm 

2069 

2070 1. Iterate all outbound edges 

2071 

2072 .. todo:: Design::CreateHierarchyGraph describe algorithm 

2073 """ 

2074 # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them 

2075 entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture 

2076 for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter): 

2077 hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex") 

2078 vertex.Value._hierarchyVertex = hierarchyVertex 

2079 

2080 # Copy implementation edges from 

2081 for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture): 

2082 for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges(): 

2083 kind: DependencyGraphEdgeKind = dependencyEdge["kind"] 

2084 if DependencyGraphEdgeKind.Implementation in kind: 

2085 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"] 

2086 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex) 

2087 elif DependencyGraphEdgeKind.Instantiation in kind: 

2088 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"] 

2089 

2090 # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks) 

2091 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex): 

2092 continue 

2093 

2094 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex) 

2095 else: 

2096 continue 

2097 

2098 newEdge["kind"] = kind 

2099 

2100 def ComputeCompileOrder(self) -> None: 

2101 def predicate(edge: Edge) -> bool: 

2102 return ( 

2103 DependencyGraphEdgeKind.Implementation in edge["kind"] or 

2104 DependencyGraphEdgeKind.Instantiation in edge["kind"] or 

2105 DependencyGraphEdgeKind.UseClause in edge["kind"] or 

2106 DependencyGraphEdgeKind.ContextReference in edge["kind"] 

2107 ) and edge.Destination["predefined"] is False 

2108 

2109 for edge in self._dependencyGraph.IterateEdges(predicate=predicate): 

2110 sourceDocument: Document = edge.Source.Value.Document 

2111 destinationDocument: Document = edge.Destination.Value.Document 

2112 

2113 sourceVertex = sourceDocument._compileOrderVertex 

2114 destinationVertex = destinationDocument._compileOrderVertex 

2115 

2116 # Don't add self-edges 

2117 if sourceVertex is destinationVertex: 2117 ↛ 2120line 2117 didn't jump to line 2120 because the condition on line 2117 was always true

2118 continue 

2119 # Don't add parallel edges 

2120 elif sourceVertex.HasEdgeToDestination(destinationVertex): 

2121 continue 

2122 

2123 e = sourceVertex.EdgeToVertex(destinationVertex) 

2124 e["kind"] = DependencyGraphEdgeKind.CompileOrder 

2125 

2126 e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"]) 

2127 e["kind"] = DependencyGraphEdgeKind.CompileOrder 

2128 

2129 def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]: 

2130 """ 

2131 Iterate all document in compile-order. 

2132 

2133 .. rubric:: Algorithm 

2134 

2135 * Check if compile-order graph was populated with vertices and its vertices are linked by edges. 

2136 

2137 1. Iterate compile-order graph in topological order. |br| 

2138 :meth:`pyTooling.Graph.Graph.IterateTopologically` 

2139 

2140 * yield the compiler-order vertex' referenced document. 

2141 

2142 :returns: A generator to iterate all documents in compile-order in the design. 

2143 :raises VHDLModelException: If compile-order was not computed. 

2144 

2145 .. seealso:: 

2146 

2147 .. todo:: missing text 

2148 

2149 :meth:`pyVHDLModel.Design.ComputeCompileOrder` 

2150 

2151 """ 

2152 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1: 

2153 raise VHDLModelException(f"Compile order is not yet computed from dependency graph.") 

2154 

2155 for compileOrderNode in self._compileOrderGraph.IterateTopologically(): 

2156 yield compileOrderNode.Value 

2157 

2158 def GetUnusedDesignUnits(self) -> List[DesignUnit]: 

2159 WarningCollector.Raise(NotImplementedWarning(f"Compute unused design units.")) 

2160 

2161 def __repr__(self) -> str: 

2162 """ 

2163 Formats a representation of the design. 

2164 

2165 **Format:** ``Document: 'my_design'`` 

2166 

2167 :returns: String representation of the design. 

2168 """ 

2169 return f"Design: {self._name}" 

2170 

2171 __str__ = __repr__ 

2172 

2173 

2174@export 

2175class Library(ModelEntity, NamedEntityMixin, AllowBlackboxMixin): 

2176 """A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units.""" 

2177 

2178 _allowBlackbox: Nullable[bool] #: Allow blackboxes for components in this library. 

2179 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library. 

2180 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library. 

2181 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library. 

2182 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library. 

2183 _packages: Dict[str, Package] #: Dictionary of all packages defined in a library. 

2184 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library. 

2185 

2186 _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`. 

2187 

2188 def __init__( 

2189 self, 

2190 identifier: str, 

2191 allowBlackbox: Nullable[bool] = None, 

2192 parent: Nullable[ModelEntity] = None 

2193 ) -> None: 

2194 """ 

2195 Initialize a VHDL library. 

2196 

2197 :param identifier: Name of the VHDL library. 

2198 :param allowBlackbox: Specify if blackboxes are allowed in this design. 

2199 :param parent: The parent model entity (design) of this VHDL library. 

2200 """ 

2201 super().__init__(parent) 

2202 NamedEntityMixin.__init__(self, identifier) 

2203 AllowBlackboxMixin.__init__(self, allowBlackbox) 

2204 

2205 self._contexts = {} 

2206 self._configurations = {} 

2207 self._entities = {} 

2208 self._architectures = {} 

2209 self._packages = {} 

2210 self._packageBodies = {} 

2211 

2212 self._dependencyVertex = None 

2213 

2214 @readonly 

2215 def Contexts(self) -> Dict[str, Context]: 

2216 """Returns a list of all context declarations declared in this library.""" 

2217 return self._contexts 

2218 

2219 @readonly 

2220 def Configurations(self) -> Dict[str, Configuration]: 

2221 """Returns a list of all configuration declarations declared in this library.""" 

2222 return self._configurations 

2223 

2224 @readonly 

2225 def Entities(self) -> Dict[str, Entity]: 

2226 """Returns a list of all entity declarations declared in this library.""" 

2227 return self._entities 

2228 

2229 @readonly 

2230 def Architectures(self) -> Dict[str, Dict[str, Architecture]]: 

2231 """Returns a list of all architectures declarations declared in this library.""" 

2232 return self._architectures 

2233 

2234 @readonly 

2235 def Packages(self) -> Dict[str, Package]: 

2236 """Returns a list of all package declarations declared in this library.""" 

2237 return self._packages 

2238 

2239 @readonly 

2240 def PackageBodies(self) -> Dict[str, PackageBody]: 

2241 """Returns a list of all package body declarations declared in this library.""" 

2242 return self._packageBodies 

2243 

2244 @readonly 

2245 def DependencyVertex(self) -> Vertex: 

2246 """ 

2247 Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`). 

2248 

2249 The dependency vertex references this library by its value field. 

2250 

2251 :returns: The corresponding dependency vertex. 

2252 """ 

2253 return self._dependencyVertex 

2254 

2255 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]: 

2256 """ 

2257 Iterate all design units in the library. 

2258 

2259 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units. 

2260 

2261 .. rubric:: Algorithm 

2262 

2263 1. Iterate all contexts in that library. 

2264 2. Iterate all packages in that library. 

2265 3. Iterate all package bodies in that library. 

2266 4. Iterate all entities in that library. 

2267 5. Iterate all architectures in that library. 

2268 6. Iterate all configurations in that library. 

2269 

2270 :param filter: An enumeration with possibly multiple flags to filter the returned design units. 

2271 :returns: A generator to iterate all matched design units in the library. 

2272 

2273 .. seealso:: 

2274 

2275 :meth:`pyVHDLModel.Design.IterateDesignUnits` 

2276 Iterate all design units in the design. 

2277 :meth:`pyVHDLModel.Document.IterateDesignUnits` 

2278 Iterate all design units in the document. 

2279 """ 

2280 if DesignUnitKind.Context in filter: 

2281 for context in self._contexts.values(): 

2282 yield context 

2283 

2284 if DesignUnitKind.Package in filter: 

2285 for package in self._packages.values(): 

2286 yield package 

2287 

2288 if DesignUnitKind.PackageBody in filter: 

2289 for packageBody in self._packageBodies.values(): 

2290 yield packageBody 

2291 

2292 if DesignUnitKind.Entity in filter: 

2293 for entity in self._entities.values(): 

2294 yield entity 

2295 

2296 if DesignUnitKind.Architecture in filter: 

2297 for architectures in self._architectures.values(): 

2298 for architecture in architectures.values(): 

2299 yield architecture 

2300 

2301 if DesignUnitKind.Configuration in filter: 

2302 for configuration in self._configurations.values(): 

2303 yield configuration 

2304 

2305 # for verificationProperty in self._verificationUnits.values(): 

2306 # yield verificationProperty 

2307 # for verificationUnit in self._verificationProperties.values(): 

2308 # yield entity 

2309 # for verificationMode in self._verificationModes.values(): 

2310 # yield verificationMode 

2311 

2312 def LinkArchitectures(self) -> None: 

2313 """ 

2314 Link all architectures to corresponding entities. 

2315 

2316 .. rubric:: Algorithm 

2317 

2318 1. Iterate all architecture groups (grouped per entity symbol's name). 

2319 

2320 * Check if entity symbol's name exists as an entity in this library. 

2321 

2322 1. For each architecture in the same architecture group: 

2323 

2324 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`. 

2325 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity` 

2326 * Set parent namespace of architecture's namespace to the entitie's namespace. 

2327 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex. 

2328 

2329 :raises VHDLModelException: If entity name doesn't exist. 

2330 :raises VHDLModelException: If architecture name already exists for entity. 

2331 

2332 .. seealso:: 

2333 

2334 :meth:`LinkPackageBodies` 

2335 Link all package bodies to corresponding packages. 

2336 :meth:`LinkPackageInstances` 

2337 Link all package instances to corresponding generic packages. 

2338 """ 

2339 for entityName, architecturesPerEntity in self._architectures.items(): 

2340 if entityName not in self._entities: 2340 ↛ 2341line 2340 didn't jump to line 2341 because the condition on line 2340 was never true

2341 architectureNames = "', '".join(architecturesPerEntity.keys()) 

2342 raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.") 

2343 # TODO: search in other libraries to find that entity. 

2344 # TODO: add code position 

2345 

2346 entity = self._entities[entityName] 

2347 for architecture in architecturesPerEntity.values(): 

2348 if architecture._normalizedIdentifier in entity._architectures: 2348 ↛ 2349line 2348 didn't jump to line 2349 because the condition on line 2348 was never true

2349 raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.") 

2350 # TODO: add code position of existing and current 

2351 

2352 entity._architectures[architecture._normalizedIdentifier] = architecture 

2353 architecture._entity.Entity = entity 

2354 architecture._namespace._parentNamespace = entity._namespace 

2355 

2356 # add "architecture -> entity" relation in dependency graph 

2357 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex) 

2358 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation 

2359 

2360 def LinkPackageBodies(self) -> None: 

2361 """ 

2362 Link all package bodies to corresponding packages. 

2363 

2364 .. rubric:: Algorithm 

2365 

2366 1. Iterate all package bodies. 

2367 

2368 * Check if package body symbol's name exists as a package in this library. 

2369 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`. 

2370 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package` 

2371 * Set parent namespace of package body's namespace to the package's namespace. 

2372 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex. 

2373 

2374 :raises VHDLModelException: If package name doesn't exist. 

2375 

2376 .. seealso:: 

2377 

2378 :meth:`LinkArchitectures` 

2379 Link all architectures to corresponding entities. 

2380 :meth:`LinkPackageInstances` 

2381 Link all package instances to corresponding generic packages. 

2382 """ 

2383 for packageBodyName, packageBody in self._packageBodies.items(): 

2384 if packageBodyName not in self._packages: 2384 ↛ 2385line 2384 didn't jump to line 2385 because the condition on line 2384 was never true

2385 raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.") 

2386 

2387 package = self._packages[packageBodyName] 

2388 package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced 

2389 packageBody._package.Package = package 

2390 packageBody._namespace._parentNamespace = package._namespace 

2391 

2392 # add "package body -> package" relation in dependency graph 

2393 dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex) 

2394 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation 

2395 

2396 def LinkPackageInstances(self) -> None: 

2397 """ 

2398 Link all package instances to corresponding generic packages. 

2399 

2400 .. rubric:: Algorithm 

2401 

2402 1. Iterate all package instances. 

2403 

2404 .. todo:: 

2405 

2406 * Check if package body symbol's name exists as a package in this library. 

2407 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`. 

2408 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package` 

2409 * Set parent namespace of package body's namespace to the package's namespace. 

2410 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex. 

2411 

2412 :raises VHDLModelException: If generic package name doesn't exist. 

2413 

2414 .. seealso:: 

2415 

2416 :meth:`LinkArchitectures` 

2417 Link all architectures to corresponding entities. 

2418 :meth:`LinkPackageBodies` 

2419 Link all package bodies to corresponding packages. 

2420 """ 

2421 for packageInstanceName, packageInstance in self._packages.items(): 

2422 if isinstance(packageInstance, PackageInstantiation): 2422 ↛ 2423line 2422 didn't jump to line 2423 because the condition on line 2422 was never true

2423 packageSymbol = packageInstance._packageReference 

2424 packageName = packageSymbol.Name 

2425 libraryName = packageName.Prefix 

2426 

2427 libraryIdentifier = libraryName.NormalizedIdentifier 

2428 packageIdentifier = packageName.NormalizedIdentifier 

2429 

2430 # In case work is used, resolve to the real library name. 

2431 if libraryIdentifier == "work": 

2432 library: Library = self 

2433 libraryIdentifier = library.NormalizedIdentifier 

2434 elif libraryIdentifier not in self._parent._libraries: 

2435 # TODO: This check doesn't trigger if it's the working library. 

2436 raise VHDLModelException(f"Package instantiation of '{packageInstanceName}' references library '{libraryName.Identifier}', which cannot be found in design.") 

2437 else: 

2438 library = self._parent._libraries[libraryIdentifier] 

2439 

2440 try: 

2441 package = library._packages[packageIdentifier] 

2442 except KeyError: 

2443 ex = VHDLModelException( 

2444 f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.") 

2445 ex.add_note(f"Caused in library '{self}' in file '{packageInstance.Document}'.") 

2446 raise ex 

2447 

2448 # FIXME: check if package is a generic package 

2449 if package.GenericCount == 0: 

2450 raise VHDLModelException(f"Package '{libraryName.Identifier}.{packageName.Identifier}' referenced by '{self._identifier}.{packageInstanceName}' is not a generic package.") 

2451 

2452 packageSymbol.Package = package 

2453 

2454 dependency = packageInstance._dependencyVertex.EdgeToVertex(package._dependencyVertex) # , edgeValue=packageReference) 

2455 dependency["kind"] = DependencyGraphEdgeKind.PackageInstantiation 

2456 

2457 packageInstance.Instantiate() 

2458 

2459 def IndexPackages(self) -> None: 

2460 """ 

2461 Index declared items in all packages. 

2462 

2463 .. rubric:: Algorithm 

2464 

2465 1. Iterate all packages: 

2466 

2467 * Index all declared items. |br| 

2468 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems` 

2469 

2470 .. seealso:: 

2471 

2472 :meth:`IndexPackageBodies` 

2473 Index all declared items in a package body. 

2474 :meth:`IndexEntities` 

2475 Index all declared items in an entity. 

2476 :meth:`IndexArchitectures` 

2477 Index all declared items in an architecture. 

2478 """ 

2479 for package in self._packages.values(): 

2480 if isinstance(package, Package): 2480 ↛ 2479line 2480 didn't jump to line 2479 because the condition on line 2480 was always true

2481 package.IndexDeclaredItems() 

2482 

2483 def IndexPackageBodies(self) -> None: 

2484 """ 

2485 Index declared items in all package bodies. 

2486 

2487 .. rubric:: Algorithm 

2488 

2489 1. Iterate all package bodies: 

2490 

2491 * Index all declared items. |br| 

2492 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems` 

2493 

2494 .. seealso:: 

2495 

2496 :meth:`IndexPackages` 

2497 Index all declared items in a package. 

2498 :meth:`IndexEntities` 

2499 Index all declared items in an entity. 

2500 :meth:`IndexArchitectures` 

2501 Index all declared items in an architecture. 

2502 """ 

2503 for packageBody in self._packageBodies.values(): 

2504 packageBody.IndexDeclaredItems() 

2505 

2506 def IndexEntities(self) -> None: 

2507 """ 

2508 Index declared items in all entities. 

2509 

2510 .. rubric:: Algorithm 

2511 

2512 1. Iterate all entities: 

2513 

2514 * Index all declared items. |br| 

2515 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems` 

2516 

2517 .. seealso:: 

2518 

2519 :meth:`IndexPackages` 

2520 Index all declared items in a package. 

2521 :meth:`IndexPackageBodies` 

2522 Index all declared items in a package body. 

2523 :meth:`IndexArchitectures` 

2524 Index all declared items in an architecture. 

2525 """ 

2526 for entity in self._entities.values(): 

2527 entity.IndexDeclaredItems() 

2528 

2529 def IndexArchitectures(self) -> None: 

2530 """ 

2531 Index declared items in all architectures. 

2532 

2533 .. rubric:: Algorithm 

2534 

2535 1. Iterate all architectures: 

2536 

2537 * Index all declared items. |br| 

2538 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems` 

2539 

2540 .. seealso:: 

2541 

2542 :meth:`IndexPackages` 

2543 Index all declared items in a package. 

2544 :meth:`IndexPackageBodies` 

2545 Index all declared items in a package body. 

2546 :meth:`IndexEntities` 

2547 Index all declared items in an entity. 

2548 """ 

2549 for architectures in self._architectures.values(): 

2550 for architecture in architectures.values(): 

2551 architecture.IndexDeclaredItems() 

2552 architecture.IndexStatements() 

2553 

2554 def __repr__(self) -> str: 

2555 """ 

2556 Formats a representation of the library. 

2557 

2558 **Format:** ``Library: 'my_library'`` 

2559 

2560 :returns: String representation of the library. 

2561 """ 

2562 return f"Library: '{self._identifier}'" 

2563 

2564 __str__ = __repr__ 

2565 

2566 

2567@export 

2568class Document(ModelEntity, DocumentedEntityMixin): 

2569 """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units.""" 

2570 

2571 _path: Path #: path to the document. ``None`` if virtual document. 

2572 _vhdlVersion: VHDLVersion #: VHDL version used for analyzing this source file. 

2573 _library: Library #: VHDL library used for analyzing the source file's content into. 

2574 _designUnits: List[DesignUnit] #: List of all design units defined in a document. 

2575 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document. 

2576 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document. 

2577 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document. 

2578 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document. 

2579 _packages: Dict[str, Package] #: Dictionary of all packages defined in a document. 

2580 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document. 

2581 _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document. 

2582 _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document. 

2583 _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document. 

2584 

2585 _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`. 

2586 _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`. 

2587 

2588 def __init__( 

2589 self, 

2590 path: Path, 

2591 documentation: Nullable[str] = None, 

2592 vhdlVersion: VHDLVersion = VHDLVersion.VHDL2008, 

2593 library: Nullable[Library] = None, 

2594 parent: Nullable[ModelEntity] = None 

2595 ) -> None: 

2596 super().__init__(parent) 

2597 DocumentedEntityMixin.__init__(self, documentation) 

2598 

2599 self._path = path 

2600 self._vhdlVersion = vhdlVersion 

2601 self._library = library 

2602 self._designUnits = [] 

2603 self._contexts = {} 

2604 self._configurations = {} 

2605 self._entities = {} 

2606 self._architectures = {} 

2607 self._packages = {} 

2608 self._packageBodies = {} 

2609 self._verificationUnits = {} 

2610 self._verificationProperties = {} 

2611 self._verificationModes = {} 

2612 

2613 self._dependencyVertex = None 

2614 self._compileOrderVertex = None 

2615 

2616 def _AddEntity(self, item: Entity) -> None: 

2617 """ 

2618 Add an entity to the document's lists of design units. 

2619 

2620 :param item: Entity object to be added to the document. 

2621 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Entity`. 

2622 :raises VHDLModelException: If entity name already exists in document. 

2623 """ 

2624 if not isinstance(item, Entity): 2624 ↛ 2625line 2624 didn't jump to line 2625 because the condition on line 2624 was never true

2625 ex = TypeError(f"Parameter 'item' is not of type 'Entity'.") 

2626 if version_info >= (3, 11): # pragma: no cover 

2627 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2628 raise ex 

2629 

2630 identifier = item._normalizedIdentifier 

2631 if identifier in self._entities: 2631 ↛ 2633line 2631 didn't jump to line 2633 because the condition on line 2631 was never true

2632 # TODO: use a more specific exception 

2633 raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.") 

2634 

2635 self._entities[identifier] = item 

2636 self._designUnits.append(item) 

2637 item._document = self 

2638 

2639 # TODO: add entity to _library and vice versa 

2640 

2641 def _AddArchitecture(self, item: Architecture) -> None: 

2642 """ 

2643 Add an architecture to the document's lists of design units. 

2644 

2645 :param item: Architecture object to be added to the document. 

2646 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Architecture`. 

2647 :raises VHDLModelException: If architecture name already exists for the referenced entity name in document. 

2648 """ 

2649 if not isinstance(item, Architecture): 2649 ↛ 2650line 2649 didn't jump to line 2650 because the condition on line 2649 was never true

2650 ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.") 

2651 if version_info >= (3, 11): # pragma: no cover 

2652 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2653 raise ex 

2654 

2655 entity = item._entity.Name 

2656 entityIdentifier = entity._normalizedIdentifier 

2657 try: 

2658 architectures = self._architectures[entityIdentifier] 

2659 if item._normalizedIdentifier in architectures: 

2660 # TODO: use a more specific exception 

2661 # FIXME: this is allowed and should be a warning or a strict mode. 

2662 raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.") 

2663 

2664 architectures[item.Identifier] = item 

2665 except KeyError: 

2666 self._architectures[entityIdentifier] = {item._identifier: item} 

2667 

2668 self._designUnits.append(item) 

2669 item._document = self 

2670 

2671 # TODO: add architecture to _library and vice versa 

2672 

2673 def _AddPackage(self, item: Package) -> None: 

2674 """ 

2675 Add a package to the document's lists of design units. 

2676 

2677 :param item: Package object to be added to the document. 

2678 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Package`. 

2679 :raises VHDLModelException: If package name already exists in document. 

2680 """ 

2681 if not isinstance(item, (Package, PackageInstantiation)): 2681 ↛ 2682line 2681 didn't jump to line 2682 because the condition on line 2681 was never true

2682 ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.") 

2683 if version_info >= (3, 11): # pragma: no cover 

2684 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2685 raise ex 

2686 

2687 identifier = item._normalizedIdentifier 

2688 if identifier in self._packages: 2688 ↛ 2690line 2688 didn't jump to line 2690 because the condition on line 2688 was never true

2689 # TODO: use a more specific exception 

2690 raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.") 

2691 

2692 self._packages[identifier] = item 

2693 self._designUnits.append(item) 

2694 item._document = self 

2695 

2696 # TODO: add package to _library and vice versa 

2697 

2698 def _AddPackageBody(self, item: PackageBody) -> None: 

2699 """ 

2700 Add a package body to the document's lists of design units. 

2701 

2702 :param item: Package body object to be added to the document. 

2703 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.PackageBody`. 

2704 :raises VHDLModelException: If package body name already exists in document. 

2705 """ 

2706 if not isinstance(item, PackageBody): 2706 ↛ 2707line 2706 didn't jump to line 2707 because the condition on line 2706 was never true

2707 ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.") 

2708 if version_info >= (3, 11): # pragma: no cover 

2709 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2710 raise ex 

2711 

2712 identifier = item._normalizedIdentifier 

2713 if identifier in self._packageBodies: 2713 ↛ 2715line 2713 didn't jump to line 2715 because the condition on line 2713 was never true

2714 # TODO: use a more specific exception 

2715 raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.") 

2716 

2717 self._packageBodies[identifier] = item 

2718 self._designUnits.append(item) 

2719 item._document = self 

2720 

2721 # TODO: add packagebody to _library and vice versa 

2722 

2723 def _AddContext(self, item: Context) -> None: 

2724 """ 

2725 Add a context to the document's lists of design units. 

2726 

2727 :param item: Context object to be added to the document. 

2728 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Context`. 

2729 :raises VHDLModelException: If context name already exists in document. 

2730 """ 

2731 if not isinstance(item, Context): 2731 ↛ 2732line 2731 didn't jump to line 2732 because the condition on line 2731 was never true

2732 ex = TypeError(f"Parameter 'item' is not of type 'Context'.") 

2733 if version_info >= (3, 11): # pragma: no cover 

2734 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2735 raise ex 

2736 

2737 identifier = item._normalizedIdentifier 

2738 if identifier in self._contexts: 2738 ↛ 2740line 2738 didn't jump to line 2740 because the condition on line 2738 was never true

2739 # TODO: use a more specific exception 

2740 raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.") 

2741 

2742 self._contexts[identifier] = item 

2743 self._designUnits.append(item) 

2744 item._document = self 

2745 

2746 # TODO: add context to _library and vice versa 

2747 

2748 def _AddConfiguration(self, item: Configuration) -> None: 

2749 """ 

2750 Add a configuration to the document's lists of design units. 

2751 

2752 :param item: Configuration object to be added to the document. 

2753 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Configuration`. 

2754 :raises VHDLModelException: If configuration name already exists in document. 

2755 """ 

2756 if not isinstance(item, Configuration): 2756 ↛ 2757line 2756 didn't jump to line 2757 because the condition on line 2756 was never true

2757 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.") 

2758 if version_info >= (3, 11): # pragma: no cover 

2759 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2760 raise ex 

2761 

2762 identifier = item._normalizedIdentifier 

2763 if identifier in self._configurations: 2763 ↛ 2765line 2763 didn't jump to line 2765 because the condition on line 2763 was never true

2764 # TODO: use a more specific exception 

2765 raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.") 

2766 

2767 self._configurations[identifier] = item 

2768 self._designUnits.append(item) 

2769 item._document = self 

2770 

2771 # TODO: add configuration to _library and vice versa 

2772 

2773 def _AddVerificationUnit(self, item: VerificationUnit) -> None: 

2774 if not isinstance(item, VerificationUnit): 

2775 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.") 

2776 if version_info >= (3, 11): # pragma: no cover 

2777 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2778 raise ex 

2779 

2780 identifier = item._normalizedIdentifier 

2781 if identifier in self._verificationUnits: 

2782 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.") 

2783 

2784 self._verificationUnits[identifier] = item 

2785 self._designUnits.append(item) 

2786 item._document = self 

2787 

2788 # TODO: add vunit to _library and vice versa 

2789 

2790 def _AddVerificationProperty(self, item: VerificationProperty) -> None: 

2791 if not isinstance(item, VerificationProperty): 

2792 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.") 

2793 if version_info >= (3, 11): # pragma: no cover 

2794 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2795 raise ex 

2796 

2797 identifier = item.NormalizedIdentifier 

2798 if identifier in self._verificationProperties: 

2799 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.") 

2800 

2801 self._verificationProperties[identifier] = item 

2802 self._designUnits.append(item) 

2803 item._document = self 

2804 

2805 # TODO: add vprop to _library and vice versa 

2806 

2807 def _AddVerificationMode(self, item: VerificationMode) -> None: 

2808 if not isinstance(item, VerificationMode): 

2809 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.") 

2810 if version_info >= (3, 11): # pragma: no cover 

2811 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2812 raise ex 

2813 

2814 identifier = item.NormalizedIdentifier 

2815 if identifier in self._verificationModes: 

2816 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.") 

2817 

2818 self._verificationModes[identifier] = item 

2819 self._designUnits.append(item) 

2820 item._document = self 

2821 

2822 # TODO: add vmode to _library and vice versa 

2823 

2824 def _AddDesignUnit(self, item: DesignUnit) -> None: 

2825 """ 

2826 Add a design unit to the document's lists of design units. 

2827 

2828 :param item: Configuration object to be added to the document. 

2829 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.DesignUnit`. 

2830 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`. 

2831 :raises VHDLModelException: If configuration name already exists in document. 

2832 """ 

2833 if not isinstance(item, DesignUnit): 2833 ↛ 2834line 2833 didn't jump to line 2834 because the condition on line 2833 was never true

2834 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.") 

2835 if version_info >= (3, 11): # pragma: no cover 

2836 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2837 raise ex 

2838 

2839 if isinstance(item, Entity): 

2840 self._AddEntity(item) 

2841 elif isinstance(item, Architecture): 

2842 self._AddArchitecture(item) 

2843 elif isinstance(item, Package): 

2844 self._AddPackage(item) 

2845 elif isinstance(item, PackageBody): 

2846 self._AddPackageBody(item) 

2847 elif isinstance(item, Context): 

2848 self._AddContext(item) 

2849 elif isinstance(item, Configuration): 2849 ↛ 2851line 2849 didn't jump to line 2851 because the condition on line 2849 was always true

2850 self._AddConfiguration(item) 

2851 elif isinstance(item, VerificationUnit): 

2852 self._AddVerificationUnit(item) 

2853 elif isinstance(item, VerificationProperty): 

2854 self._AddVerificationProperty(item) 

2855 elif isinstance(item, VerificationMode): 

2856 self._AddVerificationMode(item) 

2857 else: 

2858 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.") 

2859 if version_info >= (3, 11): # pragma: no cover 

2860 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.") 

2861 raise ex 

2862 

2863 @readonly 

2864 def Path(self) -> Path: 

2865 """ 

2866 Read-only property to access the document's path (:attr:`_path`). 

2867 

2868 :returns: The path of this document. 

2869 """ 

2870 return self._path 

2871 

2872 @readonly 

2873 def VHDLVersion(self) -> VHDLVersion: 

2874 """ 

2875 Read-only property to access the document's VHDL version (:attr:`_vhdlVersion`). 

2876 

2877 :returns: VHDL version used to analyze this VHDL file. 

2878 """ 

2879 return self._vhdlVersion 

2880 

2881 # @property 

2882 @readonly 

2883 def Library(self) -> Library: 

2884 """ 

2885 Read-only property to access the document's VHDL library (:attr:`_library`). 

2886 

2887 :returns: VHDL library used to analyze the VHDL file's design units into. 

2888 """ 

2889 return self._library 

2890 

2891 # @Library.setter 

2892 # def Library(self, library: Library) -> None: 

2893 # self._library = library 

2894 # 

2895 # # TODO: check and set library to design unit? 

2896 

2897 @readonly 

2898 def DesignUnits(self) -> List[DesignUnit]: 

2899 """ 

2900 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`). 

2901 

2902 :returns: List of all design units. 

2903 """ 

2904 return self._designUnits 

2905 

2906 @readonly 

2907 def Contexts(self) -> Dict[str, Context]: 

2908 """ 

2909 Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`). 

2910 

2911 :returns: List of all contexts. 

2912 """ 

2913 return self._contexts 

2914 

2915 @readonly 

2916 def Configurations(self) -> Dict[str, Configuration]: 

2917 """ 

2918 Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`). 

2919 

2920 :returns: List of all configurations. 

2921 """ 

2922 return self._configurations 

2923 

2924 @readonly 

2925 def Entities(self) -> Dict[str, Entity]: 

2926 """ 

2927 Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`). 

2928 

2929 :returns: List of all entities. 

2930 """ 

2931 return self._entities 

2932 

2933 @readonly 

2934 def Architectures(self) -> Dict[str, Dict[str, Architecture]]: 

2935 """ 

2936 Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`). 

2937 

2938 :returns: List of all architectures. 

2939 """ 

2940 return self._architectures 

2941 

2942 @readonly 

2943 def Packages(self) -> Dict[str, Package]: 

2944 """ 

2945 Read-only property to access a list of all package declarations found in this document (:attr:`_packages`). 

2946 

2947 :returns: List of all packages. 

2948 """ 

2949 return self._packages 

2950 

2951 @readonly 

2952 def PackageBodies(self) -> Dict[str, PackageBody]: 

2953 """ 

2954 Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`). 

2955 

2956 :returns: List of all package bodies. 

2957 """ 

2958 return self._packageBodies 

2959 

2960 @readonly 

2961 def VerificationUnits(self) -> Dict[str, VerificationUnit]: 

2962 """ 

2963 Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`). 

2964 

2965 :returns: List of all verification units. 

2966 """ 

2967 return self._verificationUnits 

2968 

2969 @readonly 

2970 def VerificationProperties(self) -> Dict[str, VerificationProperty]: 

2971 """ 

2972 Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`). 

2973 

2974 :returns: List of all verification properties. 

2975 """ 

2976 return self._verificationProperties 

2977 

2978 @readonly 

2979 def VerificationModes(self) -> Dict[str, VerificationMode]: 

2980 """ 

2981 Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`). 

2982 

2983 :returns: List of all verification modes. 

2984 """ 

2985 return self._verificationModes 

2986 

2987 @readonly 

2988 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]: 

2989 """ 

2990 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`). 

2991 

2992 The compile-order vertex references this document by its value field. 

2993 

2994 :returns: The corresponding compile-order vertex. 

2995 """ 

2996 return self._compileOrderVertex 

2997 

2998 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]: 

2999 """ 

3000 Iterate all design units in the document. 

3001 

3002 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units. 

3003 

3004 .. rubric:: Algorithm 

3005 

3006 * If contexts are selected in the filter: 

3007 

3008 1. Iterate all contexts in that library. 

3009 

3010 * If packages are selected in the filter: 

3011 

3012 1. Iterate all packages in that library. 

3013 

3014 * If package bodies are selected in the filter: 

3015 

3016 1. Iterate all package bodies in that library. 

3017 

3018 * If entites are selected in the filter: 

3019 

3020 1. Iterate all entites in that library. 

3021 

3022 * If architectures are selected in the filter: 

3023 

3024 1. Iterate all architectures in that library. 

3025 

3026 * If configurations are selected in the filter: 

3027 

3028 1. Iterate all configurations in that library. 

3029 

3030 :param filter: An enumeration with possibly multiple flags to filter the returned design units. 

3031 :returns: A generator to iterate all matched design units in the document. 

3032 

3033 .. seealso:: 

3034 

3035 :meth:`pyVHDLModel.Design.IterateDesignUnits` 

3036 Iterate all design units in the design. 

3037 :meth:`pyVHDLModel.Library.IterateDesignUnits` 

3038 Iterate all design units in the library. 

3039 """ 

3040 if DesignUnitKind.Context in filter: 3040 ↛ 3044line 3040 didn't jump to line 3044 because the condition on line 3040 was always true

3041 for context in self._contexts.values(): 

3042 yield context 

3043 

3044 if DesignUnitKind.Package in filter: 3044 ↛ 3048line 3044 didn't jump to line 3048 because the condition on line 3044 was always true

3045 for package in self._packages.values(): 

3046 yield package 

3047 

3048 if DesignUnitKind.PackageBody in filter: 3048 ↛ 3052line 3048 didn't jump to line 3052 because the condition on line 3048 was always true

3049 for packageBody in self._packageBodies.values(): 

3050 yield packageBody 

3051 

3052 if DesignUnitKind.Entity in filter: 3052 ↛ 3056line 3052 didn't jump to line 3056 because the condition on line 3052 was always true

3053 for entity in self._entities.values(): 

3054 yield entity 

3055 

3056 if DesignUnitKind.Architecture in filter: 3056 ↛ 3061line 3056 didn't jump to line 3061 because the condition on line 3056 was always true

3057 for architectures in self._architectures.values(): 

3058 for architecture in architectures.values(): 

3059 yield architecture 

3060 

3061 if DesignUnitKind.Configuration in filter: 3061 ↛ exitline 3061 didn't return from function 'IterateDesignUnits' because the condition on line 3061 was always true

3062 for configuration in self._configurations.values(): 

3063 yield configuration 

3064 

3065 # for verificationProperty in self._verificationUnits.values(): 

3066 # yield verificationProperty 

3067 # for verificationUnit in self._verificationProperties.values(): 

3068 # yield entity 

3069 # for verificationMode in self._verificationModes.values(): 

3070 # yield verificationMode 

3071 

3072 def __repr__(self) -> str: 

3073 """ 

3074 Formats a representation of the document. 

3075 

3076 **Format:** ``Document: 'path/to/file.vhdl'`` 

3077 

3078 :returns: String representation of the document. 

3079 """ 

3080 return f"Document: '{self._path}'" 

3081 

3082 __str__ = __repr__