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
`warningor`errorstring 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
660384f8f5376887aff3f0549b69f2be4b0b1b2ba8df55a23792d0b6590e5d66
|
|
| MD5 |
456987ef9046600356085686ca6538bf
|
|
| BLAKE2b-256 |
efcad4c7c1a7b5931ff9b0d989015536997c1b877f84441f047a6fd109c389f7
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
181a40fe6b480cdde983588883db27e175562f60df3035fd3cb5322da6591a83
|
|
| MD5 |
87852b062343de596b3e3ed3b2f401cb
|
|
| BLAKE2b-256 |
c57be04a758d0aed9f1fba622b0f191ad41a4b16e3cd6fb5ae9fd7e4dd4d7511
|