这是初学 SV/UVM 很容易混淆的两个概念。它们都是"引入外部内容",但机制完全不同——include是文本替换,import是引入 package 的符号。
一、`include(预处理,文本替换)
本质
`include是编译预处理指令(注意前面有反引号`),在编译前把指定文件的内容原封不动地复制粘贴到当前位置。
用法
`include "uvm_macros.svh" `include "my_driver.sv"特点
- 纯文本插入,等同于把那个文件的代码手动抄进来
- 处理的是文件
- 常用于包含:宏定义(
`define)、.svh头文件、宏文件(如uvm_macros.svh) - 谁 include,代码就出现在谁那里
二、import(编译语义,引入符号)
本质
import是语言级语句,把某个package(包)里已经编译好的类、类型、函数、变量等符号引入到当前作用域,让你能直接使用。
用法
import uvm_pkg::*; // 引入 uvm_pkg 里的所有符号 import my_pkg::trans; // 只引入 my_pkg 里的 trans 类特点
- 处理的是package(包),不是文件
- 引入的是符号(名字),不是文本
- package 必须先被编译过,import 只是"让这些名字可见"
::*表示引入包里所有公开符号;::具体名表示只引入某一个
三、核心区别对比
| 对比项 | `include | import |
|---|---|---|
| 类别 | 预处理指令(有反引号) | 语言语句 |
| 处理对象 | 文件(内容) | package(符号) |
| 机制 | 文本复制粘贴 | 引入已编译的符号名 |
| 发生时机 | 编译前(预处理) | 编译时(语义解析) |
| 内容会不会重复 | 会(复制多次可能重定义) | 不会(只是引用同一份) |
| 典型用途 | 宏文件、头文件 | 使用 package 里的类/类型/函数 |
| 是否需要 package | 不需要 | 必须有 package |
四、它们的联系(经常一起出现)
在 UVM 里你几乎总能看到这两句配对出现:
import uvm_pkg::*; // 引入 uvm 的所有类、类型 `include "uvm_macros.svh" // 引入 uvm 的宏(如 `uvm_info、`uvm_component_utils)为什么要一起用?
- 类、函数、类型→ 放在package里 → 用
import引入 - 宏(
`define)→不能放进 package(宏是预处理层面的,package 是语义层面的)→ 只能用`include引入
所以:
import uvm_pkg::*;让你能用uvm_component、uvm_test等类`include "uvm_macros.svh"让你能用`uvm_info、`uvm_component_utils等宏
两者互补,缺一不可。
五、典型的 package 组织方式
一个常见做法:在 package 内部用 include 把源文件拼进来,外部再 import 这个 package:
// ---------- my_pkg.sv ---------- package my_pkg; import uvm_pkg::*; `include "uvm_macros.svh" `include "my_trans.sv" // 把类的定义文本包含进包里 `include "my_driver.sv" `include "my_env.sv" endpackage // ---------- tb.sv ---------- module tb; import uvm_pkg::*; `include "uvm_macros.svh" import my_pkg::*; // 引入 my_pkg 里所有类 ... endmodule- 包内部:用
`include把各个类的源码"拼装"进 package - 包外部:用
import引入这个 package 的符号
六、易错点
- 宏不能靠 import 传递:即使你
import了某个 package,那个包里用`define定义的宏在外面也用不了——宏必须靠`include - 重复 include 会重定义:同一个含类定义的文件被 include 两次会报"重复定义",所以头文件常用
`ifndef / `define / `endif保护 - 反引号别漏:
`include前面是反引号`,不是普通引号 - import
::*的可见性:::*是"通配导入",只有真正用到时才解析,不会强制引入所有名字造成冲突
一句话总结
`include是"文本复制",把文件内容粘过来,主要用于宏/头文件;import是"引入符号",把 package 里编译好的类/类型/函数拿来用。UVM 里两者配对使用——import uvm_pkg::*拿类,`include "uvm_macros.svh"拿宏,互补缺一不可。