Coverage for pyEDAA/Reports/CodeCoverage/UCIS/Coverpoints.py: 73%
249 statements
« prev ^ index » next coverage.py v7.17.3, created at 2026-11-14 02:26 +0000
« prev ^ index » next coverage.py v7.17.3, created at 2026-11-14 02:26 +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 ValueError: If parameter ``binType`` is ``None``.
84 :raises TypeError: If parameter ``binType`` isn't of type :class:`str`.
85 :raises TypeError: If parameter ``alias`` isn't of type :class:`str`.
86 :raises TypeError: If parameter ``name`` isn't of type :class:`str`.
87 :raises TypeError: If parameter ``key`` isn't of type :class:`str`.
88 :raises TypeError: If parameter ``userAttributes`` isn't iterable.
89 :raises TypeError: If parameter ``userAttributes`` contains an element not of type
90 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Elements.UserAttribute`.
91 """
92 super().__init__(userAttributes)
94 if binType is None: 94 ↛ 95line 94 didn't jump to line 95 because the condition on line 94 was never true
95 raise ValueError("Parameter 'binType' is None.")
96 elif not isinstance(binType, str): 96 ↛ 97line 96 didn't jump to line 97 because the condition on line 96 was never true
97 ex = TypeError("Parameter 'binType' is not of type 'str'.")
98 ex.add_note(f"Got type '{getFullyQualifiedName(binType)}'.")
99 raise ex
101 for parameterName, value in (
102 ("alias", alias),
103 ("name", name),
104 ("key", key)
105 ):
106 if value is not None and not isinstance(value, str): 106 ↛ 107line 106 didn't jump to line 107 because the condition on line 106 was never true
107 ex = TypeError(f"Parameter '{parameterName}' is not of type 'str'.")
108 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
109 raise ex
111 self._binType = binType
112 self._alias = alias
113 self._name = name
114 self._key = key
116 @readonly
117 def BinType(self) -> str:
118 """
119 Read-only property to access the kind of the bin (:attr:`_binType`).
121 :returns: The kind, as stated, e.g. ``default``, ``ignore`` or ``illegal``.
122 """
123 return self._binType
125 @readonly
126 def Alias(self) -> Nullable[str]:
127 """
128 Read-only property to access the alias of the bin's name (:attr:`_alias`).
130 :returns: The alias; ``None``, if the report states none.
131 """
132 return self._alias
134 @readonly
135 def Name(self) -> Nullable[str]:
136 """
137 Read-only property to access the name of the bin (:attr:`_name`).
139 :returns: The name; ``None``, if the report states none.
140 """
141 return self._name
143 @readonly
144 def Key(self) -> Nullable[str]:
145 """
146 Read-only property to access the UCIS key of the bin (:attr:`_key`).
148 :returns: The key; ``None``, if the report states none.
149 """
150 return self._key
153@export
154class ValueRange(metaclass=ExtendedType, slots=True):
155 """
156 A ``<range>`` of a coverpoint's bin: a range of values, and how often the coverpoint's expression had one of them.
157 """
159 _parent: Nullable[CoverpointBin] #: The coverpoint bin the range belongs to.
160 _from: int #: The range's lowest value.
161 _to: int #: The range's highest value.
162 _contents: BinContents #: How often the expression had a value of the range.
164 def __init__(self, fromValue: int, toValue: int, contents: BinContents) -> None:
165 """
166 Initialize the range of values.
168 The coverpoint bin owning the range takes it as a parameter and becomes its parent.
170 :param fromValue: The range's lowest value.
171 :param toValue: The range's highest value; the lowest one again for a single value.
172 :param contents: How often the expression had a value of the range.
173 :raises ValueError: If parameter ``fromValue`` is ``None``.
174 :raises TypeError: If parameter ``fromValue`` isn't of type :class:`int`.
175 :raises ValueError: If parameter ``toValue`` is ``None``.
176 :raises TypeError: If parameter ``toValue`` isn't of type :class:`int`.
177 :raises ValueError: If parameter ``contents`` is ``None``.
178 :raises TypeError: If parameter ``contents`` isn't of type
179 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Bins.BinContents`.
180 """
181 for parameterName, value in (
182 ("fromValue", fromValue),
183 ("toValue", toValue)
184 ):
185 if value is None: 185 ↛ 186line 185 didn't jump to line 186 because the condition on line 185 was never true
186 raise ValueError(f"Parameter '{parameterName}' is None.")
187 elif not isinstance(value, int) or isinstance(value, bool): 187 ↛ 188line 187 didn't jump to line 188 because the condition on line 187 was never true
188 ex = TypeError(f"Parameter '{parameterName}' is not of type 'int'.")
189 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
190 raise ex
192 if contents is None: 192 ↛ 193line 192 didn't jump to line 193 because the condition on line 192 was never true
193 raise ValueError("Parameter 'contents' is None.")
194 elif not isinstance(contents, BinContents): 194 ↛ 195line 194 didn't jump to line 195 because the condition on line 194 was never true
195 ex = TypeError("Parameter 'contents' is not of type 'BinContents'.")
196 ex.add_note(f"Got type '{getFullyQualifiedName(contents)}'.")
197 raise ex
199 self._parent = None
200 self._from = fromValue
201 self._to = toValue
202 self._contents = contents
204 @classmethod
205 def Parse(cls, element: _Element) -> Self:
206 """
207 Parse a range of values from its ``<range>`` element.
209 :param element: The ``<range>`` element.
210 :returns: The range.
211 """
212 return cls(
213 int(element.attrib["from"]),
214 int(element.attrib["to"]),
215 BinContents.Parse(element.find("{*}contents"))
216 )
218 @readonly
219 def Parent(self) -> Nullable[CoverpointBin]:
220 """
221 Read-only property to access the coverpoint bin the range belongs to (:attr:`_parent`).
223 :returns: The coverpoint bin; ``None``, if the range belongs to none.
224 """
225 return self._parent
227 @readonly
228 def From(self) -> int:
229 """
230 Read-only property to access the range's lowest value (:attr:`_from`).
232 :returns: The value.
233 """
234 return self._from
236 @readonly
237 def To(self) -> int:
238 """
239 Read-only property to access the range's highest value (:attr:`_to`).
241 :returns: The value.
242 """
243 return self._to
245 @readonly
246 def Contents(self) -> BinContents:
247 """
248 Read-only property to access how often the expression had a value of the range (:attr:`_contents`).
250 :returns: The contents: the count and the tests.
251 """
252 return self._contents
255@export
256class ValueSequence(metaclass=ExtendedType, slots=True):
257 """
258 A ``<sequence>`` of a coverpoint's bin: a sequence of values, and how often the coverpoint's expression had them one
259 after the other.
260 """
262 _parent: Nullable[CoverpointBin] #: The coverpoint bin the sequence belongs to.
263 _values: list[int] #: The values, from the first one.
264 _contents: BinContents #: How often the expression had the values one after the other.
266 def __init__(self, values: Iterable[int], contents: BinContents) -> None:
267 """
268 Initialize the sequence of values.
270 The coverpoint bin owning the sequence takes it as a parameter and becomes its parent.
272 :param values: The values, from the first one.
273 :param contents: How often the expression had the values one after the other.
274 :raises ValueError: If parameter ``values`` is ``None``.
275 :raises TypeError: If parameter ``values`` isn't iterable.
276 :raises TypeError: If parameter ``values`` contains an element not of type :class:`int`.
277 :raises ValueError: If parameter ``values`` is empty.
278 :raises ValueError: If parameter ``contents`` is ``None``.
279 :raises TypeError: If parameter ``contents`` isn't of type
280 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Bins.BinContents`.
281 """
282 if contents is None: 282 ↛ 283line 282 didn't jump to line 283 because the condition on line 282 was never true
283 raise ValueError("Parameter 'contents' is None.")
284 elif not isinstance(contents, BinContents): 284 ↛ 285line 284 didn't jump to line 285 because the condition on line 284 was never true
285 ex = TypeError("Parameter 'contents' is not of type 'BinContents'.")
286 ex.add_note(f"Got type '{getFullyQualifiedName(contents)}'.")
287 raise ex
289 self._parent = None
290 self._values = valueList = []
291 self._contents = contents
293 if values is None: 293 ↛ 294line 293 didn't jump to line 294 because the condition on line 293 was never true
294 raise ValueError("Parameter 'values' is None.")
295 elif not isinstance(values, Iterable): 295 ↛ 296line 295 didn't jump to line 296 because the condition on line 295 was never true
296 ex = TypeError("Parameter 'values' is not iterable.")
297 ex.add_note(f"Got type '{getFullyQualifiedName(values)}'.")
298 raise ex
300 for value in values:
301 if not isinstance(value, int) or isinstance(value, bool): 301 ↛ 302line 301 didn't jump to line 302 because the condition on line 301 was never true
302 ex = TypeError("Parameter 'values' contains an element not of type 'int'.")
303 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
304 raise ex
306 valueList.append(value)
308 if len(self._values) == 0:
309 raise ValueError("Parameter 'values' is empty.")
311 @classmethod
312 def Parse(cls, element: _Element) -> Self:
313 """
314 Parse a sequence of values from its ``<sequence>`` element.
316 :param element: The ``<sequence>`` element.
317 :returns: The sequence.
318 """
319 return cls(
320 [int(valueElement.text) for valueElement in element.iterfind("{*}seqValue")],
321 BinContents.Parse(element.find("{*}contents"))
322 )
324 @readonly
325 def Parent(self) -> Nullable[CoverpointBin]:
326 """
327 Read-only property to access the coverpoint bin the sequence belongs to (:attr:`_parent`).
329 :returns: The coverpoint bin; ``None``, if the sequence belongs to none.
330 """
331 return self._parent
333 @readonly
334 def Values(self) -> list[int]:
335 """
336 Read-only property to access the values (:attr:`_values`).
338 :returns: The values, from the first one.
339 """
340 return self._values
342 @readonly
343 def Contents(self) -> BinContents:
344 """
345 Read-only property to access how often the expression had the values one after the other (:attr:`_contents`).
347 :returns: The contents: the count and the tests.
348 """
349 return self._contents
352@export
353class CoverpointBin(BinBase):
354 """
355 A ``<coverpointBin>`` of a coverpoint: its kind, and the ranges or sequences of values it counts.
356 """
358 _parent: Nullable[Coverpoint] #: The coverpoint the bin belongs to.
359 _ranges: list[ValueRange] #: The ranges of values the bin counts.
360 _sequences: list[ValueSequence] #: The sequences of values the bin counts.
362 def __init__(
363 self,
364 binType: str,
365 ranges: Nullable[Iterable[ValueRange]] = None,
366 sequences: Nullable[Iterable[ValueSequence]] = None,
367 alias: Nullable[str] = None,
368 name: Nullable[str] = None,
369 key: Nullable[str] = None,
370 userAttributes: Nullable[Iterable[UserAttribute]] = None,
371 *,
372 parent: Nullable[Coverpoint] = None
373 ) -> None:
374 """
375 Initialize the coverpoint bin, become its ranges' and sequences' parent, and append it to the bins of its
376 coverpoint.
378 :param binType: Kind of the bin, e.g. ``default``, ``ignore`` or ``illegal``.
379 :param ranges: Optional, the ranges of values the bin counts. Default: ``None``.
380 :param sequences: Optional, the sequences of values the bin counts. Default: ``None``.
381 :param alias: Optional, an alias of the bin's name. Default: ``None``.
382 :param name: Optional, name of the bin, as pyucis writes it. Default: ``None``.
383 :param key: Optional, UCIS key of the bin, as pyucis writes it. Default: ``None``.
384 :param userAttributes: Optional, the user-defined attributes. Default: ``None``.
385 :param parent: Optional, the coverpoint the bin belongs to. Default: ``None``.
386 :raises ValueError: If parameter ``binType`` is ``None``.
387 :raises TypeError: If parameter ``binType`` isn't of type :class:`str`.
388 :raises TypeError: If parameter ``ranges`` isn't iterable.
389 :raises TypeError: If parameter ``ranges`` contains an element not of type :class:`ValueRange`.
390 :raises TypeError: If parameter ``sequences`` isn't iterable.
391 :raises TypeError: If parameter ``sequences`` contains an element not of type :class:`ValueSequence`.
392 :raises TypeError: If parameter ``alias`` isn't of type :class:`str`.
393 :raises TypeError: If parameter ``name`` isn't of type :class:`str`.
394 :raises TypeError: If parameter ``key`` isn't of type :class:`str`.
395 :raises TypeError: If parameter ``userAttributes`` isn't iterable.
396 :raises TypeError: If parameter ``userAttributes`` contains an element not of type
397 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Elements.UserAttribute`.
398 :raises TypeError: If parameter ``parent`` isn't of type :class:`Coverpoint`.
399 """
400 super().__init__(binType, alias, name, key, userAttributes)
402 if parent is not None and not isinstance(parent, Coverpoint): 402 ↛ 403line 402 didn't jump to line 403 because the condition on line 402 was never true
403 ex = TypeError("Parameter 'parent' is not of type 'Coverpoint'.")
404 ex.add_note(f"Got type '{getFullyQualifiedName(parent)}'.")
405 raise ex
407 self._parent = parent
408 self._ranges = rangeList = []
409 self._sequences = sequenceList = []
411 if ranges is not None: 411 ↛ 426line 411 didn't jump to line 426 because the condition on line 411 was always true
412 if not isinstance(ranges, Iterable): 412 ↛ 413line 412 didn't jump to line 413 because the condition on line 412 was never true
413 ex = TypeError("Parameter 'ranges' is not iterable.")
414 ex.add_note(f"Got type '{getFullyQualifiedName(ranges)}'.")
415 raise ex
417 for valueRange in ranges:
418 if not isinstance(valueRange, ValueRange): 418 ↛ 419line 418 didn't jump to line 419 because the condition on line 418 was never true
419 ex = TypeError("Parameter 'ranges' contains an element not of type 'ValueRange'.")
420 ex.add_note(f"Got type '{getFullyQualifiedName(valueRange)}'.")
421 raise ex
423 valueRange._parent = self
424 rangeList.append(valueRange)
426 if sequences is not None:
427 if not isinstance(sequences, Iterable): 427 ↛ 428line 427 didn't jump to line 428 because the condition on line 427 was never true
428 ex = TypeError("Parameter 'sequences' is not iterable.")
429 ex.add_note(f"Got type '{getFullyQualifiedName(sequences)}'.")
430 raise ex
432 for valueSequence in sequences:
433 if not isinstance(valueSequence, ValueSequence): 433 ↛ 434line 433 didn't jump to line 434 because the condition on line 433 was never true
434 ex = TypeError("Parameter 'sequences' contains an element not of type 'ValueSequence'.")
435 ex.add_note(f"Got type '{getFullyQualifiedName(valueSequence)}'.")
436 raise ex
438 valueSequence._parent = self
439 sequenceList.append(valueSequence)
441 if parent is not None: 441 ↛ exitline 441 didn't return from function '__init__' because the condition on line 441 was always true
442 parent._bins.append(self)
444 @classmethod
445 def Parse(cls, element: _Element, *, parent: Nullable[Coverpoint] = None) -> Self:
446 """
447 Parse a coverpoint bin, its ranges and sequences from its ``<coverpointBin>`` element.
449 :param element: The ``<coverpointBin>`` element.
450 :param parent: Optional, the coverpoint the bin belongs to. Default: ``None``.
451 :returns: The coverpoint bin.
452 :raises CodeCoverageError: If a user-defined attribute's value isn't of the type the attribute states.
453 """
454 return cls(
455 element.attrib["type"],
456 [ValueRange.Parse(rangeElement) for rangeElement in element.iterfind("{*}range")],
457 [ValueSequence.Parse(sequenceElement) for sequenceElement in element.iterfind("{*}sequence")],
458 element.attrib.get("alias"),
459 element.attrib.get("name"),
460 element.attrib.get("key"),
461 cls._ParseUserAttributes(element),
462 parent=parent
463 )
465 @readonly
466 def Parent(self) -> Nullable[Coverpoint]:
467 """
468 Read-only property to access the coverpoint the bin belongs to (:attr:`_parent`).
470 :returns: The coverpoint; ``None``, if the bin belongs to none.
471 """
472 return self._parent
474 @readonly
475 def Ranges(self) -> list[ValueRange]:
476 """
477 Read-only property to access the ranges of values the bin counts (:attr:`_ranges`).
479 :returns: The ranges, in the order the report lists them; empty for a bin of sequences.
480 """
481 return self._ranges
483 @readonly
484 def Sequences(self) -> list[ValueSequence]:
485 """
486 Read-only property to access the sequences of values the bin counts (:attr:`_sequences`).
488 :returns: The sequences, in the order the report lists them; empty for a bin of ranges.
489 """
490 return self._sequences
493@export
494class Coverpoint(Base):
495 """
496 A ``<coverpoint>`` of a covergroup instance: its expression, options and bins.
497 """
499 _parent: Nullable[CovergroupInstance] #: The covergroup instance the coverpoint belongs to.
500 _name: str #: Name of the coverpoint.
501 _key: str #: UCIS key of the coverpoint.
502 _options: CoverpointOptions #: The options of the coverpoint.
503 _alias: Nullable[str] #: An alias of the coverpoint's name.
504 _expression: Nullable[str] #: The expression the coverpoint samples.
505 _bins: list[CoverpointBin] #: The bins.
507 def __init__(
508 self,
509 name: str,
510 key: str,
511 options: CoverpointOptions,
512 alias: Nullable[str] = None,
513 expression: Nullable[str] = None,
514 userAttributes: Nullable[Iterable[UserAttribute]] = None,
515 *,
516 parent: Nullable[CovergroupInstance] = None
517 ) -> None:
518 """
519 Initialize the coverpoint, and append it to the coverpoints of its covergroup instance.
521 Its bins are added by creating them with this coverpoint as their parent.
523 :param name: Name of the coverpoint, e.g. ``cvpt_a``.
524 :param key: UCIS key of the coverpoint.
525 :param options: The options of the coverpoint.
526 :param alias: Optional, an alias of the coverpoint's name. Default: ``None``.
527 :param expression: Optional, the expression the coverpoint samples, e.g. ``a``. Default: ``None``.
528 :param userAttributes: Optional, the user-defined attributes. Default: ``None``.
529 :param parent: Optional, the covergroup instance the coverpoint belongs to. Default: ``None``.
530 :raises ValueError: If parameter ``name`` is ``None``.
531 :raises TypeError: If parameter ``name`` isn't of type :class:`str`.
532 :raises ValueError: If parameter ``key`` is ``None``.
533 :raises TypeError: If parameter ``key`` isn't of type :class:`str`.
534 :raises ValueError: If parameter ``options`` is ``None``.
535 :raises TypeError: If parameter ``options`` isn't of type
536 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.CoverOptions.CoverpointOptions`.
537 :raises TypeError: If parameter ``alias`` isn't of type :class:`str`.
538 :raises TypeError: If parameter ``expression`` isn't of type :class:`str`.
539 :raises TypeError: If parameter ``userAttributes`` isn't iterable.
540 :raises TypeError: If parameter ``userAttributes`` contains an element not of type
541 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Elements.UserAttribute`.
542 :raises TypeError: If parameter ``parent`` isn't of type
543 :class:`~pyEDAA.Reports.CodeCoverage.UCIS.Covergroups.CovergroupInstance`.
544 """
545 from pyEDAA.Reports.CodeCoverage.UCIS.Covergroups import CovergroupInstance
547 super().__init__(userAttributes)
549 for parameterName, value in (
550 ("name", name),
551 ("key", key)
552 ):
553 if value is None: 553 ↛ 554line 553 didn't jump to line 554 because the condition on line 553 was never true
554 raise ValueError(f"Parameter '{parameterName}' is None.")
555 elif not isinstance(value, str): 555 ↛ 556line 555 didn't jump to line 556 because the condition on line 555 was never true
556 ex = TypeError(f"Parameter '{parameterName}' is not of type 'str'.")
557 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
558 raise ex
560 if options is None: 560 ↛ 561line 560 didn't jump to line 561 because the condition on line 560 was never true
561 raise ValueError("Parameter 'options' is None.")
562 elif not isinstance(options, CoverpointOptions): 562 ↛ 563line 562 didn't jump to line 563 because the condition on line 562 was never true
563 ex = TypeError("Parameter 'options' is not of type 'CoverpointOptions'.")
564 ex.add_note(f"Got type '{getFullyQualifiedName(options)}'.")
565 raise ex
567 for parameterName, value in (
568 ("alias", alias),
569 ("expression", expression)
570 ):
571 if value is not None and not isinstance(value, str): 571 ↛ 572line 571 didn't jump to line 572 because the condition on line 571 was never true
572 ex = TypeError(f"Parameter '{parameterName}' is not of type 'str'.")
573 ex.add_note(f"Got type '{getFullyQualifiedName(value)}'.")
574 raise ex
576 if parent is not None and not isinstance(parent, CovergroupInstance): 576 ↛ 577line 576 didn't jump to line 577 because the condition on line 576 was never true
577 ex = TypeError("Parameter 'parent' is not of type 'CovergroupInstance'.")
578 ex.add_note(f"Got type '{getFullyQualifiedName(parent)}'.")
579 raise ex
581 self._parent = parent
582 self._name = name
583 self._key = key
584 self._options = options
585 self._alias = alias
586 self._expression = expression
587 self._bins = []
589 if parent is not None: 589 ↛ exitline 589 didn't return from function '__init__' because the condition on line 589 was always true
590 parent._coverpoints.append(self)
592 @classmethod
593 def Parse(cls, element: _Element, *, parent: Nullable[CovergroupInstance] = None) -> Self:
594 """
595 Parse a coverpoint, its options and bins from its ``<coverpoint>`` element.
597 :param element: The ``<coverpoint>`` element.
598 :param parent: Optional, the covergroup instance the coverpoint belongs to. Default: ``None``.
599 :returns: The coverpoint.
600 :raises CodeCoverageError: If a user-defined attribute's value isn't of the type the attribute states.
601 """
602 coverpoint = cls(
603 element.attrib["name"],
604 element.attrib["key"],
605 CoverpointOptions.Parse(element.find("{*}options")),
606 element.attrib.get("alias"),
607 element.attrib.get("exprString"),
608 cls._ParseUserAttributes(element),
609 parent=parent
610 )
612 for binElement in element.iterfind("{*}coverpointBin"):
613 CoverpointBin.Parse(binElement, parent=coverpoint)
615 return coverpoint
617 @readonly
618 def Parent(self) -> Nullable[CovergroupInstance]:
619 """
620 Read-only property to access the covergroup instance the coverpoint belongs to (:attr:`_parent`).
622 :returns: The covergroup instance; ``None``, if the coverpoint belongs to none.
623 """
624 return self._parent
626 @readonly
627 def Name(self) -> str:
628 """
629 Read-only property to access the name of the coverpoint (:attr:`_name`).
631 :returns: The name, as declared.
632 """
633 return self._name
635 @readonly
636 def Key(self) -> str:
637 """
638 Read-only property to access the UCIS key of the coverpoint (:attr:`_key`).
640 :returns: The key, as stated.
641 """
642 return self._key
644 @readonly
645 def Options(self) -> CoverpointOptions:
646 """
647 Read-only property to access the options of the coverpoint (:attr:`_options`).
649 :returns: The options.
650 """
651 return self._options
653 @readonly
654 def Alias(self) -> Nullable[str]:
655 """
656 Read-only property to access the alias of the coverpoint's name (:attr:`_alias`).
658 :returns: The alias; ``None``, if the report states none.
659 """
660 return self._alias
662 @readonly
663 def Expression(self) -> Nullable[str]:
664 """
665 Read-only property to access the expression the coverpoint samples (:attr:`_expression`).
667 :returns: The expression, e.g. ``a``; ``None``, if the report states none.
668 """
669 return self._expression
671 @readonly
672 def Bins(self) -> list[CoverpointBin]:
673 """
674 Read-only property to access the bins (:attr:`_bins`).
676 :returns: The bins, in the order the report lists them.
677 """
678 return self._bins