Coverage for pyEDAA/Reports/CodeCoverage/UCIS/Coverpoints.py: 73%
249 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-21 23:49 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-21 23:49 +0000
1# ==================================================================================================================== #
2# _____ ____ _ _ ____ _ #
3# _ __ _ _| ____| _ \ / \ / \ | _ \ ___ _ __ ___ _ __| |_ ___ #
4# | '_ \| | | | _| | | | |/ _ \ / _ \ | |_) / _ \ '_ \ / _ \| '__| __/ __| #
5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _| _ < __/ |_) | (_) | | | |_\__ \ #
6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)_| \_\___| .__/ \___/|_| \__|___/ #
7# |_| |___/ |_| #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2026-2026 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"""
32The coverpoints of the covergroup coverage of the UCIS XML interchange format: their bins, and the value ranges or
33sequences a bin counts.
34"""
35from __future__ import annotations
37from typing import TYPE_CHECKING, Iterable, Optional as Nullable, Self
39from lxml.etree import _Element
40from pyTooling.Common import getFullyQualifiedName
41from pyTooling.Decorators import export, readonly
42from pyTooling.MetaClasses import ExtendedType, abstractclass
44from pyEDAA.Reports.CodeCoverage.UCIS.Bins import BinContents
45from pyEDAA.Reports.CodeCoverage.UCIS.CoverOptions import CoverpointOptions
46from pyEDAA.Reports.CodeCoverage.UCIS.Elements import Base, UserAttribute
48if TYPE_CHECKING: 48 ↛ 49line 48 didn't jump to line 49 because the condition on line 48 was never true
49 from pyEDAA.Reports.CodeCoverage.UCIS.Covergroups import CovergroupInstance
52@export
53@abstractclass
54class BinBase(Base):
55 """
56 Base-class of the bins of a coverpoint or a cross: the bin's kind, alias, and - as some tools write them - name and
57 key.
58 """
60 _binType: str #: Kind of the bin, e.g. ``default``, ``ignore`` or ``illegal``.
61 _alias: Nullable[str] #: An alias of the bin's name.
62 _name: Nullable[str] #: Name of the bin.
63 _key: Nullable[str] #: UCIS key of the bin.
65 def __init__(
66 self,
67 binType: str,
68 alias: Nullable[str] = None,
69 name: Nullable[str] = None,
70 key: Nullable[str] = None,
71 userAttributes: Nullable[Iterable[UserAttribute]] = None
72 ) -> None:
73 """
74 Initialize the bin's kind, alias, name and key.
76 :param binType: Kind of the bin, e.g. ``default``, ``ignore`` or ``illegal``.
77 :param alias: Optional, an alias of the bin's name. Default: ``None``.
78 :param name: Optional, name of the bin; the standard's schema has none, pyucis writes it. Default:
79 ``None``.
80 :param key: Optional, UCIS key of the bin; the standard's schema has none, pyucis writes it. Default:
81 ``None``.
82 :param userAttributes: Optional, the user-defined attributes. Default: ``None``.
83 :raises TypeError: If parameter ``userAttributes`` isn't iterable.
84 :raises TypeError: If parameter ``userAttributes`` contains an element not of type
85 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Elements.UserAttribute`.
86 :raises ValueError: If parameter ``binType`` is ``None``.
87 :raises TypeError: If parameter ``binType`` isn't of type :class:`str`.
88 :raises TypeError: If parameter ``alias``, ``name`` or ``key`` isn't of type :class:`str`.
89 """
90 super().__init__(userAttributes)
92 if binType is None: 92 ↛ 93line 92 didn't jump to line 93 because the condition on line 92 was never true
93 raise ValueError("Parameter 'binType' is None.")
94 elif not isinstance(binType, str): 94 ↛ 95line 94 didn't jump to line 95 because the condition on line 94 was never true
95 ex = TypeError("Parameter 'binType' is not of type 'str'.")
96 ex.add_note(f"Got type '{getFullyQualifiedName(binType)}'.")
97 raise ex
99 for parameterName, value in (
100 ("alias", alias),
101 ("name", name),
102 ("key", key)
103 ):
104 if value is not None and not isinstance(value, str): 104 ↛ 105line 104 didn't jump to line 105 because the condition on line 104 was never true
105 ex = TypeError(f"Parameter '{parameterName}' is not of type 'str'.")
106 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
107 raise ex
109 self._binType = binType
110 self._alias = alias
111 self._name = name
112 self._key = key
114 @readonly
115 def BinType(self) -> str:
116 """
117 Read-only property to access the kind of the bin (:attr:`_binType`).
119 :returns: The kind, as stated, e.g. ``default``, ``ignore`` or ``illegal``.
120 """
121 return self._binType
123 @readonly
124 def Alias(self) -> Nullable[str]:
125 """
126 Read-only property to access the alias of the bin's name (:attr:`_alias`).
128 :returns: The alias; ``None``, if the report states none.
129 """
130 return self._alias
132 @readonly
133 def Name(self) -> Nullable[str]:
134 """
135 Read-only property to access the name of the bin (:attr:`_name`).
137 :returns: The name; ``None``, if the report states none.
138 """
139 return self._name
141 @readonly
142 def Key(self) -> Nullable[str]:
143 """
144 Read-only property to access the UCIS key of the bin (:attr:`_key`).
146 :returns: The key; ``None``, if the report states none.
147 """
148 return self._key
151@export
152class ValueRange(metaclass=ExtendedType, slots=True):
153 """
154 A ``<range>`` of a coverpoint's bin: a range of values, and how often the coverpoint's expression had one of them.
155 """
157 _parent: Nullable[CoverpointBin] #: The coverpoint bin the range belongs to.
158 _from: int #: The range's lowest value.
159 _to: int #: The range's highest value.
160 _contents: BinContents #: How often the expression had a value of the range.
162 def __init__(self, fromValue: int, toValue: int, contents: BinContents) -> None:
163 """
164 Initialize the range of values.
166 The coverpoint bin owning the range takes it as a parameter and becomes its parent.
168 :param fromValue: The range's lowest value.
169 :param toValue: The range's highest value; the lowest one again for a single value.
170 :param contents: How often the expression had a value of the range.
171 :raises ValueError: If parameter ``fromValue`` or ``toValue`` is ``None``.
172 :raises TypeError: If parameter ``fromValue`` or ``toValue`` isn't of type :class:`int`.
173 :raises ValueError: If parameter ``contents`` is ``None``.
174 :raises TypeError: If parameter ``contents`` isn't of type
175 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Bins.BinContents`.
176 """
177 for parameterName, value in (
178 ("fromValue", fromValue),
179 ("toValue", toValue)
180 ):
181 if value is None: 181 ↛ 182line 181 didn't jump to line 182 because the condition on line 181 was never true
182 raise ValueError(f"Parameter '{parameterName}' is None.")
183 elif not isinstance(value, int) or isinstance(value, bool): 183 ↛ 184line 183 didn't jump to line 184 because the condition on line 183 was never true
184 ex = TypeError(f"Parameter '{parameterName}' is not of type 'int'.")
185 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
186 raise ex
188 if contents is None: 188 ↛ 189line 188 didn't jump to line 189 because the condition on line 188 was never true
189 raise ValueError("Parameter 'contents' is None.")
190 elif not isinstance(contents, BinContents): 190 ↛ 191line 190 didn't jump to line 191 because the condition on line 190 was never true
191 ex = TypeError("Parameter 'contents' is not of type 'BinContents'.")
192 ex.add_note(f"Got type '{getFullyQualifiedName(contents)}'.")
193 raise ex
195 self._parent = None
196 self._from = fromValue
197 self._to = toValue
198 self._contents = contents
200 @classmethod
201 def Parse(cls, element: _Element) -> Self:
202 """
203 Parse a range of values from its ``<range>`` element.
205 :param element: The ``<range>`` element.
206 :returns: The range.
207 """
208 return cls(
209 int(element.attrib["from"]),
210 int(element.attrib["to"]),
211 BinContents.Parse(element.find("{*}contents"))
212 )
214 @readonly
215 def Parent(self) -> Nullable[CoverpointBin]:
216 """
217 Read-only property to access the coverpoint bin the range belongs to (:attr:`_parent`).
219 :returns: The coverpoint bin; ``None``, if the range belongs to none.
220 """
221 return self._parent
223 @readonly
224 def From(self) -> int:
225 """
226 Read-only property to access the range's lowest value (:attr:`_from`).
228 :returns: The value.
229 """
230 return self._from
232 @readonly
233 def To(self) -> int:
234 """
235 Read-only property to access the range's highest value (:attr:`_to`).
237 :returns: The value.
238 """
239 return self._to
241 @readonly
242 def Contents(self) -> BinContents:
243 """
244 Read-only property to access how often the expression had a value of the range (:attr:`_contents`).
246 :returns: The contents: the count and the tests.
247 """
248 return self._contents
251@export
252class ValueSequence(metaclass=ExtendedType, slots=True):
253 """
254 A ``<sequence>`` of a coverpoint's bin: a sequence of values, and how often the coverpoint's expression had them one
255 after the other.
256 """
258 _parent: Nullable[CoverpointBin] #: The coverpoint bin the sequence belongs to.
259 _values: list[int] #: The values, from the first one.
260 _contents: BinContents #: How often the expression had the values one after the other.
262 def __init__(self, values: Iterable[int], contents: BinContents) -> None:
263 """
264 Initialize the sequence of values.
266 The coverpoint bin owning the sequence takes it as a parameter and becomes its parent.
268 :param values: The values, from the first one.
269 :param contents: How often the expression had the values one after the other.
270 :raises ValueError: If parameter ``contents`` is ``None``.
271 :raises TypeError: If parameter ``contents`` isn't of type
272 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Bins.BinContents`.
273 :raises ValueError: If parameter ``values`` is ``None``.
274 :raises TypeError: If parameter ``values`` isn't iterable.
275 :raises TypeError: If parameter ``values`` contains an element not of type :class:`int`.
276 :raises ValueError: If parameter ``values`` is empty.
277 """
278 if contents is None: 278 ↛ 279line 278 didn't jump to line 279 because the condition on line 278 was never true
279 raise ValueError("Parameter 'contents' is None.")
280 elif not isinstance(contents, BinContents): 280 ↛ 281line 280 didn't jump to line 281 because the condition on line 280 was never true
281 ex = TypeError("Parameter 'contents' is not of type 'BinContents'.")
282 ex.add_note(f"Got type '{getFullyQualifiedName(contents)}'.")
283 raise ex
285 self._parent = None
286 self._values = []
287 self._contents = contents
289 if values is None: 289 ↛ 290line 289 didn't jump to line 290 because the condition on line 289 was never true
290 raise ValueError("Parameter 'values' is None.")
291 elif not isinstance(values, Iterable): 291 ↛ 292line 291 didn't jump to line 292 because the condition on line 291 was never true
292 ex = TypeError("Parameter 'values' is not iterable.")
293 ex.add_note(f"Got type '{getFullyQualifiedName(values)}'.")
294 raise ex
296 for value in values:
297 if not isinstance(value, int) or isinstance(value, bool): 297 ↛ 298line 297 didn't jump to line 298 because the condition on line 297 was never true
298 ex = TypeError("Parameter 'values' contains an element not of type 'int'.")
299 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
300 raise ex
302 self._values.append(value)
304 if len(self._values) == 0:
305 raise ValueError("Parameter 'values' is empty.")
307 @classmethod
308 def Parse(cls, element: _Element) -> Self:
309 """
310 Parse a sequence of values from its ``<sequence>`` element.
312 :param element: The ``<sequence>`` element.
313 :returns: The sequence.
314 """
315 return cls(
316 [int(valueElement.text) for valueElement in element.iterfind("{*}seqValue")],
317 BinContents.Parse(element.find("{*}contents"))
318 )
320 @readonly
321 def Parent(self) -> Nullable[CoverpointBin]:
322 """
323 Read-only property to access the coverpoint bin the sequence belongs to (:attr:`_parent`).
325 :returns: The coverpoint bin; ``None``, if the sequence belongs to none.
326 """
327 return self._parent
329 @readonly
330 def Values(self) -> list[int]:
331 """
332 Read-only property to access the values (:attr:`_values`).
334 :returns: The values, from the first one.
335 """
336 return self._values
338 @readonly
339 def Contents(self) -> BinContents:
340 """
341 Read-only property to access how often the expression had the values one after the other (:attr:`_contents`).
343 :returns: The contents: the count and the tests.
344 """
345 return self._contents
348@export
349class CoverpointBin(BinBase):
350 """
351 A ``<coverpointBin>`` of a coverpoint: its kind, and the ranges or sequences of values it counts.
352 """
354 _parent: Nullable[Coverpoint] #: The coverpoint the bin belongs to.
355 _ranges: list[ValueRange] #: The ranges of values the bin counts.
356 _sequences: list[ValueSequence] #: The sequences of values the bin counts.
358 def __init__(
359 self,
360 binType: str,
361 ranges: Nullable[Iterable[ValueRange]] = None,
362 sequences: Nullable[Iterable[ValueSequence]] = None,
363 alias: Nullable[str] = None,
364 name: Nullable[str] = None,
365 key: Nullable[str] = None,
366 userAttributes: Nullable[Iterable[UserAttribute]] = None,
367 *,
368 parent: Nullable[Coverpoint] = None
369 ) -> None:
370 """
371 Initialize the coverpoint bin, become its ranges' and sequences' parent, and append it to the bins of its
372 coverpoint.
374 :param binType: Kind of the bin, e.g. ``default``, ``ignore`` or ``illegal``.
375 :param ranges: Optional, the ranges of values the bin counts. Default: ``None``.
376 :param sequences: Optional, the sequences of values the bin counts. Default: ``None``.
377 :param alias: Optional, an alias of the bin's name. Default: ``None``.
378 :param name: Optional, name of the bin, as pyucis writes it. Default: ``None``.
379 :param key: Optional, UCIS key of the bin, as pyucis writes it. Default: ``None``.
380 :param userAttributes: Optional, the user-defined attributes. Default: ``None``.
381 :param parent: Optional, the coverpoint the bin belongs to. Default: ``None``.
382 :raises TypeError: If parameter ``userAttributes`` isn't iterable.
383 :raises TypeError: If parameter ``userAttributes`` contains an element not of type
384 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Elements.UserAttribute`.
385 :raises ValueError: If parameter ``binType`` is ``None``.
386 :raises TypeError: If parameter ``binType`` isn't of type :class:`str`.
387 :raises TypeError: If parameter ``alias``, ``name`` or ``key`` isn't of type :class:`str`.
388 :raises TypeError: If parameter ``parent`` isn't of type :class:`Coverpoint`.
389 :raises TypeError: If parameter ``ranges`` isn't iterable.
390 :raises TypeError: If parameter ``ranges`` contains an element not of type :class:`ValueRange`.
391 :raises TypeError: If parameter ``sequences`` isn't iterable.
392 :raises TypeError: If parameter ``sequences`` contains an element not of type :class:`ValueSequence`.
393 """
394 super().__init__(binType, alias, name, key, userAttributes)
396 if parent is not None and not isinstance(parent, Coverpoint): 396 ↛ 397line 396 didn't jump to line 397 because the condition on line 396 was never true
397 ex = TypeError("Parameter 'parent' is not of type 'Coverpoint'.")
398 ex.add_note(f"Got type '{getFullyQualifiedName(parent)}'.")
399 raise ex
401 self._parent = parent
402 self._ranges = []
403 self._sequences = []
405 if ranges is not None: 405 ↛ 420line 405 didn't jump to line 420 because the condition on line 405 was always true
406 if not isinstance(ranges, Iterable): 406 ↛ 407line 406 didn't jump to line 407 because the condition on line 406 was never true
407 ex = TypeError("Parameter 'ranges' is not iterable.")
408 ex.add_note(f"Got type '{getFullyQualifiedName(ranges)}'.")
409 raise ex
411 for valueRange in ranges:
412 if not isinstance(valueRange, ValueRange): 412 ↛ 413line 412 didn't jump to line 413 because the condition on line 412 was never true
413 ex = TypeError("Parameter 'ranges' contains an element not of type 'ValueRange'.")
414 ex.add_note(f"Got type '{getFullyQualifiedName(valueRange)}'.")
415 raise ex
417 valueRange._parent = self
418 self._ranges.append(valueRange)
420 if sequences is not None:
421 if not isinstance(sequences, Iterable): 421 ↛ 422line 421 didn't jump to line 422 because the condition on line 421 was never true
422 ex = TypeError("Parameter 'sequences' is not iterable.")
423 ex.add_note(f"Got type '{getFullyQualifiedName(sequences)}'.")
424 raise ex
426 for valueSequence in sequences:
427 if not isinstance(valueSequence, ValueSequence): 427 ↛ 428line 427 didn't jump to line 428 because the condition on line 427 was never true
428 ex = TypeError("Parameter 'sequences' contains an element not of type 'ValueSequence'.")
429 ex.add_note(f"Got type '{getFullyQualifiedName(valueSequence)}'.")
430 raise ex
432 valueSequence._parent = self
433 self._sequences.append(valueSequence)
435 if parent is not None: 435 ↛ exitline 435 didn't return from function '__init__' because the condition on line 435 was always true
436 parent._bins.append(self)
438 @classmethod
439 def Parse(cls, element: _Element, *, parent: Nullable[Coverpoint] = None) -> Self:
440 """
441 Parse a coverpoint bin, its ranges and sequences from its ``<coverpointBin>`` element.
443 :param element: The ``<coverpointBin>`` element.
444 :param parent: Optional, the coverpoint the bin belongs to. Default: ``None``.
445 :returns: The coverpoint bin.
446 :raises CodeCoverageError: If a user-defined attribute's value isn't of the type the attribute states.
447 """
448 return cls(
449 element.attrib["type"],
450 [ValueRange.Parse(rangeElement) for rangeElement in element.iterfind("{*}range")],
451 [ValueSequence.Parse(sequenceElement) for sequenceElement in element.iterfind("{*}sequence")],
452 element.attrib.get("alias"),
453 element.attrib.get("name"),
454 element.attrib.get("key"),
455 cls._ParseUserAttributes(element),
456 parent=parent
457 )
459 @readonly
460 def Parent(self) -> Nullable[Coverpoint]:
461 """
462 Read-only property to access the coverpoint the bin belongs to (:attr:`_parent`).
464 :returns: The coverpoint; ``None``, if the bin belongs to none.
465 """
466 return self._parent
468 @readonly
469 def Ranges(self) -> list[ValueRange]:
470 """
471 Read-only property to access the ranges of values the bin counts (:attr:`_ranges`).
473 :returns: The ranges, in the order the report lists them; empty for a bin of sequences.
474 """
475 return self._ranges
477 @readonly
478 def Sequences(self) -> list[ValueSequence]:
479 """
480 Read-only property to access the sequences of values the bin counts (:attr:`_sequences`).
482 :returns: The sequences, in the order the report lists them; empty for a bin of ranges.
483 """
484 return self._sequences
487@export
488class Coverpoint(Base):
489 """
490 A ``<coverpoint>`` of a covergroup instance: its expression, options and bins.
491 """
493 _parent: Nullable[CovergroupInstance] #: The covergroup instance the coverpoint belongs to.
494 _name: str #: Name of the coverpoint.
495 _key: str #: UCIS key of the coverpoint.
496 _options: CoverpointOptions #: The options of the coverpoint.
497 _alias: Nullable[str] #: An alias of the coverpoint's name.
498 _expression: Nullable[str] #: The expression the coverpoint samples.
499 _bins: list[CoverpointBin] #: The bins.
501 def __init__(
502 self,
503 name: str,
504 key: str,
505 options: CoverpointOptions,
506 alias: Nullable[str] = None,
507 expression: Nullable[str] = None,
508 userAttributes: Nullable[Iterable[UserAttribute]] = None,
509 *,
510 parent: Nullable[CovergroupInstance] = None
511 ) -> None:
512 """
513 Initialize the coverpoint, and append it to the coverpoints of its covergroup instance.
515 Its bins are added by creating them with this coverpoint as their parent.
517 :param name: Name of the coverpoint, e.g. ``cvpt_a``.
518 :param key: UCIS key of the coverpoint.
519 :param options: The options of the coverpoint.
520 :param alias: Optional, an alias of the coverpoint's name. Default: ``None``.
521 :param expression: Optional, the expression the coverpoint samples, e.g. ``a``. Default: ``None``.
522 :param userAttributes: Optional, the user-defined attributes. Default: ``None``.
523 :param parent: Optional, the covergroup instance the coverpoint belongs to. Default: ``None``.
524 :raises TypeError: If parameter ``userAttributes`` isn't iterable.
525 :raises TypeError: If parameter ``userAttributes`` contains an element not of type
526 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Elements.UserAttribute`.
527 :raises ValueError: If parameter ``name`` or ``key`` is ``None``.
528 :raises TypeError: If parameter ``name`` or ``key`` isn't of type :class:`str`.
529 :raises ValueError: If parameter ``options`` is ``None``.
530 :raises TypeError: If parameter ``options`` isn't of type
531 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.CoverOptions.CoverpointOptions`.
532 :raises TypeError: If parameter ``alias`` or ``expression`` isn't of type :class:`str`.
533 :raises TypeError: If parameter ``parent`` isn't of type
534 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Covergroups.CovergroupInstance`.
535 """
536 from pyEDAA.Reports.CodeCoverage.UCIS.Covergroups import CovergroupInstance
538 super().__init__(userAttributes)
540 for parameterName, value in (
541 ("name", name),
542 ("key", key)
543 ):
544 if value is None: 544 ↛ 545line 544 didn't jump to line 545 because the condition on line 544 was never true
545 raise ValueError(f"Parameter '{parameterName}' is None.")
546 elif not isinstance(value, str): 546 ↛ 547line 546 didn't jump to line 547 because the condition on line 546 was never true
547 ex = TypeError(f"Parameter '{parameterName}' is not of type 'str'.")
548 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
549 raise ex
551 if options is None: 551 ↛ 552line 551 didn't jump to line 552 because the condition on line 551 was never true
552 raise ValueError("Parameter 'options' is None.")
553 elif not isinstance(options, CoverpointOptions): 553 ↛ 554line 553 didn't jump to line 554 because the condition on line 553 was never true
554 ex = TypeError("Parameter 'options' is not of type 'CoverpointOptions'.")
555 ex.add_note(f"Got type '{getFullyQualifiedName(options)}'.")
556 raise ex
558 for parameterName, value in (
559 ("alias", alias),
560 ("expression", expression)
561 ):
562 if value is not None and not isinstance(value, str): 562 ↛ 563line 562 didn't jump to line 563 because the condition on line 562 was never true
563 ex = TypeError(f"Parameter '{parameterName}' is not of type 'str'.")
564 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
565 raise ex
567 if parent is not None and not isinstance(parent, CovergroupInstance): 567 ↛ 568line 567 didn't jump to line 568 because the condition on line 567 was never true
568 ex = TypeError("Parameter 'parent' is not of type 'CovergroupInstance'.")
569 ex.add_note(f"Got type '{getFullyQualifiedName(parent)}'.")
570 raise ex
572 self._parent = parent
573 self._name = name
574 self._key = key
575 self._options = options
576 self._alias = alias
577 self._expression = expression
578 self._bins = []
580 if parent is not None: 580 ↛ exitline 580 didn't return from function '__init__' because the condition on line 580 was always true
581 parent._coverpoints.append(self)
583 @classmethod
584 def Parse(cls, element: _Element, *, parent: Nullable[CovergroupInstance] = None) -> Self:
585 """
586 Parse a coverpoint, its options and bins from its ``<coverpoint>`` element.
588 :param element: The ``<coverpoint>`` element.
589 :param parent: Optional, the covergroup instance the coverpoint belongs to. Default: ``None``.
590 :returns: The coverpoint.
591 :raises CodeCoverageError: If a user-defined attribute's value isn't of the type the attribute states.
592 """
593 coverpoint = cls(
594 element.attrib["name"],
595 element.attrib["key"],
596 CoverpointOptions.Parse(element.find("{*}options")),
597 element.attrib.get("alias"),
598 element.attrib.get("exprString"),
599 cls._ParseUserAttributes(element),
600 parent=parent
601 )
603 for binElement in element.iterfind("{*}coverpointBin"):
604 CoverpointBin.Parse(binElement, parent=coverpoint)
606 return coverpoint
608 @readonly
609 def Parent(self) -> Nullable[CovergroupInstance]:
610 """
611 Read-only property to access the covergroup instance the coverpoint belongs to (:attr:`_parent`).
613 :returns: The covergroup instance; ``None``, if the coverpoint belongs to none.
614 """
615 return self._parent
617 @readonly
618 def Name(self) -> str:
619 """
620 Read-only property to access the name of the coverpoint (:attr:`_name`).
622 :returns: The name, as declared.
623 """
624 return self._name
626 @readonly
627 def Key(self) -> str:
628 """
629 Read-only property to access the UCIS key of the coverpoint (:attr:`_key`).
631 :returns: The key, as stated.
632 """
633 return self._key
635 @readonly
636 def Options(self) -> CoverpointOptions:
637 """
638 Read-only property to access the options of the coverpoint (:attr:`_options`).
640 :returns: The options.
641 """
642 return self._options
644 @readonly
645 def Alias(self) -> Nullable[str]:
646 """
647 Read-only property to access the alias of the coverpoint's name (:attr:`_alias`).
649 :returns: The alias; ``None``, if the report states none.
650 """
651 return self._alias
653 @readonly
654 def Expression(self) -> Nullable[str]:
655 """
656 Read-only property to access the expression the coverpoint samples (:attr:`_expression`).
658 :returns: The expression, e.g. ``a``; ``None``, if the report states none.
659 """
660 return self._expression
662 @readonly
663 def Bins(self) -> list[CoverpointBin]:
664 """
665 Read-only property to access the bins (:attr:`_bins`).
667 :returns: The bins, in the order the report lists them.
668 """
669 return self._bins