systemverilog 如何在子类中修改父类中声明的变量

在 UVM(或 SystemVerilog)中,子类cfg(配置类)修改父类声明的变量,核心是利用继承的可见性规则(父类变量需为protected/public),通过 “直接赋值、方法重载、构造函数初始化” 等方式实现,以下是分场景的标准做法(含完整代码示例):

一、前提:父类变量的可见性(关键)

父类中变量的访问权限决定子类能否直接修改,UVM 中推荐父类变量声明为protected(子类可访问,外部不可改)或public(全范围可访问),禁止用local(子类不可访问)。

父类 cfg 定义(示例):

systemverilog

// 父类配置类:base_cfg
class base_cfg extends uvm_object;
  `uvm_object_utils(base_cfg)

  // 声明可被子类修改的变量(protected:子类可访问,外部不可改)
  protected int burst_len = 8;        // 默认突发长度
  protected bit en_coverage = 1;      // 默认开启覆盖率
  protected bit [31:0] base_addr = 32'h1000_0000; // 默认基地址

  // 可选:父类提供修改变量的方法(推荐,封装逻辑)
  virtual function void set_burst_len(int len);
    if (len > 0 && len <= 64) begin // 合法性检查
      burst_len = len;
    end else begin
      `uvm_error("BASE_CFG_ERR", $sformatf("burst_len=%0d 超出范围", len))
    end
  endfunction

  function new(string name = "base_cfg");
    super.new(name);
  endfunction
endclass

二、场景 1:子类 cfg 中直接修改父类变量(最简单)

子类继承父类后,可直接访问protected/public变量并赋值(推荐在new函数或post_randomize中修改)。

子类 cfg 定义:

systemverilog

// 子类配置类:axi_cfg(继承base_cfg)
class axi_cfg extends base_cfg;
  `uvm_object_utils(axi_cfg)

  // 新增子类独有的变量
  bit en_debug = 0;

  // 场景1.1:在构造函数(new)中修改父类变量
  function new(string name = "axi_cfg");
    super.new(name);
    // 直接修改父类protected变量
    burst_len = 16;          // 覆盖父类默认值8
    base_addr = 32'h2000_0000; // 覆盖默认基地址
    en_coverage = 0;         // 关闭覆盖率
  endfunction

  // 场景1.2:在自定义方法中修改父类变量
  virtual function void cfg_init();
    burst_len = 32; // 动态修改
    `uvm_info("AXI_CFG_MOD", $sformatf("父类burst_len修改为:%0d", burst_len), UVM_MEDIUM)
  endfunction

  // 场景1.3:随机化时修改(post_randomize)
  virtual function void post_randomize();
    super.post_randomize(); // 先执行父类的post_randomize
    burst_len = burst_len * 2; // 随机化后调整父类变量
  endfunction
endclass

三、场景 2:通过父类方法修改(推荐,封装性更好)

父类提供set_*方法修改变量(含合法性检查),子类调用该方法修改,避免直接赋值导致的非法值。

子类中调用父类方法:

systemverilog

class axi_cfg extends base_cfg;
  `uvm_object_utils(axi_cfg)

  function new(string name = "axi_cfg");
    super.new(name);
    // 调用父类方法修改(自动做合法性检查)
    super.set_burst_len(20); // 合法值:修改为20
    super.set_burst_len(100); // 非法值:父类会报错,变量不修改
  endfunction
endclass

四、场景 3:重载父类方法修改(适配特殊逻辑)

若父类方法的逻辑不满足子类需求,可重载父类的set_*方法,在子类中定制修改变量的逻辑。

子类重载父类方法:

systemverilog

class axi_cfg extends base_cfg;
  `uvm_object_utils(axi_cfg)

  // 重载父类的set_burst_len方法
  virtual function void set_burst_len(int len);
    // 子类定制逻辑:允许更大的突发长度
    if (len > 0 && len <= 128) begin
      burst_len = len;
      `uvm_info("AXI_CFG_SET", $sformatf("子类修改burst_len为:%0d", len), UVM_MEDIUM)
    end else begin
      `uvm_error("AXI_CFG_ERR", $sformatf("burst_len=%0d 超出子类范围(0~128)", len))
    end
  endfunction

  function new(string name = "axi_cfg");
    super.new(name);
    set_burst_len(64); // 调用子类重载后的方法
  endfunction
endclass

五、场景 4:通过外部组件(如 test/sequence)间接修改

若子类cfg已实例化,可通过句柄直接修改父类继承的变量(需变量为protected/public)。

Test 中修改子类 cfg 的父类变量:

systemverilog

class axi_test extends uvm_test;
  `uvm_component_utils(axi_test)
  axi_cfg cfg;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    // 实例化子类cfg
    cfg = axi_cfg::type_id::create("cfg");
    // 直接修改父类继承的变量
    cfg.burst_len = 4; // 子类句柄可直接访问父类protected变量
    // 调用父类方法修改
    cfg.set_burst_len(8);
  endfunction
endclass

六、关键注意事项(避坑指南)

  1. 访问权限

    • 父类变量若声明为local,子类无法访问(编译报错),需改为protected/public
    • UVM 中推荐父类变量用protected(封装性更好),仅通过方法对外暴露修改接口。
  2. 初始化顺序

    • 子类new函数中,需先调用super.new()(执行父类构造),再修改变量;
    • 若父类new中对变量做了初始化,子类new中修改会覆盖父类值。
  3. 随机化兼容

    • 若父类变量需要随机化,需在父类中用rand声明:rand int burst_len;
    • 子类可通过constraint约束父类随机变量:

      systemverilog

      class axi_cfg extends base_cfg;
        `uvm_object_utils(axi_cfg)
        constraint burst_len_c { burst_len inside {[16:32]}; } // 约束父类变量
      endclass
      
  4. UVM 工厂兼容

    • 父类和子类都需加uvm_object_utils宏,确保工厂创建实例时变量初始化生效;
    • 若通过uvm_config_db传递 cfg 句柄,修改后需确保所有使用该 cfg 的组件同步更新。

七、总结

子类 cfg 修改父类变量的核心方法:

方法适用场景优点缺点
直接赋值简单修改、无合法性检查简洁高效无校验,易赋非法值
调用父类 set 方法需合法性检查、复用父类逻辑安全、符合封装原则需父类提前定义方法
重载父类 set 方法子类需定制修改逻辑灵活、适配子类需求代码量稍多
post_randomize 修改随机化后调整变量兼容随机化流程仅随机化场景生效

核心原则:父类尽量封装修改变量的方法(而非直接暴露变量),子类通过方法修改,既保证合法性,又提升代码可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值