System verilog 通过任务驱动虚拟接口信号的位片

System verilog 通过任务驱动虚拟接口信号的位片,system-verilog,uvm,System Verilog,Uvm,我试图创建一个任务,负责设置一个向量位,并在一个时钟周期后清除它。我的驾驶员代码附在下面: class my_if_driver extends uvm_driver; `uvm_component_utils(my_if_driver) // Members // UVM stuff virtual my_if_interface vif; function new(string name="my_if_driver", uvm_componen

我试图创建一个任务,负责设置一个向量位,并在一个时钟周期后清除它。我的驾驶员代码附在下面:

class my_if_driver extends uvm_driver;
  `uvm_component_utils(my_if_driver)
 
  // Members
  // UVM stuff
  virtual my_if_interface vif;
 
  function new(string name="my_if_driver", uvm_component parent);
    super.new(name, parent);
  endfunction
 
  extern function void build_phase(uvm_phase phase);
  extern function void connect_phase(uvm_phase phase);
  extern task          run_phase(uvm_phase phase);
 
  extern task drive_my_if(my_if_transaction txn);
  extern task set_then_clear(ref logic signal);
endclass
 
function void my_if_driver::build_phase(uvm_phase phase);
endfunction
 
function void my_if_driver::connect_phase(uvm_phase phase);
endfunction
 
task my_if_driver::run_phase(uvm_phase phase);
  @(posedge vif.resetn);
  forever begin
    seq_item_port.get_next_item(req);
    fork
      drive_my_if(req);
    join_none
    seq_item_port.item_done(req);
  end
endtask

// NOTE: each 'command-signal' has bit for each tid (transaction ID)
task my_if_driver::drive_my_if(my_if_transaction txn);
  // Wait for delay
  repeat (txn.cycle_delay) @(posedge vif.clk);
  // Then drive appropriate signal
  if (txn.my_if_cmd == my_if_transaction::CMDA) begin
    set_then_clear(vif.my_if_cmd_a[txn.tid]);
  end
  else if (txn.my_if_cmd == my_if_transaction::CMDB) begin
    set_then_clear(vif.my_if_cmd_b[txn.tid]);
  end
  else if (txn.my_if_cmd == my_if_transaction::CMDC) begin
    set_then_clear(vif.my_if_cmd_c[txn.tid]);
  end
endtask
 
task my_if_driver::set_then_clear(ref logic signal);
  signal <= 1'b1;
  @(posedge vif.clk);
  signal <= 1'b0;
endtask
如果驱动程序扩展了uvm驱动程序,则将my\u分类;
`uvm_组件_utils(我的if_驱动程序)
//成员
//UVM材料
虚拟my_if_接口vif;
新函数(字符串名称=“我的驱动程序”,uvm\U组件父级);
super.new(名称、父级);
端功能
外部功能无效构建阶段(uvm阶段);
外部功能无效连接相位(uvm相位);
外部任务运行阶段(uvm阶段);
外部任务驱动\我的\如果(我的\如果\事务txn);
外部任务集然后清除(参考逻辑信号);
末级
函数void my_if_驱动程序::构建阶段(uvm_阶段);
端功能
函数void my_if_驱动程序::连接_阶段(uvm_阶段);
端功能
任务my_if_驱动程序::运行阶段(uvm_阶段);
@(posedge vif.resetn);
永远开始
seq_item_port.获取下一个_item(请求);
叉
驾驶我的车如果(需要);
加入
序号项目端口。项目完成(需求);
结束
结束任务
//注意:每个“命令信号”都有每个tid的位(事务ID)
任务my_if_驱动程序::drive_my_if(my_if_事务txn);
//等待延误
重复(txn循环延迟)@(posedge振动时钟);
//然后驱动适当的信号
如果(txn.my\u if\u cmd==my\u if\u事务::CMDA)开始
设置然后清除(vif.my\u if\u cmd\u a[txn.tid]);
结束
else if(txn.my\u if\u cmd==my\u if\u transaction::CMDB)开始
设置然后清除(vif.my\u if\u cmd\u b[txn.tid]);
结束
else if(txn.my\u if\u cmd==my\u if\u transaction::CMDC)开始
设置然后清除(vif.my\u if\u cmd\u c[txn.tid]);
结束
结束任务
任务my_if_驱动程序::设置_然后清除(参考逻辑信号);
信号LRM说

因为通过引用传递的变量可能是自动变量 ref参数不得用于禁止自动执行的任何上下文中 变量

并且不能通过引用传递压缩变量的一位select,只能传递整个变量

如果不为每个cmd编写单独的任务,或者在选择要分配的接口变量的signal任务中编写一个big case语句,那么就没有简单的方法可以做到这一点

LRM说

因为通过引用传递的变量可能是自动变量 ref参数不得用于禁止自动执行的任何上下文中 变量

并且不能通过引用传递压缩变量的一位select,只能传递整个变量


如果不为每个cmd编写单独的任务,或者在选择要分配的接口变量的signal任务中编写一个big case语句,那么就没有简单的方法可以做到这一点

尝试将这两行上的非阻塞分配更改为阻塞。我确实在服务器上尝试了你的代码,并得到另一个错误“Object”this.vif.my_if_cmd_a[txn.tid]”无法通过引用传递。允许的对象类型包括变量、类属性、未打包的结构成员和未打包的数组元素。”(我没有检查此错误是模拟器问题还是SV规则。)根据Dave的回答,这是LRM规则(第13.5.2节)。我选择执行非阻塞的原因是,我希望在所有监视活动之后更新值(目前不使用CB)。请尝试将这两行上的非阻塞分配更改为阻塞。我确实在服务器上尝试了你的代码,并得到另一个错误“Object”this.vif.my_if_cmd_a[txn.tid]”无法通过引用传递。允许的对象类型包括变量、类属性、未打包的结构成员和未打包的数组元素。”(我没有检查此错误是模拟器问题还是SV规则。)根据Dave的回答,这是LRM规则(第13.5.2节)。我选择执行非阻塞的原因是因为我希望在所有监视活动之后更新值(目前不使用CB)。谢谢Dave!我在LRM中看到了这一点,但后来我也看到了这一点,我将您的答案解释为这是可能的,因此我满怀希望:)我将采用“大案例/多假设”路线。谢谢Dave!我在LRM中看到了这一点,但后来我也看到了这一点,我将您的答案解释为这是可能的,因此我满怀希望:)我将采用“大案例/多假设”路线。