diff options
Diffstat (limited to 'pyGHDL/dom/formatting/prettyprint.py')
-rw-r--r-- | pyGHDL/dom/formatting/prettyprint.py | 330 |
1 files changed, 263 insertions, 67 deletions
diff --git a/pyGHDL/dom/formatting/prettyprint.py b/pyGHDL/dom/formatting/prettyprint.py index 4d6e5dccb..6c0f06061 100644 --- a/pyGHDL/dom/formatting/prettyprint.py +++ b/pyGHDL/dom/formatting/prettyprint.py @@ -1,25 +1,51 @@ +# ============================================================================= +# ____ _ _ ____ _ _ +# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___ +# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \ +# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | | +# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_| +# |_| |___/ +# ============================================================================= +# Authors: +# Patrick Lehmann +# +# Package module: A pretty printer to format the DOM as a tree in text form. +# +# License: +# ============================================================================ +# Copyright (C) 2019-2021 Tristan Gingold +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ============================================================================ from typing import List, Union from pydecor import export -from pyGHDL.dom.Attribute import Attribute, AttributeSpecification -from pyGHDL.dom.Misc import Alias -from pyGHDL.dom.PSL import DefaultClock -from pyGHDL.dom.Subprogram import Procedure -from pyGHDL.dom.Type import ( - IntegerType, - Subtype, - ArrayType, - RecordType, - AccessType, - EnumeratedType, - FileType, - ProtectedType, - ProtectedTypeBody, - PhysicalType, - IncompleteType, +from pyGHDL.dom.Concurrent import ( + ConcurrentBlockStatement, + ProcessStatement, + IfGenerateStatement, + CaseGenerateStatement, + ForGenerateStatement, + ComponentInstantiation, + ConfigurationInstantiation, + EntityInstantiation, + ConcurrentProcedureCall, ) -from pyVHDLModel.VHDLModel import ( +from pyVHDLModel.SyntaxModel import ( GenericInterfaceItem, NamedEntity, PortInterfaceItem, @@ -27,6 +53,8 @@ from pyVHDLModel.VHDLModel import ( Function, BaseType, FullType, + BaseConstant, + ConcurrentStatement, ) from pyGHDL import GHDLBaseException @@ -42,16 +70,33 @@ from pyGHDL.dom.DesignUnit import ( UseClause, PackageInstantiation, ) -from pyGHDL.dom.Object import Constant, Signal, SharedVariable, File +from pyGHDL.dom.Symbol import ( + SimpleSubtypeSymbol, + ConstrainedCompositeSubtypeSymbol, +) +from pyGHDL.dom.Type import ( + IntegerType, + Subtype, + ArrayType, + RecordType, + AccessType, + EnumeratedType, + FileType, + ProtectedType, + ProtectedTypeBody, + PhysicalType, + IncompleteType, +) from pyGHDL.dom.InterfaceItem import ( GenericConstantInterfaceItem, PortSignalInterfaceItem, GenericTypeInterfaceItem, ) -from pyGHDL.dom.Symbol import ( - SimpleSubtypeSymbol, - ConstrainedCompositeSubtypeSymbol, -) +from pyGHDL.dom.Object import Constant, Signal, SharedVariable, File +from pyGHDL.dom.Attribute import Attribute, AttributeSpecification +from pyGHDL.dom.Subprogram import Procedure +from pyGHDL.dom.Misc import Alias +from pyGHDL.dom.PSL import DefaultClock StringBuffer = List[str] @@ -74,14 +119,19 @@ class PrettyPrint: prefix = " " * level buffer.append("{prefix}Libraries:".format(prefix=prefix)) for library in design.Libraries.values(): - for line in self.formatLibrary(library, level + 1): + buffer.append( + "{prefix} - Name: {name}".format( + prefix=prefix, name=library.Identifier + ) + ) + for line in self.formatLibrary(library, level + 2): buffer.append(line) buffer.append("{prefix}Documents:".format(prefix=prefix)) for document in design.Documents: buffer.append( - "{prefix}- Path: '{doc!s}':".format(doc=document.Path, prefix=prefix) + "{prefix} - Path: '{doc!s}':".format(doc=document.Path, prefix=prefix) ) - for line in self.formatDocument(document, level + 1): + for line in self.formatDocument(document, level + 2): buffer.append(line) return buffer @@ -91,33 +141,41 @@ class PrettyPrint: prefix = " " * level buffer.append("{prefix}Entities:".format(prefix=prefix)) for entity in library.Entities: - for line in self.formatEntity(entity, level + 1): - buffer.append(line) - # buffer.append("{prefix}Architectures:".format(prefix=prefix)) - # for architecture in library.Architectures: - # for line in self.formatArchitecture(architecture, level + 1): - # buffer.append(line) + buffer.append( + "{prefix} - {name}({architectures})".format( + prefix=prefix, + name=entity.Identifier, + architectures=", ".join( + [a.Identifier for a in entity.Architectures] + ), + ) + ) buffer.append("{prefix}Packages:".format(prefix=prefix)) for package in library.Packages: if isinstance(package, Package): - gen = self.formatPackage - else: - gen = self.formatPackageInstance - - for line in gen(package, level + 1): - buffer.append(line) - # buffer.append("{prefix}PackageBodies:".format(prefix=prefix)) - # for packageBodies in library.PackageBodies: - # for line in self.formatPackageBody(packageBodies, level + 1): - # buffer.append(line) + buffer.append( + "{prefix} - {name}".format(prefix=prefix, name=package.Identifier) + ) + elif isinstance(package, PackageInstantiation): + buffer.append( + "{prefix} - {name} instantiate from {package}".format( + prefix=prefix, + name=package.Identifier, + package=package.PackageReference, + ) + ) buffer.append("{prefix}Configurations:".format(prefix=prefix)) for configuration in library.Configurations: - for line in self.formatConfiguration(configuration, level + 1): - buffer.append(line) + buffer.append( + "{prefix} - {name}".format( + prefix=prefix, name=configuration.Identifier + ) + ) buffer.append("{prefix}Contexts:".format(prefix=prefix)) for context in library.Contexts: - for line in self.formatContext(context, level + 1): - buffer.append(line) + buffer.append( + "{prefix} - {name}".format(prefix=prefix, name=context.Identifier) + ) return buffer @@ -160,7 +218,7 @@ class PrettyPrint: buffer = [] prefix = " " * level buffer.append( - "{prefix}- Name: {name} at {file}:{line}:{column}".format( + "{prefix}- Name: {name}\n{prefix} File: {file}\n{prefix} Position: {line}:{column}".format( name=entity.Identifier, prefix=prefix, file=entity.Position.Filename.name, @@ -180,6 +238,14 @@ class PrettyPrint: for item in entity.DeclaredItems: for line in self.formatDeclaredItems(item, level + 1): buffer.append(line) + buffer.append("{prefix} Statements:".format(prefix=prefix)) + for item in entity.Statements: + buffer.append("{prefix} ...".format(prefix=prefix)) + buffer.append("{prefix} Architecures:".format(prefix=prefix)) + for item in entity.Architectures: + buffer.append( + "{prefix} - {name}".format(prefix=prefix, name=item.Identifier) + ) return buffer @@ -189,7 +255,7 @@ class PrettyPrint: buffer = [] prefix = " " * level buffer.append( - "{prefix}- Name: {name} at {file}:{line}:{column}".format( + "{prefix}- Name: {name}\n{prefix} File: {file}\n{prefix} Position: {line}:{column}".format( name=architecture.Identifier, prefix=prefix, file=architecture.Position.Filename.name, @@ -206,6 +272,15 @@ class PrettyPrint: for item in architecture.DeclaredItems: for line in self.formatDeclaredItems(item, level + 2): buffer.append(line) + buffer.append("{prefix} Hierarchy:".format(prefix=prefix)) + for item in architecture.Statements: + for line in self.formatHierarchy(item, level + 2): + buffer.append(line) + buffer.append("{prefix} Statements:".format(prefix=prefix)) + for item in architecture.Statements: + buffer.append("{prefix} ...".format(prefix=prefix)) + # for line in self.formatStatements(item, level + 2): + # buffer.append(line) return buffer @@ -232,7 +307,13 @@ class PrettyPrint: buffer = [] prefix = " " * level buffer.append( - "{prefix}- Name: {name}".format(name=package.Identifier, prefix=prefix) + "{prefix}- Name: {name}\n{prefix} File: {file}\n{prefix} Position: {line}:{column}".format( + name=package.Identifier, + prefix=prefix, + file=package.Position.Filename.name, + line=package.Position.Line, + column=package.Position.Column, + ) ) buffer.append("{prefix} Declared:".format(prefix=prefix)) for item in package.DeclaredItems: @@ -307,8 +388,8 @@ class PrettyPrint: return self.formatGenericType(generic, level) else: raise PrettyPrintException( - "Unhandled generic kind for generic '{name}'.".format( - name=generic.Identifier + "Unhandled generic kind '{kind}' for generic '{name}'.".format( + kind=generic.__class__.__name__, name=generic.Identifiers[0] ) ) @@ -319,7 +400,9 @@ class PrettyPrint: return self.formatPortSignal(port, level) else: raise PrettyPrintException( - "Unhandled port kind for port '{name}'.".format(name=port.Identifier) + "Unhandled port kind '{kind}' for port '{name}'.".format( + kind=port.__class__.__name__, name=port.Identifiers[0] + ) ) def formatGenericConstant( @@ -331,10 +414,10 @@ class PrettyPrint: buffer.append( "{prefix} - {name} : {mode!s} {subtypeindication}{initialValue}".format( prefix=prefix, - name=generic.Identifier, + name=", ".join(generic.Identifiers), mode=generic.Mode, subtypeindication=self.formatSubtypeIndication( - generic.Subtype, "generic", generic.Identifier + generic.Subtype, "generic", generic.Identifiers[0] ), initialValue=self.formatInitialValue(generic), ) @@ -366,10 +449,10 @@ class PrettyPrint: buffer.append( "{prefix} - {name} : {mode!s} {subtypeindication}{initialValue}".format( prefix=prefix, - name=port.Identifier, + name=", ".join(port.Identifiers), mode=port.Mode, subtypeindication=self.formatSubtypeIndication( - port.Subtype, "port", port.Identifier + port.Subtype, "port", port.Identifiers[0] ), initialValue=self.formatInitialValue(port), ) @@ -381,24 +464,29 @@ class PrettyPrint: buffer = [] prefix = " " * level - if isinstance(item, Constant): + if isinstance(item, BaseConstant): + if isinstance(item, Constant): + default = " := {expr}".format(expr=str(item.DefaultExpression)) + else: + default = "" + buffer.append( - "{prefix}- constant {name} : {subtype} := {expr}".format( + "{prefix}- constant {name} : {subtype}{default}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "constant", item.Identifier + item.Subtype, "constant", item.Identifiers[0] ), - expr=str(item.DefaultExpression), + default=default, ) ) elif isinstance(item, SharedVariable): buffer.append( "{prefix}- shared variable {name} : {subtype}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "shared variable", item.Identifier + item.Subtype, "shared variable", item.Identifiers[0] ), ) ) @@ -406,9 +494,9 @@ class PrettyPrint: buffer.append( "{prefix}- signal {name} : {subtype}{initValue}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "signal", item.Identifier + item.Subtype, "signal", item.Identifiers[0] ), initValue=" := {expr}".format(expr=str(item.DefaultExpression)) if item.DefaultExpression is not None @@ -419,9 +507,9 @@ class PrettyPrint: buffer.append( "{prefix}- File {name} : {subtype}".format( prefix=prefix, - name=item.Identifier, + name=", ".join(item.Identifiers), subtype=self.formatSubtypeIndication( - item.Subtype, "file", item.Identifier + item.Subtype, "file", item.Identifiers[0] ), ) ) @@ -477,7 +565,9 @@ class PrettyPrint: ) elif isinstance(item, UseClause): buffer.append( - "{prefix}- use {name!s}".format(prefix=prefix, name=item.Item) + "{prefix}- use {names}".format( + prefix=prefix, names=", ".join([str(n) for n in item.Names]) + ) ) elif isinstance(item, Package): buffer.append( @@ -558,3 +648,109 @@ class PrettyPrint: return "" return " := {expr!s}".format(expr=item.DefaultExpression) + + def formatHierarchy( + self, statement: ConcurrentStatement, level: int = 0 + ) -> StringBuffer: + buffer = [] + prefix = " " * level + + if isinstance(statement, ProcessStatement): + buffer.append( + "{prefix}- {label}: process(...)".format( + prefix=prefix, label=statement.Label + ) + ) + elif isinstance(statement, EntityInstantiation): + buffer.append( + "{prefix}- {label}: entity {name}".format( + prefix=prefix, label=statement.Label, name=statement.Entity + ) + ) + elif isinstance(statement, ComponentInstantiation): + buffer.append( + "{prefix}- {label}: component {name}".format( + prefix=prefix, label=statement.Label, name=statement.Component + ) + ) + elif isinstance(statement, ConfigurationInstantiation): + buffer.append( + "{prefix}- {label}: configuration {name}".format( + prefix=prefix, label=statement.Label, name=statement.Configuration + ) + ) + elif isinstance(statement, ConcurrentBlockStatement): + buffer.append( + "{prefix}- {label}: block".format(prefix=prefix, label=statement.Label) + ) + for stmt in statement.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, IfGenerateStatement): + buffer.append( + "{prefix}- {label}: if {condition} generate".format( + prefix=prefix, + label=statement.Label, + condition=statement.IfBranch.Condition, + ) + ) + for stmt in statement.IfBranch.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + for elsifBranch in statement.ElsifBranches: + buffer.append( + "{prefix} {label}: elsif {condition} generate".format( + prefix=prefix, + label=statement.Label, + condition=elsifBranch.Condition, + ) + ) + for stmt in elsifBranch.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + if statement.ElseBranch is not None: + buffer.append( + "{prefix} {label}: else generate".format( + prefix=prefix, label=statement.Label + ) + ) + for stmt in statement.ElseBranch.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, CaseGenerateStatement): + buffer.append( + "{prefix}- {label}: case {expression} generate".format( + prefix=prefix, + label=statement.Label, + expression=statement.SelectExpression, + ) + ) + for case in statement.Cases: + buffer.append( + "{prefix} {case!s}".format( + prefix=prefix, label=case.Label, case=case + ) + ) + for stmt in case.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, ForGenerateStatement): + buffer.append( + "{prefix}- {label}: for {index} in {range} generate".format( + prefix=prefix, + label=statement.Label, + index=statement.LoopIndex, + range=statement.Range, + ) + ) + for stmt in statement.Statements: + for line in self.formatHierarchy(stmt, level + 2): + buffer.append(line) + elif isinstance(statement, ConcurrentProcedureCall): + buffer.append( + "{prefix}- {label}: {name!s}(...)".format( + prefix=prefix, label=statement.Label, name=statement.Procedure + ) + ) + + return buffer |