[sv-bc] Re: Fwd: Re: Priority / Unique Errors

From: Clifford E. Cummings <cliffc_at_.....>
Date: Tue Apr 05 2005 - 18:12:34 PDT
Let me bring one more person into the discussion. Arturo Salz - Hi, Arturo!

Steve raises interesting points, which I belive apply to all assertions, 
clocked or immediate (I am hoping for assertion comment from Arturo and Adam).

I believe all the points raised by Steve apply equally to assertions, and I 
think they are just the nature of assertion-based design, one that needs to 
be taught to engineers. Sampled assertions can obviously miss between-clock 
events and multiple calls to the same function leaves us with the last 
function-call values, because assertions evaluate in different regions from 
RTL code.

Steve accuses me (it's okay Steve!) of trivial RTL coding examples, when in 
fact, I discourage many of the problem areas he notes below (and I am 
feeling even better about discouraging their use now   ;-)

**** TO USERS (Matt, Adam) ****

I guess the big question is, do you want to see all the WARNINGS that can 
be produced real-time during each simulation timestep and at time-0, or do 
you want to see the clear ERRORS at the end of each time step after all RTL 
activity has settled for that timestep, even if it means missing ERRORs 
generated and overridden by looped calls to functions, etc?

I would rather see the ERRORs and risk missing some looped and 
repeat-function-called priority and unique errors than risk missing 
important errors buried in a file full of false warnings and an occasional 
important design-fatal warning. These errors were always caught with 
simulations. We were looking for full_case parallel_case equivalent 
constructs that would not generate different hardware when synthesized when 
compared to simulation (the "Evil Twins" problem).

============

- functions - I avoid them in RTL code - they can cause a mismatch between 
pre- and post-synthesis simulations (paper on my web page).
- void functions - used to model combinational logic, generally unique (per 
Matt's 2003 DAC presentation) - there aren't many (if any) useful-reusable 
void-function combinational blocks (Matt noted this)
- for-loops - I avoid them - they tend to infer very inefficient 
synthesized logic
- local variables - I avoid them - they are generally used to mix blocking 
and nonblocking assignments within the same -combinational block - violates 
my Race-Avoidance guideline #5
- for-loop local variable for iterators - generally these are nothing more 
than software loop-controls that do not translate to hardware

priority-case inside a function call called from a loop. Steve is right, I 
will not see a problem if one occurred. I can live with this to avoid 100's 
of useless camouflage-warnings.

I can teach this.

Steve's proposal to generate the warnings iteratively and on the fly within 
the same time step should indeed catch all problems ... along with a myriad 
of non-problems.

Evaluating in the observed region is really very simple. When a case- or 
if-variable changes in one of the RTL regions, an assertion event is 
scheduled in the observed region. When the observed region events are 
activated, we find out if there are any violations. If multiple changes 
occur on a case- or if-variable within a time step, it behaves like 
nonblocking assignments and the last stored event is evaluated, potentially 
missing other error events in the same time step.

I think of priority and unique as assertions. I can live with this. I would 
prefer to live with this. I believe I can describe this clearly in a 
proposal. I believe I can make it very clear in the proposed wording that 
there is potential to miss real errors this way (as Steve has so eloquently 
described).

The question is, what do other users want to see??

I will bow to the will of the team (I may murmur and grumble but I will bow 
to the will of the team!!)

Regards - Cliff

At 05:05 PM 4/5/2005, Steven Sharp wrote:

> >Adam had proposed true clocked sampling like assertions. Thinking about it
> >more, I don't think clocked-only sampling is sufficient.
> >
> >I had proposed to Adam that sampling could be done in the prepone region
> >and evaluated in the observed region. Thinking about it more, I don't think
> >the prepone-sampling is a good idea.
> >
> >I do now support observed region evaluation and reporting of ERRORs for
> >both priority and unique. More details below.
>
>These constructs are not independent assertions, and it does not make sense
>to talk about sampling or evaluating them in specific regions.  They must
>be evaluated when the procedural code executes them.  That is the only
>time that the values they are testing are guaranteed to be available.  It
>makes no sense to talk about "evaluating" them in some other region.  That
>other region has no way of duplicating the conditions for evaluating them.
>It has no way of knowing the values of variables when the case/if was
>executed (other than saving the exact values used, which then loses all
>benefits of postponing the check).
>
>The best that you can do is to have the evaluation leave around an
>indication of whether there was a violation, and wait until the observed
>region to report it.  This could provide filtering if you only look at
>whether the most recent execution was a violation.  However, this doesn't
>work in general either, because the same case/if could be evaluating
>multiple independent outputs.  There is no way to generally determine whether
>two different evaluations are re-evaluations of the same value due to a
>glitch (in which case the first should be discarded), or are evaluations
>of different values (in which case both need to be kept).
>
>
> >Steve Sharp suggested that observed region evaluation would not work in
> >looped logic and sent a good example that I will repeat here.
>
>And this is just the first problem that came to mind.  Consider the
>situation where the case is inside a function, which is called from many
>places.  In the observed region, you no longer know where it was called
>from and with what values.
>
> > He has
> >followed up with more explanation and a 1-always block FSM style below. The
> >FSM style below is not a problem (even though I object to this FSM coding
> >style). In the example that Steve has shown, Steve points out that state is
> >being tested and updated before we get to the observed region. Steve is
> >correct, however, the offending state value was updated on the last clock
> >edge and would have been recognized for the violation at that time. Bottom
> >line, Steve's most recent example would be found by observed region 
> evaluation.
>
>The case statement is not executed in the observed region.  It is executed
>at the posedge clk.  The unique does not say that the condition must be true
>at all times.  It only says that it must be true at the posedge clk.  Before
>that happens, something may change to fix the violation.  Or the case may
>be guarded by a condition that is not true.  If you produce a violation
>after the previous clock, it may be spurious.  In general you cannot know
>whether a case will actually execute or what values it will execute with
>unless you execute all of the code that leads up to it, at the time when it
>is defined to execute.  In other words, evaluating it when it executes.
>
> >The other example that Steve sent to me yesterday does potentially miss the
> >evaluation. Steve's example and explanation (good example, not a stupid
> >example as Steve claims - attaboy Steve!)
>...
> >
> >I think the error might be missed in this example unless the simulator kept
> >all the "priority case (bcd[0]) ... priority case (bcd[1]) ... priority
> >case (bcd[7])" priority case statements for observed region evaluation,
> >which may be reasonable, albeit simulation-inefficient.
>
>How does the simulator know that these evaluations must be regarded as
>independent evaluations, rather than re-evaluations of the same value,
>where all but the last should be ignored?  You can look at the code and
>know this, but you have human intelligence.  We don't have artificial
>intelligence, and the simulator has no understanding of the intent of
>your design.  All it knows is that you executed this case statement
>multiple times in the same time slice.  It also knows it is inside a
>for-loop, but not what the intended reason for putting it inside a loop.
>What rules does a simulator use to decide which violations should be
>kept and which ones should be discarded?
>
>Such rules cannot be written in human terms, but must be decisions that
>can be made by a computer program.  They also cannot be written in terms
>of what logic you expect to be synthesized, unless you want your rules
>to define what logic is synthesized for any given source construct
>(i.e. the rules are the code to implement a synthesis tool).  The simulator
>has no special knowledge of how your synthesis tool will work.
>
>Note that the rules must give an answer for any legal Verilog code, and
>must include situations where a case is inside a task or function called
>from multiple places.  This is not just a matter of inefficiency.  I
>cannot see any rules for how to do this that will work in all situations.
>Even trying to cover the most likely situations will require a hopelessly
>complex specification.  And when tasks/functions are involved, it may
>require knowledge of where the task/function is being called from, which
>tasks/functions don't normally have.
>
>The best suggestion I can make is to provide a mechanism to make the
>result of the procedural evaluation available to the user, so that they
>can use their human understanding to provide a sensible check.  For
>example, allow the user to provide a variable to be set to the result
>of the check.  If they provide a variable, then a violation does not
>produce an error/warning, and just sets the variable instead.  Then
>the variable can be used in an actual assertion that runs in the observed
>region.  Because this is under the control of the designer, they can
>figure out what values to save and what to overwrite.  So for example,
>the for-loop case would need an array of 8 flags to hold the violations
>for the different evaluations:
>
>logic [3:0] bcd [0:7];
>logic [6:0] segs [0:7];
>logic [0:7] not_exhaustive;
>
>always_comb
>    for (int i = 0; i < 8; i++)
>      priority (not_exhaustive[i])
>       case (bcd[i])
>        0: segs = `ZERO;
>        1: segs = `ONE;
>        ...
>        9: segs = `NINE;
>       endcase
>
>assert not_exhaustive == 0; // or whatever assertions look like
>
>This seems rather clumsy.  It also doesn't provide a lot of information
>about the cause of the failure.  For comparison, our simulator output for
>a unique violation will tell you exactly which cases came out true at the
>same time, not just that it happened.
>
> > At the same time, it could be
> >argued that this is already simulation inefficient, because we now have an
> >always_comb sensitive to an array of bcd vectors and that whenever any
> >vector changes, the for-loop must be re-run and test each possible vector
> >within a case statement. Maybe we should just note how this coding style
> >can be very inefficient when simulated with priority (and it already was).
>
>If you want a more efficient example, assume 8 separate always_comb blocks
>that are only sensitive to their own bcd digit, but which call a common
>function to convert bcd to 7-segment encoding.
>
>But again, this is not just a matter of efficiency.  You have a priority
>case which is evaluated multiple times in a slice.  You haven't proposed
>a rule which can distinguish this case from a re-evaluation due to a glitch.
>A programmatic rule is needed that says which violations should be kept
>and which should be discarded.
>
>
> >Aside from Steve's for-loop example above, which could cause simulation
> >inefficiency (it was already inefficient), I still don't see any problems
> >with the procedural-assertion testing style in the observed region.
> >
> >I also believe that observed-region priority and unique evaluation solves
> >all the issues that Adam and I raised above.
>
>In case my point is not clear yet, please define exactly what it means to
>do "priority and unique evaluation" for an if/case embedded inside any
>arbitrary Verilog code.  Then I will give you examples where it will not
>work.  As a starting point, consider the case where the if/case is embedded
>in a function.
>
>I'm afraid you have only considered trivial synthesizable code, with no
>loops, function calls, local temporary variables or side effects.
>
>Steven Sharp
>sharp@cadence.com

----------------------------------------------------
Cliff Cummings - Sunburst Design, Inc.
14314 SW Allen Blvd., PMB 501, Beaverton, OR 97005
Phone: 503-641-8446 / FAX: 503-641-8486
cliffc@sunburst-design.com / www.sunburst-design.com
Expert Verilog, SystemVerilog, Synthesis and Verification Training
Received on Tue Apr 5 18:16:53 2005

This archive was generated by hypermail 2.1.8 : Tue Apr 05 2005 - 18:17:01 PDT