def __init__(self, debug=False, verbose=False, quiet=False, sphinx=False): super().__init__(verbose, debug, quiet) # Initialize the Terminal class # -------------------------------------------------------------------------- Singleton.Register(LineTerminal, self) # Initialize DOM with an empty design # -------------------------------------------------------------------------- self._design = Design() # Call the constructor of the ArgParseMixin # -------------------------------------------------------------------------- textWidth = min(max(self.Width, 80), 160) description = dedent("""\ Application to test pyGHDL's DOM API. """) epilog = "\n".join( wrap( dedent("""\ pyGHDL is a Python binding for libghdl. """), textWidth, replace_whitespace=False, )) class HelpFormatter(RawDescriptionHelpFormatter): def __init__(self, *args, **kwargs): kwargs["max_help_position"] = 30 kwargs["width"] = textWidth super().__init__(*args, **kwargs) ArgParseMixin.__init__( self, description=description, epilog=epilog, formatter_class=HelpFormatter, add_help=False, ) # If executed in Sphinx to auto-document CLI arguments, exit now # -------------------------------------------------------------------------- if sphinx: return # Change error and warning reporting # -------------------------------------------------------------------------- self._LOG_MESSAGE_FORMAT__[ Severity.Fatal] = "{DARK_RED}[FATAL] {message}{NOCOLOR}" self._LOG_MESSAGE_FORMAT__[ Severity.Error] = "{RED}[ERROR] {message}{NOCOLOR}" self._LOG_MESSAGE_FORMAT__[ Severity.Warning] = "{YELLOW}[WARNING] {message}{NOCOLOR}" self._LOG_MESSAGE_FORMAT__[ Severity.Normal] = "{GRAY}{message}{NOCOLOR}"
class Literals(TestCase): _root = Path(__file__).resolve().parent.parent _design = Design() _packageTemplate = dedent("""\ package package_1 is {code} end package; """) def parse(self, filename: Path, code: str) -> ExpressionUnion: sourceCode = self._packageTemplate.format(code=code) document = Document(filename, sourceCode) self._design.Documents.append(document) # Traverse already to default value expression package: Package = document.Packages[0] item: Constant = package.DeclaredItems[0] default: ExpressionUnion = item.DefaultExpression return default def test_IntegerLiteral(self): _filename: Path = self._root / "{className}.vhdl".format( className=self.__class__.__name__) constantDeclartion = "constant c0 : integer := 0;" expected = (0, 1, 1024, 1048576) # Parse in-memory default: ExpressionUnion = self.parse(_filename, constantDeclartion) self.assertIsInstance(default, IntegerLiteral) self.assertEqual(expected[0], default.Value)
def test_Package(self): design = Design() document = Document(self._filename) design.Documents.append(document) self.assertEqual(1, len(design.Documents[0].Packages)) self.assertEqual("pack_1", design.Documents[0].Packages[0].Identifier)
def test_Architecture(self): design = Design() document = Document(self._filename) design.Documents.append(document) self.assertEqual(1, len(design.Documents[0].Architectures)) self.assertEqual("behav", design.Documents[0].Architectures[0].Identifier)
def test_Entity(self): design = Design() document = Document(self._filename) design.Documents.append(document) self.assertEqual(1, len(design.Documents[0].Entities)) self.assertEqual("entity_1", design.Documents[0].Entities[0].Identifier)
class Expressions(TestCase): _root = Path(__file__).resolve().parent.parent _design = Design() _packageTemplate = dedent("""\ package package_1 is {code} end package; """) def parse(self, filename: Path, code: str) -> Expression: sourceCode = self._packageTemplate.format(code=code) document = Document(filename, sourceCode) self._design.Documents.append(document) # Traverse already to default value expression package: Package = document.Packages[0] item: Constant = package.DeclaredItems[0] default: Expression = item.DefaultExpression return default def test_NotExpression(self): filename: Path = self._root / "{className}_{funcName}.vhdl".format( className=self.__class__.__name__, funcName=currentframe().f_code.co_name[5:]) # Define test data constantDeclartion = "constant c0 : boolean := not true;" # Parse in-memory default: Expression = self.parse(filename, constantDeclartion) # Start checks self.assertIsInstance(default, InverseExpression) self.assertIsInstance(default.Operand, SimpleObjectOrFunctionCallSymbol) self.assertEqual("true", str(default.Operand.SymbolName))
def test_Document(self): design = Design() document = Document(self._filename) design.Documents.append(document) self.assertEqual(1, len(design.Documents))
def test_Design(self): design = Design() self.assertIsNotNone(design)
class Application(LineTerminal, ArgParseMixin): HeadLine = "pyGHDL.dom - Test Application" # load platform information (Windows, Linux, Darwin, ...) __PLATFORM = platform_system() _design: Design def __init__(self, debug=False, verbose=False, quiet=False, sphinx=False): super().__init__(verbose, debug, quiet) # Initialize the Terminal class # -------------------------------------------------------------------------- Singleton.Register(LineTerminal, self) # Initialize DOM with an empty design # -------------------------------------------------------------------------- self._design = Design() # Call the constructor of the ArgParseMixin # -------------------------------------------------------------------------- textWidth = min(max(self.Width, 80), 160) description = dedent("""\ Application to test pyGHDL's DOM API. """) epilog = "\n".join( wrap( dedent("""\ pyGHDL is a Python binding for libghdl. """), textWidth, replace_whitespace=False, )) class HelpFormatter(RawDescriptionHelpFormatter): def __init__(self, *args, **kwargs): kwargs["max_help_position"] = 30 kwargs["width"] = textWidth super().__init__(*args, **kwargs) ArgParseMixin.__init__( self, description=description, epilog=epilog, formatter_class=HelpFormatter, add_help=False, ) # If executed in Sphinx to auto-document CLI arguments, exit now # -------------------------------------------------------------------------- if sphinx: return # Change error and warning reporting # -------------------------------------------------------------------------- self._LOG_MESSAGE_FORMAT__[ Severity.Fatal] = "{DARK_RED}[FATAL] {message}{NOCOLOR}" self._LOG_MESSAGE_FORMAT__[ Severity.Error] = "{RED}[ERROR] {message}{NOCOLOR}" self._LOG_MESSAGE_FORMAT__[ Severity.Warning] = "{YELLOW}[WARNING] {message}{NOCOLOR}" self._LOG_MESSAGE_FORMAT__[ Severity.Normal] = "{GRAY}{message}{NOCOLOR}" # class properties # ============================================================================ @property def Platform(self): return self.__PLATFORM def PrintHeadline(self): self.WriteNormal( dedent("""\ {HEADLINE}{line} {headline: ^80s} {line}""").format(line="=" * 80, headline=self.HeadLine, **LineTerminal.Foreground)) # ============================================================================ # Common commands # ============================================================================ # common arguments valid for all commands # ---------------------------------------------------------------------------- @CommonSwitchArgumentAttribute("-d", "--debug", dest="debug", help="Enable debug mode.") @CommonSwitchArgumentAttribute("-v", "--verbose", dest="verbose", help="Print out detailed messages.") @CommonSwitchArgumentAttribute("-q", "--quiet", dest="quiet", help="Reduce messages to a minimum.") def Run(self): ArgParseMixin.Run(self) @DefaultAttribute() def HandleDefault(self, _): self.PrintHeadline() self.MainParser.print_help() self.WriteNormal("") self.exit() # ---------------------------------------------------------------------------- # create the sub-parser for the "help" command # ---------------------------------------------------------------------------- @CommandAttribute("help", help="Display help page(s) for the given command name.") @ArgumentAttribute( metavar="Command", dest="Command", type=str, nargs="?", help="Print help page(s) for a command.", ) def HandleHelp(self, args): self.PrintHeadline() if args.Command is None: self.MainParser.print_help() elif args.Command == "help": self.WriteError("This is a recursion ...") else: try: self.SubParsers[args.Command].print_help() except KeyError: self.WriteError("Command {0} is unknown.".format(args.Command)) self.WriteNormal("") self.exit() # ---------------------------------------------------------------------------- # create the sub-parser for the "version" command # ---------------------------------------------------------------------------- @CommandAttribute("version", help="Display tool and version information.") def HandleInfo(self, args): self.PrintHeadline() copyrights = __copyright__.split("\n", 1) self.WriteNormal("Copyright: {0}".format(copyrights[0])) for copyright in copyrights[1:]: self.WriteNormal(" {0}".format(copyright)) self.WriteNormal("License: {0}".format(__license__)) authors = __author__.split(", ") self.WriteNormal("Authors: {0}".format(authors[0])) for author in authors[1:]: self.WriteNormal(" {0}".format(author)) self.WriteNormal("Version: {0}".format(__version__)) self.exit() # ---------------------------------------------------------------------------- # Create the sub-parser for the "pretty" command # ---------------------------------------------------------------------------- @CommandAttribute( "pretty", help="Pretty-print the DOM to console.", description= "Translate a source file into a DOM and pretty-print the DOM.", ) @SourceAttribute() def HandlePretty(self, args): self.PrintHeadline() if args.Files is not None: for file in args.Files: if not file.exists(): self.WriteError( "File '{0!s}' does not exist.".format(file)) continue self.WriteNormal("Parsing file '{!s}'".format(file)) document = self.addFile(file, "pretty") self.WriteInfo( dedent("""\ libghdl processing time: {: 5.3f} us DOM translation time: {:5.3f} us """).format( document.LibGHDLProcessingTime * 10**6, document.DOMTranslationTime * 10**6, )) elif args.Directory is not None: d: Path = args.Directory if not d.exists(): self.WriteError("Directory '{0!s}' does not exist.".format(d)) for file in d.glob("**/*.vhd?"): self.WriteNormal("Parsing file '{!s}'".format(file)) document = self.addFile(file, "pretty") self.WriteInfo( dedent("""\ libghdl processing time: {: 5.3f} us DOM translation time: {:5.3f} us """).format( document.LibGHDLProcessingTime * 10**6, document.DOMTranslationTime * 10**6, )) for library in self._design.Libraries.values(): for entityName, architectures in library.Architectures.items(): for entity in library.Entities: if entity.Identifier == str(entityName): for architecture in architectures: entity.Architectures.append(architecture) PP = PrettyPrint() buffer = [] buffer.append("Design:") for line in PP.formatDesign(self._design, 1): buffer.append(line) print("\n".join(buffer)) self.exit() def addFile(self, filename: Path, library: str) -> Document: lib = self._design.GetLibrary(library) document = Document(filename) self._design.AddDocument(document, lib) return document
from pytest import mark from pyGHDL.dom.NonStandard import Design if __name__ == "__main__": print( "ERROR: you called a testcase declaration file as an executable module." ) print("Use: 'python -m unitest <testcase module>'") exit(1) _TESTSUITE_ROOT = Path(__file__).parent.parent.parent.resolve() _GHDL_ROOT = _TESTSUITE_ROOT.parent design = Design() @mark.parametrize("file", [ str(f.relative_to(_TESTSUITE_ROOT)) for f in _TESTSUITE_ROOT.glob("sanity/**/*.vhdl") ]) def test_AllVHDLSources(file): check_call([ sys_executable, _GHDL_ROOT / "pyGHDL/cli/dom.py", "pretty", "-f", file ], stderr=STDOUT) # try: # lib = design.GetLibrary("sanity") # document = Document(Path(file))