Coverage for pyVHDLModel/Concurrent.py: 92%

678 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-10-25 10:05 +0000

1# ==================================================================================================================== # 

2# __ ___ _ ____ _ __ __ _ _ # 

3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | # 

4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | # 

5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | # 

6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| # 

7# |_| |___/ # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany # 

15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany # 

16# # 

17# Licensed under the Apache License, Version 2.0 (the "License"); # 

18# you may not use this file except in compliance with the License. # 

19# You may obtain a copy of the License at # 

20# # 

21# http://www.apache.org/licenses/LICENSE-2.0 # 

22# # 

23# Unless required by applicable law or agreed to in writing, software # 

24# distributed under the License is distributed on an "AS IS" BASIS, # 

25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

26# See the License for the specific language governing permissions and # 

27# limitations under the License. # 

28# # 

29# SPDX-License-Identifier: Apache-2.0 # 

30# ==================================================================================================================== # 

31# 

32""" 

33This module contains parts of an abstract document language model for VHDL. 

34 

35Concurrent defines all concurrent statements used in entities, architectures, generates and block statements. 

36""" 

37from __future__ import annotations 

38 

39from typing import TYPE_CHECKING, Union, Iterable, Generator, Optional as Nullable 

40 

41from pyTooling.Common import getFullyQualifiedName, getTypeName 

42from pyTooling.Decorators import export, readonly 

43from pyTooling.MetaClasses import ExtendedType, abstractclass 

44 

45from pyVHDLModel.Base import ModelEntity, LabeledEntityMixin, DocumentedEntityMixin, Range, BaseChoice, \ 

46 BaseCase, IfBranchMixin, ElsifBranchMixin, ElseBranchMixin, AssertStatementMixin, \ 

47 BlockStatementMixin, WaveformElement, ChoicesMixin 

48from pyVHDLModel.Exception import AlreadyInDesignError, DuplicateLabelError, NotAChildError 

49from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin, SequentialDeclarationRegionMixin, \ 

50 WithGenericsMixin, WithPortsMixin 

51from pyVHDLModel.Name import Name 

52from pyVHDLModel.Symbol import ComponentInstantiationSymbol, EntityInstantiationSymbol, ArchitectureSymbol, \ 

53 ConfigurationInstantiationSymbol, Symbol, SignalSymbol 

54from pyVHDLModel.Expression import BaseExpression, QualifiedExpression, FunctionCall, TypeConversion, Literal 

55from pyVHDLModel.Association import AssociationItem, ParameterAssociationItem, GenericAssociationItem, \ 

56 PortAssociationItem, GenericMapAspectMixin, PortMapAspectMixin 

57from pyVHDLModel.Interface import PortInterfaceItemMixin, GenericInterfaceItemMixin 

58from pyVHDLModel.Common import Statement, ProcedureCallMixin, SignalAssignmentMixin, AllowBlackboxMixin, \ 

59 ConditionalWaveform, SelectedWaveform, ConditionalWaveformsMixin, WaveformMixin, \ 

60 ExpressionMixin, SelectedWaveformsMixin 

61from pyVHDLModel.Sequential import SequentialStatement, SequentialStatementsMixin 

62 

63if TYPE_CHECKING: 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true

64 from pyVHDLModel.Visitor import Visitor 

65 

66 

67ExpressionUnion = Union[ 

68 BaseExpression, 

69 QualifiedExpression, 

70 FunctionCall, 

71 TypeConversion, 

72 # ConstantOrSymbol, TODO: ObjectSymbol 

73 Literal, 

74] 

75 

76 

77@export 

78@abstractclass 

79class ConcurrentStatement(Statement): 

80 """ 

81 A base-class for all concurrent statements. 

82 

83 .. seealso:: 

84 

85 * :class:`Instantiation <pyVHDLModel.Concurrent.Instantiation>` 

86 * :class:`Process statement <pyVHDLModel.Concurrent.ProcessStatement>` 

87 * :class:`Concurrent procedure call <pyVHDLModel.Concurrent.ConcurrentProcedureCall>` 

88 * :class:`Concurrent block statement <pyVHDLModel.Concurrent.ConcurrentBlockStatement>` 

89 * :class:`Generate statement <pyVHDLModel.Concurrent.GenerateStatement>` 

90 * :class:`Concurrent signal assignment <pyVHDLModel.Concurrent.ConcurrentSignalAssignment>` 

91 * :class:`Concurrent assert statement <pyVHDLModel.Concurrent.ConcurrentAssertStatement>` 

92 """ 

93 

94 

95@export 

96class ConcurrentStatementsMixin(metaclass=ExtendedType, mixin=True, expects=("_ClashingDeclarations", )): 

97 """ 

98 A mixin-class for all language constructs supporting concurrent statements. 

99 

100 .. seealso:: 

101 

102 * :class:`Concurrent block statement <pyVHDLModel.Concurrent.ConcurrentBlockStatement>` 

103 * :class:`Generate branch <pyVHDLModel.Concurrent.GenerateBranch>` 

104 * :class:`Concurrent case <pyVHDLModel.Concurrent.ConcurrentCase>` 

105 * :class:`For generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` 

106 * :class:`Entity <pyVHDLModel.DesignUnit.Entity>` 

107 * :class:`Architecture <pyVHDLModel.DesignUnit.Architecture>` 

108 

109 .. todo:: concurrent declaration region 

110 """ 

111 

112 _statements: list[ConcurrentStatement] #: List of all concurrent statements in this construct. 

113 

114 # TODO: add another instantiation class level for entity/configuration/component inst. 

115 _instantiations: dict[str, Instantiation] #: All instantiations, indexed by label. 

116 _hierarchy: dict[str, Union[ConcurrentBlockStatement, GenerateStatement]] #: All elements creating a hierarchy level (blocks and generates), in declaration order. 

117 _areStatementsIndexed: bool #: ``True`` if :meth:`IndexStatements` filled :attr:`_instantiations` and :attr:`_hierarchy`. 

118 

119 def __init__(self, statements: Nullable[Iterable[ConcurrentStatement]] = None) -> None: 

120 """ 

121 Initializes concurrent statements. 

122 

123 :param statements: List of all concurrent statements in this construct. 

124 """ 

125 self._statements = statementList = [] 

126 

127 self._instantiations = {} 

128 self._hierarchy = {} 

129 self._areStatementsIndexed = False 

130 

131 if statements is not None: 

132 for statement in statements: 

133 statementList.append(statement) 

134 statement.Parent = self 

135 

136 @readonly 

137 def Statements(self) -> list[ConcurrentStatement]: 

138 """ 

139 Read-only property to access the statements (:attr:`_statements`). 

140 

141 :returns: List of statements. 

142 """ 

143 return self._statements 

144 

145 def _VisitStatements(self, visitor: Visitor) -> None: 

146 """ 

147 Walk the concurrent statements in statement order with a visitor. 

148 

149 :param visitor: The visitor receiving the events. 

150 """ 

151 for statement in self._statements: 

152 statement.Visit(visitor) 

153 

154 def _Labels(self) -> tuple[ConcurrentStatement, ...]: 

155 """ 

156 Return the labeled statements, whose labels are declared in this construct's declarative region. 

157 

158 A statement nested in a block or generate statement is declared in that statement's declarative region. 

159 

160 :returns: Tuple of labeled statements, in statement order. 

161 """ 

162 return tuple(statement for statement in self._statements if statement._normalizedLabel is not None) 

163 

164 def IterateInstantiations(self) -> Generator[Instantiation, None, None]: 

165 for instance in self._instantiations.values(): 

166 yield instance 

167 

168 for element in self._hierarchy.values(): 

169 yield from element.IterateInstantiations() 

170 

171 # TODO: move into _init__ 

172 def IndexStatements(self) -> None: 

173 """ 

174 Index the instantiations, blocks and generate statements of this construct, and the statements nested in them. 

175 

176 Both lookup tables (:attr:`_instantiations`, :attr:`_hierarchy`) are cleared first, so indexing again yields the 

177 same lookup tables. Afterwards, the statement mutators (e.g. :meth:`InsertStatement`) keep them up to date. 

178 """ 

179 self._instantiations.clear() 

180 self._hierarchy.clear() 

181 for statement in self._statements: 

182 self._IndexStatement(statement) 

183 

184 self._areStatementsIndexed = True 

185 

186 def _IndexStatement(self, statement: ConcurrentStatement) -> None: 

187 """ 

188 Add an instantiation, a block or a generate statement to its lookup table, and index the statements nested in it. 

189 

190 :param statement: The concurrent statement of this construct. 

191 """ 

192 if isinstance(statement, (EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation)): 

193 self._instantiations[statement._normalizedLabel] = statement 

194 elif isinstance(statement, (ForGenerateStatement, IfGenerateStatement, CaseGenerateStatement)): 

195 self._hierarchy[statement._normalizedLabel] = statement 

196 statement.IndexStatement() 

197 elif isinstance(statement, ConcurrentBlockStatement): 

198 self._hierarchy[statement._normalizedLabel] = statement 

199 statement.IndexStatements() 

200 

201 def _UnindexStatement(self, statement: ConcurrentStatement) -> None: 

202 """ 

203 Remove an instantiation, a block or a generate statement from its lookup table. 

204 

205 :param statement: The concurrent statement of this construct. 

206 """ 

207 if self._instantiations.get(statement._normalizedLabel) is statement: 

208 del self._instantiations[statement._normalizedLabel] 

209 elif self._hierarchy.get(statement._normalizedLabel) is statement: 209 ↛ exitline 209 didn't return from function '_UnindexStatement' because the condition on line 209 was always true

210 del self._hierarchy[statement._normalizedLabel] 

211 

212 def AddStatement(self, statement: ConcurrentStatement) -> None: 

213 """ 

214 Add a concurrent statement at the end of this construct. 

215 

216 The statement's parent is set to this construct. If the statements are indexed, an instantiation, a block or a 

217 generate statement is added to the lookup table matching its kind. 

218 

219 :param statement: The concurrent statement to add. 

220 :raises ValueError: If parameter 'statement' is ``None``. 

221 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`. 

222 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

223 :raises DuplicateLabelError: If the declarative region already declares the statement's label. 

224 

225 .. seealso:: 

226 

227 :meth:`InsertStatement` 

228 |rarr| Insert a concurrent statement at a position of this construct. 

229 :meth:`RemoveStatement` 

230 |rarr| Remove a concurrent statement from this construct. 

231 """ 

232 self.InsertStatement(len(self._statements), statement) 

233 

234 def InsertStatement(self, index: int, statement: ConcurrentStatement) -> None: 

235 """ 

236 Insert a concurrent statement at a position of this construct. 

237 

238 The statement's parent is set to this construct: a process, block or generate statement connects its namespace to 

239 this construct's namespace. If the statements are indexed (:meth:`IndexStatements`), an instantiation, a block or 

240 a generate statement is added to the lookup table matching its kind, and the statements nested in it are indexed. 

241 

242 A statement label is declared in the declarative region of this construct: it may neither repeat another 

243 statement's label, nor an identifier declared in the region, including the region an entity shares with its 

244 architectures. An unlabeled statement declares nothing. 

245 

246 :param index: Position, from ``0`` (first) to the number of statements (append). A negative index 

247 counts from the end, as for :meth:`list.insert`: ``-1`` inserts before the last 

248 statement. 

249 :param statement: The concurrent statement to insert. 

250 :raises ValueError: If parameter 'index' is ``None``. 

251 :raises TypeError: If parameter 'index' is not of type :class:`int`. 

252 :raises ValueError: If parameter 'index' is out of range. 

253 :raises ValueError: If parameter 'statement' is ``None``. 

254 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`. 

255 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

256 :raises DuplicateLabelError: If the declarative region already declares the statement's label. 

257 

258 .. seealso:: 

259 

260 :meth:`AddStatement` 

261 |rarr| Add a concurrent statement at the end of this construct. 

262 :meth:`InsertStatementBefore` 

263 |rarr| Insert a concurrent statement before another statement. 

264 :meth:`InsertStatementAfter` 

265 |rarr| Insert a concurrent statement after another statement. 

266 :meth:`RemoveStatement` 

267 |rarr| Remove a concurrent statement from this construct. 

268 :meth:`MoveStatement` 

269 |rarr| Move a concurrent statement to a position of this construct. 

270 """ 

271 if index is None: 

272 raise ValueError("Parameter 'index' is None.") 

273 elif not isinstance(index, int): 

274 ex = TypeError("Parameter 'index' is not of type 'int'.") 

275 ex.add_note(f"Got type '{getFullyQualifiedName(index)}'.") 

276 raise ex 

277 elif not (-len(self._statements) <= index <= len(self._statements)): 

278 ex = ValueError(f"Parameter 'index' is out of range {-len(self._statements)}..{len(self._statements)}.") 

279 ex.add_note(f"Got value '{index}'.") 

280 raise ex 

281 

282 if statement is None: 

283 raise ValueError("Parameter 'statement' is None.") 

284 elif not isinstance(statement, ConcurrentStatement): 

285 ex = TypeError("Parameter 'statement' is not of type 'ConcurrentStatement'.") 

286 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.") 

287 raise ex 

288 elif statement._parent is not None: 

289 label = "" if statement._label is None else f" '{statement._label}'" 

290 ex = AlreadyInDesignError( 

291 f"{getTypeName(statement)}{label} already has a parent.", 

292 element=statement, 

293 parent=statement._parent 

294 ) 

295 ex.add_note(f"Remove it from its {getTypeName(statement._parent)} first.") 

296 raise ex 

297 

298 if len(clashes := self._ClashingDeclarations(statement)) > 0: 

299 ex = DuplicateLabelError( 

300 f"{getTypeName(clashes[0]._parent)} already declares '{statement._label}'.", 

301 identifier=statement._label, 

302 namespace=self._namespace, 

303 element=statement, 

304 existing=clashes[0] 

305 ) 

306 ex.add_note(f"Existing declaration is of type '{getFullyQualifiedName(clashes[0])}'.") 

307 raise ex 

308 

309 self._statements.insert(index, statement) 

310 statement.Parent = self 

311 if self._areStatementsIndexed: 

312 self._IndexStatement(statement) 

313 

314 def InsertStatementBefore(self, statement: ConcurrentStatement, before: ConcurrentStatement) -> None: 

315 """ 

316 Insert a concurrent statement before another statement of this construct. 

317 

318 The statement's parent is set to this construct. If the statements are indexed, an instantiation, a block or a 

319 generate statement is added to the lookup table matching its kind. 

320 

321 :param statement: The concurrent statement to insert. 

322 :param before: The statement of this construct to insert before. 

323 :raises ValueError: If parameter 'before' is ``None``. 

324 :raises TypeError: If parameter 'before' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

325 :raises NotAChildError: If parameter 'before' is not a statement of this construct. 

326 :raises ValueError: If parameter 'statement' is ``None``. 

327 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`. 

328 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

329 :raises DuplicateLabelError: If the declarative region already declares the statement's label. 

330 

331 .. seealso:: 

332 

333 :meth:`InsertStatement` 

334 |rarr| Insert a concurrent statement at a position of this construct. 

335 :meth:`InsertStatementAfter` 

336 |rarr| Insert a concurrent statement after another statement. 

337 """ 

338 if before is None: 338 ↛ 339line 338 didn't jump to line 339 because the condition on line 338 was never true

339 raise ValueError("Parameter 'before' is None.") 

340 elif not isinstance(before, ModelEntity): 340 ↛ 341line 340 didn't jump to line 341 because the condition on line 340 was never true

341 ex = TypeError("Parameter 'before' is not of type 'ModelEntity'.") 

342 ex.add_note(f"Got type '{getFullyQualifiedName(before)}'.") 

343 raise ex 

344 

345 for index, item in enumerate(self._statements): 

346 if item is before: 

347 break 

348 else: 

349 label = "" 

350 if isinstance(before, LabeledEntityMixin) and before._label is not None: 350 ↛ 352line 350 didn't jump to line 352 because the condition on line 350 was always true

351 label = f" '{before._label}'" 

352 raise NotAChildError( 

353 f"{getTypeName(before)}{label} is not a statement of this {getTypeName(self)}.", 

354 element=before, 

355 parent=self 

356 ) 

357 

358 self.InsertStatement(index, statement) 

359 

360 def InsertStatementAfter(self, statement: ConcurrentStatement, after: ConcurrentStatement) -> None: 

361 """ 

362 Insert a concurrent statement after another statement of this construct. 

363 

364 The statement's parent is set to this construct. If the statements are indexed, an instantiation, a block or a 

365 generate statement is added to the lookup table matching its kind. 

366 

367 :param statement: The concurrent statement to insert. 

368 :param after: The statement of this construct to insert after. 

369 :raises ValueError: If parameter 'after' is ``None``. 

370 :raises TypeError: If parameter 'after' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

371 :raises NotAChildError: If parameter 'after' is not a statement of this construct. 

372 :raises ValueError: If parameter 'statement' is ``None``. 

373 :raises TypeError: If parameter 'statement' is not of type :class:`ConcurrentStatement`. 

374 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

375 :raises DuplicateLabelError: If the declarative region already declares the statement's label. 

376 

377 .. seealso:: 

378 

379 :meth:`InsertStatement` 

380 |rarr| Insert a concurrent statement at a position of this construct. 

381 :meth:`InsertStatementBefore` 

382 |rarr| Insert a concurrent statement before another statement. 

383 """ 

384 if after is None: 384 ↛ 385line 384 didn't jump to line 385 because the condition on line 384 was never true

385 raise ValueError("Parameter 'after' is None.") 

386 elif not isinstance(after, ModelEntity): 386 ↛ 387line 386 didn't jump to line 387 because the condition on line 386 was never true

387 ex = TypeError("Parameter 'after' is not of type 'ModelEntity'.") 

388 ex.add_note(f"Got type '{getFullyQualifiedName(after)}'.") 

389 raise ex 

390 

391 for index, item in enumerate(self._statements): 

392 if item is after: 392 ↛ 391line 392 didn't jump to line 391 because the condition on line 392 was always true

393 break 

394 else: 

395 label = "" 

396 if isinstance(after, LabeledEntityMixin) and after._label is not None: 396 ↛ 397line 396 didn't jump to line 397 because the condition on line 396 was never true

397 label = f" '{after._label}'" 

398 raise NotAChildError( 

399 f"{getTypeName(after)}{label} is not a statement of this {getTypeName(self)}.", 

400 element=after, 

401 parent=self 

402 ) 

403 

404 self.InsertStatement(index + 1, statement) 

405 

406 def RemoveStatement(self, statement: ConcurrentStatement) -> None: 

407 """ 

408 Remove a concurrent statement from this construct. 

409 

410 The statement is detached: its parent is cleared. If the statements are indexed, an instantiation, a block or a 

411 generate statement is removed from its lookup table. The statement itself is unchanged and can be added to another 

412 construct, or inserted at another position. A removed process, block or generate statement keeps the link of its 

413 namespace to this construct's namespace. 

414 

415 :param statement: The concurrent statement to remove. 

416 :raises ValueError: If parameter 'statement' is ``None``. 

417 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

418 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

419 

420 .. seealso:: 

421 

422 :meth:`AddStatement` 

423 |rarr| Add a concurrent statement at the end of this construct. 

424 :meth:`InsertStatement` 

425 |rarr| Insert a concurrent statement at a position of this construct. 

426 :meth:`MoveStatement` 

427 |rarr| Move a concurrent statement to a position of this construct. 

428 """ 

429 if statement is None: 

430 raise ValueError("Parameter 'statement' is None.") 

431 elif not isinstance(statement, ModelEntity): 

432 ex = TypeError("Parameter 'statement' is not of type 'ModelEntity'.") 

433 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.") 

434 raise ex 

435 

436 for index, item in enumerate(self._statements): 

437 if item is statement: 437 ↛ 436line 437 didn't jump to line 436 because the condition on line 437 was always true

438 break 

439 else: 

440 label = "" 

441 if isinstance(statement, LabeledEntityMixin) and statement._label is not None: 441 ↛ 443line 441 didn't jump to line 443 because the condition on line 441 was always true

442 label = f" '{statement._label}'" 

443 raise NotAChildError( 

444 f"{getTypeName(statement)}{label} is not a statement of this {getTypeName(self)}.", 

445 element=statement, 

446 parent=self 

447 ) 

448 

449 if self._areStatementsIndexed: 

450 self._UnindexStatement(statement) 

451 

452 del self._statements[index] 

453 statement._parent = None 

454 

455 def MoveStatement(self, statement: ConcurrentStatement, index: int) -> None: 

456 """ 

457 Move a concurrent statement to a position of this construct. 

458 

459 The statement stays a statement of this construct: only the order of the statements changes. If the statements are 

460 indexed (:meth:`IndexStatements`), the lookup tables are unchanged. 

461 

462 :param statement: The concurrent statement to move. 

463 :param index: Position of the statement after the move, from ``0`` (first) to the number of statements 

464 minus one (last). A negative index counts from the end, as for a :class:`list` index: ``-1`` 

465 moves the statement to the end. 

466 :raises ValueError: If parameter 'statement' is ``None``. 

467 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

468 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

469 :raises ValueError: If parameter 'index' is ``None``. 

470 :raises TypeError: If parameter 'index' is not of type :class:`int`. 

471 :raises ValueError: If parameter 'index' is out of range. 

472 

473 .. seealso:: 

474 

475 :meth:`MoveStatementBefore` 

476 |rarr| Move a concurrent statement before another statement. 

477 :meth:`MoveStatementAfter` 

478 |rarr| Move a concurrent statement after another statement. 

479 :meth:`InsertStatement` 

480 |rarr| Insert a concurrent statement at a position of this construct. 

481 :meth:`RemoveStatement` 

482 |rarr| Remove a concurrent statement from this construct. 

483 """ 

484 if statement is None: 484 ↛ 485line 484 didn't jump to line 485 because the condition on line 484 was never true

485 raise ValueError("Parameter 'statement' is None.") 

486 elif not isinstance(statement, ModelEntity): 486 ↛ 487line 486 didn't jump to line 487 because the condition on line 486 was never true

487 ex = TypeError("Parameter 'statement' is not of type 'ModelEntity'.") 

488 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.") 

489 raise ex 

490 

491 for currentIndex, item in enumerate(self._statements): 

492 if item is statement: 

493 break 

494 else: 

495 label = "" 

496 if isinstance(statement, LabeledEntityMixin) and statement._label is not None: 496 ↛ 498line 496 didn't jump to line 498 because the condition on line 496 was always true

497 label = f" '{statement._label}'" 

498 raise NotAChildError( 

499 f"{getTypeName(statement)}{label} is not a statement of this {getTypeName(self)}.", 

500 element=statement, 

501 parent=self 

502 ) 

503 

504 if index is None: 504 ↛ 505line 504 didn't jump to line 505 because the condition on line 504 was never true

505 raise ValueError("Parameter 'index' is None.") 

506 elif not isinstance(index, int): 506 ↛ 507line 506 didn't jump to line 507 because the condition on line 506 was never true

507 ex = TypeError("Parameter 'index' is not of type 'int'.") 

508 ex.add_note(f"Got type '{getFullyQualifiedName(index)}'.") 

509 raise ex 

510 elif not (-len(self._statements) <= index < len(self._statements)): 

511 ex = ValueError(f"Parameter 'index' is out of range {-len(self._statements)}..{len(self._statements) - 1}.") 

512 ex.add_note(f"Got value '{index}'.") 

513 raise ex 

514 

515 newIndex = index if index >= 0 else len(self._statements) + index 

516 del self._statements[currentIndex] 

517 self._statements.insert(newIndex, statement) 

518 

519 def MoveStatementBefore(self, statement: ConcurrentStatement, before: ConcurrentStatement) -> None: 

520 """ 

521 Move a concurrent statement before another statement of this construct. 

522 

523 The statement stays a statement of this construct: only the order of the statements changes, as for 

524 :meth:`MoveStatement`. Moving a statement before itself keeps it in place. 

525 

526 :param statement: The concurrent statement to move. 

527 :param before: The statement of this construct to move before. 

528 :raises ValueError: If parameter 'before' is ``None``. 

529 :raises TypeError: If parameter 'before' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

530 :raises NotAChildError: If parameter 'before' is not a statement of this construct. 

531 :raises ValueError: If parameter 'statement' is ``None``. 

532 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

533 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

534 

535 .. seealso:: 

536 

537 :meth:`MoveStatement` 

538 |rarr| Move a concurrent statement to a position of this construct. 

539 :meth:`MoveStatementAfter` 

540 |rarr| Move a concurrent statement after another statement. 

541 """ 

542 if before is None: 542 ↛ 543line 542 didn't jump to line 543 because the condition on line 542 was never true

543 raise ValueError("Parameter 'before' is None.") 

544 elif not isinstance(before, ModelEntity): 544 ↛ 545line 544 didn't jump to line 545 because the condition on line 544 was never true

545 ex = TypeError("Parameter 'before' is not of type 'ModelEntity'.") 

546 ex.add_note(f"Got type '{getFullyQualifiedName(before)}'.") 

547 raise ex 

548 

549 for index, item in enumerate(self._statements): 

550 if item is before: 

551 break 

552 else: 

553 label = "" 

554 if isinstance(before, LabeledEntityMixin) and before._label is not None: 554 ↛ 555line 554 didn't jump to line 555 because the condition on line 554 was never true

555 label = f" '{before._label}'" 

556 raise NotAChildError( 

557 f"{getTypeName(before)}{label} is not a statement of this {getTypeName(self)}.", 

558 element=before, 

559 parent=self 

560 ) 

561 

562 precedes = any(item is statement for item in self._statements[:index]) 

563 self.MoveStatement(statement, index - 1 if precedes else index) 

564 

565 def MoveStatementAfter(self, statement: ConcurrentStatement, after: ConcurrentStatement) -> None: 

566 """ 

567 Move a concurrent statement after another statement of this construct. 

568 

569 The statement stays a statement of this construct: only the order of the statements changes, as for 

570 :meth:`MoveStatement`. Moving a statement after itself keeps it in place. 

571 

572 :param statement: The concurrent statement to move. 

573 :param after: The statement of this construct to move after. 

574 :raises ValueError: If parameter 'after' is ``None``. 

575 :raises TypeError: If parameter 'after' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

576 :raises NotAChildError: If parameter 'after' is not a statement of this construct. 

577 :raises ValueError: If parameter 'statement' is ``None``. 

578 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

579 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

580 

581 .. seealso:: 

582 

583 :meth:`MoveStatement` 

584 |rarr| Move a concurrent statement to a position of this construct. 

585 :meth:`MoveStatementBefore` 

586 |rarr| Move a concurrent statement before another statement. 

587 """ 

588 if after is None: 588 ↛ 589line 588 didn't jump to line 589 because the condition on line 588 was never true

589 raise ValueError("Parameter 'after' is None.") 

590 elif not isinstance(after, ModelEntity): 590 ↛ 591line 590 didn't jump to line 591 because the condition on line 590 was never true

591 ex = TypeError("Parameter 'after' is not of type 'ModelEntity'.") 

592 ex.add_note(f"Got type '{getFullyQualifiedName(after)}'.") 

593 raise ex 

594 

595 for index, item in enumerate(self._statements): 595 ↛ 599line 595 didn't jump to line 599 because the loop on line 595 didn't complete

596 if item is after: 596 ↛ 595line 596 didn't jump to line 595 because the condition on line 596 was always true

597 break 

598 else: 

599 label = "" 

600 if isinstance(after, LabeledEntityMixin) and after._label is not None: 

601 label = f" '{after._label}'" 

602 raise NotAChildError( 

603 f"{getTypeName(after)}{label} is not a statement of this {getTypeName(self)}.", 

604 element=after, 

605 parent=self 

606 ) 

607 

608 precedes = any(item is statement for item in self._statements[:index + 1]) 

609 self.MoveStatement(statement, index if precedes else index + 1) 

610 

611 

612@export 

613@abstractclass 

614class Instantiation(ConcurrentStatement, GenericMapAspectMixin, PortMapAspectMixin): 

615 """ 

616 A base-class for all (component) instantiations. 

617 

618 .. seealso:: 

619 

620 * :class:`Component instantiation <pyVHDLModel.Concurrent.ComponentInstantiation>` 

621 * :class:`Entity instantiation <pyVHDLModel.Concurrent.EntityInstantiation>` 

622 * :class:`Configuration instantiation <pyVHDLModel.Concurrent.ConfigurationInstantiation>` 

623 """ 

624 

625 def __init__( 

626 self, 

627 label: str, 

628 genericAssociationItems: Nullable[Iterable[GenericAssociationItem]] = None, 

629 portAssociationItems: Nullable[Iterable[PortAssociationItem]] = None, 

630 parent: Nullable[ModelEntity] = None 

631 ) -> None: 

632 """ 

633 Initializes an instantiation. 

634 

635 :param label: The label of a model entity. 

636 :param genericAssociationItems: List of all generic associations in the generic map aspect. 

637 :param portAssociationItems: List of all port associations in the port map aspect. 

638 :param parent: The parent model entity of this entity. 

639 """ 

640 super().__init__(label, parent) 

641 GenericMapAspectMixin.__init__(self, genericAssociationItems) 

642 PortMapAspectMixin.__init__(self, portAssociationItems) 

643 

644 def _VisitMapAspects(self, visitor: Visitor) -> None: 

645 """ 

646 Walk the generic map aspect and the port map aspect of this instantiation with a visitor. 

647 

648 :param visitor: The visitor receiving the events. 

649 """ 

650 self._VisitGenericMapAspect(visitor) 

651 self._VisitPortMapAspect(visitor) 

652 

653 

654 

655 

656@export 

657class ComponentInstantiation(Instantiation): 

658 """ 

659 Represents a component instantiation. 

660 

661 The instantiated component is available as :data:`Component`, the associations as 

662 :data:`GenericAssociationItems` and :data:`PortAssociationItems`. The label is mandatory. 

663 

664 .. admonition:: Example 

665 

666 .. code-block:: VHDL 

667 

668 inst : component Counter; 

669 --^^^^ <- Label 

670 -- ^^^^^^^ <- Component 

671 """ 

672 

673 _component: ComponentInstantiationSymbol #: Reference to the instantiated component. 

674 

675 def __init__( 

676 self, 

677 label: str, 

678 componentSymbol: ComponentInstantiationSymbol, 

679 genericAssociationItems: Nullable[Iterable[AssociationItem]] = None, 

680 portAssociationItems: Nullable[Iterable[AssociationItem]] = None, 

681 parent: Nullable[ModelEntity] = None 

682 ) -> None: 

683 """ 

684 Initializes a component instantiation. 

685 

686 :param label: The label of a model entity. 

687 :param componentSymbol: Reference to the instantiated component. 

688 :param genericAssociationItems: List of all generic associations in the generic map aspect. 

689 :param portAssociationItems: List of all port associations in the port map aspect. 

690 :param parent: The parent model entity of this entity. 

691 """ 

692 super().__init__(label, genericAssociationItems, portAssociationItems, parent) 

693 

694 self._component = componentSymbol 

695 componentSymbol.Parent = self 

696 

697 def Visit(self, visitor: Visitor) -> None: 

698 """ 

699 Walk this component instantiation, its component and its map aspects with a visitor. 

700 

701 :param visitor: The visitor receiving the events. 

702 """ 

703 visitor.VisitComponentInstantiation(self) 

704 self._component.Visit(visitor) 

705 self._VisitMapAspects(visitor) 

706 visitor.DepartComponentInstantiation(self) 

707 

708 @readonly 

709 def Component(self) -> ComponentInstantiationSymbol: 

710 """ 

711 Read-only property to access the component (:attr:`_component`). 

712 

713 :returns: The component. 

714 """ 

715 return self._component 

716 

717 

718@export 

719class EntityInstantiation(Instantiation): 

720 """ 

721 Represents a direct entity instantiation. 

722 

723 The instantiated entity is available as :data:`Entity` and the optionally selected architecture 

724 as :data:`Architecture`. The label is mandatory. 

725 

726 .. admonition:: Example 

727 

728 .. code-block:: VHDL 

729 

730 inst : entity work.Counter(rtl); 

731 --^^^^ <- Label 

732 -- ^^^^^^^^^^^^ <- Entity 

733 -- ^^^ <- optional Architecture 

734 """ 

735 

736 _entity: EntityInstantiationSymbol #: Reference to the directly instantiated entity. 

737 _architecture: ArchitectureSymbol #: Reference to the selected architecture, if one was given. 

738 

739 def __init__( 

740 self, 

741 label: str, 

742 entitySymbol: EntityInstantiationSymbol, 

743 architectureSymbol: Nullable[ArchitectureSymbol] = None, 

744 genericAssociationItems: Nullable[Iterable[AssociationItem]] = None, 

745 portAssociationItems: Nullable[Iterable[AssociationItem]] = None, 

746 parent: Nullable[ModelEntity] = None 

747 ) -> None: 

748 """ 

749 Initializes a direct entity instantiation. 

750 

751 :param label: The label of a model entity. 

752 :param entitySymbol: Reference to the directly instantiated entity. 

753 :param architectureSymbol: Reference to the selected architecture, if one was given. 

754 :param genericAssociationItems: List of all generic associations in the generic map aspect. 

755 :param portAssociationItems: List of all port associations in the port map aspect. 

756 :param parent: The parent model entity of this entity. 

757 """ 

758 super().__init__(label, genericAssociationItems, portAssociationItems, parent) 

759 

760 self._entity = entitySymbol 

761 entitySymbol.Parent = self 

762 

763 self._architecture = architectureSymbol 

764 if architectureSymbol is not None: 

765 architectureSymbol.Parent = self 

766 

767 def Visit(self, visitor: Visitor) -> None: 

768 """ 

769 Walk this entity instantiation, its entity, its architecture (if any) and its map aspects with a visitor. 

770 

771 :param visitor: The visitor receiving the events. 

772 """ 

773 visitor.VisitEntityInstantiation(self) 

774 self._entity.Visit(visitor) 

775 if self._architecture is not None: 

776 visitor.VisitLeftParenthesis(self) 

777 self._architecture.Visit(visitor) 

778 visitor.VisitRightParenthesis(self) 

779 

780 self._VisitMapAspects(visitor) 

781 visitor.DepartEntityInstantiation(self) 

782 

783 @readonly 

784 def Entity(self) -> EntityInstantiationSymbol: 

785 """ 

786 Read-only property to access the entity (:attr:`_entity`). 

787 

788 :returns: The entity. 

789 """ 

790 return self._entity 

791 

792 @readonly 

793 def Architecture(self) -> ArchitectureSymbol: 

794 """ 

795 Read-only property to access the architecture (:attr:`_architecture`). 

796 

797 :returns: The architecture. 

798 """ 

799 return self._architecture 

800 

801 

802@export 

803class ConfigurationInstantiation(Instantiation): 

804 """ 

805 Represents a configuration instantiation. 

806 

807 The instantiated configuration is available as :data:`Configuration`. The label is mandatory. 

808 

809 .. admonition:: Example 

810 

811 .. code-block:: VHDL 

812 

813 inst : configuration Counter; 

814 --^^^^ <- Label 

815 -- ^^^^^^^ <- Configuration 

816 """ 

817 

818 _configuration: ConfigurationInstantiationSymbol #: Reference to the instantiated configuration. 

819 

820 def __init__( 

821 self, 

822 label: str, 

823 configurationSymbol: ConfigurationInstantiationSymbol, 

824 genericAssociationItems: Nullable[Iterable[AssociationItem]] = None, 

825 portAssociationItems: Nullable[Iterable[AssociationItem]] = None, 

826 parent: Nullable[ModelEntity] = None 

827 ) -> None: 

828 """ 

829 Initializes a configuration instantiation. 

830 

831 :param label: The label of a model entity. 

832 :param configurationSymbol: Reference to the instantiated configuration. 

833 :param genericAssociationItems: List of all generic associations in the generic map aspect. 

834 :param portAssociationItems: List of all port associations in the port map aspect. 

835 :param parent: The parent model entity of this entity. 

836 """ 

837 super().__init__(label, genericAssociationItems, portAssociationItems, parent) 

838 

839 self._configuration = configurationSymbol 

840 configurationSymbol.Parent = self 

841 

842 def Visit(self, visitor: Visitor) -> None: 

843 """ 

844 Walk this configuration instantiation, its configuration and its map aspects with a visitor. 

845 

846 :param visitor: The visitor receiving the events. 

847 """ 

848 visitor.VisitConfigurationInstantiation(self) 

849 self._configuration.Visit(visitor) 

850 self._VisitMapAspects(visitor) 

851 visitor.DepartConfigurationInstantiation(self) 

852 

853 @readonly 

854 def Configuration(self) -> ConfigurationInstantiationSymbol: 

855 """ 

856 Read-only property to access the configuration (:attr:`_configuration`). 

857 

858 :returns: The configuration. 

859 """ 

860 return self._configuration 

861 

862 

863@export 

864class ProcessStatement(ConcurrentStatement, SequentialDeclarationRegionMixin, SequentialStatementsMixin, DocumentedEntityMixin): 

865 """ 

866 Represents a process statement. 

867 

868 A process declares its own items (:data:`DeclaredItems`) and groups sequential statements 

869 (:data:`Statements`). It may name a sensitivity list (:data:`SensitivityList`). 

870 

871 .. admonition:: Example 

872 

873 .. code-block:: VHDL 

874 

875 proc : process (clock) 

876 --^^^^ <- optional Label 

877 -- ^^^^^ <- optional SensitivityList 

878 variable v : bit; 

879 -- ^^^^^^^^^^^^^^^^^ <- DeclaredItems 

880 begin 

881 v := '1'; 

882 -- ^^^^^^^^^ <- Statements 

883 end process; 

884 """ 

885 

886 # TODO: implement a SignalSymbol 

887 _sensitivityList: list[Name] #: List of all signal names in the sensitivity list, or ``None`` if none was given. 

888 

889 def __init__( 

890 self, 

891 label: Nullable[str] = None, 

892 declaredItems: Nullable[Iterable] = None, 

893 statements: Nullable[Iterable[SequentialStatement]] = None, 

894 sensitivityList: Nullable[Iterable[Name]] = None, 

895 documentation: Nullable[str] = None, 

896 parent: Nullable[ModelEntity] = None 

897 ) -> None: 

898 """ 

899 Initializes a process statement. 

900 

901 :param label: The label of a model entity. 

902 :param declaredItems: List of all declared items in this sequential declaration region. 

903 :param statements: List of all sequential statements in this construct. 

904 :param sensitivityList: List of all signal names in the sensitivity list, or ``None`` if none was given. 

905 :param documentation: The documentation comment associated with this declaration. 

906 :param parent: The parent model entity of this entity. 

907 """ 

908 super().__init__(label, parent) 

909 SequentialDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems) 

910 SequentialStatementsMixin.__init__(self, statements) 

911 DocumentedEntityMixin.__init__(self, documentation) 

912 

913 if sensitivityList is None: 

914 self._sensitivityList = None 

915 else: 

916 self._sensitivityList = signalSymbols = [] # TODO: convert to dict 

917 for signalSymbol in sensitivityList: 

918 signalSymbols.append(signalSymbol) 

919 # signalSymbol._parent = self # FIXME: currently str are provided 

920 

921 def Visit(self, visitor: Visitor) -> None: 

922 """ 

923 Walk this process, its sensitivity list (if any), its declared items and its statements with a visitor. 

924 

925 :param visitor: The visitor receiving the events. 

926 """ 

927 visitor.VisitProcessStatement(self) 

928 if self._sensitivityList is not None: 

929 visitor.VisitSensitivityList(self) 

930 for index, name in enumerate(self._sensitivityList): 

931 if index > 0: 

932 visitor.VisitComma(self) 

933 

934 name.Visit(visitor) 

935 

936 visitor.DepartSensitivityList(self) 

937 

938 visitor.VisitIs(self) 

939 self._VisitDeclaredItems(visitor) 

940 visitor.VisitBegin(self) 

941 self._VisitStatements(visitor) 

942 visitor.DepartProcessStatement(self) 

943 

944 @ConcurrentStatement.Parent.setter 

945 def Parent(self, parent: ModelEntity) -> None: 

946 ConcurrentStatement.Parent.fset(self, parent) 

947 

948 # Connect the process' namespace to the enclosing declaration region's namespace, so a declaration 

949 # inside the process hides a same-named one from the architecture, block or generate around it. 

950 self._namespace.ParentNamespace = parent._namespace 

951 

952 def _LabelRegion(self) -> ProcessStatement: 

953 """ 

954 Return the process, whose declarative region declares the labels of its statements. 

955 

956 :returns: The process itself. 

957 """ 

958 return self 

959 

960 @readonly 

961 def SensitivityList(self) -> list[Name]: 

962 """ 

963 Read-only property to access the sensitivity list (:attr:`_sensitivityList`). 

964 

965 :returns: List of sensitivity list. 

966 """ 

967 return self._sensitivityList 

968 

969 

970@export 

971class ConcurrentProcedureCall(ConcurrentStatement, ProcedureCallMixin): 

972 """ 

973 Represents a concurrent procedure call. 

974 

975 Like every concurrent statement, it can carry an optional label (:data:`Label`). 

976 

977 .. admonition:: Example 

978 

979 .. code-block:: VHDL 

980 

981 proc_lbl : proc(clock, open); 

982 --^^^^^^^^ <- optional Label 

983 -- ^^^^^^^^^^^^^^^^^ <- the call 

984 

985 .. seealso:: 

986 

987 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialProcedureCall>` 

988 """ 

989 def __init__( 

990 self, 

991 label: Nullable[str], 

992 procedureName: Symbol, 

993 parameterAssociationItems: Nullable[Iterable[ParameterAssociationItem]] = None, 

994 parent: Nullable[ModelEntity] = None 

995 ) -> None: 

996 """ 

997 Initializes a concurrent procedure call. 

998 

999 :param label: The label of a model entity. 

1000 :param procedureName: Reference to the called procedure. 

1001 :param parameterAssociationItems: List of all parameter associations of the call. 

1002 :param parent: The parent model entity of this entity. 

1003 """ 

1004 super().__init__(label, parent) 

1005 ProcedureCallMixin.__init__(self, procedureName, parameterAssociationItems) 

1006 

1007 def Visit(self, visitor: Visitor) -> None: 

1008 """ 

1009 Walk this concurrent procedure call, its procedure and its parameters with a visitor. 

1010 

1011 :param visitor: The visitor receiving the events. 

1012 """ 

1013 visitor.VisitConcurrentProcedureCall(self) 

1014 self._VisitProcedureCall(visitor) 

1015 visitor.DepartConcurrentProcedureCall(self) 

1016 

1017 

1018@export 

1019class ConcurrentBlockStatement( 

1020 ConcurrentStatement, 

1021 BlockStatementMixin, 

1022 LabeledEntityMixin, 

1023 WithGenericsMixin, 

1024 WithPortsMixin, 

1025 GenericMapAspectMixin, 

1026 PortMapAspectMixin, 

1027 ConcurrentDeclarationRegionMixin, 

1028 ConcurrentStatementsMixin, 

1029 DocumentedEntityMixin, 

1030 AllowBlackboxMixin 

1031): 

1032 """ 

1033 Represents a block statement. 

1034 

1035 A block groups concurrent statements (:data:`Statements`) and may declare its own items 

1036 (:data:`DeclaredItems`). It always forms a hierarchy level; independently of that, it may also have 

1037 a block header: a generic clause (:data:`GenericItems`) with its generic map aspect 

1038 (:data:`GenericAssociationItems`), and a port clause (:data:`PortItems`) with its port map aspect 

1039 (:data:`PortAssociationItems`). 

1040 

1041 .. admonition:: Example 

1042 

1043 .. code-block:: VHDL 

1044 

1045 blk : block 

1046 --^^^ <- Label 

1047 generic (G : positive := 1); 

1048 -- ^^^^^^^^^^^^^^^^^^ <- GenericItems 

1049 generic map (G => 2); 

1050 -- ^^^^^^^^ <- GenericAssociationItems 

1051 port (bp : in bit); 

1052 -- ^^^^^^^^^^^ <- PortItems 

1053 port map (bp => clock); 

1054 -- ^^^^^^^^^^^^ <- PortAssociationItems 

1055 signal inner : bit := '0'; 

1056 -- ^^^^^^^^^^^^^^^^^^^^^^^^^^ <- DeclaredItems 

1057 begin 

1058 inner <= bp; 

1059 -- ^^^^^^^^^^^^ <- Statements 

1060 end block; 

1061 

1062 .. seealso:: 

1063 

1064 * :class:`Generate statement <pyVHDLModel.Concurrent.GenerateStatement>` 

1065 """ 

1066 def __init__( 

1067 self, 

1068 label: str, 

1069 genericItems: Nullable[Iterable[GenericInterfaceItemMixin]] = None, 

1070 genericAssociationItems: Nullable[Iterable[GenericAssociationItem]] = None, 

1071 portItems: Nullable[Iterable[PortInterfaceItemMixin]] = None, 

1072 portAssociationItems: Nullable[Iterable[PortAssociationItem]] = None, 

1073 declaredItems: Nullable[Iterable] = None, 

1074 statements: Iterable[ConcurrentStatement] = None, 

1075 documentation: Nullable[str] = None, 

1076 allowBlackbox: Nullable[bool] = None, 

1077 parent: Nullable[ModelEntity] = None 

1078 ) -> None: 

1079 """ 

1080 Initializes a block statement. 

1081 

1082 :param label: The label of a model entity. 

1083 :param genericItems: List of all generics, in declaration order. 

1084 :param genericAssociationItems: List of all generic associations in the generic map aspect. 

1085 :param portItems: List of all ports, in declaration order. 

1086 :param portAssociationItems: List of all port associations in the port map aspect. 

1087 :param declaredItems: List of all declared items in this concurrent declaration region. 

1088 :param statements: List of all concurrent statements in this construct. 

1089 :param documentation: The documentation comment associated with this declaration. 

1090 :param allowBlackbox: Allow blackboxes for components in language entity. 

1091 :param parent: The parent model entity of this entity. 

1092 """ 

1093 super().__init__(label, parent) 

1094 

1095 BlockStatementMixin.__init__(self) 

1096 LabeledEntityMixin.__init__(self, label) 

1097 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems) 

1098 if parent is not None: 1098 ↛ 1099line 1098 didn't jump to line 1099 because the condition on line 1098 was never true

1099 self._namespace.ParentNamespace = parent._namespace 

1100 

1101 WithGenericsMixin.__init__(self, genericItems) 

1102 WithPortsMixin.__init__(self, portItems) 

1103 GenericMapAspectMixin.__init__(self, genericAssociationItems) 

1104 PortMapAspectMixin.__init__(self, portAssociationItems) 

1105 ConcurrentStatementsMixin.__init__(self, statements) 

1106 DocumentedEntityMixin.__init__(self, documentation) 

1107 AllowBlackboxMixin.__init__(self, allowBlackbox) 

1108 

1109 def Visit(self, visitor: Visitor) -> None: 

1110 """ 

1111 Walk this block, its block header, its declared items and its statements with a visitor. 

1112 

1113 :param visitor: The visitor receiving the events. 

1114 """ 

1115 visitor.VisitConcurrentBlockStatement(self) 

1116 self._VisitGenericClause(visitor) 

1117 self._VisitGenericMapAspect(visitor) 

1118 self._VisitPortClause(visitor) 

1119 self._VisitPortMapAspect(visitor) 

1120 self._VisitDeclaredItems(visitor) 

1121 visitor.VisitBegin(self) 

1122 self._VisitStatements(visitor) 

1123 visitor.DepartConcurrentBlockStatement(self) 

1124 

1125 @ConcurrentStatement.Parent.setter 

1126 def Parent(self, parent: ModelEntity) -> None: 

1127 ConcurrentStatement.Parent.fset(self, parent) 

1128 

1129 self._namespace.ParentNamespace = parent._namespace 

1130 

1131 

1132 def IndexDeclaredItems(self) -> None: 

1133 """ 

1134 A block's ports share the declarative region of its declarative part. 

1135 

1136 :raises UnhandledCriticalWarningError: If an identifier is declared twice in a declarative region and no 

1137 :class:`~pyTooling.Warning.WarningCollector` collects the 

1138 :exc:`~pyVHDLModel.Exception.DuplicateDeclarationWarning`. 

1139 """ 

1140 self._IndexPortItems() 

1141 

1142 super().IndexDeclaredItems() 

1143 

1144 def _Declarations(self) -> tuple[ModelEntity, ...]: 

1145 """ 

1146 Return all declarations of this block: its generics and ports share the declarative region. 

1147 

1148 :returns: Tuple of declarations: the generics, the ports, then the declared items. 

1149 """ 

1150 return (*self._genericItems, *self._portItems, *super()._Declarations()) 

1151 

1152 

1153@export 

1154@abstractclass 

1155class GenerateBranch(ModelEntity, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin): 

1156 """ 

1157 A base-class for all branches in a generate statements. 

1158 

1159 .. seealso:: 

1160 

1161 * :class:`If generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>` 

1162 * :class:`Elsif generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>` 

1163 * :class:`Else generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>` 

1164 """ 

1165 

1166 _alternativeLabel: Nullable[str] #: The branch's alternative label, if one was given. 

1167 _normalizedAlternativeLabel: Nullable[str] #: The normalized (lower case) alternative label. 

1168 

1169 def __init__( 

1170 self, 

1171 declaredItems: Nullable[Iterable] = None, 

1172 statements: Nullable[Iterable[ConcurrentStatement]] = None, 

1173 alternativeLabel: Nullable[str] = None, 

1174 allowBlackbox: Nullable[bool] = None, 

1175 parent: Nullable[ModelEntity] = None 

1176 ) -> None: 

1177 """ 

1178 Initializes a generate branch. 

1179 

1180 :param declaredItems: List of all declared items in this concurrent declaration region. 

1181 :param statements: List of all concurrent statements in this construct. 

1182 :param alternativeLabel: The branch's alternative label, if one was given. 

1183 :param allowBlackbox: Allow blackboxes for components in language entity. 

1184 :param parent: The parent model entity of this entity. 

1185 """ 

1186 super().__init__(parent) 

1187 

1188 self._alternativeLabel = alternativeLabel 

1189 self._normalizedAlternativeLabel = alternativeLabel.lower() if alternativeLabel is not None else None 

1190 

1191 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedAlternativeLabel, declaredItems) 

1192 if parent is not None: 1192 ↛ 1193line 1192 didn't jump to line 1193 because the condition on line 1192 was never true

1193 self._namespace.ParentNamespace = parent._namespace 

1194 

1195 ConcurrentStatementsMixin.__init__(self, statements) 

1196 AllowBlackboxMixin.__init__(self, allowBlackbox) 

1197 

1198 @readonly 

1199 def AlternativeLabel(self) -> Nullable[str]: 

1200 """ 

1201 Read-only property to access the alternative label (:attr:`_alternativeLabel`). 

1202 

1203 :returns: The alternative label, or ``None`` if not set. 

1204 """ 

1205 return self._alternativeLabel 

1206 

1207 @readonly 

1208 def NormalizedAlternativeLabel(self) -> Nullable[str]: 

1209 """ 

1210 Read-only property to access the normalized alternative label (:attr:`_normalizedAlternativeLabel`). 

1211 

1212 :returns: The normalized alternative label, or ``None`` if not set. 

1213 """ 

1214 return self._normalizedAlternativeLabel 

1215 

1216 

1217@export 

1218class IfGenerateBranch(GenerateBranch, IfBranchMixin): 

1219 """ 

1220 Represents if-generate branch in a generate statement with a concurrent declaration region and concurrent statements. 

1221 

1222 .. admonition:: Example 

1223 

1224 .. code-block:: VHDL 

1225 

1226 gen: if condition generate 

1227 -- concurrent declarations 

1228 begin 

1229 -- concurrent statements 

1230 elsif condition generate 

1231 -- ... 

1232 else generate 

1233 -- ... 

1234 end generate; 

1235 """ 

1236 

1237 def __init__( 

1238 self, 

1239 condition: ExpressionUnion, 

1240 declaredItems: Nullable[Iterable] = None, 

1241 statements: Nullable[Iterable[ConcurrentStatement]] = None, 

1242 alternativeLabel: Nullable[str] = None, 

1243 allowBlackbox: Nullable[bool] = None, 

1244 parent: Nullable[ModelEntity] = None 

1245 ) -> None: 

1246 """ 

1247 Initializes an if generate branch. 

1248 

1249 :param condition: The condition guarding this statement. 

1250 :param declaredItems: List of all declared items in this concurrent declaration region. 

1251 :param statements: List of all concurrent statements in this construct. 

1252 :param alternativeLabel: The branch's alternative label, if one was given. 

1253 :param allowBlackbox: Allow blackboxes for components in language entity. 

1254 :param parent: The parent model entity of this entity. 

1255 """ 

1256 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent) 

1257 IfBranchMixin.__init__(self, condition) 

1258 

1259 def Visit(self, visitor: Visitor) -> None: 

1260 """ 

1261 Walk this if-generate branch, its condition, its declared items and its statements with a visitor. 

1262 

1263 :param visitor: The visitor receiving the events. 

1264 """ 

1265 visitor.VisitIfGenerateBranch(self) 

1266 self._condition.Visit(visitor) 

1267 visitor.VisitGenerate(self) 

1268 self._VisitDeclaredItems(visitor) 

1269 visitor.VisitBegin(self) 

1270 self._VisitStatements(visitor) 

1271 visitor.DepartIfGenerateBranch(self) 

1272 

1273 

1274@export 

1275class ElsifGenerateBranch(GenerateBranch, ElsifBranchMixin): 

1276 """ 

1277 Represents elsif-generate branch in a generate statement with a concurrent declaration region and concurrent statements. 

1278 

1279 .. admonition:: Example 

1280 

1281 .. code-block:: VHDL 

1282 

1283 gen: if condition generate 

1284 -- ... 

1285 elsif condition generate 

1286 -- concurrent declarations 

1287 begin 

1288 -- concurrent statements 

1289 else generate 

1290 -- ... 

1291 end generate; 

1292 """ 

1293 

1294 def __init__( 

1295 self, 

1296 condition: ExpressionUnion, 

1297 declaredItems: Nullable[Iterable] = None, 

1298 statements: Nullable[Iterable[ConcurrentStatement]] = None, 

1299 alternativeLabel: Nullable[str] = None, 

1300 allowBlackbox: Nullable[bool] = None, 

1301 parent: Nullable[ModelEntity] = None 

1302 ) -> None: 

1303 """ 

1304 Initializes an elsif generate branch. 

1305 

1306 :param condition: The condition guarding this statement. 

1307 :param declaredItems: List of all declared items in this concurrent declaration region. 

1308 :param statements: List of all concurrent statements in this construct. 

1309 :param alternativeLabel: The branch's alternative label, if one was given. 

1310 :param allowBlackbox: Allow blackboxes for components in language entity. 

1311 :param parent: The parent model entity of this entity. 

1312 """ 

1313 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent) 

1314 ElsifBranchMixin.__init__(self, condition) 

1315 

1316 def Visit(self, visitor: Visitor) -> None: 

1317 """ 

1318 Walk this elsif-generate branch, its condition, its declared items and its statements with a visitor. 

1319 

1320 :param visitor: The visitor receiving the events. 

1321 """ 

1322 visitor.VisitElsifGenerateBranch(self) 

1323 self._condition.Visit(visitor) 

1324 visitor.VisitGenerate(self) 

1325 self._VisitDeclaredItems(visitor) 

1326 visitor.VisitBegin(self) 

1327 self._VisitStatements(visitor) 

1328 visitor.DepartElsifGenerateBranch(self) 

1329 

1330 

1331@export 

1332class ElseGenerateBranch(GenerateBranch, ElseBranchMixin): 

1333 """ 

1334 Represents else-generate branch in a generate statement with a concurrent declaration region and concurrent statements. 

1335 

1336 .. admonition:: Example 

1337 

1338 .. code-block:: VHDL 

1339 

1340 gen: if condition generate 

1341 -- ... 

1342 elsif condition generate 

1343 -- ... 

1344 else generate 

1345 -- concurrent declarations 

1346 begin 

1347 -- concurrent statements 

1348 end generate; 

1349 """ 

1350 

1351 def __init__( 

1352 self, 

1353 declaredItems: Nullable[Iterable] = None, 

1354 statements: Nullable[Iterable[ConcurrentStatement]] = None, 

1355 alternativeLabel: Nullable[str] = None, 

1356 allowBlackbox: Nullable[bool] = None, 

1357 parent: Nullable[ModelEntity] = None 

1358 ) -> None: 

1359 """ 

1360 Initializes an else generate branch. 

1361 

1362 :param declaredItems: List of all declared items in this concurrent declaration region. 

1363 :param statements: List of all concurrent statements in this construct. 

1364 :param alternativeLabel: The branch's alternative label, if one was given. 

1365 :param allowBlackbox: Allow blackboxes for components in language entity. 

1366 :param parent: The parent model entity of this entity. 

1367 """ 

1368 super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent) 

1369 ElseBranchMixin.__init__(self) 

1370 

1371 def Visit(self, visitor: Visitor) -> None: 

1372 """ 

1373 Walk this else-generate branch, its declared items and its statements with a visitor. 

1374 

1375 :param visitor: The visitor receiving the events. 

1376 """ 

1377 visitor.VisitElseGenerateBranch(self) 

1378 visitor.VisitGenerate(self) 

1379 self._VisitDeclaredItems(visitor) 

1380 visitor.VisitBegin(self) 

1381 self._VisitStatements(visitor) 

1382 visitor.DepartElseGenerateBranch(self) 

1383 

1384 

1385@export 

1386@abstractclass 

1387class GenerateStatement(ConcurrentStatement, AllowBlackboxMixin): 

1388 """ 

1389 Represents the base-class of all generate statements. 

1390 

1391 A generate statement replicates or conditionally elaborates concurrent statements. 

1392 

1393 .. seealso:: 

1394 

1395 * :class:`If generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>` 

1396 * :class:`Case generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>` 

1397 * :class:`For generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` 

1398 """ 

1399 

1400 def __init__( 

1401 self, 

1402 label: Nullable[str] = None, 

1403 allowBlackbox: Nullable[bool] = None, 

1404 parent: Nullable[ModelEntity] = None 

1405 ) -> None: 

1406 """ 

1407 Initializes a generate statement. 

1408 

1409 :param label: The label of a model entity. 

1410 :param allowBlackbox: Allow blackboxes for components in language entity. 

1411 :param parent: The parent model entity of this entity. 

1412 """ 

1413 super().__init__(label, parent) 

1414 AllowBlackboxMixin.__init__(self, allowBlackbox) 

1415 

1416 # @mustoverride 

1417 def IterateInstantiations(self) -> Generator[Instantiation, None, None]: 

1418 raise NotImplementedError() 

1419 

1420 # @mustoverride 

1421 def IndexStatement(self) -> None: 

1422 raise NotImplementedError() 

1423 

1424 

1425@export 

1426class IfGenerateStatement(GenerateStatement): 

1427 """ 

1428 Represents an if-generate statement. 

1429 

1430 It has one ``if`` branch (:data:`IfBranch`), any number of ``elsif`` branches 

1431 (:data:`ElsifBranches`) and an optional ``else`` branch (:data:`ElseBranch`). The label is 

1432 mandatory and the branch conditions must be static expressions. 

1433 

1434 .. admonition:: Example 

1435 

1436 .. code-block:: VHDL 

1437 

1438 gen : if WIDTH > 8 generate 

1439 --^^^ <- Label 

1440 -- ^^^^^^^^^^^^^^^^^^^^^ <- IfBranch 

1441 q <= '0'; 

1442 elsif WIDTH > 4 generate 

1443 --^^^^^^^^^^^^^^^^^^^^^^^^ <- ElsifBranches[0] 

1444 q <= '1'; 

1445 else generate 

1446 --^^^^^^^^^^^^^ <- ElseBranch 

1447 q <= 'Z'; 

1448 end generate; 

1449 

1450 .. seealso:: 

1451 

1452 * :class:`Generate branch <pyVHDLModel.Concurrent.GenerateBranch>` base-class 

1453 * :class:`If-generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>` 

1454 * :class:`Elsif-generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>` 

1455 * :class:`Else-generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>` 

1456 * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>` 

1457 * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` 

1458 """ 

1459 

1460 _ifBranch: IfGenerateBranch #: The mandatory ``if`` branch. 

1461 _elsifBranches: list[ElsifGenerateBranch] #: List of all ``elsif`` branches, in the order they were written. 

1462 _elseBranch: Nullable[ElseGenerateBranch] #: The optional ``else`` branch, or ``None`` if none was given. 

1463 

1464 def __init__( 

1465 self, 

1466 label: str, 

1467 ifBranch: IfGenerateBranch, 

1468 elsifBranches: Nullable[Iterable[ElsifGenerateBranch]] = None, 

1469 elseBranch: Nullable[ElseGenerateBranch] = None, 

1470 allowBlackbox: Nullable[bool] = None, 

1471 parent: Nullable[ModelEntity] = None 

1472 ) -> None: 

1473 """ 

1474 Initializes an if-generate statement. 

1475 

1476 :param label: The label of a model entity. 

1477 :param ifBranch: The mandatory ``if`` branch. 

1478 :param elsifBranches: List of all ``elsif`` branches, in the order they were written. 

1479 :param elseBranch: The optional ``else`` branch, or ``None`` if none was given. 

1480 :param allowBlackbox: Allow blackboxes for components in language entity. 

1481 :param parent: The parent model entity of this entity. 

1482 """ 

1483 super().__init__(label, allowBlackbox, parent) 

1484 

1485 self._ifBranch = ifBranch 

1486 ifBranch.Parent = self 

1487 

1488 self._elsifBranches = elsifBranchList = [] 

1489 if elsifBranches is not None: 

1490 for branch in elsifBranches: 

1491 elsifBranchList.append(branch) 

1492 branch.Parent = self 

1493 

1494 if elseBranch is not None: 

1495 self._elseBranch = elseBranch 

1496 elseBranch.Parent = self 

1497 else: 

1498 self._elseBranch = None 

1499 

1500 def Visit(self, visitor: Visitor) -> None: 

1501 """ 

1502 Walk this if-generate statement and its branches with a visitor. 

1503 

1504 :param visitor: The visitor receiving the events. 

1505 """ 

1506 visitor.VisitIfGenerateStatement(self) 

1507 self._ifBranch.Visit(visitor) 

1508 for branch in self._elsifBranches: 

1509 branch.Visit(visitor) 

1510 

1511 if self._elseBranch is not None: 1511 ↛ 1514line 1511 didn't jump to line 1514 because the condition on line 1511 was always true

1512 self._elseBranch.Visit(visitor) 

1513 

1514 visitor.DepartIfGenerateStatement(self) 

1515 

1516 @GenerateStatement.Parent.setter 

1517 def Parent(self, parent: ModelEntity) -> None: 

1518 GenerateStatement.Parent.fset(self, parent) 

1519 

1520 # Connect namespaces 

1521 namespace = self._ifBranch._namespace 

1522 namespace.ParentNamespace = parent._namespace 

1523 if namespace._name is None: 1523 ↛ 1526line 1523 didn't jump to line 1526 because the condition on line 1523 was always true

1524 namespace._name = self._normalizedLabel 

1525 

1526 for elseBranch in self._elsifBranches: 

1527 elseBranch._namespace.ParentNamespace = parent._namespace 

1528 

1529 if self._elseBranch is not None: 1529 ↛ exitline 1529 didn't return from function 'Parent' because the condition on line 1529 was always true

1530 self._elseBranch._namespace.ParentNamespace = parent._namespace 

1531 

1532 @readonly 

1533 def IfBranch(self) -> IfGenerateBranch: 

1534 """ 

1535 Read-only property to access the if branch (:attr:`_ifBranch`). 

1536 

1537 :returns: The if branch. 

1538 """ 

1539 return self._ifBranch 

1540 

1541 @readonly 

1542 def ElsifBranches(self) -> list[ElsifGenerateBranch]: 

1543 """ 

1544 Read-only property to access the elsif branches (:attr:`_elsifBranches`). 

1545 

1546 :returns: List of elsif branches. 

1547 """ 

1548 return self._elsifBranches 

1549 

1550 @readonly 

1551 def ElseBranch(self) -> Nullable[ElseGenerateBranch]: 

1552 """ 

1553 Read-only property to access the else branch (:attr:`_elseBranch`). 

1554 

1555 :returns: The else branch, or ``None`` if not set. 

1556 """ 

1557 return self._elseBranch 

1558 

1559 def IterateInstantiations(self) -> Generator[Instantiation, None, None]: 

1560 yield from self._ifBranch.IterateInstantiations() 

1561 for branch in self._elsifBranches: 

1562 yield from branch.IterateInstantiations() 

1563 if self._elseBranch is not None: 

1564 yield from self._elseBranch.IterateInstantiations() 

1565 

1566 def IndexStatement(self) -> None: 

1567 self._ifBranch.IndexStatements() 

1568 for branch in self._elsifBranches: 

1569 branch.IndexStatements() 

1570 if self._elseBranch is not None: 

1571 self._elseBranch.IndexStatements() 

1572 

1573 

1574@export 

1575@abstractclass 

1576class ConcurrentChoice(BaseChoice): 

1577 """ 

1578 A base-class for all concurrent choices (in case...generate statements). 

1579 

1580 .. seealso:: 

1581 

1582 * :class:`Indexed generate choice <pyVHDLModel.Concurrent.IndexedGenerateChoice>` 

1583 * :class:`Ranged generate choice <pyVHDLModel.Concurrent.RangedGenerateChoice>` 

1584 """ 

1585 

1586 

1587@export 

1588class IndexedGenerateChoice(ConcurrentChoice): 

1589 """ 

1590 Represents a case-generate choice given by a single value. 

1591 

1592 The value is available as :data:`Expression`. 

1593 

1594 .. admonition:: Example 

1595 

1596 .. code-block:: VHDL 

1597 

1598 when 8 => 

1599 -- ^ <- Expression 

1600 """ 

1601 _expression: ExpressionUnion #: The expression this choice selects on. 

1602 

1603 def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None: 

1604 """ 

1605 Initializes a case-generate choice given by a single value. 

1606 

1607 :param expression: The expression this choice selects on. 

1608 :param parent: The parent model entity of this entity. 

1609 """ 

1610 super().__init__(parent) 

1611 

1612 self._expression = expression 

1613 expression.Parent = self 

1614 

1615 def Visit(self, visitor: Visitor) -> None: 

1616 """ 

1617 Walk this case-generate choice and its value with a visitor. 

1618 

1619 :param visitor: The visitor receiving the events. 

1620 """ 

1621 visitor.VisitIndexedGenerateChoice(self) 

1622 self._expression.Visit(visitor) 

1623 visitor.DepartIndexedGenerateChoice(self) 

1624 

1625 @readonly 

1626 def Expression(self) -> ExpressionUnion: 

1627 """ 

1628 Read-only property to access the expression (:attr:`_expression`). 

1629 

1630 :returns: The expression. 

1631 """ 

1632 return self._expression 

1633 

1634 def __str__(self) -> str: 

1635 """ 

1636 Formats the indexed case-generate choice. 

1637 

1638 **Format:** ``0`` 

1639 

1640 :returns: Formatted indexed case-generate choice. 

1641 """ 

1642 return str(self._expression) 

1643 

1644 

1645@export 

1646class RangedGenerateChoice(ConcurrentChoice): 

1647 """ 

1648 Represents a case-generate choice given by a range. 

1649 

1650 The range is available as :data:`Range`. 

1651 

1652 .. admonition:: Example 

1653 

1654 .. code-block:: VHDL 

1655 

1656 when 0 to 3 => 

1657 -- ^^^^^^ <- Range 

1658 """ 

1659 _range: Range #: The range this choice selects on. 

1660 

1661 def __init__(self, rng: Range, parent: Nullable[ModelEntity] = None) -> None: 

1662 """ 

1663 Initializes a case-generate choice given by a range. 

1664 

1665 :param rng: The range this choice selects on. 

1666 :param parent: The parent model entity of this entity. 

1667 """ 

1668 super().__init__(parent) 

1669 

1670 self._range = rng 

1671 rng.Parent = self 

1672 

1673 def Visit(self, visitor: Visitor) -> None: 

1674 """ 

1675 Walk this case-generate choice and its range with a visitor. 

1676 

1677 :param visitor: The visitor receiving the events. 

1678 """ 

1679 visitor.VisitRangedGenerateChoice(self) 

1680 self._range.Visit(visitor) 

1681 visitor.DepartRangedGenerateChoice(self) 

1682 

1683 @readonly 

1684 def Range(self) -> Range: 

1685 """ 

1686 Read-only property to access the range (:attr:`_range`). 

1687 

1688 :returns: The range. 

1689 """ 

1690 return self._range 

1691 

1692 def __str__(self) -> str: 

1693 """ 

1694 Formats the ranged case-generate choice. 

1695 

1696 **Format:** ``0 to 3`` 

1697 

1698 :returns: Formatted ranged case-generate choice. 

1699 """ 

1700 return str(self._range) 

1701 

1702 

1703@export 

1704@abstractclass 

1705class ConcurrentCase(BaseCase, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin, ChoicesMixin): 

1706 """ 

1707 Represents the base-class of all alternatives of a case-generate statement. 

1708 

1709 .. seealso:: 

1710 

1711 * :class:`Generate case <pyVHDLModel.Concurrent.GenerateCase>` 

1712 * :class:`Others generate case <pyVHDLModel.Concurrent.OthersGenerateCase>` 

1713 """ 

1714 def __init__( 

1715 self, 

1716 declaredItems: Nullable[Iterable] = None, 

1717 statements: Nullable[Iterable[ConcurrentStatement]] = None, 

1718 alternativeLabel: Nullable[str] = None, 

1719 choices: Nullable[Iterable[BaseChoice]] = None, 

1720 allowBlackbox: Nullable[bool] = None, 

1721 parent: Nullable[ModelEntity] = None 

1722 ) -> None: 

1723 """ 

1724 Initializes a concurrent case. 

1725 

1726 :param declaredItems: List of all declared items in this concurrent declaration region. 

1727 :param statements: List of all concurrent statements in this construct. 

1728 :param alternativeLabel: The alternative's label. 

1729 :param choices: List of all choices selecting this alternative. 

1730 :param allowBlackbox: Allow blackboxes for components in language entity. 

1731 :param parent: The parent model entity of this entity. 

1732 """ 

1733 super().__init__(parent) 

1734 LabeledEntityMixin.__init__(self, alternativeLabel) 

1735 

1736 # TODO: Why not handover self? 

1737 # This allows access to Label and NormalizedLabel, also to create a full instance path in case a lookup goes wrong. 

1738 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems) 

1739 if parent is not None: 1739 ↛ 1740line 1739 didn't jump to line 1740 because the condition on line 1739 was never true

1740 self._namespace.ParentNamespace = parent._namespace 

1741 

1742 ConcurrentStatementsMixin.__init__(self, statements) 

1743 AllowBlackboxMixin.__init__(self, allowBlackbox) 

1744 ChoicesMixin.__init__(self, choices) 

1745 

1746 

1747@export 

1748class GenerateCase(ConcurrentCase): 

1749 """ 

1750 Represents one alternative of a case-generate statement, selected by its choices. 

1751 

1752 .. admonition:: Example 

1753 

1754 .. code-block:: VHDL 

1755 

1756 when 8 => 

1757 -- ^ <- Choices 

1758 """ 

1759 def __init__( 

1760 self, 

1761 choices: Iterable[ConcurrentChoice], 

1762 declaredItems: Nullable[Iterable] = None, 

1763 statements: Nullable[Iterable[ConcurrentStatement]] = None, 

1764 alternativeLabel: Nullable[str] = None, 

1765 allowBlackbox: Nullable[bool] = None, 

1766 parent: Nullable[ModelEntity] = None 

1767 ) -> None: 

1768 """ 

1769 Initializes a generate case. 

1770 

1771 :param choices: List of all choices selecting this alternative. 

1772 :param declaredItems: List of all declared items in this concurrent declaration region. 

1773 :param statements: List of all concurrent statements in this construct. 

1774 :param alternativeLabel: The alternative's label. 

1775 :param allowBlackbox: Allow blackboxes for components in language entity. 

1776 :param parent: The parent model entity of this entity. 

1777 """ 

1778 super().__init__(declaredItems, statements, alternativeLabel, choices, allowBlackbox, parent) 

1779 

1780 def Visit(self, visitor: Visitor) -> None: 

1781 """ 

1782 Walk this case-generate alternative, its choices, its declared items and its statements with a visitor. 

1783 

1784 :param visitor: The visitor receiving the events. 

1785 """ 

1786 visitor.VisitGenerateCase(self) 

1787 for index, choice in enumerate(self._choices): 

1788 if index > 0: 

1789 visitor.VisitBar(self) 

1790 

1791 choice.Visit(visitor) 

1792 

1793 visitor.VisitArrow(self) 

1794 self._VisitDeclaredItems(visitor) 

1795 visitor.VisitBegin(self) 

1796 self._VisitStatements(visitor) 

1797 visitor.DepartGenerateCase(self) 

1798 

1799 def __str__(self) -> str: 

1800 """ 

1801 Formats the case-generate alternative. 

1802 

1803 **Format:** ``when 0 | 1 =>`` 

1804 

1805 :returns: Formatted case-generate alternative. 

1806 """ 

1807 return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices)) 

1808 

1809 

1810@export 

1811class OthersGenerateCase(ConcurrentCase): 

1812 """ 

1813 Represents the ``others`` alternative of a case-generate statement. 

1814 

1815 It covers every choice not named explicitly. 

1816 

1817 .. admonition:: Example 

1818 

1819 .. code-block:: VHDL 

1820 

1821 when others => 

1822 -- ^^^^^^ <- the choice 

1823 """ 

1824 def Visit(self, visitor: Visitor) -> None: 

1825 """ 

1826 Walk this ``others`` case-generate alternative, its declared items and its statements with a visitor. 

1827 

1828 :param visitor: The visitor receiving the events. 

1829 """ 

1830 visitor.VisitOthersGenerateCase(self) 

1831 visitor.VisitArrow(self) 

1832 self._VisitDeclaredItems(visitor) 

1833 visitor.VisitBegin(self) 

1834 self._VisitStatements(visitor) 

1835 visitor.DepartOthersGenerateCase(self) 

1836 

1837 def __str__(self) -> str: 

1838 """ 

1839 Formats the ``others`` case-generate alternative. 

1840 

1841 **Format:** ``when others =>`` 

1842 

1843 :returns: Formatted ``others`` case-generate alternative. 

1844 """ 

1845 return "when others =>" 

1846 

1847 

1848@export 

1849class CaseGenerateStatement(GenerateStatement): 

1850 """ 

1851 Represents a case-generate statement. 

1852 

1853 The expression being tested is available as :data:`SelectExpression`, the alternatives as 

1854 :data:`Cases`. The label is mandatory and the selector must be a static expression. 

1855 

1856 .. admonition:: Example 

1857 

1858 .. code-block:: VHDL 

1859 

1860 gen : case MODE generate 

1861 --^^^ <- Label 

1862 -- ^^^^ <- SelectExpression 

1863 when 0 => q <= '0'; 

1864 -- ^^^^^^^^^^^^^^^^^^^ <- Cases[0] 

1865 when others => q <= '1'; 

1866 -- ^^^^^^^^^^^^^^^^^^^^^^^^ <- Cases[1] 

1867 end generate; 

1868 

1869 .. seealso:: 

1870 

1871 * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>` 

1872 * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` 

1873 """ 

1874 

1875 _expression: ExpressionUnion #: The expression being tested; it must be static. 

1876 _cases: list[GenerateCase] #: List of all alternatives, in the order they were written. 

1877 

1878 def __init__( 

1879 self, 

1880 label: str, 

1881 expression: ExpressionUnion, 

1882 cases: Iterable[ConcurrentCase], 

1883 allowBlackbox: Nullable[bool] = None, 

1884 parent: Nullable[ModelEntity] = None 

1885 ) -> None: 

1886 """ 

1887 Initializes a case-generate statement. 

1888 

1889 :param label: The label of a model entity. 

1890 :param expression: The expression being tested; it must be static. 

1891 :param cases: List of all alternatives, in the order they were written. 

1892 :param allowBlackbox: Allow blackboxes for components in language entity. 

1893 :param parent: The parent model entity of this entity. 

1894 """ 

1895 super().__init__(label, allowBlackbox, parent) 

1896 

1897 self._expression = expression 

1898 expression.Parent = self 

1899 

1900 # TODO: create a mixin for things with cases 

1901 self._cases = caseList = [] 

1902 if cases is not None: 1902 ↛ exitline 1902 didn't return from function '__init__' because the condition on line 1902 was always true

1903 for case in cases: 

1904 caseList.append(case) 

1905 case.Parent = self 

1906 

1907 def Visit(self, visitor: Visitor) -> None: 

1908 """ 

1909 Walk this case-generate statement, its selector and its alternatives with a visitor. 

1910 

1911 :param visitor: The visitor receiving the events. 

1912 """ 

1913 visitor.VisitCaseGenerateStatement(self) 

1914 self._expression.Visit(visitor) 

1915 visitor.VisitGenerate(self) 

1916 for case in self._cases: 

1917 case.Visit(visitor) 

1918 

1919 visitor.DepartCaseGenerateStatement(self) 

1920 

1921 @GenerateStatement.Parent.setter 

1922 def Parent(self, parent: ModelEntity) -> None: 

1923 GenerateStatement.Parent.fset(self, parent) 

1924 

1925 # Connect namespaces 

1926 for case in self._cases: 

1927 case._namespace.ParentNamespace = parent._namespace 

1928 

1929 @readonly 

1930 def SelectExpression(self) -> ExpressionUnion: 

1931 """ 

1932 Read-only property to access the select expression (:attr:`_expression`). 

1933 

1934 :returns: The select expression. 

1935 """ 

1936 return self._expression 

1937 

1938 @readonly 

1939 def Cases(self) -> list[GenerateCase]: 

1940 """ 

1941 Read-only property to access the cases (:attr:`_cases`). 

1942 

1943 :returns: List of cases. 

1944 """ 

1945 return self._cases 

1946 

1947 def IterateInstantiations(self) -> Generator[Instantiation, None, None]: 

1948 for case in self._cases: 

1949 yield from case.IterateInstantiations() 

1950 

1951 def IndexStatement(self) -> None: 

1952 for case in self._cases: 

1953 case.IndexStatements() 

1954 

1955 

1956@export 

1957class ForGenerateStatement(GenerateStatement, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin): 

1958 """ 

1959 Represents a for-generate statement. 

1960 

1961 The loop index is available as :data:`LoopIndex`, the iteration range as :data:`Range` and the 

1962 generated statements as :data:`Statements`. The label is mandatory. 

1963 

1964 .. admonition:: Example 

1965 

1966 .. code-block:: VHDL 

1967 

1968 gen : for i in 0 to 3 generate 

1969 --^^^ <- Label 

1970 -- ^ <- LoopIndex 

1971 -- ^^^^^^ <- Range 

1972 q(i) <= '0'; 

1973 -- ^^^^^^^^^^^^ <- Statements 

1974 end generate; 

1975 

1976 .. seealso:: 

1977 

1978 * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>` 

1979 * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>` 

1980 """ 

1981 

1982 _loopIndex: str #: The name of the generate loop's index. 

1983 _range: Range #: The range the generate loop iterates over. 

1984 

1985 def __init__( 

1986 self, 

1987 label: str, 

1988 loopIndex: str, 

1989 rng: Range, 

1990 declaredItems: Nullable[Iterable] = None, 

1991 statements: Nullable[Iterable[ConcurrentStatement]] = None, 

1992 allowBlackbox: Nullable[bool] = None, 

1993 parent: Nullable[ModelEntity] = None 

1994 ) -> None: 

1995 """ 

1996 Initializes a for-generate statement. 

1997 

1998 :param label: The label of a model entity. 

1999 :param loopIndex: The name of the generate loop's index. 

2000 :param rng: The range the generate loop iterates over. 

2001 :param declaredItems: List of all declared items in this concurrent declaration region. 

2002 :param statements: List of all concurrent statements in this construct. 

2003 :param allowBlackbox: Allow blackboxes for components in language entity. 

2004 :param parent: The parent model entity of this entity. 

2005 """ 

2006 super().__init__(label, allowBlackbox, parent) 

2007 

2008 ConcurrentDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems) 

2009 if parent is not None: 2009 ↛ 2010line 2009 didn't jump to line 2010 because the condition on line 2009 was never true

2010 self._namespace.ParentNamespace = parent._namespace 

2011 

2012 ConcurrentStatementsMixin.__init__(self, statements) 

2013 

2014 self._loopIndex = loopIndex 

2015 

2016 self._range = rng 

2017 rng.Parent = self 

2018 

2019 def Visit(self, visitor: Visitor) -> None: 

2020 """ 

2021 Walk this for-generate statement, its range, its declared items and its statements with a visitor. 

2022 

2023 :param visitor: The visitor receiving the events. 

2024 """ 

2025 visitor.VisitForGenerateStatement(self) 

2026 self._range.Visit(visitor) 

2027 visitor.VisitGenerate(self) 

2028 self._VisitDeclaredItems(visitor) 

2029 visitor.VisitBegin(self) 

2030 self._VisitStatements(visitor) 

2031 visitor.DepartForGenerateStatement(self) 

2032 

2033 @GenerateStatement.Parent.setter 

2034 def Parent(self, parent: ModelEntity) -> None: 

2035 GenerateStatement.Parent.fset(self, parent) 

2036 

2037 self._namespace.ParentNamespace = parent._namespace 

2038 

2039 @readonly 

2040 def LoopIndex(self) -> str: 

2041 """ 

2042 Read-only property to access the loop index (:attr:`_loopIndex`). 

2043 

2044 :returns: The loop index. 

2045 """ 

2046 return self._loopIndex 

2047 

2048 @readonly 

2049 def Range(self) -> Range: 

2050 """ 

2051 Read-only property to access the range (:attr:`_range`). 

2052 

2053 :returns: The range. 

2054 """ 

2055 return self._range 

2056 

2057 # IndexDeclaredItems = ConcurrentStatements.IndexDeclaredItems 

2058 

2059 def IndexStatement(self) -> None: 

2060 self.IndexStatements() 

2061 

2062 def IndexStatements(self) -> None: 

2063 super().IndexStatements() 

2064 

2065 def IterateInstantiations(self) -> Generator[Instantiation, None, None]: 

2066 return ConcurrentStatementsMixin.IterateInstantiations(self) 

2067 

2068 

2069@export 

2070@abstractclass 

2071class ConcurrentSignalAssignment(ConcurrentStatement, SignalAssignmentMixin): 

2072 """ 

2073 Represents the base-class of all concurrent signal assignments. 

2074 

2075 .. seealso:: 

2076 

2077 * :class:`Concurrent simple signal assignment <pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment>` 

2078 * :class:`Concurrent selected signal assignment <pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment>` 

2079 * :class:`Conditional signal assignment <pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment>` """ 

2080 def __init__(self, label: Nullable[str], target: SignalSymbol, parent: Nullable[ModelEntity] = None) -> None: 

2081 """ 

2082 Initializes a concurrent signal assignment. 

2083 

2084 :param label: The label of a model entity. 

2085 :param target: Reference to the assignment's destination. 

2086 :param parent: The parent model entity of this entity. 

2087 """ 

2088 super().__init__(label, parent) 

2089 SignalAssignmentMixin.__init__(self, target) 

2090 

2091 

2092@export 

2093class ConcurrentSimpleSignalAssignment(ConcurrentSignalAssignment, WaveformMixin): 

2094 """ 

2095 Represents a simple concurrent signal assignment. 

2096 

2097 The assignment's destination is available as :data:`Target`, its value as :data:`Waveform`. 

2098 

2099 .. admonition:: Example 

2100 

2101 .. code-block:: VHDL 

2102 

2103 lbl : q <= '1'; 

2104 --^^^ <- optional Label 

2105 -- ^ <- Target 

2106 -- ^^^ <- Waveform 

2107 

2108 .. seealso:: 

2109 

2110 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialSimpleSignalAssignment>` 

2111 """ 

2112 def __init__( 

2113 self, 

2114 label: Nullable[str], 

2115 target: SignalSymbol, 

2116 waveform: Iterable[WaveformElement], 

2117 parent: Nullable[ModelEntity] = None 

2118 ) -> None: 

2119 """ 

2120 Initializes a simple concurrent signal assignment. 

2121 

2122 :param label: The label of a model entity. 

2123 :param target: Reference to the assignment's destination. 

2124 :param waveform: List of all waveform elements, in the order they were written. 

2125 :param parent: The parent model entity of this entity. 

2126 """ 

2127 super().__init__(label, target, parent) 

2128 WaveformMixin.__init__(self, waveform) 

2129 

2130 def Visit(self, visitor: Visitor) -> None: 

2131 """ 

2132 Walk this concurrent signal assignment, its target and its waveform with a visitor. 

2133 

2134 :param visitor: The visitor receiving the events. 

2135 """ 

2136 visitor.VisitConcurrentSimpleSignalAssignment(self) 

2137 self._target.Visit(visitor) 

2138 visitor.VisitSignalAssignment(self) 

2139 self._VisitWaveform(visitor) 

2140 visitor.DepartConcurrentSimpleSignalAssignment(self) 

2141 

2142 

2143@export 

2144class ConcurrentSelectedSignalAssignment(ConcurrentSignalAssignment, ExpressionMixin, SelectedWaveformsMixin): 

2145 """ 

2146 Represents a selected concurrent signal assignment. 

2147 

2148 The selector is available as :data:`Expression`, the alternatives as :data:`SelectedWaveforms`, 

2149 a list of :class:`~pyVHDLModel.Common.SelectedWaveform`. The model holds them in a list and has 

2150 no distinct field per alternative, so the markers below name list elements. 

2151 

2152 .. admonition:: Example 

2153 

2154 .. code-block:: VHDL 

2155 

2156 lbl : with sel select q <= '1' when '0', '0' when others; 

2157 --^^^ <- optional Label 

2158 -- ^^^ <- Expression 

2159 -- ^ <- Target 

2160 -- ^^^^^^^^^^^^ <- SelectedWaveforms[0] 

2161 -- ^^^^^^^^^^^^^^^ <- SelectedWaveforms[1] 

2162 

2163 .. seealso:: 

2164 

2165 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialSelectedSignalAssignment>` 

2166 * :class:`Selected waveform <pyVHDLModel.Common.SelectedWaveform>` 

2167 """ 

2168 

2169 def __init__( 

2170 self, 

2171 label: Nullable[str], 

2172 target: SignalSymbol, 

2173 expression: ExpressionUnion, 

2174 selectedWaveforms: Iterable[SelectedWaveform], 

2175 parent: Nullable[ModelEntity] = None 

2176 ) -> None: 

2177 """ 

2178 Initializes a selected concurrent signal assignment. 

2179 

2180 :param label: The label of a model entity. 

2181 :param target: Reference to the assignment's destination. 

2182 :param expression: The selector expression. 

2183 :param selectedWaveforms: All alternatives, in order. 

2184 :param parent: The parent model entity of this entity. 

2185 """ 

2186 super().__init__(label, target, parent) 

2187 ExpressionMixin.__init__(self, expression) 

2188 SelectedWaveformsMixin.__init__(self, selectedWaveforms) 

2189 

2190 def Visit(self, visitor: Visitor) -> None: 

2191 """ 

2192 Walk this selected signal assignment, its selector, its target and its alternatives with a visitor. 

2193 

2194 :param visitor: The visitor receiving the events. 

2195 """ 

2196 visitor.VisitConcurrentSelectedSignalAssignment(self) 

2197 self._expression.Visit(visitor) 

2198 visitor.VisitSelect(self) 

2199 self._target.Visit(visitor) 

2200 visitor.VisitSignalAssignment(self) 

2201 self._VisitSelectedWaveforms(visitor) 

2202 visitor.DepartConcurrentSelectedSignalAssignment(self) 

2203 

2204 

2205@export 

2206class ConcurrentConditionalSignalAssignment(ConcurrentSignalAssignment, ConditionalWaveformsMixin): 

2207 """ 

2208 Represents a conditional concurrent signal assignment. 

2209 

2210 The alternatives are available as :data:`ConditionalWaveforms`, a list of 

2211 :class:`~pyVHDLModel.Common.ConditionalWaveform`. The model holds them in a list and has no 

2212 distinct field per alternative, so the markers below name list elements. 

2213 

2214 .. admonition:: Example 

2215 

2216 .. code-block:: VHDL 

2217 

2218 lbl : q <= '1' when cond else '0'; 

2219 --^^^ <- optional Label 

2220 -- ^ <- Target 

2221 -- ^^^^^^^^^^^^^ <- ConditionalWaveforms[0] 

2222 -- ^^^ <- ConditionalWaveforms[1] 

2223 

2224 .. seealso:: 

2225 

2226 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialConditionalSignalAssignment>` 

2227 * :class:`Conditional waveform <pyVHDLModel.Common.ConditionalWaveform>` 

2228 """ 

2229 

2230 def __init__( 

2231 self, 

2232 label: Nullable[str], 

2233 target: SignalSymbol, 

2234 conditionalWaveforms: Iterable[ConditionalWaveform], 

2235 parent: Nullable[ModelEntity] = None 

2236 ) -> None: 

2237 """ 

2238 Initializes a conditional concurrent signal assignment. 

2239 

2240 :param label: The label of a model entity. 

2241 :param target: Reference to the assignment's destination. 

2242 :param conditionalWaveforms: All alternatives, in order. 

2243 :param parent: The parent model entity of this entity. 

2244 """ 

2245 super().__init__(label, target, parent) 

2246 ConditionalWaveformsMixin.__init__(self, conditionalWaveforms) 

2247 

2248 def Visit(self, visitor: Visitor) -> None: 

2249 """ 

2250 Walk this conditional signal assignment, its target and its alternatives with a visitor. 

2251 

2252 :param visitor: The visitor receiving the events. 

2253 """ 

2254 visitor.VisitConcurrentConditionalSignalAssignment(self) 

2255 self._target.Visit(visitor) 

2256 visitor.VisitSignalAssignment(self) 

2257 self._VisitConditionalWaveforms(visitor) 

2258 visitor.DepartConcurrentConditionalSignalAssignment(self) 

2259 

2260 

2261@export 

2262class ConcurrentAssertStatement(ConcurrentStatement, AssertStatementMixin): 

2263 """ 

2264 Represents a concurrent assertion statement. 

2265 

2266 The checked condition is available as :data:`Condition`, the optional report string as 

2267 :data:`Message` and the optional severity as :data:`Severity`. 

2268 

2269 .. admonition:: Example 

2270 

2271 .. code-block:: VHDL 

2272 

2273 lbl : assert cond report "bad" severity note; 

2274 --^^^ <- optional Label 

2275 -- ^^^^ <- Condition 

2276 -- ^^^^^ <- optional Message 

2277 -- ^^^^ <- optional Severity 

2278 

2279 .. seealso:: 

2280 

2281 * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialAssertStatement>` 

2282 """ 

2283 def __init__( 

2284 self, 

2285 condition: ExpressionUnion, 

2286 message: Nullable[ExpressionUnion] = None, 

2287 severity: Nullable[ExpressionUnion] = None, 

2288 label: Nullable[str] = None, 

2289 parent: Nullable[ModelEntity] = None 

2290 ) -> None: 

2291 """ 

2292 Initializes a concurrent assertion statement. 

2293 

2294 :param condition: The condition guarding this statement. 

2295 :param message: The reported message, or ``None`` if none was given. 

2296 :param severity: The reported severity level, or ``None`` if none was given. 

2297 :param label: The label of a model entity. 

2298 :param parent: The parent model entity of this entity. 

2299 """ 

2300 super().__init__(label, parent) 

2301 AssertStatementMixin.__init__(self, condition, message, severity) 

2302 

2303 def Visit(self, visitor: Visitor) -> None: 

2304 """ 

2305 Walk this concurrent assertion, its condition, its message and its severity with a visitor. 

2306 

2307 :param visitor: The visitor receiving the events. 

2308 """ 

2309 visitor.VisitConcurrentAssertStatement(self) 

2310 self._VisitAssertion(visitor) 

2311 visitor.DepartConcurrentAssertStatement(self)