Skip to main content

A simple VHDL preprocessor

Project description

VHDLproc

VHDLproc is a simple command line VHDL preprocessor written in Python following the conditional compilation directives outlined in VHDL-2019, with a few extensions.

Installation

VHDLproc can be installed via pip:

$ pip install vhdlproc
$ vhdlproc --help

It can also be installed from source

$ git clone https://github.com/nobodywasishere/vhdlproc
$ cd vhdlproc
$ python setup.py install --user
$ vhdlproc --help

It can also simply be run as a standalone file

$ git clone https://github.com/nobodywasishere/vhdlproc
$ cd vhdlproc
$ ./vhdlproc/vhdlproc.py --help

Usage

Command Line

usage: vhdlproc.py [-h] [-D IDENTIFIER=value] [-o DIRECTORY] [-e EXTENSION] [--parse-comments]
                   [--self-test] [--log-level LEVEL]
                   [input ...]

VHDLproc v2.3 - VHDL Preprocessor

positional arguments:
  input                Input files (will skip over files with the output extension)

options:
  -h, --help           show this help message and exit
  -D IDENTIFIER=value  Specify identifiers for conditional compilation, ex. DEBUG_LEVEL=2
  -o DIRECTORY         Directory to store parsed files
  -e EXTENSION         Output extension for processed files (defaults to '.proc.vhdl')
  --parse-comments     Parse commented directives as though they aren't commented, overwrite original
                       file. Disables skipping based on file extension
  --self-test          Run a self-test to ensure functionality
  --log-level LEVEL    Configure the logging level

A basic example, where VHDLproc will parse each input file, output the processed text to a new file with a given extension, and the processed files are then passed to GHDL:

vhdlproc *.vhdl              # preprocess all the files
ghdl -a --std=08 *.proc.vhdl # pass processed files to ghdl
ghdl -r --std=08 testbench   # run simulation

As VHDLproc also outputs each of the processed filenames to STDOUT, this would also work:

ghdl -a --std=08 $(vhdlproc *.vhdl)
ghdl -r --std=08 testbench

The parsed files can also be stored to another directory:

vhdlproc *.vhdl -o build/     # preprocess all the files and store in build/
ghdl -a --std=08 build/*.vhdl # pass processed files in build/ to ghdl
ghdl -r --std=08 testbench    # run simulation

Commented directives can also be parsed in-place, including replacing include directives:

vhdlproc *.vhdl -e .vhdl --parse-comments # parse commented directives and overwrite original file
ghdl -a --std=08 *.vhdl       # same exact files that were passed to ghdl
ghdl -r --std=08 testbench    # run simulation

Python Library

Parse files (will automatically set the include path):

from vhdlproc import VHDLproc

processor = VHDLproc()

identifiers = {"VHDL_VERSION": "2008"}

parsed_text = processor.parse_file("path/to/file.vhdl", identifiers=identifiers)

Parse code directly:

from vhdlproc import VHDLproc

processor = VHDLproc()

identifiers = {"VHDL_VERSION": "2008"}

# Parse list of lines of text
code = [
    '`warning "Hello"',
    'constant test_var : integer := 100',
    '`if TOOL_VERSION < "2.0" then',
    '`error "UNSUPPORTED VHDLPROC VERSION"',
    '`end',
    '`include "some/file.vhdl"',
]

parsed_text = processor.parse(code, identifiers=identifiers, include_path="path/to/pull/include/directives/from")

# Parse string
code = '''
`warning "Hello"
constant test_var : integer := 100
`if TOOL_VERSION < "2.0" then
`error "UNSUPPORTED VHDLPROC VERSION"
`end
`include "some/file.vhdl"
'''

parsed_text = processor.parse(code, identifiers=identifiers, include_path="path/to/pull/include/directives/from")

Preprocessor Directives (what you put in your VHDL files)

-- VHDL-2019 directives

`if {CONDITIONAL} then

`elsif {CONDITIONAL} then

`else

`end [if]

`warning "STRING"       --   Print STRING to standard error output stream

`error "STRING"         --   Print STRING to standard error output stream
                        --   Will force close VHDLproc without saving

-- Additional extensions not part of VHDL-2019

`define LABEL "STRING"  --   Gives LABEL the value of STRING for
                        --   conditional statements

`include "FILENAME"     --   Include another file relative to
                        --   the location of the source

`end include "FILENAME" --   This is a counterpart to `include for parsing commented directives
                        --   in-place, should not be used directly (added automatically)
                        --   Sets the bound of where to replace when re-including a file

Identifiers (or Labels)

By default, TOOL_NAME is set to VHDLproc and TOOL_VERSION is set to the current version of the code, these cannot be changed.

Todo

  • Seperate infix definitions, tests, and the main components of VHDLproc into their own files
  • Prevent a file from including itself (to prevent infinite loops)
  • Modify text and file operations to work on Windows (if they don't already)
  • Throw an error if a `warning or `error string isn't wrapped in quotes
  • Parse comments / files in-place
  • Fix precedence of operators
  • Add the option to the CLI to take in a series of file inputs, process them, save the individual results to temporary files (i.e. in /tmp/ or a local path), then return all of the filepaths. This would be useful for doing this with GHDL: ghdl -a $(vhdlproc *.vhdl).

Examples

More examples included under vhdlproc/tests/.

Include File

Input:

`include "include-to.vhdl"

include-to.vhdl:

component pll is
    port (
        clk_in : in std_logic;
        clk_out : out std_logic;
        clk_locked : out std_logic
    );
end component;

Output:

-- `include "include-to.vhdl"
component pll is
    port (
        clk_in : in std_logic;
        clk_out : out std_logic;
        clk_locked : out std_logic
    );
end component;
-- `end include "include-to.vhdl"

Define, Repeated If/Elsif

Input:

`define a "a"
`define b "z"

`if a = "a" and b = "b" then
a = "a" and b = "b"
`elsif a /= "a" and b = "b" then
a /= "a" and b = "b"
`elsif a = "a" and b /= "b" then
a = "a" and b /= "b"
`elsif a /= "a" and b /= "b" then
a /= "a" and b /= "b"
`else
`warning "Not supposed to be here"
`end

Output:

-- `define a "a"
-- `define b "z"

-- `if a = "a" and b = "b" then
-- a = "a" and b = "b"
-- `elsif a /= "a" and b = "b" then
-- a /= "a" and b = "b"
-- `elsif a = "a" and b /= "b" then
a = "a" and b /= "b"
-- `elsif a /= "a" and b /= "b" then
-- a /= "a" and b /= "b"
-- `else
-- `warning "Not supposed to be here"
-- `end

Nested If

Input:

`define a "a"
`define b "b"

`if a = "a" then
`if b = "b" then
a = "a" and b = "b"
`else
a = "a" and b /= "b"
`end
`end

Output:

-- `define a "a"
-- `define b "b"

-- `if a = "a" then
-- `if b = "b" then
a = "a" and b = "b"
-- `else
-- a = "a" and b /= "b"
-- `end
-- `end

VHDL Version

Input:

`define VHDL_VERSION "2019"
`if VHDL_VERSION >= "2008" then
constant enable_features : bool := true
`else
`warning "Certain features disabled!"
constant enable_features : bool := false
`end

Output:

-- `define VHDL_VERSION "2019"
-- `if VHDL_VERSION >= "2008" then
constant enable_features : bool := true
-- `else
-- `warning "Certain features disabled!"
-- constant enable_features : bool := false
-- `end

Parsing Comments

With the flag --parse-comments, directives are executed in-place as if they weren't commented. Code added by an include directive is replaced with an updated version, bounded by a corresponding end include.

Input:

-- `warning "== Including file =="
-- `define Include_file "TRUE"

-- `if INCLUDE_FILE = "TRUE" then
-- `include "../tests/include-to.vhdl"
component OLD_CODE is
  port(
	  a : in unsigned(3 downto 0);
	  b : in unsigned(3 downto 0);
	  s : in std_logic_vector(1 downto 0);
	  y : out unsigned(3 downto 0)
  );
end component;
-- `end include "../tests/include-to.vhdl"
-- `else
-- `error "Not including thing"
-- `end if

-- `warning "== Not including file =="
-- `define Include_file "false"
-- `define passed ""

-- `if INCLUDE_FILE = "TRUE" then
-- `include "../tests/include-to.vhdl"
-- `else
-- `end if

-- `if passed /= "" then
-- `Warning "Failed"
-- `else
-- `Warning "Passed"
-- `end

include-to.vhdl:

component pll is
    port (
        clk_in : in std_logic;
        clk_out : out std_logic;
        clk_locked : out std_logic
    );
end component;
`if include_file = "false" then
`error "Failed"
`else
`warning "Passed"
`end

`define passed "failed"

Output:

-- `warning "== Including file =="
-- `define Include_file "TRUE"

-- `if INCLUDE_FILE = "TRUE" then
-- `include "../tests/include-to.vhdl"
component pll is
    port (
        clk_in : in std_logic;
        clk_out : out std_logic;
        clk_locked : out std_logic
    );
end component;
-- `if include_file = "false" then
-- `error "Failed"
-- `else
-- `warning "Passed"
-- `end

-- `define passed "failed"
-- `end include "../tests/include-to.vhdl"
-- `else
-- `error "Not including thing"
-- `end if

-- `warning "== Not including file =="
-- `define Include_file "false"
-- `define passed ""

-- `if INCLUDE_FILE = "TRUE" then
-- `include "../tests/include-to.vhdl"
-- `else
-- `end if

-- `if passed /= "" then
-- `Warning "Failed"
-- `else
-- `Warning "Passed"
-- `end

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vhdlproc-2.3.tar.gz (23.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vhdlproc-2.3-py3-none-any.whl (23.0 kB view details)

Uploaded Python 3

File details

Details for the file vhdlproc-2.3.tar.gz.

File metadata

  • Download URL: vhdlproc-2.3.tar.gz
  • Upload date:
  • Size: 23.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.10.4

File hashes

Hashes for vhdlproc-2.3.tar.gz
Algorithm Hash digest
SHA256 660384f8f5376887aff3f0549b69f2be4b0b1b2ba8df55a23792d0b6590e5d66
MD5 456987ef9046600356085686ca6538bf
BLAKE2b-256 efcad4c7c1a7b5931ff9b0d989015536997c1b877f84441f047a6fd109c389f7

See more details on using hashes here.

File details

Details for the file vhdlproc-2.3-py3-none-any.whl.

File metadata

  • Download URL: vhdlproc-2.3-py3-none-any.whl
  • Upload date:
  • Size: 23.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.10.4

File hashes

Hashes for vhdlproc-2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 181a40fe6b480cdde983588883db27e175562f60df3035fd3cb5322da6591a83
MD5 87852b062343de596b3e3ed3b2f401cb
BLAKE2b-256 c57be04a758d0aed9f1fba622b0f191ad41a4b16e3cd6fb5ae9fd7e4dd4d7511

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page