Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Script to generate VHDL package for conversion between the record type and std_logic_vector

497 views
Skip to first unread message

Wojciech M. Zabolotny

unread,
Mar 19, 2012, 1:51:29 PM3/19/12
to
Archive-name: rec_to_pkg
Submitted-by: wz...@ise.pw.edu.pl
Last-modified: 2012-03-19 +00:00
Copyright-Notice: PUBLIC DOMAIN

Below are the PUBLIC DOMAIN sources of Python script generating
the VHDL package allowing conversion between the user defined record
type and std_logic_vector. See the README file in the archive for details.
Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.11).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `#!/bin/sh' line above, then type `sh FILE'.
#
lock_dir=_sh05909
# Made on 2012-03-19 18:32 CET by <wzab@wzab>.
# Source directory was `/tmp/rr'.
#
# Existing files will *not* be overwritten, unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 3441 -rw-r--r-- README
# 3649 -rwxr--r-- rec_to_pkg.py
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'
if test "X$1" = "X-c"
then keep_file=''
else keep_file=true
fi
echo=echo
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=
locale_dir=
set_echo=false

for dir in $PATH
do
if test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
case `$dir/gettext --version 2>&1 | sed 1q` in
*GNU*) gettext_dir=$dir
set_echo=true
break ;;
esac
fi
done

if ${set_echo}
then
set_echo=false
for dir in $PATH
do
if test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
set_echo=true
break
fi
done

if ${set_echo}
then
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
fi
IFS="$save_IFS"
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
then shar_n= shar_c='
'
else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901

if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
test ! -f ${st1} && test -f ${f}; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'

elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'

elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
test ! -f ${st3} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$2 "$8"'

else
shar_touch=:
echo
${echo} 'WARNING: not restoring timestamps. Consider getting and
installing GNU `touch'\'', distributed in GNU coreutils...'
echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir} ; then :
else ${echo} "lock directory ${lock_dir} exists"
exit 1
fi
if mkdir ${lock_dir}
then ${echo} "x - created lock directory ${lock_dir}."
else ${echo} "x - failed to create lock directory ${lock_dir}."
exit 1
fi
# ============= README ==============
if test -n "${keep_file}" && test -f 'README'
then
${echo} "x - SKIPPING README (file already exists)"
else
${echo} "x - extracting README (text)"
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
The record types in VHDL are very useful when designing more
complicated systems. However if you need to store data of record
types to memory or FIFO, it is necessary to convert such data
to the std_logic_vector type.
Similarly, when such data are read from the memory or FIFO,
it is necessary to convert to the original record type.
This problem was often discussed, eg. here:
http://stackoverflow.com/questions/3985694/serialize-vhdl-record
http://objectmix.com/vhdl/190447-converting-records-std_logic_vector.html
X
Finally I've decided to prepare a Python script which automatically
generates the appropriate VHDL package containing both the
records type declaration and functions to convert between this type and
std_logic_vector.
X
The input data is a "description file" containing:
1. The record type name in the first non-comment line:
X record name_of_my_type
2. A few (at least 1) field declarations, which may have two forms:
X name_of_the_field,type,number_of_bits
X or
X name_of_the_field,type,nr_of_left_bit,nr_of_right_bit
X
X the type may be either "signed" or "unsigned"
3. The end line, consisting of a single "end" word.
X
The description file may contain also multiple comment lines, containing
the hash "#" character in the first column.
X
For example if you run:
$ ./rec_to_pkg.py test1.rec
X
with the following test1.rec:
X
# This is a test record - packet descriptor
record pkt_desc
# Below are fields definitions
# First two pointers for linked list
# prv - previous
prv,unsigned,6
# nxt - next
nxt,unsigned,6
# Then address to the packet data
addr,unsigned,15,0
# Finally flags
flags,unsigned,9,2
end
X
You'll get the following VHDL package:
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package pkt_desc_pkg is
X
type pkt_desc is record
X prv : unsigned(5 downto 0);
X nxt : unsigned(5 downto 0);
X addr : unsigned(15 downto 0);
X flags : unsigned(9 downto 2);
end record;
X
constant pkt_desc_width : integer := 36;
X
function pkt_desc_to_stlv(
X constant din : pkt_desc)
X return std_logic_vector;
X
function stlv_to_pkt_desc(
X constant din : std_logic_vector)
X return pkt_desc;
X
end pkt_desc_pkg;
X
package body pkt_desc_pkg is
X
function pkt_desc_to_stlv(
X constant din : pkt_desc)
X return std_logic_vector is
X variable res : std_logic_vector(35 downto 0);
begin
X res(5 downto 0) := std_logic_vector(din.prv);
X res(11 downto 6) := std_logic_vector(din.nxt);
X res(27 downto 12) := std_logic_vector(din.addr);
X res(35 downto 28) := std_logic_vector(din.flags);
X return res;
end pkt_desc_to_stlv;
X
function stlv_to_pkt_desc(
X constant din : std_logic_vector)
X return pkt_desc is
X variable res : pkt_desc;
begin
X res.prv:=unsigned(din(5 downto 0));
X res.nxt:=unsigned(din(11 downto 6));
X res.addr:=unsigned(din(27 downto 12));
X res.flags:=unsigned(din(35 downto 28));
X return res;
end stlv_to_pkt_desc;
X
end pkt_desc_pkg;
X
Such automatic handling of the record type declaration and of conversion
functions should minimize nember of errors due to mistakes in mapping
of record's fields into the bits of the std_logic_vector.
X
Please note, that the information about the total number of bits in our
record type is generated as name_of_my_type_width
(pkt_desc_width in the above example).
X
I hope, that you'll find this script useful.
As it is published as PUBLIC DOMAIN, you are free to modify and use it
in any way you want.
X
Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl
X
X
SHAR_EOF
(set 20 12 03 19 18 30 23 'README'
eval "${shar_touch}") && \
chmod 0644 'README'
if test $? -ne 0
then ${echo} "restore of README failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'README': 'MD5 check failed'
) << \SHAR_EOF
b7b1566a94316efd890ed15e5d685862 README
SHAR_EOF
else
test `LC_ALL=C wc -c < 'README'` -ne 3441 && \
${echo} "restoration warning: size of 'README' is not 3441"
fi
fi
# ============= rec_to_pkg.py ==============
if test -n "${keep_file}" && test -f 'rec_to_pkg.py'
then
${echo} "x - SKIPPING rec_to_pkg.py (file already exists)"
else
${echo} "x - extracting rec_to_pkg.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'rec_to_pkg.py' &&
#!/usr/bin/python
# The script below is written by Wojciech M. Zabolotny
# wzab<at>ise.pw.edu.pl 19.03.2012
# it is published as PUBLIC DOMAIN
import sys
class field:
X last_bit = 0;
X def __init__(self,field_desc):
X fd = field_desc.split(",")
X self.fname = fd[0]
X if not fd[1] in ["signed","unsigned"]:
X raise Exception("Wrong field type")
X self.ftype = fd[1]
X if len(fd)==3:
X self.b1=int(fd[2])-1
X self.b2=0
X elif len(fd)==4:
X self.b1=int(fd[2])
X self.b2=int(fd[3])
X else:
X raise Exception("Syntax error in line: "+field_desc)
X #Assign vector bits
X self.v1=field.last_bit
X self.v2=field.last_bit+abs(self.b2-self.b1)
X field.last_bit = self.v2+1
X
if len(sys.argv) != 2:
X print """
The rec_to_pkg scripts creates VHDL package for conversion
between the VHDL records containing "signed" and "unsigned"
fields and std_logic_vectors.
It should be called as: rec_to_pkg.py description_file
where the description file should have the following syntax:
X
#Optional comment line
record record_name
#optional comment lines
#[...]
field_name,signed_or_unsigned,width
#or
field_name,signed_or_unsigned,left_bit_nr,right_bit_nr
end
X
The generated package is written to the record_name_pkg.vhd file
"""
X exit(0)
fin=open(sys.argv[1])
#Read the full description of the type
type_desc=[l.strip() for l in fin.readlines() if len(l) > 0 and l[0] != "#" ]
#The first line should contain the record name
l=type_desc[0].split(" ")
if l[0] != "record":
X raise Exception("Syntax error! The first line should have form \"record name_of_type\"")
type_name=l[1]
pkg_name=type_name+"_pkg"
#Prepare for analysis of fields
msb=0
fields=[]
end_found = False
#Find the field definitions
for l in type_desc[1:]:
X if l=="end":
X end_found=True
X break
X fields.append(field(l))
if not end_found:
X raise Exception("Syntax error: no \"end\" found")
#If we got here, probably the syntax was correct
#Lets generate the package
p="""\
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
"""
p+="package "+pkg_name+" is\n\n"
p+="type "+type_name+" is record\n"
for f in fields:
X s=" "+f.fname+" : "+f.ftype+"("
X if f.b1 > f.b2:
X s=s+str(f.b1)+" downto "+str(f.b2)+");\n"
X else:
X s=s+str(f.b1)+" to "+str(f.b2)+");\n"
X p+=s
p+="end record;\n\n"
#Write width of our type
p+="constant "+type_name+"_width : integer := "+str(field.last_bit)+";\n\n"
#Write headers of conversion functions
p+="function "+type_name+"_to_stlv(\n"
p+=" constant din : "+type_name+")\n"
p+=" return std_logic_vector;\n\n"
p+="function stlv_to_"+type_name+"(\n"
p+=" constant din : std_logic_vector)\n"
p+=" return "+type_name+";\n\n"
p+="end "+pkg_name+";\n\n"
#Now the body of the package - the conversion functions
p+="package body "+pkg_name+" is\n\n"
#
p+="function "+type_name+"_to_stlv(\n"
p+=" constant din : "+type_name+")\n"
p+=" return std_logic_vector is\n"
p+=" variable res : std_logic_vector("+str(field.last_bit-1)+" downto 0);\n"
p+="begin\n"
for f in fields:
X p+=" res("+str(f.v2)+" downto "+str(f.v1)+ ") := std_logic_vector(din."+f.fname+");\n"
p+=" return res;\n"
p+="end "+type_name+"_to_stlv;\n\n"
#
p+="function stlv_to_"+type_name+"(\n"
p+=" constant din : std_logic_vector)\n"
p+=" return "+type_name+" is\n"
p+=" variable res : "+type_name+";\n"
p+="begin\n"
for f in fields:
X p+=" res."+f.fname+":="+f.ftype+"(din("+str(f.v2)+" downto "+str(f.v1)+"));\n"
p+=" return res;\n"
p+="end stlv_to_"+type_name+";\n\n"
p+="end "+pkg_name+";\n"
X
#The output file name
fout_name=type_name+"_pkg.vhd"
fout=open(fout_name,"w")
fout.write(p)
fout.close()
X
SHAR_EOF
(set 20 12 03 19 18 26 00 'rec_to_pkg.py'
eval "${shar_touch}") && \
chmod 0744 'rec_to_pkg.py'
if test $? -ne 0
then ${echo} "restore of rec_to_pkg.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'rec_to_pkg.py': 'MD5 check failed'
) << \SHAR_EOF
bbb40377b6dc81221881b72e66e0d865 rec_to_pkg.py
SHAR_EOF
else
test `LC_ALL=C wc -c < 'rec_to_pkg.py'` -ne 3649 && \
${echo} "restoration warning: size of 'rec_to_pkg.py' is not 3649"
fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
exit 1
fi
exit 0

wzab

unread,
Mar 20, 2012, 3:45:00 AM3/20/12
to
I've added one modification to the code, which allows to use also
"std_logic_vector" as a type of the field in the record.
It is sufficient to replace the line:
if not fd[1] in ["signed","unsigned"]:
with the line:
if not fd[1] in ["signed","unsigned","std_logic_vector"]:

Then you can use record description like below (flags are now of
std_logic_vector type):

# This is a test record - packet descriptor
record pkt_desc
# Below are fields definitions
# First two pointers for linked list
# prv - previous
prv,unsigned,6
# nxt - next
nxt,unsigned,6
# Then address to the packet data
addr,unsigned,15,0
# Finally flags
flags,std_logic_vector,2,9
end

--
WZab

Wojciech M. Zabołotny

unread,
Sep 27, 2014, 11:13:23 AM9/27/14
to
Archive-name: rec_to_pkg
Submitted-by: wz...@ise.pw.edu.pl
Last-modified: 2014-09-27 +00:00
Copyright-Notice: PUBLIC DOMAIN



Below are the PUBLIC DOMAIN sources of Python script generating
the VHDL package allowing conversion between the user defined record
type and std_logic_vector. See the README file in the archive for details.
In this version I have added handling of the "std_logic" fields.

Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.14).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh08082
# Made on 2014-09-27 17:03 CEST by <xl@wzab>.
# Source directory was '/tmp'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 4128 -rwxr-xr-x rec_to_pkg.py
# ============= rec_to_pkg.py ==============
if test -n "${keep_file}" && test -f 'rec_to_pkg.py'
then
${echo} "x - SKIPPING rec_to_pkg.py (file already exists)"

else
${echo} "x - extracting rec_to_pkg.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'rec_to_pkg.py' &&
#!/usr/bin/python
# The script below is written by Wojciech M. Zabolotny
# wzab<at>ise.pw.edu.pl 27.09.2014
# it is published as PUBLIC DOMAIN
import sys
class field:
X last_bit = 0;
X def __init__(self,field_desc):
X fd = field_desc.split(",")
X self.fname = fd[0]
X #"std_logic" is handled in a special way
X if fd[1]=="std_logic":
X self.ftype = fd[1]
X self.b1=0
X self.b2=0
X elif not fd[1] in ["signed","unsigned","std_logic_vector"]:
X raise Exception("Wrong field type")
X else:
X self.ftype = fd[1]
X if len(fd)==3:
X self.b1=int(fd[2])-1
X self.b2=0
X elif len(fd)==4:
X self.b1=int(fd[2])
X self.b2=int(fd[3])
X else:
X raise Exception("Syntax error in line: "+field_desc)
X #Assign vector bits
X self.v1=field.last_bit
X self.v2=field.last_bit+abs(self.b2-self.b1)
X field.last_bit = self.v2+1
X
if len(sys.argv) != 2:
X print """
The rec_to_pkg scripts creates VHDL package for conversion
between the VHDL records containing "signed", "unsigned",
"std_logic_vector" and "std_logic" fields and std_logic_vectors.
X if f.ftype=="std_logic":
X s=" "+f.fname+" : "+f.ftype+";\n"
X else:
X if f.ftype=="std_logic":
X p+=" res("+str(f.v1)+") := din."+f.fname+";\n"
X else:
X p+=" res("+str(f.v2)+" downto "+str(f.v1)+ ") := std_logic_vector(din."+f.fname+");\n"
p+=" return res;\n"
p+="end "+type_name+"_to_stlv;\n\n"
#
p+="function stlv_to_"+type_name+"(\n"
p+=" constant din : std_logic_vector)\n"
p+=" return "+type_name+" is\n"
p+=" variable res : "+type_name+";\n"
p+="begin\n"
for f in fields:
X if f.ftype=="std_logic":
X p+=" res."+f.fname+" := din("+str(f.v1)+");\n"
X else:
X p+=" res."+f.fname+":="+f.ftype+"(din("+str(f.v2)+" downto "+str(f.v1)+"));\n"
p+=" return res;\n"
p+="end stlv_to_"+type_name+";\n\n"
p+="end "+pkg_name+";\n"
X
#The output file name
fout_name=type_name+"_pkg.vhd"
fout=open(fout_name,"w")
fout.write(p)
fout.close()
X
SHAR_EOF
(set 20 14 09 27 17 03 23 'rec_to_pkg.py'
eval "${shar_touch}") && \
chmod 0755 'rec_to_pkg.py'
if test $? -ne 0
then ${echo} "restore of rec_to_pkg.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'rec_to_pkg.py': 'MD5 check failed'
) << \SHAR_EOF
29e7c149d65dff257a7985a0a0fcecab rec_to_pkg.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'rec_to_pkg.py'` -ne 4128 && \
${echo} "restoration warning: size of 'rec_to_pkg.py' is not 4128"

Wojciech M. Zabołotny

unread,
Sep 27, 2014, 11:22:09 AM9/27/14
to
Archive-name: rec_to_pkg
Submitted-by: wz...@ise.pw.edu.pl
Last-modified: 2014-09-27 +00:00
Copyright-Notice: PUBLIC DOMAIN

Below are the PUBLIC DOMAIN sources of Python script generating
the VHDL package allowing conversion between the user defined record
type and std_logic_vector. See the README file in the archive for details.
In this version I have added handling of the "std_logic" fields.
(The previous post didn't contain the README file).

Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.14).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh08493
# Made on 2014-09-27 17:19 CEST by <wzab@wzab>.
# Source directory was '/tmp/nn'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 3524 -rw-r--r-- README
# ============= README ==============
if test -n "${keep_file}" && test -f 'README'
then
${echo} "x - SKIPPING README (file already exists)"

else
${echo} "x - extracting README (text)"
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
The record types in VHDL are very useful when designing more
complicated systems. However if you need to store data of record
types to memory or FIFO, it is necessary to convert such data
to the std_logic_vector type.
Similarly, when such data are read from the memory or FIFO,
it is necessary to convert to the original record type.
This problem was often discussed, eg. here:
http://stackoverflow.com/questions/3985694/serialize-vhdl-record
http://objectmix.com/vhdl/190447-converting-records-std_logic_vector.html
X
Finally I've decided to prepare a Python script which automatically
generates the appropriate VHDL package containing both the
records type declaration and functions to convert between this type and
std_logic_vector.
X
The input data is a "description file" containing:
1. The record type name in the first non-comment line:
X record name_of_my_type
2. A few (at least 1) field declarations, which may have three forms:
X name_of_the_field,type,number_of_bits
X or
X name_of_the_field,type,nr_of_left_bit,nr_of_right_bit
X
X where the type may be "signed","unsigned" or "std_logic_vector".
X The third possible form is:
X nam_of_the_field,std_logic
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Wojciech M. Zabolotny
wzab<at>ise.pw.edu.pl
X
X
SHAR_EOF
(set 20 14 09 27 17 19 12 'README'
eval "${shar_touch}") && \
chmod 0644 'README'
if test $? -ne 0
then ${echo} "restore of README failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'README': 'MD5 check failed'
) << \SHAR_EOF
0141d0377ab7b34e8af26eb28f2c8901 README
SHAR_EOF

else
test `LC_ALL=C wc -c < 'README'` -ne 3524 && \
${echo} "restoration warning: size of 'README' is not 3524"
fi

Wojciech M. Zabołotny

unread,
Sep 20, 2016, 7:29:36 PM9/20/16
to
Archive-name: rec_to_pkg
Submitted-by: wz...@ise.pw.edu.pl
Last-modified: 2016-09-21 +01:00
Copyright-Notice: PUBLIC DOMAIN

In this version (rec_to_pkg_nest.py) I have added the possibility
to handle nested records.

It is possible to define a record that has not only signed, unsigned, std_logic and
std_logic_vector fields, but also the fields that are records previously defined in
the same description file.

This is an example of such description file:

package test
#Subrecord 1
record subr1
p1,unsigned,4
p2,signed,6
end
# Subrecord 2
record subr2
f1,std_logic
f2,std_logic_vector,5,1
f3,unsigned,3
end
# This is a test record - packet descriptor
record pkt_desc
# Below are fields definitions
# First two pointers for linked list
# prv - previous
prv,unsigned,6
# nxt - next
nxt,unsigned,6
# Subrecord 2 in the middle
srec2,rec,subr2
# Then address to the packet data
addr,unsigned,15,0
# Finally flags
flags,std_logic_vector,2,9
# And subrecord 1
srec1,rec,subr1
end

The code below is PUBLIC DOMAIN or CC0
You use it on your own risk!

Wojtek

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.15.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh07537
# Made on 2016-09-21 01:21 CEST by <wzab@wzab>.
# Source directory was '/tmp/rec'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 5648 -rwxr-xr-x rec_to_pkg_nest.py
# ============= rec_to_pkg_nest.py ==============
if test -n "${keep_file}" && test -f 'rec_to_pkg_nest.py'
then
${echo} "x - SKIPPING rec_to_pkg_nest.py (file already exists)"

else
${echo} "x - extracting rec_to_pkg_nest.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'rec_to_pkg_nest.py' &&
#!/usr/bin/python
# The script below is written by Wojciech M. Zabolotny
# wzab<at>ise.pw.edu.pl 21.09.2016
# it is published as PUBLIC DOMAIN
import sys
rec_types=[]
rec_dict={}
class record:
X def __init__(self,name):
X self.name = name
X self.fields = []
X self.nof_bits = 0
X def add_field(self,field_desc):
X self.fields.append(field(self,field_desc))
X
class field:
X def __init__(self,par_rec,field_desc):
X fd = field_desc.split(",")
X self.fname = fd[0]
X #"rec" is handled in a special way
X if fd[1]=="rec":
X self.ftype = fd[1]
X self.rec_name = fd[2]
X self.b1=rec_dict[fd[2]].nof_bits-1
X self.b2=0
X #"std_logic" is handled in a special way
X elif fd[1]=="std_logic":
X self.ftype = fd[1]
X self.b1=0
X self.b2=0
X elif not fd[1] in ["signed","unsigned","std_logic_vector"]:
X raise Exception("Wrong field type")
X else:
X self.ftype = fd[1]
X if len(fd)==3:
X self.b1=int(fd[2])-1
X self.b2=0
X elif len(fd)==4:
X self.b1=int(fd[2])
X self.b2=int(fd[3])
X else:
X raise Exception("Syntax error in line: "+field_desc)
X #Assign vector bits
X self.v1=par_rec.nof_bits
X self.v2=par_rec.nof_bits+abs(self.b2-self.b1)
X par_rec.nof_bits = self.v2+1
X
if len(sys.argv) != 2:
X print """
The rec_to_pkg scripts creates VHDL package for conversion
between the VHDL records containing "signed", "unsigned",
"std_logic_vector" and "std_logic" fields and std_logic_vectors.
Additionally, the record may contain also another record,
defined previously in the same decription file.
It should be called as: rec_to_pkg_nest.py description_file
where the description file should have the following syntax:
X
#Optional comment line
package package_name
#Then one or more record definitions
record record_name
#optional comment lines
#[...]
field_name,signed_or_unsigned,width
#or
field_name,signed_or_unsigned,left_bit_nr,right_bit_nr
#or
field_name,rec,previously_defined_record
end
X
The generated package is written to the package_name.vhd file
"""
X exit(0)
fin=open(sys.argv[1])
#Read the full description of the type
type_desc=[l.strip() for l in fin.readlines() if len(l) > 0 and l[0] != "#" ]
#The first line should contain the package name
l=type_desc.pop(0).split(" ")
if l[0] != "package":
X raise Exception("Syntax error! The first line should have form \"package name_of_package\"")
pkg_name=l[1]
#Now we define the record types
while len(type_desc)>0:
X td=type_desc.pop(0)
X print td
X #The first line in the section should contain the record name
X l=td.split(" ")
X if l[0] != "record":
X raise Exception("Line: "+td+"\nSyntax error! The first line in the section should have form \"record name_of_type\"")
X type_name=l[1]
X cur_rec=record(type_name)
X rec_dict[type_name]=cur_rec
X rec_types.append(cur_rec)
X #Prepare for analysis of fields
X end_found = False
X #Find the field definitions
X while len(type_desc)>0:
X l=type_desc.pop(0)
X print l
X if l=="end":
X end_found=True
X break
X cur_rec.fields.append(field(cur_rec,l))
X if not end_found:
X raise Exception("Syntax error: no \"end\" found")
#If we got here, probably the syntax was correct
#Lets generate the package
p="""\
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
"""
p+="package "+pkg_name+" is\n\n"
# Now write definition of record types
for r in rec_types:
X p+="type "+r.name+" is record\n"
X for f in r.fields:
X if f.ftype=="rec":
X s=" "+f.fname+" : "+f.rec_name+";\n"
X elif f.ftype=="std_logic":
X s=" "+f.fname+" : "+f.ftype+";\n"
X else:
X s=" "+f.fname+" : "+f.ftype+"("
X if f.b1 > f.b2:
X s=s+str(f.b1)+" downto "+str(f.b2)+");\n"
X else:
X s=s+str(f.b1)+" to "+str(f.b2)+");\n"
X p+=s
X p+="end record;\n\n"
X #Write width of our type
X p+="constant "+r.name+"_width : integer := "+str(r.nof_bits)+";\n\n"
X #Write headers of conversion functions
X p+="function "+r.name+"_to_stlv(\n"
X p+=" constant din : "+r.name+")\n"
X p+=" return std_logic_vector;\n\n"
X p+="function stlv_to_"+r.name+"(\n"
X p+=" constant din : std_logic_vector)\n"
X p+=" return "+r.name+";\n\n"
p+="end "+pkg_name+";\n\n"
#Now the body of the package - the conversion functions
p+="package body "+pkg_name+" is\n\n"
# Iterate over the records
for r in rec_types:
X p+="function "+r.name+"_to_stlv(\n"
X p+=" constant din : "+r.name+")\n"
X p+=" return std_logic_vector is\n"
X p+=" variable res : std_logic_vector("+str(r.nof_bits-1)+" downto 0);\n"
X p+="begin\n"
X for f in r.fields:
X if f.ftype=="rec":
X p+=" res("+str(f.v2)+" downto "+str(f.v1)+") := "+f.rec_name+"_to_stlv(din."+f.fname+");\n"
X elif f.ftype=="std_logic":
X p+=" res("+str(f.v1)+") := din."+f.fname+";\n"
X else:
X p+=" res("+str(f.v2)+" downto "+str(f.v1)+ ") := std_logic_vector(din."+f.fname+");\n"
X p+=" return res;\n"
X p+="end "+r.name+"_to_stlv;\n\n"
X #
X p+="function stlv_to_"+r.name+"(\n"
X p+=" constant din : std_logic_vector)\n"
X p+=" return "+r.name+" is\n"
X p+=" variable res : "+r.name+";\n"
X p+="begin\n"
X for f in r.fields:
X if f.ftype=="rec":
X p+=" res."+f.fname+":= stlv_to_"+f.rec_name+"(din("+str(f.v2)+" downto "+str(f.v1)+"));\n"
X elif f.ftype=="std_logic":
X p+=" res."+f.fname+" := din("+str(f.v1)+");\n"
X else:
X p+=" res."+f.fname+":="+f.ftype+"(din("+str(f.v2)+" downto "+str(f.v1)+"));\n"
X p+=" return res;\n"
X p+="end stlv_to_"+r.name+";\n\n"
p+="end "+pkg_name+";\n"
X
#The output file name
fout_name=pkg_name+".vhd"
fout=open(fout_name,"w")
fout.write(p)
fout.close()
X
SHAR_EOF
(set 20 16 09 21 01 20 33 'rec_to_pkg_nest.py'
eval "${shar_touch}") && \
chmod 0755 'rec_to_pkg_nest.py'
if test $? -ne 0
then ${echo} "restore of rec_to_pkg_nest.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'rec_to_pkg_nest.py': 'MD5 check failed'
) << \SHAR_EOF
02fe21f4295a36aac1d86754ba9d4163 rec_to_pkg_nest.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'rec_to_pkg_nest.py'` -ne 5648 && \
${echo} "restoration warning: size of 'rec_to_pkg_nest.py' is not 5648"

Wojciech M. Zabołotny

unread,
Sep 21, 2016, 7:19:54 AM9/21/16
to
Archive-name: rec_to_pkg_nest-1.0-beta
Original-author: Wojciech M. Zabolotny ( wz...@ise.pw.edu.pl )
Submitted-by: wz...@ise.pw.edu.pl
Last-modified: 2014-09-27 +00:00
Copyright-Notice: PUBLIC DOMAIN or Creative Commons CC0

This is the new, corrected version of the previous rec_to_pkg.py tool.
Basing on the record description file, it generates the VHDL package,
that defines the record type and provides the conversion functions
for conversion of the records into std_logic_vector of tha appropriate
length, and from std_logic vector to the record.

This rec_to_pkg_nest.py may handle the nested records. Additionally
it is possible to specify comments, that should be written at the begining
of the generated VHDL package (they should start with double hash '##').

The sources contain the example record definition file, and a testbench
showing the operation.
If you have ghdl and gtkwave installed, run the run_test.sh to see the
demonstration.

Please note that the code is published as PUBLIC DOMAIN or under Creative
Commons CC0 license.
However, if you create any derived work, please provide information
about the original author.

This is a free code. I do not provide any warranty. You use it on your
own risk.

With best regards,
Wojtek

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.15.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh05086
# Made on 2016-09-21 13:06 CEST by <wzab@wzab>.
# Source directory was '/tmp/rec'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 6553 -rwxr-xr-x rec_to_pkg_nest.py
# 171 -rwxr--r-- run_test.sh
# 559 -rw-r--r-- test.rec
# 3064 -rw-r--r-- test.sav
# 2035 -rw-r--r-- test_tb.vhd
# ============= rec_to_pkg_nest.py ==============
if test -n "${keep_file}" && test -f 'rec_to_pkg_nest.py'
then
${echo} "x - SKIPPING rec_to_pkg_nest.py (file already exists)"

else
${echo} "x - extracting rec_to_pkg_nest.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'rec_to_pkg_nest.py' &&
#!/usr/bin/python
# The script below is written by Wojciech M. Zabolotny
# wzab<at>ise.pw.edu.pl 21.09.2016
# it is published as PUBLIC DOMAIN
# However, if you create any derived work, it would be nice
# if you provide information about the original author.
import sys
rec_types=[]
rec_dict={}
class record:
X def __init__(self,name):
X self.name = name
X self.fields = []
X self.nof_bits = 0
X def add_field(self,field_desc):
X self.fields.append(field(self,field_desc))
X
class field:
X def __init__(self,par_rec,field_desc):
X fd = field_desc.split(",")
X self.fname = fd[0]
X #"rec" is handled in a special way
X if fd[1]=="rec":
X self.ftype = fd[1]
X self.rec_name = fd[2]
X self.b1=rec_dict[fd[2]].nof_bits-1
X self.b2=0
X #"std_logic" is handled in a special way
X elif fd[1]=="std_logic":
X self.ftype = fd[1]
X self.b1=0
X self.b2=0
X elif not fd[1] in ["signed","unsigned","std_logic_vector"]:
X raise Exception("Wrong field type")
X else:
X self.ftype = fd[1]
X if len(fd)==3:
X self.b1=int(fd[2])-1
X self.b2=0
X elif len(fd)==4:
X self.b1=int(fd[2])
X self.b2=int(fd[3])
X else:
X raise Exception("Syntax error in line: "+field_desc)
X #Assign vector bits
X self.v1=par_rec.nof_bits
X self.v2=par_rec.nof_bits+abs(self.b2-self.b1)
X par_rec.nof_bits = self.v2+1
X
if len(sys.argv) != 2:
X print """
The rec_to_pkg scripts creates VHDL package for conversion
between the VHDL records containing "signed", "unsigned",
"std_logic_vector" and "std_logic" fields and std_logic_vectors.
Additionally, the record may contain also another record,
defined previously in the same decription file.
It should be called as: rec_to_pkg_nest.py description_file
where the description file should have the following syntax:
X
#Optional comment line
package package_name
## Comments starting with double hash are accumulated and
## copied at the begining of the generated vhdl file
#Then one or more record definitions
record record_name
#optional comment lines
#[...]
field_name,signed_or_unsigned,width
#or
field_name,signed_or_unsigned,left_bit_nr,right_bit_nr
#or
field_name,rec,previously_defined_record
end
X
The generated package is written to the package_name.vhd file
"""
X exit(0)
fin=open(sys.argv[1])
#Read the full description of the type
type_desc=[]
comments=[]
for l in fin.readlines():
X l=l.strip()
X if len(l) > 0:
X if l[0] != "#":
X type_desc.append(l)
X elif l[0:2] == "##":
X comments.append(l[2:])
#The first line should contain the package name
l=type_desc.pop(0).split(" ")
if l[0] != "package":
X raise Exception("Syntax error! The first line should have form \"package name_of_package\"")
pkg_name=l[1]
#Now we define the record types
while len(type_desc)>0:
X td=type_desc.pop(0)
X print td
X #The first line in the section should contain the record name
X l=td.split(" ")
X if l[0] != "record":
X raise Exception("Line: "+td+"\nSyntax error! The first line in the section should have form \"record name_of_type\"")
X type_name=l[1]
X cur_rec=record(type_name)
X rec_dict[type_name]=cur_rec
X rec_types.append(cur_rec)
X #Prepare for analysis of fields
X end_found = False
X #Find the field definitions
X while len(type_desc)>0:
X l=type_desc.pop(0)
X print l
X if l=="end":
X end_found=True
X break
X cur_rec.fields.append(field(cur_rec,l))
X if not end_found:
X raise Exception("Syntax error: no \"end\" found")
#If we got here, probably the syntax was correct
#Lets generate the package
p="""\
-------------------------------------------------------------------------------
-- This file has been autometically generated by the rec_to_pkg_nest.py tool
-- from the """+sys.argv[1]+""" record description file.
-- Don't edit it manually. To introduce any changes, edit the """+sys.argv[1]+""" file
-- and rerun the rec_to_pkg_nest.py
-------------------------------------------------------------------------------
"""
for l in comments:
X p+="--"+l+"\n"
p+="""\
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
"""
p+="package "+pkg_name+" is\n\n"
# Now write definition of record types
for r in rec_types:
X p+="type "+r.name+" is record\n"
X for f in r.fields:
X if f.ftype=="rec":
X s=" "+f.fname+" : "+f.rec_name+";\n"
X elif f.ftype=="std_logic":
X s=" "+f.fname+" : "+f.ftype+";\n"
X else:
X s=" "+f.fname+" : "+f.ftype+"("
X if f.b1 > f.b2:
X s=s+str(f.b1)+" downto "+str(f.b2)+");\n"
X else:
X s=s+str(f.b1)+" to "+str(f.b2)+");\n"
X p+=s
X p+="end record;\n\n"
X #Write width of our type
X p+="constant "+r.name+"_width : integer := "+str(r.nof_bits)+";\n\n"
X #Write headers of conversion functions
X p+="function "+r.name+"_to_stlv(\n"
X p+=" constant din : "+r.name+")\n"
X p+=" return std_logic_vector;\n\n"
X p+="function stlv_to_"+r.name+"(\n"
X p+=" constant din : std_logic_vector)\n"
X p+=" return "+r.name+";\n\n"
p+="end "+pkg_name+";\n\n"
#Now the body of the package - the conversion functions
p+="package body "+pkg_name+" is\n\n"
# Iterate over the records
for r in rec_types:
X p+="function "+r.name+"_to_stlv(\n"
X p+=" constant din : "+r.name+")\n"
X p+=" return std_logic_vector is\n"
X p+=" variable res : std_logic_vector("+str(r.nof_bits-1)+" downto 0);\n"
X p+="begin\n"
X for f in r.fields:
X if f.ftype=="rec":
X p+=" res("+str(f.v2)+" downto "+str(f.v1)+") := "+f.rec_name+"_to_stlv(din."+f.fname+");\n"
X elif f.ftype=="std_logic":
X p+=" res("+str(f.v1)+") := din."+f.fname+";\n"
X else:
X p+=" res("+str(f.v2)+" downto "+str(f.v1)+ ") := std_logic_vector(din."+f.fname+");\n"
X p+=" return res;\n"
X p+="end "+r.name+"_to_stlv;\n\n"
X #
X p+="function stlv_to_"+r.name+"(\n"
X p+=" constant din : std_logic_vector)\n"
X p+=" return "+r.name+" is\n"
X p+=" variable sdin : std_logic_vector("+str(r.nof_bits-1)+" downto 0);\n"
X p+=" variable res : "+r.name+";\n"
X p+="begin\n"
X p+=" sdin := din;\n"
X for f in r.fields:
X if f.ftype=="rec":
X p+=" res."+f.fname+":= stlv_to_"+f.rec_name+"(sdin("+str(f.v2)+" downto "+str(f.v1)+"));\n"
X elif f.ftype=="std_logic":
X p+=" res."+f.fname+" := sdin("+str(f.v1)+");\n"
X else:
X p+=" res."+f.fname+":="+f.ftype+"(sdin("+str(f.v2)+" downto "+str(f.v1)+"));\n"
X p+=" return res;\n"
X p+="end stlv_to_"+r.name+";\n\n"
p+="end "+pkg_name+";\n"
X
#The output file name
fout_name=pkg_name+".vhd"
fout=open(fout_name,"w")
fout.write(p)
fout.close()
X
SHAR_EOF
(set 20 16 09 21 13 06 29 'rec_to_pkg_nest.py'
eval "${shar_touch}") && \
chmod 0755 'rec_to_pkg_nest.py'
if test $? -ne 0
then ${echo} "restore of rec_to_pkg_nest.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'rec_to_pkg_nest.py': 'MD5 check failed'
) << \SHAR_EOF
e46df3ce19b0c066a8f2ae89d36637a6 rec_to_pkg_nest.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'rec_to_pkg_nest.py'` -ne 6553 && \
${echo} "restoration warning: size of 'rec_to_pkg_nest.py' is not 6553"
fi
fi
# ============= run_test.sh ==============
if test -n "${keep_file}" && test -f 'run_test.sh'
then
${echo} "x - SKIPPING run_test.sh (file already exists)"

else
${echo} "x - extracting run_test.sh (text)"
sed 's/^X//' << 'SHAR_EOF' > 'run_test.sh' &&
#!/bin/bash
set -e
X./rec_to_pkg_nest.py test.rec
ghdl -a test_pkg.vhd test_tb.vhd
ghdl -e test_tb
X./test_tb --stop-time=100ns --wave=test.ghw
gtkwave test.ghw test.sav
SHAR_EOF
(set 20 16 09 21 12 48 06 'run_test.sh'
eval "${shar_touch}") && \
chmod 0744 'run_test.sh'
if test $? -ne 0
then ${echo} "restore of run_test.sh failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'run_test.sh': 'MD5 check failed'
) << \SHAR_EOF
a38869b09390e26f194e290705cc2459 run_test.sh
SHAR_EOF

else
test `LC_ALL=C wc -c < 'run_test.sh'` -ne 171 && \
${echo} "restoration warning: size of 'run_test.sh' is not 171"
fi
fi
# ============= test.rec ==============
if test -n "${keep_file}" && test -f 'test.rec'
then
${echo} "x - SKIPPING test.rec (file already exists)"

else
${echo} "x - extracting test.rec (text)"
sed 's/^X//' << 'SHAR_EOF' > 'test.rec' &&
## The test_pkg is created to test the rec_to_pkg_new.py tool
## It is published as PUBLIC DOMAIN or Creative Commons CC0
##
package test_pkg
# First we define nested records
# Subrecord 1
record sub_rec1
X p1,unsigned,4
X stb,std_logic
end
X
# Subrecord 2
record sub_rec2
X f1,std_logic
X f2,std_logic_vector,1,4
X f3,unsigned,3
end
X
# Now we define our main record
record test_rec
X # nmbr - number of the record
X nmbr,unsigned,6
X # nested subrecord 2
X srec2,rec,sub_rec2
X # flags
X flags,std_logic_vector,5,1
X # nested subrecord 1
X srec1,rec,sub_rec1
end
SHAR_EOF
(set 20 16 09 21 12 56 56 'test.rec'
eval "${shar_touch}") && \
chmod 0644 'test.rec'
if test $? -ne 0
then ${echo} "restore of test.rec failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test.rec': 'MD5 check failed'
) << \SHAR_EOF
29b55d168dd857fd536dfc198eb76f8d test.rec
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test.rec'` -ne 559 && \
${echo} "restoration warning: size of 'test.rec' is not 559"
fi
fi
# ============= test.sav ==============
if test -n "${keep_file}" && test -f 'test.sav'
then
${echo} "x - SKIPPING test.sav (file already exists)"

else
${echo} "x - extracting test.sav (text)"
sed 's/^X//' << 'SHAR_EOF' > 'test.sav' &&
[*]
[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
[*] Wed Sep 21 08:27:53 2016
[*]
[dumpfile] "/home/wzab/biezace/VHDL/rec_to_pkg_new/check/test.ghw"
[dumpfile_mtime] "Wed Sep 21 08:27:17 2016"
[dumpfile_size] 930
[savefile] "/home/wzab/biezace/VHDL/rec_to_pkg_new/check/test.sav"
[timestart] 0
[size] 1000 600
[pos] 248 42
*-23.924660 20000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top.
[treeopen] top.test_tb.
[treeopen] top.test_tb.din.
[treeopen] top.test_tb.din.srec1.
[treeopen] top.test_tb.din.srec2.
[treeopen] top.test_tb.dout.
[treeopen] top.test_tb.dout.srec1.
[treeopen] top.test_tb.dout.srec2.
[sst_width] 210
[signals_width] 142
[sst_expanded] 1
[sst_vpaned_height] 154
@200
-din
@28
top.test_tb.din.srec1.stb
@22
#{top.test_tb.din.srec1.p1[3:0]} top.test_tb.din.srec1.p1[3] top.test_tb.din.srec1.p1[2] top.test_tb.din.srec1.p1[1] top.test_tb.din.srec1.p1[0]
#{top.test_tb.din.flags[5:1]} top.test_tb.din.flags[5] top.test_tb.din.flags[4] top.test_tb.din.flags[3] top.test_tb.din.flags[2] top.test_tb.din.flags[1]
@28
top.test_tb.din.srec2.f1
#{top.test_tb.din.srec2.f3[2:0]} top.test_tb.din.srec2.f3[2] top.test_tb.din.srec2.f3[1] top.test_tb.din.srec2.f3[0]
@22
#{top.test_tb.din.srec2.f2[4:1]} top.test_tb.din.srec2.f2[4] top.test_tb.din.srec2.f2[3] top.test_tb.din.srec2.f2[2] top.test_tb.din.srec2.f2[1]
#{top.test_tb.din.nmbr[5:0]} top.test_tb.din.nmbr[5] top.test_tb.din.nmbr[4] top.test_tb.din.nmbr[3] top.test_tb.din.nmbr[2] top.test_tb.din.nmbr[1] top.test_tb.din.nmbr[0]
@200
-dout
@28
top.test_tb.dout.srec1.stb
@22
#{top.test_tb.dout.srec1.p1[3:0]} top.test_tb.dout.srec1.p1[3] top.test_tb.dout.srec1.p1[2] top.test_tb.dout.srec1.p1[1] top.test_tb.dout.srec1.p1[0]
#{top.test_tb.dout.flags[5:1]} top.test_tb.dout.flags[5] top.test_tb.dout.flags[4] top.test_tb.dout.flags[3] top.test_tb.dout.flags[2] top.test_tb.dout.flags[1]
@28
top.test_tb.dout.srec2.f1
#{top.test_tb.dout.srec2.f3[2:0]} top.test_tb.dout.srec2.f3[2] top.test_tb.dout.srec2.f3[1] top.test_tb.dout.srec2.f3[0]
@22
#{top.test_tb.dout.srec2.f2[4:1]} top.test_tb.dout.srec2.f2[4] top.test_tb.dout.srec2.f2[3] top.test_tb.dout.srec2.f2[2] top.test_tb.dout.srec2.f2[1]
#{top.test_tb.dout.nmbr[5:0]} top.test_tb.dout.nmbr[5] top.test_tb.dout.nmbr[4] top.test_tb.dout.nmbr[3] top.test_tb.dout.nmbr[2] top.test_tb.dout.nmbr[1] top.test_tb.dout.nmbr[0]
@200
-test_vec
@22
#{top.test_tb.test_vec[23:0]} top.test_tb.test_vec[23] top.test_tb.test_vec[22] top.test_tb.test_vec[21] top.test_tb.test_vec[20] top.test_tb.test_vec[19] top.test_tb.test_vec[18] top.test_tb.test_vec[17] top.test_tb.test_vec[16] top.test_tb.test_vec[15] top.test_tb.test_vec[14] top.test_tb.test_vec[13] top.test_tb.test_vec[12] top.test_tb.test_vec[11] top.test_tb.test_vec[10] top.test_tb.test_vec[9] top.test_tb.test_vec[8] top.test_tb.test_vec[7] top.test_tb.test_vec[6] top.test_tb.test_vec[5] top.test_tb.test_vec[4] top.test_tb.test_vec[3] top.test_tb.test_vec[2] top.test_tb.test_vec[1] top.test_tb.test_vec[0]
[pattern_trace] 1
[pattern_trace] 0
SHAR_EOF
(set 20 16 09 21 12 48 06 'test.sav'
eval "${shar_touch}") && \
chmod 0644 'test.sav'
if test $? -ne 0
then ${echo} "restore of test.sav failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test.sav': 'MD5 check failed'
) << \SHAR_EOF
cf814fd41e6a8ffaddf696fda6fafdbe test.sav
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test.sav'` -ne 3064 && \
${echo} "restoration warning: size of 'test.sav' is not 3064"
fi
fi
# ============= test_tb.vhd ==============
if test -n "${keep_file}" && test -f 'test_tb.vhd'
then
${echo} "x - SKIPPING test_tb.vhd (file already exists)"

else
${echo} "x - extracting test_tb.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'test_tb.vhd' &&
-------------------------------------------------------------------------------
-- Title : Testbench for records & record converters generator
-- Project :
-------------------------------------------------------------------------------
-- File : test_tb.vhd
-- Author : Wojciech Zabolotny
-- Company :
-- Created : 2016-09-21
-- Last update: 2016-09-21
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
-- License : PUBLIC DOMAIN or Creative Commons CC0
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2016-09-21 1.0 wzab Created
-------------------------------------------------------------------------------
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
X
library work;
use work.test_pkg.all;
-------------------------------------------------------------------------------
X
entity test_tb is
X
end test_tb;
X
-------------------------------------------------------------------------------
X
architecture test1 of test_tb is
X
X -- signals
X signal din, dout : test_rec;
X signal test_vec : std_logic_vector(test_rec_width-1 downto 0);
X
begin -- test1
X test_vec <= test_rec_to_stlv(din);
X dout <= stlv_to_test_rec(test_vec);
X -- waveform generation
X WaveGen_Proc : process
X begin
X din.nmbr <= to_unsigned(1,6);
X din.flags <= "11010";
X din.srec2.f1 <= '1';
X din.srec2.f2 <="1000";
X din.srec2.f3 <=to_unsigned(4,3);
X din.srec1.p1 <="0101";
X din.srec1.stb <= '1';
X wait for 10 ns;
X din.srec1.stb <= '0';
X wait for 10 ns;
X din.srec2.f2 <= "0111";
X wait for 10 ns;
X din.flags <= "00111";
X din.nmbr <= to_unsigned(2,6);
X wait for 10 ns;
X din.srec1.p1 <= "1100";
X wait for 10 ns;
X din.srec1.stb <= '1';
X wait;
X end process WaveGen_Proc;
X
X
end test1;
X
SHAR_EOF
(set 20 16 09 21 12 48 06 'test_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'test_tb.vhd'
if test $? -ne 0
then ${echo} "restore of test_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
8f852816fa850d407976299ad50b91e4 test_tb.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test_tb.vhd'` -ne 2035 && \
${echo} "restoration warning: size of 'test_tb.vhd' is not 2035"

Wojciech Zabołotny

unread,
Sep 22, 2016, 2:59:12 PM9/22/16
to
Archive-name: rec_to_pkg_nest-1.1-beta
Original-author: Wojciech M. Zabolotny ( wz...@ise.pw.edu.pl )
Submitted-by: wz...@ise.pw.edu.pl
Last-modified: 2014-09-27 +00:00
Copyright-Notice: PUBLIC DOMAIN or Creative Commons CC0

This is the new, corrected version of the previous rec_to_pkg.py tool.
Basing on the record description file, it generates the VHDL package,
that defines the record type and provides the conversion functions
for conversion of the records into std_logic_vector of tha appropriate
length, and from std_logic vector to the record.

This rec_to_pkg_nest.py may handle the nested records and the arrays of record types.
Additionally it is possible to specify comments, that should be written at the begining
of the generated VHDL package (they should start with double hash '##').

The sources contain the example record definition file, and a testbench
showing the operation.
If you have ghdl and gtkwave installed, run the run_test.sh to see the
demonstration.

Please note that the code is published as PUBLIC DOMAIN or under Creative
Commons CC0 license.
However, if you create any derived work, please provide information
about the original author.

This is a free code. I do not provide any warranty. You use it on your
own risk.

With best regards,
Wojtek

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.15.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh05928
# Made on 2016-09-22 20:57 CEST by <wzab@wzab>.
# Source directory was '/home/wzab/biezace/VHDL/rec_to_pkg_new/publ'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 9247 -rwxr-xr-x rec_to_pkg_nest.py
# 171 -rwxr--r-- run_test.sh
# 591 -rw-r--r-- test.rec
# 8619 -rw-r--r-- test.sav
# 2796 -rw-r--r-- test_tb.vhd
# 1837 -rw-r--r-- test.vhd
# This is the version 1.1
#
import sys
rec_types=[]
arrays=[]
Additionally, the description file may contain the line
defining the array of records:
array array_type_name record_type_name
X
This generates functions converting such arrays to and from stlv
It is assumed, that the array is indexed from 0 to (nitems-1)
The nitems must be delivered as the second argument to the conversion
functions. See the included example for details.
X #We accept the line defining the arrays of records
X if l[0] == "array":
X arrays.append((l[1],l[2]))
X continue
X if l[0] != "record":
X raise Exception("Line: "+td+"\nSyntax error! The first line in the section should have form \"record name_of_type\"")
X type_name=l[1]
X cur_rec=record(type_name)
X rec_dict[type_name]=cur_rec
X rec_types.append(cur_rec)
X #Prepare for analysis of fields
X end_found = False
X #Find the field definitions
X while len(type_desc)>0:
X l=type_desc.pop(0)
X print l
X if l=="end":
X end_found=True
X break
X cur_rec.fields.append(field(cur_rec,l))
X if not end_found:
X raise Exception("Syntax error: no \"end\" found")
#If we got here, probably the syntax was correct
#Lets generate the package
p="""\
-------------------------------------------------------------------------------
-- This file has been automatically generated by the rec_to_pkg_nest.py tool
-- from the """+sys.argv[1]+""" record description file.
-- Don't edit it manually. To introduce any changes, edit the """+sys.argv[1]+""" file
-- and rerun the rec_to_pkg_nest.py
-------------------------------------------------------------------------------
"""
for l in comments:
X p+="--"+l+"\n"
p+="""\
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
"""
p+="package "+pkg_name+" is\n\n"
# Now write definitions of record types
for r in rec_types:
X p+="------------------------------------------------------\n"
X p+="-- type "+r.name+" declarations\n"
X p+="------------------------------------------------------\n"
X p+="type "+r.name+" is record\n"
X for f in r.fields:
X if f.ftype=="rec":
X s=" "+f.fname+" : "+f.rec_name+";\n"
X elif f.ftype=="std_logic":
X s=" "+f.fname+" : "+f.ftype+";\n"
X else:
X s=" "+f.fname+" : "+f.ftype+"("
X if f.b1 > f.b2:
X s=s+str(f.b1)+" downto "+str(f.b2)+");\n"
X else:
X s=s+str(f.b1)+" to "+str(f.b2)+");\n"
X p+=s
X p+="end record;\n\n"
X #Write width of our type
X p+="constant "+r.name+"_width : integer := "+str(r.nof_bits)+";\n\n"
X #Write headers of conversion functions
X p+="function "+r.name+"_to_stlv(\n"
X p+=" constant din : "+r.name+")\n"
X p+=" return std_logic_vector;\n\n"
X p+="function stlv_to_"+r.name+"(\n"
X p+=" constant din : std_logic_vector)\n"
X p+=" return "+r.name+";\n\n"
# Now we write definitions of array types
for a in arrays:
X p+="------------------------------------------------------\n"
X p+="-- array type "+a[0]+" declarations\n"
X p+="------------------------------------------------------\n"
X # Array type definition
X p+="type "+a[0]+" is array(natural range <>) of "+a[1]+";\n\n"
X # array to stlv conversion
X p+="function "+a[0]+"_to_stlv(\n"
X p+=" constant din : "+a[0]+";\n"
X p+=" constant nitems : integer)\n"
X p+=" return std_logic_vector;\n\n"
X p+="function stlv_to_"+a[0]+"(\n"
X p+=" constant din : std_logic_vector;\n"
X p+=" constant nitems : integer)\n"
X p+=" return "+a[0]+";\n\n"
p+="end "+pkg_name+";\n\n"
#Now the body of the package - the conversion functions
p+="package body "+pkg_name+" is\n\n"
# Iterate over the records
for r in rec_types:
X p+="------------------------------------------------------\n"
X p+="-- type "+r.name+" conversion implementations\n"
X p+="------------------------------------------------------\n"
# Iterate over the array types
for a in arrays:
X p+="------------------------------------------------------\n"
X p+="-- array type "+a[0]+" conversion implementations\n"
X p+="------------------------------------------------------\n"
X # array to stlv conversion
X p+="function "+a[0]+"_to_stlv(\n"
X p+=" constant din : "+a[0]+";\n"
X p+=" constant nitems : integer)\n"
X p+=" return std_logic_vector is\n"
X p+=" variable res : std_logic_vector("+a[1]+"_width * nitems - 1 downto 0);\n"
X p+="begin\n"
X p+=" for i in 0 to nitems-1 loop\n"
X p+=" res((i+1)*"+a[1]+"_width-1 downto i*"+a[1]+"_width) := "+a[1]+"_to_stlv(din(i));\n"
X p+=" end loop;\n"
X p+=" return res;\n"
X p+="end function "+a[0]+"_to_stlv;\n\n"
X
X p+="function stlv_to_"+a[0]+"(\n"
X p+=" constant din : std_logic_vector;\n"
X p+=" constant nitems : integer)\n"
X p+=" return "+a[0]+" is\n"
X p+=" variable res : "+a[0]+"(0 to nitems-1)\n;"
X p+="begin\n"
X p+=" for i in 0 to nitems-1 loop\n"
X p+=" res(i) := stlv_to_"+a[1]+"(din((i+1)*"+a[1]+"_width-1 downto i*"+a[1]+"_width));\n"
X p+=" end loop;\n"
X p+=" return res;\n"
X p+="end function stlv_to_"+a[0]+";\n\n"
p+="end "+pkg_name+";\n"
X
#The output file name
fout_name=pkg_name+".vhd"
fout=open(fout_name,"w")
fout.write(p)
fout.close()
X
SHAR_EOF
(set 20 16 09 22 20 56 54 'rec_to_pkg_nest.py'
eval "${shar_touch}") && \
chmod 0755 'rec_to_pkg_nest.py'
if test $? -ne 0
then ${echo} "restore of rec_to_pkg_nest.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'rec_to_pkg_nest.py': 'MD5 check failed'
) << \SHAR_EOF
e92394794e23e536521b0b47d8ddc13c rec_to_pkg_nest.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'rec_to_pkg_nest.py'` -ne 9247 && \
${echo} "restoration warning: size of 'rec_to_pkg_nest.py' is not 9247"
X
array test_rec_array test_rec
X
SHAR_EOF
(set 20 16 09 22 19 39 49 'test.rec'
eval "${shar_touch}") && \
chmod 0644 'test.rec'
if test $? -ne 0
then ${echo} "restore of test.rec failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test.rec': 'MD5 check failed'
) << \SHAR_EOF
16323d821a36bff2b006c2c4a0e8ec45 test.rec
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test.rec'` -ne 591 && \
${echo} "restoration warning: size of 'test.rec' is not 591"
fi
fi
# ============= test.sav ==============
if test -n "${keep_file}" && test -f 'test.sav'
then
${echo} "x - SKIPPING test.sav (file already exists)"

else
${echo} "x - extracting test.sav (text)"
sed 's/^X//' << 'SHAR_EOF' > 'test.sav' &&
[*]
[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
[*] Thu Sep 22 18:46:39 2016
[*]
[dumpfile] "/home/wzab/biezace/VHDL/rec_to_pkg_new/publ/test.ghw"
[dumpfile_mtime] "Thu Sep 22 18:45:09 2016"
[dumpfile_size] 1656
[savefile] "/home/wzab/biezace/VHDL/rec_to_pkg_new/publ/test.sav"
[timestart] 0
[size] 1280 970
[pos] 0 0
*-23.924660 20000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top.
[treeopen] top.test_tb.
[treeopen] top.test_tb.din.
[treeopen] top.test_tb.din.[0].
[treeopen] top.test_tb.din.[0].srec1.
[treeopen] top.test_tb.din.[0].srec2.
[treeopen] top.test_tb.din.[1].
[treeopen] top.test_tb.din.[1].srec1.
[treeopen] top.test_tb.din.[1].srec2.
[treeopen] top.test_tb.din.[2].
[treeopen] top.test_tb.din.[2].srec1.
[treeopen] top.test_tb.din.[2].srec2.
[treeopen] top.test_tb.dout.
[treeopen] top.test_tb.dout.[0].
[treeopen] top.test_tb.dout.[0].srec1.
[treeopen] top.test_tb.dout.[0].srec2.
[treeopen] top.test_tb.dout.[1].
[treeopen] top.test_tb.dout.[1].srec1.
[treeopen] top.test_tb.dout.[1].srec2.
[treeopen] top.test_tb.dout.[2].
[treeopen] top.test_tb.dout.[2].srec1.
[treeopen] top.test_tb.dout.[2].srec2.
[sst_width] 210
[signals_width] 142
[sst_expanded] 1
[sst_vpaned_height] 284
@200
-din0
@28
top.test_tb.din[0].srec1.stb
@22
#{top.test_tb.din[0].srec1.p1[3:0]} top.test_tb.din[0].srec1.p1[3] top.test_tb.din[0].srec1.p1[2] top.test_tb.din[0].srec1.p1[1] top.test_tb.din[0].srec1.p1[0]
#{top.test_tb.din[0].flags[5:1]} top.test_tb.din[0].flags[5] top.test_tb.din[0].flags[4] top.test_tb.din[0].flags[3] top.test_tb.din[0].flags[2] top.test_tb.din[0].flags[1]
@28
top.test_tb.din[0].srec2.f1
#{top.test_tb.din[0].srec2.f3[2:0]} top.test_tb.din[0].srec2.f3[2] top.test_tb.din[0].srec2.f3[1] top.test_tb.din[0].srec2.f3[0]
@22
#{top.test_tb.din[0].srec2.f2[1:4]} top.test_tb.din[0].srec2.f2[1] top.test_tb.din[0].srec2.f2[2] top.test_tb.din[0].srec2.f2[3] top.test_tb.din[0].srec2.f2[4]
#{top.test_tb.din[0].nmbr[5:0]} top.test_tb.din[0].nmbr[5] top.test_tb.din[0].nmbr[4] top.test_tb.din[0].nmbr[3] top.test_tb.din[0].nmbr[2] top.test_tb.din[0].nmbr[1] top.test_tb.din[0].nmbr[0]
@200
-dout0
@28
top.test_tb.dout[0].srec1.stb
@22
#{top.test_tb.dout[0].srec1.p1[3:0]} top.test_tb.dout[0].srec1.p1[3] top.test_tb.dout[0].srec1.p1[2] top.test_tb.dout[0].srec1.p1[1] top.test_tb.dout[0].srec1.p1[0]
#{top.test_tb.dout[0].flags[5:1]} top.test_tb.dout[0].flags[5] top.test_tb.dout[0].flags[4] top.test_tb.dout[0].flags[3] top.test_tb.dout[0].flags[2] top.test_tb.dout[0].flags[1]
@28
top.test_tb.dout[0].srec2.f1
#{top.test_tb.dout[0].srec2.f3[2:0]} top.test_tb.dout[0].srec2.f3[2] top.test_tb.dout[0].srec2.f3[1] top.test_tb.dout[0].srec2.f3[0]
@22
#{top.test_tb.dout[0].srec2.f2[1:4]} top.test_tb.dout[0].srec2.f2[1] top.test_tb.dout[0].srec2.f2[2] top.test_tb.dout[0].srec2.f2[3] top.test_tb.dout[0].srec2.f2[4]
#{top.test_tb.dout[0].nmbr[5:0]} top.test_tb.dout[0].nmbr[5] top.test_tb.dout[0].nmbr[4] top.test_tb.dout[0].nmbr[3] top.test_tb.dout[0].nmbr[2] top.test_tb.dout[0].nmbr[1] top.test_tb.dout[0].nmbr[0]
@200
-din1
@28
top.test_tb.din[1].srec1.stb
@22
#{top.test_tb.din[1].srec1.p1[3:0]} top.test_tb.din[1].srec1.p1[3] top.test_tb.din[1].srec1.p1[2] top.test_tb.din[1].srec1.p1[1] top.test_tb.din[1].srec1.p1[0]
#{top.test_tb.din[1].flags[5:1]} top.test_tb.din[1].flags[5] top.test_tb.din[1].flags[4] top.test_tb.din[1].flags[3] top.test_tb.din[1].flags[2] top.test_tb.din[1].flags[1]
@28
top.test_tb.din[1].srec2.f1
#{top.test_tb.din[1].srec2.f3[2:0]} top.test_tb.din[1].srec2.f3[2] top.test_tb.din[1].srec2.f3[1] top.test_tb.din[1].srec2.f3[0]
@22
#{top.test_tb.din[1].srec2.f2[1:4]} top.test_tb.din[1].srec2.f2[1] top.test_tb.din[1].srec2.f2[2] top.test_tb.din[1].srec2.f2[3] top.test_tb.din[1].srec2.f2[4]
@23
#{top.test_tb.din[1].nmbr[5:0]} top.test_tb.din[1].nmbr[5] top.test_tb.din[1].nmbr[4] top.test_tb.din[1].nmbr[3] top.test_tb.din[1].nmbr[2] top.test_tb.din[1].nmbr[1] top.test_tb.din[1].nmbr[0]
@200
-dout1
@28
top.test_tb.dout[1].srec1.stb
@22
#{top.test_tb.dout[1].srec1.p1[3:0]} top.test_tb.dout[1].srec1.p1[3] top.test_tb.dout[1].srec1.p1[2] top.test_tb.dout[1].srec1.p1[1] top.test_tb.dout[1].srec1.p1[0]
#{top.test_tb.dout[1].flags[5:1]} top.test_tb.dout[1].flags[5] top.test_tb.dout[1].flags[4] top.test_tb.dout[1].flags[3] top.test_tb.dout[1].flags[2] top.test_tb.dout[1].flags[1]
@28
top.test_tb.dout[1].srec2.f1
#{top.test_tb.dout[1].srec2.f3[2:0]} top.test_tb.dout[1].srec2.f3[2] top.test_tb.dout[1].srec2.f3[1] top.test_tb.dout[1].srec2.f3[0]
@22
#{top.test_tb.dout[1].srec2.f2[1:4]} top.test_tb.dout[1].srec2.f2[1] top.test_tb.dout[1].srec2.f2[2] top.test_tb.dout[1].srec2.f2[3] top.test_tb.dout[1].srec2.f2[4]
#{top.test_tb.dout[1].nmbr[5:0]} top.test_tb.dout[1].nmbr[5] top.test_tb.dout[1].nmbr[4] top.test_tb.dout[1].nmbr[3] top.test_tb.dout[1].nmbr[2] top.test_tb.dout[1].nmbr[1] top.test_tb.dout[1].nmbr[0]
@200
-din2
@28
top.test_tb.din[2].srec1.stb
@22
#{top.test_tb.din[2].srec1.p1[3:0]} top.test_tb.din[2].srec1.p1[3] top.test_tb.din[2].srec1.p1[2] top.test_tb.din[2].srec1.p1[1] top.test_tb.din[2].srec1.p1[0]
#{top.test_tb.din[2].flags[5:1]} top.test_tb.din[2].flags[5] top.test_tb.din[2].flags[4] top.test_tb.din[2].flags[3] top.test_tb.din[2].flags[2] top.test_tb.din[2].flags[1]
@28
top.test_tb.din[2].srec2.f1
#{top.test_tb.din[2].srec2.f3[2:0]} top.test_tb.din[2].srec2.f3[2] top.test_tb.din[2].srec2.f3[1] top.test_tb.din[2].srec2.f3[0]
@22
#{top.test_tb.din[2].srec2.f2[1:4]} top.test_tb.din[2].srec2.f2[1] top.test_tb.din[2].srec2.f2[2] top.test_tb.din[2].srec2.f2[3] top.test_tb.din[2].srec2.f2[4]
#{top.test_tb.din[2].nmbr[5:0]} top.test_tb.din[2].nmbr[5] top.test_tb.din[2].nmbr[4] top.test_tb.din[2].nmbr[3] top.test_tb.din[2].nmbr[2] top.test_tb.din[2].nmbr[1] top.test_tb.din[2].nmbr[0]
@200
-dout2
@28
top.test_tb.dout[2].srec1.stb
@22
#{top.test_tb.dout[2].srec1.p1[3:0]} top.test_tb.dout[2].srec1.p1[3] top.test_tb.dout[2].srec1.p1[2] top.test_tb.dout[2].srec1.p1[1] top.test_tb.dout[2].srec1.p1[0]
#{top.test_tb.dout[2].flags[5:1]} top.test_tb.dout[2].flags[5] top.test_tb.dout[2].flags[4] top.test_tb.dout[2].flags[3] top.test_tb.dout[2].flags[2] top.test_tb.dout[2].flags[1]
@28
top.test_tb.dout[2].srec2.f1
#{top.test_tb.dout[2].srec2.f3[2:0]} top.test_tb.dout[2].srec2.f3[2] top.test_tb.dout[2].srec2.f3[1] top.test_tb.dout[2].srec2.f3[0]
@22
#{top.test_tb.dout[2].srec2.f2[1:4]} top.test_tb.dout[2].srec2.f2[1] top.test_tb.dout[2].srec2.f2[2] top.test_tb.dout[2].srec2.f2[3] top.test_tb.dout[2].srec2.f2[4]
#{top.test_tb.dout[2].nmbr[5:0]} top.test_tb.dout[2].nmbr[5] top.test_tb.dout[2].nmbr[4] top.test_tb.dout[2].nmbr[3] top.test_tb.dout[2].nmbr[2] top.test_tb.dout[2].nmbr[1] top.test_tb.dout[2].nmbr[0]
@200
-test_vec
@22
#{top.test_tb.test_vec[71:0]} top.test_tb.test_vec[71] top.test_tb.test_vec[70] top.test_tb.test_vec[69] top.test_tb.test_vec[68] top.test_tb.test_vec[67] top.test_tb.test_vec[66] top.test_tb.test_vec[65] top.test_tb.test_vec[64] top.test_tb.test_vec[63] top.test_tb.test_vec[62] top.test_tb.test_vec[61] top.test_tb.test_vec[60] top.test_tb.test_vec[59] top.test_tb.test_vec[58] top.test_tb.test_vec[57] top.test_tb.test_vec[56] top.test_tb.test_vec[55] top.test_tb.test_vec[54] top.test_tb.test_vec[53] top.test_tb.test_vec[52] top.test_tb.test_vec[51] top.test_tb.test_vec[50] top.test_tb.test_vec[49] top.test_tb.test_vec[48] top.test_tb.test_vec[47] top.test_tb.test_vec[46] top.test_tb.test_vec[45] top.test_tb.test_vec[44] top.test_tb.test_vec[43] top.test_tb.test_vec[42] top.test_tb.test_vec[41] top.test_tb.test_vec[40] top.test_tb.test_vec[39] top.test_tb.test_vec[38] top.test_tb.test_vec[37] top.test_tb.test_vec[36] top.test_tb.test_vec[35] top.test_tb.test_vec[34] top.test_tb.test_vec[33] top.test_tb.test_vec[32] top.test_tb.test_vec[31] top.test_tb.test_vec[30] top.test_tb.test_vec[29] top.test_tb.test_vec[28] top.test_tb.test_vec[27] top.test_tb.test_vec[26] top.test_tb.test_vec[25] top.test_tb.test_vec[24] top.test_tb.test_vec[23] top.test_tb.test_vec[22] top.test_tb.test_vec[21] top.test_tb.test_vec[20] top.test_tb.test_vec[19] top.test_tb.test_vec[18] top.test_tb.test_vec[17] top.test_tb.test_vec[16] top.test_tb.test_vec[15] top.test_tb.test_vec[14] top.test_tb.test_vec[13] top.test_tb.test_vec[12] top.test_tb.test_vec[11] top.test_tb.test_vec[10] top.test_tb.test_vec[9] top.test_tb.test_vec[8] top.test_tb.test_vec[7] top.test_tb.test_vec[6] top.test_tb.test_vec[5] top.test_tb.test_vec[4] top.test_tb.test_vec[3] top.test_tb.test_vec[2] top.test_tb.test_vec[1] top.test_tb.test_vec[0]
[pattern_trace] 1
[pattern_trace] 0
SHAR_EOF
(set 20 16 09 22 20 46 39 'test.sav'
eval "${shar_touch}") && \
chmod 0644 'test.sav'
if test $? -ne 0
then ${echo} "restore of test.sav failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test.sav': 'MD5 check failed'
) << \SHAR_EOF
514ac59c3619a6be76a0c0e5681f55bf test.sav
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test.sav'` -ne 8619 && \
${echo} "restoration warning: size of 'test.sav' is not 8619"
fi
fi
# ============= test_tb.vhd ==============
if test -n "${keep_file}" && test -f 'test_tb.vhd'
then
${echo} "x - SKIPPING test_tb.vhd (file already exists)"

else
${echo} "x - extracting test_tb.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'test_tb.vhd' &&
-------------------------------------------------------------------------------
-- Title : Testbench for records & record converters generator
-- Project :
-------------------------------------------------------------------------------
-- File : test_tb.vhd
-- Author : Wojciech Zabolotny
-- Company :
-- Created : 2016-09-21
-- Last update: 2016-09-22
X constant nx : integer := 3;
X -- signals
X signal din, dout : test_rec_array(0 to nx-1);
X signal test_vec : std_logic_vector(nx*test_rec_width-1 downto 0);
X
begin -- test1
X test_vec <= test_rec_array_to_stlv(din,nx);
X dout <= stlv_to_test_rec_array(test_vec,nx);
X -- waveform generation
X WaveGen_Proc : process
X begin
X din(0).nmbr <= to_unsigned(1,6);
X din(0).flags <= "11010";
X din(0).srec2.f1 <= '1';
X din(0).srec2.f2 <="1000";
X din(0).srec2.f3 <=to_unsigned(4,3);
X din(0).srec1.p1 <="0101";
X din(0).srec1.stb <= '1';
X
X din(1).nmbr <= to_unsigned(4,6);
X din(1).flags <= "00101";
X din(1).srec2.f1 <= '0';
X din(1).srec2.f2 <="1100";
X din(1).srec2.f3 <=to_unsigned(4,3);
X din(1).srec1.p1 <="1010";
X din(1).srec1.stb <= '0';
X
X din(2).nmbr <= to_unsigned(12,6);
X din(2).flags <= "11100";
X din(2).srec2.f1 <= '1';
X din(2).srec2.f2 <="1001";
X din(2).srec2.f3 <=to_unsigned(4,3);
X din(2).srec1.p1 <="0001";
X din(2).srec1.stb <= '1';
X wait for 10 ns;
X din(0).srec1.stb <= '0';
X din(1).flags <= "10101";
X din(2).srec1.stb <= '1';
X wait for 10 ns;
X din(2).srec2.f2 <= "0111";
X din(0).srec2.f3 <= to_unsigned(5,3);
X din(1).srec1.p1 <= "1100";
X wait for 10 ns;
X din(1).flags <= "00111";
X din(2).nmbr <= to_unsigned(2,6);
X din(1).nmbr <= to_unsigned(37,6);
X din(0).nmbr <= to_unsigned(43,6);
X wait for 10 ns;
X din(0).srec1.p1 <= "1100";
X wait for 10 ns;
X din(1).srec1.stb <= '1';
X wait;
X end process WaveGen_Proc;
X
X
end test1;
X
SHAR_EOF
(set 20 16 09 22 20 45 03 'test_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'test_tb.vhd'
if test $? -ne 0
then ${echo} "restore of test_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
07c7105b413c6ffcd5007fb8e71dd19b test_tb.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test_tb.vhd'` -ne 2796 && \
${echo} "restoration warning: size of 'test_tb.vhd' is not 2796"
fi
fi
# ============= test.vhd ==============
if test -n "${keep_file}" && test -f 'test.vhd'
then
${echo} "x - SKIPPING test.vhd (file already exists)"

else
${echo} "x - extracting test.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'test.vhd' &&
--use work.test_pkg.all;
-------------------------------------------------------------------------------
X
entity test_tb is
X
end test_tb;
X
-------------------------------------------------------------------------------
X
architecture test1 of test_tb is
X
X type t_r is array(natural range <>) of integer;
X signal a1 : t_r(10 downto 2);
X signal a2 : t_r(3 to 15);
X signal p : integer;
X function vlen( constant v : t_r) return integer is
X variable res : integer;
X begin
X res := max(v'left-v'right+1, v'right-v'left+1);
X report "len=" & integer'image(res) severity note;
X return res;
X end function vlen;
X
begin -- test1
X -- waveform generation
X WaveGen_Proc : process
X begin
X wait for 10 ns;
X p<= vlen(a1);
X wait for 10 ns;
X p<= vlen(a2);
X wait for 10 ns;
X wait;
X end process WaveGen_Proc;
X
X
end test1;
X
SHAR_EOF
(set 20 16 09 22 20 02 07 'test.vhd'
eval "${shar_touch}") && \
chmod 0644 'test.vhd'
if test $? -ne 0
then ${echo} "restore of test.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test.vhd': 'MD5 check failed'
) << \SHAR_EOF
f9b791fb6738ff6d009fd224392d8c21 test.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test.vhd'` -ne 1837 && \
${echo} "restoration warning: size of 'test.vhd' is not 1837"

Wojciech M. Zabołotny

unread,
Sep 22, 2016, 3:49:57 PM9/22/16
to
Archive-name: rec_to_pkg_nest-1.2-beta
Original-author: Wojciech M. Zabolotny ( wz...@ise.pw.edu.pl )
Submitted-by: wz...@ise.pw.edu.pl
Last-modified: 2016-09-22 +00:00
Copyright-Notice: PUBLIC DOMAIN or Creative Commons CC0

This is the new, corrected version of the previous rec_to_pkg.py tool.
Basing on the record description file, it generates the VHDL package,
that defines the record type and provides the conversion functions
for conversion of the records into std_logic_vector of tha appropriate
length, and from std_logic vector to the record.

This rec_to_pkg_nest.py may handle the nested records and the arrays of record types.
Additionally it is possible to specify comments, that should be written at the begining
of the generated VHDL package (they should start with double hash '##').

The signals of array type should be defined as:
signal s1 : rec_type_array(first to first+nelems-1);
The vector for conversion should be declared as:
signal vec : std_logic_vector(nelems*rec_type_width-1 downto 0);

Then you can convert them to the std_logic_vector by
vec <= rec_type_array_to_stlv(s1,nelems,first)
If first is equal to 0, you may use the simplified form:
vec <= rec_type_array_to_stlv(s1,nelems)

Similarly, conversion from stlv should be done with
s1 <= stlv_to_rec_type_array(vec,nelems,first);
or if first==0:
s1 <= stlv_to_rec_type_array(vec,nelems);

The sources contain the example record definition file, and a testbench
showing the operation.
If you have ghdl and gtkwave installed, run the run_test.sh to see the
demonstration.

Please note that the code is published as PUBLIC DOMAIN or under Creative
Commons CC0 license.
However, if you create any derived work, please provide information
about the original author.

This is a free code. I do not provide any warranty. You use it on your
own risk.

With best regards,
Wojtek

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.15.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the '#!/bin/sh' line above, then type 'sh FILE'.
#
lock_dir=_sh06447
# Made on 2016-09-22 21:41 CEST by <wzab@wzab>.
# Source directory was '/home/wzab/biezace/VHDL/rec_to_pkg_new/publ'.
#
# Existing files will *not* be overwritten, unless '-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 9445 -rwxr-xr-x rec_to_pkg_nest.py
# 171 -rwxr--r-- run_test.sh
# 591 -rw-r--r-- test.rec
# 8619 -rw-r--r-- test.sav
# 2798 -rw-r--r-- test_tb.vhd
# This is the version 1.2
X p+=" constant nitems : integer;\n"
X p+=" constant nfirst : integer := 0)\n"
X p+=" return std_logic_vector;\n\n"
X p+="function stlv_to_"+a[0]+"(\n"
X p+=" constant din : std_logic_vector;\n"
X p+=" constant nitems : integer;\n"
X p+=" constant nfirst : integer := 0)\n"
X p+=" constant nitems : integer;\n"
X p+=" constant nfirst : integer := 0)\n"
X p+=" return std_logic_vector is\n"
X p+=" variable res : std_logic_vector("+a[1]+"_width * nitems - 1 downto 0);\n"
X p+="begin\n"
X p+=" for i in 0 to nitems-1 loop\n"
X p+=" res((i+1)*"+a[1]+"_width-1 downto i*"+a[1]+"_width) := "+a[1]+"_to_stlv(din(nfirst+i));\n"
X p+=" end loop;\n"
X p+=" return res;\n"
X p+="end function "+a[0]+"_to_stlv;\n\n"
X
X p+="function stlv_to_"+a[0]+"(\n"
X p+=" constant din : std_logic_vector;\n"
X p+=" constant nitems : integer;\n"
X p+=" constant nfirst : integer := 0)\n"
X p+=" return "+a[0]+" is\n"
X p+=" variable res : "+a[0]+"(nfirst to nfirst+nitems-1)\n;"
X p+="begin\n"
X p+=" for i in 0 to nitems-1 loop\n"
X p+=" res(i+nfirst) := stlv_to_"+a[1]+"(din((i+1)*"+a[1]+"_width-1 downto i*"+a[1]+"_width));\n"
X p+=" end loop;\n"
X p+=" return res;\n"
X p+="end function stlv_to_"+a[0]+";\n\n"
p+="end "+pkg_name+";\n"
X
#The output file name
fout_name=pkg_name+".vhd"
fout=open(fout_name,"w")
fout.write(p)
fout.close()
X
SHAR_EOF
(set 20 16 09 22 21 36 01 'rec_to_pkg_nest.py'
eval "${shar_touch}") && \
chmod 0755 'rec_to_pkg_nest.py'
if test $? -ne 0
then ${echo} "restore of rec_to_pkg_nest.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'rec_to_pkg_nest.py': 'MD5 check failed'
) << \SHAR_EOF
e2ed2ad3464c41293407bb7f061b1dda rec_to_pkg_nest.py
SHAR_EOF

else
test `LC_ALL=C wc -c < 'rec_to_pkg_nest.py'` -ne 9445 && \
${echo} "restoration warning: size of 'rec_to_pkg_nest.py' is not 9445"
[treeopen] top.test_tb.din.[3].
[treeopen] top.test_tb.din.[3].srec1.
[treeopen] top.test_tb.din.[3].srec2.
[treeopen] top.test_tb.din.[1].
[treeopen] top.test_tb.din.[1].srec1.
[treeopen] top.test_tb.din.[1].srec2.
[treeopen] top.test_tb.din.[2].
[treeopen] top.test_tb.din.[2].srec1.
[treeopen] top.test_tb.din.[2].srec2.
[treeopen] top.test_tb.dout.
[treeopen] top.test_tb.dout.[3].
[treeopen] top.test_tb.dout.[3].srec1.
[treeopen] top.test_tb.dout.[3].srec2.
[treeopen] top.test_tb.dout.[1].
[treeopen] top.test_tb.dout.[1].srec1.
[treeopen] top.test_tb.dout.[1].srec2.
[treeopen] top.test_tb.dout.[2].
[treeopen] top.test_tb.dout.[2].srec1.
[treeopen] top.test_tb.dout.[2].srec2.
[sst_width] 210
[signals_width] 142
[sst_expanded] 1
[sst_vpaned_height] 284
@200
-din3
@28
top.test_tb.din[3].srec1.stb
@22
#{top.test_tb.din[3].srec1.p1[3:0]} top.test_tb.din[3].srec1.p1[3] top.test_tb.din[3].srec1.p1[2] top.test_tb.din[3].srec1.p1[1] top.test_tb.din[3].srec1.p1[0]
#{top.test_tb.din[3].flags[5:1]} top.test_tb.din[3].flags[5] top.test_tb.din[3].flags[4] top.test_tb.din[3].flags[3] top.test_tb.din[3].flags[2] top.test_tb.din[3].flags[1]
@28
top.test_tb.din[3].srec2.f1
#{top.test_tb.din[3].srec2.f3[2:0]} top.test_tb.din[3].srec2.f3[2] top.test_tb.din[3].srec2.f3[1] top.test_tb.din[3].srec2.f3[0]
@22
#{top.test_tb.din[3].srec2.f2[1:4]} top.test_tb.din[3].srec2.f2[1] top.test_tb.din[3].srec2.f2[2] top.test_tb.din[3].srec2.f2[3] top.test_tb.din[3].srec2.f2[4]
#{top.test_tb.din[3].nmbr[5:0]} top.test_tb.din[3].nmbr[5] top.test_tb.din[3].nmbr[4] top.test_tb.din[3].nmbr[3] top.test_tb.din[3].nmbr[2] top.test_tb.din[3].nmbr[1] top.test_tb.din[3].nmbr[0]
@200
-dout3
@28
top.test_tb.dout[3].srec1.stb
@22
#{top.test_tb.dout[3].srec1.p1[3:0]} top.test_tb.dout[3].srec1.p1[3] top.test_tb.dout[3].srec1.p1[2] top.test_tb.dout[3].srec1.p1[1] top.test_tb.dout[3].srec1.p1[0]
#{top.test_tb.dout[3].flags[5:1]} top.test_tb.dout[3].flags[5] top.test_tb.dout[3].flags[4] top.test_tb.dout[3].flags[3] top.test_tb.dout[3].flags[2] top.test_tb.dout[3].flags[1]
@28
top.test_tb.dout[3].srec2.f1
#{top.test_tb.dout[3].srec2.f3[2:0]} top.test_tb.dout[3].srec2.f3[2] top.test_tb.dout[3].srec2.f3[1] top.test_tb.dout[3].srec2.f3[0]
@22
#{top.test_tb.dout[3].srec2.f2[1:4]} top.test_tb.dout[3].srec2.f2[1] top.test_tb.dout[3].srec2.f2[2] top.test_tb.dout[3].srec2.f2[3] top.test_tb.dout[3].srec2.f2[4]
#{top.test_tb.dout[3].nmbr[5:0]} top.test_tb.dout[3].nmbr[5] top.test_tb.dout[3].nmbr[4] top.test_tb.dout[3].nmbr[3] top.test_tb.dout[3].nmbr[2] top.test_tb.dout[3].nmbr[1] top.test_tb.dout[3].nmbr[0]
(set 20 16 09 22 21 41 05 'test.sav'
eval "${shar_touch}") && \
chmod 0644 'test.sav'
if test $? -ne 0
then ${echo} "restore of test.sav failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test.sav': 'MD5 check failed'
) << \SHAR_EOF
a019d730ef9743450b53d3ec8e13adbb test.sav
X signal din, dout : test_rec_array(1 to nx);
X signal test_vec : std_logic_vector(nx*test_rec_width-1 downto 0);
X
begin -- test1
X test_vec <= test_rec_array_to_stlv(din,nx,1);
X dout <= stlv_to_test_rec_array(test_vec,nx,1);
X -- waveform generation
X WaveGen_Proc : process
X begin
X din(3).nmbr <= to_unsigned(1,6);
X din(3).flags <= "11010";
X din(3).srec2.f1 <= '1';
X din(3).srec2.f2 <="1000";
X din(3).srec2.f3 <=to_unsigned(4,3);
X din(3).srec1.p1 <="0101";
X din(3).srec1.stb <= '1';
X
X din(1).nmbr <= to_unsigned(4,6);
X din(1).flags <= "00101";
X din(1).srec2.f1 <= '0';
X din(1).srec2.f2 <="1100";
X din(1).srec2.f3 <=to_unsigned(4,3);
X din(1).srec1.p1 <="1010";
X din(1).srec1.stb <= '0';
X
X din(2).nmbr <= to_unsigned(12,6);
X din(2).flags <= "11100";
X din(2).srec2.f1 <= '1';
X din(2).srec2.f2 <="1001";
X din(2).srec2.f3 <=to_unsigned(4,3);
X din(2).srec1.p1 <="0001";
X din(2).srec1.stb <= '1';
X wait for 10 ns;
X din(3).srec1.stb <= '0';
X din(1).flags <= "10101";
X din(2).srec1.stb <= '1';
X wait for 10 ns;
X din(2).srec2.f2 <= "0111";
X din(3).srec2.f3 <= to_unsigned(5,3);
X din(1).srec1.p1 <= "1100";
X wait for 10 ns;
X din(1).flags <= "00111";
X din(2).nmbr <= to_unsigned(2,6);
X din(1).nmbr <= to_unsigned(37,6);
X din(3).nmbr <= to_unsigned(43,6);
X wait for 10 ns;
X din(3).srec1.p1 <= "1100";
X wait for 10 ns;
X din(1).srec1.stb <= '1';
X wait;
X end process WaveGen_Proc;
X
X
end test1;
X
SHAR_EOF
(set 20 16 09 22 21 38 23 'test_tb.vhd'
eval "${shar_touch}") && \
chmod 0644 'test_tb.vhd'
if test $? -ne 0
then ${echo} "restore of test_tb.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'test_tb.vhd': 'MD5 check failed'
) << \SHAR_EOF
45ec062621c2c0695a7172b700d6451d test_tb.vhd
SHAR_EOF

else
test `LC_ALL=C wc -c < 'test_tb.vhd'` -ne 2798 && \
${echo} "restoration warning: size of 'test_tb.vhd' is not 2798"
0 new messages