ChangeLog¶
+Upcoming Release¶
+-
+
tbd
+
01.09.2021¶
+pyEDAA.ProjectModel was split from pyIPCMI (v1.1.6) as an independent Python package.
+diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 00000000..ccea200f --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 7133a5af6d992ad8f5e8918c0e42bbf0 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/ChangeLog/index.html b/ChangeLog/index.html new file mode 100644 index 00000000..55700222 --- /dev/null +++ b/ChangeLog/index.html @@ -0,0 +1,147 @@ + + +
+ + + ++ | + |
---|---|
+ | + |
Package |
+Version |
+License |
+Dependencies |
+
---|---|---|---|
+ | ≥5.0.0 |
++ | None |
+
+ | ≥0.27.1 |
++ | + | +
+ | ≥0.3.1 |
++ | + | +
+ | ≥0.1.0 |
++ | + | +
Additional Python packages needed for testing, code coverage collection and static type checking. These packages are +only needed for developers or on a CI server, thus sub-dependencies are not evaluated further.
+Manually Installing Test Requirements
+Use the tests/requirements.txt
file to install all dependencies via pip3
. The file will recursively install
+the mandatory dependencies too.
pip3 install -U -r tests/requirements.txt
+
Dependency List
+Package |
+Version |
+License |
+Dependencies |
+
---|---|---|---|
+ | ≥7.4.0 |
++ | Not yet evaluated. |
+
+ | ≥4.1.0 |
++ | Not yet evaluated. |
+
+ | ≥7.3 |
++ | Not yet evaluated. |
+
+ | ≥1.5 |
++ | Not yet evaluated. |
+
+ | ≥4.7.1 |
++ | Not yet evaluated. |
+
+ | ≥4.9 |
++ | Not yet evaluated. |
+
Additional Python packages needed for documentation generation. These packages are only needed for developers or on a +CI server, thus sub-dependencies are not evaluated further.
+Manually Installing Documentation Requirements
+Use the doc/requirements.txt
file to install all dependencies via pip3
. The file will recursively install
+the mandatory dependencies too.
pip3 install -U -r doc/requirements.txt
+
Dependency List
+Package |
+Version |
+License |
+Dependencies |
+
---|---|---|---|
+ | ≥5.0.0 |
++ | None |
+
+ | ≥5.3.0 |
++ | Not yet evaluated. |
+
+ | ≥0.5.2 |
++ | Not yet evaluated. |
+
+ | ≥0.0.6 |
++ | Not yet evaluated. |
+
+ | ≥1.19.5 |
++ | Not yet evaluated. |
+
Additional Python packages needed for installation package generation. These packages are only needed for developers or +on a CI server, thus sub-dependencies are not evaluated further.
+Manually Installing Packaging Requirements
+Use the build/requirements.txt
file to install all dependencies via pip3
. The file will recursively
+install the mandatory dependencies too.
pip3 install -U -r build/requirements.txt
+
Dependency List
+Package |
+Version |
+License |
+Dependencies |
+
---|---|---|---|
+ | ≥5.0.0 |
++ | None |
+
+ | ≥0.40.0 |
++ | Not yet evaluated. |
+
Additional Python packages needed for publishing the generated installation package to e.g, PyPI or any equivalent +services. These packages are only needed for maintainers or on a CI server, thus sub-dependencies are not evaluated +further.
+Manually Installing Publishing Requirements
+Use the dist/requirements.txt
file to install all dependencies via pip3
. The file will recursively
+install the mandatory dependencies too.
pip3 install -U -r dist/requirements.txt
+
Dependency List
+Package |
+Version |
+License |
+Dependencies |
+
---|---|---|---|
+ | ≥0.40.0 |
++ | Not yet evaluated. |
+
+ | ≥4.0.2 |
++ | Not yet evaluated. |
+
Note
+This is a local copy of the Creative Commons - Attribution 4.0 International (CC BY 4.0).
+Attention
+This CC BY 4.0 license applies only to the documentation of this project.
+Creative Commons Corporation (“Creative Commons”) is not a law firm and does not +provide legal services or legal advice. Distribution of Creative Commons public +licenses does not create a lawyer-client or other relationship. Creative Commons +makes its licenses and related information available on an “as-is” basis. +Creative Commons gives no warranties regarding its licenses, any material +licensed under their terms and conditions, or any related information. Creative +Commons disclaims all liability for damages resulting from their use to the +fullest extent possible.
+ +Creative Commons Attribution 4.0 International Public License
+By exercising the Licensed Rights (defined below), You accept and agree to be +bound by the terms and conditions of this Creative Commons Attribution 4.0 +International Public License (“Public License”). To the extent this Public +License may be interpreted as a contract, You are granted the Licensed Rights +in consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the Licensor +receives from making the Licensed Material available under these terms and +conditions.
+Adapted Material means material subject to Copyright and Similar +Rights that is derived from or based upon the Licensed Material and in +which the Licensed Material is translated, altered, arranged, transformed, or +otherwise modified in a manner requiring permission under the Copyright and +Similar Rights held by the Licensor. For purposes of this Public License, +where the Licensed Material is a musical work, performance, or sound +recording, Adapted Material is always produced where the Licensed Material +is synched in timed relation with a moving image.
Adapter’s License means the license You apply to Your Copyright and +Similar Rights in Your contributions to Adapted Material in accordance with +the terms and conditions of this Public License.
Copyright and Similar Rights means copyright and/or similar rights +closely related to copyright including, without limitation, performance, +broadcast, sound recording, and Sui Generis Database Rights, without regard +to how the rights are labeled or categorized. For purposes of this Public +License, the rights specified in Section 2(b)(1)-(2) are not Copyright and +Similar Rights.
Effective Technological Measures means those measures that, in the +absence of proper authority, may not be circumvented under laws fulfilling +obligations under Article 11 of the WIPO Copyright Treaty adopted on +December 20, 1996, and/or similar international agreements.
Exceptions and Limitations means fair use, fair dealing, and/or any +other exception or limitation to Copyright and Similar Rights that applies to +Your use of the Licensed Material.
Licensed Material means the artistic or literary work, database, or +other material to which the Licensor applied this Public License.
Licensed Rights means the rights granted to You subject to the terms +and conditions of this Public License, which are limited to all Copyright and +Similar Rights that apply to Your use of the Licensed Material and that the +Licensor has authority to license.
Licensor means the individual(s) or entity(ies) granting rights under +this Public License.
Share means to provide material to the public by any means or process +that requires permission under the Licensed Rights, such as reproduction, +public display, public performance, distribution, dissemination, +communication, or importation, and to make material available to the public +including in ways that members of the public may access the material from a +place and at a time individually chosen by them.
Sui Generis Database Rights means rights other than copyright +resulting from Directive 96/9/EC of the European Parliament and of the +Council of 11 March 1996 on the legal protection of databases, as amended +and/or succeeded, as well as other essentially equivalent rights anywhere +in the world.
You means the individual or entity exercising the Licensed Rights +under this Public License. Your has a corresponding meaning.
License grant.
+Subject to the terms and conditions of this Public License, the Licensor +hereby grants You a worldwide, royalty-free, non-sublicensable, +non-exclusive, irrevocable license to exercise the Licensed Rights in the +Licensed Material to:
++++
+- +
reproduce and Share the Licensed Material, in whole or in part; and
- +
produce, reproduce, and Share Adapted Material.
Exceptions and Limitations. For the avoidance of doubt, where +Exceptions and Limitations apply to Your use, this Public License does not +apply, and You do not need to comply with its terms and conditions.
Term. The term of this Public License is specified in Section 6(a).
Media and formats; technical modifications allowed. The Licensor +authorizes You to exercise the Licensed Rights in all media and formats +whether now known or hereafter created, and to make technical +modifications necessary to do so. The Licensor waives and/or agrees not to +assert any right or authority to forbid You from making technical +modifications necessary to exercise the Licensed Rights, including +technical modifications necessary to circumvent Effective Technological +Measures. For purposes of this Public License, simply making modifications +authorized by this Section 2(a)(4) never produces Adapted Material.
Downstream recipients.
++++
+- +
Offer from the Licensor – Licensed Material. Every recipient of +the Licensed Material automatically receives an offer from the +Licensor to exercise the Licensed Rights under the terms and +conditions of this Public License.
- +
No downstream restrictions. You may not offer or impose any +additional or different terms or conditions on, or apply any Effective +Technological Measures to, the Licensed Material if doing so restricts +exercise of the Licensed Rights by any recipient of the Licensed +Material.
No endorsement. Nothing in this Public License constitutes or may +be construed as permission to assert or imply that You are, or that Your +use of the Licensed Material is, connected with, or sponsored, endorsed, +or granted official status by, the Licensor or others designated to +receive attribution as provided in Section 3(a)(1)(A)(i).
Other rights.
+Moral rights, such as the right of integrity, are not licensed under this +Public License, nor are publicity, privacy, and/or other similar +personality rights; however, to the extent possible, the Licensor waives +and/or agrees not to assert any such rights held by the Licensor to the +limited extent necessary to allow You to exercise the Licensed Rights, but +not otherwise.
Patent and trademark rights are not licensed under this Public License.
To the extent possible, the Licensor waives any right to collect royalties +from You for the exercise of the Licensed Rights, whether directly or +through a collecting society under any voluntary or waivable statutory or +compulsory licensing scheme. In all other cases the Licensor expressly +reserves any right to collect such royalties.
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
+Attribution.
+If You Share the Licensed Material (including in modified form), You must:
++++
+- +
retain the following if it is supplied by the Licensor with the +Licensed Material:
+++
+- +
identification of the creator(s) of the Licensed Material and any +others designated to receive attribution, in any reasonable manner +requested by the Licensor (including by pseudonym if designated);
- +
a copyright notice;
- +
a notice that refers to this Public License;
- +
a notice that refers to the disclaimer of warranties;
- +
a URI or hyperlink to the Licensed Material to the extent reasonably +practicable;
+
+- +
indicate if You modified the Licensed Material and retain an +indication of any previous modifications; and
- +
indicate the Licensed Material is licensed under this Public License, +and include the text of, or the URI or hyperlink to, this Public +License.
You may satisfy the conditions in Section 3(a)(1) in any reasonable manner +based on the medium, means, and context in which You Share the Licensed +Material. For example, it may be reasonable to satisfy the conditions by +providing a URI or hyperlink to a resource that includes the required +information.
If requested by the Licensor, You must remove any of the information +required by Section 3(a)(1)(A) to the extent reasonably practicable.
If You Share Adapted Material You produce, the Adapter’s License You apply +must not prevent recipients of the Adapted Material from complying with +this Public License.
Where the Licensed Rights include Sui Generis Database Rights that apply to Your +use of the Licensed Material:
+for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, +reuse, reproduce, and Share all or a substantial portion of the contents of +the database;
if You include all or a substantial portion of the database contents in a +database in which You have Sui Generis Database Rights, then the database +in which You have Sui Generis Database Rights (but not its individual +contents) is Adapted Material; and
You must comply with the conditions in Section 3(a) if You Share all or a +substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not replace +Your obligations under this Public License where the Licensed Rights include +other Copyright and Similar Rights.
+Unless otherwise separately undertaken by the Licensor, to the extent +possible, the Licensor offers the Licensed Material as-is and as-available, +and makes no representations or warranties of any kind concerning the +Licensed Material, whether express, implied, statutory, or other. This +includes, without limitation, warranties of title, merchantability, +fitness for a particular purpose, non-infringement, absence of latent or +other defects, accuracy, or the presence or absence of errors, whether or +not known or discoverable. Where disclaimers of warranties are not allowed +in full or in part, this disclaimer may not apply to You.
To the extent possible, in no event will the Licensor be liable to You +on any legal theory (including, without limitation, negligence) or +otherwise for any direct, special, indirect, incidental, consequential, +punitive, exemplary, or other losses, costs, expenses, or damages arising +out of this Public License or use of the Licensed Material, even if the +Licensor has been advised of the possibility of such losses, costs, expenses, +or damages. Where a limitation of liability is not allowed in full or in +part, this limitation may not apply to You.
The disclaimer of warranties and limitation of liability provided above +shall be interpreted in a manner that, to the extent possible, most +closely approximates an absolute disclaimer and waiver of all liability.
This Public License applies for the term of the Copyright and Similar Rights +licensed here. However, if You fail to comply with this Public License, then +Your rights under this Public License terminate automatically.
Where Your right to use the Licensed Material has terminated under +Section 6(a), it reinstates:
+automatically as of the date the violation is cured, provided it is cured +within 30 days of Your discovery of the violation; or
upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any right the +Licensor may have to seek remedies for Your violations of this Public License.
+For the avoidance of doubt, the Licensor may also offer the Licensed Material +under separate terms or conditions or stop distributing the Licensed Material +at any time; however, doing so will not terminate this Public License.
Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
The Licensor shall not be bound by any additional or different terms or +conditions communicated by You unless expressly agreed.
Any arrangements, understandings, or agreements regarding the Licensed +Material not stated herein are separate from and independent of the terms +and conditions of this Public License.
For the avoidance of doubt, this Public License does not, and shall not be +interpreted to, reduce, limit, restrict, or impose conditions on any use of +the Licensed Material that could lawfully be made without permission under +this Public License.
To the extent possible, if any provision of this Public License is deemed +unenforceable, it shall be automatically reformed to the minimum extent +necessary to make it enforceable. If the provision cannot be reformed, it +shall be severed from this Public License without affecting the +enforceability of the remaining terms and conditions.
No term or condition of this Public License will be waived and no failure to +comply consented to unless expressly agreed to by the Licensor.
Nothing in this Public License constitutes or may be interpreted as a +limitation upon, or waiver of, any privileges and immunities that apply to +the Licensor or You, including from the legal processes of any jurisdiction +or authority.
Creative Commons is not a party to its public licenses. Notwithstanding, +Creative Commons may elect to apply one of its public licenses to material it +publishes and in those instances will be considered the “Licensor.” Except for +the limited purpose of indicating that material is shared under a Creative +Commons public license or as otherwise permitted by the Creative Commons +policies published at creativecommons.org/policies, +Creative Commons does not authorize the use of the trademark “Creative Commons” +or any other trademark or logo of Creative Commons without its prior written +consent including, without limitation, in connection with any unauthorized +modifications to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For the +avoidance of doubt, this paragraph does not form part of the public licenses.
+Creative Commons may be contacted at creativecommons.org
+Design Goal
+TBD
+Language Reference Manual is the name given to IEEE Standard documents defining Hardware Description Languages:
+ +An ancestor class for other derived classes.
+A representation of a physical file.
+A group of files.
+If no fileset is specified, the pre-existing fileset named default
is used to group files.
A namespace in VHDL to group and organize VHDL design units (entity, package, configuration, context).
+A …
+A …
+Note
+Python ≥3.7 is required for this package due to problems with meta classes and
+__getattr__
in Python 3.6.
pip3 install pyEDAA.ProjectModel
+
pip3 install -U pyEDAA.ProjectModel
+
pip3 uninstall pyEDAA.ProjectModel
+
pip3 install .
+
setup.py
(legacy)¶See sections above on how to use PIP.
+setup.py
¶setup.py install
+
Note
+This is a local copy of the Apache License Version 2.0.
+Attention
+This Apache License, 2.0 applies to all source and configuration files of project, except documentation.
+Version 2.0, January 2004
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+“License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+“Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+“Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that +entity. For the purposes of this definition, “control” means (i) the power, direct or indirect, to cause the direction or management of such entity, whether +by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+“You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License.
+“Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and +configuration files.
+“Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object +code, generated documentation, and conversions to other media types.
+“Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is +included in or attached to the work (an example is provided in the Appendix below).
+“Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+“Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative +Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to +submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication +sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue +tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is +conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.”
+“Contributor” shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work.
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form.
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such +license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of +their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim +or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then +any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions:
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source +form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the +Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE +file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, +alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise +complies with the conditions stated in this License.
+Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any +separate license agreement you may have executed with Licensor regarding such Contributions.
+This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable +and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, +MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and +assume any risks associated with Your exercise of permissions under this License.
+In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or +consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages +for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been +advised of the possibility of such damages.
+While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other +liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole +responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+Appendix: How to apply the Apache License to your work
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets “[]” replaced with your own identifying +information. (Don’t include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or +class name and description of purpose be included on the same “printed page” as the copyright notice for easier identification within third-party archives.
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
Generic description of an EDA design.
+Todo
+Write documentation.
+Class Relationship
+Design
¶@export
+class Design:
+ _name: str
+ _project: Nullable['Project']
+ _directory: Nullable[Path]
+ _fileSets: Dict[str, FileSet]
+ _defaultFileSet: Nullable[FileSet]
+ _vhdlLibraries: Dict[str, VHDLLibrary]
+ _vhdlVersion: VHDLVersion
+ _verilogVersion: VerilogVersion
+ _svVersion: SystemVerilogVersion
+ _externalVHDLLibraries: List
+
+ def __init__(
+ self,
+ name: str,
+ directory: Path = Path("."),
+ project: 'Project' = None,
+ vhdlVersion: VHDLVersion = None,
+ verilogVersion: VerilogVersion = None,
+ svVersion: SystemVerilogVersion = None
+ ):
+
+ @property
+ def Name(self) -> str:
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ @Project.setter
+ def Project(self, value: 'Project') -> None:
+
+ @property
+ def Directory(self) -> Path:
+ @Directory.setter
+ def Directory(self, value: Path) -> None:
+
+ @property
+ def ResolvedPath(self) -> Path:
+
+ @property
+ def DefaultFileSet(self) -> FileSet:
+ @DefaultFileSet.setter
+ def DefaultFileSet(self, value: Union[str, FileSet]) -> None:
+
+ @property
+ def FileSets(self) -> Dict[str, FileSet]:
+
+ def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[str, FileSet] = None) -> Generator[File, None, None]:
+
+ @property
+ def VHDLLibraries(self) -> List[VHDLLibrary]:
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+
+ @property
+ def VerilogVersion(self) -> VerilogVersion:
+ @VerilogVersion.setter
+ def VerilogVersion(self, value: VerilogVersion) -> None:
+
+ @property
+ def SVVersion(self) -> SystemVerilogVersion:
+ @SVVersion.setter
+ def SVVersion(self, value: SystemVerilogVersion) -> None:
+
+ @property
+ def ExternalVHDLLibraries(self) -> List:
+
+ def AddFileSet(self, fileSet: FileSet) -> None:
+
+ def AddFileSets(self, fileSets: Iterable[FileSet]) -> None:
+
+ def AddFile(self, file: File) -> None:
+
+ def AddFiles(self, files: Iterable[File]) -> None:
+
Generic description of a file in EDA design.
+Todo
+Write documentation.
+Class Relationship
+File
¶@export
+class File(metaclass=FileType):
+ _path: Path
+ _project: Nullable['Project']
+ _design: Nullable['Design']
+ _fileSet: Nullable['FileSet']
+
+ def __init__(
+ self,
+ path: Path,
+ project: 'Project' = None,
+ design: 'Design' = None,
+ fileSet: 'FileSet' = None
+ ):
+
+ @property
+ def FileType(self) -> 'FileType':
+
+ @property
+ def Path(self) -> Path:
+
+ @property
+ def ResolvedPath(self) -> Path:
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ @Project.setter
+ def Project(self, value: 'Project') -> None:
+
+ @property
+ def Design(self) -> Nullable['Design']:
+ @Design.setter
+ def Design(self, value: 'Design') -> None:
+
+ @property
+ def FileSet(self) -> Nullable['FileSet']:
+ @FileSet.setter
+ def FileSet(self, value: 'FileSet') -> None:
+
Generic description of an EDA file set (group of files).
+Todo
+Write documentation.
+Class Relationship
+FileSet
¶@export
+class FileSet:
+ _name: str
+ _project: Nullable['Project']
+ _design: Nullable['Design']
+ _directory: Nullable[Path]
+ _parent: Nullable['FileSet']
+ _fileSets: Dict[str, 'FileSet']
+ _files: List[File]
+
+ _vhdlLibrary: 'VHDLLibrary'
+ _vhdlVersion: VHDLVersion
+ _verilogVersion: VerilogVersion
+ _svVersion: SystemVerilogVersion
+
+ def __init__(
+ self,
+ name: str,
+ directory: Path = Path("."),
+ project: 'Project' = None,
+ design: 'Design' = None,
+ parent: Nullable['FileSet'] = None,
+ vhdlLibrary: Union[str, 'VHDLLibrary'] = None,
+ vhdlVersion: VHDLVersion = None,
+ verilogVersion: VerilogVersion = None,
+ svVersion: SystemVerilogVersion = None
+ ):
+
+ @property
+ def Name(self) -> str:
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ @Project.setter
+ def Project(self, value: 'Project') -> None:
+
+ @property
+ def Design(self) -> Nullable['Design']:
+ @Design.setter
+ def Design(self, value: 'Design') -> None:
+
+ @property
+ def Directory(self) -> Path:
+ @Directory.setter
+ def Directory(self, value: Path) -> None:
+
+ @property
+ def ResolvedPath(self) -> Path:
+
+ @property
+ def Parent(self) -> Nullable['FileSet']:
+ @Parent.setter
+ def Parent(self, value: 'FileSet') -> None:
+
+ @property
+ def FileSets(self) -> Dict[str, 'FileSet']:
+
+ def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[str, 'FileSet'] = None) -> Generator[File, None, None]:
+
+ def AddFile(self, file: File) -> None:
+
+ def AddFiles(self, files: Iterable[File]) -> None:
+
+ @property
+ def VHDLLibrary(self) -> 'VHDLLibrary':
+ @VHDLLibrary.setter
+ def VHDLLibrary(self, value: 'VHDLLibrary') -> None:
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+
+ @property
+ def VerilogVersion(self) -> VerilogVersion:
+ @VerilogVersion.setter
+ def VerilogVersion(self, value: VerilogVersion) -> None:
+
+ @property
+ def SVVersion(self) -> SystemVerilogVersion:
+ @SVVersion.setter
+ def SVVersion(self, value: SystemVerilogVersion) -> None:
+
Generic description of an EDA project.
+Todo
+Write documentation.
+Class Relationship
+Project
¶@export
+class Project:
+ _name: str
+ _rootDirectory: Nullable[Path]
+ _designs: Dict[str, Design]
+ _vhdlVersion: VHDLVersion
+ _verilogVersion: VerilogVersion
+ _svVersion: SystemVerilogVersion
+
+ def __init__(
+ self,
+ name: str,
+ rootDirectory: Path = Path("."),
+ vhdlVersion: VHDLVersion = None,
+ verilogVersion: VerilogVersion = None,
+ svVersion: SystemVerilogVersion = None
+ ):
+
+ @property
+ def Name(self) -> str:
+
+ @property
+ def RootDirectory(self) -> Path:
+ @RootDirectory.setter
+ def RootDirectory(self, value: Path) -> None:
+
+ @property
+ def ResolvedPath(self) -> Path:
+
+ @property
+ def Designs(self) -> Dict[str, Design]:
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+
+ @property
+ def VerilogVersion(self) -> VerilogVersion:
+ @VerilogVersion.setter
+ def VerilogVersion(self, value: VerilogVersion) -> None:
+
+ @property
+ def SVVersion(self) -> SystemVerilogVersion:
+ @SVVersion.setter
+ def SVVersion(self, value: SystemVerilogVersion) -> None:
+
Generic description of a VHDL library (group of VHDL files containing VHDL primary units).
+Todo
+Write documentation.
+Class Relationship
+VHDLLibrary
¶@export
+class VHDLLibrary:
+ _name: str
+ _project: Nullable['Project']
+ _design: Nullable['Design']
+ _files: List[File]
+ _vhdlVersion: VHDLVersion
+
+ def __init__(
+ self,
+ name: str,
+ project: 'Project' = None,
+ design: 'Design' = None,
+ vhdlVersion: VHDLVersion = None
+ ):
+
+ @property
+ def Name(self) -> str:
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ @Project.setter
+ def Project(self, value: 'Project'):
+
+ @property
+ def Design(self) -> Nullable['Design']:
+ @Design.setter
+ def Design(self, value: 'Design'):
+
+ @property
+ def Files(self) -> Generator[File, None, None]:
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+
Design Goal
+Clearly named classes that model the semantics of an EDA project.
Child objects shall have a reference to their parent.
Overall Hierarchy
+An EDA project contains one or multiple variants of a EDA design. +A design then has at least one but usually multiple file sets to group source files and apply settings or attributes to that group.
+Elements of the Project Model
+
+# ==================================================================================================================== #
+# _____ ____ _ _ ____ _ _ __ __ _ _ #
+# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | #
+# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | #
+# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | #
+# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| #
+# |_| |___/ |__/ #
+# ==================================================================================================================== #
+# Authors: #
+# Patrick Lehmann #
+# #
+# License: #
+# ==================================================================================================================== #
+# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
+# Copyright 2014-2016 Technische Universität Dresden - Germany, Chair of VLSI-Design, Diagnostics and Architecture #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+# #
+# SPDX-License-Identifier: Apache-2.0 #
+# ==================================================================================================================== #
+#
+"""An abstract model of EDA tool projects."""
+__author__ = "Patrick Lehmann"
+__email__ = "Paebbels@gmail.com"
+__copyright__ = "2014-2023, Patrick Lehmann, Unai Martinez-Corral"
+__license__ = "Apache License, Version 2.0"
+__version__ = "0.5.0"
+__keywords__ = ["eda project", "model", "abstract", "xilinx", "vivado", "osvvm", "file set", "file group", "test bench", "test harness"]
+
+from os.path import relpath as path_relpath
+from pathlib import Path as pathlib_Path
+from typing import Dict, Union, Optional as Nullable, List, Iterable, Generator, Tuple, Any as typing_Any, Type, Set, \
+ Any
+
+from pyTooling.Decorators import export
+from pyTooling.MetaClasses import ExtendedType
+from pyTooling.Graph import Graph, Vertex
+from pySVModel import SystemVerilogVersion
+from pyVHDLModel import VHDLVersion
+from pySystemRDLModel import SystemRDLVersion
+
+
+[docs]@export
+class Attribute(metaclass=ExtendedType):
+ KEY: str
+ VALUE_TYPE: typing_Any
+
+ @staticmethod
+ def resolve(obj: typing_Any, key: Type['Attribute']):
+ if isinstance(obj, File):
+ return obj._fileSet[key]
+ elif isinstance(obj, FileSet):
+ return obj._design[key]
+ elif isinstance(obj, Design):
+ return obj._project[key]
+ else:
+ raise Exception("Resolution error")
+
+
+[docs]@export
+class FileType(ExtendedType):
+ """
+ A :term:`meta-class` to construct *FileType* classes.
+
+ Modifications done by this meta-class:
+ * Register all classes of type :class:`FileType` or derived variants in a class field :attr:`FileType.FileTypes` in this meta-class.
+ """
+
+ FileTypes: Dict[str, 'FileType'] = {} #: Dictionary of all classes of type :class:`FileType` or derived variants
+ Any: 'FileType'
+
+[docs] def __init__(cls, name: str, bases: Tuple[type, ...], dictionary: Dict[str, typing_Any], **kwargs):
+ super().__init__(name, bases, dictionary, **kwargs)
+ cls.Any = cls
+
+[docs] def __new__(cls, className, baseClasses, classMembers: Dict, *args, **kwargs):
+ fileType = super().__new__(cls, className, baseClasses, classMembers, *args, **kwargs)
+ cls.FileTypes[className] = fileType
+ return fileType
+
+ def __getattr__(cls, item) -> 'FileType':
+ if item[:2] != "__" and item[-2:] != "__":
+ return cls.FileTypes[item]
+ else:
+ return super().__getattribute__(item)
+
+ def __contains__(cls, item) -> bool:
+ return issubclass(item, cls)
+
+
+@export
+class File(metaclass=FileType, slots=True):
+ """
+ A :term:`File` represents a file in a design. This :term:`base-class` is used
+ for all derived file classes.
+
+ A file can be created standalone and later associated to a fileset, design and
+ project. Or a fileset, design and/or project can be associated immediately
+ while creating a file.
+
+ :arg path: Relative or absolute path to the file.
+ :arg project: Project the file is associated with.
+ :arg design: Design the file is associated with.
+ :arg fileSet: Fileset the file is associated with.
+ """
+
+ _path: pathlib_Path
+ _fileType: 'FileType'
+ _project: Nullable['Project']
+ _design: Nullable['Design']
+ _fileSet: Nullable['FileSet']
+ _attributes: Dict[Type[Attribute], typing_Any]
+
+ def __init__(
+ self,
+ path: pathlib_Path,
+ project: 'Project' = None,
+ design: 'Design' = None,
+ fileSet: 'FileSet' = None
+ ):
+ self._fileType = getattr(FileTypes, self.__class__.__name__)
+ self._path = path
+ if project is not None:
+ self._project = project
+ self._design = design
+ if fileSet is not None:
+ self.FileSet = fileSet
+ elif design is not None:
+ self._project = design._project
+ self._design = design
+ self.FileSet = design.DefaultFileSet if fileSet is None else fileSet
+ elif fileSet is not None:
+ design = fileSet._design
+ if design is not None:
+ self._project = design._project
+ else:
+ self._project = None
+ self._design = design
+ self.FileSet = fileSet
+ else:
+ self._project = None
+ self._design = None
+ self._fileSet = None
+
+ self._attributes = {}
+ self._registerAttributes()
+
+ def _registerAttributes(self):
+ pass
+
+ @property
+ def FileType(self) -> 'FileType':
+ """Read-only property to return the file type of this file."""
+ return self._fileType
+
+ @property
+ def Path(self) -> pathlib_Path:
+ """Read-only property returning the path of this file."""
+ return self._path
+
+ # TODO: setter?
+
+ @property
+ def ResolvedPath(self) -> pathlib_Path:
+ """Read-only property returning the resolved path of this file."""
+ if self._path.is_absolute():
+ return self._path.resolve()
+ elif self._fileSet is not None:
+ path = (self._fileSet.ResolvedPath / self._path).resolve()
+
+ if path.is_absolute():
+ return path
+ else:
+ # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+ return pathlib_Path(path_relpath(path, pathlib_Path.cwd()))
+ else:
+ # TODO: message and exception type
+ raise Exception("")
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ """Property setting or returning the project this file is used in."""
+ return self._project
+
+ @Project.setter
+ def Project(self, value: 'Project') -> None:
+ self._project = value
+
+ if self._fileSet is None:
+ self._project.DefaultDesign.DefaultFileSet.AddFile(self)
+
+ @property
+ def Design(self) -> Nullable['Design']:
+ """Property setting or returning the design this file is used in."""
+ return self._design
+
+ @Design.setter
+ def Design(self, value: 'Design') -> None:
+ self._design = value
+
+ if self._fileSet is None:
+ self._design.DefaultFileSet.AddFile(self)
+
+ if self._project is None:
+ self._project = value._project
+ elif self._project is not value._project:
+ raise Exception("The design's project is not identical to the already assigned project.")
+
+ @property
+ def FileSet(self) -> Nullable['FileSet']:
+ """Property setting or returning the fileset this file is used in."""
+ return self._fileSet
+
+ @FileSet.setter
+ def FileSet(self, value: 'FileSet') -> None:
+ self._fileSet = value
+ value._files.append(self)
+
+ def Validate(self):
+ """Validate this file."""
+ if self._path is None:
+ raise Exception("Validation: File has no path.")
+ try:
+ path = self.ResolvedPath
+ except Exception as ex:
+ raise Exception(f"Validation: File '{self._path}' could not compute resolved path.") from ex
+ if not path.exists():
+ raise Exception(f"Validation: File '{self._path}' (={path}) does not exist.")
+ if not path.is_file():
+ raise Exception(f"Validation: File '{self._path}' (={path}) is not a file.")
+
+ if self._fileSet is None:
+ raise Exception(f"Validation: File '{self._path}' has no fileset.")
+ if self._design is None:
+ raise Exception(f"Validation: File '{self._path}' has no design.")
+ if self._project is None:
+ raise Exception(f"Validation: File '{self._path}' has no project.")
+
+ def __len__(self) -> int:
+ return len(self._attributes)
+
+ def __getitem__(self, key: Type[Attribute]) -> Any:
+ """Index access for returning attributes on this file."""
+ if not issubclass(key, Attribute):
+ raise TypeError("Parameter 'key' is not an 'Attribute'.")
+
+ try:
+ return self._attributes[key]
+ except KeyError:
+ return key.resolve(self, key)
+
+ def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+ """Index access for setting attributes on this file."""
+ if not issubclass(key, Attribute):
+ raise TypeError("Parameter 'key' is not an 'Attribute'.")
+
+ self._attributes[key] = value
+
+
+FileTypes = File
+
+
+[docs]@export
+class HumanReadableContent(metaclass=ExtendedType, mixin=True):
+ """A file type representing human-readable contents."""
+
+
+[docs]@export
+class XMLContent(HumanReadableContent, mixin=True):
+ """A file type representing XML contents."""
+
+
+[docs]@export
+class YAMLContent(HumanReadableContent, mixin=True):
+ """A file type representing YAML contents."""
+
+
+[docs]@export
+class JSONContent(HumanReadableContent, mixin=True):
+ """A file type representing JSON contents."""
+
+
+[docs]@export
+class INIContent(HumanReadableContent, mixin=True):
+ """A file type representing INI contents."""
+
+
+[docs]@export
+class TOMLContent(HumanReadableContent, mixin=True):
+ """A file type representing TOML contents."""
+
+
+[docs]@export
+class TCLContent(HumanReadableContent, mixin=True):
+ """A file type representing content in TCL code."""
+
+
+[docs]@export
+class SDCContent(TCLContent, mixin=True):
+ """A file type representing contents as Synopsys Design Constraints (SDC)."""
+
+
+[docs]@export
+class PythonContent(HumanReadableContent, mixin=True):
+ """A file type representing contents as Python source code."""
+
+
+@export
+class TextFile(File, HumanReadableContent):
+ """A text file (``*.txt``)."""
+
+
+@export
+class LogFile(File, HumanReadableContent):
+ """A log file (``*.log``)."""
+
+
+@export
+class XMLFile(File, XMLContent):
+ """An XML file (``*.xml``)."""
+
+
+@export
+class SourceFile(File):
+ """Base-class of all source files."""
+
+
+@export
+class HDLSourceFile(SourceFile):
+ """Base-class of all HDL source files."""
+
+
+@export
+class RDLSourceFile(SourceFile):
+ """Base-class of all RDL source files."""
+
+
+@export
+class NetlistFile(SourceFile):
+ """Base-class of all netlist source files."""
+
+
+@export
+class EDIFNetlistFile(NetlistFile):
+ """Netlist file in EDIF (Electronic Design Interchange Format)."""
+
+
+@export
+class TCLSourceFile(SourceFile, TCLContent):
+ """A TCL source file."""
+
+
+@export
+class VHDLSourceFile(HDLSourceFile, HumanReadableContent):
+ """
+ A VHDL source file (of any language version).
+
+ :arg path: Relative or absolute path to the file.
+ :arg vhdlLibrary: VHDLLibrary this VHDL source file is associated wih.
+ :arg vhdlVersion: VHDLVersion this VHDL source file is associated wih.
+ :arg project: Project the file is associated with.
+ :arg design: Design the file is associated with.
+ :arg fileSet: Fileset the file is associated with.
+ """
+
+ _vhdlLibrary: 'VHDLLibrary'
+ _vhdlVersion: VHDLVersion
+
+ def __init__(self, path: pathlib_Path, vhdlLibrary: Union[str, 'VHDLLibrary'] = None, vhdlVersion: VHDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None):
+ super().__init__(path, project, design, fileSet)
+
+ if isinstance(vhdlLibrary, str):
+ if design is not None:
+ try:
+ vhdlLibrary = design.VHDLLibraries[vhdlLibrary]
+ except KeyError as ex:
+ raise Exception(f"VHDL library '{vhdlLibrary}' not found in design '{design.Name}'.") from ex
+ elif project is not None:
+ try:
+ vhdlLibrary = project.DefaultDesign.VHDLLibraries[vhdlLibrary]
+ except KeyError as ex:
+ raise Exception(f"VHDL library '{vhdlLibrary}' not found in default design '{project.DefaultDesign.Name}'.") from ex
+ else:
+ raise Exception(f"Can't lookup VHDL library because neither 'project' nor 'design' is given as a parameter.")
+ elif isinstance(vhdlLibrary, VHDLLibrary):
+ self._vhdlLibrary = vhdlLibrary
+ vhdlLibrary.AddFile(self)
+ elif vhdlLibrary is None:
+ self._vhdlLibrary = None
+ else:
+ raise TypeError(f"Parameter 'vhdlLibrary' is neither a 'str' nor 'VHDLibrary'.")
+
+ self._vhdlVersion = vhdlVersion
+
+ def Validate(self) -> None:
+ """Validate this VHDL source file."""
+ super().Validate()
+
+ try:
+ _ = self.VHDLLibrary
+ except Exception as ex:
+ raise Exception(f"Validation: VHDLSourceFile '{self._path}' (={self.ResolvedPath}) has no VHDLLibrary assigned.") from ex
+ try:
+ _ = self.VHDLVersion
+ except Exception as ex:
+ raise Exception(f"Validation: VHDLSourceFile '{self._path}' (={self.ResolvedPath}) has no VHDLVersion assigned.") from ex
+
+ @property
+ def VHDLLibrary(self) -> 'VHDLLibrary':
+ """Property setting or returning the VHDL library this VHDL source file is used in."""
+ if self._vhdlLibrary is not None:
+ return self._vhdlLibrary
+ elif self._fileSet is not None:
+ return self._fileSet.VHDLLibrary
+ else:
+ raise Exception("VHDLLibrary was neither set locally nor globally.")
+
+ @VHDLLibrary.setter
+ def VHDLLibrary(self, value: 'VHDLLibrary') -> None:
+ self._vhdlLibrary = value
+ value._files.append(self)
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ """Property setting or returning the VHDL version this VHDL source file is used in."""
+ if self._vhdlVersion is not None:
+ return self._vhdlVersion
+ elif self._fileSet is not None:
+ return self._fileSet.VHDLVersion
+ else:
+ raise Exception("VHDLVersion was neither set locally nor globally.")
+
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+ self._vhdlVersion = value
+
+ def __repr__(self) -> str:
+ return f"<VHDL file: '{self.ResolvedPath}'; lib: '{self.VHDLLibrary}'; version: {self.VHDLVersion}>"
+
+
+class VerilogMixIn(metaclass=ExtendedType, mixin=True):
+ @property
+ def VerilogVersion(self) -> SystemVerilogVersion:
+ """Property setting or returning the Verilog version this Verilog source file is used in."""
+ if self._version is not None:
+ return self._version
+ elif self._fileSet is not None:
+ return self._fileSet.VerilogVersion
+ else:
+ raise Exception("VerilogVersion was neither set locally nor globally.")
+
+ @VerilogVersion.setter
+ def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+ self._version = value
+
+
+class SystemVerilogMixIn(metaclass=ExtendedType, mixin=True):
+ @property
+ def SVVersion(self) -> SystemVerilogVersion:
+ """Property setting or returning the SystemVerilog version this SystemVerilog source file is used in."""
+ if self._version is not None:
+ return self._version
+ elif self._fileSet is not None:
+ return self._fileSet.SVVersion
+ else:
+ raise Exception("SVVersion was neither set locally nor globally.")
+
+ @SVVersion.setter
+ def SVVersion(self, value: SystemVerilogVersion) -> None:
+ self._version = value
+
+
+@export
+class VerilogBaseFile(HDLSourceFile, HumanReadableContent):
+ _version: SystemVerilogVersion
+
+ def __init__(self, path: pathlib_Path, version: SystemVerilogVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None):
+ super().__init__(path, project, design, fileSet)
+
+ self._version = version
+
+
+@export
+class VerilogSourceFile(VerilogBaseFile, VerilogMixIn):
+ """A Verilog source file (of any language version)."""
+
+
+@export
+class VerilogHeaderFile(VerilogBaseFile, VerilogMixIn):
+ """A Verilog header file (of any language version)."""
+
+
+@export
+class SystemVerilogBaseFile(VerilogBaseFile):
+ ...
+
+
+@export
+class SystemVerilogSourceFile(SystemVerilogBaseFile, SystemVerilogMixIn):
+ """A SystemVerilog source file (of any language version)."""
+
+
+@export
+class SystemVerilogHeaderFile(SystemVerilogBaseFile, SystemVerilogMixIn):
+ """A SystemVerilog header file (of any language version)."""
+
+
+@export
+class SystemRDLSourceFile(RDLSourceFile, HumanReadableContent):
+ """A SystemRDL source file (of any language version)."""
+
+ _srdlVersion: SystemRDLVersion
+
+ def __init__(self, path: pathlib_Path, srdlVersion: SystemRDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None):
+ super().__init__(path, project, design, fileSet)
+
+ self._srdlVersion = srdlVersion
+
+ @property
+ def SystemRDLVersion(self) -> SystemRDLVersion:
+ """Property setting or returning the SystemRDL version this SystemRDL source file is used in."""
+ if self._srdlVersion is not None:
+ return self._srdlVersion
+ elif self._fileSet is not None:
+ return self._fileSet.SRDLVersion
+ else:
+ raise Exception("SRDLVersion was neither set locally nor globally.")
+
+ @SystemRDLVersion.setter
+ def SystemRDLVersion(self, value: SystemRDLVersion) -> None:
+ self._srdlVersion = value
+
+
+@export
+class PythonSourceFile(SourceFile, PythonContent):
+ """A Python source file."""
+
+
+# TODO: move to a Cocotb module
+@export
+class CocotbPythonFile(PythonSourceFile):
+ """A Python source file used by Cocotb."""
+
+
+@export
+class ConstraintFile(File, HumanReadableContent):
+ """Base-class of all constraint files."""
+
+
+@export
+class ProjectFile(File):
+ """Base-class of all tool-specific project files."""
+
+
+@export
+class CSourceFile(SourceFile):
+ """Base-class of all ANSI-C source files."""
+
+
+@export
+class CppSourceFile(SourceFile):
+ """Base-class of all ANSI-C++ source files."""
+
+
+@export
+class SettingFile(File):
+ """Base-class of all tool-specific setting files."""
+
+
+@export
+class SimulationAnalysisFile(File):
+ """Base-class of all tool-specific analysis files."""
+
+
+@export
+class SimulationElaborationFile(File):
+ """Base-class of all tool-specific elaboration files."""
+
+
+@export
+class SimulationStartFile(File):
+ """Base-class of all tool-specific simulation start-up files."""
+
+
+@export
+class SimulationRunFile(File):
+ """Base-class of all tool-specific simulation run (execution) files."""
+
+
+@export
+class WaveformConfigFile(File):
+ """Base-class of all tool-specific waveform configuration files."""
+
+
+@export
+class WaveformDatabaseFile(File):
+ """Base-class of all tool-specific waveform database files."""
+
+
+@export
+class WaveformExchangeFile(File):
+ """Base-class of all tool-independent waveform exchange files."""
+
+
+[docs]@export
+class FileSet(metaclass=ExtendedType, slots=True):
+ """
+ A :term:`FileSet` represents a group of files. Filesets can have sub-filesets.
+
+ The order of insertion is preserved. A fileset can be created standalone and
+ later associated to another fileset, design and/or project. Or a fileset,
+ design and/or project can be associated immediately while creating the
+ fileset.
+
+ :arg name: Name of this fileset.
+ :arg topLevel: Name of the fileset's toplevel.
+ :arg directory: Path of this fileset (absolute or relative to a parent fileset or design).
+ :arg project: Project the file is associated with.
+ :arg design: Design the file is associated with.
+ :arg parent: Parent fileset if this fileset is nested.
+ :arg vhdlLibrary: Default VHDL library for files in this fileset, if not specified for the file itself.
+ :arg vhdlVersion: Default VHDL version for files in this fileset, if not specified for the file itself.
+ :arg verilogVersion: Default Verilog version for files in this fileset, if not specified for the file itself.
+ :arg svVersion: Default SystemVerilog version for files in this fileset, if not specified for the file itself.
+ :arg srdlVersion: Default SystemRDL version for files in this fileset, if not specified for the file itself.
+ """
+
+ _name: str
+ _topLevel: Nullable[str]
+ _project: Nullable['Project']
+ _design: Nullable['Design']
+ _directory: pathlib_Path
+ _parent: Nullable['FileSet']
+ _fileSets: Dict[str, 'FileSet']
+ _files: List[File]
+ _set: Set
+ _attributes: Dict[Type[Attribute], typing_Any]
+ _vhdlLibraries: Dict[str, 'VHDLLibrary']
+ _vhdlLibrary: 'VHDLLibrary'
+ _vhdlVersion: VHDLVersion
+ _verilogVersion: SystemVerilogVersion
+ _svVersion: SystemVerilogVersion
+ _srdlVersion: SystemRDLVersion
+
+[docs] def __init__(
+ self,
+ name: str,
+ topLevel: str = None,
+ directory: pathlib_Path = pathlib_Path("."),
+ project: 'Project' = None,
+ design: 'Design' = None,
+ parent: Nullable['FileSet'] = None,
+ vhdlLibrary: Union[str, 'VHDLLibrary'] = None,
+ vhdlVersion: VHDLVersion = None,
+ verilogVersion: SystemVerilogVersion = None,
+ svVersion: SystemVerilogVersion = None,
+ srdlVersion: SystemRDLVersion = None
+ ):
+ self._name = name
+ self._topLevel = topLevel
+ if project is not None:
+ self._project = project
+ self._design = design if design is not None else project.DefaultDesign
+
+ elif design is not None:
+ self._project = design._project
+ self._design = design
+ else:
+ self._project = None
+ self._design = None
+ self._directory = directory
+ self._parent = parent
+ self._fileSets = {}
+ self._files = []
+ self._set = set()
+
+ if design is not None:
+ design._fileSets[name] = self
+
+ self._attributes = {}
+ self._vhdlLibraries = {}
+
+ # TODO: handle if vhdlLibrary is a string
+ self._vhdlLibrary = vhdlLibrary
+ self._vhdlVersion = vhdlVersion
+ self._verilogVersion = verilogVersion
+ self._svVersion = svVersion
+ self._srdlVersion = srdlVersion
+
+ @property
+ def Name(self) -> str:
+ """Property setting or returning the fileset's name."""
+ return self._name
+
+ @Name.setter
+ def Name(self, value: str) -> None:
+ self._name = value
+
+ @property
+ def TopLevel(self) -> str:
+ """Property setting or returning the fileset's toplevel."""
+ return self._topLevel
+
+ @TopLevel.setter
+ def TopLevel(self, value: str) -> None:
+ self._topLevel = value
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ """Property setting or returning the project this fileset is used in."""
+ return self._project
+
+ @Project.setter
+ def Project(self, value: 'Project') -> None:
+ self._project = value
+
+ @property
+ def Design(self) -> Nullable['Design']:
+ """Property setting or returning the design this fileset is used in."""
+ if self._design is not None:
+ return self._design
+ elif self._parent is not None:
+ return self._parent.Design
+ else:
+ return None
+ # TODO: raise exception instead
+ # QUESTION: how to handle if design and parent is set?
+
+ @Design.setter
+ def Design(self, value: 'Design') -> None:
+ self._design = value
+ if self._project is None:
+ self._project = value._project
+ elif self._project is not value._project:
+ raise Exception("The design's project is not identical to the already assigned project.")
+
+ @property
+ def Directory(self) -> pathlib_Path:
+ """Property setting or returning the directory this fileset is located in."""
+ return self._directory
+
+ @Directory.setter
+ def Directory(self, value: pathlib_Path) -> None:
+ self._directory = value
+
+ @property
+ def ResolvedPath(self) -> pathlib_Path:
+ """Read-only property returning the resolved path of this fileset."""
+ if self._directory.is_absolute():
+ return self._directory.resolve()
+ else:
+ if self._parent is not None:
+ directory = self._parent.ResolvedPath
+ elif self._design is not None:
+ directory = self._design.ResolvedPath
+ elif self._project is not None:
+ directory = self._project.ResolvedPath
+ else:
+ # TODO: message and exception type
+ raise Exception("")
+
+ directory = (directory / self._directory).resolve()
+ if directory.is_absolute():
+ return directory
+ else:
+ # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+ return pathlib_Path(path_relpath(directory, pathlib_Path.cwd()))
+
+ @property
+ def Parent(self) -> Nullable['FileSet']:
+ """Property setting or returning the parent fileset this fileset is used in."""
+ return self._parent
+
+ @Parent.setter
+ def Parent(self, value: 'FileSet') -> None:
+ self._parent = value
+ value._fileSets[self._name] = self
+ # TODO: check it it already exists
+ # QUESTION: make an Add fileset method?
+
+ @property
+ def FileSets(self) -> Dict[str, 'FileSet']:
+ """Read-only property returning the dictionary of sub-filesets."""
+ return self._fileSets
+
+[docs] def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[bool, str, 'FileSet'] = None) -> Generator[File, None, None]:
+ """
+ Method returning the files of this fileset.
+
+ :arg fileType: A filter for file types. Default: ``Any``.
+ :arg fileSet: Specifies how to handle sub-filesets.
+ """
+ if fileSet is False:
+ for file in self._files:
+ if file.FileType in fileType:
+ yield file
+ elif fileSet is None:
+ for fileSet in self._fileSets.values():
+ for file in fileSet.Files(fileType):
+ yield file
+ for file in self._files:
+ if file.FileType in fileType:
+ yield file
+ else:
+ if isinstance(fileSet, str):
+ fileSetName = fileSet
+ try:
+ fileSet = self._fileSets[fileSetName]
+ except KeyError as ex:
+ raise Exception(f"Fileset {fileSetName} not bound to fileset {self.Name}.") from ex
+ elif not isinstance(fileSet, FileSet):
+ raise TypeError("Parameter 'fileSet' is not of type 'str' or 'FileSet' nor value 'None'.")
+
+ for file in fileSet.Files(fileType):
+ yield file
+
+[docs] def AddFileSet(self, fileSet: "FileSet") -> None:
+ """
+ Method to add a single sub-fileset to this fileset.
+
+ :arg fileSet: A fileset to add to this fileset as sub-fileset.
+ """
+ if not isinstance(fileSet, FileSet):
+ raise ValueError("Parameter 'fileSet' is not of type ProjectModel.FileSet.")
+ elif fileSet in self._fileSets:
+ raise Exception("Sub-fileset already contains this fileset.")
+ elif fileSet.Name in self._fileSets.keys():
+ raise Exception(f"Fileset already contains a sub-fileset named '{fileSet.Name}'.")
+
+ self._fileSets[fileSet.Name] = fileSet
+ fileSet._parent = self
+
+[docs] def AddFileSets(self, fileSets: Iterable["FileSet"]) -> None:
+ """
+ Method to add a multiple sub-filesets to this fileset.
+
+ :arg fileSets: An iterable of filesets to add each to the fileset.
+ """
+ for fileSet in fileSets:
+ self.AddFileSet(fileSet)
+
+ @property
+ def FileSetCount(self) -> int:
+ """Returns number of file sets excl. sub-filesets."""
+ return len(self._fileSets)
+
+ @property
+ def TotalFileSetCount(self) -> int:
+ """Returns number of file sets incl. sub-filesets."""
+ fileSetCount = len(self._fileSets)
+ for fileSet in self._fileSets.values():
+ fileSetCount += fileSet.TotalFileSetCount
+
+ return fileSetCount
+
+[docs] def AddFile(self, file: File) -> None:
+ """
+ Method to add a single file to this fileset.
+
+ :arg file: A file to add to this fileset.
+ """
+ if not isinstance(file, File):
+ raise TypeError("Parameter 'file' is not of type ProjectModel.File.")
+ elif file._fileSet is not None:
+ ex = ValueError(f"File '{file.Path!s}' is already part of fileset '{file.FileSet.Name}'.")
+ ex.add_note(f"A file can't be assigned to another fileset.")
+ raise ex
+ elif file in self._set:
+ ex = ValueError(f"File '{file.Path!s}' is already part of this fileset.")
+ ex.add_note(f"A file can't be added twice to a fileset.")
+ raise ex
+
+ self._files.append(file)
+ self._set.add(file)
+ file._fileSet = self
+
+[docs] def AddFiles(self, files: Iterable[File]) -> None:
+ """
+ Method to add a multiple files to this fileset.
+
+ :arg files: An iterable of files to add each to the fileset.
+ """
+ for file in files:
+ self.AddFile(file)
+
+ @property
+ def FileCount(self) -> int:
+ """Returns number of files excl. sub-filesets."""
+ return len(self._files)
+
+ @property
+ def TotalFileCount(self) -> int:
+ """Returns number of files incl. the files in sub-filesets."""
+ fileCount = len(self._files)
+ for fileSet in self._fileSets.values():
+ fileCount += fileSet.FileCount
+
+ return fileCount
+
+[docs] def Validate(self) -> None:
+ """Validate this fileset."""
+ if self._name is None or self._name == "":
+ raise Exception("Validation: FileSet has no name.")
+
+ if self._directory is None:
+ raise Exception(f"Validation: FileSet '{self._name}' has no directory.")
+ try:
+ path = self.ResolvedPath
+ except Exception as ex:
+ raise Exception(f"Validation: FileSet '{self._name}' could not compute resolved path.") from ex
+ if not path.exists():
+ raise Exception(f"Validation: FileSet '{self._name}'s directory '{path}' does not exist.")
+ if not path.is_dir():
+ raise Exception(f"Validation: FileSet '{self._name}'s directory '{path}' is not a directory.")
+
+ if self._design is None:
+ raise Exception(f"Validation: FileSet '{self._path}' has no design.")
+ if self._project is None:
+ raise Exception(f"Validation: FileSet '{self._path}' has no project.")
+
+ for fileSet in self._fileSets.values():
+ fileSet.Validate()
+ for file in self._files:
+ file.Validate()
+
+[docs] def __len__(self) -> int:
+ """Returns number of attributes set on the file set."""
+ return len(self._attributes)
+
+[docs] def __getitem__(self, key: Type[Attribute]) -> Any:
+ """Index access for returning attributes on this file."""
+ if not issubclass(key, Attribute):
+ raise TypeError("Parameter 'key' is not an 'Attribute'.")
+
+ try:
+ return self._attributes[key]
+ except KeyError:
+ return key.resolve(self, key)
+
+[docs] def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+ """Index access for setting attributes on this file."""
+ self._attributes[key] = value
+
+ def GetOrCreateVHDLLibrary(self, name) -> None:
+ if name in self._vhdlLibraries:
+ return self._vhdlLibraries[name]
+ elif name in self._design._vhdlLibraries:
+ library = self._design._vhdlLibraries[name]
+ self._vhdlLibraries[name] = library
+ return library
+ else:
+ library = VHDLLibrary(name, design=self._design, vhdlVersion=self._vhdlVersion)
+ self._vhdlLibraries[name] = library
+ return library
+
+ @property
+ def VHDLLibrary(self) -> 'VHDLLibrary':
+ """Property setting or returning the VHDL library of this fileset."""
+ if self._vhdlLibrary is not None:
+ return self._vhdlLibrary
+ elif self._parent is not None:
+ return self._parent.VHDLLibrary
+ elif self._design is not None:
+ return self._design.VHDLLibrary
+ else:
+ raise Exception("VHDLLibrary was neither set locally nor globally.")
+
+ @VHDLLibrary.setter
+ def VHDLLibrary(self, value: 'VHDLLibrary') -> None:
+ self._vhdlLibrary = value
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ """Property setting or returning the VHDL version of this fileset."""
+ if self._vhdlVersion is not None:
+ return self._vhdlVersion
+ elif self._parent is not None:
+ return self._parent.VHDLVersion
+ elif self._design is not None:
+ return self._design.VHDLVersion
+ else:
+ raise Exception("VHDLVersion was neither set locally nor globally.")
+
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+ self._vhdlVersion = value
+
+ @property
+ def VerilogVersion(self) -> SystemVerilogVersion:
+ """Property setting or returning the Verilog version of this fileset."""
+ if self._verilogVersion is not None:
+ return self._verilogVersion
+ elif self._parent is not None:
+ return self._parent.VerilogVersion
+ elif self._design is not None:
+ return self._design.VerilogVersion
+ else:
+ raise Exception("VerilogVersion was neither set locally nor globally.")
+
+ @VerilogVersion.setter
+ def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+ self._verilogVersion = value
+
+ @property
+ def SVVersion(self) -> SystemVerilogVersion:
+ """Property setting or returning the SystemVerilog version of this fileset."""
+ if self._svVersion is not None:
+ return self._svVersion
+ elif self._parent is not None:
+ return self._parent.SVVersion
+ elif self._design is not None:
+ return self._design.SVVersion
+ else:
+ raise Exception("SVVersion was neither set locally nor globally.")
+
+ @SVVersion.setter
+ def SVVersion(self, value: SystemVerilogVersion) -> None:
+ self._svVersion = value
+
+ @property
+ def SRDLVersion(self) -> SystemRDLVersion:
+ if self._srdlVersion is not None:
+ return self._srdlVersion
+ elif self._parent is not None:
+ return self._parent.SRDLVersion
+ elif self._design is not None:
+ return self._design.SRDLVersion
+ else:
+ raise Exception("SRDLVersion was neither set locally nor globally.")
+
+ @SRDLVersion.setter
+ def SRDLVersion(self, value: SystemRDLVersion) -> None:
+ self._srdlVersion = value
+
+
+
+
+[docs]@export
+class VHDLLibrary(metaclass=ExtendedType, slots=True):
+ """
+ A :term:`VHDLLibrary` represents a group of VHDL source files compiled into the same VHDL library.
+
+ :arg name: The VHDL libraries' name.
+ :arg project: Project the VHDL library is associated with.
+ :arg design: Design the VHDL library is associated with.
+ :arg vhdlVersion: Default VHDL version for files in this VHDL library, if not specified for the file itself.
+ """
+
+ _name: str
+ _project: Nullable['Project']
+ _design: Nullable['Design']
+ _files: List[File]
+ _vhdlVersion: VHDLVersion
+
+ _dependencyNode: Vertex
+
+[docs] def __init__(
+ self,
+ name: str,
+ project: 'Project' = None,
+ design: 'Design' = None,
+ vhdlVersion: VHDLVersion = None
+ ):
+ self._name = name
+ if project is not None:
+ self._project = project
+ self._design = project._defaultDesign if design is None else design
+ self._dependencyNode = Vertex(value=self, graph=self._design._vhdlLibraryDependencyGraph)
+
+ if name in self._design._vhdlLibraries:
+ raise Exception(f"Library '{name}' already in design '{self._design.Name}'.")
+ else:
+ self._design._vhdlLibraries[name] = self
+
+ elif design is not None:
+ self._project = design._project
+ self._design = design
+ self._dependencyNode = Vertex(value=self, graph=design._vhdlLibraryDependencyGraph)
+
+ if name in design._vhdlLibraries:
+ raise Exception(f"Library '{name}' already in design '{design.Name}'.")
+ else:
+ design._vhdlLibraries[name] = self
+
+ else:
+ self._project = None
+ self._design = None
+ self._dependencyNode = None
+
+ self._files = []
+ self._vhdlVersion = vhdlVersion
+
+ @property
+ def Name(self) -> str:
+ return self._name
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ """Property setting or returning the project this VHDL library is used in."""
+ return self._project
+
+ @Project.setter
+ def Project(self, value: 'Project') -> None:
+ if not isinstance(value, Project):
+ raise TypeError("Parameter 'value' is not of type 'Project'.")
+
+ if value is None:
+ # TODO: unlink VHDLLibrary from project
+ self._project = None
+ else:
+ self._project = value
+ if self._design is None:
+ self._design = value._defaultDesign
+
+ @property
+ def Design(self) -> Nullable['Design']:
+ """Property setting or returning the design this VHDL library is used in."""
+ return self._design
+
+ @Design.setter
+ def Design(self, value: 'Design') -> None:
+ if not isinstance(value, Design):
+ raise TypeError("Parameter 'value' is not of type 'Design'.")
+
+ if value is None:
+ # TODO: unlink VHDLLibrary from design
+ self._design = None
+ else:
+ if self._design is None:
+ self._design = value
+ self._dependencyNode = Vertex(value=self, graph=self._design._vhdlLibraryDependencyGraph)
+ elif self._design is not value:
+ # TODO: move VHDLLibrary to other design
+ # TODO: create new vertex in dependency graph and remove vertex from old graph
+ self._design = value
+ else:
+ pass
+
+ if self._project is None:
+ self._project = value._project
+ elif self._project is not value._project:
+ raise Exception("The design's project is not identical to the already assigned project.")
+
+ @property
+ def Files(self) -> Generator[File, None, None]:
+ """Read-only property to return all files in this VHDL library."""
+ for file in self._files:
+ yield file
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ """Property setting or returning the VHDL version of this VHDL library."""
+ if self._vhdlVersion is not None:
+ return self._vhdlVersion
+ elif self._design is not None:
+ return self._design.VHDLVersion
+ else:
+ raise Exception("VHDLVersion is not set on VHDLLibrary nor parent object.")
+
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+ self._vhdlVersion = value
+
+ def AddDependency(self, library: 'VHDLLibrary') -> None:
+ library.parent = self
+
+ def AddFile(self, vhdlFile: VHDLSourceFile) -> None:
+ if not isinstance(vhdlFile, VHDLSourceFile):
+ raise TypeError(f"Parameter 'vhdlFile' is not a 'VHDLSourceFile'.")
+
+ self._files.append(vhdlFile)
+
+ def AddFiles(self, vhdlFiles: Iterable[VHDLSourceFile]) -> None:
+ for vhdlFile in vhdlFiles:
+ if not isinstance(vhdlFile, VHDLSourceFile):
+ raise TypeError(f"Item '{vhdlFile}' in parameter 'vhdlFiles' is not a 'VHDLSourceFile'.")
+
+ self._files.append(vhdlFile)
+
+ @property
+ def FileCount(self) -> int:
+ """Returns number of files."""
+ return len(self._files)
+
+
+
+
+[docs]@export
+class Design(metaclass=ExtendedType, slots=True):
+ """
+ A :term:`Design` represents a group of filesets and the source files therein.
+
+ Each design contains at least one fileset - the :term:`default fileset`. For
+ designs with VHDL source files, a independent `VHDLLibraries` overlay structure
+ exists.
+
+ :arg name: The design's name.
+ :arg topLevel: Name of the design's toplevel.
+ :arg directory: Path of this design (absolute or relative to the project).
+ :arg project: Project the design is associated with.
+ :arg vhdlVersion: Default VHDL version for files in this design, if not specified for the file itself.
+ :arg verilogVersion: Default Verilog version for files in this design, if not specified for the file itself.
+ :arg svVersion: Default SystemVerilog version for files in this design, if not specified for the file itself.
+ :arg srdlVersion: Default SystemRDL version for files in this fileset, if not specified for the file itself.
+ """
+
+ _name: str
+ _topLevel: Nullable[str]
+ _project: Nullable['Project']
+ _directory: pathlib_Path
+ _fileSets: Dict[str, FileSet]
+ _defaultFileSet: Nullable[FileSet]
+ _attributes: Dict[Type[Attribute], typing_Any]
+
+ _vhdlLibraries: Dict[str, VHDLLibrary]
+ _vhdlVersion: VHDLVersion
+ _verilogVersion: SystemVerilogVersion
+ _svVersion: SystemVerilogVersion
+ _srdlVersion: SystemRDLVersion
+ _externalVHDLLibraries: List
+
+ _vhdlLibraryDependencyGraph: Graph
+ _fileDependencyGraph: Graph
+
+[docs] def __init__(
+ self,
+ name: str,
+ topLevel: str = None,
+ directory: pathlib_Path = pathlib_Path("."),
+ project: 'Project' = None,
+ vhdlVersion: VHDLVersion = None,
+ verilogVersion: SystemVerilogVersion = None,
+ svVersion: SystemVerilogVersion = None,
+ srdlVersion: SystemRDLVersion = None
+ ):
+ self._name = name
+ self._topLevel = topLevel
+ self._project = project
+ if project is not None:
+ project._designs[name] = self
+ self._directory = directory
+ self._fileSets = {}
+ self._defaultFileSet = FileSet("default", project=project, design=self)
+ self._attributes = {}
+ self._vhdlLibraries = {}
+ self._vhdlVersion = vhdlVersion
+ self._verilogVersion = verilogVersion
+ self._svVersion = svVersion
+ self._srdlVersion = srdlVersion
+ self._externalVHDLLibraries = []
+
+ self._vhdlLibraryDependencyGraph = Graph()
+ self._fileDependencyGraph = Graph()
+
+ @property
+ def Name(self) -> str:
+ """Property setting or returning the design's name."""
+ return self._name
+
+ @Name.setter
+ def Name(self, value: str) -> None:
+ self._name = value
+
+ @property
+ def TopLevel(self) -> str:
+ """Property setting or returning the fileset's toplevel."""
+ return self._topLevel
+
+ @TopLevel.setter
+ def TopLevel(self, value: str) -> None:
+ self._topLevel = value
+
+ @property
+ def Project(self) -> Nullable['Project']:
+ """Property setting or returning the project this design is used in."""
+ return self._project
+
+ @Project.setter
+ def Project(self, value: 'Project') -> None:
+ self._project = value
+
+ @property
+ def Directory(self) -> pathlib_Path:
+ """Property setting or returning the directory this design is located in."""
+ return self._directory
+
+ @Directory.setter
+ def Directory(self, value: pathlib_Path) -> None:
+ self._directory = value
+
+ @property
+ def ResolvedPath(self) -> pathlib_Path:
+ """Read-only property returning the resolved path of this fileset."""
+ if self._directory.is_absolute():
+ return self._directory.resolve()
+ elif self._project is not None:
+ path = (self._project.ResolvedPath / self._directory).resolve()
+
+ if path.is_absolute():
+ return path
+ else:
+ # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+ return pathlib_Path(path_relpath(path, pathlib_Path.cwd()))
+ else:
+ # TODO: message and exception type
+ raise Exception("")
+
+ @property
+ def DefaultFileSet(self) -> FileSet:
+ """Property setting or returning the default fileset of this design."""
+ return self._defaultFileSet
+
+ @DefaultFileSet.setter
+ def DefaultFileSet(self, value: Union[str, FileSet]) -> None:
+ if isinstance(value, str):
+ if value not in self._fileSets.keys():
+ raise Exception(f"Fileset '{value}' is not in this design.")
+
+ self._defaultFileSet = self._fileSets[value]
+ elif isinstance(value, FileSet):
+ if value not in self.FileSets:
+ raise Exception(f"Fileset '{value}' is not associated to this design.")
+
+ self._defaultFileSet = value
+ else:
+ raise ValueError("Unsupported parameter type for 'value'.")
+
+ # TODO: return generator with another method
+ @property
+ def FileSets(self) -> Dict[str, FileSet]:
+ """Read-only property returning the dictionary of filesets."""
+ return self._fileSets
+
+[docs] def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[str, FileSet] = None) -> Generator[File, None, None]:
+ """
+ Method returning the files of this design.
+
+ :arg fileType: A filter for file types. Default: ``Any``.
+ :arg fileSet: Specifies if all files from all filesets (``fileSet=None``) are files from a single fileset are returned.
+ """
+ if fileSet is None:
+ for fileSet in self._fileSets.values():
+ for file in fileSet.Files(fileType):
+ yield file
+ else:
+ if isinstance(fileSet, str):
+ try:
+ fileSet = self._fileSets[fileSet]
+ except KeyError as ex:
+ raise Exception(f"Fileset {fileSet.Name} not bound to design {self.Name}.") from ex
+ elif not isinstance(fileSet, FileSet):
+ raise TypeError("Parameter 'fileSet' is not of type 'str' or 'FileSet' nor value 'None'.")
+
+ for file in fileSet.Files(fileType):
+ yield file
+
+
+
+[docs] def Validate(self) -> None:
+ """Validate this design."""
+ if self._name is None or self._name == "":
+ raise Exception("Validation: Design has no name.")
+
+ if self._directory is None:
+ raise Exception(f"Validation: Design '{self._name}' has no directory.")
+ try:
+ path = self.ResolvedPath
+ except Exception as ex:
+ raise Exception(f"Validation: Design '{self._name}' could not compute resolved path.") from ex
+ if not path.exists():
+ raise Exception(f"Validation: Design '{self._name}'s directory '{path}' does not exist.")
+ if not path.is_dir():
+ raise Exception(f"Validation: Design '{self._name}'s directory '{path}' is not a directory.")
+
+ if len(self._fileSets) == 0:
+ raise Exception(f"Validation: Design '{self._name}' has no fileset.")
+ try:
+ if self._defaultFileSet is not self._fileSets[self._defaultFileSet.Name]:
+ raise Exception(f"Validation: Design '{self._name}'s default fileset is the same as listed in filesets.")
+ except KeyError as ex:
+ raise Exception(f"Validation: Design '{self._name}'s default fileset is not in list of filesets.") from ex
+ if self._project is None:
+ raise Exception(f"Validation: Design '{self._path}' has no project.")
+
+ for fileSet in self._fileSets.values():
+ fileSet.Validate()
+
+[docs] def __len__(self) -> int:
+ """Returns number of attributes set on the file set."""
+ return len(self._attributes)
+
+ def __getitem__(self, key: Type[Attribute]) -> Any:
+ if not issubclass(key, Attribute):
+ raise TypeError("Parameter 'key' is not an 'Attribute'.")
+
+ try:
+ return self._attributes[key]
+ except KeyError:
+ return key.resolve(self, key)
+
+ def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+ self._attributes[key] = value
+
+ @property
+ def VHDLLibraries(self) -> Dict[str, VHDLLibrary]:
+ return self._vhdlLibraries
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ if self._vhdlVersion is not None:
+ return self._vhdlVersion
+ elif self._project is not None:
+ return self._project.VHDLVersion
+ else:
+ raise Exception("VHDLVersion was neither set locally nor globally.")
+
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+ self._vhdlVersion = value
+
+ @property
+ def VerilogVersion(self) -> SystemVerilogVersion:
+ if self._verilogVersion is not None:
+ return self._verilogVersion
+ elif self._project is not None:
+ return self._project.VerilogVersion
+ else:
+ raise Exception("VerilogVersion was neither set locally nor globally.")
+
+ @VerilogVersion.setter
+ def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+ self._verilogVersion = value
+
+ @property
+ def SVVersion(self) -> SystemVerilogVersion:
+ if self._svVersion is not None:
+ return self._svVersion
+ elif self._project is not None:
+ return self._project.SVVersion
+ else:
+ raise Exception("SVVersion was neither set locally nor globally.")
+
+ @SVVersion.setter
+ def SVVersion(self, value: SystemVerilogVersion) -> None:
+ self._svVersion = value
+
+ @property
+ def SRDLVersion(self) -> SystemRDLVersion:
+ if self._srdlVersion is not None:
+ return self._srdlVersion
+ elif self._project is not None:
+ return self._project.SRDLVersion
+ else:
+ raise Exception("SRDLVersion was neither set locally nor globally.")
+
+ @SRDLVersion.setter
+ def SRDLVersion(self, value: SystemRDLVersion) -> None:
+ self._srdlVersion = value
+
+ @property
+ def ExternalVHDLLibraries(self) -> List:
+ return self._externalVHDLLibraries
+
+ def AddFileSet(self, fileSet: FileSet) -> None:
+ if not isinstance(fileSet, FileSet):
+ raise ValueError("Parameter 'fileSet' is not of type ProjectModel.FileSet.")
+ elif fileSet in self._fileSets:
+ raise Exception("Design already contains this fileset.")
+ elif fileSet.Name in self._fileSets.keys():
+ raise Exception(f"Design already contains a fileset named '{fileSet.Name}'.")
+
+ self._fileSets[fileSet.Name] = fileSet
+ fileSet.Design = self
+ fileSet._parent = self
+
+ def AddFileSets(self, fileSets: Iterable[FileSet]) -> None:
+ for fileSet in fileSets:
+ self.AddFileSet(fileSet)
+
+ @property
+ def FileSetCount(self) -> int:
+ """Returns number of file sets excl. sub-filesets."""
+ return len(self._fileSets)
+
+ @property
+ def TotalFileSetCount(self) -> int:
+ """Returns number of file sets incl. sub-filesets."""
+ fileSetCount = len(self._fileSets)
+ for fileSet in self._fileSets.values():
+ fileSetCount += fileSet.TotalFileSetCount
+
+ return fileSetCount
+
+ def AddFile(self, file: File) -> None:
+ if file.FileSet is None:
+ self._defaultFileSet.AddFile(file)
+ else:
+ raise ValueError(f"File '{file.Path!s}' is already part of fileset '{file.FileSet.Name}' and can't be assigned via Design to a default fileset.")
+
+ def AddFiles(self, files: Iterable[File]) -> None:
+ for file in files:
+ self.AddFile(file)
+
+ def AddVHDLLibrary(self, vhdlLibrary: VHDLLibrary) -> None:
+ if vhdlLibrary.Name in self._vhdlLibraries:
+ if self._vhdlLibraries[vhdlLibrary.Name] is vhdlLibrary:
+ raise Exception(f"The VHDLLibrary '{vhdlLibrary.Name}' was already added to the design.")
+ else:
+ raise Exception(f"A VHDLLibrary with same name ('{vhdlLibrary.Name}') already exists for this design.")
+
+
+
+
+[docs]@export
+class Project(metaclass=ExtendedType, slots=True):
+ """
+ A :term:`Project` represents a group of designs and the source files therein.
+
+ :arg name: The project's name.
+ :arg rootDirectory: Base-path to the project.
+ :arg vhdlVersion: Default VHDL version for files in this project, if not specified for the file itself.
+ :arg verilogVersion: Default Verilog version for files in this project, if not specified for the file itself.
+ :arg svVersion: Default SystemVerilog version for files in this project, if not specified for the file itself.
+ """
+
+ _name: str
+ _rootDirectory: pathlib_Path
+ _designs: Dict[str, Design]
+ _defaultDesign: Design
+ _attributes: Dict[Type[Attribute], typing_Any]
+
+ _vhdlVersion: VHDLVersion
+ _verilogVersion: SystemVerilogVersion
+ _svVersion: SystemVerilogVersion
+ _srdlVersion: SystemRDLVersion
+
+[docs] def __init__(
+ self,
+ name: str,
+ rootDirectory: pathlib_Path = pathlib_Path("."),
+ vhdlVersion: VHDLVersion = None,
+ verilogVersion: SystemVerilogVersion = None,
+ svVersion: SystemVerilogVersion = None
+ ):
+ self._name = name
+ self._rootDirectory = rootDirectory
+ self._designs = {}
+ self._defaultDesign = Design("default", project=self)
+ self._attributes = {}
+ self._vhdlVersion = vhdlVersion
+ self._verilogVersion = verilogVersion
+ self._svVersion = svVersion
+
+ @property
+ def Name(self) -> str:
+ """Property setting or returning the project's name."""
+ return self._name
+
+ @property
+ def RootDirectory(self) -> pathlib_Path:
+ """Property setting or returning the root directory this project is located in."""
+ return self._rootDirectory
+
+ @RootDirectory.setter
+ def RootDirectory(self, value: pathlib_Path) -> None:
+ self._rootDirectory = value
+
+ @property
+ def ResolvedPath(self) -> pathlib_Path:
+ """Read-only property returning the resolved path of this fileset."""
+ path = self._rootDirectory.resolve()
+ if self._rootDirectory.is_absolute():
+ return path
+ else:
+ # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+ return pathlib_Path(path_relpath(path, pathlib_Path.cwd()))
+
+ # TODO: return generator with another method
+ @property
+ def Designs(self) -> Dict[str, Design]:
+ return self._designs
+
+ @property
+ def DefaultDesign(self) -> Design:
+ return self._defaultDesign
+
+[docs] def Validate(self) -> None:
+ """Validate this project."""
+ if self._name is None or self._name == "":
+ raise Exception("Validation: Project has no name.")
+
+ if self._rootDirectory is None:
+ raise Exception(f"Validation: Project '{self._name}' has no root directory.")
+ try:
+ path = self.ResolvedPath
+ except Exception as ex:
+ raise Exception(f"Validation: Project '{self._name}' could not compute resolved path.") from ex
+ if not path.exists():
+ raise Exception(f"Validation: Project '{self._name}'s directory '{path}' does not exist.")
+ if not path.is_dir():
+ raise Exception(f"Validation: Project '{self._name}'s directory '{path}' is not a directory.")
+
+ if len(self._designs) == 0:
+ raise Exception(f"Validation: Project '{self._name}' has no design.")
+ try:
+ if self._defaultDesign is not self._designs[self._defaultDesign.Name]:
+ raise Exception(f"Validation: Project '{self._name}'s default design is the same as listed in designs.")
+ except KeyError as ex:
+ raise Exception(f"Validation: Project '{self._name}'s default design is not in list of designs.") from ex
+
+ for design in self._designs.values():
+ design.Validate()
+
+ @property
+ def DesignCount(self) -> int:
+ """Returns number of designs."""
+ return len(self._designs)
+
+[docs] def __len__(self) -> int:
+ """Returns number of attributes set on the file set."""
+ return len(self._attributes)
+
+ def __getitem__(self, key: Type[Attribute]) -> Any:
+ if not issubclass(key, Attribute):
+ raise TypeError("Parameter 'key' is not an 'Attribute'.")
+
+ try:
+ return self._attributes[key]
+ except KeyError:
+ return key.resolve(self, key)
+
+ def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+ self._attributes[key] = value
+
+ @property
+ def VHDLVersion(self) -> VHDLVersion:
+ # TODO: check for None and return exception
+ return self._vhdlVersion
+
+ @VHDLVersion.setter
+ def VHDLVersion(self, value: VHDLVersion) -> None:
+ self._vhdlVersion = value
+
+ @property
+ def VerilogVersion(self) -> SystemVerilogVersion:
+ # TODO: check for None and return exception
+ return self._verilogVersion
+
+ @VerilogVersion.setter
+ def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+ self._verilogVersion = value
+
+ @property
+ def SVVersion(self) -> SystemVerilogVersion:
+ # TODO: check for None and return exception
+ return self._svVersion
+
+ @SVVersion.setter
+ def SVVersion(self, value: SystemVerilogVersion) -> None:
+ self._svVersion = value
+
+ @property
+ def SRDLVersion(self) -> SystemRDLVersion:
+ # TODO: check for None and return exception
+ return self._srdlVersion
+
+ @SRDLVersion.setter
+ def SRDLVersion(self, value: SystemRDLVersion) -> None:
+ self._srdlVersion = value
+
+
+
+# ==================================================================================================================== #
+# _____ ____ _ _ ____ _ _ __ __ _ _ #
+# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | #
+# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | #
+# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | #
+# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| #
+# |_| |___/ |__/ #
+# ==================================================================================================================== #
+# Authors: #
+# Patrick Lehmann #
+# #
+# License: #
+# ==================================================================================================================== #
+# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+# #
+# SPDX-License-Identifier: Apache-2.0 #
+# ==================================================================================================================== #
+#
+"""A set of common attributes to store meta information on ProjectModel entities (project, design, fileset, file, ...)."""
+from typing import Dict
+from pyTooling.Decorators import export
+
+from pyEDAA.ProjectModel import Attribute
+
+
+[docs]@export
+class KeyValueAttribute(Attribute):
+ KEY = "ID"
+
+ _keyValuePairs: Dict[str, str]
+
+
+
+ def __getitem__(self, item: str) -> str:
+ return self._keyValuePairs[item]
+
+ def __setitem__(self, key: str, value: str) -> None:
+ self._keyValuePairs[key] = value
+
+# ==================================================================================================================== #
+# _____ ____ _ _ ____ _ _ __ __ _ _ #
+# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | #
+# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | #
+# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | #
+# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| #
+# |_| |___/ |__/ #
+# ==================================================================================================================== #
+# Authors: #
+# Patrick Lehmann #
+# #
+# License: #
+# ==================================================================================================================== #
+# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+# #
+# SPDX-License-Identifier: Apache-2.0 #
+# ==================================================================================================================== #
+#
+"""Specific file types and attributes for Xilinx Vivado."""
+from pathlib import Path
+from typing import Iterable
+
+from xml.dom import minidom, Node
+
+from pyTooling.MetaClasses import ExtendedType
+from pyVHDLModel import VHDLVersion
+from pyTooling.Decorators import export
+
+from pyEDAA.ProjectModel import ProjectFile, XMLFile, XMLContent, SDCContent, Project, FileSet, Attribute, Design
+from pyEDAA.ProjectModel import File as Model_File
+from pyEDAA.ProjectModel import ConstraintFile as Model_ConstraintFile
+from pyEDAA.ProjectModel import VerilogSourceFile as Model_VerilogSourceFile
+from pyEDAA.ProjectModel import VHDLSourceFile as Model_VHDLSourceFile
+
+
+
+
+
+@export
+class File(Model_File):
+ pass
+
+
+class VivadoFileMixIn(metaclass=ExtendedType, mixin=True):
+ def _registerAttributes(self):
+ self._attributes[UsedInAttribute] = []
+
+
+@export
+class ConstraintFile(Model_ConstraintFile, VivadoFileMixIn):
+ def _registerAttributes(self):
+ super()._registerAttributes()
+ VivadoFileMixIn._registerAttributes(self)
+
+
+@export
+class VerilogSourceFile(Model_VerilogSourceFile):
+ def _registerAttributes(self):
+ super()._registerAttributes()
+ VivadoFileMixIn._registerAttributes(self)
+
+
+@export
+class VHDLSourceFile(Model_VHDLSourceFile):
+ def _registerAttributes(self):
+ super()._registerAttributes()
+ VivadoFileMixIn._registerAttributes(self)
+
+
+@export
+class VivadoProjectFile(ProjectFile, XMLContent):
+ """A Vivado project file (``*.xpr``)."""
+
+ _xprProject: Project
+
+ def __init__(
+ self,
+ path: Path,
+ project: Project = None,
+ design: Design = None,
+ fileSet: FileSet = None
+ ):
+ super().__init__(path, project, design, fileSet)
+
+ self._xprProject = None
+
+ @property
+ def ProjectModel(self) -> Project:
+ return self._xprProject
+
+ def Parse(self):
+ if not self._path.exists():
+ raise Exception(f"Vivado project file '{self._path!s}' not found.") from FileNotFoundError(f"File '{self._path!s}' not found.")
+
+ try:
+ root = minidom.parse(str(self._path)).documentElement
+ except Exception as ex:
+ raise Exception(f"Couldn't open '{self._path!s}'.") from ex
+
+ self._xprProject = Project(self._path.stem, rootDirectory=self._path.parent)
+ self._ParseRootElement(root)
+
+ def _ParseRootElement(self, root):
+ for rootNode in root.childNodes:
+ if rootNode.nodeName == "FileSets":
+ self._ParseFileSets(rootNode)
+ break
+
+ def _ParseFileSets(self, filesetsNode):
+ for fileSetsNode in filesetsNode.childNodes:
+ if fileSetsNode.nodeType == Node.ELEMENT_NODE and fileSetsNode.tagName == "FileSet":
+ self._ParseFileSet(fileSetsNode)
+
+ def _ParseFileSet(self, filesetNode):
+ filesetName = filesetNode.getAttribute("Name")
+ fileset = FileSet(filesetName, design=self._xprProject.DefaultDesign)
+
+ for fileNode in filesetNode.childNodes:
+ if fileNode.nodeType == Node.ELEMENT_NODE:
+ if fileNode.tagName == "File":
+ self._ParseFile(fileNode, fileset)
+ elif fileNode.nodeType == Node.ELEMENT_NODE and fileNode.tagName == "Config":
+ self._ParseFileSetConfig(fileNode, fileset)
+
+ def _ParseFile(self, fileNode, fileset):
+ croppedPath = fileNode.getAttribute("Path").replace("$PPRDIR/", "")
+ filePath = Path(croppedPath)
+ if filePath.suffix in (".vhd", ".vhdl"):
+ self._ParseVHDLFile(fileNode, filePath, fileset)
+ elif filePath.suffix == ".xdc":
+ self._ParseXDCFile(fileNode, filePath, fileset)
+ elif filePath.suffix == ".v":
+ self._ParseVerilogFile(fileNode, filePath, fileset)
+ elif filePath.suffix == ".xci":
+ self._ParseXCIFile(fileNode, filePath, fileset)
+ else:
+ self._ParseDefaultFile(fileNode, filePath, fileset)
+
+ def _ParseVHDLFile(self, fileNode, path, fileset):
+ vhdlFile = VHDLSourceFile(path)
+ fileset.AddFile(vhdlFile)
+ usedInAttr = vhdlFile[UsedInAttribute]
+
+ for childNode in fileNode.childNodes:
+ if childNode.nodeType == Node.ELEMENT_NODE and childNode.tagName == "FileInfo":
+ if childNode.getAttribute("SFType") == "VHDL2008":
+ vhdlFile.VHDLVersion = VHDLVersion.VHDL2008
+ else:
+ vhdlFile.VHDLVersion = VHDLVersion.VHDL93
+
+ for fileAttribute in childNode.childNodes:
+ if fileAttribute.nodeType == Node.ELEMENT_NODE and fileAttribute.tagName == "Attr":
+ if fileAttribute.getAttribute("Name") == "Library":
+ libraryName = fileAttribute.getAttribute("Val")
+ vhdlFile.VHDLLibrary = fileset.GetOrCreateVHDLLibrary(libraryName)
+ elif fileAttribute.getAttribute("Val") == "UsedIn":
+ usedInAttr.append(fileAttribute.getAttribute("Val"))
+
+ def _ParseDefaultFile(self, _, path, fileset):
+ File(path, fileSet=fileset)
+
+ def _ParseXDCFile(self, _, path, fileset):
+ XDCConstraintFile(path, fileSet=fileset)
+
+ def _ParseVerilogFile(self, _, path, fileset):
+ VerilogSourceFile(path, fileSet=fileset)
+
+ def _ParseXCIFile(self, _, path, fileset):
+ IPCoreInstantiationFile(path, fileSet=fileset)
+
+ def _ParseFileSetConfig(self, fileNode, fileset):
+ for option in fileNode.childNodes:
+ if option.nodeType == Node.ELEMENT_NODE and option.tagName == "Option":
+ if option.getAttribute("Name") == "TopModule":
+ fileset.TopLevel = option.getAttribute("Val")
+
+
+@export
+class XDCConstraintFile(ConstraintFile, SDCContent):
+ """A Vivado constraint file (Xilinx Design Constraints; ``*.xdc``)."""
+
+
+@export
+class IPCoreDescriptionFile(XMLFile):
+ pass
+
+
+@export
+class IPCoreInstantiationFile(XMLFile):
+ """A Vivado IP core instantiation file (Xilinx IPCore Instance; ``*.xci``)."""
+
' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(SphinxHighlight.highlightSearchWords); +_ready(SphinxHighlight.initEscapeListener); diff --git a/coverage/coverage_html.js b/coverage/coverage_html.js new file mode 100644 index 00000000..59348828 --- /dev/null +++ b/coverage/coverage_html.js @@ -0,0 +1,624 @@ +// Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +// For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt + +// Coverage.py HTML report browser code. +/*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */ +/*global coverage: true, document, window, $ */ + +coverage = {}; + +// General helpers +function debounce(callback, wait) { + let timeoutId = null; + return function(...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + callback.apply(this, args); + }, wait); + }; +}; + +function checkVisible(element) { + const rect = element.getBoundingClientRect(); + const viewBottom = Math.max(document.documentElement.clientHeight, window.innerHeight); + const viewTop = 30; + return !(rect.bottom < viewTop || rect.top >= viewBottom); +} + +function on_click(sel, fn) { + const elt = document.querySelector(sel); + if (elt) { + elt.addEventListener("click", fn); + } +} + +// Helpers for table sorting +function getCellValue(row, column = 0) { + const cell = row.cells[column] // nosemgrep: eslint.detect-object-injection + if (cell.childElementCount == 1) { + const child = cell.firstElementChild + if (child instanceof HTMLTimeElement && child.dateTime) { + return child.dateTime + } else if (child instanceof HTMLDataElement && child.value) { + return child.value + } + } + return cell.innerText || cell.textContent; +} + +function rowComparator(rowA, rowB, column = 0) { + let valueA = getCellValue(rowA, column); + let valueB = getCellValue(rowB, column); + if (!isNaN(valueA) && !isNaN(valueB)) { + return valueA - valueB + } + return valueA.localeCompare(valueB, undefined, {numeric: true}); +} + +function sortColumn(th) { + // Get the current sorting direction of the selected header, + // clear state on other headers and then set the new sorting direction + const currentSortOrder = th.getAttribute("aria-sort"); + [...th.parentElement.cells].forEach(header => header.setAttribute("aria-sort", "none")); + if (currentSortOrder === "none") { + th.setAttribute("aria-sort", th.dataset.defaultSortOrder || "ascending"); + } else { + th.setAttribute("aria-sort", currentSortOrder === "ascending" ? "descending" : "ascending"); + } + + const column = [...th.parentElement.cells].indexOf(th) + + // Sort all rows and afterwards append them in order to move them in the DOM + Array.from(th.closest("table").querySelectorAll("tbody tr")) + .sort((rowA, rowB) => rowComparator(rowA, rowB, column) * (th.getAttribute("aria-sort") === "ascending" ? 1 : -1)) + .forEach(tr => tr.parentElement.appendChild(tr) ); +} + +// Find all the elements with data-shortcut attribute, and use them to assign a shortcut key. +coverage.assign_shortkeys = function () { + document.querySelectorAll("[data-shortcut]").forEach(element => { + document.addEventListener("keypress", event => { + if (event.target.tagName.toLowerCase() === "input") { + return; // ignore keypress from search filter + } + if (event.key === element.dataset.shortcut) { + element.click(); + } + }); + }); +}; + +// Create the events for the filter box. +coverage.wire_up_filter = function () { + // Cache elements. + const table = document.querySelector("table.index"); + const table_body_rows = table.querySelectorAll("tbody tr"); + const no_rows = document.getElementById("no_rows"); + + // Observe filter keyevents. + document.getElementById("filter").addEventListener("input", debounce(event => { + // Keep running total of each metric, first index contains number of shown rows + const totals = new Array(table.rows[0].cells.length).fill(0); + // Accumulate the percentage as fraction + totals[totals.length - 1] = { "numer": 0, "denom": 0 }; // nosemgrep: eslint.detect-object-injection + + // Hide / show elements. + table_body_rows.forEach(row => { + if (!row.cells[0].textContent.includes(event.target.value)) { + // hide + row.classList.add("hidden"); + return; + } + + // show + row.classList.remove("hidden"); + totals[0]++; + + for (let column = 1; column < totals.length; column++) { + // Accumulate dynamic totals + cell = row.cells[column] // nosemgrep: eslint.detect-object-injection + if (column === totals.length - 1) { + // Last column contains percentage + const [numer, denom] = cell.dataset.ratio.split(" "); + totals[column]["numer"] += parseInt(numer, 10); // nosemgrep: eslint.detect-object-injection + totals[column]["denom"] += parseInt(denom, 10); // nosemgrep: eslint.detect-object-injection + } else { + totals[column] += parseInt(cell.textContent, 10); // nosemgrep: eslint.detect-object-injection + } + } + }); + + // Show placeholder if no rows will be displayed. + if (!totals[0]) { + // Show placeholder, hide table. + no_rows.style.display = "block"; + table.style.display = "none"; + return; + } + + // Hide placeholder, show table. + no_rows.style.display = null; + table.style.display = null; + + const footer = table.tFoot.rows[0]; + // Calculate new dynamic sum values based on visible rows. + for (let column = 1; column < totals.length; column++) { + // Get footer cell element. + const cell = footer.cells[column]; // nosemgrep: eslint.detect-object-injection + + // Set value into dynamic footer cell element. + if (column === totals.length - 1) { + // Percentage column uses the numerator and denominator, + // and adapts to the number of decimal places. + const match = /\.([0-9]+)/.exec(cell.textContent); + const places = match ? match[1].length : 0; + const { numer, denom } = totals[column]; // nosemgrep: eslint.detect-object-injection + cell.dataset.ratio = `${numer} ${denom}`; + // Check denom to prevent NaN if filtered files contain no statements + cell.textContent = denom + ? `${(numer * 100 / denom).toFixed(places)}%` + : `${(100).toFixed(places)}%`; + } else { + cell.textContent = totals[column]; // nosemgrep: eslint.detect-object-injection + } + } + })); + + // Trigger change event on setup, to force filter on page refresh + // (filter value may still be present). + document.getElementById("filter").dispatchEvent(new Event("input")); +}; + +coverage.INDEX_SORT_STORAGE = "COVERAGE_INDEX_SORT_2"; + +// Loaded on index.html +coverage.index_ready = function () { + coverage.assign_shortkeys(); + coverage.wire_up_filter(); + document.querySelectorAll("[data-sortable] th[aria-sort]").forEach( + th => th.addEventListener("click", e => sortColumn(e.target)) + ); + + // Look for a localStorage item containing previous sort settings: + const stored_list = localStorage.getItem(coverage.INDEX_SORT_STORAGE); + + if (stored_list) { + const {column, direction} = JSON.parse(stored_list); + const th = document.querySelector("[data-sortable]").tHead.rows[0].cells[column]; // nosemgrep: eslint.detect-object-injection + th.setAttribute("aria-sort", direction === "ascending" ? "descending" : "ascending"); + th.click() + } + + // Watch for page unload events so we can save the final sort settings: + window.addEventListener("unload", function () { + const th = document.querySelector('[data-sortable] th[aria-sort="ascending"], [data-sortable] [aria-sort="descending"]'); + if (!th) { + return; + } + localStorage.setItem(coverage.INDEX_SORT_STORAGE, JSON.stringify({ + column: [...th.parentElement.cells].indexOf(th), + direction: th.getAttribute("aria-sort"), + })); + }); + + on_click(".button_prev_file", coverage.to_prev_file); + on_click(".button_next_file", coverage.to_next_file); + + on_click(".button_show_hide_help", coverage.show_hide_help); +}; + +// -- pyfile stuff -- + +coverage.LINE_FILTERS_STORAGE = "COVERAGE_LINE_FILTERS"; + +coverage.pyfile_ready = function () { + // If we're directed to a particular line number, highlight the line. + var frag = location.hash; + if (frag.length > 2 && frag[1] === "t") { + document.querySelector(frag).closest(".n").classList.add("highlight"); + coverage.set_sel(parseInt(frag.substr(2), 10)); + } else { + coverage.set_sel(0); + } + + on_click(".button_toggle_run", coverage.toggle_lines); + on_click(".button_toggle_mis", coverage.toggle_lines); + on_click(".button_toggle_exc", coverage.toggle_lines); + on_click(".button_toggle_par", coverage.toggle_lines); + + on_click(".button_next_chunk", coverage.to_next_chunk_nicely); + on_click(".button_prev_chunk", coverage.to_prev_chunk_nicely); + on_click(".button_top_of_page", coverage.to_top); + on_click(".button_first_chunk", coverage.to_first_chunk); + + on_click(".button_prev_file", coverage.to_prev_file); + on_click(".button_next_file", coverage.to_next_file); + on_click(".button_to_index", coverage.to_index); + + on_click(".button_show_hide_help", coverage.show_hide_help); + + coverage.filters = undefined; + try { + coverage.filters = localStorage.getItem(coverage.LINE_FILTERS_STORAGE); + } catch(err) {} + + if (coverage.filters) { + coverage.filters = JSON.parse(coverage.filters); + } + else { + coverage.filters = {run: false, exc: true, mis: true, par: true}; + } + + for (cls in coverage.filters) { + coverage.set_line_visibilty(cls, coverage.filters[cls]); // nosemgrep: eslint.detect-object-injection + } + + coverage.assign_shortkeys(); + coverage.init_scroll_markers(); + coverage.wire_up_sticky_header(); + + document.querySelectorAll("[id^=ctxs]").forEach( + cbox => cbox.addEventListener("click", coverage.expand_contexts) + ); + + // Rebuild scroll markers when the window height changes. + window.addEventListener("resize", coverage.build_scroll_markers); +}; + +coverage.toggle_lines = function (event) { + const btn = event.target.closest("button"); + const category = btn.value + const show = !btn.classList.contains("show_" + category); + coverage.set_line_visibilty(category, show); + coverage.build_scroll_markers(); + coverage.filters[category] = show; + try { + localStorage.setItem(coverage.LINE_FILTERS_STORAGE, JSON.stringify(coverage.filters)); + } catch(err) {} +}; + +coverage.set_line_visibilty = function (category, should_show) { + const cls = "show_" + category; + const btn = document.querySelector(".button_toggle_" + category); + if (btn) { + if (should_show) { + document.querySelectorAll("#source ." + category).forEach(e => e.classList.add(cls)); + btn.classList.add(cls); + } + else { + document.querySelectorAll("#source ." + category).forEach(e => e.classList.remove(cls)); + btn.classList.remove(cls); + } + } +}; + +// Return the nth line div. +coverage.line_elt = function (n) { + return document.getElementById("t" + n)?.closest("p"); +}; + +// Set the selection. b and e are line numbers. +coverage.set_sel = function (b, e) { + // The first line selected. + coverage.sel_begin = b; + // The next line not selected. + coverage.sel_end = (e === undefined) ? b+1 : e; +}; + +coverage.to_top = function () { + coverage.set_sel(0, 1); + coverage.scroll_window(0); +}; + +coverage.to_first_chunk = function () { + coverage.set_sel(0, 1); + coverage.to_next_chunk(); +}; + +coverage.to_prev_file = function () { + window.location = document.getElementById("prevFileLink").href; +} + +coverage.to_next_file = function () { + window.location = document.getElementById("nextFileLink").href; +} + +coverage.to_index = function () { + location.href = document.getElementById("indexLink").href; +} + +coverage.show_hide_help = function () { + const helpCheck = document.getElementById("help_panel_state") + helpCheck.checked = !helpCheck.checked; +} + +// Return a string indicating what kind of chunk this line belongs to, +// or null if not a chunk. +coverage.chunk_indicator = function (line_elt) { + const classes = line_elt?.className; + if (!classes) { + return null; + } + const match = classes.match(/\bshow_\w+\b/); + if (!match) { + return null; + } + return match[0]; +}; + +coverage.to_next_chunk = function () { + const c = coverage; + + // Find the start of the next colored chunk. + var probe = c.sel_end; + var chunk_indicator, probe_line; + while (true) { + probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + chunk_indicator = c.chunk_indicator(probe_line); + if (chunk_indicator) { + break; + } + probe++; + } + + // There's a next chunk, `probe` points to it. + var begin = probe; + + // Find the end of this chunk. + var next_indicator = chunk_indicator; + while (next_indicator === chunk_indicator) { + probe++; + probe_line = c.line_elt(probe); + next_indicator = c.chunk_indicator(probe_line); + } + c.set_sel(begin, probe); + c.show_selection(); +}; + +coverage.to_prev_chunk = function () { + const c = coverage; + + // Find the end of the prev colored chunk. + var probe = c.sel_begin-1; + var probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + var chunk_indicator = c.chunk_indicator(probe_line); + while (probe > 1 && !chunk_indicator) { + probe--; + probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + chunk_indicator = c.chunk_indicator(probe_line); + } + + // There's a prev chunk, `probe` points to its last line. + var end = probe+1; + + // Find the beginning of this chunk. + var prev_indicator = chunk_indicator; + while (prev_indicator === chunk_indicator) { + probe--; + if (probe <= 0) { + return; + } + probe_line = c.line_elt(probe); + prev_indicator = c.chunk_indicator(probe_line); + } + c.set_sel(probe+1, end); + c.show_selection(); +}; + +// Returns 0, 1, or 2: how many of the two ends of the selection are on +// the screen right now? +coverage.selection_ends_on_screen = function () { + if (coverage.sel_begin === 0) { + return 0; + } + + const begin = coverage.line_elt(coverage.sel_begin); + const end = coverage.line_elt(coverage.sel_end-1); + + return ( + (checkVisible(begin) ? 1 : 0) + + (checkVisible(end) ? 1 : 0) + ); +}; + +coverage.to_next_chunk_nicely = function () { + if (coverage.selection_ends_on_screen() === 0) { + // The selection is entirely off the screen: + // Set the top line on the screen as selection. + + // This will select the top-left of the viewport + // As this is most likely the span with the line number we take the parent + const line = document.elementFromPoint(0, 0).parentElement; + if (line.parentElement !== document.getElementById("source")) { + // The element is not a source line but the header or similar + coverage.select_line_or_chunk(1); + } else { + // We extract the line number from the id + coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10)); + } + } + coverage.to_next_chunk(); +}; + +coverage.to_prev_chunk_nicely = function () { + if (coverage.selection_ends_on_screen() === 0) { + // The selection is entirely off the screen: + // Set the lowest line on the screen as selection. + + // This will select the bottom-left of the viewport + // As this is most likely the span with the line number we take the parent + const line = document.elementFromPoint(document.documentElement.clientHeight-1, 0).parentElement; + if (line.parentElement !== document.getElementById("source")) { + // The element is not a source line but the header or similar + coverage.select_line_or_chunk(coverage.lines_len); + } else { + // We extract the line number from the id + coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10)); + } + } + coverage.to_prev_chunk(); +}; + +// Select line number lineno, or if it is in a colored chunk, select the +// entire chunk +coverage.select_line_or_chunk = function (lineno) { + var c = coverage; + var probe_line = c.line_elt(lineno); + if (!probe_line) { + return; + } + var the_indicator = c.chunk_indicator(probe_line); + if (the_indicator) { + // The line is in a highlighted chunk. + // Search backward for the first line. + var probe = lineno; + var indicator = the_indicator; + while (probe > 0 && indicator === the_indicator) { + probe--; + probe_line = c.line_elt(probe); + if (!probe_line) { + break; + } + indicator = c.chunk_indicator(probe_line); + } + var begin = probe + 1; + + // Search forward for the last line. + probe = lineno; + indicator = the_indicator; + while (indicator === the_indicator) { + probe++; + probe_line = c.line_elt(probe); + indicator = c.chunk_indicator(probe_line); + } + + coverage.set_sel(begin, probe); + } + else { + coverage.set_sel(lineno); + } +}; + +coverage.show_selection = function () { + // Highlight the lines in the chunk + document.querySelectorAll("#source .highlight").forEach(e => e.classList.remove("highlight")); + for (let probe = coverage.sel_begin; probe < coverage.sel_end; probe++) { + coverage.line_elt(probe).querySelector(".n").classList.add("highlight"); + } + + coverage.scroll_to_selection(); +}; + +coverage.scroll_to_selection = function () { + // Scroll the page if the chunk isn't fully visible. + if (coverage.selection_ends_on_screen() < 2) { + const element = coverage.line_elt(coverage.sel_begin); + coverage.scroll_window(element.offsetTop - 60); + } +}; + +coverage.scroll_window = function (to_pos) { + window.scroll({top: to_pos, behavior: "smooth"}); +}; + +coverage.init_scroll_markers = function () { + // Init some variables + coverage.lines_len = document.querySelectorAll("#source > p").length; + + // Build html + coverage.build_scroll_markers(); +}; + +coverage.build_scroll_markers = function () { + const temp_scroll_marker = document.getElementById("scroll_marker") + if (temp_scroll_marker) temp_scroll_marker.remove(); + // Don't build markers if the window has no scroll bar. + if (document.body.scrollHeight <= window.innerHeight) { + return; + } + + const marker_scale = window.innerHeight / document.body.scrollHeight; + const line_height = Math.min(Math.max(3, window.innerHeight / coverage.lines_len), 10); + + let previous_line = -99, last_mark, last_top; + + const scroll_marker = document.createElement("div"); + scroll_marker.id = "scroll_marker"; + document.getElementById("source").querySelectorAll( + "p.show_run, p.show_mis, p.show_exc, p.show_exc, p.show_par" + ).forEach(element => { + const line_top = Math.floor(element.offsetTop * marker_scale); + const line_number = parseInt(element.querySelector(".n a").id.substr(1)); + + if (line_number === previous_line + 1) { + // If this solid missed block just make previous mark higher. + last_mark.style.height = `${line_top + line_height - last_top}px`; + } else { + // Add colored line in scroll_marker block. + last_mark = document.createElement("div"); + last_mark.id = `m${line_number}`; + last_mark.classList.add("marker"); + last_mark.style.height = `${line_height}px`; + last_mark.style.top = `${line_top}px`; + scroll_marker.append(last_mark); + last_top = line_top; + } + + previous_line = line_number; + }); + + // Append last to prevent layout calculation + document.body.append(scroll_marker); +}; + +coverage.wire_up_sticky_header = function () { + const header = document.querySelector("header"); + const header_bottom = ( + header.querySelector(".content h2").getBoundingClientRect().top - + header.getBoundingClientRect().top + ); + + function updateHeader() { + if (window.scrollY > header_bottom) { + header.classList.add("sticky"); + } else { + header.classList.remove("sticky"); + } + } + + window.addEventListener("scroll", updateHeader); + updateHeader(); +}; + +coverage.expand_contexts = function (e) { + var ctxs = e.target.parentNode.querySelector(".ctxs"); + + if (!ctxs.classList.contains("expanded")) { + var ctxs_text = ctxs.textContent; + var width = Number(ctxs_text[0]); + ctxs.textContent = ""; + for (var i = 1; i < ctxs_text.length; i += width) { + key = ctxs_text.substring(i, i + width).trim(); + ctxs.appendChild(document.createTextNode(contexts[key])); + ctxs.appendChild(document.createElement("br")); + } + ctxs.classList.add("expanded"); + } +}; + +document.addEventListener("DOMContentLoaded", () => { + if (document.body.classList.contains("indexfile")) { + coverage.index_ready(); + } else { + coverage.pyfile_ready(); + } +}); diff --git a/coverage/d_bb657af29d23493a_Attributes_py.html b/coverage/d_bb657af29d23493a_Attributes_py.html new file mode 100644 index 00000000..7234a794 --- /dev/null +++ b/coverage/d_bb657af29d23493a_Attributes_py.html @@ -0,0 +1,152 @@ + + + + ++ « prev + ^ index + » next + + coverage.py v7.3.0, + created at 2023-08-13 23:53 +0000 +
+ +1# ==================================================================================================================== #
+2# _____ ____ _ _ ____ _ _ __ __ _ _ #
+3# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | #
+4# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | #
+5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | #
+6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| #
+7# |_| |___/ |__/ #
+8# ==================================================================================================================== #
+9# Authors: #
+10# Patrick Lehmann #
+11# #
+12# License: #
+13# ==================================================================================================================== #
+14# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
+15# #
+16# Licensed under the Apache License, Version 2.0 (the "License"); #
+17# you may not use this file except in compliance with the License. #
+18# You may obtain a copy of the License at #
+19# #
+20# http://www.apache.org/licenses/LICENSE-2.0 #
+21# #
+22# Unless required by applicable law or agreed to in writing, software #
+23# distributed under the License is distributed on an "AS IS" BASIS, #
+24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+25# See the License for the specific language governing permissions and #
+26# limitations under the License. #
+27# #
+28# SPDX-License-Identifier: Apache-2.0 #
+29# ==================================================================================================================== #
+30#
+31"""A set of common attributes to store meta information on ProjectModel entities (project, design, fileset, file, ...)."""
+32from typing import Dict
+33from pyTooling.Decorators import export
+ +35from pyEDAA.ProjectModel import Attribute
+ + +38@export
+39class KeyValueAttribute(Attribute):
+40 KEY = "ID"
+ +42 _keyValuePairs: Dict[str, str]
+ +44 def __init__(self):
+45 super().__init__()
+ +47 self._keyValuePairs = {}
+ +49 def __getitem__(self, item: str) -> str:
+50 return self._keyValuePairs[item]
+ +52 def __setitem__(self, key: str, value: str) -> None:
+53 self._keyValuePairs[key] = value
++ « prev + ^ index + » next + + coverage.py v7.3.0, + created at 2023-08-13 23:53 +0000 +
+ +1# ==================================================================================================================== #
+2# _____ ____ _ _ ____ _ _ __ __ _ _ #
+3# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | #
+4# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | #
+5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | #
+6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| #
+7# |_| |___/ |__/ #
+8# ==================================================================================================================== #
+9# Authors: #
+10# Patrick Lehmann #
+11# #
+12# License: #
+13# ==================================================================================================================== #
+14# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
+15# Copyright 2014-2016 Technische Universität Dresden - Germany, Chair of VLSI-Design, Diagnostics and Architecture #
+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"""An abstract model of EDA tool projects."""
+33__author__ = "Patrick Lehmann"
+34__email__ = "Paebbels@gmail.com"
+35__copyright__ = "2014-2023, Patrick Lehmann, Unai Martinez-Corral"
+36__license__ = "Apache License, Version 2.0"
+37__version__ = "0.5.0"
+38__keywords__ = ["eda project", "model", "abstract", "xilinx", "vivado", "osvvm", "file set", "file group", "test bench", "test harness"]
+ +40from os.path import relpath as path_relpath
+41from pathlib import Path as pathlib_Path
+42from typing import Dict, Union, Optional as Nullable, List, Iterable, Generator, Tuple, Any as typing_Any, Type, Set, \
+43 Any
+ +45from pyTooling.Decorators import export
+46from pyTooling.MetaClasses import ExtendedType
+47from pyTooling.Graph import Graph, Vertex
+48from pySVModel import SystemVerilogVersion
+49from pyVHDLModel import VHDLVersion
+50from pySystemRDLModel import SystemRDLVersion
+ + +53@export
+54class Attribute(metaclass=ExtendedType):
+55 KEY: str
+56 VALUE_TYPE: typing_Any
+ +58 @staticmethod
+59 def resolve(obj: typing_Any, key: Type['Attribute']):
+60 if isinstance(obj, File): 60 ↛ 62line 60 didn't jump to line 62, because the condition on line 60 was never false
+61 return obj._fileSet[key]
+62 elif isinstance(obj, FileSet):
+63 return obj._design[key]
+64 elif isinstance(obj, Design):
+65 return obj._project[key]
+66 else:
+67 raise Exception("Resolution error")
+ + +70@export
+71class FileType(ExtendedType):
+72 """
+73 A :term:`meta-class` to construct *FileType* classes.
+ +75 Modifications done by this meta-class:
+76 * Register all classes of type :class:`FileType` or derived variants in a class field :attr:`FileType.FileTypes` in this meta-class.
+77 """
+ +79 FileTypes: Dict[str, 'FileType'] = {} #: Dictionary of all classes of type :class:`FileType` or derived variants
+80 Any: 'FileType'
+ +82 def __init__(cls, name: str, bases: Tuple[type, ...], dictionary: Dict[str, typing_Any], **kwargs):
+83 super().__init__(name, bases, dictionary, **kwargs)
+84 cls.Any = cls
+ +86 def __new__(cls, className, baseClasses, classMembers: Dict, *args, **kwargs):
+87 fileType = super().__new__(cls, className, baseClasses, classMembers, *args, **kwargs)
+88 cls.FileTypes[className] = fileType
+89 return fileType
+ +91 def __getattr__(cls, item) -> 'FileType':
+92 if item[:2] != "__" and item[-2:] != "__":
+93 return cls.FileTypes[item]
+94 else:
+95 return super().__getattribute__(item)
+ +97 def __contains__(cls, item) -> bool:
+98 return issubclass(item, cls)
+ + +101@export
+102class File(metaclass=FileType, slots=True):
+103 """
+104 A :term:`File` represents a file in a design. This :term:`base-class` is used
+105 for all derived file classes.
+ +107 A file can be created standalone and later associated to a fileset, design and
+108 project. Or a fileset, design and/or project can be associated immediately
+109 while creating a file.
+ +111 :arg path: Relative or absolute path to the file.
+112 :arg project: Project the file is associated with.
+113 :arg design: Design the file is associated with.
+114 :arg fileSet: Fileset the file is associated with.
+115 """
+ +117 _path: pathlib_Path
+118 _fileType: 'FileType'
+119 _project: Nullable['Project']
+120 _design: Nullable['Design']
+121 _fileSet: Nullable['FileSet']
+122 _attributes: Dict[Type[Attribute], typing_Any]
+ +124 def __init__(
+125 self,
+126 path: pathlib_Path,
+127 project: 'Project' = None,
+128 design: 'Design' = None,
+129 fileSet: 'FileSet' = None
+130 ):
+131 self._fileType = getattr(FileTypes, self.__class__.__name__)
+132 self._path = path
+133 if project is not None:
+134 self._project = project
+135 self._design = design
+136 if fileSet is not None: 136 ↛ 137line 136 didn't jump to line 137, because the condition on line 136 was never true
+137 self.FileSet = fileSet
+138 elif design is not None:
+139 self._project = design._project
+140 self._design = design
+141 self.FileSet = design.DefaultFileSet if fileSet is None else fileSet
+142 elif fileSet is not None:
+143 design = fileSet._design
+144 if design is not None:
+145 self._project = design._project
+146 else:
+147 self._project = None
+148 self._design = design
+149 self.FileSet = fileSet
+150 else:
+151 self._project = None
+152 self._design = None
+153 self._fileSet = None
+ +155 self._attributes = {}
+156 self._registerAttributes()
+ +158 def _registerAttributes(self):
+159 pass
+ +161 @property
+162 def FileType(self) -> 'FileType':
+163 """Read-only property to return the file type of this file."""
+164 return self._fileType
+ +166 @property
+167 def Path(self) -> pathlib_Path:
+168 """Read-only property returning the path of this file."""
+169 return self._path
+ +171 # TODO: setter?
+ +173 @property
+174 def ResolvedPath(self) -> pathlib_Path:
+175 """Read-only property returning the resolved path of this file."""
+176 if self._path.is_absolute(): 176 ↛ 177line 176 didn't jump to line 177, because the condition on line 176 was never true
+177 return self._path.resolve()
+178 elif self._fileSet is not None: 178 ↛ 188line 178 didn't jump to line 188, because the condition on line 178 was never false
+179 path = (self._fileSet.ResolvedPath / self._path).resolve()
+ +181 if path.is_absolute(): 181 ↛ 185line 181 didn't jump to line 185, because the condition on line 181 was never false
+182 return path
+183 else:
+184 # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+185 return pathlib_Path(path_relpath(path, pathlib_Path.cwd()))
+186 else:
+187 # TODO: message and exception type
+188 raise Exception("")
+ +190 @property
+191 def Project(self) -> Nullable['Project']:
+192 """Property setting or returning the project this file is used in."""
+193 return self._project
+ +195 @Project.setter
+196 def Project(self, value: 'Project') -> None:
+197 self._project = value
+ +199 if self._fileSet is None: 199 ↛ exitline 199 didn't return from function 'Project', because the condition on line 199 was never false
+200 self._project.DefaultDesign.DefaultFileSet.AddFile(self)
+ +202 @property
+203 def Design(self) -> Nullable['Design']:
+204 """Property setting or returning the design this file is used in."""
+205 return self._design
+ +207 @Design.setter
+208 def Design(self, value: 'Design') -> None:
+209 self._design = value
+ +211 if self._fileSet is None: 211 ↛ 214line 211 didn't jump to line 214, because the condition on line 211 was never false
+212 self._design.DefaultFileSet.AddFile(self)
+ +214 if self._project is None: 214 ↛ 216line 214 didn't jump to line 216, because the condition on line 214 was never false
+215 self._project = value._project
+216 elif self._project is not value._project:
+217 raise Exception("The design's project is not identical to the already assigned project.")
+ +219 @property
+220 def FileSet(self) -> Nullable['FileSet']:
+221 """Property setting or returning the fileset this file is used in."""
+222 return self._fileSet
+ +224 @FileSet.setter
+225 def FileSet(self, value: 'FileSet') -> None:
+226 self._fileSet = value
+227 value._files.append(self)
+ +229 def Validate(self):
+230 """Validate this file."""
+231 if self._path is None: 231 ↛ 232line 231 didn't jump to line 232, because the condition on line 231 was never true
+232 raise Exception("Validation: File has no path.")
+233 try:
+234 path = self.ResolvedPath
+235 except Exception as ex:
+236 raise Exception(f"Validation: File '{self._path}' could not compute resolved path.") from ex
+237 if not path.exists(): 237 ↛ 238line 237 didn't jump to line 238, because the condition on line 237 was never true
+238 raise Exception(f"Validation: File '{self._path}' (={path}) does not exist.")
+239 if not path.is_file(): 239 ↛ 240line 239 didn't jump to line 240, because the condition on line 239 was never true
+240 raise Exception(f"Validation: File '{self._path}' (={path}) is not a file.")
+ +242 if self._fileSet is None: 242 ↛ 243line 242 didn't jump to line 243, because the condition on line 242 was never true
+243 raise Exception(f"Validation: File '{self._path}' has no fileset.")
+244 if self._design is None: 244 ↛ 245line 244 didn't jump to line 245, because the condition on line 244 was never true
+245 raise Exception(f"Validation: File '{self._path}' has no design.")
+246 if self._project is None: 246 ↛ 247line 246 didn't jump to line 247, because the condition on line 246 was never true
+247 raise Exception(f"Validation: File '{self._path}' has no project.")
+ +249 def __len__(self) -> int:
+250 return len(self._attributes)
+ +252 def __getitem__(self, key: Type[Attribute]) -> Any:
+253 """Index access for returning attributes on this file."""
+254 if not issubclass(key, Attribute): 254 ↛ 255line 254 didn't jump to line 255, because the condition on line 254 was never true
+255 raise TypeError("Parameter 'key' is not an 'Attribute'.")
+ +257 try:
+258 return self._attributes[key]
+259 except KeyError:
+260 return key.resolve(self, key)
+ +262 def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+263 """Index access for setting attributes on this file."""
+264 if not issubclass(key, Attribute): 264 ↛ 265line 264 didn't jump to line 265, because the condition on line 264 was never true
+265 raise TypeError("Parameter 'key' is not an 'Attribute'.")
+ +267 self._attributes[key] = value
+ + +270FileTypes = File
+ + +273@export
+274class HumanReadableContent(metaclass=ExtendedType, mixin=True):
+275 """A file type representing human-readable contents."""
+ + +278@export
+279class XMLContent(HumanReadableContent, mixin=True):
+280 """A file type representing XML contents."""
+ + +283@export
+284class YAMLContent(HumanReadableContent, mixin=True):
+285 """A file type representing YAML contents."""
+ + +288@export
+289class JSONContent(HumanReadableContent, mixin=True):
+290 """A file type representing JSON contents."""
+ + +293@export
+294class INIContent(HumanReadableContent, mixin=True):
+295 """A file type representing INI contents."""
+ + +298@export
+299class TOMLContent(HumanReadableContent, mixin=True):
+300 """A file type representing TOML contents."""
+ + +303@export
+304class TCLContent(HumanReadableContent, mixin=True):
+305 """A file type representing content in TCL code."""
+ + +308@export
+309class SDCContent(TCLContent, mixin=True):
+310 """A file type representing contents as Synopsys Design Constraints (SDC)."""
+ + +313@export
+314class PythonContent(HumanReadableContent, mixin=True):
+315 """A file type representing contents as Python source code."""
+ + +318@export
+319class TextFile(File, HumanReadableContent):
+320 """A text file (``*.txt``)."""
+ + +323@export
+324class LogFile(File, HumanReadableContent):
+325 """A log file (``*.log``)."""
+ + +328@export
+329class XMLFile(File, XMLContent):
+330 """An XML file (``*.xml``)."""
+ + +333@export
+334class SourceFile(File):
+335 """Base-class of all source files."""
+ + +338@export
+339class HDLSourceFile(SourceFile):
+340 """Base-class of all HDL source files."""
+ + +343@export
+344class RDLSourceFile(SourceFile):
+345 """Base-class of all RDL source files."""
+ + +348@export
+349class NetlistFile(SourceFile):
+350 """Base-class of all netlist source files."""
+ + +353@export
+354class EDIFNetlistFile(NetlistFile):
+355 """Netlist file in EDIF (Electronic Design Interchange Format)."""
+ + +358@export
+359class TCLSourceFile(SourceFile, TCLContent):
+360 """A TCL source file."""
+ + +363@export
+364class VHDLSourceFile(HDLSourceFile, HumanReadableContent):
+365 """
+366 A VHDL source file (of any language version).
+ +368 :arg path: Relative or absolute path to the file.
+369 :arg vhdlLibrary: VHDLLibrary this VHDL source file is associated wih.
+370 :arg vhdlVersion: VHDLVersion this VHDL source file is associated wih.
+371 :arg project: Project the file is associated with.
+372 :arg design: Design the file is associated with.
+373 :arg fileSet: Fileset the file is associated with.
+374 """
+ +376 _vhdlLibrary: 'VHDLLibrary'
+377 _vhdlVersion: VHDLVersion
+ +379 def __init__(self, path: pathlib_Path, vhdlLibrary: Union[str, 'VHDLLibrary'] = None, vhdlVersion: VHDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None):
+380 super().__init__(path, project, design, fileSet)
+ +382 if isinstance(vhdlLibrary, str): 382 ↛ 383line 382 didn't jump to line 383, because the condition on line 382 was never true
+383 if design is not None:
+384 try:
+385 vhdlLibrary = design.VHDLLibraries[vhdlLibrary]
+386 except KeyError as ex:
+387 raise Exception(f"VHDL library '{vhdlLibrary}' not found in design '{design.Name}'.") from ex
+388 elif project is not None:
+389 try:
+390 vhdlLibrary = project.DefaultDesign.VHDLLibraries[vhdlLibrary]
+391 except KeyError as ex:
+392 raise Exception(f"VHDL library '{vhdlLibrary}' not found in default design '{project.DefaultDesign.Name}'.") from ex
+393 else:
+394 raise Exception(f"Can't lookup VHDL library because neither 'project' nor 'design' is given as a parameter.")
+395 elif isinstance(vhdlLibrary, VHDLLibrary):
+396 self._vhdlLibrary = vhdlLibrary
+397 vhdlLibrary.AddFile(self)
+398 elif vhdlLibrary is None: 398 ↛ 401line 398 didn't jump to line 401, because the condition on line 398 was never false
+399 self._vhdlLibrary = None
+400 else:
+401 raise TypeError(f"Parameter 'vhdlLibrary' is neither a 'str' nor 'VHDLibrary'.")
+ +403 self._vhdlVersion = vhdlVersion
+ +405 def Validate(self) -> None:
+406 """Validate this VHDL source file."""
+407 super().Validate()
+ +409 try:
+410 _ = self.VHDLLibrary
+411 except Exception as ex:
+412 raise Exception(f"Validation: VHDLSourceFile '{self._path}' (={self.ResolvedPath}) has no VHDLLibrary assigned.") from ex
+413 try:
+414 _ = self.VHDLVersion
+415 except Exception as ex:
+416 raise Exception(f"Validation: VHDLSourceFile '{self._path}' (={self.ResolvedPath}) has no VHDLVersion assigned.") from ex
+ +418 @property
+419 def VHDLLibrary(self) -> 'VHDLLibrary':
+420 """Property setting or returning the VHDL library this VHDL source file is used in."""
+421 if self._vhdlLibrary is not None:
+422 return self._vhdlLibrary
+423 elif self._fileSet is not None:
+424 return self._fileSet.VHDLLibrary
+425 else:
+426 raise Exception("VHDLLibrary was neither set locally nor globally.")
+ +428 @VHDLLibrary.setter
+429 def VHDLLibrary(self, value: 'VHDLLibrary') -> None:
+430 self._vhdlLibrary = value
+431 value._files.append(self)
+ +433 @property
+434 def VHDLVersion(self) -> VHDLVersion:
+435 """Property setting or returning the VHDL version this VHDL source file is used in."""
+436 if self._vhdlVersion is not None:
+437 return self._vhdlVersion
+438 elif self._fileSet is not None:
+439 return self._fileSet.VHDLVersion
+440 else:
+441 raise Exception("VHDLVersion was neither set locally nor globally.")
+ +443 @VHDLVersion.setter
+444 def VHDLVersion(self, value: VHDLVersion) -> None:
+445 self._vhdlVersion = value
+ +447 def __repr__(self) -> str:
+448 return f"<VHDL file: '{self.ResolvedPath}'; lib: '{self.VHDLLibrary}'; version: {self.VHDLVersion}>"
+ + +451class VerilogMixIn(metaclass=ExtendedType, mixin=True):
+452 @property
+453 def VerilogVersion(self) -> SystemVerilogVersion:
+454 """Property setting or returning the Verilog version this Verilog source file is used in."""
+455 if self._version is not None:
+456 return self._version
+457 elif self._fileSet is not None:
+458 return self._fileSet.VerilogVersion
+459 else:
+460 raise Exception("VerilogVersion was neither set locally nor globally.")
+ +462 @VerilogVersion.setter
+463 def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+464 self._version = value
+ + +467class SystemVerilogMixIn(metaclass=ExtendedType, mixin=True):
+468 @property
+469 def SVVersion(self) -> SystemVerilogVersion:
+470 """Property setting or returning the SystemVerilog version this SystemVerilog source file is used in."""
+471 if self._version is not None:
+472 return self._version
+473 elif self._fileSet is not None:
+474 return self._fileSet.SVVersion
+475 else:
+476 raise Exception("SVVersion was neither set locally nor globally.")
+ +478 @SVVersion.setter
+479 def SVVersion(self, value: SystemVerilogVersion) -> None:
+480 self._version = value
+ + +483@export
+484class VerilogBaseFile(HDLSourceFile, HumanReadableContent):
+485 _version: SystemVerilogVersion
+ +487 def __init__(self, path: pathlib_Path, version: SystemVerilogVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None):
+488 super().__init__(path, project, design, fileSet)
+ +490 self._version = version
+ + +493@export
+494class VerilogSourceFile(VerilogBaseFile, VerilogMixIn):
+495 """A Verilog source file (of any language version)."""
+ + +498@export
+499class VerilogHeaderFile(VerilogBaseFile, VerilogMixIn):
+500 """A Verilog header file (of any language version)."""
+ + +503@export
+504class SystemVerilogBaseFile(VerilogBaseFile):
+505 ...
+ + +508@export
+509class SystemVerilogSourceFile(SystemVerilogBaseFile, SystemVerilogMixIn):
+510 """A SystemVerilog source file (of any language version)."""
+ + +513@export
+514class SystemVerilogHeaderFile(SystemVerilogBaseFile, SystemVerilogMixIn):
+515 """A SystemVerilog header file (of any language version)."""
+ + +518@export
+519class SystemRDLSourceFile(RDLSourceFile, HumanReadableContent):
+520 """A SystemRDL source file (of any language version)."""
+ +522 _srdlVersion: SystemRDLVersion
+ +524 def __init__(self, path: pathlib_Path, srdlVersion: SystemRDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None):
+525 super().__init__(path, project, design, fileSet)
+ +527 self._srdlVersion = srdlVersion
+ +529 @property
+530 def SystemRDLVersion(self) -> SystemRDLVersion:
+531 """Property setting or returning the SystemRDL version this SystemRDL source file is used in."""
+532 if self._srdlVersion is not None:
+533 return self._srdlVersion
+534 elif self._fileSet is not None:
+535 return self._fileSet.SRDLVersion
+536 else:
+537 raise Exception("SRDLVersion was neither set locally nor globally.")
+ +539 @SystemRDLVersion.setter
+540 def SystemRDLVersion(self, value: SystemRDLVersion) -> None:
+541 self._srdlVersion = value
+ + +544@export
+545class PythonSourceFile(SourceFile, PythonContent):
+546 """A Python source file."""
+ + +549# TODO: move to a Cocotb module
+550@export
+551class CocotbPythonFile(PythonSourceFile):
+552 """A Python source file used by Cocotb."""
+ + +555@export
+556class ConstraintFile(File, HumanReadableContent):
+557 """Base-class of all constraint files."""
+ + +560@export
+561class ProjectFile(File):
+562 """Base-class of all tool-specific project files."""
+ + +565@export
+566class CSourceFile(SourceFile):
+567 """Base-class of all ANSI-C source files."""
+ + +570@export
+571class CppSourceFile(SourceFile):
+572 """Base-class of all ANSI-C++ source files."""
+ + +575@export
+576class SettingFile(File):
+577 """Base-class of all tool-specific setting files."""
+ + +580@export
+581class SimulationAnalysisFile(File):
+582 """Base-class of all tool-specific analysis files."""
+ + +585@export
+586class SimulationElaborationFile(File):
+587 """Base-class of all tool-specific elaboration files."""
+ + +590@export
+591class SimulationStartFile(File):
+592 """Base-class of all tool-specific simulation start-up files."""
+ + +595@export
+596class SimulationRunFile(File):
+597 """Base-class of all tool-specific simulation run (execution) files."""
+ + +600@export
+601class WaveformConfigFile(File):
+602 """Base-class of all tool-specific waveform configuration files."""
+ + +605@export
+606class WaveformDatabaseFile(File):
+607 """Base-class of all tool-specific waveform database files."""
+ + +610@export
+611class WaveformExchangeFile(File):
+612 """Base-class of all tool-independent waveform exchange files."""
+ + +615@export
+616class FileSet(metaclass=ExtendedType, slots=True):
+617 """
+618 A :term:`FileSet` represents a group of files. Filesets can have sub-filesets.
+ +620 The order of insertion is preserved. A fileset can be created standalone and
+621 later associated to another fileset, design and/or project. Or a fileset,
+622 design and/or project can be associated immediately while creating the
+623 fileset.
+ +625 :arg name: Name of this fileset.
+626 :arg topLevel: Name of the fileset's toplevel.
+627 :arg directory: Path of this fileset (absolute or relative to a parent fileset or design).
+628 :arg project: Project the file is associated with.
+629 :arg design: Design the file is associated with.
+630 :arg parent: Parent fileset if this fileset is nested.
+631 :arg vhdlLibrary: Default VHDL library for files in this fileset, if not specified for the file itself.
+632 :arg vhdlVersion: Default VHDL version for files in this fileset, if not specified for the file itself.
+633 :arg verilogVersion: Default Verilog version for files in this fileset, if not specified for the file itself.
+634 :arg svVersion: Default SystemVerilog version for files in this fileset, if not specified for the file itself.
+635 :arg srdlVersion: Default SystemRDL version for files in this fileset, if not specified for the file itself.
+636 """
+ +638 _name: str
+639 _topLevel: Nullable[str]
+640 _project: Nullable['Project']
+641 _design: Nullable['Design']
+642 _directory: pathlib_Path
+643 _parent: Nullable['FileSet']
+644 _fileSets: Dict[str, 'FileSet']
+645 _files: List[File]
+646 _set: Set
+647 _attributes: Dict[Type[Attribute], typing_Any]
+648 _vhdlLibraries: Dict[str, 'VHDLLibrary']
+649 _vhdlLibrary: 'VHDLLibrary'
+650 _vhdlVersion: VHDLVersion
+651 _verilogVersion: SystemVerilogVersion
+652 _svVersion: SystemVerilogVersion
+653 _srdlVersion: SystemRDLVersion
+ +655 def __init__(
+656 self,
+657 name: str,
+658 topLevel: str = None,
+659 directory: pathlib_Path = pathlib_Path("."),
+660 project: 'Project' = None,
+661 design: 'Design' = None,
+662 parent: Nullable['FileSet'] = None,
+663 vhdlLibrary: Union[str, 'VHDLLibrary'] = None,
+664 vhdlVersion: VHDLVersion = None,
+665 verilogVersion: SystemVerilogVersion = None,
+666 svVersion: SystemVerilogVersion = None,
+667 srdlVersion: SystemRDLVersion = None
+668 ):
+669 self._name = name
+670 self._topLevel = topLevel
+671 if project is not None:
+672 self._project = project
+673 self._design = design if design is not None else project.DefaultDesign
+ +675 elif design is not None:
+676 self._project = design._project
+677 self._design = design
+678 else:
+679 self._project = None
+680 self._design = None
+681 self._directory = directory
+682 self._parent = parent
+683 self._fileSets = {}
+684 self._files = []
+685 self._set = set()
+ +687 if design is not None:
+688 design._fileSets[name] = self
+ +690 self._attributes = {}
+691 self._vhdlLibraries = {}
+ +693 # TODO: handle if vhdlLibrary is a string
+694 self._vhdlLibrary = vhdlLibrary
+695 self._vhdlVersion = vhdlVersion
+696 self._verilogVersion = verilogVersion
+697 self._svVersion = svVersion
+698 self._srdlVersion = srdlVersion
+ +700 @property
+701 def Name(self) -> str:
+702 """Property setting or returning the fileset's name."""
+703 return self._name
+ +705 @Name.setter
+706 def Name(self, value: str) -> None:
+707 self._name = value
+ +709 @property
+710 def TopLevel(self) -> str:
+711 """Property setting or returning the fileset's toplevel."""
+712 return self._topLevel
+ +714 @TopLevel.setter
+715 def TopLevel(self, value: str) -> None:
+716 self._topLevel = value
+ +718 @property
+719 def Project(self) -> Nullable['Project']:
+720 """Property setting or returning the project this fileset is used in."""
+721 return self._project
+ +723 @Project.setter
+724 def Project(self, value: 'Project') -> None:
+725 self._project = value
+ +727 @property
+728 def Design(self) -> Nullable['Design']:
+729 """Property setting or returning the design this fileset is used in."""
+730 if self._design is not None:
+731 return self._design
+732 elif self._parent is not None: 732 ↛ 733line 732 didn't jump to line 733, because the condition on line 732 was never true
+733 return self._parent.Design
+734 else:
+735 return None
+736 # TODO: raise exception instead
+737 # QUESTION: how to handle if design and parent is set?
+ +739 @Design.setter
+740 def Design(self, value: 'Design') -> None:
+741 self._design = value
+742 if self._project is None: 742 ↛ 744line 742 didn't jump to line 744, because the condition on line 742 was never false
+743 self._project = value._project
+744 elif self._project is not value._project:
+745 raise Exception("The design's project is not identical to the already assigned project.")
+ +747 @property
+748 def Directory(self) -> pathlib_Path:
+749 """Property setting or returning the directory this fileset is located in."""
+750 return self._directory
+ +752 @Directory.setter
+753 def Directory(self, value: pathlib_Path) -> None:
+754 self._directory = value
+ +756 @property
+757 def ResolvedPath(self) -> pathlib_Path:
+758 """Read-only property returning the resolved path of this fileset."""
+759 if self._directory.is_absolute(): 759 ↛ 760line 759 didn't jump to line 760, because the condition on line 759 was never true
+760 return self._directory.resolve()
+761 else:
+762 if self._parent is not None: 762 ↛ 763line 762 didn't jump to line 763, because the condition on line 762 was never true
+763 directory = self._parent.ResolvedPath
+764 elif self._design is not None: 764 ↛ 766line 764 didn't jump to line 766, because the condition on line 764 was never false
+765 directory = self._design.ResolvedPath
+766 elif self._project is not None:
+767 directory = self._project.ResolvedPath
+768 else:
+769 # TODO: message and exception type
+770 raise Exception("")
+ +772 directory = (directory / self._directory).resolve()
+773 if directory.is_absolute(): 773 ↛ 777line 773 didn't jump to line 777, because the condition on line 773 was never false
+774 return directory
+775 else:
+776 # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+777 return pathlib_Path(path_relpath(directory, pathlib_Path.cwd()))
+ +779 @property
+780 def Parent(self) -> Nullable['FileSet']:
+781 """Property setting or returning the parent fileset this fileset is used in."""
+782 return self._parent
+ +784 @Parent.setter
+785 def Parent(self, value: 'FileSet') -> None:
+786 self._parent = value
+787 value._fileSets[self._name] = self
+788 # TODO: check it it already exists
+789 # QUESTION: make an Add fileset method?
+ +791 @property
+792 def FileSets(self) -> Dict[str, 'FileSet']:
+793 """Read-only property returning the dictionary of sub-filesets."""
+794 return self._fileSets
+ +796 def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[bool, str, 'FileSet'] = None) -> Generator[File, None, None]:
+797 """
+798 Method returning the files of this fileset.
+ +800 :arg fileType: A filter for file types. Default: ``Any``.
+801 :arg fileSet: Specifies how to handle sub-filesets.
+802 """
+803 if fileSet is False: 803 ↛ 804line 803 didn't jump to line 804, because the condition on line 803 was never true
+804 for file in self._files:
+805 if file.FileType in fileType:
+806 yield file
+807 elif fileSet is None: 807 ↛ 815line 807 didn't jump to line 815, because the condition on line 807 was never false
+808 for fileSet in self._fileSets.values(): 808 ↛ 809line 808 didn't jump to line 809, because the loop on line 808 never started
+809 for file in fileSet.Files(fileType):
+810 yield file
+811 for file in self._files:
+812 if file.FileType in fileType:
+813 yield file
+814 else:
+815 if isinstance(fileSet, str):
+816 fileSetName = fileSet
+817 try:
+818 fileSet = self._fileSets[fileSetName]
+819 except KeyError as ex:
+820 raise Exception(f"Fileset {fileSetName} not bound to fileset {self.Name}.") from ex
+821 elif not isinstance(fileSet, FileSet):
+822 raise TypeError("Parameter 'fileSet' is not of type 'str' or 'FileSet' nor value 'None'.")
+ +824 for file in fileSet.Files(fileType):
+825 yield file
+ +827 def AddFileSet(self, fileSet: "FileSet") -> None:
+828 """
+829 Method to add a single sub-fileset to this fileset.
+ +831 :arg fileSet: A fileset to add to this fileset as sub-fileset.
+832 """
+833 if not isinstance(fileSet, FileSet): 833 ↛ 834line 833 didn't jump to line 834, because the condition on line 833 was never true
+834 raise ValueError("Parameter 'fileSet' is not of type ProjectModel.FileSet.")
+835 elif fileSet in self._fileSets: 835 ↛ 836line 835 didn't jump to line 836, because the condition on line 835 was never true
+836 raise Exception("Sub-fileset already contains this fileset.")
+837 elif fileSet.Name in self._fileSets.keys(): 837 ↛ 838line 837 didn't jump to line 838, because the condition on line 837 was never true
+838 raise Exception(f"Fileset already contains a sub-fileset named '{fileSet.Name}'.")
+ +840 self._fileSets[fileSet.Name] = fileSet
+841 fileSet._parent = self
+ +843 def AddFileSets(self, fileSets: Iterable["FileSet"]) -> None:
+844 """
+845 Method to add a multiple sub-filesets to this fileset.
+ +847 :arg fileSets: An iterable of filesets to add each to the fileset.
+848 """
+849 for fileSet in fileSets:
+850 self.AddFileSet(fileSet)
+ +852 @property
+853 def FileSetCount(self) -> int:
+854 """Returns number of file sets excl. sub-filesets."""
+855 return len(self._fileSets)
+ +857 @property
+858 def TotalFileSetCount(self) -> int:
+859 """Returns number of file sets incl. sub-filesets."""
+860 fileSetCount = len(self._fileSets)
+861 for fileSet in self._fileSets.values():
+862 fileSetCount += fileSet.TotalFileSetCount
+ +864 return fileSetCount
+ +866 def AddFile(self, file: File) -> None:
+867 """
+868 Method to add a single file to this fileset.
+ +870 :arg file: A file to add to this fileset.
+871 """
+872 if not isinstance(file, File): 872 ↛ 873line 872 didn't jump to line 873, because the condition on line 872 was never true
+873 raise TypeError("Parameter 'file' is not of type ProjectModel.File.")
+874 elif file._fileSet is not None: 874 ↛ 875line 874 didn't jump to line 875, because the condition on line 874 was never true
+875 ex = ValueError(f"File '{file.Path!s}' is already part of fileset '{file.FileSet.Name}'.")
+876 ex.add_note(f"A file can't be assigned to another fileset.")
+877 raise ex
+878 elif file in self._set: 878 ↛ 879line 878 didn't jump to line 879, because the condition on line 878 was never true
+879 ex = ValueError(f"File '{file.Path!s}' is already part of this fileset.")
+880 ex.add_note(f"A file can't be added twice to a fileset.")
+881 raise ex
+ +883 self._files.append(file)
+884 self._set.add(file)
+885 file._fileSet = self
+ +887 def AddFiles(self, files: Iterable[File]) -> None:
+888 """
+889 Method to add a multiple files to this fileset.
+ +891 :arg files: An iterable of files to add each to the fileset.
+892 """
+893 for file in files:
+894 self.AddFile(file)
+ +896 @property
+897 def FileCount(self) -> int:
+898 """Returns number of files excl. sub-filesets."""
+899 return len(self._files)
+ +901 @property
+902 def TotalFileCount(self) -> int:
+903 """Returns number of files incl. the files in sub-filesets."""
+904 fileCount = len(self._files)
+905 for fileSet in self._fileSets.values():
+906 fileCount += fileSet.FileCount
+ +908 return fileCount
+ +910 def Validate(self) -> None:
+911 """Validate this fileset."""
+912 if self._name is None or self._name == "": 912 ↛ 913line 912 didn't jump to line 913, because the condition on line 912 was never true
+913 raise Exception("Validation: FileSet has no name.")
+ +915 if self._directory is None: 915 ↛ 916line 915 didn't jump to line 916, because the condition on line 915 was never true
+916 raise Exception(f"Validation: FileSet '{self._name}' has no directory.")
+917 try:
+918 path = self.ResolvedPath
+919 except Exception as ex:
+920 raise Exception(f"Validation: FileSet '{self._name}' could not compute resolved path.") from ex
+921 if not path.exists(): 921 ↛ 922line 921 didn't jump to line 922, because the condition on line 921 was never true
+922 raise Exception(f"Validation: FileSet '{self._name}'s directory '{path}' does not exist.")
+923 if not path.is_dir(): 923 ↛ 924line 923 didn't jump to line 924, because the condition on line 923 was never true
+924 raise Exception(f"Validation: FileSet '{self._name}'s directory '{path}' is not a directory.")
+ +926 if self._design is None: 926 ↛ 927line 926 didn't jump to line 927, because the condition on line 926 was never true
+927 raise Exception(f"Validation: FileSet '{self._path}' has no design.")
+928 if self._project is None: 928 ↛ 929line 928 didn't jump to line 929, because the condition on line 928 was never true
+929 raise Exception(f"Validation: FileSet '{self._path}' has no project.")
+ +931 for fileSet in self._fileSets.values(): 931 ↛ 932line 931 didn't jump to line 932, because the loop on line 931 never started
+932 fileSet.Validate()
+933 for file in self._files: 933 ↛ 934line 933 didn't jump to line 934, because the loop on line 933 never started
+934 file.Validate()
+ +936 def __len__(self) -> int:
+937 """Returns number of attributes set on the file set."""
+938 return len(self._attributes)
+ +940 def __getitem__(self, key: Type[Attribute]) -> Any:
+941 """Index access for returning attributes on this file."""
+942 if not issubclass(key, Attribute): 942 ↛ 943line 942 didn't jump to line 943, because the condition on line 942 was never true
+943 raise TypeError("Parameter 'key' is not an 'Attribute'.")
+ +945 try:
+946 return self._attributes[key]
+947 except KeyError:
+948 return key.resolve(self, key)
+ +950 def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+951 """Index access for setting attributes on this file."""
+952 self._attributes[key] = value
+ +954 def GetOrCreateVHDLLibrary(self, name) -> None:
+955 if name in self._vhdlLibraries:
+956 return self._vhdlLibraries[name]
+957 elif name in self._design._vhdlLibraries:
+958 library = self._design._vhdlLibraries[name]
+959 self._vhdlLibraries[name] = library
+960 return library
+961 else:
+962 library = VHDLLibrary(name, design=self._design, vhdlVersion=self._vhdlVersion)
+963 self._vhdlLibraries[name] = library
+964 return library
+ +966 @property
+967 def VHDLLibrary(self) -> 'VHDLLibrary':
+968 """Property setting or returning the VHDL library of this fileset."""
+969 if self._vhdlLibrary is not None:
+970 return self._vhdlLibrary
+971 elif self._parent is not None: 971 ↛ 973line 971 didn't jump to line 973, because the condition on line 971 was never false
+972 return self._parent.VHDLLibrary
+973 elif self._design is not None:
+974 return self._design.VHDLLibrary
+975 else:
+976 raise Exception("VHDLLibrary was neither set locally nor globally.")
+ +978 @VHDLLibrary.setter
+979 def VHDLLibrary(self, value: 'VHDLLibrary') -> None:
+980 self._vhdlLibrary = value
+ +982 @property
+983 def VHDLVersion(self) -> VHDLVersion:
+984 """Property setting or returning the VHDL version of this fileset."""
+985 if self._vhdlVersion is not None:
+986 return self._vhdlVersion
+987 elif self._parent is not None:
+988 return self._parent.VHDLVersion
+989 elif self._design is not None: 989 ↛ 992line 989 didn't jump to line 992, because the condition on line 989 was never false
+990 return self._design.VHDLVersion
+991 else:
+992 raise Exception("VHDLVersion was neither set locally nor globally.")
+ +994 @VHDLVersion.setter
+995 def VHDLVersion(self, value: VHDLVersion) -> None:
+996 self._vhdlVersion = value
+ +998 @property
+999 def VerilogVersion(self) -> SystemVerilogVersion:
+1000 """Property setting or returning the Verilog version of this fileset."""
+1001 if self._verilogVersion is not None:
+1002 return self._verilogVersion
+1003 elif self._parent is not None:
+1004 return self._parent.VerilogVersion
+1005 elif self._design is not None: 1005 ↛ 1008line 1005 didn't jump to line 1008, because the condition on line 1005 was never false
+1006 return self._design.VerilogVersion
+1007 else:
+1008 raise Exception("VerilogVersion was neither set locally nor globally.")
+ +1010 @VerilogVersion.setter
+1011 def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+1012 self._verilogVersion = value
+ +1014 @property
+1015 def SVVersion(self) -> SystemVerilogVersion:
+1016 """Property setting or returning the SystemVerilog version of this fileset."""
+1017 if self._svVersion is not None:
+1018 return self._svVersion
+1019 elif self._parent is not None:
+1020 return self._parent.SVVersion
+1021 elif self._design is not None: 1021 ↛ 1024line 1021 didn't jump to line 1024, because the condition on line 1021 was never false
+1022 return self._design.SVVersion
+1023 else:
+1024 raise Exception("SVVersion was neither set locally nor globally.")
+ +1026 @SVVersion.setter
+1027 def SVVersion(self, value: SystemVerilogVersion) -> None:
+1028 self._svVersion = value
+ +1030 @property
+1031 def SRDLVersion(self) -> SystemRDLVersion:
+1032 if self._srdlVersion is not None:
+1033 return self._srdlVersion
+1034 elif self._parent is not None:
+1035 return self._parent.SRDLVersion
+1036 elif self._design is not None:
+1037 return self._design.SRDLVersion
+1038 else:
+1039 raise Exception("SRDLVersion was neither set locally nor globally.")
+ +1041 @SRDLVersion.setter
+1042 def SRDLVersion(self, value: SystemRDLVersion) -> None:
+1043 self._srdlVersion = value
+ +1045 def __str__(self) -> str:
+1046 """Returns the fileset's name."""
+1047 return self._name
+ + +1050@export
+1051class VHDLLibrary(metaclass=ExtendedType, slots=True):
+1052 """
+1053 A :term:`VHDLLibrary` represents a group of VHDL source files compiled into the same VHDL library.
+ +1055 :arg name: The VHDL libraries' name.
+1056 :arg project: Project the VHDL library is associated with.
+1057 :arg design: Design the VHDL library is associated with.
+1058 :arg vhdlVersion: Default VHDL version for files in this VHDL library, if not specified for the file itself.
+1059 """
+ +1061 _name: str
+1062 _project: Nullable['Project']
+1063 _design: Nullable['Design']
+1064 _files: List[File]
+1065 _vhdlVersion: VHDLVersion
+ +1067 _dependencyNode: Vertex
+ +1069 def __init__(
+1070 self,
+1071 name: str,
+1072 project: 'Project' = None,
+1073 design: 'Design' = None,
+1074 vhdlVersion: VHDLVersion = None
+1075 ):
+1076 self._name = name
+1077 if project is not None:
+1078 self._project = project
+1079 self._design = project._defaultDesign if design is None else design
+1080 self._dependencyNode = Vertex(value=self, graph=self._design._vhdlLibraryDependencyGraph)
+ +1082 if name in self._design._vhdlLibraries: 1082 ↛ 1083line 1082 didn't jump to line 1083, because the condition on line 1082 was never true
+1083 raise Exception(f"Library '{name}' already in design '{self._design.Name}'.")
+1084 else:
+1085 self._design._vhdlLibraries[name] = self
+ +1087 elif design is not None:
+1088 self._project = design._project
+1089 self._design = design
+1090 self._dependencyNode = Vertex(value=self, graph=design._vhdlLibraryDependencyGraph)
+ +1092 if name in design._vhdlLibraries: 1092 ↛ 1093line 1092 didn't jump to line 1093, because the condition on line 1092 was never true
+1093 raise Exception(f"Library '{name}' already in design '{design.Name}'.")
+1094 else:
+1095 design._vhdlLibraries[name] = self
+ +1097 else:
+1098 self._project = None
+1099 self._design = None
+1100 self._dependencyNode = None
+ +1102 self._files = []
+1103 self._vhdlVersion = vhdlVersion
+ +1105 @property
+1106 def Name(self) -> str:
+1107 return self._name
+ +1109 @property
+1110 def Project(self) -> Nullable['Project']:
+1111 """Property setting or returning the project this VHDL library is used in."""
+1112 return self._project
+ +1114 @Project.setter
+1115 def Project(self, value: 'Project') -> None:
+1116 if not isinstance(value, Project): 1116 ↛ 1117line 1116 didn't jump to line 1117, because the condition on line 1116 was never true
+1117 raise TypeError("Parameter 'value' is not of type 'Project'.")
+ +1119 if value is None: 1119 ↛ 1121line 1119 didn't jump to line 1121, because the condition on line 1119 was never true
+1120 # TODO: unlink VHDLLibrary from project
+1121 self._project = None
+1122 else:
+1123 self._project = value
+1124 if self._design is None: 1124 ↛ exitline 1124 didn't return from function 'Project', because the condition on line 1124 was never false
+1125 self._design = value._defaultDesign
+ +1127 @property
+1128 def Design(self) -> Nullable['Design']:
+1129 """Property setting or returning the design this VHDL library is used in."""
+1130 return self._design
+ +1132 @Design.setter
+1133 def Design(self, value: 'Design') -> None:
+1134 if not isinstance(value, Design):
+1135 raise TypeError("Parameter 'value' is not of type 'Design'.")
+ +1137 if value is None:
+1138 # TODO: unlink VHDLLibrary from design
+1139 self._design = None
+1140 else:
+1141 if self._design is None:
+1142 self._design = value
+1143 self._dependencyNode = Vertex(value=self, graph=self._design._vhdlLibraryDependencyGraph)
+1144 elif self._design is not value:
+1145 # TODO: move VHDLLibrary to other design
+1146 # TODO: create new vertex in dependency graph and remove vertex from old graph
+1147 self._design = value
+1148 else:
+1149 pass
+ +1151 if self._project is None:
+1152 self._project = value._project
+1153 elif self._project is not value._project:
+1154 raise Exception("The design's project is not identical to the already assigned project.")
+ +1156 @property
+1157 def Files(self) -> Generator[File, None, None]:
+1158 """Read-only property to return all files in this VHDL library."""
+1159 for file in self._files:
+1160 yield file
+ +1162 @property
+1163 def VHDLVersion(self) -> VHDLVersion:
+1164 """Property setting or returning the VHDL version of this VHDL library."""
+1165 if self._vhdlVersion is not None:
+1166 return self._vhdlVersion
+1167 elif self._design is not None: 1167 ↛ 1170line 1167 didn't jump to line 1170, because the condition on line 1167 was never false
+1168 return self._design.VHDLVersion
+1169 else:
+1170 raise Exception("VHDLVersion is not set on VHDLLibrary nor parent object.")
+ +1172 @VHDLVersion.setter
+1173 def VHDLVersion(self, value: VHDLVersion) -> None:
+1174 self._vhdlVersion = value
+ +1176 def AddDependency(self, library: 'VHDLLibrary') -> None:
+1177 library.parent = self
+ +1179 def AddFile(self, vhdlFile: VHDLSourceFile) -> None:
+1180 if not isinstance(vhdlFile, VHDLSourceFile): 1180 ↛ 1181line 1180 didn't jump to line 1181, because the condition on line 1180 was never true
+1181 raise TypeError(f"Parameter 'vhdlFile' is not a 'VHDLSourceFile'.")
+ +1183 self._files.append(vhdlFile)
+ +1185 def AddFiles(self, vhdlFiles: Iterable[VHDLSourceFile]) -> None:
+1186 for vhdlFile in vhdlFiles:
+1187 if not isinstance(vhdlFile, VHDLSourceFile):
+1188 raise TypeError(f"Item '{vhdlFile}' in parameter 'vhdlFiles' is not a 'VHDLSourceFile'.")
+ +1190 self._files.append(vhdlFile)
+ +1192 @property
+1193 def FileCount(self) -> int:
+1194 """Returns number of files."""
+1195 return len(self._files)
+ +1197 def __str__(self) -> str:
+1198 """Returns the VHDL library's name."""
+1199 return self._name
+ + +1202@export
+1203class Design(metaclass=ExtendedType, slots=True):
+1204 """
+1205 A :term:`Design` represents a group of filesets and the source files therein.
+ +1207 Each design contains at least one fileset - the :term:`default fileset`. For
+1208 designs with VHDL source files, a independent `VHDLLibraries` overlay structure
+1209 exists.
+ +1211 :arg name: The design's name.
+1212 :arg topLevel: Name of the design's toplevel.
+1213 :arg directory: Path of this design (absolute or relative to the project).
+1214 :arg project: Project the design is associated with.
+1215 :arg vhdlVersion: Default VHDL version for files in this design, if not specified for the file itself.
+1216 :arg verilogVersion: Default Verilog version for files in this design, if not specified for the file itself.
+1217 :arg svVersion: Default SystemVerilog version for files in this design, if not specified for the file itself.
+1218 :arg srdlVersion: Default SystemRDL version for files in this fileset, if not specified for the file itself.
+1219 """
+ +1221 _name: str
+1222 _topLevel: Nullable[str]
+1223 _project: Nullable['Project']
+1224 _directory: pathlib_Path
+1225 _fileSets: Dict[str, FileSet]
+1226 _defaultFileSet: Nullable[FileSet]
+1227 _attributes: Dict[Type[Attribute], typing_Any]
+ +1229 _vhdlLibraries: Dict[str, VHDLLibrary]
+1230 _vhdlVersion: VHDLVersion
+1231 _verilogVersion: SystemVerilogVersion
+1232 _svVersion: SystemVerilogVersion
+1233 _srdlVersion: SystemRDLVersion
+1234 _externalVHDLLibraries: List
+ +1236 _vhdlLibraryDependencyGraph: Graph
+1237 _fileDependencyGraph: Graph
+ +1239 def __init__(
+1240 self,
+1241 name: str,
+1242 topLevel: str = None,
+1243 directory: pathlib_Path = pathlib_Path("."),
+1244 project: 'Project' = None,
+1245 vhdlVersion: VHDLVersion = None,
+1246 verilogVersion: SystemVerilogVersion = None,
+1247 svVersion: SystemVerilogVersion = None,
+1248 srdlVersion: SystemRDLVersion = None
+1249 ):
+1250 self._name = name
+1251 self._topLevel = topLevel
+1252 self._project = project
+1253 if project is not None:
+1254 project._designs[name] = self
+1255 self._directory = directory
+1256 self._fileSets = {}
+1257 self._defaultFileSet = FileSet("default", project=project, design=self)
+1258 self._attributes = {}
+1259 self._vhdlLibraries = {}
+1260 self._vhdlVersion = vhdlVersion
+1261 self._verilogVersion = verilogVersion
+1262 self._svVersion = svVersion
+1263 self._srdlVersion = srdlVersion
+1264 self._externalVHDLLibraries = []
+ +1266 self._vhdlLibraryDependencyGraph = Graph()
+1267 self._fileDependencyGraph = Graph()
+ +1269 @property
+1270 def Name(self) -> str:
+1271 """Property setting or returning the design's name."""
+1272 return self._name
+ +1274 @Name.setter
+1275 def Name(self, value: str) -> None:
+1276 self._name = value
+ +1278 @property
+1279 def TopLevel(self) -> str:
+1280 """Property setting or returning the fileset's toplevel."""
+1281 return self._topLevel
+ +1283 @TopLevel.setter
+1284 def TopLevel(self, value: str) -> None:
+1285 self._topLevel = value
+ +1287 @property
+1288 def Project(self) -> Nullable['Project']:
+1289 """Property setting or returning the project this design is used in."""
+1290 return self._project
+ +1292 @Project.setter
+1293 def Project(self, value: 'Project') -> None:
+1294 self._project = value
+ +1296 @property
+1297 def Directory(self) -> pathlib_Path:
+1298 """Property setting or returning the directory this design is located in."""
+1299 return self._directory
+ +1301 @Directory.setter
+1302 def Directory(self, value: pathlib_Path) -> None:
+1303 self._directory = value
+ +1305 @property
+1306 def ResolvedPath(self) -> pathlib_Path:
+1307 """Read-only property returning the resolved path of this fileset."""
+1308 if self._directory.is_absolute(): 1308 ↛ 1309line 1308 didn't jump to line 1309, because the condition on line 1308 was never true
+1309 return self._directory.resolve()
+1310 elif self._project is not None: 1310 ↛ 1320line 1310 didn't jump to line 1320, because the condition on line 1310 was never false
+1311 path = (self._project.ResolvedPath / self._directory).resolve()
+ +1313 if path.is_absolute(): 1313 ↛ 1317line 1313 didn't jump to line 1317, because the condition on line 1313 was never false
+1314 return path
+1315 else:
+1316 # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+1317 return pathlib_Path(path_relpath(path, pathlib_Path.cwd()))
+1318 else:
+1319 # TODO: message and exception type
+1320 raise Exception("")
+ +1322 @property
+1323 def DefaultFileSet(self) -> FileSet:
+1324 """Property setting or returning the default fileset of this design."""
+1325 return self._defaultFileSet
+ +1327 @DefaultFileSet.setter
+1328 def DefaultFileSet(self, value: Union[str, FileSet]) -> None:
+1329 if isinstance(value, str):
+1330 if value not in self._fileSets.keys():
+1331 raise Exception(f"Fileset '{value}' is not in this design.")
+ +1333 self._defaultFileSet = self._fileSets[value]
+1334 elif isinstance(value, FileSet):
+1335 if value not in self.FileSets:
+1336 raise Exception(f"Fileset '{value}' is not associated to this design.")
+ +1338 self._defaultFileSet = value
+1339 else:
+1340 raise ValueError("Unsupported parameter type for 'value'.")
+ +1342 # TODO: return generator with another method
+1343 @property
+1344 def FileSets(self) -> Dict[str, FileSet]:
+1345 """Read-only property returning the dictionary of filesets."""
+1346 return self._fileSets
+ +1348 def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[str, FileSet] = None) -> Generator[File, None, None]:
+1349 """
+1350 Method returning the files of this design.
+ +1352 :arg fileType: A filter for file types. Default: ``Any``.
+1353 :arg fileSet: Specifies if all files from all filesets (``fileSet=None``) are files from a single fileset are returned.
+1354 """
+1355 if fileSet is None:
+1356 for fileSet in self._fileSets.values():
+1357 for file in fileSet.Files(fileType):
+1358 yield file
+1359 else:
+1360 if isinstance(fileSet, str): 1360 ↛ 1365line 1360 didn't jump to line 1365, because the condition on line 1360 was never false
+1361 try:
+1362 fileSet = self._fileSets[fileSet]
+1363 except KeyError as ex:
+1364 raise Exception(f"Fileset {fileSet.Name} not bound to design {self.Name}.") from ex
+1365 elif not isinstance(fileSet, FileSet):
+1366 raise TypeError("Parameter 'fileSet' is not of type 'str' or 'FileSet' nor value 'None'.")
+ +1368 for file in fileSet.Files(fileType):
+1369 yield file
+ + + +1373 def Validate(self) -> None:
+1374 """Validate this design."""
+1375 if self._name is None or self._name == "": 1375 ↛ 1376line 1375 didn't jump to line 1376, because the condition on line 1375 was never true
+1376 raise Exception("Validation: Design has no name.")
+ +1378 if self._directory is None: 1378 ↛ 1379line 1378 didn't jump to line 1379, because the condition on line 1378 was never true
+1379 raise Exception(f"Validation: Design '{self._name}' has no directory.")
+1380 try:
+1381 path = self.ResolvedPath
+1382 except Exception as ex:
+1383 raise Exception(f"Validation: Design '{self._name}' could not compute resolved path.") from ex
+1384 if not path.exists(): 1384 ↛ 1385line 1384 didn't jump to line 1385, because the condition on line 1384 was never true
+1385 raise Exception(f"Validation: Design '{self._name}'s directory '{path}' does not exist.")
+1386 if not path.is_dir(): 1386 ↛ 1387line 1386 didn't jump to line 1387, because the condition on line 1386 was never true
+1387 raise Exception(f"Validation: Design '{self._name}'s directory '{path}' is not a directory.")
+ +1389 if len(self._fileSets) == 0: 1389 ↛ 1390line 1389 didn't jump to line 1390, because the condition on line 1389 was never true
+1390 raise Exception(f"Validation: Design '{self._name}' has no fileset.")
+1391 try:
+1392 if self._defaultFileSet is not self._fileSets[self._defaultFileSet.Name]: 1392 ↛ 1393line 1392 didn't jump to line 1393, because the condition on line 1392 was never true
+1393 raise Exception(f"Validation: Design '{self._name}'s default fileset is the same as listed in filesets.")
+1394 except KeyError as ex:
+1395 raise Exception(f"Validation: Design '{self._name}'s default fileset is not in list of filesets.") from ex
+1396 if self._project is None: 1396 ↛ 1397line 1396 didn't jump to line 1397, because the condition on line 1396 was never true
+1397 raise Exception(f"Validation: Design '{self._path}' has no project.")
+ +1399 for fileSet in self._fileSets.values():
+1400 fileSet.Validate()
+ +1402 def __len__(self) -> int:
+1403 """Returns number of attributes set on the file set."""
+1404 return len(self._attributes)
+ +1406 def __getitem__(self, key: Type[Attribute]) -> Any:
+1407 if not issubclass(key, Attribute):
+1408 raise TypeError("Parameter 'key' is not an 'Attribute'.")
+ +1410 try:
+1411 return self._attributes[key]
+1412 except KeyError:
+1413 return key.resolve(self, key)
+ +1415 def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+1416 self._attributes[key] = value
+ +1418 @property
+1419 def VHDLLibraries(self) -> Dict[str, VHDLLibrary]:
+1420 return self._vhdlLibraries
+ +1422 @property
+1423 def VHDLVersion(self) -> VHDLVersion:
+1424 if self._vhdlVersion is not None:
+1425 return self._vhdlVersion
+1426 elif self._project is not None: 1426 ↛ 1429line 1426 didn't jump to line 1429, because the condition on line 1426 was never false
+1427 return self._project.VHDLVersion
+1428 else:
+1429 raise Exception("VHDLVersion was neither set locally nor globally.")
+ +1431 @VHDLVersion.setter
+1432 def VHDLVersion(self, value: VHDLVersion) -> None:
+1433 self._vhdlVersion = value
+ +1435 @property
+1436 def VerilogVersion(self) -> SystemVerilogVersion:
+1437 if self._verilogVersion is not None:
+1438 return self._verilogVersion
+1439 elif self._project is not None: 1439 ↛ 1442line 1439 didn't jump to line 1442, because the condition on line 1439 was never false
+1440 return self._project.VerilogVersion
+1441 else:
+1442 raise Exception("VerilogVersion was neither set locally nor globally.")
+ +1444 @VerilogVersion.setter
+1445 def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+1446 self._verilogVersion = value
+ +1448 @property
+1449 def SVVersion(self) -> SystemVerilogVersion:
+1450 if self._svVersion is not None:
+1451 return self._svVersion
+1452 elif self._project is not None: 1452 ↛ 1455line 1452 didn't jump to line 1455, because the condition on line 1452 was never false
+1453 return self._project.SVVersion
+1454 else:
+1455 raise Exception("SVVersion was neither set locally nor globally.")
+ +1457 @SVVersion.setter
+1458 def SVVersion(self, value: SystemVerilogVersion) -> None:
+1459 self._svVersion = value
+ +1461 @property
+1462 def SRDLVersion(self) -> SystemRDLVersion:
+1463 if self._srdlVersion is not None:
+1464 return self._srdlVersion
+1465 elif self._project is not None:
+1466 return self._project.SRDLVersion
+1467 else:
+1468 raise Exception("SRDLVersion was neither set locally nor globally.")
+ +1470 @SRDLVersion.setter
+1471 def SRDLVersion(self, value: SystemRDLVersion) -> None:
+1472 self._srdlVersion = value
+ +1474 @property
+1475 def ExternalVHDLLibraries(self) -> List:
+1476 return self._externalVHDLLibraries
+ +1478 def AddFileSet(self, fileSet: FileSet) -> None:
+1479 if not isinstance(fileSet, FileSet):
+1480 raise ValueError("Parameter 'fileSet' is not of type ProjectModel.FileSet.")
+1481 elif fileSet in self._fileSets:
+1482 raise Exception("Design already contains this fileset.")
+1483 elif fileSet.Name in self._fileSets.keys():
+1484 raise Exception(f"Design already contains a fileset named '{fileSet.Name}'.")
+ +1486 self._fileSets[fileSet.Name] = fileSet
+1487 fileSet.Design = self
+1488 fileSet._parent = self
+ +1490 def AddFileSets(self, fileSets: Iterable[FileSet]) -> None:
+1491 for fileSet in fileSets:
+1492 self.AddFileSet(fileSet)
+ +1494 @property
+1495 def FileSetCount(self) -> int:
+1496 """Returns number of file sets excl. sub-filesets."""
+1497 return len(self._fileSets)
+ +1499 @property
+1500 def TotalFileSetCount(self) -> int:
+1501 """Returns number of file sets incl. sub-filesets."""
+1502 fileSetCount = len(self._fileSets)
+1503 for fileSet in self._fileSets.values():
+1504 fileSetCount += fileSet.TotalFileSetCount
+ +1506 return fileSetCount
+ +1508 def AddFile(self, file: File) -> None:
+1509 if file.FileSet is None: 1509 ↛ 1512line 1509 didn't jump to line 1512, because the condition on line 1509 was never false
+1510 self._defaultFileSet.AddFile(file)
+1511 else:
+1512 raise ValueError(f"File '{file.Path!s}' is already part of fileset '{file.FileSet.Name}' and can't be assigned via Design to a default fileset.")
+ +1514 def AddFiles(self, files: Iterable[File]) -> None:
+1515 for file in files:
+1516 self.AddFile(file)
+ +1518 def AddVHDLLibrary(self, vhdlLibrary: VHDLLibrary) -> None:
+1519 if vhdlLibrary.Name in self._vhdlLibraries:
+1520 if self._vhdlLibraries[vhdlLibrary.Name] is vhdlLibrary:
+1521 raise Exception(f"The VHDLLibrary '{vhdlLibrary.Name}' was already added to the design.")
+1522 else:
+1523 raise Exception(f"A VHDLLibrary with same name ('{vhdlLibrary.Name}') already exists for this design.")
+ +1525 def __str__(self) -> str:
+1526 return self._name
+ + +1529@export
+1530class Project(metaclass=ExtendedType, slots=True):
+1531 """
+1532 A :term:`Project` represents a group of designs and the source files therein.
+ +1534 :arg name: The project's name.
+1535 :arg rootDirectory: Base-path to the project.
+1536 :arg vhdlVersion: Default VHDL version for files in this project, if not specified for the file itself.
+1537 :arg verilogVersion: Default Verilog version for files in this project, if not specified for the file itself.
+1538 :arg svVersion: Default SystemVerilog version for files in this project, if not specified for the file itself.
+1539 """
+ +1541 _name: str
+1542 _rootDirectory: pathlib_Path
+1543 _designs: Dict[str, Design]
+1544 _defaultDesign: Design
+1545 _attributes: Dict[Type[Attribute], typing_Any]
+ +1547 _vhdlVersion: VHDLVersion
+1548 _verilogVersion: SystemVerilogVersion
+1549 _svVersion: SystemVerilogVersion
+1550 _srdlVersion: SystemRDLVersion
+ +1552 def __init__(
+1553 self,
+1554 name: str,
+1555 rootDirectory: pathlib_Path = pathlib_Path("."),
+1556 vhdlVersion: VHDLVersion = None,
+1557 verilogVersion: SystemVerilogVersion = None,
+1558 svVersion: SystemVerilogVersion = None
+1559 ):
+1560 self._name = name
+1561 self._rootDirectory = rootDirectory
+1562 self._designs = {}
+1563 self._defaultDesign = Design("default", project=self)
+1564 self._attributes = {}
+1565 self._vhdlVersion = vhdlVersion
+1566 self._verilogVersion = verilogVersion
+1567 self._svVersion = svVersion
+ +1569 @property
+1570 def Name(self) -> str:
+1571 """Property setting or returning the project's name."""
+1572 return self._name
+ +1574 @property
+1575 def RootDirectory(self) -> pathlib_Path:
+1576 """Property setting or returning the root directory this project is located in."""
+1577 return self._rootDirectory
+ +1579 @RootDirectory.setter
+1580 def RootDirectory(self, value: pathlib_Path) -> None:
+1581 self._rootDirectory = value
+ +1583 @property
+1584 def ResolvedPath(self) -> pathlib_Path:
+1585 """Read-only property returning the resolved path of this fileset."""
+1586 path = self._rootDirectory.resolve()
+1587 if self._rootDirectory.is_absolute():
+1588 return path
+1589 else:
+1590 # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath
+1591 return pathlib_Path(path_relpath(path, pathlib_Path.cwd()))
+ +1593 # TODO: return generator with another method
+1594 @property
+1595 def Designs(self) -> Dict[str, Design]:
+1596 return self._designs
+ +1598 @property
+1599 def DefaultDesign(self) -> Design:
+1600 return self._defaultDesign
+ +1602 def Validate(self) -> None:
+1603 """Validate this project."""
+1604 if self._name is None or self._name == "": 1604 ↛ 1605line 1604 didn't jump to line 1605, because the condition on line 1604 was never true
+1605 raise Exception("Validation: Project has no name.")
+ +1607 if self._rootDirectory is None: 1607 ↛ 1608line 1607 didn't jump to line 1608, because the condition on line 1607 was never true
+1608 raise Exception(f"Validation: Project '{self._name}' has no root directory.")
+1609 try:
+1610 path = self.ResolvedPath
+1611 except Exception as ex:
+1612 raise Exception(f"Validation: Project '{self._name}' could not compute resolved path.") from ex
+1613 if not path.exists(): 1613 ↛ 1614line 1613 didn't jump to line 1614, because the condition on line 1613 was never true
+1614 raise Exception(f"Validation: Project '{self._name}'s directory '{path}' does not exist.")
+1615 if not path.is_dir(): 1615 ↛ 1616line 1615 didn't jump to line 1616, because the condition on line 1615 was never true
+1616 raise Exception(f"Validation: Project '{self._name}'s directory '{path}' is not a directory.")
+ +1618 if len(self._designs) == 0: 1618 ↛ 1619line 1618 didn't jump to line 1619, because the condition on line 1618 was never true
+1619 raise Exception(f"Validation: Project '{self._name}' has no design.")
+1620 try:
+1621 if self._defaultDesign is not self._designs[self._defaultDesign.Name]: 1621 ↛ 1622line 1621 didn't jump to line 1622, because the condition on line 1621 was never true
+1622 raise Exception(f"Validation: Project '{self._name}'s default design is the same as listed in designs.")
+1623 except KeyError as ex:
+1624 raise Exception(f"Validation: Project '{self._name}'s default design is not in list of designs.") from ex
+ +1626 for design in self._designs.values():
+1627 design.Validate()
+ +1629 @property
+1630 def DesignCount(self) -> int:
+1631 """Returns number of designs."""
+1632 return len(self._designs)
+ +1634 def __len__(self) -> int:
+1635 """Returns number of attributes set on the file set."""
+1636 return len(self._attributes)
+ +1638 def __getitem__(self, key: Type[Attribute]) -> Any:
+1639 if not issubclass(key, Attribute):
+1640 raise TypeError("Parameter 'key' is not an 'Attribute'.")
+ +1642 try:
+1643 return self._attributes[key]
+1644 except KeyError:
+1645 return key.resolve(self, key)
+ +1647 def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None:
+1648 self._attributes[key] = value
+ +1650 @property
+1651 def VHDLVersion(self) -> VHDLVersion:
+1652 # TODO: check for None and return exception
+1653 return self._vhdlVersion
+ +1655 @VHDLVersion.setter
+1656 def VHDLVersion(self, value: VHDLVersion) -> None:
+1657 self._vhdlVersion = value
+ +1659 @property
+1660 def VerilogVersion(self) -> SystemVerilogVersion:
+1661 # TODO: check for None and return exception
+1662 return self._verilogVersion
+ +1664 @VerilogVersion.setter
+1665 def VerilogVersion(self, value: SystemVerilogVersion) -> None:
+1666 self._verilogVersion = value
+ +1668 @property
+1669 def SVVersion(self) -> SystemVerilogVersion:
+1670 # TODO: check for None and return exception
+1671 return self._svVersion
+ +1673 @SVVersion.setter
+1674 def SVVersion(self, value: SystemVerilogVersion) -> None:
+1675 self._svVersion = value
+ +1677 @property
+1678 def SRDLVersion(self) -> SystemRDLVersion:
+1679 # TODO: check for None and return exception
+1680 return self._srdlVersion
+ +1682 @SRDLVersion.setter
+1683 def SRDLVersion(self, value: SystemRDLVersion) -> None:
+1684 self._srdlVersion = value
+ +1686 def __str__(self) -> str:
+1687 return self._name
++ « prev + ^ index + » next + + coverage.py v7.3.0, + created at 2023-08-13 23:53 +0000 +
+ +1# ==================================================================================================================== #
+2# _____ ____ _ _ ____ _ _ __ __ _ _ #
+3# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | #
+4# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | #
+5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | #
+6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| #
+7# |_| |___/ |__/ #
+8# ==================================================================================================================== #
+9# Authors: #
+10# Patrick Lehmann #
+11# #
+12# License: #
+13# ==================================================================================================================== #
+14# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
+15# #
+16# Licensed under the Apache License, Version 2.0 (the "License"); #
+17# you may not use this file except in compliance with the License. #
+18# You may obtain a copy of the License at #
+19# #
+20# http://www.apache.org/licenses/LICENSE-2.0 #
+21# #
+22# Unless required by applicable law or agreed to in writing, software #
+23# distributed under the License is distributed on an "AS IS" BASIS, #
+24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+25# See the License for the specific language governing permissions and #
+26# limitations under the License. #
+27# #
+28# SPDX-License-Identifier: Apache-2.0 #
+29# ==================================================================================================================== #
+30#
+31"""Specific file types and attributes for Xilinx Vivado."""
+32from pathlib import Path
+33from typing import Iterable
+ +35from xml.dom import minidom, Node
+ +37from pyTooling.MetaClasses import ExtendedType
+38from pyVHDLModel import VHDLVersion
+39from pyTooling.Decorators import export
+ +41from pyEDAA.ProjectModel import ProjectFile, XMLFile, XMLContent, SDCContent, Project, FileSet, Attribute, Design
+42from pyEDAA.ProjectModel import File as Model_File
+43from pyEDAA.ProjectModel import ConstraintFile as Model_ConstraintFile
+44from pyEDAA.ProjectModel import VerilogSourceFile as Model_VerilogSourceFile
+45from pyEDAA.ProjectModel import VHDLSourceFile as Model_VHDLSourceFile
+ + +48@export
+49class UsedInAttribute(Attribute):
+50 KEY = "UsedIn"
+51 VALUE_TYPE = Iterable[str]
+ + +54@export
+55class File(Model_File):
+56 pass
+ + +59class VivadoFileMixIn(metaclass=ExtendedType, mixin=True):
+60 def _registerAttributes(self):
+61 self._attributes[UsedInAttribute] = []
+ + +64@export
+65class ConstraintFile(Model_ConstraintFile, VivadoFileMixIn):
+66 def _registerAttributes(self):
+67 super()._registerAttributes()
+68 VivadoFileMixIn._registerAttributes(self)
+ + +71@export
+72class VerilogSourceFile(Model_VerilogSourceFile):
+73 def _registerAttributes(self):
+74 super()._registerAttributes()
+75 VivadoFileMixIn._registerAttributes(self)
+ + +78@export
+79class VHDLSourceFile(Model_VHDLSourceFile):
+80 def _registerAttributes(self):
+81 super()._registerAttributes()
+82 VivadoFileMixIn._registerAttributes(self)
+ + +85@export
+86class VivadoProjectFile(ProjectFile, XMLContent):
+87 """A Vivado project file (``*.xpr``)."""
+ +89 _xprProject: Project
+ +91 def __init__(
+92 self,
+93 path: Path,
+94 project: Project = None,
+95 design: Design = None,
+96 fileSet: FileSet = None
+97 ):
+98 super().__init__(path, project, design, fileSet)
+ +100 self._xprProject = None
+ +102 @property
+103 def ProjectModel(self) -> Project:
+104 return self._xprProject
+ +106 def Parse(self):
+107 if not self._path.exists(): 107 ↛ 108line 107 didn't jump to line 108, because the condition on line 107 was never true
+108 raise Exception(f"Vivado project file '{self._path!s}' not found.") from FileNotFoundError(f"File '{self._path!s}' not found.")
+ +110 try:
+111 root = minidom.parse(str(self._path)).documentElement
+112 except Exception as ex:
+113 raise Exception(f"Couldn't open '{self._path!s}'.") from ex
+ +115 self._xprProject = Project(self._path.stem, rootDirectory=self._path.parent)
+116 self._ParseRootElement(root)
+ +118 def _ParseRootElement(self, root):
+119 for rootNode in root.childNodes: 119 ↛ exitline 119 didn't return from function '_ParseRootElement', because the loop on line 119 didn't complete
+120 if rootNode.nodeName == "FileSets":
+121 self._ParseFileSets(rootNode)
+122 break
+ +124 def _ParseFileSets(self, filesetsNode):
+125 for fileSetsNode in filesetsNode.childNodes:
+126 if fileSetsNode.nodeType == Node.ELEMENT_NODE and fileSetsNode.tagName == "FileSet":
+127 self._ParseFileSet(fileSetsNode)
+ +129 def _ParseFileSet(self, filesetNode):
+130 filesetName = filesetNode.getAttribute("Name")
+131 fileset = FileSet(filesetName, design=self._xprProject.DefaultDesign)
+ +133 for fileNode in filesetNode.childNodes:
+134 if fileNode.nodeType == Node.ELEMENT_NODE:
+135 if fileNode.tagName == "File":
+136 self._ParseFile(fileNode, fileset)
+137 elif fileNode.nodeType == Node.ELEMENT_NODE and fileNode.tagName == "Config":
+138 self._ParseFileSetConfig(fileNode, fileset)
+ +140 def _ParseFile(self, fileNode, fileset):
+141 croppedPath = fileNode.getAttribute("Path").replace("$PPRDIR/", "")
+142 filePath = Path(croppedPath)
+143 if filePath.suffix in (".vhd", ".vhdl"):
+144 self._ParseVHDLFile(fileNode, filePath, fileset)
+145 elif filePath.suffix == ".xdc": 145 ↛ 147line 145 didn't jump to line 147, because the condition on line 145 was never false
+146 self._ParseXDCFile(fileNode, filePath, fileset)
+147 elif filePath.suffix == ".v":
+148 self._ParseVerilogFile(fileNode, filePath, fileset)
+149 elif filePath.suffix == ".xci":
+150 self._ParseXCIFile(fileNode, filePath, fileset)
+151 else:
+152 self._ParseDefaultFile(fileNode, filePath, fileset)
+ +154 def _ParseVHDLFile(self, fileNode, path, fileset):
+155 vhdlFile = VHDLSourceFile(path)
+156 fileset.AddFile(vhdlFile)
+157 usedInAttr = vhdlFile[UsedInAttribute]
+ +159 for childNode in fileNode.childNodes:
+160 if childNode.nodeType == Node.ELEMENT_NODE and childNode.tagName == "FileInfo":
+161 if childNode.getAttribute("SFType") == "VHDL2008":
+162 vhdlFile.VHDLVersion = VHDLVersion.VHDL2008
+163 else:
+164 vhdlFile.VHDLVersion = VHDLVersion.VHDL93
+ +166 for fileAttribute in childNode.childNodes:
+167 if fileAttribute.nodeType == Node.ELEMENT_NODE and fileAttribute.tagName == "Attr":
+168 if fileAttribute.getAttribute("Name") == "Library":
+169 libraryName = fileAttribute.getAttribute("Val")
+170 vhdlFile.VHDLLibrary = fileset.GetOrCreateVHDLLibrary(libraryName)
+171 elif fileAttribute.getAttribute("Val") == "UsedIn": 171 ↛ 172line 171 didn't jump to line 172, because the condition on line 171 was never true
+172 usedInAttr.append(fileAttribute.getAttribute("Val"))
+ +174 def _ParseDefaultFile(self, _, path, fileset):
+175 File(path, fileSet=fileset)
+ +177 def _ParseXDCFile(self, _, path, fileset):
+178 XDCConstraintFile(path, fileSet=fileset)
+ +180 def _ParseVerilogFile(self, _, path, fileset):
+181 VerilogSourceFile(path, fileSet=fileset)
+ +183 def _ParseXCIFile(self, _, path, fileset):
+184 IPCoreInstantiationFile(path, fileSet=fileset)
+ +186 def _ParseFileSetConfig(self, fileNode, fileset):
+187 for option in fileNode.childNodes:
+188 if option.nodeType == Node.ELEMENT_NODE and option.tagName == "Option":
+189 if option.getAttribute("Name") == "TopModule":
+190 fileset.TopLevel = option.getAttribute("Val")
+ + +193@export
+194class XDCConstraintFile(ConstraintFile, SDCContent):
+195 """A Vivado constraint file (Xilinx Design Constraints; ``*.xdc``)."""
+ + +198@export
+199class IPCoreDescriptionFile(XMLFile):
+200 pass
+ + +203@export
+204class IPCoreInstantiationFile(XMLFile):
+205 """A Vivado IP core instantiation file (Xilinx IPCore Instance; ``*.xci``)."""
++ « prev + ^ index + » next + + coverage.py v7.3.0, + created at 2023-08-13 23:53 +0000 +
+ +1# ==================================================================================================================== #
+2# _____ ____ _ _ ____ _ _ __ __ _ _ #
+3# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | #
+4# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | #
+5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | #
+6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| #
+7# |_| |___/ |__/ #
+8# ==================================================================================================================== #
+9# Authors: #
+10# Patrick Lehmann #
+11# #
+12# License: #
+13# ==================================================================================================================== #
+14# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
+15# #
+16# Licensed under the Apache License, Version 2.0 (the "License"); #
+17# you may not use this file except in compliance with the License. #
+18# You may obtain a copy of the License at #
+19# #
+20# http://www.apache.org/licenses/LICENSE-2.0 #
+21# #
+22# Unless required by applicable law or agreed to in writing, software #
+23# distributed under the License is distributed on an "AS IS" BASIS, #
+24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+25# See the License for the specific language governing permissions and #
+26# limitations under the License. #
+27# #
+28# SPDX-License-Identifier: Apache-2.0 #
+29# ==================================================================================================================== #
+30#
+31"""A vendor specific package for Xilinx."""
++ coverage.py v7.3.0, + created at 2023-08-13 23:53 +0000 +
+Module | +statements | +missing | +excluded | +branches | +partial | +coverage | +
---|---|---|---|---|---|---|
pyEDAA/ProjectModel/Attributes.py | +15 | +0 | +0 | +2 | +0 | +100% | +
pyEDAA/ProjectModel/Xilinx/Vivado.py | +121 | +14 | +0 | +66 | +4 | +88% | +
pyEDAA/ProjectModel/Xilinx/__init__.py | +1 | +0 | +0 | +0 | +0 | +100% | +
pyEDAA/ProjectModel/__init__.py | +1023 | +246 | +0 | +618 | +74 | +75% | +
Total | +1160 | +260 | +0 | +686 | +78 | +76% | +
+ No items found using the specified filter. +
++ | + |
|
+
+ | + |
+ | + |
+ |
+ |
+ |
+ |
|
+
+ |
|
+
|
+
+ | + |
+ | + |
+ | + |
+ |
+ | + |
+ |
+ |
An abstract model of HDL design projects and EDA tooling.
+This package provides a unified abstract project model for HDL designs and EDA tools. +Third-party frameworks can derive own classes and implement additional logic to create a concrete project model for +their tools.
+Frameworks consuming this model can build higher level features and services on top of such a model, while supporting +multiple input sources.
+Describing HDL projects for open source simulation and synthesis tools: +GHDL, +Icarus Verilog, +Verilator, +Yosys, +Verilog to Routing (VTR), +nextpnr, +etc.
Managing IP cores and projects with pyIPCMI.
*.xpr
and *.pro
Files¶Xilinx Vivado’s *.xpr
and OSVVM’s *.pro
files can now be read.
Filesets can be nested.
The dataset can be validated.
Patrick Lehmann (Maintainer)
Unai Martinez-Corral (Maintainer)
This Python package (source code) is licensed under Apache License 2.0.
+The accompanying documentation is licensed under Creative Commons - Attribution 4.0 (CC-BY 4.0).
This document was generated on 13.Aug 2023 - 23:53.
++ p | ||
+ |
+ pyEDAA | + |
+ |
+ pyEDAA.ProjectModel | + |
+ |
+ pyEDAA.ProjectModel.Altera | + |
+ |
+ pyEDAA.ProjectModel.Altera.Quartus | + |
+ |
+ pyEDAA.ProjectModel.Attributes | + |
+ |
+ pyEDAA.ProjectModel.GHDL | + |
+ |
+ pyEDAA.ProjectModel.Intel | + |
+ |
+ pyEDAA.ProjectModel.Intel.QuartusPrime | + |
+ |
+ pyEDAA.ProjectModel.MentorGraphics | + |
+ |
+ pyEDAA.ProjectModel.MentorGraphics.ModelSim | + |
+ |
+ pyEDAA.ProjectModel.MentorGraphics.QuestaSim | + |
+ |
+ pyEDAA.ProjectModel.OSVVM | + |
+ |
+ pyEDAA.ProjectModel.Verilog | + |
+ |
+ pyEDAA.ProjectModel.VHDL | + |
+ |
+ pyEDAA.ProjectModel.Xilinx | + |
+ |
+ pyEDAA.ProjectModel.Xilinx.ISE | + |
+ |
+ pyEDAA.ProjectModel.Xilinx.Vivado | + |
Reference of all packages and modules:
+pyEDAA.ProjectModel
pyEDAA.ProjectModel.Altera
+pyEDAA.ProjectModel.Attributes
+pyEDAA.ProjectModel.GHDL
pyEDAA.ProjectModel.Intel
+pyEDAA.ProjectModel.MentorGraphics
+pyEDAA.ProjectModel.OSVVM
pyEDAA.ProjectModel.VHDL
pyEDAA.ProjectModel.Verilog
pyEDAA.ProjectModel.Xilinx
+Attribute
FileType
FileType.FileTypes
FileType.__init__()
FileType.__new__()
FileType.__base__
FileType.__call__()
FileType.__delattr__()
FileType.__dir__()
FileType.__getattribute__()
FileType.__instancecheck__()
FileType.__or__()
FileType.__prepare__()
FileType.__repr__()
FileType.__ror__()
FileType.__setattr__()
FileType.__sizeof__()
FileType.__subclasscheck__()
FileType.__subclasses__()
FileType.__text_signature__
FileType._checkForAbstractMethods()
FileType._iterateBaseClassPaths()
FileType._wrapNewMethodIfAbstract()
FileType._wrapNewMethodIfSingleton()
FileType.mro()
HumanReadableContent
XMLContent
YAMLContent
JSONContent
INIContent
TOMLContent
TCLContent
SDCContent
PythonContent
FileSet
FileSet.__init__()
FileSet.Name
FileSet.TopLevel
FileSet.Project
FileSet.Design
FileSet.Directory
FileSet.ResolvedPath
FileSet.Parent
FileSet.FileSets
FileSet.Files()
FileSet.AddFileSet()
FileSet.AddFileSets()
FileSet.FileSetCount
FileSet.TotalFileSetCount
FileSet.AddFile()
FileSet.AddFiles()
FileSet.FileCount
FileSet.TotalFileCount
FileSet.Validate()
FileSet.__len__()
FileSet.__getitem__()
FileSet.__setitem__()
FileSet.VHDLLibrary
FileSet.VHDLVersion
FileSet.VerilogVersion
FileSet.SVVersion
FileSet.__str__()
VHDLLibrary
+Design
+Project
+pyEDAA.ProjectModel.Altera.Quartus
¶Classes
+QuartusProjectFile
:
+A Quartus project file (*.qpf
).
SDCConstraintFile
:
+A Quartus constraint file (Synopsys Design Constraints; *.sdc
).
pyEDAA.ProjectModel.Altera
¶Submodules
+ +pyEDAA.ProjectModel.GHDL
¶Classes
+GHDLWaveformFile
:
+GHDL’s waveform file (*.ghw
) supporting VHDL and Verilog simulation results.
pyEDAA.ProjectModel.Intel.QuartusPrime
¶Classes
+QuartusProjectFile
:
+A Quartus project file (*.qpf
).
SDCConstraintFile
:
+A Quartus constraint file (Synopsys Design Constraints; *.sdc
).
pyEDAA.ProjectModel.Intel
¶Submodules
+ +pyEDAA.ProjectModel.MentorGraphics.ModelSim
¶Classes
+ModelSimProjectFile
:
+Base-class of all tool-specific project files.
ModelSimINIFile
:
+Base-class of all tool-specific setting files.
WaveDoFile
:
+Base-class of all tool-specific waveform configuration files.
pyEDAA.ProjectModel.MentorGraphics.QuestaSim
¶Classes
+ModelSimProjectFile
:
+Base-class of all tool-specific project files.
ModelSimINIFile
:
+Base-class of all tool-specific setting files.
WaveDoFile
:
+Base-class of all tool-specific waveform configuration files.
pyEDAA.ProjectModel.MentorGraphics
¶Submodules
+ +pyEDAA.ProjectModel.OSVVM
¶Classes
+OSVVMProjectFile
:
+An OSVVM project file (*.pro
).
pyEDAA.ProjectModel.VHDL
¶pyEDAA.ProjectModel.Verilog
¶Classes
+ValueChangeDumpFile
:
+Verilog’s waveform file (*.vcd
) for exchanging value changes as defined by IEEE Std. 1364.
pyEDAA.ProjectModel.Xilinx.ISE
¶Classes
+ISEProjectFile
:
+Base-class of all tool-specific project files.
UCFConstraintFile
:
+Base-class of all constraint files.
pyEDAA.ProjectModel.Xilinx.Vivado
¶Classes
+UsedInAttribute
:
+Undocumented.
File
:
+A File represents a file in a design. This base-class is used
ConstraintFile
:
+Base-class of all constraint files.
VerilogSourceFile
:
+A Verilog source file (of any language version).
VHDLSourceFile
:
+A VHDL source file (of any language version).
VivadoProjectFile
:
+A Vivado project file (*.xpr
).
XDCConstraintFile
:
+A Vivado constraint file (Xilinx Design Constraints; *.xdc
).
IPCoreDescriptionFile
:
+An XML file (*.xml
).
IPCoreInstantiationFile
:
+A Vivado IP core instantiation file (Xilinx IPCore Instance; *.xci
).
pyEDAA.ProjectModel.Xilinx
¶Submodules
+ +pyEDAA.ProjectModel
¶Submodules
+Classes
+Attribute
:
+Undocumented.
FileType
:
+A meta-class to construct FileType classes.
File
:
+A File represents a file in a design. This base-class is used
HumanReadableContent
:
+A file type representing human-readable contents.
XMLContent
:
+A file type representing XML contents.
YAMLContent
:
+A file type representing YAML contents.
JSONContent
:
+A file type representing JSON contents.
INIContent
:
+A file type representing INI contents.
TOMLContent
:
+A file type representing TOML contents.
TCLContent
:
+A file type representing content in TCL code.
SDCContent
:
+A file type representing contents as Synopsys Design Constraints (SDC).
PythonContent
:
+A file type representing contents as Python source code.
TextFile
:
+A text file (*.txt
).
LogFile
:
+A log file (*.log
).
XMLFile
:
+An XML file (*.xml
).
SourceFile
:
+Base-class of all source files.
HDLSourceFile
:
+Base-class of all HDL source files.
RDLSourceFile
:
+Base-class of all RDL source files.
NetlistFile
:
+Base-class of all netlist source files.
EDIFNetlistFile
:
+Netlist file in EDIF (Electronic Design Interchange Format).
TCLSourceFile
:
+A TCL source file.
VHDLSourceFile
:
+A VHDL source file (of any language version).
VerilogBaseFile
:
+Base-class of all HDL source files.
VerilogSourceFile
:
+A Verilog source file (of any language version).
VerilogHeaderFile
:
+A Verilog header file (of any language version).
SystemVerilogBaseFile
:
+Base-class of all HDL source files.
SystemVerilogSourceFile
:
+A SystemVerilog source file (of any language version).
SystemVerilogHeaderFile
:
+A SystemVerilog header file (of any language version).
SystemRDLSourceFile
:
+A SystemRDL source file (of any language version).
PythonSourceFile
:
+A Python source file.
CocotbPythonFile
:
+A Python source file used by Cocotb.
ConstraintFile
:
+Base-class of all constraint files.
ProjectFile
:
+Base-class of all tool-specific project files.
CSourceFile
:
+Base-class of all ANSI-C source files.
CppSourceFile
:
+Base-class of all ANSI-C++ source files.
SettingFile
:
+Base-class of all tool-specific setting files.
SimulationAnalysisFile
:
+Base-class of all tool-specific analysis files.
SimulationElaborationFile
:
+Base-class of all tool-specific elaboration files.
SimulationStartFile
:
+Base-class of all tool-specific simulation start-up files.
SimulationRunFile
:
+Base-class of all tool-specific simulation run (execution) files.
WaveformConfigFile
:
+Base-class of all tool-specific waveform configuration files.
WaveformDatabaseFile
:
+Base-class of all tool-specific waveform database files.
WaveformExchangeFile
:
+Base-class of all tool-independent waveform exchange files.
FileSet
:
+A FileSet represents a group of files. Filesets can have sub-filesets.
VHDLLibrary
:
+A VHDLLibrary represents a group of VHDL source files compiled into the same VHDL library.
Design
:
+A Design represents a group of filesets and the source files therein.
Project
:
+A Project represents a group of designs and the source files therein.
A meta-class to construct FileType classes.
+Modifications done by this meta-class:
+* Register all classes of type FileType
or derived variants in a class field FileType.FileTypes
in this meta-class.
Inheritance
+ +classMembers (Dict) –
+Dict
[str
, FileType
] = {'CSourceFile': <class 'pyEDAA.ProjectModel.CSourceFile'>, 'CocotbPythonFile': <class 'pyEDAA.ProjectModel.CocotbPythonFile'>, 'ConstraintFile': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.ConstraintFile'>, 'CppSourceFile': <class 'pyEDAA.ProjectModel.CppSourceFile'>, 'EDIFNetlistFile': <class 'pyEDAA.ProjectModel.EDIFNetlistFile'>, 'File': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.File'>, 'GHDLWaveformFile': <class 'pyEDAA.ProjectModel.GHDL.GHDLWaveformFile'>, 'HDLSourceFile': <class 'pyEDAA.ProjectModel.HDLSourceFile'>, 'IPCoreDescriptionFile': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.IPCoreDescriptionFile'>, 'IPCoreInstantiationFile': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.IPCoreInstantiationFile'>, 'ISEProjectFile': <class 'pyEDAA.ProjectModel.Xilinx.ISE.ISEProjectFile'>, 'LogFile': <class 'pyEDAA.ProjectModel.LogFile'>, 'ModelSimINIFile': <class 'pyEDAA.ProjectModel.MentorGraphics.QuestaSim.ModelSimINIFile'>, 'ModelSimProjectFile': <class 'pyEDAA.ProjectModel.MentorGraphics.QuestaSim.ModelSimProjectFile'>, 'NetlistFile': <class 'pyEDAA.ProjectModel.NetlistFile'>, 'OSVVMProjectFile': <class 'pyEDAA.ProjectModel.OSVVM.OSVVMProjectFile'>, 'ProjectFile': <class 'pyEDAA.ProjectModel.ProjectFile'>, 'PythonSourceFile': <class 'pyEDAA.ProjectModel.PythonSourceFile'>, 'QuartusProjectFile': <class 'pyEDAA.ProjectModel.Intel.QuartusPrime.QuartusProjectFile'>, 'RDLSourceFile': <class 'pyEDAA.ProjectModel.RDLSourceFile'>, 'SDCConstraintFile': <class 'pyEDAA.ProjectModel.Intel.QuartusPrime.SDCConstraintFile'>, 'SettingFile': <class 'pyEDAA.ProjectModel.SettingFile'>, 'SimulationAnalysisFile': <class 'pyEDAA.ProjectModel.SimulationAnalysisFile'>, 'SimulationElaborationFile': <class 'pyEDAA.ProjectModel.SimulationElaborationFile'>, 'SimulationRunFile': <class 'pyEDAA.ProjectModel.SimulationRunFile'>, 'SimulationStartFile': <class 'pyEDAA.ProjectModel.SimulationStartFile'>, 'SourceFile': <class 'pyEDAA.ProjectModel.SourceFile'>, 'SystemRDLSourceFile': <class 'pyEDAA.ProjectModel.SystemRDLSourceFile'>, 'SystemVerilogBaseFile': <class 'pyEDAA.ProjectModel.SystemVerilogBaseFile'>, 'SystemVerilogHeaderFile': <class 'pyEDAA.ProjectModel.SystemVerilogHeaderFile'>, 'SystemVerilogSourceFile': <class 'pyEDAA.ProjectModel.SystemVerilogSourceFile'>, 'TCLSourceFile': <class 'pyEDAA.ProjectModel.TCLSourceFile'>, 'TextFile': <class 'pyEDAA.ProjectModel.TextFile'>, 'UCFConstraintFile': <class 'pyEDAA.ProjectModel.Xilinx.ISE.UCFConstraintFile'>, 'VHDLSourceFile': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.VHDLSourceFile'>, 'ValueChangeDumpFile': <class 'pyEDAA.ProjectModel.Verilog.ValueChangeDumpFile'>, 'VerilogBaseFile': <class 'pyEDAA.ProjectModel.VerilogBaseFile'>, 'VerilogHeaderFile': <class 'pyEDAA.ProjectModel.VerilogHeaderFile'>, 'VerilogSourceFile': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.VerilogSourceFile'>, 'VivadoProjectFile': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.VivadoProjectFile'>, 'WaveDoFile': <class 'pyEDAA.ProjectModel.MentorGraphics.QuestaSim.WaveDoFile'>, 'WaveformConfigFile': <class 'pyEDAA.ProjectModel.WaveformConfigFile'>, 'WaveformDatabaseFile': <class 'pyEDAA.ProjectModel.WaveformDatabaseFile'>, 'WaveformExchangeFile': <class 'pyEDAA.ProjectModel.WaveformExchangeFile'>, 'XDCConstraintFile': <class 'pyEDAA.ProjectModel.Xilinx.Vivado.XDCConstraintFile'>, 'XMLFile': <class 'pyEDAA.ProjectModel.XMLFile'>}¶Dictionary of all classes of type FileType
or derived variants
Construct a new class using this meta-class.
+className – The name of the class to construct.
baseClasses – The tuple of base-classes the class is derived from.
members – The dictionary of members for the constructed class.
slots – If true, store object attributes in __slots__ instead of __dict__
.
mixin – If true, make the class a Mixin-Class.
+If false, create slots if slots
is true.
+If none, preserve behavior of primary base-class.
singleton – If true, make the class a Singleton.
classMembers (Dict) –
The new class.
+AttributeError – If base-class has no ‘__slots__’ attribute.
AttributeError – If slot already exists in base-class.
alias of ExtendedType
Call self as a function.
+Implement delattr(self, name).
+Specialized __dir__ implementation for types.
+Return getattr(self, name).
+Check if an object is an instance.
+Return self|value.
+used to create the namespace for the class statement
+ +Return repr(self).
+Return value|self.
+Implement setattr(self, name, value).
+Return memory consumption of the type object.
+Check if a class is a subclass.
+Return a list of immediate subclasses.
+Check if the current class contains abstract methods and return a tuple of them.
+These abstract methods might be inherited from any base-class. If there are inherited abstract methods, check if +they are now implemented (overridden) by the current class that’s right now constructed.
+ +Return a generator to iterate all possible inheritance paths for a given list of base-classes.
+An inheritance path is expressed as a tuple of base-classes from current base-class (left-most item) to
+object
(right-most item).
If the class has abstract methods, replace the _new__
method, so it raises an exception.
newClass – The newly constructed class for further modifications.
+True
, if the class is abstract.
AbstractClassError – If the class is abstract and can’t be instantiated.
+If a class is a singleton, wrap the _new__
method, so it returns a cached object, if a first object was created.
Only the first object creation initializes the object.
+This implementation is threadsafe.
+ +Return a type’s method resolution order.
+A file type representing human-readable contents.
+Inheritance
+ +A file type representing XML contents.
+Inheritance
+ +A file type representing YAML contents.
+Inheritance
+ +A file type representing JSON contents.
+Inheritance
+ +A file type representing INI contents.
+Inheritance
+ +A file type representing TOML contents.
+Inheritance
+ +A file type representing content in TCL code.
+Inheritance
+ +A file type representing contents as Synopsys Design Constraints (SDC).
+Inheritance
+ +A file type representing contents as Python source code.
+Inheritance
+ +A FileSet represents a group of files. Filesets can have sub-filesets.
+The order of insertion is preserved. A fileset can be created standalone and +later associated to another fileset, design and/or project. Or a fileset, +design and/or project can be associated immediately while creating the +fileset.
+name (str
) – Name of this fileset.
topLevel (str
) – Name of the fileset’s toplevel.
directory (Path
) – Path of this fileset (absolute or relative to a parent fileset or design).
project (Project
) – Project the file is associated with.
design (Design
) – Design the file is associated with.
parent (Optional
[FileSet
]) – Parent fileset if this fileset is nested.
vhdlLibrary (Union
[str
, VHDLLibrary
]) – Default VHDL library for files in this fileset, if not specified for the file itself.
vhdlVersion (VHDLVersion
) – Default VHDL version for files in this fileset, if not specified for the file itself.
verilogVersion (SystemVerilogVersion
) – Default Verilog version for files in this fileset, if not specified for the file itself.
svVersion (SystemVerilogVersion
) – Default SystemVerilog version for files in this fileset, if not specified for the file itself.
srdlVersion (SystemRDLVersion
) – Default SystemRDL version for files in this fileset, if not specified for the file itself.
name –
topLevel –
directory –
project –
design –
parent –
vhdlLibrary –
vhdlVersion –
verilogVersion –
svVersion –
srdlVersion –
Inheritance
+ +Property setting or returning the project this fileset is used in.
+Property setting or returning the design this fileset is used in.
+Property setting or returning the directory this fileset is located in.
+Property setting or returning the parent fileset this fileset is used in.
+Read-only property returning the dictionary of sub-filesets.
+Method returning the files of this fileset.
+ +Method to add a single file to this fileset.
+file (File
) – A file to add to this fileset.
file –
Property setting or returning the VHDL library of this fileset.
+Property setting or returning the VHDL version of this fileset.
+Property setting or returning the Verilog version of this fileset.
+Property setting or returning the SystemVerilog version of this fileset.
+A VHDLLibrary represents a group of VHDL source files compiled into the same VHDL library.
+name (str
) – The VHDL libraries’ name.
project (Project
) – Project the VHDL library is associated with.
design (Design
) – Design the VHDL library is associated with.
vhdlVersion (VHDLVersion
) – Default VHDL version for files in this VHDL library, if not specified for the file itself.
name –
project –
design –
vhdlVersion –
Inheritance
+ + + +Property setting or returning the project this VHDL library is used in.
+Property setting or returning the design this VHDL library is used in.
+Read-only property to return all files in this VHDL library.
+Property setting or returning the VHDL version of this VHDL library.
+A Design represents a group of filesets and the source files therein.
+Each design contains at least one fileset - the default fileset. For +designs with VHDL source files, a independent VHDLLibraries overlay structure +exists.
+name (str
) – The design’s name.
topLevel (str
) – Name of the design’s toplevel.
directory (Path
) – Path of this design (absolute or relative to the project).
project (Project
) – Project the design is associated with.
vhdlVersion (VHDLVersion
) – Default VHDL version for files in this design, if not specified for the file itself.
verilogVersion (SystemVerilogVersion
) – Default Verilog version for files in this design, if not specified for the file itself.
svVersion (SystemVerilogVersion
) – Default SystemVerilog version for files in this design, if not specified for the file itself.
srdlVersion (SystemRDLVersion
) – Default SystemRDL version for files in this fileset, if not specified for the file itself.
name –
topLevel –
directory –
project –
vhdlVersion –
verilogVersion –
svVersion –
srdlVersion –
Inheritance
+ +Property setting or returning the project this design is used in.
+Property setting or returning the directory this design is located in.
+Property setting or returning the default fileset of this design.
+Read-only property returning the dictionary of filesets.
+A Project represents a group of designs and the source files therein.
+name (str
) – The project’s name.
rootDirectory (Path
) – Base-path to the project.
vhdlVersion (VHDLVersion
) – Default VHDL version for files in this project, if not specified for the file itself.
verilogVersion (SystemVerilogVersion
) – Default Verilog version for files in this project, if not specified for the file itself.
svVersion (SystemVerilogVersion
) – Default SystemVerilog version for files in this project, if not specified for the file itself.
name –
rootDirectory –
vhdlVersion –
verilogVersion –
svVersion –
Inheritance
+ +pyEDAA.ProjectModel
", "pyEDAA.ProjectModel.Altera
", "pyEDAA.ProjectModel.Altera.Quartus
", "pyEDAA.ProjectModel.Attributes
", "pyEDAA.ProjectModel.GHDL
", "pyEDAA.ProjectModel.Intel
", "pyEDAA.ProjectModel.Intel.QuartusPrime
", "pyEDAA.ProjectModel.MentorGraphics
", "pyEDAA.ProjectModel.MentorGraphics.ModelSim
", "pyEDAA.ProjectModel.MentorGraphics.QuestaSim
", "pyEDAA.ProjectModel.OSVVM
", "pyEDAA.ProjectModel.VHDL
", "pyEDAA.ProjectModel.Verilog
", "pyEDAA.ProjectModel.Xilinx
", "pyEDAA.ProjectModel.Xilinx.ISE
", "pyEDAA.ProjectModel.Xilinx.Vivado
", "Static Type Checking Report"], "terms": {"\u00bd": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00bc": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u215b": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00be": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u215c": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u215d": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u215e": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "_": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00b5": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03c9": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00aa": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00ba": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00b9": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00b2": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u00b3": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u212c": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2145": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u212d": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2102": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2146": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03dd": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2130": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2147": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2131": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u02c7": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u210f": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u210b": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2111": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2148": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2110": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2124": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2112": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2133": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2115": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2134": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u210c": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2119": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u210d": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u211a": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u211c": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u211b": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u211d": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03f5": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03d5": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03c5": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03b5": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03f0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03c6": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03d6": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03f1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03c2": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u03d1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "\u2128": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], "tbd": [0, 3], "pyedaa": [0, 5, 17], "projectmodel": [0, 5, 17], "wa": [0, 6, 15, 18], "split": 0, "from": [0, 2, 6, 18], "pyipcmi": 0, "v1": 0, "1": [0, 1, 4], "6": [0, 1, 5], "an": [0, 2, 4, 6, 7, 9, 10, 12, 15, 18, 28, 33], "independ": [0, 2, 18], "python": [0, 1, 5, 15, 18], "packag": [0, 4, 5, 15, 17], "librari": [1, 12, 18], "io": 1, "requir": [1, 2, 5, 6], "version": [1, 6, 18, 33], "licens": 1, "pytool": [1, 18], "5": 1, "0": [1, 15], "apach": [1, 15], "2": [1, 15], "none": [1, 7, 8, 9, 10, 11, 18], "pyvhdlmodel": 1, "27": 1, "pysvmodel": 1, "3": [1, 5], "pysystemrdlmodel": 1, "addit": [1, 2, 15], "need": [1, 2], "code": [1, 6, 15, 18], "collect": [1, 2], "static": [1, 18], "These": [1, 18], "ar": [1, 2, 6, 18], "develop": 1, "thu": 1, "sub": [1, 18], "evalu": 1, "further": [1, 18], "manual": [1, 4], "instal": 1, "us": [1, 4, 6, 18, 33], "txt": [1, 18], "file": [1, 4, 6, 7, 9, 11, 12, 17, 18, 20, 22, 24, 26, 27, 28, 30, 32, 33], "all": [1, 2, 6, 17, 18, 26, 27, 32, 33], "via": 1, "pip3": [1, 5], "The": [1, 2, 6, 18], "recurs": 1, "mandatori": 1, "too": 1, "u": [1, 5], "r": 1, "list": [1, 6, 7, 9, 11, 18], "pytest": [1, 13], "7": [1, 5], "4": [1, 15], "mit": 1, "Not": [1, 6], "yet": 1, "cov": 1, "mypi": [1, 34], "extens": 1, "psf": 1, "lxml": 1, "9": [1, 2], "bsd": 1, "claus": 1, "gener": [1, 6, 7, 8, 9, 10, 11, 13, 15, 18, 34], "doc": 1, "sphinx_btd_them": 1, "sphinx_fontawesom": 1, "gpl": 1, "sphinx_autodoc_typehint": 1, "19": 1, "build": [1, 15], "wheel": 1, "40": 1, "e": 1, "g": 1, "pypi": [1, 15], "ani": [1, 2, 6, 7, 9, 18, 33], "equival": [1, 2], "servic": [1, 2, 6, 15], "maintain": [1, 15], "dist": 1, "twine": 1, "thi": [2, 5, 6, 15, 18, 33], "i": [2, 4, 5, 6, 15, 18, 33], "local": [2, 6], "copi": [2, 6], "cc": [2, 15], "BY": [2, 15], "appli": [2, 6, 12], "onli": [2, 6, 18], "document": [2, 4, 6, 7, 8, 9, 10, 11], "project": [2, 4, 6, 7, 8, 9, 11, 15, 17, 18, 20, 24, 26, 27, 28, 32, 33], "corpor": 2, "law": [2, 6], "firm": 2, "doe": [2, 6], "provid": [2, 6, 15], "legal": [2, 6], "advic": 2, "distribut": [2, 6], "creat": [2, 15, 18], "lawyer": 2, "client": 2, "relationship": [2, 7, 8, 9, 10, 11], "make": [2, 6, 18], "its": [2, 6], "relat": 2, "inform": [2, 6], "avail": [2, 6], "basi": [2, 6], "give": [2, 6], "regard": [2, 6], "materi": 2, "under": [2, 6, 15], "damag": [2, 6], "result": [2, 6, 22], "fullest": 2, "extent": 2, "possibl": [2, 6, 18], "standard": [2, 4], "set": [2, 9, 12, 18, 26, 27], "creator": 2, "holder": 2, "mai": [2, 6], "share": [2, 6], "origin": [2, 6], "work": [2, 6], "authorship": [2, 6], "subject": [2, 6], "copyright": 2, "certain": 2, "specifi": [2, 4, 18], "below": [2, 6], "follow": [2, 6], "consider": 2, "purpos": [2, 6], "exhaust": 2, "do": [2, 6], "form": [2, 6], "part": [2, 6], "our": 2, "licensor": [2, 6], "intend": 2, "those": [2, 6], "author": [2, 6], "permiss": [2, 6], "wai": 2, "otherwis": [2, 6], "restrict": 2, "irrevoc": [2, 6], "should": [2, 6], "read": [2, 18], "understand": 2, "thei": [2, 18], "choos": [2, 6], "befor": 2, "also": [2, 6], "secur": 2, "necessari": 2, "so": [2, 18], "can": [2, 15, 18], "reus": 2, "expect": 2, "clearli": [2, 12], "mark": [2, 6], "includ": [2, 6], "except": [2, 6, 18], "more": [2, 6, 15], "By": 2, "one": [2, 6, 12, 18], "grant": 2, "If": [2, 4, 6, 18], "": [2, 6, 15, 18, 22, 30], "reason": [2, 6], "exampl": [2, 6], "becaus": 2, "applic": [2, 6], "regul": 2, "ha": [2, 6, 12, 15, 18], "still": 2, "have": [2, 6, 12, 18], "A": [2, 4, 6, 12, 18, 20, 24, 33], "special": [2, 6, 18], "request": 2, "ask": 2, "chang": [2, 6, 30], "describ": [2, 6, 15], "although": 2, "you": [2, 6], "encourag": 2, "respect": 2, "where": [2, 6], "exercis": [2, 6], "defin": [2, 4, 6, 30], "accept": 2, "agre": [2, 6], "bound": 2, "To": [2, 6], "contract": [2, 6], "your": [2, 6], "benefit": 2, "receiv": [2, 6], "adapt": 2, "mean": [2, 6], "similar": 2, "deriv": [2, 4, 6, 15, 18], "base": [2, 4, 6, 18, 26, 27, 32, 33], "upon": 2, "which": [2, 6], "translat": [2, 6], "alter": 2, "arrang": 2, "transform": [2, 6], "modifi": [2, 6], "manner": 2, "held": 2, "For": [2, 6, 18], "music": 2, "perform": [2, 6], "sound": 2, "record": 2, "alwai": 2, "produc": 2, "synch": 2, "time": 2, "move": 2, "imag": 2, "contribut": 2, "accord": 2, "close": 2, "without": [2, 6], "broadcast": 2, "how": [2, 5, 6, 18], "label": 2, "categor": 2, "b": 2, "effect": 2, "technolog": 2, "measur": 2, "absenc": 2, "proper": 2, "circumv": 2, "fulfil": 2, "oblig": [2, 6], "articl": 2, "11": 2, "wipo": 2, "treati": 2, "adopt": 2, "decemb": 2, "20": 2, "1996": 2, "agreement": [2, 6], "fair": 2, "deal": 2, "artist": 2, "literari": 2, "individu": [2, 6], "entiti": [2, 4, 6], "process": 2, "reproduct": [2, 6], "displai": [2, 6], "dissemin": 2, "commun": [2, 6], "import": [2, 6], "member": [2, 18], "access": [2, 18], "place": [2, 6], "chosen": 2, "them": [2, 18], "than": 2, "direct": [2, 6], "96": 2, "ec": 2, "european": 2, "parliament": 2, "council": 2, "march": 2, "protect": 2, "amend": 2, "succeed": 2, "well": 2, "essenti": 2, "anywher": 2, "world": 2, "correspond": 2, "herebi": [2, 6], "worldwid": [2, 6], "royalti": [2, 6], "free": [2, 6], "non": [2, 6], "sublicens": [2, 6], "exclus": [2, 6], "reproduc": [2, 6], "whole": [2, 6], "avoid": 2, "doubt": 2, "compli": [2, 6], "media": [2, 6], "format": [2, 6, 18], "technic": 2, "modif": [2, 6, 18], "allow": [2, 18], "whether": [2, 6], "now": [2, 15, 18], "known": 2, "hereaft": 2, "waiv": 2, "assert": [2, 6], "forbid": 2, "simpli": 2, "never": 2, "downstream": 2, "recipi": [2, 6], "offer": [2, 6], "everi": 2, "automat": 2, "No": 2, "impos": 2, "differ": [2, 6], "endors": 2, "noth": [2, 6], "constitut": [2, 6], "constru": [2, 6], "impli": [2, 6], "connect": 2, "sponsor": 2, "offici": 2, "statu": 2, "design": [2, 3, 4, 6, 8, 9, 10, 11, 12, 15, 17, 18, 20, 24, 33], "moral": 2, "integr": [2, 15], "nor": 2, "privaci": 2, "person": 2, "howev": [2, 6], "patent": 2, "trademark": 2, "directli": 2, "through": [2, 6], "societi": 2, "voluntari": 2, "waivabl": 2, "statutori": 2, "compulsori": 2, "scheme": 2, "In": [2, 6], "case": 2, "expressli": 2, "reserv": 2, "made": [2, 6], "must": [2, 6], "retain": [2, 6], "suppli": 2, "identif": [2, 6], "pseudonym": 2, "notic": [2, 6], "refer": [2, 4, 12], "uri": 2, "hyperlink": 2, "practic": 2, "indic": [2, 6], "previou": 2, "text": [2, 6, 18], "satisfi": 2, "medium": [2, 6], "context": [2, 4], "resourc": 2, "remov": 2, "prevent": 2, "extract": 2, "substanti": 2, "portion": 2, "content": [2, 6, 18], "supplement": 2, "replac": [2, 6, 18], "unless": [2, 6], "separ": [2, 6], "undertaken": 2, "represent": [2, 4], "kind": [2, 6], "concern": 2, "express": [2, 6, 18], "titl": [2, 6], "merchant": [2, 6], "fit": [2, 6], "particular": [2, 6], "infring": [2, 6], "latent": 2, "defect": 2, "accuraci": 2, "presenc": 2, "error": 2, "discover": 2, "full": 2, "event": [2, 6], "liabl": [2, 6], "theori": [2, 6], "neglig": [2, 6], "indirect": [2, 6], "incident": [2, 6], "consequenti": [2, 6], "punit": 2, "exemplari": 2, "loss": [2, 6], "cost": 2, "expens": 2, "aris": [2, 6], "out": [2, 6], "even": [2, 6], "been": [2, 6, 15], "advis": [2, 6], "abov": [2, 5, 6], "shall": [2, 6, 12], "most": [2, 18], "approxim": 2, "absolut": [2, 18], "waiver": 2, "here": 2, "fail": 2, "reinstat": 2, "date": [2, 6], "violat": 2, "cure": 2, "within": [2, 6], "30": 2, "dai": 2, "discoveri": 2, "affect": 2, "seek": 2, "remedi": 2, "stop": 2, "surviv": 2, "state": [2, 6], "herein": [2, 6], "reduc": 2, "could": 2, "lawfulli": 2, "provis": 2, "deem": 2, "unenforc": 2, "reform": 2, "minimum": 2, "enforc": 2, "cannot": [2, 6], "sever": 2, "remain": [2, 6], "failur": [2, 6], "consent": 2, "privileg": 2, "immun": 2, "jurisdict": 2, "parti": [2, 6, 15], "notwithstand": [2, 6], "elect": 2, "publish": 2, "instanc": [2, 18, 33], "consid": 2, "permit": 2, "polici": 2, "creativecommon": 2, "org": [2, 6], "logo": 2, "prior": 2, "written": [2, 6], "unauthor": 2, "paragraph": 2, "contact": 2, "goal": [3, 12], "lrm": 4, "languag": [4, 6, 18, 33], "name": [4, 6, 7, 9, 10, 11, 12, 17, 18], "given": [4, 18], "ieee": [4, 30], "hardwar": 4, "descript": [4, 6, 7, 8, 9, 10, 11], "vhdl": [4, 12, 17, 18, 22, 33], "revis": [4, 6], "1076": 4, "2019": 4, "2008": 4, "aka": 4, "iec": 4, "61691": 4, "2011": 4, "2002": 4, "ed": 4, "2004": [4, 6], "10": 4, "2000": 4, "1993": 4, "1987": 4, "verilog": [4, 15, 17, 18, 22, 33], "tbc": 4, "system": [4, 6], "class": [4, 5, 6, 12, 15, 18, 20, 21, 22, 24, 26, 27, 28, 30, 32, 33], "ancestor": 4, "other": [4, 6], "physic": 4, "fileset": [4, 7, 8, 12, 15, 17, 18], "group": [4, 9, 11, 12, 18], "default": [4, 18], "pre": 4, "exist": [4, 18], "vhdllibrari": [4, 7, 9, 17, 18], "namespac": [4, 15, 18], "organ": 4, "unit": [4, 11], "configur": [4, 6, 18, 26, 27], "due": 5, "problem": 5, "meta": [5, 18], "__getattr__": 5, "see": [5, 6], "section": [5, 6], "sourc": [6, 12, 15, 18, 21, 33], "januari": 6, "term": 6, "AND": 6, "condit": 6, "FOR": 6, "owner": 6, "union": [6, 7, 9, 18], "act": 6, "control": 6, "common": [6, 15], "power": 6, "caus": 6, "manag": [6, 15], "ii": 6, "ownership": 6, "fifti": 6, "percent": 6, "50": 6, "outstand": 6, "iii": 6, "benefici": 6, "prefer": 6, "softwar": 6, "object": [6, 12, 18], "mechan": 6, "compil": [6, 18], "convers": 6, "type": [6, 18], "attach": 6, "appendix": 6, "editori": 6, "annot": 6, "elabor": [6, 18], "repres": [6, 18, 33], "mere": 6, "link": 6, "bind": 6, "interfac": 6, "thereof": 6, "intention": 6, "submit": 6, "inclus": 6, "behalf": 6, "electron": [6, 18], "verbal": 6, "sent": 6, "mail": 6, "issu": 6, "track": 6, "discuss": 6, "improv": 6, "exclud": 6, "conspicu": 6, "write": [6, 7, 8, 9, 10, 11], "contributor": 6, "whom": 6, "subsequ": 6, "incorpor": 6, "each": [6, 18], "perpetu": 6, "charg": 6, "prepar": 6, "publicli": 6, "sell": 6, "transfer": 6, "claim": 6, "necessarili": 6, "alon": 6, "combin": 6, "institut": 6, "litig": 6, "against": 6, "cross": 6, "counterclaim": 6, "lawsuit": 6, "alleg": 6, "contributori": 6, "termin": 6, "meet": 6, "carri": 6, "promin": 6, "attribut": [6, 12, 15, 17, 18, 33], "pertain": 6, "readabl": [6, 18], "contain": [6, 11, 12, 18], "least": [6, 12, 18], "along": 6, "wherev": 6, "third": [6, 15], "normal": 6, "appear": 6, "add": [6, 18], "own": [6, 15], "alongsid": 6, "addendum": 6, "statement": [6, 18], "explicitli": 6, "supersed": 6, "execut": [6, 18], "trade": 6, "product": 6, "customari": 6, "AS": 6, "OR": 6, "OF": 6, "either": 6, "sole": 6, "respons": 6, "determin": 6, "appropri": 6, "assum": 6, "risk": 6, "associ": [6, 18], "tort": 6, "deliber": 6, "grossli": 6, "charact": 6, "inabl": 6, "goodwil": 6, "stoppag": 6, "comput": 6, "malfunct": 6, "commerci": 6, "while": [6, 15, 18], "fee": 6, "support": [6, 15, 22], "indemn": 6, "right": [6, 18], "consist": 6, "indemnifi": 6, "defend": 6, "hold": 6, "harmless": 6, "incur": 6, "boilerpl": 6, "field": [6, 18], "enclos": 6, "bracket": 6, "identifi": 6, "don": 6, "t": [6, 18], "comment": 6, "syntax": 6, "we": 6, "recommend": 6, "same": [6, 18], "print": 6, "page": 6, "easier": 6, "archiv": 6, "yyyi": 6, "complianc": 6, "obtain": 6, "http": 6, "www": 6, "specif": [6, 18, 26, 27, 32], "govern": 6, "eda": [7, 8, 9, 10, 12, 15], "export": [7, 8, 9, 10, 11], "_name": [7, 9, 10, 11], "str": [7, 9, 10, 11, 18], "_project": [7, 8, 9, 11], "nullabl": [7, 8, 9, 10, 11], "_directori": [7, 9], "path": [7, 8, 9, 10, 18], "_fileset": [7, 8, 9], "dict": [7, 9, 10, 18], "_defaultfileset": 7, "_vhdllibrari": [7, 9], "_vhdlversion": [7, 9, 10, 11], "vhdlversion": [7, 9, 10, 11, 17, 18], "_verilogvers": [7, 9, 10], "verilogvers": [7, 9, 10, 17, 18], "_svversion": [7, 9, 10], "systemverilogvers": [7, 9, 10, 18], "_externalvhdllibrari": 7, "def": [7, 8, 9, 10, 11], "__init__": [7, 8, 9, 10, 11, 17, 18, 21], "self": [7, 8, 9, 10, 11, 18], "directori": [7, 9, 17, 18], "svversion": [7, 9, 10, 17, 18], "properti": [7, 8, 9, 10, 11, 18], "setter": [7, 8, 9, 10, 11], "valu": [7, 8, 9, 10, 11, 18, 30], "resolvedpath": [7, 8, 9, 10, 17, 18], "defaultfileset": [7, 17, 18], "filetyp": [7, 8, 9, 17, 18], "externalvhdllibrari": 7, "addfileset": [7, 17, 18], "iter": [7, 9, 18], "addfil": [7, 9, 17, 18], "metaclass": [8, 18], "_path": 8, "_design": [8, 9, 10, 11], "_parent": 9, "_file": [9, 11], "parent": [9, 12, 17, 18], "_rootdirectori": 10, "rootdirectori": [10, 17, 18], "primari": [11, 18], "semant": 12, "child": 12, "overal": 12, "hierarchi": 12, "multipl": [12, 15, 18], "variant": [12, 18], "usual": 12, "element": 12, "placehold": [13, 34], "abstract": [15, 18], "model": 15, "hdl": [15, 18], "tool": [15, 18, 26, 27, 32], "unifi": 15, "framework": 15, "implement": [15, 18], "logic": 15, "concret": 15, "consum": 15, "higher": 15, "level": 15, "featur": 15, "top": 15, "input": 15, "open": 15, "simul": [15, 18, 22], "synthesi": 15, "ghdl": [15, 17, 18], "icaru": 15, "veril": 15, "yosi": 15, "rout": 15, "vtr": 15, "nextpnr": 15, "etc": 15, "ip": [15, 33], "core": [15, 33], "xilinx": [15, 17, 18], "vivado": [15, 17, 18, 31], "osvvm": [15, 17, 18], "nest": [15, 18], "dataset": 15, "valid": [15, 17, 18], "becam": 15, "first": [15, 18], "citizen": 15, "eda\u00b2": 15, "got": 15, "patrick": 15, "lehmann": 15, "unai": 15, "martinez": 15, "corral": 15, "accompani": 15, "creativ": 15, "13": 15, "aug": 15, "2023": 15, "23": 15, "53": 15, "modul": 17, "altera": [17, 18], "quartu": [17, 18, 19, 24], "keyvalueattribut": [17, 18, 21], "intel": [17, 18], "quartusprim": [17, 18, 23], "mentorgraph": [17, 18], "modelsim": [17, 18, 25], "questasim": [17, 18, 25], "ISE": [17, 18, 31], "usedinattribut": [17, 18, 31, 33], "__new__": [17, 18], "__base__": [17, 18], "__call__": [17, 18], "__delattr__": [17, 18], "__dir__": [17, 18], "__getattribute__": [17, 18], "__instancecheck__": [17, 18], "__or__": [17, 18], "__prepare__": [17, 18], "__repr__": [17, 18], "__ror__": [17, 18], "__setattr__": [17, 18], "__sizeof__": [17, 18], "__subclasscheck__": [17, 18], "__subclasses__": [17, 18], "__text_signature__": [17, 18], "_checkforabstractmethod": [17, 18], "_iteratebaseclasspath": [17, 18], "_wrapnewmethodifabstract": [17, 18], "_wrapnewmethodifsingleton": [17, 18], "mro": [17, 18], "humanreadablecont": [17, 18], "xmlcontent": [17, 18], "yamlcont": [17, 18], "jsoncont": [17, 18], "inicont": [17, 18], "tomlcont": [17, 18], "tclcontent": [17, 18], "sdccontent": [17, 18], "pythoncont": [17, 18], "toplevel": [17, 18], "filesetcount": [17, 18], "totalfilesetcount": [17, 18], "filecount": [17, 18], "totalfilecount": [17, 18], "__len__": [17, 18], "__getitem__": [17, 18], "__setitem__": [17, 18], "__str__": [17, 18], "designcount": [17, 18], "submodul": [18, 19, 23, 25, 31], "undocu": [18, 21, 33], "construct": 18, "human": 18, "xml": [18, 33], "yaml": 18, "json": 18, "ini": 18, "toml": 18, "tcl": 18, "synopsi": [18, 20, 24], "constraint": [18, 20, 24, 32, 33], "sdc": [18, 20, 24], "textfil": 18, "logfil": 18, "log": 18, "xmlfile": 18, "sourcefil": 18, "hdlsourcefil": 18, "rdlsourcefil": 18, "rdl": 18, "netlistfil": 18, "netlist": 18, "edifnetlistfil": 18, "edif": 18, "interchang": 18, "tclsourcefil": 18, "vhdlsourcefil": [18, 33], "verilogbasefil": 18, "verilogsourcefil": [18, 33], "verilogheaderfil": 18, "header": 18, "systemverilogbasefil": 18, "systemverilogsourcefil": 18, "systemverilog": 18, "systemverilogheaderfil": 18, "systemrdlsourcefil": 18, "systemrdl": 18, "pythonsourcefil": 18, "cocotbpythonfil": 18, "cocotb": 18, "constraintfil": [18, 33], "projectfil": 18, "csourcefil": 18, "ansi": 18, "c": 18, "cppsourcefil": 18, "settingfil": 18, "simulationanalysisfil": 18, "analysi": 18, "simulationelaborationfil": 18, "simulationstartfil": 18, "start": 18, "up": 18, "simulationrunfil": 18, "run": 18, "waveformconfigfil": 18, "waveform": [18, 22, 26, 27, 30], "waveformdatabasefil": 18, "databas": 18, "waveformexchangefil": 18, "exchang": [18, 30], "therein": 18, "inherit": [18, 21, 33], "dictionari": 18, "kwarg": 18, "done": 18, "regist": 18, "extendedtyp": 18, "paramet": 18, "classmemb": 18, "ghdlwaveformfil": [18, 22], "ipcoredescriptionfil": [18, 33], "ipcoreinstantiationfil": [18, 33], "iseprojectfil": [18, 32], "modelsiminifil": [18, 26, 27], "modelsimprojectfil": [18, 26, 27], "osvvmprojectfil": [18, 28], "quartusprojectfil": [18, 20, 24], "sdcconstraintfil": [18, 20, 24], "ucfconstraintfil": [18, 32], "valuechangedumpfil": [18, 30], "vivadoprojectfil": [18, 33], "wavedofil": [18, 26, 27], "xdcconstraintfil": [18, 33], "tupl": 18, "cl": 18, "classnam": 18, "baseclass": 18, "arg": 18, "new": 18, "slot": 18, "true": 18, "store": 18, "__slots__": 18, "instead": 18, "__dict__": 18, "mixin": 18, "fals": 18, "preserv": 18, "behavior": 18, "singleton": 18, "return": 18, "rais": 18, "attributeerror": 18, "alreadi": 18, "alia": 18, "call": 18, "function": 18, "delattr": 18, "getattr": 18, "check": 18, "classmethod": 18, "bool": 18, "repr": 18, "setattr": 18, "memori": 18, "consumpt": 18, "subclass": 18, "immedi": 18, "current": 18, "method": 18, "might": 18, "overridden": 18, "callabl": 18, "left": 18, "item": 18, "newclass": 18, "_new__": 18, "newli": 18, "abstractclasserror": 18, "instanti": [18, 33], "wrap": 18, "cach": 18, "creation": 18, "initi": 18, "threadsaf": 18, "singl": 18, "resolut": 18, "order": 18, "posixpath": 18, "srdlversion": 18, "insert": 18, "standalon": 18, "later": 18, "anoth": 18, "Or": 18, "rel": 18, "option": 18, "itself": 18, "systemrdlvers": 18, "locat": 18, "resolv": 18, "filter": 18, "handl": 18, "int": 18, "number": 18, "excl": 18, "incl": 18, "kei": 18, "index": 18, "overlai": 18, "structur": 18, "root": 18, "qpf": [20, 24], "ghw": 22, "pro": 28, "vcd": 30, "std": 30, "1364": 30, "xpr": 33, "xdc": 33, "ipcor": 33, "xci": 33}, "objects": {"pyEDAA": [[18, 0, 0, "-", "ProjectModel"]], "pyEDAA.ProjectModel": [[19, 0, 0, "-", "Altera"], [18, 1, 1, "", "Attribute"], [21, 0, 0, "-", "Attributes"], [18, 1, 1, "", "Design"], [18, 1, 1, "", "FileSet"], [18, 1, 1, "", "FileType"], [22, 0, 0, "-", "GHDL"], [18, 1, 1, "", "HumanReadableContent"], [18, 1, 1, "", "INIContent"], [23, 0, 0, "-", "Intel"], [18, 1, 1, "", "JSONContent"], [25, 0, 0, "-", "MentorGraphics"], [28, 0, 0, "-", "OSVVM"], [18, 1, 1, "", "Project"], [18, 1, 1, "", "PythonContent"], [18, 1, 1, "", "SDCContent"], [18, 1, 1, "", "TCLContent"], [18, 1, 1, "", "TOMLContent"], [29, 0, 0, "-", "VHDL"], [18, 1, 1, "", "VHDLLibrary"], [30, 0, 0, "-", "Verilog"], [18, 1, 1, "", "XMLContent"], [31, 0, 0, "-", "Xilinx"], [18, 1, 1, "", "YAMLContent"]], "pyEDAA.ProjectModel.Altera": [[20, 0, 0, "-", "Quartus"]], "pyEDAA.ProjectModel.Attributes": [[21, 1, 1, "", "KeyValueAttribute"]], "pyEDAA.ProjectModel.Attributes.KeyValueAttribute": [[21, 2, 1, "", "__init__"]], "pyEDAA.ProjectModel.Design": [[18, 3, 1, "", "DefaultFileSet"], [18, 3, 1, "", "Directory"], [18, 3, 1, "", "FileSetCount"], [18, 3, 1, "", "FileSets"], [18, 2, 1, "", "Files"], [18, 3, 1, "", "Name"], [18, 3, 1, "", "Project"], [18, 3, 1, "", "ResolvedPath"], [18, 3, 1, "", "TopLevel"], [18, 3, 1, "", "TotalFileSetCount"], [18, 2, 1, "", "Validate"], [18, 2, 1, "", "__init__"], [18, 2, 1, "", "__len__"], [18, 2, 1, "", "__str__"]], "pyEDAA.ProjectModel.FileSet": [[18, 2, 1, "", "AddFile"], [18, 2, 1, "", "AddFileSet"], [18, 2, 1, "", "AddFileSets"], [18, 2, 1, "", "AddFiles"], [18, 3, 1, "", "Design"], [18, 3, 1, "", "Directory"], [18, 3, 1, "", "FileCount"], [18, 3, 1, "", "FileSetCount"], [18, 3, 1, "", "FileSets"], [18, 2, 1, "", "Files"], [18, 3, 1, "", "Name"], [18, 3, 1, "", "Parent"], [18, 3, 1, "", "Project"], [18, 3, 1, "", "ResolvedPath"], [18, 3, 1, "", "SVVersion"], [18, 3, 1, "", "TopLevel"], [18, 3, 1, "", "TotalFileCount"], [18, 3, 1, "", "TotalFileSetCount"], [18, 3, 1, "", "VHDLLibrary"], [18, 3, 1, "", "VHDLVersion"], [18, 2, 1, "", "Validate"], [18, 3, 1, "", "VerilogVersion"], [18, 2, 1, "", "__getitem__"], [18, 2, 1, "", "__init__"], [18, 2, 1, "", "__len__"], [18, 2, 1, "", "__setitem__"], [18, 2, 1, "", "__str__"]], "pyEDAA.ProjectModel.FileType": [[18, 4, 1, "", "FileTypes"], [18, 4, 1, "", "__base__"], [18, 2, 1, "", "__call__"], [18, 2, 1, "", "__delattr__"], [18, 2, 1, "", "__dir__"], [18, 2, 1, "", "__getattribute__"], [18, 2, 1, "", "__init__"], [18, 2, 1, "", "__instancecheck__"], [18, 2, 1, "", "__new__"], [18, 2, 1, "", "__or__"], [18, 2, 1, "", "__prepare__"], [18, 2, 1, "", "__repr__"], [18, 2, 1, "", "__ror__"], [18, 2, 1, "", "__setattr__"], [18, 2, 1, "", "__sizeof__"], [18, 2, 1, "", "__subclasscheck__"], [18, 2, 1, "", "__subclasses__"], [18, 4, 1, "", "__text_signature__"], [18, 2, 1, "", "_checkForAbstractMethods"], [18, 2, 1, "", "_iterateBaseClassPaths"], [18, 2, 1, "", "_wrapNewMethodIfAbstract"], [18, 2, 1, "", "_wrapNewMethodIfSingleton"], [18, 2, 1, "", "mro"]], "pyEDAA.ProjectModel.Intel": [[24, 0, 0, "-", "QuartusPrime"]], "pyEDAA.ProjectModel.MentorGraphics": [[26, 0, 0, "-", "ModelSim"], [27, 0, 0, "-", "QuestaSim"]], "pyEDAA.ProjectModel.Project": [[18, 3, 1, "", "DesignCount"], [18, 3, 1, "", "Name"], [18, 3, 1, "", "ResolvedPath"], [18, 3, 1, "", "RootDirectory"], [18, 2, 1, "", "Validate"], [18, 2, 1, "", "__init__"], [18, 2, 1, "", "__len__"], [18, 2, 1, "", "__str__"]], "pyEDAA.ProjectModel.VHDLLibrary": [[18, 3, 1, "", "Design"], [18, 3, 1, "", "FileCount"], [18, 3, 1, "", "Files"], [18, 3, 1, "", "Project"], [18, 3, 1, "", "VHDLVersion"], [18, 2, 1, "", "__init__"], [18, 2, 1, "", "__str__"]], "pyEDAA.ProjectModel.Xilinx": [[32, 0, 0, "-", "ISE"], [33, 0, 0, "-", "Vivado"]], "pyEDAA.ProjectModel.Xilinx.Vivado": [[33, 1, 1, "", "UsedInAttribute"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "attribute", "Python attribute"]}, "titleterms": {"changelog": 0, "upcom": 0, "releas": 0, "01": 0, "09": 0, "2021": [0, 15], "depend": 1, "pyedaa": [1, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33], "projectmodel": [1, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33], "packag": 1, "unit": 1, "test": 1, "coverag": [1, 13], "type": [1, 3, 34], "check": [1, 34], "option": 1, "sphinx": 1, "document": [1, 15], "publish": 1, "ci": 1, "server": 1, "onli": 1, "creativ": 2, "common": 2, "attribut": [2, 21], "4": [2, 6], "0": [2, 6], "intern": 2, "us": [2, 5, 15], "public": 2, "licens": [2, 6, 15], "section": 2, "1": [2, 6], "definit": [2, 6, 7, 8, 9, 10, 11], "2": [2, 6], "scope": 2, "3": [2, 6], "condit": 2, "sui": 2, "generi": 2, "databas": 2, "right": 2, "5": [2, 6], "disclaim": [2, 6], "warranti": [2, 6], "limit": [2, 6], "liabil": [2, 6], "6": [2, 6], "term": 2, "termin": 2, "7": [2, 6], "other": 2, "8": [2, 6], "interpret": 2, "file": [3, 8, 15], "content": 3, "overal": 3, "hierarchi": 3, "glossari": 4, "instal": 5, "updat": 5, "pip": 5, "from": [5, 15], "pypi": 5, "uninstal": 5, "local": 5, "directori": 5, "setup": 5, "py": 5, "legaci": 5, "apach": 6, "grant": 6, "copyright": 6, "patent": 6, "redistribut": 6, "submiss": 6, "contribut": 6, "trademark": 6, "9": 6, "accept": 6, "addit": 6, "design": 7, "todo": [7, 8, 9, 10, 11], "condens": [7, 8, 9, 10, 11], "class": [7, 8, 9, 10, 11, 17], "fileset": 9, "project": [10, 12], "vhdl": [11, 29], "librari": 11, "vhdllibrari": 11, "model": 12, "report": [13, 34], "index": [14, 16], "The": 15, "main": 15, "goal": 15, "case": 15, "new": 15, "oct": 15, "read": 15, "xpr": 15, "pro": 15, "sep": 15, "extract": 15, "pyipcmi": 15, "contributor": 15, "modul": 16, "python": 17, "refer": 17, "altera": [19, 20], "quartu": 20, "ghdl": 22, "intel": [23, 24], "quartusprim": 24, "mentorgraph": [25, 26, 27], "modelsim": 26, "questasim": 27, "osvvm": 28, "verilog": 30, "xilinx": [31, 32, 33], "ISE": 32, "vivado": 33, "static": 34}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.intersphinx": 1, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx": 58}, "alltitles": {"ChangeLog": [[0, "changelog"]], "Upcoming Release": [[0, "upcoming-release"]], "01.09.2021": [[0, "id1"]], "Dependency": [[1, "dependency"]], "pyEDAA.ProjectModel Package": [[1, "pyedaa-projectmodel-package"]], "Unit Testing / Coverage / Type Checking (Optional)": [[1, "unit-testing-coverage-type-checking-optional"]], "Sphinx Documentation (Optional)": [[1, "sphinx-documentation-optional"]], "Packaging (Optional)": [[1, "packaging-optional"]], "Publishing (CI-Server only)": [[1, "publishing-ci-server-only"]], "Creative Commons Attribution 4.0 International": [[2, "creative-commons-attribution-4-0-international"]], "Using Creative Commons Public Licenses": [[2, null]], "Section 1 \u2013 Definitions.": [[2, "section-1-definitions"]], "Section 2 \u2013 Scope.": [[2, "section-2-scope"]], "Section 3 \u2013 License Conditions.": [[2, "section-3-license-conditions"]], "Section 4 \u2013 Sui Generis Database Rights.": [[2, "section-4-sui-generis-database-rights"]], "Section 5 \u2013 Disclaimer of Warranties and Limitation of Liability.": [[2, "section-5-disclaimer-of-warranties-and-limitation-of-liability"]], "Section 6 \u2013 Term and Termination.": [[2, "section-6-term-and-termination"]], "Section 7 \u2013 Other Terms and Conditions.": [[2, "section-7-other-terms-and-conditions"]], "Section 8 \u2013 Interpretation.": [[2, "section-8-interpretation"]], "File Types": [[3, "file-types"]], "Content Types": [[3, "content-types"]], "Overall Hierarchy": [[3, "overall-hierarchy"]], "Glossary": [[4, "glossary"]], "Installation/Updates": [[5, "installation-updates"]], "Using PIP": [[5, "using-pip"]], "Installation from PyPI using PIP": [[5, "installation-from-pypi-using-pip"]], "Updating from PyPI using PIP": [[5, "updating-from-pypi-using-pip"]], "Uninstallation using PIP": [[5, "uninstallation-using-pip"]], "Installation from local directory using PIP": [[5, "installation-from-local-directory-using-pip"]], "Using setup.py (legacy)": [[5, "using-setup-py-legacy"]], "Installation using setup.py": [[5, "installation-using-setup-py"]], "Apache License 2.0": [[6, "apache-license-2-0"]], "1. Definitions.": [[6, "definitions"]], "2. Grant of Copyright License.": [[6, "grant-of-copyright-license"]], "3. Grant of Patent License.": [[6, "grant-of-patent-license"]], "4. Redistribution.": [[6, "redistribution"]], "5. Submission of Contributions.": [[6, "submission-of-contributions"]], "6. Trademarks.": [[6, "trademarks"]], "7. Disclaimer of Warranty.": [[6, "disclaimer-of-warranty"]], "8. Limitation of Liability.": [[6, "limitation-of-liability"]], "9. Accepting Warranty or Additional Liability.": [[6, "accepting-warranty-or-additional-liability"]], "Design": [[7, "design"]], "Todo": [[7, "id1"], [8, "id1"], [9, "id1"], [10, "id1"], [11, "id1"]], "Condensed definition of class Design": [[7, "condensed-definition-of-class-design"]], "File": [[8, "file"]], "Condensed definition of class File": [[8, "condensed-definition-of-class-file"]], "FileSet": [[9, "fileset"]], "Condensed definition of class FileSet": [[9, "condensed-definition-of-class-fileset"]], "Project": [[10, "project"]], "Condensed definition of class Project": [[10, "condensed-definition-of-class-project"]], "VHDL Library": [[11, "vhdl-library"]], "Condensed definition of class VHDLLibrary": [[11, "condensed-definition-of-class-vhdllibrary"]], "Project Model": [[12, "project-model"]], "Coverage Report": [[13, "coverage-report"]], "Index": [[14, "index"]], "The pyEDAA.ProjectModel Documentation": [[15, "the-pyedaa-projectmodel-documentation"]], "Main Goals": [[15, "main-goals"]], "Use Cases": [[15, "use-cases"]], "News": [[15, "news"]], "Oct. 2021 - Reading *.xpr and *.pro Files": [[15, "oct-2021-reading-xpr-and-pro-files"]], "Sep. 2021 - Extracted ProjectModel from pyIPCMI": [[15, "sep-2021-extracted-projectmodel-from-pyipcmi"]], "Contributors": [[15, "contributors"]], "License": [[15, "license"]], "Module Index": [[16, "module-index"]], "Python Class Reference": [[17, "python-class-reference"]], "pyEDAA.ProjectModel": [[18, "module-pyEDAA.ProjectModel"]], "pyEDAA.ProjectModel.Altera": [[19, "module-pyEDAA.ProjectModel.Altera"]], "pyEDAA.ProjectModel.Altera.Quartus": [[20, "module-pyEDAA.ProjectModel.Altera.Quartus"]], "pyEDAA.ProjectModel.Attributes": [[21, "module-pyEDAA.ProjectModel.Attributes"]], "pyEDAA.ProjectModel.GHDL": [[22, "module-pyEDAA.ProjectModel.GHDL"]], "pyEDAA.ProjectModel.Intel": [[23, "module-pyEDAA.ProjectModel.Intel"]], "pyEDAA.ProjectModel.Intel.QuartusPrime": [[24, "module-pyEDAA.ProjectModel.Intel.QuartusPrime"]], "pyEDAA.ProjectModel.MentorGraphics": [[25, "module-pyEDAA.ProjectModel.MentorGraphics"]], "pyEDAA.ProjectModel.MentorGraphics.ModelSim": [[26, "module-pyEDAA.ProjectModel.MentorGraphics.ModelSim"]], "pyEDAA.ProjectModel.MentorGraphics.QuestaSim": [[27, "module-pyEDAA.ProjectModel.MentorGraphics.QuestaSim"]], "pyEDAA.ProjectModel.OSVVM": [[28, "module-pyEDAA.ProjectModel.OSVVM"]], "pyEDAA.ProjectModel.VHDL": [[29, "module-pyEDAA.ProjectModel.VHDL"]], "pyEDAA.ProjectModel.Verilog": [[30, "module-pyEDAA.ProjectModel.Verilog"]], "pyEDAA.ProjectModel.Xilinx": [[31, "module-pyEDAA.ProjectModel.Xilinx"]], "pyEDAA.ProjectModel.Xilinx.ISE": [[32, "module-pyEDAA.ProjectModel.Xilinx.ISE"]], "pyEDAA.ProjectModel.Xilinx.Vivado": [[33, "module-pyEDAA.ProjectModel.Xilinx.Vivado"]], "Static Type Checking Report": [[34, "static-type-checking-report"]]}, "indexentries": {"default fileset": [[4, "term-Default-fileset"]], "design": [[4, "term-Design"]], "file": [[4, "term-File"]], "fileset": [[4, "term-FileSet"]], "lrm": [[4, "term-LRM"]], "project": [[4, "term-Project"]], "vhdllibrary": [[4, "term-VHDLLibrary"]], "base-class": [[4, "term-base-class"]], "addfile() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.AddFile"]], "addfileset() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.AddFileSet"]], "addfilesets() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.AddFileSets"]], "addfiles() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.AddFiles"]], "attribute (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.Attribute"]], "defaultfileset (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.DefaultFileSet"]], "design (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.Design"]], "design (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.Design"]], "design (pyedaa.projectmodel.vhdllibrary property)": [[18, "pyEDAA.ProjectModel.VHDLLibrary.Design"]], "designcount (pyedaa.projectmodel.project property)": [[18, "pyEDAA.ProjectModel.Project.DesignCount"]], "directory (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.Directory"]], "directory (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.Directory"]], "filecount (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.FileCount"]], "filecount (pyedaa.projectmodel.vhdllibrary property)": [[18, "pyEDAA.ProjectModel.VHDLLibrary.FileCount"]], "fileset (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.FileSet"]], "filesetcount (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.FileSetCount"]], "filesetcount (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.FileSetCount"]], "filesets (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.FileSets"]], "filesets (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.FileSets"]], "filetype (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.FileType"]], "filetypes (pyedaa.projectmodel.filetype attribute)": [[18, "pyEDAA.ProjectModel.FileType.FileTypes"]], "files (pyedaa.projectmodel.vhdllibrary property)": [[18, "pyEDAA.ProjectModel.VHDLLibrary.Files"]], "files() (pyedaa.projectmodel.design method)": [[18, "pyEDAA.ProjectModel.Design.Files"]], "files() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.Files"]], "humanreadablecontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.HumanReadableContent"]], "inicontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.INIContent"]], "jsoncontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.JSONContent"]], "name (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.Name"]], "name (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.Name"]], "name (pyedaa.projectmodel.project property)": [[18, "pyEDAA.ProjectModel.Project.Name"]], "parent (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.Parent"]], "project (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.Project"]], "project (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.Project"]], "project (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.Project"]], "project (pyedaa.projectmodel.vhdllibrary property)": [[18, "pyEDAA.ProjectModel.VHDLLibrary.Project"]], "pythoncontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.PythonContent"]], "resolvedpath (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.ResolvedPath"]], "resolvedpath (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.ResolvedPath"]], "resolvedpath (pyedaa.projectmodel.project property)": [[18, "pyEDAA.ProjectModel.Project.ResolvedPath"]], "rootdirectory (pyedaa.projectmodel.project property)": [[18, "pyEDAA.ProjectModel.Project.RootDirectory"]], "sdccontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.SDCContent"]], "svversion (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.SVVersion"]], "tclcontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.TCLContent"]], "tomlcontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.TOMLContent"]], "toplevel (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.TopLevel"]], "toplevel (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.TopLevel"]], "totalfilecount (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.TotalFileCount"]], "totalfilesetcount (pyedaa.projectmodel.design property)": [[18, "pyEDAA.ProjectModel.Design.TotalFileSetCount"]], "totalfilesetcount (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.TotalFileSetCount"]], "vhdllibrary (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.VHDLLibrary"]], "vhdllibrary (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.VHDLLibrary"]], "vhdlversion (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.VHDLVersion"]], "vhdlversion (pyedaa.projectmodel.vhdllibrary property)": [[18, "pyEDAA.ProjectModel.VHDLLibrary.VHDLVersion"]], "validate() (pyedaa.projectmodel.design method)": [[18, "pyEDAA.ProjectModel.Design.Validate"]], "validate() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.Validate"]], "validate() (pyedaa.projectmodel.project method)": [[18, "pyEDAA.ProjectModel.Project.Validate"]], "verilogversion (pyedaa.projectmodel.fileset property)": [[18, "pyEDAA.ProjectModel.FileSet.VerilogVersion"]], "xmlcontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.XMLContent"]], "yamlcontent (class in pyedaa.projectmodel)": [[18, "pyEDAA.ProjectModel.YAMLContent"]], "__base__ (pyedaa.projectmodel.filetype attribute)": [[18, "pyEDAA.ProjectModel.FileType.__base__"]], "__call__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__call__"]], "__delattr__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__delattr__"]], "__dir__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__dir__"]], "__getattribute__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__getattribute__"]], "__getitem__() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.__getitem__"]], "__init__() (pyedaa.projectmodel.design method)": [[18, "pyEDAA.ProjectModel.Design.__init__"]], "__init__() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.__init__"]], "__init__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__init__"]], "__init__() (pyedaa.projectmodel.project method)": [[18, "pyEDAA.ProjectModel.Project.__init__"]], "__init__() (pyedaa.projectmodel.vhdllibrary method)": [[18, "pyEDAA.ProjectModel.VHDLLibrary.__init__"]], "__instancecheck__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__instancecheck__"]], "__len__() (pyedaa.projectmodel.design method)": [[18, "pyEDAA.ProjectModel.Design.__len__"]], "__len__() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.__len__"]], "__len__() (pyedaa.projectmodel.project method)": [[18, "pyEDAA.ProjectModel.Project.__len__"]], "__new__() (pyedaa.projectmodel.filetype static method)": [[18, "pyEDAA.ProjectModel.FileType.__new__"]], "__or__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__or__"]], "__prepare__() (pyedaa.projectmodel.filetype class method)": [[18, "pyEDAA.ProjectModel.FileType.__prepare__"]], "__repr__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__repr__"]], "__ror__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__ror__"]], "__setattr__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__setattr__"]], "__setitem__() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.__setitem__"]], "__sizeof__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__sizeof__"]], "__str__() (pyedaa.projectmodel.design method)": [[18, "pyEDAA.ProjectModel.Design.__str__"]], "__str__() (pyedaa.projectmodel.fileset method)": [[18, "pyEDAA.ProjectModel.FileSet.__str__"]], "__str__() (pyedaa.projectmodel.project method)": [[18, "pyEDAA.ProjectModel.Project.__str__"]], "__str__() (pyedaa.projectmodel.vhdllibrary method)": [[18, "pyEDAA.ProjectModel.VHDLLibrary.__str__"]], "__subclasscheck__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__subclasscheck__"]], "__subclasses__() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.__subclasses__"]], "__text_signature__ (pyedaa.projectmodel.filetype attribute)": [[18, "pyEDAA.ProjectModel.FileType.__text_signature__"]], "_checkforabstractmethods() (pyedaa.projectmodel.filetype class method)": [[18, "pyEDAA.ProjectModel.FileType._checkForAbstractMethods"]], "_iteratebaseclasspaths() (pyedaa.projectmodel.filetype class method)": [[18, "pyEDAA.ProjectModel.FileType._iterateBaseClassPaths"]], "_wrapnewmethodifabstract() (pyedaa.projectmodel.filetype class method)": [[18, "pyEDAA.ProjectModel.FileType._wrapNewMethodIfAbstract"]], "_wrapnewmethodifsingleton() (pyedaa.projectmodel.filetype class method)": [[18, "pyEDAA.ProjectModel.FileType._wrapNewMethodIfSingleton"]], "module": [[18, "module-pyEDAA.ProjectModel"], [19, "module-pyEDAA.ProjectModel.Altera"], [20, "module-pyEDAA.ProjectModel.Altera.Quartus"], [21, "module-pyEDAA.ProjectModel.Attributes"], [22, "module-pyEDAA.ProjectModel.GHDL"], [23, "module-pyEDAA.ProjectModel.Intel"], [24, "module-pyEDAA.ProjectModel.Intel.QuartusPrime"], [25, "module-pyEDAA.ProjectModel.MentorGraphics"], [26, "module-pyEDAA.ProjectModel.MentorGraphics.ModelSim"], [27, "module-pyEDAA.ProjectModel.MentorGraphics.QuestaSim"], [28, "module-pyEDAA.ProjectModel.OSVVM"], [29, "module-pyEDAA.ProjectModel.VHDL"], [30, "module-pyEDAA.ProjectModel.Verilog"], [31, "module-pyEDAA.ProjectModel.Xilinx"], [32, "module-pyEDAA.ProjectModel.Xilinx.ISE"], [33, "module-pyEDAA.ProjectModel.Xilinx.Vivado"]], "mro() (pyedaa.projectmodel.filetype method)": [[18, "pyEDAA.ProjectModel.FileType.mro"]], "pyedaa.projectmodel": [[18, "module-pyEDAA.ProjectModel"]], "pyedaa.projectmodel.altera": [[19, "module-pyEDAA.ProjectModel.Altera"]], "pyedaa.projectmodel.altera.quartus": [[20, "module-pyEDAA.ProjectModel.Altera.Quartus"]], "keyvalueattribute (class in pyedaa.projectmodel.attributes)": [[21, "pyEDAA.ProjectModel.Attributes.KeyValueAttribute"]], "__init__() (pyedaa.projectmodel.attributes.keyvalueattribute method)": [[21, "pyEDAA.ProjectModel.Attributes.KeyValueAttribute.__init__"]], "pyedaa.projectmodel.attributes": [[21, "module-pyEDAA.ProjectModel.Attributes"]], "pyedaa.projectmodel.ghdl": [[22, "module-pyEDAA.ProjectModel.GHDL"]], "pyedaa.projectmodel.intel": [[23, "module-pyEDAA.ProjectModel.Intel"]], "pyedaa.projectmodel.intel.quartusprime": [[24, "module-pyEDAA.ProjectModel.Intel.QuartusPrime"]], "pyedaa.projectmodel.mentorgraphics": [[25, "module-pyEDAA.ProjectModel.MentorGraphics"]], "pyedaa.projectmodel.mentorgraphics.modelsim": [[26, "module-pyEDAA.ProjectModel.MentorGraphics.ModelSim"]], "pyedaa.projectmodel.mentorgraphics.questasim": [[27, "module-pyEDAA.ProjectModel.MentorGraphics.QuestaSim"]], "pyedaa.projectmodel.osvvm": [[28, "module-pyEDAA.ProjectModel.OSVVM"]], "pyedaa.projectmodel.vhdl": [[29, "module-pyEDAA.ProjectModel.VHDL"]], "pyedaa.projectmodel.verilog": [[30, "module-pyEDAA.ProjectModel.Verilog"]], "pyedaa.projectmodel.xilinx": [[31, "module-pyEDAA.ProjectModel.Xilinx"]], "pyedaa.projectmodel.xilinx.ise": [[32, "module-pyEDAA.ProjectModel.Xilinx.ISE"]], "usedinattribute (class in pyedaa.projectmodel.xilinx.vivado)": [[33, "pyEDAA.ProjectModel.Xilinx.Vivado.UsedInAttribute"]], "pyedaa.projectmodel.xilinx.vivado": [[33, "module-pyEDAA.ProjectModel.Xilinx.Vivado"]]}})
\ No newline at end of file
diff --git a/typing/html/ProjectModel/Altera/Quartus.py.html b/typing/html/ProjectModel/Altera/Quartus.py.html
new file mode 100644
index 00000000..f1b492ae
--- /dev/null
+++ b/typing/html/ProjectModel/Altera/Quartus.py.html
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for Altera Quartus.""" +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import ConstraintFile, ProjectFile, SDCContent, TCLContent + + +@export +class QuartusProjectFile(ProjectFile, TCLContent): + """A Quartus project file (``*.qpf``).""" + + +@export +class SDCConstraintFile(ConstraintFile, SDCContent): + """A Quartus constraint file (Synopsys Design Constraints; ``*.sdc``).""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""A vendor specific package for Altera (now Intel FPGA).""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""A set of common attributes to store meta information on ProjectModel entities (project, design, fileset, file, ...).""" +from typing import Dict +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import Attribute + + +@export +class KeyValueAttribute(Attribute): + KEY = "ID" + + _keyValuePairs: Dict[str, str] + + def __init__(self): + super().__init__() + + self._keyValuePairs = {} + + def __getitem__(self, item: str) -> str: + return self._keyValuePairs[item] + + def __setitem__(self, key: str, value: str) -> None: + self._keyValuePairs[key] = value + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for `GHDL <https://github.com/ghdl>`__.""" +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import WaveformExchangeFile + + +@export +class GHDLWaveformFile(WaveformExchangeFile): + """GHDL's waveform file (``*.ghw``) supporting VHDL and Verilog simulation results.""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for Intel FPGA Quartus Prime.""" +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import ConstraintFile, ProjectFile, SDCContent, TCLContent + + +@export +class QuartusProjectFile(ProjectFile, TCLContent): + """A Quartus project file (``*.qpf``).""" + + +@export +class SDCConstraintFile(ConstraintFile, SDCContent): + """A Quartus constraint file (Synopsys Design Constraints; ``*.sdc``).""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""A vendor specific package for Intel FPGA (formerly Altera).""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for Mentor Graphics ModelSim.""" +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import ProjectFile, SettingFile, INIContent, WaveformConfigFile, TCLContent + + +@export +class ModelSimProjectFile(ProjectFile): + pass + + +@export +class ModelSimINIFile(SettingFile, INIContent): + pass + + +@export +class WaveDoFile(WaveformConfigFile, TCLContent): + pass + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for Mentor Graphics QuestaSim.""" +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import ProjectFile, SettingFile, INIContent, WaveformConfigFile, TCLContent + + +@export +class ModelSimProjectFile(ProjectFile): + pass + + +@export +class ModelSimINIFile(SettingFile, INIContent): + pass + + +@export +class WaveDoFile(WaveformConfigFile, TCLContent): + pass + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""A vendor specific package for Mentor Graphics (now Siemens EDA).""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for `OSVVM <https://github.com/OSVVM>`__.""" +from pathlib import Path + +from pyTooling.Decorators import export +from typing import Optional as Nullable, List + +from pyEDAA.ProjectModel import ProjectFile, TCLContent, Project, Design, FileSet, VHDLLibrary, VHDLSourceFile + + +@export +class OSVVMProjectFile(ProjectFile, TCLContent): + """An OSVVM project file (``*.pro``).""" + + _osvvmProject: Nullable[Project] + + def __init__( + self, + path: Path, + project: Project = None, + design: Design = None, + fileSet: FileSet = None + ): + super().__init__(path, project, design, fileSet) + + self._osvvmProject = None + + @property + def ProjectModel(self) -> Project: + return self._osvvmProject + + class Instruction: + _line: int + + def __init__(self, line: int): + self._line = line + + class Empty(Instruction): + def __init__(self, line: int): + super().__init__(line) + + class Comment(Instruction): + _commentText: str + + def __init__(self, line: int, commentText: str): + super().__init__(line) + self._commentText = commentText.rstrip() + + @property + def CommentText(self) -> str: + return self._commentText + + class Analyze(Instruction): + _vhdlSourceFile: VHDLSourceFile + + def __init__(self, line: int, parameterText: str): + super().__init__(line) + self._vhdlSourceFile = VHDLSourceFile(Path(parameterText.strip())) + + @property + def VHDLSourceFile(self) -> VHDLSourceFile: + return self._vhdlSourceFile + + class Library(Instruction): + _vhdlLibrary: VHDLLibrary + + def __init__(self, line: int, parameterText: str): + super().__init__(line) + self._vhdlLibrary = VHDLLibrary(parameterText.strip()) + + @property + def VHDLLibrary(self) -> VHDLLibrary: + return self._vhdlLibrary + + class Include(Instruction): + _osvvmProjectFile: 'OSVVMProjectFile' + _fileSet: FileSet + + def __init__(self, line: int, workingDirectory: Path, parameterText: str): + super().__init__(line) + + includeFile = Path(parameterText.strip()) + includePath = (workingDirectory / includeFile).resolve() + + self._fileSet = FileSet(includeFile.name, directory=includeFile.parent) + self._osvvmProjectFile = OSVVMProjectFile(includePath) + + @property + def OSVVMProjectFile(self) -> 'OSVVMProjectFile': + return self._osvvmProjectFile + + def Parse(self, fileSet: FileSet): + self._fileSet.Parent = fileSet + + for instruction in self._osvvmProjectFile._Parse(): + if isinstance(instruction, OSVVMProjectFile.Include): + instruction.Parse(self._fileSet) + elif isinstance(instruction, OSVVMProjectFile.Analyze): + self._fileSet.AddFile(instruction.VHDLSourceFile) + elif isinstance(instruction, OSVVMProjectFile.Library): + self._fileSet.Design.AddVHDLLibrary(instruction.VHDLLibrary) +# elif isinstance(instruction, OSVVMProjectFile.Build): + + elif not isinstance(instruction, (OSVVMProjectFile.Empty, OSVVMProjectFile.Comment)): + raise Exception(f"Unknown instruction '{instruction.__class__.__name__}' in OSVVM project file '{self._osvvmProjectFile.ResolvedPath}'") + + def Parse(self): + projectName = self._path.name + self._osvvmProject = Project(projectName, rootDirectory=self._path.parent) + + fileSet = self._osvvmProject.DefaultDesign.DefaultFileSet + + for instruction in self._Parse(): + if isinstance(instruction, OSVVMProjectFile.Include): + instruction.Parse(fileSet) + elif isinstance(instruction, OSVVMProjectFile.Analyze): + fileSet.AddFile(instruction.VHDLSourceFile) + elif not isinstance(instruction, (OSVVMProjectFile.Empty, OSVVMProjectFile.Comment)): + raise Exception(f"Unknown instruction '{instruction.__class__.__name__}' in OSVVM project file '{self.ResolvedPath}'") + + def _Parse(self): + path = self.ResolvedPath + if not path.exists(): + raise Exception(f"OSVVM project file '{path}' not found.") from FileNotFoundError(f"File '{path}' not found.") + + instructions: List = [] + print() + with path.open("r") as file: + i = 1 + for line in file: + line = line.lstrip() + + if line.startswith("#"): + comment = OSVVMProjectFile.Comment(i, line[1:]) + instructions.append(comment) + + elif line.startswith("analyze"): + vhdlFile = OSVVMProjectFile.Analyze(i, line[8:]) + instructions.append(vhdlFile) + + elif line.startswith("library"): + vhdlLibrary = OSVVMProjectFile.Library(i, line[8:]) + instructions.append(vhdlLibrary) + + elif line.startswith("include"): + include = OSVVMProjectFile.Include(i, path.parent, line[8:]) + instructions.append(include) + + elif line.startswith("build"): + parameter = line[6:] + print(f"BUILD: {parameter}") + elif line.startswith("if"): + print(f"IF (line={i}): {line[3:].rstrip()}") + elif line.startswith("}"): + print(f"}} (line={i}): {line[2:].rstrip()}") + elif len(line) == 0: + instructions.append(OSVVMProjectFile.Empty(i)) + else: + print(f"UNKNOWN (line={i}): '{line.rstrip()}'") + + i += 1 + + return instructions + |
+
+ | + |
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for Verilog.""" +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import WaveformExchangeFile + + +@export +class ValueChangeDumpFile(WaveformExchangeFile): + """Verilog's waveform file (``*.vcd``) for exchanging value changes as defined by IEEE Std. 1364.""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for Xilinx ISE.""" +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import ConstraintFile, ProjectFile, HumanReadableContent + + +@export +class ISEProjectFile(ProjectFile): + pass + + +@export +class UCFConstraintFile(ConstraintFile, HumanReadableContent): + pass + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""Specific file types and attributes for Xilinx Vivado.""" +from pathlib import Path +from typing import Iterable + +from xml.dom import minidom, Node + +from pyTooling.MetaClasses import ExtendedType +from pyVHDLModel import VHDLVersion +from pyTooling.Decorators import export + +from pyEDAA.ProjectModel import ProjectFile, XMLFile, XMLContent, SDCContent, Project, FileSet, Attribute, Design +from pyEDAA.ProjectModel import File as Model_File +from pyEDAA.ProjectModel import ConstraintFile as Model_ConstraintFile +from pyEDAA.ProjectModel import VerilogSourceFile as Model_VerilogSourceFile +from pyEDAA.ProjectModel import VHDLSourceFile as Model_VHDLSourceFile + + +@export +class UsedInAttribute(Attribute): + KEY = "UsedIn" + VALUE_TYPE = Iterable[str] + + +@export +class File(Model_File): + pass + + +class VivadoFileMixIn(metaclass=ExtendedType, mixin=True): + def _registerAttributes(self): + self._attributes[UsedInAttribute] = [] + + +@export +class ConstraintFile(Model_ConstraintFile, VivadoFileMixIn): + def _registerAttributes(self): + super()._registerAttributes() + VivadoFileMixIn._registerAttributes(self) + + +@export +class VerilogSourceFile(Model_VerilogSourceFile): + def _registerAttributes(self): + super()._registerAttributes() + VivadoFileMixIn._registerAttributes(self) + + +@export +class VHDLSourceFile(Model_VHDLSourceFile): + def _registerAttributes(self): + super()._registerAttributes() + VivadoFileMixIn._registerAttributes(self) + + +@export +class VivadoProjectFile(ProjectFile, XMLContent): + """A Vivado project file (``*.xpr``).""" + + _xprProject: Project + + def __init__( + self, + path: Path, + project: Project = None, + design: Design = None, + fileSet: FileSet = None + ): + super().__init__(path, project, design, fileSet) + + self._xprProject = None + + @property + def ProjectModel(self) -> Project: + return self._xprProject + + def Parse(self): + if not self._path.exists(): + raise Exception(f"Vivado project file '{self._path!s}' not found.") from FileNotFoundError(f"File '{self._path!s}' not found.") + + try: + root = minidom.parse(str(self._path)).documentElement + except Exception as ex: + raise Exception(f"Couldn't open '{self._path!s}'.") from ex + + self._xprProject = Project(self._path.stem, rootDirectory=self._path.parent) + self._ParseRootElement(root) + + def _ParseRootElement(self, root): + for rootNode in root.childNodes: + if rootNode.nodeName == "FileSets": + self._ParseFileSets(rootNode) + break + + def _ParseFileSets(self, filesetsNode): + for fileSetsNode in filesetsNode.childNodes: + if fileSetsNode.nodeType == Node.ELEMENT_NODE and fileSetsNode.tagName == "FileSet": + self._ParseFileSet(fileSetsNode) + + def _ParseFileSet(self, filesetNode): + filesetName = filesetNode.getAttribute("Name") + fileset = FileSet(filesetName, design=self._xprProject.DefaultDesign) + + for fileNode in filesetNode.childNodes: + if fileNode.nodeType == Node.ELEMENT_NODE: + if fileNode.tagName == "File": + self._ParseFile(fileNode, fileset) + elif fileNode.nodeType == Node.ELEMENT_NODE and fileNode.tagName == "Config": + self._ParseFileSetConfig(fileNode, fileset) + + def _ParseFile(self, fileNode, fileset): + croppedPath = fileNode.getAttribute("Path").replace("$PPRDIR/", "") + filePath = Path(croppedPath) + if filePath.suffix in (".vhd", ".vhdl"): + self._ParseVHDLFile(fileNode, filePath, fileset) + elif filePath.suffix == ".xdc": + self._ParseXDCFile(fileNode, filePath, fileset) + elif filePath.suffix == ".v": + self._ParseVerilogFile(fileNode, filePath, fileset) + elif filePath.suffix == ".xci": + self._ParseXCIFile(fileNode, filePath, fileset) + else: + self._ParseDefaultFile(fileNode, filePath, fileset) + + def _ParseVHDLFile(self, fileNode, path, fileset): + vhdlFile = VHDLSourceFile(path) + fileset.AddFile(vhdlFile) + usedInAttr = vhdlFile[UsedInAttribute] + + for childNode in fileNode.childNodes: + if childNode.nodeType == Node.ELEMENT_NODE and childNode.tagName == "FileInfo": + if childNode.getAttribute("SFType") == "VHDL2008": + vhdlFile.VHDLVersion = VHDLVersion.VHDL2008 + else: + vhdlFile.VHDLVersion = VHDLVersion.VHDL93 + + for fileAttribute in childNode.childNodes: + if fileAttribute.nodeType == Node.ELEMENT_NODE and fileAttribute.tagName == "Attr": + if fileAttribute.getAttribute("Name") == "Library": + libraryName = fileAttribute.getAttribute("Val") + vhdlFile.VHDLLibrary = fileset.GetOrCreateVHDLLibrary(libraryName) + elif fileAttribute.getAttribute("Val") == "UsedIn": + usedInAttr.append(fileAttribute.getAttribute("Val")) + + def _ParseDefaultFile(self, _, path, fileset): + File(path, fileSet=fileset) + + def _ParseXDCFile(self, _, path, fileset): + XDCConstraintFile(path, fileSet=fileset) + + def _ParseVerilogFile(self, _, path, fileset): + VerilogSourceFile(path, fileSet=fileset) + + def _ParseXCIFile(self, _, path, fileset): + IPCoreInstantiationFile(path, fileSet=fileset) + + def _ParseFileSetConfig(self, fileNode, fileset): + for option in fileNode.childNodes: + if option.nodeType == Node.ELEMENT_NODE and option.tagName == "Option": + if option.getAttribute("Name") == "TopModule": + fileset.TopLevel = option.getAttribute("Val") + + +@export +class XDCConstraintFile(ConstraintFile, SDCContent): + """A Vivado constraint file (Xilinx Design Constraints; ``*.xdc``).""" + + +@export +class IPCoreDescriptionFile(XMLFile): + pass + + +@export +class IPCoreInstantiationFile(XMLFile): + """A Vivado IP core instantiation file (Xilinx IPCore Instance; ``*.xci``).""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""A vendor specific package for Xilinx.""" + |
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193 +1194 +1195 +1196 +1197 +1198 +1199 +1200 +1201 +1202 +1203 +1204 +1205 +1206 +1207 +1208 +1209 +1210 +1211 +1212 +1213 +1214 +1215 +1216 +1217 +1218 +1219 +1220 +1221 +1222 +1223 +1224 +1225 +1226 +1227 +1228 +1229 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +1240 +1241 +1242 +1243 +1244 +1245 +1246 +1247 +1248 +1249 +1250 +1251 +1252 +1253 +1254 +1255 +1256 +1257 +1258 +1259 +1260 +1261 +1262 +1263 +1264 +1265 +1266 +1267 +1268 +1269 +1270 +1271 +1272 +1273 +1274 +1275 +1276 +1277 +1278 +1279 +1280 +1281 +1282 +1283 +1284 +1285 +1286 +1287 +1288 +1289 +1290 +1291 +1292 +1293 +1294 +1295 +1296 +1297 +1298 +1299 +1300 +1301 +1302 +1303 +1304 +1305 +1306 +1307 +1308 +1309 +1310 +1311 +1312 +1313 +1314 +1315 +1316 +1317 +1318 +1319 +1320 +1321 +1322 +1323 +1324 +1325 +1326 +1327 +1328 +1329 +1330 +1331 +1332 +1333 +1334 +1335 +1336 +1337 +1338 +1339 +1340 +1341 +1342 +1343 +1344 +1345 +1346 +1347 +1348 +1349 +1350 +1351 +1352 +1353 +1354 +1355 +1356 +1357 +1358 +1359 +1360 +1361 +1362 +1363 +1364 +1365 +1366 +1367 +1368 +1369 +1370 +1371 +1372 +1373 +1374 +1375 +1376 +1377 +1378 +1379 +1380 +1381 +1382 +1383 +1384 +1385 +1386 +1387 +1388 +1389 +1390 +1391 +1392 +1393 +1394 +1395 +1396 +1397 +1398 +1399 +1400 +1401 +1402 +1403 +1404 +1405 +1406 +1407 +1408 +1409 +1410 +1411 +1412 +1413 +1414 +1415 +1416 +1417 +1418 +1419 +1420 +1421 +1422 +1423 +1424 +1425 +1426 +1427 +1428 +1429 +1430 +1431 +1432 +1433 +1434 +1435 +1436 +1437 +1438 +1439 +1440 +1441 +1442 +1443 +1444 +1445 +1446 +1447 +1448 +1449 +1450 +1451 +1452 +1453 +1454 +1455 +1456 +1457 +1458 +1459 +1460 +1461 +1462 +1463 +1464 +1465 +1466 +1467 +1468 +1469 +1470 +1471 +1472 +1473 +1474 +1475 +1476 +1477 +1478 +1479 +1480 +1481 +1482 +1483 +1484 +1485 +1486 +1487 +1488 +1489 +1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596 +1597 +1598 +1599 +1600 +1601 +1602 +1603 +1604 +1605 +1606 +1607 +1608 +1609 +1610 +1611 +1612 +1613 +1614 +1615 +1616 +1617 +1618 +1619 +1620 +1621 +1622 +1623 +1624 +1625 +1626 +1627 +1628 +1629 +1630 +1631 +1632 +1633 +1634 +1635 +1636 +1637 +1638 +1639 +1640 +1641 +1642 +1643 +1644 +1645 +1646 +1647 +1648 +1649 +1650 +1651 +1652 +1653 +1654 +1655 +1656 +1657 +1658 +1659 +1660 +1661 +1662 +1663 +1664 +1665 +1666 +1667 +1668 +1669 +1670 +1671 +1672 +1673 +1674 +1675 +1676 +1677 +1678 +1679 +1680 +1681 +1682 +1683 +1684 +1685 +1686 +1687 + |
+# ==================================================================================================================== # +# _____ ____ _ _ ____ _ _ __ __ _ _ # +# _ __ _ _| ____| _ \ / \ / \ | _ \ _ __ ___ (_) ___ ___| |_| \/ | ___ __| | ___| | # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) | '__/ _ \| |/ _ \/ __| __| |\/| |/ _ \ / _` |/ _ \ | # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| __/| | | (_) | | __/ (__| |_| | | | (_) | (_| | __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| |_| \___// |\___|\___|\__|_| |_|\___/ \__,_|\___|_| # +# |_| |___/ |__/ # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany # +# Copyright 2014-2016 Technische Universität Dresden - Germany, Chair of VLSI-Design, Diagnostics and Architecture # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +"""An abstract model of EDA tool projects.""" +__author__ = "Patrick Lehmann" +__email__ = "Paebbels@gmail.com" +__copyright__ = "2014-2023, Patrick Lehmann, Unai Martinez-Corral" +__license__ = "Apache License, Version 2.0" +__version__ = "0.5.0" +__keywords__ = ["eda project", "model", "abstract", "xilinx", "vivado", "osvvm", "file set", "file group", "test bench", "test harness"] + +from os.path import relpath as path_relpath +from pathlib import Path as pathlib_Path +from typing import Dict, Union, Optional as Nullable, List, Iterable, Generator, Tuple, Any as typing_Any, Type, Set, \ + Any + +from pyTooling.Decorators import export +from pyTooling.MetaClasses import ExtendedType +from pyTooling.Graph import Graph, Vertex +from pySVModel import SystemVerilogVersion +from pyVHDLModel import VHDLVersion +from pySystemRDLModel import SystemRDLVersion + + +@export +class Attribute(metaclass=ExtendedType): + KEY: str + VALUE_TYPE: typing_Any + + @staticmethod + def resolve(obj: typing_Any, key: Type['Attribute']): + if isinstance(obj, File): + return obj._fileSet[key] + elif isinstance(obj, FileSet): + return obj._design[key] + elif isinstance(obj, Design): + return obj._project[key] + else: + raise Exception("Resolution error") + + +@export +class FileType(ExtendedType): + """ + A :term:`meta-class` to construct *FileType* classes. + + Modifications done by this meta-class: + * Register all classes of type :class:`FileType` or derived variants in a class field :attr:`FileType.FileTypes` in this meta-class. + """ + + FileTypes: Dict[str, 'FileType'] = {} #: Dictionary of all classes of type :class:`FileType` or derived variants + Any: 'FileType' + + def __init__(cls, name: str, bases: Tuple[type, ...], dictionary: Dict[str, typing_Any], **kwargs): + super().__init__(name, bases, dictionary, **kwargs) + cls.Any = cls + + def __new__(cls, className, baseClasses, classMembers: Dict, *args, **kwargs): + fileType = super().__new__(cls, className, baseClasses, classMembers, *args, **kwargs) + cls.FileTypes[className] = fileType + return fileType + + def __getattr__(cls, item) -> 'FileType': + if item[:2] != "__" and item[-2:] != "__": + return cls.FileTypes[item] + else: + return super().__getattribute__(item) + + def __contains__(cls, item) -> bool: + return issubclass(item, cls) + + +@export +class File(metaclass=FileType, slots=True): + """ + A :term:`File` represents a file in a design. This :term:`base-class` is used + for all derived file classes. + + A file can be created standalone and later associated to a fileset, design and + project. Or a fileset, design and/or project can be associated immediately + while creating a file. + + :arg path: Relative or absolute path to the file. + :arg project: Project the file is associated with. + :arg design: Design the file is associated with. + :arg fileSet: Fileset the file is associated with. + """ + + _path: pathlib_Path + _fileType: 'FileType' + _project: Nullable['Project'] + _design: Nullable['Design'] + _fileSet: Nullable['FileSet'] + _attributes: Dict[Type[Attribute], typing_Any] + + def __init__( + self, + path: pathlib_Path, + project: 'Project' = None, + design: 'Design' = None, + fileSet: 'FileSet' = None + ): + self._fileType = getattr(FileTypes, self.__class__.__name__) + self._path = path + if project is not None: + self._project = project + self._design = design + if fileSet is not None: + self.FileSet = fileSet + elif design is not None: + self._project = design._project + self._design = design + self.FileSet = design.DefaultFileSet if fileSet is None else fileSet + elif fileSet is not None: + design = fileSet._design + if design is not None: + self._project = design._project + else: + self._project = None + self._design = design + self.FileSet = fileSet + else: + self._project = None + self._design = None + self._fileSet = None + + self._attributes = {} + self._registerAttributes() + + def _registerAttributes(self): + pass + + @property + def FileType(self) -> 'FileType': + """Read-only property to return the file type of this file.""" + return self._fileType + + @property + def Path(self) -> pathlib_Path: + """Read-only property returning the path of this file.""" + return self._path + + # TODO: setter? + + @property + def ResolvedPath(self) -> pathlib_Path: + """Read-only property returning the resolved path of this file.""" + if self._path.is_absolute(): + return self._path.resolve() + elif self._fileSet is not None: + path = (self._fileSet.ResolvedPath / self._path).resolve() + + if path.is_absolute(): + return path + else: + # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath + return pathlib_Path(path_relpath(path, pathlib_Path.cwd())) + else: + # TODO: message and exception type + raise Exception("") + + @property + def Project(self) -> Nullable['Project']: + """Property setting or returning the project this file is used in.""" + return self._project + + @Project.setter + def Project(self, value: 'Project') -> None: + self._project = value + + if self._fileSet is None: + self._project.DefaultDesign.DefaultFileSet.AddFile(self) + + @property + def Design(self) -> Nullable['Design']: + """Property setting or returning the design this file is used in.""" + return self._design + + @Design.setter + def Design(self, value: 'Design') -> None: + self._design = value + + if self._fileSet is None: + self._design.DefaultFileSet.AddFile(self) + + if self._project is None: + self._project = value._project + elif self._project is not value._project: + raise Exception("The design's project is not identical to the already assigned project.") + + @property + def FileSet(self) -> Nullable['FileSet']: + """Property setting or returning the fileset this file is used in.""" + return self._fileSet + + @FileSet.setter + def FileSet(self, value: 'FileSet') -> None: + self._fileSet = value + value._files.append(self) + + def Validate(self): + """Validate this file.""" + if self._path is None: + raise Exception("Validation: File has no path.") + try: + path = self.ResolvedPath + except Exception as ex: + raise Exception(f"Validation: File '{self._path}' could not compute resolved path.") from ex + if not path.exists(): + raise Exception(f"Validation: File '{self._path}' (={path}) does not exist.") + if not path.is_file(): + raise Exception(f"Validation: File '{self._path}' (={path}) is not a file.") + + if self._fileSet is None: + raise Exception(f"Validation: File '{self._path}' has no fileset.") + if self._design is None: + raise Exception(f"Validation: File '{self._path}' has no design.") + if self._project is None: + raise Exception(f"Validation: File '{self._path}' has no project.") + + def __len__(self) -> int: + return len(self._attributes) + + def __getitem__(self, key: Type[Attribute]) -> Any: + """Index access for returning attributes on this file.""" + if not issubclass(key, Attribute): + raise TypeError("Parameter 'key' is not an 'Attribute'.") + + try: + return self._attributes[key] + except KeyError: + return key.resolve(self, key) + + def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None: + """Index access for setting attributes on this file.""" + if not issubclass(key, Attribute): + raise TypeError("Parameter 'key' is not an 'Attribute'.") + + self._attributes[key] = value + + +FileTypes = File + + +@export +class HumanReadableContent(metaclass=ExtendedType, mixin=True): + """A file type representing human-readable contents.""" + + +@export +class XMLContent(HumanReadableContent, mixin=True): + """A file type representing XML contents.""" + + +@export +class YAMLContent(HumanReadableContent, mixin=True): + """A file type representing YAML contents.""" + + +@export +class JSONContent(HumanReadableContent, mixin=True): + """A file type representing JSON contents.""" + + +@export +class INIContent(HumanReadableContent, mixin=True): + """A file type representing INI contents.""" + + +@export +class TOMLContent(HumanReadableContent, mixin=True): + """A file type representing TOML contents.""" + + +@export +class TCLContent(HumanReadableContent, mixin=True): + """A file type representing content in TCL code.""" + + +@export +class SDCContent(TCLContent, mixin=True): + """A file type representing contents as Synopsys Design Constraints (SDC).""" + + +@export +class PythonContent(HumanReadableContent, mixin=True): + """A file type representing contents as Python source code.""" + + +@export +class TextFile(File, HumanReadableContent): + """A text file (``*.txt``).""" + + +@export +class LogFile(File, HumanReadableContent): + """A log file (``*.log``).""" + + +@export +class XMLFile(File, XMLContent): + """An XML file (``*.xml``).""" + + +@export +class SourceFile(File): + """Base-class of all source files.""" + + +@export +class HDLSourceFile(SourceFile): + """Base-class of all HDL source files.""" + + +@export +class RDLSourceFile(SourceFile): + """Base-class of all RDL source files.""" + + +@export +class NetlistFile(SourceFile): + """Base-class of all netlist source files.""" + + +@export +class EDIFNetlistFile(NetlistFile): + """Netlist file in EDIF (Electronic Design Interchange Format).""" + + +@export +class TCLSourceFile(SourceFile, TCLContent): + """A TCL source file.""" + + +@export +class VHDLSourceFile(HDLSourceFile, HumanReadableContent): + """ + A VHDL source file (of any language version). + + :arg path: Relative or absolute path to the file. + :arg vhdlLibrary: VHDLLibrary this VHDL source file is associated wih. + :arg vhdlVersion: VHDLVersion this VHDL source file is associated wih. + :arg project: Project the file is associated with. + :arg design: Design the file is associated with. + :arg fileSet: Fileset the file is associated with. + """ + + _vhdlLibrary: 'VHDLLibrary' + _vhdlVersion: VHDLVersion + + def __init__(self, path: pathlib_Path, vhdlLibrary: Union[str, 'VHDLLibrary'] = None, vhdlVersion: VHDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None): + super().__init__(path, project, design, fileSet) + + if isinstance(vhdlLibrary, str): + if design is not None: + try: + vhdlLibrary = design.VHDLLibraries[vhdlLibrary] + except KeyError as ex: + raise Exception(f"VHDL library '{vhdlLibrary}' not found in design '{design.Name}'.") from ex + elif project is not None: + try: + vhdlLibrary = project.DefaultDesign.VHDLLibraries[vhdlLibrary] + except KeyError as ex: + raise Exception(f"VHDL library '{vhdlLibrary}' not found in default design '{project.DefaultDesign.Name}'.") from ex + else: + raise Exception(f"Can't lookup VHDL library because neither 'project' nor 'design' is given as a parameter.") + elif isinstance(vhdlLibrary, VHDLLibrary): + self._vhdlLibrary = vhdlLibrary + vhdlLibrary.AddFile(self) + elif vhdlLibrary is None: + self._vhdlLibrary = None + else: + raise TypeError(f"Parameter 'vhdlLibrary' is neither a 'str' nor 'VHDLibrary'.") + + self._vhdlVersion = vhdlVersion + + def Validate(self) -> None: + """Validate this VHDL source file.""" + super().Validate() + + try: + _ = self.VHDLLibrary + except Exception as ex: + raise Exception(f"Validation: VHDLSourceFile '{self._path}' (={self.ResolvedPath}) has no VHDLLibrary assigned.") from ex + try: + _ = self.VHDLVersion + except Exception as ex: + raise Exception(f"Validation: VHDLSourceFile '{self._path}' (={self.ResolvedPath}) has no VHDLVersion assigned.") from ex + + @property + def VHDLLibrary(self) -> 'VHDLLibrary': + """Property setting or returning the VHDL library this VHDL source file is used in.""" + if self._vhdlLibrary is not None: + return self._vhdlLibrary + elif self._fileSet is not None: + return self._fileSet.VHDLLibrary + else: + raise Exception("VHDLLibrary was neither set locally nor globally.") + + @VHDLLibrary.setter + def VHDLLibrary(self, value: 'VHDLLibrary') -> None: + self._vhdlLibrary = value + value._files.append(self) + + @property + def VHDLVersion(self) -> VHDLVersion: + """Property setting or returning the VHDL version this VHDL source file is used in.""" + if self._vhdlVersion is not None: + return self._vhdlVersion + elif self._fileSet is not None: + return self._fileSet.VHDLVersion + else: + raise Exception("VHDLVersion was neither set locally nor globally.") + + @VHDLVersion.setter + def VHDLVersion(self, value: VHDLVersion) -> None: + self._vhdlVersion = value + + def __repr__(self) -> str: + return f"<VHDL file: '{self.ResolvedPath}'; lib: '{self.VHDLLibrary}'; version: {self.VHDLVersion}>" + + +class VerilogMixIn(metaclass=ExtendedType, mixin=True): + @property + def VerilogVersion(self) -> SystemVerilogVersion: + """Property setting or returning the Verilog version this Verilog source file is used in.""" + if self._version is not None: + return self._version + elif self._fileSet is not None: + return self._fileSet.VerilogVersion + else: + raise Exception("VerilogVersion was neither set locally nor globally.") + + @VerilogVersion.setter + def VerilogVersion(self, value: SystemVerilogVersion) -> None: + self._version = value + + +class SystemVerilogMixIn(metaclass=ExtendedType, mixin=True): + @property + def SVVersion(self) -> SystemVerilogVersion: + """Property setting or returning the SystemVerilog version this SystemVerilog source file is used in.""" + if self._version is not None: + return self._version + elif self._fileSet is not None: + return self._fileSet.SVVersion + else: + raise Exception("SVVersion was neither set locally nor globally.") + + @SVVersion.setter + def SVVersion(self, value: SystemVerilogVersion) -> None: + self._version = value + + +@export +class VerilogBaseFile(HDLSourceFile, HumanReadableContent): + _version: SystemVerilogVersion + + def __init__(self, path: pathlib_Path, version: SystemVerilogVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None): + super().__init__(path, project, design, fileSet) + + self._version = version + + +@export +class VerilogSourceFile(VerilogBaseFile, VerilogMixIn): + """A Verilog source file (of any language version).""" + + +@export +class VerilogHeaderFile(VerilogBaseFile, VerilogMixIn): + """A Verilog header file (of any language version).""" + + +@export +class SystemVerilogBaseFile(VerilogBaseFile): + ... + + +@export +class SystemVerilogSourceFile(SystemVerilogBaseFile, SystemVerilogMixIn): + """A SystemVerilog source file (of any language version).""" + + +@export +class SystemVerilogHeaderFile(SystemVerilogBaseFile, SystemVerilogMixIn): + """A SystemVerilog header file (of any language version).""" + + +@export +class SystemRDLSourceFile(RDLSourceFile, HumanReadableContent): + """A SystemRDL source file (of any language version).""" + + _srdlVersion: SystemRDLVersion + + def __init__(self, path: pathlib_Path, srdlVersion: SystemRDLVersion = None, project: 'Project' = None, design: 'Design' = None, fileSet: 'FileSet' = None): + super().__init__(path, project, design, fileSet) + + self._srdlVersion = srdlVersion + + @property + def SystemRDLVersion(self) -> SystemRDLVersion: + """Property setting or returning the SystemRDL version this SystemRDL source file is used in.""" + if self._srdlVersion is not None: + return self._srdlVersion + elif self._fileSet is not None: + return self._fileSet.SRDLVersion + else: + raise Exception("SRDLVersion was neither set locally nor globally.") + + @SystemRDLVersion.setter + def SystemRDLVersion(self, value: SystemRDLVersion) -> None: + self._srdlVersion = value + + +@export +class PythonSourceFile(SourceFile, PythonContent): + """A Python source file.""" + + +# TODO: move to a Cocotb module +@export +class CocotbPythonFile(PythonSourceFile): + """A Python source file used by Cocotb.""" + + +@export +class ConstraintFile(File, HumanReadableContent): + """Base-class of all constraint files.""" + + +@export +class ProjectFile(File): + """Base-class of all tool-specific project files.""" + + +@export +class CSourceFile(SourceFile): + """Base-class of all ANSI-C source files.""" + + +@export +class CppSourceFile(SourceFile): + """Base-class of all ANSI-C++ source files.""" + + +@export +class SettingFile(File): + """Base-class of all tool-specific setting files.""" + + +@export +class SimulationAnalysisFile(File): + """Base-class of all tool-specific analysis files.""" + + +@export +class SimulationElaborationFile(File): + """Base-class of all tool-specific elaboration files.""" + + +@export +class SimulationStartFile(File): + """Base-class of all tool-specific simulation start-up files.""" + + +@export +class SimulationRunFile(File): + """Base-class of all tool-specific simulation run (execution) files.""" + + +@export +class WaveformConfigFile(File): + """Base-class of all tool-specific waveform configuration files.""" + + +@export +class WaveformDatabaseFile(File): + """Base-class of all tool-specific waveform database files.""" + + +@export +class WaveformExchangeFile(File): + """Base-class of all tool-independent waveform exchange files.""" + + +@export +class FileSet(metaclass=ExtendedType, slots=True): + """ + A :term:`FileSet` represents a group of files. Filesets can have sub-filesets. + + The order of insertion is preserved. A fileset can be created standalone and + later associated to another fileset, design and/or project. Or a fileset, + design and/or project can be associated immediately while creating the + fileset. + + :arg name: Name of this fileset. + :arg topLevel: Name of the fileset's toplevel. + :arg directory: Path of this fileset (absolute or relative to a parent fileset or design). + :arg project: Project the file is associated with. + :arg design: Design the file is associated with. + :arg parent: Parent fileset if this fileset is nested. + :arg vhdlLibrary: Default VHDL library for files in this fileset, if not specified for the file itself. + :arg vhdlVersion: Default VHDL version for files in this fileset, if not specified for the file itself. + :arg verilogVersion: Default Verilog version for files in this fileset, if not specified for the file itself. + :arg svVersion: Default SystemVerilog version for files in this fileset, if not specified for the file itself. + :arg srdlVersion: Default SystemRDL version for files in this fileset, if not specified for the file itself. + """ + + _name: str + _topLevel: Nullable[str] + _project: Nullable['Project'] + _design: Nullable['Design'] + _directory: pathlib_Path + _parent: Nullable['FileSet'] + _fileSets: Dict[str, 'FileSet'] + _files: List[File] + _set: Set + _attributes: Dict[Type[Attribute], typing_Any] + _vhdlLibraries: Dict[str, 'VHDLLibrary'] + _vhdlLibrary: 'VHDLLibrary' + _vhdlVersion: VHDLVersion + _verilogVersion: SystemVerilogVersion + _svVersion: SystemVerilogVersion + _srdlVersion: SystemRDLVersion + + def __init__( + self, + name: str, + topLevel: str = None, + directory: pathlib_Path = pathlib_Path("."), + project: 'Project' = None, + design: 'Design' = None, + parent: Nullable['FileSet'] = None, + vhdlLibrary: Union[str, 'VHDLLibrary'] = None, + vhdlVersion: VHDLVersion = None, + verilogVersion: SystemVerilogVersion = None, + svVersion: SystemVerilogVersion = None, + srdlVersion: SystemRDLVersion = None + ): + self._name = name + self._topLevel = topLevel + if project is not None: + self._project = project + self._design = design if design is not None else project.DefaultDesign + + elif design is not None: + self._project = design._project + self._design = design + else: + self._project = None + self._design = None + self._directory = directory + self._parent = parent + self._fileSets = {} + self._files = [] + self._set = set() + + if design is not None: + design._fileSets[name] = self + + self._attributes = {} + self._vhdlLibraries = {} + + # TODO: handle if vhdlLibrary is a string + self._vhdlLibrary = vhdlLibrary + self._vhdlVersion = vhdlVersion + self._verilogVersion = verilogVersion + self._svVersion = svVersion + self._srdlVersion = srdlVersion + + @property + def Name(self) -> str: + """Property setting or returning the fileset's name.""" + return self._name + + @Name.setter + def Name(self, value: str) -> None: + self._name = value + + @property + def TopLevel(self) -> str: + """Property setting or returning the fileset's toplevel.""" + return self._topLevel + + @TopLevel.setter + def TopLevel(self, value: str) -> None: + self._topLevel = value + + @property + def Project(self) -> Nullable['Project']: + """Property setting or returning the project this fileset is used in.""" + return self._project + + @Project.setter + def Project(self, value: 'Project') -> None: + self._project = value + + @property + def Design(self) -> Nullable['Design']: + """Property setting or returning the design this fileset is used in.""" + if self._design is not None: + return self._design + elif self._parent is not None: + return self._parent.Design + else: + return None + # TODO: raise exception instead + # QUESTION: how to handle if design and parent is set? + + @Design.setter + def Design(self, value: 'Design') -> None: + self._design = value + if self._project is None: + self._project = value._project + elif self._project is not value._project: + raise Exception("The design's project is not identical to the already assigned project.") + + @property + def Directory(self) -> pathlib_Path: + """Property setting or returning the directory this fileset is located in.""" + return self._directory + + @Directory.setter + def Directory(self, value: pathlib_Path) -> None: + self._directory = value + + @property + def ResolvedPath(self) -> pathlib_Path: + """Read-only property returning the resolved path of this fileset.""" + if self._directory.is_absolute(): + return self._directory.resolve() + else: + if self._parent is not None: + directory = self._parent.ResolvedPath + elif self._design is not None: + directory = self._design.ResolvedPath + elif self._project is not None: + directory = self._project.ResolvedPath + else: + # TODO: message and exception type + raise Exception("") + + directory = (directory / self._directory).resolve() + if directory.is_absolute(): + return directory + else: + # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath + return pathlib_Path(path_relpath(directory, pathlib_Path.cwd())) + + @property + def Parent(self) -> Nullable['FileSet']: + """Property setting or returning the parent fileset this fileset is used in.""" + return self._parent + + @Parent.setter + def Parent(self, value: 'FileSet') -> None: + self._parent = value + value._fileSets[self._name] = self + # TODO: check it it already exists + # QUESTION: make an Add fileset method? + + @property + def FileSets(self) -> Dict[str, 'FileSet']: + """Read-only property returning the dictionary of sub-filesets.""" + return self._fileSets + + def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[bool, str, 'FileSet'] = None) -> Generator[File, None, None]: + """ + Method returning the files of this fileset. + + :arg fileType: A filter for file types. Default: ``Any``. + :arg fileSet: Specifies how to handle sub-filesets. + """ + if fileSet is False: + for file in self._files: + if file.FileType in fileType: + yield file + elif fileSet is None: + for fileSet in self._fileSets.values(): + for file in fileSet.Files(fileType): + yield file + for file in self._files: + if file.FileType in fileType: + yield file + else: + if isinstance(fileSet, str): + fileSetName = fileSet + try: + fileSet = self._fileSets[fileSetName] + except KeyError as ex: + raise Exception(f"Fileset {fileSetName} not bound to fileset {self.Name}.") from ex + elif not isinstance(fileSet, FileSet): + raise TypeError("Parameter 'fileSet' is not of type 'str' or 'FileSet' nor value 'None'.") + + for file in fileSet.Files(fileType): + yield file + + def AddFileSet(self, fileSet: "FileSet") -> None: + """ + Method to add a single sub-fileset to this fileset. + + :arg fileSet: A fileset to add to this fileset as sub-fileset. + """ + if not isinstance(fileSet, FileSet): + raise ValueError("Parameter 'fileSet' is not of type ProjectModel.FileSet.") + elif fileSet in self._fileSets: + raise Exception("Sub-fileset already contains this fileset.") + elif fileSet.Name in self._fileSets.keys(): + raise Exception(f"Fileset already contains a sub-fileset named '{fileSet.Name}'.") + + self._fileSets[fileSet.Name] = fileSet + fileSet._parent = self + + def AddFileSets(self, fileSets: Iterable["FileSet"]) -> None: + """ + Method to add a multiple sub-filesets to this fileset. + + :arg fileSets: An iterable of filesets to add each to the fileset. + """ + for fileSet in fileSets: + self.AddFileSet(fileSet) + + @property + def FileSetCount(self) -> int: + """Returns number of file sets excl. sub-filesets.""" + return len(self._fileSets) + + @property + def TotalFileSetCount(self) -> int: + """Returns number of file sets incl. sub-filesets.""" + fileSetCount = len(self._fileSets) + for fileSet in self._fileSets.values(): + fileSetCount += fileSet.TotalFileSetCount + + return fileSetCount + + def AddFile(self, file: File) -> None: + """ + Method to add a single file to this fileset. + + :arg file: A file to add to this fileset. + """ + if not isinstance(file, File): + raise TypeError("Parameter 'file' is not of type ProjectModel.File.") + elif file._fileSet is not None: + ex = ValueError(f"File '{file.Path!s}' is already part of fileset '{file.FileSet.Name}'.") + ex.add_note(f"A file can't be assigned to another fileset.") + raise ex + elif file in self._set: + ex = ValueError(f"File '{file.Path!s}' is already part of this fileset.") + ex.add_note(f"A file can't be added twice to a fileset.") + raise ex + + self._files.append(file) + self._set.add(file) + file._fileSet = self + + def AddFiles(self, files: Iterable[File]) -> None: + """ + Method to add a multiple files to this fileset. + + :arg files: An iterable of files to add each to the fileset. + """ + for file in files: + self.AddFile(file) + + @property + def FileCount(self) -> int: + """Returns number of files excl. sub-filesets.""" + return len(self._files) + + @property + def TotalFileCount(self) -> int: + """Returns number of files incl. the files in sub-filesets.""" + fileCount = len(self._files) + for fileSet in self._fileSets.values(): + fileCount += fileSet.FileCount + + return fileCount + + def Validate(self) -> None: + """Validate this fileset.""" + if self._name is None or self._name == "": + raise Exception("Validation: FileSet has no name.") + + if self._directory is None: + raise Exception(f"Validation: FileSet '{self._name}' has no directory.") + try: + path = self.ResolvedPath + except Exception as ex: + raise Exception(f"Validation: FileSet '{self._name}' could not compute resolved path.") from ex + if not path.exists(): + raise Exception(f"Validation: FileSet '{self._name}'s directory '{path}' does not exist.") + if not path.is_dir(): + raise Exception(f"Validation: FileSet '{self._name}'s directory '{path}' is not a directory.") + + if self._design is None: + raise Exception(f"Validation: FileSet '{self._path}' has no design.") + if self._project is None: + raise Exception(f"Validation: FileSet '{self._path}' has no project.") + + for fileSet in self._fileSets.values(): + fileSet.Validate() + for file in self._files: + file.Validate() + + def __len__(self) -> int: + """Returns number of attributes set on the file set.""" + return len(self._attributes) + + def __getitem__(self, key: Type[Attribute]) -> Any: + """Index access for returning attributes on this file.""" + if not issubclass(key, Attribute): + raise TypeError("Parameter 'key' is not an 'Attribute'.") + + try: + return self._attributes[key] + except KeyError: + return key.resolve(self, key) + + def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None: + """Index access for setting attributes on this file.""" + self._attributes[key] = value + + def GetOrCreateVHDLLibrary(self, name) -> None: + if name in self._vhdlLibraries: + return self._vhdlLibraries[name] + elif name in self._design._vhdlLibraries: + library = self._design._vhdlLibraries[name] + self._vhdlLibraries[name] = library + return library + else: + library = VHDLLibrary(name, design=self._design, vhdlVersion=self._vhdlVersion) + self._vhdlLibraries[name] = library + return library + + @property + def VHDLLibrary(self) -> 'VHDLLibrary': + """Property setting or returning the VHDL library of this fileset.""" + if self._vhdlLibrary is not None: + return self._vhdlLibrary + elif self._parent is not None: + return self._parent.VHDLLibrary + elif self._design is not None: + return self._design.VHDLLibrary + else: + raise Exception("VHDLLibrary was neither set locally nor globally.") + + @VHDLLibrary.setter + def VHDLLibrary(self, value: 'VHDLLibrary') -> None: + self._vhdlLibrary = value + + @property + def VHDLVersion(self) -> VHDLVersion: + """Property setting or returning the VHDL version of this fileset.""" + if self._vhdlVersion is not None: + return self._vhdlVersion + elif self._parent is not None: + return self._parent.VHDLVersion + elif self._design is not None: + return self._design.VHDLVersion + else: + raise Exception("VHDLVersion was neither set locally nor globally.") + + @VHDLVersion.setter + def VHDLVersion(self, value: VHDLVersion) -> None: + self._vhdlVersion = value + + @property + def VerilogVersion(self) -> SystemVerilogVersion: + """Property setting or returning the Verilog version of this fileset.""" + if self._verilogVersion is not None: + return self._verilogVersion + elif self._parent is not None: + return self._parent.VerilogVersion + elif self._design is not None: + return self._design.VerilogVersion + else: + raise Exception("VerilogVersion was neither set locally nor globally.") + + @VerilogVersion.setter + def VerilogVersion(self, value: SystemVerilogVersion) -> None: + self._verilogVersion = value + + @property + def SVVersion(self) -> SystemVerilogVersion: + """Property setting or returning the SystemVerilog version of this fileset.""" + if self._svVersion is not None: + return self._svVersion + elif self._parent is not None: + return self._parent.SVVersion + elif self._design is not None: + return self._design.SVVersion + else: + raise Exception("SVVersion was neither set locally nor globally.") + + @SVVersion.setter + def SVVersion(self, value: SystemVerilogVersion) -> None: + self._svVersion = value + + @property + def SRDLVersion(self) -> SystemRDLVersion: + if self._srdlVersion is not None: + return self._srdlVersion + elif self._parent is not None: + return self._parent.SRDLVersion + elif self._design is not None: + return self._design.SRDLVersion + else: + raise Exception("SRDLVersion was neither set locally nor globally.") + + @SRDLVersion.setter + def SRDLVersion(self, value: SystemRDLVersion) -> None: + self._srdlVersion = value + + def __str__(self) -> str: + """Returns the fileset's name.""" + return self._name + + +@export +class VHDLLibrary(metaclass=ExtendedType, slots=True): + """ + A :term:`VHDLLibrary` represents a group of VHDL source files compiled into the same VHDL library. + + :arg name: The VHDL libraries' name. + :arg project: Project the VHDL library is associated with. + :arg design: Design the VHDL library is associated with. + :arg vhdlVersion: Default VHDL version for files in this VHDL library, if not specified for the file itself. + """ + + _name: str + _project: Nullable['Project'] + _design: Nullable['Design'] + _files: List[File] + _vhdlVersion: VHDLVersion + + _dependencyNode: Vertex + + def __init__( + self, + name: str, + project: 'Project' = None, + design: 'Design' = None, + vhdlVersion: VHDLVersion = None + ): + self._name = name + if project is not None: + self._project = project + self._design = project._defaultDesign if design is None else design + self._dependencyNode = Vertex(value=self, graph=self._design._vhdlLibraryDependencyGraph) + + if name in self._design._vhdlLibraries: + raise Exception(f"Library '{name}' already in design '{self._design.Name}'.") + else: + self._design._vhdlLibraries[name] = self + + elif design is not None: + self._project = design._project + self._design = design + self._dependencyNode = Vertex(value=self, graph=design._vhdlLibraryDependencyGraph) + + if name in design._vhdlLibraries: + raise Exception(f"Library '{name}' already in design '{design.Name}'.") + else: + design._vhdlLibraries[name] = self + + else: + self._project = None + self._design = None + self._dependencyNode = None + + self._files = [] + self._vhdlVersion = vhdlVersion + + @property + def Name(self) -> str: + return self._name + + @property + def Project(self) -> Nullable['Project']: + """Property setting or returning the project this VHDL library is used in.""" + return self._project + + @Project.setter + def Project(self, value: 'Project') -> None: + if not isinstance(value, Project): + raise TypeError("Parameter 'value' is not of type 'Project'.") + + if value is None: + # TODO: unlink VHDLLibrary from project + self._project = None + else: + self._project = value + if self._design is None: + self._design = value._defaultDesign + + @property + def Design(self) -> Nullable['Design']: + """Property setting or returning the design this VHDL library is used in.""" + return self._design + + @Design.setter + def Design(self, value: 'Design') -> None: + if not isinstance(value, Design): + raise TypeError("Parameter 'value' is not of type 'Design'.") + + if value is None: + # TODO: unlink VHDLLibrary from design + self._design = None + else: + if self._design is None: + self._design = value + self._dependencyNode = Vertex(value=self, graph=self._design._vhdlLibraryDependencyGraph) + elif self._design is not value: + # TODO: move VHDLLibrary to other design + # TODO: create new vertex in dependency graph and remove vertex from old graph + self._design = value + else: + pass + + if self._project is None: + self._project = value._project + elif self._project is not value._project: + raise Exception("The design's project is not identical to the already assigned project.") + + @property + def Files(self) -> Generator[File, None, None]: + """Read-only property to return all files in this VHDL library.""" + for file in self._files: + yield file + + @property + def VHDLVersion(self) -> VHDLVersion: + """Property setting or returning the VHDL version of this VHDL library.""" + if self._vhdlVersion is not None: + return self._vhdlVersion + elif self._design is not None: + return self._design.VHDLVersion + else: + raise Exception("VHDLVersion is not set on VHDLLibrary nor parent object.") + + @VHDLVersion.setter + def VHDLVersion(self, value: VHDLVersion) -> None: + self._vhdlVersion = value + + def AddDependency(self, library: 'VHDLLibrary') -> None: + library.parent = self + + def AddFile(self, vhdlFile: VHDLSourceFile) -> None: + if not isinstance(vhdlFile, VHDLSourceFile): + raise TypeError(f"Parameter 'vhdlFile' is not a 'VHDLSourceFile'.") + + self._files.append(vhdlFile) + + def AddFiles(self, vhdlFiles: Iterable[VHDLSourceFile]) -> None: + for vhdlFile in vhdlFiles: + if not isinstance(vhdlFile, VHDLSourceFile): + raise TypeError(f"Item '{vhdlFile}' in parameter 'vhdlFiles' is not a 'VHDLSourceFile'.") + + self._files.append(vhdlFile) + + @property + def FileCount(self) -> int: + """Returns number of files.""" + return len(self._files) + + def __str__(self) -> str: + """Returns the VHDL library's name.""" + return self._name + + +@export +class Design(metaclass=ExtendedType, slots=True): + """ + A :term:`Design` represents a group of filesets and the source files therein. + + Each design contains at least one fileset - the :term:`default fileset`. For + designs with VHDL source files, a independent `VHDLLibraries` overlay structure + exists. + + :arg name: The design's name. + :arg topLevel: Name of the design's toplevel. + :arg directory: Path of this design (absolute or relative to the project). + :arg project: Project the design is associated with. + :arg vhdlVersion: Default VHDL version for files in this design, if not specified for the file itself. + :arg verilogVersion: Default Verilog version for files in this design, if not specified for the file itself. + :arg svVersion: Default SystemVerilog version for files in this design, if not specified for the file itself. + :arg srdlVersion: Default SystemRDL version for files in this fileset, if not specified for the file itself. + """ + + _name: str + _topLevel: Nullable[str] + _project: Nullable['Project'] + _directory: pathlib_Path + _fileSets: Dict[str, FileSet] + _defaultFileSet: Nullable[FileSet] + _attributes: Dict[Type[Attribute], typing_Any] + + _vhdlLibraries: Dict[str, VHDLLibrary] + _vhdlVersion: VHDLVersion + _verilogVersion: SystemVerilogVersion + _svVersion: SystemVerilogVersion + _srdlVersion: SystemRDLVersion + _externalVHDLLibraries: List + + _vhdlLibraryDependencyGraph: Graph + _fileDependencyGraph: Graph + + def __init__( + self, + name: str, + topLevel: str = None, + directory: pathlib_Path = pathlib_Path("."), + project: 'Project' = None, + vhdlVersion: VHDLVersion = None, + verilogVersion: SystemVerilogVersion = None, + svVersion: SystemVerilogVersion = None, + srdlVersion: SystemRDLVersion = None + ): + self._name = name + self._topLevel = topLevel + self._project = project + if project is not None: + project._designs[name] = self + self._directory = directory + self._fileSets = {} + self._defaultFileSet = FileSet("default", project=project, design=self) + self._attributes = {} + self._vhdlLibraries = {} + self._vhdlVersion = vhdlVersion + self._verilogVersion = verilogVersion + self._svVersion = svVersion + self._srdlVersion = srdlVersion + self._externalVHDLLibraries = [] + + self._vhdlLibraryDependencyGraph = Graph() + self._fileDependencyGraph = Graph() + + @property + def Name(self) -> str: + """Property setting or returning the design's name.""" + return self._name + + @Name.setter + def Name(self, value: str) -> None: + self._name = value + + @property + def TopLevel(self) -> str: + """Property setting or returning the fileset's toplevel.""" + return self._topLevel + + @TopLevel.setter + def TopLevel(self, value: str) -> None: + self._topLevel = value + + @property + def Project(self) -> Nullable['Project']: + """Property setting or returning the project this design is used in.""" + return self._project + + @Project.setter + def Project(self, value: 'Project') -> None: + self._project = value + + @property + def Directory(self) -> pathlib_Path: + """Property setting or returning the directory this design is located in.""" + return self._directory + + @Directory.setter + def Directory(self, value: pathlib_Path) -> None: + self._directory = value + + @property + def ResolvedPath(self) -> pathlib_Path: + """Read-only property returning the resolved path of this fileset.""" + if self._directory.is_absolute(): + return self._directory.resolve() + elif self._project is not None: + path = (self._project.ResolvedPath / self._directory).resolve() + + if path.is_absolute(): + return path + else: + # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath + return pathlib_Path(path_relpath(path, pathlib_Path.cwd())) + else: + # TODO: message and exception type + raise Exception("") + + @property + def DefaultFileSet(self) -> FileSet: + """Property setting or returning the default fileset of this design.""" + return self._defaultFileSet + + @DefaultFileSet.setter + def DefaultFileSet(self, value: Union[str, FileSet]) -> None: + if isinstance(value, str): + if value not in self._fileSets.keys(): + raise Exception(f"Fileset '{value}' is not in this design.") + + self._defaultFileSet = self._fileSets[value] + elif isinstance(value, FileSet): + if value not in self.FileSets: + raise Exception(f"Fileset '{value}' is not associated to this design.") + + self._defaultFileSet = value + else: + raise ValueError("Unsupported parameter type for 'value'.") + + # TODO: return generator with another method + @property + def FileSets(self) -> Dict[str, FileSet]: + """Read-only property returning the dictionary of filesets.""" + return self._fileSets + + def Files(self, fileType: FileType = FileTypes.Any, fileSet: Union[str, FileSet] = None) -> Generator[File, None, None]: + """ + Method returning the files of this design. + + :arg fileType: A filter for file types. Default: ``Any``. + :arg fileSet: Specifies if all files from all filesets (``fileSet=None``) are files from a single fileset are returned. + """ + if fileSet is None: + for fileSet in self._fileSets.values(): + for file in fileSet.Files(fileType): + yield file + else: + if isinstance(fileSet, str): + try: + fileSet = self._fileSets[fileSet] + except KeyError as ex: + raise Exception(f"Fileset {fileSet.Name} not bound to design {self.Name}.") from ex + elif not isinstance(fileSet, FileSet): + raise TypeError("Parameter 'fileSet' is not of type 'str' or 'FileSet' nor value 'None'.") + + for file in fileSet.Files(fileType): + yield file + + + + def Validate(self) -> None: + """Validate this design.""" + if self._name is None or self._name == "": + raise Exception("Validation: Design has no name.") + + if self._directory is None: + raise Exception(f"Validation: Design '{self._name}' has no directory.") + try: + path = self.ResolvedPath + except Exception as ex: + raise Exception(f"Validation: Design '{self._name}' could not compute resolved path.") from ex + if not path.exists(): + raise Exception(f"Validation: Design '{self._name}'s directory '{path}' does not exist.") + if not path.is_dir(): + raise Exception(f"Validation: Design '{self._name}'s directory '{path}' is not a directory.") + + if len(self._fileSets) == 0: + raise Exception(f"Validation: Design '{self._name}' has no fileset.") + try: + if self._defaultFileSet is not self._fileSets[self._defaultFileSet.Name]: + raise Exception(f"Validation: Design '{self._name}'s default fileset is the same as listed in filesets.") + except KeyError as ex: + raise Exception(f"Validation: Design '{self._name}'s default fileset is not in list of filesets.") from ex + if self._project is None: + raise Exception(f"Validation: Design '{self._path}' has no project.") + + for fileSet in self._fileSets.values(): + fileSet.Validate() + + def __len__(self) -> int: + """Returns number of attributes set on the file set.""" + return len(self._attributes) + + def __getitem__(self, key: Type[Attribute]) -> Any: + if not issubclass(key, Attribute): + raise TypeError("Parameter 'key' is not an 'Attribute'.") + + try: + return self._attributes[key] + except KeyError: + return key.resolve(self, key) + + def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None: + self._attributes[key] = value + + @property + def VHDLLibraries(self) -> Dict[str, VHDLLibrary]: + return self._vhdlLibraries + + @property + def VHDLVersion(self) -> VHDLVersion: + if self._vhdlVersion is not None: + return self._vhdlVersion + elif self._project is not None: + return self._project.VHDLVersion + else: + raise Exception("VHDLVersion was neither set locally nor globally.") + + @VHDLVersion.setter + def VHDLVersion(self, value: VHDLVersion) -> None: + self._vhdlVersion = value + + @property + def VerilogVersion(self) -> SystemVerilogVersion: + if self._verilogVersion is not None: + return self._verilogVersion + elif self._project is not None: + return self._project.VerilogVersion + else: + raise Exception("VerilogVersion was neither set locally nor globally.") + + @VerilogVersion.setter + def VerilogVersion(self, value: SystemVerilogVersion) -> None: + self._verilogVersion = value + + @property + def SVVersion(self) -> SystemVerilogVersion: + if self._svVersion is not None: + return self._svVersion + elif self._project is not None: + return self._project.SVVersion + else: + raise Exception("SVVersion was neither set locally nor globally.") + + @SVVersion.setter + def SVVersion(self, value: SystemVerilogVersion) -> None: + self._svVersion = value + + @property + def SRDLVersion(self) -> SystemRDLVersion: + if self._srdlVersion is not None: + return self._srdlVersion + elif self._project is not None: + return self._project.SRDLVersion + else: + raise Exception("SRDLVersion was neither set locally nor globally.") + + @SRDLVersion.setter + def SRDLVersion(self, value: SystemRDLVersion) -> None: + self._srdlVersion = value + + @property + def ExternalVHDLLibraries(self) -> List: + return self._externalVHDLLibraries + + def AddFileSet(self, fileSet: FileSet) -> None: + if not isinstance(fileSet, FileSet): + raise ValueError("Parameter 'fileSet' is not of type ProjectModel.FileSet.") + elif fileSet in self._fileSets: + raise Exception("Design already contains this fileset.") + elif fileSet.Name in self._fileSets.keys(): + raise Exception(f"Design already contains a fileset named '{fileSet.Name}'.") + + self._fileSets[fileSet.Name] = fileSet + fileSet.Design = self + fileSet._parent = self + + def AddFileSets(self, fileSets: Iterable[FileSet]) -> None: + for fileSet in fileSets: + self.AddFileSet(fileSet) + + @property + def FileSetCount(self) -> int: + """Returns number of file sets excl. sub-filesets.""" + return len(self._fileSets) + + @property + def TotalFileSetCount(self) -> int: + """Returns number of file sets incl. sub-filesets.""" + fileSetCount = len(self._fileSets) + for fileSet in self._fileSets.values(): + fileSetCount += fileSet.TotalFileSetCount + + return fileSetCount + + def AddFile(self, file: File) -> None: + if file.FileSet is None: + self._defaultFileSet.AddFile(file) + else: + raise ValueError(f"File '{file.Path!s}' is already part of fileset '{file.FileSet.Name}' and can't be assigned via Design to a default fileset.") + + def AddFiles(self, files: Iterable[File]) -> None: + for file in files: + self.AddFile(file) + + def AddVHDLLibrary(self, vhdlLibrary: VHDLLibrary) -> None: + if vhdlLibrary.Name in self._vhdlLibraries: + if self._vhdlLibraries[vhdlLibrary.Name] is vhdlLibrary: + raise Exception(f"The VHDLLibrary '{vhdlLibrary.Name}' was already added to the design.") + else: + raise Exception(f"A VHDLLibrary with same name ('{vhdlLibrary.Name}') already exists for this design.") + + def __str__(self) -> str: + return self._name + + +@export +class Project(metaclass=ExtendedType, slots=True): + """ + A :term:`Project` represents a group of designs and the source files therein. + + :arg name: The project's name. + :arg rootDirectory: Base-path to the project. + :arg vhdlVersion: Default VHDL version for files in this project, if not specified for the file itself. + :arg verilogVersion: Default Verilog version for files in this project, if not specified for the file itself. + :arg svVersion: Default SystemVerilog version for files in this project, if not specified for the file itself. + """ + + _name: str + _rootDirectory: pathlib_Path + _designs: Dict[str, Design] + _defaultDesign: Design + _attributes: Dict[Type[Attribute], typing_Any] + + _vhdlVersion: VHDLVersion + _verilogVersion: SystemVerilogVersion + _svVersion: SystemVerilogVersion + _srdlVersion: SystemRDLVersion + + def __init__( + self, + name: str, + rootDirectory: pathlib_Path = pathlib_Path("."), + vhdlVersion: VHDLVersion = None, + verilogVersion: SystemVerilogVersion = None, + svVersion: SystemVerilogVersion = None + ): + self._name = name + self._rootDirectory = rootDirectory + self._designs = {} + self._defaultDesign = Design("default", project=self) + self._attributes = {} + self._vhdlVersion = vhdlVersion + self._verilogVersion = verilogVersion + self._svVersion = svVersion + + @property + def Name(self) -> str: + """Property setting or returning the project's name.""" + return self._name + + @property + def RootDirectory(self) -> pathlib_Path: + """Property setting or returning the root directory this project is located in.""" + return self._rootDirectory + + @RootDirectory.setter + def RootDirectory(self, value: pathlib_Path) -> None: + self._rootDirectory = value + + @property + def ResolvedPath(self) -> pathlib_Path: + """Read-only property returning the resolved path of this fileset.""" + path = self._rootDirectory.resolve() + if self._rootDirectory.is_absolute(): + return path + else: + # WORKAROUND: https://stackoverflow.com/questions/67452690/pathlib-path-relative-to-vs-os-path-relpath + return pathlib_Path(path_relpath(path, pathlib_Path.cwd())) + + # TODO: return generator with another method + @property + def Designs(self) -> Dict[str, Design]: + return self._designs + + @property + def DefaultDesign(self) -> Design: + return self._defaultDesign + + def Validate(self) -> None: + """Validate this project.""" + if self._name is None or self._name == "": + raise Exception("Validation: Project has no name.") + + if self._rootDirectory is None: + raise Exception(f"Validation: Project '{self._name}' has no root directory.") + try: + path = self.ResolvedPath + except Exception as ex: + raise Exception(f"Validation: Project '{self._name}' could not compute resolved path.") from ex + if not path.exists(): + raise Exception(f"Validation: Project '{self._name}'s directory '{path}' does not exist.") + if not path.is_dir(): + raise Exception(f"Validation: Project '{self._name}'s directory '{path}' is not a directory.") + + if len(self._designs) == 0: + raise Exception(f"Validation: Project '{self._name}' has no design.") + try: + if self._defaultDesign is not self._designs[self._defaultDesign.Name]: + raise Exception(f"Validation: Project '{self._name}'s default design is the same as listed in designs.") + except KeyError as ex: + raise Exception(f"Validation: Project '{self._name}'s default design is not in list of designs.") from ex + + for design in self._designs.values(): + design.Validate() + + @property + def DesignCount(self) -> int: + """Returns number of designs.""" + return len(self._designs) + + def __len__(self) -> int: + """Returns number of attributes set on the file set.""" + return len(self._attributes) + + def __getitem__(self, key: Type[Attribute]) -> Any: + if not issubclass(key, Attribute): + raise TypeError("Parameter 'key' is not an 'Attribute'.") + + try: + return self._attributes[key] + except KeyError: + return key.resolve(self, key) + + def __setitem__(self, key: Type[Attribute], value: typing_Any) -> None: + self._attributes[key] = value + + @property + def VHDLVersion(self) -> VHDLVersion: + # TODO: check for None and return exception + return self._vhdlVersion + + @VHDLVersion.setter + def VHDLVersion(self, value: VHDLVersion) -> None: + self._vhdlVersion = value + + @property + def VerilogVersion(self) -> SystemVerilogVersion: + # TODO: check for None and return exception + return self._verilogVersion + + @VerilogVersion.setter + def VerilogVersion(self, value: SystemVerilogVersion) -> None: + self._verilogVersion = value + + @property + def SVVersion(self) -> SystemVerilogVersion: + # TODO: check for None and return exception + return self._svVersion + + @SVVersion.setter + def SVVersion(self, value: SystemVerilogVersion) -> None: + self._svVersion = value + + @property + def SRDLVersion(self) -> SystemRDLVersion: + # TODO: check for None and return exception + return self._srdlVersion + + @SRDLVersion.setter + def SRDLVersion(self, value: SystemRDLVersion) -> None: + self._srdlVersion = value + + def __str__(self) -> str: + return self._name + |
+
File | +Imprecision | +Lines | +
---|---|---|
Total | +14.67% imprecise | +2569 LOC | +
ProjectModel | +12.09% imprecise | +1687 LOC | +
ProjectModel.Altera | +0.00% imprecise | +31 LOC | +
ProjectModel.Altera.Quartus | +2.27% imprecise | +44 LOC | +
ProjectModel.Attributes | +7.55% imprecise | +53 LOC | +
ProjectModel.GHDL | +2.56% imprecise | +39 LOC | +
ProjectModel.Intel | +0.00% imprecise | +31 LOC | +
ProjectModel.Intel.QuartusPrime | +2.27% imprecise | +44 LOC | +
ProjectModel.MentorGraphics | +0.00% imprecise | +31 LOC | +
ProjectModel.MentorGraphics.ModelSim | +2.04% imprecise | +49 LOC | +
ProjectModel.MentorGraphics.QuestaSim | +2.04% imprecise | +49 LOC | +
ProjectModel.OSVVM | +38.02% imprecise | +192 LOC | +
ProjectModel.VHDL | +0.00% imprecise | +0 LOC | +
ProjectModel.Verilog | +2.56% imprecise | +39 LOC | +
ProjectModel.Xilinx | +0.00% imprecise | +31 LOC | +
ProjectModel.Xilinx.ISE | +2.27% imprecise | +44 LOC | +
ProjectModel.Xilinx.Vivado | +43.41% imprecise | +205 LOC | +