Code Monkey home page Code Monkey logo

pyvhdlparser's Introduction

Sourcecode on GitHub License GitHub tag (latest SemVer incl. pre-release) GitHub release (latest SemVer incl. including pre-releases) GitHub release date
GitHub Workflow Status PyPI PyPI - Status PyPI - Python Version Dependent repos (via libraries.io)
Libraries.io status for latest release Codacy - Quality Codacy - Coverage Codecov - Branch Coverage Libraries.io SourceRank
Read the Docs

pyVHDLParser

This is a token-stream based parser for VHDL-2008.

This project requires Python 3.8+.

Introduction

Main Goals

  • Parsing
    • slice an input document into tokens and text blocks which are categorized
    • preserve case, whitespace and comments
    • recover on parsing errors
    • good error reporting / throw exceptions
  • Fast Processing
    • multi-pass parsing and analysis
    • delay analysis if not needed at current pass
    • link tokens and blocks for fast-forward scanning
  • Generic VHDL Language Model
    • Assemble a document-object-model (Code-DOM)
    • Provide an API for code introspection

Use Cases

  • generate documentation by using the fast-forward scanner
  • generate a document/language model by using the grouped text-block scanner
  • extract compile orders and other dependency graphs
  • generate highlighted syntax
  • re-annotate documenting comments to their objects for doc extraction

Parsing approach

  1. slice an input document into tokens
  2. assemble tokens to text blocks which are categorized
  3. assemble text blocks for fast-forward scanning into groups
  4. translate groups into a document-object-model (DOM)
  5. provide a generic VHDL language model

Long time goals

  • A Sphinx language plugin for VHDL

    TODO: Move the following documentation to ReadTheDocs and replace it with a more lightweight version.

Basic Concept

Example 1

This is an input file:

-- Copryright 2016
library IEEE;
use     IEEE.std_logic_1164.all;

entity myEntity is
  generic (
    BITS : positive := 8
  );
  port (
    Clock   : in   std_logic;
    Output  : out  std_logic_vector(BITS - 1 downto 0)
  );
end entity;

architecture rtl of myEntity is
  constant const0 : integer := 5;
begin
  process(Clock)
  begin
  end process;
end architecture;

library IEEE, PoC;
use     PoC.Utils.all, PoC.Common.all;

package pkg0 is
  function func0(a : integer) return string;
end package;

package body Components is
  function func0(a : integer) return string is
    procedure proc0 is
    begin
    end procedure;
  begin
  end function
end package body;

Step 1

The input file (stream of characters) is translated into stream of basic tokens:

  • StartOfDocumentToken
  • LinebreakToken
  • SpaceToken
    • IndentationToken
  • WordToken
  • CharacterToken
    • FusedCharacterToken
  • CommentToken
    • SingleLineCommentToken
    • MultiLineCommentToken
  • EndOfDocumentToken

The stream looks like this:

<StartOfDocumentToken>
<SLCommentToken '-- Copryright 2016\n'  ................ at 1:1>
<WordToken      'library'  ............................. at 2:1>
<SpaceToken     ' '  ................................... at 2:8>
<WordToken      'IEEE'  ................................ at 2:9>
<CharacterToken ';'  ................................... at 2:13>
<LinebreakToken ---------------------------------------- at 2:14>
<WordToken      'use'  ................................. at 3:1>
<SpaceToken     '     '  ............................... at 3:4>
<WordToken      'IEEE'  ................................ at 3:9>
<CharacterToken '.'  ................................... at 3:13>
<WordToken      'std_logic_1164'  ...................... at 3:14>
<CharacterToken '.'  ................................... at 3:28>
<WordToken      'all'  ................................. at 3:29>
<CharacterToken ';'  ................................... at 3:32>
<LinebreakToken ---------------------------------------- at 3:33>
<LinebreakToken ---------------------------------------- at 4:1>
<WordToken      'entity'  .............................. at 5:1>
<SpaceToken     ' '  ................................... at 5:7>
<WordToken      'myEntity'  ............................ at 5:8>
<SpaceToken     ' '  ................................... at 5:16>
<WordToken      'is'  .................................. at 5:17>
<LinebreakToken ---------------------------------------- at 5:19>
<IndentToken    '\t'  .................................. at 6:1>
<WordToken      'generic'  ............................. at 6:2>
<SpaceToken     ' '  ................................... at 6:9>
<CharacterToken '('  ................................... at 6:10>
<LinebreakToken ---------------------------------------- at 6:11>
<IndentToken    '\t\t'  ................................ at 7:1>
<WordToken      'BITS'  ................................ at 7:3>
<SpaceToken     ' '  ................................... at 7:7>
<CharacterToken ':'  ................................... at 7:8>
<SpaceToken     ' '  ................................... at 7:8>
<WordToken      'positive'  ............................ at 7:10>
<SpaceToken     ' '  ................................... at 7:18>
<FusedCharToken ':='  .................................. at 7:19>
<SpaceToken     ' '  ................................... at 7:21>
<WordToken      '8'  ................................... at 7:22>
<LinebreakToken ---------------------------------------- at 7:23>
<IndentToken    '\t'  .................................. at 8:1>
<CharacterToken ')'  ................................... at 8:2>
<CharacterToken ';'  ................................... at 8:3>
<LinebreakToken ---------------------------------------- at 8:4>
<IndentToken    '\t'  .................................. at 9:1>
<WordToken      'port'  ................................ at 9:2>
<SpaceToken     ' '  ................................... at 9:6>
<CharacterToken '('  ................................... at 9:7>
<LinebreakToken ---------------------------------------- at 9:8>
<IndentToken    '\t\t'  ................................ at 10:1>
<WordToken      'Clock'  ............................... at 10:3>
<SpaceToken     '   '  ................................. at 10:8>
<CharacterToken ':'  ................................... at 10:11>
<SpaceToken     ' '  ................................... at 10:11>
<WordToken      'in'  .................................. at 10:13>
<SpaceToken     '  '  .................................. at 10:15>
<WordToken      'std_logic'  ........................... at 10:17>
<CharacterToken ';'  ................................... at 10:26>
<LinebreakToken ---------------------------------------- at 10:27>
<IndentToken    '\t\t'  ................................ at 11:1>
<WordToken      'Output'  .............................. at 11:3>
<SpaceToken     '       '  ................................... at 11:9>
<CharacterToken ':'  ................................... at 11:10>
<SpaceToken     ' '  ................................... at 11:10>
<WordToken      'out'  ................................. at 11:12>
<SpaceToken     '       '  ................................... at 11:15>
<WordToken      'std_logic_vector'  .................... at 11:16>
<CharacterToken '('  ................................... at 11:32>
<WordToken      'BITS'  ................................ at 11:33>
<SpaceToken     ' '  ................................... at 11:37>
<CharacterToken '-'  ................................... at 11:38>
<SpaceToken     ' '  ................................... at 11:38>
<WordToken      '1'  ................................... at 11:40>
<SpaceToken     ' '  ................................... at 11:41>
<WordToken      'downto'  .............................. at 11:42>
<SpaceToken     ' '  ................................... at 11:48>
<WordToken      '0'  ................................... at 11:49>
<CharacterToken ')'  ................................... at 11:50>
<LinebreakToken ---------------------------------------- at 11:51>
<IndentToken    '\t'  .................................. at 12:1>
<CharacterToken ')'  ................................... at 12:2>
<CharacterToken ';'  ................................... at 12:3>
<LinebreakToken ---------------------------------------- at 12:4>
<WordToken      'end'  ................................. at 13:1>
<SpaceToken     ' '  ................................... at 13:4>
<WordToken      'entity'  .............................. at 13:5>
<CharacterToken ';'  ................................... at 13:11>
<LinebreakToken ---------------------------------------- at 13:12>
<LinebreakToken ---------------------------------------- at 14:1>
<WordToken      'architecture'  ........................ at 15:1>
<SpaceToken     ' '  ................................... at 15:13>
<WordToken      'rtl'  ................................. at 15:14>
<SpaceToken     ' '  ................................... at 15:17>
<WordToken      'of'  .................................. at 15:18>
<SpaceToken     ' '  ................................... at 15:20>
<WordToken      'myEntity'  ............................ at 15:21>
<SpaceToken     ' '  ................................... at 15:29>
<WordToken      'is'  .................................. at 15:30>
<LinebreakToken ---------------------------------------- at 15:32>
<IndentToken    '\t'  .................................. at 16:1>
<WordToken      'constant'  ............................ at 16:2>
<SpaceToken     ' '  ................................... at 16:10>
<WordToken      'const0'  .............................. at 16:11>
<SpaceToken     ' '  ................................... at 16:17>
<CharacterToken ':'  ................................... at 16:18>
<SpaceToken     ' '  ................................... at 16:18>
<WordToken      'integer'  ............................. at 16:20>
<SpaceToken     ' '  ................................... at 16:27>
<FusedCharToken ':='  .................................. at 16:28>
<SpaceToken     ' '  ................................... at 16:30>
<WordToken      '5'  ................................... at 16:31>
<CharacterToken ';'  ................................... at 16:32>
<LinebreakToken ---------------------------------------- at 16:33>
<WordToken      'begin'  ............................... at 17:1>
<LinebreakToken ---------------------------------------- at 17:6>
<IndentToken    '\t'  .................................. at 18:1>
<WordToken      'process'  ............................. at 18:2>
<CharacterToken '('  ................................... at 18:9>
<WordToken      'Clock'  ............................... at 18:10>
<CharacterToken ')'  ................................... at 18:15>
<LinebreakToken ---------------------------------------- at 18:16>
<IndentToken    '\t'  .................................. at 19:1>
<WordToken      'begin'  ............................... at 19:2>
<LinebreakToken ---------------------------------------- at 19:7>
<IndentToken    '\t'  .................................. at 20:1>
<WordToken      'end'  ................................. at 20:2>
<SpaceToken     ' '  ................................... at 20:5>
<WordToken      'process'  ............................. at 20:6>
<CharacterToken ';'  ................................... at 20:13>
<LinebreakToken ---------------------------------------- at 20:14>
<WordToken      'end'  ................................. at 21:1>
<SpaceToken     ' '  ................................... at 21:4>
<WordToken      'architecture'  ........................ at 21:5>
<CharacterToken ';'  ................................... at 21:17>
<LinebreakToken ---------------------------------------- at 21:18>
<LinebreakToken ---------------------------------------- at 22:1>
<WordToken      'library'  ............................. at 23:1>
<SpaceToken     ' '  ................................... at 23:8>
<WordToken      'IEEE'  ................................ at 23:9>
<CharacterToken ','  ................................... at 23:13>
<SpaceToken     ' '  ................................... at 23:14>
<WordToken      'PoC'  ................................. at 23:15>
<CharacterToken ';'  ................................... at 23:18>
<LinebreakToken ---------------------------------------- at 23:19>
<WordToken      'use'  ................................. at 24:1>
<SpaceToken     '     '  ............................... at 24:4>
<WordToken      'PoC'  ................................. at 24:9>
<CharacterToken '.'  ................................... at 24:12>
<WordToken      'Utils'  ............................... at 24:13>
<CharacterToken '.'  ................................... at 24:18>
<WordToken      'all'  ................................. at 24:19>
<CharacterToken ','  ................................... at 24:22>
<SpaceToken     ' '  ................................... at 24:23>
<WordToken      'PoC'  ................................. at 24:24>
<CharacterToken '.'  ................................... at 24:27>
<WordToken      'Common'  .............................. at 24:28>
<CharacterToken '.'  ................................... at 24:34>
<WordToken      'all'  ................................. at 24:35>
<CharacterToken ';'  ................................... at 24:38>
<LinebreakToken ---------------------------------------- at 24:39>
<LinebreakToken ---------------------------------------- at 25:1>
<WordToken      'package'  ............................. at 26:1>
<SpaceToken     ' '  ................................... at 26:8>
<WordToken      'pkg0'  ................................ at 26:9>
<SpaceToken     ' '  ................................... at 26:13>
<WordToken      'is'  .................................. at 26:14>
<LinebreakToken ---------------------------------------- at 26:16>
<IndentToken    '\t'  .................................. at 27:1>
<WordToken      'function'  ............................ at 27:2>
<SpaceToken     ' '  ................................... at 27:10>
<WordToken      'func0'  ............................... at 27:11>
<CharacterToken '('  ................................... at 27:16>
<WordToken      'a'  ................................... at 27:17>
<SpaceToken     ' '  ................................... at 27:18>
<CharacterToken ':'  ................................... at 27:19>
<SpaceToken     ' '  ................................... at 27:19>
<WordToken      'integer'  ............................. at 27:21>
<CharacterToken ')'  ................................... at 27:28>
<SpaceToken     ' '  ................................... at 27:29>
<WordToken      'return'  .............................. at 27:30>
<SpaceToken     ' '  ................................... at 27:36>
<WordToken      'string'  .............................. at 27:37>
<CharacterToken ';'  ................................... at 27:43>
<LinebreakToken ---------------------------------------- at 27:44>
<WordToken      'end'  ................................. at 28:1>
<SpaceToken     ' '  ................................... at 28:4>
<WordToken      'package'  ............................. at 28:5>
<CharacterToken ';'  ................................... at 28:12>
<LinebreakToken ---------------------------------------- at 28:13>
<LinebreakToken ---------------------------------------- at 29:1>
<WordToken      'package'  ............................. at 30:1>
<SpaceToken     ' '  ................................... at 30:8>
<WordToken      'body'  ................................ at 30:9>
<SpaceToken     ' '  ................................... at 30:13>
<WordToken      'Components'  .......................... at 30:14>
<SpaceToken     ' '  ................................... at 30:24>
<WordToken      'is'  .................................. at 30:25>
<LinebreakToken ---------------------------------------- at 30:27>
<IndentToken    '\t'  .................................. at 31:1>
<WordToken      'function'  ............................ at 31:2>
<SpaceToken     ' '  ................................... at 31:10>
<WordToken      'func0'  ............................... at 31:11>
<CharacterToken '('  ................................... at 31:16>
<WordToken      'a'  ................................... at 31:17>
<SpaceToken     ' '  ................................... at 31:18>
<CharacterToken ':'  ................................... at 31:19>
<SpaceToken     ' '  ................................... at 31:19>
<WordToken      'integer'  ............................. at 31:21>
<CharacterToken ')'  ................................... at 31:28>
<SpaceToken     ' '  ................................... at 31:29>
<WordToken      'return'  .............................. at 31:30>
<SpaceToken     ' '  ................................... at 31:36>
<WordToken      'string'  .............................. at 31:37>
<SpaceToken     ' '  ................................... at 31:43>
<WordToken      'is'  .................................. at 31:44>
<LinebreakToken ---------------------------------------- at 31:46>
<IndentToken    '\t\t'  ................................ at 32:1>
<WordToken      'procedure'  ........................... at 32:3>
<SpaceToken     ' '  ................................... at 32:12>
<WordToken      'proc0'  ............................... at 32:13>
<SpaceToken     ' '  ................................... at 32:18>
<WordToken      'is'  .................................. at 32:19>
<LinebreakToken ---------------------------------------- at 32:21>
<IndentToken    '\t\t'  ................................ at 33:1>
<WordToken      'begin'  ............................... at 33:3>
<LinebreakToken ---------------------------------------- at 33:8>
<IndentToken    '\t\t'  ................................ at 34:1>
<WordToken      'end'  ................................. at 34:3>
<SpaceToken     ' '  ................................... at 34:6>
<WordToken      'procedure'  ........................... at 34:7>
<CharacterToken ';'  ................................... at 34:16>
<LinebreakToken ---------------------------------------- at 34:17>
<IndentToken    '\t'  .................................. at 35:1>
<WordToken      'begin'  ............................... at 35:2>
<LinebreakToken ---------------------------------------- at 35:7>
<IndentToken    '\t'  .................................. at 36:1>
<WordToken      'end'  ................................. at 36:2>
<SpaceToken     ' '  ................................... at 36:5>
<WordToken      'function'  ............................ at 36:6>
<LinebreakToken ---------------------------------------- at 36:14>
<WordToken      'end'  ................................. at 37:1>
<SpaceToken     ' '  ................................... at 37:4>
<WordToken      'package'  ............................. at 37:5>
<SpaceToken     ' '  ................................... at 37:12>
<WordToken      'body'  ................................ at 37:13>
<CharacterToken ';'  ................................... at 37:17>
<LinebreakToken ---------------------------------------- at 37:18>

Screenshot

Step 2

The token stream from step 1 is translated into typed tokens like DelimiterToken (:), EndToken (;) or subtypes of KeywordToken. These tokens are then grouped into blocks.

The example generates:

[StartOfDocumentBlock]
[Blocks.CommentBlock            '-- Copryright 2016\n'                                         at (line:   1, col:  1) .. (line:   1, col: 19)]
[LibraryStatement.LibraryBlock           'library '                                                     at (line:   2, col:  1) .. (line:   2, col:  8)]
[LibraryStatement.LibraryNameBlock       'IEEE'                                                         at (line:   2, col:  9) .. (line:   2, col: 13)]
[LibraryStatement.LibraryEndBlock        ';'                                                            at (line:   2, col: 13) .. (line:   2, col: 13)]
[LinebreakBlock                                                                                at (line:   2, col: 14) .. (line:   2, col: 14)]
[Use.UseBlock                   'use     '                                                     at (line:   3, col:  1) .. (line:   3, col:  8)]
[Use.UseNameBlock               'IEEE.std_logic_1164.all'                                      at (line:   3, col:  9) .. (line:   3, col: 32)]
[Use.UseEndBlock                ';'                                                            at (line:   3, col: 32) .. (line:   3, col: 32)]
[LinebreakBlock                                                                                at (line:   3, col: 33) .. (line:   3, col: 33)]
[EmptyLineBlock                                                                                at (line:   4, col:  1) .. (line:   4, col:  1)]
[Entity.NameBlock               'entity myEntity is'                                           at (line:   5, col:  1) .. (line:   5, col: 19)]
[LinebreakBlock                                                                                at (line:   5, col: 19) .. (line:   5, col: 19)]
[IndentationBlock                length=1 (2)                                                  at (line:   6, col:  1) .. (line:   6, col:  1)]
[GenericList.OpenBlock          'generic ('                                                    at (line:   6, col:  2) .. (line:   6, col: 10)]
[LinebreakBlock                                                                                at (line:   6, col: 11) .. (line:   6, col: 11)]
[IndentationBlock                length=2 (4)                                                  at (line:   7, col:  1) .. (line:   7, col:  2)]
[GenericList.ItemBlock          'BITS : positive := 8\n\t'                                     at (line:   7, col:  3) .. (line:   8, col:  1)]
[GenericList.CloseBlock         ');'                                                           at (line:   8, col:  2) .. (line:   8, col:  3)]
[LinebreakBlock                                                                                at (line:   8, col:  4) .. (line:   8, col:  4)]
[IndentationBlock                length=1 (2)                                                  at (line:   9, col:  1) .. (line:   9, col:  1)]
[PortList.OpenBlock             'port ('                                                       at (line:   9, col:  2) .. (line:   9, col:  7)]
[LinebreakBlock                                                                                at (line:   9, col:  8) .. (line:   9, col:  8)]
[IndentationBlock                length=2 (4)                                                  at (line:  10, col:  1) .. (line:  10, col:  2)]
[PortList.ItemBlock             'Clock   : in  std_logic'                                      at (line:  10, col:  3) .. (line:  10, col: 26)]
[PortList.DelimiterBlock        ';'                                                            at (line:  10, col: 26) .. (line:  10, col: 26)]
[LinebreakBlock                                                                                at (line:  10, col: 27) .. (line:  10, col: 27)]
[IndentationBlock                length=2 (4)                                                  at (line:  11, col:  1) .. (line:  11, col:  2)]
[PortList.ItemBlock             'Output\t: out\tstd_logic_vector(BITS - 1 downto 0)\n\t'       at (line:  11, col:  3) .. (line:  12, col:  1)]
[PortList.CloseBlock            ');'                                                           at (line:  12, col:  2) .. (line:  12, col:  3)]
[LinebreakBlock                                                                                at (line:  12, col:  4) .. (line:  12, col:  4)]
[Entity.EndBlock                'end entity;'                                                  at (line:  13, col:  1) .. (line:  13, col: 11)]
[LinebreakBlock                                                                                at (line:  13, col: 12) .. (line:  13, col: 12)]
[EmptyLineBlock                                                                                at (line:  14, col:  1) .. (line:  14, col:  1)]
[Architecture.NameBlock         'architecture rtl of myEntity is'                              at (line:  15, col:  1) .. (line:  15, col: 32)]
[LinebreakBlock                                                                                at (line:  15, col: 32) .. (line:  15, col: 32)]
[IndentationBlock                length=1 (2)                                                  at (line:  16, col:  1) .. (line:  16, col:  1)]
[Constant.ConstantBlock         'constant const0 : integer := 5;'                              at (line:  16, col:  2) .. (line:  16, col: 32)]
[LinebreakBlock                                                                                at (line:  16, col: 33) .. (line:  16, col: 33)]
[EmptyLineBlock                                                                                at (line:  17, col:  6) .. (line:  17, col:  6)]
[IndentationBlock                length=1 (2)                                                  at (line:  18, col:  1) .. (line:  18, col:  1)]
[Process.OpenBlock              'process('                                                     at (line:  18, col:  2) .. (line:  18, col:  9)]
[SensitivityList.ItemBlock      'Clock'                                                        at (line:  18, col: 10) .. (line:  18, col: 15)]
[Process.OpenBlock2*            ')'                                                            at (line:  18, col: 15) .. (line:  18, col: 15)]
[LinebreakBlock                                                                                at (line:  18, col: 16) .. (line:  18, col: 16)]
...

The following screenshot shows the resulting stream of blocks:

[outdated] The block stream can also be "opened" to show the stream of tokens within each block. This is shown in the next screenshot:

Step 3

The stream of blocks from step 2 is transformed into a stream of groups.

Step 4

One of many post processing steps could be to remove whitespaces, indentation and comment blocks. So a filter can be applied to remove these block types. Additionally, multiparted blocks (e.g. if a comment or linebreak was inserted between consecutive code sequences, which belong to one block) can be fused to one single block.

This screenshot shows the filtered results:

Example 2 - Simple_1

This is an input file:

-- Copryright 2016
library IEEE;
use     IEEE.std_logic_1164.all;
use      IEEE.numeric_std.all;

entity myEntity is
  generic (
    BITS : positive := 8
  );
  port (
    Clock   : in  std_logic;
    Reset   : in  std_logic;
    Output  : out  std_logic_vector(BITS - 1 downto 0)
  );
end entity;

architecture rtl of myEntity is

begin

end architecture;

This is the result stream:

And this is the filtered and fused result stream:

Contributors

License

This Python package (source code) licensed under Apache License 2.0.
The accompanying documentation is licensed under Creative Commons - Attribution 4.0 (CC-BY 4.0).


SPDX-License-Identifier: Apache-2.0

pyvhdlparser's People

Contributors

dependabot[bot] avatar paebbels avatar std-max avatar xiretza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyvhdlparser's Issues

Incompatible Required Packages

I am interested in using this tool and tried to use the VHDLParser debug tool, but it turns out that there are some incompatibilities with the packages that are currently released vs what the package says is acceptable.

The following requirements are causing issues.

pyTooling>=1.7.0
pyTooling.TerminalUI>=1.5.5

The latest version of pyTooling is 2.0.1 which no longer includes the Singleton metaclass and caused this line to fail:

  File "...\pyVHDLParser\pyVHDLParser\CLI\VHDLParser.py", line 36, in <module>
    from pyTooling.MetaClasses            import Singleton
ImportError: cannot import name 'Singleton' from 'pyTooling.MetaClasses' (...Python\Python39\lib\site-packages\pyTooling
\MetaClasses\__init__.py)

After falling back to pyTooling==1.7.0 there were further issues, but those were indirect import issues not necessarily caused by pyVHDLParser.

I upgraded pyTooling==1.9.5 but that was incompatible with pyTooling.TerminalUI==1.5.8. After downgrading back to pyTooling.TerminalUI==1.5.5 it finally worked.

Suggestion

Require pyTooling to be between 1.7.0 and 1.9.5. I haven't tested later version before 2.0.1 so perhaps just version <= 2 would work.
Require pyTooling.TerminalUI==1.5.5.

Few problems.

Today I have cloned the project and encountered few problems.

  1. You have added PyCharm .idea directory to the git, but it is not synced with the actual project. Namely the run configurations use Frontend.py whereas it should be FrontEnd.py.

  2. Step 2 (block parsing) fails. So far I have encountered 2 problems, but the source of both may be the same. Here are short snippets.

library ieee;
use ieee.std_logic_1164.all;

entity my_entity is
  port (
    i : in std_logic;
    o : out std_logic
  );
end entity my_entity;

architecture rtl of my_entity is

begin

  o <= i;

end architecture rtl;
library ieee;
use ieee.std_logic_1164.all;

entity my_entity is
  port (
    i : in std_logic;
    o : out std_logic
  );
end entity my_entity;

architecture rtl of my_entity is

  signal a, b : std_logic;

begin

  a <= i;
  b <= a;
  o <= b;

end architecture rtl;

You can run BlockStream configuration to recreate them.

Problem parsing generics

Final generic line is not parsing, but this code compiles in ModelSim.

Command: VHDLParser block-stream file.vhdl

lutsize    : positive range 2 to positive'high := 4

Error

ERROR: Expected ';' or ':='.

Code snippet example:

entity comparator is
  generic(
    depth      : positive := 3;  -- pipeline depth required
    data_width : positive := 32; -- data bus width required for data_a and data_b.
    -- number of inputs to a LUT in an FPGA, or for an ASIC, how many bits it is
    -- reasonable to operate on in a single clock cycle. Can be odd number.
    lutsize    : positive range 2 to positive'high := 4
  );
  port(
    clk    : in  std_ulogic;
    reset  : in  std_ulogic;
    data_a : in  std_ulogic_vector(data_width-1 downto 0);
    data_b : in  std_ulogic_vector(data_width-1 downto 0);
    equal  : out std_ulogic
  );
end entity;

Setup failure

The setup of this nice tool fails, due to the missing file "README.rst" referenced by setup.py in line 42:
long_description=open("README.rst").read(),
Running the setup gives the following error:
FileNotFoundError: [Errno 2] No such file or directory: 'README.rst'
It would be great to add a small section to readme.md to explain how the tool should be installed and the example executed.

Code formatting style.

You use some custom style for formatting Python code. Your style differs significantly from PEP8. I know there is no obligation to format non core packages according to the PEP8, however a lot of developers use it and it is much easier to read new code if it has formatting style that you are used to.
Would you consider reformatting to PEP8?

Clk'event

The following piece of legal code if Clk'event and Clk = '1' then -- rising clock edge yields this error:

ERROR: Expected ';', ':=' or whitespace after subtype indication.
================================================================================================================================================================
ERROR: (line: 103, col: 12): Ambiguous syntax detected.

Context clause not supported

The following code fails to parse with VHDLParser block-stream context.vhd

library test_lib;
context test_lib.test_context;

With the output

================================================================================
                        pyVHDLParser - Test Application
================================================================================
[StartOfDocumentBlock]
[Library.StartBlock                                 'library '                                                     at (line:   1, col:  1) .. (line:   1, col:  8)]
[Library.LibraryNameBlock                           'test_lib'                                                     at (line:   1, col:  9) .. (line:   1, col: 17)]
[Library.EndBlock                                   ';'                                                            at (line:   1, col: 17) .. (line:   1, col: 17)]
[LinebreakBlock                                                                                                    at (line:   1, col: 18) .. (line:   1, col: 18)]
ERROR: Expected whitespace after context name (identifier).

From the context.py code it looks like only context declaration is implemented.

Unhandled exception

Running VHDLParser token-stream test_file.vhd I get the following unhandled exception

<CharacterToken                                      ';'  ...................................................... at 138:24>
<LinebreakToken  ----------------------------------------------------------------------------------------------- at 138:25>
<EndOfDocumentToken>
FATAL: An unknown or unhandled exception reached the topmost exception handler!
  Exception type:      TypeError
  Exception message:   isinstance() arg 2 must be a type or tuple of types
  Caused in:           translate in file 'C:\prog\Anaconda3\lib\site-packages\pyvhdlparser-0.6.1-py3.8.egg\pyVHDLParser\CLI\__init__.py' at line 84
--------------------------------------------------------------------------------
  File "C:\prog\Anaconda3\lib\site-packages\pyvhdlparser-0.6.1-py3.8.egg\pyVHDLParser\CLI\VHDLParser.py", line 217, in main
    app.Run()
  File "C:\prog\Anaconda3\lib\site-packages\pyvhdlparser-0.6.1-py3.8.egg\pyVHDLParser\CLI\VHDLParser.py", line 148, in Run
    ArgParseMixin.Run(self)
  File "C:\prog\Anaconda3\lib\site-packages\pyattributes-2.1.0-py3.8.egg\pyAttributes\ArgParseAttributes.py", line 304, in Run
    self._ParseArguments()
  File "C:\prog\Anaconda3\lib\site-packages\pyattributes-2.1.0-py3.8.egg\pyAttributes\ArgParseAttributes.py", line 316, in _ParseArguments
    self._RouteToHandler(args)
  File "C:\prog\Anaconda3\lib\site-packages\pyattributes-2.1.0-py3.8.egg\pyAttributes\ArgParseAttributes.py", line 320, in _RouteToHandler
    args.func(self, args)
  File "C:\prog\Anaconda3\lib\site-packages\pyvhdlparser-0.6.1-py3.8.egg\pyVHDLParser\CLI\Token.py", line 122, in HandleTokenize
    color=translate(token),
  File "C:\prog\Anaconda3\lib\site-packages\pyvhdlparser-0.6.1-py3.8.egg\pyVHDLParser\CLI\__init__.py", line 84, in translate
    if isinstance(token, Token):
--------------------------------------------------------------------------------
Please report this bug at GitHub: https://github.com/Paebbels/pyTerminalUI/issues
--------------------------------------------------------------------------------

Running python 3.8.5 on Win 10.

It seems the issue is Token in if isinstance(token, Token): is detected as pyVHDLParser.CLI.Token instead of pyVHDLParser.Token.Token

Attribute single quote mark errors as "Ambiguous syntax"

Quite excited to see what I can make of the pyVHDLparser. In using it on a simple enough file, I encounter the following:

================================================================================
                        pyVHDLParser - Test Application
================================================================================
FATAL: An unknown or unhandled exception reached the topmost exception handler!
  Exception type:      TokenizerException
  Exception message:   (line:  15, col: 37): Ambiguous syntax detected. buffer: ''l'
  Caused in:           GetVHDLTokenizer in file '/mnt/d/Development/OpenSource/pyVHDLParser/pyVHDLParser/Token/Parser.py' at line 368
--------------------------------------------------------------------------------
  ...Token/Parser.py", line 368, in GetVHDLTokenizer
    raise TokenizerException("Ambiguous syntax detected. buffer: '{buffer}'".format(buffer=buffer), start)
--------------------------------------------------------------------------------
Please report this bug at GitHub: https://github.com/VLSI-EDA/pyIPCMI/issues
--------------------------------------------------------------------------------

This seems to be triggered by the access of 'length... I'll be diving into the Parser.py file to see if I can rectify.

Thanks!

Are std_logic_vectors not supported?

Greetings,

Python I am using:

vhdl_file_path = "C:\\projects\\auto_wapper\\example\\demo.vhd"

# Open a source file
with open(vhdl_file_path, 'r') as fileHandle:
    content = fileHandle.read()


from pyVHDLParser.Token.Parser      import Tokenizer
from pyVHDLParser.Blocks            import TokenToBlockParser
from pyVHDLParser.Base              import ParserException

# get a token generator
tokenStream = Tokenizer.GetVHDLTokenizer(content)
# get a block generator
blockStream = TokenToBlockParser.Transform(tokenStream)



from pyVHDLParser.Blocks            import MetaBlock
for block in MetaBlock.BLOCKS:
        try:
            block.__cls_init__()
        except AttributeError:
            pass

try:
    for block in blockStream:
        print("{block!s}".format(block=block))
    for token in block:
        print("  {token!s}".format(token=token))
except ParserException as ex:
    print("ERROR: {0!s}".format(ex))
except NotImplementedError as ex:
    print("NotImplementedError: {0!s}".format(ex))    

When run on this .vhd file, everything works fine:

entity demo is
    port (
        a    : in  std_logic;
        -- b    : out std_logic_vector( 15 downto 0 );
        c    : out std_logic
    );
end entity demo;

But when I uncomment the line with the std_logic_vector as shown below, I receive the following error.

entity demo is
    port (
        a    : in  std_logic;
        b    : out std_logic_vector( 15 downto 0 );
        c    : out std_logic
    );
end entity demo;
pydev debugger: starting (pid: 18620)
[StartOfDocumentBlock]
[LinebreakBlock                                                                                                    at (line:   1, col:  1) .. (line:   1, col:  1)]
[Entity.NameBlock                                   'entity demo is'                                               at (line:   2, col:  1) .. (line:   2, col: 15)]
[LinebreakBlock                                                                                                    at (line:   2, col: 15) .. (line:   2, col: 15)]
[IndentationBlock                                    length=4 (4)                                                  at (line:   3, col:  1) .. (line:   3, col:  4)]
[PortList.OpenBlock                                 'port ('                                                       at (line:   3, col:  5) .. (line:   3, col: 10)]
[LinebreakBlock                                                                                                    at (line:   3, col: 11) .. (line:   3, col: 11)]
[IndentationBlock                                    length=8 (8)                                                  at (line:   4, col:  1) .. (line:   4, col:  8)]
[PortList.PortListInterfaceSignalBlock              'a    : in  std_logic'                                         at (line:   4, col:  9) .. (line:   4, col: 29)]
[PortList.DelimiterBlock                            ';'                                                            at (line:   4, col: 29) .. (line:   4, col: 29)]
[LinebreakBlock                                                                                                    at (line:   4, col: 30) .. (line:   4, col: 30)]
[IndentationBlock                                    length=8 (8)                                                  at (line:   5, col:  1) .. (line:   5, col:  8)]
ERROR: Expected ';', ':=' or whitespace after subtype indication.

Am I doing something wrong? Any recomendations on how I should proceed? Any and all assistance is greatly appreciated! :)

Error replicating example from the docs

I am trying to run the example from the docs https://pyvhdlparser.readthedocs.io/en/latest/BlockStream/Usage.html
And I get an NoneType is not iterable error.

here is my code

from pyVHDLParser.Token.Parser      import Tokenizer
from pyVHDLParser.Blocks            import TokenToBlockParser
from pyVHDLParser.Base              import ParserException


# Open a source file
with open('strobe_analyzer.vhd', 'r') as fileHandle:
  content = fileHandle.read()


# get a token generator
tokenStream = Tokenizer.GetVHDLTokenizer(content)
# get a block generator
blockStream = TokenToBlockParser.Transform(tokenStream)

try:
  for block in blockStream:
    print("{block!s}".format(block=block))
    for token in block:
      print("  {token!s}".format(token=token))
except ParserException as ex:
  print("ERROR: {0!s}".format(ex))
except NotImplementedError as ex:
  print("NotImplementedError: {0!s}".format(ex))

and you can see the vhdl file I am using to test this attetched (just change the extension to vhd, stupid github issue woudltn let me upload .vhd files.....)
strobe_analyzer.txt

TokenizerException: Ambiguous syntax detected when using arrays

Thank you very much for this project. this looks great so far. But I stumbled upon an error.
Some synthesis tools don't support the direction of array indices very well, but to get that right, we use for example ar(ar'left+i)

Minimal working example:
test.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test is
  port (
    clk : in std_logic
    );
end entity test;

architecture str of test is
  type int_vector is array (natural range<>) of integer;
  constant numbers : int_vector := (1, 2, 3, 4, 5);
  component reg is
    generic (
      content : integer := 0
      );
    port (
      clk : in std_logic
      );
  end component reg;
begin  -- architecture str
  reg_gen : for i in 0 to 3 generate
    reg_inst : reg
      generic map (
        content => numbers(numbers'left+i)
        )
      port map (
        clk => clk);
  end generate reg_gen;
end architecture str;

test.py

with open("test.vhd") as fd:
    content = fd.read()
print(content)
from pyVHDLParser.Token.Parser import Tokenizer
tokenStream = Tokenizer.GetVHDLTokenizer(content)
# get the iterator for that generator
tokenIterator = iter(tokenStream)
firstToken =    next(tokenIterator)
try:
  while lastToken := next(tokenIterator):
    pass
except StopIteration:
  pass
print("first token: {token}".format(token=firstToken))
print("last token:  {token}".format(token=lastToken))

you will geht the following exception for the line content => numbers(numbers'left+i):
TokenizerException: (line: 26, col: 36): Ambiguous syntax detected. buffer: ''l'

I think this is related to issue #18

'range not supported?

Seems to be failing on 'range in the example below.

Win10
python3 --version
Python 3.9.5

Cygwin
python3 --version
Python 3.8.7

library ieee;
use ieee.std_logic_1164.all;


entity transfer is
  generic (
    num_bits1 : positive := 2;
    num_bits2 : positive := 4
  );
  port (
    clk_src1   : in  std_logic;
    reset_src1 : in  std_logic;
    clk_src2   : in  std_logic;
    reset_src2 : in  std_logic;
    clk_dest   : in  std_logic;
    reset_dest : in  std_logic;
    flags_src1 : in  std_logic_vector(num_bits1-1 downto 0);
    flags_src2 : in  std_logic_vector(num_bits2-1 downto 0);
    flags_out  : out std_logic_vector(num_bits1+num_bits2-1 downto 0)
  );
end entity;

architecture rtl of transfer is

  signal reg_catch1   : std_logic_vector(flags_src1'range);
  signal reg_catch2   : std_logic_vector(flags_src2'range);
  signal reg_dest_r   : std_logic_vector(num_bits1+num_bits2-1 downto 0);
  signal conf_src1_r1 : std_logic_vector(flags_src1'range);
  signal conf_src1_r2 : std_logic_vector(flags_src1'range);
  signal conf_src2_r1 : std_logic_vector(flags_src2'range);
  signal conf_src2_r2 : std_logic_vector(flags_src2'range);
  signal conf_dest    : std_logic_vector(num_bits1+num_bits2-1 downto 0);

  -- Could be placed in a constraints file
  attribute ASYNC_REG : string;
  attribute ASYNC_REG of conf_src1_r1 : signal is "TRUE";
  attribute ASYNC_REG of conf_src1_r2 : signal is "TRUE";
  attribute ASYNC_REG of conf_src2_r1 : signal is "TRUE";
  attribute ASYNC_REG of conf_src2_r2 : signal is "TRUE";
  attribute ASYNC_REG of reg_dest_r   : signal is "TRUE";
  attribute ASYNC_REG of flags_out    : signal is "TRUE";

begin

  -- Retain the flag until it has been read in the slower clock domain.
  process(clk_src1)
  begin
    if rising_edge(clk_src1) then
      if reset_src1 = '1' then
        conf_src1_r1 <= (others => '0');
        conf_src1_r2 <= (others => '0');
        reg_catch1   <= (others => '0');
      else
        conf_src1_r1 <= flags_out(num_bits1-1+num_bits2 downto num_bits2);
        conf_src1_r2 <= conf_src1_r1;
        -- Remember the flags until they are acknowledged
        for i in flags_src1'range loop
          if conf_src1_r2(i) = '1' then
            reg_catch1(i) <= '0';
          elsif flags_src1(i) = '1' then
            reg_catch1(i) <= '1';
          end if;
        end loop;
      end if;
    end if;
  end process;

  -- Retain the flag until it has been read in the slower clock domain.
  process(clk_src2)
  begin
    if rising_edge(clk_src2) then
      if reset_src2 = '1' then
        conf_src2_r1 <= (others => '0');
        conf_src2_r2 <= (others => '0');
        reg_catch2   <= (others => '0');
      else
        conf_src2_r1 <= flags_out(num_bits2-1 downto 0);
        conf_src2_r2 <= conf_src2_r1;
        -- Remember the flags until they are acknowledged
        for i in flags_src2'range loop
          if conf_src2_r2(i) = '1' then
            reg_catch2(i) <= '0';
          elsif flags_src2(i) = '1' then
            reg_catch2(i) <= '1';
          end if;
        end loop;
      end if;
    end if;
  end process;

  process(clk_dest)
  begin
    if rising_edge(clk_dest) then
      if reset_dest = '1' then
        reg_dest_r <= (others => '0');
        flags_out  <= (others => '0');
      else
        reg_dest_r <= reg_catch1 & reg_catch2;
        flags_out  <= reg_dest_r;
      end if;
    end if;
  end process;

end architecture;

$ VHDLParser token-stream transfer.vhdl

================================================================================
                        pyVHDLParser - Test Application
================================================================================
FATAL: An unknown or unhandled exception reached the topmost exception handler!
  Exception type:      TokenizerException
  Exception message:   (line:  25, col: 53): Ambiguous syntax detected. buffer: ''r'
  Caused in:           GetVHDLTokenizer in file 'D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyVHDLParser\Token\Parser.py' at line 368
--------------------------------------------------------------------------------
  File "D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyVHDLParser\CLI\VHDLParser.py", line 217, in main
    app.Run()
  File "D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyVHDLParser\CLI\VHDLParser.py", line 148, in Run
    ArgParseMixin.Run(self)
  File "D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyAttributes\ArgParseAttributes.py", line 304, in Run
    self._ParseArguments()
  File "D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyAttributes\ArgParseAttributes.py", line 316, in _ParseArguments
    self._RouteToHandler(args)
  File "D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyAttributes\ArgParseAttributes.py", line 320, in _RouteToHandler
    args.func(self, args)
  File "D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyVHDLParser\CLI\Token.py", line 62, in HandleTokenize
    while next(tokenIterator):
  File "D:\Users\Philip\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pyVHDLParser\Token\Parser.py", line 368, in GetVHDLTokenizer
    raise TokenizerException("Ambiguous syntax detected. buffer: '{buffer}'".format(buffer=buffer), start)
--------------------------------------------------------------------------------
Please report this bug at GitHub: https://github.com/Paebbels/pyTerminalUI/issues
--------------------------------------------------------------------------------

Component not expected before begin in architecture

Parse failure with: VHDLParser block-stream recursive.vhdl

ERROR: Expected one of these keywords: BEGIN, END, USE, CONSTANT, FUNCTION, PROCEDURE, IMPURE, PURE, SIGNAL, SHARED. Found: 'component'.

Example file recursive.vhdl:

--
-- Recursive component instantiation
--
-- instantiation_recursive.vhd
--
-- From p153 https://www.xilinx.com/support/documentation/sw_manuals/xilinx2015_3/ug901-vivado-synthesis.pdf
-- Solely tail recursive example.
--

library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;

entity instantiation_recursive is
  generic(
    sh_st : integer := 4
  );
  port(
    CLK : in  std_logic;
    DI  : in  std_logic;
    DO  : out std_logic
  );
end entity instantiation_recursive;

architecture recursive of instantiation_recursive is
  component instantiation_recursive
    generic(
      sh_st : integer
    );
    port(
      CLK : in std_logic;
      DI : in std_logic;
      DO : out std_logic
    );
  end component;

  signal tmp : std_logic;

begin

  GEN_FD_LAST : if sh_st = 1 generate
    inst_fd : FD
      port map(D => DI, C => CLK, Q => DO);
  end generate;

  GEN_FD_INTERM : if sh_st /= 1 generate
    inst_fd : FD
      port map(D => DI, C => CLK, Q => tmp);

    inst_sstage : instantiation_recursive
      generic map(sh_st => sh_st - 1)
      port map(DI => tmp, CLK => CLK, DO => DO);
  end generate;

end recursive;

Type not expected in package

Command fails: VHDLParser block-stream comp_pkg.vhdl

ERROR: Expected one of these keywords: BEGIN, END, USE, CONSTANT, FUNCTION, PROCEDURE, IMPURE, PURE, VARIABLE, GENERIC. Found: 'type'.

File comp_pkg.vhdl contains:

-------------------------------------------------------------------------------------
-- Package used to provide the tricky calculations for how to divide the logic tree
-- at each level or recursion, calculating top-down as the layers are logic are
-- created. Challenges to take into consideration.
--  1) How much to divide by at each level. How can that be distributed so as to not
--     use more level of logic (LUTs) than is optimally required?
--  2) How to avoid poor division where LUTS are only partially packed, and hence
--     more LUTs end up being consumed than is strictly necessary.
--  3) How to avoid 'pathological' cases where the amount of pipelining requested
--     exceeds that which is really necessary, and causes inefficient LUT packing.
--     E.g. Divide by 2 at each stage when LUTs have 6 inputs (e.g. Xilinx Virtex-6
--     or UltraScale devices, Intel Stratix 10 devices).
--
-------------------------------------------------------------------------------------

package comp_pkg is

  type divide_item_t is record
    divide   : positive;
    maxwidth : positive;
    lutdepth : natural;
  end record;

  function minimum(a, b : positive) return positive;
  
  function lut_depth(
    constant depth   : positive;
    constant width   : positive;
    constant lutsize : positive := 4
  ) return natural;
  
  function recurse_divide(
    constant depth   : positive;
    constant width   : positive;
    constant lutsize : positive := 4
  ) return divide_item_t;

end package;

library ieee;
use ieee.math_real.all;

package body comp_pkg is

  -- Not been implemented for 'positive' in some tools! Where it has been implemented, the function's
  -- presence causes ambiguity. Helpful...
  --
  -- Quartus Prime:
  -- Error (10482): VHDL error at comparator.vhdl(85): object "minimum" is used but not declared
  -- Error: Quartus Prime Analysis & Synthesis was unsuccessful. 1 error, 0 warnings
  --
  -- ModelSim: ** Error: A:/Philip/Work/VHDL/Comparator/comparator.vhdl(89): Subprogram "minimum" is ambiguous.
  --
  function minimum(a, b : positive) return positive is
  begin
    if a < b then
      return a;
    else
      return b;
    end if;
  end function;

  -- For the height in the hierarchy given by 'depth', what is the expected depth of LUTs between
  -- flops for the tree below?
  --
  --          | Depth=1         | Depth=2         | Depth=3         |
  --   Output | Flop - LUT Tree | Flop - LUT tree | Flop - LUT Tree | Inputs
  --
  -- For 'depth' levels of pipelining of 2 * data_width inputs, calculate the LUT depth for the
  -- whole tree and divide by the number of levels that will be spread over. Take into account
  -- that leaf nodes will compare two data buses, so will have 2 * width work to do, or should be
  -- given half the data width on a single bus to work with.
  --
  -- log(width, lutsize)
  --   Gives the LUT depth required when failing to take into account the extra work at leaf nodes.
  --
  -- Extra work at leaf nodes needs to be taken into account, allowing for a doubling of bus width
  -- when calculating the LUT depth.
  --
  -- log(width*2, lutsize)
  --   Becomes the new amount of work to do in the remaining tree.
  --
  -- log(width*2, lutsize) / depth
  --   Averages out that adjusted work over levels of hierarchy or pipeline stages.
  --
  -- This calculation leaves leaf nodes with half the bus width in 2 inputs. The more naive or
  -- basic 'log(width, lutsize)' does not allowed for this, potentially doubling the LUT depth in
  -- the leaf nodes and slowing the achievable maximum clock speed.
  --
  -- Some notes for odd values of 'lutsize'.
  -- =======================================
  --
  -- log(2 * lutsize / (lutsize-1), lutsize)
  --   Replaces the previous calculation taking into account the extra work done in leaf nodes,
  --   where one LUT input can no longer be used. Take for example lutsize = 5:
  --
  -- LUT inputs | Pairs of input bits compared | Usage Ratio
  --      4     |               2              |      2
  --      5     |               2              |     5/2
  --      6     |               3              |      2
  --      7     |               3              |     7/3
  --
  -- '2 * lutsize / (lutsize-1)' is the ratio of the number of inputs to the LUT over the number
  -- of pairs of bits compared. In this example 5/2. In the even case this is equivalent to 6/3
  -- or 4/2, hence the fixed factor of '2' in the adjustment of 'width'.
  --
  -- Given the comparison between adjustment factors of '2' and '2 * lutsize / (lutsize-1)', this
  -- formula can be made more concise with:
  --
  --   2 * lutsize / (lutsize - (lutsize mod 2))
  --
  -- With even lutsize, '2 * lutsize / (lutsize - (lutsize mod 2))' reduces to '2'.
  --
  function lut_depth(
    constant depth   : positive;
    constant width   : positive;
    constant lutsize : positive := 4
  ) return natural is
  begin
    return natural(ceil(
      log(
        real(width * 2 * lutsize / (lutsize - (lutsize mod 2))),
        real(lutsize)
      ) / real(depth)
    ));
  end function;

  -- Decide how much to divide the work with 'depth' levels of hierarchy to go.
  --
  -- If 'depth' is 1, just consume the remaining bits in a comparator implemented with LUTs.
  -- This function is never actually called by leaf nodes, so this clause is perhaps irrelevant.
  --
  -- if 'depth' > 1, then test if we can afford to delay by one level of hierarchy before doing
  -- the work. This tests for the situation where excessive pipelining is requested and avoids
  -- the gratuitous and wasteful use of partially filled LUTs.
  --
  -- If it is appropriate to perform division then:
  --
  --   lutsize ** lutdepth
  --     is the maximum number of inputs that can be consumed by the LUT tree in a single level
  --     of hierarchy.
  --
  --   (lutsize ** lutdepth) ** (depth-1)
  --     is the maximum number of inputs that can be consumed by the remaining 'depth-1' levels
  --     of hierarchy.
  --
  --   maxwidth = (lutsize ** lutdepth) ** (depth-1) / 2
  --                       or
  --   maxwidth = (lutsize ** (lutdepth * (depth-1))) / 2
  --     accounts for leaf nodes having to compare two data buses, so should be assigned half
  --     the width in each input.
  --
  --   round up or ceiling of '(data) width / maxwidth'
  --     the number of divisions of the input data width, maximising the early divisions, leaving
  --     fragments for the last division. Fragments are managed by using the 'minimum' function
  --     to calculate the actual bus width and array indices at comparator instantiation.
  --
  -- Some notes for odd values of 'lutsize'.
  -- =======================================
  --
  -- recurse_divide(): 'maxwidth' needs amending to give a series
  --  depth | maxwidth
  --  ------+---------------------------
  --    1   | (lutsize-1) / 2
  --    2   | lutsize * (lutsize-1) / 2
  --    3   | lutsize**2 * (lutsize-1) / 2
  --
  -- i.e. maxwidth := ((lutsize ** (lutdepth * (depth-1))) - (lutsize ** ((lutdepth * (depth-1))-1))) / 2;
  --
  -- For calculation efficiency, return multiple values from this function call. Otherwise
  -- the same calculations are made repeatedly and unnecessarily in the separate functions.
  --
  function recurse_divide(
    constant depth   : positive;
    constant width   : positive;
    constant lutsize : positive := 4
  ) return divide_item_t is
    variable maxwidth : positive;
    variable lutdepth : natural;
  begin
    if depth = 1 then
      return divide_item_t'(
        width,
        -- Leaf nodes have two input buses, so don't forget to double the logic work.
        width * 2,
        -- lut_depth() takes into account the doubling of width in leaf nodes.
        lut_depth(1, width, lutsize)
      );
    else
      lutdepth := lut_depth(depth, width, lutsize);
      -- If delaying the work for one level of hierarchy does not adversely affect the LUT
      -- depth, do no work this time.
      if lutdepth = lut_depth(depth-1, width, lutsize) then
        return divide_item_t'(1, width, 0);
      else
        maxwidth := (
          -- (lutsize ** lutdepth) bits per level, for depth-1 levels
          (lutsize ** (lutdepth * (depth-1))) -
          -- For odd 'lutsize' only subtract the LUT inputs that can't be connected at leaf nodes.
          ( (lutsize mod 2) * (lutsize ** ((lutdepth * (depth-1))-1)) )
        ) / 2;
        return divide_item_t'(
          positive(ceil( real(width) / real(maxwidth) )),
          maxwidth,
          lutdepth
        );
      end if;
    end if;
  end function;

end package body;

Incompatibility with pyVHDLModel>=v0.10.0

On a fresh install the latest pyVHDLModel package is pulled in (v0.11.1 at the time of writing), which lacks the LibraryReference class. Trying to invoke the cli results in the following error:

from pyVHDLModel.VHDLModel import LibraryReference as LibraryReferenceModel, PackageReference as UseModel
ImportError: cannot import name 'LibraryReference' from 'pyVHDLModel.VHDLModel'

It appears this particular class was removed in v0.10.0 of pyVHDLModel, so perhaps the requirements.txt file should be updated to reflect this dependency.

Subtype Constraint in Entity Port Causes Error

I'd like to help contribute to this project because I find there aren't enough VHDL parsers that are complete and open source, available for use in other projects.

This seems to be as good a place to start as any, so I cloned the repository and quickly found out the subtype constraint on an entity port doesn't pass the blockstreaming with the error ERROR: Expected ';', ':=' or whitespace after subtype indication.

To be clear, this happens whenever the port has a constraint, like a range constraint: s_axis_tdata : in std_logic_vector(31 downto 0);.

There are a lot of constraints which can apply to the subtype. I'm not necessarily worried about capturing them all, but I am interested in parsing out mostly entities and instantiations in code.

If you have a recommendation on where to look in the code to help add the capabilities, and a list of capabilities in order of precedence you want others to handle, I'd like to try to help out.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.