@@ -189,35 +189,84 @@ def Processor(self) -> "Processor":
189189
190190@export
191191class Preamble (Parser ):
192- _toolVersion : Nullable [ YearReleaseVersion ]
193- _startDatetime : Nullable [ datetime ]
192+ """
193+ A parser for the preamble emitted by Vivado at session start.
194194
195+ .. rubric:: Extracted information
196+
197+ * Vivado tool version. |br|
198+ See :data:`ToolVersion`
199+ * Session start timestamp (date and time). |br|
200+ See :data:`StartDatetime`
201+
202+ .. rubric:: Example
203+
204+ .. code-block::
205+
206+ #-----------------------------------------------------------
207+ # Vivado v2019.1 (64-bit)
208+ # SW Build 2552052 on Fri May 24 14:49:42 MDT 2019
209+ # IP Build 2548770 on Fri May 24 18:01:18 MDT 2019
210+ # Start of session at: Tue Sep 2 08:44:13 2025
211+ # Process ID: 35680
212+ # Current directory: C:/[...]/MercuryZX5_PE1.runs/synth_1
213+ # Command line: vivado.exe -log system_top.vds -product Vivado -mode batch -messageDb vivado.pb -notrace -source system_top.tcl
214+ # Log file: C:/[...]/MercuryZX5_PE1.runs/synth_1/system_top.vds
215+ # Journal file: C:/[...]/MercuryZX5_PE1.runs/synth_1/vivado.jou
216+ #-----------------------------------------------------------
217+
218+ """
195219 _VERSION : ClassVar [Pattern ] = re_compile (r"""# Vivado v(\d+\.\d(\.\d)?) \(64-bit\)""" )
196- _STARTTIME : ClassVar [Pattern ] = re_compile (r"""# Start of session at: (\w+ \w+ \d+ \d+:\d+:\d+ \d+)""" )
220+ _STARTTIME : ClassVar [Pattern ] = re_compile (r"""# Start of session at: (\w+\s+\w+\s+\d+\s+\d+:\d+:\d+\s+\d+)""" )
221+
222+ _toolVersion : Nullable [YearReleaseVersion ] #: Used Vivado version.
223+ _startDatetime : Nullable [datetime ] #: Session start timestamp.
197224
198225 def __init__ (self , processor : "BaseProcessor" ) -> None :
226+ """
227+ Initializes a Vivado preamble parser.
228+
229+ :param processor: Reference to the Vivado log processor.
230+ """
199231 super ().__init__ (processor )
200232
201233 self ._toolVersion = None
202234 self ._startDatetime = None
203235
204236 @readonly
205237 def ToolVersion (self ) -> YearReleaseVersion :
238+ """
239+ Read-only property to access the extracted Vivado tool version.
240+
241+ :returns: The used Vivado version as reported in the Vivado log messages.
242+ """
206243 return self ._toolVersion
207244
208245 @readonly
209246 def StartDatetime (self ) -> datetime :
247+ """
248+ Read-only property to access the date and time when the Vivado session was started.
249+
250+ :returns: Datatime when the session was started.
251+ """
210252 return self ._startDatetime
211253
212254 def Generator (self , line : Line ) -> Generator [Line , Line , Line ]:
255+ """
256+ A generator for processing the Vivado session preamble line-by-line.
257+
258+ :param line: First line to process.
259+ :returns: A generator processing log messages.
260+ """
213261 if line .StartsWith ("#----" ):
214262 line ._kind = LineKind .SectionDelimiter
215263 else :
216- line ._kind |= LineKind .ProcessorError
264+ line ._kind |= LineKind .ProcessorError # TODO: throw / return error
217265
218266 line = yield line
219267
220- while True :
268+ # a normal preamble has 11 lines including both delimiter lines.
269+ for _ in range (15 ):
221270 if (match := self ._VERSION .match (line ._message )) is not None :
222271 self ._toolVersion = YearReleaseVersion .Parse (match [1 ])
223272 line ._kind = LineKind .Normal
@@ -231,31 +280,68 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]:
231280 line ._kind = LineKind .Verbose
232281
233282 line = yield line
283+ else :
284+ line ._kind |= LineKind .ProcessorError # TODO: throw / return error
234285
235286 nextLine = yield line
236287 return nextLine
237288
238289
239290@export
240291class Task (BaseParser , VivadoMessagesMixin , metaclass = ExtendedType , slots = True ):
292+ """
293+ A task's output emitted by a Vivado command.
294+
295+ .. rubric:: Extracted information
296+
297+ * Vivado messages (info, warning, critical warning, error).
298+
299+ .. rubric:: Example
300+
301+ .. code-block::
302+
303+ Starting Cache Timing Information Task
304+ INFO: [Timing 38-35] 79-Done setting XDC timing constraints.
305+ Ending Cache Timing Information Task | Checksum: 19fe8cb97
306+
307+ Time (s): cpu = 00:00:09 ; elapsed = 00:00:09 . Memory (MB): peak = 1370.594 ; gain = 493.266
308+
309+ """
241310 # _START: ClassVar[str]
242311 # _FINISH: ClassVar[str]
243312 _TIME : ClassVar [str ] = "Time (s):"
244313
245- _command : "Command"
246- _duration : float
314+ _command : "Command" #: Reference to the command (parent).
315+ _duration : float #: Duration of a task according to reported times by Vivado.
247316
248317 def __init__ (self , command : "Command" ) -> None :
318+ """
319+ Initializes a task (without child elements).
320+
321+ :param command: Reference to the command.
322+ """
249323 super ().__init__ ()
250324 VivadoMessagesMixin .__init__ (self )
251325
252326 self ._command = command
253327
254328 @readonly
255329 def Command (self ) -> "Command" :
330+ """
331+ Read-only property to access the command.
332+
333+ :returns: The command this task's output was logged for.
334+ """
256335 return self ._command
257336
258337 def _TaskStart (self , line : Line ) -> Generator [Line , Line , Line ]:
338+ """
339+ A generator for processing a task start (single line).
340+
341+ :param line: First line to process (task start).
342+ :returns: A generator processing log messages.
343+ :raises ProcessorException: If first line doesn't conform to the *task start* pattern.
344+ """
259345 if not line .StartsWith (self ._START ):
260346 raise ProcessorException (f"{ self .__class__ .__name__ } ._TaskStart(): Expected '{ self ._START } ' at line { line ._lineNumber } ." )
261347
@@ -264,12 +350,19 @@ def _TaskStart(self, line: Line) -> Generator[Line, Line, Line]:
264350 return nextLine
265351
266352 def _TaskFinish (self , line : Line ) -> Generator [Line , Line , Line ]:
353+ """
354+ A generator for processing a task finish line-by-line.
355+
356+ :param line: First line to process (task finish).
357+ :returns: A generator processing log messages.
358+ :raises ProcessorException: If finish line doesn't conform to the *task finish* pattern.
359+ """
267360 if not line .StartsWith (self ._FINISH ):
268361 raise ProcessorException (f"{ self .__class__ .__name__ } ._TaskFinish(): Expected '{ self ._FINISH } ' at line { line ._lineNumber } ." )
269362
270363 line ._kind = LineKind .TaskEnd
271364 line = yield line
272- while self ._TIME is not None :
365+ while self ._TIME is not None : # TODO: limit search for time pattern to XX lines
273366 if line .StartsWith (self ._TIME ):
274367 line ._kind = LineKind .TaskTime
275368 break
@@ -280,6 +373,23 @@ def _TaskFinish(self, line: Line) -> Generator[Line, Line, Line]:
280373 return line
281374
282375 def Generator (self , line : Line ) -> Generator [Line , Line , Line ]:
376+ """
377+ A generator for processing a task without child elements line-by-line.
378+
379+ .. rubric:: Algorithm
380+
381+ 1. Send first line to :meth:`_TaskStart`.
382+ 2. Process body lines
383+
384+ * Collect Vivado messages (info, warning, critical warning, error).
385+ * Check for *task finish* pattern.
386+ * Check for *time* pattern.
387+
388+ 3. Send last lines to :meth:`_TaskFinish`.
389+
390+ :param line: First line to process.
391+ :returns: A generator processing log messages.
392+ """
283393 line = yield from self ._TaskStart (line )
284394
285395 while True :
@@ -306,13 +416,32 @@ def __str__(self) -> str:
306416
307417@export
308418class TaskWithSubTasks (Task ):
419+ """
420+ A task's output emitted by a Vivado command.
421+
422+ .. rubric:: Extracted information
423+
424+ * Vivado messages (info, warning, critical warning, error).
425+ * Subtasks
426+
427+ .. rubric:: Example
428+
429+ .. code-block::
430+
431+ Starting Cache Timing Information Task
432+ INFO: [Timing 38-35] 79-Done setting XDC timing constraints.
433+ Ending Cache Timing Information Task | Checksum: 19fe8cb97
434+
435+ Time (s): cpu = 00:00:09 ; elapsed = 00:00:09 . Memory (MB): peak = 1370.594 ; gain = 493.266
436+
437+ """
309438 # _START: ClassVar[str]
310439 # _FINISH: ClassVar[str]
311440 # _TIME: ClassVar[str] = "Time (s):"
312441
313- _PARSERS : ClassVar [Dict [YearReleaseVersion ,Tuple [Type ["SubTask" ], ...]]] = dict ()
442+ _PARSERS : ClassVar [Dict [YearReleaseVersion ,Tuple [Type ["SubTask" ], ...]]] = dict ()
314443
315- _subtasks : Dict [Type ["SubTask" ], "SubTask" ]
444+ _subtasks : Dict [Type ["SubTask" ], "SubTask" ]
316445
317446 def __init__ (self , command : "Command" ) -> None :
318447 super ().__init__ (command )
0 commit comments