From: James A. Markevitch (jam@magic.com)
Date: Thu Sep 21 2000 - 08:19:45 PDT
The point is not that your example was pathological, but that it assumed
a single-threaded programming environment, rather than a multi-threaded one,
which Verilog is.
Your example, using the always blocks, would be a dangerous programming
practice in any multi-threaded environment. And as I indicated in my
earlier email, always blocks are considered to be separate threads.
In any other multi-threaded language, I would do the equivalent of the
following:
always @(posedge clk) begin
reg tmp;
a = ...
b = ...
c = ...
tmp = a & b & c;
cucu = tmp;
end
always @(posedge clk) begin
reg tmp;
tmp = d | e | f;
dudu = tmp;
end
Most multi-threaded environments would *not* make changes to ensure that
the variable "tmp" is race-free. The environment would not be able to know
which variables you want shared between threads and which you don't.
Generally, you need to identify such variables and/or explicitly indicate
a critical region of code (via locks, for example).
A high-quality tool, however, might emit a warning for variables which are
assigned in multiple threads.
Perhaps the standard should include a clear warning to the effect that:
DON'T ASSIGN VARIABLES IN MULTIPLE INITIAL OR ALWAYS BLOCKS UNLESS YOU
HAVE CLEARLY CONSIDERED THE IMPLICATIONS OR RACE CONDITIONS; IF YOU DON'T
NEED TO, DON'T DO IT.
James Markevitch
> I believe I have given an example of a common programming practice which all beh
> avioral Verilog coders will use. No one has ever
> feared to use such a structure. It is forbidden for us to cause such code to be
> "broken".
> It is not a pathological example.
>
> (I think that multi-thread environments of regular programming languages take sp
> ecial precautions,
> such as variable aliasing, to ensure that such problems will not occur.)
>
> Similarly, I can make an example using always constructs and temporary variables
> , which most normal programmers will always assume
> to be problem-free.
>
> always @(posedge clk) begin
> a = ...
> b = ...
> c = ...
> tmp = a & b & c ;
> cucu = tmp ;
> end
>
> always @(posedge clk) begin
> tmp = d | e | f ;
> dudu = tmp ;
> end
>
> (Remember, I am writing behavioral code, not a hardware description, and certain
> ly not intended for synthesis.)
>
> The key intuitive assumption, which I believe it is forbidden for us to break if
> Verilog is to flourish, is that within a given
> procedural block without any delays or event controls, a variable will retain it
> s value from line to line, assuming also that the
> procedural block does not trigger any additional process which can feed back to
> change the value of such a variable.
>
> In the example above, for example, I will assume that "tmp" will retain its valu
> e between its assignment and its usage, because the
> procedural block does not trigger any event which can change its value.
>
> On the other hand, if I have "assign b = func(c) ;", then I cannot assume that b
> will retain its value between its assignment and
> its usage because I have violated the conditions I stated.
>
> Shalom
This archive was generated by hypermail 2.1.4
: Mon Jul 08 2002 - 12:54:13 PDT
and
sponsored by Boyd Technology, Inc.