Coverage for pyEDAA/OutputFilter/Xilinx/PlaceDesign.py: 89%
482 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, Dict, Tuple
34from pyTooling.Decorators import export
36from pyEDAA.OutputFilter.Xilinx import Line, VivadoMessage, LineKind
37from pyEDAA.OutputFilter.Xilinx.Common2 import Task, Phase, SubPhase, SubSubPhase, SubSubSubPhase
40@export
41class Phase11_PlacerInitializationNetlistSorting(SubPhase):
42 _START: ClassVar[str] = "Phase 1.1 Placer Initialization Netlist Sorting"
43 _FINISH: ClassVar[str] = "Phase 1.1 Placer Initialization Netlist Sorting | Checksum:"
44 _TIME: ClassVar[str] = "Time (s):"
47@export
48class Phase12_IOPlacement_ClockPlacement_BuildPlacerDevice(SubPhase):
49 _START: ClassVar[str] = "Phase 1.2 IO Placement/ Clock Placement/ Build Placer Device"
50 _FINISH: ClassVar[str] = "Phase 1.2 IO Placement/ Clock Placement/ Build Placer Device | Checksum:"
51 _TIME: ClassVar[str] = "Time (s):"
54@export
55class Phase13_BuildPlacerNetlistModel(SubPhase):
56 _START: ClassVar[str] = "Phase 1.3 Build Placer Netlist Model"
57 _FINISH: ClassVar[str] = "Phase 1.3 Build Placer Netlist Model | Checksum:"
58 _TIME: ClassVar[str] = "Time (s):"
61@export
62class Phase14_ConstrainClocks_Macros(SubPhase):
63 _START: ClassVar[str] = "Phase 1.4 Constrain Clocks/Macros"
64 _FINISH: ClassVar[str] = "Phase 1.4 Constrain Clocks/Macros | Checksum:"
65 _TIME: ClassVar[str] = "Time (s):"
68@export
69class Phase1_PlacerInitialization(Phase):
70 _START: ClassVar[str] = "Phase 1 Placer Initialization"
71 _FINISH: ClassVar[str] = "Phase 1 Placer Initialization | Checksum:"
72 _TIME: ClassVar[str] = "Time (s):"
73 _FINAL: ClassVar[str] = None
75 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
76 Phase11_PlacerInitializationNetlistSorting,
77 Phase12_IOPlacement_ClockPlacement_BuildPlacerDevice,
78 Phase13_BuildPlacerNetlistModel,
79 Phase14_ConstrainClocks_Macros
80 )
82 _subphases: Dict[Type[SubPhase], SubPhase]
84 def __init__(self, phase: Phase):
85 super().__init__(phase)
87 self._subphases = {p: p(self) for p in self._PARSERS}
89 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
90 line = yield from self._PhaseStart(line)
92 activeParsers: List[Phase] = list(self._subphases.values())
94 while True:
95 while True:
96 if line._kind is LineKind.Empty:
97 line = yield line
98 continue
99 elif isinstance(line, VivadoMessage): 99 ↛ 100line 99 didn't jump to line 100 because the condition on line 99 was never true
100 self._AddMessage(line)
101 elif line.StartsWith("Phase 1."):
102 for parser in activeParsers: # type: Section 102 ↛ 107line 102 didn't jump to line 107 because the loop on line 102 didn't complete
103 if line.StartsWith(parser._START): 103 ↛ 102line 103 didn't jump to line 102 because the condition on line 103 was always true
104 line = yield next(phase := parser.Generator(line))
105 break
106 else:
107 raise Exception(f"Unknown subphase: {line!r}")
108 break
109 elif line.StartsWith(self._FINISH):
110 nextLine = yield from self._PhaseFinish(line)
111 return nextLine
113 line = yield line
115 while phase is not None: 115 ↛ 94line 115 didn't jump to line 94 because the condition on line 115 was always true
116 # if line.StartsWith("Ending"):
117 # line = yield task.send(line)
118 # break
120 if isinstance(line, VivadoMessage):
121 self._AddMessage(line)
123 try:
124 line = yield phase.send(line)
125 except StopIteration as ex:
126 activeParsers.remove(parser)
127 line = ex.value
128 break
131@export
132class Phase21_Floorplanning(SubPhase):
133 _START: ClassVar[str] = "Phase 2.1 Floorplanning"
134 _FINISH: ClassVar[str] = "Phase 2.1 Floorplanning | Checksum:"
135 _TIME: ClassVar[str] = "Time (s):"
138@export
139class Phase22_UpdateTimingBeforeSLRPathOpt(SubPhase):
140 _START: ClassVar[str] = "Phase 2.2 Update Timing before SLR Path Opt"
141 _FINISH: ClassVar[str] = "Phase 2.2 Update Timing before SLR Path Opt | Checksum:"
142 _TIME: ClassVar[str] = "Time (s):"
145@export
146class Phase23_PostProcessingInFloorplanning(SubPhase):
147 _START: ClassVar[str] = "Phase 2.3 Post-Processing in Floorplanning"
148 _FINISH: ClassVar[str] = "Phase 2.3 Post-Processing in Floorplanning | Checksum:"
149 _TIME: ClassVar[str] = "Time (s):"
152@export
153class Phase24_GlobalPlacePhase1(SubPhase):
154 _START: ClassVar[str] = "Phase 2.4 Global Place Phase1"
155 _FINISH: ClassVar[str] = "Phase 2.4 Global Place Phase1 | Checksum:"
156 _TIME: ClassVar[str] = "Time (s):"
159@export
160class Phase251_UpdateTimingBeforePhysicalSynthesis(SubSubPhase):
161 _START: ClassVar[str] = "Phase 2.5.1 UpdateTiming Before Physical Synthesis"
162 _FINISH: ClassVar[str] = "Phase 2.5.1 UpdateTiming Before Physical Synthesis | Checksum:"
163 _TIME: ClassVar[str] = "Time (s):"
166@export
167class Phase252_PhysicalSynthesisInPlacer(SubSubPhase):
168 _START: ClassVar[str] = "Phase 2.5.2 Physical Synthesis In Placer"
169 _FINISH: ClassVar[str] = "Phase 2.5.2 Physical Synthesis In Placer | Checksum:"
170 _TIME: ClassVar[str] = "Time (s):"
173@export
174class Phase25_GlobalPlacePhase2(SubPhase):
175 _START: ClassVar[str] = "Phase 2.5 Global Place Phase2"
176 _FINISH: ClassVar[str] = "Phase 2.5 Global Place Phase2 | Checksum:"
177 _TIME: ClassVar[str] = "Time (s):"
179 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
180 Phase251_UpdateTimingBeforePhysicalSynthesis,
181 Phase252_PhysicalSynthesisInPlacer
182 )
184 _subsubphases: Dict[Type[SubSubPhase], SubSubPhase]
186 def __init__(self, subphase: SubPhase):
187 super().__init__(subphase)
189 self._subsubphases = {p: p(self) for p in self._PARSERS}
191 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
192 line = yield from self._SubPhaseStart(line)
194 activeParsers: List[Phase] = list(self._subsubphases.values())
196 while True:
197 while True:
198 if line._kind is LineKind.Empty:
199 line = yield line
200 continue
201 elif isinstance(line, VivadoMessage): 201 ↛ 202line 201 didn't jump to line 202 because the condition on line 201 was never true
202 self._AddMessage(line)
203 elif line.StartsWith("Phase 2.5."):
204 for parser in activeParsers: # type: SubSubPhase 204 ↛ 209line 204 didn't jump to line 209 because the loop on line 204 didn't complete
205 if line.StartsWith(parser._START): 205 ↛ 204line 205 didn't jump to line 204 because the condition on line 205 was always true
206 line = yield next(phase := parser.Generator(line))
207 break
208 else:
209 raise Exception(f"Unknown subsubphase: {line!r}")
210 break
211 elif line.StartsWith(self._FINISH): 211 ↛ 215line 211 didn't jump to line 215 because the condition on line 211 was always true
212 nextLine = yield from self._SubPhaseFinish(line)
213 return nextLine
215 line = yield line
217 while phase is not None: 217 ↛ 196line 217 didn't jump to line 196 because the condition on line 217 was always true
218 # if line.StartsWith("Ending"):
219 # line = yield task.send(line)
220 # break
222 if isinstance(line, VivadoMessage):
223 self._AddMessage(line)
225 try:
226 line = yield phase.send(line)
227 except StopIteration as ex:
228 activeParsers.remove(parser)
229 line = ex.value
230 break
233@export
234class Phase2_GlobalPlacement(Phase):
235 _START: ClassVar[str] = "Phase 2 Global Placement"
236 _FINISH: ClassVar[str] = "Phase 2 Global Placement | Checksum:"
237 _TIME: ClassVar[str] = "Time (s):"
238 _FINAL: ClassVar[str] = None
240 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
241 Phase21_Floorplanning,
242 Phase22_UpdateTimingBeforeSLRPathOpt,
243 Phase23_PostProcessingInFloorplanning,
244 Phase24_GlobalPlacePhase1,
245 Phase25_GlobalPlacePhase2
246 )
248 _subphases: Dict[Type[SubPhase], SubPhase]
250 def __init__(self, phase: Phase):
251 super().__init__(phase)
253 self._subphases = {p: p(self) for p in self._PARSERS}
255 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
256 line = yield from self._PhaseStart(line)
258 activeParsers: List[Phase] = list(self._subphases.values())
260 while True:
261 while True:
262 if line._kind is LineKind.Empty:
263 line = yield line
264 continue
265 elif isinstance(line, VivadoMessage): 265 ↛ 266line 265 didn't jump to line 266 because the condition on line 265 was never true
266 self._AddMessage(line)
267 elif line.StartsWith("Phase 2."):
268 for parser in activeParsers: # type: Phase 268 ↛ 273line 268 didn't jump to line 273 because the loop on line 268 didn't complete
269 if line.StartsWith(parser._START): 269 ↛ 268line 269 didn't jump to line 268 because the condition on line 269 was always true
270 line = yield next(phase := parser.Generator(line))
271 break
272 else:
273 raise Exception(f"Unknown subphase: {line!r}")
274 break
275 elif line.StartsWith(self._FINISH): 275 ↛ 279line 275 didn't jump to line 279 because the condition on line 275 was always true
276 nextLine = yield from self._PhaseFinish(line)
277 return nextLine
279 line = yield line
281 while phase is not None: 281 ↛ 260line 281 didn't jump to line 260 because the condition on line 281 was always true
282 # if line.StartsWith("Ending"):
283 # line = yield task.send(line)
284 # break
286 if isinstance(line, VivadoMessage):
287 self._AddMessage(line)
289 try:
290 line = yield phase.send(line)
291 except StopIteration as ex:
292 activeParsers.remove(parser)
293 line = ex.value
294 break
297@export
298class Phase31_CommitMultiColumnMacros(SubPhase):
299 _START: ClassVar[str] = "Phase 3.1 Commit Multi Column Macros"
300 _FINISH: ClassVar[str] = "Phase 3.1 Commit Multi Column Macros | Checksum:"
301 _TIME: ClassVar[str] = "Time (s):"
304@export
305class Phase32_CommitMostMacrosLUTRAMs(SubPhase):
306 _START: ClassVar[str] = "Phase 3.2 Commit Most Macros & LUTRAMs"
307 _FINISH: ClassVar[str] = "Phase 3.2 Commit Most Macros & LUTRAMs | Checksum:"
308 _TIME: ClassVar[str] = "Time (s):"
311@export
312class Phase33_AreaSwapOptimization(SubPhase):
313 _START: ClassVar[str] = "Phase 3.3 Area Swap Optimization"
314 _FINISH: ClassVar[str] = "Phase 3.3 Area Swap Optimization | Checksum:"
315 _TIME: ClassVar[str] = "Time (s):"
318@export
319class Phase34_PipelineRegisterOptimization(SubPhase):
320 _START: ClassVar[str] = "Phase 3.4 Pipeline Register Optimization"
321 _FINISH: ClassVar[str] = "Phase 3.4 Pipeline Register Optimization | Checksum:"
322 _TIME: ClassVar[str] = "Time (s):"
325@export
326class Phase35_FastOptimization(SubPhase):
327 _START: ClassVar[str] = "Phase 3.5 Fast Optimization"
328 _FINISH: ClassVar[str] = "Phase 3.5 Fast Optimization | Checksum:"
329 _TIME: ClassVar[str] = "Time (s):"
332@export
333class Phase36_SmallShapeDetailPlacement(SubPhase):
334 _START: ClassVar[str] = "Phase 3.6 Small Shape Detail Placement"
335 _FINISH: ClassVar[str] = "Phase 3.6 Small Shape Detail Placement | Checksum:"
336 _TIME: ClassVar[str] = "Time (s):"
339@export
340class Phase37_ReassignLUTPins(SubPhase):
341 _START: ClassVar[str] = "Phase 3.7 Re-assign LUT pins"
342 _FINISH: ClassVar[str] = "Phase 3.7 Re-assign LUT pins | Checksum:"
343 _TIME: ClassVar[str] = "Time (s):"
346@export
347class Phase38_PipelineRegisterOptimization(SubPhase):
348 _START: ClassVar[str] = "Phase 3.8 Pipeline Register Optimization"
349 _FINISH: ClassVar[str] = "Phase 3.8 Pipeline Register Optimization | Checksum:"
350 _TIME: ClassVar[str] = "Time (s):"
353@export
354class Phase39_FastOptimization(SubPhase):
355 _START: ClassVar[str] = "Phase 3.9 Fast Optimization"
356 _FINISH: ClassVar[str] = "Phase 3.9 Fast Optimization | Checksum:"
357 _TIME: ClassVar[str] = "Time (s):"
360@export
361class Phase3_DetailPlacement(Phase):
362 _START: ClassVar[str] = "Phase 3 Detail Placement"
363 _FINISH: ClassVar[str] = "Phase 3 Detail Placement | Checksum:"
364 _TIME: ClassVar[str] = "Time (s):"
365 _FINAL: ClassVar[str] = None
367 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
368 Phase31_CommitMultiColumnMacros,
369 Phase32_CommitMostMacrosLUTRAMs,
370 Phase33_AreaSwapOptimization,
371 Phase34_PipelineRegisterOptimization,
372 Phase35_FastOptimization,
373 Phase36_SmallShapeDetailPlacement,
374 Phase37_ReassignLUTPins,
375 Phase38_PipelineRegisterOptimization,
376 Phase39_FastOptimization
377 )
379 _subphases: Dict[Type[SubPhase], SubPhase]
381 def __init__(self, phase: Phase):
382 super().__init__(phase)
384 self._subphases = {p: p(self) for p in self._PARSERS}
386 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
387 line = yield from self._PhaseStart(line)
389 activeParsers: List[Phase] = list(self._subphases.values())
391 while True:
392 while True:
393 if line._kind is LineKind.Empty:
394 line = yield line
395 continue
396 elif isinstance(line, VivadoMessage): 396 ↛ 397line 396 didn't jump to line 397 because the condition on line 396 was never true
397 self._AddMessage(line)
398 elif line.StartsWith("Phase 3."):
399 for parser in activeParsers: # type: Section 399 ↛ 404line 399 didn't jump to line 404 because the loop on line 399 didn't complete
400 if line.StartsWith(parser._START): 400 ↛ 399line 400 didn't jump to line 399 because the condition on line 400 was always true
401 line = yield next(phase := parser.Generator(line))
402 break
403 else:
404 raise Exception(f"Unknown subphase: {line!r}")
405 break
406 elif line.StartsWith(self._FINISH): 406 ↛ 410line 406 didn't jump to line 410 because the condition on line 406 was always true
407 nextLine = yield from self._PhaseFinish(line)
408 return nextLine
410 line = yield line
412 while phase is not None: 412 ↛ 391line 412 didn't jump to line 391 because the condition on line 412 was always true
413 # if line.StartsWith("Ending"):
414 # line = yield task.send(line)
415 # break
417 if isinstance(line, VivadoMessage): 417 ↛ 418line 417 didn't jump to line 418 because the condition on line 417 was never true
418 self._AddMessage(line)
420 try:
421 line = yield phase.send(line)
422 except StopIteration as ex:
423 activeParsers.remove(parser)
424 line = ex.value
425 break
428@export
429class Phase4111_BUFGInsertion(SubSubSubPhase):
430 _START: ClassVar[str] = "Phase 4.1.1.1 BUFG Insertion"
431 _FINISH: ClassVar[str] = "Phase 4.1.1.1 BUFG Insertion | Checksum:"
432 _TIME: ClassVar[str] = "Time (s):"
435@export
436class Phase4112_PostPlacementTimingOptimization(SubSubSubPhase):
437 _START: ClassVar[str] = "Phase 4.1.1.2 Post Placement Timing Optimization"
438 _FINISH: ClassVar[str] = "Phase 4.1.1.2 Post Placement Timing Optimization | Checksum:"
439 _TIME: ClassVar[str] = "Time (s):"
442@export
443class Phase411_PostPlacementOptimization(SubSubPhase):
444 _START: ClassVar[str] = "Phase 4.1.1 Post Placement Optimization"
445 _FINISH: ClassVar[str] = None # Phase 4.1.1 Post Placement Optimization | Checksum:"
446 _TIME: ClassVar[str] = "Time (s):"
448 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
449 Phase4111_BUFGInsertion,
450 Phase4112_PostPlacementTimingOptimization
451 )
453 _subsubsubphases: Dict[Type[SubSubSubPhase], SubSubSubPhase]
455 def __init__(self, subsubphase: SubSubPhase):
456 super().__init__(subsubphase)
458 self._subsubsubphases = {p: p(self) for p in self._PARSERS}
460 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
461 line = yield from self._SubSubPhaseStart(line)
463 activeParsers: List[Phase] = list(self._subsubsubphases.values())
465 while True:
466 while True:
467 if line._kind is LineKind.Empty:
468 line = yield line
469 continue
470 elif isinstance(line, VivadoMessage): 470 ↛ 471line 470 didn't jump to line 471 because the condition on line 470 was never true
471 self._AddMessage(line)
472 elif line.StartsWith("Phase 4.1.1."):
473 for parser in activeParsers: # type: SubSubSubPhase 473 ↛ 478line 473 didn't jump to line 478 because the loop on line 473 didn't complete
474 if line.StartsWith(parser._START): 474 ↛ 473line 474 didn't jump to line 473 because the condition on line 474 was always true
475 line = yield next(phase := parser.Generator(line))
476 break
477 else:
478 raise Exception(f"Unknown subsubsubphase: {line!r}")
479 break
480 elif line.StartsWith(self._TIME):
481 line._kind = LineKind.SubSubPhaseTime
482 nextLine = yield line
483 return nextLine
485 line = yield line
487 while phase is not None: 487 ↛ 465line 487 didn't jump to line 465 because the condition on line 487 was always true
488 # if line.StartsWith("Ending"):
489 # line = yield task.send(line)
490 # break
492 if isinstance(line, VivadoMessage):
493 self._AddMessage(line)
495 try:
496 line = yield phase.send(line)
497 except StopIteration as ex:
498 activeParsers.remove(parser)
499 line = ex.value
500 break
503@export
504class Phase41_PostCommitOptimization(SubPhase):
505 _START: ClassVar[str] = "Phase 4.1 Post Commit Optimization"
506 _FINISH: ClassVar[str] = "Phase 4.1 Post Commit Optimization | Checksum:"
507 _TIME: ClassVar[str] = "Time (s):"
509 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
510 Phase411_PostPlacementOptimization,
511 )
513 _subsubphases: Dict[Type[SubSubPhase], SubSubPhase]
515 def __init__(self, subphase: SubPhase):
516 super().__init__(subphase)
518 self._subsubphases = {p: p(self) for p in self._PARSERS}
520 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
521 line = yield from self._SubPhaseStart(line)
523 activeParsers: List[Phase] = list(self._subsubphases.values())
525 while True:
526 while True:
527 if line._kind is LineKind.Empty:
528 line = yield line
529 continue
530 elif isinstance(line, VivadoMessage):
531 self._AddMessage(line)
532 elif line.StartsWith("Phase 4.1."):
533 for parser in activeParsers: # type: SubSubPhase 533 ↛ 538line 533 didn't jump to line 538 because the loop on line 533 didn't complete
534 if line.StartsWith(parser._START): 534 ↛ 533line 534 didn't jump to line 533 because the condition on line 534 was always true
535 line = yield next(phase := parser.Generator(line))
536 break
537 else:
538 raise Exception(f"Unknown subsubphase: {line!r}")
539 break
540 elif line.StartsWith(self._FINISH): 540 ↛ 544line 540 didn't jump to line 544 because the condition on line 540 was always true
541 nextLine = yield from self._SubPhaseFinish(line)
542 return nextLine
544 line = yield line
546 while phase is not None: 546 ↛ 525line 546 didn't jump to line 525 because the condition on line 546 was always true
547 # if line.StartsWith("Ending"):
548 # line = yield task.send(line)
549 # break
551 if isinstance(line, VivadoMessage):
552 self._AddMessage(line)
554 try:
555 line = yield phase.send(line)
556 except StopIteration as ex:
557 activeParsers.remove(parser)
558 line = ex.value
559 break
562@export
563class Phase42_PostPlacementCleanup(SubPhase):
564 _START: ClassVar[str] = "Phase 4.2 Post Placement Cleanup"
565 _FINISH: ClassVar[str] = "Phase 4.2 Post Placement Cleanup | Checksum:"
566 _TIME: ClassVar[str] = "Time (s):"
569@export
570class Phase431_PrintEstimatedCongestion(SubSubPhase):
571 _START: ClassVar[str] = "Phase 4.3.1 Print Estimated Congestion"
572 _FINISH: ClassVar[str] = "Phase 4.3.1 Print Estimated Congestion | Checksum:"
573 _TIME: ClassVar[str] = "Time (s):"
576@export
577class Phase43_PlacerReporting(SubPhase):
578 _START: ClassVar[str] = "Phase 4.3 Placer Reporting"
579 _FINISH: ClassVar[str] = "Phase 4.3 Placer Reporting | Checksum:"
580 _TIME: ClassVar[str] = "Time (s):"
582 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
583 Phase431_PrintEstimatedCongestion,
584 )
586 _subsubphases: Dict[Type[SubSubPhase], SubSubPhase]
588 def __init__(self, subphase: SubPhase):
589 super().__init__(subphase)
591 self._subsubphases = {p: p(self) for p in self._PARSERS}
593 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
594 line = yield from self._SubPhaseStart(line)
596 activeParsers: List[Phase] = list(self._subsubphases.values())
598 while True:
599 while True:
600 if line._kind is LineKind.Empty:
601 line = yield line
602 continue
603 elif isinstance(line, VivadoMessage): 603 ↛ 604line 603 didn't jump to line 604 because the condition on line 603 was never true
604 self._AddMessage(line)
605 elif line.StartsWith("Phase 4.3."):
606 for parser in activeParsers: # type: SubSubPhase 606 ↛ 611line 606 didn't jump to line 611 because the loop on line 606 didn't complete
607 if line.StartsWith(parser._START): 607 ↛ 606line 607 didn't jump to line 606 because the condition on line 607 was always true
608 line = yield next(phase := parser.Generator(line))
609 break
610 else:
611 raise Exception(f"Unknown subsubphase: {line!r}")
612 break
613 elif line.StartsWith(self._FINISH): 613 ↛ 617line 613 didn't jump to line 617 because the condition on line 613 was always true
614 nextLine = yield from self._SubPhaseFinish(line)
615 return nextLine
617 line = yield line
619 while phase is not None: 619 ↛ 598line 619 didn't jump to line 598 because the condition on line 619 was always true
620 # if line.StartsWith("Ending"):
621 # line = yield task.send(line)
622 # break
624 if isinstance(line, VivadoMessage):
625 self._AddMessage(line)
627 try:
628 line = yield phase.send(line)
629 except StopIteration as ex:
630 activeParsers.remove(parser)
631 line = ex.value
632 break
635@export
636class Phase44_FinalPlacementCleanup(SubPhase):
637 _START: ClassVar[str] = "Phase 4.4 Final Placement Cleanup"
638 _FINISH: ClassVar[str] = "Time (s):"
639 _TIME: ClassVar[str] = None
642@export
643class Phase4_PostPlacementOptimizationAndCleanUp(Phase):
644 _START: ClassVar[str] = "Phase 4 Post Placement Optimization and Clean-Up"
645 _FINISH: ClassVar[str] = "Phase 4 Post Placement Optimization and Clean-Up | Checksum:"
646 _TIME: ClassVar[str] = "Time (s):"
647 _FINAL: ClassVar[str] = None
649 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
650 Phase41_PostCommitOptimization,
651 Phase42_PostPlacementCleanup,
652 Phase43_PlacerReporting,
653 Phase44_FinalPlacementCleanup
654 )
656 _subphases: Dict[Type[SubPhase], SubPhase]
658 def __init__(self, phase: Phase):
659 super().__init__(phase)
661 self._subphases = {p: p(self) for p in self._PARSERS}
663 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
664 line = yield from self._PhaseStart(line)
666 activeParsers: List[Phase] = list(self._subphases.values())
668 while True:
669 while True:
670 if isinstance(line, VivadoMessage): 670 ↛ 671line 670 didn't jump to line 671 because the condition on line 670 was never true
671 self._AddMessage(line)
672 elif line.StartsWith("Phase 4."):
673 for parser in activeParsers: # type: Section 673 ↛ 678line 673 didn't jump to line 678 because the loop on line 673 didn't complete
674 if line.StartsWith(parser._START): 674 ↛ 673line 674 didn't jump to line 673 because the condition on line 674 was always true
675 line = yield next(phase := parser.Generator(line))
676 break
677 else:
678 raise Exception(f"Unknown subphase: {line!r}")
679 break
680 elif line.StartsWith(self._FINISH):
681 nextLine = yield from self._PhaseFinish(line)
682 return nextLine
684 line = yield line
686 while phase is not None: 686 ↛ 668line 686 didn't jump to line 668 because the condition on line 686 was always true
687 # if line.StartsWith("Ending"):
688 # line = yield task.send(line)
689 # break
691 if isinstance(line, VivadoMessage):
692 self._AddMessage(line)
694 try:
695 line = yield phase.send(line)
696 except StopIteration as ex:
697 activeParsers.remove(parser)
698 line = ex.value
699 break
702@export
703class PlacerTask(Task):
704 _START: ClassVar[str] = "Starting Placer Task"
705 _FINISH: ClassVar[str] = "Ending Placer Task"
707 _PARSERS: ClassVar[Tuple[Type[Phase], ...]] = (
708 Phase1_PlacerInitialization,
709 Phase2_GlobalPlacement,
710 Phase3_DetailPlacement,
711 Phase4_PostPlacementOptimizationAndCleanUp
712 )
714 def Generator(self, line: Line) -> Generator[Line, Line, Line]:
715 line = yield from self._TaskStart(line)
717 activeParsers: List[Phase] = list(self._phases.values())
719 while True:
720 while True:
721 if isinstance(line, VivadoMessage): 721 ↛ 722line 721 didn't jump to line 722 because the condition on line 721 was never true
722 self._AddMessage(line)
723 elif line.StartsWith("Phase "):
724 for parser in activeParsers: # type: Section 724 ↛ 729line 724 didn't jump to line 729 because the loop on line 724 didn't complete
725 if line.StartsWith(parser._START): 725 ↛ 724line 725 didn't jump to line 724 because the condition on line 725 was always true
726 line = yield next(phase := parser.Generator(line))
727 break
728 else:
729 raise Exception(f"Unknown phase: {line!r}")
730 break
731 elif line.StartsWith("Ending"):
732 nextLine = yield from self._TaskFinish(line)
733 return nextLine
734 elif line.StartsWith(self._TIME): 734 ↛ 735line 734 didn't jump to line 735 because the condition on line 734 was never true
735 line._kind = LineKind.TaskTime
736 nextLine = yield line
737 return nextLine
739 line = yield line
741 while phase is not None: 741 ↛ 719line 741 didn't jump to line 719 because the condition on line 741 was always true
742 # if line.StartsWith("Ending"):
743 # line = yield task.send(line)
744 # break
746 if isinstance(line, VivadoMessage):
747 self._AddMessage(line)
749 try:
750 line = yield phase.send(line)
751 except StopIteration as ex:
752 activeParsers.remove(parser)
753 line = ex.value
754 break