简体   繁体   English

Specman UVM:当值写入另一个寄存器时,如何更新寄存器的值?

[英]Specman UVM: How update a value of a register when the value was written to another register?

(in my verification environment we use vr_ad package.). (在我的验证环境中,我们使用vr_ad包。)。 I try to implement the next: When data is written to one of the registers ( timer_load ), another register ( timer_bgload ) should be updated with the same data. 我尝试实现下一个:当数据写入其中一个寄存器( timer_load )时,应使用相同的数据更新另一个寄存器( timer_bgload )。

I've found the next example in UVM User Guide : 在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());
        };
    };
};

My registers: 我的寄存器:

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
};

My code for updating the timer_bgload register after a data was written to tiemr_load : 我将用于在将数据写入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);
    };  
};

I get a compilation error : 我收到编译错误

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

I really appreciate any help. 我非常感谢任何帮助。

You can attach the timer_load register to the timer_bgload register directly and implement indirect_access(...) there: 您可以直接将timer_load寄存器附加到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());
    };
  };
};

I don't know why the Cadence example took the long route of attaching the register file to the indirect register. 我不知道为什么Cadence示例采用了将寄存器文件附加到间接寄存器的漫长路径。

Also, if you have more than one TIMER_LOAD/BGLOAD registers (seems like you may have 2), then the best thing to do is define the types first: 此外,如果您有多个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;
};

After you define the types, you instantiate them in the register file manually as many times as you need to. 定义类型后,可以根据需要手动在寄存器文件中实例化它们。 Have a look in the manual, there is an example showing you exactly how to do it. 看一下手册,有一个例子向您展示如何做到这一点。

This means that it's enough to implement the indirect_access(...) method in the TIMER_BGLOAD subtype (only once) as opposed to two times (for TIMER_BGLOAD_0 and TIMER_BGLOAD_1 ). 这意味着它足以在TIMER_BGLOAD子类型中实现indirect_access(...)方法(仅一次)而不是两次(对于TIMER_BGLOAD_0TIMER_BGLOAD_1 )。

I'd implement it with post_access , something like that: 我用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;
        };
    };
};

Pay attention, that it might not work on first hit. 注意,它可能不适用于第一次打击。 If it's not, I'd build it gradually, starting with 'empty' code like this: 如果不是,我会逐渐构建它,从这样的'空'代码开始:

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

And putting a breakpoint in the print statement, opening a data browser, looking what are the exact names of the fields we got there, try to access them from Specman CLI - and when it works - code it back. 并在print语句中打开一个断点,打开一个数据浏览器,查看我们在那里获得的字段的确切名称,尝试从Specman CLI访问它们 - 当它工作时 - 编码回来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM