pyEDAA.OutputFilter 0.1.0__tar.gz → 0.2.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.
Files changed (19) hide show
  1. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/PKG-INFO +32 -27
  2. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/README.md +9 -4
  3. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA/OutputFilter/CLI/Vivado.py +85 -60
  4. pyedaa_outputfilter-0.2.0/pyEDAA/OutputFilter/Xilinx/Synthesis.py +656 -0
  5. pyedaa_outputfilter-0.2.0/pyEDAA/OutputFilter/Xilinx/__init__.py +644 -0
  6. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA/OutputFilter/__init__.py +1 -1
  7. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA.OutputFilter.egg-info/PKG-INFO +32 -27
  8. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA.OutputFilter.egg-info/requires.txt +22 -22
  9. pyedaa_outputfilter-0.1.0/pyEDAA/OutputFilter/Xilinx/Synthesis.py +0 -573
  10. pyedaa_outputfilter-0.1.0/pyEDAA/OutputFilter/Xilinx/__init__.py +0 -179
  11. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/LICENSE.md +0 -0
  12. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA/OutputFilter/CLI/__init__.py +0 -0
  13. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA.OutputFilter.egg-info/SOURCES.txt +0 -0
  14. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA.OutputFilter.egg-info/dependency_links.txt +0 -0
  15. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA.OutputFilter.egg-info/entry_points.txt +0 -0
  16. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyEDAA.OutputFilter.egg-info/top_level.txt +0 -0
  17. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/pyproject.toml +0 -0
  18. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/setup.cfg +0 -0
  19. {pyedaa_outputfilter-0.1.0 → pyedaa_outputfilter-0.2.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyEDAA.OutputFilter
3
- Version: 0.1.0
3
+ Version: 0.2.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
+ Requires-Dist: pyTooling[terminal]~=8.5; extra == "doc"
30
32
  Requires-Dist: docutils_stubs~=0.0.22; extra == "doc"
31
- Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "doc"
32
- Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "doc"
33
- Requires-Dist: autoapi>=2.0.1; extra == "doc"
34
33
  Requires-Dist: sphinx_rtd_theme~=3.0; extra == "doc"
35
- Requires-Dist: docutils~=0.21; extra == "doc"
36
- Requires-Dist: pyTooling[terminal]~=8.5; extra == "doc"
34
+ Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "doc"
37
35
  Requires-Dist: sphinx_autodoc_typehints~=3.2; extra == "doc"
38
- Requires-Dist: sphinx_design~=0.6.1; extra == "doc"
39
36
  Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
40
37
  Requires-Dist: sphinx~=8.2; extra == "doc"
41
38
  Requires-Dist: sphinx_reports~=0.9; extra == "doc"
39
+ Requires-Dist: autoapi>=2.0.1; extra == "doc"
40
+ Requires-Dist: docutils~=0.21; extra == "doc"
41
+ Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "doc"
42
42
  Provides-Extra: test
43
- Requires-Dist: typing_extensions~=4.13; extra == "test"
44
- Requires-Dist: mypy~=1.16; extra == "test"
45
- Requires-Dist: lxml~=5.4; extra == "test"
46
- Requires-Dist: pytest-cov~=6.2; extra == "test"
47
- Requires-Dist: Coverage~=7.9; extra == "test"
48
43
  Requires-Dist: pyTooling[terminal]~=8.5; extra == "test"
44
+ Requires-Dist: typing_extensions~=4.14; extra == "test"
45
+ Requires-Dist: pytest-cov~=6.2; extra == "test"
49
46
  Requires-Dist: pytest~=8.4; extra == "test"
47
+ Requires-Dist: Coverage~=7.9; extra == "test"
48
+ 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
+ Requires-Dist: pyTooling[terminal]~=8.5; extra == "all"
51
53
  Requires-Dist: docutils_stubs~=0.0.22; extra == "all"
52
- Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "all"
53
- Requires-Dist: typing_extensions~=4.13; extra == "all"
54
- Requires-Dist: mypy~=1.16; extra == "all"
55
- Requires-Dist: lxml~=5.4; extra == "all"
56
54
  Requires-Dist: sphinxcontrib-mermaid~=1.0; extra == "all"
57
- Requires-Dist: pytest-cov~=6.2; extra == "all"
58
- Requires-Dist: autoapi>=2.0.1; extra == "all"
59
- Requires-Dist: Coverage~=7.9; extra == "all"
60
55
  Requires-Dist: sphinx_rtd_theme~=3.0; extra == "all"
61
- Requires-Dist: docutils~=0.21; extra == "all"
62
- Requires-Dist: pyTooling[terminal]~=8.5; extra == "all"
63
56
  Requires-Dist: sphinx_autodoc_typehints~=3.2; extra == "all"
64
- Requires-Dist: sphinx_design~=0.6.1; extra == "all"
65
57
  Requires-Dist: sphinx-copybutton>=0.5.2; extra == "all"
66
58
  Requires-Dist: sphinx~=8.2; extra == "all"
67
- Requires-Dist: pytest~=8.4; extra == "all"
59
+ Requires-Dist: typing_extensions~=4.14; extra == "all"
68
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
+ Requires-Dist: lxml~=5.4; extra == "all"
65
+ Requires-Dist: autoapi>=2.0.1; extra == "all"
66
+ Requires-Dist: docutils~=0.21; extra == "all"
67
+ Requires-Dist: sphinxcontrib-autoprogram~=0.1; extra == "all"
68
+ Requires-Dist: mypy~=1.16; extra == "all"
69
69
  Dynamic: author
70
70
  Dynamic: author-email
71
71
  Dynamic: classifier
@@ -110,13 +110,18 @@ Dynamic: summary
110
110
 
111
111
  # Main Goals
112
112
 
113
- * Analyze text outputs from CLI of EDA tools.
114
- * Filter and categorize by severity (*info*, *warning*, *error*, *fatal*, ...).
115
- * Extract information from e.g. OSVVM logs, VUnit logs, ...
113
+ * Live and offline parsing and classification of message lines from tool outputs.
114
+ * Provide a data model for tool specific log files.
115
+ * Extract values, lists and tables of embedded reports or summaries.
116
+ * Implement checks and policies.
116
117
 
117
118
  # Use Cases
118
119
 
119
- * *tbd*
120
+ * Write colorized logs to CI server logs or to shells based on classification.
121
+ * Increase or decrease the severity level of message.
122
+ * List messages of a certain kind (e.g. unused sequential elements).
123
+ * Check for existence / non-existence of messages or outputs (e.g. latches).
124
+ * Collect statistics and convert to datasets for a time series database (TSDB).
120
125
 
121
126
  # Examples
122
127
 
@@ -27,13 +27,18 @@
27
27
 
28
28
  # Main Goals
29
29
 
30
- * Analyze text outputs from CLI of EDA tools.
31
- * Filter and categorize by severity (*info*, *warning*, *error*, *fatal*, ...).
32
- * Extract information from e.g. OSVVM logs, VUnit logs, ...
30
+ * Live and offline parsing and classification of message lines from tool outputs.
31
+ * Provide a data model for tool specific log files.
32
+ * Extract values, lists and tables of embedded reports or summaries.
33
+ * Implement checks and policies.
33
34
 
34
35
  # Use Cases
35
36
 
36
- * *tbd*
37
+ * Write colorized logs to CI server logs or to shells based on classification.
38
+ * Increase or decrease the severity level of message.
39
+ * List messages of a certain kind (e.g. unused sequential elements).
40
+ * Check for existence / non-existence of messages or outputs (e.g. latches).
41
+ * Collect statistics and convert to datasets for a time series database (TSDB).
37
42
 
38
43
  # Examples
39
44
 
@@ -30,60 +30,23 @@
30
30
  #
31
31
  from argparse import Namespace
32
32
  from pathlib import Path
33
- from sys import stdin
34
- from typing import NoReturn
33
+ from typing import NoReturn, Iterable
35
34
 
36
- from pyTooling.Decorators import readonly
37
- from pyTooling.MetaClasses import ExtendedType
38
- from pyTooling.Common import count
39
- from pyTooling.Attributes.ArgParse import CommandHandler
40
- from pyTooling.Attributes.ArgParse.Flag import LongFlag
41
- from pyTooling.Attributes.ArgParse.ValuedFlag import LongValuedFlag
42
- from pyTooling.Stopwatch import Stopwatch
35
+ from pyTooling.Decorators import readonly
36
+ from pyTooling.MetaClasses import ExtendedType
37
+ from pyTooling.Attributes.ArgParse import CommandHandler
38
+ from pyTooling.Attributes.ArgParse.Flag import LongFlag
39
+ from pyTooling.Attributes.ArgParse.ValuedFlag import LongValuedFlag
43
40
 
44
- from pyEDAA.OutputFilter.Xilinx.Synthesis import Processor, Preamble, WritingSynthesisReport
41
+ from pyEDAA.OutputFilter.Xilinx import Preamble, LineKind, Line
42
+ from pyEDAA.OutputFilter.Xilinx.Synthesis import WritingSynthesisReport, Processor, LoadingPart
45
43
 
46
44
 
47
- class Proto(metaclass=ExtendedType, mixin=True):
48
- @readonly
49
- def Verbose(self) -> bool:
50
- ...
51
-
52
- @readonly
53
- def Width(self) -> int:
54
- ...
55
-
56
- def _PrintHeadline(self):
57
- ...
58
-
59
- def WriteDebug(self, a: str, appendLinebreak: bool = True):
60
- ...
61
-
62
- def WriteVerbose(self, a: str, appendLinebreak: bool = True):
63
- ...
64
-
65
- def WriteNormal(self, a: str, appendLinebreak: bool = True):
66
- ...
67
-
68
- def WriteWarning(self, a: str, appendLinebreak: bool = True):
69
- ...
70
-
71
- def WriteCritical(self, a: str, appendLinebreak: bool = True):
72
- ...
73
-
74
- def WriteError(self, a: str, appendLinebreak: bool = True):
75
- ...
76
-
77
- def WriteFatal(self, a: str, appendLinebreak: bool = True, immediateExit: bool = True):
78
- ...
79
-
80
- def Exit(self, i: int = 0) -> NoReturn:
81
- ...
82
-
83
-
84
- class VivadoHandlers(Proto, metaclass=ExtendedType, mixin=True):
45
+ class VivadoHandlers(metaclass=ExtendedType, mixin=True):
85
46
  @CommandHandler("vivado-synth", help="Parse AMD/Xilinx Vivado Synthesis log files.", description="Parse AMD/Xilinx Vivado Synthesis log files.")
86
47
  @LongValuedFlag("--file", dest="logfile", metaName='Synthesis Log', help="Synthesis log file (*.vds).")
48
+ @LongFlag("--colored", dest="colored", help="Render logfile with colored lines.")
49
+ @LongFlag("--summary", dest="summary", help="Print a summary.")
87
50
  @LongFlag("--info", dest="info", help="Print info messages.")
88
51
  @LongFlag("--warning", dest="warning", help="Print warning messages.")
89
52
  @LongFlag("--critical", dest="critical", help="Print critical warning messages.")
@@ -110,6 +73,9 @@ class VivadoHandlers(Proto, metaclass=ExtendedType, mixin=True):
110
73
  processor = Processor(logfile)
111
74
  processor.Parse()
112
75
 
76
+ if args.colored:
77
+ self.ColoredOutput(processor._lines)
78
+
113
79
  if args.info:
114
80
  self.WriteNormal(f"INFO messages: {len(processor.InfoMessages)}")
115
81
  for message in processor.InfoMessages:
@@ -150,18 +116,77 @@ class VivadoHandlers(Proto, metaclass=ExtendedType, mixin=True):
150
116
 
151
117
  self.WriteNormal(influxString)
152
118
 
153
- self.WriteNormal("Summary:")
154
- self.WriteNormal(f" Processing duration: {processor.Duration:.3f} s")
155
- self.WriteNormal(f" Info: {len(processor.InfoMessages)} Warning: {len(processor.WarningMessages)} Critical Warning: {len(processor.CriticalWarningMessages)} Error: {len(processor.ErrorMessages)}")
119
+ if args.summary:
120
+ self.WriteNormal("Summary:")
121
+ self.WriteNormal(f" Tool version: {processor[Preamble].ToolVersion}")
122
+ self.WriteNormal(f" Started at: {processor[Preamble].StartDatetime}")
123
+ self.WriteNormal(f" Processing duration: {processor.Duration:.3f} s")
124
+ self.WriteNormal(f" Info: {len(processor.InfoMessages)}")
125
+ self.WriteNormal(f" Warning: {len(processor.WarningMessages)}")
126
+ self.WriteNormal(f" Critical Warning: {len(processor.CriticalWarningMessages)}")
127
+ self.WriteNormal(f" Error: {len(processor.ErrorMessages)}")
128
+ self.WriteNormal(f" Part: {processor[LoadingPart].Part}")
129
+
130
+ self.WriteNormal("Policies:")
131
+ self.WriteNormal(f" Latches: {'found' if processor.HasLatches else '----'}")
132
+ if processor.HasLatches:
133
+ for cellName in ("LD", ):
134
+ try:
135
+ self.WriteNormal(f" {cellName}: {processor.Cells[cellName]}")
136
+ except KeyError:
137
+ pass
138
+ for latch in processor.Latches:
139
+ self.WriteNormal(f" {latch}")
140
+ self.WriteNormal(f" Blackboxes: {'found' if processor.HasBlackboxes else '----'}")
141
+ if processor.HasBlackboxes:
142
+ for bbox in processor[WritingSynthesisReport].Blackboxes:
143
+ self.WriteNormal(f" {bbox}")
144
+
145
+ self.WriteNormal(f"VHDL report statements ({len(processor.VHDLReportMessages)}):")
146
+ for message in processor.VHDLReportMessages:
147
+ self.WriteNormal(f" {message}")
148
+ self.WriteNormal(f"VHDL assert statements ({len(processor.VHDLAssertMessages)}):")
149
+ for message in processor.VHDLAssertMessages:
150
+ self.WriteNormal(f" {message}")
151
+
152
+ self.WriteNormal(f"Cells: {len(processor.Cells)}")
153
+ for cell, count in processor.Cells.items():
154
+ self.WriteNormal(f" {cell}: {count}")
156
155
 
157
156
  self.ExitOnPreviousErrors()
158
157
 
159
- @CommandHandler("vivado-impl", help="Parse AMD/Xilinx Vivado Implementation log files.", description="Parse AMD/Xilinx Vivado Implementation log files.")
160
- @LongValuedFlag("--file", dest="logfile", metaName='Implementation Log', help="Implementation log file (*.vdi).")
161
- @LongFlag("--info", dest="info", help="Print info messages.")
162
- @LongFlag("--warning", dest="warning", help="Print warning messages.")
163
- @LongFlag("--critical", dest="critical", help="Print critical warning messages.")
164
- @LongFlag("--error", dest="error", help="Print error messages.")
165
- def HandleVivadoImplementation(self, args: Namespace) -> None:
166
- """Handle program calls with command ``vivado-impl``."""
167
- self._PrintHeadline()
158
+ def ColoredOutput(self, lines: Iterable[Line]) -> None:
159
+ for i, line in enumerate(lines, start=1):
160
+ if line.Kind is LineKind.Normal:
161
+ print(f"{i:4}: {line.Message}")
162
+ elif LineKind.Message in line.Kind:
163
+ if line.Kind is LineKind.InfoMessage:
164
+ print(f"{i:4}: {{BLUE}}{line}{{NOCOLOR}}".format(**self.Foreground))
165
+ elif line.Kind is LineKind.WarningMessage:
166
+ print(f"{i:4}: {{YELLOW}}{line}{{NOCOLOR}}".format(**self.Foreground))
167
+ elif line.Kind is LineKind.CriticalWarningMessage:
168
+ print(f"{i:4}: {{MAGENTA}}{line}{{NOCOLOR}}".format(**self.Foreground))
169
+ elif line.Kind is LineKind.ErrorMessage:
170
+ print(f"{i:4}: {{RED}}{line}{{NOCOLOR}}".format(**self.Foreground))
171
+ elif LineKind.Command in line.Kind:
172
+ print(f"{i:4}: {{CYAN}}{line}{{NOCOLOR}}".format(**self.Foreground))
173
+ elif (LineKind.Start in line.Kind) or (LineKind.End in line.Kind):
174
+ print(f"{i:4}: {{DARK_CYAN}}{line}{{NOCOLOR}}".format(**self.Foreground))
175
+ elif line.Kind is LineKind.ParagraphHeadline:
176
+ print(f"{i:4}: {{DARK_YELLOW}}{line}{{NOCOLOR}}".format(**self.Foreground))
177
+ elif LineKind.Table in line.Kind:
178
+ print(f"{i:4}: {{WHITE}}{line}{{NOCOLOR}}".format(**self.Foreground))
179
+ elif LineKind.Delimiter in line.Kind:
180
+ print(f"{i:4}: {{GRAY}}{line}{{NOCOLOR}}".format(**self.Foreground))
181
+ elif LineKind.Verbose in line.Kind:
182
+ print(f"{i:4}: {{DARK_GRAY}}{line}{{NOCOLOR}}".format(**self.Foreground))
183
+ elif line.Kind is LineKind.Empty:
184
+ print(f"{i:4}:")
185
+ elif line.Kind is LineKind.ProcessorError:
186
+ print(f"{i:4}: {{RED}}{line}{{NOCOLOR}}".format(**self.Foreground))
187
+ elif line.Kind is LineKind.Unprocessed:
188
+ print(f"{i:4}: {{DARK_RED}}{line}{{NOCOLOR}}".format(**self.Foreground))
189
+ else:
190
+ print(f"{i:4}: Unknown LineKind '{line._kind}' for line {line._lineNumber}.")
191
+ print(line)
192
+ raise Exception()