stdio_h.vhd modules for string/file processing

E

Eli Bendersky

Hello,

Is anyone using the stdio_h/strings_h and kin libraries from
http://bear.ces.cwru.edu/VHDL/index.html ?

I find their implementation of C-like strings (Nul terminated) on top
of VHDL strings quite robust, but some things are missing. For
instance, there seems to be no easy way to sscanf several consecutive
tokens from a string.

Have you had experience with this library you can share ? Any useful
utilities you've added to it ? Are you aware of more complete
versions ?

Thanks in advance
 
T

Tricky

Hello,

Is anyone using the stdio_h/strings_h and kin libraries fromhttp://bear.ces.cwru.edu/VHDL/index.html?

I find their implementation of C-like strings (Nul terminated) on top
of VHDL strings quite robust, but some things are missing. For
instance, there seems to be no easy way to sscanf several consecutive
tokens from a string.

Aslong as the tokens are separated by spaces, read(l: line; i:
integer) works well enough for me.
Have you had experience with this library you can share ? Any useful
utilities you've added to it ? Are you aware of more complete
versions ?

Thanks in advance

I dont get the point of what these packages are trying to do, other
than make code look more C-like and ease software programmers into
VHDL by giving them familiar functions. Functioanlly, Im pretty sure
anything you can do in these packages can be done via the std.textio
package. Reading data files is a bit of a workaround, as you can only
read 1 byte at a time, but it can be done quite easily.

I worry that packages like this bring more software programmers into
VHDL without understanding the unlying principals of digital
electronics.
 
M

Mike Treseler

Eli said:
Is anyone using the stdio_h/strings_h and kin libraries from
http://bear.ces.cwru.edu/VHDL/index.html ?

I find their implementation of C-like strings (Nul terminated) on top
of VHDL strings quite robust, but some things are missing. For
instance, there seems to be no easy way to sscanf several consecutive
tokens from a string.

When I want to do string or file processing,
I use python or shell script. When I want
to make hardware models for synthesis
or simulation, I use vhdl, modelsim, and quartus.

-- Mike Treseler
 
E

Eli Bendersky

I dont get the point of what these packages are trying to do, other
than make code look more C-like and ease software programmers into
VHDL by giving them familiar functions. Functioanlly, Im pretty sure
anything you can do in these packages can be done via the std.textio
package. Reading data files is a bit of a workaround, as you can only
read 1 byte at a time, but it can be done quite easily.

I worry that packages like this bring more software programmers into
VHDL without understanding the unlying principals of digital
electronics.

No.

This package actually tries to combat the brain-dead VHDL string
processing. One of the biggest cons of VHDL string processing is
needing to declare strings with known length. This is solved in the
package by emulating C strings ending with NUL. As long as you use
functions / procedures from the package, you can really beautifully
handle variable-length strings.

Eli
 
E

Eli Bendersky

When I want to do string or file processing,
I use python or shell script. When I want
to make hardware models for synthesis
or simulation, I use vhdl, modelsim, and quartus.

      -- Mike Treseler

I agree in general, but sometimes it does make sense to read a file in
VHDL for a sophisticated testbench. In these cases, it is nice to have
a powerful library of functions to make the process less painful.

Eli
 
T

Tricky

No.

This package actually tries to combat the brain-dead VHDL string
processing. One of the biggest cons of VHDL string processing is
needing to declare strings with known length. This is solved in the
package by emulating C strings ending with NUL. As long as you use
functions / procedures from the package, you can really beautifully
handle variable-length strings.

Eli

Then use a line type instead. The read/write functions all resize the
string dynamically. If you need access to the actual string you can
just dereference the pointer with something like:
report myline.all;
DEALLOCATE(myline); --to clear the string
 
E

Eli Bendersky

Then use a line type instead. The read/write functions all resize the
string dynamically. If you need access to the actual string you can
just dereference the pointer with something like:
report myline.all;
DEALLOCATE(myline); --to clear the string

I'm aware of the existence of lines, thanks. But they still aren't
flexible enough. Consider the following simple goal:

I want to read lines from a file, formatted:

<int> <name> <hex_int> <bin_int>

Where <name> is some identifier, up to 20 chars long. I want to read
and store all these data in variables, and later write <name> along
with other things into another file.
How do you achieve this with using regular strings and lines ?

Eli
 
M

Mike Treseler

Eli said:
I agree in general, but sometimes it does make sense to read a file in
VHDL for a sophisticated testbench. In these cases, it is nice to have
a powerful library of functions to make the process less painful.

I will agree that file IO using vhdl is painful.
Parsing text or binary files is even worse.
I prefer to convert binary or text files into
vhdl constant arrays using the best available tool.
This way, vcom can do the parsing for me.

-- Mike Treseler
 
T

Tricky

I'm aware of the existence of lines, thanks. But they still aren't
flexible enough. Consider the following simple goal:

I want to read lines from a file, formatted:

<int> <name> <hex_int> <bin_int>

Where <name> is some identifier, up to 20 chars long. I want to read
and store all these data in variables, and later write <name> along
with other things into another file.
How do you achieve this with using regular strings and lines ?

Eli

Ok, you got me there, but it's only the <name> bit that causes me a
problem. for <int> you can read it directly into an int, and the
<hex_int> and <bin_int> can be read using the ieee.std_logic_textio
package (I know its synopsys, but it works well), assuming the hex and
bin integers are exactly the correct lengths to fill a
std_logic_vector, which can then be cast to and integer via
numeric_std. Otherwise it's stuffed again.
 
E

Eli Bendersky

Ok, you got me there, but it's only the <name> bit that causes me a
problem. for <int> you can read it directly into an int, and the
<hex_int> and <bin_int> can be read using the ieee.std_logic_textio
package (I know its synopsys, but it works well), assuming the hex and
bin integers are exactly the correct lengths to fill a
std_logic_vector, which can then be cast to and integer via
numeric_std. Otherwise it's stuffed again.

Yep, but the <name> is a problem. There's just no sane way to read and
write it back.

The c-like string libraries allow it, because strings are inherently
variable-length, and if you only use the lib's procedures to work with
them, you'll get what you want.

Eli
 
E

Eli Bendersky

I will agree that file IO using vhdl is painful.
Parsing text or binary files is even worse.
I prefer to convert binary or text files into
vhdl constant arrays using the best available tool.
This way, vcom can do the parsing for me.

         -- Mike Treseler

This is the most general and powerful method, yes. And I have also
utilized "template" VHDL files into which a Perl script inserts VHDL
lines for transactions.

However, this method has its cons. For instance, it requires a longer
"chain" of script/tool calls to work (something, i.e. some kind of
shell script / driver script has to call the Perl tool to do the
generation, and then re-compile the file). Also, it requires
recompilation, which isn't needed when files are read by VHDL from
text directly.

Eli
 
D

Dal

I use it and find it easier to use than VHDL as I prefer the C style
of string/file handling over VHDL.

I found a couple of issues in stdio_h.vhd file. I sent an email to
the authors and they said they would look into it. This was in May
2006 and as far as I know this has not been done. For you reference
here is an extract of the email I sent them...

snip

In the following line in fgets()..

WHILE i<n AND i<s'LENGTH AND NOT feof(stream) LOOP

the feof check will prevent the last line of a file being read
correctly. When the following call to fgetc gets the last line in a
file, and returns the first character in that line, then the next time
around the loop feof(stream) will return true as all the lines in the
file have been read. fgetc already checks the eof so this test for
eof can be omitted. This issue also applies to gets().

Also noticed that fflush() only deallocates if the fmode=WRITE_MODE.
If you have a file open in read mode and fclose part way through the
line the streamiob(stream).buf line will never get NULL'ed. If the
file handle id/stream id gets reused then the first read will be
incorrect as stream doesn't contain an NULL line. The contents of
this line will be treated as if it came from the file just opened.

snip

Let me know if you need details of the simple fixes.

I added the strchr and strstr functions;


-------------------------------------------------------------------------------
-- Search through a string for a character
-- Returns the position of the character if it is found
-- Returns '0' if it wasn't found
function strchr(cs : string; c : character) return integer is
begin
for i in cs'low to cs'high loop
if (cs(i) = c) then
-- Found it - return where it is
return i;
end if;
end loop;
-- Character was not found, so return a '0'
return 0;
end;

-------------------------------------------------------------------------------
-- Search through a string for a string
-- Returns the position of the character if it is found
-- Returns '0' if it wasn't found
function strstr(cs1 : string; cs2 : string) return integer is
variable i : integer := cs1'low;
variable cs1_len : integer := strlen(cs1);
variable cs2_len : integer := strlen(cs2);
begin
loop
if (i > (cs1'low + cs1_len - cs2_len)) then
-- Character was not found, so return a '0'
i:=0;
exit;
elsif (cs1(i to i+cs2_len-1) = cs2(1 to cs2_len)) then
-- elsif (strcmp(cs1(i to i+cs2_len), cs2(1 to cs2_len)) = 0)
then
-- Found it - return where it is
exit;
else
i:=i+1;
end if;
end loop;
return i;
end;



Darrin
 
E

Eli Bendersky

I use it and find it easier to use than VHDL as I prefer the C style
of string/file handling over VHDL.

I found a couple of issues in stdio_h.vhd file.  I sent an email to
the authors and they said they would look into it.  This was in May
2006 and as far as I know this has not been done.  For you reference
here is an extract of the email I sent them...

snip

In the following line in fgets()..

    WHILE i<n AND i<s'LENGTH AND NOT feof(stream) LOOP

the feof check will prevent the last line of a file being read
correctly.  When the following call to fgetc gets the last line in a
file, and returns the first character in that line, then the next time
around the loop feof(stream) will return true as all the lines in the
file have been read.  fgetc already checks the eof so this test for
eof can be omitted.  This issue also applies to gets().

Also noticed that fflush() only deallocates if the fmode=WRITE_MODE.
If you have a file open in read mode and fclose part way through the
line the streamiob(stream).buf line will never get NULL'ed.  If the
file handle id/stream id gets reused then the first read will be
incorrect as stream doesn't contain an NULL line.  The contents of
this line will be treated as if it came from the file just opened.

snip

Thanks for the info and the functions. This is useful.

The largest problem I have with the library is currently the sscanf
family, which only seems to catch the first token in each line,
without moving any state. So basically, parsing a line with sscanf
after it has been read with fgets can not be done.
How do you parse lines read from a file with this library ?

Eli
 
M

Mike Treseler

Eli said:
This is the most general and powerful method, yes. And I have also
utilized "template" VHDL files into which a Perl script inserts VHDL
lines for transactions.

Rather than a template, I have the script
read the file and write a package of constant arrays
that can be checked into svn
and used directly by the testbench.

In cases where the sample data can be computed,
a vhdl function can generate such constants directly.

-- Mike Treseler
 
E

Eli Bendersky

Rather than a template, I have the script
read the file and write a package of constant arrays
that can be checked into svn
and used directly by the testbench.

In cases where the sample data can be computed,
a vhdl function can generate such constants directly.

And yet, note that if one of the vectors is a string (that's used, for
example, as a test ID to be printed out by a monitor module to a file
for script comparison), you have no normal way of specifying an array
of strings of variable length, so you'll have to make all the strings
of the same length.
The C-like package I refer to attempts to solve this problem.

Eli
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top