slvcodec
========
slvcodec is a tool that analyzes VHDL and generates:
* Functions to convert arbitrary VHDL types to and from std_logic_vector.
* Generate testbenches for entities that read inputs from a file, and
write outputs to a file.
* Utilities so that unit tests for VHDL code can easily to be written
in python.
Generation of functions to convert to and from std_logic_vector
---------------------------------------------------------------
Here's an example VHDL package.
.. code:: vhdl
library ieee;
use ieee.numeric_std.all;
package complex is
constant FIXED_WIDTH: natural := 8;
subtype fixed_t is unsigned(FIXED_WIDTH-1 downto 0);
type complex_t is record
real: fixed_t;
imag: fixed_t;
end record;
type array_of_complex is array(natural range <>) of complex_t;
end package;
The following python script is used to generate a helper package that contains
functions to convert the types to and from std_logic_vector.
.. code:: python
import os
from slvcodec import filetestbench_generator
thisdir = os.path.dirname(__file__)
def make_slvcodec_package():
complex_pkg_fn = os.path.join(thisdir, 'complex_pkg.vhd')
directory = os.path.join(thisdir, 'generated')
os.mkdir(directory)
filetestbench_generator.add_slvcodec_files(directory, [complex_pkg_fn])
if __name__ == '__main__':
make_slvcodec_package()
Here is what the generated VHDL looks like.
.. code:: vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.complex.all;
use work.slvcodec.all;
package complex_slvcodec is
function to_slvcodec (constant data: array_of_complex) return std_logic_vector;
function from_slvcodec (constant slv: std_logic_vector) return array_of_complex;
constant fixed_t_slvcodecwidth: natural := fixed_width;
constant complex_t_slvcodecwidth: natural := 2*fixed_width;
function to_slvcodec (constant data: complex_t) return std_logic_vector;
function from_slvcodec (constant slv: std_logic_vector) return complex_t;
end package;
package body complex_slvcodec is
function to_slvcodec (constant data: array_of_complex) return std_logic_vector is
constant W: natural := complex_t_slvcodecwidth;
constant N: natural := data'length;
variable slv: std_logic_vector(N*W-1 downto 0);
begin
for ii in 0 to N-1 loop
slv((ii+1)*W-1 downto ii*W) := to_slvcodec(data(ii));
end loop;
return slv;
end function;
function from_slvcodec (constant slv: std_logic_vector) return array_of_complex is
constant W: natural := complex_t_slvcodecwidth;
constant N: natural := slv'length/W;
variable mapped: std_logic_vector(slv'length-1 downto 0);
variable output: array_of_complex(N-1 downto 0);
begin
mapped := slv;
for ii in 0 to N-1 loop
output(ii) := from_slvcodec(mapped((ii+1)*W-1 downto ii*W));
end loop;
return output;
end function;
function to_slvcodec (constant data: complex_t) return std_logic_vector is
constant W0: natural := 0;
constant W1: natural := W0 + fixed_width;
constant W2: natural := W1 + fixed_width;
variable slv: std_logic_vector(complex_t_slvcodecwidth-1 downto 0);
begin
slv(W1-1 downto W0) := to_slvcodec(data.real);
slv(W2-1 downto W1) := to_slvcodec(data.imag);
return slv;
end function;
function from_slvcodec (constant slv: std_logic_vector) return complex_t is
constant W0: natural := 0;
constant W1: natural := W0 + fixed_width;
constant W2: natural := W1 + fixed_width;
variable data: complex_t;
variable mapped: std_logic_vector(complex_t_slvcodecwidth-1 downto 0);
begin
mapped := slv;
data.real := from_slvcodec(mapped(W1-1 downto W0));
data.imag := from_slvcodec(mapped(W2-1 downto W1));
return data;
end function;
end package body;
Generation of file-based testbenches
------------------------------------
Here's an example entity that just returns the magnitude squared of a complex data type
that we defined earlier.
.. code:: vhdl
library ieee;
use ieee.numeric_std.all;
use work.complex.all;
entity complex_mag2 is
port (
i: in complex_t;
o: out unsigned(FIXED_WIDTH+1-1 downto 0)
);
end entity;
architecture arch of complex_mag2 is
signal real2: signed(FIXED_WIDTH*2-1 downto 0);
signal imag2: signed(FIXED_WIDTH*2-1 downto 0);
signal mag2: unsigned(FIXED_WIDTH*2-1 downto 0);
signal scaled_mag2: unsigned(FIXED_WIDTH+1-1 downto 0);
begin
real2 <= i.real * i.real;
imag2 <= i.imag * i.imag;
mag2 <= unsigned(real2) + unsigned(imag2);
scaled_mag2 <= mag2(FIXED_WIDTH*2-1-1 downto FIXED_WIDTH-2);
o <= scaled_mag2;
end architecture;
We can use slvcodec to generate a testbench that reads input data from a file,
and writes output data to another file.
.. code:: python
import os
from slvcodec import filetestbench_generator
thisdir = os.path.dirname(__file__)
def make_slvcodec_package():
complex_pkg_fn = os.path.join(thisdir, 'complex_pkg.vhd')
directory = os.path.join(thisdir, 'generated')
os.mkdir(directory)
slvcodec_files = filetestbench_generator.add_slvcodec_files(directory, [complex_pkg_fn])
return slvcodec_files
def make_complex_mag2_testbench():
base_filenames = [
os.path.join(thisdir, 'complex_pkg.vhd'),
os.path.join(thisdir, 'complex_mag2.vhd'),
]
slvcodec_fns = make_slvcodec_package()
with_slvcodec_fns = base_filenames + slvcodec_fns
directory = os.path.join(thisdir, 'generated')
generated_fns, generated_wrapper_fns, resolved = filetestbench_generator.prepare_files(
directory=directory, filenames=with_slvcodec_fns,
top_entity='complex_mag2')
return generated_fns
if __name__ == '__main__':
make_complex_mag2_testbench()
This will generate the following VHDL testbench.
.. code:: vhdl
library ieee;
use ieee.std_logic_1164.all;
use work.slvcodec.all;
use ieee.numeric_std.all;
use work.complex.all;
use work.complex_slvcodec.all;
entity complex_mag2_tb is
generic (
CLOCK_PERIOD: time := 10 ns;
RUNNER_CFG: string;
OUTPUT_PATH: string
);
end entity;
architecture arch of complex_mag2_tb is
type t_input is
record
i: complex_t;
end record;
type t_output is
record
o: unsigned((1+fixed_width)-1 downto 0);
end record;
constant t_input_slvcodecwidth: natural := 2*fixed_width;
function to_slvcodec (constant data: t_input) return std_logic_vector;
function from_slvcodec (constant slv: std_logic_vector) return t_input;
function to_slvcodec (constant data: t_input) return std_logic_vector is
constant W0: natural := 0;
constant W1: natural := W0 + 2*fixed_width;
variable slv: std_logic_vector(t_input_slvcodecwidth-1 downto 0);
begin
slv(W1-1 downto W0) := to_slvcodec(data.i);
return slv;
end function;
function from_slvcodec (constant slv: std_logic_vector) return t_input is
constant W0: natural := 0;
constant W1: natural := W0 + 2*fixed_width;
variable data: t_input;
variable mapped: std_logic_vector(t_input_slvcodecwidth-1 downto 0);
begin
mapped := slv;
data.i := from_slvcodec(mapped(W1-1 downto W0));
return data;
end function;
constant t_output_slvcodecwidth: natural := (1+fixed_width);
function to_slvcodec (constant data: t_output) return std_logic_vector;
function from_slvcodec (constant slv: std_logic_vector) return t_output;
function to_slvcodec (constant data: t_output) return std_logic_vector is
constant W0: natural := 0;
constant W1: natural := W0 + (1+fixed_width);
variable slv: std_logic_vector(t_output_slvcodecwidth-1 downto 0);
begin
slv(W1-1 downto W0) := to_slvcodec(data.o);
return slv;
end function;
function from_slvcodec (constant slv: std_logic_vector) return t_output is
constant W0: natural := 0;
constant W1: natural := W0 + (1+fixed_width);
variable data: t_output;
variable mapped: std_logic_vector(t_output_slvcodecwidth-1 downto 0);
begin
mapped := slv;
data.o := from_slvcodec(mapped(W1-1 downto W0));
return data;
end function;
signal input_data: t_input;
signal output_data: t_output;
signal input_slv: std_logic_vector(t_input_slvcodecwidth-1 downto 0);
signal output_slv: std_logic_vector(t_output_slvcodecwidth-1 downto 0);
signal clk: std_logic;
signal read_clk: std_logic;
signal write_clk: std_logic;
begin
input_data <= from_slvcodec(input_slv);
output_slv <= to_slvcodec(output_data);
file_reader: entity work.ReadFile
generic map(FILENAME => OUTPUT_PATH & "/indata.dat",
PASSED_RUNNER_CFG => RUNNER_CFG,
WIDTH => t_input_slvcodecwidth)
port map(clk => read_clk,
out_data => input_slv);
file_writer: entity work.WriteFile
generic map(FILENAME => OUTPUT_PATH & "/outdata.dat",
WIDTH => t_output_slvcodecwidth)
port map(clk => write_clk,
in_data => output_slv);
clock_generator: entity work.ClockGenerator
generic map(CLOCK_PERIOD => CLOCK_PERIOD,
CLOCK_OFFSET => 0 ns
)
port map(clk => clk);
read_clock_generator: entity work.ClockGenerator
generic map(CLOCK_PERIOD => CLOCK_PERIOD,
CLOCK_OFFSET => CLOCK_PERIOD/10
)
port map(clk => read_clk);
write_clock_generator: entity work.ClockGenerator
generic map(CLOCK_PERIOD => CLOCK_PERIOD,
CLOCK_OFFSET => 4*CLOCK_PERIOD/10
)
port map(clk => write_clk);
dut: entity work.complex_mag2
port map(
i => input_data.i,
o => output_data.o
);
end architecture;
But generating a test bench that just reads and writes the input and output data
to and from files isn't particularly useful unless we have a way of generating the
input data, and checking the output data. Slvcodec include tools to do this
with python.
Python-based testing
--------------------
We define a python class with a ``make_input_data`` method that returns an iterable of
dictionaries specifying the input data, and a ``check_output_data`` method that receives
a list of input_data dictionaries and a list of output data dictionaries, that raises an
exeception is the output data is incorrect.
.. code:: python
class ComplexMag2Test:
def __init__(self, resolved, generics, top_params):
# Here we're taking advantage of the fact that when the test is intialized it
# has access to the parsed VHDL. We use that to get the value of the constant
# FIXED_WIDTH that is defined in complex_pkg.vhd.
self.fixed_width = resolved['packages']['complex'].constants['fixed_width'].value()
self.max_fixed = pow(2, self.fixed_width-1)-1
self.min_fixed = -pow(2, self.fixed_width-1)
self.n_data = 100
def fixed_to_float(self, f):
r = f / pow(2, self.fixed_width-2)
return r
def make_input_data(self, seed=None, n_data=3000):
input_data = [{
'i': {'real': random.randint(self.min_fixed, self.max_fixed),
'imag': random.randint(self.min_fixed, self.max_fixed)},
} for i in range(self.n_data)]
return input_data
def check_output_data(self, input_data, output_data):
inputs = [self.fixed_to_float(d['i']['real']) + self.fixed_to_float(d['i']['imag']) * 1j
for d in input_data]
input_float_mag2s = [abs(v)*abs(v) for v in inputs]
outputs = [self.fixed_to_float(d['o']) for d in output_data]
differences = [abs(expected - actual) for expected, actual in zip(input_float_mag2s, outputs)]
allowed_error = 1/pow(2, self.fixed_width-2)
assert all([d < allowed_error for d in differences])
We then use ``slvcodec.test_utils.register_test_with_vunit`` to generate an appropriate testbench and input
data file, and register the produced test with vunit. VUnit can then be run as normal.
.. code:: python
from slvcodec import test_utils, config
import os
if __name__ == '__main__':
random.seed(0)
# Initialize vunit with command line parameters.
vu = config.setup_vunit()
# Set up logging.
config.setup_logging(vu.log_level)
# Get filenames for test
this_dir = os.path.dirname(os.path.realpath(__file__))
filenames = [
os.path.join(this_dir, 'complex_pkg.vhd'),
os.path.join(this_dir, 'complex_mag2.vhd'),
]
# Register the test with VUnit.
test_output_directory = os.path.join(this_dir, 'generated')
test_utils.register_test_with_vunit(
vu=vu,
directory=test_output_directory,
filenames=filenames,
top_entity='complex_mag2',
all_generics=[{}],
test_class=ComplexMag2Test,
top_params={},
)
# Run the tests with VUnit
vu.set_sim_option('disable_ieee_warnings', True)
vu.main()
Raw data
{
"_id": null,
"home_page": "https://github.com/benreynwar/slvcodec",
"name": "slvcodec",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "VHDL, hdl, rtl, FPGA, ASIC, Xilinx, Altera",
"author": "Ben Reynwar",
"author_email": "ben@reynwar.net",
"download_url": "https://files.pythonhosted.org/packages/71/f9/80deec0a36ca541990704cafd8b544ef2d304c1d18f259fdd91e78d0cf7e/slvcodec-0.4.19.tar.gz",
"platform": null,
"description": "\nslvcodec\n========\n\nslvcodec is a tool that analyzes VHDL and generates:\n\n * Functions to convert arbitrary VHDL types to and from std_logic_vector.\n\n * Generate testbenches for entities that read inputs from a file, and\n write outputs to a file.\n\n * Utilities so that unit tests for VHDL code can easily to be written\n in python.\n\n\nGeneration of functions to convert to and from std_logic_vector\n---------------------------------------------------------------\n\nHere's an example VHDL package.\n\n.. code:: vhdl\n \n library ieee;\n use ieee.numeric_std.all;\n \n package complex is\n \n constant FIXED_WIDTH: natural := 8;\n subtype fixed_t is unsigned(FIXED_WIDTH-1 downto 0);\n \n type complex_t is record\n real: fixed_t;\n imag: fixed_t;\n end record;\n \n type array_of_complex is array(natural range <>) of complex_t;\n \n end package;\n\nThe following python script is used to generate a helper package that contains\nfunctions to convert the types to and from std_logic_vector.\n\n.. code:: python\n \n import os\n \n from slvcodec import filetestbench_generator\n \n \n thisdir = os.path.dirname(__file__)\n \n \n def make_slvcodec_package():\n complex_pkg_fn = os.path.join(thisdir, 'complex_pkg.vhd')\n directory = os.path.join(thisdir, 'generated')\n os.mkdir(directory)\n filetestbench_generator.add_slvcodec_files(directory, [complex_pkg_fn])\n \n \n if __name__ == '__main__':\n make_slvcodec_package()\n\nHere is what the generated VHDL looks like.\n\n.. code:: vhdl\n\n library ieee;\n use ieee.std_logic_1164.all;\n use ieee.numeric_std.all;\n use work.complex.all;\n use work.slvcodec.all;\n \n package complex_slvcodec is\n \n \n function to_slvcodec (constant data: array_of_complex) return std_logic_vector;\n function from_slvcodec (constant slv: std_logic_vector) return array_of_complex;\n constant fixed_t_slvcodecwidth: natural := fixed_width;\n constant complex_t_slvcodecwidth: natural := 2*fixed_width;\n function to_slvcodec (constant data: complex_t) return std_logic_vector;\n function from_slvcodec (constant slv: std_logic_vector) return complex_t;\n \n end package;\n \n package body complex_slvcodec is\n \n function to_slvcodec (constant data: array_of_complex) return std_logic_vector is\n constant W: natural := complex_t_slvcodecwidth;\n constant N: natural := data'length;\n variable slv: std_logic_vector(N*W-1 downto 0);\n begin\n for ii in 0 to N-1 loop\n slv((ii+1)*W-1 downto ii*W) := to_slvcodec(data(ii));\n end loop;\n return slv; \n end function;\n \n function from_slvcodec (constant slv: std_logic_vector) return array_of_complex is\n constant W: natural := complex_t_slvcodecwidth;\n constant N: natural := slv'length/W;\n variable mapped: std_logic_vector(slv'length-1 downto 0);\n variable output: array_of_complex(N-1 downto 0);\n begin\n mapped := slv;\n for ii in 0 to N-1 loop\n output(ii) := from_slvcodec(mapped((ii+1)*W-1 downto ii*W));\n end loop;\n return output; \n end function;\n \n function to_slvcodec (constant data: complex_t) return std_logic_vector is\n constant W0: natural := 0;\n constant W1: natural := W0 + fixed_width;\n constant W2: natural := W1 + fixed_width;\n variable slv: std_logic_vector(complex_t_slvcodecwidth-1 downto 0);\n begin\n slv(W1-1 downto W0) := to_slvcodec(data.real);\n slv(W2-1 downto W1) := to_slvcodec(data.imag);\n return slv; \n end function;\n \n function from_slvcodec (constant slv: std_logic_vector) return complex_t is\n constant W0: natural := 0;\n constant W1: natural := W0 + fixed_width;\n constant W2: natural := W1 + fixed_width;\n variable data: complex_t;\n variable mapped: std_logic_vector(complex_t_slvcodecwidth-1 downto 0);\n begin\n mapped := slv;\n data.real := from_slvcodec(mapped(W1-1 downto W0)); \n data.imag := from_slvcodec(mapped(W2-1 downto W1)); \n return data; \n end function;\n \n end package body;\n \n\nGeneration of file-based testbenches\n------------------------------------\n\nHere's an example entity that just returns the magnitude squared of a complex data type\nthat we defined earlier.\n\n.. code:: vhdl\n \n library ieee;\n use ieee.numeric_std.all;\n use work.complex.all;\n \n entity complex_mag2 is\n port (\n i: in complex_t;\n o: out unsigned(FIXED_WIDTH+1-1 downto 0)\n );\n end entity;\n \n architecture arch of complex_mag2 is\n \n signal real2: signed(FIXED_WIDTH*2-1 downto 0);\n signal imag2: signed(FIXED_WIDTH*2-1 downto 0);\n signal mag2: unsigned(FIXED_WIDTH*2-1 downto 0);\n signal scaled_mag2: unsigned(FIXED_WIDTH+1-1 downto 0);\n \n begin\n \n real2 <= i.real * i.real;\n imag2 <= i.imag * i.imag;\n mag2 <= unsigned(real2) + unsigned(imag2);\n \n scaled_mag2 <= mag2(FIXED_WIDTH*2-1-1 downto FIXED_WIDTH-2);\n \n o <= scaled_mag2;\n \n end architecture;\n\nWe can use slvcodec to generate a testbench that reads input data from a file,\nand writes output data to another file.\n\n.. code:: python\n\n import os\n \n from slvcodec import filetestbench_generator\n \n \n thisdir = os.path.dirname(__file__)\n \n \n def make_slvcodec_package():\n complex_pkg_fn = os.path.join(thisdir, 'complex_pkg.vhd')\n directory = os.path.join(thisdir, 'generated')\n os.mkdir(directory)\n slvcodec_files = filetestbench_generator.add_slvcodec_files(directory, [complex_pkg_fn])\n return slvcodec_files\n \n \n def make_complex_mag2_testbench():\n base_filenames = [\n os.path.join(thisdir, 'complex_pkg.vhd'),\n os.path.join(thisdir, 'complex_mag2.vhd'),\n ]\n slvcodec_fns = make_slvcodec_package()\n with_slvcodec_fns = base_filenames + slvcodec_fns\n directory = os.path.join(thisdir, 'generated')\n generated_fns, generated_wrapper_fns, resolved = filetestbench_generator.prepare_files(\n directory=directory, filenames=with_slvcodec_fns,\n top_entity='complex_mag2')\n return generated_fns\n \n\n if __name__ == '__main__':\n make_complex_mag2_testbench()\n\n\nThis will generate the following VHDL testbench.\n\n.. code:: vhdl\n \n library ieee;\n use ieee.std_logic_1164.all;\n use work.slvcodec.all;\n use ieee.numeric_std.all;\n use work.complex.all;\n use work.complex_slvcodec.all;\n \n entity complex_mag2_tb is\n generic (\n \n CLOCK_PERIOD: time := 10 ns;\n RUNNER_CFG: string;\n OUTPUT_PATH: string\n );\n end entity;\n \n architecture arch of complex_mag2_tb is\n type t_input is\n record\n i: complex_t;\n end record;\n type t_output is\n record\n o: unsigned((1+fixed_width)-1 downto 0);\n end record;\n constant t_input_slvcodecwidth: natural := 2*fixed_width;\n function to_slvcodec (constant data: t_input) return std_logic_vector;\n function from_slvcodec (constant slv: std_logic_vector) return t_input;\n function to_slvcodec (constant data: t_input) return std_logic_vector is\n constant W0: natural := 0;\n constant W1: natural := W0 + 2*fixed_width;\n variable slv: std_logic_vector(t_input_slvcodecwidth-1 downto 0);\n begin\n slv(W1-1 downto W0) := to_slvcodec(data.i);\n return slv; \n end function;\n \n function from_slvcodec (constant slv: std_logic_vector) return t_input is\n constant W0: natural := 0;\n constant W1: natural := W0 + 2*fixed_width;\n variable data: t_input;\n variable mapped: std_logic_vector(t_input_slvcodecwidth-1 downto 0);\n begin\n mapped := slv;\n data.i := from_slvcodec(mapped(W1-1 downto W0)); \n return data; \n end function;\n constant t_output_slvcodecwidth: natural := (1+fixed_width);\n function to_slvcodec (constant data: t_output) return std_logic_vector;\n function from_slvcodec (constant slv: std_logic_vector) return t_output;\n function to_slvcodec (constant data: t_output) return std_logic_vector is\n constant W0: natural := 0;\n constant W1: natural := W0 + (1+fixed_width);\n variable slv: std_logic_vector(t_output_slvcodecwidth-1 downto 0);\n begin\n slv(W1-1 downto W0) := to_slvcodec(data.o);\n return slv; \n end function;\n \n function from_slvcodec (constant slv: std_logic_vector) return t_output is\n constant W0: natural := 0;\n constant W1: natural := W0 + (1+fixed_width);\n variable data: t_output;\n variable mapped: std_logic_vector(t_output_slvcodecwidth-1 downto 0);\n begin\n mapped := slv;\n data.o := from_slvcodec(mapped(W1-1 downto W0)); \n return data; \n end function;\n signal input_data: t_input;\n signal output_data: t_output;\n signal input_slv: std_logic_vector(t_input_slvcodecwidth-1 downto 0);\n signal output_slv: std_logic_vector(t_output_slvcodecwidth-1 downto 0);\n signal clk: std_logic;\n signal read_clk: std_logic;\n signal write_clk: std_logic;\n begin\n \n input_data <= from_slvcodec(input_slv);\n output_slv <= to_slvcodec(output_data);\n \n file_reader: entity work.ReadFile\n generic map(FILENAME => OUTPUT_PATH & \"/indata.dat\",\n PASSED_RUNNER_CFG => RUNNER_CFG,\n WIDTH => t_input_slvcodecwidth)\n port map(clk => read_clk,\n out_data => input_slv);\n \n file_writer: entity work.WriteFile\n generic map(FILENAME => OUTPUT_PATH & \"/outdata.dat\",\n WIDTH => t_output_slvcodecwidth)\n port map(clk => write_clk,\n in_data => output_slv);\n \n clock_generator: entity work.ClockGenerator\n generic map(CLOCK_PERIOD => CLOCK_PERIOD,\n CLOCK_OFFSET => 0 ns\n )\n port map(clk => clk);\n \n read_clock_generator: entity work.ClockGenerator\n generic map(CLOCK_PERIOD => CLOCK_PERIOD,\n CLOCK_OFFSET => CLOCK_PERIOD/10\n )\n port map(clk => read_clk);\n \n write_clock_generator: entity work.ClockGenerator\n generic map(CLOCK_PERIOD => CLOCK_PERIOD,\n CLOCK_OFFSET => 4*CLOCK_PERIOD/10\n )\n port map(clk => write_clk);\n \n dut: entity work.complex_mag2\n port map(\n i => input_data.i,\n o => output_data.o\n );\n \n end architecture;\n\n\nBut generating a test bench that just reads and writes the input and output data\nto and from files isn't particularly useful unless we have a way of generating the\ninput data, and checking the output data. Slvcodec include tools to do this\nwith python.\n\nPython-based testing\n--------------------\n\nWe define a python class with a ``make_input_data`` method that returns an iterable of\ndictionaries specifying the input data, and a ``check_output_data`` method that receives\na list of input_data dictionaries and a list of output data dictionaries, that raises an\nexeception is the output data is incorrect.\n\n.. code:: python\n\n class ComplexMag2Test:\n \n def __init__(self, resolved, generics, top_params):\n # Here we're taking advantage of the fact that when the test is intialized it\n # has access to the parsed VHDL. We use that to get the value of the constant\n # FIXED_WIDTH that is defined in complex_pkg.vhd.\n self.fixed_width = resolved['packages']['complex'].constants['fixed_width'].value()\n self.max_fixed = pow(2, self.fixed_width-1)-1\n self.min_fixed = -pow(2, self.fixed_width-1)\n self.n_data = 100\n \n def fixed_to_float(self, f):\n r = f / pow(2, self.fixed_width-2)\n return r\n \n def make_input_data(self, seed=None, n_data=3000):\n input_data = [{\n 'i': {'real': random.randint(self.min_fixed, self.max_fixed),\n 'imag': random.randint(self.min_fixed, self.max_fixed)},\n } for i in range(self.n_data)]\n \n return input_data\n \n def check_output_data(self, input_data, output_data):\n inputs = [self.fixed_to_float(d['i']['real']) + self.fixed_to_float(d['i']['imag']) * 1j\n for d in input_data]\n input_float_mag2s = [abs(v)*abs(v) for v in inputs] \n outputs = [self.fixed_to_float(d['o']) for d in output_data]\n differences = [abs(expected - actual) for expected, actual in zip(input_float_mag2s, outputs)]\n allowed_error = 1/pow(2, self.fixed_width-2)\n assert all([d < allowed_error for d in differences])\n\n\nWe then use ``slvcodec.test_utils.register_test_with_vunit`` to generate an appropriate testbench and input\ndata file, and register the produced test with vunit. VUnit can then be run as normal.\n\n\n.. code:: python\n\n from slvcodec import test_utils, config\n import os\n \n if __name__ == '__main__':\n random.seed(0)\n # Initialize vunit with command line parameters.\n vu = config.setup_vunit()\n # Set up logging.\n config.setup_logging(vu.log_level)\n # Get filenames for test\n this_dir = os.path.dirname(os.path.realpath(__file__))\n filenames = [\n os.path.join(this_dir, 'complex_pkg.vhd'),\n os.path.join(this_dir, 'complex_mag2.vhd'),\n ]\n # Register the test with VUnit.\n test_output_directory = os.path.join(this_dir, 'generated')\n test_utils.register_test_with_vunit(\n vu=vu,\n directory=test_output_directory,\n filenames=filenames,\n top_entity='complex_mag2',\n all_generics=[{}],\n test_class=ComplexMag2Test,\n top_params={},\n )\n # Run the tests with VUnit\n vu.set_sim_option('disable_ieee_warnings', True)\n vu.main()\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Utilities for generating VHDL to convert to and from std_logic_vector, as well as utilties to create testbenches described by python.",
"version": "0.4.19",
"project_urls": {
"Homepage": "https://github.com/benreynwar/slvcodec"
},
"split_keywords": [
"vhdl",
" hdl",
" rtl",
" fpga",
" asic",
" xilinx",
" altera"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "71f980deec0a36ca541990704cafd8b544ef2d304c1d18f259fdd91e78d0cf7e",
"md5": "04d5f09e6efdbc464f4600d90aa2314d",
"sha256": "1fc54ff05b83663b79ca839a5be09d6e5452afe1affd574859fe5edcf1e028ea"
},
"downloads": -1,
"filename": "slvcodec-0.4.19.tar.gz",
"has_sig": false,
"md5_digest": "04d5f09e6efdbc464f4600d90aa2314d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 74754,
"upload_time": "2024-11-27T23:13:31",
"upload_time_iso_8601": "2024-11-27T23:13:31.829945Z",
"url": "https://files.pythonhosted.org/packages/71/f9/80deec0a36ca541990704cafd8b544ef2d304c1d18f259fdd91e78d0cf7e/slvcodec-0.4.19.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-27 23:13:31",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "benreynwar",
"github_project": "slvcodec",
"travis_ci": true,
"coveralls": false,
"github_actions": false,
"lcname": "slvcodec"
}