return a variable size string

A

Amal

Guest
I am writing a to_string function for a type that I have defined. I
have used the STD.TEXTIO' write function to write a string
representation of the type that is of variable length to a line (L).
The function looks something like below:

impure function to_string( ... ) return string is
variable L : line;
begin
write( L, string'("+--------+") & CR );
for i in .... loop
write( L, ... );
end loop;
write( L, ... );
return L.all;
end function to_string;

L is an access type and write function keeps deallocating L and
allocating more storage (the string that L points to would grow in
size from write to write). My question is that, normally it is best
to release the storage pointed to by L by calling deallocate on L.
But in this case I cannot call deallocate(L) explicitly before the
function returns. Do simulators release the storage after the
function returns?

-- Amal
 
On Wed, 28 Nov 2007 12:13:05 -0800 (PST), Amal wrote:

L is an access type and write function keeps deallocating L and
allocating more storage (the string that L points to would grow in
size from write to write). My question is that, normally it is best
to release the storage pointed to by L by calling deallocate on L.
But in this case I cannot call deallocate(L) explicitly before the
function returns. Do simulators release the storage after the
function returns?
I'm afraid I don't know - in this particular case, presumably,
a sufficiently clever tool could see that the access variable
L cannot be "given away" by the function and therefore it
can safely be deallocated on exit. But I agree with
you that it feels wrong.

One trick for getting around this is to move variable L
outside your function, and then wrap the whole thing in
yet another function. Like this (in which the "to_string"
function merely makes a string of N asterisks, but you'll
get the idea):

impure function to_string(n: positive) return string is
variable L: line;
impure function to_string_inner(n: positive) return string is
begin
for i in 1 to n loop
write(L, character' ('*') );
end loop;
return L.all;
end;
constant s: string := to_string_inner(n);
begin
deallocate(L);
return s;
end;

Someone else may have some nicer ideas...
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Amal wrote:

But in this case I cannot call deallocate(L) explicitly before the
function returns. Do simulators release the storage after the
function returns?
I don't know, because I find that writing
my own string conversion functions is more
efficient than tinkering with std.textio.
Here's some examples:
http://home.comcast.net/~mike_treseler/min_vec_len.vhd

I do use std.textio.write to print strings to
modelsim's standard output (std.textio.output) like this:

procedure echo (
arg : in string := "") is
begin
std.textio.write(std.textio.output, arg);
end procedure echo;

Then I can say something like this in a testbench

echo("The answer is " & odd2string(my_oddity) & LF & LF);

-- Mike Treseler
 
On Nov 28, 5:22 pm, Mike Treseler <mike_trese...@comcast.net> wrote:
Amal wrote:
But in this case I cannot call deallocate(L) explicitly before the
function returns. Do simulators release the storage after the
function returns?
It shouldn't matter that write may repeatedly reallocate L; L is an
inout parameter and (although it's not explicitly stated as such in
the LRM), 'write' ought to be managing the allocated storage and
updating L appropriately. The only thing that matters is the L that
you are leaving as garbage when you exit.

The "wrapper" above makes sense. Alternately you could return L
directly and rely on the caller to free L (admittedly ugly).

The LRM states that "An implementation may (but need not) deallocate
the storage occupied by an object created by an allocator, once this
object has become inaccessible." So I think the answer to your final
question is "maybe".

If you don't trust your implementation to deallocate L for you, I
don't think you have a much better solution that using the wrapper.

Also, depending on how you want your data formatted, you might also be
able to make creative use of the 'image attribute with catenation to
avoid dynamically allocated objects completely.

HTH,

- Kenn
 
Jonathan Bromley wrote:

One trick for getting around this is to move variable L
outside your function, and then wrap the whole thing in
yet another function. Like this (in which the "to_string"
function merely makes a string of N asterisks, but you'll
get the idea):

impure function to_string(n: positive) return string is
variable L: line;
impure function to_string_inner(n: positive) return string is
begin
for i in 1 to n loop
write(L, character' ('*') );
end loop;
return L.all;
end;
constant s: string := to_string_inner(n);
begin
deallocate(L);
return s;
end;

Someone else may have some nicer ideas...
They don't come nicer than that one.
Elegant and simple.
I like it!

--
Paul Uiterlinden
www.aimvalley.nl
e-mail addres: remove the not.
 

Welcome to EDABoard.com

Sponsor

Back
Top