Coverage for pyVHDLModel/__init__.py: 64%

1186 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-11 23:50 +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.39.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 

60 

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

62 

63from pyTooling.Common import getFullyQualifiedName 

64from pyTooling.Decorators import export, readonly 

65from pyTooling.Graph import Graph, Vertex, Edge 

66from pyTooling.Warning import WarningCollector 

67 

68from pyVHDLModel.Exception import VHDLModelException, NotImplementedWarning, BlackboxWarning 

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

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

71from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError 

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

73from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression 

74from pyVHDLModel.Namespace import Namespace 

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

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

77from pyVHDLModel.Common import AllowBlackboxMixin 

78from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin 

79from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation 

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

81from pyVHDLModel.Concurrent import GenerateBranch, ConcurrentStatementsMixin, ConcurrentBlockStatement 

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

83from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode 

84from pyVHDLModel.Instantiation import PackageInstantiation 

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

86 

87 

88@export 

89@unique 

90class VHDLVersion(Enum): 

91 """ 

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

93 

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

95 enumeration value. 

96 

97 This enumeration supports compare operators. 

98 """ 

99 

100 Any = -1 #: Any 

101 VHDL87 = 87 #: VHDL-1987 

102 VHDL93 = 93 #: VHDL-1993 

103 AMS93 = 1993 #: VHDL-AMS-1993 

104 AMS99 = 1999 #: VHDL-AMS-1999 

105 VHDL2000 = 2000 #: VHDL-2000 

106 VHDL2002 = 2002 #: VHDL-2002 

107 VHDL2008 = 2008 #: VHDL-2008 

108 AMS2017 = 2017 #: VHDL-AMS-2017 

109 VHDL2019 = 2019 #: VHDL-2019 

110 Latest = 10000 #: Latest VHDL (2019) 

111 

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

113 -1: Any, 

114 87: VHDL87, 

115 93: VHDL93, 

116 # 93: AMS93, 

117 99: AMS99, 

118 0: VHDL2000, 

119 2: VHDL2002, 

120 8: VHDL2008, 

121 17: AMS2017, 

122 19: VHDL2019, 

123 1987: VHDL87, 

124 # 1993: VHDL93, 

125 1993: AMS93, 

126 1999: AMS99, 

127 2000: VHDL2000, 

128 2002: VHDL2002, 

129 2008: VHDL2008, 

130 2017: AMS2017, 

131 2019: VHDL2019, 

132 10000: Latest, 

133 "Any": Any, 

134 "87": VHDL87, 

135 "93": VHDL93, 

136 # "93": AMS93, 

137 "99": AMS99, 

138 "00": VHDL2000, 

139 "02": VHDL2002, 

140 "08": VHDL2008, 

141 "17": AMS2017, 

142 "19": VHDL2019, 

143 "1987": VHDL87, 

144 # "1993": VHDL93, 

145 "1993": AMS93, 

146 "1999": AMS99, 

147 "2000": VHDL2000, 

148 "2002": VHDL2002, 

149 "2008": VHDL2008, 

150 "2017": AMS2017, 

151 "2019": VHDL2019, 

152 "Latest": Latest, 

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

154 

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

156 """Patch the embedded MAP dictionary""" 

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

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

159 self.__class__.__VERSION_MAPPINGS__[k] = self 

160 

161 @classmethod 

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

163 """ 

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

165 

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

167 :returns: Enumeration value. 

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

169 """ 

170 try: 

171 return cls.__VERSION_MAPPINGS__[value] 

172 except KeyError: 

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

174 

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

176 """ 

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

178 

179 :param other: Parameter to compare against. 

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

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

182 """ 

183 if isinstance(other, VHDLVersion): 

184 return self.value < other.value 

185 else: 

186 ex = TypeError("Second operand is not of type 'VHDLVersion'.") 

187 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.") 

188 raise ex 

189 

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

191 """ 

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

193 

194 :param other: Parameter to compare against. 

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

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

197 """ 

198 if isinstance(other, VHDLVersion): 

199 return self.value <= other.value 

200 else: 

201 ex = TypeError("Second operand is not of type 'VHDLVersion'.") 

202 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.") 

203 raise ex 

204 

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

206 """ 

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

208 

209 :param other: Parameter to compare against. 

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

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

212 """ 

213 if isinstance(other, VHDLVersion): 

214 return self.value > other.value 

215 else: 

216 ex = TypeError("Second operand is not of type 'VHDLVersion'.") 

217 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.") 

218 raise ex 

219 

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

221 """ 

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

223 

224 :param other: Parameter to compare against. 

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

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

227 """ 

228 if isinstance(other, VHDLVersion): 

229 return self.value >= other.value 

230 else: 

231 ex = TypeError("Second operand is not of type 'VHDLVersion'.") 

232 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.") 

233 raise ex 

234 

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

236 """ 

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

238 

239 :param other: Parameter to compare against. 

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

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

242 """ 

243 if isinstance(other, VHDLVersion): 

244 return self.value != other.value 

245 else: 

246 ex = TypeError("Second operand is not of type 'VHDLVersion'.") 

247 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.") 

248 raise ex 

249 

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

251 """ 

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

253 

254 :param other: Parameter to compare against. 

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

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

257 """ 

258 if isinstance(other, VHDLVersion): 

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

260 return True 

261 else: 

262 return self.value == other.value 

263 else: 

264 ex = TypeError("Second operand is not of type 'VHDLVersion'.") 

265 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.") 

266 raise ex 

267 

268 def __hash__(self) -> int: 

269 """ 

270 Return the hash of the VHDL version using the underlying version number. 

271 

272 .. note:: 

273 

274 ``Any`` compares equal to every other member (see :meth:`__eq__`), which no hash value can satisfy 

275 simultaneously for all members without collapsing every member to the same hash. This implementation 

276 hashes by ``self.value``, which is internally consistent for all comparisons *except* those 

277 involving ``Any`` - avoid using ``Any`` as a dict key or set member. 

278 

279 :returns: Hash value of the underlying VHDL version number. 

280 """ 

281 return hash(self.value) 

282 

283 @readonly 

284 def IsVHDL(self) -> bool: 

285 """ 

286 Check if the version is a VHDL (not VHDL-AMS) version. 

287 

288 :returns: ``True``, if the version is a VHDL version. 

289 """ 

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

291 

292 @readonly 

293 def IsAMS(self) -> bool: 

294 """ 

295 Check if the version is a VHDL-AMS (not VHDL) version. 

296 

297 :returns: ``True``, if the version is a VHDL-AMS version. 

298 """ 

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

300 

301 def __str__(self) -> str: 

302 """ 

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

304 

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

306 """ 

307 if self.value == self.Any.value: 

308 return "VHDL'Any" 

309 elif self.value == self.Latest.value: 

310 return "VHDL'Latest" 

311 

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

313 if self.IsVHDL: 

314 return f"VHDL'{year}" 

315 else: 

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

317 

318 def __repr__(self) -> str: 

319 """ 

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

321 

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

323 """ 

324 if self.value == self.Any.value: 

325 return "Any" 

326 elif self.value == self.Latest.value: 

327 return "Latest" 

328 else: 

329 return str(self.value) 

330 

331 

332@export 

333class IEEEFlavor(Flag): 

334 """ 

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

336 

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

338 Supported flavors are: 

339 

340 * ``Synopsys`` 

341 * ``MentorGraphics`` 

342 

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

344 Supported extensions are: 

345 

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

347 

348 """ 

349 Unknown = 0 #: Unknown IEEE flavor 

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

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

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

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

354 

355 

356@export 

357@unique 

358class ObjectClass(Enum): 

359 """ 

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

361 

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

363 """ 

364 

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

366 Constant = 1 #: Constant 

367 Variable = 2 #: Variable 

368 Signal = 3 #: Signal 

369 File = 4 #: File 

370 Type = 5 #: Type 

371 # FIXME: Package? 

372 Procedure = 6 #: Procedure 

373 Function = 7 #: Function 

374 

375 def __str__(self) -> str: 

376 """ 

377 Formats the object class. 

378 

379 :returns: Formatted object class. 

380 """ 

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

382 

383 

384@export 

385@unique 

386class DesignUnitKind(Flag): 

387 """ 

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

389 

390 """ 

391 Context = auto() #: Context 

392 Package = auto() #: Package 

393 PackageBody = auto() #: Package Body 

394 Entity = auto() #: Entity 

395 Architecture = auto() #: Architecture 

396 Configuration = auto() #: Configuration 

397 

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

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

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

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

402 

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

404 

405 

406@export 

407@unique 

408class DependencyGraphVertexKind(Flag): 

409 """ 

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

411 """ 

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

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

414 

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

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

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

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

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

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

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

422 

423 

424@export 

425@unique 

426class DependencyGraphEdgeKind(Flag): 

427 """ 

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

429 """ 

430 Document = auto() 

431 Library = auto() 

432 Context = auto() 

433 Package = auto() 

434 Entity = auto() 

435 # Architecture = auto() 

436 Configuration = auto() 

437 Component = auto() 

438 

439 DeclaredIn = auto() 

440 Order = auto() 

441 Reference = auto() 

442 Implementation = auto() 

443 Instantiation = auto() 

444 

445 SourceFile = Document | DeclaredIn 

446 CompileOrder = Document | Order 

447 

448 LibraryClause = Library | Reference 

449 UseClause = Package | Reference 

450 ContextReference = Context | Reference 

451 

452 EntityImplementation = Entity | Implementation 

453 PackageImplementation = Package | Implementation 

454 

455 EntityInstantiation = Entity | Instantiation 

456 ComponentInstantiation = Component | Instantiation 

457 ConfigurationInstantiation = Configuration | Instantiation 

458 

459 PackageInstantiation = Package | Instantiation 

460 

461 

462@export 

463@unique 

464class ObjectGraphVertexKind(Flag): 

465 """ 

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

467 """ 

468 Type = auto() 

469 Subtype = auto() 

470 

471 Constant = auto() 

472 DeferredConstant = auto() 

473 Variable = auto() 

474 Signal = auto() 

475 File = auto() 

476 

477 Alias = auto() 

478 

479 

480@export 

481@unique 

482class ObjectGraphEdgeKind(Flag): 

483 """ 

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

485 """ 

486 BaseType = auto() 

487 Subtype = auto() 

488 

489 ReferenceInExpression = auto() 

490 

491 

492@export 

493class Design(ModelEntity, AllowBlackboxMixin): 

494 """ 

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

496 

497 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 

498 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 

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

500 

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

502 

503 * :attr:`DependencyGraph` 

504 * :attr:`CompileOrderGraph` 

505 * :attr:`HierarchyGraph` 

506 * :attr:`ObjectGraph` 

507 """ 

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

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

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

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

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

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

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

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

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

517 

518 def __init__( 

519 self, 

520 name: Nullable[str] = None, 

521 allowBlackbox: bool = False 

522 ) -> None: 

523 """ 

524 Initialize a VHDL design. 

525 

526 :param name: Name of the design. 

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

528 """ 

529 super().__init__() 

530 AllowBlackboxMixin.__init__(self, allowBlackbox) 

531 

532 self._name = name 

533 

534 self._libraries = {} 

535 self._documents = [] 

536 

537 self._compileOrderGraph = Graph() 

538 self._dependencyGraph = Graph() 

539 self._hierarchyGraph = Graph() 

540 self._objectGraph = Graph() 

541 self._toplevel = None 

542 

543 @readonly 

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

545 """ 

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

547 

548 :returns: The name of the design. 

549 """ 

550 return self._name 

551 

552 @readonly 

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

554 """ 

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

556 

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

558 """ 

559 return self._libraries 

560 

561 @readonly 

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

563 """ 

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

565 

566 :returns: A list of all documents. 

567 """ 

568 return self._documents 

569 

570 @readonly 

571 def CompileOrderGraph(self) -> Graph: 

572 """ 

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

574 

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

576 """ 

577 return self._compileOrderGraph 

578 

579 @readonly 

580 def DependencyGraph(self) -> Graph: 

581 """ 

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

583 

584 :returns: Reference to the dependency graph. 

585 """ 

586 return self._dependencyGraph 

587 

588 @readonly 

589 def HierarchyGraph(self) -> Graph: 

590 """ 

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

592 

593 :returns: Reference to the hierarchy graph. 

594 """ 

595 return self._hierarchyGraph 

596 

597 @readonly 

598 def ObjectGraph(self) -> Graph: 

599 """ 

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

601 

602 :returns: Reference to the object graph. 

603 """ 

604 return self._objectGraph 

605 

606 @readonly 

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

608 """ 

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

610 

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

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

613 

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

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

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

617 """ 

618 # Check for cached result 

619 if self._toplevel is not None: 619 ↛ 620line 619 didn't jump to line 620 because the condition on line 619 was never true

620 return self._toplevel 

621 

622 if self._hierarchyGraph.VertexCount == 0: 

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

624 

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

626 if len(roots) == 1: 626 ↛ 633line 626 didn't jump to line 633 because the condition on line 626 was always true

627 toplevel = roots[0] 

628 self._hierarchyGraph["toplevel"] = toplevel 

629 self._toplevel = toplevel.Value 

630 

631 return toplevel.Value 

632 else: 

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

634 

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

636 """ 

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

638 

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

640 

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

642 """ 

643 from pyVHDLModel.STD import Std 

644 

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

646 

647 library = Std() 

648 for designUnit in library.IterateDesignUnits(): 

649 doc._AddDesignUnit(designUnit) 

650 

651 self.AddLibrary(library) 

652 

653 return library 

654 

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

656 """ 

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

658 

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

660 

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

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

663 """ 

664 from pyVHDLModel.IEEE import Ieee 

665 

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

667 

668 library = Ieee(flavor) 

669 for designUnit in library.IterateDesignUnits(): 

670 doc._AddDesignUnit(designUnit) 

671 

672 self.AddLibrary(library) 

673 

674 return library 

675 

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

677 """ 

678 Add a VHDL library to the design. 

679 

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

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

682 

683 :param library: Library object to loaded. 

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

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

686 """ 

687 libraryIdentifier = library.NormalizedIdentifier 

688 if libraryIdentifier in self._libraries: 

689 raise LibraryExistsInDesignError(library) 

690 

691 if library._parent is not None: 

692 raise LibraryRegisteredToForeignDesignError(library) 

693 

694 self._libraries[libraryIdentifier] = library 

695 library.Parent = self 

696 

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

698 """ 

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

700 

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

702 

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

704 :returns: The VHDL library object. 

705 """ 

706 libraryIdentifier = libraryName.lower() 

707 try: 

708 return self._libraries[libraryIdentifier] 

709 except KeyError: 

710 lib = Library(libraryName, parent=self) 

711 self._libraries[libraryIdentifier] = lib 

712 lib.Parent = self 

713 return lib 

714 

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

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

717 """ 

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

719 

720 .. rubric:: Algorithm 

721 

722 1. Iterate all entities in the document 

723 

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

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

726 

727 2. Iterate all architectures in the document 

728 

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

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

731 

732 3. Iterate all packages in the document 

733 

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

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

736 

737 4. Iterate all package bodies in the document 

738 

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

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

741 

742 5. Iterate all configurations in the document 

743 

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

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

746 

747 6. Iterate all contexts in the document 

748 

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

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

751 

752 :param document: The VHDL source code file. 

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

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

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

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

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

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

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

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

761 """ 

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

763 # should the libraries parent be checked too? 

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

765 raise LibraryNotRegisteredError(library) 

766 

767 self._documents.append(document) 

768 document.Parent = self 

769 #document.Library = library 

770 

771 document._library = library 

772 

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

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

775 raise EntityExistsInLibraryError(entity, library) 

776 

777 library._entities[entityIdentifier] = entity 

778 entity.Library = library 

779 

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

781 try: 

782 architecturesPerEntity = library._architectures[entityIdentifier] 

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

784 if architectureIdentifier in architecturesPerEntity: 

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

786 

787 architecturesPerEntity[architectureIdentifier] = architecture 

788 architecture.Library = library 

789 except KeyError: 

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

791 library._architectures[entityIdentifier] = architecturesPerEntity 

792 

793 for architecture in architecturesPerEntity.values(): 

794 architecture.Library = library 

795 

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

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

798 raise PackageExistsInLibraryError(package, library) 

799 

800 library._packages[packageIdentifier] = package 

801 package.Library = library 

802 

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

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

805 raise PackageBodyExistsError(packageBody, library) 

806 

807 library._packageBodies[packageBodyIdentifier] = packageBody 

808 packageBody.Library = library 

809 

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

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

812 raise ConfigurationExistsInLibraryError(configuration, library) 

813 

814 library._configurations[configurationIdentifier] = configuration 

815 configuration.Library = library 

816 

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

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

819 raise ContextExistsInLibraryError(context, library) 

820 

821 library._contexts[contextIdentifier] = context 

822 context.Library = library 

823 

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

825 """ 

826 Iterate all design units in the design. 

827 

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

829 

830 .. rubric:: Algorithm 

831 

832 1. Iterate all VHDL libraries. 

833 

834 1. Iterate all contexts in that library. 

835 2. Iterate all packages in that library. 

836 3. Iterate all package bodies in that library. 

837 4. Iterate all entites in that library. 

838 5. Iterate all architectures in that library. 

839 6. Iterate all configurations in that library. 

840 

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

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

843 

844 .. seealso:: 

845 

846 :meth:`pyVHDLModel.Library.IterateDesignUnits` 

847 Iterate all design units in the library. 

848 :meth:`pyVHDLModel.Document.IterateDesignUnits` 

849 Iterate all design units in the document. 

850 """ 

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

852 yield from library.IterateDesignUnits(filter) 

853 

854 def Analyze(self) -> None: 

855 """ 

856 Analyze the whole design. 

857 

858 .. rubric:: Algorithm 

859 

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

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

862 2. Analyze dependencies of types and objects. 

863 

864 .. seealso:: 

865 

866 :meth:`AnalyzeDependencies` 

867 Analyze the dependencies of design units. 

868 

869 :meth:`AnalyzeObjects` 

870 Analyze the dependencies of types and objects. 

871 """ 

872 self.AnalyzeDependencies() 

873 # self.AnalyzeObjects() 

874 

875 def AnalyzeDependencies(self) -> None: 

876 """ 

877 Analyze the dependencies of design units. 

878 

879 .. rubric:: Algorithm 

880 

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

882 |rarr| :meth:`CreateDependencyGraph` 

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

884 |rarr| :meth:`CreateCompileOrderGraph` 

885 3. Index all packages. |br| 

886 |rarr| :meth:`IndexPackages` 

887 4. Index all architectures. |br| 

888 |rarr| :meth:`IndexArchitectures` 

889 5. Link all contexts |br| 

890 |rarr| :meth:`LinkContexts` 

891 6. Link all architectures. |br| 

892 |rarr| :meth:`LinkArchitectures` 

893 7. Link all package bodies. |br| 

894 |rarr| :meth:`LinkPackageBodies` 

895 8. Link all package instances. |br| 

896 |rarr| :meth:`LinkPackageInstances` 

897 9. Link all library references. |br| 

898 |rarr| :meth:`LinkLibraryReferences` 

899 10. Link all package references. |br| 

900 |rarr| :meth:`LinkPackageReferences` 

901 11. Link all context references. |br| 

902 |rarr| :meth:`LinkContextReferences` 

903 12. Link all components. |br| 

904 |rarr| :meth:`LinkComponents` 

905 13. Link all instantiations. |br| 

906 |rarr| :meth:`LinkInstantiations` 

907 14. Create the hierarchy graph. |br| 

908 |rarr| :meth:`CreateHierarchyGraph` 

909 15. Compute the compile order. |br| 

910 |rarr| :meth:`ComputeCompileOrder` 

911 """ 

912 self.CreateDependencyGraph() 

913 self.CreateCompileOrderGraph() 

914 

915 self.IndexPackages() 

916 self.IndexArchitectures() 

917 

918 self.LinkContexts() 

919 self.LinkArchitectures() 

920 self.LinkPackageBodies() 

921 self.LinkPackageInstances() 

922 self.LinkLibraryReferences() 

923 self.LinkPackageReferences() 

924 self.LinkContextReferences() 

925 

926 self.LinkComponents() 

927 self.LinkInstantiations() 

928 self.CreateHierarchyGraph() 

929 self.ComputeCompileOrder() 

930 

931 def AnalyzeObjects(self) -> None: 

932 """ 

933 Analyze the dependencies of types and objects. 

934 

935 .. rubric:: Algorithm 

936 

937 1. Index all entities. |br| 

938 |rarr| :meth:`IndexEntities` 

939 2. Index all package bodies. |br| 

940 |rarr| :meth:`IndexPackageBodies` 

941 3. Import objects. |br| 

942 |rarr| :meth:`ImportObjects` 

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

944 |rarr| :meth:`CreateTypeAndObjectGraph` 

945 """ 

946 self.IndexEntities() 

947 self.IndexPackageBodies() 

948 

949 self.ImportObjects() 

950 self.CreateTypeAndObjectGraph() 

951 

952 def CreateDependencyGraph(self) -> None: 

953 """ 

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

955 

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

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

958 

959 Each vertex has the following properties: 

960 

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

962 * The vertex' value references the design unit. 

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

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

965 

966 .. rubric:: Algorithm 

967 

968 1. Iterate all libraries in the design. 

969 

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

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

972 

973 1. Iterate all contexts in that library. 

974 

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

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

977 

978 2. Iterate all packages in that library. 

979 

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

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

982 

983 3. Iterate all package bodies in that library. 

984 

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

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

987 

988 4. Iterate all entities in that library. 

989 

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

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

992 

993 5. Iterate all architectures in that library. 

994 

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

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

997 

998 6. Iterate all configurations in that library. 

999 

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

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

1002 """ 

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

1004 

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

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

1007 dependencyVertex["kind"] = DependencyGraphVertexKind.Library 

1008 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries 

1009 library._dependencyVertex = dependencyVertex 

1010 

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

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

1013 dependencyVertex["kind"] = DependencyGraphVertexKind.Context 

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

1015 context._dependencyVertex = dependencyVertex 

1016 

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

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

1019 dependencyVertex["kind"] = DependencyGraphVertexKind.Package 

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

1021 package._dependencyVertex = dependencyVertex 

1022 

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

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

1025 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody 

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

1027 packageBody._dependencyVertex = dependencyVertex 

1028 

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

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

1031 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity 

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

1033 entity._dependencyVertex = dependencyVertex 

1034 

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

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

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

1038 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture 

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

1040 architecture._dependencyVertex = dependencyVertex 

1041 

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

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

1044 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration 

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

1046 configuration._dependencyVertex = dependencyVertex 

1047 

1048 def CreateCompileOrderGraph(self) -> None: 

1049 """ 

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

1051 

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

1053 graph and bidirectionally referenced. 

1054 

1055 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 

1056 document relationship. 

1057 

1058 Each added vertex has the following properties: 

1059 

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

1061 * The vertex' value references the document. 

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

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

1064 

1065 .. rubric:: Algorithm 

1066 

1067 1. Iterate all documents in the design. 

1068 

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

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

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

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

1073 

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

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

1076 

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

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

1079 

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

1081 """ 

1082 for document in self._documents: 

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

1084 dependencyVertex["kind"] = DependencyGraphVertexKind.Document 

1085 document._dependencyVertex = dependencyVertex 

1086 

1087 compilerOrderVertex = dependencyVertex.Copy( 

1088 self._compileOrderGraph, 

1089 copyDict=True, 

1090 linkingKeyToOriginalVertex="dependencyVertex", 

1091 linkingKeyFromOriginalVertex="compileOrderVertex" 

1092 ) 

1093 document._compileOrderVertex = compilerOrderVertex 

1094 

1095 for designUnit in document._designUnits: 

1096 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex) 

1097 edge["kind"] = DependencyGraphEdgeKind.SourceFile 

1098 

1099 def ImportObjects(self) -> None: 

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

1101 from pyVHDLModel.Declaration import AttributeSpecification 

1102 

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

1104 for referencedPackage in referencedLibrary.values(): 

1105 for declaredItem in referencedPackage._declaredItems: 

1106 if isinstance(declaredItem, MultipleNamedEntityMixin): 

1107 for normalizedIdentifier in declaredItem._normalizedIdentifiers: 

1108 package._namespace._elements[normalizedIdentifier] = declaredItem 

1109 elif isinstance(declaredItem, NamedEntityMixin): 

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

1111 elif isinstance(declaredItem, AttributeSpecification): 

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

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

1114 

1115 else: 

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

1117 

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

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

1120 _ImportObjects(package) 

1121 

1122 for document in self.IterateDocumentsInCompileOrder(): 

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

1124 _ImportObjects(package) 

1125 

1126 def CreateTypeAndObjectGraph(self) -> None: 

1127 def _HandlePackage(package) -> None: 

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

1129 

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

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

1132 deferredConstantVertex = Vertex( 

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

1134 value=deferredConstant, 

1135 graph=self._objectGraph 

1136 ) 

1137 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant 

1138 deferredConstant._objectVertex = deferredConstantVertex 

1139 

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

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

1142 constantVertex = Vertex( 

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

1144 value=constant, 

1145 graph=self._objectGraph 

1146 ) 

1147 constantVertex["kind"] = ObjectGraphVertexKind.Constant 

1148 constant._objectVertex = constantVertex 

1149 

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

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

1152 typeVertex = Vertex( 

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

1154 value=type, 

1155 graph=self._objectGraph 

1156 ) 

1157 typeVertex["kind"] = ObjectGraphVertexKind.Type 

1158 type._objectVertex = typeVertex 

1159 

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

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

1162 subtypeVertex = Vertex( 

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

1164 value=subtype, 

1165 graph=self._objectGraph 

1166 ) 

1167 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype 

1168 subtype._objectVertex = subtypeVertex 

1169 

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

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

1172 functionVertex = Vertex( 

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

1174 value=function, 

1175 graph=self._objectGraph 

1176 ) 

1177 functionVertex["kind"] = ObjectGraphVertexKind.Function 

1178 function._objectVertex = functionVertex 

1179 

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

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

1182 procedureVertex = Vertex( 

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

1184 value=procedure, 

1185 graph=self._objectGraph 

1186 ) 

1187 procedureVertex["kind"] = ObjectGraphVertexKind.Function 

1188 procedure._objectVertex = procedureVertex 

1189 

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

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

1192 signalVertex = Vertex( 

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

1194 value=signal, 

1195 graph=self._objectGraph 

1196 ) 

1197 signalVertex["kind"] = ObjectGraphVertexKind.Signal 

1198 signal._objectVertex = signalVertex 

1199 

1200 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex) -> None: 

1201 if isinstance(expression, UnaryExpression): 

1202 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex) 

1203 elif isinstance(expression, BinaryExpression): 

1204 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex) 

1205 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex) 

1206 elif isinstance(expression, TernaryExpression): 

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

1208 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): 

1209 obj = namespace.FindObject(expression) 

1210 expression._reference = obj 

1211 

1212 edge = obj._objectVertex.EdgeToVertex(typeVertex) 

1213 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression 

1214 else: 

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

1216 

1217 def _LinkItems(package: Package) -> None: 

1218 for item in package._declaredItems: 

1219 if isinstance(item, Constant): 

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

1221 elif isinstance(item, DeferredConstant): 

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

1223 elif isinstance(item, Signal): 

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

1225 elif isinstance(item, IntegerType): 

1226 typeNode = item._objectVertex 

1227 

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

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

1230 # elif isinstance(item, FloatingType): 

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

1232 elif isinstance(item, PhysicalType): 

1233 typeNode = item._objectVertex 

1234 

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

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

1237 elif isinstance(item, ArrayType): 

1238 # Resolve dimensions 

1239 for dimension in item._dimensions: 

1240 subtype = package._namespace.FindSubtype(dimension) 

1241 dimension._reference = subtype 

1242 

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

1244 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1245 

1246 # Resolve element subtype 

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

1248 item._elementType._reference = subtype 

1249 

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

1251 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1252 elif isinstance(item, RecordType): 

1253 # Resolve each elements subtype 

1254 for element in item._elements: 

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

1256 element._subtype._reference = subtype 

1257 

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

1259 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1260 else: 

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

1262 

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

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

1265 _HandlePackage(package) 

1266 _LinkItems(package) 

1267 

1268 for document in self.IterateDocumentsInCompileOrder(): 

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

1270 _HandlePackage(package) 

1271 _LinkItems(package) 

1272 

1273 def LinkContexts(self) -> None: 

1274 """ 

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

1276 

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

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

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

1280 

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

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

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

1284 dependency graph is added for that relationship. 

1285 

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

1287 referenced package, 

1288 """ 

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

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

1291 workingLibrary: Library = context.Library 

1292 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier 

1293 

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

1295 context._referencedPackages[libraryNormalizedIdentifier] = {} 

1296 context._referencedContexts[libraryNormalizedIdentifier] = {} 

1297 

1298 # Process all library clauses 

1299 for libraryReference in context._libraryReferences: 

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

1301 for libraryName in libraryReference.Symbols: 

1302 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier 

1303 try: 

1304 library = self._libraries[libraryNormalizedIdentifier] 

1305 except KeyError: 

1306 raise ReferencedLibraryNotExistingError(context, libraryName) 

1307 # TODO: add position to these messages 

1308 

1309 libraryName.Library = library 

1310 

1311 context._referencedLibraries[libraryNormalizedIdentifier] = library 

1312 context._referencedPackages[libraryNormalizedIdentifier] = {} 

1313 context._referencedContexts[libraryNormalizedIdentifier] = {} 

1314 # TODO: warn duplicate library reference 

1315 

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

1317 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1318 

1319 # Process all use clauses 

1320 for packageReference in context.PackageReferences: 

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

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

1323 packageName = symbol.Name.Prefix 

1324 libraryName = packageName.Prefix 

1325 

1326 libraryNormalizedIdentifier = libraryName._normalizedIdentifier 

1327 packageNormalizedIdentifier = packageName._normalizedIdentifier 

1328 

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

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

1331 library: Library = context._parent 

1332 libraryNormalizedIdentifier = library._normalizedIdentifier 

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

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

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

1336 else: 

1337 library = self._libraries[libraryNormalizedIdentifier] 

1338 

1339 try: 

1340 package = library._packages[packageNormalizedIdentifier] 

1341 except KeyError: 

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

1343 

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

1345 symbol.Package = package 

1346 

1347 # TODO: warn duplicate package reference 

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

1349 

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

1351 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1352 

1353 # TODO: update the namespace with visible members 

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

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

1356 

1357 elif isinstance(symbol, PackageMemberReferenceSymbol): 

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

1359 

1360 else: 

1361 raise VHDLModelException() 

1362 

1363 def LinkArchitectures(self) -> None: 

1364 """ 

1365 Link all architectures to corresponding entities in all libraries. 

1366 

1367 .. rubric:: Algorithm 

1368 

1369 1. Iterate all libraries: 

1370 

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

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

1373 

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

1375 

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

1377 

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

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

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

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

1382 

1383 .. seealso:: 

1384 

1385 :meth:`LinkPackageBodies` 

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

1387 :meth:`LinkPackageInstances` 

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

1389 """ 

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

1391 library.LinkArchitectures() 

1392 

1393 def LinkPackageBodies(self) -> None: 

1394 """ 

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

1396 

1397 .. rubric:: Algorithm 

1398 

1399 1. Iterate all libraries: 

1400 

1401 1. Iterate all package bodies. 

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

1403 

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

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

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

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

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

1409 

1410 .. seealso:: 

1411 

1412 :meth:`LinkArchitectures` 

1413 Link all architectures to corresponding entities in all libraries. 

1414 :meth:`LinkPackageInstances` 

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

1416 """ 

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

1418 library.LinkPackageBodies() 

1419 

1420 def LinkPackageInstances(self) -> None: 

1421 """ 

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

1423 

1424 .. rubric:: Algorithm 

1425 

1426 1. Iterate all libraries: 

1427 

1428 1. Iterate all package instances. 

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

1430 

1431 .. todo:: 

1432 

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

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

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

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

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

1438 

1439 .. seealso:: 

1440 

1441 :meth:`LinkArchitectures` 

1442 Link all architectures to corresponding entities in all libraries. 

1443 :meth:`LinkPackageBodies` 

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

1445 """ 

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

1447 library.LinkPackageInstances() 

1448 

1449 def LinkLibraryReferences(self) -> None: 

1450 """ 

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

1452 

1453 .. rubric:: Algorithm 

1454 

1455 1. Iterate all design units with contexts: 

1456 

1457 * If the design unit is a primary unit: 

1458 

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

1460 

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

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

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

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

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

1466 

1467 2. Get the design unit's library: 

1468 

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

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

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

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

1473 

1474 * If the design unit is a secondary unit: 

1475 

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

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

1478 * Otherwise, raise an exception 

1479 

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

1481 

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

1483 

1484 * Iterate every library symbol within the library reference: 

1485 

1486 * Get the library identifier from the symbol. 

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

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

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

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

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

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

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

1494 

1495 .. seealso:: 

1496 

1497 :meth:`LinkPackageReferences` 

1498 Link *use clause*. 

1499 :meth:`LinkContextReferences` 

1500 Link *context clause*. 

1501 :meth:`AnalyzeDependencies` 

1502 Analyze dependencies and link relations. 

1503 """ 

1504 DEFAULT_LIBRARIES = ("std",) 

1505 

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

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

1508 if isinstance(designUnit, PrimaryUnit): 

1509 for libraryIdentifier in DEFAULT_LIBRARIES: 

1510 referencedLibrary = self._libraries[libraryIdentifier] 

1511 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary 

1512 designUnit._referencedPackages[libraryIdentifier] = {} 

1513 designUnit._referencedContexts[libraryIdentifier] = {} 

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

1515 # TODO: warn duplicate library reference 

1516 

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

1518 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1519 

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

1521 workingLibrary: Library = designUnit.Library 

1522 libraryIdentifier = workingLibrary.NormalizedIdentifier 

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

1524 

1525 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary 

1526 designUnit._referencedPackages[libraryIdentifier] = {} 

1527 designUnit._referencedContexts[libraryIdentifier] = {} 

1528 

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

1530 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1531 

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

1533 else: 

1534 if isinstance(designUnit, Architecture): 

1535 referencedLibraries = designUnit.Entity.Entity._referencedLibraries 

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

1537 referencedLibraries = designUnit.Package.Package._referencedLibraries 

1538 else: 

1539 raise VHDLModelException() # FIXME: exception message 

1540 

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

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

1543 

1544 for libraryReference in designUnit._libraryReferences: 

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

1546 for librarySymbol in libraryReference.Symbols: 

1547 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier 

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

1549 continue 

1550 

1551 try: 

1552 library = self._libraries[libraryIdentifier] 

1553 except KeyError: 

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

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

1556 raise ex 

1557 

1558 librarySymbol.Library = library 

1559 designUnit._referencedLibraries[libraryIdentifier] = library 

1560 designUnit._referencedPackages[libraryIdentifier] = {} 

1561 designUnit._referencedContexts[libraryIdentifier] = {} 

1562 # TODO: warn duplicate library reference 

1563 

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

1565 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1566 

1567 def LinkPackageReferences(self) -> None: 

1568 """ 

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

1570 

1571 .. rubric:: Algorithm 

1572 

1573 1. Iterate all design units with contexts: 

1574 

1575 * If the design unit is a primary unit: 

1576 

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

1578 

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

1580 

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

1582 * For every package in packages: 

1583 

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

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

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

1587 

1588 * If the design unit is a secondary unit: 

1589 

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

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

1592 * Otherwise, raise an exception 

1593 

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

1595 

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

1597 

1598 * Iterate every package symbol within the package reference: 

1599 

1600 1. Get the library identifier from the symbol. 

1601 2. Get the package identifier from the symbol. 

1602 3. Resolve library: 

1603 

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

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

1606 * Otherwise, lookup library by name in design. 

1607 

1608 4. Resolve package: 

1609 

1610 * Lookup package by name in library. 

1611 

1612 5. Update design unit: 

1613 

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

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

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

1617 

1618 6. Import public package members. 

1619 

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

1621 

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

1623 

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

1625 

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

1627 

1628 .. todo:: Not implemented. 

1629 

1630 * Otherwise, raise an exception. 

1631 

1632 .. seealso:: 

1633 

1634 :meth:`LinkLibraryReferences` 

1635 Link *library clause*. 

1636 :meth:`LinkContextReferences` 

1637 Link *context clause*. 

1638 :meth:`AnalyzeDependencies` 

1639 Analyze dependencies and link relations. 

1640 """ 

1641 DEFAULT_PACKAGES = ( 

1642 ("std", ("standard",)), 

1643 ) 

1644 

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

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

1647 if isinstance(designUnit, PrimaryUnit): 

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

1649 for lib, packages in DEFAULT_PACKAGES: 

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

1651 raise VHDLModelException() # TODO: missing exception message 

1652 for package in packages: 

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

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

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

1656 # TODO: warn duplicate package reference 

1657 

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

1659 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1660 

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

1662 else: 

1663 if isinstance(designUnit, Architecture): 

1664 referencedPackages = designUnit.Entity.Entity._referencedPackages 

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

1666 referencedPackages = designUnit.Package.Package._referencedPackages 

1667 else: 

1668 raise VHDLModelException() # FIXME: exception message 

1669 

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

1671 designUnit._referencedPackages[packageIdentifier] = package 

1672 

1673 for packageReference in designUnit.PackageReferences: 

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

1675 for packageMemberSymbol in packageReference.Symbols: 

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

1677 packageName = packageMemberSymbol.Name 

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

1679 packageName = packageMemberSymbol.Name.Prefix 

1680 

1681 libraryName = packageName.Prefix 

1682 

1683 libraryIdentifier = libraryName.NormalizedIdentifier 

1684 packageIdentifier = packageName.NormalizedIdentifier 

1685 

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

1687 if libraryIdentifier == "work": 

1688 library: Library = designUnit.Library 

1689 libraryIdentifier = library.NormalizedIdentifier 

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

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

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

1693 else: 

1694 library = self._libraries[libraryIdentifier] 

1695 

1696 try: 

1697 package = library._packages[packageIdentifier] 

1698 except KeyError: 

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

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

1701 raise ex 

1702 

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

1704 packageMemberSymbol.Package = package 

1705 

1706 # TODO: warn duplicate package reference 

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

1708 

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

1710 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1711 

1712 # TODO: update the namespace with visible members 

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

1714 designUnit._namespace._elements[packageIdentifier] = package 

1715 

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

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

1718 

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

1720 designUnit._namespace._elements[componentIdentifier] = component 

1721 

1722 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol): 

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

1724 

1725 else: 

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

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

1728 raise ex 

1729 

1730 def LinkContextReferences(self) -> None: 

1731 """ 

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

1733 

1734 .. rubric:: Algorithm 

1735 

1736 1. Iterate all design units: 

1737 

1738 * Iterate all context references in the design unit: 

1739 

1740 * Iterate each context symbol within the context reference. 

1741 

1742 1. Get the library identifier from the symbol. 

1743 2. Get the context identifier from the symbol. 

1744 3. Resolve library: 

1745 

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

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

1748 * Otherwise, lookup library by name in design. 

1749 

1750 4. Resolve context: 

1751 

1752 * Lookup context by name in library. 

1753 

1754 5. Update design unit: 

1755 

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

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

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

1759 

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

1761 

1762 * Get the context from the context vertex. 

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

1764 

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

1766 2. Iterate referenced libraries of the context: 

1767 

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

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

1770 

1771 3. Iterate referenced packages of the context: 

1772 

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

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

1775 

1776 .. seealso:: 

1777 

1778 :meth:`LinkLibraryReferences` 

1779 Link *library clause*. 

1780 :meth:`LinkPackageReferences` 

1781 Link *use clause*. 

1782 :meth:`AnalyzeDependencies` 

1783 Analyze dependencies and link relations. 

1784 """ 

1785 for designUnit in self.IterateDesignUnits(): 

1786 for contextReference in designUnit._contextReferences: 

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

1788 for contextSymbol in contextReference.Symbols: 

1789 libraryName = contextSymbol.Name.Prefix 

1790 

1791 libraryIdentifier = libraryName.NormalizedIdentifier 

1792 contextIdentifier = contextSymbol.Name.NormalizedIdentifier 

1793 

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

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

1796 referencedLibrary = designUnit.Library 

1797 libraryIdentifier = referencedLibrary.NormalizedIdentifier 

1798 elif libraryIdentifier not in designUnit._referencedLibraries: 

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

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

1801 else: 

1802 referencedLibrary = self._libraries[libraryIdentifier] 

1803 

1804 try: 

1805 referencedContext = referencedLibrary._contexts[contextIdentifier] 

1806 except KeyError: 

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

1808 

1809 contextSymbol.Package = referencedContext 

1810 

1811 # TODO: warn duplicate referencedContext reference 

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

1813 

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

1815 dependency["kind"] = DependencyGraphEdgeKind.ContextReference 

1816 

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

1818 context: Context = vertex.Value 

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

1820 designUnit: DesignUnit = designUnitVertex.Value 

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

1822 # if libraryIdentifier in designUnit._referencedLibraries: 

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

1824 

1825 designUnit._referencedLibraries[libraryIdentifier] = library 

1826 designUnit._referencedPackages[libraryIdentifier] = {} 

1827 

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

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

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

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

1832 

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

1834 

1835 def LinkComponents(self) -> None: 

1836 """ 

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

1838 

1839 .. rubric:: Algorithm 

1840 

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

1842 

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

1844 

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

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

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

1848 

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

1850 unit is an architecture: 

1851 

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

1853 

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

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

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

1857 

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

1859 

1860 1. Iterate declared components. 

1861 

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

1863 

1864 1. Iterate declared components. 

1865 2. Iterate 

1866 

1867 .. seealso:: 

1868 

1869 :meth:`LinkInstantiations` 

1870 Link instantiations to components and entities. 

1871 :meth:`AnalyzeDependencies` 

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

1873 """ 

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

1875 for statement in concurrent._statements: 

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

1877 linkComponents(library, statement._ifBranch) 

1878 linkStatements(library, statement._ifBranch) 

1879 for branch in statement._elsifBranches: 

1880 linkComponents(library, branch) 

1881 linkStatements(library, branch) 

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

1883 linkComponents(library, branch) 

1884 linkStatements(library, branch) 

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

1886 linkComponents(library, statement) 

1887 linkStatements(library, statement) 

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

1889 for case in statement._cases: 

1890 linkComponents(library, case) 

1891 linkStatements(library, case) 

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

1893 linkComponents(library, statement) 

1894 linkStatements(library, statement) 

1895 

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

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

1898 # Currently, component has no _dependencyVertex field 

1899 try: 

1900 entity = library._entities[component.NormalizedIdentifier] 

1901 except KeyError: 

1902 if component.AllowBlackbox: 

1903 component._isBlackbox = True 

1904 return 

1905 else: 

1906 raise VHDLModelException( 

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

1908 

1909 component.Entity = entity 

1910 

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

1912 for item in declarationRegion._declaredItems: 

1913 if isinstance(item, Component): 

1914 searchEntityAndLinkComponent(library, item) 

1915 

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

1917 library = designUnit._parent 

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

1919 searchEntityAndLinkComponent(library, component) 

1920 

1921 if isinstance(designUnit, Architecture): 

1922 linkStatements(library, designUnit) 

1923 

1924 def LinkInstantiations(self) -> None: 

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

1926 for instance in architecture.IterateInstantiations(): 

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

1928 libraryName = instance.Entity.Name.Prefix 

1929 libraryIdentifier = libraryName.Identifier 

1930 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier 

1931 if normalizedLibraryIdentifier == "work": 

1932 libraryIdentifier = architecture.Library.Identifier 

1933 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier 

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

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

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

1937 raise ex 

1938 

1939 try: 

1940 library = self._libraries[normalizedLibraryIdentifier] 

1941 except KeyError: 

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

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

1944 raise ex 

1945 

1946 try: 

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

1948 except KeyError: 

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

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

1951 if libs: 

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

1953 raise ex 

1954 

1955 instance.Entity.Entity = entity 

1956 

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

1958 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation 

1959 

1960 elif isinstance(instance, ComponentInstantiation): 

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

1962 

1963 instance.Component.Component = component 

1964 

1965 if not component.IsBlackbox: 

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

1967 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation 

1968 else: 

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

1970 

1971 elif isinstance(instance, ConfigurationInstantiation): 

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

1973 

1974 def IndexPackages(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.IndexPackages` 

1984 

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

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

1987 

1988 .. seealso:: 

1989 

1990 :meth:`IndexPackageBodies` 

1991 Index all declared items in all package bodies 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.IndexPackages() 

1999 

2000 def IndexPackageBodies(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.IndexPackageBodies` 

2010 

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

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

2013 

2014 .. seealso:: 

2015 

2016 :meth:`IndexPackages` 

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

2018 :meth:`IndexEntities` 

2019 Index all declared items in all entities 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.IndexPackageBodies() 

2025 

2026 def IndexEntities(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.IndexEntities` 

2036 

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

2038 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.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:`IndexArchitectures` 

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

2048 """ 

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

2050 library.IndexEntities() 

2051 

2052 def IndexArchitectures(self) -> None: 

2053 """ 

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

2055 

2056 .. rubric:: Algorithm 

2057 

2058 1. Iterate all libraries: 

2059 

2060 1. Iterate all packages |br| 

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

2062 

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

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

2065 

2066 .. seealso:: 

2067 

2068 :meth:`IndexPackages` 

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

2070 :meth:`IndexPackageBodies` 

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

2072 :meth:`IndexEntities` 

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

2074 """ 

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

2076 library.IndexArchitectures() 

2077 

2078 def CreateHierarchyGraph(self) -> None: 

2079 """ 

2080 Create the hierarchy graph from dependency graph. 

2081 

2082 .. rubric:: Algorithm 

2083 

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

2085 

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

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

2088 

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

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

2091 

2092 2. Iterate all architectures ... 

2093 

2094 .. todo:: Design::CreateHierarchyGraph describe algorithm 

2095 

2096 1. Iterate all outbound edges 

2097 

2098 .. todo:: Design::CreateHierarchyGraph describe algorithm 

2099 """ 

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

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

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

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

2104 vertex.Value._hierarchyVertex = hierarchyVertex 

2105 

2106 # Copy implementation edges from 

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

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

2109 kind: DependencyGraphEdgeKind = dependencyEdge["kind"] 

2110 if DependencyGraphEdgeKind.Implementation in kind: 

2111 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"] 

2112 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex) 

2113 elif DependencyGraphEdgeKind.Instantiation in kind: 

2114 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"] 

2115 

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

2117 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex): 

2118 continue 

2119 

2120 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex) 

2121 else: 

2122 continue 

2123 

2124 newEdge["kind"] = kind 

2125 

2126 def ComputeCompileOrder(self) -> None: 

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

2128 return ( 

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

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

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

2132 DependencyGraphEdgeKind.ContextReference in edge["kind"] 

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

2134 

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

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

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

2138 

2139 sourceVertex = sourceDocument._compileOrderVertex 

2140 destinationVertex = destinationDocument._compileOrderVertex 

2141 

2142 # Don't add self-edges 

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

2144 continue 

2145 # Don't add parallel edges 

2146 elif sourceVertex.HasEdgeToDestination(destinationVertex): 

2147 continue 

2148 

2149 e = sourceVertex.EdgeToVertex(destinationVertex) 

2150 e["kind"] = DependencyGraphEdgeKind.CompileOrder 

2151 

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

2153 e["kind"] = DependencyGraphEdgeKind.CompileOrder 

2154 

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

2156 """ 

2157 Iterate all document in compile-order. 

2158 

2159 .. rubric:: Algorithm 

2160 

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

2162 

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

2164 :meth:`pyTooling.Graph.Graph.IterateTopologically` 

2165 

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

2167 

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

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

2170 

2171 .. seealso:: 

2172 

2173 .. todo:: missing text 

2174 

2175 :meth:`pyVHDLModel.Design.ComputeCompileOrder` 

2176 

2177 """ 

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

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

2180 

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

2182 yield compileOrderNode.Value 

2183 

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

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

2186 

2187 def __repr__(self) -> str: 

2188 """ 

2189 Formats a representation of the design. 

2190 

2191 **Format:** ``Document: 'my_design'`` 

2192 

2193 :returns: String representation of the design. 

2194 """ 

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

2196 

2197 __str__ = __repr__ 

2198 

2199 

2200@export 

2201class Library(ModelEntity, NamedEntityMixin, DocumentedEntityMixin, AllowBlackboxMixin): 

2202 """ 

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

2204 

2205 .. seealso:: 

2206 

2207 * :class:`Predefined library <pyVHDLModel.Predefined.PredefinedLibrary>` 

2208 """ 

2209 

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

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

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

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

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

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

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

2217 

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

2219 

2220 def __init__( 

2221 self, 

2222 identifier: str, 

2223 documentation: Nullable[str] = None, 

2224 allowBlackbox: Nullable[bool] = None, 

2225 parent: Nullable[ModelEntity] = None 

2226 ) -> None: 

2227 """ 

2228 Initialize a VHDL library. 

2229 

2230 :param identifier: Name of the VHDL library. 

2231 :param documentation: Documentation of this VHDL library, if the caller has one to supply. 

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

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

2234 """ 

2235 super().__init__(parent) 

2236 NamedEntityMixin.__init__(self, identifier) 

2237 DocumentedEntityMixin.__init__(self, documentation) 

2238 AllowBlackboxMixin.__init__(self, allowBlackbox) 

2239 

2240 self._contexts = {} 

2241 self._configurations = {} 

2242 self._entities = {} 

2243 self._architectures = {} 

2244 self._packages = {} 

2245 self._packageBodies = {} 

2246 

2247 self._dependencyVertex = None 

2248 

2249 @property 

2250 def Documentation(self) -> Nullable[str]: 

2251 """ 

2252 Property to access the library's documentation (:attr:`_documentation`). 

2253 

2254 .. hint:: 

2255 

2256 Unlike every other documented entity, a library's documentation cannot come from VHDL source: 

2257 the language has no library declaration to attach a comment to. It is therefore settable, so a 

2258 caller can supply one from elsewhere - a compile-order file, a project description, ... 

2259 

2260 :returns: Associated documentation of this VHDL library. 

2261 """ 

2262 return self._documentation 

2263 

2264 @Documentation.setter 

2265 def Documentation(self, documentation: Nullable[str]) -> None: 

2266 self._documentation = documentation 

2267 

2268 @readonly 

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

2270 """ 

2271 Read-only property to access the dictionary of all context declarations in this library (:attr:`_contexts`). 

2272 

2273 :returns: Dictionary of all contexts, indexed by normalized identifier. 

2274 """ 

2275 return self._contexts 

2276 

2277 @readonly 

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

2279 """ 

2280 Read-only property to access the dictionary of all configuration declarations in this library (:attr:`_configurations`). 

2281 

2282 :returns: Dictionary of all configurations, indexed by normalized identifier. 

2283 """ 

2284 return self._configurations 

2285 

2286 @readonly 

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

2288 """ 

2289 Read-only property to access the dictionary of all entity declarations in this library (:attr:`_entities`). 

2290 

2291 :returns: Dictionary of all entities, indexed by normalized identifier. 

2292 """ 

2293 return self._entities 

2294 

2295 @readonly 

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

2297 """ 

2298 Read-only property to access the dictionary of all architecture declarations in this library (:attr:`_architectures`). 

2299 

2300 :returns: Dictionary of all architectures, indexed by normalized entity identifier, then by normalized 

2301 architecture identifier. 

2302 """ 

2303 return self._architectures 

2304 

2305 @readonly 

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

2307 """ 

2308 Read-only property to access the dictionary of all package declarations in this library (:attr:`_packages`). 

2309 

2310 :returns: Dictionary of all packages, indexed by normalized identifier. 

2311 """ 

2312 return self._packages 

2313 

2314 @readonly 

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

2316 """ 

2317 Read-only property to access the dictionary of all package body declarations in this library (:attr:`_packageBodies`). 

2318 

2319 :returns: Dictionary of all package bodies, indexed by normalized identifier. 

2320 """ 

2321 return self._packageBodies 

2322 

2323 @readonly 

2324 def DependencyVertex(self) -> Vertex: 

2325 """ 

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

2327 

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

2329 

2330 :returns: The corresponding dependency vertex. 

2331 """ 

2332 return self._dependencyVertex 

2333 

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

2335 """ 

2336 Iterate all design units in the library. 

2337 

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

2339 

2340 .. rubric:: Algorithm 

2341 

2342 1. Iterate all contexts in that library. 

2343 2. Iterate all packages in that library. 

2344 3. Iterate all package bodies in that library. 

2345 4. Iterate all entities in that library. 

2346 5. Iterate all architectures in that library. 

2347 6. Iterate all configurations in that library. 

2348 

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

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

2351 

2352 .. seealso:: 

2353 

2354 :meth:`pyVHDLModel.Design.IterateDesignUnits` 

2355 Iterate all design units in the design. 

2356 :meth:`pyVHDLModel.Document.IterateDesignUnits` 

2357 Iterate all design units in the document. 

2358 """ 

2359 if DesignUnitKind.Context in filter: 

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

2361 yield context 

2362 

2363 if DesignUnitKind.Package in filter: 

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

2365 yield package 

2366 

2367 if DesignUnitKind.PackageBody in filter: 

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

2369 yield packageBody 

2370 

2371 if DesignUnitKind.Entity in filter: 

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

2373 yield entity 

2374 

2375 if DesignUnitKind.Architecture in filter: 

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

2377 for architecture in architectures.values(): 

2378 yield architecture 

2379 

2380 if DesignUnitKind.Configuration in filter: 

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

2382 yield configuration 

2383 

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

2385 # yield verificationProperty 

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

2387 # yield entity 

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

2389 # yield verificationMode 

2390 

2391 def LinkArchitectures(self) -> None: 

2392 """ 

2393 Link all architectures to corresponding entities. 

2394 

2395 .. rubric:: Algorithm 

2396 

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

2398 

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

2400 

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

2402 

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

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

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

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

2407 

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

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

2410 

2411 .. seealso:: 

2412 

2413 :meth:`LinkPackageBodies` 

2414 Link all package bodies to corresponding packages. 

2415 :meth:`LinkPackageInstances` 

2416 Link all package instances to corresponding generic packages. 

2417 """ 

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

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

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

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

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

2423 # TODO: add code position 

2424 

2425 entity = self._entities[entityName] 

2426 for architecture in architecturesPerEntity.values(): 

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

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

2429 # TODO: add code position of existing and current 

2430 

2431 entity._architectures[architecture._normalizedIdentifier] = architecture 

2432 architecture._entity.Entity = entity 

2433 architecture._namespace._parentNamespace = entity._namespace 

2434 

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

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

2437 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation 

2438 

2439 def LinkPackageBodies(self) -> None: 

2440 """ 

2441 Link all package bodies to corresponding packages. 

2442 

2443 .. rubric:: Algorithm 

2444 

2445 1. Iterate all package bodies. 

2446 

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

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

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

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

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

2452 

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

2454 

2455 .. seealso:: 

2456 

2457 :meth:`LinkArchitectures` 

2458 Link all architectures to corresponding entities. 

2459 :meth:`LinkPackageInstances` 

2460 Link all package instances to corresponding generic packages. 

2461 """ 

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

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

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

2465 

2466 package = self._packages[packageBodyName] 

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

2468 packageBody._package.Package = package 

2469 packageBody._namespace._parentNamespace = package._namespace 

2470 

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

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

2473 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation 

2474 

2475 def LinkPackageInstances(self) -> None: 

2476 """ 

2477 Link all package instances to corresponding generic packages. 

2478 

2479 .. rubric:: Algorithm 

2480 

2481 1. Iterate all package instances. 

2482 

2483 .. todo:: 

2484 

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

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

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

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

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

2490 

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

2492 

2493 .. seealso:: 

2494 

2495 :meth:`LinkArchitectures` 

2496 Link all architectures to corresponding entities. 

2497 :meth:`LinkPackageBodies` 

2498 Link all package bodies to corresponding packages. 

2499 """ 

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

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

2502 packageSymbol = packageInstance._packageReference 

2503 packageName = packageSymbol.Name 

2504 libraryName = packageName.Prefix 

2505 

2506 libraryIdentifier = libraryName.NormalizedIdentifier 

2507 packageIdentifier = packageName.NormalizedIdentifier 

2508 

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

2510 if libraryIdentifier == "work": 

2511 library: Library = self 

2512 libraryIdentifier = library.NormalizedIdentifier 

2513 elif libraryIdentifier not in self._parent._libraries: 

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

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

2516 else: 

2517 library = self._parent._libraries[libraryIdentifier] 

2518 

2519 try: 

2520 package = library._packages[packageIdentifier] 

2521 except KeyError: 

2522 ex = VHDLModelException( 

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

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

2525 raise ex 

2526 

2527 # FIXME: check if package is a generic package 

2528 if package.GenericCount == 0: 

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

2530 

2531 packageSymbol.Package = package 

2532 

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

2534 dependency["kind"] = DependencyGraphEdgeKind.PackageInstantiation 

2535 

2536 packageInstance.Instantiate() 

2537 

2538 def IndexPackages(self) -> None: 

2539 """ 

2540 Index declared items in all packages. 

2541 

2542 .. rubric:: Algorithm 

2543 

2544 1. Iterate all packages: 

2545 

2546 * Index all declared items. |br| 

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

2548 

2549 .. seealso:: 

2550 

2551 :meth:`IndexPackageBodies` 

2552 Index all declared items in a package body. 

2553 :meth:`IndexEntities` 

2554 Index all declared items in an entity. 

2555 :meth:`IndexArchitectures` 

2556 Index all declared items in an architecture. 

2557 """ 

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

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

2560 package.IndexDeclaredItems() 

2561 

2562 def IndexPackageBodies(self) -> None: 

2563 """ 

2564 Index declared items in all package bodies. 

2565 

2566 .. rubric:: Algorithm 

2567 

2568 1. Iterate all package bodies: 

2569 

2570 * Index all declared items. |br| 

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

2572 

2573 .. seealso:: 

2574 

2575 :meth:`IndexPackages` 

2576 Index all declared items in a package. 

2577 :meth:`IndexEntities` 

2578 Index all declared items in an entity. 

2579 :meth:`IndexArchitectures` 

2580 Index all declared items in an architecture. 

2581 """ 

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

2583 packageBody.IndexDeclaredItems() 

2584 

2585 def IndexEntities(self) -> None: 

2586 """ 

2587 Index declared items in all entities. 

2588 

2589 .. rubric:: Algorithm 

2590 

2591 1. Iterate all entities: 

2592 

2593 * Index all declared items. |br| 

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

2595 

2596 .. seealso:: 

2597 

2598 :meth:`IndexPackages` 

2599 Index all declared items in a package. 

2600 :meth:`IndexPackageBodies` 

2601 Index all declared items in a package body. 

2602 :meth:`IndexArchitectures` 

2603 Index all declared items in an architecture. 

2604 """ 

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

2606 entity.IndexDeclaredItems() 

2607 

2608 def IndexArchitectures(self) -> None: 

2609 """ 

2610 Index declared items in all architectures. 

2611 

2612 .. rubric:: Algorithm 

2613 

2614 1. Iterate all architectures: 

2615 

2616 * Index all declared items. |br| 

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

2618 

2619 .. seealso:: 

2620 

2621 :meth:`IndexPackages` 

2622 Index all declared items in a package. 

2623 :meth:`IndexPackageBodies` 

2624 Index all declared items in a package body. 

2625 :meth:`IndexEntities` 

2626 Index all declared items in an entity. 

2627 """ 

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

2629 for architecture in architectures.values(): 

2630 architecture.IndexDeclaredItems() 

2631 architecture.IndexStatements() 

2632 

2633 def __repr__(self) -> str: 

2634 """ 

2635 Formats a representation of the library. 

2636 

2637 **Format:** ``Library: 'my_library'`` 

2638 

2639 :returns: String representation of the library. 

2640 """ 

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

2642 

2643 __str__ = __repr__ 

2644 

2645 

2646@export 

2647class Document(ModelEntity, DocumentedEntityMixin): 

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

2649 

2650 _path: Path #: Path to the document. ``None`` if in-memory document. 

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

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

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

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

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

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

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

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

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

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

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

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

2663 

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

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

2666 

2667 def __init__( 

2668 self, 

2669 path: Path, 

2670 documentation: Nullable[str] = None, 

2671 vhdlVersion: VHDLVersion = VHDLVersion.VHDL2008, 

2672 library: Nullable[Library] = None, 

2673 parent: Nullable[ModelEntity] = None 

2674 ) -> None: 

2675 """ 

2676 Initializes a VHDL document. 

2677 

2678 :param path: Path to the document. ``None`` if in-memory document. 

2679 :param documentation: The documentation comment associated with this declaration. 

2680 :param vhdlVersion: VHDL version used for analyzing this source file. 

2681 :param library: VHDL library used for analyzing the source file's content into. 

2682 :param parent: The parent model entity of this entity. 

2683 """ 

2684 super().__init__(parent) 

2685 DocumentedEntityMixin.__init__(self, documentation) 

2686 

2687 self._path = path 

2688 self._vhdlVersion = vhdlVersion 

2689 self._library = library 

2690 self._designUnits = [] 

2691 self._contexts = {} 

2692 self._configurations = {} 

2693 self._entities = {} 

2694 self._architectures = {} 

2695 self._packages = {} 

2696 self._packageBodies = {} 

2697 self._verificationUnits = {} 

2698 self._verificationProperties = {} 

2699 self._verificationModes = {} 

2700 

2701 self._dependencyVertex = None 

2702 self._compileOrderVertex = None 

2703 

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

2705 """ 

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

2707 

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

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

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

2711 """ 

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

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

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

2715 raise ex 

2716 

2717 identifier = item._normalizedIdentifier 

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

2719 # TODO: use a more specific exception 

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

2721 

2722 self._entities[identifier] = item 

2723 self._designUnits.append(item) 

2724 item._document = self 

2725 

2726 # TODO: add entity to _library and vice versa 

2727 

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

2729 """ 

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

2731 

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

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

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

2735 """ 

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

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

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

2739 raise ex 

2740 

2741 entity = item._entity.Name 

2742 entityIdentifier = entity._normalizedIdentifier 

2743 try: 

2744 architectures = self._architectures[entityIdentifier] 

2745 if item._normalizedIdentifier in architectures: 

2746 # TODO: use a more specific exception 

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

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

2749 

2750 architectures[item.Identifier] = item 

2751 except KeyError: 

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

2753 

2754 self._designUnits.append(item) 

2755 item._document = self 

2756 

2757 # TODO: add architecture to _library and vice versa 

2758 

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

2760 """ 

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

2762 

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

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

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

2766 """ 

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

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

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

2770 raise ex 

2771 

2772 identifier = item._normalizedIdentifier 

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

2774 # TODO: use a more specific exception 

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

2776 

2777 self._packages[identifier] = item 

2778 self._designUnits.append(item) 

2779 item._document = self 

2780 

2781 # TODO: add package to _library and vice versa 

2782 

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

2784 """ 

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

2786 

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

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

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

2790 """ 

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

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

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

2794 raise ex 

2795 

2796 identifier = item._normalizedIdentifier 

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

2798 # TODO: use a more specific exception 

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

2800 

2801 self._packageBodies[identifier] = item 

2802 self._designUnits.append(item) 

2803 item._document = self 

2804 

2805 # TODO: add packagebody to _library and vice versa 

2806 

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

2808 """ 

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

2810 

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

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

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

2814 """ 

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

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

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

2818 raise ex 

2819 

2820 identifier = item._normalizedIdentifier 

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

2822 # TODO: use a more specific exception 

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

2824 

2825 self._contexts[identifier] = item 

2826 self._designUnits.append(item) 

2827 item._document = self 

2828 

2829 # TODO: add context to _library and vice versa 

2830 

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

2832 """ 

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

2834 

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

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

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

2838 """ 

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

2840 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.") 

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

2842 raise ex 

2843 

2844 identifier = item._normalizedIdentifier 

2845 if identifier in self._configurations: 2845 ↛ 2847line 2845 didn't jump to line 2847 because the condition on line 2845 was never true

2846 # TODO: use a more specific exception 

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

2848 

2849 self._configurations[identifier] = item 

2850 self._designUnits.append(item) 

2851 item._document = self 

2852 

2853 # TODO: add configuration to _library and vice versa 

2854 

2855 def _AddVerificationUnit(self, item: VerificationUnit) -> None: 

2856 if not isinstance(item, VerificationUnit): 

2857 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.") 

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

2859 raise ex 

2860 

2861 identifier = item._normalizedIdentifier 

2862 if identifier in self._verificationUnits: 

2863 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.") 

2864 

2865 self._verificationUnits[identifier] = item 

2866 self._designUnits.append(item) 

2867 item._document = self 

2868 

2869 # TODO: add vunit to _library and vice versa 

2870 

2871 def _AddVerificationProperty(self, item: VerificationProperty) -> None: 

2872 if not isinstance(item, VerificationProperty): 

2873 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.") 

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

2875 raise ex 

2876 

2877 identifier = item.NormalizedIdentifier 

2878 if identifier in self._verificationProperties: 

2879 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.") 

2880 

2881 self._verificationProperties[identifier] = item 

2882 self._designUnits.append(item) 

2883 item._document = self 

2884 

2885 # TODO: add vprop to _library and vice versa 

2886 

2887 def _AddVerificationMode(self, item: VerificationMode) -> None: 

2888 if not isinstance(item, VerificationMode): 

2889 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.") 

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

2891 raise ex 

2892 

2893 identifier = item.NormalizedIdentifier 

2894 if identifier in self._verificationModes: 

2895 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.") 

2896 

2897 self._verificationModes[identifier] = item 

2898 self._designUnits.append(item) 

2899 item._document = self 

2900 

2901 # TODO: add vmode to _library and vice versa 

2902 

2903 def _AddDesignUnit(self, item: DesignUnit) -> None: 

2904 """ 

2905 Add a design unit to the document's lists of design units. 

2906 

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

2908 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.DesignUnit`. 

2909 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnit.DesignUnit`. 

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

2911 """ 

2912 if not isinstance(item, DesignUnit): 2912 ↛ 2913line 2912 didn't jump to line 2913 because the condition on line 2912 was never true

2913 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.") 

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

2915 raise ex 

2916 

2917 if isinstance(item, Entity): 

2918 self._AddEntity(item) 

2919 elif isinstance(item, Architecture): 

2920 self._AddArchitecture(item) 

2921 elif isinstance(item, Package): 

2922 self._AddPackage(item) 

2923 elif isinstance(item, PackageBody): 

2924 self._AddPackageBody(item) 

2925 elif isinstance(item, Context): 

2926 self._AddContext(item) 

2927 elif isinstance(item, Configuration): 2927 ↛ 2929line 2927 didn't jump to line 2929 because the condition on line 2927 was always true

2928 self._AddConfiguration(item) 

2929 elif isinstance(item, VerificationUnit): 

2930 self._AddVerificationUnit(item) 

2931 elif isinstance(item, VerificationProperty): 

2932 self._AddVerificationProperty(item) 

2933 elif isinstance(item, VerificationMode): 

2934 self._AddVerificationMode(item) 

2935 else: 

2936 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.") 

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

2938 raise ex 

2939 

2940 @readonly 

2941 def Path(self) -> Path: 

2942 """ 

2943 Read-only property to access the document's path (:attr:`_path`). 

2944 

2945 :returns: The path of this document. 

2946 """ 

2947 return self._path 

2948 

2949 @readonly 

2950 def VHDLVersion(self) -> VHDLVersion: 

2951 """ 

2952 Read-only property to access the document's VHDL version (:attr:`_vhdlVersion`). 

2953 

2954 :returns: VHDL version used to analyze this VHDL file. 

2955 """ 

2956 return self._vhdlVersion 

2957 

2958 # @property 

2959 @readonly 

2960 def Library(self) -> Library: 

2961 """ 

2962 Read-only property to access the document's VHDL library (:attr:`_library`). 

2963 

2964 :returns: VHDL library used to analyze the VHDL file's design units into. 

2965 """ 

2966 return self._library 

2967 

2968 # @Library.setter 

2969 # def Library(self, library: Library) -> None: 

2970 # self._library = library 

2971 # 

2972 # # TODO: check and set library to design unit? 

2973 

2974 @readonly 

2975 def DesignUnits(self) -> List[DesignUnit]: 

2976 """ 

2977 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`). 

2978 

2979 :returns: List of all design units. 

2980 """ 

2981 return self._designUnits 

2982 

2983 @readonly 

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

2985 """ 

2986 Read-only property to access the dictionary of all context declarations in this document (:attr:`_contexts`). 

2987 

2988 :returns: Dictionary of all contexts, indexed by normalized identifier. 

2989 """ 

2990 return self._contexts 

2991 

2992 @readonly 

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

2994 """ 

2995 Read-only property to access the dictionary of all configuration declarations in this document (:attr:`_configurations`). 

2996 

2997 :returns: Dictionary of all configurations, indexed by normalized identifier. 

2998 """ 

2999 return self._configurations 

3000 

3001 @readonly 

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

3003 """ 

3004 Read-only property to access the dictionary of all entity declarations in this document (:attr:`_entities`). 

3005 

3006 :returns: Dictionary of all entities, indexed by normalized identifier. 

3007 """ 

3008 return self._entities 

3009 

3010 @readonly 

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

3012 """ 

3013 Read-only property to access the dictionary of all architecture declarations in this document (:attr:`_architectures`). 

3014 

3015 :returns: Dictionary of all architectures, indexed by normalized entity identifier, then by normalized 

3016 architecture identifier. 

3017 """ 

3018 return self._architectures 

3019 

3020 @readonly 

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

3022 """ 

3023 Read-only property to access the dictionary of all package declarations in this document (:attr:`_packages`). 

3024 

3025 :returns: Dictionary of all packages, indexed by normalized identifier. 

3026 """ 

3027 return self._packages 

3028 

3029 @readonly 

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

3031 """ 

3032 Read-only property to access the dictionary of all package body declarations in this document (:attr:`_packageBodies`). 

3033 

3034 :returns: Dictionary of all package bodies, indexed by normalized identifier. 

3035 """ 

3036 return self._packageBodies 

3037 

3038 @readonly 

3039 def VerificationUnits(self) -> Dict[str, VerificationUnit]: 

3040 """ 

3041 Read-only property to access the dictionary of all verification unit declarations in this document (:attr:`_verificationUnits`). 

3042 

3043 :returns: Dictionary of all verification units, indexed by normalized identifier. 

3044 """ 

3045 return self._verificationUnits 

3046 

3047 @readonly 

3048 def VerificationProperties(self) -> Dict[str, VerificationProperty]: 

3049 """ 

3050 Read-only property to access the dictionary of all verification property declarations in this document (:attr:`_verificationProperties`). 

3051 

3052 :returns: Dictionary of all verification properties, indexed by normalized identifier. 

3053 """ 

3054 return self._verificationProperties 

3055 

3056 @readonly 

3057 def VerificationModes(self) -> Dict[str, VerificationMode]: 

3058 """ 

3059 Read-only property to access the dictionary of all verification mode declarations in this document (:attr:`_verificationModes`). 

3060 

3061 :returns: Dictionary of all verification mode declarations, indexed by normalized identifier. 

3062 """ 

3063 return self._verificationModes 

3064 

3065 @readonly 

3066 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]: 

3067 """ 

3068 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`). 

3069 

3070 The compile-order vertex references this document by its value field. 

3071 

3072 :returns: The corresponding compile-order vertex. 

3073 """ 

3074 return self._compileOrderVertex 

3075 

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

3077 """ 

3078 Iterate all design units in the document. 

3079 

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

3081 

3082 .. rubric:: Algorithm 

3083 

3084 * If contexts are selected in the filter: 

3085 

3086 1. Iterate all contexts in that library. 

3087 

3088 * If packages are selected in the filter: 

3089 

3090 1. Iterate all packages in that library. 

3091 

3092 * If package bodies are selected in the filter: 

3093 

3094 1. Iterate all package bodies in that library. 

3095 

3096 * If entites are selected in the filter: 

3097 

3098 1. Iterate all entites in that library. 

3099 

3100 * If architectures are selected in the filter: 

3101 

3102 1. Iterate all architectures in that library. 

3103 

3104 * If configurations are selected in the filter: 

3105 

3106 1. Iterate all configurations in that library. 

3107 

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

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

3110 

3111 .. seealso:: 

3112 

3113 :meth:`pyVHDLModel.Design.IterateDesignUnits` 

3114 Iterate all design units in the design. 

3115 :meth:`pyVHDLModel.Library.IterateDesignUnits` 

3116 Iterate all design units in the library. 

3117 """ 

3118 if DesignUnitKind.Context in filter: 3118 ↛ 3122line 3118 didn't jump to line 3122 because the condition on line 3118 was always true

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

3120 yield context 

3121 

3122 if DesignUnitKind.Package in filter: 3122 ↛ 3126line 3122 didn't jump to line 3126 because the condition on line 3122 was always true

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

3124 yield package 

3125 

3126 if DesignUnitKind.PackageBody in filter: 3126 ↛ 3130line 3126 didn't jump to line 3130 because the condition on line 3126 was always true

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

3128 yield packageBody 

3129 

3130 if DesignUnitKind.Entity in filter: 3130 ↛ 3134line 3130 didn't jump to line 3134 because the condition on line 3130 was always true

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

3132 yield entity 

3133 

3134 if DesignUnitKind.Architecture in filter: 3134 ↛ 3139line 3134 didn't jump to line 3139 because the condition on line 3134 was always true

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

3136 for architecture in architectures.values(): 

3137 yield architecture 

3138 

3139 if DesignUnitKind.Configuration in filter: 3139 ↛ exitline 3139 didn't return from function 'IterateDesignUnits' because the condition on line 3139 was always true

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

3141 yield configuration 

3142 

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

3144 # yield verificationProperty 

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

3146 # yield entity 

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

3148 # yield verificationMode 

3149 

3150 def __repr__(self) -> str: 

3151 """ 

3152 Formats a representation of the document. 

3153 

3154 **Format:** ``Document: 'path/to/file.vhdl'`` 

3155 

3156 :returns: String representation of the document. 

3157 """ 

3158 return f"Document: '{self._path}'" 

3159 

3160 __str__ = __repr__