【问题标题】:Specman UVM: How update a value of a register when the value was written to another register?Specman UVM:当值被写入另一个寄存器时,如何更新寄存器的值?
【发布时间】:2014-09-15 08:46:57
【问题描述】:

(在我的验证环境中,我们使用vr_ad 包。)。我尝试实现下一个: 当数据写入其中一个寄存器 (timer_load) 时,另一个寄存器 (timer_bgload) 应该使用相同的数据进行更新。

我在 UVM 用户指南中找到了下一个 示例

// Attaching the target register file to the broadcasted register
extend ex_c_bus_env {
    post_generate() is also {
        xcore_regs.vr_ad_rx_data.attach(xbus_regs);
    };
};
// Implement the broadcast:
// When writing to register VR_AD_RX_DATA in XCORE vr_ad_reg_file,
// propagate the value to the VR_AD_XBUS_DATA register in ACTIVE_XBUS.
extend ACTIVE_XBUS vr_ad_reg_file {
    indirect_access( direction : vr_ad_rw_t, ad_item : vr_ad_base) is {
        if ad_item is a VR_AD_RX_DATA vr_ad_reg (d) {
            vr_ad_xbus_data.write_reg_val(d.get_cur_value());
        };
    };
};

我的注册:

reg_def TIMER_LOAD_0 TIMER 20'h00010 {
    reg_fld timer_load : uint (bits : 32) : RW : 0xffff;
};


reg_def TIMER_BGLOAD_0 TIMER 20'h00014 {
    reg_fld timer_bgload : uint (bits : 32) : RW : 0xffff;
};


reg_def TIMER_BGLOAD_1 TIMER 20'h00028 { 
    reg_fld timer_bgload : uint (bits : 32) : RW : 0xffff;
    //another reg with the same instance name
};

我的代码,用于在将数据写入tiemr_load 后更新timer_bgload 寄存器:

extend TIMER vr_ad_reg_file {
    indirect_access( direction : vr_ad_rw_t, ad_item : vr_ad_base) is {
        if ad_item is a TIMER_LOAD_0 vr_ad_reg (d) {
            timer_bgload.write_reg_val(d.get_cur_value());
        };
    };
};

unit timer_env_u like any_env {
    post_generate() is also {
        timer_regs.timer_load_0.attach(timer_regs.timer_bgload_0.timer_bgload);
    };  
};

我得到一个编译错误

*** Error: No such variable 'timer_bgload'
                at line 17 in @timer_reg_db
            timer_bgload.write_reg_val(d.get_cur_value());

非常感谢任何帮助。

【问题讨论】:

  • timer_bgload 仅存在于TIMER_BGLOAD_0TIMER_BGLOAD_1 (它们不是同一个字段!)您无法从TIMER vr_ad_reg_file 访问它们

标签: specman uvm e


【解决方案1】:

您可以将timer_load 寄存器直接附加到timer_bgload 寄存器并在那里实现indirect_access(...)

// attach the regs
extend TIMER vr_ad_reg_file {
  post_generate() is also {
    timer_load_0.attach(timer_bgload_0);
  }; 
};

// implement indirect_access()
extend TIMER_BGLOAD_0 vr_ad_reg {
  indirect_access(direction : vr_ad_rw_t, ad_item : vr_ad_base) is {
    if direction == WRITE and ad_item is a TIMER_LOAD_0 vr_ad_reg (d) {
      write_reg_val(d.get_cur_value());
    };
  };
};

我不知道为什么 Cadence 的例子花了很长的路将寄存器文件附加到间接寄存器。

另外,如果您有多个 TIMER_LOAD/BGLOAD 寄存器(好像您可能有 2 个),那么最好先定义类型:

// define register types without instantiation in reg_file
reg_def TIMER_LOAD {
  reg_fld timer_load : uint (bits : 32) : RW : 0xffff;
};

reg_def TIMER_BGLOAD {
  reg_fld timer_bgload : uint (bits : 32) : RW : 0xffff;
};

定义类型后,您可以根据需要在寄存器文件中手动实例化它们多次。看看手册,有一个例子告诉你如何做到这一点。

这意味着在TIMER_BGLOAD 子类型中实现indirect_access(...) 方法(仅一次)而不是两次(对于TIMER_BGLOAD_0TIMER_BGLOAD_1)就足够了。

【讨论】:

    【解决方案2】:

    我会用post_access 来实现它,类似这样:

    extend TIMER_LOAD_0 TIMER vr_ad_reg {
        post_access(operation : vr_ad_rw_t) is {
            if operation == WRITE {
                var rgf := get_access_path()[0].as_a(TIMER vr_ad_reg_file);
                rgf.timer_bgload_0.timer_bgload = timer_load;
            };
        };
    };
    

    请注意,它可能不会在第一次点击时起作用。如果不是,我会逐步构建它,从这样的“空”代码开始:

    extend TIMER_LOAD_0 TIMER vr_ad_reg {
        post_access(operation : vr_ad_rw_t) is {
            print me, operation;
        };
    };
    

    然后在print 语句中放置一个断点,打开一个数据浏览器,查看我们到达那里的字段的确切名称,尝试从 Specman CLI 访问它们 - 当它工作时 - 将其编码。

    【讨论】:

    • 这也是我过去使用post_access(...)的方式,但indirect_access(...)是专门为这种事情设计的。
    猜你喜欢
    • 1970-01-01
    • 2019-01-09
    • 2019-08-18
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    相关资源
    最近更新 更多