parallel block inside a function ?

V

very_very_log

Guest
Can somebody tell me why a function cannot include a parallel block ?

eg. why is the following an error ?

function void abc();
fork
join_none
endfunction
 
On Sun, 20 Jan 2008 22:04:38 -0800 (PST), very_very_log
<sgiitnewid@gmail.com> wrote:

Can somebody tell me why a function cannot include a parallel block ?

eg. why is the following an error ?

function void abc();
fork
join_none
endfunction
That's something that will be changed for the upcoming 2008
revision of the SystemVerilog standard. The big idea is that
functions must not block - their execution must happen in
zero simulated time. Clearly, a procedural delay such
as "@(posedge clk)" or "#5" breaks that rule. However,

fork
#5 $display("Happened later");
join_none

does not block the thread that called the function, and
therefore it makes sense for it to be legalized.

In particular, this means that a class will be able to
spawn a thread in its constructor (new).

Meanwhile, work around it some other way - the obvious
choice is to use a task.
--
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.
 
mrfirmware wrote:

I find it unhelpful the current distinction between
tasks and functions. Does anyone appreciate the distinction between
the two? Why?
A function is easier to test and reuse.

-- Mike Treseler
 
On Jan 21, 4:01 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Sun, 20 Jan 2008 22:04:38 -0800 (PST), very_very_log

sgiitne...@gmail.com> wrote:
Can somebody tell me why a function cannot include a parallel block ?

eg. why is the following an error ?

function void abc();
fork
join_none
endfunction

That's something that will be changed for the upcoming 2008
revision of the SystemVerilog standard. The big idea is that
functions must not block - their execution must happen in
zero simulated time. Clearly, a procedural delay such
as "@(posedge clk)" or "#5" breaks that rule. However,

fork
#5 $display("Happened later");
join_none

does not block the thread that called the function, and
therefore it makes sense for it to be legalized.

In particular, this means that a class will be able to
spawn a thread in its constructor (new).

Meanwhile, work around it some other way - the obvious
choice is to use a task.

Is it possible that some day the standard might dispense with the task/
function distinction, combining them into a new notion of a function?
This new function type could block, or not, return a value or void? As
a C programmer, I find it unhelpful the current distinction between
tasks and functions. Does anyone appreciate the distinction between
the two? Why?

Thanks,

- Mark
 
On Jan 21, 10:37 am, Mike Treseler <mike_trese...@comcast.net> wrote:
mrfirmware wrote:
I find it unhelpful the current distinction between
tasks and functions. Does anyone appreciate the distinction between
the two? Why?

A function is easier to test and reuse.

-- Mike Treseler
I'm not sure that point makes the need for two different types of
"calls". I could just as easily say that a function that does not
block is easier to debug that one that does block. If you want to
write something that is easier to debug, simply don't block. If that's
not possible then you have no choice but to debug the more complex
function.

- Mark
 
mrfirmware wrote:

I find it unhelpful the current distinction between
tasks and functions. Does anyone appreciate the distinction between
the two? Why?

A function is easier to test and reuse.

I'm not sure that point makes the need for two different types of
"calls".
Perhaps, but I do appreciate the distinction.

In vhdl I would use an impure function to
to make assignments as side effects
and still get a return value.
I guess it depends on my mood.

Which is easier to read?

mangle(my_count_v);

or

my_count_v := mangle(my_count_v);



And sometimes an automatic/pure function
is needed to recurse.

-- Mike Treseler
 
On Jan 21, 1:20 pm, Mike Treseler <mike_trese...@comcast.net> wrote:
mrfirmware wrote:
I find it unhelpful the current distinction between
tasks and functions. Does anyone appreciate the distinction between
the two? Why?
A function is easier to test and reuse.
I'm not sure that point makes the need for two different types of
"calls".

Perhaps, but I do appreciate the distinction.

In vhdl I would use an impure function to
to make assignments as side effects
and still get a return value.
I guess it depends on my mood.

Which is easier to read?

mangle(my_count_v);

or

my_count_v := mangle(my_count_v);

And sometimes an automatic/pure function
is needed to recurse.
You're asking a programmer, the answer is both. There is no difference
(to me) between foo(in_var, &status); and status = foo(in_var); In
practice, I'd just like to be able to have a function get a semaphore,
do "something", put it back, and return the result of "something". but
I can't since semaphore get can block. So, I have to use a task but it
can't return a value. If it could then the need for a distinction
between a task and function would no longer be needed. My only point.

Regards,

- Mark
 
On Mon, 21 Jan 2008 07:14:56 -0800 (PST),
mrfirmware wrote:

Is it possible that some day the standard might dispense with the task/
function distinction, combining them into a new notion of a function?
SystemVerilog already lifted the traditional Verilog requirements
that a function must return a result, and can have only input
arguments. Consequently, the ONLY notweowrthy distinction is
that functions are guaranteed not to block, and tasks may block.
A task is free to call a function if it wishes, but a function
may not call a task.

If an existing piece of code - a module or a class, perhaps -
publishes a function, it comes with a guarantee that it will
not block. Tasks have no such guarantee. The distinction
is important and useful. The verification language 'e' has
a similar split between regular and "time consuming" methods.

Verilog does not allow a task to return a value, but there are
plenty of things in Verilog that would become very difficult
if that were possible. For example, continuous assignment:

assign some_net = expression;

The expression can contain function calls without difficulty.
Suppose, though, the expression contains a blocking function
(a value-returning task, if such a thing were to be invented).
What is the meaning of it? Value-returning tasks would need
to be outlawed in numerous places: RHS of continuous assignment,
initialisers, ...

This new function type could block, or not, return a value or void? As
a C programmer, I find it unhelpful the current distinction between
tasks and functions.
As a C programmer, your impoverished language (!!!) lacks
timing control of any kind, concurrency (except through appeals
to the operating system), events, value-change detection, and
many other things that are the bread and butter of a
hardware description language. Of course, C is none the
orse for those omissions - but it is a pretty poor effort
at a discrete-event simulation language,
while Verilog makes rather a good job of that.
--
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.
 
On Mon, 21 Jan 2008 12:03:20 -0800 (PST),
mrfirmware <mrfirmware@gmail.com> wrote:

The expression can contain function calls without difficulty.
Suppose, though, the expression contains a blocking function
(a value-returning task, if such a thing were to be invented).
What is the meaning of it? Value-returning tasks would need
to be outlawed in numerous places: RHS of continuous assignment,
initialisers, ...

Fair enough. I guess I should think of the limitation of tasks not
able to return a value as a safety mechanism of the language.
I thought about this a bit more, and I agree that it still
seems a little odd to have the asymmetry that tasks can never
return a value. 'e' time-consuming methods CAN do so, although
the facility is rarely used. But then it occurred to me that
SystemVerilog functions can, in effect, return a value with
a time delay, when used in a procedural context. You can do
blocking intra-assignment delay waiting on an event that is
fired by a thread launched by a function (in SystemVerilog 2008,
when the business of fork...join_none in a function is fixed):

function return_with_delay(args, event e);
fork
delaying_actions;
->e; // trigger the event
join_none
return <some value calculated in zero time>;
endfunction

Now I can use that function thus:

event E;
...
some_variable = @E return_with_delay(args, E);
...

Yeah, I know, the product of a sick mind... sorry.

Well let's not get personal :), anyhow I call "Uncle!".
Sadly the allusion is beyond me... Uncle who?
--
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.
 
"UNCLE" is the safe word for a kids game. When you are westling and
fighting, when the pain get to be too much and you admit defeat you would
call "UNCLE"

"Jonathan Bromley" <jonathan.bromley@MYCOMPANY.com> wrote in message
news:9pu9p3l7481b3k28t3b7afd64vi9pfu0ar@4ax.com...
On Mon, 21 Jan 2008 12:03:20 -0800 (PST),
mrfirmware <mrfirmware@gmail.com> wrote:

The expression can contain function calls without difficulty.
Suppose, though, the expression contains a blocking function
(a value-returning task, if such a thing were to be invented).
What is the meaning of it? Value-returning tasks would need
to be outlawed in numerous places: RHS of continuous assignment,
initialisers, ...

Fair enough. I guess I should think of the limitation of tasks not
able to return a value as a safety mechanism of the language.

I thought about this a bit more, and I agree that it still
seems a little odd to have the asymmetry that tasks can never
return a value. 'e' time-consuming methods CAN do so, although
the facility is rarely used. But then it occurred to me that
SystemVerilog functions can, in effect, return a value with
a time delay, when used in a procedural context. You can do
blocking intra-assignment delay waiting on an event that is
fired by a thread launched by a function (in SystemVerilog 2008,
when the business of fork...join_none in a function is fixed):

function return_with_delay(args, event e);
fork
delaying_actions;
->e; // trigger the event
join_none
return <some value calculated in zero time>;
endfunction

Now I can use that function thus:

event E;
...
some_variable = @E return_with_delay(args, E);
...

Yeah, I know, the product of a sick mind... sorry.

Well let's not get personal :), anyhow I call "Uncle!".

Sadly the allusion is beyond me... Uncle who?
--
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.
 
On Jan 21, 2:28 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Mon, 21 Jan 2008 07:14:56 -0800 (PST),

mrfirmware wrote:
Is it possible that some day the standard might dispense with the task/
function distinction, combining them into a new notion of a function?

SystemVerilog already lifted the traditional Verilog requirements
that a function must return a result, and can have only input
arguments. Consequently, the ONLY notweowrthy distinction is
that functions are guaranteed not to block, and tasks may block.
A task is free to call a function if it wishes, but a function
may not call a task.

If an existing piece of code - a module or a class, perhaps -
publishes a function, it comes with a guarantee that it will
not block. Tasks have no such guarantee. The distinction
is important and useful. The verification language 'e' has
a similar split between regular and "time consuming" methods.

Verilog does not allow a task to return a value, but there are
plenty of things in Verilog that would become very difficult
if that were possible. For example, continuous assignment:

assign some_net = expression;
Excellent concrete example. Well put, I withdraw my complaint.

The expression can contain function calls without difficulty.
Suppose, though, the expression contains a blocking function
(a value-returning task, if such a thing were to be invented).
What is the meaning of it? Value-returning tasks would need
to be outlawed in numerous places: RHS of continuous assignment,
initialisers, ...
Fair enough. I guess I should think of the limitation of tasks not
able to return a value as a safety mechanism of the language.

This new function type could block, or not, return a value or void? As
a C programmer, I find it unhelpful the current distinction between
tasks and functions.

As a C programmer, your impoverished language (!!!) lacks
timing control of any kind, concurrency (except through appeals
to the operating system), events, value-change detection, and
many other things that are the bread and butter of a
hardware description language. Of course, C is none the
orse for those omissions - but it is a pretty poor effort
at a discrete-event simulation language,
while Verilog makes rather a good job of that.
Well let's not get personal :), anyhow I call "Uncle!". Thanks to all
for the replies.

Regards,

- Mark
 
On Jan 21, 12:28 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:

SystemVerilog already lifted the traditional Verilog requirements
that a function must return a result, and can have only input
arguments. Consequently, the ONLY notweowrthy distinction is
that functions are guaranteed not to block, and tasks may block.
A task is free to call a function if it wishes, but a function
may not call a task.
In my view, it is a silly state of affairs. With SV and complex test
code it is often very desired and natural to want to write blocking
calls that return a value from within procedural code (ie do a read
transaction and return the result). It is limiting to link the
attribute of 'do not block' with the attribute of 'can return a
value'. IMHO the simple solution is to allow tasks to return a value.
Then task and function are well defined blocking/noblocking attribute
specifiers and no expressive power is lost. All the same rules where
tasks can be used would be retained, and value returning tasks would
still not be permitted in places like continuous assignments/etc/etc.

As a C programmer, your impoverished language (!!!) lacks
timing control of any kind, concurrency (except through appeals
to the operating system), events, value-change detection, and
many other things that are the bread and butter of a
hardware description language. Of course, C is none the
orse for those omissions - but it is a pretty poor effort
at a discrete-event simulation language,
while Verilog makes rather a good job of that.
That is true, but SV in particular is being focused more on typical
software tasks where things like being able to block and return a
value count. :)

Regards,
Jason
 
On Mon, 21 Jan 2008 15:52:25 -0800 (PST),
jgg <jgunthorpe@gmail.com> wrote:

[tasks can't return a value]
is a silly state of affairs.
As you say, the ability to return a value from a blocking
task would be handy in some specific situations.

However, the extreme pain of creating, maintaining and
remembering all the special-case rules - about where you
can and can't use such a task in an expression - surely
outweigh the minor inconvenience of introducing an
intermediate variable to hold a task's output result(s).

See my earlier post for some of the reasons why it would
be painful to permit tasks to return a value.

Apart from 'e' which I've already mentioned, can
you name any other language that has value-returning
blocking functions?
--
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.
 
On Jan 22, 3:55 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Mon, 21 Jan 2008 15:52:25 -0800 (PST),

jgg <jguntho...@gmail.com> wrote:

[tasks can't return a value]

is a silly state of affairs.

As you say, the ability to return a value from a blocking
task would be handy in some specific situations.

However, the extreme pain of creating, maintaining and
remembering all the special-case rules - about where you
can and can't use such a task in an expression - surely
outweigh the minor inconvenience of introducing an
intermediate variable to hold a task's output result(s).
On Jan 22, 3:55 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Mon, 21 Jan 2008 15:52:25 -0800 (PST),

jgg <jguntho...@gmail.com> wrote:

[tasks can't return a value]

is a silly state of affairs.

As you say, the ability to return a value from a blocking
task would be handy in some specific situations.

However, the extreme pain of creating, maintaining and
remembering all the special-case rules - about where you
can and can't use such a task in an expression - surely
outweigh the minor inconvenience of introducing an
intermediate variable to hold a task's output result(s).
I'll jump in once more, despite my earlier call of "uncle". To remedy
this pain I could imagine yet-another-attribute that would be similar
in some sense to 'const'. Let's call it 'noblock'. When we declare a
mythical new-style function with the attribute noblock the compiler
would enforce this by detecting any sort of blocking statement in said
function or subsequent call-related block and flag it as a compile
time error. E.g.

function automatic noblock int foo(input bit param);

...
bar(5); ... // Line nnn
...

endfunction : foo

Now if the call to bar(5) blocks, or any further call blocks the
compiler would quit with a warning on line nnn. How it would determine
all this, I don't know. I don't know if it's even possible.

This would allow the author to state explicitly, not by convention,
that foo() must not be allowed to block.

Regards,

- Mark
 
On Jan 22, 1:55 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Mon, 21 Jan 2008 15:52:25 -0800 (PST),

jgg <jguntho...@gmail.com> wrote:

However, the extreme pain of creating, maintaining and
remembering all the special-case rules - about where you
can and can't use such a task in an expression - surely
outweigh the minor inconvenience of introducing an
intermediate variable to hold a task's output result(s).
Well, I generally philosophically disagree with this. Verilog is not a
'nanny' language and is already full of various silent pitfalls.
Having a rule that blocking value returning calls can't be used in
certain contexts is useful and at least something the compiler can
perform static checking on.

Missing this feature really messes up the code flow for some more
complex cases ie:

for (int I = 0; I < 10 && (blocking_read(10) & 16) == 0 ||
(blocking_read(5) && 8) == 0; I++) [..]

Becomes much more ugly if you have to use temporaries.

Apart from 'e' which I've already mentioned, can
you name any other language that has value-returning
blocking functions?
I can't think of any other language with a specific blocking/not-
blocking concept, but the notion of function attributes restricting
the allowed call sites is well established in other languages:
1) C++ has 'const' functions that can only call other const functions.
2) C/C++ often have 'pure' functions that are usable for things like
static initializers without a .init construct. Pure functions can also
only call other pure functions to retain their pureness (this is a
compiler extension today)
3) VHDL has pure/impure where impure functions cannot be used in
static initializers and other contexts. Pure functions cannot call
impure functions/etc.
4) Java has this notion of a declared exception list attribute which
prevents functions from being called in certain contexts if the
exception guarantee is violated
5) Many 'co-operative multitasking' environments built in C/C++ have
an implicit notion of sleeping/not-sleeping functions and due to the
lack of language support use automatic tools like covarity or sparse
to validate that non-sleeping functions never call sleeping functions.

etc

As far as special case rules go, blocking/non-blocking is not that
different from the C++/Java notion of const-correctness and is pretty
well understood these days. It isn't like you already don't have to
make the choice - for every routine you code you must decide if
declaring it task or function is the correct thing to do, and the
decision is certainly not driven by if it needs to return a value.

Regards,
Jason
 
On Tue, 22 Jan 2008 11:16:45 -0800 (PST),
jgg <jgunthorpe@gmail.com> wrote:

Missing this feature really messes up the code flow for some more
complex cases ie:

for (int I = 0; I < 10 && (blocking_read(10) & 16) == 0 ||
(blocking_read(5) && 8) == 0; I++) [..]

Becomes much more ugly if you have to use temporaries.
Oh, please. In what order do you think the two functions
will execute? What happens if they have side-effects
that are impacted by the delay? The existing non-
determinism of Verilog messes this horribly.

I agree this *could* be done. But, as I said before,
the pain of *defining* it, and *maintaining* the
definition across future language changes, seems to
me not to be worth the bother.
--
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.
 
On Tue, 22 Jan 2008 11:16:45 -0800 (PST),
jgg <jgunthorpe@gmail.com> wrote: [many things]

As far as special case rules go, blocking/non-blocking is not that
different from the C++/Java notion of const-correctness and is pretty
well understood these days. It isn't like you already don't have to
make the choice - for every routine you code you must decide if
declaring it task or function is the correct thing to do, and the
decision is certainly not driven by if it needs to return a value.
Sorry, I took fright at your scary example and replied before
reading the remainder carefully. I think I accept what
you say. I don't think it'll happen, though; the notion
of an "expression" as a non-time-consuming, value-returning
thing is so pervasive in Verilog that it would be very
disruptive to change. As I've already said ad nauseam,
I don't think the benefits justify the considerable effort.
And there are plenty of things in SV that are in far more
urgent need of repair or structural reinforcement :)
--
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.
 
On Jan 22, 2:08 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Tue, 22 Jan 2008 11:16:45 -0800 (PST),

jgg <jguntho...@gmail.com> wrote: [many things]
As far as special case rules go, blocking/non-blocking is not that
different from the C++/Java notion of const-correctness and is pretty
well understood these days. It isn't like you already don't have to
make the choice - for every routine you code you must decide if
declaring it task or function is the correct thing to do, and the
decision is certainly not driven by if it needs to return a value.

Sorry, I took fright at your scary example and replied before
reading the remainder carefully. I think I accept what
you say. I don't think it'll happen, though; the notion
Heh - thanks, I understand that it would be complicated to define
given some of the other unfortunate things in Verilog, I only wished
to make the point that it can be well defined and considering where
other languages are it is not even an unusual concept.

BTW, I've always assumed that since functions in verilog have side
effects (in terms of blocking assignments to shared variables) that
the order of evaluation when using short circuit operators is already
well defined, just like in almost every other language :) Something
like this is what gives me fright:

foo(bar(1),bar(baz(9)));

Some languages define an order of evaluation for this, others like C++
do not.

Regards,
Jason
 
On Tue, 22 Jan 2008 14:48:09 -0800 (PST),
jgg <jgunthorpe@gmail.com> wrote:

BTW, I've always assumed that since functions in verilog have side
effects (in terms of blocking assignments to shared variables) that
the order of evaluation when using short circuit operators is already
well defined, just like in almost every other language :)
Ah. Two wrong assumptions in one sentence :)

1) Logic operators in Verilog may be, but are not required
to be, short-circuit evaluated. Tools differ.
Consequently, using functions with side-effects in
a (potentially) short-circuitable expression is...
hmmmm.
2) Order of evaluation of things within an expression is
not defined.

Something like this is what gives me fright:

foo(bar(1),bar(baz(9)));

Some languages define an order of evaluation for this,
others like C++ >do not.
Given what you know about Verilog, what would your guess be?
--
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.
 
On Jan 23, 2:13 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:

1) Logic operators in Verilog may be, but are not required
to be, short-circuit evaluated. Tools differ.
Consequently, using functions with side-effects in
a (potentially) short-circuitable expression is...
hmmmm.
Really? Oh what a pain :p I guess I better go and remove the if (foo !
= null && foo.bar()) expressions from my code

Now that you mention it I remember reading about this on DeepChip a
few months ago..

http://www.deepchip.com/items/0466-05.html

Sigh. You know, Verilog is probably the only language that has both &
and && where they are the same for boolean inputs. Even VHDL specifies
short circuit evaluation of and/or/nand/nor in boolean like contexts.

Something like this is what gives me fright:

foo(bar(1),bar(baz(9)));

Some languages define an order of evaluation for this,
others like C++ >do not.

Given what you know about Verilog, what would your guess be?
Oh, definitely unordered.

Regards,
Jason
 

Welcome to EDABoard.com

Sponsor

Back
Top