Coverage for tsfpga/vivado/build_result.py: 97%
30 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-21 23:39 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-21 23:39 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the tsfpga project, a project platform for modern FPGA development.
5# https://tsfpga.com
6# https://github.com/tsfpga/tsfpga
7# --------------------------------------------------------------------------------------------------
9from __future__ import annotations
11from tsfpga.build_result import BuildResult as BaseBuildResult
12from tsfpga.build_result import _to_engineering_string
14from .logic_level_distribution_parser import LogicLevelDistributionParser
17class VivadoBuildResult(BaseBuildResult):
18 """
19 The result of a Vivado build.
21 Attributes:
22 synthesis_run_name (`str`): The name of the Vivado synthesis run that produced this
23 result (e.g. ``synth_2``).
24 implementation_run_name (`str`): The name of the Vivado implementation run that produced
25 this result (e.g. ``impl_2``). Will be ``None`` for netlist (synthesis-only) builds,
26 since those have no implementation step.
27 implementation_size (`dict`): A dictionary with the utilization of primitives for
28 the implemented design.
29 Will be ``None`` if implementation failed or did not run.
30 logic_level_distribution (str): A table with logic level distribution as reported by
31 Vivado. Will be ``None`` for non-netlist builds.
32 Will be ``None`` if synthesis failed or did not run.
33 """
35 def __init__(self, name: str, synthesis_run_name: str) -> None:
36 """
37 Arguments:
38 name: The name of the build.
39 synthesis_run_name: The name of the Vivado run that produced this result
40 (e.g. ``synth_2``).
41 """
42 super().__init__(name=name)
44 self.synthesis_run_name = synthesis_run_name
45 self.implementation_run_name: str | None = None
47 self.implementation_size: dict[str, int] | None = None
49 self.logic_level_distribution: str | None = None
51 self.maximum_synthesis_frequency_hz: float | None = None
53 def _get_size_to_report(self) -> tuple[str, dict[str, int]] | None:
54 if self.implementation_size:
55 return "implementation", self.implementation_size
57 return super()._get_size_to_report()
59 def report(self) -> str | None:
60 """
61 Return a report of the build result. Includes all metrics and information that has been
62 extracted from the Vivado reports.
63 """
64 result = super().report()
65 if result is None:
66 return None
68 if self.maximum_synthesis_frequency_hz:
69 result += (
70 f"\nMaximum synthesis frequency estimate: "
71 f"{_to_engineering_string(value=self.maximum_synthesis_frequency_hz)}Hz"
72 )
74 if self.logic_level_distribution:
75 result += f"\nLogic level distribution:\n{self.logic_level_distribution}"
77 return result
79 @property
80 def maximum_logic_level(self) -> int | None:
81 """
82 The maximum level in the the :attr:`.VivadoBuildResult.logic_level_distribution`.
83 Will be ``None`` for non-netlist builds.
84 Will be ``None`` if synthesis failed or did not run.
86 Return:
87 The maximum logic level.
88 """
89 if not self.logic_level_distribution:
90 return None
92 return LogicLevelDistributionParser.get_maximum_logic_level(
93 table=self.logic_level_distribution
94 )