Coverage for pyEDAA/OutputFilter/Xilinx/Synthesis.py: 82%

392 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-27 22:12 +0000

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

2# _____ ____ _ _ ___ _ _ _____ _ _ _ # 

3# _ __ _ _| ____| _ \ / \ / \ / _ \ _ _| |_ _ __ _ _| |_| ___(_) | |_ ___ _ __ # 

4# | '_ \| | | | _| | | | |/ _ \ / _ \ | | | | | | | __| '_ \| | | | __| |_ | | | __/ _ \ '__| # 

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

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

7# |_| |___/ |_| # 

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

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

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

14# Copyright 2025-2025 Electronic Design Automation Abstraction (EDA²) # 

15# # 

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

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

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

19# # 

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

21# # 

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

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

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

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

26# limitations under the License. # 

27# # 

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

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

30# 

31"""A filtering anc classification processor for AMD/Xilinx Vivado Synthesis outputs.""" 

32from pathlib import Path 

33from re import compile as re_compile 

34from typing import ClassVar, List, Callable, Dict, Type, Iterator, Union, Generator 

35 

36from pyTooling.Decorators import export, readonly 

37from pyTooling.MetaClasses import mustoverride 

38from pyTooling.Common import firstValue 

39 

40from pyEDAA.OutputFilter.Xilinx import VivadoMessage, ProcessingState, Parser, Preamble, BaseProcessor, BaseDocument, \ 

41 Line, ProcessorException, LineKind, VivadoInfoMessage, VHDLAssertionMessage, VHDLReportMessage 

42 

43TIME_MEMORY_PATTERN = re_compile(r"""Time \(s\): cpu = (\d{2}:\d{2}:\d{2}) ; elapsed = (\d{2}:\d{2}:\d{2}) . Memory \(MB\): peak = (\d+\.\d+) ; gain = (\d+\.\d+)""") 

44 

45 

46@export 

47class Initialize(Parser): 

48 _command: str 

49 _license: VivadoMessage 

50 

51 def ParseLine(self, lineNumber: int, line: str) -> bool: 

52 pass 

53 

54 

55@export 

56class Section(Parser): 

57 # _START: ClassVar[str] 

58 # _FINISH: ClassVar[str] 

59 

60 _duration: float 

61 

62 def __init__(self, processor: "Processor"): 

63 super().__init__(processor) 

64 

65 self._duration = 0.0 

66 

67 @readonly 

68 def Duration(self) -> float: 

69 return self._duration 

70 

71 def _SectionStart(self, line: Line) -> Generator[Line, Line, Line]: 

72 line._kind = LineKind.SectionStart 

73 

74 line = yield line 

75 if line._message.startswith("----"): 75 ↛ 78line 75 didn't jump to line 78 because the condition on line 75 was always true

76 line._kind = LineKind.SectionStart | LineKind.SectionDelimiter 

77 else: 

78 line._kind |= LineKind.ProcessorError 

79 

80 nextLine = yield line 

81 return nextLine 

82 

83 def _SectionFinish(self, line: Line) -> Generator[Line, Line, None]: 

84 if line._message.startswith(self._FINISH): 84 ↛ 87line 84 didn't jump to line 87 because the condition on line 84 was always true

85 line._kind = LineKind.SectionEnd 

86 else: 

87 line._kind |= LineKind.ProcessorError 

88 

89 line = yield line 

90 if line._message.startswith("----"): 90 ↛ 93line 90 didn't jump to line 93 because the condition on line 90 was always true

91 line._kind = LineKind.SectionEnd | LineKind.SectionDelimiter | LineKind.Last 

92 else: 

93 line._kind |= LineKind.ProcessorError 

94 

95 check = yield line 

96 if check is not None: 

97 raise Exception() 

98 

99 # @mustoverride 

100 # def ParseLine(self, lineNumber: int, line: str) -> ProcessingState: 

101 # if len(line) == 0: 

102 # return ProcessingState.EmptyLine 

103 # elif line.startswith("----"): 

104 # return ProcessingState.DelimiterLine 

105 # elif line.startswith(self._START): 

106 # return ProcessingState.Skipped 

107 # elif line.startswith(self._FINISH): 

108 # l = line[len(self._FINISH):] 

109 # if (match := TIME_MEMORY_PATTERN.match(l)) is not None: 

110 # # cpuParts = match[1].split(":") 

111 # elapsedParts = match[2].split(":") 

112 # # peakMemory = float(match[3]) 

113 # # gainMemory = float(match[4]) 

114 # self._duration = int(elapsedParts[0]) * 3600 + int(elapsedParts[1]) * 60 + int(elapsedParts[2]) 

115 # 

116 # return ProcessingState.Skipped | ProcessingState.Last 

117 # elif line.startswith("Start") or line.startswith("Starting"): 

118 # print(f"ERROR: didn't find finish\n {line}") 

119 # return ProcessingState.Reprocess 

120 # 

121 # return ProcessingState.Skipped 

122 

123 def Generator(self, line: Line) -> Generator[Line, Line, Line]: 

124 line = yield from self._SectionStart(line) 

125 

126 while line is not None: 126 ↛ 137line 126 didn't jump to line 137 because the condition on line 126 was always true

127 rawMessage = line._message 

128 

129 if rawMessage.startswith("----"): 

130 line._kind = LineKind.SectionEnd | LineKind.SectionDelimiter 

131 break 

132 else: 

133 line._kind = LineKind.Verbose 

134 

135 line = yield line 

136 

137 line = yield line 

138 nextLine = yield from self._SectionFinish(line) 

139 return nextLine 

140 

141 

142@export 

143class SubSection(Section): 

144 def _SectionStart(self, line: Line) -> Generator[Line, Line, Line]: 

145 line._kind = LineKind.SubSectionStart 

146 

147 line = yield line 

148 if line._message.startswith("----"): 148 ↛ 151line 148 didn't jump to line 151 because the condition on line 148 was always true

149 line._kind = LineKind.SubSectionStart | LineKind.SubSectionDelimiter 

150 else: 

151 line._kind |= LineKind.ProcessorError 

152 

153 nextLine = yield line 

154 return nextLine 

155 

156 def _SectionFinish(self, line: Line) -> Generator[Line, Line, None]: 

157 if line._message.startswith(self._FINISH): 157 ↛ 160line 157 didn't jump to line 160 because the condition on line 157 was always true

158 line._kind = LineKind.SubSectionEnd 

159 else: 

160 line._kind |= LineKind.ProcessorError 

161 

162 line = yield line 

163 if line._message.startswith("----"): 163 ↛ 166line 163 didn't jump to line 166 because the condition on line 163 was always true

164 line._kind = LineKind.SubSectionEnd | LineKind.SubSectionDelimiter | LineKind.Last 

165 else: 

166 line._kind |= LineKind.ProcessorError 

167 

168 nextLine = yield line 

169 return nextLine 

170 

171 def Generator(self, line: Line) -> Generator[Line, Line, Line]: 

172 line = yield from self._SectionStart(line) 

173 

174 while line is not None: 174 ↛ 185line 174 didn't jump to line 185 because the condition on line 174 was always true

175 rawMessage = line._message 

176 

177 if rawMessage.startswith("----"): 177 ↛ 181line 177 didn't jump to line 181 because the condition on line 177 was always true

178 line._kind = LineKind.SubSectionEnd | LineKind.SubSectionDelimiter 

179 break 

180 else: 

181 line._kind = LineKind.Verbose 

182 

183 line = yield line 

184 

185 line = yield line 

186 nextLine = yield from self._SectionFinish(line) 

187 

188 return nextLine 

189 

190 

191@export 

192class RTLElaboration(Section): 

193 _START: ClassVar[str] = "Starting RTL Elaboration : " 

194 _FINISH: ClassVar[str] = "Finished RTL Elaboration : " 

195 

196 def Generator(self, line: Line) -> Generator[Line, Line, Line]: 

197 line = yield from self._SectionStart(line) 

198 

199 while line is not None: 199 ↛ 225line 199 didn't jump to line 225 because the condition on line 199 was always true

200 rawMessage = line._message 

201 

202 if isinstance(line, VivadoInfoMessage): 

203 if line._toolID == 8: 203 ↛ 217line 203 didn't jump to line 217 because the condition on line 203 was always true

204 if line._messageKindID == 63: # VHDL assert statement 

205 newLine = VHDLAssertionMessage.Convert(line) 

206 if newLine is None: 206 ↛ 207line 206 didn't jump to line 207 because the condition on line 206 was never true

207 print(f"Convert error at: {line}") 

208 else: 

209 line = newLine 

210 elif line._messageKindID == 6031: # VHDL report statement 

211 newLine = VHDLReportMessage.Convert(line) 

212 if newLine is None: 212 ↛ 213line 212 didn't jump to line 213 because the condition on line 212 was never true

213 print(f"Convert error at: {line}") 

214 else: 

215 line = newLine 

216 

217 if rawMessage.startswith("----"): 

218 line._kind = LineKind.SectionEnd | LineKind.SectionDelimiter 

219 break 

220 elif not isinstance(line, VivadoMessage): 

221 line._kind = LineKind.Verbose 

222 

223 line = yield line 

224 

225 line = yield line 

226 nextLine = yield from self._SectionFinish(line) 

227 return nextLine 

228 

229 

230@export 

231class HandlingCustomAttributes1(Section): 

232 _START: ClassVar[str] = "Start Handling Custom Attributes" 

233 _FINISH: ClassVar[str] = "Finished Handling Custom Attributes : " 

234 

235 

236@export 

237class ConstraintValidation(Section): 

238 _START: ClassVar[str] = "Finished RTL Optimization Phase 1" 

239 _FINISH: ClassVar[str] = "Finished Constraint Validation : " 

240 

241 

242@export 

243class LoadingPart(Section): 

244 _START: ClassVar[str] = "Start Loading Part and Timing Information" 

245 _FINISH: ClassVar[str] = "Finished Loading Part and Timing Information : " 

246 

247 _part: str 

248 

249 def __init__(self, processor: "Processor"): 

250 super().__init__(processor) 

251 

252 self._part = None 

253 

254 @readonly 

255 def Part(self) -> str: 

256 return self._part 

257 

258 def Generator(self, line: Line) -> Generator[Line, Line, Line]: 

259 line = yield from self._SectionStart(line) 

260 

261 while line is not None: 261 ↛ 274line 261 didn't jump to line 274 because the condition on line 261 was always true

262 rawMessage = line._message 

263 

264 if line._message.startswith("Loading part: "): 

265 line._kind = LineKind.Normal 

266 self._part = line._message[14:].strip() 

267 

268 if rawMessage.startswith("----"): 

269 line._kind = LineKind.SectionEnd | LineKind.SectionDelimiter 

270 break 

271 

272 line = yield line 

273 

274 line = yield line 

275 nextLine = yield from self._SectionFinish(line) 

276 return nextLine 

277 

278@export 

279class ApplySetProperty(Section): 

280 _START: ClassVar[str] = "Start Applying 'set_property' XDC Constraints" 

281 _FINISH: ClassVar[str] = "Finished applying 'set_property' XDC Constraints : " 

282 

283 

284@export 

285class RTLComponentStatistics(Section): 

286 _START: ClassVar[str] = "Start RTL Component Statistics" 

287 _FINISH: ClassVar[str] = "Finished RTL Component Statistics" 

288 

289 def Generator(self, line: Line) -> Generator[Line, Line, Line]: 

290 line = yield from self._SectionStart(line) 

291 

292 while line is not None: 292 ↛ 303line 292 didn't jump to line 303 because the condition on line 292 was always true

293 rawMessage = line._message 

294 

295 if rawMessage.startswith("----"): 

296 line._kind = LineKind.SectionEnd | LineKind.SectionDelimiter 

297 break 

298 else: 

299 line._kind = LineKind.Verbose 

300 

301 line = yield line 

302 

303 line = yield line 

304 nextLine = yield from self._SectionFinish(line) 

305 return nextLine 

306 

307 

308@export 

309class PartResourceSummary(Section): 

310 _START: ClassVar[str] = "Start Part Resource Summary" 

311 _FINISH: ClassVar[str] = "Finished Part Resource Summary" 

312 

313 

314@export 

315class CrossBoundaryAndAreaOptimization(Section): 

316 _START: ClassVar[str] = "Start Cross Boundary and Area Optimization" 

317 _FINISH: ClassVar[str] = "Finished Cross Boundary and Area Optimization : " 

318 

319 

320@export 

321class ApplyingXDCTimingConstraints(Section): 

322 _START: ClassVar[str] = "Start Applying XDC Timing Constraints" 

323 _FINISH: ClassVar[str] = "Finished Applying XDC Timing Constraints : " 

324 

325 

326@export 

327class TimingOptimization(Section): 

328 _START: ClassVar[str] = "Start Timing Optimization" 

329 _FINISH: ClassVar[str] = "Finished Timing Optimization : " 

330 

331 

332@export 

333class TechnologyMapping(Section): 

334 _START: ClassVar[str] = "Start Technology Mapping" 

335 _FINISH: ClassVar[str] = "Finished Technology Mapping : " 

336 

337 

338@export 

339class FlatteningBeforeIOInsertion(SubSection): 

340 _START: ClassVar[str] = "Start Flattening Before IO Insertion" 

341 _FINISH: ClassVar[str] = "Finished Flattening Before IO Insertion" 

342 

343 

344@export 

345class FinalNetlistCleanup(SubSection): 

346 _START: ClassVar[str] = "Start Final Netlist Cleanup" 

347 _FINISH: ClassVar[str] = "Finished Final Netlist Cleanup" 

348 

349 

350@export 

351class IOInsertion(Section): 

352 _START: ClassVar[str] = "Start IO Insertion" 

353 _FINISH: ClassVar[str] = "Finished IO Insertion : " 

354 

355 def Generator(self, line: Line) -> Generator[Line, Line, Line]: 

356 flattening = FlatteningBeforeIOInsertion(None) 

357 netlist = FinalNetlistCleanup(None) 

358 

359 line = yield from self._SectionStart(line) 

360 if line._message.startswith("----"): 360 ↛ 363line 360 didn't jump to line 363 because the condition on line 360 was always true

361 line._kind = LineKind.SectionStart | LineKind.SectionDelimiter 

362 else: 

363 line._kind |= LineKind.ProcessorError 

364 

365 line = yield line 

366 if line._message.startswith("Start "): 366 ↛ 369line 366 didn't jump to line 369 because the condition on line 366 was always true

367 line = yield from flattening.Generator(line) 

368 

369 if line._message.startswith("----"): 369 ↛ 372line 369 didn't jump to line 372 because the condition on line 369 was always true

370 line._kind = LineKind.SubSectionStart | LineKind.SectionDelimiter 

371 else: 

372 line._kind |= LineKind.ProcessorError 

373 

374 line = yield line 

375 if line._message.startswith("Start "): 375 ↛ 378line 375 didn't jump to line 378 because the condition on line 375 was always true

376 line = yield from netlist.Generator(line) 

377 

378 if line._message.startswith("----"): 378 ↛ 381line 378 didn't jump to line 381 because the condition on line 378 was always true

379 line._kind = LineKind.SubSectionEnd | LineKind.SectionDelimiter 

380 else: 

381 line._kind |= LineKind.ProcessorError 

382 

383 line = yield line 

384 nextLine = yield from self._SectionFinish(line) 

385 return nextLine 

386 

387@export 

388class RenamingGeneratedInstances(Section): 

389 _START: ClassVar[str] = "Start Renaming Generated Instances" 

390 _FINISH: ClassVar[str] = "Finished Renaming Generated Instances : " 

391 

392 

393@export 

394class RebuildingUserHierarchy(Section): 

395 _START: ClassVar[str] = "Start Rebuilding User Hierarchy" 

396 _FINISH: ClassVar[str] = "Finished Rebuilding User Hierarchy : " 

397 

398 

399@export 

400class RenamingGeneratedPorts(Section): 

401 _START: ClassVar[str] = "Start Renaming Generated Ports" 

402 _FINISH: ClassVar[str] = "Finished Renaming Generated Ports : " 

403 

404 

405@export 

406class HandlingCustomAttributes2(Section): 

407 _START: ClassVar[str] = "Start Handling Custom Attributes" 

408 _FINISH: ClassVar[str] = "Finished Handling Custom Attributes : " 

409 

410 

411@export 

412class RenamingGeneratedNets(Section): 

413 _START: ClassVar[str] = "Start Renaming Generated Nets" 

414 _FINISH: ClassVar[str] = "Finished Renaming Generated Nets : " 

415 

416 

417@export 

418class WritingSynthesisReport(Section): 

419 _START: ClassVar[str] = "Start Writing Synthesis Report" 

420 _FINISH: ClassVar[str] = "Finished Writing Synthesis Report : " 

421 

422 _blackboxes: Dict[str, int] 

423 _cells: Dict[str, int] 

424 

425 def __init__(self, processor: "Processor"): 

426 super().__init__(processor) 

427 

428 self._blackboxes = {} 

429 self._cells = {} 

430 

431 @readonly 

432 def Cells(self) -> Dict[str, int]: 

433 return self._cells 

434 

435 @readonly 

436 def Blackboxes(self) -> Dict[str, int]: 

437 return self._blackboxes 

438 

439 def _BlackboxesGenerator(self, line: Line) -> Generator[Line, Line, Line]: 

440 if line._message.startswith("+-"): 440 ↛ 443line 440 didn't jump to line 443 because the condition on line 440 was always true

441 line._kind = LineKind.TableFrame 

442 else: 

443 line._kind = LineKind.ProcessorError 

444 

445 line = yield line 

446 if line._message.startswith("| "): 446 ↛ 449line 446 didn't jump to line 449 because the condition on line 446 was always true

447 line._kind = LineKind.TableHeader 

448 else: 

449 line._kind = LineKind.ProcessorError 

450 

451 line = yield line 

452 if line._message.startswith("+-"): 452 ↛ 455line 452 didn't jump to line 455 because the condition on line 452 was always true

453 line._kind = LineKind.TableFrame 

454 else: 

455 line._kind = LineKind.ProcessorError 

456 

457 line = yield line 

458 while line is not None: 458 ↛ 472line 458 didn't jump to line 472 because the condition on line 458 was always true

459 if line._message.startswith("| "): 459 ↛ 460line 459 didn't jump to line 460 because the condition on line 459 was never true

460 line._kind = LineKind.TableRow 

461 

462 columns = line._message.strip("|").split("|") 

463 self._blackboxes[columns[1].strip()] = int(columns[2].strip()) 

464 elif line._message.startswith("+-"): 464 ↛ 468line 464 didn't jump to line 468 because the condition on line 464 was always true

465 line._kind = LineKind.TableFrame 

466 break 

467 else: 

468 line._kind = LineKind.ProcessorError 

469 

470 line = yield line 

471 

472 nextLine = yield line 

473 return nextLine 

474 

475 def _CellGenerator(self, line: Line) -> Generator[Line, Line, Line]: 

476 if line._message.startswith("+-"): 476 ↛ 479line 476 didn't jump to line 479 because the condition on line 476 was always true

477 line._kind = LineKind.TableFrame 

478 else: 

479 line._kind = LineKind.ProcessorError 

480 

481 line = yield line 

482 if line._message.startswith("| "): 482 ↛ 485line 482 didn't jump to line 485 because the condition on line 482 was always true

483 line._kind = LineKind.TableHeader 

484 else: 

485 line._kind = LineKind.ProcessorError 

486 

487 line = yield line 

488 if line._message.startswith("+-"): 488 ↛ 491line 488 didn't jump to line 491 because the condition on line 488 was always true

489 line._kind = LineKind.TableFrame 

490 else: 

491 line._kind = LineKind.ProcessorError 

492 

493 line = yield line 

494 while line is not None: 494 ↛ 508line 494 didn't jump to line 508 because the condition on line 494 was always true

495 if line._message.startswith("|"): 

496 line._kind = LineKind.TableRow 

497 

498 columns = line._message.strip("|").split("|") 

499 self._cells[columns[1].strip()] = int(columns[2].strip()) 

500 elif line._message.startswith("+-"): 500 ↛ 504line 500 didn't jump to line 504 because the condition on line 500 was always true

501 line._kind = LineKind.TableFrame 

502 break 

503 else: 

504 line._kind = LineKind.ProcessorError 

505 

506 line = yield line 

507 

508 nextLine = yield line 

509 return nextLine 

510 

511 def Generator(self, line: Line) -> Generator[Line, Line, Line]: 

512 line = yield from self._SectionStart(line) 

513 

514 while line is not None: 514 ↛ 534line 514 didn't jump to line 534 because the condition on line 514 was always true

515 rawMessage = line._message 

516 

517 if rawMessage.startswith("Report BlackBoxes:"): 

518 line._kind = LineKind.ParagraphHeadline 

519 line = yield line 

520 line = yield from self._BlackboxesGenerator(line) 

521 elif rawMessage.startswith("Report Cell Usage:"): 

522 line._kind = LineKind.ParagraphHeadline 

523 line = yield line 

524 line = yield from self._CellGenerator(line) 

525 elif rawMessage.startswith("----"): 

526 line._kind = LineKind.SectionEnd | LineKind.SectionDelimiter 

527 break 

528 elif not isinstance(line, VivadoMessage): 528 ↛ 531line 528 didn't jump to line 531 because the condition on line 528 was always true

529 line._kind = LineKind.Verbose 

530 line = yield line 

531 elif line._kind is LineKind.Empty: 

532 line = yield line 

533 

534 line = yield line 

535 nextLine = yield from self._SectionFinish(line) 

536 return nextLine 

537 

538 

539PARSERS = ( 

540 Preamble, 

541 RTLElaboration, 

542 HandlingCustomAttributes1, 

543 ConstraintValidation, 

544 LoadingPart, 

545 ApplySetProperty, 

546 RTLComponentStatistics, 

547 PartResourceSummary, 

548 CrossBoundaryAndAreaOptimization, 

549 ApplyingXDCTimingConstraints, 

550 TimingOptimization, 

551 TechnologyMapping, 

552 IOInsertion, 

553 FlatteningBeforeIOInsertion, 

554 FinalNetlistCleanup, 

555 RenamingGeneratedInstances, 

556 RebuildingUserHierarchy, 

557 RenamingGeneratedPorts, 

558 HandlingCustomAttributes2, 

559 RenamingGeneratedNets, 

560 WritingSynthesisReport, 

561) 

562 

563 

564Parsers = Union[*PARSERS] 

565 

566 

567@export 

568class Processor(BaseDocument): 

569 _parsers: Dict[Type[Parser], Parsers] 

570 

571 def __init__(self, synthesisLogfile: Path): 

572 super().__init__(synthesisLogfile) 

573 

574 self._parsers = {p: p(self) for p in PARSERS} 

575 

576 @readonly 

577 def HasLatches(self) -> bool: 

578 if (8 in self._messagesByID) and (327 in self._messagesByID[8]): 

579 return True 

580 

581 return "LD" in self._parsers[WritingSynthesisReport]._cells 

582 

583 @readonly 

584 def Latches(self) -> Iterator[VivadoMessage]: 

585 try: 

586 yield from iter(self._messagesByID[8][327]) 

587 except KeyError: 

588 yield from () 

589 

590 @readonly 

591 def HasBlackboxes(self) -> bool: 

592 return len(self._parsers[WritingSynthesisReport]._blackboxes) > 0 

593 

594 @readonly 

595 def Cells(self) -> Dict[str, int]: 

596 return self._parsers[WritingSynthesisReport]._cells 

597 

598 def __getitem__(self, item: Type[Parser]) -> Parsers: 

599 return self._parsers[item] 

600 

601 def DocumentSlicer(self) -> Generator[Union[Line, ProcessorException], Line, None]: 

602 parser: Section = firstValue(self._parsers) 

603 activeParsers: List[Parsers] = list(self._parsers.values()) 

604 

605 rtlElaboration = self._parsers[RTLElaboration] 

606 constraintValidation = self._parsers[ConstraintValidation] 

607 

608 # get first line and send to preamble filter 

609 line = yield 

610 line = next(filter := parser.Generator(line)) 

611 

612 # return first line and get the second line 

613 line = yield line 

614 

615 while line is not None: 615 ↛ 646line 615 didn't jump to line 646 because the condition on line 615 was always true

616 if filter is not None: 

617 line = filter.send(line) 

618 

619 if (LineKind.Last in line._kind) and (LineKind.SectionDelimiter in line._kind): 

620 activeParsers.remove(parser) 

621 filter = None 

622 else: 

623 if line._message.startswith("Start "): 

624 for parser in activeParsers: # type: Section 624 ↛ 629line 624 didn't jump to line 629 because the loop on line 624 didn't complete

625 if line._message.startswith(parser._START): 

626 line = next(filter := parser.Generator(line)) 

627 break 

628 else: 

629 raise Exception(f"Unknown section: {line}") 

630 elif line._message.startswith("Starting "): 

631 if line._message[9:].startswith("synth_design"): 

632 line._kind = LineKind.Verbose 

633 elif line._message.startswith(rtlElaboration._START): 633 ↛ 641line 633 didn't jump to line 641 because the condition on line 633 was always true

634 parser = rtlElaboration 

635 line = next(filter := parser.Generator(line)) 

636 elif line._message.startswith("Finished "): 

637 if line._message.startswith(constraintValidation._START): 

638 parser = constraintValidation 

639 line = next(filter := parser.Generator(line)) 

640 

641 if line._kind is LineKind.Unprocessed: 

642 line._kind = LineKind.Normal 

643 

644 line = yield line 

645 

646 pass 

647 

648# unused 

649# used but not set 

650# statemachine encodings 

651# resources 

652# * RTL 

653# * Mapped 

654 

655# Design hierarchy + generics per hierarchy 

656# read XDC files