[sv-bc] DataTypes: Background on primary issues

From: Kathy McKinley (mckinley@cadence.com)
Date: Wed Oct 27 2004 - 18:57:14 PDT

  • Next message: Kathy McKinley: "[sv-bc] DataTypes: Complex Data Types of Wires"

    Hello,

    I have appended a brief write-up that served as the basis for
    a slide presentation at the October p1800 meeting. This presentation
    covered justification for extending SystemVerilog to allow new
    datatypes on nets, as well as an overview of possible issues.
    It is my understanding that the slides themselves (which are a
    subset of this information) are available as a part of the meeting
    minutes.

    Kathy

    ---------------------------------------------------------------------

    SystemVerilog extended Verilog by adding powerful new datatypes and
    operators that can be used to declare and manipulate parameters and
    variables. Extensions like packed structs provide a very convenient
    abstraction for manipulating an object that is really just a bit vector.

    SystemVerilog did not extend these new datatypes to nets. However,
    with the addition of continuous assignments to variables, hardware
    designers can use the extended datatypes with variables to model
    many common network behaviors. Users would like to have these
    convenient abstractions for nets too, because other common network
    behaviors -- bidirectionality, multiple driver resolution, and delays
    -- cannot be modeled with variables.

    The IEEE 1364 working group endorsed the concept of datatype
    orthogonality as the way to extend SystemVerilog datatypes to nets.
    Orthogonality is a fundamental principle of good language design.
    Datatype orthogonality means that the rules for how an object is updated
    are independent from the set of values that the object can have.

    In most respects, extending SystemVerilog to allow new datatypes on
    nets is very straightforward. The LRM might need to talk about datatypes
    a little differently, and the net and port declaration syntax needs
    extension, but the right thing to do is obvious and such changes
    would not impact existing SystemVerilog designs.

    However, there appears to be a small number of areas where the "right"
    answer is not obvious. Clarifications, restrictions, or perhaps even
    minor changes might be required. A special datatypes subgroup of the
    behavioral task force was formed to identify and propose resolutions
    for such issues.

    The datatypes group adopted the classical programming language view
    of a datatype as a set of values and corresponding operations.
    The following issues were identified as needing exploration and
    resolution:

        - What are the semantics of nets and ports declared as two-state?
          How are multiple drivers handled? How are mixed 2-state and 4-state
          connections handled?

        - How do you use new datatypes to declare ports? When is a port
          declaration a variable, and when is it a net?

        - What are the semantics and issues when ports using new datatypes
          are connected to Verilog 2001 style ports?

    The following discussion explores the idea of datatype orthogonality
    in a little more detail, and then covers major aspects of the three
    issues listed above.

    -------------------
    WHAT IS A DATATYPE?
    -------------------

    You can look at Verilog data objects as having two different
    attributes.

    One is the "kind" of the object (i.e., variable vs. parameter
    vs. net) and the other is the "datatype" of the object (integer
    vs. real vs. scalar bit, etc).

    Roughly, the object kind indicates what you can do with the object.
    Only parameters can be modified with defparam statements,
    only variables can be assigned by procedural assignments,
    only nets have values that are resolved from their drivers, etc.

    Roughly, the datatype of an object indicates the values the object
    can take on. An object of type 'real' can take on the value 3.14,
    an object of a bit vector type can take on the value 4'b0xz1, etc.

    These two attributes of an object are largely orthogonal. As
    examples, a net can be of most any datatype, and a bit vector can
    be the datatype of most any kind of object.

    --------------
    TWO-STATE NETS
    --------------

    Verilog defines a variety of network resolution behaviors to accurately
    model real hardware at different levels of abstraction: RTL, gate level,
    and switch level. Built-in algorithms rely on drivers, strength, net type
    (wire, trireg, etc.), and primitive properties (cmos, tran, etc.)
    to determine the value of a Verilog net at any given time. The user does
    not use language mechanisms to invent network behavior; the behavior is
    built into the language.

    Verilog nets as defined today are inherently four-state, logic-based
    entities. The set of four logic values is not some abstraction like
    an enumeration -- each of these values has a vital role to play in the
    built-in mechanisms that simulate real hardware behavior. X and Z
    values are required for these built-in mechanisms to work as expected.
    The Z value is critical for accurate net resolution, and the X value
    is necessary for correct initialization behavior.

    At the time that the transition from 1364 to P1800 began, the datatypes
    subgroup was moving rapidly towards a consensus on a proposal for how
    to handle two-state nets. Maintaining accurate hardware behavior was
    a paramount consideration. The favored approach was very similar to
    the way that SystemVerilog treats packed structs with mixed two-state
    and four-state members. The next few paragraphs provide an overview
    of such an approach.

    Network resolution is four-state, and the semantics for computing the
    value of a net from its drivers remains unchanged. Declaring a net
    as two-state does not change the way that it is resolved; however,
    it does change the way that the net is read. If a net or port is
    declared to be two-state ("bit", "int", etc.), then when that net is
    read in procedural code, its value is converted to two-state with an
    implicit type cast.

    The procedural contexts (as defined by Verilog 2001 and extended
    by SystemVerilog) are the following constructs:

        initial
        always
        always_comb
        always_ff
        always_latch
        final
        program
        task
        function

    The value of a net that is declared as two state is *not* converted
    in network contexts. Network contexts include continuous assignments
    (including implicit continuous assignments at port connections),
    specify blocks, and primitives. This means that drivers are not
    converted prior to resolution, and so Z values have their intended
    effect.

    Port collapsing may result in two different net declarations referring
    to the same simulated net. Port collapsing is allowed for port connections
    where one declaration is two-state and the other is four-state. Due to
    four-state network resolution, the network value in this case is computed
    correctly, and all network contexts see this four-state value. In procedural
    contexts, port collapsing can result in the same simulated net being read
    as two-state via one declaration and as four-state via another.

    Here is a very simple example that illustrates these concepts:

        module top;
            wire my_net;
            bottom b1 (my_net);
        endmodule

        module bottom ( input wire bit my_port );
            initial $monitor ("my_port = %b, my_net = %b", my_port, top.my_net);
        endmodule

    A wire that is declared as four state, my_net, is connected to a port
    that is declared as two state, my_port. The simulated net has no drivers,
    so its value is Z. The initial statement is a procedural context, so an
    implicit type cast is performed for the display of my_port (because it
    is declared two-state), but not for the hierarchical reference to my_net:

        my_port = 0, my_net = z

    This approach to handling two state in networks offers several advantages:

        1) Accurate hardware behavior is maintained.

        2) The rules are simple.

        3) The approach builds upon the treatment of packed structs and
           unions that contain mixed logic types, providing consistency
           for users.

        4) Mixed two-state/four-state network simulation matches synthesis
           results in "copies", e.g.

           wire logic a,c;
           wire bit b;
           assign a=b;
           assign b=c;

        5) The implementation choice of implicit continuous assignments at
           port connections vs. port collapsing (for performance and capacity)
           does not produce any new visible differences.

    ------------------
    DATATYPES ON PORTS
    ------------------

    If you are going to declare a net with a new datatype, you will want
    to be able to use that datatype for connections to that net throughout
    the design. What does a port declaration for a net with a new datatype
    look like? It might be helpful to consider output, inout, and input ports
    separately.

    Output ports
    ------------

    SystemVerilog extends Verilog output port declarations to allow
    variables declared with the new datatypes, like this:

        output bus_type p;

    An obvious way to make that output port a net rather than a variable
    would be to require a net type in front of the datatype name, like this:

        output wire bus_type p;

    Inout ports
    -----------

    SystemVerilog does not allow an inout port declaration to use a new
    datatype, because it assumes that such a declaration would be a variable,
    and variables cannot model bidirectional behavior.

    There are two obvious possibilities for declaring an inout port
    that is a net. One form would allow an explicit net type:

        inout wire bus_type p;

    A second form would not include a net type, and would assume the default
    net type for the port:

        inout bus_type p;

    Verilog traditionally tries to do what the user wants, without unnecessary
    baggage. It would be fitting to assume that any inout port is a net,
    and to allow both forms of declaration shown above.

    Input ports
    -----------

    SystemVerilog allows you to connect a variable to an input port declaration:

        input bus_type p;

    This connection implies a continuous assignment, thus making any other
    assignments to the variable illegal, including an implied continuous
    assignment from a connection to a lower-level output or inout port.

    An obvious extension to SystemVerilog for datatypes on nets would be
    to allow you to declare an input port with a net type:

        input wire bus_type p;

    The intent implied by the variable continuous assignment rules raises
    an interesting question for input ports, because the intent is not
    fulfilled if this variable is connected to a lower-level port that
    is a net, for example:

        input p;

    In Verilog 2001, an input port is always a net, and it is perfectly legal
    for an input port to have drivers. In fact, an implementation must coerce
    the port to inout or warn you if it does not (drivers are not silently
    ignored). This sort of connection bypasses the strictly input semantic
    that appears to be intended for the port. Inaccurate port direction
    in existing Verilog designs and Verilog netlisting tools is rampant.

    The SystemVerilog input port variable is very close to being a net,
    particularly with the net-style force/release semantics that apply
    to a variable with a continuous assignment. A powerful extension might
    promote this input port to a net, and define more comprehensive rules
    to enforce the intended restrictions on drivers.

    An input port that is a net offers the following advantages:

        1) You can apply timing (SDF) to the port.

        2) Tool providers can implement port collapsing to get performance
           and capacity improvements for a deep hierarchy of connections.

        3) Behavior between new SystemVerilog ports and Verilog 2001 ports
           is closer to what the user expects.

        4) Input ports that are nets are suitable for connection to other
           language domains, like VHDL.

    Given that reference ports are available to pass variables through
    the design hierarchy, how do the benefits of this second form of
    variable connection compare to the benefits of an input port that
    is a net?

    The "net or variable" rule for a port could be very simple. Input and
    inout ports are nets, and the net type in the declaration is optional.
    An output port that is declared with a datatype name is a variable,
    unless the declaration includes an explicit net type.

    The datatypes group had not yet considered all of these possibilities
    for variable/net ports when the transition to p1800 began. This discussion
    is intended to provide a feel for both the options and the scope of
    consideration that might be required to extend the new datatypes to ports
    that are nets.

    --------------------------------
    CONNECTION TO VERILOG 2001 PORTS
    --------------------------------

    SystemVerilog allows variables to be driven by a single continuous
    assignment, like nets. This includes connecting variables to the "sink"
    side of a port (an input port in a module declaration, or an output port
    of a module instantiation). Unlike nets, they are not allowed to have
    multiple drivers, because their behavior would not resemble real hardware
    if they did.

    Some design styles restrict the use of multiple-driver nets. It has been
    suggested that if variables are used for connections, their limitations
    will have the side effect of acting as a design rule check. This is only
    true if a hardware net is represented with a variable everywhere in the
    hierarchy. If some part of the hierarchy (perhaps legacy code or some
    third-party IP) uses a net, then multiple drivers connected to that portion
    of the net will not be caught.

    For example,

        // New design in SystemVerilog
        module top;
          logic mout;
          ...
          mux m1(sel, in0, in1, mout);
        endmodule

        // Legacy Verilog code
        module mux (sel, in0, in1, mout);
          input sel, in0, in1;
          output mout;
          
          bufif0 b0(mout, sel, in0);
          bufif1 b1(mout, sel, in1);
        endmodule

    Inside module mux, mout has two drivers. This is legal because it is
    implicitly a wire. However, the logic variable mout in module top only
    has one driver: the implicit continuous assignment from the output port
    of m1. This is legal also. In the actual hardware, the wire and the
    variable will become the same net, which has two drivers. The limitation
    on variables has not enforced the design rule. This is not surprising,
    since it was not designed for that purpose.

    A new net type for enforcing single driver semantics for a net was
    proposed to the IEEE 1364 working group. The new net type, wone,
    explicitly indicates a desire for a net with only one driver.
    For example, the top-level module can be rewritten as:

        // New design in NC-Verilog
        module top;
          wone logic mout;
          ...
          mux m1(sel, in0, in1, mout);
        endmodule

    Because of port collapsing, the mout nets inside and outside module m1
    will be collapsed into a single wone net. The presence of multiple
    drivers on that net will be detected and produce an error.

    A wone net type could complement the variable continuous assignment
    rules by providing single driver checking for nets.



    This archive was generated by hypermail 2.1.4 : Wed Oct 27 2004 - 18:46:25 PDT and
    sponsored by Boyd Technology, Inc.