Conditional compilation
SystemVerilog Studio evaluates `ifdef, `ifndef, `elsif, `else and `endif the way a
compiler does, and treats only the active branch as code:
- the code of an inactive branch is greyed out;
- it declares nothing: Go to Declaration, Find Usages, completion, the Structure View and Go to Symbol see only
the active branch, and a
`definein it defines no macro; - it folds like a block (⌘- / Ctrl+-);
- it is not checked for syntax errors or typos, and Reformat Code leaves it as written (the directive lines take the indent of the items around them); Enter in inactive code keeps the indent of the line you are on.
A macro is defined when a `define for it comes earlier in the file, in active code, and no `undef (or
`undefineall) removed it — also in a header it includes, or, for the files a compile file lists, in a file before
it (see below) — or when the
compile file or the settings define it. Directives inside an inactive branch are part of it and have no effect. A comment on
the directive line (`ifdef SIM // gate-level only) stays a comment. An `ifdef without a macro name is
false; a branch without `endif runs to the end of the file.
`ifdef GATE_LEVEL initial $sdf_annotate("top.sdf", u_counter); // greyed out`else initial $display("RTL simulation"); // code`endifBecause only one branch is code, branches that make sense only one at a time — two alternative module or class headers, for example — parse without errors.
The color of inactive code is Inactive code in Settings | Editor | Color Scheme | SystemVerilog.
Defines from a compile file and the settings
Section titled “Defines from a compile file and the settings”Simulators get their macros from the command line or from a compile file (.f). Set yours in Settings |
Languages & Frameworks | SystemVerilog:
| Setting | Meaning |
|---|---|
Evaluate `ifdef / `ifndef |
On by default. Off: every branch is code, nothing is greyed out. |
| Compile file (.f) | Its defines (+define+NAME[=value], -D NAME, -DNAME, -define NAME, …, minus +undefine+/-U) apply to the files it covers: the files it lists (also in nested -f/-F files and as -v library files) and the files under its +incdir+/-I and -y/+libdir+ directories. A local path; a relative one starts at the project directory. If you rename or move the file, it stays selected. |
| When empty, use the project’s only .f file | On by default: with the field empty, a project with exactly one .f file uses it (the choice is not written to the settings). Off: no compile file. |
| Working directory | Where the relative paths in the .f start (as when you run the simulator). Empty: the directory of the .f. |
| Extra defines | One per line, NAME or NAME=value. They apply to every file. |
Below the fields, the page shows what the compile file says: its number of defines and source files, and any
problem (a nested file that cannot be read, an undefined environment variable, a malformed extra define, a missing
working directory, …). Environment variables ($VAR, ${VAR}) in paths are expanded.
Files the compile file does not cover use the macros they define themselves (and the extra defines). The settings
are stored in .idea/systemverilog.xml, so they can be shared through version control. When you apply a change,
or save a change to a compile file, the files are parsed and indexed again with the new defines, in the background;
until that is done, the old defines stay in effect everywhere. If the settings, a compile file or an environment
variable it uses changed while the IDE was closed, the files are indexed again when the project opens; until then, the
defines of the last session stay in effect.
Macros from headers and earlier files
Section titled “Macros from headers and earlier files”As in a simulator, a macro stays defined across files until it is undefined:
- Compile order. Each file the compile file lists starts with the macros defined by the files listed before it
(and by the headers they include). A
`defineindefs.svis seen in the files afterdefs.sv, not in those before it. - Includes. An
`include "file.svh"applies the macros the header defines (or undefines) at that point, following its own`ifdefs — include guards work. The header is looked for next to the including file, then in the working directory, then in the compile file’s+incdir+directories. - Headers. A header you open starts with the macros defined where it is first included.
When you save a file, the files after it are parsed again only if a macro they test (in their own `ifdefs or
in the headers they include) changes — a new `define that no later file tests, or a change that adds or removes
no directive, parses nothing again. A change of a header’s directives parses every file again.
Limitations
Section titled “Limitations”- Only headers that the compile file’s sources include (directly or through other headers) are known: an
`includeof another header defines nothing. An`includeof a macro (`include `FILE) or in angle brackets (`include <file>) is not followed. - Macros from other files take effect when those files are saved. An
`ifdefyou type (not yet saved) on a macro the saved file did not test sees the compile file’s and the settings’ defines until you save. - Changes to the compile file take effect when it is saved.
- Paths in the compile file are matched as written: a different letter case (
RTL/a.svforrtl/a.sv) or a path through a symbolic link does not cover the file.+incdir+.covers every file under the working directory. - Any file with the extension
.fcounts as a compile file for the automatic choice. - The first time a project is opened (for example a fresh clone), files that get macros from other files (or, with the automatic choice, from the compile file) are indexed once without them and then once more with them.
- Rename changes the active branch and the usages; a name in inactive code is text and is not renamed.
- The SystemVerilog 2023 condition expressions (
`ifdef (A && !B)) are not supported: the condition counts as missing, so it is false.
Try it
Section titled “Try it”- Open
rtl/top.svfrom the sample project. - Near the end of the module, the line inside
`ifdef GATE_LEVELis greyed out:GATE_LEVELis not defined. The line in the`elsebranch is ordinary code. - Add the line
`define GATE_LEVELat the top of the file. The$sdf_annotateline becomes code and the$display("RTL simulation")line is greyed out instead. Undo your change afterwards.
With a compile file:
- Open Settings | Languages & Frameworks | SystemVerilog. Compile file (.f) is empty and When empty, use
the project’s only .f file is on, so
sim.fis used: the page sayssim.f (selected automatically): 0 defines, 3 source files. - Open
sim.f, add the line+define+GATE_LEVELand save (⌘S / Ctrl+S). Inrtl/top.sv, the$sdf_annotateline becomes code and the$display("RTL simulation")line is greyed out. Remove the line again. - In the settings, type
GATE_LEVELinto Extra defines and click OK: the same happens, for every file of the project. Clear the field again. - Open
rtl/defines.svh(whichtop.svincludes), add the line`define GATE_LEVELafter`define LANES 2and save: inrtl/top.svthe$sdf_annotateline becomes code again. Remove the line.