From fb7ef864c019d325f3fc37125e6d6cdc50ae4b83 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 12 Jan 2023 05:53:48 +0100 Subject: Dependency Graphs (#2308) * Further fixes to the example code. * Bumped dependencies. * Fixed Debouncer example code. * Some more cleanup. * Black's opinion. * Run with pyVHDLModel dev-branch. * Fixed imports for Name. * Fixed test case. * Added a formatter to write dependency graphs and hierarchy as graphml. * Improved GraphML formatting. * Write compile order graph. * Computing compile order. * Bumped dependencies. * Black's opinion. * Fixed incorrect dependency. --- doc/requirements.txt | 4 +- pyGHDL/cli/requirements.txt | 2 +- pyGHDL/dom/Aggregates.py | 17 +- pyGHDL/dom/Attribute.py | 14 +- pyGHDL/dom/Concurrent.py | 55 ++-- pyGHDL/dom/DesignUnit.py | 56 ++-- pyGHDL/dom/Expression.py | 31 +- pyGHDL/dom/InterfaceItem.py | 39 ++- pyGHDL/dom/Literal.py | 19 +- pyGHDL/dom/Misc.py | 5 +- pyGHDL/dom/Names.py | 21 +- pyGHDL/dom/NonStandard.py | 12 +- pyGHDL/dom/Object.py | 30 +- pyGHDL/dom/PSL.py | 10 +- pyGHDL/dom/Range.py | 2 +- pyGHDL/dom/Sequential.py | 56 ++-- pyGHDL/dom/Subprogram.py | 13 +- pyGHDL/dom/Symbol.py | 64 ++-- pyGHDL/dom/Type.py | 39 ++- pyGHDL/dom/_Translate.py | 49 ++- pyGHDL/dom/_Utils.py | 13 +- pyGHDL/dom/formatting/GraphML.py | 340 +++++++++++++++++++++ pyGHDL/dom/formatting/prettyprint.py | 28 +- pyGHDL/dom/requirements.txt | 2 +- pyGHDL/libghdl/requirements.txt | 2 +- pyproject.toml | 4 +- testsuite/pyunit/dom/Expressions.py | 2 +- testsuite/pyunit/dom/Literals.py | 5 +- testsuite/pyunit/dom/StopWatch.py | 73 ++++- .../pyunit/dom/examples/StopWatch/Debouncer.vhdl | 2 +- .../dom/examples/StopWatch/StopWatch.pkg.vhdl | 17 ++ .../pyunit/dom/examples/StopWatch/StopWatch.vhdl | 6 +- .../dom/examples/StopWatch/seg7_Display.vhdl | 2 +- .../dom/examples/StopWatch/toplevel.StopWatch.vhdl | 2 +- 34 files changed, 698 insertions(+), 338 deletions(-) create mode 100644 pyGHDL/dom/formatting/GraphML.py diff --git a/doc/requirements.txt b/doc/requirements.txt index b40787cd7..c787fab4f 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -8,11 +8,11 @@ python-dateutil>=2.8.2 # sphinxcontrib-textstyle>=0.2.1 # sphinxcontrib-spelling>=2.2.0 # changelog>=0.3.5 -autoapi +autoapi>=2.0.1 sphinx_fontawesome>=0.0.6 sphinx_autodoc_typehints>=1.19.5 # BuildTheDocs Extensions (mostly patched Sphinx extensions) -btd.sphinx.autoprogram>=0.1.6.post1 +btd.sphinx.autoprogram>=0.1.7.post1 btd.sphinx.graphviz>=2.3.1.post1 btd.sphinx.inheritance_diagram>=2.3.1.post1 diff --git a/pyGHDL/cli/requirements.txt b/pyGHDL/cli/requirements.txt index e453bcbde..063ef74f6 100644 --- a/pyGHDL/cli/requirements.txt +++ b/pyGHDL/cli/requirements.txt @@ -1,5 +1,5 @@ -r ../dom/requirements.txt -pyTooling>=2.1.0 +pyTooling>=2.11.0 pyTooling.TerminalUI>=1.5.9 pyAttributes>=2.3.2 diff --git a/pyGHDL/dom/Aggregates.py b/pyGHDL/dom/Aggregates.py index a1fe40866..968d3afc9 100644 --- a/pyGHDL/dom/Aggregates.py +++ b/pyGHDL/dom/Aggregates.py @@ -41,15 +41,14 @@ This module contains all DOM classes for VHDL's design units (:class:`context List: @export def GetArrayConstraintsFromSubtypeIndication( subtypeIndication: Iir, -) -> List[ConstraintUnion]: +) -> List: constraints = [] for constraint in utils.flist_iter(nodes.Get_Index_Constraint_List(subtypeIndication)): constraintKind = GetIirKindOfNode(constraint) @@ -303,13 +294,13 @@ def GetAnonymousTypeFromNode(node: Iir) -> BaseType: @export -def GetSubtypeIndicationFromNode(node: Iir, entity: str, name: str) -> SubtypeOrSymbol: +def GetSubtypeIndicationFromNode(node: Iir, entity: str, name: str) -> Symbol: subtypeIndicationNode = nodes.Get_Subtype_Indication(node) return GetSubtypeIndicationFromIndicationNode(subtypeIndicationNode, entity, name) @export -def GetSubtypeIndicationFromIndicationNode(subtypeIndicationNode: Iir, entity: str, name: str) -> SubtypeOrSymbol: +def GetSubtypeIndicationFromIndicationNode(subtypeIndicationNode: Iir, entity: str, name: str) -> Symbol: if subtypeIndicationNode is nodes.Null_Iir: raise ValueError("Parameter 'subtypeIndicationNode' is 'Null_Iir'.") @@ -331,7 +322,7 @@ def GetSubtypeIndicationFromIndicationNode(subtypeIndicationNode: Iir, entity: s @export def GetSimpleTypeFromNode(subtypeIndicationNode: Iir) -> SimpleSubtypeSymbol: subtypeName = GetNameFromNode(subtypeIndicationNode) - return SimpleSubtypeSymbol(subtypeIndicationNode, subtypeName) + return SimpleSubtypeSymbol(subtypeIndicationNode, str(subtypeName)) # XXX: hacked @export @@ -343,7 +334,7 @@ def GetScalarConstrainedSubtypeFromNode( simpleTypeMark = SimpleName(typeMark, typeMarkName) rangeConstraint = nodes.Get_Range_Constraint(subtypeIndicationNode) r = GetRangeFromNode(rangeConstraint) - return ConstrainedScalarSubtypeSymbol(subtypeIndicationNode, simpleTypeMark, r) + return ConstrainedScalarSubtypeSymbol(subtypeIndicationNode, str(simpleTypeMark), r) # XXX: hacked @export @@ -355,11 +346,11 @@ def GetCompositeConstrainedSubtypeFromNode( simpleTypeMark = SimpleName(typeMark, typeMarkName) constraints = GetArrayConstraintsFromSubtypeIndication(subtypeIndicationNode) - return ConstrainedCompositeSubtypeSymbol(subtypeIndicationNode, simpleTypeMark, constraints) + return ConstrainedCompositeSubtypeSymbol(subtypeIndicationNode, str(simpleTypeMark), constraints) # XXX: hacked @export -def GetSubtypeFromNode(subtypeNode: Iir) -> SubtypeOrSymbol: +def GetSubtypeFromNode(subtypeNode: Iir) -> Symbol: subtypeName = GetNameOfNode(subtypeNode) return Subtype(subtypeNode, subtypeName) diff --git a/pyGHDL/dom/_Utils.py b/pyGHDL/dom/_Utils.py index 09f336c03..7ab02ace9 100644 --- a/pyGHDL/dom/_Utils.py +++ b/pyGHDL/dom/_Utils.py @@ -34,6 +34,13 @@ from typing import Union from pyTooling.Decorators import export +from pyVHDLModel.Base import Mode + +from pyGHDL.libghdl import LibGHDLException, name_table, errorout_memory, files_map, file_comments +from pyGHDL.libghdl._types import Iir +from pyGHDL.libghdl.vhdl import nodes, utils +from pyGHDL.libghdl.vhdl.nodes import Null_Iir +from pyGHDL.dom import DOMException, Position from pyGHDL.dom.Symbol import ( LibraryReferenceSymbol, PackageReferenceSymbol, @@ -44,13 +51,7 @@ from pyGHDL.dom.Symbol import ( ComponentInstantiationSymbol, ConfigurationInstantiationSymbol, ) -from pyVHDLModel.SyntaxModel import Mode -from pyGHDL.libghdl import LibGHDLException, name_table, errorout_memory, files_map, file_comments -from pyGHDL.libghdl._types import Iir -from pyGHDL.libghdl.vhdl import nodes, utils -from pyGHDL.libghdl.vhdl.nodes import Null_Iir -from pyGHDL.dom import DOMException, Position __MODE_TRANSLATION = { nodes.Iir_Mode.In_Mode: Mode.In, diff --git a/pyGHDL/dom/formatting/GraphML.py b/pyGHDL/dom/formatting/GraphML.py new file mode 100644 index 000000000..7f72d54b5 --- /dev/null +++ b/pyGHDL/dom/formatting/GraphML.py @@ -0,0 +1,340 @@ +from pathlib import Path +from textwrap import dedent +from typing import Dict, List + +from pyTooling.Graph import Graph, Vertex + +from pyVHDLModel import ( + DependencyGraphVertexKind, + DependencyGraphEdgeKind, + Library as VHDLModel_Library, + Document as VHDLModel_Document, +) + + +class DependencyGraphFormatter: + _graph: Graph + + NODE_COLORS = { + DependencyGraphVertexKind.Document: "#999999", + DependencyGraphVertexKind.Library: "#99ccff", + DependencyGraphVertexKind.Package: "#ff9900", + DependencyGraphVertexKind.PackageBody: "#ff9900", + DependencyGraphVertexKind.Context: "#cc99ff", + DependencyGraphVertexKind.Entity: "#ffff99", + DependencyGraphVertexKind.Architecture: "#ff99cc", + DependencyGraphVertexKind.Configuration: "#ff9900", + } + EDGE_COLORS = { + DependencyGraphEdgeKind.SourceFile: "#000000", + DependencyGraphEdgeKind.CompileOrder: "#ff0000", + DependencyGraphEdgeKind.LibraryClause: "#000000", + DependencyGraphEdgeKind.UseClause: "#000000", + DependencyGraphEdgeKind.ContextReference: "#000000", + DependencyGraphEdgeKind.EntityImplementation: "#99ccff", + DependencyGraphEdgeKind.PackageImplementation: "#99ccff", + DependencyGraphEdgeKind.EntityInstantiation: "#000000", + DependencyGraphEdgeKind.ComponentInstantiation: "#000000", + DependencyGraphEdgeKind.ConfigurationInstantiation: "#000000", + } + + def __init__(self, graph: Graph): + self._graph = graph + + def WriteGraphML(self, path: Path): + with path.open("w") as file: + file.write( + dedent( + f"""\ + + + + + + + + + + """ + ) + ) + groups: Dict[str, List[Vertex]] = {} + for vertex in self._graph._verticesWithID.values(): + if isinstance(vertex.Value, VHDLModel_Library): + identifier = vertex.Value.NormalizedIdentifier + elif isinstance(vertex.Value, VHDLModel_Document): + identifier = vertex.Value.DesignUnits[0].Library.NormalizedIdentifier + else: + identifier = vertex.Value.Library.NormalizedIdentifier + + if identifier in groups: + groups[identifier].append(vertex) + else: + groups[identifier] = [vertex] + + for group, vertices in groups.items(): + file.write( + dedent( + """\ + {prefix} + {prefix} {value} + {prefix} + """ + ).format(prefix=" ", id=group, value=group) + ) + + for vertex in vertices: + if vertex["kind"] is DependencyGraphVertexKind.Architecture: + value = f"{vertex.Value.Entity.Identifier}({vertex.Value.Identifier})" + elif vertex["kind"] is DependencyGraphVertexKind.Document: + value = f"{vertex.ID}" + else: + value = f"{vertex.Value.Identifier}" + file.write( + dedent( + """\ + {prefix} + {prefix} {vertex.ID} + {prefix} {value} + {prefix} {vertex[kind].name} + {prefix} {color} + {prefix} + """ + ).format(prefix=" ", vertex=vertex, value=value, color=self.NODE_COLORS[vertex["kind"]]) + ) + + file.write( + dedent( + """\ + {prefix} + {prefix} + """ + ).format(prefix=" ") + ) + + edgeCount = 1 + for edge in self._graph._edgesWithoutID: + file.write( + dedent( + """\ + {prefix} + {prefix} {edge[kind].name} + {prefix} {color} + {prefix} + """ + ).format(prefix=" ", edgeCount=edgeCount, edge=edge, color=self.EDGE_COLORS[edge["kind"]]) + ) + edgeCount += 1 + + file.write( + dedent( + """\ + + + """ + ) + ) + + +class HierarchyGraphFormatter: + _graph: Graph + + NODE_COLORS = { + DependencyGraphVertexKind.Document: "#999999", + DependencyGraphVertexKind.Library: "#99ccff", + DependencyGraphVertexKind.Package: "#ff9900", + DependencyGraphVertexKind.PackageBody: "#ff9900", + DependencyGraphVertexKind.Context: "#cc99ff", + DependencyGraphVertexKind.Entity: "#ffff99", + DependencyGraphVertexKind.Architecture: "#ff99cc", + DependencyGraphVertexKind.Configuration: "#ff9900", + } + EDGE_COLORS = { + DependencyGraphEdgeKind.SourceFile: "#000000", + DependencyGraphEdgeKind.CompileOrder: "#ff0000", + DependencyGraphEdgeKind.LibraryClause: "#000000", + DependencyGraphEdgeKind.UseClause: "#000000", + DependencyGraphEdgeKind.ContextReference: "#000000", + DependencyGraphEdgeKind.EntityImplementation: "#99ccff", + DependencyGraphEdgeKind.PackageImplementation: "#99ccff", + DependencyGraphEdgeKind.EntityInstantiation: "#000000", + DependencyGraphEdgeKind.ComponentInstantiation: "#000000", + DependencyGraphEdgeKind.ConfigurationInstantiation: "#000000", + } + + def __init__(self, graph: Graph): + self._graph = graph + + def WriteGraphML(self, path: Path): + with path.open("w") as file: + file.write( + dedent( + f"""\ + + + + + + + + + + """ + ) + ) + + for vertex in self._graph._verticesWithID.values(): + if vertex["kind"] is DependencyGraphVertexKind.Entity: + file.write( + dedent( + """\ + {prefix} + {prefix} {vertex.ID} + {prefix} {vertex.Value.Identifier} + {prefix} {vertex[kind].name} + {prefix} {color} + {prefix} + """ + ).format(prefix=" ", vertex=vertex, color=self.NODE_COLORS[vertex["kind"]]) + ) + elif vertex["kind"] is DependencyGraphVertexKind.Architecture: + file.write( + dedent( + """\ + {prefix} + {prefix} {vertex.ID} + {prefix} {vertex.Value.Identifier} + {prefix} {vertex[kind].name} + {prefix} {color} + {prefix} + """ + ).format(prefix=" ", vertex=vertex, color=self.NODE_COLORS[vertex["kind"]]) + ) + + edgeCount = 1 + for edge in self._graph._edgesWithoutID: + file.write( + dedent( + """\ + {prefix} + {prefix} {edge[kind].name} + {prefix} {color} + {prefix} + """ + ).format(prefix=" ", edgeCount=edgeCount, edge=edge, color=self.EDGE_COLORS[edge["kind"]]) + ) + edgeCount += 1 + + file.write( + dedent( + """\ + + + """ + ) + ) + + +class CompileOrderGraphFormatter: + _graph: Graph + + NODE_COLORS = { + DependencyGraphVertexKind.Document: "#999999", + DependencyGraphVertexKind.Library: "#99ccff", + DependencyGraphVertexKind.Package: "#ff9900", + DependencyGraphVertexKind.PackageBody: "#ff9900", + DependencyGraphVertexKind.Context: "#cc99ff", + DependencyGraphVertexKind.Entity: "#ffff99", + DependencyGraphVertexKind.Architecture: "#ff99cc", + DependencyGraphVertexKind.Configuration: "#ff9900", + } + EDGE_COLORS = { + DependencyGraphEdgeKind.SourceFile: "#000000", + DependencyGraphEdgeKind.CompileOrder: "#ff0000", + DependencyGraphEdgeKind.LibraryClause: "#000000", + DependencyGraphEdgeKind.UseClause: "#000000", + DependencyGraphEdgeKind.ContextReference: "#000000", + DependencyGraphEdgeKind.EntityImplementation: "#99ccff", + DependencyGraphEdgeKind.PackageImplementation: "#99ccff", + DependencyGraphEdgeKind.EntityInstantiation: "#000000", + DependencyGraphEdgeKind.ComponentInstantiation: "#000000", + DependencyGraphEdgeKind.ConfigurationInstantiation: "#000000", + } + + def __init__(self, graph: Graph): + self._graph = graph + + def WriteGraphML(self, path: Path): + print(path.absolute()) + with path.open("w") as file: + file.write( + dedent( + f"""\ + + + + + + + + + + """ + ) + ) + + for vertex in self._graph._verticesWithID.values(): + if vertex["kind"] is DependencyGraphVertexKind.Document: + file.write( + dedent( + """\ + {prefix} + {prefix} {vertex.ID} + {prefix} {vertex.Value.Path.name} + {prefix} {vertex[kind].name} + {prefix} {color} + {prefix} + """ + ).format(prefix=" ", vertex=vertex, color=self.NODE_COLORS[vertex["kind"]]) + ) + + edgeCount = 1 + for edge in self._graph._edgesWithoutID: + file.write( + dedent( + """\ + {prefix} + {prefix} {edge[kind].name} + {prefix} {color} + {prefix} + """ + ).format(prefix=" ", edgeCount=edgeCount, edge=edge, color=self.EDGE_COLORS[edge["kind"]]) + ) + edgeCount += 1 + + file.write( + dedent( + """\ + + + """ + ) + ) diff --git a/pyGHDL/dom/formatting/prettyprint.py b/pyGHDL/dom/formatting/prettyprint.py index da26372c4..5be27492d 100644 --- a/pyGHDL/dom/formatting/prettyprint.py +++ b/pyGHDL/dom/formatting/prettyprint.py @@ -34,6 +34,15 @@ from typing import List, Union from pyTooling.Decorators import export +from pyVHDLModel.Base import NamedEntityMixin +from pyVHDLModel.Interface import GenericInterfaceItem, PortInterfaceItem +from pyVHDLModel.Subprogram import Function +from pyVHDLModel.Object import BaseConstant, WithDefaultExpressionMixin +from pyVHDLModel.Type import BaseType, FullType +from pyVHDLModel.Concurrent import ConcurrentStatement + +from pyGHDL import GHDLBaseException +from pyGHDL.dom.NonStandard import Document, Design, Library from pyGHDL.dom.Concurrent import ( ConcurrentBlockStatement, ProcessStatement, @@ -45,20 +54,6 @@ from pyGHDL.dom.Concurrent import ( EntityInstantiation, ConcurrentProcedureCall, ) -from pyVHDLModel.SyntaxModel import ( - GenericInterfaceItem, - NamedEntityMixin, - PortInterfaceItem, - WithDefaultExpressionMixin, - Function, - BaseType, - FullType, - BaseConstant, - ConcurrentStatement, -) - -from pyGHDL import GHDLBaseException -from pyGHDL.dom.NonStandard import Document, Design, Library from pyGHDL.dom.DesignUnit import ( Entity, Architecture, @@ -70,10 +65,7 @@ from pyGHDL.dom.DesignUnit import ( UseClause, PackageInstantiation, ) -from pyGHDL.dom.Symbol import ( - SimpleSubtypeSymbol, - ConstrainedCompositeSubtypeSymbol, -) +from pyGHDL.dom.Symbol import SimpleSubtypeSymbol, ConstrainedCompositeSubtypeSymbol from pyGHDL.dom.Type import ( IntegerType, Subtype, diff --git a/pyGHDL/dom/requirements.txt b/pyGHDL/dom/requirements.txt index 90c229354..ec127c98c 100644 --- a/pyGHDL/dom/requirements.txt +++ b/pyGHDL/dom/requirements.txt @@ -1,4 +1,4 @@ -r ../libghdl/requirements.txt -pyVHDLModel==0.20.2 +pyVHDLModel==0.22.1 #https://github.com/VHDL/pyVHDLModel/archive/dev.zip#pyVHDLModel diff --git a/pyGHDL/libghdl/requirements.txt b/pyGHDL/libghdl/requirements.txt index 5f5b740d6..9b79bd34d 100644 --- a/pyGHDL/libghdl/requirements.txt +++ b/pyGHDL/libghdl/requirements.txt @@ -1 +1 @@ -pyTooling>=2.1.0 +pyTooling>=2.11.0 diff --git a/pyproject.toml b/pyproject.toml index 3d59efe58..699b7bfab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [build-system] requires = [ - "pyTooling >= 2.1.0", + "pyTooling >= 2.11.0", "setuptools >= 62.3.3", - "wheel >= 0.37.1" + "wheel >= 0.38.1" ] build-backend = "setuptools.build_meta" diff --git a/testsuite/pyunit/dom/Expressions.py b/testsuite/pyunit/dom/Expressions.py index 4b2e47507..fe9bf22eb 100644 --- a/testsuite/pyunit/dom/Expressions.py +++ b/testsuite/pyunit/dom/Expressions.py @@ -97,7 +97,7 @@ class Expressions(TestCase): # Start checks self.assertIsInstance(default, InverseExpression) self.assertIsInstance(default.Operand, SimpleObjectOrFunctionCallSymbol) - self.assertEqual("true", str(default.Operand.SymbolName)) + self.assertEqual("true", str(default.Operand)) # .SymbolName)) # XXX: hacked # def test_AbsExpression(self): # filename: Path = self._root / "{className}_{funcName}.vhdl".format( diff --git a/testsuite/pyunit/dom/Literals.py b/testsuite/pyunit/dom/Literals.py index 9f53a6cc6..8d0b72fb0 100644 --- a/testsuite/pyunit/dom/Literals.py +++ b/testsuite/pyunit/dom/Literals.py @@ -35,13 +35,12 @@ from textwrap import dedent from typing import TypeVar, Dict from unittest import TestCase -from pyVHDLModel.SyntaxModel import ExpressionUnion - -from pyGHDL.dom.DesignUnit import Package +from pyVHDLModel.Base import ExpressionUnion from pyGHDL.dom.NonStandard import Design, Document from pyGHDL.dom.Object import Constant from pyGHDL.dom.Literal import IntegerLiteral +from pyGHDL.dom.DesignUnit import Package if __name__ == "__main__": diff --git a/testsuite/pyunit/dom/StopWatch.py b/testsuite/pyunit/dom/StopWatch.py index 6301eb1df..deab50a9f 100644 --- a/testsuite/pyunit/dom/StopWatch.py +++ b/testsuite/pyunit/dom/StopWatch.py @@ -30,11 +30,20 @@ # # SPDX-License-Identifier: GPL-2.0-or-later # ============================================================================ +from time import perf_counter_ns as time_perf_counter from pathlib import Path +from textwrap import dedent +from typing import Dict, List from unittest import TestCase +from pyTooling.Graph import Vertex + +import pyVHDLModel +import pyVHDLModel.DesignUnit from pyGHDL.dom.NonStandard import Design, Document +from pyGHDL.dom.formatting.GraphML import DependencyGraphFormatter, HierarchyGraphFormatter, CompileOrderGraphFormatter from pyGHDL.dom.formatting.prettyprint import PrettyPrint +from pyVHDLModel import DependencyGraphVertexKind, DependencyGraphEdgeKind, Library if __name__ == "__main__": print("ERROR: you called a testcase declaration file as an executable module.") @@ -106,19 +115,65 @@ class Display(Designs): class CompileOrder(Designs): def test_Encoder(self): + print() design = Design() - design.LoadStdLibrary() - design.LoadIEEELibrary() - for lib, file in self._encoderFiles: + design.LoadDefaultLibraries() + t1 = time_perf_counter() + for lib, file in self._stopwatchFiles: library = design.GetLibrary(lib) document = Document(self._sourceDirectory / file) design.AddDocument(document, library) + print(dedent("""\ + file: {} + libghdl processing time: {:5.3f} us + DOM translation time: {:5.3f} us + """ + ).format( + document.Path, + document.LibGHDLProcessingTime * 10**6, + document.DOMTranslationTime * 10**6, + ) + ) + pyGHDLTime = time_perf_counter() - t1 design.Analyze() - PP = PrettyPrint() - buffer = [] - buffer.append("Design:") - for line in PP.formatDesign(design, 1): - buffer.append(line) - print("\n".join(buffer)) + toplevel = [root.Value.Identifier for root in design.HierarchyGraph.IterateRoots()] + + print(dedent(""" + pyGHDL: + sum: {:5.3f} us + Analysis: + default library load time: {:5.3f} us + dependency analysis time: {:5.3f} us + Toplevel: {toplevel} + Compile order:\ + """ + ).format( + pyGHDLTime * 10**6, + design._loadDefaultLibraryTime * 10**6, + design._analyzeTime * 10**6, + toplevel=", ".join(toplevel) + ) + ) + for i, vertex in enumerate(design.IterateDocumentsInCompileOrder()): + print(f" {i:<2}: {vertex.Value.Path.relative_to(Path.cwd())}") + + graphML = Path("dependencies.graphml") + dependencyFormatter = DependencyGraphFormatter(design.DependencyGraph) + dependencyFormatter.WriteGraphML(graphML) + + graphML = Path("hierarchy.graphml") + hierarchyFormatter = HierarchyGraphFormatter(design.HierarchyGraph) + hierarchyFormatter.WriteGraphML(graphML) + + graphML = Path("compileorder.graphml") + compileOrderFormatter = CompileOrderGraphFormatter(design.CompileOrderGraph) + compileOrderFormatter.WriteGraphML(graphML) + + # PP = PrettyPrint() + # buffer = [] + # buffer.append("Design:") + # for line in PP.formatDesign(design, 1): + # buffer.append(line) + # print("\n".join(buffer)) diff --git a/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl b/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl index ef1474164..2c4a0130f 100644 --- a/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl +++ b/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl @@ -7,7 +7,7 @@ library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; -use work.Utilities_pkg.all; +context work.Utilities_ctx; entity Debouncer is diff --git a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl index f67f99c72..3755e4575 100644 --- a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl +++ b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl @@ -30,4 +30,21 @@ package StopWatch_pkg is Seg7Code : out std_logic_vector(7 downto 0) ); end component; + + component seg7_Display is + generic ( + CLOCK_PERIOD : time := 10 ns; + REFRESH_RATE : time := 200 us; + DIGITS : positive + ); + port ( + Clock : in std_logic; + + DigitValues : in T_BCD_Vector(DIGITS - 1 downto 0); + DotValues : in std_logic_vector(DIGITS - 1 downto 0) := (others => '0'); + + Seg7_Segments : out std_logic_vector(7 downto 0); + Seg7_Selects : out std_logic_vector(DIGITS - 1 downto 0) + ); + end component; end package; diff --git a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl index 3d73fa0fa..87a147833 100644 --- a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl +++ b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl @@ -32,7 +32,7 @@ entity Stopwatch is end entity; -architecture trl of Stopwatch is +architecture rtl of Stopwatch is type T_STATE is (ST_RESET, ST_IDLE, ST_COUNTING, ST_PAUSE); signal State : T_STATE := ST_IDLE; @@ -92,7 +92,7 @@ begin end case; end process; - TimeBaseCnt: entity work.Counter + TimeBaseCnt: entity lib_Utilities.Counter generic map ( MODULO => TIMEBASE / (CLOCK_PERIOD * ite(IS_SIMULATION, 100, 1)), BITS => 0 @@ -109,7 +109,7 @@ begin Overflows(0) <= Tick; genDigits: for i in CONFIG'range generate - cnt: entity work.Counter + cnt: entity lib_Utilities.Counter generic map ( MODULO => CONFIG(i).Modulo, BITS => Digits(i)'length diff --git a/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl b/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl index da21075cf..6ed4ecaba 100644 --- a/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl +++ b/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl @@ -79,7 +79,7 @@ begin Dot <= DotValues(to_index(Digit_Select, DotValues'high)); -- 7-segment encoder - enc: configuration seg7_Encoder + enc: component seg7_Encoder port map ( BCDValue => Digit, Dot => Dot, diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl index 08046e2cc..d23d75b2e 100644 --- a/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl +++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl @@ -100,7 +100,7 @@ begin ); -- 7-segment display - display: configuration seg7_Display_cfg + display: /* configuration */ seg7_Display--_cfg generic map ( CLOCK_PERIOD => CLOCK_PERIOD, DIGITS => Digits'length -- cgit v1.2.3