dynamic memory allocation for images in a test bench

W

wallge

Guest
Say I to implement the following C language constructs in my VHDL
testbench:
I want to have a generic image struct:

typedef struct {
unsigned int height;
unsigned int width;
unsigned char *pixels;
} Image_Type;

I think something like this can be done with a VHDL record type.

Then initialize it with the following function:

int init_image_struct(unsigned int height, unsigned int width,
Image_Type *image)
{
image->height = height;
image->width = width;
image->pixels = (unsigned char*) malloc(sizeof(unsigned char) *
height * width);
return 0;
}


I would like to pass my vhdl functions constants or parameters read
from files at some point during the course of my simulation run.

I want to be able to do this so I can handle images of various sizes
without knowing the size ahead of time.
This would prevent the need for hard coded images sizes (need a new
type for each different image size).

Can anyone tell me how to do this in VHDL?

Also how to prevent memory leaks?
 
"wallge" <wallge@gmail.com> wrote in message
news:1171652317.265672.70270@a75g2000cwd.googlegroups.com...
Say I to implement the following C language constructs in my VHDL
testbench:
I want to have a generic image struct:

typedef struct {
unsigned int height;
unsigned int width;
unsigned char *pixels;
} Image_Type;

I think something like this can be done with a VHDL record type.

Then initialize it with the following function:

int init_image_struct(unsigned int height, unsigned int width,
Image_Type *image)
{
image->height = height;
image->width = width;
image->pixels = (unsigned char*) malloc(sizeof(unsigned char) *
height * width);
return 0;
}


I would like to pass my vhdl functions constants or parameters read
from files at some point during the course of my simulation run.
Good approach.

I'd also suggest also since you're dealing with images that it would be
handy to directly work with .BMP, .TIF, .JPG files, whatever native image
file format is convenient for your project. Just code up some VHDL to
read/write these types of files directly. Once you've got that down, it
will be a snap to integrate that all in with the rest of your testbench.

I want to be able to do this so I can handle images of various sizes
without knowing the size ahead of time.
This would prevent the need for hard coded images sizes (need a new
type for each different image size).

Can anyone tell me how to do this in VHDL?
You need to use the 'new' keyword. It is similar to 'malloc' in C or 'new'
in C++ i.e.

Image_Type_variable := new Image_Type.

You can allocate an array of your type with

Image_Type_variable := new Image_Type(Number_Of_Things);

This will come in handy for allocating the chunk of memory that you'll need
for your image as an array of pixels.

You deallocate the memory using the deallocate function i.e.
deallocate(Image_Type_variable);

Also how to prevent memory leaks?

Make sure that every call to 'new' eventually results in a call to
'deallocate'. There is no magic that will help you out here, it's more like
C in this regard where every 'malloc' needs a 'free'.

Experiment with it a bit and google if needed but it's pretty
straightforward.

Kevin Jennings
 
I've already got the image opening procedures built.
I just use pgm and ppm images since they are just text based files, no
complex
headers or compression schemes to deal with...

Is there a way to use shared variable or something along these lines
to be able to access my dynamically allocated memory
in multiple processes or procedures.

Also, can the various elements of allocated data types
be accessed with standard array(index) notation?

For instance in the Image_Type_variable := new
Image_Type(Number_Of_Things);
declaration, can i write:
Image_Type(5)
to assign or access that particular array value?

or if I am using a for-loop:

Image_Type(i) := some_value;

to assign to that array value?

On Feb 16, 4:22 pm, "KJ" <kkjenni...@sbcglobal.net> wrote:
"wallge" <wal...@gmail.com> wrote in message

news:1171652317.265672.70270@a75g2000cwd.googlegroups.com...



Say I to implement the following C language constructs in my VHDL
testbench:
I want to have a generic image struct:

typedef struct {
unsigned int height;
unsigned int width;
unsigned char *pixels;
} Image_Type;

I think something like this can be done with a VHDL record type.

Then initialize it with the following function:

int init_image_struct(unsigned int height, unsigned int width,
Image_Type *image)
{
image->height = height;
image->width = width;
image->pixels = (unsigned char*) malloc(sizeof(unsigned char) *
height * width);
return 0;
}

I would like to pass my vhdl functions constants or parameters read
from files at some point during the course of my simulation run.

Good approach.

I'd also suggest also since you're dealing with images that it would be
handy to directly work with .BMP, .TIF, .JPG files, whatever native image
file format is convenient for your project. Just code up some VHDL to
read/write these types of files directly. Once you've got that down, it
will be a snap to integrate that all in with the rest of your testbench.



I want to be able to do this so I can handle images of various sizes
without knowing the size ahead of time.
This would prevent the need for hard coded images sizes (need a new
type for each different image size).

Can anyone tell me how to do this in VHDL?

You need to use the 'new' keyword. It is similar to 'malloc' in C or 'new'
in C++ i.e.

Image_Type_variable := new Image_Type.

You can allocate an array of your type with

Image_Type_variable := new Image_Type(Number_Of_Things);

This will come in handy for allocating the chunk of memory that you'll need
for your image as an array of pixels.

You deallocate the memory using the deallocate function i.e.
deallocate(Image_Type_variable);



Also how to prevent memory leaks?

Make sure that every call to 'new' eventually results in a call to
'deallocate'. There is no magic that will help you out here, it's more like
C in this regard where every 'malloc' needs a 'free'.

Experiment with it a bit and google if needed but it's pretty
straightforward.

Kevin Jennings
 
"wallge" <wallge@gmail.com> wrote in message
news:1171664692.895430.79180@j27g2000cwj.googlegroups.com...
Is there a way to use shared variable or something along these lines
to be able to access my dynamically allocated memory
in multiple processes or procedures.
Like any other variable, a pointer can be a shared variable.

One detail I left out of the first post is the definition of the pointer
type and might have been confusing about which were pointers and which were
not.

If you have type 'Image_Type' (presumably a record type along the lines of
your C 'struct') then you define yet another type which is a pointer to
something of that type
type ptr_Image_Type is access Image_Type;

Now you would declare a variable (shared if you'd prefer) of that pointer
type
variable A_ptr_Image_Type_variable: ptr_Image_Type;

and then you would get a new thing of that type with the 'new' statement
like...
A_ptr_Image_Type_variable := new Image_Type;

The assignment could also have combined with the declaration like this...
variable A_ptr_Image_Type_variable: ptr_Image_Type := new Image_Type;

Then access elements of that record like this...

A_ptr_Image_Type_variable.element1 := 123;

and lastly deallocate it and free memory with
deallocate(A_ptr_Image_Type_variable);

Also, can the various elements of allocated data types
be accessed with standard array(index) notation?

Yes

For instance in the Image_Type_variable := new
Image_Type(Number_Of_Things);
declaration, can i write:
Image_Type(5)
to assign or access that particular array value?

Yes.

or if I am using a for-loop:

Image_Type(i) := some_value;

to assign to that array value?
Yes.

The notation when accessing the variable is identical whether the
'Image_Type' variable is a pointer or a plain old fixed type that you're
used to. It's different than C in that regard in that with C the notation
you use is different based on whether the variable is a pointer or not.

Kevin Jennings
 
I guess what I would like is a type that Would not have to be
initialized
before compile time.

Does the following code work?
if not, why not?


--architecture of our testbench
architecture behavior of testbench is

--component I/O
signal data_in, data_out : std_logic_vector(7 downto 0);
signal counter : natural;

-- Images read in from file
signal height, width : natural;

-- test bench start switch,
--so we only read data from file once at start of sim
signal init : boolean := false;

type pixel is natural range 0 to 255;
type pixel_ptr is access pixel;

-- this should be a global variable accessible by any process
shared variable Image : pixel_ptr;


begin

init_ptrs : process(init)
if init = false then
--get image dimensions from file
height <= get_image_height("image.pgm");
width <= get_image_width("image.pgm");
--allocate memory
Image := new pixel_ptr(height * width);
-- get pixel data from file, and put into pointer
get_image_pixels("image.pgm", Image);
init <= true;
end if;
end process;

-- access our pixels in a clocked process...
access_pix : process(clk, rst, data_in, counter
if rst = '1' then
counter <= 0;
data_in <= (others => '0');
elsif rising_edge(clk) then
data_in <= std_logic_vector(to_unsigned(Image(counter),
data_in'length));
counter <= counter + 1;
end if;
end process;


---rest of test bench occurs below...
uut : some_component
port map
(
rst => rst,
clk => clk,
data_in => data_in,
data_out => data_out
);

end architecture;




On Feb 16, 9:12 pm, "KJ" <kkjenni...@sbcglobal.net> wrote:
"wallge" <wal...@gmail.com> wrote in message

news:1171664692.895430.79180@j27g2000cwj.googlegroups.com...> Is there a way to use shared variable or something along these lines
to be able to access my dynamically allocated memory
in multiple processes or procedures.

Like any other variable, a pointer can be a shared variable.

One detail I left out of the first post is the definition of the pointer
type and might have been confusing about which were pointers and which were
not.

If you have type 'Image_Type' (presumably a record type along the lines of
your C 'struct') then you define yet another type which is a pointer to
something of that type
type ptr_Image_Type is access Image_Type;

Now you would declare a variable (shared if you'd prefer) of that pointer
type
variable A_ptr_Image_Type_variable: ptr_Image_Type;

and then you would get a new thing of that type with the 'new' statement
like...
A_ptr_Image_Type_variable := new Image_Type;

The assignment could also have combined with the declaration like this...
variable A_ptr_Image_Type_variable: ptr_Image_Type := new Image_Type;

Then access elements of that record like this...

A_ptr_Image_Type_variable.element1 := 123;

and lastly deallocate it and free memory with
deallocate(A_ptr_Image_Type_variable);



Also, can the various elements of allocated data types
be accessed with standard array(index) notation?

Yes

For instance in the Image_Type_variable := new
Image_Type(Number_Of_Things);
declaration, can i write:
Image_Type(5)
to assign or access that particular array value?

Yes.

or if I am using a for-loop:

Image_Type(i) := some_value;

to assign to that array value?

Yes.

The notation when accessing the variable is identical whether the
'Image_Type' variable is a pointer or a plain old fixed type that you're
used to. It's different than C in that regard in that with C the notation
you use is different based on whether the variable is a pointer or not.

Kevin Jennings
 

Welcome to EDABoard.com

Sponsor

Back
Top