` include "file.svh"`` replaces the directive with the entire contents of the file, verbatim, at that exact spot. It is not an import and it creates no namespace.
The pasted text compiles in whatever context surrounds the include. Paste order is dependency order: base classes come before derived classes.
// snippet
package net_pkg;
`include "txn_base.svh" // class txn_base: plain fields, no UVM
`include "txn_ext.svh" // class txn_ext extends txn_base: pasted after its base
endpackage
// Compile the package file only. The .svh fragments never compile standalone:
// they exist solely as text pasted into the package.Two files including the same header paste the class inside it twice, which is a duplicate-definition error. The ifndef guard fixes it: the first paste defines a marker, and later pastes skip the body.
// snippet
`ifndef TXN_BASE_SVH // first include: not yet defined, so enter
`define TXN_BASE_SVH // define the marker immediately
class txn_base;
int addr;
int data;
function new();
addr = 0;
data = 0;
endfunction
endclass
`endif // TXN_BASE_SVH // comment the endif: guards nest deeplyDOUBLE-INCLUDE: FAILURE vs GUARD
WITHOUT GUARD WITH GUARD
------------- ----------
driver.svh: `include "txn_base.svh" driver.svh: `include "txn_base.svh"
monitor.svh: `include "txn_base.svh" monitor.svh: `include "txn_base.svh"
│ │
▼ both pasted into package ▼
class txn_base ... <- 1st copy 1st paste: TXN_BASE_SVH undefined
class txn_base ... <- 2nd copy -> define it, paste class body
│ 2nd paste: TXN_BASE_SVH defined
▼ -> body skipped entirely
ERROR: 'txn_base' already declared COMPILES CLEANThe preprocessor finds included files through search directories. Source names only the file, and the build flow supplies the paths.
iverilog -g2012 -I tb/agents/bus_agent -I tb/env -o simv net_pkg.sv tb_top.sv
verilator --binary --timing +incdir+tb/agents/bus_agent +incdir+tb/env --top-module tb_top tb_top.sv.sv files are compilation units: packages and modules. .svh files are include-only fragments that never compile standalone.
Every .svh file gets a guard whose marker mirrors the file path, so same-named files in different agents cannot collide.
One package file per agent includes its .svh fragments in dependency order. Everything else imports the package.
Never ` include` a file that declares a module. Modules belong in separately compiled .sv` files.
One compiled package, used through an import. Inside it, the guarded text of txn_c.svh appears twice, exactly as two ` include`` lines would paste it. The guard skips the second copy, so the package compiles; delete the guard lines and the second copy is a duplicate-class error.
// engine: verilator
package txn_pkg;
// --- first paste of txn_c.svh ---
`ifndef TXN_C_SVH
`define TXN_C_SVH
class txn_c;
int addr;
int data;
function void set(int a, int d); addr = a; data = d; endfunction
function int checksum(); return addr ^ data; endfunction
endclass
`endif // TXN_C_SVH
// --- second paste of the same header: the guard skips it ---
`ifndef TXN_C_SVH
`define TXN_C_SVH
class txn_c;
int addr;
int data;
function void set(int a, int d); addr = a; data = d; endfunction
function int checksum(); return addr ^ data; endfunction
endclass
`endif // TXN_C_SVH
endpackage
module tb_pkg;
import txn_pkg::*;
int errors = 0;
txn_c first_h;
txn_c second_h;
initial begin
first_h = new();
second_h = new();
first_h.set(32'h1000, 32'h00FF);
second_h.set(32'h2000, 32'h000F);
if (first_h.checksum() !== (32'h1000 ^ 32'h00FF)) errors++;
if (second_h.checksum() !== (32'h2000 ^ 32'h000F)) errors++;
if (first_h.addr !== 32'h1000) errors++;
if (second_h.data !== 32'h000F) errors++;
if (errors == 0) $display("PASS: guarded double paste compiled once; package classes store and checksum independently");
else $fatal(1, "FAIL: package class state is wrong");
$finish;
end
endmoduleThe first paste defined the shared marker. The second header saw it already defined and skipped its whole body, so its class never entered the build.
A search-path entry for that directory: -I for Icarus or +incdir+ for Verilator. Source keeps bare file names so the flow supplies the paths.