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

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 

36 

37from typing import TYPE_CHECKING, Iterable, Optional as Nullable, Self 

38 

39from lxml.etree import _Element 

40from pyTooling.Common import getFullyQualifiedName 

41from pyTooling.Decorators import export, readonly 

42from pyTooling.MetaClasses import ExtendedType, abstractclass 

43 

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 

47 

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 

50 

51 

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 """ 

59 

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. 

64 

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. 

75 

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) 

93 

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 

100 

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 

110 

111 self._binType = binType 

112 self._alias = alias 

113 self._name = name 

114 self._key = key 

115 

116 @readonly 

117 def BinType(self) -> str: 

118 """ 

119 Read-only property to access the kind of the bin (:attr:`_binType`). 

120 

121 :returns: The kind, as stated, e.g. ``default``, ``ignore`` or ``illegal``. 

122 """ 

123 return self._binType 

124 

125 @readonly 

126 def Alias(self) -> Nullable[str]: 

127 """ 

128 Read-only property to access the alias of the bin's name (:attr:`_alias`). 

129 

130 :returns: The alias; ``None``, if the report states none. 

131 """ 

132 return self._alias 

133 

134 @readonly 

135 def Name(self) -> Nullable[str]: 

136 """ 

137 Read-only property to access the name of the bin (:attr:`_name`). 

138 

139 :returns: The name; ``None``, if the report states none. 

140 """ 

141 return self._name 

142 

143 @readonly 

144 def Key(self) -> Nullable[str]: 

145 """ 

146 Read-only property to access the UCIS key of the bin (:attr:`_key`). 

147 

148 :returns: The key; ``None``, if the report states none. 

149 """ 

150 return self._key 

151 

152 

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 """ 

158 

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. 

163 

164 def __init__(self, fromValue: int, toValue: int, contents: BinContents) -> None: 

165 """ 

166 Initialize the range of values. 

167 

168 The coverpoint bin owning the range takes it as a parameter and becomes its parent. 

169 

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 

191 

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 

198 

199 self._parent = None 

200 self._from = fromValue 

201 self._to = toValue 

202 self._contents = contents 

203 

204 @classmethod 

205 def Parse(cls, element: _Element) -> Self: 

206 """ 

207 Parse a range of values from its ``<range>`` element. 

208 

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 ) 

217 

218 @readonly 

219 def Parent(self) -> Nullable[CoverpointBin]: 

220 """ 

221 Read-only property to access the coverpoint bin the range belongs to (:attr:`_parent`). 

222 

223 :returns: The coverpoint bin; ``None``, if the range belongs to none. 

224 """ 

225 return self._parent 

226 

227 @readonly 

228 def From(self) -> int: 

229 """ 

230 Read-only property to access the range's lowest value (:attr:`_from`). 

231 

232 :returns: The value. 

233 """ 

234 return self._from 

235 

236 @readonly 

237 def To(self) -> int: 

238 """ 

239 Read-only property to access the range's highest value (:attr:`_to`). 

240 

241 :returns: The value. 

242 """ 

243 return self._to 

244 

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`). 

249 

250 :returns: The contents: the count and the tests. 

251 """ 

252 return self._contents 

253 

254 

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 """ 

261 

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. 

265 

266 def __init__(self, values: Iterable[int], contents: BinContents) -> None: 

267 """ 

268 Initialize the sequence of values. 

269 

270 The coverpoint bin owning the sequence takes it as a parameter and becomes its parent. 

271 

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 

288 

289 self._parent = None 

290 self._values = valueList = [] 

291 self._contents = contents 

292 

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 

299 

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 

305 

306 valueList.append(value) 

307 

308 if len(self._values) == 0: 

309 raise ValueError("Parameter 'values' is empty.") 

310 

311 @classmethod 

312 def Parse(cls, element: _Element) -> Self: 

313 """ 

314 Parse a sequence of values from its ``<sequence>`` element. 

315 

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 ) 

323 

324 @readonly 

325 def Parent(self) -> Nullable[CoverpointBin]: 

326 """ 

327 Read-only property to access the coverpoint bin the sequence belongs to (:attr:`_parent`). 

328 

329 :returns: The coverpoint bin; ``None``, if the sequence belongs to none. 

330 """ 

331 return self._parent 

332 

333 @readonly 

334 def Values(self) -> list[int]: 

335 """ 

336 Read-only property to access the values (:attr:`_values`). 

337 

338 :returns: The values, from the first one. 

339 """ 

340 return self._values 

341 

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`). 

346 

347 :returns: The contents: the count and the tests. 

348 """ 

349 return self._contents 

350 

351 

352@export 

353class CoverpointBin(BinBase): 

354 """ 

355 A ``<coverpointBin>`` of a coverpoint: its kind, and the ranges or sequences of values it counts. 

356 """ 

357 

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. 

361 

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. 

377 

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) 

401 

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 

406 

407 self._parent = parent 

408 self._ranges = rangeList = [] 

409 self._sequences = sequenceList = [] 

410 

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 

416 

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 

422 

423 valueRange._parent = self 

424 rangeList.append(valueRange) 

425 

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 

431 

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 

437 

438 valueSequence._parent = self 

439 sequenceList.append(valueSequence) 

440 

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) 

443 

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. 

448 

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 ) 

464 

465 @readonly 

466 def Parent(self) -> Nullable[Coverpoint]: 

467 """ 

468 Read-only property to access the coverpoint the bin belongs to (:attr:`_parent`). 

469 

470 :returns: The coverpoint; ``None``, if the bin belongs to none. 

471 """ 

472 return self._parent 

473 

474 @readonly 

475 def Ranges(self) -> list[ValueRange]: 

476 """ 

477 Read-only property to access the ranges of values the bin counts (:attr:`_ranges`). 

478 

479 :returns: The ranges, in the order the report lists them; empty for a bin of sequences. 

480 """ 

481 return self._ranges 

482 

483 @readonly 

484 def Sequences(self) -> list[ValueSequence]: 

485 """ 

486 Read-only property to access the sequences of values the bin counts (:attr:`_sequences`). 

487 

488 :returns: The sequences, in the order the report lists them; empty for a bin of ranges. 

489 """ 

490 return self._sequences 

491 

492 

493@export 

494class Coverpoint(Base): 

495 """ 

496 A ``<coverpoint>`` of a covergroup instance: its expression, options and bins. 

497 """ 

498 

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. 

506 

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. 

520 

521 Its bins are added by creating them with this coverpoint as their parent. 

522 

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 

546 

547 super().__init__(userAttributes) 

548 

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 

559 

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 

566 

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 

575 

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 

580 

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 = [] 

588 

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) 

591 

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. 

596 

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 ) 

611 

612 for binElement in element.iterfind("{*}coverpointBin"): 

613 CoverpointBin.Parse(binElement, parent=coverpoint) 

614 

615 return coverpoint 

616 

617 @readonly 

618 def Parent(self) -> Nullable[CovergroupInstance]: 

619 """ 

620 Read-only property to access the covergroup instance the coverpoint belongs to (:attr:`_parent`). 

621 

622 :returns: The covergroup instance; ``None``, if the coverpoint belongs to none. 

623 """ 

624 return self._parent 

625 

626 @readonly 

627 def Name(self) -> str: 

628 """ 

629 Read-only property to access the name of the coverpoint (:attr:`_name`). 

630 

631 :returns: The name, as declared. 

632 """ 

633 return self._name 

634 

635 @readonly 

636 def Key(self) -> str: 

637 """ 

638 Read-only property to access the UCIS key of the coverpoint (:attr:`_key`). 

639 

640 :returns: The key, as stated. 

641 """ 

642 return self._key 

643 

644 @readonly 

645 def Options(self) -> CoverpointOptions: 

646 """ 

647 Read-only property to access the options of the coverpoint (:attr:`_options`). 

648 

649 :returns: The options. 

650 """ 

651 return self._options 

652 

653 @readonly 

654 def Alias(self) -> Nullable[str]: 

655 """ 

656 Read-only property to access the alias of the coverpoint's name (:attr:`_alias`). 

657 

658 :returns: The alias; ``None``, if the report states none. 

659 """ 

660 return self._alias 

661 

662 @readonly 

663 def Expression(self) -> Nullable[str]: 

664 """ 

665 Read-only property to access the expression the coverpoint samples (:attr:`_expression`). 

666 

667 :returns: The expression, e.g. ``a``; ``None``, if the report states none. 

668 """ 

669 return self._expression 

670 

671 @readonly 

672 def Bins(self) -> list[CoverpointBin]: 

673 """ 

674 Read-only property to access the bins (:attr:`_bins`). 

675 

676 :returns: The bins, in the order the report lists them. 

677 """ 

678 return self._bins