• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
    • Interfacing-tools
    • Hardware-verification
      • Gl
      • Esim
      • Vl2014
      • Sv
      • Fgl
      • Vwsim
      • Vl
        • Syntax
          • Vl-module
          • Vl-vardecl
          • Vl-fundecl
          • Vl-interface
          • Vl-design
          • Vl-assign
          • Vl-modinst
          • Vl-gateinst
          • Vl-taskdecl
          • Vl-portdecl
          • Vl-commentmap
          • Vl-dpiimport
          • Vl-ansi-portdecl
          • Vl-package
          • Vl-paramdecl
          • Vl-dpiexport
          • Vl-class
          • Vl-sort-blockitems-aux
          • Vl-plainarglist->exprs
          • Vl-taskdecllist->names
          • Expressions-and-datatypes
            • Vl-atts
            • Vl-expr
              • Vl-expr-p
              • Vl-expr->atts
              • Vl-index
              • Vl-call
              • Vl-exprsign
              • Vl-maybe-expr
              • Vl-stream
              • Vl-expr-case
              • Vl-pattern
                • Vl-patternkey
                  • Vl-patternkey-ambiguity
                    • Vl-patternkey-case
                    • Vl-patternkey-equiv
                    • Vl-patternkey-structmem
                    • Vl-patternkey-p
                    • Vl-patternkey-expr
                    • Vl-patternkey-type
                    • Vl-patternkey-kind
                    • Vl-patternkey-default
                    • Vl-patternkey-fix
                    • Vl-patternkey-count
                  • Vl-assignpat
                  • Vl-pattern->pattype
                  • Make-vl-pattern
                  • Vl-pattern->pat
                  • Vl-pattern->atts
                  • Change-vl-pattern
                  • Vl-keyvallist
                • Vl-literal
                • Vl-binary
                • Vl-expr-update-atts
                • Vl-unary
                • Vl-special
                • Vl-qmark
                • Vl-inside
                • Vl-cast
                • Vl-multiconcat
                • Vl-mintypmax
                • Vl-partselect-expr
                • Vl-bitselect-expr
                • Vl-tagged
                • Vl-concat
                • Vl-expr-equiv
                • Vl-eventexpr
                • Vl-expr-kind
                • Vl-exprlist
                • Vl-maybe-exprlist
                • Vl-expr-fix
                • Vl-expr-count
              • Vl-datatype
              • New-expression-representation
              • Vl-paramargs
              • Vl-evatom
              • Vl-maybe-paramargs
              • Vl-evatomlist
              • Vl-call-namedargs
              • Vl-paramvaluelist
              • Vl-namedparamvaluelist
            • Vl-fundecllist->names
            • Vl-udp
            • Vl-port
            • Vl-genelement
            • Vl-clkdecl
            • Vl-parse-temps
            • Vl-bind
            • Vl-namedarg
            • Vl-exprdist
            • Vl-clkassign
            • Vl-range
            • Vl-propport
            • Vl-typedef
            • Vl-gatedelay
            • Vl-dimension
            • Vl-sequence
            • Vl-clkskew
            • Vl-program
            • Vl-gatestrength
            • Vl-property
            • Vl-config
            • Vl-always
            • Vl-import
            • Vl-repeateventcontrol
            • Vl-timeliteral
            • Vl-initial
            • Vl-eventcontrol
            • Vl-final
            • Vl-udpsymbol-p
            • Vl-maybe-clkskew
            • Vl-function-specialization
            • Vl-alias
            • Vl-maybe-nettypename
            • Vl-maybe-gatedelay
            • Vl-letdecl
            • Vl-direction-p
            • Vl-modelement
            • Vl-maybe-timeprecisiondecl
            • Vl-maybe-scopeid
            • Vl-maybe-gatestrength
            • Vl-maybe-direction
            • Vl-maybe-delayoreventcontrol
            • Vl-gclkdecl
            • Vl-fwdtypedef
            • Vl-maybe-udpsymbol-p
            • Vl-maybe-timeunitdecl
            • Vl-maybe-timeliteral
            • Vl-maybe-parse-temps
            • Vl-maybe-cstrength
            • Vl-arguments
            • Vl-maybe-module
            • Vl-maybe-design
            • Vl-covergroup
            • Vl-udpline
            • Vl-timeunitdecl
            • Vl-genvar
            • Vl-defaultdisable
            • Vl-context1
            • Vl-timeprecisiondecl
            • Vl-sort-blockitems
            • Vl-elabtask
            • Vl-udpedge
            • Vl-delaycontrol
            • Vl-context
            • Vl-ctxelement
            • Vl-ctxelement->loc
            • Vl-modelement->loc
            • Statements
            • Vl-blockitem
            • Vl-vardecllist
            • Vl-interface->ifports
            • Vl-syntaxversion
            • Vl-nettypename-p
            • Vl-module->ifports
            • Vl-lifetime-p
            • Vl-paramdecllist
            • Vl-modelementlist->genelements
            • Vl-importlist
            • Vl-typedeflist
            • Vl-gatetype-p
            • Vl-cstrength-p
            • Vl-port->name
            • Vl-genelement->loc
            • Vl-delayoreventcontrol
            • Vl-udpentry-p
            • Vl-portdecllist
            • Vl-elabtask->loc
            • Property-expressions
            • Vl-taskdecllist
            • Vl-port->loc
            • Vl-fundecllist
            • Vl-sequencelist
            • Vl-propertylist
            • Vl-portlist
            • Vl-dpiimportlist
            • Vl-dpiexportlist
            • Vl-classlist
            • Vl-arguments->args
            • Vl-alwaystype-p
            • Vl-modinstlist
            • Vl-importpart-p
            • Vl-importpart-fix
            • Vl-bindlist
            • Vl-initiallist
            • Vl-genvarlist
            • Vl-gclkdecllist
            • Vl-function-specialization-map
            • Vl-finallist
            • Vl-elabtasklist
            • Vl-defaultdisablelist
            • Vl-clkdecllist
            • Vl-cassertionlist
            • Vl-blockstmt-p
            • Vl-assignlist
            • Vl-assertionlist
            • Vl-alwayslist
            • Vl-aliaslist
            • Vl-udptable
            • Vl-udplist
            • Vl-udpentrylist
            • Vl-propportlist
            • Vl-programlist
            • Vl-packagelist
            • Vl-namedarglist
            • Vl-modulelist
            • Vl-modportlist
            • Vl-modport-portlist
            • Vl-letdecllist
            • Vl-interfacelist
            • Vl-gateinstlist
            • Vl-fwdtypedeflist
            • Vl-covergrouplist
            • Vl-configlist
            • Vl-clkassignlist
            • Vl-blockitemlist
            • Vl-ansi-portdecllist
            • Vl-regularportlist
            • Vl-paramdecllist-list
            • Vl-modelementlist
            • Vl-interfaceportlist
            • Vl-casekey-p
            • Sv::maybe-4veclist
          • Loader
          • Warnings
          • Getting-started
          • Utilities
          • Printer
          • Kit
          • Mlib
          • Transforms
        • X86isa
        • Svl
        • Rtl
      • Software-verification
      • Math
      • Testing-utilities
    • Vl-patternkey
    • Supported-constructs

    Vl-patternkey-ambiguity

    Notes about our handling of vl-patternkeys.

    The keys in assignment patterns can be expressions (which should resolve to array indexes, for array patterns), structure member names, type names, or the special keyword default. Here are some examples:

    '{ 0: a, 1: b, 2: c, default: 0 }    // assign to some array indices, default others...
    '{ foo: 3, bar: 5 }                  // assign to struct members by name (maybe)
    '{ integer: 5, opcode_t: 7 }         // assign to struct members by type (maybe)

    Simple names are particularly ambiguous here. For instance, a name like place might perhaps refer to any of (1) a parameter value to be used as an array index, as in:

    int arr [3:0];
    parameter place = 0;
    assign arr = '{place: 3, default: 0 };

    or (2) a structure member name, as in:

    typedef struct { int place; int value; } slot_t;
    slot_t s = '{ place: 3, value: 4 };

    or (3) the name of some type, as in:

    typedef logic [3:0] place;
    typedef struct { place src; place dest; int data; } msg_t;
    msg_t m = '{ place: 0, data: 0 };

    This ambiguity is problematic in early parts of annotate, such as shadowcheck, where we want to check that, e.g., wires are used declared before they are used. Here, because of type parameters, we might not be able to tell the names of a structure's members until elaboration time. For example, suppose there is no type named place and that, in some module, we are have a type parameter mytype_t and an assignment like:

    mytype_t foo = '{ place: 0, ... }

    In this case, we won't know whether place is the name of a structure field of mytype_t until elaboration provides us with a definition for mytype_t. If mytype_t ends up having a member named place, then it's fine for place not to be declared here. But if it doesn't have such a member, then the only way this makes sense is for place to be the name of some parameter that's being used as an array index, in which case place needs to be declared here.

    Rather than further intertwine shadowcheck and elaborate, our approach is to avoid this ambiguity by require that all simple names used in assignment pattern keys must be either the names of types or structure members. Although NCVerilog doesn't impose this restriction, it appears that our behavior matches that of VCS. For instance, when we submit the following to VCS J-2014.12-SP3-1:

    module foo1 ;
      int arr [3:0];
      parameter place = 0;
      assign arr = '{place: 3, default: 0 };
    endmodule

    we find that it reports the following error:

    Error-[IAP] Illegal assignment pattern
    test.sv, 5
    foo1, "place:3"
      Assignment pattern is illegal due to: Assignment Pattern with named fields
      cannot be assigned to a non-structure target

    Implementation notes, disambiguation strategy

    Upon parsing a vl-patternkey there are four possibilities:

    1. It is the default keyword, which is no problem.
    2. It is unambiguously an index expression, e.g., 3 + 5.
    3. It is unambiguously a built-in type expression, e.g., integer.
    4. It is ambiguously a simple name like foo, which might be a structure member, type name, or parameter name.

    To reduce insanity we are going to assume that any such foo must not be a parameter.

    At parse time, after dealing with default, we try to parse an expression and then (to account for core type names like integer which aren't expressions) fall back to trying to parse a type. If we get anything other than a simple name then it's already unambiguous.

    On the other hand, if we get an expression which is a simple name, then we will immediately convert it to a structmem instead of an expr vl-patternkey. Note that we don't yet know whether it's a structure name or a type name; structmems will need to be further disambiguated before we're sure they aren't types.

    During shadowcheck, we have enough information to tell whether a structmem is actually a type. We can then check for tricky shadowing as per usual. Type disambiguation can then make the final conversion of structmems to types as necessary.

    Later on, in svex conversion: if we encounter a struct pattern, we should probably also explicitly check that any type keys such as foo_t are NOT also the names of structure members. If so, there might be confusion about what we are assigning to. We might want this to be smart enough to handle things like struct mystruct { foo foo; bar bar; }, or maybe those aren't handled by other Verilog tools anyway.