Skip to content

Macros

A macro defined with `define is a declaration like any other: navigation, Find Usages and Rename work on it, across files.

Use Example
A macro call, with or without arguments, in any expression or as a statement `WIDTH, `MAX(a, b), `LOG("hi")
Conditional compilation `ifdef WIDTH, `ifndef WIDTH, `elsif WIDTH
Undefining it `undef WIDTH
Inside the body of another macro `define BUS_W (`WIDTH * 2)

A macro call on its own line is a statement or item whether or not it ends with ;: in

`uvm_info("ID", "msg", UVM_LOW)
x = 1;

x = 1; is an assignment to x. A macro used as a type declares the name after it only on the same line (`REG_T(8) r;). Arguments may be empty (`M(, x)) or be code other than an expression, such as a constraint block in `uvm_do_with(req, { addr == 5; }); names inside such an argument are not navigable.

From any of these, Navigate | Declaration or Usages (⌘B / Ctrl+B) opens the `define. If the macro is defined in several places, you choose; a `define in an inactive `ifdef branch is not a definition (see Conditional compilation). Find Usages (⌥F7 / Alt+F7) on a `define lists every use above, and Rename (⇧F6 / Shift+F6) renames the definition and all its uses. The macro’s name is what is renamed; its formal arguments (`define MAX(a, b)) are not part of the name.

A name passed on its own as a macro argument is a use of that name. Go to Declaration works on it, and Find Usages and Rename of the declaration include it:

class my_item extends uvm_sequence_item;
rand bit [7:0] addr;
`uvm_object_utils_begin(my_item) // the class my_item
`uvm_field_int(addr, UVM_ALL_ON) // the property addr
`uvm_object_utils_end
endclass

The macro’s body decides how an argument is used, so the name refers to whatever declaration of it is visible at that point: a class or type, a variable or parameter, a function or task, a module, or a package. The usual lookup applies: a local declaration hides a class of the same name elsewhere in the project, pkg::name names a package member, and a name from a package that is not imported gets the same warning and quick fix as anywhere else. This holds for macro calls inside expressions (x = `CREATE(my_item);) and for nested calls (`A(`B(my_item))). A name that is only part of an argument (`MAX(a + 1, b), `SHOW(h.f), `M(f(1, a))) is resolved like that expression outside a macro.

After a backtick, Code | Code Completion (⌃Space / Ctrl+Space) offers the project’s macros, marked macro and shown with their formal arguments (`WAIT_CYCLES(n)), and the compiler directives (`define, `ifdef, `include, …), marked directive. Ordinary names and keywords are not offered there.

Names match from their start, ignoring case (`la offers LANES). Not inside strings, comments, or after a token-pasting ``.

Quick Documentation (F1 / Ctrl+Q) on a macro use shows its `define with the body (the first 40 lines) and the file it is defined in; hovering with ⌘ (Ctrl) shows the `define line. For a macro defined in several places, there is one entry per definition.

Macros are also listed by Go to Symbol (⌥⌘O / Ctrl+Alt+Shift+N).

  • Predefined macros (`__FILE__, `__LINE__) and macros defined on the tool’s command line (+define+) have no `define to go to.
  • Formal arguments inside a macro body are not navigable.
  • Names declared by the code a macro expands to, such as type_id in my_item::type_id::create, are not navigable (see Known limitations).
  1. Open rtl/top.sv from the sample project. ⌘-click (Ctrl-click) `LANES in the generate loop. rtl/defines.svh opens at `define LANES 2.
  2. In rtl/defines.svh, ⌘-click DEFINES_SVH in `ifndef DEFINES_SVH. You land on the `define DEFINES_SVH line below it.
  3. Put the caret on LANES in `define LANES 2 and press ⌥F7 (Alt+F7): the use in rtl/top.sv is listed.
  4. Press ⇧F6 (Shift+F6) and rename it to LANE_COUNT. The `define and the use in rtl/top.sv both change. Undo afterwards.
  5. In rtl/top.sv, add a line localparam int N = `LA and press ⌃Space (Ctrl+Space). The only match, LANES, is completed. Undo afterwards.
  6. Open uvm/my_pkg.sv, put the caret on my_driver in class my_driver extends and press ⌥F7 (Alt+F7). The use in `uvm_component_utils(my_driver) on the next line is listed.