Skip to content

Unknown members

If you write sq.scal(2.0), where sq is a handle (a variable that refers to a class object, such as sq in square sq;) and the class square has no scal, a simulator rejects it only when it elaborates the design (builds it before running). The Unknown member of a class or struct inspection (a check the IDE runs as you type and shows in the editor) underlines it at once. It marks a name after . that the type does not declare, where the IDE knows every member the type can have. It is on by default, at level Error (change the level under Settings | Editor | Inspections | SystemVerilog).

The steps use the sample project; open it and wait for indexing first.

  1. Open classes/shapes.sv, find sq.scale(2.0); in shapes_demo (⌘F / Ctrl+F) and change it to sq.scal(2.0);.
  2. scal is underlined in red. Hover over it to read the message: 'scal' is not a member of class 'square'; did you mean 'scale'?
  3. Put the caret (the text cursor) on scal, press ⌥Enter (macOS) / Alt+Enter (Windows/Linux) and choose Change to ‘scale’: the line reads sq.scale(2.0); again and the underline is gone. (Or undo with ⌘Z / Ctrl+Z until the line reads sq.scale(2.0); again.)

If nothing is underlined, see Nothing underlined?.

Each row is a one-line excerpt. Rows 1 and 3 misspell a name that exists (scb_chek for scb_check, adr for addr); the others name something the type does not have; the middle column shows what the IDE sees declared.

Code Where the name is declared Reported
cfg.scb_chek = 1; my_cfg cfg;, my_cfg and its base classes declare scb_check 'scb_chek' is not a member of class 'my_cfg'; did you mean 'scb_check'?
cfg.seq_cfg.check_mem_post = 1; seq_cfg_c seq_cfg; in the configuration class 'check_mem_post' is not a member of class 'seq_cfg_c'
op.adr = 1; typedef struct { int addr; int data; } op_t; op_t op; 'adr' is not a field of 'op_t'
s.b = 1; struct { int a; } s; 'b' is not a field of the struct
assign t = u_sub.no_such_sig; sub u_sub (…);, module sub does not declare no_such_sig 'no_such_sig' is not declared in module 'sub'

When the name you typed is one edit away from a member (one character added, removed or changed, or two neighbouring characters swapped), or two edits if your name has five characters or more, the message suggests that member and ⌥Enter / Alt+Enter offers Change to ‘…’, which writes it. If several members are equally close, the class’s own member comes before a base class’s, then the one declared first. Names of three characters or fewer get no suggestion (adr above), and neither does a name no member is that close to (check_mem_post). The distance rule is the same as for undeclared names. Candidates are:

  • for a class, the members of the class and its base classes that this code may use (not a base class’s local member; built-in methods such as randomize included);
  • for a struct, its fields;
  • for an instance, the names its module, interface or program declares.

Members include covergroups declared in a class (w.err_cg.sample(1), where w is a handle to a class that declares the covergroup err_cg) and constraints (item.stop_bit_c.constraint_mode(0), where item is a handle to a class with a constraint stop_bit_c). Built-in class methods are not reported: randomize, srandom, get_randstate, set_randstate, rand_mode, constraint_mode, pre_randomize and post_randomize. (The language rules behind the checks are IEEE 1800-2017 §8.4 for classes and §7.2 for structs.)

A handle typed by a class type parameter is checked, in a subclass, against the class that subclass binds it to. CFG_T below is a placeholder type that each subclass fills in; here my_vseq fills it with my_cfg (a class that declares scb_check, not scb_chek), so the inherited handle cfg is checked against my_cfg:

class base_vseq #(type CFG_T = base_cfg);
CFG_T cfg;
endclass
class my_vseq extends base_vseq #(.CFG_T(my_cfg));
function void f();
cfg.scb_chek = 1; // 'scb_chek' is not a member of class 'my_cfg'
endfunction
endclass

This includes defaults that name another parameter (type RSP = REQ). Inside a parameterized class that passes its own parameter on (class my_drv #(type REQ = item) extends uvm_driver #(REQ)), the handle is not checked: the class may be used with another type.

A name after an instance (for an instance u_sub of a module sub, u_sub.x is reported when sub has no x; also u_arr[0].x and g_subs[1].u_g.x) is checked against the module, interface or program the instance is of (called a unit below; §23.6): its ports, parameters, signals, instances, generate block names, tasks and functions. To avoid false errors, it stays silent when:

  • that unit is defined more than once (two libraries) or not found;
  • the unit itself writes the name (an implicit net, an assertion label), or it is an unnamed generate block’s genblk1;
  • the unit’s inactive `ifdef code, its macro calls or its included files may declare the name (as for undeclared names);
  • a bind anywhere in the project writes the name (a bind adds an instance to the unit, §23.11).

A name is reported only where the IDE sees every member the type can have. The most likely reasons it is not:

Likely cause What to do
A base class is not in the project (for example the UVM library, when the class extends uvm_object) Add the library sources to the project; see Known limitations
A macro or an `include in the class, which the IDE cannot expand or find Check the macro is defined and the file is found; see Macros
The name is in code an `ifdef switches off See Conditional compilation
The inspection is turned off Check Settings (⌘, / Ctrl+Alt+S) | Editor | Inspections | SystemVerilog | Unknown member of a class or struct
Indexing (the IDE scanning your files) is not finished Wait for the progress bar at the bottom right to disappear

If the name is underlined but ⌥Enter / Alt+Enter shows no Change to ‘…’: the caret is not on the underlined name, or no member is close enough to suggest (the message then has no “did you mean”). Put the caret on the name, or correct it by hand.

The full list of cases that are not reported

The chain below is the class and its base classes.

It is not reported when:

  • a class in the chain extends a class the IDE cannot find;
  • a class in the chain has a macro it cannot expand, or an `include in its body;
  • the name is written in an inactive `ifdef branch of a class in the chain, or that branch calls a macro;
  • the name is written in code of a class in the chain that does not parse, or in a macro expansion that does not parse on its own (UVM’s `uvm_field_* macros parse only together with `uvm_object_utils_begin);
  • a struct body has a macro call (`FIELD(x));
  • the handle’s type is a class type parameter that no subclass binds, or binds to a type the IDE cannot find (a generated register block that is not in the checkout);
  • the handle’s type cannot be found;
  • the handle is an array (q.size() is an array method);
  • the handle is a virtual interface;
  • the name follows this. or super.;
  • the name is inside a macro’s arguments, unless every `define of the macro writes that argument as code (`DV_CHECK_EQ(cfg.scb_chek, 1) is checked). Not checked: an argument a definition only stringifies with `"…`", pastes with ``, passes on to another macro or writes only inside an `ifdef; an argument whose first name the body writes itself (the body may declare it: begin cfg_t cfg = …; S end); any argument of a macro whose body has with (a randomize() with scope looks names up in the object first); a call inside another call’s arguments.