SV-BC: Issues List - Additional Details


Subject: SV-BC: Issues List - Additional Details
From: Clifford E. Cummings (cliffc@sunburst-design.com)
Date: Mon Jul 08 2002 - 09:16:28 PDT


>Date: Mon, 8 Jul 2002 11:32:40 -0400 (EDT)
>From: Steven Sharp <sharp@cadence.com>
>Reply-To: Steven Sharp <sharp@cadence.com>
>Subject: Issues List - Additional Details
>To: cliffc@sunburst-design.com
>X-Mailer: dtmail 1.3.0 @(#)CDE Version 1.4.6_06 SunOS 5.8 sun4u sparc
>X-Received: By mailgate.Cadence.COM as IAA08077 at Mon Jul 8 08:32:42 2002
>
>Here is the more detailed version of the issues list. I tried sending it
>to you earlier but it bounced.
>
>------------- Begin Forwarded Message -------------
>
>X-MimeOLE: Produced By Microsoft Exchange V6.0.5762.3
>content-class: urn:content-classes:message
>MIME-Version: 1.0
>Subject: Issues List - Additional Details
>Date: Mon, 10 Jun 2002 17:53:25 -0700
>X-MS-Has-Attach:
>X-MS-TNEF-Correlator:
>Thread-Topic: Issues List - Additional Details
>Thread-Index: AcIQ4lV0GDBQBaZuQ96/jdyIrw94eQ==
>From: "Erich Marschner" <erichm@cadence.com>
>To: <vlog-pp@eda.org>
>X-Received: By mailgate2.Cadence.COM as RAA25444 at Mon Jun 10 17:58:45 2002
>Content-Transfer-Encoding: 8bit
>X-MIME-Autoconverted: from quoted-printable to 8bit by server.eda.org id
>g5B0sKEA025959
>
>
>In the System Verilog meeting last Wednesday, the issues list that I
>submitted
>was reviewed, and the items were categorized. Following is the same set of
>issues, with the categories that I understood were assigned to each, and with
>the additional detail we promised to provide.
>
>Most items were identified as basic issues (i.e., for cleanup). I've labeled
>these [Basic].
>
>Some items were specifically noted as documentation issues. I've labeled
>these
>[Basic/Doc], or in one specific case, [Basic/BNF].
>
>Some items having to do with interfaces seemed to be both basic and to
>relate to
>system level design. I've labeled these as [Basic, System].
>
>Any questions about the detailed comments should be addressed to the person
>listed as the source of each issue.
>
>Regards,
>
>Erich
>
>
>-------------------------------------------
>Erich Marschner, Cadence Design Systems
>Senior Architect, Advanced Verification
>Phone: +1 410 750 6995 Email: erichm@cadence.com
>Vmail: +1 410 872 4369 Email: erichm@comcast.net
>
>
>======================================================================
>
>Additional detail for the issues discussed in the System Verilog 3.1 Kickoff
>Meeting
>
>======================================================================
>Section 2 - Issues with Literals (Steve/Cadence) [Basic]
>- width/signedness of an unsized literal without a base specifier?
>- legal constructs within an array or structure literal?
>- legal use of array or structure literals?
>
>a. Is the width of an unsized literal without a base specifier (section
>2.3) one
>bit? This seems to be implied by the wording, but since other unsized
>constants
>must be at least 32 bits, it should be made clearer. This is especially
>important in self-determined contexts. For example, how many bits are
>printed
>by $display("%b",'0)?'
>
>b. Are unsized literals without a base specifier considered to be
>unsigned? The
>Verilog standard states that based constants are unsigned, while simple
>decimal
>numbers without the size and base are signed. This case doesn't really match
>either. It comes closest to matching the signed case, but the intent was
>probably for them to be unsigned.
>
>c. What is legal inside an array or structure literal (sections 2.7 and
>2.8)?
>Can strings be used inside them? How precisely must the types match? One of
>the examples shows a real literal inside a structure literal being
>assigned to a
>shortreal element of a structure, which implies some implicit type
>conversion.
>And section 7.9 shows examples where the bit widths don't match, again
>implying
>conversions. And yet section 7.9 states that each element must match the
>type
>being initialized. Since the examples don't actually match exactly, it is
>not
>clear what degree of matching is required.
>
>d. Where exactly are array and structure literals legal? They are apparently
>only supposed to be legal on initializers. However, the example in
>section 2.8
>assigns a structure literal to the struct c in an assignment separate from
>the
>declaration of c. Is this just a typo?
>
>e. Since data types can be passed into modules or interfaces, it may not be
>possible to distinguish an array/structure literal from an ordinary
>concatenation until elaboration time. This probably doesn't place too
>much of a
>burden on the implementation. It does either delay error checking until
>elaboration, or require duplication of error checking so that errors can be
>produced as early as possible.
>
>
>======================================================================
>Section 3 - Issues with new data types and keywords (Steve/Cadence) [Basic]
>- actual utility of char, shortint, longint, byte, shortreal
>- non-orthogonality of definitions
>- inconsistent with C definitions
>- void type - is it necessary?
>
>The new data types add a lot of new reserved words. From the viewpoint of
>backward compatibility with Verilog, each of these should be carefully
>examined
>for utility to offset the incompatibility introduced.
>
>a. What exactly is the purpose of char? There is no interface to C
>defined, so
>it can't be intended for values produced and consumed only by C. And Verilog
>specifically only handles 8-bit ASCII values, so it can't manipulate char
>values properly itself when they could be 16-bit Unicode. Trying to use them
>with Verilog string literals, string I/O, or in combination with ASCII string
>variables wouldn't work. If it isn't usable, it should be removed.
>
>b. The shortint type has limited utility. There is no interface to C
>defined,
>so it can't be needed to match struct layout at an interface. The 16-bit
>short
>is rarely used in C, and can usually be replaced with a 32-bit int without
>any
>problems. And in the unlikely event that a 16-bit int is really needed,
>it can
>always be declared as a packed array of bit. The utility of shortint does
>not
>appear to justify the addition of a reserved word.
>
>c. The int type seems reasonable as a general purpose 2-state variable,
>similar
>to the Verilog integer. However, one would expect orthogonality between the
>2-state and 4-state types. The int type is exactly 32 bits, while the
>integer
>type is 32 bits or more. The types really should be orthogonal, rather
>than an
>ad hoc collection.
>
>d. The longint type probably has more utility than shortint, since it can't
>always be replaced with an int. However, it doesn't correspond to a commonly
>used C type except with a C compiler that is compiling for 64-bit. The
>need for
>a 64-bit integer type in Verilog is limited, and can be declared as a packed
>array of bit if necessary. It doesn't appear to justify the addition of a
>reserved word.
>
>e. The byte type could be justified by a desire to conveniently declare
>2-state
>strings. However, it does not appear that they can be used for this. String
>literals can be assigned to arrays of char, but not to arrays of
>byte. Nor can
>arrays of byte be used with string I/O or manipulated with Verilog
>operators or
>in combination with other strings, which are packed vectors. This actually
>makes the byte type less useful than an array of bits. And since "byte"
>is more
>likely to be used as an identifier name in existing designs than most of the
>other new types, it creates a more serious backward compatibility issue. The
>limited utility does not appear to justify the addition of a reserved word
>that
>is likely to match existing identifiers.
>
>f. The bit type is needed to support 2-state vectors, though it carries some
>risk of matching identifiers in existing designs.
>
>g. The logic type has issues that will be discussed elsewhere. The name also
>carries some risk of matching existing identifiers.
>
>h. The fact that the unsigned keyword is officially reserved does not really
>avoid backward compatibility issues. I don't know of any implementations
>that
>actually reserve it, so it may appear as an identifier in existing Verilog
>designs. This seems unlikely, and it does add significant utility.
>
>i. The shortreal type adds limited utility. Again, without a direct
>interface
>to C, there is no need to match an exact data type. The real data type
>can be
>used instead. The use of reals in Verilog is rare enough that the
>difference in
>storage space and speed is unlikely to be significant. Also note that most
>floating point operations in C are automatically done in double precision
>regardless of the variable types. This means that an operation done with
>floats in C could get a different answer than an equivalent operation done
>with
>shortreal in SystemVerilog, due to different roundoff errors. So if the
>goal
>is to match C floating point, then it fails.
>
>j. The void type is unnecessary. It was added to C because C only has
>functions, and void allows declaring a subroutine without a return value.
>Verilog already has tasks, so it doesn't need void. There is nothing that
>can
>be done with a void function that cannot already be done with a
>task. There is
>no need to copy this type from C.
>
>======================================================================
>Section 3 - Data packing issue (Kevin/NSC) [Basic]
>- it is impossible to implement "union" from the current LRM description
>- there are many ways to do it which are not compatible
>- encoding of logic types is a factor, and "big-endian" vs. "little-endian"
>- unions should have either all logic or all bit as the base type of all
>elements
>- if packing is defined then 'packed' union syntax is redundant
>- may be desirable to state the packing/alignment explicitly for software
>compatibility
>
>[See email on the reflector archive for details from Kevin.]
>
>======================================================================
>Section 3 - Type use before definition (Steve, Paul/Cadence) [Basic]
>- forces type checking to be post-elaboration
>- cause unnecessary complication of analysis, particularly separate analysis
>- useful only with pointer types
>
>[This has been discussed before - no additional detail is involved.]
>
>======================================================================
>Section 3.1 - Parameterized data types (Stuart/Cadence) [Basic]
>- nice, but difficult to use because they cannot be resolved until
>elaboration
>- (can we improve this to better support separate compilation?)
>
>It's nice to be able to use parameters to specify data types (similar to C++
>class templates), but in Verilog parameters cannot be resolved until
>elaboration. The end result is that for such parameterized modules almost no
>error-checking or code generation can be done until after elaboration.
>This is
>painful for the user (due to very late error checking) and complicates tool
>implementation.
>
>======================================================================
>Section 3.4.1 - Issues with Time data type (Steve/Cadence) [Basic]
>- need to detail the rules for mixed expressions, scaling, etc.
>
>The specification of the time data type (section 3.4.1) is extremely
>unclear.
>The examples are not particularly helpful, since they only involve simple
>time
>literals used as delays. There is no specification of what happens when a
>time
>literal is assigned to a time variable, or an integer or real value is
>assigned
>to a time variable, or a time value is assigned to an integer or real
>variable,
>or time and integer values are combined in an expression. It is so
>unclear that
>it is hard to even formulate a general question, so I will ask about
>examples.
>The answers will help clarify things, but what is really needed is a
>specification of the underlying rules that produce those answers.
>
>a. If I have the following code:
>
> `timescale 1ns/10ps
> time t;
> initial
> begin
> t = 1;
> #(t) $display(t);
> end
>
>What is the numerical value in the variable t? In normal Verilog, a time
>variable is just a 64-bit vector, so it would be 1. But the specification
>seems
>to indicate that a time variable is this new time data type, so it needs
>to be
>scaled. I would guess that this means multiplication by the ratio between
>the
>time unit and the time precision, or 100. Does this mean that t gets the
>scaled
>value of 100? What if some other module has a precision of 1ps, so that the
>overall time step for the simulation is 1ps? Does t still get 100 based on
>the
>local precision, or 1000 based on the smallest precision? What is the delay
>produced by the #(t)?
>
>b. If I have the following code:
>
> `timescale 1ns/10ps
> time t;
> initial
> begin
> t = 1ns;
> #(t) $display(t);
> end
>
>what is the numerical value in the variable t? Presumably it is 100,
>since that
>is the multiple of the time step. Again, does this depend on the local
>precision or the overall precision? What is the delay produced by the #(t)?
>One would hope it is 1ns.
>
>c. If I have the following code:
>
> `timescale 1ns/10ps
> integer i;
> initial
> begin
> i = 1ns;
> #(i) $display(i);
> end
>
>Is this legal? If so, what is the numerical value of the integer variable
>i?
>Does this produce a delay of 1ns?
>
>d. If I have the following code:
>
> `timescale 1ns/10ps
> time t;
> initial
> begin
> t = 1ns + 10ps;
> #(t) $display(t);
> #(1ns + 10ps) $display($time);
> end
>
>What is the value of t? Presumably both time literals get scaled and then
>added, so the result is 101.
>
>e. If I have the following code:
>
> `timescale 1ns/10ps
> time t;
> initial
> begin
> t = 1ns + 1;
> #(t) $display(t);
> #(1ns + 1) $display($time);
> end
>
>How are mixed expressions like this handled? Note that an integer expression
>would fully evaluate as an integer and then be scaled for the delay. But
>a time
>literal needs to be scaled to the time unit first, and can't be re-scaled
>again
>later. How and when are these scalings done?
>
>f. If I have the following code:
>
> `timescale 1ns/10ps
> time t1,t2;
> initial
> begin
> t1 = 0.1 + 0.1;
> #(t) $display(t);
> end
>
>What is the value of t? Presumably it is 20, and the #(t) delays by
>200ps. But
>are those answers obtained by adding and then scaling, or scaling and then
>adding? Some further questions will expose differences between those.
>
>g. If I have the following code:
>
> `timescale 1ns/10ps
> time t;
> initial
> begin
> t = 0.004 + 0.004;
> #(t) $display(t);
> end
>
>What is the value of t? Are the two reals scaled and truncated to 0, and
>then
>added to get 0? Or are they added, then scaled and truncated, producing 1?
>
>h. One possible rule is that operands are all scaled and then combined. But
>this doesn't work for all types of operands. For example:
>
> `timescale 1ns/10ps
> time t;
> initial
> begin
> t = 1ns << 1;
> #(t) $display(t);
> end
>
>Clearly scaling the 1 by 100 before the shift is undesirable. Perhaps it
>only
>scales operands that are not self-determined. And what happens if we try to
>shift by 1ns? Is this legal? There are no specifications of where times
>are
>legal.
>
>i. Even scaling only operands that are not self-determined doesn't always
>work
>properly. Whenever dimensional analysis would result in units that are not
>times, this scaling falls apart. For example:
>
> `timescale 1ns/10ps
> time t;
> initial
> begin
> t = 1ns + 1 * 1;
> #(t) $display(t);
> end
>
>What is the value of t here? If both integer literals get scaled, then the
>scaling factor gets multiplied in twice. So apparently scaling needs to wait
>until the integer sub-expression is actually combined with a time (unlike the
>other integer type conversions in Verilog, which are applied to operands
>before
>any operations). But this is not specified anywhere.
>
>======================================================================
>Section 3.6 - Implications of Enum type I/O (Steve/Cadence) [Basic]
>- need to detail what is expected of Verilog I/O routines to support this
>- [also vcd enhancements]
>
>In section 3.6, it is stated that enumerated types can be displayed using the
>enumerated names. Is this supposed to imply some capability of the
>Verilog I/O
>routines? If so, these capabilities need to be defined. If it is just a
>speculation about what the user interface to some tool might allow during
>debugging, then this should be made plain.
>
>======================================================================
>Section 3.7 - Definition of "masked" and "unmasked" (Steve/Cadence)
>[Basic/Doc]
>- apparently not defined?
>
>Section 3.7 refers to structure members as being masked or unmasked. These
>terms do not appear to be defined anywhere, and appear to refer to 4-state
>and
>2-state values. The terminology should be fixed.
>
>======================================================================
>Section 3.7 - Size requirement(?) on members of a packed union
>(Steve/Cadence)
>[Basic/Doc]
>- should say "must be the same size", not "are the same size" (?)
>
>The text in section 3.7 stating that members of a packed union "are" the same
>size should be changed to state that they "must be" the same size, if that is
>the intent.
>
>======================================================================
>Section 3.7 - Passing large structs/arrays (Stuart/Cadence) [Basic, System]
>- can this be done by reference instead of value (which would be inefficient)?
>
>Is there a way to pass large structs or arrays to functions/tasks by
>pointer or
>as const references, rather than by value? If not, this can be extremely
>inefficient for large structs or arrays.
>
>======================================================================
>Section 3.8 - Conversion of shortreals to 32 bits (Steve/Cadence) [Basic/Doc]
>- "bit pattern is preserved" is inconsistent with other conversions
>- should use $realtobits if the intent is to transfer the bit pattern
>
>In section 3.8, it is stated that when a shortreal is converted to 32
>bits, the
>bit pattern is preserved (instead of rounding). This is not consistent
>with the
>rest of Verilog. If a shortreal converts to int by rounding, then it should
>convert to 32 bits by rounding. The int type is equivalent to 32
>bits. Also, a
>real converts to a reg by rounding, so a shortreal should do the
>same. Nothing
>is said about real transferring its bit pattern when converted to bits, just
>shortreal. Since the statement is made in the section on casting, it implies
>that this happens only when casting, and that a conversion on assigning to a
>variable of that type would behave differently. This statement in the
>document
>is a bizarre exception to all related situations. If a real needs its bit
>pattern transferred to a vector, Verilog provides $realtobits for this
>purpose.
>A similar function could be provided for shortreal. Alternately, a union
>of a
>shortreal and a bit vector, or a struct or !
>union containing just a shortreal, could be used for conversion.
>
>======================================================================
>Section 4.2 - Packed array of signed (Erich/Cadence) [Basic]
>- conflict between signed elements and signed whole array
>
>This has been partially addressed in draft 9, but there is still an issue.
>
>Draft 9 says
>
> "If a packed array is declared as signed, then the
> array viewed as a single vector shall be signed.
> A part-select of a packed array shall be unsigned."
>
>But if a part-select of a signed packed array includes the MSB, shouldn't
>that
>part-select be signed? In particular, if the part-select selects all the
>bits
>of a signed packed array, shouldn't it be considered signed, since the
>array as
>a whole is considered signed?
>
>======================================================================
>Section 5.3 Constant expression (Paul/Cadence) [Basic]
>- need to define precisely what can/cannot appear in a constant expression
>
>[This has been discussed before - no additional detail is involved.]
>
>======================================================================
>Section 6.1 Attribute syntax (Paul/Cadence) [Basic/BNF]
>- should factor syntax to improve readability
>
>[This has been discussed before - no additional detail is involved.]
>
>======================================================================
>Section 9 - Process execution efficiency when calling C (Kevin/NSC) [C/C++
>Intf]
>- LRM doesn't say much about calling C from Verilog processes
>- should require that C functions can't suspend
>
>======================================================================
>Section 9.1 - Interleaving of exection (Stuart/Cadence) [Basic]
>- allowing arbitrary interruption is error-prone
>- should only allow interruption at synchronization points
>
>Why allow a thread of execution to be interrupted by another thread
>between any
>statements? Why not only at synchronization points such as wait (#) or
>blocking
>assignments? The current proposal results in a modeling style that is very
>error prone and provides no benefit in terms of performance or functionality
>over only allowing interruption at synchronization points.
>
>======================================================================
>Section 9.1-Related - Verilog 2001 - Scheduling Algorithm (Shalom/Motorola)
>[Basic]
>- allows interleaving of processes that need to be atomic
>- conflicts with requirement that non-blocking assignments execute in
>order of
>appearance
>- potential problem with scheduling of PLI calls
>
>======================================================================
>Section 9.1 - Issues with dynamic processes (Stuart/Cadence) [Basic]
>- need the ability to suspend/resume/abort child processes
>- need process handles to support this
>
>Ability to use dynamic processes seems incomplete without ability to specify
>suspend/resume of child processes, and ability to abort child processes.
>These
>are needed to model pipelines with stalls, operating systems, etc. The
>current
>proposal doesn't seem to have a clean way to return process handles that
>will be
>needed once suspend/resume/abort etc are supported in future.
>
>======================================================================
>Section 13 - Interfaces vs. Modules (Stuart/Cadence) [Basic, System]
>- interfaces and modules are almost the same
>- should make them so and simplify definition
>
>I see no reason why "interfaces" and "modules" aren't exactly the same thing.
>Both can have ports, both can export tasks, both can be parameterized, both
>represent hierarchical structures, both can have "always" blocks and
>processes,
>etc. Making "interfaces" and "modules" be exactly equivalent would go a
>long way
>towards simplifying SystemVerilog.
>
>======================================================================
>Section 13.1 - Interfaces restrictions (Stuart/Cadence) [Basic, System]
>- should allow an interface to contain other modules
>- would allow wrapping of a module with an interface
>
>Why can't an interface contain other modules? This would allow existing
>module
>implementations to be "wrapped" within an interface implementation and then
>instantiated just like any other interface. For example, I might have an RTL
>implementation of a FIFO. I might want to embed this within an interface
>implementation that implements write() and read() tasks.
>
>======================================================================
>Section 13.1 - Scheduling issues (Stuart/Cadence) [Basic, System]
>- interfaces allow non-deterministic behavior due to scheduling order
>- need ability to control scheduling order
>
>Interfaces provide plenty of opportunities for users to create
>non-deterministic
>designs (i.e. designs whose behavior is dependent on the scheduling order
>that a
>particular simulator happens to use.) What are the rules and the capabilities
>that System Verilog will provide to enable users to create interfaces that do
>NOT result in non-deterministic designs? For example: Can the user model the
>equivalent of non-blocking delays & delta cycles within interfaces? Can
>the user
>do the equivalent of signal resolution for multiple processes that
>simultaneously update the state of an interface?
>
>======================================================================
>Section 13.2.3 - Interface usage issues (Stuart/Cadence) [Basic, System]
>- need to be able to specify and enforce rules about interface usage
>- e.g., use of either Read or Write operation but not both
>- e.g., limits on number of modules/processes invoking a given interface
>operation
>- should be possible to define such rules in the interface itself without
>changing other code
>- need to check rules in a way that allows for separate compilation
>- need to be able to specify that some tasks/members of an interface are
>private
>
>"Generic" interfaces allow a module to be attached to different
>interfaces, but
>they do not convey to the reader or allow tools to enforce that the module
>must
>be connected to an interface that implements a specific set of tasks or has
>specific members. As a simple example, there may be several different
>interface
>implementations of a FIFO -- one might gather statistics, another might
>not. In
>both cases modules that might be connected to such FIFOs should have an
>interface declaration that clearly specifies the set of FIFO operations that
>must be supported. E.g. write() but NOT read(), or vice-versa. Given the
>current proposed scheme, it can only be determined at elaboration-time
>whether
>an interface binding in a particular case is legal or not. Instead I
>believe it
>ought to be possible to determine this legality at the time a single
>module or
>interface is compiled.
>
>It should be possible to do port registration checks for interfaces. For
>example, a user might want to implement a FIFO interface that enforces
>that it
>has exactly one module or process that writes to it, and exactly one
>module or
>process that reads from it. It should be possible for the designer to create
>such checks only within the interface, without forcing the code within
>modules
>attached to the interface to be modified.
>
>In SystemVerilog today all tasks and members of an interface are available
>to be
>used by modules attached to the interface. This will inevitably lead to
>designs
>or models that use tasks or members of an interface that were never
>intended to
>be used externally. Therefore I believe that it should be possible to make
>certain tasks and members private so that they cannot be accessed externally.
>
>======================================================================
>Section 13.4 - Modports issues (Stuart/Cadence) [Basic, System]
>- allow modports to be declared outside of interface/module, for reuse
>- allow (modules and) interfaces to specify which modport(s) they implement
>- import/export is confusing and unnecessary
>
>It appears that Modports can only be declared within an interface. Why not
>allow modports to be declared outside of interfaces and modules, so that more
>than one interface implementation can implement the same modport? This
>would be
>a less error-prone solution than "generic interfaces".
>
>The use of "import/export" within Modports is confusing and unnecessary.
>Instead
>I believe that modports should be declared separately from interfaces, and
>the
>tasks that a modport makes available should be declared within the modport.
>Then when an interface is to implement the tasks of a modport, it explicitly
>indicates this via a "implements mod_port_name" construct. Similarly, since I
>believe that modules and interfaces should be equivalent, a module that
>wishes
>to make tasks available to other modules or interfaces will simply specify
>that
>it "implements some_mod_port_name".
>
>Modules and interfaces should be able to implement multiple modports.
>
>======================================================================
>Section 13.5.4 - Issue with extern forkjoin task (Stuart/Cadence) [Basic,
>System]
>- not necessary (at least for the example)
>- unnecessarily inefficient - there are better methods
>
>"Extern forkjoin tasks" capability is highly specialized and unnecessarily
>inefficient. A much better approach to modeling the example within this
>section
>is to have the simple_bus be aware of the address map for the slaves
>attached to
>the bus -- then only the slave responsible for a particular address needs
>to be
>activated for any request. This would allow us to get rid of the "extern
>forkjoin task" construct altogether and have a much more straightforward and
>efficient solution.
>
>
>
>
>------------- End Forwarded Message -------------
>
>
>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, Synthesis and Verification Training



This archive was generated by hypermail 2b28 : Mon Jul 08 2002 - 09:19:20 PDT