Coverage for pyVHDLModel/Configuration.py: 98%

156 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 2026-2026 Patrick Lehmann - Boetzingen, Germany # 

15# # 

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

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

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

19# # 

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

21# # 

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

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

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

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

26# limitations under the License. # 

27# # 

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

29# ==================================================================================================================== # 

30# 

31""" 

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

33 

34Configurations: entity aspects, binding indications, component configurations (and the structurally 

35identical configuration specifications), and block configurations. 

36""" 

37from __future__ import annotations 

38 

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

40 

41from pyTooling.Decorators import export, readonly 

42from pyTooling.MetaClasses import abstractclass 

43 

44from pyVHDLModel.Base import ModelEntity 

45from pyVHDLModel.Name import Name 

46from pyVHDLModel.Symbol import Symbol, EntitySymbol, ArchitectureSymbol, ConfigurationSymbol, \ 

47 ComponentInstantiationSymbol 

48from pyVHDLModel.Association import GenericAssociationItem, PortAssociationItem, GenericMapAspectMixin, \ 

49 PortMapAspectMixin 

50 

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

52 from pyVHDLModel.Visitor import Visitor 

53 

54 

55@export 

56@abstractclass 

57class EntityAspect(ModelEntity): 

58 """ 

59 Base-class for the three forms an entity aspect can take in a binding indication: an entity 

60 (optionally with an architecture), a configuration, or ``open``. 

61 

62 .. admonition:: Example 

63 

64 .. code-block:: VHDL 

65 

66 for U1 : comp use entity work.sub(behav); 

67 -- ^^^^^^^^^^^^^^^^^^^^^^ 

68 

69 .. seealso:: 

70 

71 * :class:`Entity aspect entity <pyVHDLModel.Configuration.EntityAspectEntity>` 

72 * :class:`Entity aspect configuration <pyVHDLModel.Configuration.EntityAspectConfiguration>` 

73 * :class:`Entity aspect open <pyVHDLModel.Configuration.EntityAspectOpen>` 

74 """ 

75 

76 

77@export 

78class EntityAspectEntity(EntityAspect): 

79 """ 

80 Represents an entity aspect naming an entity, optionally with an architecture. 

81 

82 .. admonition:: Example 

83 

84 .. code-block:: VHDL 

85 

86 use entity work.e_rest(rtl); 

87 -- ^^^^^^^^^^^ <- Entity 

88 -- ^^^ <- Architecture 

89 """ 

90 

91 _entity: EntitySymbol #: Reference to the named entity. 

92 _architecture: Nullable[ArchitectureSymbol] #: Reference to the selected architecture, or ``None`` if none was given. 

93 

94 def __init__( 

95 self, 

96 entity: EntitySymbol, 

97 architecture: Nullable[ArchitectureSymbol] = None, 

98 parent: Nullable[ModelEntity] = None 

99 ) -> None: 

100 """ 

101 Initializes an entity aspect naming an entity, optionally with an architecture. 

102 

103 :param entity: Reference to the named entity. 

104 :param architecture: Reference to the selected architecture, or ``None`` if none was given. 

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

106 """ 

107 super().__init__(parent) 

108 

109 self._entity = entity 

110 entity.Parent = self 

111 

112 self._architecture = architecture 

113 if architecture is not None: 

114 architecture.Parent = self 

115 

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

117 """ 

118 Walk this entity aspect, its entity and its architecture (if any) with a visitor. 

119 

120 :param visitor: The visitor receiving the events. 

121 """ 

122 visitor.VisitEntityAspectEntity(self) 

123 self._entity.Visit(visitor) 

124 if self._architecture is not None: 

125 visitor.VisitLeftParenthesis(self) 

126 self._architecture.Visit(visitor) 

127 visitor.VisitRightParenthesis(self) 

128 

129 visitor.DepartEntityAspectEntity(self) 

130 

131 @readonly 

132 def Entity(self) -> EntitySymbol: 

133 """ 

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

135 

136 :returns: The entity. 

137 """ 

138 return self._entity 

139 

140 @readonly 

141 def Architecture(self) -> Nullable[ArchitectureSymbol]: 

142 """ 

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

144 

145 :returns: The architecture, or ``None`` if not set. 

146 """ 

147 return self._architecture 

148 

149 

150@export 

151class EntityAspectConfiguration(EntityAspect): 

152 """ 

153 Represents an entity aspect naming a configuration. 

154 

155 .. admonition:: Example 

156 

157 .. code-block:: VHDL 

158 

159 use configuration work.cfg; 

160 -- ^^^^^^^^ <- Configuration 

161 """ 

162 

163 _configuration: ConfigurationSymbol #: Reference to the named configuration. 

164 

165 def __init__(self, configuration: ConfigurationSymbol, parent: Nullable[ModelEntity] = None) -> None: 

166 """ 

167 Initializes an entity aspect naming a configuration. 

168 

169 :param configuration: Reference to the named configuration. 

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

171 """ 

172 super().__init__(parent) 

173 

174 self._configuration = configuration 

175 configuration.Parent = self 

176 

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

178 """ 

179 Walk this entity aspect and its configuration with a visitor. 

180 

181 :param visitor: The visitor receiving the events. 

182 """ 

183 visitor.VisitEntityAspectConfiguration(self) 

184 self._configuration.Visit(visitor) 

185 visitor.DepartEntityAspectConfiguration(self) 

186 

187 @readonly 

188 def Configuration(self) -> ConfigurationSymbol: 

189 """ 

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

191 

192 :returns: The configuration. 

193 """ 

194 return self._configuration 

195 

196 

197@export 

198class EntityAspectOpen(EntityAspect): 

199 """ 

200 Represents an open entity aspect, leaving the binding unspecified. 

201 

202 .. admonition:: Example 

203 

204 .. code-block:: VHDL 

205 

206 use open; 

207 -- ^^^^ <- the aspect 

208 """ 

209 

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

211 """ 

212 Walk this open entity aspect with a visitor. 

213 

214 :param visitor: The visitor receiving the events. 

215 """ 

216 visitor.VisitEntityAspectOpen(self) 

217 visitor.DepartEntityAspectOpen(self) 

218 

219 

220@export 

221class BindingIndication(ModelEntity, GenericMapAspectMixin, PortMapAspectMixin): 

222 """ 

223 Represents a binding indication: which design entity a component is bound to. 

224 

225 The entity aspect is available as :data:`EntityAspect`, together with the generic and port maps 

226 (:data:`GenericAssociations`, :data:`PortAssociations`). 

227 """ 

228 

229 _entityAspect: Nullable[EntityAspect] #: The bound design entity, or ``None`` if not given. 

230 

231 def __init__( 

232 self, 

233 entityAspect: Nullable[EntityAspect] = None, 

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

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

236 parent: Nullable[ModelEntity] = None 

237 ) -> None: 

238 """ 

239 Initializes a binding indication. 

240 

241 :param entityAspect: The bound design entity, or ``None`` if not given. 

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

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

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

245 """ 

246 super().__init__(parent) 

247 GenericMapAspectMixin.__init__(self, genericAssociationItems) 

248 PortMapAspectMixin.__init__(self, portAssociationItems) 

249 

250 self._entityAspect = entityAspect 

251 if entityAspect is not None: 

252 entityAspect.Parent = self 

253 

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

255 """ 

256 Walk this binding indication, its entity aspect and its map aspects with a visitor. 

257 

258 :param visitor: The visitor receiving the events. 

259 """ 

260 visitor.VisitBindingIndication(self) 

261 if self._entityAspect is not None: 261 ↛ 264line 261 didn't jump to line 264 because the condition on line 261 was always true

262 self._entityAspect.Visit(visitor) 

263 

264 self._VisitGenericMapAspect(visitor) 

265 self._VisitPortMapAspect(visitor) 

266 visitor.DepartBindingIndication(self) 

267 

268 @readonly 

269 def EntityAspect(self) -> Nullable[EntityAspect]: 

270 """ 

271 Read-only property to access the entity aspect (:attr:`_entityAspect`). 

272 

273 :returns: The entity aspect, or ``None`` if not set. 

274 """ 

275 return self._entityAspect 

276 

277 

278 

279 

280@export 

281class AllInstantiationList(ModelEntity): 

282 """ 

283 Represents an instantiation list naming ``all`` instances of a component. 

284 

285 .. admonition:: Example 

286 

287 .. code-block:: VHDL 

288 

289 for all : comp use entity work.sub(behav); 

290 -- ^^^ <- the instantiation list 

291 """ 

292 

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

294 """ 

295 Walk this ``all`` instantiation list with a visitor. 

296 

297 :param visitor: The visitor receiving the events. 

298 """ 

299 visitor.VisitAllInstantiationList(self) 

300 visitor.DepartAllInstantiationList(self) 

301 

302 

303@export 

304class OthersInstantiationList(ModelEntity): 

305 """ 

306 Represents an instantiation list naming all instances not configured elsewhere. 

307 

308 .. admonition:: Example 

309 

310 .. code-block:: VHDL 

311 

312 for others : comp use entity work.sub(behav); 

313 -- ^^^^^^ <- the instantiation list 

314 """ 

315 

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

317 """ 

318 Walk this ``others`` instantiation list with a visitor. 

319 

320 :param visitor: The visitor receiving the events. 

321 """ 

322 visitor.VisitOthersInstantiationList(self) 

323 visitor.DepartOthersInstantiationList(self) 

324 

325 

326InstantiationListUnion = Union[list[Name], AllInstantiationList, OthersInstantiationList] 

327 

328 

329@export 

330class ComponentConfiguration(ModelEntity): 

331 """ 

332 Represents a component configuration (inside a block configuration), or - structurally identical 

333 - a configuration specification (declared directly in an architecture's declarative part). 

334 

335 .. admonition:: Example 

336 

337 .. code-block:: VHDL 

338 

339 for U1 : comp use entity work.sub(behav); 

340 -- ^^ ^^^^ 

341 -- | Component name 

342 -- Instantiation list 

343 """ 

344 

345 _instantiationList: InstantiationListUnion #: The instances this configuration applies to. 

346 _componentName: ComponentInstantiationSymbol #: Reference to the component being configured. 

347 _bindingIndication: Nullable[BindingIndication] #: The binding indication, or ``None`` if none was given. 

348 

349 def __init__( 

350 self, 

351 instantiationList: InstantiationListUnion, 

352 componentName: ComponentInstantiationSymbol, 

353 bindingIndication: Nullable[BindingIndication] = None, 

354 parent: Nullable[ModelEntity] = None 

355 ) -> None: 

356 """ 

357 Initializes a component configuration. 

358 

359 :param instantiationList: The instances this configuration applies to. 

360 :param componentName: Reference to the component being configured. 

361 :param bindingIndication: The binding indication, or ``None`` if none was given. 

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

363 """ 

364 super().__init__(parent) 

365 

366 if isinstance(instantiationList, (AllInstantiationList, OthersInstantiationList)): 

367 self._instantiationList = instantiationList 

368 instantiationList.Parent = self 

369 else: 

370 self._instantiationList = list(instantiationList) 

371 for label in self._instantiationList: 

372 label.Parent = self 

373 

374 self._componentName = componentName 

375 componentName.Parent = self 

376 

377 self._bindingIndication = bindingIndication 

378 if bindingIndication is not None: 

379 bindingIndication.Parent = self 

380 

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

382 """ 

383 Walk this component configuration, its component specification and its binding indication with a visitor. 

384 

385 :param visitor: The visitor receiving the events. 

386 """ 

387 visitor.VisitComponentConfiguration(self) 

388 visitor.VisitInstantiationList(self) 

389 if isinstance(self._instantiationList, list): 

390 for index, label in enumerate(self._instantiationList): 

391 if index > 0: 

392 visitor.VisitComma(self) 

393 

394 label.Visit(visitor) 

395 else: 

396 self._instantiationList.Visit(visitor) 

397 

398 visitor.DepartInstantiationList(self) 

399 self._componentName.Visit(visitor) 

400 if self._bindingIndication is not None: 

401 self._bindingIndication.Visit(visitor) 

402 

403 visitor.DepartComponentConfiguration(self) 

404 

405 @readonly 

406 def InstantiationList(self) -> InstantiationListUnion: 

407 """ 

408 Read-only property to access the instantiation list (:attr:`_instantiationList`). 

409 

410 :returns: The instantiation list. 

411 """ 

412 return self._instantiationList 

413 

414 @readonly 

415 def ComponentName(self) -> ComponentInstantiationSymbol: 

416 """ 

417 Read-only property to access the component name (:attr:`_componentName`). 

418 

419 :returns: The component name. 

420 """ 

421 return self._componentName 

422 

423 @readonly 

424 def BindingIndication(self) -> Nullable[BindingIndication]: 

425 """ 

426 Read-only property to access the binding indication (:attr:`_bindingIndication`). 

427 

428 :returns: The binding indication, or ``None`` if not set. 

429 """ 

430 return self._bindingIndication 

431 

432 

433@export 

434class BlockConfiguration(ModelEntity): 

435 """ 

436 Represents the configuration of one block: an architecture, a block statement or a generate body. 

437 

438 Nested configurations are available as :data:`ConfigurationItems`. 

439 

440 .. admonition:: Example 

441 

442 .. code-block:: VHDL 

443 

444 for rtl 

445 -- ^^^ <- Block 

446 end for; 

447 """ 

448 

449 _blockSpecification: Symbol #: The configured block. 

450 _items: list[Union[BlockConfiguration, ComponentConfiguration]] #: Nested configurations. 

451 

452 def __init__( 

453 self, 

454 blockSpecification: Symbol, 

455 items: Nullable[Iterable[Union[BlockConfiguration, ComponentConfiguration]]] = None, 

456 parent: Nullable[ModelEntity] = None 

457 ) -> None: 

458 """ 

459 Initializes a block configuration. 

460 

461 :param blockSpecification: The configured block. 

462 :param items: Nested configurations. 

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

464 """ 

465 super().__init__(parent) 

466 

467 self._blockSpecification = blockSpecification 

468 blockSpecification.Parent = self 

469 

470 self._items = itemList = [] 

471 if items is not None: 

472 for item in items: 

473 itemList.append(item) 

474 item.Parent = self 

475 

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

477 """ 

478 Walk this block configuration, its block specification and its nested configurations with a visitor. 

479 

480 :param visitor: The visitor receiving the events. 

481 """ 

482 visitor.VisitBlockConfiguration(self) 

483 visitor.VisitBlockSpecification(self) 

484 self._blockSpecification.Visit(visitor) 

485 visitor.DepartBlockSpecification(self) 

486 for item in self._items: 

487 item.Visit(visitor) 

488 

489 visitor.DepartBlockConfiguration(self) 

490 

491 @readonly 

492 def BlockSpecification(self) -> Symbol: 

493 """ 

494 Read-only property to access the block specification (:attr:`_blockSpecification`). 

495 

496 :returns: The block specification. 

497 """ 

498 return self._blockSpecification 

499 

500 @readonly 

501 def Items(self) -> list[Union[BlockConfiguration, ComponentConfiguration]]: 

502 """ 

503 Read-only property to access the items (:attr:`_items`). 

504 

505 :returns: List of items. 

506 """ 

507 return self._items