Coverage for pyEDAA/OutputFilter/Xilinx/PhysicalOptimizeDesign.py: 90%
65 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-16 06:19 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-16 06:19 +0000
1# ==================================================================================================================== #
2# _____ ____ _ _ ___ _ _ _____ _ _ _ #
3# _ __ _ _| ____| _ \ / \ / \ / _ \ _ _| |_ _ __ _ _| |_| ___(_) | |_ ___ _ __ #
4# | '_ \| | | | _| | | | |/ _ \ / _ \ | | | | | | | __| '_ \| | | | __| |_ | | | __/ _ \ '__| #
5# | |_) | |_| | |___| |_| / ___ \ / ___ \ | |_| | |_| | |_| |_) | |_| | |_| _| | | | || __/ | #
6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___/ \__,_|\__| .__/ \__,_|\__|_| |_|_|\__\___|_| #
7# |_| |___/ |_| #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2025-2025 Electronic Design Automation Abstraction (EDA²) #
15# #
16# Licensed under the Apache License, Version 2.0 (the "License"); #
17# you may not use this file except in compliance with the License. #
18# You may obtain a copy of the License at #
19# #
20# http://www.apache.org/licenses/LICENSE-2.0 #
21# #
22# Unless required by applicable law or agreed to in writing, software #
23# distributed under the License is distributed on an "AS IS" BASIS, #
24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
25# See the License for the specific language governing permissions and #
26# limitations under the License. #
27# #
28# SPDX-License-Identifier: Apache-2.0 #
29# ==================================================================================================================== #
30#
31"""A filtering anc classification processor for AMD/Xilinx Vivado Synthesis outputs."""
32from typing import Generator, ClassVar, List, Type, Tuple
34from pyTooling.Decorators import export
36from pyEDAA.OutputFilter.Xilinx import Line, VivadoMessage, LineKind
37from pyEDAA.OutputFilter.Xilinx.Common2 import Task, Phase
40@export
41class InitialUpdateTimingTask(Task):
42 _NAME: ClassVar[str] = "Initial Update Timing Task"
43 _START: ClassVar[str] = "Starting Initial Update Timing Task"
44 _FINISH: ClassVar[str] = None
47@export
48class Phase1_PlacerInitialization(Phase):
49 _START: ClassVar[str] = "Phase 1 Physical Synthesis Initialization"
50 _FINISH: ClassVar[str] = "Phase 1 Physical Synthesis Initialization | Checksum:"
53@export
54class Phase2_DSPRegisterOptimization(Phase):
55 _START: ClassVar[str] = "Phase 2 DSP Register Optimization"
56 _FINISH: ClassVar[str] = "Phase 2 DSP Register Optimization | Checksum:"
59@export
60class Phase3_CriticalPathOptimization(Phase):
61 _START: ClassVar[str] = "Phase 3 Critical Path Optimization"
62 _FINISH: ClassVar[str] = "Phase 3 Critical Path Optimization | Checksum:"
65@export
66class Phase4_CriticalPathOptimization(Phase):
67 _START: ClassVar[str] = "Phase 4 Critical Path Optimization"
68 _FINISH: ClassVar[str] = "Phase 4 Critical Path Optimization | Checksum:"
71@export
72class PhysicalSynthesisTask(Task):
73 _NAME: ClassVar[str] = "Physical Synthesis Task"
74 _START: ClassVar[str] = "Starting Physical Synthesis Task"
75 _FINISH: ClassVar[str] = "Ending Physical Synthesis Task"
77 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
78 Phase1_PlacerInitialization,
79 Phase2_DSPRegisterOptimization,
80 Phase3_CriticalPathOptimization,
81 Phase4_CriticalPathOptimization
82 )
84 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
85 line = yield from self._TaskStart(line)
87 activeParsers: List[Phase] = list(self._phases.values())
89 while True:
90 while True:
91 if line._kind is LineKind.Empty:
92 line = yield line
93 continue
94 elif isinstance(line, VivadoMessage):
95 self._AddMessage(line)
96 elif line.StartsWith("Phase "):
97 for parser in activeParsers: # type: Phase 97 ↛ 102line 97 didn't jump to line 102 because the loop on line 97 didn't complete
98 if line.StartsWith(parser._START): 98 ↛ 97line 98 didn't jump to line 97 because the condition on line 98 was always true
99 line = yield next(phase := parser.Generator(line))
100 break
101 else:
102 raise Exception(f"Unknown phase: {line!r}")
103 break
104 elif line.StartsWith("Ending"):
105 nextLine = yield from self._TaskFinish(line)
106 return nextLine
107 elif line.StartsWith(self._TIME): 107 ↛ 108line 107 didn't jump to line 108 because the condition on line 107 was never true
108 line._kind = LineKind.TaskTime
109 nextLine = yield line
110 return nextLine
112 line = yield line
114 while phase is not None: 114 ↛ 89line 114 didn't jump to line 89 because the condition on line 114 was always true
115 # if line.StartsWith("Ending"):
116 # line = yield task.send(line)
117 # break
119 if isinstance(line, VivadoMessage):
120 self._AddMessage(line)
122 try:
123 line = yield phase.send(line)
124 except StopIteration as ex:
125 activeParsers.remove(parser)
126 line = ex.value
127 break