Coverage for pyVHDLModel/__init__.py: 77%

1075 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-10 23:46 +0000

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

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

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

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

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

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

7# |_| |___/ # 

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

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

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

14# Copyright 2017-2024 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-2024 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-2024, Patrick Lehmann" 

50__license__ = "Apache License, Version 2.0" 

51__version__ = "0.29.2" 

52 

53 

54from enum import unique, Enum, Flag, auto 

55from pathlib import Path 

56from sys import version_info 

57 

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

59 

60from pyTooling.Common import getFullyQualifiedName 

61from pyTooling.Decorators import export, readonly 

62from pyTooling.Graph import Graph, Vertex, Edge 

63 

64from pyVHDLModel.Exception import VHDLModelException 

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

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

67from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError 

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

69from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression 

70from pyVHDLModel.Namespace import Namespace 

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

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

73from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation 

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

75from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode 

76from pyVHDLModel.Instantiation import PackageInstantiation 

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

78 

79 

80@export 

81@unique 

82class VHDLVersion(Enum): 

83 """ 

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

85 

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

87 enumeration value. 

88 

89 This enumeration supports compare operators. 

90 """ 

91 

92 Any = -1 #: Any 

93 VHDL87 = 87 #: VHDL-1987 

94 VHDL93 = 93 #: VHDL-1993 

95 AMS93 = 1993 #: VHDL-AMS-1993 

96 AMS99 = 1999 #: VHDL-AMS-1999 

97 VHDL2000 = 2000 #: VHDL-2000 

98 VHDL2002 = 2002 #: VHDL-2002 

99 VHDL2008 = 2008 #: VHDL-2008 

100 AMS2017 = 2017 #: VHDL-AMS-2017 

101 VHDL2019 = 2019 #: VHDL-2019 

102 Latest = 10000 #: Latest VHDL (2019) 

103 

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

105 -1: Any, 

106 87: VHDL87, 

107 93: VHDL93, 

108 # 93: AMS93, 

109 99: AMS99, 

110 0: VHDL2000, 

111 2: VHDL2002, 

112 8: VHDL2008, 

113 17: AMS2017, 

114 19: VHDL2019, 

115 1987: VHDL87, 

116 # 1993: VHDL93, 

117 1993: AMS93, 

118 1999: AMS99, 

119 2000: VHDL2000, 

120 2002: VHDL2002, 

121 2008: VHDL2008, 

122 2017: AMS2017, 

123 2019: VHDL2019, 

124 10000: Latest, 

125 "Any": Any, 

126 "87": VHDL87, 

127 "93": VHDL93, 

128 # "93": AMS93, 

129 "99": AMS99, 

130 "00": VHDL2000, 

131 "02": VHDL2002, 

132 "08": VHDL2008, 

133 "17": AMS2017, 

134 "19": VHDL2019, 

135 "1987": VHDL87, 

136 # "1993": VHDL93, 

137 "1993": AMS93, 

138 "1999": AMS99, 

139 "2000": VHDL2000, 

140 "2002": VHDL2002, 

141 "2008": VHDL2008, 

142 "2017": AMS2017, 

143 "2019": VHDL2019, 

144 "Latest": Latest, 

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

146 

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

148 """Patch the embedded MAP dictionary""" 

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

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

151 self.__class__.__VERSION_MAPPINGS__[k] = self 

152 

153 @classmethod 

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

155 """ 

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

157 

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

159 :returns: Enumeration value. 

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

161 """ 

162 try: 

163 return cls.__VERSION_MAPPINGS__[value] 

164 except KeyError: 

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

166 

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

168 """ 

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

170 

171 :param other: Parameter to compare against. 

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

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

174 """ 

175 if isinstance(other, VHDLVersion): 

176 return self.value < other.value 

177 else: 

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

179 

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

181 """ 

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

183 

184 :param other: Parameter to compare against. 

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

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

187 """ 

188 if isinstance(other, VHDLVersion): 

189 return self.value <= other.value 

190 else: 

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

192 

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

194 """ 

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

196 

197 :param other: Parameter to compare against. 

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

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

200 """ 

201 if isinstance(other, VHDLVersion): 

202 return self.value > other.value 

203 else: 

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

205 

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

207 """ 

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

209 

210 :param other: Parameter to compare against. 

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

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

213 """ 

214 if isinstance(other, VHDLVersion): 

215 return self.value >= other.value 

216 else: 

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

218 

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

220 """ 

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

222 

223 :param other: Parameter to compare against. 

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

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

226 """ 

227 if isinstance(other, VHDLVersion): 

228 return self.value != other.value 

229 else: 

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

231 

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

233 """ 

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

235 

236 :param other: Parameter to compare against. 

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

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

239 """ 

240 if isinstance(other, VHDLVersion): 

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

242 return True 

243 else: 

244 return self.value == other.value 

245 else: 

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

247 

248 @readonly 

249 def IsVHDL(self) -> bool: 

250 """ 

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

252 

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

254 """ 

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

256 

257 @readonly 

258 def IsAMS(self) -> bool: 

259 """ 

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

261 

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

263 """ 

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

265 

266 def __str__(self) -> str: 

267 """ 

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

269 

270 :return: Formatted VHDL/VHDL-AMS version. 

271 """ 

272 if self.value == self.Any.value: 

273 return "VHDL'Any" 

274 elif self.value == self.Latest.value: 

275 return "VHDL'Latest" 

276 

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

278 if self.IsVHDL: 

279 return f"VHDL'{year}" 

280 else: 

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

282 

283 def __repr__(self) -> str: 

284 """ 

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

286 

287 :return: Formatted VHDL/VHDL-AMS version. 

288 """ 

289 if self.value == self.Any.value: 

290 return "Any" 

291 elif self.value == self.Latest.value: 

292 return "Latest" 

293 else: 

294 return str(self.value) 

295 

296 

297@export 

298@unique 

299class ObjectClass(Enum): 

300 """ 

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

302 

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

304 """ 

305 

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

307 Constant = 1 #: Constant 

308 Variable = 2 #: Variable 

309 Signal = 3 #: Signal 

310 File = 4 #: File 

311 Type = 5 #: Type 

312 # FIXME: Package? 

313 Procedure = 6 #: Procedure 

314 Function = 7 #: Function 

315 

316 def __str__(self) -> str: 

317 """ 

318 Formats the object class. 

319 

320 :return: Formatted object class. 

321 """ 

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

323 

324 

325@export 

326@unique 

327class DesignUnitKind(Flag): 

328 """ 

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

330 

331 """ 

332 Context = auto() #: Context 

333 Package = auto() #: Package 

334 PackageBody = auto() #: Package Body 

335 Entity = auto() #: Entity 

336 Architecture = auto() #: Architecture 

337 Configuration = auto() #: Configuration 

338 

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

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

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

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

343 

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

345 

346 

347@export 

348@unique 

349class DependencyGraphVertexKind(Flag): 

350 """ 

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

352 """ 

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

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

355 

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

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

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

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

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

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

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

363 

364 

365@export 

366@unique 

367class DependencyGraphEdgeKind(Flag): 

368 """ 

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

370 """ 

371 Document = auto() 

372 Library = auto() 

373 Context = auto() 

374 Package = auto() 

375 Entity = auto() 

376 # Architecture = auto() 

377 Configuration = auto() 

378 Component = auto() 

379 

380 DeclaredIn = auto() 

381 Order = auto() 

382 Reference = auto() 

383 Implementation = auto() 

384 Instantiation = auto() 

385 

386 SourceFile = Document | DeclaredIn 

387 CompileOrder = Document | Order 

388 

389 LibraryClause = Library | Reference 

390 UseClause = Package | Reference 

391 ContextReference = Context | Reference 

392 

393 EntityImplementation = Entity | Implementation 

394 PackageImplementation = Package | Implementation 

395 

396 EntityInstantiation = Entity | Instantiation 

397 ComponentInstantiation = Component | Instantiation 

398 ConfigurationInstantiation = Configuration | Instantiation 

399 

400 

401@export 

402@unique 

403class ObjectGraphVertexKind(Flag): 

404 """ 

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

406 """ 

407 Type = auto() 

408 Subtype = auto() 

409 

410 Constant = auto() 

411 DeferredConstant = auto() 

412 Variable = auto() 

413 Signal = auto() 

414 File = auto() 

415 

416 Alias = auto() 

417 

418 

419@export 

420@unique 

421class ObjectGraphEdgeKind(Flag): 

422 """ 

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

424 """ 

425 BaseType = auto() 

426 Subtype = auto() 

427 

428 ReferenceInExpression = auto() 

429 

430 

431@export 

432class Design(ModelEntity): 

433 """ 

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

435 

436 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 

437 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 

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

439 

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

441 

442 * :attr:`DependencyGraph` 

443 * :attr:`CompileOrderGraph` 

444 * :attr:`HierarchyGraph` 

445 * :attr:`ObjectGraph` 

446 """ 

447 _name: Nullable[str] #: Name of the design 

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

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

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

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

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

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

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

455 

456 def __init__(self, name: Nullable[str] = None) -> None: 

457 """ 

458 Initializes a VHDL design. 

459 

460 :param name: Name of the design. 

461 """ 

462 super().__init__() 

463 

464 self._name = name 

465 self._libraries = {} 

466 self._documents = [] 

467 

468 self._compileOrderGraph = Graph() 

469 self._dependencyGraph = Graph() 

470 self._hierarchyGraph = Graph() 

471 self._objectGraph = Graph() 

472 self._toplevel = None 

473 

474 @readonly 

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

476 """ 

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

478 

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

480 """ 

481 return self._libraries 

482 

483 @readonly 

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

485 """ 

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

487 

488 :returns: A list of all documents. 

489 """ 

490 return self._documents 

491 

492 @readonly 

493 def CompileOrderGraph(self) -> Graph: 

494 """ 

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

496 

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

498 """ 

499 return self._compileOrderGraph 

500 

501 @readonly 

502 def DependencyGraph(self) -> Graph: 

503 """ 

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

505 

506 :returns: Reference to the dependency graph. 

507 """ 

508 return self._dependencyGraph 

509 

510 @readonly 

511 def HierarchyGraph(self) -> Graph: 

512 """ 

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

514 

515 :returns: Reference to the hierarchy graph. 

516 """ 

517 return self._hierarchyGraph 

518 

519 @readonly 

520 def ObjectGraph(self) -> Graph: 

521 """ 

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

523 

524 :returns: Reference to the object graph. 

525 """ 

526 return self._objectGraph 

527 

528 @readonly 

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

530 """ 

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

532 

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

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

535 

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

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

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

539 """ 

540 # Check for cached result 

541 if self._toplevel is not None: 

542 return self._toplevel 

543 

544 if self._hierarchyGraph.EdgeCount == 0: 

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

546 

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

548 if len(roots) == 1: 

549 toplevel = roots[0] 

550 self._hierarchyGraph["toplevel"] = toplevel 

551 self._toplevel = toplevel.Value 

552 

553 return toplevel.Value 

554 else: 

555 raise VHDLModelException(f"Found more than one toplevel: {', '.join(roots)}") 

556 

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

558 """ 

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

560 

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

562 

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

564 """ 

565 from pyVHDLModel.STD import Std 

566 

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

568 

569 library = Std() 

570 for designUnit in library.IterateDesignUnits(): 

571 doc._AddDesignUnit(designUnit) 

572 

573 self.AddLibrary(library) 

574 

575 return library 

576 

577 def LoadIEEELibrary(self) -> 'Library': 

578 """ 

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

580 

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

582 

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

584 """ 

585 from pyVHDLModel.IEEE import Ieee 

586 

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

588 

589 library = Ieee() 

590 for designUnit in library.IterateDesignUnits(): 

591 doc._AddDesignUnit(designUnit) 

592 

593 self.AddLibrary(library) 

594 

595 return library 

596 

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

598 """ 

599 Add a VHDL library to the design. 

600 

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

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

603 

604 :param library: Library object to loaded. 

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

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

607 """ 

608 libraryIdentifier = library.NormalizedIdentifier 

609 if libraryIdentifier in self._libraries: 

610 raise LibraryExistsInDesignError(library) 

611 

612 if library._parent is not None: 

613 raise LibraryRegisteredToForeignDesignError(library) 

614 

615 self._libraries[libraryIdentifier] = library 

616 library._parent = self 

617 

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

619 """ 

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

621 

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

623 

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

625 :returns: The VHDL library object. 

626 """ 

627 libraryIdentifier = libraryName.lower() 

628 try: 

629 return self._libraries[libraryIdentifier] 

630 except KeyError: 

631 lib = Library(libraryName, parent=self) 

632 self._libraries[libraryIdentifier] = lib 

633 lib._parent = self 

634 return lib 

635 

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

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

638 """ 

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

640 

641 .. rubric:: Algorithm 

642 

643 1. Iterate all entities in the document 

644 

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

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

647 

648 2. Iterate all architectures in the document 

649 

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

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

652 

653 3. Iterate all packages in the document 

654 

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

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

657 

658 4. Iterate all package bodies in the document 

659 

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

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

662 

663 5. Iterate all configurations in the document 

664 

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

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

667 

668 6. Iterate all contexts in the document 

669 

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

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

672 

673 :param document: The VHDL source code file. 

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

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

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

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

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

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

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

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

682 """ 

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

684 # should the libraries parent be checked too? 

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

686 raise LibraryNotRegisteredError(library) 

687 

688 self._documents.append(document) 

689 document._parent = self 

690 

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

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

693 raise EntityExistsInLibraryError(entity, library) 

694 

695 library._entities[entityIdentifier] = entity 

696 entity.Library = library 

697 

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

699 try: 

700 architecturesPerEntity = library._architectures[entityIdentifier] 

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

702 if architectureIdentifier in architecturesPerEntity: 

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

704 

705 architecturesPerEntity[architectureIdentifier] = architecture 

706 architecture.Library = library 

707 except KeyError: 

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

709 library._architectures[entityIdentifier] = architecturesPerEntity 

710 

711 for architecture in architecturesPerEntity.values(): 

712 architecture.Library = library 

713 

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

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

716 raise PackageExistsInLibraryError(package, library) 

717 

718 library._packages[packageIdentifier] = package 

719 package.Library = library 

720 

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

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

723 raise PackageBodyExistsError(packageBody, library) 

724 

725 library._packageBodies[packageBodyIdentifier] = packageBody 

726 packageBody.Library = library 

727 

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

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

730 raise ConfigurationExistsInLibraryError(configuration, library) 

731 

732 library._configurations[configurationIdentifier] = configuration 

733 configuration.Library = library 

734 

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

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

737 raise ContextExistsInLibraryError(context, library) 

738 

739 library._contexts[contextIdentifier] = context 

740 context.Library = library 

741 

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

743 """ 

744 Iterate all design units in the design. 

745 

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

747 

748 .. rubric:: Algorithm 

749 

750 1. Iterate all VHDL libraries. 

751 

752 1. Iterate all contexts in that library. 

753 2. Iterate all packages in that library. 

754 3. Iterate all package bodies in that library. 

755 4. Iterate all entites in that library. 

756 5. Iterate all architectures in that library. 

757 6. Iterate all configurations in that library. 

758 

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

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

761 

762 .. seealso:: 

763 

764 :meth:`pyVHDLModel.Library.IterateDesignUnits` 

765 Iterate all design units in the library. 

766 :meth:`pyVHDLModel.Document.IterateDesignUnits` 

767 Iterate all design units in the document. 

768 """ 

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

770 yield from library.IterateDesignUnits(filter) 

771 

772 def Analyze(self) -> None: 

773 """ 

774 Analyze the whole design. 

775 

776 .. rubric:: Algorithm 

777 

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

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

780 2. Analyze dependencies of types and objects. 

781 

782 .. seealso:: 

783 

784 :meth:`AnalyzeDependencies` 

785 Analyze the dependencies of design units. 

786 

787 :meth:`AnalyzeObjects` 

788 Analyze the dependencies of types and objects. 

789 """ 

790 self.AnalyzeDependencies() 

791 self.AnalyzeObjects() 

792 

793 def AnalyzeDependencies(self) -> None: 

794 """ 

795 Analyze the dependencies of design units. 

796 

797 .. rubric:: Algorithm 

798 

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

800 |rarr| :meth:`CreateDependencyGraph` 

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

802 |rarr| :meth:`CreateCompileOrderGraph` 

803 3. Index all packages. |br| 

804 |rarr| :meth:`IndexPackages` 

805 4. Index all architectures. |br| 

806 |rarr| :meth:`IndexArchitectures` 

807 5. Link all contexts |br| 

808 |rarr| :meth:`LinkContexts` 

809 6. Link all architectures. |br| 

810 |rarr| :meth:`LinkArchitectures` 

811 7. Link all package bodies. |br| 

812 |rarr| :meth:`LinkPackageBodies` 

813 8. Link all library references. |br| 

814 |rarr| :meth:`LinkLibraryReferences` 

815 9. Link all package references. |br| 

816 |rarr| :meth:`LinkPackageReferences` 

817 10. Link all context references. |br| 

818 |rarr| :meth:`LinkContextReferences` 

819 11. Link all components. |br| 

820 |rarr| :meth:`LinkComponents` 

821 12. Link all instantiations. |br| 

822 |rarr| :meth:`LinkInstantiations` 

823 13. Create the hierarchy graph. |br| 

824 |rarr| :meth:`CreateHierarchyGraph` 

825 14. Compute the compile order. |br| 

826 |rarr| :meth:`ComputeCompileOrder` 

827 """ 

828 self.CreateDependencyGraph() 

829 self.CreateCompileOrderGraph() 

830 

831 self.IndexPackages() 

832 self.IndexArchitectures() 

833 

834 self.LinkContexts() 

835 self.LinkArchitectures() 

836 self.LinkPackageBodies() 

837 self.LinkLibraryReferences() 

838 self.LinkPackageReferences() 

839 self.LinkContextReferences() 

840 

841 self.LinkComponents() 

842 self.LinkInstantiations() 

843 self.CreateHierarchyGraph() 

844 self.ComputeCompileOrder() 

845 

846 def AnalyzeObjects(self) -> None: 

847 """ 

848 Analyze the dependencies of types and objects. 

849 

850 .. rubric:: Algorithm 

851 

852 1. Index all entities. |br| 

853 |rarr| :meth:`IndexEntities` 

854 2. Index all package bodies. |br| 

855 |rarr| :meth:`IndexPackageBodies` 

856 3. Import objects. |br| 

857 |rarr| :meth:`ImportObjects` 

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

859 |rarr| :meth:`CreateTypeAndObjectGraph` 

860 """ 

861 self.IndexEntities() 

862 self.IndexPackageBodies() 

863 

864 self.ImportObjects() 

865 self.CreateTypeAndObjectGraph() 

866 

867 def CreateDependencyGraph(self) -> None: 

868 """ 

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

870 

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

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

873 

874 Each vertex has the following properties: 

875 

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

877 * The vertex' value references the design unit. 

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

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

880 

881 .. rubric:: Algorithm 

882 

883 1. Iterate all libraries in the design. 

884 

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

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

887 

888 1. Iterate all contexts in that library. 

889 

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

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

892 

893 2. Iterate all packages in that library. 

894 

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

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

897 

898 3. Iterate all package bodies in that library. 

899 

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

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

902 

903 4. Iterate all entities in that library. 

904 

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

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

907 

908 5. Iterate all architectures in that library. 

909 

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

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

912 

913 6. Iterate all configurations in that library. 

914 

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

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

917 """ 

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

919 

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

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

922 dependencyVertex["kind"] = DependencyGraphVertexKind.Library 

923 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries 

924 library._dependencyVertex = dependencyVertex 

925 

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

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

928 dependencyVertex["kind"] = DependencyGraphVertexKind.Context 

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

930 context._dependencyVertex = dependencyVertex 

931 

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

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

934 dependencyVertex["kind"] = DependencyGraphVertexKind.Package 

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

936 package._dependencyVertex = dependencyVertex 

937 

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

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

940 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody 

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

942 packageBody._dependencyVertex = dependencyVertex 

943 

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

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

946 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity 

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

948 entity._dependencyVertex = dependencyVertex 

949 

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

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

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

953 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture 

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

955 architecture._dependencyVertex = dependencyVertex 

956 

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

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

959 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration 

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

961 configuration._dependencyVertex = dependencyVertex 

962 

963 def CreateCompileOrderGraph(self) -> None: 

964 """ 

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

966 

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

968 graph and bidirectionally referenced. 

969 

970 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 

971 document relationship. 

972 

973 Each added vertex has the following properties: 

974 

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

976 * The vertex' value references the document. 

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

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

979 

980 .. rubric:: Algorithm 

981 

982 1. Iterate all documents in the design. 

983 

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

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

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

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

988 

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

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

991 

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

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

994 

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

996 """ 

997 for document in self._documents: 

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

999 dependencyVertex["kind"] = DependencyGraphVertexKind.Document 

1000 document._dependencyVertex = dependencyVertex 

1001 

1002 compilerOrderVertex = dependencyVertex.Copy( 

1003 self._compileOrderGraph, 

1004 copyDict=True, 

1005 linkingKeyToOriginalVertex="dependencyVertex", 

1006 linkingKeyFromOriginalVertex="compileOrderVertex" 

1007 ) 

1008 document._compileOrderVertex = compilerOrderVertex 

1009 

1010 for designUnit in document._designUnits: 

1011 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex) 

1012 edge["kind"] = DependencyGraphEdgeKind.SourceFile 

1013 

1014 def ImportObjects(self) -> None: 

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

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

1017 for referencedPackage in referencedLibrary.values(): 

1018 for declaredItem in referencedPackage._declaredItems: 

1019 if isinstance(declaredItem, MultipleNamedEntityMixin): 1019 ↛ 1020line 1019 didn't jump to line 1020 because the condition on line 1019 was never true

1020 for normalizedIdentifier in declaredItem._normalizedIdentifiers: 

1021 package._namespace._elements[normalizedIdentifier] = declaredItem 

1022 elif isinstance(declaredItem, NamedEntityMixin): 1022 ↛ 1025line 1022 didn't jump to line 1025 because the condition on line 1022 was always true

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

1024 else: 

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

1026 

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

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

1029 _ImportObjects(package) 

1030 

1031 for document in self.IterateDocumentsInCompileOrder(): 

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

1033 _ImportObjects(package) 

1034 

1035 def CreateTypeAndObjectGraph(self) -> None: 

1036 def _HandlePackage(package) -> None: 

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

1038 

1039 for deferredConstant in package._deferredConstants.values(): 1039 ↛ 1040line 1039 didn't jump to line 1040 because the loop on line 1039 never started

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

1041 deferredConstantVertex = Vertex( 

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

1043 value=deferredConstant, 

1044 graph=self._objectGraph 

1045 ) 

1046 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant 

1047 deferredConstant._objectVertex = deferredConstantVertex 

1048 

1049 for constant in package._constants.values(): 1049 ↛ 1050line 1049 didn't jump to line 1050 because the loop on line 1049 never started

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

1051 constantVertex = Vertex( 

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

1053 value=constant, 

1054 graph=self._objectGraph 

1055 ) 

1056 constantVertex["kind"] = ObjectGraphVertexKind.Constant 

1057 constant._objectVertex = constantVertex 

1058 

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

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

1061 typeVertex = Vertex( 

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

1063 value=type, 

1064 graph=self._objectGraph 

1065 ) 

1066 typeVertex["kind"] = ObjectGraphVertexKind.Type 

1067 type._objectVertex = typeVertex 

1068 

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

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

1071 subtypeVertex = Vertex( 

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

1073 value=subtype, 

1074 graph=self._objectGraph 

1075 ) 

1076 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype 

1077 subtype._objectVertex = subtypeVertex 

1078 

1079 for function in package._functions.values(): 1079 ↛ 1080line 1079 didn't jump to line 1080 because the loop on line 1079 never started

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

1081 functionVertex = Vertex( 

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

1083 value=function, 

1084 graph=self._objectGraph 

1085 ) 

1086 functionVertex["kind"] = ObjectGraphVertexKind.Function 

1087 function._objectVertex = functionVertex 

1088 

1089 for procedure in package._procedures.values(): 1089 ↛ 1090line 1089 didn't jump to line 1090 because the loop on line 1089 never started

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

1091 procedureVertex = Vertex( 

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

1093 value=procedure, 

1094 graph=self._objectGraph 

1095 ) 

1096 procedureVertex["kind"] = ObjectGraphVertexKind.Function 

1097 procedure._objectVertex = procedureVertex 

1098 

1099 for signal in package._signals.values(): 1099 ↛ 1100line 1099 didn't jump to line 1100 because the loop on line 1099 never started

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

1101 signalVertex = Vertex( 

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

1103 value=signal, 

1104 graph=self._objectGraph 

1105 ) 

1106 signalVertex["kind"] = ObjectGraphVertexKind.Signal 

1107 signal._objectVertex = signalVertex 

1108 

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

1110 if isinstance(expression, UnaryExpression): 1110 ↛ 1111line 1110 didn't jump to line 1111 because the condition on line 1110 was never true

1111 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex) 

1112 elif isinstance(expression, BinaryExpression): 1112 ↛ 1113line 1112 didn't jump to line 1113 because the condition on line 1112 was never true

1113 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex) 

1114 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex) 

1115 elif isinstance(expression, TernaryExpression): 1115 ↛ 1116line 1115 didn't jump to line 1116 because the condition on line 1115 was never true

1116 pass 

1117 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): 1117 ↛ 1118line 1117 didn't jump to line 1118 because the condition on line 1117 was never true

1118 obj = namespace.FindObject(expression) 

1119 expression._reference = obj 

1120 

1121 edge = obj._objectVertex.EdgeToVertex(typeVertex) 

1122 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression 

1123 else: 

1124 pass 

1125 

1126 def _LinkItems(package: Package): 

1127 for item in package._declaredItems: 

1128 if isinstance(item, Constant): 1128 ↛ 1129line 1128 didn't jump to line 1129 because the condition on line 1128 was never true

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

1130 elif isinstance(item, DeferredConstant): 1130 ↛ 1131line 1130 didn't jump to line 1131 because the condition on line 1130 was never true

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

1132 elif isinstance(item, Signal): 1132 ↛ 1133line 1132 didn't jump to line 1133 because the condition on line 1132 was never true

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

1134 elif isinstance(item, IntegerType): 

1135 typeNode = item._objectVertex 

1136 

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

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

1139 # elif isinstance(item, FloatingType): 

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

1141 elif isinstance(item, PhysicalType): 

1142 typeNode = item._objectVertex 

1143 

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

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

1146 elif isinstance(item, ArrayType): 

1147 # Resolve dimensions 

1148 for dimension in item._dimensions: 

1149 subtype = package._namespace.FindSubtype(dimension) 

1150 dimension._reference = subtype 

1151 

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

1153 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1154 

1155 # Resolve element subtype 

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

1157 item._elementType._reference = subtype 

1158 

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

1160 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1161 elif isinstance(item, RecordType): 1161 ↛ 1163line 1161 didn't jump to line 1163 because the condition on line 1161 was never true

1162 # Resolve each elements subtype 

1163 for element in item._elements: 

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

1165 element._subtype._reference = subtype 

1166 

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

1168 edge["kind"] = ObjectGraphEdgeKind.Subtype 

1169 else: 

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

1171 

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

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

1174 _HandlePackage(package) 

1175 _LinkItems(package) 

1176 

1177 for document in self.IterateDocumentsInCompileOrder(): 

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

1179 _HandlePackage(package) 

1180 _LinkItems(package) 

1181 

1182 def LinkContexts(self) -> None: 

1183 """ 

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

1185 

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

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

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

1189 

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

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

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

1193 dependency graph is added for that relationship. 

1194 

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

1196 referenced package, 

1197 """ 

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

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

1200 workingLibrary: Library = context.Library 

1201 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier 

1202 

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

1204 context._referencedPackages[libraryNormalizedIdentifier] = {} 

1205 context._referencedContexts[libraryNormalizedIdentifier] = {} 

1206 

1207 # Process all library clauses 

1208 for libraryReference in context._libraryReferences: 

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

1210 for libraryName in libraryReference.Symbols: 

1211 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier 

1212 try: 

1213 library = self._libraries[libraryNormalizedIdentifier] 

1214 except KeyError: 

1215 raise ReferencedLibraryNotExistingError(context, libraryName) 

1216 # TODO: add position to these messages 

1217 

1218 libraryName.Library = library 

1219 

1220 context._referencedLibraries[libraryNormalizedIdentifier] = library 

1221 context._referencedPackages[libraryNormalizedIdentifier] = {} 

1222 context._referencedContexts[libraryNormalizedIdentifier] = {} 

1223 # TODO: warn duplicate library reference 

1224 

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

1226 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1227 

1228 # Process all use clauses 

1229 for packageReference in context.PackageReferences: 

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

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

1232 packageName = symbol.Name.Prefix 

1233 libraryName = packageName.Prefix 

1234 

1235 libraryNormalizedIdentifier = libraryName._normalizedIdentifier 

1236 packageNormalizedIdentifier = packageName._normalizedIdentifier 

1237 

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

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

1240 library: Library = context._parent 

1241 libraryNormalizedIdentifier = library._normalizedIdentifier 

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

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

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

1245 else: 

1246 library = self._libraries[libraryNormalizedIdentifier] 

1247 

1248 try: 

1249 package = library._packages[packageNormalizedIdentifier] 

1250 except KeyError: 

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

1252 

1253 symbol.Package = package 

1254 

1255 # TODO: warn duplicate package reference 

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

1257 

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

1259 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1260 

1261 # TODO: update the namespace with visible members 

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

1263 pass 

1264 

1265 elif isinstance(symbol, PackageMemberReferenceSymbol): 

1266 raise NotImplementedError() 

1267 else: 

1268 raise VHDLModelException() 

1269 

1270 def LinkArchitectures(self) -> None: 

1271 """ 

1272 Link all architectures to corresponding entities in all libraries. 

1273 

1274 .. rubric:: Algorithm 

1275 

1276 1. Iterate all libraries: 

1277 

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

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

1280 

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

1282 

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

1284 

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

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

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

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

1289 

1290 .. seealso:: 

1291 

1292 :meth:`LinkPackageBodies` 

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

1294 """ 

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

1296 library.LinkArchitectures() 

1297 

1298 def LinkPackageBodies(self) -> None: 

1299 """ 

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

1301 

1302 .. rubric:: Algorithm 

1303 

1304 1. Iterate all libraries: 

1305 

1306 1. Iterate all package bodies. 

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

1308 

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

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

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

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

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

1314 

1315 .. seealso:: 

1316 

1317 :meth:`LinkArchitectures` 

1318 Link all architectures to corresponding entities in all libraries. 

1319 """ 

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

1321 library.LinkPackageBodies() 

1322 

1323 def LinkLibraryReferences(self) -> None: 

1324 DEFAULT_LIBRARIES = ("std",) 

1325 

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

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

1328 if isinstance(designUnit, PrimaryUnit): 

1329 for libraryIdentifier in DEFAULT_LIBRARIES: 

1330 referencedLibrary = self._libraries[libraryIdentifier] 

1331 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary 

1332 designUnit._referencedPackages[libraryIdentifier] = {} 

1333 designUnit._referencedContexts[libraryIdentifier] = {} 

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

1335 # TODO: warn duplicate library reference 

1336 

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

1338 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1339 

1340 workingLibrary: Library = designUnit.Library 

1341 libraryIdentifier = workingLibrary.NormalizedIdentifier 

1342 referencedLibrary = self._libraries[libraryIdentifier] 

1343 

1344 

1345 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary 

1346 designUnit._referencedPackages[libraryIdentifier] = {} 

1347 designUnit._referencedContexts[libraryIdentifier] = {} 

1348 

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

1350 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1351 

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

1353 else: 

1354 if isinstance(designUnit, Architecture): 

1355 referencedLibraries = designUnit.Entity.Entity._referencedLibraries 

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

1357 referencedLibraries = designUnit.Package.Package._referencedLibraries 

1358 else: 

1359 raise VHDLModelException() 

1360 

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

1362 designUnit._referencedLibraries[libraryIdentifier] = library 

1363 

1364 for libraryReference in designUnit._libraryReferences: 

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

1366 for librarySymbol in libraryReference.Symbols: 

1367 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier 

1368 try: 

1369 library = self._libraries[libraryIdentifier] 

1370 except KeyError: 

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

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

1373 raise ex 

1374 

1375 librarySymbol.Library = library 

1376 designUnit._referencedLibraries[libraryIdentifier] = library 

1377 designUnit._referencedPackages[libraryIdentifier] = {} 

1378 designUnit._referencedContexts[libraryIdentifier] = {} 

1379 # TODO: warn duplicate library reference 

1380 

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

1382 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause 

1383 

1384 def LinkPackageReferences(self) -> None: 

1385 DEFAULT_PACKAGES = ( 

1386 ("std", ("standard",)), 

1387 ) 

1388 

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

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

1391 if isinstance(designUnit, PrimaryUnit): 

1392 if designUnit.Library.NormalizedIdentifier != "std" and \ 

1393 designUnit.NormalizedIdentifier != "standard": 

1394 for lib in DEFAULT_PACKAGES: 

1395 if lib[0] not in designUnit._referencedLibraries: 1395 ↛ 1396line 1395 didn't jump to line 1396 because the condition on line 1395 was never true

1396 raise VHDLModelException() 

1397 for pack in lib[1]: 

1398 referencedPackage = self._libraries[lib[0]]._packages[pack] 

1399 designUnit._referencedPackages[lib[0]][pack] = referencedPackage 

1400 # TODO: catch KeyError on self._libraries[lib[0]]._packages[pack] 

1401 # TODO: warn duplicate package reference 

1402 

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

1404 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1405 

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

1407 else: 

1408 if isinstance(designUnit, Architecture): 

1409 referencedPackages = designUnit.Entity.Entity._referencedPackages 

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

1411 referencedPackages = designUnit.Package.Package._referencedPackages 

1412 else: 

1413 raise VHDLModelException() 

1414 

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

1416 designUnit._referencedPackages[packageIdentifier] = package 

1417 

1418 for packageReference in designUnit.PackageReferences: 

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

1420 for packageMemberSymbol in packageReference.Symbols: 

1421 packageName = packageMemberSymbol.Name.Prefix 

1422 libraryName = packageName.Prefix 

1423 

1424 libraryIdentifier = libraryName.NormalizedIdentifier 

1425 packageIdentifier = packageName.NormalizedIdentifier 

1426 

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

1428 if libraryIdentifier == "work": 

1429 library: Library = designUnit.Library 

1430 libraryIdentifier = library.NormalizedIdentifier 

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

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

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

1434 else: 

1435 library = self._libraries[libraryIdentifier] 

1436 

1437 try: 

1438 package = library._packages[packageIdentifier] 

1439 except KeyError: 

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

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

1442 raise ex 

1443 

1444 packageMemberSymbol.Package = package 

1445 

1446 # TODO: warn duplicate package reference 

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

1448 

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

1450 dependency["kind"] = DependencyGraphEdgeKind.UseClause 

1451 

1452 # TODO: update the namespace with visible members 

1453 if isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1453 ↛ 1457line 1453 didn't jump to line 1457 because the condition on line 1453 was always true

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

1455 designUnit._namespace._elements[componentIdentifier] = component 

1456 

1457 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol): 

1458 raise NotImplementedError() 

1459 else: 

1460 raise VHDLModelException() 

1461 

1462 def LinkContextReferences(self) -> None: 

1463 for designUnit in self.IterateDesignUnits(): 

1464 for contextReference in designUnit._contextReferences: 

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

1466 for contextSymbol in contextReference.Symbols: 

1467 libraryName = contextSymbol.Name.Prefix 

1468 

1469 libraryIdentifier = libraryName.NormalizedIdentifier 

1470 contextIdentifier = contextSymbol.Name.NormalizedIdentifier 

1471 

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

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

1474 referencedLibrary = designUnit.Library 

1475 libraryIdentifier = referencedLibrary.NormalizedIdentifier 

1476 elif libraryIdentifier not in designUnit._referencedLibraries: 

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

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

1479 else: 

1480 referencedLibrary = self._libraries[libraryIdentifier] 

1481 

1482 try: 

1483 referencedContext = referencedLibrary._contexts[contextIdentifier] 

1484 except KeyError: 

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

1486 

1487 contextSymbol.Package = referencedContext 

1488 

1489 # TODO: warn duplicate referencedContext reference 

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

1491 

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

1493 dependency["kind"] = DependencyGraphEdgeKind.ContextReference 

1494 

1495 for vertex in self._dependencyGraph.IterateTopologically(): 

1496 if vertex["kind"] is DependencyGraphVertexKind.Context: 

1497 context: Context = vertex.Value 

1498 for designUnitVertex in vertex.IteratePredecessorVertices(): 

1499 designUnit: DesignUnit = designUnitVertex.Value 

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

1501 # if libraryIdentifier in designUnit._referencedLibraries: 

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

1503 

1504 designUnit._referencedLibraries[libraryIdentifier] = library 

1505 designUnit._referencedPackages[libraryIdentifier] = {} 

1506 

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

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

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

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

1511 

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

1513 

1514 def LinkComponents(self) -> None: 

1515 for package in self.IterateDesignUnits(DesignUnitKind.Package): # type: Package 

1516 library = package._parent 

1517 for component in package._components.values(): 1517 ↛ 1518line 1517 didn't jump to line 1518 because the loop on line 1517 never started

1518 try: 

1519 entity = library._entities[component.NormalizedIdentifier] 

1520 except KeyError: 

1521 print(f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.") 

1522 

1523 component.Entity = entity 

1524 

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

1526 # Currently, component has no _dependencyVertex field 

1527 

1528 def LinkInstantiations(self) -> None: 

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

1530 for instance in architecture.IterateInstantiations(): 

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

1532 libraryName = instance.Entity.Name.Prefix 

1533 libraryIdentifier = libraryName.Identifier 

1534 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier 

1535 if normalizedLibraryIdentifier == "work": 

1536 libraryIdentifier = architecture.Library.Identifier 

1537 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier 

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

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

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

1541 raise ex 

1542 

1543 try: 

1544 library = self._libraries[normalizedLibraryIdentifier] 

1545 except KeyError: 

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

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

1548 raise ex 

1549 

1550 try: 

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

1552 except KeyError: 

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

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

1555 if libs: 

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

1557 raise ex 

1558 

1559 instance.Entity.Entity = entity 

1560 

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

1562 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation 

1563 

1564 elif isinstance(instance, ComponentInstantiation): 

1565 component = architecture._namespace.FindComponent(instance.Component) 

1566 

1567 instance.Component.Component = component 

1568 

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

1570 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation 

1571 

1572 elif isinstance(instance, ConfigurationInstantiation): 

1573 # pass 

1574 print(instance.Label, instance.Configuration) 

1575 

1576 def IndexPackages(self) -> None: 

1577 """ 

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

1579 

1580 .. rubric:: Algorithm 

1581 

1582 1. Iterate all libraries: 

1583 

1584 1. Iterate all packages |br| 

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

1586 

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

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

1589 

1590 .. seealso:: 

1591 

1592 :meth:`IndexPackageBodies` 

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

1594 :meth:`IndexEntities` 

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

1596 :meth:`IndexArchitectures` 

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

1598 """ 

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

1600 library.IndexPackages() 

1601 

1602 def IndexPackageBodies(self) -> None: 

1603 """ 

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

1605 

1606 .. rubric:: Algorithm 

1607 

1608 1. Iterate all libraries: 

1609 

1610 1. Iterate all packages |br| 

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

1612 

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

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

1615 

1616 .. seealso:: 

1617 

1618 :meth:`IndexPackages` 

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

1620 :meth:`IndexEntities` 

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

1622 :meth:`IndexArchitectures` 

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

1624 """ 

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

1626 library.IndexPackageBodies() 

1627 

1628 def IndexEntities(self) -> None: 

1629 """ 

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

1631 

1632 .. rubric:: Algorithm 

1633 

1634 1. Iterate all libraries: 

1635 

1636 1. Iterate all packages |br| 

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

1638 

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

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

1641 

1642 .. seealso:: 

1643 

1644 :meth:`IndexPackages` 

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

1646 :meth:`IndexPackageBodies` 

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

1648 :meth:`IndexArchitectures` 

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

1650 """ 

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

1652 library.IndexEntities() 

1653 

1654 def IndexArchitectures(self) -> None: 

1655 """ 

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

1657 

1658 .. rubric:: Algorithm 

1659 

1660 1. Iterate all libraries: 

1661 

1662 1. Iterate all packages |br| 

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

1664 

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

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

1667 

1668 .. seealso:: 

1669 

1670 :meth:`IndexPackages` 

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

1672 :meth:`IndexPackageBodies` 

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

1674 :meth:`IndexEntities` 

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

1676 """ 

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

1678 library.IndexArchitectures() 

1679 

1680 def CreateHierarchyGraph(self) -> None: 

1681 """ 

1682 Create the hierarchy graph from dependency graph. 

1683 

1684 .. rubric:: Algorithm 

1685 

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

1687 

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

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

1690 

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

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

1693 

1694 2. Iterate all architectures ... 

1695 

1696 .. todo:: Design::CreateHierarchyGraph describe algorithm 

1697 

1698 1. Iterate all outbound edges 

1699 

1700 .. todo:: Design::CreateHierarchyGraph describe algorithm 

1701 """ 

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

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

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

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

1706 vertex.Value._hierarchyVertex = hierarchyVertex 

1707 

1708 # Copy implementation edges from 

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

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

1711 kind: DependencyGraphEdgeKind = dependencyEdge["kind"] 

1712 if DependencyGraphEdgeKind.Implementation in kind: 

1713 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"] 

1714 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex) 

1715 elif DependencyGraphEdgeKind.Instantiation in kind: 

1716 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"] 

1717 

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

1719 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex): 

1720 continue 

1721 

1722 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex) 

1723 else: 

1724 continue 

1725 

1726 newEdge["kind"] = kind 

1727 

1728 def ComputeCompileOrder(self) -> None: 

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

1730 return ( 

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

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

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

1734 DependencyGraphEdgeKind.ContextReference in edge["kind"] 

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

1736 

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

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

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

1740 

1741 sourceVertex = sourceDocument._compileOrderVertex 

1742 destinationVertex = destinationDocument._compileOrderVertex 

1743 

1744 # Don't add self-edges 

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

1746 continue 

1747 # Don't add parallel edges 

1748 elif sourceVertex.HasEdgeToDestination(destinationVertex): 

1749 continue 

1750 

1751 e = sourceVertex.EdgeToVertex(destinationVertex) 

1752 e["kind"] = DependencyGraphEdgeKind.CompileOrder 

1753 

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

1755 e["kind"] = DependencyGraphEdgeKind.CompileOrder 

1756 

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

1758 """ 

1759 Iterate all document in compile-order. 

1760 

1761 .. rubric:: Algorithm 

1762 

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

1764 

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

1766 :meth:`pyTooling.Graph.Graph.IterateTopologically` 

1767 

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

1769 

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

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

1772 

1773 .. seealso:: 

1774 

1775 .. todo:: missing text 

1776 

1777 :meth:`pyVHDLModel.Design.ComputeCompileOrder` 

1778 

1779 """ 

1780 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1: 1780 ↛ 1781line 1780 didn't jump to line 1781 because the condition on line 1780 was never true

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

1782 

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

1784 yield compileOrderNode.Value 

1785 

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

1787 raise NotImplementedError() 

1788 

1789 def __repr__(self) -> str: 

1790 """ 

1791 Formats a representation of the design. 

1792 

1793 **Format:** ``Document: 'my_design'`` 

1794 

1795 :returns: String representation of the design. 

1796 """ 

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

1798 

1799 __str__ = __repr__ 

1800 

1801 

1802@export 

1803class Library(ModelEntity, NamedEntityMixin): 

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

1805 

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

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

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

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

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

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

1812 

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

1814 

1815 def __init__(self, identifier: str, parent: ModelEntity = None) -> None: 

1816 super().__init__(parent) 

1817 NamedEntityMixin.__init__(self, identifier) 

1818 

1819 self._contexts = {} 

1820 self._configurations = {} 

1821 self._entities = {} 

1822 self._architectures = {} 

1823 self._packages = {} 

1824 self._packageBodies = {} 

1825 

1826 self._dependencyVertex = None 

1827 

1828 @readonly 

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

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

1831 return self._contexts 

1832 

1833 @readonly 

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

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

1836 return self._configurations 

1837 

1838 @readonly 

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

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

1841 return self._entities 

1842 

1843 @readonly 

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

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

1846 return self._architectures 

1847 

1848 @readonly 

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

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

1851 return self._packages 

1852 

1853 @readonly 

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

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

1856 return self._packageBodies 

1857 

1858 @readonly 

1859 def DependencyVertex(self) -> Vertex: 

1860 """ 

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

1862 

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

1864 

1865 :returns: The corresponding dependency vertex. 

1866 """ 

1867 return self._dependencyVertex 

1868 

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

1870 """ 

1871 Iterate all design units in the library. 

1872 

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

1874 

1875 .. rubric:: Algorithm 

1876 

1877 1. Iterate all contexts in that library. 

1878 2. Iterate all packages in that library. 

1879 3. Iterate all package bodies in that library. 

1880 4. Iterate all entites in that library. 

1881 5. Iterate all architectures in that library. 

1882 6. Iterate all configurations in that library. 

1883 

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

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

1886 

1887 .. seealso:: 

1888 

1889 :meth:`pyVHDLModel.Design.IterateDesignUnits` 

1890 Iterate all design units in the design. 

1891 :meth:`pyVHDLModel.Document.IterateDesignUnits` 

1892 Iterate all design units in the document. 

1893 """ 

1894 if DesignUnitKind.Context in filter: 

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

1896 yield context 

1897 

1898 if DesignUnitKind.Package in filter: 

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

1900 yield package 

1901 

1902 if DesignUnitKind.PackageBody in filter: 

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

1904 yield packageBody 

1905 

1906 if DesignUnitKind.Entity in filter: 

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

1908 yield entity 

1909 

1910 if DesignUnitKind.Architecture in filter: 

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

1912 for architecture in architectures.values(): 

1913 yield architecture 

1914 

1915 if DesignUnitKind.Configuration in filter: 

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

1917 yield configuration 

1918 

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

1920 # yield verificationProperty 

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

1922 # yield entity 

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

1924 # yield verificationMode 

1925 

1926 def LinkArchitectures(self) -> None: 

1927 """ 

1928 Link all architectures to corresponding entities. 

1929 

1930 .. rubric:: Algorithm 

1931 

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

1933 

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

1935 

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

1937 

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

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

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

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

1942 

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

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

1945 

1946 .. seealso:: 

1947 

1948 :meth:`LinkPackageBodies` 

1949 Link all package bodies to corresponding packages. 

1950 """ 

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

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

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

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

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

1956 # TODO: add code position 

1957 

1958 entity = self._entities[entityName] 

1959 for architecture in architecturesPerEntity.values(): 

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

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

1962 # TODO: add code position of existing and current 

1963 

1964 entity._architectures[architecture._normalizedIdentifier] = architecture 

1965 architecture._entity.Entity = entity 

1966 architecture._namespace._parentNamespace = entity._namespace 

1967 

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

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

1970 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation 

1971 

1972 def LinkPackageBodies(self) -> None: 

1973 """ 

1974 Link all package bodies to corresponding packages. 

1975 

1976 .. rubric:: Algorithm 

1977 

1978 1. Iterate all package bodies. 

1979 

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

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

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

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

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

1985 

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

1987 

1988 .. seealso:: 

1989 

1990 :meth:`LinkArchitectures` 

1991 Link all architectures to corresponding entities. 

1992 """ 

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

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

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

1996 

1997 package = self._packages[packageBodyName] 

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

1999 packageBody._package.Package = package 

2000 packageBody._namespace._parentNamespace = package._namespace 

2001 

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

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

2004 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation 

2005 

2006 def IndexPackages(self) -> None: 

2007 """ 

2008 Index declared items in all packages. 

2009 

2010 .. rubric:: Algorithm 

2011 

2012 1. Iterate all packages: 

2013 

2014 * Index all declared items. |br| 

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

2016 

2017 .. seealso:: 

2018 

2019 :meth:`IndexPackageBodies` 

2020 Index all declared items in a package body. 

2021 :meth:`IndexEntities` 

2022 Index all declared items in an entity. 

2023 :meth:`IndexArchitectures` 

2024 Index all declared items in an architecture. 

2025 """ 

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

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

2028 package.IndexDeclaredItems() 

2029 

2030 def IndexPackageBodies(self) -> None: 

2031 """ 

2032 Index declared items in all package bodies. 

2033 

2034 .. rubric:: Algorithm 

2035 

2036 1. Iterate all package bodies: 

2037 

2038 * Index all declared items. |br| 

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

2040 

2041 .. seealso:: 

2042 

2043 :meth:`IndexPackages` 

2044 Index all declared items in a package. 

2045 :meth:`IndexEntities` 

2046 Index all declared items in an entity. 

2047 :meth:`IndexArchitectures` 

2048 Index all declared items in an architecture. 

2049 """ 

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

2051 packageBody.IndexDeclaredItems() 

2052 

2053 def IndexEntities(self) -> None: 

2054 """ 

2055 Index declared items in all entities. 

2056 

2057 .. rubric:: Algorithm 

2058 

2059 1. Iterate all entities: 

2060 

2061 * Index all declared items. |br| 

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

2063 

2064 .. seealso:: 

2065 

2066 :meth:`IndexPackages` 

2067 Index all declared items in a package. 

2068 :meth:`IndexPackageBodies` 

2069 Index all declared items in a package body. 

2070 :meth:`IndexArchitectures` 

2071 Index all declared items in an architecture. 

2072 """ 

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

2074 entity.IndexDeclaredItems() 

2075 

2076 def IndexArchitectures(self) -> None: 

2077 """ 

2078 Index declared items in all architectures. 

2079 

2080 .. rubric:: Algorithm 

2081 

2082 1. Iterate all architectures: 

2083 

2084 * Index all declared items. |br| 

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

2086 

2087 .. seealso:: 

2088 

2089 :meth:`IndexPackages` 

2090 Index all declared items in a package. 

2091 :meth:`IndexPackageBodies` 

2092 Index all declared items in a package body. 

2093 :meth:`IndexEntities` 

2094 Index all declared items in an entity. 

2095 """ 

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

2097 for architecture in architectures.values(): 

2098 architecture.IndexDeclaredItems() 

2099 architecture.IndexStatements() 

2100 

2101 def __repr__(self) -> str: 

2102 """ 

2103 Formats a representation of the library. 

2104 

2105 **Format:** ``Library: 'my_library'`` 

2106 

2107 :returns: String representation of the library. 

2108 """ 

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

2110 

2111 __str__ = __repr__ 

2112 

2113 

2114@export 

2115class Document(ModelEntity, DocumentedEntityMixin): 

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

2117 

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

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

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

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

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

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

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

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

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

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

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

2129 

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

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

2132 

2133 def __init__(self, path: Path, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: 

2134 super().__init__(parent) 

2135 DocumentedEntityMixin.__init__(self, documentation) 

2136 

2137 self._path = path 

2138 self._designUnits = [] 

2139 self._contexts = {} 

2140 self._configurations = {} 

2141 self._entities = {} 

2142 self._architectures = {} 

2143 self._packages = {} 

2144 self._packageBodies = {} 

2145 self._verificationUnits = {} 

2146 self._verificationProperties = {} 

2147 self._verificationModes = {} 

2148 

2149 self._dependencyVertex = None 

2150 self._compileOrderVertex = None 

2151 

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

2153 """ 

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

2155 

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

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

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

2159 """ 

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

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

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

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

2164 raise ex 

2165 

2166 identifier = item._normalizedIdentifier 

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

2168 # TODO: use a more specific exception 

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

2170 

2171 self._entities[identifier] = item 

2172 self._designUnits.append(item) 

2173 item._document = self 

2174 

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

2176 """ 

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

2178 

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

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

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

2182 """ 

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

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

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

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

2187 raise ex 

2188 

2189 entity = item._entity.Name 

2190 entityIdentifier = entity._normalizedIdentifier 

2191 try: 

2192 architectures = self._architectures[entityIdentifier] 

2193 if item._normalizedIdentifier in architectures: 

2194 # TODO: use a more specific exception 

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

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

2197 

2198 architectures[item.Identifier] = item 

2199 except KeyError: 

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

2201 

2202 self._designUnits.append(item) 

2203 item._document = self 

2204 

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

2206 """ 

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

2208 

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

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

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

2212 """ 

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

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

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

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

2217 raise ex 

2218 

2219 identifier = item._normalizedIdentifier 

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

2221 # TODO: use a more specific exception 

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

2223 

2224 self._packages[identifier] = item 

2225 self._designUnits.append(item) 

2226 item._document = self 

2227 

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

2229 """ 

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

2231 

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

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

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

2235 """ 

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

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

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

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

2240 raise ex 

2241 

2242 identifier = item._normalizedIdentifier 

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

2244 # TODO: use a more specific exception 

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

2246 

2247 self._packageBodies[identifier] = item 

2248 self._designUnits.append(item) 

2249 item._document = self 

2250 

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

2252 """ 

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

2254 

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

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

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

2258 """ 

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

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

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

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

2263 raise ex 

2264 

2265 identifier = item._normalizedIdentifier 

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

2267 # TODO: use a more specific exception 

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

2269 

2270 self._contexts[identifier] = item 

2271 self._designUnits.append(item) 

2272 item._document = self 

2273 

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

2275 """ 

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

2277 

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

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

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

2281 """ 

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

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

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

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

2286 raise ex 

2287 

2288 identifier = item._normalizedIdentifier 

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

2290 # TODO: use a more specific exception 

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

2292 

2293 self._configurations[identifier] = item 

2294 self._designUnits.append(item) 

2295 item._document = self 

2296 

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

2298 if not isinstance(item, VerificationUnit): 

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

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

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

2302 raise ex 

2303 

2304 identifier = item._normalizedIdentifier 

2305 if identifier in self._verificationUnits: 

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

2307 

2308 self._verificationUnits[identifier] = item 

2309 self._designUnits.append(item) 

2310 item._document = self 

2311 

2312 def _AddVerificationProperty(self, item: VerificationProperty) -> None: 

2313 if not isinstance(item, VerificationProperty): 

2314 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.") 

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

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

2317 raise ex 

2318 

2319 identifier = item.NormalizedIdentifier 

2320 if identifier in self._verificationProperties: 

2321 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.") 

2322 

2323 self._verificationProperties[identifier] = item 

2324 self._designUnits.append(item) 

2325 item._document = self 

2326 

2327 def _AddVerificationMode(self, item: VerificationMode) -> None: 

2328 if not isinstance(item, VerificationMode): 

2329 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.") 

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

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

2332 raise ex 

2333 

2334 identifier = item.NormalizedIdentifier 

2335 if identifier in self._verificationModes: 

2336 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.") 

2337 

2338 self._verificationModes[identifier] = item 

2339 self._designUnits.append(item) 

2340 item._document = self 

2341 

2342 def _AddDesignUnit(self, item: DesignUnit) -> None: 

2343 """ 

2344 Add a design unit to the document's lists of design units. 

2345 

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

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

2348 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`. 

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

2350 """ 

2351 if not isinstance(item, DesignUnit): 2351 ↛ 2352line 2351 didn't jump to line 2352 because the condition on line 2351 was never true

2352 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.") 

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

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

2355 raise ex 

2356 

2357 if isinstance(item, Entity): 

2358 self._AddEntity(item) 

2359 elif isinstance(item, Architecture): 

2360 self._AddArchitecture(item) 

2361 elif isinstance(item, Package): 

2362 self._AddPackage(item) 

2363 elif isinstance(item, PackageBody): 

2364 self._AddPackageBody(item) 

2365 elif isinstance(item, Context): 

2366 self._AddContext(item) 

2367 elif isinstance(item, Configuration): 2367 ↛ 2369line 2367 didn't jump to line 2369 because the condition on line 2367 was always true

2368 self._AddConfiguration(item) 

2369 elif isinstance(item, VerificationUnit): 

2370 self._AddVerificationUnit(item) 

2371 elif isinstance(item, VerificationProperty): 

2372 self._AddVerificationProperty(item) 

2373 elif isinstance(item, VerificationMode): 

2374 self._AddVerificationMode(item) 

2375 else: 

2376 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.") 

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

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

2379 raise ex 

2380 

2381 @readonly 

2382 def Path(self) -> Path: 

2383 """ 

2384 Read-only property to access the document's path (:attr:`_path`). 

2385 

2386 :returns: The path of this document. 

2387 """ 

2388 return self._path 

2389 

2390 @readonly 

2391 def DesignUnits(self) -> List[DesignUnit]: 

2392 """ 

2393 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`). 

2394 

2395 :returns: List of all design units. 

2396 """ 

2397 return self._designUnits 

2398 

2399 @readonly 

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

2401 """ 

2402 Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`). 

2403 

2404 :returns: List of all contexts. 

2405 """ 

2406 return self._contexts 

2407 

2408 @readonly 

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

2410 """ 

2411 Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`). 

2412 

2413 :returns: List of all configurations. 

2414 """ 

2415 return self._configurations 

2416 

2417 @readonly 

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

2419 """ 

2420 Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`). 

2421 

2422 :returns: List of all entities. 

2423 """ 

2424 return self._entities 

2425 

2426 @readonly 

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

2428 """ 

2429 Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`). 

2430 

2431 :returns: List of all architectures. 

2432 """ 

2433 return self._architectures 

2434 

2435 @readonly 

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

2437 """ 

2438 Read-only property to access a list of all package declarations found in this document (:attr:`_packages`). 

2439 

2440 :returns: List of all packages. 

2441 """ 

2442 return self._packages 

2443 

2444 @readonly 

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

2446 """ 

2447 Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`). 

2448 

2449 :returns: List of all package bodies. 

2450 """ 

2451 return self._packageBodies 

2452 

2453 @readonly 

2454 def VerificationUnits(self) -> Dict[str, VerificationUnit]: 

2455 """ 

2456 Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`). 

2457 

2458 :returns: List of all verification units. 

2459 """ 

2460 return self._verificationUnits 

2461 

2462 @readonly 

2463 def VerificationProperties(self) -> Dict[str, VerificationProperty]: 

2464 """ 

2465 Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`). 

2466 

2467 :returns: List of all verification properties. 

2468 """ 

2469 return self._verificationProperties 

2470 

2471 @readonly 

2472 def VerificationModes(self) -> Dict[str, VerificationMode]: 

2473 """ 

2474 Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`). 

2475 

2476 :returns: List of all verification modes. 

2477 """ 

2478 return self._verificationModes 

2479 

2480 @readonly 

2481 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]: 

2482 """ 

2483 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`). 

2484 

2485 The compile-order vertex references this document by its value field. 

2486 

2487 :returns: The corresponding compile-order vertex. 

2488 """ 

2489 return self._compileOrderVertex 

2490 

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

2492 """ 

2493 Iterate all design units in the document. 

2494 

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

2496 

2497 .. rubric:: Algorithm 

2498 

2499 * If contexts are selected in the filter: 

2500 

2501 1. Iterate all contexts in that library. 

2502 

2503 * If packages are selected in the filter: 

2504 

2505 1. Iterate all packages in that library. 

2506 

2507 * If package bodies are selected in the filter: 

2508 

2509 1. Iterate all package bodies in that library. 

2510 

2511 * If entites are selected in the filter: 

2512 

2513 1. Iterate all entites in that library. 

2514 

2515 * If architectures are selected in the filter: 

2516 

2517 1. Iterate all architectures in that library. 

2518 

2519 * If configurations are selected in the filter: 

2520 

2521 1. Iterate all configurations in that library. 

2522 

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

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

2525 

2526 .. seealso:: 

2527 

2528 :meth:`pyVHDLModel.Design.IterateDesignUnits` 

2529 Iterate all design units in the design. 

2530 :meth:`pyVHDLModel.Library.IterateDesignUnits` 

2531 Iterate all design units in the library. 

2532 """ 

2533 if DesignUnitKind.Context in filter: 

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

2535 yield context 

2536 

2537 if DesignUnitKind.Package in filter: 2537 ↛ 2541line 2537 didn't jump to line 2541 because the condition on line 2537 was always true

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

2539 yield package 

2540 

2541 if DesignUnitKind.PackageBody in filter: 

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

2543 yield packageBody 

2544 

2545 if DesignUnitKind.Entity in filter: 

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

2547 yield entity 

2548 

2549 if DesignUnitKind.Architecture in filter: 

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

2551 for architecture in architectures.values(): 

2552 yield architecture 

2553 

2554 if DesignUnitKind.Configuration in filter: 

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

2556 yield configuration 

2557 

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

2559 # yield verificationProperty 

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

2561 # yield entity 

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

2563 # yield verificationMode 

2564 

2565 def __repr__(self) -> str: 

2566 """ 

2567 Formats a representation of the document. 

2568 

2569 **Format:** ``Document: 'path/to/file.vhdl'`` 

2570 

2571 :returns: String representation of the document. 

2572 """ 

2573 return f"Document: '{self._path}'" 

2574 

2575 __str__ = __repr__