SystemVerilog的UVM学习(二)

SystemVerilogUVM 中,fpu_envfpu_init_seqfpu_add_seq自定义类,它们并不是直接继承自 UVM 的标准类,而是由你或者你的团队根据验证需求重新定义的类。它们是 验证环境的一部分,负责处理特定的任务。

1. 它们是自定义类,还是继承的?

这些类(如 fpu_envfpu_init_seqfpu_add_seq)通常是 自定义类,并且它们可能会继承自 UVM 的基类(如 uvm_componentuvm_sequence 等)来实现一些标准功能。也就是说,它们是根据需要创建的类,并且可能会选择继承 UVM 标准类,以便利用 UVM 提供的功能和设计模式。

2. fpu_env 类的作用

fpu_env 类代表一个 FPU 加法器的测试环境。它可以继承自 uvm_envuvm_component,用于组织和管理与 FPU 相关的所有验证组件,如 驱动器、监视器代理 等。

  • fpu_env 可能继承自 uvm_env,后者是 UVM 中用于封装环境相关组件的基类。

示例:

class fpu_env extends uvm_env;

    // 子组件:例如 驱动器(driver)、监视器(monitor)等
    fpu_driver driver;
    fpu_monitor monitor;

    // 构造函数
    function new(string name = "fpu_env", uvm_component parent = null);
        super.new(name, parent);
    endfunction

    // build_phase 阶段:实例化子组件
    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        driver = fpu_driver::type_id::create("driver", this);
        monitor = fpu_monitor::type_id::create("monitor", this);
    endfunction
endclass

3. fpu_init_seq 类的作用

fpu_init_seq 类代表一个 初始化序列,它负责为 FPU 加法器配置初始状态(如寄存器设置、输入初始化等)。它通常会继承自 uvm_sequence,这是 UVM 中用于描述 序列 的基类,定义了如何执行一系列的验证操作。

示例:

class fpu_init_seq extends uvm_sequence #(fpu_transaction);

    // 构造函数
    function new(string name = "fpu_init_seq");
        super.new(name);
    endfunction

    // body 阶段:执行初始化步骤
    virtual task body();
        // 模拟初始化步骤,例如设置 FPU 的初始值
        start_item(req);
        req.opcode = `FPU_INIT;
        finish_item(req);
    endtask
endclass

4. fpu_add_seq 类的作用

fpu_add_seq 类代表一个 加法操作序列,它描述了如何执行 FPU 加法器的 加法操作。它可能会继承自 uvm_sequence,用于生成一组输入数据并验证结果。

示例:

class fpu_add_seq extends uvm_sequence #(fpu_transaction);

    // 构造函数
    function new(string name = "fpu_add_seq");
        super.new(name);
    endfunction

    // body 阶段:执行加法操作的步骤
    virtual task body();
        // 模拟加法操作步骤,例如提供两个输入并检查加法结果
        start_item(req);
        req.opcode = `FPU_ADD;
        finish_item(req);
    endtask
endclass

5. 类的组织和职责

  • fpu_env 类:代表整个 FPU 加法器的测试环境,负责 环境的搭建,比如创建驱动器、监视器等组件。
  • fpu_init_seq 类:负责执行 FPU 初始化操作,设置初始状态。
  • fpu_add_seq 类:执行 FPU 加法操作,包括加法输入、结果验证等。

这些类是根据 测试需求验证环境 的设计目标 自己定义的,而不是 UVM 中的标准类。它们可能会继承 UVM 的标准类(如 uvm_envuvm_sequence 等),以便重用 UVM 提供的功能,比如 工厂机制、序列控制、测试阶段管理 等。

6. 如何创建和使用这些类

这些类通过 new 构造函数 创建对象,并在验证环境的 不同阶段(如 build_phaserun_phase 等)中被使用和调度。

  • fpu_add_test 类中,fpu_envfpu_init_seqfpu_add_seq 是作为 子组件 被实例化的。fpu_add_test 会通过 build_phaserun_phase 来管理它们,并确保测试按照预期执行。

7. 总结

  • fpu_envfpu_init_seqfpu_add_seq自定义类,它们的设计是为了完成特定的验证任务,如 环境搭建、初始化、加法操作
  • 这些类可能会继承自 UVM 的标准类(如 uvm_componentuvm_sequence),从而利用 UVM 提供的 验证功能设计模式
  • 通过组合这些类,你可以创建一个 模块化、可扩展的验证环境,用于测试 FPU 加法器 等功能。

UVM 中,fpu_add_test 类继承自 uvm_test 类的关系是通过 extends 关键字 明确指定的。在你提供的代码中,fpu_add_test 类通过 extends uvm_test 表示它继承自 uvm_test

代码中体现的地方:

class fpu_add_test extends uvm_test;

1. extends uvm_test

  • extends 关键字表示 继承,也就是 fpu_add_test 类是从 uvm_test 类派生出来的。
  • 通过继承,fpu_add_test 可以使用 uvm_test 中定义的所有功能和方法,此外,fpu_add_test 还可以 重写 这些方法或添加新的功能来实现 FPU 加法器测试

2. uvm_test 是 UVM 中的一个基类

  • uvm_testUVM 框架中的一个基类,表示一个 验证用例(test case)

  • uvm_test 类继承自 uvm_component,它提供了一个标准化的 测试流程管理,包括:

    • 初始化阶段:设置验证环境。
    • 执行阶段:执行验证步骤(如运行验证序列)。
    • 清理阶段:清理测试后操作。

3. fpu_add_test 的作用

  • fpu_add_test 是一个具体的 测试用例 类,它继承自 uvm_test,并在此基础上添加了 FPU 加法器 的验证逻辑。
  • 通过继承 uvm_testfpu_add_test 可以利用 UVM 提供的结构化流程,例如 阶段(phases)(如 build_phaserun_phase 等)和 组件管理(如创建环境组件、序列等)。

4. 代码结构说明

class fpu_add_test extends uvm_test;
    `uvm_component_utils(fpu_add_test)  // 使用宏注册到UVM工厂中

    fpu_env env;  // FPU 环境
    fpu_init_seq init_seq;  // 初始化序列
    fpu_add_seq add_seq;    // 加法序列

    function new(string name = "fpu_add_test", uvm_component parent = null);
        super.new(name, parent);  // 调用父类构造函数
        `uvm_info("fpu_add_test", "Inside constructor of fpu_add_test", UVM_HIGH)
    endfunction
endclass

5. uvm_test 的继承关系

  • fpu_add_test 通过 extends uvm_test 显式继承了 uvm_test 类,这意味着 fpu_add_testUVM 测试用例,并具备 uvm_test 类提供的所有功能。
  • fpu_add_test 可以在其构造函数、build_phaserun_phase 等方法中实现特定的测试步骤。

6. uvm_test 的功能

  • uvm_test 是一个基类,通常在 UVM 仿真框架 中用于创建具体的验证测试。
  • 你可以在 fpu_add_test 中通过重写 build_phaserun_phase 等方法来执行你的验证工作。

7. 总结

  • fpu_add_test 继承自 uvm_test,通过 extends 关键字 显式指定。
  • fpu_add_test 可以使用 uvm_test 类中的方法和功能,并且可以根据实际需要对这些方法进行 重写
  • 通过继承 uvm_testfpu_add_test 成为一个完整的 UVM 测试用例,具备标准的测试功能和验证流程。

function newSystemVerilog 中用于类的构造函数(constructor)的定义,它在创建类的实例时自动调用,用于初始化类的属性、资源等。通过构造函数,类的对象可以在实例化时获得初始的状态或设置。

1. 构造函数的作用

构造函数 newUVM 中,通常用于初始化 测试类(如 fpu_add_test 的各个组件,确保在测试执行前为这些组件分配必要的资源或状态。它类似于其他编程语言中的构造函数,目的是 初始化类的对象,使其具备正确的初始值和环境。

2. function new 的含义

function new(string name = "fpu_add_test", uvm_component parent = null);
    super.new(name, parent);  // 调用父类构造函数
    `uvm_info("fpu_add_test", "Inside constructor of fpu_add_test", UVM_HIGH)
endfunction

解释:

  • function new() 是类 fpu_add_test构造函数,当你创建 fpu_add_test 的实例时,new 函数会自动被调用
  • string name = "fpu_add_test":这是构造函数的第一个参数,name,表示 fpu_add_test 类的名称。它有一个默认值 "fpu_add_test",如果实例化时没有传入 name 参数,则使用默认值。
  • uvm_component parent = null:这是构造函数的第二个参数,parent,表示当前类的父组件。在 UVM 中,组件通常有层次结构(父组件和子组件),如果没有显式指定父组件,则默认设置为 null

3. super.new(name, parent):调用父类的构造函数

super.new(name, parent);
  • super.new(name, parent):调用父类 uvm_test 的构造函数。这里的 super 关键字表示调用父类的构造函数,确保继承自 uvm_test 的功能得到正确初始化。nameparent 参数会被传递给父类的构造函数。

fpu_add_test 中,通过调用 super.new(name, parent),确保 fpu_add_test 在继承 uvm_test 的同时,能够正确初始化其父类中的属性和功能。

4. uvm_info:输出调试信息

`uvm_info("fpu_add_test", "Inside constructor of fpu_add_test", UVM_HIGH)
  • uvm_info 是一个 UVM 宏,用于在仿真中输出调试信息。

    • "fpu_add_test":这是信息的标识符(Tag),帮助区分不同的消息来源。
    • "Inside constructor of fpu_add_test":消息的内容,表示当前正处于 fpu_add_test 类的构造函数中。
    • UVM_HIGH:是消息的优先级,UVM_HIGH 表示高优先级的调试信息,适用于开发阶段,帮助追踪程序的执行。

5. 形象解释 new 函数的功能

类似现实生活中的 构造过程

可以将 new 函数类比为你在 工厂里生产一台机器 的过程:

  • 当你从工厂拿到机器时,机器已经完成了所有的基本初始化工作,例如电池安装、设置默认参数等。

  • new 函数 就是执行这类初始化工作的工具,确保你获得的对象(例如 fpu_add_test 类的实例)是 准备好的,可以立即开始使用。

    • 它设置了 名字name)。
    • 它确保机器(fpu_add_test)有正确的 父组件(parent 关系,符合设计的层次结构。
    • 它还输出一条调试信息,告诉你这台机器已经准备好了。

测试环境中的作用:

  1. 初始化组件:通过 new 构造函数,fpu_add_test 类会创建其成员变量,如 fpu_envfpu_init_seqfpu_add_seq 等组件,确保这些组件在测试开始前已经正确配置和初始化。
  2. 调试信息:通过 uvm_info 输出的信息,你可以在仿真日志中看到是否成功进入了构造函数,帮助你验证测试环境的初始化是否成功。

6. 总结:

  • function newfpu_add_test 类的 构造函数,它在实例化时被自动调用,负责 初始化对象 并为其设置默认值或执行配置。
  • 通过 super.new(name, parent) 调用父类 uvm_test 的构造函数,确保继承的功能能够正确初始化。
  • uvm_info 输出了一条调试信息,帮助你确认构造函数是否执行。

简而言之,new 构造函数是一个 初始化过程,确保你创建的 fpu_add_test 对象已经具备运行所需的环境和配置,并且能够在仿真过程中正常执行。


env = fpu_env::type_id::create("env", this); 这一行代码的作用和背后的概念。

背景概念:

UVM(Universal Verification Methodology)中,我们通常使用 工厂模式 来创建 组件。通过 工厂方法,你可以动态创建不同类型的 验证组件,并将它们组织成层次化的结构(父子组件关系)。这一点非常适合构建复杂的验证环境,因为它允许你 动态创建 组件,并且通过父子关系来管理它们。

代码分析:

env = fpu_env::type_id::create("env", this);

这一行代码的目的是使用 UVM 工厂方法 来创建一个类型为 fpu_env 的组件,并将该组件命名为 env。创建的组件会作为 fpu_add_test 的子组件。

我们来分解这段代码:

  1. fpu_env::type_id::create("env", this)

    • fpu_env 是一个类,表示 FPU 加法器的测试环境。它可能包含与 FPU 加法器 测试相关的多个组件(如驱动器、监视器、代理等)。

    • type_id 是 UVM 中的一个工厂方法,用来创建 指定类型的组件type_id 是 UVM 中的 类型标识符,它会自动管理组件类型,并支持动态创建实例。

    • create("env", this)

      • "env":这是创建的 组件实例的名称,也就是该 fpu_env 实例的名字。
      • this:表示 当前组件(fpu_add_test 的实例。this 会传递给 fpu_env,让它知道它的父组件是谁。UVM 会根据 父子组件关系,将 fpu_add_test 作为 fpu_env父组件
  2. env =

    • 这部分表示创建的 fpu_env 实例会被赋值给 env,即 fpu_add_test 中的 env 变量。env 是一个类型为 fpu_env 的对象,表示当前测试用例中的 FPU 环境

为什么要使用 type_id::create

UVM 中,工厂模式 被广泛使用。type_id::createUVM 的工厂方法,允许你在仿真过程中动态创建 不同类型的组件。使用工厂模式的好处包括:

  • 类型安全type_id 确保你创建的组件类型是正确的。
  • 动态创建:你不需要在设计时硬编码组件类型,而是可以在运行时根据需要动态创建不同的组件。
  • 统一管理:工厂模式帮助管理组件的实例化、创建、销毁等过程,简化了复杂验证环境的管理。

具体例子:

在这段代码中,fpu_add_test 作为 测试用例,它需要一个 FPU 加法器的测试环境(即 fpu_env)。通过 type_id::create,我们可以动态创建 fpu_env 实例,并将其命名为 envenv 将会成为 fpu_add_test 的子组件,并通过 this 参数建立父子关系。

更形象的类比:

假设你在做一个 FPU 加法器的验证,你需要为测试创建一些 组件,例如:

  • fpu_env:是你的 验证环境,它包含了 FPU 的驱动器、监视器等组件。通过 fpu_env::type_id::create 创建它。
  • fpu_add_test:是整个测试用例,它负责协调和管理 fpu_env,控制测试流程。

类比:想象你有一个 工作场所(fpu_add_test),里面有一个 工作台(fpu_env)。通过 type_id::create,你给工作台命名为 env,并把它放入工作场所。fpu_add_test 负责指挥 工作场所,而 工作台(fpu_env) 负责执行具体的 工作(即测试)。

总结:

  • env = fpu_env::type_id::create("env", this); 通过 UVM 工厂方法 type_id::create 创建了一个 fpu_env 类型的 测试环境 实例,并将其命名为 env
  • this 参数将当前 fpu_add_test 作为父组件传递给 fpu_env,使得 fpu_env 成为 fpu_add_test 的子组件。
  • 通过工厂模式,UVM 提供了动态创建和管理组件的能力,这样你可以更灵活地构建和配置测试环境。

这段代码定义了 run_phase 任务,它是 fpu_add_test 测试用例中的一个重要阶段。run_phaseUVM 测试中的一个阶段,用于执行实际的测试步骤。下面我们逐步分析这段代码的功能。

1. task run_phase(uvm_phase phase);

task run_phase(uvm_phase phase);
  • run_phaseUVM 测试的一个标准阶段函数。UVM 中的每个测试用例都会有多个阶段,如 build_phaserun_phaseend_phase 等。run_phase 通常用于执行 测试的主要操作,例如启动测试序列、运行仿真等。
  • uvm_phase phase:是输入参数,表示当前的测试阶段。uvm_phase 是 UVM 中的一个类,表示不同的测试阶段(如 buildconnectrun 等)。在仿真过程中,UVM 会自动管理这些阶段的执行,并调用相应的函数。

2. super.run_phase(phase);

super.run_phase(phase);
  • super.run_phase(phase):调用 父类(uvm_testrun_phase 方法。
  • 通过调用 super.run_phase(phase)fpu_add_test 类继承自 uvm_testrun_phase 方法。父类的 run_phase 方法通常包含了 标准的测试流程控制,例如管理阶段的切换和测试的一些基础操作。

3. uvm_info:输出调试信息

`uvm_info("fpu_add_test", "Inside run phase", UVM_HIGH)
  • uvm_infoUVM 宏,用于输出调试信息。它会在仿真日志中输出一条消息。

    • "fpu_add_test":消息的标识符(Tag),帮助你区分不同来源的消息。
    • "Inside run phase":消息内容,表示当前正在执行 fpu_add_test 类的 run_phase 阶段。
    • UVM_HIGH:消息的优先级,UVM_HIGH 表示高优先级的调试信息,适用于开发过程中,帮助追踪测试的执行进度。

4. phase.raise_objection(this);

phase.raise_objection(this);
  • phase.raise_objection(this):在 run_phase 阶段开始时,调用 raise_objection 来通知 UVM 测试尚未完成,它应该等待所有阶段的操作完成。

    • this:表示当前的 fpu_add_test 对象,表示该对象正在请求 “阻止” 阶段的结束,直到所有测试步骤都完成。
    • 阶段对象 raise_objection 用来告知 UVM 系统 当前阶段的操作还未完成,UVM 不会结束该阶段,直到 drop_objection 被调用。

5. #10ns;

#10ns;
  • #10ns延时语句,表示仿真中 暂停 10 纳秒。它通常用于模拟时间延迟,确保测试中的时序正确。
  • 这里的延时可能是为了给 FPU 环境一些时间准备好,或者模拟一些操作的延迟。

6. repeat(1)init_seq.start(env.agent.seqr);

repeat(1) begin
    init_seq = fpu_init_seq::type_id::create("init_seq");
    init_seq.start(env.agent.seqr);
end
  • repeat(1):表示执行 1 次。这里的 repeat(1) 看似多余,实际上只会执行一次。
  • init_seq = fpu_init_seq::type_id::create("init_seq");:通过 工厂方法 创建一个名为 init_seq初始化序列fpu_init_seq 类型)。type_id::create 是 UVM 工厂方法,用于动态创建 fpu_init_seq 的实例。
  • init_seq.start(env.agent.seqr);:调用 init_seqstart 方法,并将 env.agent.seqr 传递给它。env.agent.seqrFPU 环境中代理的序列生成器(sequence generator),用于启动和执行序列。start 方法会开始执行初始化序列。

7. repeat(\TESTS)add_seq.start(env.agent.seqr);`

repeat(`TESTS) begin
    #1ns;
    add_seq = fpu_add_seq::type_id::create("add_seq");
    add_seq.start(env.agent.seqr);
end
  • repeat(\TESTS)**:TESTS 是一个宏,表示执行 **TESTS** 次。在实际执行时,TESTS会被替换为宏定义的值(比如100)。这里的代码表示会 **执行 TESTS` 次加法操作
  • #1ns:表示每次执行时都会 暂停 1 纳秒,模拟每个操作的时序延迟。
  • add_seq = fpu_add_seq::type_id::create("add_seq");:创建一个 加法操作序列fpu_add_seq 类型),名为 add_seq
  • add_seq.start(env.agent.seqr);:启动加法序列,并将 env.agent.seqr 传递给它,表示 执行加法操作

8. wait(env.scb.test_cnt == \TESTS);`

wait(env.scb.test_cnt == `TESTS);
  • wait 是一个 等待语句,表示等待条件 env.scb.test_cnt == \TESTS` 成立。
  • env.scb.test_cntFPU 环境中的计数器,表示已经执行的加法操作次数。这里,wait 语句会等待加法操作次数达到 TESTS (宏定义的次数)后才继续执行。

9. phase.drop_objection(this);

phase.drop_objection(this);
  • phase.drop_objection(this):在 run_phase 完成时,调用 drop_objection 来通知 UVM 当前测试阶段已经完成

    • 之前,调用了 raise_objection 来阻止阶段结束,直到测试完成。现在,通过 drop_objection 告诉 UVM 该阶段可以结束。

总结:

  • run_phaseUVM 测试 中的一个阶段函数,负责执行测试用例中的 主要验证步骤

  • 代码的功能:

    1. 调用父类的 run_phase 方法,执行基础操作。
    2. 输出调试信息,表示进入 run_phase 阶段。
    3. 阻止阶段结束,直到测试操作完成。
    4. 执行 初始化序列init_seq)和 加法操作序列add_seq),重复执行加法操作 TESTS 次。
    5. 等待 加法操作次数达到预期值。
    6. 最后,结束阶段,允许 run_phase 阶段完成。

通过这种方式,run_phase 使得 FPU 加法器 的测试过程得以系统化,逐步执行并验证加法操作,直到所有加法操作完成。


工厂模式(Factory Pattern) 是一种 创建对象的设计模式,它将 对象的实例化过程 从类的内部提取出来,交由专门的 工厂方法工厂类 来负责。这种设计模式的核心目的是 解耦 对象的创建和使用,使得类与其实例化过程分离,从而提高了灵活性和可扩展性。

1. 工厂模式的基本概念

工厂模式通过定义一个接口(或方法),由 工厂 来负责创建对象,而不是在客户端代码中直接创建实例。这样,客户端只需要依赖 工厂接口,不需要了解具体的对象实现细节。

2. 工厂模式的组成部分

  • 产品(Product):需要创建的对象。
  • 工厂(Factory):负责创建 产品 的类,通常通过工厂方法来创建产品实例。
  • 工厂方法(Factory Method):用于创建产品实例的方法。

3. 工厂模式的优点

  • 解耦:客户端不需要知道如何创建产品的具体实现,工厂类负责创建对象,客户端仅需依赖工厂接口。
  • 扩展性好:如果你需要扩展新的产品,只需要增加新的工厂类,不需要修改现有的客户端代码。
  • 可维护性:将对象的创建过程集中在工厂中,便于管理和维护。

4. 常见的工厂模式类型

  • 简单工厂模式(Simple Factory Pattern):通过一个方法创建多个不同类型的产品,但该方法通常会根据传入的参数决定创建哪个具体的产品。
  • 工厂方法模式(Factory Method Pattern):由一个抽象的工厂类来定义接口,具体的子类实现该接口并返回具体的产品实例。
  • 抽象工厂模式(Abstract Factory Pattern):提供一个创建产品系列的接口,每个产品系列中有多个相关的产品对象。

5. UVM 中的工厂模式:

UVM(Universal Verification Methodology)中,工厂模式用于 动态创建管理验证组件,例如测试用例(uvm_test)、验证环境(uvm_env)等。

  • type_id::create:是 UVM 工厂方法,它是实现工厂模式的核心方法。它通过类型标识符(type_id)来创建对象。你可以用它来动态创建 UVM 组件的实例,而无需直接使用构造函数。

  • 工厂方法的作用

    • 它允许 UVM 自动管理对象的生命周期(例如,创建、销毁)。
    • 它让测试用例能够根据需求动态创建不同类型的组件(如环境、序列等),而不需要在代码中硬编码。

6. UVM 工厂模式示例

假设你有一个测试用例 fpu_add_test,其中需要创建一个 fpu_env 对象,表示 FPU 加法器的测试环境。你可以使用 工厂模式 来动态创建这个对象。

// 创建 fpu_env 对象,使用 UVM 的工厂模式
fpu_env env;
env = fpu_env::type_id::create("env", this);
  • fpu_env::type_id::create:这是 UVM 的工厂方法,它创建了一个 fpu_env 类型的对象,并将其命名为 "env",同时将当前组件(fpu_add_test)作为父组件(this)。

  • 通过 工厂模式,你不需要知道 fpu_env 的具体创建方式,只需要使用 type_id::create 来动态创建这个对象,UVM 会自动处理对象的实例化过程。

7. 更形象的类比

假设你在一个 餐厅 点餐,餐厅菜单上有不同种类的菜肴,你不需要关心每道菜的具体做法(即具体如何创建这些菜),你只需要告诉 厨师 想要什么菜,厨师会根据菜单提供相应的菜品。

  • 菜单:相当于 工厂接口,它列出了所有可以创建的对象(在 UVM 中是组件、环境等)。
  • 厨师:相当于 工厂类,负责根据菜单提供具体的菜肴(即通过 type_id::create 创建不同类型的对象)。
  • 菜肴:相当于 具体的对象(产品),你可以根据需要点不同的菜,而不用关心它们如何做(即对象如何创建)。

8. 总结

  • 工厂模式 通过 工厂类工厂方法 来封装对象的创建过程,提供一个统一的接口,允许客户端动态地创建不同类型的对象。
  • UVM 中,工厂模式通过 type_id::create 方法实现,动态创建测试用例、环境、序列等组件,简化了组件管理和实例化过程。
  • UVM 工厂模式 使得验证环境更加灵活和可扩展,便于在不同测试用例中动态地创建和管理验证组件。

SystemVerilog 中,有几个基础的语法和关键字用于简化代码结构和增强功能的表达。下面是对你提到的一些基础语法符号和关键字的解释:

1. :: (范围解析运算符)

SystemVerilog 中,:: 被称为 范围解析运算符。它用于访问类中的静态成员、调用工厂方法、引用模块实例等。它的作用类似于其他编程语言中的 命名空间静态方法调用

用途

  • 访问类的静态方法和静态成员
  • 访问模块、接口、类中的类型
  • UVM 工厂模式:通过 type_id::create 调用工厂方法。

示例

class MyClass;
    static int my_value = 10;
    
    // 静态方法
    static function void print_value();
        $display("Value: %0d", my_value);
    endfunction
endclass

// 使用范围解析运算符访问静态成员和方法
MyClass::print_value();  // 调用静态方法
$display("Value: %0d", MyClass::my_value);  // 访问静态成员
  • MyClass::my_value:访问 MyClass 类中的静态成员。
  • MyClass::print_value():调用 MyClass 类中的静态方法。

2. . (成员访问运算符)

.成员访问运算符,用于访问类、模块或接口的成员(如变量、方法、任务等)。在面向对象编程中,通常使用 . 来访问对象的 实例成员

用途

  • 访问类的实例成员(变量、方法)。
  • 访问模块或接口的端口和信号

示例

class MyClass;
    int my_value;
    
    // 构造函数
    function new();
        my_value = 10;
    endfunction
    
    // 方法
    function void print_value();
        $display("Value: %0d", my_value);
    endfunction
endclass

MyClass obj = new();  // 创建 MyClass 类的实例

// 使用 '.' 来访问成员
obj.print_value();  // 调用实例方法
$display("Value: %0d", obj.my_value);  // 访问实例成员
  • obj.print_value():通过 obj 实例调用 print_value 方法。
  • obj.my_value:访问 obj 实例的成员变量 my_value

3. this(当前实例)

SystemVerilog 中,this 关键字表示当前对象的 实例,即当前类的实例。当你在类的方法或构造函数中使用 this 时,它引用的是当前对象自身。

用途

  • 访问当前实例的成员
  • 用于传递当前对象的引用

示例

class MyClass;
    int my_value;
    
    function new(int value);
        this.my_value = value;  // 使用 this 来访问当前实例的成员
    endfunction
    
    function void print_value();
        $display("Value: %0d", this.my_value);  // 使用 this 来访问当前实例的成员
    endfunction
endclass

MyClass obj = new(5);
obj.print_value();  // 输出: Value: 5
  • this.my_value:访问当前对象的成员 my_value
  • this 通常用于 构造函数方法 中,特别是当你需要区分 实例成员局部变量 时,this 非常有用。

4. super(父类调用)

superSystemVerilog 中用于调用 父类 的方法、构造函数等的关键字。它可以用来访问父类的成员或方法,特别是在类继承的上下文中。

用途

  • 调用父类的构造函数
  • 调用父类的方法或任务

示例

class ParentClass;
    function new();
        $display("Parent class constructor");
    endfunction
    
    function void display_message();
        $display("Message from parent class");
    endfunction
endclass

class ChildClass extends ParentClass;
    function new();
        super.new();  // 调用父类的构造函数
        $display("Child class constructor");
    endfunction
    
    function void display_message();
        super.display_message();  // 调用父类的 display_message 方法
        $display("Message from child class");
    endfunction
endclass

ChildClass child = new();  // 创建 ChildClass 的实例
child.display_message();  // 调用 display_message 方法
  • super.new():调用父类 ParentClass 的构造函数。
  • super.display_message():调用父类的 display_message 方法。

5. 总结

  • :::用于访问类的 静态成员调用静态方法,也用于 UVM 工厂方法 的调用(如 type_id::create)。
  • .:用于访问类、模块或接口的 实例成员(变量、方法、任务等)。
  • this:表示当前对象的实例,用于访问当前对象的成员或传递当前对象的引用。
  • super:用于 调用父类的构造函数方法,通常在类继承中使用。

这些语法符号和关键字是 SystemVerilog面向对象编程(OOP) 中常用的基础工具,帮助你更好地组织和管理代码,特别是在验证和仿真中使用类、组件等结构时。

posted @ 2025-07-16 16:34  江左子固  阅读(104)  评论(0)    收藏  举报