Coverage for pyVHDLModel/Concurrent.py: 45%

374 statements  

« prev     ^ index     » next       coverage.py v7.15.1, created at 2026-07-13 17:58 +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 typing import List, Dict, Union, Iterable, Generator, Optional as Nullable 

38 

39from pyTooling.Decorators import export, readonly 

40from pyTooling.MetaClasses import ExtendedType 

41 

42from pyVHDLModel.Base import ModelEntity, LabeledEntityMixin, DocumentedEntityMixin, Range, BaseChoice, BaseCase, IfBranchMixin 

43from pyVHDLModel.Base import ElsifBranchMixin, ElseBranchMixin, AssertStatementMixin, BlockStatementMixin, WaveformElement 

44from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin 

45from pyVHDLModel.Namespace import Namespace 

46from pyVHDLModel.Name import Name 

47from pyVHDLModel.Symbol import ComponentInstantiationSymbol, EntityInstantiationSymbol, ArchitectureSymbol, ConfigurationInstantiationSymbol 

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

49from pyVHDLModel.Association import AssociationItem, ParameterAssociationItem 

50from pyVHDLModel.Interface import PortInterfaceItemMixin 

51from pyVHDLModel.Common import Statement, ProcedureCallMixin, SignalAssignmentMixin, AllowBlackboxMixin 

52from pyVHDLModel.Sequential import SequentialStatement, SequentialStatementsMixin, SequentialDeclarationsMixin 

53 

54 

55ExpressionUnion = Union[ 

56 BaseExpression, 

57 QualifiedExpression, 

58 FunctionCall, 

59 TypeConversion, 

60 # ConstantOrSymbol, TODO: ObjectSymbol 

61 Literal, 

62] 

63 

64 

65@export 

66class ConcurrentStatement(Statement): 

67 """A base-class for all concurrent statements.""" 

68 

69 

70@export 

71class ConcurrentStatementsMixin(metaclass=ExtendedType, mixin=True): 

72 """ 

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

74 

75 .. seealso:: 

76 

77 .. todo:: concurrent declaration region 

78 """ 

79 

80 _statements: List[ConcurrentStatement] 

81 

82 _instantiations: Dict[str, 'Instantiation'] # TODO: add another instantiation class level for entity/configuration/component inst. 

83 _blocks: Dict[str, 'ConcurrentBlockStatement'] 

84 _generates: Dict[str, 'GenerateStatement'] 

85 _hierarchy: Dict[str, Union['ConcurrentBlockStatement', 'GenerateStatement']] 

86 

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

88 self._statements = [] 

89 

90 self._instantiations = {} 

91 self._blocks = {} 

92 self._generates = {} 

93 self._hierarchy = {} 

94 

95 if statements is not None: 

96 for statement in statements: 

97 self._statements.append(statement) 

98 statement.Parent = self 

99 

100 @readonly 

101 def Statements(self) -> List[ConcurrentStatement]: 

102 return self._statements 

103 

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

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

106 yield instance 

107 

108 for block in self._blocks.values(): 108 ↛ 109line 108 didn't jump to line 109 because the loop on line 108 never started

109 yield from block.IterateInstantiations() 

110 

111 for generate in self._generates.values(): 111 ↛ 112line 111 didn't jump to line 112 because the loop on line 111 never started

112 yield from generate.IterateInstantiations() 

113 

114 # TODO: move into _init__ 

115 def IndexStatements(self) -> None: 

116 for statement in self._statements: 

117 if isinstance(statement, (EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation)): 117 ↛ 119line 117 didn't jump to line 119 because the condition on line 117 was always true

118 self._instantiations[statement.NormalizedLabel] = statement 

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

120 self._generates[statement.NormalizedLabel] = statement 

121 statement.IndexStatement() 

122 elif isinstance(statement, ConcurrentBlockStatement): 

123 self._hierarchy[statement.NormalizedLabel] = statement 

124 statement.IndexStatements() 

125 

126 

127@export 

128class Instantiation(ConcurrentStatement): 

129 """ 

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

131 """ 

132 

133 _genericAssociations: List[AssociationItem] 

134 _portAssociations: List[AssociationItem] 

135 

136 def __init__( 

137 self, 

138 label: str, 

139 genericAssociations: Nullable[Iterable[AssociationItem]] = None, 

140 portAssociations: Nullable[Iterable[AssociationItem]] = None, 

141 parent: Nullable[ModelEntity] = None 

142 ) -> None: 

143 super().__init__(label, parent) 

144 

145 # TODO: extract to mixin 

146 self._genericAssociations = [] 

147 if genericAssociations is not None: 147 ↛ 148line 147 didn't jump to line 148 because the condition on line 147 was never true

148 for association in genericAssociations: 

149 self._genericAssociations.append(association) 

150 association.Parent = self 

151 

152 # TODO: extract to mixin 

153 self._portAssociations = [] 

154 if portAssociations is not None: 154 ↛ 155line 154 didn't jump to line 155 because the condition on line 154 was never true

155 for association in portAssociations: 

156 self._portAssociations.append(association) 

157 association.Parent = self 

158 

159 @readonly 

160 def GenericAssociations(self) -> List[AssociationItem]: 

161 return self._genericAssociations 

162 

163 @property 

164 def PortAssociations(self) -> List[AssociationItem]: 

165 return self._portAssociations 

166 

167 

168@export 

169class ComponentInstantiation(Instantiation): 

170 """ 

171 Represents a component instantiation by referring to a component name. 

172 

173 .. admonition:: Example 

174 

175 .. code-block:: VHDL 

176 

177 inst : component Counter; 

178 """ 

179 

180 _component: ComponentInstantiationSymbol 

181 

182 def __init__( 

183 self, 

184 label: str, 

185 componentSymbol: ComponentInstantiationSymbol, 

186 genericAssociations: Nullable[Iterable[AssociationItem]] = None, 

187 portAssociations: Nullable[Iterable[AssociationItem]] = None, 

188 parent: Nullable[ModelEntity] = None 

189 ) -> None: 

190 super().__init__(label, genericAssociations, portAssociations, parent) 

191 

192 self._component = componentSymbol 

193 componentSymbol.Parent = self 

194 

195 @property 

196 def Component(self) -> ComponentInstantiationSymbol: 

197 return self._component 

198 

199 

200@export 

201class EntityInstantiation(Instantiation): 

202 """ 

203 Represents an entity instantiation by referring to an entity name with optional architecture name. 

204 

205 .. admonition:: Example 

206 

207 .. code-block:: VHDL 

208 

209 inst : entity work. Counter; 

210 """ 

211 

212 _entity: EntityInstantiationSymbol 

213 _architecture: ArchitectureSymbol 

214 

215 def __init__( 

216 self, 

217 label: str, 

218 entitySymbol: EntityInstantiationSymbol, 

219 architectureSymbol: Nullable[ArchitectureSymbol] = None, 

220 genericAssociations: Nullable[Iterable[AssociationItem]] = None, 

221 portAssociations: Nullable[Iterable[AssociationItem]] = None, 

222 parent: Nullable[ModelEntity] = None 

223 ) -> None: 

224 super().__init__(label, genericAssociations, portAssociations, parent) 

225 

226 self._entity = entitySymbol 

227 entitySymbol.Parent = self 

228 

229 self._architecture = architectureSymbol 

230 if architectureSymbol is not None: 230 ↛ 231line 230 didn't jump to line 231 because the condition on line 230 was never true

231 architectureSymbol.Parent = self 

232 

233 @property 

234 def Entity(self) -> EntityInstantiationSymbol: 

235 return self._entity 

236 

237 @property 

238 def Architecture(self) -> ArchitectureSymbol: 

239 return self._architecture 

240 

241 

242@export 

243class ConfigurationInstantiation(Instantiation): 

244 """ 

245 Represents a configuration instantiation by referring to a configuration name. 

246 

247 .. admonition:: Example 

248 

249 .. code-block:: VHDL 

250 

251 inst : configuration Counter; 

252 """ 

253 

254 _configuration: ConfigurationInstantiationSymbol 

255 

256 def __init__( 

257 self, 

258 label: str, 

259 configurationSymbol: ConfigurationInstantiationSymbol, 

260 genericAssociations: Nullable[Iterable[AssociationItem]] = None, 

261 portAssociations: Nullable[Iterable[AssociationItem]] = None, 

262 parent: Nullable[ModelEntity] = None 

263 ) -> None: 

264 super().__init__(label, genericAssociations, portAssociations, parent) 

265 

266 self._configuration = configurationSymbol 

267 configurationSymbol.Parent = self 

268 

269 @property 

270 def Configuration(self) -> ConfigurationInstantiationSymbol: 

271 return self._configuration 

272 

273 

274@export 

275class ProcessStatement(ConcurrentStatement, SequentialDeclarationsMixin, SequentialStatementsMixin, DocumentedEntityMixin): 

276 """ 

277 Represents a process statement with sensitivity list, sequential declaration region and sequential statements. 

278 

279 .. admonition:: Example 

280 

281 .. code-block:: VHDL 

282 

283 proc: process(Clock) 

284 -- sequential declarations 

285 begin 

286 -- sequential statements 

287 end process; 

288 """ 

289 

290 _sensitivityList: List[Name] # TODO: implement a SignalSymbol 

291 

292 def __init__( 

293 self, 

294 label: Nullable[str] = None, 

295 declaredItems: Nullable[Iterable] = None, 

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

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

298 documentation: Nullable[str] = None, 

299 parent: Nullable[ModelEntity] = None 

300 ) -> None: 

301 super().__init__(label, parent) 

302 SequentialDeclarationsMixin.__init__(self, declaredItems) 

303 SequentialStatementsMixin.__init__(self, statements) 

304 DocumentedEntityMixin.__init__(self, documentation) 

305 

306 if sensitivityList is None: 

307 self._sensitivityList = None 

308 else: 

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

310 for signalSymbol in sensitivityList: 

311 self._sensitivityList.append(signalSymbol) 

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

313 

314 @property 

315 def SensitivityList(self) -> List[Name]: 

316 return self._sensitivityList 

317 

318 

319@export 

320class ConcurrentProcedureCall(ConcurrentStatement, ProcedureCallMixin): 

321 def __init__( 

322 self, 

323 label: str, 

324 procedureName: Name, 

325 parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None, 

326 parent: Nullable[ModelEntity] = None 

327 ) -> None: 

328 super().__init__(label, parent) 

329 ProcedureCallMixin.__init__(self, procedureName, parameterMappings) 

330 

331 

332@export 

333class ConcurrentBlockStatement(ConcurrentStatement, BlockStatementMixin, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, DocumentedEntityMixin, AllowBlackboxMixin): 

334 _portItems: List[PortInterfaceItemMixin] 

335 

336 _namespace: Namespace 

337 

338 def __init__( 

339 self, 

340 label: str, 

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

342 declaredItems: Nullable[Iterable] = None, 

343 statements: Iterable['ConcurrentStatement'] = None, 

344 documentation: Nullable[str] = None, 

345 allowBlackbox: Nullable[bool] = None, 

346 parent: Nullable[ModelEntity] = None 

347 ) -> None: 

348 super().__init__(label, parent) 

349 

350 self._namespace = Namespace(self._normalizedLabel) 

351 if parent is not None: 

352 self._namespace.ParentNamespace = parent._namespace 

353 

354 BlockStatementMixin.__init__(self) 

355 LabeledEntityMixin.__init__(self, label) 

356 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

357 ConcurrentStatementsMixin.__init__(self, statements) 

358 DocumentedEntityMixin.__init__(self, documentation) 

359 AllowBlackboxMixin.__init__(self, allowBlackbox) 

360 

361 # TODO: extract to mixin 

362 self._portItems = [] 

363 if portItems is not None: 

364 for item in portItems: 

365 self._portItems.append(item) 

366 item.Parent = self 

367 

368 @ConcurrentStatement.Parent.setter 

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

370 ConcurrentStatement.Parent.fset(self, parent) 

371 

372 self._namespace.ParentNamespace = parent._namespace 

373 

374 @property 

375 def PortItems(self) -> List[PortInterfaceItemMixin]: 

376 return self._portItems 

377 

378 

379@export 

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

381 """ 

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

383 

384 .. seealso:: 

385 

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

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

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

389 """ 

390 

391 _alternativeLabel: Nullable[str] 

392 _normalizedAlternativeLabel: Nullable[str] 

393 

394 _namespace: Namespace 

395 

396 def __init__( 

397 self, 

398 declaredItems: Nullable[Iterable] = None, 

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

400 alternativeLabel: Nullable[str] = None, 

401 allowBlackbox: Nullable[bool] = None, 

402 parent: Nullable[ModelEntity] = None 

403 ) -> None: 

404 super().__init__(parent) 

405 

406 self._alternativeLabel = alternativeLabel 

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

408 

409 self._namespace = Namespace(self._normalizedAlternativeLabel) 

410 if parent is not None: 

411 self._namespace.ParentNamespace = parent._namespace 

412 

413 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

414 ConcurrentStatementsMixin.__init__(self, statements) 

415 AllowBlackboxMixin.__init__(self, allowBlackbox) 

416 

417 @property 

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

419 return self._alternativeLabel 

420 

421 @property 

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

423 return self._normalizedAlternativeLabel 

424 

425 

426@export 

427class IfGenerateBranch(GenerateBranch, IfBranchMixin): 

428 """ 

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

430 

431 .. admonition:: Example 

432 

433 .. code-block:: VHDL 

434 

435 gen: if condition generate 

436 -- concurrent declarations 

437 begin 

438 -- concurrent statements 

439 elsif condition generate 

440 -- ... 

441 else generate 

442 -- ... 

443 end generate; 

444 """ 

445 

446 def __init__( 

447 self, 

448 condition: ExpressionUnion, 

449 declaredItems: Nullable[Iterable] = None, 

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

451 alternativeLabel: Nullable[str] = None, 

452 allowBlackbox: Nullable[bool] = None, 

453 parent: Nullable[ModelEntity] = None 

454 ) -> None: 

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

456 IfBranchMixin.__init__(self, condition) 

457 

458 

459@export 

460class ElsifGenerateBranch(GenerateBranch, ElsifBranchMixin): 

461 """ 

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

463 

464 .. admonition:: Example 

465 

466 .. code-block:: VHDL 

467 

468 gen: if condition generate 

469 -- ... 

470 elsif condition generate 

471 -- concurrent declarations 

472 begin 

473 -- concurrent statements 

474 else generate 

475 -- ... 

476 end generate; 

477 """ 

478 

479 def __init__( 

480 self, 

481 condition: ExpressionUnion, 

482 declaredItems: Nullable[Iterable] = None, 

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

484 alternativeLabel: Nullable[str] = None, 

485 allowBlackbox: Nullable[bool] = None, 

486 parent: Nullable[ModelEntity] = None 

487 ) -> None: 

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

489 ElsifBranchMixin.__init__(self, condition) 

490 

491 

492@export 

493class ElseGenerateBranch(GenerateBranch, ElseBranchMixin): 

494 """ 

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

496 

497 .. admonition:: Example 

498 

499 .. code-block:: VHDL 

500 

501 gen: if condition generate 

502 -- ... 

503 elsif condition generate 

504 -- ... 

505 else generate 

506 -- concurrent declarations 

507 begin 

508 -- concurrent statements 

509 end generate; 

510 """ 

511 

512 def __init__( 

513 self, 

514 declaredItems: Nullable[Iterable] = None, 

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

516 alternativeLabel: Nullable[str] = None, 

517 allowBlackbox: Nullable[bool] = None, 

518 parent: Nullable[ModelEntity] = None 

519 ) -> None: 

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

521 ElseBranchMixin.__init__(self) 

522 

523 

524@export 

525class GenerateStatement(ConcurrentStatement, AllowBlackboxMixin): 

526 """ 

527 A base-class for all generate statements. 

528 

529 .. seealso:: 

530 

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

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

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

534 """ 

535 

536 def __init__( 

537 self, 

538 label: Nullable[str] = None, 

539 allowBlackbox: Nullable[bool] = None, 

540 parent: Nullable[ModelEntity] = None 

541 ) -> None: 

542 super().__init__(label, parent) 

543 AllowBlackboxMixin.__init__(self, allowBlackbox) 

544 

545 # @mustoverride 

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

547 raise NotImplementedError() 

548 

549 # @mustoverride 

550 def IndexStatement(self) -> None: 

551 raise NotImplementedError() 

552 

553 

554@export 

555class IfGenerateStatement(GenerateStatement): 

556 """ 

557 Represents an if...generate statement. 

558 

559 .. admonition:: Example 

560 

561 .. code-block:: VHDL 

562 

563 gen: if condition generate 

564 -- ... 

565 elsif condition generate 

566 -- ... 

567 else generate 

568 -- ... 

569 end generate; 

570 

571 .. seealso:: 

572 

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

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

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

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

577 """ 

578 

579 _ifBranch: IfGenerateBranch 

580 _elsifBranches: List[ElsifGenerateBranch] 

581 _elseBranch: Nullable[ElseGenerateBranch] 

582 

583 def __init__( 

584 self, 

585 label: str, 

586 ifBranch: IfGenerateBranch, 

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

588 elseBranch: Nullable[ElseGenerateBranch] = None, 

589 allowBlackbox: Nullable[bool] = None, 

590 parent: Nullable[ModelEntity] = None 

591 ) -> None: 

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

593 

594 self._ifBranch = ifBranch 

595 ifBranch.Parent = self 

596 

597 self._elsifBranches = [] 

598 if elsifBranches is not None: 

599 for branch in elsifBranches: 

600 self._elsifBranches.append(branch) 

601 branch.Parent = self 

602 

603 if elseBranch is not None: 

604 self._elseBranch = elseBranch 

605 elseBranch.Parent = self 

606 else: 

607 self._elseBranch = None 

608 

609 @GenerateStatement.Parent.setter 

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

611 from pyVHDLModel.DesignUnit import Architecture 

612 

613 GenerateStatement.Parent.fset(self, parent) 

614 

615 # Connect namespaces 

616 namespace = self._ifBranch._namespace 

617 namespace.ParentNamespace = parent._namespace 

618 if namespace._name == "": 

619 namespace._name = self._normalizedLabel 

620 

621 for elseBranch in self._elsifBranches: 

622 elseBranch._namespace.ParentNamespace = parent._namespace 

623 

624 if self._elseBranch is not None: 

625 self._elseBranch._namespace.ParentNamespace = parent._namespace 

626 

627 @property 

628 def IfBranch(self) -> IfGenerateBranch: 

629 return self._ifBranch 

630 

631 @property 

632 def ElsifBranches(self) -> List[ElsifGenerateBranch]: 

633 return self._elsifBranches 

634 

635 @property 

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

637 return self._elseBranch 

638 

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

640 yield from self._ifBranch.IterateInstantiations() 

641 for branch in self._elsifBranches: 

642 yield from branch.IterateInstantiations() 

643 if self._elseBranch is not None: 

644 yield from self._ifBranch.IterateInstantiations() 

645 

646 def IndexStatement(self) -> None: 

647 self._ifBranch.IndexStatements() 

648 for branch in self._elsifBranches: 

649 branch.IndexStatements() 

650 if self._elseBranch is not None: 

651 self._elseBranch.IndexStatements() 

652 

653 

654@export 

655class ConcurrentChoice(BaseChoice): 

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

657 

658 

659@export 

660class IndexedGenerateChoice(ConcurrentChoice): 

661 _expression: ExpressionUnion 

662 

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

664 super().__init__(parent) 

665 

666 self._expression = expression 

667 expression.Parent = self 

668 

669 @property 

670 def Expression(self) -> ExpressionUnion: 

671 return self._expression 

672 

673 def __str__(self) -> str: 

674 return str(self._expression) 

675 

676 

677@export 

678class RangedGenerateChoice(ConcurrentChoice): 

679 _range: 'Range' 

680 

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

682 super().__init__(parent) 

683 

684 self._range = rng 

685 rng.Parent = self 

686 

687 @property 

688 def Range(self) -> 'Range': 

689 return self._range 

690 

691 def __str__(self) -> str: 

692 return str(self._range) 

693 

694 

695@export 

696class ConcurrentCase(BaseCase, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin): 

697 _namespace: Namespace 

698 

699 def __init__( 

700 self, 

701 declaredItems: Nullable[Iterable] = None, 

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

703 alternativeLabel: Nullable[str] = None, 

704 allowBlackbox: Nullable[bool] = None, 

705 parent: Nullable[ModelEntity] = None 

706 ) -> None: 

707 super().__init__(parent) 

708 LabeledEntityMixin.__init__(self, alternativeLabel) 

709 

710 # TODO: Why not handover self? 

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

712 # TODO: How about a WithNamespaceMixin class? 

713 self._namespace = Namespace(self._normalizedLabel) 

714 if parent is not None: 

715 self._namespace.ParentNamespace = parent._namespace 

716 

717 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

718 ConcurrentStatementsMixin.__init__(self, statements) 

719 AllowBlackboxMixin.__init__(self, allowBlackbox) 

720 

721 

722@export 

723class GenerateCase(ConcurrentCase): 

724 _choices: List[ConcurrentChoice] 

725 

726 def __init__( 

727 self, 

728 choices: Iterable[ConcurrentChoice], 

729 declaredItems: Nullable[Iterable] = None, 

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

731 alternativeLabel: Nullable[str] = None, 

732 allowBlackbox: Nullable[bool] = None, 

733 parent: Nullable[ModelEntity] = None 

734 ) -> None: 

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

736 

737 # TODO: move to parent or grandparent 

738 self._choices = [] 

739 if choices is not None: 

740 for choice in choices: 

741 self._choices.append(choice) 

742 choice.Parent = self 

743 

744 # TODO: move to parent or grandparent 

745 @property 

746 def Choices(self) -> List[ConcurrentChoice]: 

747 return self._choices 

748 

749 def __str__(self) -> str: 

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

751 

752 

753@export 

754class OthersGenerateCase(ConcurrentCase): 

755 def __str__(self) -> str: 

756 return "when others =>" 

757 

758 

759@export 

760class CaseGenerateStatement(GenerateStatement): 

761 """ 

762 Represents a case...generate statement. 

763 

764 .. admonition:: Example 

765 

766 .. code-block:: VHDL 

767 

768 gen: case selector generate 

769 case choice1 => 

770 -- ... 

771 case choice2 => 

772 -- ... 

773 case others => 

774 -- ... 

775 end generate; 

776 """ 

777 

778 _expression: ExpressionUnion 

779 _cases: List[GenerateCase] 

780 

781 def __init__( 

782 self, 

783 label: str, 

784 expression: ExpressionUnion, 

785 cases: Iterable[ConcurrentCase], 

786 allowBlackbox: Nullable[bool] = None, 

787 parent: Nullable[ModelEntity] = None 

788 ) -> None: 

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

790 

791 self._expression = expression 

792 expression.Parent = self 

793 

794 # TODO: create a mixin for things with cases 

795 self._cases = [] 

796 if cases is not None: 

797 for case in cases: 

798 self._cases.append(case) 

799 case.Parent = self 

800 

801 @GenerateStatement.Parent.setter 

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

803 GenerateStatement.Parent.fset(self, parent) 

804 

805 # Connect namespaces 

806 for case in self._cases: 

807 case._namespace.ParentNamespace = parent._namespace 

808 

809 @property 

810 def SelectExpression(self) -> ExpressionUnion: 

811 return self._expression 

812 

813 @property 

814 def Cases(self) -> List[GenerateCase]: 

815 return self._cases 

816 

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

818 for case in self._cases: 

819 yield from case.IterateInstantiations() 

820 

821 def IndexStatement(self) -> None: 

822 for case in self._cases: 

823 case.IndexStatements() 

824 

825 

826@export 

827class ForGenerateStatement(GenerateStatement, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin): 

828 """ 

829 Represents a for...generate statement. 

830 

831 .. admonition:: Example 

832 

833 .. code-block:: VHDL 

834 

835 gen: for i in 0 to 3 generate 

836 -- ... 

837 end generate; 

838 """ 

839 

840 _loopIndex: str 

841 _range: Range 

842 

843 _namespace: Namespace 

844 

845 def __init__( 

846 self, 

847 label: str, 

848 loopIndex: str, 

849 rng: Range, 

850 declaredItems: Nullable[Iterable] = None, 

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

852 allowBlackbox: Nullable[bool] = None, 

853 parent: Nullable[ModelEntity] = None 

854 ) -> None: 

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

856 

857 self._namespace = Namespace(self._normalizedLabel) 

858 if parent is not None: 

859 self._namespace.ParentNamespace = parent._namespace 

860 

861 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

862 ConcurrentStatementsMixin.__init__(self, statements) 

863 

864 self._loopIndex = loopIndex 

865 

866 self._range = rng 

867 rng.Parent = self 

868 

869 @GenerateStatement.Parent.setter 

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

871 GenerateStatement.Parent.fset(self, parent) 

872 

873 self._namespace.ParentNamespace = parent._namespace 

874 

875 @property 

876 def LoopIndex(self) -> str: 

877 return self._loopIndex 

878 

879 @property 

880 def Range(self) -> Range: 

881 return self._range 

882 

883 # IndexDeclaredItems = ConcurrentStatements.IndexDeclaredItems 

884 

885 def IndexStatement(self) -> None: 

886 self.IndexStatements() 

887 

888 def IndexStatements(self) -> None: 

889 super().IndexStatements() 

890 

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

892 return ConcurrentStatementsMixin.IterateInstantiations(self) 

893 

894 

895@export 

896class ConcurrentSignalAssignment(ConcurrentStatement, SignalAssignmentMixin): 

897 """ 

898 A base-class for concurrent signal assignments. 

899 

900 .. seealso:: 

901 

902 * :class:`~pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment` 

903 * :class:`~pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment` 

904 * :class:`~pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment` 

905 """ 

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

907 super().__init__(label, parent) 

908 SignalAssignmentMixin.__init__(self, target) 

909 

910 

911@export 

912class ConcurrentSimpleSignalAssignment(ConcurrentSignalAssignment): 

913 _waveform: List[WaveformElement] 

914 

915 def __init__(self, label: str, target: Name, waveform: Iterable[WaveformElement], parent: Nullable[ModelEntity] = None) -> None: 

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

917 

918 # TODO: extract to mixin 

919 self._waveform = [] 

920 if waveform is not None: 

921 for waveformElement in waveform: 

922 self._waveform.append(waveformElement) 

923 waveformElement.Parent = self 

924 

925 @property 

926 def Waveform(self) -> List[WaveformElement]: 

927 return self._waveform 

928 

929 

930@export 

931class ConcurrentSelectedSignalAssignment(ConcurrentSignalAssignment): 

932 def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None: 

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

934 

935 

936@export 

937class ConcurrentConditionalSignalAssignment(ConcurrentSignalAssignment): 

938 def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None: 

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

940 

941 

942@export 

943class ConcurrentAssertStatement(ConcurrentStatement, AssertStatementMixin): 

944 def __init__( 

945 self, 

946 condition: ExpressionUnion, 

947 message: ExpressionUnion, 

948 severity: Nullable[ExpressionUnion] = None, 

949 label: Nullable[str] = None, 

950 parent: Nullable[ModelEntity] = None 

951 ) -> None: 

952 super().__init__(label, parent) 

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