在 UVM 监视器中循环时无法退出
Unable to exit while loop in UVM monitor
这可能是我忽略的一个愚蠢的错误,但我对 UVM 还很陌生,在此之前我曾尝试修改我的代码一段时间。我正在尝试使用 Data valid stall 协议从我的 UVM 驱动程序向 DUT 发送数据包中的 8 位数据流。我的输入监视器无法获取这些驱动的事务。
我有一个 while 循环,其条件是有效位必须为高,停止位必须为低。只要这个条件成立,监视器就需要拾取数据字节并推入队列。我知道一个事实,当我一路使用 $display
语句时,数据正在被提取并推送到队列。一旦接收到所有数据字节并且有效位变低,就会出现问题。理想情况下,这应该会导致退出 while 循环,但实际上并没有这样做。这里的任何帮助将不胜感激。我附上了下面的代码片段。提前致谢。
virtual task main_phase (uvm_phase phase);
$display("Run phase of input monitor");
collect_transfer();
endtask: main_phase
virtual task collect_transfer();
fork
forever begin
wait_for_valid_transaction_cycle();
create_and_populate_pkt();
broadcast_pkt();
@(iP0_vif.cb_iP0_MON);
end
join_none
endtask: collect_transfer
virtual task wait_for_valid_transaction_cycle();
wait(iP0_vif.cb_iP0_MON.ip_valid && ~iP0_vif.cb_iP0_MON.ip_stall);
endtask: wait_for_valid_transaction_cycle
virtual task create_and_populate_pkt();
pkt = Router_seq_item :: type_id :: create("pkt");
pkt.valid = iP0_vif.cb_iP0_MON.ip_valid;
pkt.sop = iP0_vif.cb_iP0_MON.ip_sop;
$display("before data collection");
while(iP0_vif.cb_iP0_MON.ip_valid === `HIGH && iP0_vif.cb_iP0_MON.ip_stall === `LOW) begin
$display("After checking for stall");
pkt.data = iP0_vif.cb_iP0_MON.ip_data;
$display(pkt.data);
pkt.data_q.push_front(pkt.data);
pkt.eop = iP0_vif.cb_iP0_MON.ip_eop;
$display("print check in input monitor @ time = %0t", $time);
@(iP0_vif.cb_iP0_MON);
end
$display("before printing input packet from monitor");
Check_for_port_route_and_populate_packet_field(pkt);
print_packet(pkt);
endtask: create_and_populate_pkt
未显示 $display
语句 "before printing input packet from monitor"。
HIGH 定义为二进制 1,LOW 定义为二进制 0。
显示语句方面的代码输出如下。
数据收集前
在检查失速之前
检查失速后
2
在输入监视器中打印检查 @ time = 105
在检查失速之前
检查失速后
1
在输入监视器中打印检查 @ time = 115
在检查失速之前
检查失速后
3
在输入监视器中打印检查 @ time = 125
您环境中的其他地方可能会放弃主要阶段异议。 UVM 将自动终止在阶段结束时生成的任何线程。
要解决此问题,请不要反对您显示器中的主要阶段。反对那个阶段是创建刺激的线程的责任。相反,您应该在 run_phase 期间启动此监视器,这将确保您的循环在模拟结束之前不会被终止。
此外,在关闭阶段,您会希望您的监视器在当前看到数据包时进行反对。这将确保模拟不会在发送刺激后立即结束,让您的其他监视器有时间收集来自 DUT 的响应。
这可能是我忽略的一个愚蠢的错误,但我对 UVM 还很陌生,在此之前我曾尝试修改我的代码一段时间。我正在尝试使用 Data valid stall 协议从我的 UVM 驱动程序向 DUT 发送数据包中的 8 位数据流。我的输入监视器无法获取这些驱动的事务。
我有一个 while 循环,其条件是有效位必须为高,停止位必须为低。只要这个条件成立,监视器就需要拾取数据字节并推入队列。我知道一个事实,当我一路使用 $display
语句时,数据正在被提取并推送到队列。一旦接收到所有数据字节并且有效位变低,就会出现问题。理想情况下,这应该会导致退出 while 循环,但实际上并没有这样做。这里的任何帮助将不胜感激。我附上了下面的代码片段。提前致谢。
virtual task main_phase (uvm_phase phase);
$display("Run phase of input monitor");
collect_transfer();
endtask: main_phase
virtual task collect_transfer();
fork
forever begin
wait_for_valid_transaction_cycle();
create_and_populate_pkt();
broadcast_pkt();
@(iP0_vif.cb_iP0_MON);
end
join_none
endtask: collect_transfer
virtual task wait_for_valid_transaction_cycle();
wait(iP0_vif.cb_iP0_MON.ip_valid && ~iP0_vif.cb_iP0_MON.ip_stall);
endtask: wait_for_valid_transaction_cycle
virtual task create_and_populate_pkt();
pkt = Router_seq_item :: type_id :: create("pkt");
pkt.valid = iP0_vif.cb_iP0_MON.ip_valid;
pkt.sop = iP0_vif.cb_iP0_MON.ip_sop;
$display("before data collection");
while(iP0_vif.cb_iP0_MON.ip_valid === `HIGH && iP0_vif.cb_iP0_MON.ip_stall === `LOW) begin
$display("After checking for stall");
pkt.data = iP0_vif.cb_iP0_MON.ip_data;
$display(pkt.data);
pkt.data_q.push_front(pkt.data);
pkt.eop = iP0_vif.cb_iP0_MON.ip_eop;
$display("print check in input monitor @ time = %0t", $time);
@(iP0_vif.cb_iP0_MON);
end
$display("before printing input packet from monitor");
Check_for_port_route_and_populate_packet_field(pkt);
print_packet(pkt);
endtask: create_and_populate_pkt
未显示 $display
语句 "before printing input packet from monitor"。
HIGH 定义为二进制 1,LOW 定义为二进制 0。
显示语句方面的代码输出如下。
数据收集前
在检查失速之前
检查失速后
2
在输入监视器中打印检查 @ time = 105
在检查失速之前
检查失速后
1
在输入监视器中打印检查 @ time = 115
在检查失速之前
检查失速后
3
在输入监视器中打印检查 @ time = 125
您环境中的其他地方可能会放弃主要阶段异议。 UVM 将自动终止在阶段结束时生成的任何线程。
要解决此问题,请不要反对您显示器中的主要阶段。反对那个阶段是创建刺激的线程的责任。相反,您应该在 run_phase 期间启动此监视器,这将确保您的循环在模拟结束之前不会被终止。
此外,在关闭阶段,您会希望您的监视器在当前看到数据包时进行反对。这将确保模拟不会在发送刺激后立即结束,让您的其他监视器有时间收集来自 DUT 的响应。