pyEDAA.OutputFilter 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/PKG-INFO +21 -21
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/README.md +1 -1
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA/OutputFilter/CLI/Vivado.py +56 -43
- pyedaa_outputfilter-0.3.0/pyEDAA/OutputFilter/Xilinx/Commands.py +285 -0
- pyedaa_outputfilter-0.2.0/pyEDAA/OutputFilter/Xilinx/__init__.py → pyedaa_outputfilter-0.3.0/pyEDAA/OutputFilter/Xilinx/Common.py +79 -302
- pyedaa_outputfilter-0.3.0/pyEDAA/OutputFilter/Xilinx/Common2.py +179 -0
- pyedaa_outputfilter-0.3.0/pyEDAA/OutputFilter/Xilinx/Exception.py +59 -0
- pyedaa_outputfilter-0.2.0/pyEDAA/OutputFilter/Xilinx/Synthesis.py → pyedaa_outputfilter-0.3.0/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py +154 -229
- pyedaa_outputfilter-0.3.0/pyEDAA/OutputFilter/Xilinx/__init__.py +209 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA/OutputFilter/__init__.py +1 -1
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA.OutputFilter.egg-info/PKG-INFO +21 -21
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA.OutputFilter.egg-info/SOURCES.txt +5 -1
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/LICENSE.md +0 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA/OutputFilter/CLI/__init__.py +0 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA.OutputFilter.egg-info/dependency_links.txt +0 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA.OutputFilter.egg-info/entry_points.txt +0 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA.OutputFilter.egg-info/requires.txt +19 -19
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyEDAA.OutputFilter.egg-info/top_level.txt +0 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/pyproject.toml +0 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/setup.cfg +0 -0
- {pyedaa_outputfilter-0.2.0 → pyedaa_outputfilter-0.3.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyEDAA.OutputFilter
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Post-processing of EDA Tool outputs (log files).
|
|
5
5
|
Home-page: https://GitHub.com/edaa-org/pyEDAA.OutputFilter
|
|
6
6
|
Author: Patrick Lehmann
|
|
@@ -27,45 +27,45 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
License-File: LICENSE.md
|
|
28
28
|
Requires-Dist: pyTooling[terminal]~=8.5
|
|
29
29
|
Provides-Extra: doc
|
|
30
|
-
Requires-Dist: sphinx_design~=0.6.1; extra == "doc"
|
|
31
30
|
Requires-Dist: pyTooling[terminal]~=8.5; extra == "doc"
|
|
32
31
|
Requires-Dist: docutils_stubs~=0.0.22; extra == "doc"
|
|
33
|
-
Requires-Dist: sphinx_rtd_theme~=3.0; extra == "doc"
|
|
34
|
-
Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "doc"
|
|
35
32
|
Requires-Dist: sphinx_autodoc_typehints~=3.2; extra == "doc"
|
|
36
|
-
Requires-Dist:
|
|
33
|
+
Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "doc"
|
|
37
34
|
Requires-Dist: sphinx~=8.2; extra == "doc"
|
|
38
|
-
Requires-Dist:
|
|
35
|
+
Requires-Dist: sphinx_design~=0.6.1; extra == "doc"
|
|
36
|
+
Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "doc"
|
|
39
37
|
Requires-Dist: autoapi>=2.0.1; extra == "doc"
|
|
38
|
+
Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
|
|
39
|
+
Requires-Dist: sphinx_reports~=0.9; extra == "doc"
|
|
40
|
+
Requires-Dist: sphinx_rtd_theme~=3.0; extra == "doc"
|
|
40
41
|
Requires-Dist: docutils~=0.21; extra == "doc"
|
|
41
|
-
Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "doc"
|
|
42
42
|
Provides-Extra: test
|
|
43
43
|
Requires-Dist: pyTooling[terminal]~=8.5; extra == "test"
|
|
44
|
+
Requires-Dist: pytest~=8.4; extra == "test"
|
|
44
45
|
Requires-Dist: typing_extensions~=4.14; extra == "test"
|
|
46
|
+
Requires-Dist: mypy~=1.16; extra == "test"
|
|
45
47
|
Requires-Dist: pytest-cov~=6.2; extra == "test"
|
|
46
|
-
Requires-Dist: pytest~=8.4; extra == "test"
|
|
47
48
|
Requires-Dist: Coverage~=7.9; extra == "test"
|
|
48
49
|
Requires-Dist: lxml~=5.4; extra == "test"
|
|
49
|
-
Requires-Dist: mypy~=1.16; extra == "test"
|
|
50
50
|
Provides-Extra: all
|
|
51
|
-
Requires-Dist: sphinx_design~=0.6.1; extra == "all"
|
|
52
51
|
Requires-Dist: pyTooling[terminal]~=8.5; extra == "all"
|
|
52
|
+
Requires-Dist: pytest~=8.4; extra == "all"
|
|
53
|
+
Requires-Dist: Coverage~=7.9; extra == "all"
|
|
53
54
|
Requires-Dist: docutils_stubs~=0.0.22; extra == "all"
|
|
54
|
-
Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "all"
|
|
55
|
-
Requires-Dist: sphinx_rtd_theme~=3.0; extra == "all"
|
|
56
55
|
Requires-Dist: sphinx_autodoc_typehints~=3.2; extra == "all"
|
|
57
|
-
Requires-Dist:
|
|
56
|
+
Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "all"
|
|
58
57
|
Requires-Dist: sphinx~=8.2; extra == "all"
|
|
59
|
-
Requires-Dist: typing_extensions~=4.14; extra == "all"
|
|
60
|
-
Requires-Dist: sphinx_reports~=0.9; extra == "all"
|
|
61
|
-
Requires-Dist: pytest-cov~=6.2; extra == "all"
|
|
62
|
-
Requires-Dist: pytest~=8.4; extra == "all"
|
|
63
|
-
Requires-Dist: Coverage~=7.9; extra == "all"
|
|
64
58
|
Requires-Dist: lxml~=5.4; extra == "all"
|
|
59
|
+
Requires-Dist: typing_extensions~=4.14; extra == "all"
|
|
60
|
+
Requires-Dist: sphinx_design~=0.6.1; extra == "all"
|
|
61
|
+
Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "all"
|
|
65
62
|
Requires-Dist: autoapi>=2.0.1; extra == "all"
|
|
66
|
-
Requires-Dist:
|
|
67
|
-
Requires-Dist:
|
|
63
|
+
Requires-Dist: sphinx-copybutton>=0.5.2; extra == "all"
|
|
64
|
+
Requires-Dist: sphinx_reports~=0.9; extra == "all"
|
|
65
|
+
Requires-Dist: sphinx_rtd_theme~=3.0; extra == "all"
|
|
68
66
|
Requires-Dist: mypy~=1.16; extra == "all"
|
|
67
|
+
Requires-Dist: docutils~=0.21; extra == "all"
|
|
68
|
+
Requires-Dist: pytest-cov~=6.2; extra == "all"
|
|
69
69
|
Dynamic: author
|
|
70
70
|
Dynamic: author-email
|
|
71
71
|
Dynamic: classifier
|
|
@@ -127,7 +127,7 @@ Dynamic: summary
|
|
|
127
127
|
|
|
128
128
|
```python
|
|
129
129
|
from pathlib import Path
|
|
130
|
-
from pyEDAA.OutputFilter.Xilinx.
|
|
130
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import Processor
|
|
131
131
|
|
|
132
132
|
logfile = Path("tests/data/Stopwatch/toplevel.vds")
|
|
133
133
|
processor = Processor(logfile)
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
|
|
45
45
|
```python
|
|
46
46
|
from pathlib import Path
|
|
47
|
-
from pyEDAA.OutputFilter.Xilinx.
|
|
47
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import Processor
|
|
48
48
|
|
|
49
49
|
logfile = Path("tests/data/Stopwatch/toplevel.vds")
|
|
50
50
|
processor = Processor(logfile)
|
|
@@ -38,13 +38,16 @@ from pyTooling.Attributes.ArgParse import CommandHandler
|
|
|
38
38
|
from pyTooling.Attributes.ArgParse.Flag import LongFlag
|
|
39
39
|
from pyTooling.Attributes.ArgParse.ValuedFlag import LongValuedFlag
|
|
40
40
|
|
|
41
|
-
from pyEDAA.OutputFilter.Xilinx
|
|
42
|
-
from pyEDAA.OutputFilter.Xilinx.
|
|
41
|
+
from pyEDAA.OutputFilter.Xilinx import Document, ProcessorException, SynthesizeDesign
|
|
42
|
+
from pyEDAA.OutputFilter.Xilinx.Common import LineKind, Line
|
|
43
|
+
from pyEDAA.OutputFilter.Xilinx.Common2 import Preamble
|
|
44
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import WritingSynthesisReport, LoadingPart
|
|
45
|
+
|
|
43
46
|
|
|
44
47
|
|
|
45
48
|
class VivadoHandlers(metaclass=ExtendedType, mixin=True):
|
|
46
|
-
@CommandHandler("vivado
|
|
47
|
-
@LongValuedFlag("--file", dest="logfile", metaName='
|
|
49
|
+
@CommandHandler("vivado", help="Parse AMD/Xilinx Vivado log files.", description="Parse AMD/Xilinx Vivado log files.")
|
|
50
|
+
@LongValuedFlag("--file", dest="logfile", metaName='Log file', help="Log file (*.vds|*.vdi).")
|
|
48
51
|
@LongFlag("--colored", dest="colored", help="Render logfile with colored lines.")
|
|
49
52
|
@LongFlag("--summary", dest="summary", help="Print a summary.")
|
|
50
53
|
@LongFlag("--info", dest="info", help="Print info messages.")
|
|
@@ -53,8 +56,8 @@ class VivadoHandlers(metaclass=ExtendedType, mixin=True):
|
|
|
53
56
|
@LongFlag("--error", dest="error", help="Print error messages.")
|
|
54
57
|
@LongFlag("--influxdb", dest="influxdb", help="Write statistics as InfluxDB line protocol file (*.line).")
|
|
55
58
|
# @LongValuedFlag("--file", dest="logfile", metaName='Synthesis Log', help="Synthesis log file (*.vds).")
|
|
56
|
-
def
|
|
57
|
-
"""Handle program calls with command ``vivado
|
|
59
|
+
def HandleVivado(self, args: Namespace) -> None:
|
|
60
|
+
"""Handle program calls with command ``vivado``."""
|
|
58
61
|
self._PrintHeadline()
|
|
59
62
|
|
|
60
63
|
returnCode = 0
|
|
@@ -64,13 +67,13 @@ class VivadoHandlers(metaclass=ExtendedType, mixin=True):
|
|
|
64
67
|
|
|
65
68
|
logfile = Path(args.logfile)
|
|
66
69
|
if not logfile.exists():
|
|
67
|
-
self.WriteError(f"Vivado
|
|
70
|
+
self.WriteError(f"Vivado log file '{logfile}' doesn't exist.")
|
|
68
71
|
returnCode = 4
|
|
69
72
|
|
|
70
73
|
if returnCode != 0:
|
|
71
74
|
self.Exit(returnCode)
|
|
72
75
|
|
|
73
|
-
processor =
|
|
76
|
+
processor = Document(logfile)
|
|
74
77
|
processor.Parse()
|
|
75
78
|
|
|
76
79
|
if args.colored:
|
|
@@ -94,98 +97,108 @@ class VivadoHandlers(metaclass=ExtendedType, mixin=True):
|
|
|
94
97
|
self.WriteNormal(f" {message}")
|
|
95
98
|
|
|
96
99
|
if args.influxdb:
|
|
100
|
+
synthesizeDesign = processor[SynthesizeDesign]
|
|
97
101
|
influxString = "vivado_synthesis_overview"
|
|
98
|
-
influxString += f",version={processor
|
|
102
|
+
influxString += f",version={processor.Preamble.ToolVersion}"
|
|
99
103
|
influxString += f",branch=main"
|
|
100
104
|
influxString += f",design=Stopwatch"
|
|
101
105
|
influxString += " "
|
|
102
106
|
influxString += f"processing_duration={processor.Duration:.3f}"
|
|
103
|
-
influxString += f",synthesis_duration={
|
|
107
|
+
influxString += f",synthesis_duration={synthesizeDesign[WritingSynthesisReport].Duration:.1f}"
|
|
104
108
|
influxString += f",info_count={len(processor.InfoMessages)}u"
|
|
105
109
|
influxString += f",warning_count={len(processor.WarningMessages)}u"
|
|
106
110
|
influxString += f",critical_count={len(processor.CriticalWarningMessages)}u"
|
|
107
111
|
influxString += f",error_count={len(processor.ErrorMessages)}u"
|
|
108
|
-
influxString += f",blackbox_count={len(
|
|
112
|
+
influxString += f",blackbox_count={len(synthesizeDesign[WritingSynthesisReport].Blackboxes)}u"
|
|
109
113
|
influxString += "\n"
|
|
110
114
|
influxString += "vivado_synthesis_cells"
|
|
111
|
-
influxString += f",version={processor
|
|
115
|
+
influxString += f",version={processor.Preamble.ToolVersion}"
|
|
112
116
|
influxString += f",branch=main"
|
|
113
117
|
influxString += f",design=Stopwatch"
|
|
114
118
|
influxString += " "
|
|
115
|
-
influxString += ",".join(f"{cellName}={cellCount}" for cellName, cellCount in
|
|
119
|
+
influxString += ",".join(f"{cellName}={cellCount}" for cellName, cellCount in synthesizeDesign[WritingSynthesisReport].Cells.items() if not cellName.endswith("_bbox"))
|
|
116
120
|
|
|
117
121
|
self.WriteNormal(influxString)
|
|
118
122
|
|
|
119
123
|
if args.summary:
|
|
124
|
+
synthesizeDesign : SynthesizeDesign = processor[SynthesizeDesign]
|
|
120
125
|
self.WriteNormal("Summary:")
|
|
121
|
-
self.WriteNormal(f" Tool version: {processor
|
|
122
|
-
self.WriteNormal(f" Started at: {processor
|
|
126
|
+
self.WriteNormal(f" Tool version: {processor.Preamble.ToolVersion}")
|
|
127
|
+
self.WriteNormal(f" Started at: {processor.Preamble.StartDatetime}")
|
|
123
128
|
self.WriteNormal(f" Processing duration: {processor.Duration:.3f} s")
|
|
124
129
|
self.WriteNormal(f" Info: {len(processor.InfoMessages)}")
|
|
125
130
|
self.WriteNormal(f" Warning: {len(processor.WarningMessages)}")
|
|
126
131
|
self.WriteNormal(f" Critical Warning: {len(processor.CriticalWarningMessages)}")
|
|
127
132
|
self.WriteNormal(f" Error: {len(processor.ErrorMessages)}")
|
|
128
|
-
self.WriteNormal(f" Part: {
|
|
133
|
+
self.WriteNormal(f" Part: {synthesizeDesign[LoadingPart].Part}")
|
|
129
134
|
|
|
130
135
|
self.WriteNormal("Policies:")
|
|
131
|
-
self.WriteNormal(f" Latches: {'found' if
|
|
132
|
-
if
|
|
136
|
+
self.WriteNormal(f" Latches: {'found' if synthesizeDesign.HasLatches else '----'}")
|
|
137
|
+
if synthesizeDesign.HasLatches:
|
|
133
138
|
for cellName in ("LD", ):
|
|
134
139
|
try:
|
|
135
|
-
self.WriteNormal(f" {cellName}: {
|
|
140
|
+
self.WriteNormal(f" {cellName}: {synthesizeDesign.Cells[cellName]}")
|
|
136
141
|
except KeyError:
|
|
137
142
|
pass
|
|
138
|
-
for latch in
|
|
143
|
+
for latch in synthesizeDesign.Latches:
|
|
139
144
|
self.WriteNormal(f" {latch}")
|
|
140
|
-
self.WriteNormal(f" Blackboxes: {'found' if
|
|
141
|
-
if
|
|
142
|
-
for bbox in
|
|
145
|
+
self.WriteNormal(f" Blackboxes: {'found' if synthesizeDesign.HasBlackboxes else '----'}")
|
|
146
|
+
if synthesizeDesign.HasBlackboxes:
|
|
147
|
+
for bbox in synthesizeDesign.Blackboxes:
|
|
143
148
|
self.WriteNormal(f" {bbox}")
|
|
144
149
|
|
|
145
|
-
self.WriteNormal(f"VHDL report statements ({len(
|
|
146
|
-
for message in
|
|
150
|
+
self.WriteNormal(f"VHDL report statements ({len(synthesizeDesign.VHDLReportMessages)}):")
|
|
151
|
+
for message in synthesizeDesign.VHDLReportMessages:
|
|
147
152
|
self.WriteNormal(f" {message}")
|
|
148
|
-
self.WriteNormal(f"VHDL assert statements ({len(
|
|
149
|
-
for message in
|
|
153
|
+
self.WriteNormal(f"VHDL assert statements ({len(synthesizeDesign.VHDLAssertMessages)}):")
|
|
154
|
+
for message in synthesizeDesign.VHDLAssertMessages:
|
|
150
155
|
self.WriteNormal(f" {message}")
|
|
151
156
|
|
|
152
|
-
self.WriteNormal(f"Cells: {len(
|
|
153
|
-
for cell, count in
|
|
157
|
+
self.WriteNormal(f"Cells: {len(synthesizeDesign.Cells)}")
|
|
158
|
+
for cell, count in synthesizeDesign.Cells.items():
|
|
154
159
|
self.WriteNormal(f" {cell}: {count}")
|
|
155
160
|
|
|
156
161
|
self.ExitOnPreviousErrors()
|
|
157
162
|
|
|
158
163
|
def ColoredOutput(self, lines: Iterable[Line]) -> None:
|
|
159
164
|
for i, line in enumerate(lines, start=1):
|
|
160
|
-
|
|
165
|
+
message = str(line).replace("{", "{{").replace("}", "}}")
|
|
166
|
+
if isinstance(line, ProcessorException):
|
|
167
|
+
print(f"{i:4}: {{RED}}EXCEPTION:{{NOCOLOR}} {message}".format(**self.Foreground))
|
|
168
|
+
elif line.Kind is LineKind.Normal:
|
|
161
169
|
print(f"{i:4}: {line.Message}")
|
|
162
170
|
elif LineKind.Message in line.Kind:
|
|
163
171
|
if line.Kind is LineKind.InfoMessage:
|
|
164
|
-
print(f"{i:4}: {{BLUE}}{
|
|
172
|
+
print(f"{i:4}: {{BLUE}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
165
173
|
elif line.Kind is LineKind.WarningMessage:
|
|
166
|
-
print(f"{i:4}: {{YELLOW}}{
|
|
174
|
+
print(f"{i:4}: {{YELLOW}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
167
175
|
elif line.Kind is LineKind.CriticalWarningMessage:
|
|
168
|
-
print(f"{i:4}: {{MAGENTA}}{
|
|
176
|
+
print(f"{i:4}: {{MAGENTA}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
169
177
|
elif line.Kind is LineKind.ErrorMessage:
|
|
170
|
-
print(f"{i:4}: {{RED}}{
|
|
171
|
-
elif LineKind.
|
|
172
|
-
print(f"{i:4}: {{CYAN}}{
|
|
178
|
+
print(f"{i:4}: {{RED}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
179
|
+
elif LineKind.TclCommand in line.Kind:
|
|
180
|
+
print(f"{i:4}: {{CYAN}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
173
181
|
elif (LineKind.Start in line.Kind) or (LineKind.End in line.Kind):
|
|
174
|
-
|
|
182
|
+
if LineKind.Phase in line.Kind:
|
|
183
|
+
print(f"{i:4}: {{YELLOW}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
184
|
+
else:
|
|
185
|
+
print(f"{i:4}: {{DARK_CYAN}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
175
186
|
elif line.Kind is LineKind.ParagraphHeadline:
|
|
176
|
-
print(f"{i:4}: {{DARK_YELLOW}}{
|
|
187
|
+
print(f"{i:4}: {{DARK_YELLOW}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
177
188
|
elif LineKind.Table in line.Kind:
|
|
178
|
-
print(f"{i:4}: {{WHITE}}{
|
|
189
|
+
print(f"{i:4}: {{WHITE}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
179
190
|
elif LineKind.Delimiter in line.Kind:
|
|
180
|
-
print(f"{i:4}: {{GRAY}}{
|
|
191
|
+
print(f"{i:4}: {{GRAY}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
181
192
|
elif LineKind.Verbose in line.Kind:
|
|
182
|
-
print(f"{i:4}: {{DARK_GRAY}}{
|
|
193
|
+
print(f"{i:4}: {{DARK_GRAY}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
194
|
+
elif LineKind.Success in line.Kind:
|
|
195
|
+
print(f"{i:4}: {{GREEN}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
183
196
|
elif line.Kind is LineKind.Empty:
|
|
184
197
|
print(f"{i:4}:")
|
|
185
198
|
elif line.Kind is LineKind.ProcessorError:
|
|
186
|
-
print(f"{i:4}: {{RED}}{
|
|
199
|
+
print(f"{i:4}: {{RED}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
187
200
|
elif line.Kind is LineKind.Unprocessed:
|
|
188
|
-
print(f"{i:4}: {{DARK_RED}}{
|
|
201
|
+
print(f"{i:4}: {{DARK_RED}}{message}{{NOCOLOR}}".format(**self.Foreground))
|
|
189
202
|
else:
|
|
190
203
|
print(f"{i:4}: Unknown LineKind '{line._kind}' for line {line._lineNumber}.")
|
|
191
204
|
print(line)
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# ==================================================================================================================== #
|
|
2
|
+
# _____ ____ _ _ ___ _ _ _____ _ _ _ #
|
|
3
|
+
# _ __ _ _| ____| _ \ / \ / \ / _ \ _ _| |_ _ __ _ _| |_| ___(_) | |_ ___ _ __ #
|
|
4
|
+
# | '_ \| | | | _| | | | |/ _ \ / _ \ | | | | | | | __| '_ \| | | | __| |_ | | | __/ _ \ '__| #
|
|
5
|
+
# | |_) | |_| | |___| |_| / ___ \ / ___ \ | |_| | |_| | |_| |_) | |_| | |_| _| | | | || __/ | #
|
|
6
|
+
# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___/ \__,_|\__| .__/ \__,_|\__|_| |_|_|\__\___|_| #
|
|
7
|
+
# |_| |___/ |_| #
|
|
8
|
+
# ==================================================================================================================== #
|
|
9
|
+
# Authors: #
|
|
10
|
+
# Patrick Lehmann #
|
|
11
|
+
# #
|
|
12
|
+
# License: #
|
|
13
|
+
# ==================================================================================================================== #
|
|
14
|
+
# Copyright 2025-2025 Electronic Design Automation Abstraction (EDA²) #
|
|
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
|
+
"""Basic classes for outputs from AMD/Xilinx Vivado."""
|
|
32
|
+
from typing import ClassVar, Generator, Union, List, Type, Dict, Iterator, Any
|
|
33
|
+
|
|
34
|
+
from pyTooling.Decorators import export, readonly
|
|
35
|
+
|
|
36
|
+
from pyEDAA.OutputFilter.Xilinx import VivadoTclCommand
|
|
37
|
+
from pyEDAA.OutputFilter.Xilinx.Exception import ProcessorException
|
|
38
|
+
from pyEDAA.OutputFilter.Xilinx.Common import Line, LineKind, VivadoMessage, VHDLReportMessage
|
|
39
|
+
from pyEDAA.OutputFilter.Xilinx.Common2 import Parser
|
|
40
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import Section, RTLElaboration, HandlingCustomAttributes
|
|
41
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import ConstraintValidation, LoadingPart, ApplySetProperty
|
|
42
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import RTLComponentStatistics, PartResourceSummary
|
|
43
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import CrossBoundaryAndAreaOptimization, ROM_RAM_DSP_SR_Retiming
|
|
44
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import ApplyingXDCTimingConstraints, TimingOptimization
|
|
45
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import TechnologyMapping, IOInsertion, FlatteningBeforeIOInsertion
|
|
46
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import FinalNetlistCleanup, RenamingGeneratedInstances
|
|
47
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import RebuildingUserHierarchy, RenamingGeneratedPorts
|
|
48
|
+
from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import RenamingGeneratedNets, WritingSynthesisReport
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@export
|
|
52
|
+
class NotPresentException(ProcessorException):
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@export
|
|
57
|
+
class SectionNotPresentException(NotPresentException):
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@export
|
|
62
|
+
class HandlingCustomAttributes1(HandlingCustomAttributes):
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@export
|
|
67
|
+
class HandlingCustomAttributes2(HandlingCustomAttributes):
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@export
|
|
72
|
+
class ROM_RAM_DSP_SR_Retiming1(ROM_RAM_DSP_SR_Retiming):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@export
|
|
77
|
+
class ROM_RAM_DSP_SR_Retiming2(ROM_RAM_DSP_SR_Retiming):
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@export
|
|
82
|
+
class ROM_RAM_DSP_SR_Retiming3(ROM_RAM_DSP_SR_Retiming):
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@export
|
|
87
|
+
class Command(Parser):
|
|
88
|
+
# _TCL_COMMAND: ClassVar[str]
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@export
|
|
93
|
+
class SynthesizeDesign(Command):
|
|
94
|
+
_TCL_COMMAND: ClassVar[str] = "synth_design"
|
|
95
|
+
_PARSERS: ClassVar[List[Type[Section]]] = (
|
|
96
|
+
RTLElaboration,
|
|
97
|
+
HandlingCustomAttributes1,
|
|
98
|
+
ConstraintValidation,
|
|
99
|
+
LoadingPart,
|
|
100
|
+
ApplySetProperty,
|
|
101
|
+
RTLComponentStatistics,
|
|
102
|
+
PartResourceSummary,
|
|
103
|
+
CrossBoundaryAndAreaOptimization,
|
|
104
|
+
ROM_RAM_DSP_SR_Retiming1,
|
|
105
|
+
ApplyingXDCTimingConstraints,
|
|
106
|
+
TimingOptimization,
|
|
107
|
+
ROM_RAM_DSP_SR_Retiming2,
|
|
108
|
+
TechnologyMapping,
|
|
109
|
+
IOInsertion,
|
|
110
|
+
FlatteningBeforeIOInsertion,
|
|
111
|
+
FinalNetlistCleanup,
|
|
112
|
+
RenamingGeneratedInstances,
|
|
113
|
+
RebuildingUserHierarchy,
|
|
114
|
+
RenamingGeneratedPorts,
|
|
115
|
+
HandlingCustomAttributes2,
|
|
116
|
+
RenamingGeneratedNets,
|
|
117
|
+
ROM_RAM_DSP_SR_Retiming3,
|
|
118
|
+
WritingSynthesisReport,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
_sections: Dict[Type[Section], Section]
|
|
122
|
+
|
|
123
|
+
def __init__(self, processor: "Processor") -> None:
|
|
124
|
+
super().__init__(processor)
|
|
125
|
+
|
|
126
|
+
self._sections = {p: p(self) for p in self._PARSERS}
|
|
127
|
+
|
|
128
|
+
@readonly
|
|
129
|
+
def HasLatches(self) -> bool:
|
|
130
|
+
if (8 in self._messagesByID) and (327 in self._messagesByID[8]):
|
|
131
|
+
return True
|
|
132
|
+
|
|
133
|
+
return "LD" in self._sections[WritingSynthesisReport]._cells
|
|
134
|
+
|
|
135
|
+
@readonly
|
|
136
|
+
def Latches(self) -> Iterator[VivadoMessage]:
|
|
137
|
+
try:
|
|
138
|
+
yield from iter(self._messagesByID[8][327])
|
|
139
|
+
except KeyError:
|
|
140
|
+
yield from ()
|
|
141
|
+
|
|
142
|
+
@readonly
|
|
143
|
+
def HasBlackboxes(self) -> bool:
|
|
144
|
+
return len(self._sections[WritingSynthesisReport]._blackboxes) > 0
|
|
145
|
+
|
|
146
|
+
@readonly
|
|
147
|
+
def Blackboxes(self) -> Dict[str, int]:
|
|
148
|
+
return self._sections[WritingSynthesisReport]._blackboxes
|
|
149
|
+
|
|
150
|
+
@readonly
|
|
151
|
+
def Cells(self) -> Dict[str, int]:
|
|
152
|
+
return self._sections[WritingSynthesisReport]._cells
|
|
153
|
+
|
|
154
|
+
@readonly
|
|
155
|
+
def VHDLReportMessages(self) -> List[VHDLReportMessage]:
|
|
156
|
+
if 8 in self._messagesByID:
|
|
157
|
+
if 6031 in (synthMessages := self._messagesByID[8]):
|
|
158
|
+
return [message for message in synthMessages[6031]]
|
|
159
|
+
|
|
160
|
+
return []
|
|
161
|
+
|
|
162
|
+
@readonly
|
|
163
|
+
def VHDLAssertMessages(self) -> List[VHDLReportMessage]:
|
|
164
|
+
if 8 in self._messagesByID:
|
|
165
|
+
if 63 in (synthMessages := self._messagesByID[8]):
|
|
166
|
+
return [message for message in synthMessages[63]]
|
|
167
|
+
|
|
168
|
+
return []
|
|
169
|
+
|
|
170
|
+
def __getitem__(self, item: Type[Parser]) -> Union[_PARSERS]:
|
|
171
|
+
try:
|
|
172
|
+
return self._sections[item]
|
|
173
|
+
except KeyError as ex:
|
|
174
|
+
raise SectionNotPresentException(F"Section '{item._NAME}' not present in '{self._parent.logfile}'.") from ex
|
|
175
|
+
|
|
176
|
+
def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorException], Line, None]:
|
|
177
|
+
# parser: Section = firstValue(self._sections)
|
|
178
|
+
activeParsers: List[Parser] = list(self._sections.values())
|
|
179
|
+
|
|
180
|
+
rtlElaboration = self._sections[RTLElaboration]
|
|
181
|
+
# constraintValidation = self._sections[ConstraintValidation]
|
|
182
|
+
|
|
183
|
+
if not (isinstance(line, VivadoTclCommand) and line._command == self._TCL_COMMAND):
|
|
184
|
+
raise ProcessorException()
|
|
185
|
+
|
|
186
|
+
line = yield line
|
|
187
|
+
if line == "Starting synth_design":
|
|
188
|
+
line._kind = LineKind.Verbose
|
|
189
|
+
else:
|
|
190
|
+
raise ProcessorException()
|
|
191
|
+
|
|
192
|
+
line = yield line
|
|
193
|
+
|
|
194
|
+
while True:
|
|
195
|
+
while True:
|
|
196
|
+
if line.StartsWith("Start "):
|
|
197
|
+
for parser in activeParsers: # type: Section
|
|
198
|
+
if line.StartsWith(parser._START):
|
|
199
|
+
line = next(section := parser.Generator(line))
|
|
200
|
+
line._previousLine._kind = LineKind.SectionStart | LineKind.SectionDelimiter
|
|
201
|
+
break
|
|
202
|
+
else:
|
|
203
|
+
raise Exception(f"Unknown section: {line}")
|
|
204
|
+
break
|
|
205
|
+
elif line.StartsWith("Starting "):
|
|
206
|
+
if line.StartsWith(rtlElaboration._START):
|
|
207
|
+
parser = rtlElaboration
|
|
208
|
+
line = next(section := parser.Generator(line))
|
|
209
|
+
line._previousLine._kind = LineKind.SectionStart | LineKind.SectionDelimiter
|
|
210
|
+
break
|
|
211
|
+
elif line.StartsWith(self._TCL_COMMAND):
|
|
212
|
+
if line[len(self._TCL_COMMAND) + 1:].startswith("completed successfully"):
|
|
213
|
+
line._kind |= LineKind.Success
|
|
214
|
+
|
|
215
|
+
line = yield line
|
|
216
|
+
if line.StartsWith(self._TCL_COMMAND + ":"):
|
|
217
|
+
line._kind |= LineKind.Last
|
|
218
|
+
else:
|
|
219
|
+
pass
|
|
220
|
+
|
|
221
|
+
lastLine = yield line
|
|
222
|
+
return lastLine
|
|
223
|
+
elif line.StartsWith("Finished RTL Optimization Phase"):
|
|
224
|
+
line._kind = LineKind.PhaseEnd
|
|
225
|
+
line._previousLine._kind = LineKind.PhaseEnd | LineKind.PhaseDelimiter
|
|
226
|
+
elif line.StartsWith("----"):
|
|
227
|
+
if LineKind.Phase in line._previousLine._kind:
|
|
228
|
+
line._kind = LineKind.PhaseEnd | LineKind.PhaseDelimiter
|
|
229
|
+
elif not isinstance(line, VivadoMessage):
|
|
230
|
+
pass
|
|
231
|
+
# line._kind = LineKind.Unprocessed
|
|
232
|
+
|
|
233
|
+
line = yield line
|
|
234
|
+
|
|
235
|
+
line = yield line
|
|
236
|
+
|
|
237
|
+
while True:
|
|
238
|
+
if line.StartsWith("Finished"):
|
|
239
|
+
l = line[9:]
|
|
240
|
+
if not (l.startswith("Flattening") or l.startswith("Final")):
|
|
241
|
+
line = yield section.send(line)
|
|
242
|
+
break
|
|
243
|
+
|
|
244
|
+
if isinstance(line, VivadoMessage):
|
|
245
|
+
self._AddMessage(line)
|
|
246
|
+
|
|
247
|
+
line = yield section.send(line)
|
|
248
|
+
|
|
249
|
+
line = yield section.send(line)
|
|
250
|
+
|
|
251
|
+
activeParsers.remove(parser)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@export
|
|
255
|
+
class LinkDesign(Command):
|
|
256
|
+
_TCL_COMMAND: ClassVar[str] = "link_design"
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@export
|
|
260
|
+
class OptimizeDesign(Command):
|
|
261
|
+
_TCL_COMMAND: ClassVar[str] = "opt_design"
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@export
|
|
265
|
+
class PlaceDesign(Command):
|
|
266
|
+
_TCL_COMMAND: ClassVar[str] = "place_design"
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@export
|
|
270
|
+
class PhysicalOptimizationDesign(Command):
|
|
271
|
+
_TCL_COMMAND: ClassVar[str] = "phys_opt_design"
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@export
|
|
275
|
+
class PhysicalOptimizationDesign(Command):
|
|
276
|
+
_TCL_COMMAND: ClassVar[str] = "route_design"
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
@export
|
|
280
|
+
class WriteBitstream(Command):
|
|
281
|
+
_TCL_COMMAND: ClassVar[str] = "write_bitstream"
|
|
282
|
+
|
|
283
|
+
# report_drc
|
|
284
|
+
# report_methodology
|
|
285
|
+
# report_power
|