From bcf94b80f2125645b902c64a63b84c1d528decb2 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 1 Feb 2026 01:29:09 +0100 Subject: [PATCH 1/7] Added more doc-strings. --- pyEDAA/OutputFilter/Xilinx/Commands.py | 127 +++++++++ pyEDAA/OutputFilter/Xilinx/Common.py | 9 +- pyEDAA/OutputFilter/Xilinx/Exception.py | 22 +- pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py | 88 +++--- .../Xilinx/PhysicalOptimizeDesign.py | 25 ++ pyEDAA/OutputFilter/Xilinx/PlaceDesign.py | 188 +++++++++++++ pyEDAA/OutputFilter/Xilinx/RouteDesign.py | 256 ++++++++++++++++++ .../OutputFilter/Xilinx/SynthesizeDesign.py | 95 +++++++ pyEDAA/OutputFilter/__init__.py | 2 +- run.ps1 | 2 +- 10 files changed, 768 insertions(+), 46 deletions(-) diff --git a/pyEDAA/OutputFilter/Xilinx/Commands.py b/pyEDAA/OutputFilter/Xilinx/Commands.py index 94c6293..0403702 100644 --- a/pyEDAA/OutputFilter/Xilinx/Commands.py +++ b/pyEDAA/OutputFilter/Xilinx/Commands.py @@ -96,9 +96,50 @@ class ROM_RAM_DSP_SR_Retiming3(ROM_RAM_DSP_SR_Retiming): @export class Command(Parser): + """ + This parser parses outputs from Vivado TCL commands. + + Depending on the command's output (and how it's implemented), they use different subcategories. + + .. rubric:: Command subcategories + + * :class:`CommandWithSections` + * :class:`CommandWithtasks` + + .. rubric:: Supported commands + + * :class:`SynthesizeDesign` + * :class:`LinkDesign` + * :class:`OptimizeDesign` + * :class:`PlaceDesign` + * :class:`PhysicalOptimizeDesign` + * :class:`RouteDesign` + * :class:`WriteBitstream` + * :class:`ReportDRC` + * :class:`ReportMethodology` + * :class:`ReportPower` + + .. rubric:: Example + + .. code-block:: + + [...] + Command: synth_design -top system_top -part xc7z015clg485-2 + Starting synth_design + [...] + """ + # _TCL_COMMAND: ClassVar[str] def _CommandStart(self, line: Line) -> Generator[Line, Line, Line]: + """ + A generator accepting a line containing the expected Vivado TCL command. + + When the generator exits, the returned line is the successor line to the line containing the Vivado TCL command. + + :param line: The first line for the generator to process. + :returns: A generator processing Vivado output log lines. + """ if not (isinstance(line, VivadoTclCommand) and line._command == self._TCL_COMMAND): raise ProcessorException() @@ -145,6 +186,27 @@ def __str__(self) -> str: @export class CommandWithSections(Command): + """ + A Vivado command writing sections into the output log. + + .. rubric:: Example + + .. code-block:: + + [...] + --------------------------------------------------------------------------------- + Starting RTL Elaboration : Time (s): cpu = 00:00:03 ; elapsed = 00:00:03 . Memory (MB): peak = 847.230 ; gain = 176.500 + --------------------------------------------------------------------------------- + INFO: [Synth 8-638] synthesizing module 'system_top' [C:/Users/tgomes/git/2019_1/src/system_top_PE1.vhd:257] + [...] + [...] + [...] + --------------------------------------------------------------------------------- + Finished RTL Elaboration : Time (s): cpu = 00:00:04 ; elapsed = 00:00:04 . Memory (MB): peak = 917.641 ; gain = 246.910 + --------------------------------------------------------------------------------- + [...] + """ + _sections: Dict[Type[Section], Section] _PARSERS: ClassVar[Tuple[Type[Section], ...]] = dict() @@ -156,6 +218,11 @@ def __init__(self, processor: "Processor") -> None: @readonly def Sections(self) -> Dict[Type[Section], Section]: + """ + Read-only property to access a dictionary of found sections within the TCL command's output. + + :returns: A dictionary of found :class:`~pyEDAA.OutputFilter.Xilinx.SynthesizeDesign.Section`s. + """ return self._sections def __getitem__(self, key: Type[Section]) -> Section: @@ -164,6 +231,21 @@ def __getitem__(self, key: Type[Section]) -> Section: @export class CommandWithTasks(Command): + """ + A Vivado command writing tasks into the output log. + + .. rubric:: Example + + .. code-block:: + + [...] + Starting Cache Timing Information Task + INFO: [Timing 38-35] 79-Done setting XDC timing constraints. + [...] + [...] + Ending Cache Timing Information Task | Checksum: 19fe8cb97 + [...] + """ _tasks: Dict[Type[Task], Task] def __init__(self, processor: "Processor") -> None: @@ -173,6 +255,11 @@ def __init__(self, processor: "Processor") -> None: @readonly def Tasks(self) -> Dict[Type[Task], Task]: + """ + Read-only property to access a dictionary of found tasks within the TCL command's output. + + :returns: A dictionary of found :class:`~pyEDAA.OutputFilter.Xilinx.Common2.Task`s. + """ return self._tasks def __getitem__(self, key: Type[Task]) -> Task: @@ -181,6 +268,9 @@ def __getitem__(self, key: Type[Task]) -> Task: @export class SynthesizeDesign(CommandWithSections): + """ + A Vivado command output parser for ``synth_design``. + """ _TCL_COMMAND: ClassVar[str] = "synth_design" _PARSERS: ClassVar[Tuple[Type[Section], ...]] = ( RTLElaboration, @@ -211,6 +301,16 @@ class SynthesizeDesign(CommandWithSections): @readonly def HasLatches(self) -> bool: + """ + Read-only property returning if synthesis inferred latches into the design. + + Latch detection is based on: + + * Vivado message ``synth 8-327`` + * Cells of lind ``LD`` listed in the *Cell Usage* report. + + :returns: True, if the design contains latches. + """ if (8 in self._messagesByID) and (327 in self._messagesByID[8]): return True @@ -338,6 +438,9 @@ def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorExceptio @export class LinkDesign(Command): + """ + A Vivado command output parser for ``link_design``. + """ _TCL_COMMAND: ClassVar[str] = "link_design" _TIME: ClassVar[str] = "Time (s):" @@ -435,6 +538,9 @@ def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorExceptio @export class OptimizeDesign(CommandWithTasks): + """ + A Vivado command output parser for ``opt_design``. + """ _TCL_COMMAND: ClassVar[str] = "opt_design" _TIME: ClassVar[str] = None @@ -510,6 +616,9 @@ def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorExceptio @export class PlaceDesign(CommandWithTasks): + """ + A Vivado command output parser for ``place_design``. + """ _TCL_COMMAND: ClassVar[str] = "place_design" _TIME: ClassVar[str] = None @@ -580,6 +689,9 @@ def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorExceptio @export class PhysicalOptimizeDesign(CommandWithTasks): + """ + A Vivado command output parser for ``phy_opt_design``. + """ _TCL_COMMAND: ClassVar[str] = "phys_opt_design" _TIME: ClassVar[str] = None @@ -651,6 +763,9 @@ def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorExceptio @export class RouteDesign(CommandWithTasks): + """ + A Vivado command output parser for ``route_design``. + """ _TCL_COMMAND: ClassVar[str] = "route_design" _TIME: ClassVar[str] = "Time (s):" @@ -721,23 +836,35 @@ def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorExceptio @export class WriteBitstream(Command): + """ + A Vivado command output parser for ``write_bitstream``. + """ _TCL_COMMAND: ClassVar[str] = "write_bitstream" _TIME: ClassVar[str] = "Time (s):" @export class ReportDRC(Command): + """ + A Vivado command output parser for ``report_drc``. + """ _TCL_COMMAND: ClassVar[str] = "report_drc" _TIME: ClassVar[str] = None @export class ReportMethodology(Command): + """ + A Vivado command output parser for ``report_methodology``. + """ _TCL_COMMAND: ClassVar[str] = "report_methodology" _TIME: ClassVar[str] = None @export class ReportPower(Command): + """ + A Vivado command output parser for ``report_power``. + """ _TCL_COMMAND: ClassVar[str] = "report_power" _TIME: ClassVar[str] = None diff --git a/pyEDAA/OutputFilter/Xilinx/Common.py b/pyEDAA/OutputFilter/Xilinx/Common.py index dd26533..60522e5 100644 --- a/pyEDAA/OutputFilter/Xilinx/Common.py +++ b/pyEDAA/OutputFilter/Xilinx/Common.py @@ -32,7 +32,7 @@ from enum import Flag from pathlib import Path from re import Pattern, compile as re_compile -from typing import Optional as Nullable, Self, ClassVar, Tuple, Union, Any +from typing import Optional as Nullable, Self, ClassVar, Tuple, Union, Any from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType @@ -40,6 +40,9 @@ @export class LineKind(Flag): + """ + Classification of a log message line. + """ Unprocessed = 0 ProcessorError = 2** 0 Empty = 2** 1 @@ -440,6 +443,10 @@ def __str__(self) -> str: @export class VivadoTclCommand(TclCommand): + """ + Represents a Vivado specific TCL command. + """ + _PREFIX: ClassVar[str] = "Command:" @classmethod diff --git a/pyEDAA/OutputFilter/Xilinx/Exception.py b/pyEDAA/OutputFilter/Xilinx/Exception.py index 15a4504..ba816bd 100644 --- a/pyEDAA/OutputFilter/Xilinx/Exception.py +++ b/pyEDAA/OutputFilter/Xilinx/Exception.py @@ -36,15 +36,27 @@ @export class ProcessorException(OutputFilterException): - pass + """ + Base-class for exceptions raised by processors parsing log outputs. + """ @export class ClassificationException(ProcessorException): - _lineNumber: int - _rawMessage: str + """ + Raised if a log output line couldn't be classified. + """ + _lineNumber: int #: Line number of the unclassified line. + _rawMessage: str #: Raw message of the unclassified line. def __init__(self, errorMessage: str, lineNumber: int, rawMessageLine: str) -> None: + """ + Initializes a classification exception. + + :param errorMessage: Error message why the line couldn't be classified. + :param lineNumber: Line number of the unclassified line. + :param rawMessageLine: Raw message of the unclassified line. + """ super().__init__(errorMessage) self._lineNumber = lineNumber @@ -56,4 +68,6 @@ def __str__(self) -> str: @export class ParserStateException(ProcessorException): - pass + """ + Raised if a log output parser has a broken state. + """ diff --git a/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py b/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py index 8ceaf46..f17ba16 100644 --- a/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py @@ -41,6 +41,11 @@ @export class Phase_Retarget(Phase): + """ + *Retarget* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Retarget") _FINISH: ClassVar[str] = "Phase {phaseIndex} Retarget | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -63,6 +68,11 @@ class SubPhase_SetupConstraintsAndSortNetlist(SubPhase): @export class Phase_Initialization(PhaseWithChildren): + """ + *Initialization* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Initialization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Initialization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -76,6 +86,11 @@ class Phase_Initialization(PhaseWithChildren): @export class Phase_ConstantPropagation(Phase): + """ + *Constant propagation* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Constant propagation") _FINISH: ClassVar[str] = "Phase {phaseIndex} Constant propagation | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -98,6 +113,11 @@ class SubPhase_TimingDataCollection(SubPhase): @export class Phase_TimerUpdateAndTimingDataCollection(PhaseWithChildren): + """ + *Timer Update And Timing Data Collection* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Timer Update And Timing Data Collection") _FINISH: ClassVar[str] = "Phase {phaseIndex} Timer Update And Timing Data Collection | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -111,54 +131,24 @@ class Phase_TimerUpdateAndTimingDataCollection(PhaseWithChildren): @export class Phase_Sweep(Phase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Sweep") - _FINISH: ClassVar[str] = "Phase {phaseIndex} Sweep | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - _FINAL: ClassVar[str] = "Sweep | Checksum:" - - -@export -class Phase_BUFGOptimization(Phase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} BUFG optimization") - _FINISH: ClassVar[str] = "Phase {phaseIndex} BUFG optimization | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - _FINAL: ClassVar[str] = "BUFG optimization | Checksum:" - - -@export -class Phase_ConstantPropagation(Phase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Constant propagation") - _FINISH: ClassVar[str] = "Phase {phaseIndex} Constant propagation | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - _FINAL: ClassVar[str] = "Constant propagation | Checksum:" + """ + *Sweep* phase. - -@export -class Phase_ShiftRegisterOptimization(Phase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Shift Register Optimization") - _FINISH: ClassVar[str] = "Phase {phaseIndex} Shift Register Optimization | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - _FINAL: ClassVar[str] = "Shift Register Optimization | Checksum:" - - -@export -class Phase_Sweep(Phase): + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Sweep") _FINISH: ClassVar[str] = "Phase {phaseIndex} Sweep | Checksum:" _TIME: ClassVar[str] = "Time (s):" _FINAL: ClassVar[str] = "Sweep | Checksum:" -@export -class Phase_PostProcessingNetlist(Phase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post Processing Netlist") - _FINISH: ClassVar[str] = "Phase {phaseIndex} Post Processing Netlist | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - _FINAL: ClassVar[str] = "Post Processing Netlist | Checksum:" - - @export class Phase_BUFGOptimization(Phase): + """ + *BUFG optimization* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} BUFG optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex} BUFG optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -167,6 +157,11 @@ class Phase_BUFGOptimization(Phase): @export class Phase_ShiftRegisterOptimization(Phase): + """ + *Shift Register Optimization* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Shift Register Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Shift Register Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -175,6 +170,11 @@ class Phase_ShiftRegisterOptimization(Phase): @export class Phase_PostProcessingNetlist(Phase): + """ + *Post Processing Netlist* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post Processing Netlist") _FINISH: ClassVar[str] = "Phase {phaseIndex} Post Processing Netlist | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -197,6 +197,11 @@ class SubPhase_VerifyingNetlistConnectivity(SubPhase): @export class Phase_Finalization(PhaseWithChildren): + """ + *Finalization* phase. + + Used by task :class:`LogicOptimizationTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Finalization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Finalization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -222,6 +227,11 @@ class CacheTimingInformationTask(Task): @export class LogicOptimizationTask(TaskWithPhases): + """ + *Logic Optimization* task. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.OptimizeDesign`. + """ _START: ClassVar[str] = "Starting Logic Optimization Task" _FINISH: ClassVar[str] = "Ending Logic Optimization Task" diff --git a/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py b/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py index d6e8ef7..8d14090 100644 --- a/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py @@ -47,30 +47,55 @@ class InitialUpdateTimingTask(Task): @export class Phase_PlacerInitialization(Phase): + """ + *Physical Synthesis Initialization* phase. + + Used by task :class:`PhysicalSynthesisTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Physical Synthesis Initialization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Physical Synthesis Initialization | Checksum:" @export class Phase_DSPRegisterOptimization(Phase): + """ + *DSP Register Optimization* phase. + + Used by task :class:`PhysicalSynthesisTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} DSP Register Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex} DSP Register Optimization | Checksum:" @export class Phase_CriticalPathOptimization_1(Phase): + """ + *Critical Path Optimization* phase. + + Used by task :class:`PhysicalSynthesisTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Critical Path Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Critical Path Optimization | Checksum:" @export class Phase_CriticalPathOptimization_2(Phase): + """ + *Critical Path Optimization* phase. + + Used by task :class:`PhysicalSynthesisTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Critical Path Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Critical Path Optimization | Checksum:" @export class PhysicalSynthesisTask(TaskWithPhases): + """ + Parses *Physical Synthesis* task's outputs. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.PhysicalOptimizeDesign`. + """ _NAME: ClassVar[str] = "Physical Synthesis Task" _START: ClassVar[str] = "Starting Physical Synthesis Task" _FINISH: ClassVar[str] = "Ending Physical Synthesis Task" diff --git a/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py b/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py index 5c5f0f9..07d573d 100644 --- a/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py @@ -42,6 +42,11 @@ @export class SubPhase_PlacerInitializationNetlistSorting(SubPhase): + """ + *Placer Initialization Netlist Sorting* subphase. + + Used by phase :class:`Phase_PlacerInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Placer Initialization Netlist Sorting") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Placer Initialization Netlist Sorting | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -49,6 +54,11 @@ class SubPhase_PlacerInitializationNetlistSorting(SubPhase): @export class SubPhase_IOPlacement_ClockPlacement_BuildPlacerDevice(SubPhase): + """ + *IO Placement/ Clock Placement/ Build Placer Device* subphase. + + Used by phase :class:`Phase_PlacerInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} IO Placement/ Clock Placement/ Build Placer Device") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} IO Placement/ Clock Placement/ Build Placer Device | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -56,6 +66,11 @@ class SubPhase_IOPlacement_ClockPlacement_BuildPlacerDevice(SubPhase): @export class SubPhase_BuildPlacerNetlistModel(SubPhase): + """ + *Build Placer Netlist Model* subphase. + + Used by phase :class:`Phase_PlacerInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Build Placer Netlist Model") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Build Placer Netlist Model | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -63,6 +78,11 @@ class SubPhase_BuildPlacerNetlistModel(SubPhase): @export class SubPhase_ConstrainClocks_Macros(SubPhase): + """ + *Constrain Clocks/Macros* subphase. + + Used by phase :class:`Phase_PlacerInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Constrain Clocks/Macros") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Constrain Clocks/Macros | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -70,6 +90,18 @@ class SubPhase_ConstrainClocks_Macros(SubPhase): @export class Phase_PlacerInitialization(PhaseWithChildren): + """ + *Placer Initialization* phase. + + .. topic:: Uses + + * :class:`SubPhase_PlacerInitializationNetlistSorting` + * :class:`SubPhase_IOPlacement_ClockPlacement_BuildPlacerDevice` + * :class:`SubPhase_BuildPlacerNetlistModel` + * :class:`SubPhase_ConstrainClocks_Macros` + + Used by task :class:`PlacerTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Placer Initialization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Placer Initialization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -85,6 +117,11 @@ class Phase_PlacerInitialization(PhaseWithChildren): @export class SubPhase_Floorplanning(SubPhase): + """ + *Floorplanning* subphase. + + Used by phase :class:`Phase_GlobalPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Floorplanning") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Floorplanning | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -92,6 +129,11 @@ class SubPhase_Floorplanning(SubPhase): @export class SubPhase_UpdateTimingBeforeSLRPathOpt(SubPhase): + """ + *Update Timing before SLR Path Opt* subphase. + + Used by phase :class:`Phase_GlobalPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Update Timing before SLR Path Opt") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Update Timing before SLR Path Opt | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -99,6 +141,11 @@ class SubPhase_UpdateTimingBeforeSLRPathOpt(SubPhase): @export class SubPhase_PostProcessingInFloorplanning(SubPhase): + """ + *Post-Processing in Floorplanning* subphase. + + Used by phase :class:`Phase_GlobalPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Post-Processing in Floorplanning") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Post-Processing in Floorplanning | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -120,6 +167,11 @@ class SubSubPhase_PhysicalSynthesisInPlacer(SubSubPhase): @export class SubPhase_GlobalPlacementCore(SubPhaseWithChildren): + """ + *Global Placement Core* subphase. + + Used by phase :class:`Phase_GlobalPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Placement Core") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Placement Core | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -132,6 +184,11 @@ class SubPhase_GlobalPlacementCore(SubPhaseWithChildren): @export class SubPhase_GlobalPlacePhase1(SubPhase): + """ + *Global Place Phase1* subphase. + + Used by phase :class:`Phase_GlobalPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Place Phase1") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Place Phase1 | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -153,6 +210,11 @@ class SubPhase_GlobalPlacePhase1(SubPhase): @export class SubPhase_GlobalPlacePhase2(SubPhaseWithChildren): + """ + *Global Place Phase2* subphase. + + Used by phase :class:`Phase_GlobalPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Place Phase2") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Place Phase2 | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -165,6 +227,20 @@ class SubPhase_GlobalPlacePhase2(SubPhaseWithChildren): @export class Phase_GlobalPlacement(PhaseWithChildren): + """ + *Global Placement* phase. + + .. topic:: Uses + + * :class:`SubPhase_Floorplanning` + * :class:`SubPhase_UpdateTimingBeforeSLRPathOpt` + * :class:`SubPhase_PostProcessingInFloorplanning` + * :class:`SubPhase_GlobalPlacePhase1` + * :class:`SubPhase_GlobalPlacePhase2` + * :class:`SubPhase_GlobalPlacementCore` + + Used by task :class:`PlacerTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Global Placement") _FINISH: ClassVar[str] = "Phase {phaseIndex} Global Placement | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -182,6 +258,11 @@ class Phase_GlobalPlacement(PhaseWithChildren): @export class SubPhase_CommitMultiColumnMacros(SubPhase): + """ + *Commit Multi Column Macros* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Commit Multi Column Macros") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Commit Multi Column Macros | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -189,6 +270,11 @@ class SubPhase_CommitMultiColumnMacros(SubPhase): @export class SubPhase_CommitMostMacrosLUTRAMs(SubPhase): + """ + *Commit Most Macros & LUTRAMs* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Commit Most Macros & LUTRAMs") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Commit Most Macros & LUTRAMs | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -221,6 +307,11 @@ class SubSubPhase_SliceAreaSwap(SubSubPhaseWithChildren): @export class SubPhase_SmallShapeDP(SubPhaseWithChildren): + """ + *Small Shape DP* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Small Shape DP") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Small Shape DP | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -233,6 +324,11 @@ class SubPhase_SmallShapeDP(SubPhaseWithChildren): @export class SubPhase_AreaSwapOptimization(SubPhase): + """ + *Area Swap Optimization* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Area Swap Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Area Swap Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -240,6 +336,11 @@ class SubPhase_AreaSwapOptimization(SubPhase): @export class SubPhase_ReassignLUTPins(SubPhase): + """ + *Re-assign LUT pins* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Re-assign LUT pins") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Re-assign LUT pins | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -247,6 +348,11 @@ class SubPhase_ReassignLUTPins(SubPhase): @export class SubPhase_PipelineRegisterOptimization_1(SubPhase): + """ + *Floorplanning* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Pipeline Register Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Pipeline Register Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -254,6 +360,11 @@ class SubPhase_PipelineRegisterOptimization_1(SubPhase): @export class SubPhase_PipelineRegisterOptimization_2(SubPhase): + """ + *Pipeline Register Optimization* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Pipeline Register Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Pipeline Register Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -261,6 +372,11 @@ class SubPhase_PipelineRegisterOptimization_2(SubPhase): @export class SubPhase_FastOptimization_1(SubPhase): + """ + *Fast Optimization* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Fast Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Fast Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -268,6 +384,11 @@ class SubPhase_FastOptimization_1(SubPhase): @export class SubPhase_FastOptimization_2(SubPhase): + """ + *Fast Optimization* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Fast Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Fast Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -275,6 +396,11 @@ class SubPhase_FastOptimization_2(SubPhase): @export class SubPhase_SmallShapeDetailPlacement(SubPhase): + """ + *Small Shape Detail Placement* subphase. + + Used by phase :class:`Phase_DetailPlacement`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Small Shape Detail Placement") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Small Shape Detail Placement | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -282,6 +408,24 @@ class SubPhase_SmallShapeDetailPlacement(SubPhase): @export class Phase_DetailPlacement(PhaseWithChildren): + """ + *Detail Placement* phase. + + .. topic:: Uses + + * :class:`SubPhase_CommitMultiColumnMacros` + * :class:`SubPhase_CommitMostMacrosLUTRAMs` + * :class:`SubPhase_SmallShapeDP` + * :class:`SubPhase_AreaSwapOptimization` + * :class:`SubPhase_PipelineRegisterOptimization_1` + * :class:`SubPhase_PipelineRegisterOptimization_2` + * :class:`SubPhase_FastOptimization_1` + * :class:`SubPhase_FastOptimization_2` + * :class:`SubPhase_SmallShapeDetailPlacement` + * :class:`SubPhase_ReassignLUTPins` + + Used by task :class:`PlacerTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Detail Placement") _FINISH: ClassVar[str] = "Phase {phaseIndex} Detail Placement | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -329,6 +473,11 @@ class SubSubPhase_PostPlacementOptimization(SubSubPhaseWithChildren): @export class SubPhase_PostCommitOptimization(SubPhaseWithChildren): + """ + *Post Commit Optimization* subphase. + + Used by phase :class:`Phase_PostPlacementOptimizationAndCleanUp`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Post Commit Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Post Commit Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -340,6 +489,11 @@ class SubPhase_PostCommitOptimization(SubPhaseWithChildren): @export class SubPhase_PostPlacementCleanup(SubPhase): + """ + *Post Placement Cleanup* subphase. + + Used by phase :class:`Phase_PostPlacementOptimizationAndCleanUp`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Post Placement Cleanup") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Post Placement Cleanup | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -354,6 +508,11 @@ class SubSubPhase_PrintEstimatedCongestion(SubSubPhase): @export class SubPhase_PlacerReporting(SubPhaseWithChildren): + """ + *Placer Reporting* subphase. + + Used by phase :class:`Phase_PostPlacementOptimizationAndCleanUp`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Placer Reporting") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Placer Reporting | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -365,6 +524,11 @@ class SubPhase_PlacerReporting(SubPhaseWithChildren): @export class SubPhase_FinalPlacementCleanup(SubPhase): + """ + *Final Placement Cleanup* subphase. + + Used by phase :class:`Phase_PostPlacementOptimizationAndCleanUp`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Final Placement Cleanup") _FINISH: ClassVar[Pattern] = compile(r"Time \(s\):") _TIME: ClassVar[str] = None @@ -372,6 +536,18 @@ class SubPhase_FinalPlacementCleanup(SubPhase): @export class Phase_PostPlacementOptimizationAndCleanUp(PhaseWithChildren): + """ + *Post Placement Optimization and Clean-Up* phase. + + .. topic:: Uses + + * :class:`SubPhase_PostCommitOptimization` + * :class:`SubPhase_PostPlacementCleanup` + * :class:`SubPhase_PlacerReporting` + * :class:`SubPhase_FinalPlacementCleanup` + + Used by task :class:`PlacerTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post Placement Optimization and Clean-Up") _FINISH: ClassVar[str] = "Phase {phaseIndex} Post Placement Optimization and Clean-Up | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -387,6 +563,18 @@ class Phase_PostPlacementOptimizationAndCleanUp(PhaseWithChildren): @export class PlacerTask(TaskWithPhases): + """ + *Placer* task. + + .. topic:: Uses + + * :class:`Phase_PlacerInitialization` + * :class:`Phase_GlobalPlacement` + * :class:`Phase_DetailPlacement` + * :class:`Phase_PostPlacementOptimizationAndCleanUp` + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.PlaceDesign`. + """ _START: ClassVar[str] = "Starting Placer Task" _FINISH: ClassVar[str] = "Ending Placer Task" diff --git a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py index de2f55a..95ff569 100644 --- a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py @@ -44,6 +44,11 @@ @export class Phase_BuildRTDesign(Phase): + """ + *Build RT Design* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Build RT Design") _FINISH: ClassVar[str] = "Phase {phaseIndex} Build RT Design | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -51,6 +56,11 @@ class Phase_BuildRTDesign(Phase): @export class SubPhase_CreateTimer(SubPhase): + """ + *Create Timer* subphase. + + Used by phase :class:`Phase_RouterInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Create Timer") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Create Timer | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -58,6 +68,11 @@ class SubPhase_CreateTimer(SubPhase): @export class SubPhase_FixTopologyConstraints(SubPhase): + """ + *Fix Topology Constraints* subphase. + + Used by phase :class:`Phase_RouterInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Fix Topology Constraints") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Fix Topology Constraints | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -65,6 +80,11 @@ class SubPhase_FixTopologyConstraints(SubPhase): @export class SubPhase_PreRouteCleanup(SubPhase): + """ + *Pre Route Cleanup* subphase. + + Used by phase :class:`Phase_RouterInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Pre Route Cleanup") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Pre Route Cleanup | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -72,6 +92,11 @@ class SubPhase_PreRouteCleanup(SubPhase): @export class SubPhase_GlobalClockNetRouting(SubPhase): + """ + *Global Clock Net Routing* subphase. + + Used by phase :class:`Phase_RouterInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Clock Net Routing") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Clock Net Routing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -79,6 +104,11 @@ class SubPhase_GlobalClockNetRouting(SubPhase): @export class SubPhase_UpdateTiming(SubPhase): + """ + *Update Timing* subphase. + + Used by phase :class:`Phase_RouterInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Update Timing") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Update Timing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -86,6 +116,11 @@ class SubPhase_UpdateTiming(SubPhase): @export class SubPhase_SoftConstraintPins_FastBudgeting(SubPhase): + """ + *Soft Constraint Pins - Fast Budgeting* subphase. + + Used by phase :class:`Phase_RouterInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Soft Constraint Pins - Fast Budgeting") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Soft Constraint Pins - Fast Budgeting | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -93,6 +128,11 @@ class SubPhase_SoftConstraintPins_FastBudgeting(SubPhase): @export class SubSubPhase_UpdateTiming(SubSubPhase): + """ + *Update Timing - Fast Budgeting* sub-subphase. + + Used by phase :class:`SubPhase_UpdateTimingForBusSkew`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR_MICRO} Update Timing") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex}.{subSubPhaseIndex} Update Timing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -100,6 +140,15 @@ class SubSubPhase_UpdateTiming(SubSubPhase): @export class SubPhase_UpdateTimingForBusSkew(SubPhaseWithChildren): + """ + *Update Timing for Bus Skew* subphase. + + .. topic:: Uses + + * :class:`SubSubPhase_UpdateTiming` + + Used by phase :class:`Phase_RouterInitialization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Update Timing for Bus Skew") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Update Timing for Bus Skew | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -111,6 +160,21 @@ class SubPhase_UpdateTimingForBusSkew(SubPhaseWithChildren): @export class Phase_RouterInitialization(PhaseWithChildren): + """ + *Router Initialization* phase. + + .. topic:: Uses + + * :class:`SubPhase_CreateTimer` + * :class:`SubPhase_FixTopologyConstraints` + * :class:`SubPhase_PreRouteCleanup` + * :class:`SubPhase_GlobalClockNetRouting` + * :class:`SubPhase_UpdateTiming` + * :class:`SubPhase_UpdateTimingForBusSkew` + * :class:`SubPhase_SoftConstraintPins_FastBudgeting` + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Router Initialization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Router Initialization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -128,6 +192,11 @@ class Phase_RouterInitialization(PhaseWithChildren): @export class SubPhase_GlobalRouting(SubPhase): + """ + *Global Routing* subphase. + + Used by phase :class:`Phase_Initial_Routing`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Routing") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Routing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -135,6 +204,11 @@ class SubPhase_GlobalRouting(SubPhase): @export class SubPhase_InitialNetRouting(SubPhase): + """ + *Initial Net Routing* subphase. + + Used by phase :class:`Phase_Initial_Routing`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Initial Net Routing") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Initial Net Routing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -142,6 +216,16 @@ class SubPhase_InitialNetRouting(SubPhase): @export class Phase_Initial_Routing(PhaseWithChildren): + """ + *Initial Routing* phase. + + .. topic:: Uses + + * :class:`SubPhase_GlobalRouting` + * :class:`SubPhase_InitialNetRouting` + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Initial Routing") _FINISH: ClassVar[str] = "Phase {phaseIndex} Initial Routing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -154,6 +238,11 @@ class Phase_Initial_Routing(PhaseWithChildren): @export class Phase_GlobalRouting(Phase): + """ + *Global Routing* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Global Routing") _FINISH: ClassVar[str] = "Phase {phaseIndex} Global Routing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -161,6 +250,11 @@ class Phase_GlobalRouting(Phase): @export class SubPhase_GlobalIteration0(SubPhase): + """ + *Global Iteration 0* subphase. + + Used by phase :class:`Phase_RipUpAndReroute`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Iteration 0") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Iteration 0 | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -168,6 +262,11 @@ class SubPhase_GlobalIteration0(SubPhase): @export class SubPhase_AdditionalIterationForHold(SubPhase): + """ + *Additional Iteration for Hold* subphase. + + Used by phase :class:`Phase_RipUpAndReroute`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Additional Iteration for Hold") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Additional Iteration for Hold | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -175,6 +274,11 @@ class SubPhase_AdditionalIterationForHold(SubPhase): @export class SubPhase_GlobalIteration1(SubPhase): + """ + *Global Iteration 1* subphase. + + Used by phase :class:`Phase_RipUpAndReroute`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Iteration 1") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Iteration 1 | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -182,6 +286,11 @@ class SubPhase_GlobalIteration1(SubPhase): @export class SubPhase_GlobalIteration2(SubPhase): + """ + *Global Iteration 2* subphase. + + Used by phase :class:`Phase_RipUpAndReroute`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Global Iteration 2") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Global Iteration 2 | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -189,6 +298,18 @@ class SubPhase_GlobalIteration2(SubPhase): @export class Phase_RipUpAndReroute(PhaseWithChildren): + """ + *Rip-up And Reroute* phase. + + .. topic:: Uses + + * :class:`SubPhase_GlobalIteration0` + * :class:`SubPhase_AdditionalIterationForHold` + * :class:`SubPhase_GlobalIteration1` + * :class:`SubPhase_GlobalIteration2` + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Rip-up And Reroute") _FINISH: ClassVar[str] = "Phase {phaseIndex} Rip-up And Reroute | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -203,6 +324,11 @@ class Phase_RipUpAndReroute(PhaseWithChildren): @export class SubPhase_InitialNetRoutingPass(SubPhase): + """ + *Initial Net Routing Pass* subphase. + + Used by phase :class:`Phase_InitialRouting`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Initial Net Routing Pass") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Initial Net Routing Pass | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -210,6 +336,17 @@ class SubPhase_InitialNetRoutingPass(SubPhase): @export class Phase_InitialRouting(PhaseWithChildren): + """ + *Initial Routing* phase. + + .. topic:: Uses + + * :class:`SubPhase_InitialNetRoutingPass` + * :class:`SubPhase_GlobalRouting` + * :class:`SubPhase_InitialNetRouting` + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Initial Routing") _FINISH: ClassVar[str] = "Phase {phaseIndex} Initial Routing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -223,6 +360,11 @@ class Phase_InitialRouting(PhaseWithChildren): @export class SubPhase_DelayCleanUp(SubPhase): + """ + *Delay CleanUp* subphase. + + Used by phase :class:`Phase_DelayAndSkewOptimization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Delay CleanUp") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Delay CleanUp | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -230,6 +372,11 @@ class SubPhase_DelayCleanUp(SubPhase): @export class SubPhase_ClockSkewOptimization(SubPhase): + """ + *Clock Skew Optimization* subphase. + + Used by phase :class:`Phase_DelayAndSkewOptimization`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Clock Skew Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Clock Skew Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -237,6 +384,16 @@ class SubPhase_ClockSkewOptimization(SubPhase): @export class Phase_DelayAndSkewOptimization(PhaseWithChildren): + """ + *Delay and Skew Optimization* phase. + + .. topic:: Uses + + * :class:`SubPhase_DelayCleanUp` + * :class:`SubPhase_ClockSkewOptimization` + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Delay and Skew Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Delay and Skew Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -249,6 +406,11 @@ class Phase_DelayAndSkewOptimization(PhaseWithChildren): @export class SubPhase_HoldFixIter(SubPhase): + """ + *Hold Fix Iter* subphase. + + Used by phase :class:`Phase_PostHoldFix`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Hold Fix Iter") _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Hold Fix Iter | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -256,6 +418,11 @@ class SubPhase_HoldFixIter(SubPhase): @export class Phase_PostHoldFix(PhaseWithChildren): + """ + *Post Hold Fix* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post Hold Fix") _FINISH: ClassVar[str] = "Phase {phaseIndex} Post Hold Fix | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -281,6 +448,16 @@ class SubPhase_ClockSkewOptimization(SubPhase): @export class Phase_DelayAndSkewOptimization(PhaseWithChildren): + """ + *Delay and Skew Optimization* phase. + + .. topic:: Uses + + * :class:`SubPhase_DelayCleanUp` + * :class:`SubPhase_ClockSkewOptimization` + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Delay and Skew Optimization") _FINISH: ClassVar[str] = "Phase {phaseIndex} Delay and Skew Optimization | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -293,6 +470,11 @@ class Phase_DelayAndSkewOptimization(PhaseWithChildren): @export class Phase_RouteFinalize_1(Phase): + """ + *Route finalize* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Route finalize") _FINISH: ClassVar[str] = "Phase {phaseIndex} Route finalize | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -300,6 +482,11 @@ class Phase_RouteFinalize_1(Phase): @export class Phase_RouteFinalize_2(Phase): + """ + *Route finalize* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Route finalize") _FINISH: ClassVar[str] = "Phase {phaseIndex} Route finalize | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -314,6 +501,11 @@ class SubPhase_HoldFixIter(SubPhase): @export class Phase_PostHoldFix(PhaseWithChildren): + """ + *Post Hold Fix* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post Hold Fix") _FINISH: ClassVar[str] = "Phase {phaseIndex} Post Hold Fix | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -325,6 +517,11 @@ class Phase_PostHoldFix(PhaseWithChildren): @export class Phase_VerifyingRoutedNets(Phase): + """ + *Verifying routed nets* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Verifying routed nets") _FINISH: ClassVar[str] = "Phase {phaseIndex} Verifying routed nets | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -332,6 +529,11 @@ class Phase_VerifyingRoutedNets(Phase): @export class Phase_DepositingRoutes(Phase): + """ + *Depositing Routes* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Depositing Routes") _FINISH: ClassVar[str] = "Phase {phaseIndex} Depositing Routes | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -339,6 +541,11 @@ class Phase_DepositingRoutes(Phase): @export class Phase_VerifyingRoutedNets(Phase): + """ + *Verifying routed nets* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Verifying routed nets") _FINISH: ClassVar[str] = "Phase {phaseIndex} Verifying routed nets | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -346,6 +553,11 @@ class Phase_VerifyingRoutedNets(Phase): @export class Phase_ResolveXTalk(Phase): + """ + *Resolve XTalk* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Resolve XTalk") _FINISH: ClassVar[str] = "Phase {phaseIndex} Resolve XTalk | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -353,6 +565,11 @@ class Phase_ResolveXTalk(Phase): @export class Phase_DepositingRoutes(Phase): + """ + *Depositing Routes* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Depositing Routes") _FINISH: ClassVar[str] = "Phase {phaseIndex} Depositing Routes | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -360,6 +577,11 @@ class Phase_DepositingRoutes(Phase): @export class Phase_PostProcessRouting(Phase): + """ + *Post Process Routing* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post Process Routing") _FINISH: ClassVar[str] = "Phase {phaseIndex} Post Process Routing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -367,6 +589,11 @@ class Phase_PostProcessRouting(Phase): @export class Phase_PostRouterTiming(Phase): + """ + *Post Router Timing* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post Router Timing") _FINISH: ClassVar[str] = "Phase {phaseIndex} Post Router Timing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -374,6 +601,11 @@ class Phase_PostRouterTiming(Phase): @export class Phase_PostRouteEventProcessing(Phase): + """ + *Post-Route Event Processing* phase. + + Used by task :class:`RoutingTask`. + """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Post-Route Event Processing") _FINISH: ClassVar[str] = "Phase {phaseIndex} Post-Route Event Processing | Checksum:" _TIME: ClassVar[str] = "Time (s):" @@ -381,6 +613,30 @@ class Phase_PostRouteEventProcessing(Phase): @export class RoutingTask(TaskWithPhases): + """ + *Routing* task. + + .. topic:: Uses + + * :class:`Phase_BuildRTDesign` + * :class:`Phase_RouterInitialization` + * :class:`Phase_GlobalRouting` + * :class:`Phase_InitialRouting` + * :class:`Phase_RipUpAndReroute` + * :class:`Phase_DelayAndSkewOptimization` + * :class:`Phase_PostHoldFix` + * :class:`Phase_RouteFinalize_1` + * :class:`Phase_VerifyingRoutedNets` + * :class:`Phase_DepositingRoutes` + * :class:`Phase_ResolveXTalk` + * :class:`Phase_RouteFinalize_2` + * :class:`Phase_PostRouterTiming` + * :class:`Phase_PostProcessRouting` + * :class:`Phase_PostRouterTiming` + * :class:`Phase_PostRouteEventProcessing` + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.RouteDesign`. + """ _START: ClassVar[str] = "Starting Routing Task" _FINISH: ClassVar[str] = "Ending Routing Task" diff --git a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py index adcee64..8c637f8 100644 --- a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py @@ -220,6 +220,11 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class RTLElaboration(Section): + """ + *RTL Elaboration* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Starting RTL Elaboration : " _FINISH: ClassVar[str] = "Finished RTL Elaboration : " @@ -262,18 +267,33 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class HandlingCustomAttributes(Section): + """ + *Handling Custom Attributes* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Handling Custom Attributes" _FINISH: ClassVar[str] = "Finished Handling Custom Attributes : " @export class ConstraintValidation(Section): + """ + *Constraint Validation* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Finished RTL Optimization Phase 1" _FINISH: ClassVar[str] = "Finished Constraint Validation : " @export class LoadingPart(Section): + """ + *Loading Part and Timing Information* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Loading Part and Timing Information" _FINISH: ClassVar[str] = "Finished Loading Part and Timing Information : " @@ -313,12 +333,22 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class ApplySetProperty(Section): + """ + *Applying 'set_property' XDC Constraints* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Applying 'set_property' XDC Constraints" _FINISH: ClassVar[str] = "Finished applying 'set_property' XDC Constraints : " @export class RTLComponentStatistics(Section): + """ + *RTL Component Statistics* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start RTL Component Statistics" _FINISH: ClassVar[str] = "Finished RTL Component Statistics" @@ -345,42 +375,77 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class RTLHierarchicalComponentStatistics(Section): + """ + *RTL Hierarchical Component Statistics* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start RTL Hierarchical Component Statistics" _FINISH: ClassVar[str] = "Finished RTL Hierarchical Component Statistics" @export class PartResourceSummary(Section): + """ + *Part Resource Summary* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Part Resource Summary" _FINISH: ClassVar[str] = "Finished Part Resource Summary" @export class CrossBoundaryAndAreaOptimization(Section): + """ + *Cross Boundary and Area Optimization* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Cross Boundary and Area Optimization" _FINISH: ClassVar[str] = "Finished Cross Boundary and Area Optimization : " @export class ROM_RAM_DSP_SR_Retiming(Section): + """ + *ROM, RAM, DSP, Shift Register and Retiming Reporting* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start ROM, RAM, DSP, Shift Register and Retiming Reporting" _FINISH: ClassVar[str] = "Finished ROM, RAM, DSP, Shift Register and Retiming Reporting" @export class ApplyingXDCTimingConstraints(Section): + """ + *Applying XDC Timing Constraints* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Applying XDC Timing Constraints" _FINISH: ClassVar[str] = "Finished Applying XDC Timing Constraints : " @export class TimingOptimization(Section): + """ + *Timing Optimization* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Timing Optimization" _FINISH: ClassVar[str] = "Finished Timing Optimization : " @export class TechnologyMapping(Section): + """ + *Technology Mapping* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Technology Mapping" _FINISH: ClassVar[str] = "Finished Technology Mapping : " @@ -399,6 +464,11 @@ class FinalNetlistCleanup(SubSection): @export class IOInsertion(Section): + """ + *IO Insertion* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start IO Insertion" _FINISH: ClassVar[str] = "Finished IO Insertion : " @@ -461,30 +531,55 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class RenamingGeneratedInstances(Section): + """ + *Renaming Generated Instances* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Renaming Generated Instances" _FINISH: ClassVar[str] = "Finished Renaming Generated Instances : " @export class RebuildingUserHierarchy(Section): + """ + *Rebuilding User Hierarchy* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Rebuilding User Hierarchy" _FINISH: ClassVar[str] = "Finished Rebuilding User Hierarchy : " @export class RenamingGeneratedPorts(Section): + """ + *Renaming Generated Ports* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Renaming Generated Ports" _FINISH: ClassVar[str] = "Finished Renaming Generated Ports : " @export class RenamingGeneratedNets(Section): + """ + *Renaming Generated Nets* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Renaming Generated Nets" _FINISH: ClassVar[str] = "Finished Renaming Generated Nets : " @export class WritingSynthesisReport(Section): + """ + *Writing Synthesis Report* section. + + Used by Vivado command :class:`~pyEDAA.OutputFilter.Xilinx.Commands.SynthesizeDesign`. + """ _START: ClassVar[str] = "Start Writing Synthesis Report" _FINISH: ClassVar[str] = "Finished Writing Synthesis Report : " diff --git a/pyEDAA/OutputFilter/__init__.py b/pyEDAA/OutputFilter/__init__.py index 1c79b64..a903358 100644 --- a/pyEDAA/OutputFilter/__init__.py +++ b/pyEDAA/OutputFilter/__init__.py @@ -34,7 +34,7 @@ __email__ = "Paebbels@gmail.com" __copyright__ = "2014-2026, Patrick Lehmann" __license__ = "Apache License, Version 2.0" -__version__ = "0.5.1" +__version__ = "0.6.0" __keywords__ = ["cli", "abstraction layer", "eda", "filter", "classification"] diff --git a/run.ps1 b/run.ps1 index 772d75c..4722490 100644 --- a/run.ps1 +++ b/run.ps1 @@ -33,7 +33,7 @@ Param( ) $PackageName = "pyEDAA.OutputFilter" -$PackageVersion = "0.5.1" +$PackageVersion = "0.6.0" # set default values $EnableDebug = [bool]$PSCmdlet.MyInvocation.BoundParameters["Debug"] From fe7aa0265bcb432fac50a7c2fa87a1e6e2d55522 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 1 Feb 2026 01:30:36 +0100 Subject: [PATCH 2/7] Renamed field and fixed type hint. --- pyEDAA/OutputFilter/Xilinx/Commands.py | 13 +++++++---- pyEDAA/OutputFilter/Xilinx/Common.py | 30 +++++++++++++++----------- pyEDAA/OutputFilter/Xilinx/__init__.py | 2 +- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/pyEDAA/OutputFilter/Xilinx/Commands.py b/pyEDAA/OutputFilter/Xilinx/Commands.py index 0403702..9aaef8a 100644 --- a/pyEDAA/OutputFilter/Xilinx/Commands.py +++ b/pyEDAA/OutputFilter/Xilinx/Commands.py @@ -41,7 +41,7 @@ from pyEDAA.OutputFilter.Xilinx import VivadoTclCommand from pyEDAA.OutputFilter.Xilinx.Exception import ProcessorException from pyEDAA.OutputFilter.Xilinx.Common import Line, LineKind, VivadoMessage, VHDLReportMessage -from pyEDAA.OutputFilter.Xilinx.Common2 import Parser, UnknownSection, UnknownTask +from pyEDAA.OutputFilter.Xilinx.Common2 import Parser, UnknownSection, UnknownTask, Task from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import Section, RTLElaboration, HandlingCustomAttributes from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import ConstraintValidation, LoadingPart, ApplySetProperty from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import RTLComponentStatistics, RTLHierarchicalComponentStatistics @@ -52,7 +52,7 @@ from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import RenamingGeneratedInstances, RebuildingUserHierarchy from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import RenamingGeneratedPorts, RenamingGeneratedNets from pyEDAA.OutputFilter.Xilinx.SynthesizeDesign import WritingSynthesisReport -from pyEDAA.OutputFilter.Xilinx.OptimizeDesign import Task, DRCTask, CacheTimingInformationTask, LogicOptimizationTask +from pyEDAA.OutputFilter.Xilinx.OptimizeDesign import DRCTask, CacheTimingInformationTask, LogicOptimizationTask from pyEDAA.OutputFilter.Xilinx.OptimizeDesign import PowerOptimizationTask, FinalCleanupTask, NetlistObfuscationTask from pyEDAA.OutputFilter.Xilinx.PlaceDesign import PlacerTask from pyEDAA.OutputFilter.Xilinx.PhysicalOptimizeDesign import PhysicalSynthesisTask, InitialUpdateTimingTask @@ -141,7 +141,7 @@ def _CommandStart(self, line: Line) -> Generator[Line, Line, Line]: :returns: A generator processing Vivado output log lines. """ if not (isinstance(line, VivadoTclCommand) and line._command == self._TCL_COMMAND): - raise ProcessorException() + raise ProcessorException() # FIXME: add exception message nextLine = yield line return nextLine @@ -325,6 +325,11 @@ def Latches(self) -> Iterator[VivadoMessage]: @readonly def HasBlackboxes(self) -> bool: + """ + Read-only property returning if the design contains black-boxes. + + :returns: True, if the design contains black-boxes. + """ return len(self._sections[WritingSynthesisReport]._blackboxes) > 0 @readonly @@ -359,7 +364,7 @@ def __getitem__(self, item: Type[Parser]) -> Union[_PARSERS]: def SectionDetector(self, line: Line) -> Generator[Union[Line, ProcessorException], Line, None]: if not (isinstance(line, VivadoTclCommand) and line._command == self._TCL_COMMAND): - raise ProcessorException() + raise ProcessorException() # FIXME: add exception message activeParsers: List[Parser] = list(self._sections.values()) diff --git a/pyEDAA/OutputFilter/Xilinx/Common.py b/pyEDAA/OutputFilter/Xilinx/Common.py index 60522e5..725f9fb 100644 --- a/pyEDAA/OutputFilter/Xilinx/Common.py +++ b/pyEDAA/OutputFilter/Xilinx/Common.py @@ -414,22 +414,28 @@ class VHDLAssertionMessage(VHDLReportMessage): @export class TclCommand(Line): - _command: str - _args: Tuple[str, ...] + """ + Represents a TCL command found in a Vivado log output. + + Besides the full log message (:class:`Line`), this class splits the TCL command into the command name and its + arguments. + """ + _command: str + _arguments: Tuple[str, ...] - def __init__(self, lineNumber: int, command: str, arguments: Tuple[str, ...], tclCommand: str) -> None: - super().__init__(lineNumber, LineKind.GenericTclCommand, tclCommand) + def __init__(self, lineNumber: int, command: str, arguments: Tuple[str, ...], rawMessage: str) -> None: + super().__init__(lineNumber, LineKind.GenericTclCommand, rawMessage) self._command = command - self._args = arguments + self._arguments = arguments @readonly def Command(self) -> str: return self._command @readonly - def Arguments(self) -> Tuple[str]: - return self._args + def Arguments(self) -> Tuple[str, ...]: + return self._arguments @classmethod def FromLine(cls, line: Line) -> Nullable[Self]: @@ -438,7 +444,7 @@ def FromLine(cls, line: Line) -> Nullable[Self]: return cls(line._lineNumber, args[0], tuple(args[1:]), line._message) def __str__(self) -> str: - return f"{self._command} {' '.join(self._args)}" + return f"{self._command} {' '.join(self._arguments)}" @export @@ -454,9 +460,9 @@ def Parse(cls, lineNumber: int, rawMessage: str) -> Nullable[Self]: command = rawMessage[len(cls._PREFIX) + 1:] args = command.split() - command = cls(lineNumber, args[0], tuple(args[1:]), command) - command._kind = LineKind.VivadoTclCommand - return command + vivadoCommand = cls(lineNumber, args[0], tuple(args[1:]), rawMessage) + vivadoCommand._kind = LineKind.VivadoTclCommand + return vivadoCommand def __str__(self) -> str: - return f"{self._PREFIX} {self._command} {' '.join(self._args)}" + return f"{self._PREFIX} {self._command} {' '.join(self._arguments)}" diff --git a/pyEDAA/OutputFilter/Xilinx/__init__.py b/pyEDAA/OutputFilter/Xilinx/__init__.py index 490764f..f009185 100644 --- a/pyEDAA/OutputFilter/Xilinx/__init__.py +++ b/pyEDAA/OutputFilter/Xilinx/__init__.py @@ -168,7 +168,7 @@ def CommandFinder(self) -> Generator[Line, Line, None]: # wait for first line line = yield - # process preable + # process preamble line = yield from self._preamble.Generator(line) while True: From c0f73320a99a972c314b785342dc3f8a6c9b2d56 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 1 Feb 2026 01:31:31 +0100 Subject: [PATCH 3/7] Import cleanups. --- pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py | 10 +++++----- pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py | 2 +- pyEDAA/OutputFilter/Xilinx/PlaceDesign.py | 8 ++++---- pyEDAA/OutputFilter/Xilinx/RouteDesign.py | 7 ++----- pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py | 3 +-- 5 files changed, 13 insertions(+), 17 deletions(-) diff --git a/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py b/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py index f17ba16..2cb0ae0 100644 --- a/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py @@ -34,8 +34,8 @@ from pyTooling.Decorators import export -from pyEDAA.OutputFilter.Xilinx.Common2 import Task, Phase, SubPhase, TaskWithPhases, TaskWithSubTasks, SubTask, \ - PhaseWithChildren +from pyEDAA.OutputFilter.Xilinx.Common2 import Task, TaskWithPhases, TaskWithSubTasks, SubTask +from pyEDAA.OutputFilter.Xilinx.Common2 import Phase, SubPhase, PhaseWithChildren from pyEDAA.OutputFilter.Xilinx.Common2 import MAJOR, MAJOR_MINOR @@ -47,9 +47,9 @@ class Phase_Retarget(Phase): Used by task :class:`LogicOptimizationTask`. """ _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR} Retarget") - _FINISH: ClassVar[str] = "Phase {phaseIndex} Retarget | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - _FINAL: ClassVar[str] = "Retarget | Checksum:" + _FINISH: ClassVar[str] = "Phase {phaseIndex} Retarget | Checksum:" + _TIME: ClassVar[str] = "Time (s):" + _FINAL: ClassVar[str] = "Retarget | Checksum:" @export diff --git a/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py b/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py index 8d14090..af8f5fe 100644 --- a/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py @@ -30,7 +30,7 @@ # """A filtering anc classification processor for AMD/Xilinx Vivado Synthesis outputs.""" from re import compile, Pattern -from typing import ClassVar, Type, Tuple, Dict +from typing import ClassVar, Type, Tuple from pyTooling.Decorators import export diff --git a/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py b/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py index 07d573d..7c7a380 100644 --- a/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py @@ -30,13 +30,13 @@ # """A filtering anc classification processor for AMD/Xilinx Vivado Synthesis outputs.""" from re import compile, Pattern -from typing import Generator, ClassVar, List, Type, Dict, Tuple +from typing import ClassVar, Type, Tuple from pyTooling.Decorators import export -from pyEDAA.OutputFilter.Xilinx import Line, VivadoMessage, LineKind -from pyEDAA.OutputFilter.Xilinx.Common2 import TaskWithPhases, Phase, SubPhase, SubSubPhase, SubSubSubPhase, \ - PhaseWithChildren, SubPhaseWithChildren, SubSubPhaseWithChildren +from pyEDAA.OutputFilter.Xilinx.Common2 import TaskWithPhases +from pyEDAA.OutputFilter.Xilinx.Common2 import Phase, SubPhase, SubSubPhase, SubSubSubPhase +from pyEDAA.OutputFilter.Xilinx.Common2 import PhaseWithChildren, SubPhaseWithChildren, SubSubPhaseWithChildren from pyEDAA.OutputFilter.Xilinx.Common2 import MAJOR, MAJOR_MINOR, MAJOR_MINOR_MICRO, MAJOR_MINOR_MICRO_NANO diff --git a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py index 95ff569..d36ff26 100644 --- a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py @@ -30,14 +30,11 @@ # """A filtering anc classification processor for AMD/Xilinx Vivado Synthesis outputs.""" from re import compile, Pattern -from typing import Generator, ClassVar, List, Type, Dict, Tuple +from typing import ClassVar, Type, Tuple from pyTooling.Decorators import export -from pyTooling.Warning import WarningCollector -from pyEDAA.OutputFilter.Xilinx import Line, VivadoMessage, LineKind -from pyEDAA.OutputFilter.Xilinx.Common2 import TaskWithPhases, Phase, SubPhase, UnknownSubPhase, PhaseWithChildren, \ - SubPhaseWithChildren +from pyEDAA.OutputFilter.Xilinx.Common2 import TaskWithPhases, Phase, SubPhase, PhaseWithChildren, SubPhaseWithChildren from pyEDAA.OutputFilter.Xilinx.Common2 import MAJOR, MAJOR_MINOR, MAJOR_MINOR_MICRO from pyEDAA.OutputFilter.Xilinx.PlaceDesign import SubSubPhase diff --git a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py index 8c637f8..69b43b3 100644 --- a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py @@ -35,8 +35,7 @@ from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType, abstractmethod -from pyEDAA.OutputFilter.Xilinx.Common import VHDLAssertionMessage, Line, LineKind, VivadoInfoMessage, \ - VHDLReportMessage, VivadoMessage, VivadoWarningMessage, VivadoCriticalWarningMessage, VivadoErrorMessage +from pyEDAA.OutputFilter.Xilinx.Common import VHDLAssertionMessage, Line, LineKind, VivadoInfoMessage, VHDLReportMessage, VivadoMessage from pyEDAA.OutputFilter.Xilinx.Common2 import BaseParser TIME_MEMORY_PATTERN = re_compile(r"""Time \(s\): cpu = (\d{2}:\d{2}:\d{2}) ; elapsed = (\d{2}:\d{2}:\d{2}) . Memory \(MB\): peak = (\d+\.\d+) ; gain = (\d+\.\d+)""") From 543ee9994c2a072660bf46d38e7deb032137ae1c Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 1 Feb 2026 23:18:17 +0100 Subject: [PATCH 4/7] Added more doc-strings. --- pyEDAA/OutputFilter/Xilinx/Commands.py | 60 +++++++- pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py | 6 - pyEDAA/OutputFilter/Xilinx/RouteDesign.py | 21 --- .../OutputFilter/Xilinx/SynthesizeDesign.py | 130 +++++++++++++++--- 4 files changed, 167 insertions(+), 50 deletions(-) diff --git a/pyEDAA/OutputFilter/Xilinx/Commands.py b/pyEDAA/OutputFilter/Xilinx/Commands.py index 9aaef8a..eedc9d4 100644 --- a/pyEDAA/OutputFilter/Xilinx/Commands.py +++ b/pyEDAA/OutputFilter/Xilinx/Commands.py @@ -317,11 +317,25 @@ def HasLatches(self) -> bool: return "LD" in self._sections[WritingSynthesisReport]._cells @readonly - def Latches(self) -> Iterator[VivadoMessage]: - try: - yield from iter(self._messagesByID[8][327]) - except KeyError: - yield from () + def Latches(self) -> List[VivadoMessage]: + """ + Read-only property to access a list of Vivado output messages for inferred latches. + + :returns: A list of Vivado messages for interred latches. + + .. note:: + + This returns ``[Synth 8-327]`` messages. + + .. code-block:: + + WARNING: [Synth 8-327] inferring latch for variable 'Q_reg' + """ + if 8 in self._messagesByID: + if 327 in (synthMessages := self._messagesByID[8]): + return [message for message in synthMessages[327]] + + return [] @readonly def HasBlackboxes(self) -> bool: @@ -334,14 +348,37 @@ def HasBlackboxes(self) -> bool: @readonly def Blackboxes(self) -> Dict[str, int]: + """ + Read-only property to access the dictionary of found blackbox statistics. + + :returns: The dictionary of found blackbox statistics. + """ return self._sections[WritingSynthesisReport]._blackboxes @readonly def Cells(self) -> Dict[str, int]: + """ + Read-only property to access the dictionary of synthesized cell statistics. + + :returns: The dictionary of used cell statistics. + """ return self._sections[WritingSynthesisReport]._cells @readonly def VHDLReportMessages(self) -> List[VHDLReportMessage]: + """ + Read-only property to access a list of Vivado output messages generated by VHDL report statement. + + :returns: A list of VHDL report statement outputs. + + .. note:: + + This returns ``[Synth 8-6031]`` messages. + + .. code-block:: + + INFO: [Synth 8-6031] RTL report: "TimingToCycles(time, freq): period=10.000000 ns -- 0.000000 fs" [C:/[...]/StopWatch/src/Utilities.pkg.vhdl:118] + """ if 8 in self._messagesByID: if 6031 in (synthMessages := self._messagesByID[8]): return [message for message in synthMessages[6031]] @@ -350,6 +387,19 @@ def VHDLReportMessages(self) -> List[VHDLReportMessage]: @readonly def VHDLAssertMessages(self) -> List[VHDLReportMessage]: + """ + Read-only property to access a list of Vivado output messages generated by VHDL assert statement. + + :returns: A list of VHDL assert statement outputs. + + .. note:: + + This returns ``[Synth 8-63]`` messages. + + .. code-block:: + + INFO: [Synth 8-63] RTL assertion: "CLOCK_FREQ: 100.000000 ns" [C:/[...]/StopWatch/src/Debouncer.vhdl:28] + """ if 8 in self._messagesByID: if 63 in (synthMessages := self._messagesByID[8]): return [message for message in synthMessages[63]] diff --git a/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py b/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py index 2cb0ae0..6bbc6bc 100644 --- a/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/OptimizeDesign.py @@ -264,12 +264,6 @@ class PowerOptimizationTask(TaskWithSubTasks): ) -@export -class LogicOptimizationTask(SubTask): - _START: ClassVar[str] = "Starting Logic Optimization Task" - _FINISH: ClassVar[str] = "Ending Logic Optimization Task" - - @export class FinalCleanupTask(TaskWithSubTasks): _START: ClassVar[str] = "Starting Final Cleanup Task" diff --git a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py index d36ff26..8d415c3 100644 --- a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py @@ -429,20 +429,6 @@ class Phase_PostHoldFix(PhaseWithChildren): ) -@export -class SubPhase_DelayCleanUp(SubPhase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Delay CleanUp") - _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Delay CleanUp | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - - -@export -class SubPhase_ClockSkewOptimization(SubPhase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Clock Skew Optimization") - _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Clock Skew Optimization | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - - @export class Phase_DelayAndSkewOptimization(PhaseWithChildren): """ @@ -489,13 +475,6 @@ class Phase_RouteFinalize_2(Phase): _TIME: ClassVar[str] = "Time (s):" -@export -class SubPhase_HoldFixIter(SubPhase): - _START: ClassVar[Pattern] = compile(f"^Phase {MAJOR_MINOR} Hold Fix Iter") - _FINISH: ClassVar[str] = "Phase {phaseIndex}.{subPhaseIndex} Hold Fix Iter | Checksum:" - _TIME: ClassVar[str] = "Time (s):" - - @export class Phase_PostHoldFix(PhaseWithChildren): """ diff --git a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py index 69b43b3..7265754 100644 --- a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py @@ -30,7 +30,7 @@ # """A filtering anc classification processor for AMD/Xilinx Vivado Synthesis outputs.""" from re import compile as re_compile -from typing import ClassVar, Dict, Generator, Type +from typing import ClassVar, Dict, Generator, Type, Optional as Nullable from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType, abstractmethod @@ -58,13 +58,21 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class Section(BaseParser, BaseSection): + """ + Base-class for sections within log outputs from *synthesize design*. + """ # _START: ClassVar[str] # _FINISH: ClassVar[str] - _command: "Command" - _duration: float + _command: "Command" #: Reference to the command (parent). + _duration: float #: Duration synthesis spent in processing a synthesis step logged in this log output section. def __init__(self, command: "Command") -> None: + """ + Initialized a section. + + :param command: Reference to the parent TCL command. + """ super().__init__() #command._processor) self._command = command @@ -72,6 +80,12 @@ def __init__(self, command: "Command") -> None: @readonly def Duration(self) -> float: + """ + Read-only property to access the duration synthesis spent in processing a synthesis step logged in this log output + section. + + :returns: Synthesis step duration in seconds. + """ return self._duration def _SectionStart(self, line: Line) -> Generator[Line, Line, Line]: @@ -157,9 +171,17 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class SubSection(BaseParser, BaseSection): - _section: Section + """ + Base-class for subsections within log outputs from *synthesize design*. + """ + _section: Section #: Reference to the section (parent). def __init__(self, section: Section) -> None: + """ + Initialized a subsection. + + :param section: Reference to the parent section. + """ super().__init__() self._section = section @@ -217,6 +239,19 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: return nextLine +@export +class SectionWithChildren(Section): + """ + Base-class for sections with subsections. + """ + _subsections: Dict[Type[SubSection], SubSection] + + def __init__(self, command: "Command") -> None: + super().__init__(command) + + self._subsections = {} + + @export class RTLElaboration(Section): """ @@ -296,15 +331,25 @@ class LoadingPart(Section): _START: ClassVar[str] = "Start Loading Part and Timing Information" _FINISH: ClassVar[str] = "Finished Loading Part and Timing Information : " - _part: str + _part: Nullable[str] #: Part name of the device this design was synthesized for. - def __init__(self, processor: "Processor") -> None: - super().__init__(processor) + def __init__(self, command: "Command") -> None: + """ + Initializes the section for loading the device information. + + :param command: Reference to the TCL command. + """ + super().__init__(command) self._part = None @readonly - def Part(self) -> str: + def Part(self) -> Nullable[str]: + """ + Read-only property to access the used device's part name. + + :returns: Part name of the device this design was synthesized for. + """ return self._part def Generator(self, line: Line) -> Generator[Line, Line, Line]: @@ -451,18 +496,28 @@ class TechnologyMapping(Section): @export class FlatteningBeforeIOInsertion(SubSection): + """ + *Flattening Before IO Insertion* subsection. + + Used by section :class:`IOInsertion`. + """ _START: ClassVar[str] = "Start Flattening Before IO Insertion" _FINISH: ClassVar[str] = "Finished Flattening Before IO Insertion" @export class FinalNetlistCleanup(SubSection): + """ + *Final Netlist Cleanup* subsection. + + Used by section :class:`IOInsertion`. + """ _START: ClassVar[str] = "Start Final Netlist Cleanup" _FINISH: ClassVar[str] = "Finished Final Netlist Cleanup" @export -class IOInsertion(Section): +class IOInsertion(SectionWithChildren): """ *IO Insertion* section. @@ -471,13 +526,6 @@ class IOInsertion(Section): _START: ClassVar[str] = "Start IO Insertion" _FINISH: ClassVar[str] = "Finished IO Insertion : " - _subsections: Dict[Type[SubSection], SubSection] - - def __init__(self, command: "Command") -> None: - super().__init__(command) - - self._subsections = {} - def Generator(self, line: Line) -> Generator[Line, Line, Line]: line = yield from self._SectionStart(line) @@ -582,8 +630,8 @@ class WritingSynthesisReport(Section): _START: ClassVar[str] = "Start Writing Synthesis Report" _FINISH: ClassVar[str] = "Finished Writing Synthesis Report : " - _blackboxes: Dict[str, int] - _cells: Dict[str, int] + _blackboxes: Dict[str, int] #: Blackbox statistics: blackbox name -> count + _cells: Dict[str, int] #: Cell statistics: cell name -> count def __init__(self, command: "Command") -> None: super().__init__(command) @@ -593,13 +641,41 @@ def __init__(self, command: "Command") -> None: @readonly def Cells(self) -> Dict[str, int]: + """ + Read-only property to access the dictionary of synthesized cell statistics. + + :returns: The dictionary of used cell statistics. + """ return self._cells @readonly def Blackboxes(self) -> Dict[str, int]: + """ + Read-only property to access the dictionary of found blackbox statistics. + + :returns: The dictionary of found blackbox statistics. + """ return self._blackboxes def _BlackboxesGenerator(self, line: Line) -> Generator[Line, Line, Line]: + """ + A parser parsing the blackboxes table. + + :param line: First line to process. + :returns: A generator to process multiple lines containing a table of blackboxes. + + .. topic:: Example + + .. code-block:: + + Report BlackBoxes: + +------+----------------------------------+----------+ + | |BlackBox name |Instances | + +------+----------------------------------+----------+ + |1 |name | 1| + |[...] |[...] | [...]| + +------+----------------------------------+----------+ + """ if line.StartsWith("+-"): line._kind = LineKind.TableFrame else: @@ -636,6 +712,24 @@ def _BlackboxesGenerator(self, line: Line) -> Generator[Line, Line, Line]: return nextLine def _CellGenerator(self, line: Line) -> Generator[Line, Line, Line]: + """ + A parser parsing the cell statistic table. + + :param line: First line to process. + :returns: A generator to process multiple lines containing a table of cell statistics. + + .. topic:: Example + + .. code-block:: + + Report Cell Usage: + +------+----------------------------------+------+ + | |Cell |Count | + +------+----------------------------------+------+ + |1 |name | 1| + |[...] |[...] | [...]| + +------+----------------------------------+------+ + """ if line.StartsWith("+-"): line._kind = LineKind.TableFrame else: From 0729262a80a7cf45dd89e340f08f8138ac3684f3 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Mon, 2 Feb 2026 23:38:06 +0100 Subject: [PATCH 5/7] Fixed VivadoMessage statistics. --- pyEDAA/OutputFilter/Xilinx/Common2.py | 10 +++++----- pyEDAA/OutputFilter/Xilinx/__init__.py | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pyEDAA/OutputFilter/Xilinx/Common2.py b/pyEDAA/OutputFilter/Xilinx/Common2.py index 1b484d3..eb99dc7 100644 --- a/pyEDAA/OutputFilter/Xilinx/Common2.py +++ b/pyEDAA/OutputFilter/Xilinx/Common2.py @@ -39,7 +39,7 @@ from pyTooling.Warning import WarningCollector, Warning, CriticalWarning from pyEDAA.OutputFilter import OutputFilterException -from pyEDAA.OutputFilter.Xilinx import Line, LineKind, VivadoMessage +from pyEDAA.OutputFilter.Xilinx import Line, LineKind, VivadoMessage, InfoMessage, WarningMessage, CriticalWarningMessage, ErrorMessage from pyEDAA.OutputFilter.Xilinx import VivadoInfoMessage, VivadoWarningMessage, VivadoCriticalWarningMessage, VivadoErrorMessage from pyEDAA.OutputFilter.Xilinx.Exception import ProcessorException @@ -146,13 +146,13 @@ def ErrorMessages(self) -> List[VivadoErrorMessage]: return self._errorMessages def _AddMessage(self, message: VivadoMessage) -> None: - if isinstance(message, VivadoInfoMessage): + if isinstance(message, InfoMessage): self._infoMessages.append(message) - elif isinstance(message, VivadoWarningMessage): + elif isinstance(message, WarningMessage): self._warningMessages.append(message) - elif isinstance(message, VivadoCriticalWarningMessage): + elif isinstance(message, CriticalWarningMessage): self._criticalWarningMessages.append(message) - elif isinstance(message, VivadoErrorMessage): + elif isinstance(message, ErrorMessage): self._errorMessages.append(message) if message._toolID in self._messagesByID: diff --git a/pyEDAA/OutputFilter/Xilinx/__init__.py b/pyEDAA/OutputFilter/Xilinx/__init__.py index f009185..f330b89 100644 --- a/pyEDAA/OutputFilter/Xilinx/__init__.py +++ b/pyEDAA/OutputFilter/Xilinx/__init__.py @@ -54,6 +54,9 @@ @export class Processor(VivadoMessagesMixin, metaclass=ExtendedType, slots=True): + """ + A processor for Vivado log outputs. + """ _duration: float _lines: List[ProcessedLine] @@ -85,6 +88,9 @@ def Commands(self) -> Dict[Type[Command], Command]: def Duration(self) -> float: return self._duration + def __contains__(self, item: Type[Command]) -> bool: + return item in self._commands + def __getitem__(self, item: Type[Command]) -> Command: return self._commands[item] From 0f4b05f278037a99bea3db8914f88be8028587e6 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Mon, 2 Feb 2026 23:38:39 +0100 Subject: [PATCH 6/7] New unit tests for synth_design outputs. --- tests/unit/Vivado/Synthesis.py | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 tests/unit/Vivado/Synthesis.py diff --git a/tests/unit/Vivado/Synthesis.py b/tests/unit/Vivado/Synthesis.py new file mode 100644 index 0000000..16e9dfa --- /dev/null +++ b/tests/unit/Vivado/Synthesis.py @@ -0,0 +1,78 @@ +# ==================================================================================================================== # +# _____ ____ _ _ ___ _ _ _____ _ _ _ # +# _ __ _ _| ____| _ \ / \ / \ / _ \ _ _| |_ _ __ _ _| |_| ___(_) | |_ ___ _ __ # +# | '_ \| | | | _| | | | |/ _ \ / _ \ | | | | | | | __| '_ \| | | | __| |_ | | | __/ _ \ '__| # +# | |_) | |_| | |___| |_| / ___ \ / ___ \ | |_| | |_| | |_| |_) | |_| | |_| _| | | | || __/ | # +# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___/ \__,_|\__| .__/ \__,_|\__|_| |_|_|\__\___|_| # +# |_| |___/ |_| # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2025-2026 Electronic Design Automation Abstraction (EDA²) # +# # +# 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 # +# ==================================================================================================================== # +# +"""Unit tests for Vivado synthesis log files.""" +from datetime import datetime +from textwrap import dedent +from unittest import TestCase as TestCase + +from pyEDAA.OutputFilter.Xilinx import Processor, SynthesizeDesign + +if __name__ == "__main__": # pragma: no cover + print("ERROR: you called a testcase declaration file as an executable module.") + print("Use: 'python -m unitest '") + exit(1) + + +class SynthDesign(TestCase): + def test_SynthesisLogfile(self) -> None: + print() + report = dedent("""\ + #----------------------------------------------------------- + # Vivado v2019.1 (64-bit) + # SW Build 2552052 on Fri May 24 14:49:42 MDT 2019 + # IP Build 2548770 on Fri May 24 18:01:18 MDT 2019 + # Start of session at: Tue Sep 2 08:44:13 2025 + #----------------------------------------------------------- + source system_top.tcl -notrace + Command: synth_design -top system_top -part xc7z015clg485-2 + Starting synth_design + 66 Infos, 111 Warnings, 0 Critical Warnings and 0 Errors encountered. + synth_design completed successfully + synth_design: Time (s): cpu = 00:00:24 ; elapsed = 00:00:26 . Memory (MB): peak = 1050.637 ; gain = 665.508 + Netlist sorting complete. Time (s): cpu = 00:00:00 ; elapsed = 00:00:00 . Memory (MB): peak = 1050.637 ; gain = 0.000 + WARNING: [Constraints 18-5210] No constraints selected for write. + Resolution: This message can indicate that there are no constraints for the design, or it can indicate that the used_in flags are set such that the constraints are ignored. This later case is used when running synth_design to not write synthesis constraints to the resulting checkpoint. Instead, project constraints are read when the synthesized design is opened. + INFO: [Common 17-1381] The checkpoint 'C:/Users/tgomes/git/2019_1/Vivado_PE1/MercuryZX5_PE1.runs/synth_1/system_top.dcp' has been generated. + INFO: [runtcl-4] Executing : report_utilization -file system_top_utilization_synth.rpt -pb system_top_utilization_synth.pb + INFO: [Common 17-206] Exiting Vivado at Tue Sep 2 08:44:45 2025... + """) + + processor = Processor() + next(generator := processor.LineClassification()) + for rawLine in report.splitlines(): + generator.send(rawLine) + + # self.assertEqual(datetime(2025, 9, 2, 8, 44, 13), processor.Preamble.StartDatetime) + # self.assertEqual(32, processor.Duration) + self.assertEqual(3, len(processor.InfoMessages)) + self.assertIn(SynthesizeDesign, processor) + + synthDesign = processor[SynthesizeDesign] From a2041f697b0eaa7f8465a1f427d08ba6e7f6ed33 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 5 Feb 2026 00:56:04 +0100 Subject: [PATCH 7/7] More doc-strings. --- pyEDAA/OutputFilter/Xilinx/Common2.py | 149 ++++++++++++++++-- pyEDAA/OutputFilter/Xilinx/PlaceDesign.py | 10 +- pyEDAA/OutputFilter/Xilinx/RouteDesign.py | 16 +- .../OutputFilter/Xilinx/SynthesizeDesign.py | 4 +- pyEDAA/OutputFilter/Xilinx/__init__.py | 96 ++++++++++- 5 files changed, 242 insertions(+), 33 deletions(-) diff --git a/pyEDAA/OutputFilter/Xilinx/Common2.py b/pyEDAA/OutputFilter/Xilinx/Common2.py index eb99dc7..68f49cd 100644 --- a/pyEDAA/OutputFilter/Xilinx/Common2.py +++ b/pyEDAA/OutputFilter/Xilinx/Common2.py @@ -189,13 +189,45 @@ def Processor(self) -> "Processor": @export class Preamble(Parser): - _toolVersion: Nullable[YearReleaseVersion] - _startDatetime: Nullable[datetime] + """ + A parser for the preamble emitted by Vivado at session start. + .. rubric:: Extracted information + + * Vivado tool version. |br| + See :data:`ToolVersion` + * Session start timestamp (date and time). |br| + See :data:`StartDatetime` + + .. rubric:: Example + + .. code-block:: + + #----------------------------------------------------------- + # Vivado v2019.1 (64-bit) + # SW Build 2552052 on Fri May 24 14:49:42 MDT 2019 + # IP Build 2548770 on Fri May 24 18:01:18 MDT 2019 + # Start of session at: Tue Sep 2 08:44:13 2025 + # Process ID: 35680 + # Current directory: C:/[...]/MercuryZX5_PE1.runs/synth_1 + # Command line: vivado.exe -log system_top.vds -product Vivado -mode batch -messageDb vivado.pb -notrace -source system_top.tcl + # Log file: C:/[...]/MercuryZX5_PE1.runs/synth_1/system_top.vds + # Journal file: C:/[...]/MercuryZX5_PE1.runs/synth_1/vivado.jou + #----------------------------------------------------------- + + """ _VERSION: ClassVar[Pattern] = re_compile(r"""# Vivado v(\d+\.\d(\.\d)?) \(64-bit\)""") - _STARTTIME: ClassVar[Pattern] = re_compile(r"""# Start of session at: (\w+ \w+ \d+ \d+:\d+:\d+ \d+)""") + _STARTTIME: ClassVar[Pattern] = re_compile(r"""# Start of session at: (\w+\s+\w+\s+\d+\s+\d+:\d+:\d+\s+\d+)""") + + _toolVersion: Nullable[YearReleaseVersion] #: Used Vivado version. + _startDatetime: Nullable[datetime] #: Session start timestamp. def __init__(self, processor: "BaseProcessor") -> None: + """ + Initializes a Vivado preamble parser. + + :param processor: Reference to the Vivado log processor. + """ super().__init__(processor) self._toolVersion = None @@ -203,21 +235,38 @@ def __init__(self, processor: "BaseProcessor") -> None: @readonly def ToolVersion(self) -> YearReleaseVersion: + """ + Read-only property to access the extracted Vivado tool version. + + :returns: The used Vivado version as reported in the Vivado log messages. + """ return self._toolVersion @readonly def StartDatetime(self) -> datetime: + """ + Read-only property to access the date and time when the Vivado session was started. + + :returns: Datatime when the session was started. + """ return self._startDatetime def Generator(self, line: Line) -> Generator[Line, Line, Line]: + """ + A generator for processing the Vivado session preamble line-by-line. + + :param line: First line to process. + :returns: A generator processing log messages. + """ if line.StartsWith("#----"): line._kind = LineKind.SectionDelimiter else: - line._kind |= LineKind.ProcessorError + line._kind |= LineKind.ProcessorError # TODO: throw / return error line = yield line - while True: + # a normal preamble has 11 lines including both delimiter lines. + for _ in range(15): if (match := self._VERSION.match(line._message)) is not None: self._toolVersion = YearReleaseVersion.Parse(match[1]) line._kind = LineKind.Normal @@ -231,6 +280,8 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: line._kind = LineKind.Verbose line = yield line + else: + line._kind |= LineKind.ProcessorError # TODO: throw / return error nextLine = yield line return nextLine @@ -238,14 +289,37 @@ def Generator(self, line: Line) -> Generator[Line, Line, Line]: @export class Task(BaseParser, VivadoMessagesMixin, metaclass=ExtendedType, slots=True): + """ + A task's output emitted by a Vivado command. + + .. rubric:: Extracted information + + * Vivado messages (info, warning, critical warning, error). + + .. rubric:: Example + + .. code-block:: + + Starting Cache Timing Information Task + INFO: [Timing 38-35] 79-Done setting XDC timing constraints. + Ending Cache Timing Information Task | Checksum: 19fe8cb97 + + Time (s): cpu = 00:00:09 ; elapsed = 00:00:09 . Memory (MB): peak = 1370.594 ; gain = 493.266 + + """ # _START: ClassVar[str] # _FINISH: ClassVar[str] _TIME: ClassVar[str] = "Time (s):" - _command: "Command" - _duration: float + _command: "Command" #: Reference to the command (parent). + _duration: float #: Duration of a task according to reported times by Vivado. def __init__(self, command: "Command") -> None: + """ + Initializes a task (without child elements). + + :param command: Reference to the command. + """ super().__init__() VivadoMessagesMixin.__init__(self) @@ -253,9 +327,21 @@ def __init__(self, command: "Command") -> None: @readonly def Command(self) -> "Command": + """ + Read-only property to access the command. + + :returns: The command this task's output was logged for. + """ return self._command def _TaskStart(self, line: Line) -> Generator[Line, Line, Line]: + """ + A generator for processing a task start (single line). + + :param line: First line to process (task start). + :returns: A generator processing log messages. + :raises ProcessorException: If first line doesn't conform to the *task start* pattern. + """ if not line.StartsWith(self._START): raise ProcessorException(f"{self.__class__.__name__}._TaskStart(): Expected '{self._START}' at line {line._lineNumber}.") @@ -264,12 +350,19 @@ def _TaskStart(self, line: Line) -> Generator[Line, Line, Line]: return nextLine def _TaskFinish(self, line: Line) -> Generator[Line, Line, Line]: + """ + A generator for processing a task finish line-by-line. + + :param line: First line to process (task finish). + :returns: A generator processing log messages. + :raises ProcessorException: If finish line doesn't conform to the *task finish* pattern. + """ if not line.StartsWith(self._FINISH): raise ProcessorException(f"{self.__class__.__name__}._TaskFinish(): Expected '{self._FINISH}' at line {line._lineNumber}.") line._kind = LineKind.TaskEnd line = yield line - while self._TIME is not None: + while self._TIME is not None: # TODO: limit search for time pattern to XX lines if line.StartsWith(self._TIME): line._kind = LineKind.TaskTime break @@ -280,6 +373,23 @@ def _TaskFinish(self, line: Line) -> Generator[Line, Line, Line]: return line def Generator(self, line: Line) -> Generator[Line, Line, Line]: + """ + A generator for processing a task without child elements line-by-line. + + .. rubric:: Algorithm + + 1. Send first line to :meth:`_TaskStart`. + 2. Process body lines + + * Collect Vivado messages (info, warning, critical warning, error). + * Check for *task finish* pattern. + * Check for *time* pattern. + + 3. Send last lines to :meth:`_TaskFinish`. + + :param line: First line to process. + :returns: A generator processing log messages. + """ line = yield from self._TaskStart(line) while True: @@ -306,13 +416,32 @@ def __str__(self) -> str: @export class TaskWithSubTasks(Task): + """ + A task's output emitted by a Vivado command. + + .. rubric:: Extracted information + + * Vivado messages (info, warning, critical warning, error). + * Subtasks + + .. rubric:: Example + + .. code-block:: + + Starting Cache Timing Information Task + INFO: [Timing 38-35] 79-Done setting XDC timing constraints. + Ending Cache Timing Information Task | Checksum: 19fe8cb97 + + Time (s): cpu = 00:00:09 ; elapsed = 00:00:09 . Memory (MB): peak = 1370.594 ; gain = 493.266 + + """ # _START: ClassVar[str] # _FINISH: ClassVar[str] # _TIME: ClassVar[str] = "Time (s):" - _PARSERS: ClassVar[Dict[YearReleaseVersion,Tuple[Type["SubTask"], ...]]] = dict() + _PARSERS: ClassVar[Dict[YearReleaseVersion,Tuple[Type["SubTask"], ...]]] = dict() - _subtasks: Dict[Type["SubTask"], "SubTask"] + _subtasks: Dict[Type["SubTask"], "SubTask"] def __init__(self, command: "Command") -> None: super().__init__(command) diff --git a/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py b/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py index 7c7a380..26a8c27 100644 --- a/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/PlaceDesign.py @@ -93,7 +93,7 @@ class Phase_PlacerInitialization(PhaseWithChildren): """ *Placer Initialization* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_PlacerInitializationNetlistSorting` * :class:`SubPhase_IOPlacement_ClockPlacement_BuildPlacerDevice` @@ -230,7 +230,7 @@ class Phase_GlobalPlacement(PhaseWithChildren): """ *Global Placement* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_Floorplanning` * :class:`SubPhase_UpdateTimingBeforeSLRPathOpt` @@ -411,7 +411,7 @@ class Phase_DetailPlacement(PhaseWithChildren): """ *Detail Placement* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_CommitMultiColumnMacros` * :class:`SubPhase_CommitMostMacrosLUTRAMs` @@ -539,7 +539,7 @@ class Phase_PostPlacementOptimizationAndCleanUp(PhaseWithChildren): """ *Post Placement Optimization and Clean-Up* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_PostCommitOptimization` * :class:`SubPhase_PostPlacementCleanup` @@ -566,7 +566,7 @@ class PlacerTask(TaskWithPhases): """ *Placer* task. - .. topic:: Uses + .. rubric:: Uses * :class:`Phase_PlacerInitialization` * :class:`Phase_GlobalPlacement` diff --git a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py index 8d415c3..4577fbb 100644 --- a/pyEDAA/OutputFilter/Xilinx/RouteDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/RouteDesign.py @@ -140,7 +140,7 @@ class SubPhase_UpdateTimingForBusSkew(SubPhaseWithChildren): """ *Update Timing for Bus Skew* subphase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubSubPhase_UpdateTiming` @@ -160,7 +160,7 @@ class Phase_RouterInitialization(PhaseWithChildren): """ *Router Initialization* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_CreateTimer` * :class:`SubPhase_FixTopologyConstraints` @@ -216,7 +216,7 @@ class Phase_Initial_Routing(PhaseWithChildren): """ *Initial Routing* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_GlobalRouting` * :class:`SubPhase_InitialNetRouting` @@ -298,7 +298,7 @@ class Phase_RipUpAndReroute(PhaseWithChildren): """ *Rip-up And Reroute* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_GlobalIteration0` * :class:`SubPhase_AdditionalIterationForHold` @@ -336,7 +336,7 @@ class Phase_InitialRouting(PhaseWithChildren): """ *Initial Routing* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_InitialNetRoutingPass` * :class:`SubPhase_GlobalRouting` @@ -384,7 +384,7 @@ class Phase_DelayAndSkewOptimization(PhaseWithChildren): """ *Delay and Skew Optimization* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_DelayCleanUp` * :class:`SubPhase_ClockSkewOptimization` @@ -434,7 +434,7 @@ class Phase_DelayAndSkewOptimization(PhaseWithChildren): """ *Delay and Skew Optimization* phase. - .. topic:: Uses + .. rubric:: Uses * :class:`SubPhase_DelayCleanUp` * :class:`SubPhase_ClockSkewOptimization` @@ -592,7 +592,7 @@ class RoutingTask(TaskWithPhases): """ *Routing* task. - .. topic:: Uses + .. rubric:: Uses * :class:`Phase_BuildRTDesign` * :class:`Phase_RouterInitialization` diff --git a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py index 7265754..dd2b49b 100644 --- a/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py +++ b/pyEDAA/OutputFilter/Xilinx/SynthesizeDesign.py @@ -664,7 +664,7 @@ def _BlackboxesGenerator(self, line: Line) -> Generator[Line, Line, Line]: :param line: First line to process. :returns: A generator to process multiple lines containing a table of blackboxes. - .. topic:: Example + .. rubric:: Example .. code-block:: @@ -718,7 +718,7 @@ def _CellGenerator(self, line: Line) -> Generator[Line, Line, Line]: :param line: First line to process. :returns: A generator to process multiple lines containing a table of cell statistics. - .. topic:: Example + .. rubric:: Example .. code-block:: diff --git a/pyEDAA/OutputFilter/Xilinx/__init__.py b/pyEDAA/OutputFilter/Xilinx/__init__.py index f330b89..43c27b5 100644 --- a/pyEDAA/OutputFilter/Xilinx/__init__.py +++ b/pyEDAA/OutputFilter/Xilinx/__init__.py @@ -56,17 +56,25 @@ class Processor(VivadoMessagesMixin, metaclass=ExtendedType, slots=True): """ A processor for Vivado log outputs. + + Each output line from Vivado gets processed and converted into a :class:`ProcessedLine` objects. Such lines form a + doubly-linked list. """ - _duration: float + _duration: float #: Duration of the observed process (e.g. start to end of synthesis). + _processingDuration: float #: Duration for the log output processor to parse all log messages. - _lines: List[ProcessedLine] - _preamble: Preamble - _commands: Dict[Type[Command], Command] + _lines: List[ProcessedLine] #: A list of processed log message lines. + _preamble: Preamble #: Reference to the Vivado preamble written after tool startup. + _commands: Dict[Type[Command], Command] #: A dictionary of processed Vivado commands. def __init__(self) -> None: + """ + Initializes a Vivado log output processor. + """ super().__init__() self._duration = 0.0 + self._processingDuration = 0.0 self._lines = [] self._preamble = None @@ -74,34 +82,88 @@ def __init__(self) -> None: @readonly def Lines(self) -> List[ProcessedLine]: + """ + Read-only property to access the list of processed and classified log lines (messages). + + :returns: A list of processed lines. + """ return self._lines @readonly def Preamble(self) -> Preamble: + """ + Read-only property to access the parsed preamble information. + + :returns: The log output preamble. + """ return self._preamble @readonly def Commands(self) -> Dict[Type[Command], Command]: + """ + Read-only property to access the dictionary of processed Vivado commands. + + :returns: The dictionary of processed Vivado commands. + """ return self._commands @readonly def Duration(self) -> float: + """ + Duration of the observed process (e.g. start to end of synthesis). + + :returns: The observed process' execution duration in seconds. + """ + start = self._preamble._startDatetime + + return self._duration + @readonly + def ProcessingDuration(self) -> float: + """ + Processing duration for the log output processor to parse all log messages. + + :returns: The processing duration in seconds. + """ + return self._processingDuration + def __contains__(self, item: Type[Command]) -> bool: + """ + Returns True, if log outputs where found for the given command. + + :param item: Vivado command (class). + :returns: True, if the Vivado command's outputs were found in log outputs. + """ return item in self._commands def __getitem__(self, item: Type[Command]) -> Command: + """ + Access Vivado command specific log outputs and parsed data by the command. + + :param item: Vivado command (class) to access. + :returns: A Vivado command instance with parsed log messages and extracted data. + """ return self._commands[item] + @readonly def IsIncompleteLog(self) -> bool: """ + Read-only property returning true if the processed Vivado log output is incomplete. + + A log can be incomplete, because: + + * Vivado disabled messages, because too many messages of the same kind appeared. Usually, a message type is disabled + after 100 messages of that type. This is indicated by message ``[Common 17-14]``. - :returns: undocumented + :returns: True, if messages where silenced by Vivado. .. note:: - ``INFO: [Common 17-14] Message 'Synth 8-3321' appears 100 times and further instances of the messages will be disabled. Use the Tcl command set_msg_config to change the current settings.`` + .. code-block:: + + INFO: [Common 17-14] Message 'Synth 8-3321' appears 100 times and further instances of the messages will be + disabled. Use the Tcl command set_msg_config to change the current settings. """ return 17 in self._messagesByID and 14 in self._messagesByID[17] @@ -254,15 +316,33 @@ def CommandFinder(self) -> Generator[Line, Line, None]: @export class Document(Processor): - _logfile: Path + """ + A Vivado log output processor for a log file. + This processor represents a Vivado log file (e.g. ``*.vds`` or ``*.vdi``). It processees its content line-by-line + while classifying each line as a message. The processing duration is available via :data:`ProcessingDuration`. + """ + _logfile: Path #: Path to the processed logfile. + + # FIXME: parse=True parameter def __init__(self, logfile: Path) -> None: + """ + Initializes a log file. + + :param logfile: Path to the log file. + """ super().__init__() + # FIXME: check if path self._logfile = logfile @readonly def Logfile(self) -> Path: + """ + Read-only property to access the document's path. + + :returns: Path to the log file. + """ return self._logfile def Parse(self) -> None: @@ -274,4 +354,4 @@ def Parse(self) -> None: for rawLine in content.splitlines(): generator.send(rawLine) - self._duration = sw.Duration + self._processingDuration = sw.Duration