Coverage for pyVHDLModel/Concurrent.py: 52%

363 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-20 22:13 +0000

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

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

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

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

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

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

7# |_| |___/ # 

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

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

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

14# Copyright 2017-2024 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 

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: 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: 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: 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: 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: 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: 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): 

334 _portItems: List[PortInterfaceItemMixin] 

335 

336 def __init__( 

337 self, 

338 label: str, 

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

340 declaredItems: Nullable[Iterable] = None, 

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

342 documentation: Nullable[str] = None, 

343 parent: ModelEntity = None 

344 ) -> None: 

345 super().__init__(label, parent) 

346 BlockStatementMixin.__init__(self) 

347 LabeledEntityMixin.__init__(self, label) 

348 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

349 ConcurrentStatementsMixin.__init__(self, statements) 

350 DocumentedEntityMixin.__init__(self, documentation) 

351 

352 # TODO: extract to mixin 

353 self._portItems = [] 

354 if portItems is not None: 

355 for item in portItems: 

356 self._portItems.append(item) 

357 item._parent = self 

358 

359 @property 

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

361 return self._portItems 

362 

363 

364@export 

365class GenerateBranch(ModelEntity, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin): 

366 """ 

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

368 

369 .. seealso:: 

370 

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

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

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

374 """ 

375 

376 _alternativeLabel: Nullable[str] 

377 _normalizedAlternativeLabel: Nullable[str] 

378 

379 _namespace: Namespace 

380 

381 def __init__( 

382 self, 

383 declaredItems: Nullable[Iterable] = None, 

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

385 alternativeLabel: Nullable[str] = None, 

386 parent: ModelEntity = None 

387 ) -> None: 

388 super().__init__(parent) 

389 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

390 ConcurrentStatementsMixin.__init__(self, statements) 

391 

392 self._alternativeLabel = alternativeLabel 

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

394 

395 self._namespace = Namespace(self._normalizedAlternativeLabel) 

396 

397 @property 

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

399 return self._alternativeLabel 

400 

401 @property 

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

403 return self._normalizedAlternativeLabel 

404 

405 

406@export 

407class IfGenerateBranch(GenerateBranch, IfBranchMixin): 

408 """ 

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

410 

411 .. admonition:: Example 

412 

413 .. code-block:: VHDL 

414 

415 gen: if condition generate 

416 -- concurrent declarations 

417 begin 

418 -- concurrent statements 

419 elsif condition generate 

420 -- ... 

421 else generate 

422 -- ... 

423 end generate; 

424 """ 

425 

426 def __init__( 

427 self, 

428 condition: ExpressionUnion, 

429 declaredItems: Nullable[Iterable] = None, 

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

431 alternativeLabel: Nullable[str] = None, 

432 parent: ModelEntity = None 

433 ) -> None: 

434 super().__init__(declaredItems, statements, alternativeLabel, parent) 

435 IfBranchMixin.__init__(self, condition) 

436 

437 

438@export 

439class ElsifGenerateBranch(GenerateBranch, ElsifBranchMixin): 

440 """ 

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

442 

443 .. admonition:: Example 

444 

445 .. code-block:: VHDL 

446 

447 gen: if condition generate 

448 -- ... 

449 elsif condition generate 

450 -- concurrent declarations 

451 begin 

452 -- concurrent statements 

453 else generate 

454 -- ... 

455 end generate; 

456 """ 

457 

458 def __init__( 

459 self, 

460 condition: ExpressionUnion, 

461 declaredItems: Nullable[Iterable] = None, 

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

463 alternativeLabel: Nullable[str] = None, 

464 parent: ModelEntity = None 

465 ) -> None: 

466 super().__init__(declaredItems, statements, alternativeLabel, parent) 

467 ElsifBranchMixin.__init__(self, condition) 

468 

469 

470@export 

471class ElseGenerateBranch(GenerateBranch, ElseBranchMixin): 

472 """ 

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

474 

475 .. admonition:: Example 

476 

477 .. code-block:: VHDL 

478 

479 gen: if condition generate 

480 -- ... 

481 elsif condition generate 

482 -- ... 

483 else generate 

484 -- concurrent declarations 

485 begin 

486 -- concurrent statements 

487 end generate; 

488 """ 

489 

490 def __init__( 

491 self, 

492 declaredItems: Nullable[Iterable] = None, 

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

494 alternativeLabel: Nullable[str] = None, 

495 parent: ModelEntity = None 

496 ) -> None: 

497 super().__init__(declaredItems, statements, alternativeLabel, parent) 

498 ElseBranchMixin.__init__(self) 

499 

500 

501@export 

502class GenerateStatement(ConcurrentStatement): 

503 """ 

504 A base-class for all generate statements. 

505 

506 .. seealso:: 

507 

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

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

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

511 """ 

512 

513 _namespace: Namespace 

514 

515 def __init__( 

516 self, 

517 label: Nullable[str] = None, 

518 parent: ModelEntity = None 

519 ) -> None: 

520 super().__init__(label, parent) 

521 

522 self._namespace = Namespace(self._normalizedLabel) 

523 

524 # @mustoverride 

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

526 raise NotImplementedError() 

527 

528 # @mustoverride 

529 def IndexStatement(self) -> None: 

530 raise NotImplementedError() 

531 

532 

533@export 

534class IfGenerateStatement(GenerateStatement): 

535 """ 

536 Represents an if...generate statement. 

537 

538 .. admonition:: Example 

539 

540 .. code-block:: VHDL 

541 

542 gen: if condition generate 

543 -- ... 

544 elsif condition generate 

545 -- ... 

546 else generate 

547 -- ... 

548 end generate; 

549 

550 .. seealso:: 

551 

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

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

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

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

556 """ 

557 

558 _ifBranch: IfGenerateBranch 

559 _elsifBranches: List[ElsifGenerateBranch] 

560 _elseBranch: Nullable[ElseGenerateBranch] 

561 

562 def __init__( 

563 self, 

564 label: str, 

565 ifBranch: IfGenerateBranch, 

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

567 elseBranch: Nullable[ElseGenerateBranch] = None, 

568 parent: ModelEntity = None 

569 ) -> None: 

570 super().__init__(label, parent) 

571 

572 self._ifBranch = ifBranch 

573 ifBranch._parent = self 

574 

575 self._elsifBranches = [] 

576 if elsifBranches is not None: 

577 for branch in elsifBranches: 

578 self._elsifBranches.append(branch) 

579 branch._parent = self 

580 

581 if elseBranch is not None: 

582 self._elseBranch = elseBranch 

583 elseBranch._parent = self 

584 else: 

585 self._elseBranch = None 

586 

587 @property 

588 def IfBranch(self) -> IfGenerateBranch: 

589 return self._ifBranch 

590 

591 @property 

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

593 return self._elsifBranches 

594 

595 @property 

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

597 return self._elseBranch 

598 

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

600 yield from self._ifBranch.IterateInstantiations() 

601 for branch in self._elsifBranches: 

602 yield from branch.IterateInstantiations() 

603 if self._elseBranch is not None: 

604 yield from self._ifBranch.IterateInstantiations() 

605 

606 def IndexStatement(self) -> None: 

607 self._ifBranch.IndexStatements() 

608 for branch in self._elsifBranches: 

609 branch.IndexStatements() 

610 if self._elseBranch is not None: 

611 self._elseBranch.IndexStatements() 

612 

613 

614@export 

615class ConcurrentChoice(BaseChoice): 

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

617 

618 

619@export 

620class IndexedGenerateChoice(ConcurrentChoice): 

621 _expression: ExpressionUnion 

622 

623 def __init__(self, expression: ExpressionUnion, parent: ModelEntity = None) -> None: 

624 super().__init__(parent) 

625 

626 self._expression = expression 

627 expression._parent = self 

628 

629 @property 

630 def Expression(self) -> ExpressionUnion: 

631 return self._expression 

632 

633 def __str__(self) -> str: 

634 return str(self._expression) 

635 

636 

637@export 

638class RangedGenerateChoice(ConcurrentChoice): 

639 _range: 'Range' 

640 

641 def __init__(self, rng: 'Range', parent: ModelEntity = None) -> None: 

642 super().__init__(parent) 

643 

644 self._range = rng 

645 rng._parent = self 

646 

647 @property 

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

649 return self._range 

650 

651 def __str__(self) -> str: 

652 return str(self._range) 

653 

654 

655@export 

656class ConcurrentCase(BaseCase, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin): 

657 def __init__( 

658 self, 

659 declaredItems: Nullable[Iterable] = None, 

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

661 alternativeLabel: Nullable[str] = None, 

662 parent: ModelEntity = None 

663 ) -> None: 

664 super().__init__(parent) 

665 LabeledEntityMixin.__init__(self, alternativeLabel) 

666 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

667 ConcurrentStatementsMixin.__init__(self, statements) 

668 

669 

670@export 

671class GenerateCase(ConcurrentCase): 

672 _choices: List[ConcurrentChoice] 

673 

674 def __init__( 

675 self, 

676 choices: Iterable[ConcurrentChoice], 

677 declaredItems: Nullable[Iterable] = None, 

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

679 alternativeLabel: Nullable[str] = None, 

680 parent: ModelEntity = None 

681 ) -> None: 

682 super().__init__(declaredItems, statements, alternativeLabel, parent) 

683 

684 # TODO: move to parent or grandparent 

685 self._choices = [] 

686 if choices is not None: 

687 for choice in choices: 

688 self._choices.append(choice) 

689 choice._parent = self 

690 

691 # TODO: move to parent or grandparent 

692 @property 

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

694 return self._choices 

695 

696 def __str__(self) -> str: 

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

698 

699 

700@export 

701class OthersGenerateCase(ConcurrentCase): 

702 def __str__(self) -> str: 

703 return "when others =>" 

704 

705 

706@export 

707class CaseGenerateStatement(GenerateStatement): 

708 """ 

709 Represents a case...generate statement. 

710 

711 .. admonition:: Example 

712 

713 .. code-block:: VHDL 

714 

715 gen: case selector generate 

716 case choice1 => 

717 -- ... 

718 case choice2 => 

719 -- ... 

720 case others => 

721 -- ... 

722 end generate; 

723 """ 

724 

725 _expression: ExpressionUnion 

726 _cases: List[GenerateCase] 

727 

728 def __init__( 

729 self, 

730 label: str, 

731 expression: ExpressionUnion, 

732 cases: Iterable[ConcurrentCase], 

733 parent: ModelEntity = None 

734 ) -> None: 

735 super().__init__(label, parent) 

736 

737 self._expression = expression 

738 expression._parent = self 

739 

740 # TODO: create a mixin for things with cases 

741 self._cases = [] 

742 if cases is not None: 

743 for case in cases: 

744 self._cases.append(case) 

745 case._parent = self 

746 

747 @property 

748 def SelectExpression(self) -> ExpressionUnion: 

749 return self._expression 

750 

751 @property 

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

753 return self._cases 

754 

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

756 for case in self._cases: 

757 yield from case.IterateInstantiations() 

758 

759 def IndexStatement(self) -> None: 

760 for case in self._cases: 

761 case.IndexStatements() 

762 

763 

764@export 

765class ForGenerateStatement(GenerateStatement, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin): 

766 """ 

767 Represents a for...generate statement. 

768 

769 .. admonition:: Example 

770 

771 .. code-block:: VHDL 

772 

773 gen: for i in 0 to 3 generate 

774 -- ... 

775 end generate; 

776 """ 

777 

778 _loopIndex: str 

779 _range: Range 

780 

781 def __init__( 

782 self, 

783 label: str, 

784 loopIndex: str, 

785 rng: Range, 

786 declaredItems: Nullable[Iterable] = None, 

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

788 parent: ModelEntity = None 

789 ) -> None: 

790 super().__init__(label, parent) 

791 ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) 

792 ConcurrentStatementsMixin.__init__(self, statements) 

793 

794 self._loopIndex = loopIndex 

795 

796 self._range = rng 

797 rng._parent = self 

798 

799 @property 

800 def LoopIndex(self) -> str: 

801 return self._loopIndex 

802 

803 @property 

804 def Range(self) -> Range: 

805 return self._range 

806 

807 # IndexDeclaredItems = ConcurrentStatements.IndexDeclaredItems 

808 

809 def IndexStatement(self) -> None: 

810 self.IndexStatements() 

811 

812 def IndexStatements(self) -> None: 

813 super().IndexStatements() 

814 

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

816 return ConcurrentStatementsMixin.IterateInstantiations(self) 

817 

818 

819@export 

820class ConcurrentSignalAssignment(ConcurrentStatement, SignalAssignmentMixin): 

821 """ 

822 A base-class for concurrent signal assignments. 

823 

824 .. seealso:: 

825 

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

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

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

829 """ 

830 def __init__(self, label: str, target: Name, parent: ModelEntity = None) -> None: 

831 super().__init__(label, parent) 

832 SignalAssignmentMixin.__init__(self, target) 

833 

834 

835@export 

836class ConcurrentSimpleSignalAssignment(ConcurrentSignalAssignment): 

837 _waveform: List[WaveformElement] 

838 

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

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

841 

842 # TODO: extract to mixin 

843 self._waveform = [] 

844 if waveform is not None: 

845 for waveformElement in waveform: 

846 self._waveform.append(waveformElement) 

847 waveformElement._parent = self 

848 

849 @property 

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

851 return self._waveform 

852 

853 

854@export 

855class ConcurrentSelectedSignalAssignment(ConcurrentSignalAssignment): 

856 def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: ModelEntity = None) -> None: 

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

858 

859 

860@export 

861class ConcurrentConditionalSignalAssignment(ConcurrentSignalAssignment): 

862 def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: ModelEntity = None) -> None: 

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

864 

865 

866@export 

867class ConcurrentAssertStatement(ConcurrentStatement, AssertStatementMixin): 

868 def __init__( 

869 self, 

870 condition: ExpressionUnion, 

871 message: ExpressionUnion, 

872 severity: Nullable[ExpressionUnion] = None, 

873 label: Nullable[str] = None, 

874 parent: ModelEntity = None 

875 ) -> None: 

876 super().__init__(label, parent) 

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