Re: [sv-bc] Proposal for 216

From: Steven Sharp <sharp@cadence.com>
Date: Tue Nov 09 2004 - 15:45:20 PST

Neil,

Here are my responses to your comments and questions.

> You are proposing to modify the enum built-in methods to clearly specify
> their semantics when they get called in this situation.

Yes. Brad suggested that this would be a good idea. I don't recall whether
he suggested any particular behavior.

In proposing behavior, I considered the possibility that someone might
have a state machine in which the default transition was to the next state
in the sequence. They might want to have these transitions use the same
code that just increments the state. They could do this with either
the next() method, or state_t'(state+1). In both cases, you would want
an unknown state in to produce an unknown state out. So I chose a
definition that would do that, and which seems to make sense in general.

> I don't see anything in your proposal that mentions what happens when one
> of these enumerated variables is used in an expression. In your email you
> were suggesting that they reflect the last assigned value, regardless of
> whether the last assigned value was in-range or not. If this is the intent
> of your proposal I suggest that it be explicitly stated. Having a defined
> behavior is probably better than having it completely undefined.

Yes, that was the intent. I can add text for that. It would be easier to
describe if the LRM admitted that the underlying representation for an enum
is a data object of the enum base type. I think the best place to add text
would be in 3.10.4, since that deals with reading the enum in an expression.
It says:

 "An enum variable or identifier used as part of an expression is
  automatically cast to the base type of the enum declaration (either
  explicitly or using int as the default). An assignment to an enum
  variable from an expression other than the same type shall require
  a cast. Casting to an enum type shall cause a conversion of the
  expression to its base type without checking the validity of the
  value (unless a dynamic cast is used as described in Section 3.15."
  
I could add a sentence to this paragraph that said something like

 "If an enum variable is assigned a value of its base type that is not a
  member of the enumeration, it will have that value when used in an
  expression."

Or

 "An enum variable shall be capable of holding any value of its base type
  if cast in this way."

Or something else? Suggestions are welcome.

> Another objection to the statement you want to delete is the following.
> As it is written, I am unable to use an enumerated variable once it has
> been assigned an out of range value. Instead it should be possible to
> reclaim this variable by explicitly assigning it a valid value for this
> enumerated variable. If this statement is retained it will need to
> be clarified for this case.

Agreed. If assignment to the variable is considered an operation that has
undefined results, that causes this problem.

> There is a statement in the LRM that mentions the legality of using
> an explicit cast to assign an otherwise illegal value to an enumerated
> variable. I wasn't involved in the creation of this portion of the LRM
> but I suspect that it was added in order to allow users to get around the
> type checking in those cases where it is "convenient" to do so. Those
> users that want the strong type checking capability would simply not
> allow such casts to occur in their code.

I suspect that as this gets used more for hardware design, users will find
the type checking inconvenient and want to circumvent it. Verilog users
won't want the hassles of VHDL-like type checking.

If you want to use enums, and continue to use them after parts of the
design have been turned into boolean operations on their bits, or other
lower-level operations, you will want to bypass the type checking (at
least if you want the operations to produce values of enum types, rather
than just take them as inputs).

And even without the casts, unions and packed aggregates would allow
bypasing the type checking anyway.

> To sum up, I agree with your email suggestion of having en enumerated
> variable reflect the last value it was set to, regardless of whther it
> is a legal value or not. Your proposal for errata 216 should be updated to
> state this intention.

Sounds good. I think the text in 3.10.4 indicates that this was desired,
but the sentence at the end of 3.10.3 conflicts with it.

>2. Allowing an "illegal" initial value
>
> A 4-state enumerated variable can be defined such that the all-x state is
> not specified as a legal value.
>
> enum integer {Red,Green,Yellow} streetlight; // defaults to values
{0,1,2}
>
> The intent of the proposal for errata 216 is to initialize all 4-state
> enumerated variables to the all-x state. The reasoning for this is to
> make it harder for designers to unwittingly design their hardware such
> that it works in a simulator but fails when turned into actual devices.
> This is a worthy objective.

I think so :-). After all, the primary purpose of Verilog is to help
designers produce working devices.

> It would be useful in the testbench world to be able to avoid
> initializing 4-state enumerated types to the x-state. One way to
> accomplish this would be to slightly refine the definition of the
> semantics for variable declaration assignments for enumerated variables.
>
> enum integer {Red,Green,Yellow} streetlight=Red; // initialize to Red
>
> The description in 1364 3.2.2 for variable intialization is a bit
> inconsistent. For real and realtime it mentions a "default" initialization,
> but for reg, time and integer it leaves out the word "default".
>
> "The initialization value for reg, time and integer data types shall
> be the unknown value, x. The default initialization value for real
> and realtime variable data types shall be 0.0."
>
> Section 3.2.2 then goes on to say
>
> "If a variable declaration assignment is used, the variable shall take
> this value as if the assignment occurred in a blocking assignment in
> an initial construct."
>
> Based on this, it appears that a variable will first take on the default
> initial value and then be followed by an assignment to the value specified
> in the variable declaration assignment (when one is specified).
>
> Defining the "default initial value" for an enumerated type to be the
> value specified in the enum variable declaration assignment would be
> sufficient to prevent an enumerated variable from being arbitarily
> initialized to an illegal value. When there is no variable declaration
> assignment the defined default value would be used for initialization. When
> there is a variable declaration assignment the value specified in this
> assignment would become the initial value. I believe that this allows
> people to get stronger type checking when they desire it while still
> allowing designers to get 4-state x initialization without having to
> remember to do any extra work.

SystemVerilog already added constraints to variable initializers, which I
believe may cover your concerns. Section 5.4 specifies that setting the
initial value shall occur before any initial or always blocks are started.
There has been some concern about this, particularly the part about not
generating an event, but I believe it is still in place. In this situation,
the value will be that of the initializer before any procedural code can
execute, so it won't see the other value.

This does bring up another issue related to initializing to X. Someone
may be using an old-style combinational always block (not always_comb),
waiting on an enum. If the design goes through a proper reset sequence
and sets the enum to the first enum member, there will not be an event
to cause the combinational block to execute. The value of the enum will
not get propagated through the combinational block. If it is initialized
to X, then when it gets reset to non-X, that event will cause the block
to execute and propagate the value. The Verilog initialization values
really were chosen for good reasons. You may consider this problem to
be solved by the use of always_comb, but it is good for older constructs
to work properly too.

>3. 2-state versus 4-state enum variable initialization
>
> I would like to see consistent rules apply to both.

OK. We don't have consensus on this one. I tend to agree on the basis
of consistency, and because it resolves issue 286 nicely also.

However, I consider getting initialization to X on 4-state much more
important than what decision is made on 2-state.

>4. Iterating
>
> How do the built-in methods treat the default initial value if it is
> not one of the values specified in the enum list?
>
> Do they simply ignore it when iterating through the list of valid values?
> What label would be assigned to it if they are part of the iteration list?

This is specified in the proposal.

> Right now it appears that we are unable to iterate through the list of
> enumerated values for an enumerated variable that is set to an out of
> range value, which could inlcude the default initial value.

You wouldn't necessarily be able to iterate successfully starting with
the default initial value. However, if your iteration starts by setting
the variable to a valid value (presumably the first), it would work fine.
Since writing a loop that doesn't initialize the loop index at the start
would generally be considered poor programming practice, this doesn't seem
like a problem to me.

> Given the current proposal it appears that the example of section 3.10.4.7
> produces an infinite loop.
>
> typedef enum {red,green,blue,yellow} Colors;
> Colors c = c.first;
> forever begin
> $display("%s: %d\n", c.name,c);
> if (c==c.last) break;
> c=c.next; // <-- may sit at the default value
> end

The example would work, because c is initialized to c.first before the
loop starts (well actually, this fragment may be illegal code, depending
on what appears around it or has been left out.)

> I would think that it would be useful to be able to explicitly check
> for the initial value. This would allow a user to differentiate between
> an enum variable that is set to the default initial value versus an enum
> variable that is at an out of range value. Do we need to specify a
> value at the end of the enumeration list of values that expicitly
> specifies the initialization value to do this? (e.g. 'x for a 4-state enum)

If someone wanted to compare an enum against X, they can do so with a
numerical expression as in 3.10.4, and using a case equality compare.
It would also be possible to add a method to check the validity of an
enum value. You can actually do this already by the indirect approach
of comparing enum.name against the null string.

Steven Sharp
sharp@cadence.com
Received on Tue Nov 9 15:45:29 2004

This archive was generated by hypermail 2.1.8 : Tue Nov 09 2004 - 15:45:44 PST