multiple task 'instances'

S

Steven Sharp

Guest
Eric Peterson <Eric.R.Peterson@verizon.net> wrote in message news:<pan.2003.07.21.16.48.38.1973@verizon.net>...
I'm trying to use Verilog tasks to make my code more structured, but
am running into a potential limitation - there seems to be no concept
of multiple 'instances' of a task.
Actually, there is a concept of multiple instances of a task: there is
a separate instance of the task in each instance of the module that
declares it (just as there is a separate instance of a reg in each
instance of the module that declares it). But there is not a separate
instance of the task for each place that calls it within a module.
That means that multiple processes in the same module that call the same
task at overlapping times will be sharing the same variables.

If this seems confusing, what I'm
running up against is the way Verilog has only a single copy of all
task-scoped variables - each caller shares those same variables. I'm
looking to have separate ('per-instance') copies of those variables.
Understood.

So my question is, is there a way to have multiple instances of a
task, each with their own independent task variables? Can one have a
vector of tasks? If not, then is there a conventional way to do this,
say keeping external task 'state' in an array (per instance) and pass
that state as an inout variable?
Verilog-2001 adds re-entrant tasks and functions, which allocate a new
copy of each variable whenever execution enters its scope, and deallocate
it when execution exits the scope. These variables are initialized to the
default initialization value (X for most variables) when allocated. Since
there is not guaranteed to be one instance of each variable, these variables
cannot be referenced by hierarchical names, unlike normal task variables.
There are also some other restrictions on what can be done with them.

Re-entrant tasks and functions are declared by putting the word "automatic"
after the keyword "task" or "function" in the declaration. Whether you
can make use of this depends on whether your tools support this particular
Verilog-2001 feature. NC-Verilog and BuildGates support it, and I believe
that VCS supports it by now also.

The "vector of tasks" approach could have been done by using a different
Verilog-2001 feature: the generate-for. However, the standard specifically
made it illegal to put tasks and functions inside generate-for loops, for
no good reason. At any rate, a tool that supports generates is likely to
support re-entrant tasks and functions already.

The most obvious approach to this using Verilog-1995 would be to put the
tasks into a module, and instantiate the module as many times as you
need instances of the task. An array of instances could be used to do
this in one instantiation, like your vector of tasks. Then call the task
using a hierarchical name for the appropriate instance. This is less
convenient than a re-entrant task, especially if the task needs to access
variables in the instantiating module, but even that can be done by using
hierarchical names in the task (probably of the form of
parent_module_name.variable_name, rather than the more usual
parent_instance_name.variable_name, so that it doesn't care about the
instance name of the module using it).
 
Steven,

Thank you for the suggestion - I used the latter one (an array of
instances of modules, which contain tasks), but I must have done something
wrong - it requires me to put a _literal_ number in to index the
particular module instance:

module HasProblems; // much simplified
integer i;

// declare array of Channel modules
Channel channels ['NUM_CHANNELS - 1:0](initializers);

always begin
for (i = 0 ; i < `NUM_CHANNELS ; i = i + 1) begin
channels.rx(buf); // Verilog complains here
end
end
endmodule

module Channel(initializers);
reg rx_state; // this is the per-module variable

task rx;
output [31:0] buf;
begin
...
end
endtask

endmodule

On the line that says 'Verilog complains here' - if I replace 'i' with a
hard-coded number (e.g. 0), all works fine. But the a big reason for the
array was to allow me to put variable array indices in. Am I doing
something wrong here?

The error spit out by NC-Verilog is 'Non-numeric expression in
instance-select.' Seems like an integer would be numeric enough for
me...

Maybe I should consider myself lucky, a few of the Verilog simulators I
tried didn't even support arrays of modules :)

Regards,
Eric




On Mon, 21 Jul 2003 15:36:27 -0700, Steven Sharp wrote:
Eric Peterson <Eric.R.Peterson@verizon.net> wrote in message news:<pan.2003.07.21.16.48.38.1973@verizon.net>...

I'm trying to use Verilog tasks to make my code more structured, but
am running into a potential limitation - there seems to be no concept
of multiple 'instances' of a task.
[ deleted for brevity ]

[ your suggestion I took: ]
The most obvious approach to this using Verilog-1995 would be to put the
tasks into a module, and instantiate the module as many times as you need
instances of the task. An array of instances could be used to do this in
one instantiation, like your vector of tasks. Then call the task using a
hierarchical name for the appropriate instance. This is less convenient
than a re-entrant task, especially if the task needs to access variables in
the instantiating module, but even that can be done by using hierarchical
names in the task (probably of the form of parent_module_name.variable_name,
rather than the more usual parent_instance_name.variable_name, so that it
doesn't care about the instance name of the module using it).
 
Eric Peterson <Eric.R.Peterson@verizon.net> wrote in message news:<pan.2003.07.23.04.39.37.282499@verizon.net>...
Thank you for the suggestion - I used the latter one (an array of
instances of modules, which contain tasks), but I must have done something
wrong - it requires me to put a _literal_ number in to index the
particular module instance:
I'm afraid that is a restriction of arrays of instances. The standard
actually requires an unsized, unbased decimal number. It should allow
any constant expression, and I am working on getting it extended. But
variables cannot be allowed.

Arrays of instances aren't really arrays in the normal sense. Normal
arrays are homogeneous, i.e. all of their elements are the same size
and type. This allows them to be indexed by variables at runtime,
because it isn't important to know which one will be selected since
we still know at compile time what it will look like.

Different instances in an instance "array" are not necessarily
homogeneous. Defparams can customize each one with different parameter
values, resulting in different object sizes in each one. Other kinds
of hierarchical references, or different connections to their ports can
also create internal differences between instances. This gets even
worse in Verilog-2001, since conditional generates can cause the
contents of different instances to be completely different. These
differences make it impractical to wait until runtime to determine
which instance is being referenced.

In most cases, being unable to do this shouldn't affect a design
that needs multiple task instances. A loop can only be used to
call multiple tasks sequentially, with one task returning before
the next one is called. In this situation, there should be no
need for multiple task instances. Multiple task instances are
needed when there are multiple processes executing the task at
the same time, which would interfere with each other by sharing
the same variables. If there is no overlap in execution (as
there isn't with iterations of a loop), a single task should
suffice.

So I am not clear what your situation is, and what you are trying
to do here. I assumed that you really needed multiple task
instances due to overlapping execution. If you just need to have a
task operate on a different state variable in different calls,
you can pass an element of an array of state variables in and out
via an argument of the task. I am guessing that this is the case,
since you chose to use the multiple-instance approach, rather than
the reentrant task solution.

Note that a Verilog-2001 generate-for loop could generate multiple
processes that could call a task at the same time. But in that
case the loop index would be treated as a constant in each instance
of the loop body, and could be used as an index in an array of
instances (assuming the extension to allow any constant expression
as an instance array index).
 

Welcome to EDABoard.com

Sponsor

Back
Top